本文主要是介绍ARM-Linux驱动--DM9000网卡驱动分析(一),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
硬件平台:FL2440(s3c2440)
内核版本: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
下面是设备的资源定义
- /*DM9000*/
- /* 定义该设备使用的资源 */
- static struct resource s3c_dm9000_resource[] = {
- [0] = { /* 寄存器定义在mach-s3c2410/include/mach/map.h */
- .start = S3C24XX_PA_DM9000, /* 实际地址 0x20000300 */
- .end = S3C24XX_PA_DM9000+ 0x3, /* 0x20000303 */
- .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, /* 中断为外部7号中断 */
- .end = IRQ_EINT7, /* 中断为外部7号中断 */
- .flags = IORESOURCE_IRQ /* 资源标志为中断资源 */
- },
- };
这里可以看到,DM9000网卡使用的地址空间资源在nGCS4地址区域,所以上图的DM9000地址使能引脚连接nGCS4引脚。中断使用的是EINT7外部中断。
接着定义平台数据和平台设备,代码如下:
- /* 定义平台数据 */
- static struct dm9000_plat_data s3c_device_dm9000_platdata = {
- .flags= DM9000_PLATF_16BITONLY,
- };
- /* 定义平台设备 */
- struct platform_device s3c_device_dm9000 = {
- .name= "dm9000", //设备名,该名称与平台设备驱动中的名称一致
- .id= 0,
- .num_resources= ARRAY_SIZE(s3c_dm9000_resource),
- .resource= s3c_dm9000_resource, //定义设备的资源
- .dev= {
- .platform_data = &s3c_device_dm9000_platdata, //定义平台数据
- }
- };
最后导出函数符号,保存函数地址和名称
- EXPORT_SYMBOL(s3c_device_dm9000);
3、设备启动的初始化过程
- MACHINE_START(S3C2440, "SMDK2440")
- /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
- .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,
- MACHINE_END
而后会执行下面函数
- static void __init smdk2440_machine_init(void)
- {
- s3c24xx_fb_set_platdata(&smdk2440_fb_info);
- s3c_i2c0_set_platdata(NULL);
- s3c24xx_ts_set_platdata(&smdk2410_ts_cfg);/* Added by yan */
- platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));/* 向平台中添加设备 */
- smdk_machine_init();
- }
下面是具体的设备列表
- static struct platform_device *smdk2440_devices[] __initdata = {
- &s3c_device_ohci,
- &s3c_device_lcd,/* ok */
- &s3c_device_wdt,/* ok */
- &s3c_device_i2c0,
- &s3c_device_iis,
- &s3c_device_rtc,/* ok */
- &s3c24xx_uda134x,
- &s3c_device_dm9000,
- &s3c_device_adc,/* ok */
- &s3c_device_ts,/* ok */
- };
这样系统启动时,会给设备列表中的设备分配资源(地址资源和中断资源等)。
4、信息传输中的信息封装结构
4.1、sk_buff结构,定义在include/linux/skbuff.h中
- struct sk_buff {
- /* These two members must be first. */
- struct sk_buff *next;
- struct sk_buff *prev;
- ktime_t tstamp;
- struct sock *sk;
- struct net_device *dev;
- /*
- * This is the control buffer. It is free to use for every
- * layer. Please put your private variables there. If you
- * want to keep them across layers you have to do a skb_clone()
- * first. This is owned by whoever has the skb queued ATM.
- */
- char cb[48] __aligned(8);
- unsigned long _skb_refdst;
- #ifdef CONFIG_XFRM
- struct sec_path *sp;
- #endif
- 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);
- #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
- struct nf_conntrack *nfct;
- struct sk_buff *nfct_reasm;
- #endif
- #ifdef CONFIG_BRIDGE_NETFILTER
- struct nf_bridge_info *nf_bridge;
- #endif
- int skb_iif;
- #ifdef CONFIG_NET_SCHED
- __u16 tc_index; /* traffic control index */
- #ifdef CONFIG_NET_CLS_ACT
- __u16 tc_verd; /* traffic control verdict */
- #endif
- #endif
- __u32 rxhash;
- kmemcheck_bitfield_begin(flags2);
- __u16 queue_mapping:16;
- #ifdef CONFIG_IPV6_NDISC_NODETYPE
- __u8 ndisc_nodetype:2,
- deliver_no_wcard:1;
- #else
- __u8 deliver_no_wcard:1;
- #endif
- kmemcheck_bitfield_end(flags2);
- /* 0/14 bit hole */
- #ifdef CONFIG_NET_DMA
- dma_cookie_t dma_cookie;
- #endif
- #ifdef CONFIG_NETWORK_SECMARK
- __u32 secmark;
- #endif
- 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;
- /* These elements must be at the end, see alloc_skb() for details. */
- sk_buff_data_t tail;
- sk_buff_data_t end;
- unsigned char *head,
- *data;
- unsigned int truesize;
- atomic_t users;
- };
元素的含义如下(摘自内核,源码,版本2.6.35.4)
*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, don't 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
关于sk_buff的更多分析见另一篇转载的博文http://blog.csdn.net/yming0221/article/details/6609734
4.2、net_device
关于net_device一个非常庞大的结构体,定义在/inlcude/linux/netdevice.h中
如下:
- struct net_device {
- /*
- * This is the first field of the "visible" part of this structure
- * (i.e. as seen by users in the "Space.c" file). It is the name
- * the interface.
- */
- char name[IFNAMSIZ];
- struct pm_qos_request_list *pm_qos_req;
- /* device name hash chain */
- struct hlist_node name_hlist;
- /* snmp alias */
- char *ifalias;
- /*
- * I/O specific fields
- * FIXME: Merge these and struct ifmap into one
- */
- unsigned long mem_end; /* shared mem end */
- unsigned long mem_start; /* shared mem start */
- unsigned long base_addr; /* device I/O address */
- unsigned int irq; /* device IRQ number */
- /*
- * Some hardware also needs these fields, but they are not
- * part of the usual set specified in Space.c.
- */
- unsigned char if_port; /* Selectable AUI, TP,..*/
- unsigned char dma; /* DMA channel */
- unsigned long state;
- struct list_head dev_list;
- struct list_head napi_list;
- struct list_head unreg_list;
- /* Net device features */
- unsigned long features;
- #define NETIF_F_SG 1 /* Scatter/gather IO. */
- #define NETIF_F_IP_CSUM 2 /* Can checksum TCP/UDP over IPv4. */
- #define NETIF_F_NO_CSUM 4 /* Does not require checksum. F.e. loopack. */
- #define NETIF_F_HW_CSUM 8 /* Can checksum all the packets. */
- #define NETIF_F_IPV6_CSUM 16 /* Can checksum TCP/UDP over IPV6 */
- #define NETIF_F_HIGHDMA 32 /* Can DMA to high memory. */
- #define NETIF_F_FRAGLIST 64 /* Scatter/gather IO. */
- #define NETIF_F_HW_VLAN_TX 128 /* Transmit VLAN hw acceleration */
- #define NETIF_F_HW_VLAN_RX 256 /* Receive VLAN hw acceleration */
- #define NETIF_F_HW_VLAN_FILTER 512 /* Receive filtering on VLAN */
- #define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */
- #define NETIF_F_GSO 2048 /* Enable software GSO. */
- #define NETIF_F_LLTX 4096 /* LockLess TX - deprecated. Please */
- /* do not use LLTX in new drivers */
- #define NETIF_F_NETNS_LOCAL 8192 /* Does not change network namespaces */
- #define NETIF_F_GRO 16384 /* Generic receive offload */
- #define NETIF_F_LRO 32768 /* large receive offload */
- /* the GSO_MASK reserves bits 16 through 23 */
- #define NETIF_F_FCOE_CRC (1 << 24) /* FCoE CRC32 */
- #define NETIF_F_SCTP_CSUM (1 << 25) /* SCTP checksum offload */
- #define NETIF_F_FCOE_MTU (1 << 26) /* Supports max FCoE MTU, 2158 bytes*/
- #define NETIF_F_NTUPLE (1 << 27) /* N-tuple filters supported */
- #define NETIF_F_RXHASH (1 << 28) /* Receive hashing offload */
- /* Segmentation offload features */
- #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)
- /* List of features with software fallbacks. */
- #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)
- /*
- * If one device supports one of these features, then enable them
- * for all in netdev_increment_features.
- */
- #define NETIF_F_ONE_FOR_ALL (NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ROBUST | \
- NETIF_F_SG | NETIF_F_HIGHDMA | \
- NETIF_F_FRAGLIST)
- /* Interface index. Unique device identifier */
- int ifindex;
- int iflink;
- struct net_device_stats stats;
- #ifdef CONFIG_WIRELESS_EXT
- /* List of functions to handle Wireless Extensions (instead of ioctl).
- * See <net/iw_handler.h> for details. Jean II */
- const struct iw_handler_def * wireless_handlers;
- /* Instance data managed by the core of Wireless Extensions. */
- struct iw_public_data * wireless_data;
- #endif
- /* Management operations */
- const struct net_device_ops *netdev_ops;
- const struct ethtool_ops *ethtool_ops;
- /* Hardware header description */
- const struct header_ops *header_ops;
- unsigned int flags; /* interface flags (a la BSD) */
- unsigned short gflags;
- unsigned short priv_flags; /* Like 'flags' but invisible to userspace. */
- unsigned short padded; /* How much padding added by alloc_netdev() */
- unsigned char operstate; /* RFC2863 operstate */
- unsigned char link_mode; /* mapping policy to operstate */
- unsigned int mtu; /* interface MTU value */
- unsigned short type; /* interface hardware type */
- unsigned short hard_header_len; /* hardware hdr length */
- /* extra head- and tailroom the hardware may need, but not in all cases
- * can this be guaranteed, especially tailroom. Some cases also use
- * LL_MAX_HEADER instead to allocate the skb.
- */
- unsigned short needed_headroom;
- unsigned short needed_tailroom;
- struct net_device *master; /* Pointer to master device of a group,
- * which this device is member of.
- */
- /* Interface address info. */
- unsigned char perm_addr[MAX_ADDR_LEN]; /* permanent hw address */
- unsigned char addr_len; /* hardware address length */
- unsigned short dev_id; /* for shared network cards */
- spinlock_t addr_list_lock;
- struct netdev_hw_addr_list uc; /* Unicast mac addresses */
- struct netdev_hw_addr_list mc; /* Multicast mac addresses */
- int uc_promisc;
- unsigned int promiscuity;
- unsigned int allmulti;
- /* Protocol specific pointers */
- #ifdef CONFIG_NET_DSA
- void *dsa_ptr; /* dsa specific data */
- #endif
- void *atalk_ptr; /* AppleTalk link */
- void *ip_ptr; /* IPv4 specific data */
- void *dn_ptr; /* DECnet specific data */
- void *ip6_ptr; /* IPv6 specific data */
- void *ec_ptr; /* Econet specific data */
- void *ax25_ptr; /* AX.25 specific data */
- struct wireless_dev *ieee80211_ptr; /* IEEE 802.11 specific data,
- assign before registering */
- /*
- * Cache line mostly used on receive path (including eth_type_trans())
- */
- unsigned long last_rx; /* Time of last Rx */
- /* Interface address info used in eth_type_trans() */
- unsigned char *dev_addr; /* hw address, (before bcast
- because most packets are
- unicast) */
- struct netdev_hw_addr_list dev_addrs; /* list of device
- hw addresses */
- unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */
- #ifdef CONFIG_RPS
- struct kset *queues_kset;
- struct netdev_rx_queue *_rx;
- /* Number of RX queues allocated at alloc_netdev_mq() time */
- unsigned int num_rx_queues;
- #endif
- struct netdev_queue rx_queue;
- struct netdev_queue *_tx ____cacheline_aligned_in_smp;
- /* Number of TX queues allocated at alloc_netdev_mq() time */
- unsigned int num_tx_queues;
- /* Number of TX queues currently active in device */
- unsigned int real_num_tx_queues;
- /* root qdisc from userspace point of view */
- struct Qdisc *qdisc;
- unsigned long tx_queue_len; /* Max frames per queue allowed */
- spinlock_t tx_global_lock;
- /*
- * One part is mostly used on xmit path (device)
- */
- /* These may be needed for future network-power-down code. */
- /*
- * trans_start here is expensive for high speed devices on SMP,
- * please use netdev_queue->trans_start instead.
- */
- unsigned long trans_start; /* Time (in jiffies) of last Tx */
- int watchdog_timeo; /* used by dev_watchdog() */
- struct timer_list watchdog_timer;
- /* Number of references to this device */
- atomic_t refcnt ____cacheline_aligned_in_smp;
- /* delayed register/unregister */
- struct list_head todo_list;
- /* device index hash chain */
- struct hlist_node index_hlist;
- struct list_head link_watch_list;
- /* register/unregister state machine */
- enum { NETREG_UNINITIALIZED=0,
- NETREG_REGISTERED, /* completed register_netdevice */
- NETREG_UNREGISTERING, /* called unregister_netdevice */
- NETREG_UNREGISTERED, /* completed unregister todo */
- NETREG_RELEASED, /* called free_netdev */
- NETREG_DUMMY, /* dummy device for NAPI poll */
- } reg_state:16;
- enum {
- RTNL_LINK_INITIALIZED,
- RTNL_LINK_INITIALIZING,
- } rtnl_link_state:16;
- /* Called from unregister, can be used to call free_netdev */
- void (*destructor)(struct net_device *dev);
- #ifdef CONFIG_NETPOLL
- struct netpoll_info *npinfo;
- #endif
- #ifdef CONFIG_NET_NS
- /* Network namespace this network device is inside */
- struct net *nd_net;
- #endif
- /* mid-layer private */
- void *ml_priv;
- /* bridge stuff */
- struct net_bridge_port *br_port;
- /* macvlan */
- struct macvlan_port *macvlan_port;
- /* GARP */
- struct garp_port *garp_port;
- /* class/net/name entry */
- struct device dev;
- /* space for optional device, statistics, and wireless sysfs groups */
- const struct attribute_group *sysfs_groups[4];
- /* rtnetlink link ops */
- const struct rtnl_link_ops *rtnl_link_ops;
- /* VLAN feature mask */
- unsigned long vlan_features;
- /* for setting kernel sock attribute on TCP connection setup */
- #define GSO_MAX_SIZE 65536
- unsigned int gso_max_size;
- #ifdef CONFIG_DCB
- /* Data Center Bridging netlink ops */
- const struct dcbnl_rtnl_ops *dcbnl_ops;
- #endif
- #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
- /* max exchange id for FCoE LRO by ddp */
- unsigned int fcoe_ddp_xid;
- #endif
- /* n-tuple filter list attached to this device */
- struct ethtool_rx_ntuple_list ethtool_ntuple_list;
- };
我还没有细细的分析这个结构体,驱动程序在probe函数中使用register_netdev()注册该结构体指明的设备,将内核操作硬件的函数个内核联系起来。
更多见下一节分析ARM-Linux驱动--DM9000网卡驱动分析(二)
这篇关于ARM-Linux驱动--DM9000网卡驱动分析(一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!