【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的卸载挂起和恢复以及打开和停止
4、曼彻斯特编码
曼彻斯特编码又称曼彻斯特相位编码,它通过相位变化来实现每个位(图2)。通常,用一个时钟周期中部的上升沿表示“1”,下降沿表示“0”。周期末端的相位变化可忽略不计,但有时又可能需要将这种相位变化计算在内,这取决于前一位的值。
5、4B/5B编码
4B/5B编码是一种块编码方式。它将一个4位的块编码成一个5位的块。这就使5位块内永远至少包含2个“1”转换,所以在一个5位块内总能进行时钟同步。该方法需要25%的额外开销。
【linux驱动分析】之dm9000驱动分析(二):定义在板文件中的资源和设备以及几个宏
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是定义在lib/vsprintf.c中的函数,它的作用是把一个字符串转换为unsigned long型的整数,并返回。/** * 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)
其中的endp参数存放解析后的字符串地址,base参数,是要转换的进制数。
vsprintf.c里还定义了其他好多字符串处理的函数,具体用到时去查。
3、__setup
它是定义在include/linux/init.h中的一个宏:
#define __setup(str, fn) \ __setup_param(str, fn, fn, 0)
关于__setup的更多分析见《__setup宏的作用》其中:str是关键字,fn是关联处理函数。__setup只是告诉内核在启动时输入串中含有str时,内核要去执行fn。Str必须以“=”符结束以使parse_args更方便解析。紧随“=”后的任何文本都会作为输入传给fn。
例如本例中的: __setup ( " ethmac= " , dm9000_set_mac);
【linux驱动分析】之dm9000驱动分析(三):sk_buff结构分析
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结构体
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驱动中用到的另外几个重要的结构体
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 };
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的卸载挂起和恢复以及打开和停止
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 }
二、关于电源管理的设备的挂起和恢复函数
3、停止函数dm9000_stopsuspend函数并不真正把设备从内核中移除,而只是标志设备为removed状态,并设置挂起标志位为1,最后关闭设备。
resume函数将挂起的设备复位并初始化,软后将设备标志为attached状态,并设置挂起标志位为0。
三、dm9000的打开和停止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 }1、打开函数dm9000_open
2、dm9000_init_dm9000函数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 }
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 }它会做与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 }