一、dm9000_probe函数为网卡初始化函数,在加载驱动模块时执行,完成设备初始化及网络设备注册到系统
dm9000_probe:
ndev = alloc_etherdev(sizeof(struct board_info)); //net_device分配与初始化
db = netdev_priv(ndev); //网卡硬件信息初始化
db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);//地址资源获取
db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
db->irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);//中断号获取与初始化
db->addr_req = request_mem_region(db->addr_res->start, iosize, pdev->name);//向内核申请物理资源
db->io_addr = ioremap(db->addr_res->start, iosize); //网卡中指令缓存(基地址)映射为虚拟地址
db->data_req = request_mem_region(db->data_res->start, iosize, pdev->name);
db->io_data = ioremap(db->data_res->start, iosize); //网卡中数据缓存(网卡接收和发送暂存)映射为虚拟地址
ndev->netdev_ops = &dm9000_netdev_ops; //初始化 如 ndo_open、ndo_stop、ndo_start_xmit= dm9000_start_xmit
register_netdevice //注册网络设备驱动
二、dm9000_open函数开启网卡 ifconfig eth0 up最终会执行此函数
dm9000_open:
request_irq(dev->irq, &dm9000_interrupt, irqflags, dev->name, dev) //注册中断处理函数
netif_start_queue(dev); //使能上层(协议栈)调用设备hard_start_xmit功能 ip层dev_queue_xmit调用dm9000_start_xmit
三、dm9000_start_xmit是网卡设备发送函数
dm9000_start_xmit:
/* Move data to DM9000 TX RAM */
writeb(DM9000_MWCMD, db->io_addr); //写入指令到io_addr
(db->outblk)(db->io_data, skb->data, skb->len); //发送data到io_data
dm9000_send_packet
iow(dm, DM9000_TXPLL, pkt_len); //writeb(reg, db->io_addr); writeb(value, db->io_data); 设置发送大小低位
iow(dm, DM9000_TXPLH, pkt_len >> 8); //设置发送大小高位
/* Issue TX polling command */
iow(dm, DM9000_TCR, TCR_TXREQ); //发送及清除
四、dm9000_interrupt //接收中断处理函数 ,数据到来触发中断,cpu执行此函数
dm9000_interrupt
dm9000_rx(dev)
dev_alloc_skb //分配sk_buff套接字缓冲区
rdptr = (u8 *) skb_put(skb, RxLen - 4)
(db->inblk)(db->io_data, rdptr, RxLen)//写入缓存 dm9000_inblk_16bit
netif_rx(skb) //传送到协议栈
__skb_queue_tail(&queue->input_pkt_queue, skb);//softnet_data队列,是数据链路层中的数据结构,它是一个Per-CPU变量,每个CPU都有一个
local_irq_restore(flags); //恢复本地cpu中断
napi_schedule(&queue->backlog); //对软中断进行调度
__raise_softirq_irqoff(NET_RX_SOFTIRQ); //主动唤起一个软中断