Davicom公司DM9000A和DM9010 ISA NIC 以太網(wǎng)驅(qū)動分析
/* Request IO from system */
if(!request_region(iobase, 2, dev->name))
return -ENODEV;
printk(
dm9000_found = TRUE;
/* Allocated board information structure */
memset(dev->priv, 0, sizeof(struct board_info));
db = (board_info_t *)dev->priv;
dmfe_dev = dev;
db->io_addr = iobase;
db->io_data = iobase + 4;
/* driver system function */
dev->base_addr = iobase;
dev->irq = irq;
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;
#if defined(CHECKSUM)
dev->features = dev->features | NETIF_F_NO_CSUM;
#endif
/* Read SROM content */
for (i=0; i64; i++)
((u16 *)db->srom)[i] = read_srom_word(db, i);
/* Set Node Address */
for (i=0; i6; i++)
dev->dev_addr[i] = db->srom[i];
}//end of if()
iobase += 0x10;
}while(!dm9000_found iobase = DM9KS_MAX_IO);
return dm9000_found ? 0:-ENODEV;
}
/*
Open the interface.
The interface is opened whenever ifconfig actives it.
*/
static int dmfe_open(struct net_device *dev)
{
board_info_t *db = (board_info_t *)dev->priv;
u8 reg_nsr;
int i;
DMFE_DBUG(0, dmfe_open, 0);
if (request_irq(dev->irq,dmfe_interrupt,SA_SHIRQ,dev->name,dev))
return -EAGAIN;
/* Initilize DM910X board */
dmfe_init_dm9000(dev);
/* Init driver variable */
db->reset_counter = 0;
db->reset_tx_timeout = 0;
db->cont_rx_pkt_cnt = 0;
/* check link state and media speed */
db->Speed =10;
i=0;
do {
reg_nsr = ior(db,0x1);
if(reg_nsr 0x40) /* link OK!! */
{
/* wait for detected Speed */
mdelay(200);
reg_nsr = ior(db,0x1);
if(reg_nsr 0x80)
db->Speed =10;
else
db->Speed =100;
break;
}
i++;
mdelay(1);
}while(i3000); /* wait 3 second */
//printk(i=%d Speed=%dn,i,db->Speed);
/* set and active a timer process */
init_timer(db->timer);
db->timer.expires = DMFE_TIMER_WUT * 2;
db->timer.data = (unsigned long)dev;
db->timer.function = dmfe_timer;
add_timer(db->timer); //Move to DM9000 initiallization was finished.
netif_start_queue(dev);
return 0;
}
/* Set PHY operationg mode
*/
static void set_PHY_mode(board_info_t *db)
{
u16 phy_reg0 = 0x1200; /* Auto-negotiation Restart Auto-negotiation */
u16 phy_reg4 = 0x01e1; /* Default flow control disable*/
if ( !(db->op_mode DM9KS_AUTO) ) // op_mode didn't auto sense */
{
switch(db->op_mode) {
case DM9KS_10MHD: phy_reg4 = 0x21;
phy_reg0 = 0x1000;
break;
case DM9KS_10MFD: phy_reg4 = 0x41;
phy_reg0 = 0x1100;
break;
case DM9KS_100MHD: phy_reg4 = 0x81;
phy_reg0 = 0x3000;
break;
case DM9KS_100MFD: phy_reg4 = 0x101;
phy_reg0 = 0x3100;
break;
default:
break;
} // end of switch
} // end of if
phy_write(db, 0, phy_reg0);
phy_write(db, 4, phy_reg4);
}
/*
Initilize dm9000 board
*/
static void dmfe_init_dm9000(struct net_device *dev)
{
board_info_t *db = (board_info_t *)dev->priv;
DMFE_DBUG(0, dmfe_init_dm9000(), 0);
/* set the internal PHY power-on, GPIOs normal, and wait 2ms */
iow(db, DM9KS_GPR, 1); /* Power-Down PHY */
udelay(500);
iow(db, DM9KS_GPR, 0); /* GPR (reg_1Fh)bit GPIO0=0 pre-activate PHY */
udelay(20); /* wait 2ms for PHY power-on ready */
/* do a software reset and wait 20us */
iow(db, DM9KS_NCR, 3);
udelay(20); /* wait 20us at least for software reset ok */
iow(db, DM9KS_NCR, 3); /* NCR (reg_00h) bit[0] RST=1 Loopback=1, reset on */
udelay(20); /* wait 20us at least for software reset ok */
/* I/O mode */
db->io_mode = ior(db, DM9KS_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */
/* Set PHY */
db->op_mode = media_mode;
set_PHY_mode(db);
/* Program operating register */
iow(db, DM9KS_NCR, 0);
iow(db, DM9KS_TCR, 0); /* TX Polling clear */
pid控制相關(guān)文章:pid控制原理
評論