网卡驱动程序设计

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;
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值