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

 

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,

},

};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值