驱动程序源码解析(转)

本文档深入解析了Linux网络设备驱动程序的结构和关键元素,包括网络设备的宏定义,如ETH_ALEN、ETH_DATA_LEN和ETH_HLEN,以及`struct net_device`结构体的详细成员,如设备名称、内存地址、中断号、状态标志和操作函数等。此外,还介绍了设备的初始化、打开、关闭、发送数据包的流程,以及中断响应处理函数`nic_8019_rx`的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

////////////////    I.与网络设备相关的宏:        /////////////////////////////////

/*下列宏定义于<linux/if_ether.h>中
  ETH_ALEN        网络设备的硬件地址(即MAC地址)长度,单位为一个八位字节,该值通常为6。
  ETH_DATA_LEN        每次传输的最大数据量(不包括14位设备报头)。该值通常为1500。
  ETH_HLEN        设备报头长度。该值通常为14。(包括目的地址(DA长度6)、源地址(SA长度6)、类型字段(TYPE长度2))
  ETH_ZLEN              整个数据包的最小长度。该值通常为60。    
*/    

/*MAX_ADDR_LEN          该宏定义于<linux/netdevice.h>中,指的是网络设备地址(即MAC地址)的最大长度,该值通常为32。*/



///////////////          II.与网络设备相关的结构体:      //////////////////////////////////

/*********************************     struct net_device     *************************************************/
/*为了屏蔽网络环境中物理网络设备的多样性,Linux对所有的物理网络设备进行抽象并定义了一个统一的概念,
  称之为接口(Interface)。每个接口在内部都表现为一个这样的结构体。以下为该结构体的定义:*/
struct net_device    
{    
    /* 以下为该结构体的可见成员,用户可从Space.c等文件中查看到它们*/
    
    char            name[IFNAMSIZ];    /* 网络设备的名称*/
    
    unsigned long        mem_end;    /* 设备发送和接收数据时需要占用内存空间,该值为内存区域的结束地址*/
    
    unsigned long        mem_start;    /* 共享内存区域的起始地址*/
    
    unsigned long        base_addr;    /* 设备I/O操作的基地址,由驱动程序设置,该成员可通过ifconfig来查看或更新*/
    
    unsigned int        irq;        /* 设备的中断号,该成员可通过ifconfig来查看或更新*/


    /*
     *    下列成员只用于部分设备,它们不会出现在Space.c文件中
     */

    unsigned char        if_port;    /* 端口传输特性,用于多端口设备,可选值如下:
                        enum {
                                IF_PORT_UNKNOWN = 0,    //未知方式
                                IF_PORT_10BASE2,    //10兆同轴方式
                                    IF_PORT_10BASET,    //10兆双绞方式
                                IF_PORT_AUI,
                                IF_PORT_100BASET,    
                                IF_PORT_100BASETX,
                                IF_PORT_100BASEFX
                        };*/
                        
    unsigned char        dma;        /* 设备的DMA通道,通常只在与外部总线通讯时才有意义,通过ifconfig可查看该成员*/

    unsigned long        state;        /* 设备的当前状态*/

    struct net_device    *next;        /* 指向全局设备链表中下一个设备的指针*/
    
    
    int            (*init)(struct net_device *dev);    /* 设备的初始化函数,仅需调用一次 */

    /* 至此,在Space.c文件中可见的成员介绍完毕 */
    //////////////////////////////////////////////////////////////////////////////////////////
    
    struct net_device    *next_sched;

    /* 设备索引,唯一的设备标识    */
    int            ifindex;
    int            iflink;


    struct net_device_stats* (*get_stats)(struct net_device *dev);
    struct iw_statistics*    (*get_wireless_stats)(struct net_device *dev);

    /*用于处理无线传输的函数,ioctl的替代品,详情查看 <net/iw_handler.h>*/
    struct iw_handler_def *    wireless_handlers;

    struct ethtool_ops *ethtool_ops;

    /* 至此,该结构体的可见成员已介绍完毕,以下的所有成员都属于系统底层,
     * 而且可能会有不定期变动。*/
    

    /* 在未来处理网络设备掉电的代码中也许会用到以下成员:*/
    unsigned long        trans_start;    /* 进行最后一次发送操作的时间(以jiffies表示)*/
    
