DM9000网卡驱动详细分析(1)

来源:互联网 发布:淘宝宝贝销量多久清空 编辑:程序博客网 时间:2024/04/27 16:32

 

linux下DM9000网卡驱动同样是注册成平台驱动(platform driver)的形式.平台驱动在此就不多做介绍了,具体请参考linux驱动分析之framebuffer驱动.重点介绍DM9000网卡的控制.

首先大致介绍一下DM9000的相关情况.这里参考大牛黄刚博客的一段(略有改动).

 

DM9000的引脚和MINI2440的引脚连接:

 

DM9000  MINI2440 功能描述

SD0   DATA0  数据信号

 |           |

SD15 DATA15  数据信号

CMD  ADDR2  识别为地址还是数据(为高电平时16位数据线上传输的是数据,为低电平时16位数据线上传输的是地址)

INT   EINT7  中断

IOR#  nOE   读命令使能

IOW#  nWE   写命令使能

AEN   nGCS4  片选使能

 

可以看出DM9000与处理器连接了16根数据线,1根地址线,而这唯一的一根地址线用于判断16根数据线上传输的是地址还是数据,所以这16条数据线为数据和地址复用.而片选信号使用的nGCS4(BANK4),则当处理器访问0x20000000 – 0x27FFFFFF这个范围的地址时会激活片选使能信号nGCS4.由于MINI2440使用的是ADDR2这根地址线,故DM9000的地址IO为0x20000000,数据IO为0x2000 0004.向地址IO写数据的时候不会激活ADDR2,所以向DM9000传送的为地址,而向数据IO写数据的时候会激活ADDR2,所以向DM9000传送的为数据.

 

以上为DM9000的读写大致情况.下面着重从源代码的角度分析linux下是如何驱动DM9000的.(driver/net/dm9000.c)

 

static int __init dm9000_init(void)

{

#if defined(CONFIG_ARCH_S3C2410)

unsigned int oldval_bwscon = *(volatile unsigned int *)S3C2410_BWSCON;

unsigned int oldval_bankcon4 = *(volatile unsigned int *)S3C2410_BANKCON4;

*((volatile unsigned int *)S3C2410_BWSCON)=(oldval_bwscon&~(3<<16))|S3C2410_BWSCON_DW4_16|S3C2410_BWSCON_WS4 |

                                                                                             S3C2410_BWSCON_ST4;

*((volatile unsigned int *)S3C2410_BANKCON4) = 0x1f7c;

   *(volatile unsigned int *)S3C2410_BWSCON = oldval_bwscon;

*(volatile unsigned int *)S3C2410_BANKCON4 = oldval_bankcon4;

#endif//这一段是FriendARM加上去的,下面会有所分析

printk(KERN_INFO "%s Ethernet Driver, V%s/n", CARDNAME, DRV_VERSION);

 

return platform_driver_register(&dm9000_driver);

}

 

static void __exit

dm9000_cleanup(void)

{

platform_driver_unregister(&dm9000_driver);

}

 

module_init(dm9000_init);

module_exit(dm9000_cleanup);

 

struct platform_driver dm9000_driver初始化如下:

 

static struct platform_driver dm9000_driver = {

.driver= {

.name    = "dm9000",

.owner = THIS_MODULE,

.pm = &dm9000_drv_pm_ops,

},

.probe   = dm9000_probe,

.remove  = __devexit_p(dm9000_drv_remove),

};

平台设备驱动注册成功时最终会调用到dm9000_driver的probe成员,在函数dm9000_probe中完成设备资源的申请,注册,dm9000网卡的相关检测(如类型,ID号等),网络设备结构的初始化,注册等工作.下面来重点分析这个函数.

 

static int __devinit dm9000_probe(struct platform_device *pdev)

{

struct dm9000_plat_data *pdata = pdev->dev.platform_data;

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

struct net_device *ndev;

const unsigned char *mac_src;

int ret = 0;

int iosize;

int i;

u32 id_val;

 

/* Init network device */

ndev = alloc_etherdev(sizeof(struct board_info));

if (!ndev) {

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

return -ENOMEM;

}

 

SET_NETDEV_DEV(ndev, &pdev->dev);

 

dev_dbg(&pdev->dev, "dm9000_probe()/n");

 

/* setup board info structure */

db = netdev_priv(ndev);

 

db->dev = &pdev->dev;

db->ndev = ndev;

 

spin_lock_init(&db->lock);

mutex_init(&db->addr_lock);

 

INIT_DELAYED_WORK(&db->phy_poll, dm9000_poll_work);

 

此函数的参数struct platform_device *pdev是在平台驱动注册的时候传进来的,指向的结构具体为:

 

static struct resource mini2440_dm9k_resource[] = {

[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,

},

};

/*

* * * The DM9000 has no eeprom, and it's MAC address is set by

* * * the bootloader before starting the kernel.

* * */

static struct dm9000_plat_data mini2440_dm9k_pdata = {

.flags = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),

};

static struct platform_device mini2440_device_eth = {

.name = "dm9000",

.id = -1,

.num_resources = ARRAY_SIZE(mini2440_dm9k_resource),

.resource = mini2440_dm9k_resource,

.dev = {

.platform_data = &mini2440_dm9k_pdata,

},

};

 

原创粉丝点击