历史上的今天
返回首页

历史上的今天

今天是:2024年11月10日(星期日)

正在发生

2021年11月10日 | mini2440 dm9000 网卡驱动详解 (一)

2021-11-10 来源:eefocus

虽然Linux驱动程序应该是和具体的硬件平台分离的,但是为了更好的理解DM9000的驱动程序,这里还是结合一下Mini2440开发板,这样也可以更好的体会如何实现驱动和平台分离。


本文分成以下几个部分:


一、Mini2440开发板上DM9000的电气连接和Mach-mini2440.c文件的关系。 


二、两个重要的结构体介绍:sk_buff和net_device


三、具体代码分析


一、Mini2440开发板上DM9000的电气连接和Mach-mini2440.c文件的关系


Mini2440开发板上DM9000与S3C2440的连接关系如下:

这个DM9000平台设备作为众多平台设备中的一个在扳子初始化的时候就被添加到了总线上。代码清单如下:


其中片选信号AEN使用了nGCS4,所以网卡的内存区域在BANK4,也就是从地址0x20000000开始。DM9000的TXD[2:0]作为strap pin在电路图中是空接的,所以IO base是300H。中断使用了EINT7。这些内容在Mach文件中有如下体现:


#define S3C2410_CS4 (0x20000000)     

#define MACH_MINI2440_DM9K_BASE (S3C2410_CS4 + 0x300)      

static struct resource mini2440_dm9k_resource[] __initdata = {       

    [0] = {       

        .start = MACH_MINI2440_DM9K_BASE,       

        .end   = MACH_MINI2440_DM9K_BASE + 3,       

        .flags = IORESOURCE_MEM       

    },       

    [1] = {       

        .start = MACH_MINI2440_DM9K_BASE + 4,       

        .end   = MACH_MINI2440_DM9K_BASE + 7,       

        .flags = IORESOURCE_MEM       

    },       

    [2] = {       

        .start = IRQ_EINT7,       

        .end   = IRQ_EINT7,       

        .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,       

    }       

};    


另外在Mach文件中还定义了DM9000平台设备,设备名称为“dm9000”,设备资源就是上面定义的IO和中断资源。代码清单如下:


static struct dm9000_plat_data mini2440_dm9k_pdata __initdata = {      

    .flags      = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),      

};      

     

static struct platform_device mini2440_device_eth __initdata = {      

    .name       = "dm9000",      

    .id     = -1,      

    .num_resources  = ARRAY_SIZE(mini2440_dm9k_resource),      

    .resource   = mini2440_dm9k_resource,      

    .dev        = {      

        .platform_data  = &mini2440_dm9k_pdata,      

    },      

};    


MACHINE_START(MINI2440, "MINI2440")      

    /* Maintainer: Michel Pollet */     

    .phys_io    = S3C2410_PA_UART,      

    .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,      

    .boot_params    = S3C2410_SDRAM_PA + 0x100,      

    .map_io     = mini2440_map_io,      

    .init_machine   = mini2440_init, /*初始化函数*/     

    .init_irq   = s3c24xx_init_irq,      

    .timer      = &s3c24xx_timer,      

MACHINE_END    

  

static void __init mini2440_init(void)      

{      

    ...      

         ...      

    platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));      

     

        ...      

        ...      

}    

 

static struct platform_device *mini2440_devices[] __initdata = {      

    &s3c_device_usb,      

    &s3c_device_wdt,      

/*  &s3c_device_adc,*/ /* ADC doesn't like living with touchscreen ! */     

    &s3c_device_i2c0,      

    &s3c_device_rtc,      

    &s3c_device_usbgadget,      

    &mini2440_device_eth, /*dm9000是众多平台设备中的一个*/     

    &mini2440_led1,      

    &mini2440_led2,      

    &mini2440_led3,      

    &mini2440_led4,      

    &mini2440_button_device,      

    &s3c_device_nand,      

    &s3c_device_sdi,      

    &s3c_device_iis,      

    &mini2440_audio,      

/*  &s3c_device_timer[0],*/ /* buzzer pwm, no API for it */     

    /* remaining devices are optional */     

};    


二、两个重要的结构体简单介绍:sk_buff和net_device

 *sk_buff


