Davicom公司DM9000A和DM9010 ISA NIC 以太網(wǎng)驅(qū)動(dòng)分析
receive the packet to upper layer, free the transmitted packet
*/
#if LINUX_VERSION_CODE KERNEL_VERSION(2,5,0)
static void dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#else
static irqreturn_t dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#endif
{
struct net_device *dev = dev_id;
board_info_t *db;
int int_status,i;
u8 reg_save;
DMFE_DBUG(0, dmfe_interrupt(), 0);
/* A real interrupt coming */
db = (board_info_t *)dev->priv;
spin_lock(db->lock);
/* Save previous register address */
reg_save = inb(db->io_addr);
/* Disable all interrupt */
iow(db, DM9KS_IMR, DM9KS_DISINTR);
/* Got DM9000A/DM9010 interrupt status */
int_status = ior(db, DM9KS_ISR); /* Got ISR */
iow(db, DM9KS_ISR, int_status); /* Clear ISR status */
/* Link status change */
if (int_status DM9KS_LINK_INTR)
{
netif_stop_queue(dev);
for(i=0; i500; i++) /*wait link OK, waiting time =0.5s */
{
phy_read(db,0x1);
if(phy_read(db,0x1) 0x4) /*Link OK*/
{
/* wait for detected Speed */
for(i=0; i200;i++)
udelay(1000);
/* set media speed */
if(phy_read(db,0)0x2000) db->Speed =100;
else db->Speed =10;
break;
}
udelay(1000);
}
netif_wake_queue(dev);
//printk([INTR]i=%d speed=%dn,i, (int)(db->Speed));
}
/* Received the coming packet */
if (int_status DM9KS_RX_INTR)
dmfe_packet_receive(dev);
/* Trnasmit Interrupt check */
if (int_status DM9KS_TX_INTR)
dmfe_tx_done(0);
if (db->cont_rx_pkt_cnt>=CONT_RX_PKT_CNT)
{
iow(db, DM9KS_IMR, 0xa2);
}
else
{
/* Re-enable interrupt mask */
iow(db, DM9KS_IMR, DM9KS_REGFF);
}
/* Restore previous register address */
outb(reg_save, db->io_addr);
spin_unlock(db->lock);
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
return IRQ_HANDLED;
#endif
}
/*
Get statistics from driver.
*/
static struct net_device_stats * dmfe_get_stats(struct net_device *dev)
{
board_info_t *db = (board_info_t *)dev->priv;
DMFE_DBUG(0, dmfe_get_stats, 0);
return db->stats;
}
/*
Process the upper socket ioctl command
*/
static int dmfe_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
DMFE_DBUG(0, dmfe_do_ioctl(), 0);
return 0;
}
/* Our watchdog timed out. Called by the networking layer */
static void
dmfe_timeout(struct net_device *dev)
{
board_info_t *db = (board_info_t *)dev->priv;
DMFE_DBUG(0, dmfe_TX_timeout(), 0);
printk(TX time-out -- dmfe_timeout().n);
db->reset_tx_timeout++;
db->stats.tx_errors++;
#if FALSE
printk(TX packet count = %dn, db->tx_pkt_cnt);
printk(TX timeout = %dn, db->reset_tx_timeout);
printk(22H=0x%02x 23H=0x%02xn,ior(db,0x22),ior(db,0x23));
printk(faH=0x%02x fbH=0x%02xn,ior(db,0xfa),ior(db,0xfb));
#endif
dmfe_reset(dev);
}
static void dmfe_reset(struct net_device * dev)
{
board_info_t *db = (board_info_t *)dev->priv;
u8 reg_save;
int i;
/* Save previous register address */
reg_save = inb(db->io_addr);
netif_stop_queue(dev);
db->reset_counter++;
dmfe_init_dm9000(dev);
db->Speed =10;
for(i=0; i1000; i++) /*wait link OK, waiting time=1 second */
{
if(phy_read(db,0x1) 0x4) /*Link OK*/
{
if(phy_read(db,0)0x2000) db->Speed =100;
else db->Speed =10;
break;
}
udelay(1000);
}
netif_wake_queue(dev);
/* Restore previous register address */
outb(reg_save, db->io_addr);
}
/*
A periodic timer routine
*/
static void dmfe_timer(unsigned long data)
{
struct net_device * dev = (struct net_device *)data;
board_info_t *db = (board_info_t *)dev->priv;
DMFE_DBUG(0, dmfe_timer(), 0);
if (db->cont_rx_pkt_cnt>=CONT_RX_PKT_CNT)
{
db->cont_rx_pkt_cnt=0;
iow(db, DM9KS_IMR, DM9KS_REGFF);
}
/* Set timer again */
db->timer.expires = DMFE_TIMER_WUT;
add_timer(db->timer);
return;
}
#if !defined(CHECKSUM)
pid控制相關(guān)文章:pid控制原理
評論