📄 dm9000x.c
字号:
#if 0 /* comment by mhfan */ spin_lock(&db->lock);#else spin_lock_irq(&db->lock);#endif /* comment by mhfan */ /* Save previous register address */ reg_save = inb(db->ioaddr); /* Disable all interrupt */ iow(db, 0xff, 0x80);//by he /* Got DM9000 interrupt status */ int_status = ior(db, 0xfe); /* Got ISR */ iow(db, 0xfe, int_status); /* Clear ISR status *///by he if (int_status & DM9000_TX_INTR) { /* Trnasmit Interrupt check */ dmfe_tx_done(0); } if (int_status & DM9000_RX_INTR) { /* Received the coming packet */ rxintrflag++;#if 0 /* comment by mhfan */ tasklet_schedule(&dmfe_rx_tasklet);#else dmfe_packet_receive(0);#endif /* comment by mhfan */ } /* Re-enable interrupt mask */ iow(db, 0xff, 0x83); /* Restore previous register address */ outb(reg_save, db->ioaddr);#if 0 /* comment by mhfan */ spin_unlock(&db->lock);#else spin_unlock_irq(&db->lock);#endif /* comment by mhfan */ return IRQ_HANDLED;}/* 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;}/* A periodic timer routine Dynamic media sense, allocated Rx buffer...*/static void dmfe_timer(unsigned long data){ struct net_device *dev = (struct net_device *) data; board_info_t *db = (board_info_t *) dev->priv; u8 reg_save, tmp_reg;// DMFE_DBUG(0, "dmfe_timer()", 0); /* Save previous register address */ reg_save = inb(db->ioaddr); /* TX timeout check */ if (dev->trans_start && ((jiffies - dev->trans_start) > DMFE_TX_TIMEOUT)) { db->device_wait_reset = 1; db->reset_tx_timeout++; } /* DM9000 dynamic RESET check and do */ if (db->device_wait_reset) { netif_stop_queue(dev); db->reset_counter++; db->device_wait_reset = 0; dev->trans_start = 0; dmfe_init_dm9000(dev); netif_wake_queue(dev); } /* Auto Sense Media mode policy: FastEthernet NIC: don't need to do * anything. Media Force mode: don't need to do anything. HomeRun/LongRun * NIC and AUTO_Mode: INT_MII not link, select EXT_MII EXT_MII not link, * select INT_MII */ if ((db->nic_type != FASTETHER_NIC) & (db->op_mode == DM9000_AUTO)) { tmp_reg = ior(db, 0x01); /* Got link status */ if (!(tmp_reg & 0x40)) { /* not link */ db->reg0 ^= 0x80; iow(db, 0x00, db->reg0); } } /* Restore previous register address */ outb(reg_save, db->ioaddr); /* Set timer again */ db->timer.expires = DMFE_TIMER_WUT; add_timer(&db->timer);}#if defined(AUTOMDIX)static void dmfe_mdix_timer(unsigned long data){ struct net_device *dev = (struct net_device *) data; board_info_t *db = (board_info_t *) dev->priv; /* support AUTO-MDIX */ db->mdix = ior(db, DM9000_GPR); db->link_status = ior(db, DM9000_NSR); db->link_status = test_bit(6, &db->link_status); udelay(2000); if (!db->link_status) { switch (db->mdix) { case 0x7c: // use parallel line change to cross line if (netif_carrier_ok(dev)) netif_carrier_off(dev); iow(db, DM9000_GPCR, 0x03); iow(db, DM9000_GPR, 0x02); break; case 0x7e: // use cross line change to parallel line if (netif_carrier_ok(dev)) netif_carrier_off(dev); iow(db, DM9000_GPCR, 0x03); iow(db, DM9000_GPR, 0x00); break; default: break; } } else { if (!netif_carrier_ok(dev)) netif_carrier_on(dev); } /* Set timer again */ db->mdix_timer.expires = DMFE_TIMER_MDIX; add_timer(&db->mdix_timer);}#endif/* Received a packet and pass to upper layer */static void dmfe_packet_receive(unsigned long unused){ struct net_device *dev = dmfe_dev; board_info_t *db = (board_info_t *) dev->priv; struct sk_buff *skb; u8 rxbyte, *rdptr; u16 i, RxStatus, RxLen, GoodPacket, tmplen; u32 tmpdata; DMFE_DBUG(0, "dmfe_packet_receive()", 0); do { /* Check packet ready or not */ ior(db, 0xf0); /* Dummy read */ rxbyte = inb(db->io_data); /* Got most updated data */ if (rxbyte == DM9000_PKT_RDY) { /* packet ready to receive check */ /* A packet ready now & Get status/length */ GoodPacket = TRUE; outb(0xf2, db->ioaddr); /* Selecting io mode */ RxStatus = RxLen = (u16) 0; /* modify Select io mode by jackal 10/28/2003 */ switch (db->io_mode) { case DM9000_BYTE_MODE: RxStatus = inb(db->io_data) + (inb(db->io_data) << 8); RxLen = inb(db->io_data) + (inb(db->io_data) << 8); break; case DM9000_WORD_MODE: RxStatus = inw(db->io_data);#ifndef CONFIG_BLKFIN_DCACHEoutb(0xf2, db->ioaddr);#endif /* comment by mhfan */ RxLen = inw(db->io_data); break; case DM9000_DWORD_MODE: tmpdata = inl(db->io_data); RxStatus = tmpdata; RxLen = tmpdata >> 16; break; default: break; } /* Packet Status check */ if (RxLen < 0x40) { GoodPacket = FALSE; db->runt_length_counter++; } else if (RxLen > DM9000_PKT_MAX) { printk("<DM9000> RST: RX Len:%x(%x)\n", RxLen, RxStatus); db->device_wait_reset = TRUE; db->long_length_counter++; } if (RxStatus & 0xbf00) { GoodPacket = FALSE; if (RxStatus & 0x100) db->stats.rx_fifo_errors++; if (RxStatus & 0x200) db->stats.rx_crc_errors++; if (RxStatus & 0x8000) db->stats.rx_length_errors++; } if (!db->device_wait_reset) { /* Move data from DM9000 */ if (GoodPacket && ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) { skb->dev = dev; skb_reserve(skb, 2); rdptr = (u8 *) skb_put(skb, RxLen - 4); /* Read received packet from RX SARM */ if (db->io_mode == DM9000_BYTE_MODE) { /* Byte mode */ for (i = 0; i < RxLen; i++) rdptr[i] = inb(db->io_data); } else if (db->io_mode == DM9000_WORD_MODE) { /* Word mode */ tmplen = (RxLen + 1) / 2; for (i = 0; i < tmplen; i++) ((u16 *) rdptr)[i] = inw(db->io_data);#if 0 /* comment by mhfan */{ int j = 0; printk("\n\033[32mRxStatus=%04x, RxLen=%04x\n", RxStatus, RxLen); for (i = 0; i < tmplen; i++) { printk("%04x ", ((u16 *) rdptr)[i]); if (++j == 16) { printk("\n"); j = 0; } } printk("\n\033[0m");}#endif /* comment by mhfan */ } else { /* DWord mode */ tmplen = (RxLen + 3) / 4; for (i = 0; i < tmplen; i++) ((u32 *) rdptr)[i] = inl(db->io_data); } /* Pass to upper layer */ skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); db->stats.rx_packets++; } else { /* Without buffer or error packet */ if (db->io_mode == DM9000_BYTE_MODE) { /* Byte mode */ for (i = 0; i < RxLen; i++) inb(db->io_data); } else if (db->io_mode == DM9000_WORD_MODE) { /* Word mode */ tmplen = (RxLen + 1) / 2; for (i = 0; i < tmplen; i++) inw(db->io_data); } else { /* DWord mode */ tmplen = (RxLen + 3) / 4; for (i = 0; i < tmplen; i++) inl(db->io_data); } } } } else if (rxbyte > DM9000_PKT_RDY) { /* Status check: this byte must be 0 or 1 */ printk("RX SRAM 1st byte(%02x) != 01, must reset.\n", rxbyte); iow(db, 0x05, 0x00); /* Stop Device */ iow(db, 0xfe, 0x80); /* Stop INT request */ db->device_wait_reset = TRUE; db->reset_rx_status++; } } while (rxbyte == DM9000_PKT_RDY && !db->device_wait_reset); #if 0 // Spenser if (!db->device_wait_reset) { dmfe_tx_done(0); iow(db, 0xff, 0x83); }#endif /* comment by mhfan */}#if 0 /* comment by mhfan *//* Read a word data from SROM */static u16 read_srom_word(board_info_t * db, int offset){ iow(db, 0xc, offset); iow(db, 0xb, 0x4); udelay(200); iow(db, 0xb, 0x0); return (ior(db, 0xd) + (ior(db, 0xe) << 8));}#endif /* comment by mhfan *//* Set DM9000 multicast address */static void dm9000_hash_table(struct net_device *dev){ board_info_t *db = (board_info_t *) dev->priv; struct dev_mc_list *mcptr = dev->mc_list; int mc_cnt = dev->mc_count; u32 hash_val; u16 i, oft, hash_table[4]; DMFE_DBUG(0, "dm9000_hash_table()", 0); /* Set Node address */ for (i = 0, oft = 0x10; i < 6; i++, oft++) iow(db, oft, dev->dev_addr[i]); /* Clear Hash Table */ for (i = 0; i < 4; i++) hash_table[i] = 0x0; /* broadcast address */ hash_table[3] = 0x8000; /* the multicast address in Hash Table : 64 bits */ for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) { hash_val = cal_CRC((char *) mcptr->dmi_addr, 6, 0) & 0x3f; hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16); } /* Write the hash table to MAC MD table */ for (i = 0, oft = 0x16; i < 4; i++) { iow(db, oft++, hash_table[i] & 0xff); iow(db, oft++, (hash_table[i] >> 8) & 0xff); }}/* Calculate the CRC valude of the Rx packet * flag = 1 : return the reverse CRC (for the received packet CRC) * 0 : return the normal CRC (for Hash Table index) */static unsigned long cal_CRC(unsigned char *Data, unsigned int Len, u8 flag){ u32 crc = ether_crc_le(Len, Data); if (flag) return ~crc; return crc;}/* Read a byte from I/O port */static u8 ior(board_info_t * db, int reg){ outb(reg, db->ioaddr); return inb(db->io_data);}/* Write a byte to I/O port */static void iow(board_info_t * db, int reg, u8 value){ outb(reg, db->ioaddr); outb(value, db->io_data);}/* Read a word from phyxcer */static u16 phy_read(board_info_t * db, int reg){ /* Fill the phyxcer register into REG_0C */ iow(db, 0xc, DM9000_PHY | reg); iow(db, 0xb, 0xc); /* Issue phyxcer read command */ udelay(100); /* Wait read complete */ iow(db, 0xb, 0x0); /* Clear phyxcer read command */ /* The read data keeps on REG_0D & REG_0E */ return (ior(db, 0xe) << 8) | ior(db, 0xd);}/* Write a word to phyxcer */static void phy_write(board_info_t * db, int reg, u16 value){ /* Fill the phyxcer register into REG_0C */ iow(db, 0xc, DM9000_PHY | reg); /* Fill the written data into REG_0D & REG_0E */ iow(db, 0xd, (value & 0xff)); iow(db, 0xe, ((value >> 8) & 0xff)); iow(db, 0xb, 0xa); /* Issue phyxcer write command */ udelay(500); /* Wait write complete */ iow(db, 0xb, 0x0); /* Clear phyxcer write command */}#ifdef MODULEMODULE_LICENSE("GPL");MODULE_AUTHOR("Sten Wang, sten_wang@davicom.com.tw");MODULE_DESCRIPTION("Davicom DM9000 ISA/uP Fast Ethernet Driver");MODULE_PARM(debug, "i");MODULE_PARM(mode, "i");MODULE_PARM(reg5, "i");MODULE_PARM(reg9, "i");MODULE_PARM(rega, "i");MODULE_PARM(nfloor, "i");//MODULE_PARM(SF_mode, "i");/* Description: * when user used insmod to add module, * system invoked init_module() to initilize and register. */int init_module(void){ DMFE_DBUG(0, "init_module() ", debug); printk("\n\nsun----init_module\n\n"); if (debug) dmfe_debug = debug; /* set debug flag */ switch (mode) { case DM9000_10MHD: case DM9000_100MHD: case DM9000_10MFD: case DM9000_100MFD: case DM9000_1M_HPNA: media_mode = mode; break; default: media_mode = DM9000_AUTO; } nfloor = (nfloor > 15) ? 0 : nfloor; return dmfe_probe(0); /* search board and register */}/* Description: * when user used rmmod to delete module, * system invoked clean_module() to un-register DEVICE. */void cleanup_module(void){ board_info_t *db; printk("\n\nsun----cleanup_module\n\n"); DMFE_DBUG(0, "clean_module()", 0); unregister_netdev(dmfe_dev); db = (board_info_t *) dmfe_dev->priv; release_region(dmfe_dev->base_addr, 2); kfree(db); /* free board information */ kfree(dmfe_dev); /* free device structure */ DMFE_DBUG(0, "clean_module() exit", 0);}#elsestatic int __init dmfe_init_module(void){ int err; //printk("\n\nsun----dmfe_init_module\n\n"); dmfe_dev = alloc_etherdev(sizeof(*dmfe_dev)); dmfe_dev->init = dmfe_probe; /* Find a name for this unit */ err = dev_alloc_name(dmfe_dev, "eth%d"); if (err < 0) { printk("\nsun---dev_alloc_name error\n"); return err; } err = register_netdev(dmfe_dev); if (err < 0) { printk("\n sun----register_netdev error\n"); return err; } return 0;}static void __exit dmfe_cleanup_module(void){ printk("\n\nsun----dmfe_cleanup_module\n\n"); unregister_netdev(dmfe_dev); kfree(dmfe_dev->priv); memset(dmfe_dev, 0, sizeof (*dmfe_dev)); dmfe_dev->init = dmfe_probe;}module_init(dmfe_init_module);module_exit(dmfe_cleanup_module);#endif//MODULE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -