Linux下DM9000网卡驱动实验(二)

首先熟悉以下重要的数据结构,然后对照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(出错)

 

   错误处理

 

 

 

清除中断源;

 

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值