ARM-Linux驱动--DM9000网卡驱动分析(一)
硬件平台:FL2440(s3c2440)

[0] = { .start = S3C24XX_PA_DM9000, .end = S3C24XX_PA_DM9000+ 0x3, .flags = IORESOURCE_MEM }, [1]={ .start = S3C24XX_PA_DM9000 + 0x4, //CMD pin is A2 0x20000304 .end = S3C24XX_PA_DM9000 + 0x4 + 0x7c, // 0x20000380 .flags = IORESOURCE_MEM }, [2] = { .start = IRQ_EINT7, .end = IRQ_EINT7, .flags = IORESOURCE_IRQ }, .flags= DM9000_PLATF_16BITONLY, .name= "dm9000", //设备名,该名称与平台设备驱动中的名称一致 .id= 0, .num_resources= ARRAY_SIZE(s3c_dm9000_resource), .resource= s3c_dm9000_resource, //定义设备的资源 .dev= { .platform_data = &s3c_device_dm9000_platdata, //定义平台数据 } .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, .init_irq = s3c24xx_init_irq, .map_io = smdk2440_map_io, .init_machine = smdk2440_machine_init,//定义设备的初始化函数 .timer = &s3c24xx_timer, s3c24xx_fb_set_platdata(&smdk2440_fb_info); s3c_i2c0_set_platdata(NULL); s3c24xx_ts_set_platdata(&smdk2410_ts_cfg); platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices)); smdk_machine_init(); &s3c_device_ohci, &s3c_device_lcd, &s3c_device_wdt, &s3c_device_i2c0, &s3c_device_iis, &s3c_device_rtc, &s3c24xx_uda134x, &s3c_device_dm9000, &s3c_device_adc, &s3c_device_ts, struct sk_buff *next; struct sk_buff *prev; ktime_t tstamp; struct sock *sk; struct net_device *dev; char cb[48] __aligned(8); unsigned long _skb_refdst; struct sec_path *sp; unsigned int len, data_len; __u16 mac_len, hdr_len; union { __wsum csum; struct { __u16 csum_start; __u16 csum_offset; }; }; __u32 priority; kmemcheck_bitfield_begin(flags1); __u8 local_df:1, cloned:1, ip_summed:2, nohdr:1, nfctinfo:3; __u8 pkt_type:3, fclone:2, ipvs_property:1, peeked:1, nf_trace:1; kmemcheck_bitfield_end(flags1); __be16 protocol; void (*destructor)(struct sk_buff *skb); struct nf_conntrack *nfct; struct sk_buff *nfct_reasm; struct nf_bridge_info *nf_bridge; int skb_iif; __u16 tc_index; __u16 tc_verd; __u32 rxhash; kmemcheck_bitfield_begin(flags2); __u16 queue_mapping:16; __u8 ndisc_nodetype:2, deliver_no_wcard:1; __u8 deliver_no_wcard:1; kmemcheck_bitfield_end(flags2); dma_cookie_t dma_cookie; __u32 secmark; union { __u32 mark; __u32 dropcount; }; __u16 vlan_tci; sk_buff_data_t transport_header; sk_buff_data_t network_header; sk_buff_data_t mac_header; sk_buff_data_t tail; sk_buff_data_t end; unsigned char *head, *data; unsigned int truesize; atomic_t users; *struct sk_buff - socket buffer * @next: Next buffer inlist * @prev: Previous buffer in list * @sk: Socketwe are owned by * @tstamp: Time we arrived * @dev:Device we arrived on/are leaving by * @transport_header:Transport layer header * @network_header: Network layerheader * @mac_header: Link layer header *@_skb_refdst: destination entry (with norefcount bit) * @sp:the security path, used for xfrm * @cb: Control buffer. Freefor use by every layer. Put private vars here * @len: Lengthof actual data * @data_len: Data length * @mac_len:Length of link layer header * @hdr_len: writable headerlength of cloned skb * @csum: Checksum (must includestart/offset pair) * @csum_start: Offset from skb->headwhere checksumming should start * @csum_offset: Offset fromcsum_start where checksum should be stored * @local_df:allow local fragmentation * @cloned: Head may be cloned(check refcnt to be sure) * @nohdr: Payload reference only,must not modify header * @pkt_type: Packet class *@fclone: skbuff clone status * @ip_summed: Driver fed us anIP checksum * @priority: Packet queueing priority *@users: User count - see {datagram,tcp}.c * @protocol:Packet protocol from driver * @truesize: Buffer size *@head: Head of buffer * @data: Data head pointer *@tail: Tail pointer * @end: End pointer *@destructor: Destruct function * @mark: Generic packetmark * @nfct: Associated connection, if any *@ipvs_property: skbuff is owned by ipvs * @peeked: thispacket has been seen already, so stats have been * done forit, dont do them again * @nf_trace: netfilter packet traceflag * @nfctinfo: Relationship of this skb to theconnection * @nfct_reasm: netfilter conntrack re-assemblypointer * @nf_bridge: Saved data about a bridged frame - seebr_netfilter.c * @skb_iif: ifindex of device we arrivedon * @rxhash: the packet hash computed on receive *@queue_mapping: Queue mapping for multiqueue devices *@tc_index: Traffic control index * @tc_verd: traffic controlverdict * @ndisc_nodetype: router type (from link layer) *@dma_cookie: a cookie to one of several possible DMA operations *done by skb DMA functions * @secmark: security marking *@vlan_tci: vlan tag control information char name[IFNAMSIZ]; struct pm_qos_request_list *pm_qos_req; struct hlist_node name_hlist; char *ifalias; unsigned long mem_end; unsigned long mem_start; unsigned long base_addr; unsigned int irq; unsigned char if_port; unsigned char dma; unsigned long state; struct list_head dev_list; struct list_head napi_list; struct list_head unreg_list; unsigned long features; NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST) int ifindex; int iflink; struct net_device_stats stats; const struct iw_handler_def * wireless_handlers; struct iw_public_data * wireless_data; const struct net_device_ops *netdev_ops; const struct ethtool_ops *ethtool_ops; const struct header_ops *header_ops; unsigned int flags; unsigned short gflags; unsigned short priv_flags; unsigned short padded; unsigned char operstate; unsigned char link_mode; unsigned int mtu; unsigned short type; unsigned short hard_header_len; unsigned short needed_headroom; unsigned short needed_tailroom; struct net_device *master; unsigned char perm_addr[MAX_ADDR_LEN]; unsigned char addr_len; unsigned short dev_id; spinlock_t addr_list_lock; struct netdev_hw_addr_list uc; struct netdev_hw_addr_list mc; int uc_promisc; unsigned int promiscuity; unsigned int allmulti; void *dsa_ptr; void *atalk_ptr; void *ip_ptr; void *dn_ptr; void *ip6_ptr; void *ec_ptr; void *ax25_ptr; struct wireless_dev *ieee80211_ptr; unsigned long last_rx; unsigned char *dev_addr; struct netdev_hw_addr_list dev_addrs; unsigned char broadcast[MAX_ADDR_LEN]; struct kset *queues_kset; struct netdev_rx_queue *_rx; unsigned int num_rx_queues; struct netdev_queue rx_queue; struct netdev_queue *_tx ____cacheline_aligned_in_smp; unsigned int num_tx_queues; unsigned int real_num_tx_queues; struct Qdisc *qdisc; unsigned long tx_queue_len; spinlock_t tx_global_lock; unsigned long trans_start; int watchdog_timeo; struct timer_list watchdog_timer; atomic_t refcnt ____cacheline_aligned_in_smp; struct list_head todo_list; struct hlist_node index_hlist; struct list_head link_watch_list; enum { NETREG_UNINITIALIZED=0, NETREG_REGISTERED, NETREG_UNREGISTERING, NETREG_UNREGISTERED, NETREG_RELEASED, NETREG_DUMMY, } reg_state:16; enum { RTNL_LINK_INITIALIZED, RTNL_LINK_INITIALIZING, } rtnl_link_state:16; void (*destructor)(struct net_device *dev); struct netpoll_info *npinfo; struct net *nd_net; void *ml_priv; struct net_bridge_port *br_port; struct macvlan_port *macvlan_port; struct garp_port *garp_port; struct device dev; const struct attribute_group *sysfs_groups[4]; const struct rtnl_link_ops *rtnl_link_ops; unsigned long vlan_features; unsigned int gso_max_size; const struct dcbnl_rtnl_ops *dcbnl_ops; unsigned int fcoe_ddp_xid; struct ethtool_rx_ntuple_list ethtool_ntuple_list;
内核版本:2.6.35
主机平台:Ubuntu11.04
内核版本:2.6.39
原创作品,转载请标明出处http://blog.csdn.net/yming0221/article/details/6609742
1、下图是DM9000的引脚图

2、这里我们结合具体的开发板FL2440
下面是FL2440和DM9000的引脚链接图

本人移植DM9000的时候将设备的资源定义放在了arch/arm/plat-s3c24xx/devs.c中,详情点击上一篇博文linux内核移植-移植2.6.35.4内核到s3c2440
下面是设备的资源定义
view plainprint?
static struct resource s3c_dm9000_resource[] = {
};
这里可以看到,DM9000网卡使用的地址空间资源在nGCS4地址区域,所以上图的DM9000地址使能引脚连接nGCS4引脚。中断使用的是EINT7外部中断。
接着定义平台数据和平台设备,代码如下:
view plainprint?
static struct dm9000_plat_data s3c_device_dm9000_platdata = {
};
struct platform_device s3c_device_dm9000 = {
};
最后导出函数符号,保存函数地址和名称
view plainprint?
EXPORT_SYMBOL(s3c_device_dm9000);
3、设备启动的初始化过程
view plainprint?
MACHINE_START(S3C2440, "SMDK2440")
MACHINE_END
而后会执行下面函数
view plainprint?
static void __init smdk2440_machine_init(void)
{
}
下面是具体的设备列表
view plainprint?
static struct platform_device *smdk2440_devices[] __initdata = {
};
这样系统启动时,会给设备列表中的设备分配资源(地址资源和中断资源等)。
4、信息传输中的信息封装结构
4.1、sk_buff结构,定义在include/linux/skbuff.h中
view plainprint?
struct sk_buff {
#ifdef CONFIG_XFRM
#endif
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
#endif
#ifdef CONFIG_NET_SCHED
#ifdef CONFIG_NET_CLS_ACT
#endif
#endif
#ifdef CONFIG_IPV6_NDISC_NODETYPE
#else
#endif
#ifdef CONFIG_NET_DMA
#endif
#ifdef CONFIG_NETWORK_SECMARK
#endif
};
元素的含义如下(摘自内核,源码,版本2.6.35.4)
关于sk_buff的更多分析见另一篇转载的博文http://blog.csdn.net/yming0221/article/details/6609734
4.2、net_device
关于net_device一个非常庞大的结构体,定义在/inlcude/linux/netdevice.h中
如下:
view plainprint?
struct net_device {
#define NETIF_F_SG 1
#define NETIF_F_IP_CSUM 2
#define NETIF_F_NO_CSUM 4
#define NETIF_F_HW_CSUM 8
#define NETIF_F_IPV6_CSUM 16
#define NETIF_F_HIGHDMA 32
#define NETIF_F_FRAGLIST 64
#define NETIF_F_HW_VLAN_TX 128
#define NETIF_F_HW_VLAN_RX 256
#define NETIF_F_HW_VLAN_FILTER 512
#define NETIF_F_VLAN_CHALLENGED 1024
#define NETIF_F_GSO 2048
#define NETIF_F_LLTX 4096
#define NETIF_F_NETNS_LOCAL 8192
#define NETIF_F_GRO 16384
#define NETIF_F_LRO 32768
#define NETIF_F_FCOE_CRC (1 << 24)
#define NETIF_F_SCTP_CSUM (1 << 25)
#define NETIF_F_FCOE_MTU (1 << 26)
#define NETIF_F_NTUPLE (1 << 27)
#define NETIF_F_RXHASH (1 << 28)
#define NETIF_F_GSO_SHIFT 16
#define NETIF_F_GSO_MASK 0x00ff0000
#define NETIF_F_TSO (SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT)
#define NETIF_F_UFO (SKB_GSO_UDP << NETIF_F_GSO_SHIFT)
#define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT)
#define NETIF_F_TSO_ECN (SKB_GSO_TCP_ECN << NETIF_F_GSO_SHIFT)
#define NETIF_F_TSO6 (SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT)
#define NETIF_F_FSO (SKB_GSO_FCOE << NETIF_F_GSO_SHIFT)
#define NETIF_F_GSO_SOFTWARE (NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6)
#define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
#define NETIF_F_V4_CSUM (NETIF_F_GEN_CSUM | NETIF_F_IP_CSUM)
#define NETIF_F_V6_CSUM (NETIF_F_GEN_CSUM | NETIF_F_IPV6_CSUM)
#define NETIF_F_ALL_CSUM (NETIF_F_V4_CSUM | NETIF_F_V6_CSUM)
#define NETIF_F_ONE_FOR_ALL (NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ROBUST |
#ifdef CONFIG_WIRELESS_EXT
#endif
#ifdef CONFIG_NET_DSA
#endif
#ifdef CONFIG_RPS
#endif
#ifdef CONFIG_NETPOLL
#endif
#ifdef CONFIG_NET_NS
#endif
#define GSO_MAX_SIZE 65536
#ifdef CONFIG_DCB
#endif
#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
#endif
};
我还没有细细的分析这个结构体,驱动程序在probe函数中使用register_netdev()注册该结构体指明的设备,将内核操作硬件的函数个内核联系起来。
关键词: ARMLinux驱动DM9000网卡驱

加入微信
获取电子行业最新资讯
搜索微信公众号:EEPW
或用微信扫描左侧二维码