如果把网络传输看成是运送货物的话,那么sk_buff就是这个“货物”了,所有经手这个货物的人都要干点什么事儿,要么加个包装,要么印个戳儿等等。收货的时候就要拆掉这些包装,得到我们需要的货物(payload data)。没有货物你还运输什么呢?由此可见sk_buff的重要性了。关于sk_buff的详细介绍和几个操作它的函数,参考:“linux内核sk_buff的结构分析” http://www.linuxidc.com/Linux/2011-07/39163.htm,写得非常明白了。赞一个~


 *net_device


又是一个庞大的结构体。好吧,我承认我从来就没有看全过这个结构体。它在内核中就是指代了一个网络设备。驱动程序需要在探测的时候分配并初始化这个结构体,然后使用register_netdev来注册它,这样就可以把操作硬件的函数与内核挂接在一起。


三、具体代码的分析


在顺序分析之前先看三个结构体变量和一个自定义的结构体。


* dm9000_driver变量。是platform_driver结构体变量,其中包含了重要的:驱动的名字(用来match)和几个重要操作函数。


static struct platform_driver dm9000_driver = {      

    .driver = {      

        .name    = "dm9000",      

        .owner   = THIS_MODULE,      

    },      

    .probe   = dm9000_probe,      

    .remove  = __devexit_p(dm9000_drv_remove),      

    .suspend = dm9000_drv_suspend,      

    .resume  = dm9000_drv_resume,      

};    


* dm9000_netdev_ops变量。是net_device_ops结构体变量, 其中定义了操作net_device的重要函数,我们在驱动程序中根据需要的操作要填充这些函数。代码清单如下:


static const struct net_device_ops dm9000_netdev_ops = {      

    .ndo_open       = dm9000_open,      

    .ndo_stop       = dm9000_stop,      

    .ndo_start_xmit     = dm9000_start_xmit,      

    .ndo_tx_timeout     = dm9000_timeout,      

    .ndo_set_multicast_list = dm9000_hash_table,      

    .ndo_do_ioctl       = dm9000_ioctl,      

    .ndo_change_mtu     = eth_change_mtu,      

    .ndo_validate_addr  = eth_validate_addr,      

    .ndo_set_mac_address    = eth_mac_addr,     

#ifdef CONFIG_NET_POLL_CONTROLLER      

    .ndo_poll_controller    = dm9000_poll_controller,     

#endif      

};    



 * dm9000_ethtool_ops变量。是ethtool_ops结构体变量,为了支持ethtool,其中的函数主要是用于查询和设置网卡参数(当然也有的驱动程序可能不支持ethtool)。代码清单如下:


static const struct ethtool_ops dm9000_ethtool_ops = {      

    .get_drvinfo        = dm9000_get_drvinfo,      

    .get_settings       = dm9000_get_settings,      

    .set_settings       = dm9000_set_settings,      

    .get_msglevel       = dm9000_get_msglevel,      

    .set_msglevel       = dm9000_set_msglevel,      

    .nway_reset     = dm9000_nway_reset,      

    .get_link       = dm9000_get_link,      

    .get_eeprom_len     = dm9000_get_eeprom_len,      

    .get_eeprom     = dm9000_get_eeprom,      

    .set_eeprom     = dm9000_set_eeprom,      

};    


*board_info结构体。用来保存芯片相关的一些私有信息。具体在代码中分析。下面是这个结构体的清单。


/* Structure/enum declaration ------------------------------- */     

typedef 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     dbug_cnt;      

    u8      io_mode;        /* 0:word, 2:byte */     

    u8      phy_addr;      

    u8      imr_all;      

推荐阅读

史海拾趣

Hamlin ( Littelfuse )公司的发展小趣事

故事一:市场定位与技术创新

HAHN - Elektrobau GmbH & Co KG公司自成立以来,便在电子行业中找到了自己的独特定位,专注于生产面向特定应用的特种变压器线圈。起初,公司通过深入研究市场需求,发现传统变压器线圈在特定应用中存在效率低下、体积过大等问题。于是,HAHN投入大量资源进行技术研发,优化产品设计,成功开发出了一系列高效、紧凑的特种变压器线圈,迅速赢得了市场的认可。这一举措不仅巩固了公司在电子行业中的地位,也为后续的发展奠定了坚实的基础。

