实现与局域网传输介质之间物理连接和电信号匹配,还涉及帧的发送和接收,真的封装与拆封,介质访问控制,数据的编码与解码及数据缓存的功能
    
    
    9.2 网络设备驱动程序体系结构
        9.2.1 嵌入式linux网络驱动介绍
        9.2.2 Linux网络设备驱动的体系结构
        9.2.3 网络设备驱动程序编写方法
            1.初始化
            2.数据包的发送和接收
            3.实现模式
            4.
        9.2.4 网络设备驱动程序应用实例
            1.模块加载和卸载
            2.网络接口初始化
    9.3 net_device 数据结构
        9.3.1 全局信息
        9.3.1 硬件信息
        9.3.3 接口信息
        9.3.4 设备方法
        9.3.5 公用成员
    9.4 DM9000网卡概述
        9.4.1 总述
        9.4.2 特点
        9.4.3 内部寄存器
            1.网络控制寄存器(NCR)
            2.网络状态寄存器(NSR)
            3.发送控制寄存器(TCR)
            4.数据包指针1的发送状态寄存器1(TSR_I)
            5.数据包指针2的发送状态寄存器2(TSR_II)
            6.接收控制寄存器(RCR)
            7.接收状态寄存器(RSR)
            8.接收/发送溢出控制寄存器(RTFCR)
            9.发送数据长度寄存器
            10.中断状态寄存器
            11.中断掩码寄存器(IMR)
            
        9.4.4 功能描述
            1.总线
            2.存储器直接访问控制
            3.包的发送
            
    9.5 DM9000网卡驱动移植 driver/net/ethernet/davicom/dm9000.c
        9.5.1 网卡连接
              ********************DM9000网卡与芯片连接图*************

