DM9000网卡驱动分析

发布时间:2024-09-19  

s3c6410自带的DM9000网卡驱动也是基于platform设备模型。


其定义的设备资源在arch/arm/mach-s3c64xx/mach-smdk6410中。有网卡的resource resource dm9000_resources[],还有一些板级信息,dm9000_plat_data dm9000_setup。

 

1.宏及参数  //板级、系统定义


 1 #define DM9000_PHY        0x40    /* PHY address 0x01 */

 2 

 3 #define CARDNAME    'dm9000'

 4 #define DRV_VERSION    '1.31'

 5 /*

 6  * Transmit timeout, default 5 seconds.

 7  */

 8 static int watchdog = 5000; //5s的延时时间

 9 module_param(watchdog, int, 0400);

10 MODULE_PARM_DESC(watchdog, 'transmit timeout in milliseconds');

11 enum dm9000_type {  //开发板定义了三个DM9000类型

12     TYPE_DM9000E,    /* original DM9000 */

13     TYPE_DM9000A,

14     TYPE_DM9000B

15 };


2.模块注册

此处因为基于platform模型,采用platform_driver_register函数注册内核模块,当设备驱动与设备匹配真确后,转入执行dm9000_probe()函数,该函数包含真正的dm9000网卡驱动注册函数是register_netdev()函数。

1 static int __init dm9000_init(void)

2 {

3     printk(KERN_INFO '%s Ethernet Driver, V%sn', CARDNAME, DRV_VERSION);

5     return platform_driver_register(&dm9000_driver); //platform设备模型注册驱动

6 }

dm9000的platform设备驱动函数如下:


1 static struct platform_driver dm9000_driver = {

2     .driver    = {

3         .name = 'dm9000',

4         .owner     = THIS_MODULE,

5         .pm     = &dm9000_drv_pm_ops,

6     },

7     .probe = dm9000_probe,

8     .remove = __devexit_p(dm9000_drv_remove),

9 };


3.dm9000_probe函数