故事二:合作与共赢

在发展过程中,HAHN深知合作的重要性。公司积极与上下游企业建立紧密的合作关系,共同推动技术进步和产业升级。例如,HAHN与多家知名电子制造商建立了长期合作关系,共同开发新产品,优化生产工艺。通过这些合作,HAHN不仅获得了宝贵的市场信息和技术支持,还成功地将自身产品打入了更广阔的市场领域。同时,公司还积极与供应商和分包商合作,通过优化供应链管理,降低了生产成本,提高了生产效率,实现了共赢发展。

故事三:全球化战略

随着电子行业的全球化趋势日益明显,HAHN也开始了自己的全球化战略。公司不仅在欧洲市场取得了显著成绩,还积极向亚洲、北美等市场扩张。为了更好地服务全球客户,HAHN在多个国家和地区设立了分支机构,并建立了完善的销售和服务网络。通过这些举措,HAHN成功地将自己的产品和服务推向了全球市场,进一步提升了品牌知名度和市场份额。

故事四:品质与服务的双重保障

在电子行业中,品质和服务是企业生存和发展的关键。HAHN深知这一点,因此始终将品质和服务放在首位。公司建立了严格的质量控制体系,对每一个环节都进行严格的把关,确保产品质量达到最高标准。同时,公司还注重提升客户服务水平,建立了专业的客户服务团队,为客户提供全方位、个性化的服务。这些举措不仅赢得了客户的信赖和好评,也为公司赢得了更多的业务机会。

故事五:持续研发与创新

面对日新月异的电子行业技术,HAHN始终保持着高度的敏锐性和前瞻性。公司不断加大研发投入,引进高端人才和先进设备,致力于新技术、新产品的开发。通过持续的研发和创新,HAHN不断推出具有自主知识产权的新产品和技术方案,为电子行业的发展注入了新的活力。同时,公司还积极参与行业标准的制定和修订工作,推动行业技术进步和产业升级。这些努力不仅提升了公司的核心竞争力,也为公司的可持续发展奠定了坚实的基础。

AAEON公司的发展小趣事

AAEON公司是一家总部位于台湾的全球性电子公司,专注于提供嵌入式计算解决方案和人工智能应用平台。以下是关于该公司发展的五个相关故事:

  1. 公司成立和初期发展: AAEON公司成立于1992年,最初主要从事电脑主板的设计和生产。公司在成立初期致力于提供高质量、高性能的计算解决方案,迅速在台湾本地市场建立了良好的声誉。

  2. 技术创新和产品多样化: 随着技术的发展和市场需求的变化,AAEON开始进行技术创新,并逐步扩展产品线。公司不仅持续改进和推出新型的嵌入式计算产品,还积极涉足人工智能领域,开发智能边缘计算平台和解决方案。

  3. 国际市场拓展: 为了进一步扩大业务规模,AAEON积极拓展国际市场。公司与全球各地的合作伙伴建立了广泛的合作关系,产品销售网络覆盖了亚洲、欧洲、北美和其他地区。公司还在一些国家设立了分支机构和办事处,加强了对当地市场的开拓和服务。

  4. 合作伙伴关系和生态系统建设: AAEON与众多的合作伙伴建立了紧密的合作关系,共同推动产品的创新和市场拓展。公司与主流的芯片厂商、系统集成商、软件开发商等建立了长期稳定的合作关系,共同打造了完善的生态系统。

  5. 未来展望和发展方向: AAEON将继续致力于技术创新和产品升级,加强在嵌入式计算和人工智能领域的领先地位。公司将不断推出符合市场需求的新产品和解决方案,为客户提供更优质的服务和支持。同时,AAEON将继续加强与合作伙伴之间的合作,共同推动行业的发展和进步。

CIF公司的发展小趣事

A公司是一家专注于电子元器件生产的CIF公司。在成立初期,A公司凭借其创新的研发能力和高效的生产流程,迅速在市场中脱颖而出。通过与全球多家知名电子产品制造商建立稳定的CIF贸易关系,A公司不断扩大生产规模,优化产品质量,逐渐发展成为行业内的领军企业。