第九章:网卡驱动程序移植
              1.GCS4作为片选信号,所以访问DM9000基址为0x20000000,这是物理地址
              2.CMD:高电平,数据总路线传输数据信号,反之传递地址信号。每次访问需要先将CMD置为低电平发送地址信号,然后置高读写数据
              3.总路线宽为16位,用你WAIT信号
              4.用EINT7外部中断作为中断引脚。
        9.5.2 驱动分析---硬件数据结构
                              
                /* Structure/enum declaration ------------------------------- */
                struct board_info {

                    void __iomem    *io_addr;    //地址基址,这两个地址是内核虚拟地址不是物理地址/* Register I/O base address */
                    void __iomem    *io_data;    //数据基址/* Data I/O address */
                    u16         irq;        /* IRQ 中断号*/

                    u16        tx_pkt_cnt;  //发包计数
                    u16        queue_pkt_len; //队列长度
                    u16        queue_start_addr;//队列开始地址
                    u16        queue_ip_summed;
                    u16        dbug_cnt;
                    u8        io_mode;        /* 0:word, 2:byte */
                    u8        phy_addr;
                    u8        imr_all;

                    unsigned int    flags;
                    unsigned int    in_timeout:1;
                    unsigned int    in_suspend:1;
                    unsigned int    wake_supported:1;
                    //
                    enum dm9000_type type;

                    void (*inblk)(void __iomem *port, void *data, int length); //输入方法
                    void (*outblk)(void __iomem *port, void *data, int length); //输出方法
                    void (*dumpblk)(void __iomem *port, int length);

                    struct device    *dev;         /* parent device */

                    struct resource    *addr_res;   /* resources found *///找到在devs.c中定义的资源
                    struct resource *data_res;
                    struct resource    *addr_req;   /* resources requested *///根据addr_res申请到的资源,上面两个只是知道了网卡所使用的所有资源,但在内核中,物力资源的使用时要经过申请的
                    struct resource *data_req;

                    int         irq_wake;

                    struct mutex     addr_lock;    /* phy and eeprom access lock */

                    struct delayed_work phy_poll;
                    struct net_device  *ndev;

                    spinlock_t    lock; //自旋锁

                    struct mii_if_info mii;//mii信息
                    u32        msg_enable; //使能标志
                    u32        wake_state;

                    int        ip_summed;
                };
                以上用于保存设备属性和相关操作,是设备的物理抽象,最后被挂载到net_device的priv成员也
                
        9.5.3 驱动分析---数据读写函数
                DM9000地址和数据线复用,故读写方法特别。
                当从网卡某个寄存器读值时,要先在地址基址中写入要读取的寄存器地址,然后再从数据基址读取数据。
                    /*
                 *   Read a byte from I/O port
                 */
                static u8
                ior(struct board_info *db, int reg)
                {
                    writeb(reg, db->io_addr);
                    return readb(db->io_data);
                }
                当从网卡某寄存器写入值时,要现在地址基址中写入目标寄存器地址,然后再从数据机制中写入要写进去的数据
                /*
                 *   Write a byte to I/O port
                 */

                static void
                iow(struct board_info *db, int reg, int value)
                {
                    writeb(reg, db->io_addr);
                    writeb(value, db->io_data);
                }
                    
        9.5.4 驱动分析---重置网卡
                启动网卡前要重置,全部网络控制寄存器写入1
                static void
                dm9000_reset(struct board_info *db)
                {
                    dev_dbg(db->dev, "resetting device\n");//调试信息

                    /* Reset DM9000, see DM9000 Application Notes V1.22 Jun 11, 2004 page 29
                     * The essential point is that we have to do a double reset, and the
                     * instruction is to set LBK into MAC internal loopback mode.
                     */
                    iow(db, DM9000_NCR, NCR_RST | NCR_MAC_LBK);//写入要操作的寄存器地址这里是NCR
                    udelay(100); /* Application note says at least 20 us *///延时200
                    if (ior(db, DM9000_NCR) & 1)
                        dev_err(db->dev, "dm9000 did not respond to first reset\n");

                    iow(db, DM9000_NCR, 0);
                    iow(db, DM9000_NCR, NCR_RST | NCR_MAC_LBK);
                    udelay(100);
                    if (ior(db, DM9000_NCR) & 1)//写入置位值,这里是1
                        dev_err(db->dev, "dm9000 did not respond to second reset\n");
                }
        9.5.5 驱动分析---初始化网卡
                由dm9000_probe完成,
                    1.主要是获取和申请硬件资源,
                    2.申请中断号
                    3.初始化net_device结构体
                    4.最后注册网络设备
        9.5.6 驱动分析---打开和关闭网卡
                打开即**网络接口,使能接收网络数据,并能传送到网络协议栈,也可将数据发送到网络上,二网卡的关闭就是是网络接口停止工作。
                static int dm9000_open()
                    
        9.5.7 驱动分析---数据包的发送和接收
                驱动层次,数据包的收发都是通过底层对硬件读写完成,网络来数据将触发硬件中断,根据注册的中断向量表确定处理函数,进入中断向量处理函数,将数据送到上层协议进行处理或转发。
                当协议层已封装好上层协议数据的skb_buffer后,将调用dm9000_start_xmit(struct sk_buff* skb,structnet_device *dev)把数据发送出去
                   ********************8dm9000_start_xmit**************

                 第九章:网卡驱动程序移植
                网络数据包到达,DM9000自动接收并存放在DM9000内部RAM中,产生中断。在中断处理中识别中断原因,并调用接收处理函数。
                接收函数如下
                    static void dm9000_rx()
        9.5.8 DM9000网卡驱动移植
                    
                1.定义网卡设备
                    硬件的使用需要知道硬件所用道德资源,如IO端口和中断号,在arch/arm/plat-s3c24xx中的devs.c添加DM9000用到的地址端口,数据端口,和中断号。
                    要依据硬件连接图
                    1.static struct resource s3c_dm9000_resource[]={}
                    2.添加DM9000平台数据,该数据用于内核传递给驱动程序,
                        arch/arm/mach-s3c2410/devs.c 定义platform_device挂载到structplatform_device结构体成员的dev.platform_data中。
                        DM9000平台数据结构定义在include/linux/dm9000.h,定义如下
                            struct dm9000_plat_data{
                                unsigned int flags;
                                
                                void (*inblk)
                                void (*outblk)
                                void(*dumpblk)
                            }
                        arch/arm/plat-s3c24xx中的devs.c,只需添加以下
                        static struct dm9000_plat_data s3c_device_dm9000_platdata = {
                            .flags = DM9000_PLATF_16BITONLY
                        };
                        
                        struct platform_device s3c_device_dm9000 ={
                            .name = "dm9000",
                            .id =-1,
                            .num
                            .resource
                            .dev = {
                                .platform_data = &s3c_device_dm9000_platdata,
                            }
                        };
                        EXPORT_SYMBOL(s3c_device_dm9000); //声明为全局变量,
                2.添加变量声明
                    在arch/arm/plat-S3c24xx/include/plat/devs.h声明如下
                    extern struct platform_device s3c_device_dm9000;
                3.添加平台设备列表
                    添加网络设备到系统启动设备初始化列表中
                    static struct platform_device *smdk2440_devices[] __initdata ={
                    }
                4.修改dm9000.c
                    0.前面已经完成设备注册到驱动核心
                    1.设置芯片MAC地址
                    2.使能DM9000中断
                    修改如下
                        1.设置GPGCON使GPG1功能设置为EINT7,使用s3c2410_gpio_cfgpin(S3C2410_GPG1,S3C2410_GPF3_EINT7);
                        2.外部中断EXTINT1的[6:4]位置100上升沿触发中,因用到GPIO寄存器地址,必须在文件开头吧相关mach/regs-gpio.h文件包含仅dm9000.c;
                             #include<mach/regs-gpio.h>
                             static void *extin1; //中断寄存器地址
                             static void *intmsk; //中断屏蔽寄存器地址
                             #define EINTMASK (0x560000a4)//外部中断屏蔽
                             #define EXTINT1 (0x5600008c) //外部中断方式
                             #define INTMSK  (0x4A000008) //中断屏蔽
                        3.在dm9000.c中初始化函数xxx_probe的register_netdev添加如下
                             memcpy(ndev->dev_addr,"\0andy1",6);
                             extin1 = ioremap_nocache(EXTINT1,4);
                             intmsk = ioremap_nocache(INTMSK,4);
                             s3c2410_gpio_cfgpin(S3C2410_GPF7,S3C2410_GPF7_EINT7);
                             write1(readl(extin1)|0x40,extin1);
                             write1(read1(intmsk)&0xfff1,intmsk);
                             iounmap(intmsk);
                             iounmap(extint1);
                5.编译内核
                    device drivers -> Network device support ->Ethernet(10 or 100Mbit)->DM9000support
    9.6 小结--分析硬件,内核自带驱动,讲述移植--了解网络驱动体系结构
            9.2解释基础,特别是网络数据结构的主要成员含义

相关文章:

  • 2021-10-05
  • 2022-12-23
  • 2022-01-06
  • 2021-11-14
  • 2022-01-11
  • 2021-08-12
  • 2021-04-15
  • 2021-07-14
猜你喜欢
  • 2021-12-24
  • 2021-04-18
  • 2021-06-25
  • 2022-12-23
  • 2022-01-08
  • 2021-12-02
  • 2021-08-11
相关资源
相似解决方案