网卡驱动程序设计---网络子系统深入分析以及DM9000网卡驱动实现

网络子系统:

比如网络编程里面通过socket创建好了一个文件操作符,然后对其进行write操作,这个write对应的入口其实是一个socket_file_ops结构对应的函数操作集:

网卡驱动程序设计---网络子系统深入分析以及DM9000网卡驱动实现_第1张图片

可以看到write对应的入口函数是sock_aio_write函数


这个函数又对应着do_sock_write


一层又一层,这个函数又调用了__sock_sendmsg函数,下面来看看这个函数


总结一下,这里write调用了sock_aio_write,然后sock_aio_write调用了do_sock_write,然后do_sock_write又调用了__sock_sendmsg函数,其实这三个函数是属于SCI层和协议无关层,(系统调用接口层、协议无关层、协议栈、设备无关层、设备驱动层,网络子系统)


网卡数据的发送流程图:

网卡驱动程序设计---网络子系统深入分析以及DM9000网卡驱动实现_第2张图片

网卡数据接收架构分析流程图:



下面来逐步深入分析DM9000网卡驱动,首先还是先找到驱动的入口函数dm9000.c中的module_init


可以看到dm9000_init函数里面实际上是注册了一个平台设备驱动,也就是说网卡驱动实际上是一平台驱动的方式来编写的,还记得之前说到的probe函数吗?和设备进行一个匹配,当匹配的上的时候就会执行一些相应的操作

网卡驱动程序设计---网络子系统深入分析以及DM9000网卡驱动实现_第3张图片

网卡驱动程序设计---网络子系统深入分析以及DM9000网卡驱动实现_第4张图片

上图中第一个箭头指向的部分可以看到dm9000_probe这个函数内部第一步就是分配一个net_device结构!这个可以结和上篇博客的来对照着看!

接着比较重要的一步是获取相关资源:


这里先来分析一下上面的资源!可以看到这里取出了基地址、数据、中断号。结合前面的驱动基础可以知道,平台驱动和平台设备是通过设备的name来进行匹配的!从上面的struct platform_driver dm9000_driver这个结构体中可以看到.name =dm9000,也就说在这个平台设备对于的.name为dm9000,那么对应的平台驱动肯定也有一个与之对应的dm9000(这里要分清平台设备,平台驱动之间的区别和关系,平台设备指的像这里分析的网卡,平台驱动是一种驱动模型,也可以理解为一种总线模型),直接在内核源码中搜索dm9000,可以找到如下一个结构体:

网卡驱动程序设计---网络子系统深入分析以及DM9000网卡驱动实现_第5张图片

对比着之前的平台设备驱动(上图是平台驱动)里面的一个结构体看看:

网卡驱动程序设计---网络子系统深入分析以及DM9000网卡驱动实现_第6张图片

平台设备驱动和平台驱动就是通过名字来匹配的,当然这里我先来重点关心一下.resource = dm9000_resources

先来瞅瞅里面的资源:


然后下面接着比较重要的一步是将获取到的地址使用ioremap进行映射:

db->io_addr = ioremap(db->addr_res->start, iosize);

分析过程实在是太长了!(未完,待续。。。)

其实呢?linux驱动基本上可以分为两个部分,一个就是linux驱动模型,一个就是裸机驱动硬件操作部分,将这两个结合就是Linux驱动了!前边的裸机驱动的博客还没写!这里先只实现一部分,发送部分代码,修改还是参照之前的分析流程来的:

/*
 *  Hardware start transmission.
 *  Send a packet to media from the upper layer.
 */
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_TCREQ);//启动发送

	//3. 释放skb
	dev_kfree_skb(skb);

	return NETDEV_TX_OK;
}


1. 通知协议栈,暂停向驱动传送数据

2. 将skb中的数据写入寄存器

3. 释放skb

4. 在发送中断处理程序中通知协议栈发送数据//这个前边也分析了的
一个子系统的驱动的学习时间还是相当漫长的!看来绝不是短期内能掌握的!这里先记一部分笔记,后边回过头来逐步深入研究,这里笔记也只是记录相当小的一部分知识,网络子系统知识实在是有点庞大,想吃透还是要费点脑壳的(未完,后边持续更新完善本篇笔记。。。)




你可能感兴趣的:(linux,ARM,linux驱动,dm9000,网卡驱动笔记)