Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2209302
  • 博文数量: 668
  • 博客积分: 10016
  • 博客等级: 上将
  • 技术积分: 8588
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-29 19:22
文章分类

全部博文(668)

文章存档

2011年(1)

2010年(2)

2009年(273)

2008年(392)

分类:

2009-01-01 08:40:10

该驱动基于linux-2.6.24.4内核。 

首先,需要在arch/arm/mach-s3c2410/mach-smdk2410.c文件中添加如下代码: 
static struct resource s3c_dm9000_resource [] = { 
[0] = { 
.start = 0x10000000, 
.end = 0x10000040, 
.flags = IORESOURCE_MEM 
}, 
[1] = { 
.start = IRQ_EINT2, 
.end = IRQ_EINT2, 
.flags = IORESOURCE_IRQ, 
} 
}; 
注意上面的start、end等地址是指的网卡的物理地址。然后,还要在该文件中加入如下代码: 
struct platform_device s3c_device_dm9000 = { 
.name = "dm9000", 
.id = -1, 
.num_resources = ARRAY_SIZE(s3c_dm9000_resource), 
.resource = s3c_dm9000_resource, 
}; 
需要特别注意上面的name字段,当设备驱动程序寻找设别资源时,会根据该字段对设备进行匹配。另外,该文件中的smdk2410_devices[]数组中,还需要加入s3c_device_dm9000,不然系统启动时没有找到该资源就不会调用相应的probe函数。 
下面分析驱动程序的probe函数。若驱动被编译进内核,则在系统启动的时候,该函数会被调用。该函数的源代码如下: 
static int dm9k_drv_probe(struct platform_device *pdev) 
{ 
struct net_device *ndev; 
unsigned long base; 
unsigned int *addr = NULL; 
int ret = -ENODEV; 
ndev = alloc_etherdev(sizeof(struct board_info)); 
if (!ndev) { 
printk("%s: could not allocate device.\n", CARDNAME); 
return -ENOMEM; 
} 

ndev->dma = (unsigned char)-1; 
if (pdev->num_resources  2 || pdev->num_resources > 3) { 
printk("DM9000: Wrong num of resources %d\n", pdev->num_resources); 
ret = -ENODEV; 
goto out; 
} 
base = pdev->resource[0].start; 
ndev->irq = pdev->resource[1].start; 
/* 
* Request the regions. 
*/ 
if (!request_mem_region(base, 4, ndev->name)) { 
ret = -EBUSY; 
goto out; 
} 
addr = ioremap(base, 4); 
if (!addr) { 
ret = -ENOMEM; 
goto release_mem; 
} 
ret = dm9k_probe(ndev, (unsigned long)addr); 
if (ret != 0) { 
iounmap(addr); 
release_mem: 
release_mem_region(base, 4); 
out: 
printk("%s: not found (%d).\n", CARDNAME, ret); 
kfree(ndev); 
} 
return ret; 
} 
函数首先调用alloc_etherdev,该函数在include/linux/etherdevice.h中声明,其中有如下语句: 
#define alloc_etherdev(sizeof_priv) alloc_etherdev_mq(sizeof_priv, 1) 
而alloc_etherdev_mq函数又定义在net/ethernet/eth.c中,如下: 
struct net_device *alloc_etherdev_mq(int sizeof_priv, unsigned int queue_count) 
{ 
return alloc_netdev_mq(sizeof_priv, "eth%d", ether_setup, queue_count); 
} 
可见,该函数只是用自己的参数来调用alloc_netdev_mq函数。alloc_netdev_mq函数定义在net/core/dev.c中,原型如下: 
struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, 
void (*setup)(struct net_device *), unsigned int queue_count) 
关于该函数的说明: 
/** 
* alloc_netdev_mq - allocate network device 
* @sizeof_priv: size of private data to allocate space for 
* @name:  device name format string 
* @setup:  callback to initialize device 
* @queue_count: the number of subqueues to allocate 
* 
* Allocates a struct net_device with private data area for driver use 
* and performs basic initialization.  Also allocates subquue structs 
* for each queue on the device at the end of the netdevice. 
*/ 
阅读(839) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~