Linux下DM9000网卡驱动实验〈二〉
2006-10-19 17:14
405 查看
1.1.1 步骤三:网络驱动程序的数据结构和抽象接口
首先熟悉以下重要的数据结构,然后对照DM9000的驱动程序,察看具体数据结构的用法。保存网络设备信息的结构体net_device
net_device结构存储了网络设备的操作方法和其他信息。其定义如下面的清单。仅仅列出了部分常用的成员,对于普通的网络设备驱动程序已足够。想详细了解的结构体参考LDD(Linux Device Driver)或内核源码/include/linux/netdevice.h
程序清单 0‑2
struct net_device { char name[IFNAMSIZ]; unsigned short flags; /* interface flags (a la BSD) */ unsigned long base_addr; /* device I/O address */ unsigned int irq; /* device IRQ number */ unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address */ unsigned char addr_len; /* hardware address length */ unsigned long trans_start; /* Time (in jiffies) of last Tx */ unsigned long last_rx; /* Time of last Rx */ int watchdog_timeo; void *priv; /* pointer to private data */ struct module *owner; /* open/release and usage marking */ int (*init)(struct net_device *dev); int (*open)(struct net_device *dev); int (*stop)(struct net_device *dev); int (*set_config)(struct net_device *dev, struct ifmap *map); int (*hard_start_xmit) (struct sk_buff *skb,struct net_device *dev); int (*set_mac_address)(struct net_device *dev, void *addr); //.............. }; |
init(),open(),stop(),set_config()方法在模板中已经清楚地介绍了,这里重点讲解hard_start_xmit()方法。当内核需要发送一个数据包时,他调用hard_start_xmit()方法将数据放到一个输出队列。数据包包含在一个套接字缓冲区结构体(struct sk_buff)变量中。对于驱动程序来说,sk_buff只是一个数据包,不用关心里面复杂的结构成员。
程序清单 0‑3
static int test_tx(struct sk_buff * skb , struct net_device * dev) { int len; netif_stop_queue(dev); //让内核暂停调用hard_start_xmit()方法 len = skb->len < ETH_ZLEN ? ETH_ZLEN :skb->len; //把len个数据写入网络设备硬件缓冲区并启动发送; dev->trans_start = jiffies; //记录时间 dev_kfree_skb(skb); //等待数据发送完毕 netif_wake_queue(dev); return 0; } static int test_set_mac_address(struct net_device * dev, void *addr) { struct socketaddr * mac_addr; mac_addr = addr; if(netif_running(dev)) { Return –EBUSY; } memcpy(dev->dev_addr , mac_addr->sa_data , dev->addr_len); //改变mac地址,与具体硬件相关。 return 0; } |
一般网络驱动程序不对发送数据进行缓存,而是直接使用硬件的发送功能把数据发送出去。接收数据则通过硬件中断来通知的。在中断处理程序中,把硬件帧信息填入一个sk_buff结构中,然后调用netif_rx()传递给上层处理。当然,在使用中断之前,需要向系统注册中断处理程序。
下面是中断服务程序的写法:
static void net_irq_handle(int irq, void * dev_id, struct pt_regs * regs) { struct net_device * dev; struct sk_buff *skb; unsigned int length; u8 * dec; dev = (struct net_device *)dev_id; if(发送成功) { 清除发送中断标志; netif_wake_queue(dev); } if(接收成功) { 清除接受中断标志; length = 数据包长度; skb = dev_alloc_skb(length + 2); if(!skb) { return; } skb_reserve(skb, 2); dec = skb->data; //把数据包(length长度)读到dec指向的内存中; skb->dev = dev; skb->protocol = eth_type_trans(skb, dev); skb->ip_summed = CHECKSUM_UNNECESSARY; netif_rx(skb); dev->last_rx = jiffies; } if(出错) 错误处理 清除中断源; } |
相关文章推荐
- Linux下DM9000网卡驱动实验
- Linux下DM9000网卡驱动实验〈三〉
- Linux下DM9000网卡驱动实验
- Linux下DM9000网卡驱动实验
- linux-2.6.32在mini2440开发板上移植--移植DM9000 网卡驱动
- ARM-Linux驱动--DM9000网卡驱动分析(四)
- ARM-Linux驱动--DM9000网卡驱动分析(三)
- ARM-Linux驱动--DM9000网卡驱动分析(一)
- dm9000网卡的linux驱动分析
- ARM-Linux驱动--DM9000网卡驱动分析(三)
- Linux2.6 下DM9000网卡驱动
- Linux-2.6.32.2 中固然有 DM9000 网卡驱动,但并不是完全的适合mini2440,导致挂载不上nfs文件系统
- ARM-Linux驱动--DM9000网卡驱动分析(三)
- ARM-Linux驱动--DM9000网卡驱动分析(一) .
- ARM-Linux驱动--DM9000网卡驱动分析(二)
- linux网卡驱动dm9000_poll_work函数分析
- 基于linux2.6.30.4内核的DM9000网卡驱动编译成模块成功ping通
- ARM-Linux驱动--DM9000网卡驱动分析(一)
- linux2.6.32.2 mini2440平台移植--移植DM9000网卡驱动
- 【Linux驱动】TQ2440 DM9000E网卡驱动移植(Linux-2.6.30.4)