网卡驱动程序设计

来源:互联网 发布:搜不到网络打印机 编辑:程序博客网 时间:2024/06/08 20:13

Linux网络子系统

这里写图片描述

系统调用接口层
为应用程序提供访问网络子系统的统一方法。

协议无关层
提供通用的方法来使用传输层协议,对不同的协议有统一的接口。

协议栈的实现
实现具体的网络协议。

设备无关层
协议与设备驱动之前通信的通用接口,对于不同的网络通信设备有统一的接口。

重要的数据结构

网卡描述结构:
在Linux内核中,每个网卡都由一个 net_device结构 来描述,其中的一些重要成员有:
这里写图片描述

网卡操作集合:
类似于字符设备驱动中的file_operations结构, net_device_ops结构 记录了网卡所支持的操作。

static const struct net_device_ops dm9000_netdev_ops ={    .ndo_open = dm9000_open,    .ndo_stop = dm9000_stop,    .ndo_start_xmit = dm9000_start_xmit,    .ndo_do_ioctl = dm9000_ioctl,    .ndo_validate_addr = eth_validate_addr,    .ndo_set_mac_address = eth_mac_addr,};

网络数据包:
Linux内核中的每个网络数据包都由一个套接字缓冲区结构 struct sk_buff 描述,即一个 sk _ buff 结构就是一个网络包,指向sk_buff 的指针通常被称做skb

网卡驱动模型

网卡初始化:
这里写图片描述

数据发送:
这里写图片描述

数据接收:
这里写图片描述

回环网卡驱动设计

#include <linux/kernel.h>#include <linux/module.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/if_ether.h> /* For the statistics structure. */unsigned long bytes = 0;unsigned long packets = 0;static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)//数据发送函数,skb是数据包{    //对于回环网卡,不需要暂停和重启协议栈发送数据,也不需要写入和释放skb    skb->protocol = eth_type_trans(skb,dev);//标明协议    bytes += skb->len;//数据量    packets++;        //包的数目    netif_rx(skb);    //将包发走    return 0;        }static struct net_device_stats *loopback_get_stats(struct net_device *dev)//获取网卡状态信息{    struct net_device_stats *stats = &dev->stats;       stats->rx_packets = packets;    stats->tx_packets = packets;    stats->rx_bytes = bytes;    stats->tx_bytes = bytes;    return stats;}//定义ops结构static const struct net_device_ops loopback_ops = {    .ndo_start_xmit= loopback_xmit, //发送函数    .ndo_get_stats = loopback_get_stats, //获取网卡状态};static void loopback_setup(struct net_device *dev) //2、初始化net_device结构{    dev->mtu         =  (16 * 1024) + 20 + 20 + 12; //网卡能接受的包的最大尺寸,16K数据+tcp头+ip头+以太网头    dev->flags       =  IFF_LOOPBACK;    //回环网卡专有标志    dev->header_ops  =  &eth_header_ops; //构造头的函数,系统已经提供    dev->netdev_ops  =  &loopback_ops;   //回环网卡的操作集}/* Setup and register the loopback device. */static __net_init int loopback_net_init(struct net *net) //入口函数{    struct net_device *dev;    //1、分配 net_device 结构  2、初始化 net_device 结构    dev = alloc_netdev(0, "lo", loopback_setup);     //3、回环网卡没有硬件结构,不需要初始化硬件    //4、注册网卡驱动    register_netdev(dev);    net->loopback_dev = dev;    return 0;}static __net_exit void loopback_net_exit(struct net *net)//出口函数{    struct net_device *dev = net->loopback_dev;    unregister_netdev(dev); //注销 dev 结构}/* Registered in net/core/dev.c */struct pernet_operations __net_initdata loopback_net_ops = {    .init = loopback_net_init,    .exit = loopback_net_exit,};

DM9000网卡驱动设计

参考内核源代码:linux-ok6410\drivers\net\dm9000.c
和 linux-ok6410\drivers\net\dm9000.h

DM9000网卡 数据发送 代码:

//dm9000芯片的发送数据代码static int dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev){    board_info_t *db = netdev_priv(dev);    //1、通知协议栈,暂停向驱动发送数据    netif_stop_queue(dev);    //2、将skb中的数据写入寄存器    iow(db, DM9000_TXPLL, skb -> len);    iow(db, DM9000_TXPLH, skb -> len >> 8);    writeb(DM9000_MWCMD, db->io_addr);    (db->outblk)(db->io_data, skb->data, skb->len);    iow(db, DM9000_TCR, TCR_TXREQ);    //3、释放skb    dev_kfree_skb(skb);    //4、通知协议栈继续发送数据,在中断处理函数中写,不在这个函数中    return 0;}
原创粉丝点击