    unsigned long        last_rx;    /* 进行最后一次接收操作的时间*/

    unsigned short        flags;        /* 设备标记。可用标记查看<linux/if.h>*/
    
    unsigned short        gflags;        /* 全局标记(?)*/
    
        unsigned short          priv_flags;     /* 类似于flags,但用户空间不可见 */
        
        unsigned short          unused_alignment_fixer; /* Because we need priv_flags,
                 * and we want to be 32-bit aligned.
                 */

    unsigned        mtu;        /* 每次传输的最大数据量(即ETH_DATA_LEN),缺省值为1500字节,该成员可通过ifconfig更改*/
    
    unsigned short        type;        /* 设备类型。(ARP)地址解析协议根据该成员来判断接口支持何种硬件地址。对于以太网设备
                              来说,合适的值为ARPHRD_ETHER。在<linux/if_arp.h>中有所有设备类型。该成员通过ether_setup设置*/
                       
    unsigned short        hard_header_len;/* 设备报头长度。即位于发送数据包中IP报头之前的数据长度(即ETH_HLEN),
                           以太网设备的该值为14。*/
                               
    void            *priv;        /* 相当于filp->private_data。通过alloc_netdev设置,通过netdev_priv访问*/

    struct net_device    *master;     /* 该指针指向当前设备组中该设备所属的主设备*/
    

    /* 设备地址相关信息 */
    unsigned char        broadcast[MAX_ADDR_LEN];    /* 广播地址。由ether_setup 进行分配*/
    
    unsigned char        dev_addr[MAX_ADDR_LEN];        /* 设备地址(MAC地址),通过读取设备信息获得*/
    
    unsigned char        addr_len;    /* 设备地址长度(MAC地址),通常为6*/

    struct dev_mc_list    *mc_list;    /* 用于多点传送的MAC地址列表    */
    
    int            mc_count;    /* 多点传送时MAC地址列表中的元素个数    */
    int            promiscuity;
    int            allmulti;

    int            watchdog_timeo; /* 该成员是一个以jiffies为单位的时间数。表示的是网络层判定传输超时的最小时间标准*/
    struct timer_list    watchdog_timer; /* 用来为超时计数的定时器(?)*/

    /* Protocol specific pointers */
    
    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 list_head    poll_list;    /* Link to poll list    */
    int            quota;
    int            weight;

    struct Qdisc        *qdisc;
    struct Qdisc        *qdisc_sleeping;
    struct Qdisc        *qdisc_ingress;
    struct list_head    qdisc_list;
    unsigned long        tx_queue_len;    /* Max frames per queue allowed */

    /* ingress path synchronizer */
    spinlock_t        ingress_lock;
    /* hard_start_xmit synchronizer */
    spinlock_t        xmit_lock;    /* 该锁用来防止同一时间内对hard_start_xmit函数进行多次调用*/
    /* cpu id of processor entered to hard_start_xmit or -1,
       if nobody entered there.
     */
    int            xmit_lock_owner; /* 该成员指的是获得了xmit_lock的CPU的ID号。-1表示没有当前CPU获得xmit_lock*/
    /* device queue lock */
    spinlock_t        queue_lock;
    /* Number of references to this device */
    atomic_t        refcnt;
    /* delayed register/unregister */
    struct list_head    todo_list;
    /* device name hash chain */
    struct hlist_node    name_hlist;
    /* device index hash chain */
    struct hlist_node    index_hlist;

    /* register/unregister state machine */
    enum { NETREG_UNINITIALIZED=0,
           NETREG_REGISTERING,    /* called register_netdevice */
           NETREG_REGISTERED,    /* completed register todo */
           NETREG_UNREGISTERING,    /* called unregister_netdevice */
           NETREG_UNREGISTERED,    /* completed unregister todo */
           NETREG_RELEASED,        /* called free_netdev */
    } reg_state;

    /* 网络设备的特性 */
    int            features;
#define NETIF_F_SG        1    /* 分散/整合的I/O操作。标志设备可以将分散的数据包整合后再发送 */    
#define NETIF_F_IP_CSUM        2    /* 只对TCP/UDP包进行校验 */
#define NETIF_F_NO
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值