BELDEN公司的发展小趣事

在20世纪初,BELDEN公司在技术创新方面取得了显著突破。公司不仅将塑料绝缘材料应用于电线和电缆制造,还着眼于精密和高质量产品的需求,致力于高附加值的绝缘材料、电缆、防护和护套材料的生产。这些技术创新使得BELDEN的产品在性能和质量上都有了显著提升,进一步巩固了公司在市场中的地位。同时,公司还不断扩大产品线,增加了橡胶绝缘材料等多种新产品,满足了不同客户的需求。

Dicon Fiberoptics Inc公司的发展小趣事

作为一家具有高度责任感的企业,DiCon长期以来一直致力于为国防工业提供高质量的光纤通信产品。公司的首批产品之一FDDI交换机在许多海军舰艇上部署了30多年,为国家的安全稳定做出了重要贡献。这一里程碑事件不仅彰显了DiCon在光纤通信技术领域的实力,也进一步提升了公司的品牌形象和市场地位。

EDAC公司的发展小趣事

ECS-B公司是一家以生产高端电子产品为主的企业。在竞争激烈的电子行业中,ECS-B公司深知品质是企业生存和发展的关键。因此,公司非常重视品质管理,从原材料采购、生产过程到成品检验,都实行严格的质量控制。ECS-B公司还建立了完善的品质管理体系,通过持续改进和优化生产流程,提升产品的品质水平。正是凭借卓越的品质和可靠的性能,ECS-B公司的产品在市场上赢得了良好的口碑和广泛的认可。

问答坊 | AI 解惑

整理下裁员/倒闭行业类别~有个快消招聘,找工作的来~ 奢侈品行业的情况有谁知道?

最近裁员倒闭的一片片,实在看的太多了,整理下下,有补充的可以跟贴,一并列举上。 也给要找的在找的将要找工作的人一点点参考。 申明: 本来的确打算一直做,因为都是大家提供的消息,但是似乎现在有些不同的“凡响”,我无意争什么,所以, ...…

查看全部问答>

杭州,嵌入式项目开发合作,有兴趣的进来看看

准备上个项目,人手不够,打算找人合作。 杭州有产品经验,有业余时间,熟悉工业级ARM,51,tcp/ip,RTOS等之一的技术便可。 有兴趣的回个贴。 技术专长,业余时间,要求等。 sssbang@163.com …

查看全部问答>

RDA的一个例子 pull方法成功,而push不行

//向服务器提交数据 void CRDAExamDlg::OnBtnpush() {         ISSCERDA*pCERDA = NULL;         BSTR bStr = NULL;         BSTR bConnectStr = NULL;       ...…

查看全部问答>

广东北电做vxwork应用,小公司做嵌入式linux应用,该选择哪个?

广东北电做vxwork应用,小公司做嵌入式linux应用,该选择哪个? 其中小公司离家很近,北电离家远一点(隔壁城市) 本人有嵌入式linux两年经验了 两者待遇差不多…

查看全部问答>

汽车电子整车方案

在前面的一个月里,我们一起温习了2008年~2009年上海汽车电子论坛有关技术方面的演讲资料,希望各位网友有所收获。最后一期汽车电子论坛精彩回顾 将与你分享有关零件供应商的演讲资料,了解他们的核心市场及技术优势,这对于研发和采购工程师们来 ...…

查看全部问答>

TI LM3S811 DIY之【数控电源】讨论

目标板是基本最小系统+JTAG部分,所以很多部分都要自己动手来完成了!     数控电源人机界面   1、数码管+键盘;  2、LCD+键盘; 3、PC小工具;   预留PWM,ADC,COMP功能的外围脚       [ ...…

查看全部问答>

DC、AC二者的稳压输出

DC可进行稳压输出,而AC是不是不可以稳压输出,其中的原因是什么呢。。。…

查看全部问答>

大家帮忙看看这几个管子的型号,非常感谢

丝印:6kcA1  封装为SOT-23 丝印:6kX11  封装为SOT-23 丝印:VB02  封装为SOT-23 谢谢大家!…

查看全部问答>