主要完成网络设备的初始化,以及网卡驱动的注册register_netdev()


  1 static int __devinit  dm9000_probe(struct platform_device *pdev)

  2 {

  3     struct dm9000_plat_data *pdata = pdev->dev.platform_data;//驱动程序中获得系统定义的网卡板级信息

  4                                             //定义在/arch/arm/mach-s3c64xx/mach-smdk6410.c中。

  5     struct board_info *db;    /* Point a board information structure */

  6     struct net_device *ndev; //定义设备结构体

  7     const unsigned char *mac_src;

  8     int ret = 0;

  9     int iosize;

 10     int i;

 11     u32 id_val;

 12 

 13     /* Init network device */

 14 //分配生成net_device结构体  alloc_etherdev是alloc_netdev()针对以太网的快捷操作函数

 15     ndev = alloc_etherdev(sizeof(struct board_info)); 

 16 

 17 //判断是否分配正确

 18     if (!ndev) {

 19         dev_err(&pdev->dev, 'could not allocate device.n');

 20         return -ENOMEM;

 21     }

 22 //建立net_device到device的连接

 23     SET_NETDEV_DEV(ndev, &pdev->dev); 

 24 //内核输出信息

 25     dev_dbg(&pdev->dev, 'dm9000_probe()n');

 26 //函数netdev_priv直接返回了net_device结构末端地址,也就是网卡私有数据结构的起始地址。

 27     /* setup board info structure */

 28     db = netdev_priv(ndev);

 29 

 30     db->dev = &pdev->dev;

 31     db->ndev = ndev;

 32 

 33     spin_lock_init(&db->lock);//初始化自旋锁

 34     mutex_init(&db->addr_lock);

 35 

 36     INIT_DELAYED_WORK(&db->phy_poll, dm9000_poll_work); //??

 37 //获取平台设备资源 resource 地址空间、数据空间、中断信号 7号中断

 38     db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

 39     db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);

 40     db->irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);

 41 //判断资源是否获取成功

 42     if (db->addr_res == NULL || db->data_res == NULL ||

 43      db->irq_res == NULL) {

 44         dev_err(db->dev, 'insufficient resourcesn');

 45         ret = -ENOENT;

 46         goto out;

 47     }

 48 //platform_get_resource的变体 同  platform_get_resource(pdev, IORESOURCE_IRQ, 1)

 49     db->irq_wake = platform_get_irq(pdev, 1); 

 50     if (db->irq_wake >= 0) {

 51         dev_dbg(db->dev, 'wakeup irq %dn', db->irq_wake);

 52                                                                                                          //前面获得中断号  申请中断

 53         ret = request_irq(db->irq_wake, dm9000_wol_interrupt,

 54                  IRQF_SHARED, dev_name(db->dev), ndev);

 55         if (ret) {

 56             dev_err(db->dev, 'cannot get wakeup irq (%d)n', ret);

 57         } else {

 58             /* test to see if irq is really wakeup capable */

 59             ret = set_irq_wake(db->irq_wake, 1);

 60             if (ret) {

 61                 dev_err(db->dev, 'irq %d cannot set wakeup (%d)n',

 62                     db->irq_wake, ret);

 63                 ret = 0;

 64             } else {

 65                 set_irq_wake(db->irq_wake, 0);

 66                 db->wake_supported = 1;

 67             }

 68         }

 69     }

 70 //IO资源分配大小  地址  为resource分配内存

 71     iosize = resource_size(db->addr_res);

 72     db->addr_req = request_mem_region(db->addr_res->start, iosize,

 73                      pdev->name); //内存申请

 74 

 75     if (db->addr_req == NULL) {

 76         dev_err(db->dev, 'cannot claim address reg arean');

 77         ret = -EIO;

 78         goto out;

 79     }

 80 

 81     db->io_addr = ioremap(db->addr_res->start, iosize);

 82 

 83     if (db->io_addr == NULL) {

 84         dev_err(db->dev, 'failed to ioremap address regn');

 85         ret = -EINVAL;

 86         goto out;

 87     }

 88 

 89     iosize = resource_size(db->data_res);

 90     db->data_req = request_mem_region(db->data_res->start, iosize,

 91                      pdev->name);

 92 

 93     if (db->data_req == NULL) {

 94         dev_err(db->dev, 'cannot claim data reg arean');

 95         ret = -EIO;

 96         goto out;

 97     }

 98 

 99     db->io_data = ioremap(db->data_res->start, iosize);

100 

101     if (db->io_data == NULL) {

102         dev_err(db->dev, 'failed to ioremap data regn');

103         ret = -EINVAL;

104         goto out;

105     }

106 //初始化net_device中的成员

107     /* fill in parameters for net-dev structure */

108     ndev->base_addr = (unsigned long)db->io_addr; //网络接口的IO基地址

109     ndev->irq    = db->irq_res->start;//中断号  ifconfig时会打印出这个值  也可通过这个修改

110 

111     /* ensure at least we have a default set of IO routines */

112     dm9000_set_io(db, iosize); 

113 

114     /* check to see if anything is being over-ridden */

115     if (pdata != NULL) {

116         /* check to see if the driver wants to over-ride the

117          * default IO width */

118 //检测与板级信息是否相同

119         if (pdata->flags & DM9000_PLATF_8BITONLY)

120             dm9000_set_io(db, 1);

121 

122         if (pdata->flags & DM9000_PLATF_16BITONLY)

123             dm9000_set_io(db, 2);

124 

125         if (pdata->flags & DM9000_PLATF_32BITONLY)

126             dm9000_set_io(db, 4);

127 

128         /* check to see if there are any IO routine

129          * over-rides */

130 

131         if (pdata->inblk != NULL)

132             db->inblk = pdata->inblk;

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>