【linux驱动分析】之dm9000驱动分析(一):dm9000原理及硬件分析
【linux驱动分析】之dm9000驱动分析(一):dm9000原理及硬件分析
【linux驱动分析】之dm9000驱动分析(二):定义在板文件中的资源和设备以及几个宏
【linux驱动分析】之dm9000驱动分析(三):sk_buff结构分析
【linux驱动分析】之dm9000驱动分析(四):net_device结构体
【linux驱动分析】之dm9000驱动分析(五):另外几个重要的结构体
【linux驱动分析】之dm9000驱动分析(六):dm9000_init和dm9000_probe的实现
【linux驱动分析】之dm9000驱动分析(七):dm9000的卸载挂起和恢复以及打开和停止
一、了解几个概念
1、MAC
MAC是Media Access Control 的缩写,即媒体访问控制子层协议,又翻译为媒体接入控制器。
该协议位于OSI七层协议中数据链路层的下半部分,主要负责控制与连接物理层的物理介质。在发送数据的时候,MAC协议可以事先判断是否可以发送数据,如果可以发送将给数据加上一些控制信息,最终将数据以及控制信息以规定的格式发送到物理层;在接收数据的时候,MAC协议首先判断输入的信息并是否发生传输错误,如果没有错误,则去掉控制信息发送至LLC层。以太网MAC由IEEE-802.3以太网标准定义。
2、MII
MII即媒体独立接口, “媒体独立”表明在不对MAC硬件重新设计或替换的情况下,任何类型的PHY设备都可以正常工作。包括分别用于发送器和接收器的两条独立信道。每条信道都有自己的数据、时钟和控制信号。MII数据接口总共需要16个信号,包括TX_ER,TXD<3:0>,TX_EN,TX_CLK,COL,RXD<3:0>,RX_EX,RX_CLK,CRS,RX_DV等。
MII以4位半字节方式传送数据双向传输,时钟速率25MHz。其工作速率可达100Mb/s。MII管理接口是个双信号接口,一个是时钟信号,另一个是数据信号。通过管理接口,上层能监视和控制PHY。其管理是使用SMI(Serial Management Interface)总线通过读写PHY的寄存器来完成的。PHY里面的部分寄存器是IEEE定义的,这样PHY把自己的目前的状态反映到寄存器里面,MAC通过SMI总线不断的读取PHY的状态寄存器以得知目前PHY的状态,例如连接速度,双工的能力等。当然也可以通过SMI设置PHY的寄存器达到控制的目的,例如流控的打开关闭,自协商模式还是强制模式等。不论是物理连接的MII总线和SMI总线还是PHY的状态寄存器和控制寄存器都是有IEEE的规范的,因此不同公司的MAC和PHY一样可以协调工作。当然为了配合不同公司的PHY的自己特有的一些功能,驱动需要做相应的修改。
3、PHY
PHY是物理接口收发器,它实现物理层。包括MII/GMII(介质独立接口)子层、PCS(物理编码子层)、PMA(物理介质附加)子层、PMD(物理介质相关)子层、MDI子层。
100BaseTX采用4B/5B编码。PHY在发送数据的时候,收到MAC过来的数据(对PHY来说,没有帧的概念,对它来说,都是数据而不管什么地址,数据还是CRC),每4bit就增加1bit的检错码,然后把并行数据转化为串行流数据,再按照物理层的编码规则把数据编码,再变为模拟信号把数据送出去。收数据时的流程反之。PHY还有个重要的功能就是实现CSMA/CD的部分功能。它可以检测到网络上是否有数据在传送,如果有数据在传送中就等待,一旦检测到网络空闲,再等待一个随机时间后将送数据出去。如果两个碰巧同时送出了数据,那样必将造成冲突,这时候,冲突检测机构可以检测到冲突,然后各等待一个随机的时间重新发送数据。这个随机时间很有讲究的,并不是一个常数,在不同的时刻计算出来的随机时间都是不同的,而且有多重算法来应付出现概率很低的同两台主机之间的第二次冲突。通信速率通过双方协商,协商的结果是两个设备中能同时支持的最大速度和最好的双工模式。这个技术被称为Auto Negotiation或者NWAY。隔离变压器把PHY送出来的差分信号用差模耦合的线圈耦合滤波以增强信号,并且通过电磁场的转换耦合到连接网线的另外一端。RJ-45中1、2是传送数据的,3、6是接收数据的。新的PHY支持AUTO MDI-X功能(也需要隔离变压器支持)。它可以实现RJ-45接口的1、2上的传送信号线和3、6上的接收信号线的功能自动互相交换
网卡工作在osi的最后两层,物理层和数据链路层,物理层定义了数据传送与接收所需要的电与光信号、线路状态、时钟基准、数据编码和电路等,并向数据链路层设备提供标准接口。物理层的芯片称之为PHY。数据链路层则提供寻址机构、数据帧的构建、数据差错检查、传送控制、向网络层提供标准的数据接口等功能。以太网卡中数据链路层的芯片称之为MAC控制器。很多网卡的这两个部分是做到一起的。他们之间的关系是pci总线接mac总线,mac接phy,phy接网线(当然也不是直接接上的,还有一个变压装置)。
MAC 和PHY 一个是数据链路层 一个是物理层 两者通过MII传送数据。
4、曼彻斯特编码
曼彻斯特编码又称曼彻斯特相位编码,它通过相位变化来实现每个位(图2)。通常,用一个时钟周期中部的上升沿表示“1”,下降沿表示“0”。周期末端的相位变化可忽略不计,但有时又可能需要将这种相位变化计算在内,这取决于前一位的值。
5、4B/5B编码
4B/5B编码是一种块编码方式。它将一个4位的块编码成一个5位的块。这就使5位块内永远至少包含2个“1”转换,所以在一个5位块内总能进行时钟同步。该方法需要25%的额外开销。
二、DM9000
1、框图
2、芯片引脚图
MII接口和32位总线模式可以配置
(1)、MII接口
(2)、32位数据总线
【linux驱动分析】之dm9000驱动分析(二):定义在板文件中的资源和设备以及几个宏
硬件平台:友善之臂Tiny6410核心板 + DM9000EP
软件平台:linux-2.6.38
交叉编译器:Friendly ARM提供的arm-linux-gcc 4.5.1
一、源代码(mach-mini6410.c)
1 /* Ethernet */ 2 #ifdef CONFIG_DM9000 3 #define S3C64XX_PA_DM9000 (0x18000000) 4 #define S3C64XX_SZ_DM9000 SZ_1M 5 #define S3C64XX_VA_DM9000 S3C_ADDR(0x03b00300) 6 7 static struct resource dm9000_resources[] = { 8 [0] = { 9 .start = S3C64XX_PA_DM9000, 10 .end = S3C64XX_PA_DM9000 + 3, 11 .flags = IORESOURCE_MEM, 12 }, 13 [1] = { 14 .start = S3C64XX_PA_DM9000 + 4, 15 .end = S3C64XX_PA_DM9000 + S3C64XX_SZ_DM9000 - 1, 16 .flags = IORESOURCE_MEM, 17 }, 18 [2] = { 19 .start = IRQ_EINT(7), 20 .end = IRQ_EINT(7), 21 .flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH, 22 }, 23 }; 24 25 static struct dm9000_plat_data dm9000_setup = { 26 .flags = DM9000_PLATF_16BITONLY | DM9000_PLATF_EXT_PHY, 27 .dev_addr = { 0x08, 0x90, 0x00, 0xa0, 0x90, 0x90 }, 28 }; 29 30 static struct platform_device s3c_device_dm9000 = { 31 .name = "dm9000", 32 .id = 0, 33 .num_resources = ARRAY_SIZE(dm9000_resources), 34 .resource = dm9000_resources, 35 .dev = { 36 .platform_data = &dm9000_setup, 37 } 38 }; 39 40 static int __init dm9000_set_mac(char *str) { 41 unsigned char addr[6]; 42 unsigned int val; 43 int idx = 0; 44 char *p = str, *end; 45 46 while (*p && idx < 6) { 47 val = simple_strtoul(p, &end, 16); 48 if (end <= p) { 49 /* convert failed */ 50 break; 51 } else { 52 addr[idx++] = val; 53 p = end; 54 if (*p == ':'|| *p == '-') { 55 p++; 56 } else { 57 break; 58 } 59 } 60 } 61 62 if (idx == 6) { 63 printk("Setup ethernet address to %pM\n", addr); 64 memcpy(dm9000_setup.param_addr, addr, 6); 65 } 66 67 return 1; 68 } 69 70 __setup("ethmac=", dm9000_set_mac); 71 #endif 72 73 static struct map_desc mini6410_iodesc[] = { 74 { 75 /* LCD support */ 76 .virtual = (unsigned long)S3C_VA_LCD, 77 .pfn = __phys_to_pfn(S3C_PA_FB), 78 .length = SZ_16K, 79 .type = MT_DEVICE, 80 }, 81 #ifdef CONFIG_DM9000 /*这里的定义不知道是做什么用的*/ 82 { 83 .virtual = (u32)S3C64XX_VA_DM9000, 84 .pfn = __phys_to_pfn(S3C64XX_PA_DM9000), 85 .length = S3C64XX_SZ_DM9000, 86 .type = MT_DEVICE, 87 }, 88 #endif 89 };
DM9000的设备会在
platform_add_devices(mini6410_devices, ARRAY_SIZE(mini6410_devices));
里统一注册。
二、下面分析一下上面代码中红色的宏或者函数
1、ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof( (arr)[0] ) + __must_be_array(arr) )
它是定义在include/linux/kernel.h中的一个宏,用来计算数组中元素的个数。
__must_be_array是编译器相关的,用来防止传入的参数不是数组,比如说传入了指针,这样的话可能回编译不通过(猜测)。
2、simple_strtoul
/** * simple_strtoul - convert a string to an unsigned long * @cp: The start of the string * @endp: A pointer to the end of the parsed string will be placed here * @base: The number base to use */ unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
simple_strtoul是定义在lib/vsprintf.c中的函数,它的作用是把一个字符串转换为unsigned long型的整数,并返回。
其中的endp参数存放解析后的字符串地址,base参数,是要转换的进制数。
vsprintf.c里还定义了其他好多字符串处理的函数,具体用到时去查。
3、__setup
它是定义在include/linux/init.h中的一个宏:
#define __setup(str, fn) \ __setup_param(str, fn, fn, 0)
其中:str是关键字,fn是关联处理函数。__setup只是告诉内核在启动时输入串中含有str时,内核要去执行fn。Str必须以“=”符结束以使parse_args更方便解析。紧随“=”后的任何文本都会作为输入传给fn。
例如本例中的:__setup("ethmac=", dm9000_set_mac);关于__setup的更多分析见《__setup宏的作用》
【linux驱动分析】之dm9000驱动分析(三):sk_buff结构分析
源码分析
sk_buff_head和sk_buff定义在include/linux/skbuff.h中,下面是linux-2.6.38中的定义。
1、在内核中sk_buff是一个网络数据包,它是一个双向链表,而链表头就是sk_buff_head。
而sk_buff的内存布局可以分作3个段,第一个就是sk_buff自身,第二个是linear-data buff,第三个是paged-data buff(也就是skb_shared_info)。 先来看一下sk_buff_head:
struct sk_buff_head { /* These two members must be first. */ struct sk_buff *next; struct sk_buff *prev; __u32 qlen; spinlock_t lock; };
这里可以看到前两个域是和sk_buff一致的,而且内核的注释是必须放到最前面。这里的原因是:
这使得两个不同的结构可以放到同一个链表中,尽管sk_buff_head要比sk_buff小巧的多。另外,相同的函数可以同样应用于sk_buff和sk_buff_head。
然后qlen域表示了当前的sk_buff链上包含多少个skb。
lock域是自旋锁。 2、sk_buff结构
1 /** 2 * struct sk_buff - socket buffer 3 * @next: Next buffer in list 4 * @prev: Previous buffer in list 5 * @sk: Socket we are owned by 6 * @tstamp: Time we arrived 7 * @dev: Device we arrived on/are leaving by 8 * @transport_header: Transport layer header 9 * @network_header: Network layer header 10 * @mac_header: Link layer header 11 * @_skb_refdst: destination entry (with norefcount bit) 12 * @sp: the security path, used for xfrm 13 * @cb: Control buffer. Free for use by every layer. Put private vars here 14 * @len: Length of actual data 15 * @data_len: Data length 16 * @mac_len: Length of link layer header 17 * @hdr_len: writable header length of cloned skb 18 * @csum: Checksum (must include start/offset pair) 19 * @csum_start: Offset from skb->head where checksumming should start 20 * @csum_offset: Offset from csum_start where checksum should be stored 21 * @local_df: allow local fragmentation 22 * @cloned: Head may be cloned (check refcnt to be sure) 23 * @nohdr: Payload reference only, must not modify header 24 * @pkt_type: Packet class 25 * @fclone: skbuff clone status 26 * @ip_summed: Driver fed us an IP checksum 27 * @priority: Packet queueing priority 28 * @users: User count - see {datagram,tcp}.c 29 * @protocol: Packet protocol from driver 30 * @truesize: Buffer size 31 * @head: Head of buffer 32 * @data: Data head pointer 33 * @tail: Tail pointer 34 * @end: End pointer 35 * @destructor: Destruct function 36 * @mark: Generic packet mark 37 * @nfct: Associated connection, if any 38 * @ipvs_property: skbuff is owned by ipvs 39 * @peeked: this packet has been seen already, so stats have been 40 * done for it, don't do them again 41 * @nf_trace: netfilter packet trace flag 42 * @nfctinfo: Relationship of this skb to the connection 43 * @nfct_reasm: netfilter conntrack re-assembly pointer 44 * @nf_bridge: Saved data about a bridged frame - see br_netfilter.c 45 * @skb_iif: ifindex of device we arrived on 46 * @rxhash: the packet hash computed on receive 47 * @queue_mapping: Queue mapping for multiqueue devices 48 * @tc_index: Traffic control index 49 * @tc_verd: traffic control verdict 50 * @ndisc_nodetype: router type (from link layer) 51 * @dma_cookie: a cookie to one of several possible DMA operations 52 * done by skb DMA functions 53 * @secmark: security marking 54 * @vlan_tci: vlan tag control information 55 */ 56 57 struct sk_buff { 58 /* These two members must be first. */ 59 struct sk_buff *next; 60 struct sk_buff *prev; 61 62 //表示这个skb被接收的时间。 63 ktime_t tstamp; 64 //表示从属于那个socket,主要是被4层用到 65 struct sock *sk; 66 /*这个表示一个网络设备,当skb为输出时它表示skb将要输出的设备,当接收时,它表示输入设备。 67 * 要注意,这个设备有可能会是虚拟设备(在3层以上看来) 68 */ 69 struct net_device *dev; 70 71 /* 72 * This is the control buffer. It is free to use for every 73 * layer. Please put your private variables there. If you 74 * want to keep them across layers you have to do a skb_clone() 75 * first. This is owned by whoever has the skb queued ATM. 76 */ 77 char cb[48] __aligned(8); 78 ///这里其实应该是dst_entry类型,不知道为什么内核要改为ul。这个域主要用于路由子系统。 79 //这个数据结构保存了一些路由相关信息 80 unsigned long _skb_refdst; 81 #ifdef CONFIG_XFRM 82 struct sec_path *sp; 83 #endif 84 ///这个长度表示当前的skb中的数据的长度,这个长度即包括buf中的数据也包括切片的数据, 85 //也就是保存在skb_shared_info中的数据。这个值是会随着从一层到另一层而改变的。下面我们会对比这几个长度的。 86 unsigned int len, 87 ///这个长度只表示切片数据的长度,也就是skb_shared_info中的长度 88 data_len; 89 //链路层头部的长度 90 __u16 mac_len, 91 //这个主要用于clone的时候,它表示clone的skb的头的长度 92 hdr_len; 93 //接下来是校验相关的域 94 union { 95 __wsum csum; 96 struct { 97 __u16 csum_start; 98 __u16 csum_offset; 99 }; 100 }; 101 __u32 priority; 102 kmemcheck_bitfield_begin(flags1); 103 //首先是是否可以本地切片的标志。 104 __u8 local_df:1, 105 //为1说明头可能已被clone 106 cloned:1, 107 //这个表示校验相关的一个标记,表示硬件驱动是否为我们已经进行了校验 108 ip_summed:2, 109 //这个域如果为1,则说明这个skb的头域指针已经分配完毕,因此这个时候计算头的长度只需要head和data的差就可以了。 110 nohdr:1, 111 nfctinfo:3; 112 //pkt_type主要是表示数据包的类型,比如多播,单播,回环等等 113 __u8 pkt_type:3, 114 //这个域是一个clone标记。主要是在fast clone中被设置,我们后面讲到fast clone时会详细介绍这个域 115 fclone:2, 116 //ipvs拥有的域 117 ipvs_property:1, 118 //这个包已经被查看过了 119 peeked:1, 120 //netfilter使用的域。是一个trace 标记 121 nf_trace:1; 122 kmemcheck_bitfield_end(flags1); 123 __be16 protocol; 124 //skb的析构函数,一般都是设置为sock_rfree或者sock_wfree 125 void (*destructor)(struct sk_buff *skb); 126 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) 127 struct nf_conntrack *nfct; 128 #endif 129 #ifdef NET_SKBUFF_NF_DEFRAG_NEEDED 130 struct sk_buff *nfct_reasm; 131 #endif 132 #ifdef CONFIG_BRIDGE_NETFILTER 133 struct nf_bridge_info *nf_bridge; 134 #endif 135 //接收设备的index 136 int skb_iif; 137 138 //流量控制的相关域 139 #ifdef CONFIG_NET_SCHED 140 __u16 tc_index; /* traffic control index */ 141 #ifdef CONFIG_NET_CLS_ACT 142 __u16 tc_verd; /* traffic control verdict */ 143 #endif 144 #endif 145 146 __u32 rxhash; 147 148 kmemcheck_bitfield_begin(flags2); 149 //多队列设备的映射,也就是说映射到那个队列 150 __u16 queue_mapping:16; 151 #ifdef CONFIG_IPV6_NDISC_NODETYPE 152 __u8 ndisc_nodetype:2, 153 deliver_no_wcard:1; 154 #else 155 __u8 deliver_no_wcard:1; 156 #endif 157 __u8 ooo_okay:1; 158 kmemcheck_bitfield_end(flags2); 159 160 /* 0/13 bit hole */ 161 162 #ifdef CONFIG_NET_DMA 163 dma_cookie_t dma_cookie; 164 #endif 165 #ifdef CONFIG_NETWORK_SECMARK 166 __u32 secmark; 167 #endif 168 union { 169 //skb的标记 170 __u32 mark; 171 __u32 dropcount; 172 }; 173 //vlan的控制tag 174 __u16 vlan_tci; 175 //传输层的头 176 sk_buff_data_t transport_header; 177 //网络层的头 178 sk_buff_data_t network_header; 179 //链路层的头 180 sk_buff_data_t mac_header; 181 /* These elements must be at the end, see alloc_skb() for details. */ 182 sk_buff_data_t tail; 183 sk_buff_data_t end; 184 unsigned char *head, 185 *data; 186 //这个表示整个skb的大小,包括skb本身,以及数据 187 unsigned int truesize; 188 //skb的引用计数 189 atomic_t users; 190 };
【linux驱动分析】之dm9000驱动分析(四):net_device结构体
net_device结构体,定义在include/linux/netdevice.h中,这是一个很复杂的结构体,先把代码清单列出来,再用到的过程中,逐步分析,最后来这里做个总结。
下面的代码是linux-2.6.38中的。
1 /* 2 * The DEVICE structure. 3 * Actually, this whole structure is a big mistake. It mixes I/O 4 * data with strictly "high-level" data, and it has to know about 5 * almost every data structure used in the INET module. 6 * 7 * FIXME: cleanup struct net_device such that network protocol info 8 * moves out. 9 */ 10 11 struct net_device { 12 13 /* 14 * This is the first field of the "visible" part of this structure 15 * (i.e. as seen by users in the "Space.c" file). It is the name 16 * of the interface. 17 */ 18 char name[IFNAMSIZ]; 19 20 struct pm_qos_request_list pm_qos_req; 21 22 /* device name hash chain */ 23 struct hlist_node name_hlist; 24 /* snmp alias */ 25 char *ifalias; 26 27 /* 28 * I/O specific fields 29 * FIXME: Merge these and struct ifmap into one 30 */ 31 unsigned long mem_end; /* shared mem end */ 32 unsigned long mem_start; /* shared mem start */ 33 unsigned long base_addr; /* device I/O address */ 34 unsigned int irq; /* device IRQ number */ 35 36 /* 37 * Some hardware also needs these fields, but they are not 38 * part of the usual set specified in Space.c. 39 */ 40 41 unsigned char if_port; /* Selectable AUI, TP,..*/ 42 unsigned char dma; /* DMA channel */ 43 44 unsigned long state; 45 46 struct list_head dev_list; 47 struct list_head napi_list; 48 struct list_head unreg_list; 49 50 /* Net device features */ 51 unsigned long features; 52 #define NETIF_F_SG 1 /* Scatter/gather IO. */ 53 #define NETIF_F_IP_CSUM 2 /* Can checksum TCP/UDP over IPv4. */ 54 #define NETIF_F_NO_CSUM 4 /* Does not require checksum. F.e. loopack. */ 55 #define NETIF_F_HW_CSUM 8 /* Can checksum all the packets. */ 56 #define NETIF_F_IPV6_CSUM 16 /* Can checksum TCP/UDP over IPV6 */ 57 #define NETIF_F_HIGHDMA 32 /* Can DMA to high memory. */ 58 #define NETIF_F_FRAGLIST 64 /* Scatter/gather IO. */ 59 #define NETIF_F_HW_VLAN_TX 128 /* Transmit VLAN hw acceleration */ 60 #define NETIF_F_HW_VLAN_RX 256 /* Receive VLAN hw acceleration */ 61 #define NETIF_F_HW_VLAN_FILTER 512 /* Receive filtering on VLAN */ 62 #define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */ 63 #define NETIF_F_GSO 2048 /* Enable software GSO. */ 64 #define NETIF_F_LLTX 4096 /* LockLess TX - deprecated. Please */ 65 /* do not use LLTX in new drivers */ 66 #define NETIF_F_NETNS_LOCAL 8192 /* Does not change network namespaces */ 67 #define NETIF_F_GRO 16384 /* Generic receive offload */ 68 #define NETIF_F_LRO 32768 /* large receive offload */ 69 70 /* the GSO_MASK reserves bits 16 through 23 */ 71 #define NETIF_F_FCOE_CRC (1 << 24) /* FCoE CRC32 */ 72 #define NETIF_F_SCTP_CSUM (1 << 25) /* SCTP checksum offload */ 73 #define NETIF_F_FCOE_MTU (1 << 26) /* Supports max FCoE MTU, 2158 bytes*/ 74 #define NETIF_F_NTUPLE (1 << 27) /* N-tuple filters supported */ 75 #define NETIF_F_RXHASH (1 << 28) /* Receive hashing offload */ 76 77 /* Segmentation offload features */ 78 #define NETIF_F_GSO_SHIFT 16 79 #define NETIF_F_GSO_MASK 0x00ff0000 80 #define NETIF_F_TSO (SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT) 81 #define NETIF_F_UFO (SKB_GSO_UDP << NETIF_F_GSO_SHIFT) 82 #define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT) 83 #define NETIF_F_TSO_ECN (SKB_GSO_TCP_ECN << NETIF_F_GSO_SHIFT) 84 #define NETIF_F_TSO6 (SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT) 85 #define NETIF_F_FSO (SKB_GSO_FCOE << NETIF_F_GSO_SHIFT) 86 87 /* List of features with software fallbacks. */ 88 #define NETIF_F_GSO_SOFTWARE (NETIF_F_TSO | NETIF_F_TSO_ECN | \ 89 NETIF_F_TSO6 | NETIF_F_UFO) 90 91 92 #define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM) 93 #define NETIF_F_V4_CSUM (NETIF_F_GEN_CSUM | NETIF_F_IP_CSUM) 94 #define NETIF_F_V6_CSUM (NETIF_F_GEN_CSUM | NETIF_F_IPV6_CSUM) 95 #define NETIF_F_ALL_CSUM (NETIF_F_V4_CSUM | NETIF_F_V6_CSUM) 96 97 /* 98 * If one device supports one of these features, then enable them 99 * for all in netdev_increment_features. 100 */ 101 #define NETIF_F_ONE_FOR_ALL (NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ROBUST | \ 102 NETIF_F_SG | NETIF_F_HIGHDMA | \ 103 NETIF_F_FRAGLIST) 104 105 /* Interface index. Unique device identifier */ 106 int ifindex; 107 int iflink; 108 109 struct net_device_stats stats; 110 atomic_long_t rx_dropped; /* dropped packets by core network 111 * Do not use this in drivers. 112 */ 113 114 #ifdef CONFIG_WIRELESS_EXT 115 /* List of functions to handle Wireless Extensions (instead of ioctl). 116 * See <net/iw_handler.h> for details. Jean II */ 117 const struct iw_handler_def * wireless_handlers; 118 /* Instance data managed by the core of Wireless Extensions. */ 119 struct iw_public_data * wireless_data; 120 #endif 121 /* Management operations */ 122 const struct net_device_ops *netdev_ops; 123 const struct ethtool_ops *ethtool_ops; 124 125 /* Hardware header description */ 126 const struct header_ops *header_ops; 127 128 unsigned int flags; /* interface flags (a la BSD) */ 129 unsigned short gflags; 130 unsigned int priv_flags; /* Like 'flags' but invisible to userspace. */ 131 unsigned short padded; /* How much padding added by alloc_netdev() */ 132 133 unsigned char operstate; /* RFC2863 operstate */ 134 unsigned char link_mode; /* mapping policy to operstate */ 135 136 unsigned int mtu; /* interface MTU value */ 137 unsigned short type; /* interface hardware type */ 138 unsigned short hard_header_len; /* hardware hdr length */ 139 140 /* extra head- and tailroom the hardware may need, but not in all cases 141 * can this be guaranteed, especially tailroom. Some cases also use 142 * LL_MAX_HEADER instead to allocate the skb. 143 */ 144 unsigned short needed_headroom; 145 unsigned short needed_tailroom; 146 147 /* Interface address info. */ 148 unsigned char perm_addr[MAX_ADDR_LEN]; /* permanent hw address */ 149 unsigned char addr_assign_type; /* hw address assignment type */ 150 unsigned char addr_len; /* hardware address length */ 151 unsigned short dev_id; /* for shared network cards */ 152 153 spinlock_t addr_list_lock; 154 struct netdev_hw_addr_list uc; /* Unicast mac addresses */ 155 struct netdev_hw_addr_list mc; /* Multicast mac addresses */ 156 int uc_promisc; 157 unsigned int promiscuity; 158 unsigned int allmulti; 159 160 161 /* Protocol specific pointers */ 162 163 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) 164 struct vlan_group __rcu *vlgrp; /* VLAN group */ 165 #endif 166 #ifdef CONFIG_NET_DSA 167 void *dsa_ptr; /* dsa specific data */ 168 #endif 169 void *atalk_ptr; /* AppleTalk link */ 170 struct in_device __rcu *ip_ptr; /* IPv4 specific data */ 171 struct dn_dev __rcu *dn_ptr; /* DECnet specific data */ 172 struct inet6_dev __rcu *ip6_ptr; /* IPv6 specific data */ 173 void *ec_ptr; /* Econet specific data */ 174 void *ax25_ptr; /* AX.25 specific data */ 175 struct wireless_dev *ieee80211_ptr; /* IEEE 802.11 specific data, 176 assign before registering */ 177 178 /* 179 * Cache lines mostly used on receive path (including eth_type_trans()) 180 */ 181 unsigned long last_rx; /* Time of last Rx 182 * This should not be set in 183 * drivers, unless really needed, 184 * because network stack (bonding) 185 * use it if/when necessary, to 186 * avoid dirtying this cache line. 187 */ 188 189 struct net_device *master; /* Pointer to master device of a group, 190 * which this device is member of. 191 */ 192 193 /* Interface address info used in eth_type_trans() */ 194 unsigned char *dev_addr; /* hw address, (before bcast 195 because most packets are 196 unicast) */ 197 198 struct netdev_hw_addr_list dev_addrs; /* list of device 199 hw addresses */ 200 201 unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */ 202 203 #ifdef CONFIG_RPS 204 struct kset *queues_kset; 205 206 struct netdev_rx_queue *_rx; 207 208 /* Number of RX queues allocated at register_netdev() time */ 209 unsigned int num_rx_queues; 210 211 /* Number of RX queues currently active in device */ 212 unsigned int real_num_rx_queues; 213 #endif 214 215 rx_handler_func_t __rcu *rx_handler; 216 void __rcu *rx_handler_data; 217 218 struct netdev_queue __rcu *ingress_queue; 219 220 /* 221 * Cache lines mostly used on transmit path 222 */ 223 struct netdev_queue *_tx ____cacheline_aligned_in_smp; 224 225 /* Number of TX queues allocated at alloc_netdev_mq() time */ 226 unsigned int num_tx_queues; 227 228 /* Number of TX queues currently active in device */ 229 unsigned int real_num_tx_queues; 230 231 /* root qdisc from userspace point of view */ 232 struct Qdisc *qdisc; 233 234 unsigned long tx_queue_len; /* Max frames per queue allowed */ 235 spinlock_t tx_global_lock; 236 237 #ifdef CONFIG_XPS 238 struct xps_dev_maps __rcu *xps_maps; 239 #endif 240 241 /* These may be needed for future network-power-down code. */ 242 243 /* 244 * trans_start here is expensive for high speed devices on SMP, 245 * please use netdev_queue->trans_start instead. 246 */ 247 unsigned long trans_start; /* Time (in jiffies) of last Tx */ 248 249 int watchdog_timeo; /* used by dev_watchdog() */ 250 struct timer_list watchdog_timer; 251 252 /* Number of references to this device */ 253 int __percpu *pcpu_refcnt; 254 255 /* delayed register/unregister */ 256 struct list_head todo_list; 257 /* device index hash chain */ 258 struct hlist_node index_hlist; 259 260 struct list_head link_watch_list; 261 262 /* register/unregister state machine */ 263 enum { NETREG_UNINITIALIZED=0, 264 NETREG_REGISTERED, /* completed register_netdevice */ 265 NETREG_UNREGISTERING, /* called unregister_netdevice */ 266 NETREG_UNREGISTERED, /* completed unregister todo */ 267 NETREG_RELEASED, /* called free_netdev */ 268 NETREG_DUMMY, /* dummy device for NAPI poll */ 269 } reg_state:16; 270 271 enum { 272 RTNL_LINK_INITIALIZED, 273 RTNL_LINK_INITIALIZING, 274 } rtnl_link_state:16; 275 276 /* Called from unregister, can be used to call free_netdev */ 277 void (*destructor)(struct net_device *dev); 278 279 #ifdef CONFIG_NETPOLL 280 struct netpoll_info *npinfo; 281 #endif 282 283 #ifdef CONFIG_NET_NS 284 /* Network namespace this network device is inside */ 285 struct net *nd_net; 286 #endif 287 288 /* mid-layer private */ 289 union { 290 void *ml_priv; 291 struct pcpu_lstats __percpu *lstats; /* loopback stats */ 292 struct pcpu_tstats __percpu *tstats; /* tunnel stats */ 293 struct pcpu_dstats __percpu *dstats; /* dummy stats */ 294 }; 295 /* GARP */ 296 struct garp_port __rcu *garp_port; 297 298 /* class/net/name entry */ 299 struct device dev; 300 /* space for optional device, statistics, and wireless sysfs groups */ 301 const struct attribute_group *sysfs_groups[4]; 302 303 /* rtnetlink link ops */ 304 const struct rtnl_link_ops *rtnl_link_ops; 305 306 /* VLAN feature mask */ 307 unsigned long vlan_features; 308 309 /* for setting kernel sock attribute on TCP connection setup */ 310 #define GSO_MAX_SIZE 65536 311 unsigned int gso_max_size; 312 313 #ifdef CONFIG_DCB 314 /* Data Center Bridging netlink ops */ 315 const struct dcbnl_rtnl_ops *dcbnl_ops; 316 #endif 317 318 #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) 319 /* max exchange id for FCoE LRO by ddp */ 320 unsigned int fcoe_ddp_xid; 321 #endif 322 /* n-tuple filter list attached to this device */ 323 struct ethtool_rx_ntuple_list ethtool_ntuple_list; 324 325 /* phy device may attach itself for hardware timestamping */ 326 struct phy_device *phydev; 327 };
【linux驱动分析】之dm9000驱动分析(五):另外几个重要的结构体
除了sk_buff和net_device,dm9000驱动中用到的另外几个重要的结构体
一、platform_driver
定义在include/linux/platform_device.h中,代码如下:
1 struct platform_driver { 2 int (*probe)(struct platform_device *); 3 int (*remove)(struct platform_device *); 4 void (*shutdown)(struct platform_device *); 5 int (*suspend)(struct platform_device *, pm_message_t state); 6 int (*resume)(struct platform_device *); 7 struct device_driver driver; 8 const struct platform_device_id *id_table; 9 };
dm9000.c中的初始化:
1 static struct platform_driver dm9000_driver = { 2 .driver = { 3 .name = "dm9000", 4 .owner = THIS_MODULE, 5 .pm = &dm9000_drv_pm_ops, 6 }, 7 .probe = dm9000_probe, 8 .remove = __devexit_p(dm9000_drv_remove), 9 };
二、net_device_ops
操作网络设备的函数,定义在include/linux/netdevice.h中,它有很多成员,这里只列出dm9000驱动用到的:
1 static const struct net_device_ops dm9000_netdev_ops = { 2 .ndo_open = dm9000_open, 3 .ndo_stop = dm9000_stop, 4 .ndo_start_xmit = dm9000_start_xmit, 5 .ndo_tx_timeout = dm9000_timeout, 6 .ndo_set_multicast_list = dm9000_hash_table, 7 .ndo_do_ioctl = dm9000_ioctl, 8 .ndo_change_mtu = eth_change_mtu, 9 .ndo_validate_addr = eth_validate_addr, 10 .ndo_set_mac_address = eth_mac_addr, 11 #ifdef CONFIG_NET_POLL_CONTROLLER 12 .ndo_poll_controller = dm9000_poll_controller, 13 #endif 14 };
三、ethtool_ops
ethtool_ops定义在include/linux/ethtool.h中,它有很多成员,这里只列出dm9000驱动用到的:
1 static const struct ethtool_ops dm9000_ethtool_ops = { 2 .get_drvinfo = dm9000_get_drvinfo, 3 .get_settings = dm9000_get_settings, 4 .set_settings = dm9000_set_settings, 5 .get_msglevel = dm9000_get_msglevel, 6 .set_msglevel = dm9000_set_msglevel, 7 .nway_reset = dm9000_nway_reset, 8 .get_link = dm9000_get_link, 9 .get_wol = dm9000_get_wol, 10 .set_wol = dm9000_set_wol, 11 .get_eeprom_len = dm9000_get_eeprom_len, 12 .get_eeprom = dm9000_get_eeprom, 13 .set_eeprom = dm9000_set_eeprom, 14 .get_rx_csum = dm9000_get_rx_csum, 15 .set_rx_csum = dm9000_set_rx_csum, 16 .get_tx_csum = ethtool_op_get_tx_csum, 17 .set_tx_csum = dm9000_set_tx_csum, 18 };
四、board_info
用来保存芯片相关的一些信息。
1 /* Structure/enum declaration ------------------------------- */ 2 typedef struct board_info { 3 4 void __iomem *io_addr; /* Register I/O base address */ 5 void __iomem *io_data; /* Data I/O address */ 6 u16 irq; /* IRQ */ 7 8 u16 tx_pkt_cnt; 9 u16 queue_pkt_len; 10 u16 queue_start_addr; 11 u16 queue_ip_summed; 12 u16 dbug_cnt; 13 u8 io_mode; /* 0:word, 2:byte */ 14 u8 phy_addr; 15 u8 imr_all; 16 17 unsigned int flags; 18 unsigned int in_suspend :1; 19 unsigned int wake_supported :1; 20 int debug_level; 21 22 enum dm9000_type type; 23 24 void (*inblk)(void __iomem *port, void *data, int length); 25 void (*outblk)(void __iomem *port, void *data, int length); 26 void (*dumpblk)(void __iomem *port, int length); 27 28 struct device *dev; /* parent device */ 29 30 struct resource *addr_res; /* resources found */ 31 struct resource *data_res; 32 struct resource *addr_req; /* resources requested */ 33 struct resource *data_req; 34 struct resource *irq_res; 35 36 int irq_wake; 37 38 struct mutex addr_lock; /* phy and eeprom access lock */ 39 40 struct delayed_work phy_poll; 41 struct net_device *ndev; 42 43 spinlock_t lock; 44 45 struct mii_if_info mii; 46 u32 msg_enable; 47 u32 wake_state; 48 49 int rx_csum; 50 int can_csum; 51 int ip_summed; 52 } board_info_t;
【linux驱动分析】之dm9000驱动分析(六):dm9000_init和dm9000_probe的实现
一、dm9000_init
打印出驱动的版本号,注册dm9000_driver驱动,将驱动添加到总线上,执行match,如果匹配,将会执行probe函数。
1 static int __init 2 dm9000_init(void) 3 { 4 printk(KERN_INFO "%s Ethernet Driver, V%s\n", CARDNAME, DRV_VERSION); 5 6 return platform_driver_register(&dm9000_driver); 7 }
二、dm9000_probe函数
1 /* 2 * Search DM9000 board, allocate space and register it 3 */ 4 static int __devinit 5 dm9000_probe(struct platform_device *pdev) 6 { 7 /* 把mach-mini6410.c中定义的dm9000_plat_data传递过来 */ 8 struct dm9000_plat_data *pdata = pdev->dev.platform_data; 9 struct board_info *db; /* Point a board information structure */ 10 struct net_device *ndev; 11 const unsigned char *mac_src; 12 int ret = 0; 13 int iosize; 14 int i; 15 u32 id_val; 16 17 /* Init network device */ 18 /* 分配一个名为eth%d的网络设备,同时分配一个私有数据区,数据区是32字节对齐 */ 19 ndev = alloc_etherdev(sizeof(struct board_info)); 20 if (!ndev) { 21 dev_err(&pdev->dev, "could not allocate device.\n"); 22 return -ENOMEM; 23 } 24 /* 把网络设备的基类dev的父指针设为平台设备的基类dev */ 25 SET_NETDEV_DEV(ndev, &pdev->dev); 26 27 dev_dbg(&pdev->dev, "dm9000_probe()\n"); 28 29 /* setup board info structure */ 30 /* 设置私有数据,下面会具体分析这个函数 */ 31 db = netdev_priv(ndev); 32 /* 给私有数据赋值 */ 33 db->dev = &pdev->dev; 34 db->ndev = ndev; 35 36 /* 初始化一个自旋锁和一个互斥体 */ 37 spin_lock_init(&db->lock); 38 mutex_init(&db->addr_lock); 39 40 /* 往工作队列插入一个工作,随后我们调用schedule_delayed_work就会执行传递的函数 41 * 关于工作队列会有专门一篇文章来学习总结 42 */ 43 INIT_DELAYED_WORK(&db->phy_poll, dm9000_poll_work); 44 45 /* 获得资源,这个函数会在下面讲解 */ 46 db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 47 db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 48 db->irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 49 50 if (db->addr_res == NULL || db->data_res == NULL || 51 db->irq_res == NULL) { 52 dev_err(db->dev, "insufficient resources\n"); 53 ret = -ENOENT; 54 goto out; 55 } 56 57 /* 获取中断号,这个中断号是不存在的,因为resource里只有一个中断号 */ 58 db->irq_wake = platform_get_irq(pdev, 1); 59 if (db->irq_wake >= 0) { 60 dev_dbg(db->dev, "wakeup irq %d\n", db->irq_wake); 61 62 /* 为ndev申请中断,中断服务程序为dm9000_wol_interrupt,关于中断也会有一篇文章来学习总结 */ 63 ret = request_irq(db->irq_wake, dm9000_wol_interrupt, 64 IRQF_SHARED, dev_name(db->dev), ndev); 65 if (ret) { 66 dev_err(db->dev, "cannot get wakeup irq (%d)\n", ret); 67 } else { 68 69 /* test to see if irq is really wakeup capable */ 70 ret = set_irq_wake(db->irq_wake, 1); 71 if (ret) { 72 dev_err(db->dev, "irq %d cannot set wakeup (%d)\n", 73 db->irq_wake, ret); 74 ret = 0; 75 } else { 76 set_irq_wake(db->irq_wake, 0); 77 db->wake_supported = 1; 78 } 79 } 80 } 81 /* 返回dm9000内存资源的大小,下面一句是申请内存,关于内存的申请和分配也会有一篇文章 */ 82 iosize = resource_size(db->addr_res); 83 db->addr_req = request_mem_region(db->addr_res->start, iosize, 84 pdev->name); 85 86 if (db->addr_req == NULL) { 87 dev_err(db->dev, "cannot claim address reg area\n"); 88 ret = -EIO; 89 goto out; 90 } 91 /* 存放地址的内存空间开始地址,地址寄存器,一共占3个地址, 92 * 分别是0x18000000,0x18000001,0x18000002,0x18000003, 93 * 这也是一个巧妙之处,dm9000芯片的cmd引脚接的是arm11的addr2, 94 * 所以写“0地址”代表送地址,读写4地址表示读写数据 95 * */ 96 db->io_addr = ioremap(db->addr_res->start, iosize); 97 98 if (db->io_addr == NULL) { 99 dev_err(db->dev, "failed to ioremap address reg\n"); 100 ret = -EINVAL; 101 goto out; 102 } 103 104 iosize = resource_size(db->data_res); 105 db->data_req = request_mem_region(db->data_res->start, iosize, 106 pdev->name); 107 108 if (db->data_req == NULL) { 109 dev_err(db->dev, "cannot claim data reg area\n"); 110 ret = -EIO; 111 goto out; 112 } 113 /* 数据寄存器的地址,1MB的空间 */ 114 db->io_data = ioremap(db->data_res->start, iosize); 115 116 if (db->io_data == NULL) { 117 dev_err(db->dev, "failed to ioremap data reg\n"); 118 ret = -EINVAL; 119 goto out; 120 } 121 122 /* fill in parameters for net-dev structure */ 123 ndev->base_addr = (unsigned long)db->io_addr; 124 ndev->irq = db->irq_res->start; 125 126 /* ensure at least we have a default set of IO routines */ 127 /* iosize是一个很大的值,这里是先保证有个默认值位宽,32位 */ 128 dm9000_set_io(db, iosize); 129 130 /* check to see if anything is being over-ridden */ 131 if (pdata != NULL) { 132 /* check to see if the driver wants to over-ride the 133 * default IO width */ 134 135 if (pdata->flags & DM9000_PLATF_8BITONLY) 136 dm9000_set_io(db, 1); 137 /* 138 * 我们这里设置的是16位,他会做下面几件事: 139 * db->dumpblk = dm9000_dumpblk_16bit; 140 * db->outblk = dm9000_outblk_16bit; 141 * db->inblk = dm9000_inblk_16bit; 142 */ 143 if (pdata->flags & DM9000_PLATF_16BITONLY) 144 dm9000_set_io(db, 2); 145 146 if (pdata->flags & DM9000_PLATF_32BITONLY) 147 dm9000_set_io(db, 4); 148 149 /* check to see if there are any IO routine 150 * over-rides */ 151 152 if (pdata->inblk != NULL) 153 db->inblk = pdata->inblk; 154 155 if (pdata->outblk != NULL) 156 db->outblk = pdata->outblk; 157 158 if (pdata->dumpblk != NULL) 159 db->dumpblk = pdata->dumpblk; 160 161 db->flags = pdata->flags; 162 } 163 164 #ifdef CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL 165 db->flags |= DM9000_PLATF_SIMPLE_PHY; 166 #endif 167 /* 168 * dm9000_reset函数是执行下面两句话,中间有延时,这里省略了 169 * writeb(DM9000_NCR, db->io_addr); //先写NCR寄存器的地址到“0地址”(写到0地址就代表写地址) 170 * writeb(NCR_RST, db->io_data); //再给“4地址”写NCR_RST(0x01),即NCR = 1; 171 * 读写“4地址”就相当于发送数据,cmd引脚连的是addr2,dm9000地址线数据线复用 172 * */ 173 dm9000_reset(db); 174 175 /* try multiple times, DM9000 sometimes gets the read wrong */ 176 /* 下面所做的是读出dm9000的供应商ID和产品ID */ 177 for (i = 0; i < 8; i++) { 178 /* ior是从reg读出数据,类型是u8,它的原理与上面分析reset函数的原理是一样的 */ 179 id_val = ior(db, DM9000_VIDL); 180 id_val |= (u32)ior(db, DM9000_VIDH) << 8; 181 id_val |= (u32)ior(db, DM9000_PIDL) << 16; 182 id_val |= (u32)ior(db, DM9000_PIDH) << 24; 183 184 if (id_val == DM9000_ID) 185 break; 186 dev_err(db->dev, "read wrong id 0x%08x\n", id_val); 187 } 188 189 if (id_val != DM9000_ID) { 190 dev_err(db->dev, "wrong id: 0x%08x\n", id_val); 191 ret = -ENODEV; 192 goto out; 193 } 194 195 /* Identify what type of DM9000 we are working on */ 196 /* 读出芯片版本寄存器,判断dm9000的型号,默认是dm9000E */ 197 id_val = ior(db, DM9000_CHIPR); 198 dev_dbg(db->dev, "dm9000 revision 0x%02x\n", id_val); 199 200 switch (id_val) { 201 case CHIPR_DM9000A: 202 db->type = TYPE_DM9000A; 203 break; 204 case CHIPR_DM9000B: 205 db->type = TYPE_DM9000B; 206 break; 207 default: 208 dev_dbg(db->dev, "ID %02x => defaulting to DM9000E\n", id_val); 209 db->type = TYPE_DM9000E; 210 } 211 212 /* dm9000a/b are capable of hardware checksum offload */ 213 if (db->type == TYPE_DM9000A || db->type == TYPE_DM9000B) { 214 db->can_csum = 1; 215 db->rx_csum = 1; 216 ndev->features |= NETIF_F_IP_CSUM; 217 } 218 219 /* from this point we assume that we have found a DM9000 */ 220 221 /* driver system function */ 222 /* 这个函数是初始化ndev的一些成员 */ 223 ether_setup(ndev); 224 225 /* 下面也是初始化ndev的一些成员 */ 226 ndev->netdev_ops = &dm9000_netdev_ops; 227 ndev->watchdog_timeo = msecs_to_jiffies(watchdog); 228 ndev->ethtool_ops = &dm9000_ethtool_ops; 229 230 db->msg_enable = NETIF_MSG_LINK; 231 db->mii.phy_id_mask = 0x1f; 232 db->mii.reg_num_mask = 0x1f; 233 db->mii.force_media = 0; 234 db->mii.full_duplex = 0; 235 db->mii.dev = ndev; 236 db->mii.mdio_read = dm9000_phy_read; 237 db->mii.mdio_write = dm9000_phy_write; 238 239 mac_src = "eeprom"; 240 /* node address是在网络中的一个电脑或终端的号码或名字, 241 * 这里从eeprom读取,由于我们没有,所以它读回来的是6个FF 242 * */ 243 /* try reading the node address from the attached EEPROM */ 244 for (i = 0; i < 6; i += 2) 245 dm9000_read_eeprom(db, i / 2, ndev->dev_addr+i); 246 247 /* try MAC address passed by kernel command line */ 248 /* 这个函数是友善之臂添加的,它在mach-mini6410里添加了这样一句话__setup("ethmac=", dm9000_set_mac); 249 * 内核启动时,遇到"ethmac="回去执行dm9000_set_mac函数,所以就实现了mac从内核传递过来 250 * 这也是一个很巧妙的设计,需要写一篇文章学习总结一下 251 * */ 252 if (!is_valid_ether_addr(ndev->dev_addr) && pdata != NULL) { 253 mac_src = "param data"; 254 memcpy(ndev->dev_addr, pdata->param_addr, 6); 255 } 256 /* 下面是读取mac的几种方法,当前这一种是从dm9000的Physical Address Register读取 */ 257 if (!is_valid_ether_addr(ndev->dev_addr)) { 258 /* try reading from mac */ 259 mac_src = "chip"; 260 for (i = 0; i < 6; i++) 261 ndev->dev_addr[i] = ior(db, i+DM9000_PAR); 262 } 263 /* 从pdata里的dev_addr读取 */ 264 if (!is_valid_ether_addr(ndev->dev_addr) && pdata != NULL) { 265 mac_src = "platform data"; 266 memcpy(ndev->dev_addr, pdata->dev_addr, 6); 267 } 268 /* 没有读到有效的mac地址,提示用ifconfig命令设置 */ 269 if (!is_valid_ether_addr(ndev->dev_addr)) 270 dev_warn(db->dev, "%s: Invalid ethernet MAC address. Please " 271 "set using ifconfig\n", ndev->name); 272 273 /* 274 * 这里由于ndev是我们定义的一个局部变量,所以要ndev传递给平台设备pdev 275 * 即pdev->dev->p->driver_data = ndev; 276 * 要使用是通过platform_get_drvdata获得 277 * */ 278 platform_set_drvdata(pdev, ndev); 279 /* net_device结构体初始化好后,剩余的工作就是把该结构传递给register_netdev函数, 280 * 当调用register_netdev后就可以用驱动程序操作设备了,所以 281 * 必须在初始化一切事情后再注册 282 * */ 283 ret = register_netdev(ndev); 284 285 if (ret == 0) 286 printk(KERN_INFO "%s: dm9000%c at %p,%p IRQ %d MAC: %pM (%s)\n", 287 ndev->name, dm9000_type_to_char(db->type), 288 db->io_addr, db->io_data, ndev->irq, 289 ndev->dev_addr, mac_src); 290 return 0; 291 292 out: 293 dev_err(db->dev, "not found (%d).\n", ret); 294 295 dm9000_release_board(pdev, db); 296 free_netdev(ndev); 297 298 return ret; 299 } 300 /*********** probe函数大功告成 *************/ 301
三、总结probe函数分析是留下的问题
在上面用红色标记出来了要分析的东西
1、分析netdev_priv
在执行 ndev = alloc_etherdev(sizeof(struct board_info));时,先分配了一个net_device结构,又分配了一个board_info结构体,作为ndev的私有数据,然后执行了db = netdev_priv( ndev );来获得私有数据的开始地址,并在以后做初始化。
在probe函数最后,通过platform_set_drvdata函数把ndev结构传给了平台设备,以供使用,那么我猜想这里把board_info也传过去了,以后也可以用,获得它的地址的方法是通过下面的函数。
303 /** 304 * netdev_priv - access network device private data 305 * @dev: network device 306 * 307 * Get network device private data 308 */ 309 static inline void *netdev_priv(const struct net_device *dev) 310 { 311 return (char *)dev + ALIGN(sizeof(struct net_device), NETDEV_ALIGN); 312 }
2、platform_get_resource函数分析
46 db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 47 db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 48 db->irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
platform_data的关系是这样的:platform device->dev->platform_data
对于dm9000驱动来说是这样实现的:
8 struct dm9000_plat_data *pdata = pdev->dev.platform_data;
static struct dm9000_plat_data dm9000_setup = {
.flags = DM9000_PLATF_16BITONLY | DM9000_PLATF_EXT_PHY,
.dev_addr = { 0x08, 0x90, 0x00, 0xa0, 0x90, 0x90 },
};
3、以后要写文章总结的东西
(1)、关于工作队列的要总结一下
43 INIT_DELAYED_WORK(&db->phy_poll, dm9000_poll_work);
(2)、关于内核中断的原理和操作方法
63 ret = request_irq(db->irq_wake, dm9000_wol_interrupt, 64 IRQF_SHARED, dev_name(db->dev), ndev);
(3)、关于内核内存分配和操作方法
83 db->addr_req = request_mem_region(db->addr_res->start, iosize, 84 pdev->name);
(4)、关于__setup的作用
__setup("ethmac=", dm9000_set_mac);
【linux驱动分析】之dm9000驱动分析(七):dm9000的卸载挂起和恢复以及打开和停止
分析dm9000的卸载,挂起和恢复,以及dm9000的打开和停止。涉及到的函数为:
1 static int __devexit 2 dm9000_drv_remove(struct platform_device *pdev) 3 static int 4 dm9000_drv_suspend(struct device *dev) 5 static int 6 dm9000_drv_resume(struct device *dev) 7 static int 8 dm9000_open(struct net_device *dev) 9 static int 10 dm9000_stop(struct net_device *ndev)
一、卸载驱动
驱动中可以看到,在模块卸载时执行
platform_driver_unregister(&dm9000_driver);
在卸载platform_driver时会执行remove函数,remove函数的功能是把设备从内核中移除,释放内存区域。下面给出dm9000_drv_remove函数的代码:
1 static int __devexit 2 dm9000_drv_remove(struct platform_device *pdev) 3 { 4 struct net_device *ndev = platform_get_drvdata(pdev); 5 6 platform_set_drvdata(pdev, NULL); 7 8 unregister_netdev(ndev); 9 dm9000_release_board(pdev, netdev_priv(ndev)); 10 free_netdev(ndev); /* free device structure */ 11 12 dev_dbg(&pdev->dev, "released and freed device\n"); 13 return 0; 14 } 15 16 17 /* dm9000_release_board 18 * 19 * release a board, and any mapped resources 20 */ 21 22 static void 23 dm9000_release_board(struct platform_device *pdev, struct board_info *db) 24 { 25 /* unmap our resources */ 26 27 iounmap(db->io_addr); 28 iounmap(db->io_data); 29 30 /* release the resources */ 31 32 release_resource(db->data_req); 33 kfree(db->data_req); 34 35 release_resource(db->addr_req); 36 kfree(db->addr_req); 37 }
二、关于电源管理的设备的挂起和恢复函数
suspend函数并不真正把设备从内核中移除,而只是标志设备为removed状态,并设置挂起标志位为1,最后关闭设备。
resume函数将挂起的设备复位并初始化,软后将设备标志为attached状态,并设置挂起标志位为0。
1 static int 2 dm9000_drv_suspend(struct device *dev) 3 { 4 struct platform_device *pdev = to_platform_device(dev); 5 struct net_device *ndev = platform_get_drvdata(pdev); 6 board_info_t *db; 7 8 if (ndev) { 9 db = netdev_priv(ndev); 10 db->in_suspend = 1; 11 12 if (!netif_running(ndev)) 13 return 0; 14 15 netif_device_detach(ndev); 16 17 /* only shutdown if not using WoL */ 18 if (!db->wake_state) 19 dm9000_shutdown(ndev); 20 } 21 return 0; 22 } 23 24 static int 25 dm9000_drv_resume(struct device *dev) 26 { 27 struct platform_device *pdev = to_platform_device(dev); 28 struct net_device *ndev = platform_get_drvdata(pdev); 29 board_info_t *db = netdev_priv(ndev); 30 31 if (ndev) { 32 if (netif_running(ndev)) { 33 /* reset if we were not in wake mode to ensure if 34 * the device was powered off it is in a known state */ 35 if (!db->wake_state) { 36 dm9000_reset(db); 37 dm9000_init_dm9000(ndev); 38 } 39 40 netif_device_attach(ndev); 41 } 42 43 db->in_suspend = 0; 44 } 45 return 0; 46 }
三、dm9000的打开和停止
1、打开函数dm9000_open
1 /* 2 * Open the interface. 3 * The interface is opened whenever "ifconfig" actives it. 4 */ 5 static int 6 dm9000_open(struct net_device *dev) 7 { 8 board_info_t *db = netdev_priv(dev); 9 unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK; 10 11 /* db结构体中的成员msg_enble,在probe函数中赋值为NETIF_MSG_LINK */ 12 if (netif_msg_ifup(db)) 13 dev_dbg(db->dev, "enabling %s\n", dev->name); 14 15 /* If there is no IRQ type specified, default to something that 16 * may work, and tell the user that this is a problem */ 17 18 if (irqflags == IRQF_TRIGGER_NONE) 19 dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n"); 20 21 irqflags |= IRQF_SHARED; 22 /* 申请中断,中断函数dm9000_interrupt */ 23 if (request_irq(dev->irq, dm9000_interrupt, irqflags, dev->name, dev)) 24 return -EAGAIN; 25 26 /* GPIO0 on pre-activate PHY, Reg 1F is not set by reset */ 27 iow(db, DM9000_GPR, 0); /* REG_1F bit0 activate phyxcer */ 28 mdelay(1); /* delay needs by DM9000B */ 29 30 /* Initialize DM9000 board */ 31 dm9000_reset(db); 32 /* dm9000初始化,下面会对这个函数做详细分析 */ 33 dm9000_init_dm9000(dev); 34 35 /* Init driver variable */ 36 db->dbug_cnt = 0; 37 38 /* 检查mii接口 39 * Returns 1 if the duplex mode changed, 0 if not. 40 * If the media type is forced, always returns 0. 41 * */ 42 mii_check_media(&db->mii, netif_msg_link(db), 1); 43 /* 开启网络接口数据发送队列 */ 44 netif_start_queue(dev); 45 /*延时一段时间执行dm9000_poll_work,原来在probe函数里把这个函数加入了工作队列,现在来调度执行*/ 46 dm9000_schedule_poll(db); 47 48 return 0; 49 }
2、dm9000_init_dm9000函数
1 /* 2 * Initialize dm9000 board 3 */ 4 static void 5 dm9000_init_dm9000(struct net_device *dev) 6 { 7 board_info_t *db = netdev_priv(dev); 8 unsigned int imr; 9 unsigned int ncr; 10 11 dm9000_dbg(db, 1, "entering %s\n", __func__); 12 13 /* I/O mode */ 14 db->io_mode = ior(db, DM9000_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */ 15 16 /* Checksum mode */ 17 dm9000_set_rx_csum_unlocked(dev, db->rx_csum); 18 19 iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */ 20 21 ncr = (db->flags & DM9000_PLATF_EXT_PHY) ? NCR_EXT_PHY : 0; 22 23 /* if wol is needed, then always set NCR_WAKEEN otherwise we end 24 * up dumping the wake events if we disable this. There is already 25 * a wake-mask in DM9000_WCR */ 26 if (db->wake_supported) 27 ncr |= NCR_WAKEEN; 28 29 iow(db, DM9000_NCR, ncr); 30 31 /* Program operating register */ 32 iow(db, DM9000_TCR, 0); /* TX Polling clear */ 33 iow(db, DM9000_BPTR, 0x3f); /* Less 3Kb, 200us */ 34 iow(db, DM9000_FCR, 0xff); /* Flow Control */ 35 iow(db, DM9000_SMCR, 0); /* Special Mode */ 36 /* clear TX status */ 37 iow(db, DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END); 38 iow(db, DM9000_ISR, ISR_CLR_STATUS); /* Clear interrupt status */ 39 40 /* Set address filter table */ 41 dm9000_hash_table_unlocked(dev); 42 43 imr = IMR_PAR | IMR_PTM | IMR_PRM; 44 if (db->type != TYPE_DM9000E) 45 imr |= IMR_LNKCHNG; 46 47 db->imr_all = imr; 48 49 /* Enable TX/RX interrupt mask */ 50 iow(db, DM9000_IMR, imr); 51 52 /* Init Driver variable */ 53 db->tx_pkt_cnt = 0; 54 db->queue_pkt_len = 0; 55 dev->trans_start = jiffies; 56 }
3、停止函数dm9000_stop它会做与dm9000_stop相反的事情。
1 /* 2 * Stop the interface. 3 * The interface is stopped when it is brought. 4 */ 5 static int 6 dm9000_stop(struct net_device *ndev) 7 { 8 board_info_t *db = netdev_priv(ndev); 9 10 if (netif_msg_ifdown(db)) 11 dev_dbg(db->dev, "shutting down %s\n", ndev->name); 12 13 cancel_delayed_work_sync(&db->phy_poll); 14 15 netif_stop_queue(ndev); 16 netif_carrier_off(ndev); 17 18 /* free interrupt */ 19 free_irq(ndev->irq, ndev); 20 21 dm9000_shutdown(ndev); 22 23 return 0; 24 }