您的位置:首页 > 运维架构 > Linux

ARM-Linux驱动--DM9000网卡驱动分析(一) .

2011-10-18 09:15 555 查看
1、下图是DM9000的引脚图



2、这里我们结合具体的开发板FL2440

下面是FL2440和DM9000的引脚链接图



本人移植DM9000的时候将设备的资源定义放在了arch/arm/plat-s3c24xx/devs.c中,详情点击上一篇博文linux内核移植-移植2.6.35.4内核到s3c2440

下面是设备的资源定义

view plaincopy to clipboardprint?

/*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外部中断。

接着定义平台数据和平台设备,代码如下:

view plaincopy to clipboardprint?

/* 定义平台数据 */
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, //定义平台数据
}
};

最后导出函数符号,保存函数地址和名称

view plaincopy to clipboardprint?

EXPORT_SYMBOL(s3c_device_dm9000);

3、设备启动的初始化过程

view plaincopy to clipboardprint?

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

而后会执行下面函数

view plaincopy to clipboardprint?

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();
}

下面是具体的设备列表

view plaincopy to clipboardprint?

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中

view plaincopy to clipboardprint?

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中

如下:

view plaincopy to clipboardprint?

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()注册该结构体指明的设备,将内核操作硬件的函数个内核联系起来。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: