dm9k_probe函数的全部代码如下
int __init dm9k_probe(struct net_device *dev, unsigned long addr)
{
struct board_info *db; /* Point a board information structure */
u32 id_val;
u16 i, j;
int retval;
/* Search for DM9000 serial NIC */
PUTB(DM9KS_VID_L, addr);
id_val = GETB(addr + 2); /* Change offset to 2 ^^^^^ */
PUTB(DM9KS_VID_H, addr);
id_val |= GETB(addr + 2) 8;
PUTB(DM9KS_PID_L, addr);
id_val |= GETB(addr + 2) 16;
PUTB(DM9KS_PID_H, addr);
id_val |= GETB(addr + 2) 24;
if (id_val != DM9KS_ID && id_val != DM9010_ID) {
/* Dm9k chip not found */
printk("dmfe_probe(): DM9000 not found. ID=%08X\n", id_val);
return -ENODEV;
}
printk(" I/O: %lx, VID: %x \n",addr, id_val);
/* Allocated board information structure */
memset(dev->priv, 0, sizeof(struct board_info));
db = (board_info_t *)dev->priv;
dmfe_dev = dev;
db->io_addr = addr;
db->io_data = addr + 2; /* Change offset to 2 ^^^^^ */
/* driver system function */
dev->base_addr = addr;
dev->irq = IRQ_EINT2;
dev->open = &dmfe_open;
dev->hard_start_xmit = &dmfe_start_xmit;
dev->watchdog_timeo = HZ;
dev->tx_timeout = dmfe_timeout;
dev->stop = &dmfe_stop;
dev->get_stats = &dmfe_get_stats;
dev->set_multicast_list = &dm9000_hash_table;
dev->do_ioctl = &dmfe_do_ioctl;
for(i=0,j=0x10; i6; i++,j++)
{
db->srom = ior(db, j);
}
/* Set Node Address */
for (i=0; i6; i++)
dev->dev_addr = db->srom;
retval = register_netdev(dev);
if (retval == 0) {
/* now, print out the card info, in a short format.. */
printk("%s: at %#lx IRQ %d\n",
dev->name, dev->base_addr, dev->irq);
if (dev->dma != (unsigned char)-1)
printk(" DMA %d\n", dev->dma);
if (!is_valid_ether_addr(dev->dev_addr)) {
printk("%s: Invalid ethernet MAC address. Please "
"set using ifconfig\n", dev->name);
} else {
/* Print the Ethernet address */
printk("%s: Ethernet addr: ", dev->name);
for (i = 0; i 5; i++)
printk("%2.2x:", dev->dev_addr);
printk("%2.2x\n", dev->dev_addr[5]);
}
}
return 0;
}
函数首先调用PUTB来写dm9000a芯片,来看看PUTB的实现
#define PUTB(d,a) *((volatile unsigned char *) (a)) = d
可见,PUTB是直接使用的指针,而没有使用内核提供的write等函数,同样,GETB函数如下
#define GETB(a) *((volatile unsigned char *) (a))
注意,这里的地址都是虚拟地址,因为前面调用函数dm9k_probe时传递的addr时重新映射后的,而不是直接传送的物理地址。
具体操作涉及到dm9000a的硬件实现,做简单的说明。dm9000a有两个PORT,一个是INDEX PORT,另一个就是DATA PORT。具体访问哪一个是根据CMD引脚的信号来确定的:CMD为0,则访问INDEX,否则,访问DATA。访问寄存器之前,必须将寄存器的地址存放在INDEX PORT。
首先,驱动程序需要读芯片的ID。DM9000A的ID存放在四个不同的字节中,分别叫做Vendor ID和Product ID。将着四个字节读出来,组合后应该得到0x90000A46,如果读出来的ID与该值不相等,说明不是DM9000A网卡,程序将返回,初始化失败。
读出ID相同后,就可以认为系统中存在dm9000a网卡了,接下来就开始进行其他初始化工作。主要工作
dev->base_addr = addr;
dev->irq = IRQ_EINT2;
dev->open = &dmfe_open;
dev->hard_start_xmit = &dmfe_start_xmit;
dev->watchdog_timeo = HZ;
dev->tx_timeout = dmfe_timeout;
dev->stop = &dmfe_stop;
dev->get_stats = &dmfe_get_stats;
dev->set_multicast_list = &dm9000_hash_table;
dev->do_ioctl = &dmfe_do_ioctl;
就是为net_device的成员指定功能函数,以便系统需要的时候进行调用。完成这些基本的工作后,就可以向系统注册设备了
retval = register_netdev(dev);
注册完成,该函数就返回。probe函数剩下的就是对返回值的判断了,若注册成功,直接推出,probe完成;失败的话,还需要将ioremap过的地方ioumap掉,request_mem_region的地方release掉。
阅读(835) | 评论(0) | 转发(0) |