📄 dm9000x.c
字号:
for (i = 0; i < 6; i++) dev->dev_addr[i] = db->srom[i];#else //random_ether_addr(dev->dev_addr); // mhfan { ////unsigned char enet_addr[]={0x26, 0xdc, 0x6c, 0x11, 0x7b, 0xbb}; //origion unsigned char enet_addr[6] = {0x00, 0x13, 0xf6, 0x6c, 0x87, 0x89}; //from 2.4 for (i=0; i < 6; i++) dev->dev_addr[i] = enet_addr[i]; }#endif /* comment by mhfan */ /* Request IO from system */ request_region(iobase, 2, dev->name); } } while (!dm9000_found && (iobase+=0x10) <= DM9000_MAX_IO); printk("\n\nsun----dmfe_probe_exit\n\n"); 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; printk("\n\nsun----dmfe_open\n\n"); DMFE_DBUG(0, "dmfe_open", 0); //MOD_INC_USE_COUNT; //printk("net irq num is %d\n",dev->irq); //dev->irq=0; //-- // dev->irq=IRQ_EINT0 ; //-- printk("net irq num is %d\n",dev->irq); printk("dev->name is %s\n",dev->name); // set_irq_type(dev->irq, IRQT_RISING); //net irq num is 0 //dev->name is eth0 //if (request_irq(dev->irq, &dmfe_interrupt, SA_INTERRUPT/*SA_SHIRQ*/, dev->name, dev)) if (request_irq(dev->irq, &dmfe_interrupt, /*SA_INTERRUPT*/SA_SHIRQ, dev->name/*"DM9000 device"*/, dev)) { printk("\n\nsun----request_irq failure\n\n"); // if (request_irq(dev->irq, &dmfe_interrupt, SA_INTERRUPT, dev->name, dev)) return -EAGAIN; } //printk("sun-----requets irq exit\n"); /* //writel(0x04|0x4,extint0); //OLD writel(readl(extint0)|0x4444,extint0); //rising edge //writel(readl(intmsk)&0xfff7,intmsk); //OLD writel(readl(intmsk)&0xfffffff0,intmsk); //mask open printk("sun-----set irq register exit\n"); */ /* Initilize DM910X board */ dmfe_init_dm9000(dev); /* Init driver variable */ db->dbug_cnt = 0; db->runt_length_counter = 0; db->long_length_counter = 0; db->reset_counter = 0; /* 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.#if defined(AUTOMDIX) /* set and active a timer process for Auto-MDIX */ init_timer(&db->mdix_timer); db->mdix_timer.expires = DMFE_TIMER_MDIX; db->mdix_timer.data = (unsigned long) dev; db->mdix_timer.function = &dmfe_mdix_timer; add_timer(&db->mdix_timer);#endif netif_start_queue(dev); enable_irq(dev->irq); return 0;}/* Set PHY operationg mode */static void set_PHY_mode(board_info_t * db){ u16 phy_reg0 = 0x1000; /* Auto-negotiation & non-duplux mode */ u16 phy_reg4 = 0x01e1; /* Default non flow control */ if (!(db->op_mode & DM9000_AUTO)) { // op_mode didn't auto sense */ switch (db->op_mode) { case DM9000_10MHD: phy_reg4 = 0x21; phy_reg0 = 0x0000; break; case DM9000_10MFD: phy_reg4 = 0x41; phy_reg0 = 0x1100; break; case DM9000_100MHD: phy_reg4 = 0x81; phy_reg0 = 0x2000; break; case DM9000_100MFD: phy_reg4 = 0x101; phy_reg0 = 0x3100; break; } // end of switch } // end of if phy_write(db, 0, phy_reg0); phy_write(db, 4, 0x0400 | phy_reg4); db->Preg0 = phy_reg0; db->Preg4 = phy_reg4 + 0x0400;}/* Init HomeRun DM9801 */static void program_dm9801(board_info_t * db, u16 HPNA_rev){ __u16 reg16, reg17, reg24, reg25; if (!nfloor) nfloor = DM9801_NOISE_FLOOR; reg16 = phy_read(db, 16); reg17 = phy_read(db, 17); reg24 = phy_read(db, 24); reg25 = phy_read(db, 25); switch (HPNA_rev) { case 0xb900: /* DM9801 E3 */ reg16 |= 0x1000; reg25 = ((reg24 + nfloor) & 0x00ff) | 0xf000; break; case 0xb901: /* DM9801 E4 */ reg25 = ((reg24 + nfloor) & 0x00ff) | 0xc200; reg17 = (reg17 & 0xfff0) + nfloor + 3; break; case 0xb902: /* DM9801 E5 */ case 0xb903: /* DM9801 E6 */ default: reg16 |= 0x1000; reg25 = ((reg24 + nfloor - 3) & 0x00ff) | 0xc200; reg17 = (reg17 & 0xfff0) + nfloor; } phy_write(db, 16, reg16); phy_write(db, 17, reg17); phy_write(db, 25, reg25);}/* Init LongRun DM9802 */static void program_dm9802(board_info_t * db){ __u16 reg25; if (!nfloor) nfloor = DM9802_NOISE_FLOOR; reg25 = phy_read(db, 25); reg25 = (reg25 & 0xff00) + nfloor; phy_write(db, 25, reg25);}/* Identify NIC type */static void identify_nic(board_info_t * db){ u16 phy_reg3; iow(db, 0, DM9000_EXT_MII); phy_reg3 = phy_read(db, 3); switch (phy_reg3 & 0xfff0) { case 0xb900: if (phy_read(db, 31) == 0x4404) { db->nic_type = HOMERUN_NIC; program_dm9801(db, phy_reg3); } else { db->nic_type = LONGRUN_NIC; program_dm9802(db); } break; default: db->nic_type = FASTETHER_NIC; break; } iow(db, 0, DM9000_INT_MII);}/* Initilize dm9000 board */static void dmfe_init_dm9000(struct net_device *dev){ board_info_t *db = (board_info_t *) dev->priv; //printk("\n\nsun----dmfe_init_dm9000\n\n"); DMFE_DBUG(0, "dmfe_init_dm9000()", 0); /* set the internal PHY power-on, GPIOs normal, and wait 2ms */ iow(db, 0x1F, 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, DM9000_NCR, 3); udelay(20); /* wait 20us at least for software reset ok */ iow(db, 0, 3); /* NCR (reg_00h) bit[0] RST=1 & Loopback=1, * reset on. Added by SPenser */ udelay(20); /* wait 20us at least for software reset ok */// Marked by Spenser /* set GPIO0=1 then GPIO0=0 to turn off and on the internal PHY */ iow(db, 0x1F, 1); /* GPR (reg_1Fh) bit[0] GPIO0=1 turn-off PHY */ iow(db, 0x1F, 0); /* GPR (reg_1Fh) bit[0] GPIO0=0 activate PHY *///modify by he udelay(1000); /* wait 4ms linking PHY (AUTO sense) if RX/TX */ udelay(1000); udelay(1000); udelay(1000); /* I/O mode */ db->io_mode = ior(db, 0xfe) >> 6; /* ISR bit7:6 keeps I/O mode */ /* NIC Type: FASTETHER, HOMERUN, LONGRUN */ identify_nic(db); /* Set PHY */ db->op_mode = media_mode; set_PHY_mode(db); /* Init needed register value */ db->reg0 = DM9000_NCR; if ((db->nic_type != FASTETHER_NIC) && (db->op_mode & DM9000_1M_HPNA)) db->reg0 |= DM9000_EXT_MII; /* User passed argument */ db->reg5 = reg5; db->reg8 = reg8; db->reg9 = reg9; db->rega = rega; /* Program operating register */ iow(db, 0x00, 0x08); iow(db, 0x02, 0); /* TX Polling clear */ iow(db, 0x2f, 0); /* Special Mode */ iow(db, 0x01, 0x2c); /* clear TX status */ iow(db, 0xfe, 0x0f); /* Clear interrupt status */ iow(db, 0x08, 0x37); iow(db, 0x09, 0x38); /* Flow control: High/Low water */ iow(db, 0x0a, 0x29); /* flow control */ /* Set address filter table */ dm9000_hash_table(dev); /* Activate DM9000 */ iow(db, 0x05, db->reg5 | 1); /* RX enable */ iow(db, 0xff, DM9000_REGFF); /* Enable TX/RX interrupt mask */ /* Init Driver variable */ db->link_failed = 1; db->tx_pkt_cnt = 0; db->queue_pkt_len = 0; dev->trans_start = 0; netif_carrier_on(dev); spin_lock_init(&db->lock);}#if 0 /* comment by mhfan *//* Reset dm9000 board due to 32bits mode while excess collision * or late collision. */static void dmfe_reset_dm9000(struct net_device *dev){ board_info_t *db = (board_info_t *) dev->priv; DMFE_DBUG(0, "dmfe_reset_dm9000()", 0); iow(db, 0, 1); /* NCR (reg_00h) bit[0] RST=1, reset on. * Added by SPenser */ udelay(1); /* wait 20us at least for software reset ok */ iow(db, 0, 0); /* software reset 2 times */ iow(db, DM9000_NCR, 3); udelay(20); iow(db, DM9000_NCR, 3); udelay(20); /* Program operating register */ iow(db, 0x00, db->reg0); iow(db, 0x02, 0); /* TX Polling clear */ iow(db, 0x08, 0x3f); /* Less 3Kb, 200us */ iow(db, 0x09, 0x38); /* Flow Control : High/Low Water */ iow(db, 0x0a, 0x29); /* TX Pause packet */ iow(db, 0x2f, 0); /* Special Mode */ iow(db, 0x01, 0x2c); /* clear TX status */ iow(db, 0xfe, 0x0f); /* Clear interrupt status */ /* Activate DM9000 */ iow(db, 0x05, db->reg5 | 1); /* RX enable */ iow(db, 0xff, DM9000_REGFF); /* Enable TX/RX interrupt mask */ /* Init Driver variable */ db->link_failed = 1; db->tx_pkt_cnt = 0; db->queue_pkt_len = 0; dev->trans_start = 0; netif_carrier_on(dev);}#endif /* comment by mhfan *//* Hardware start transmission. * Send a packet to media from the upper layer. */static int dmfe_start_xmit(struct sk_buff *skb, struct net_device *dev){ board_info_t *db = (board_info_t *) dev->priv; char *data_ptr; int i, tmplen; //printk("\n\nsun----dmfe_start_xmit\n\n"); DMFE_DBUG(0, "dmfe_start_xmit", 0); if (db->tx_pkt_cnt > 1) return 1; netif_stop_queue(dev); /* Disable all interrupt */ iow(db, 0xff, 0x80); /* Move data to DM9000 TX RAM */ data_ptr = (char *) skb->data; outb(0xf8, db->ioaddr); db->sent_pkt_len = skb->len; if (db->io_mode == DM9000_BYTE_MODE) { /* Byte mode */ for (i = 0; i < skb->len; i++) outb((data_ptr[i] & 0xff), db->io_data); } else if (db->io_mode == DM9000_WORD_MODE) { /* Word mode */ tmplen = (skb->len + 1) / 2;#if 0 /* comment by mhfan */{ int j = 0; for (i = 0; i < tmplen; i++) { printk("%04x ", ((u16 *) data_ptr)[i]); if (++j == 16) { printk("\n"); j = 0; } } printk("\n\033[0m");}#endif /* comment by mhfan */ for (i = 0; i < tmplen; i++) outw(((u16 *) data_ptr)[i], db->io_data); } else { /* DWord mode */ tmplen = (skb->len + 3) / 4; for (i = 0; i < tmplen; i++) outl(((u32 *) data_ptr)[i], db->io_data); } /* TX control: First packet immediately send, second packet queue */ if (db->tx_pkt_cnt == 0) { /* First Packet */ db->tx_pkt_cnt++; /* Set TX length to DM9000 */ iow(db, 0xfc, skb->len & 0xff); iow(db, 0xfd, (skb->len >> 8) & 0xff); /* Issue TX polling command */ iow(db, 0x2, 0x1); /* Cleared after TX complete */ /* saved the time stamp */ dev->trans_start = jiffies; } else { /* Second packet */ db->tx_pkt_cnt++; db->queue_pkt_len = skb->len; } /* free this SKB */ dev_kfree_skb(skb); /* Re-enable resource check */ if (db->tx_pkt_cnt == 1) netif_wake_queue(dev); /* Re-enable interrupt */iow(db, 0xff, 0x83); return 0;}/* Stop the interface. * The interface is stopped when it is brought. */static int dmfe_stop(struct net_device *dev){ board_info_t *db = (board_info_t *) dev->priv; //printk("\n\nsun----dmfe_stop\n\n"); DMFE_DBUG(0, "dmfe_stop", 0); /* deleted timer */ del_timer(&db->timer); del_timer(&db->mdix_timer); netif_stop_queue(dev); /* free interrupt */ free_irq(dev->irq, dev); /* RESET devie */ phy_write(db, 0x00, 0x8000); /* PHY RESET */ iow(db, 0x1f, 0x01); /* Power-Down PHY */ iow(db, 0xff, 0x80); /* Disable all interrupt */ iow(db, 0x05, 0x00); /* Disable RX */ //MOD_DEC_USE_COUNT;#if FALSE /* Dump Statistic counter */ printk("\nRX FIFO OVERFLOW %lx\n", db->stats.rx_fifo_errors); printk("RX CRC %lx\n", db->stats.rx_crc_errors); printk("RX LEN Err %lx\n", db->stats.rx_length_errors); printk("RX LEN < 64byte %x\n", db->runt_length_counter); printk("RX LEN > 1514byte %x\n", db->long_length_counter); printk("RESET %x\n", db->reset_counter); printk("RESET: TX Timeout %x\n", db->reset_tx_timeout); printk("RESET: RX Status Wrong %x\n", db->reset_rx_status);#endif return 0;}static void dmfe_tx_done(unsigned long unused){ struct net_device *dev = dmfe_dev; board_info_t *db = (board_info_t *) dev->priv; int tx_status = ior(db, 0x01); /* Got TX status */ DMFE_DBUG(0, "dmfe_tx_done()", 0); if (tx_status & 0xc) { /* One packet sent complete */ db->tx_pkt_cnt--; dev->trans_start = 0; db->stats.tx_packets++; if (db->tx_pkt_cnt > 0) { /* Queue packet check & send */ /* Set TX length to DM9000 */ iow(db, 0xfc, db->queue_pkt_len & 0xff); iow(db, 0xfd, (db->queue_pkt_len >> 8) & 0xff); /* Issue TX polling command */ iow(db, 0x2, 0x1); /* Cleared after TX complete */ dev->trans_start = jiffies; /* saved the time stamp */ } netif_wake_queue(dev); }}/* DM9102 insterrupt handler. * receive the packet to upper layer, free the transmitted packet */static irqreturn_t dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs){ struct net_device *dev = dev_id; board_info_t *db; int int_status; u8 reg_save; //printk("\n\nsun----dmfe_interrupt\n\n");#if 0 /* comment by mhfan */ DMFE_DBUG(0, "dmfe_interrupt()", 0); if (!(*pFIO_FLAG_C & LAN_FIO_PATTERN)) return IRQ_NONE; *pFIO_FLAG_C = LAN_FIO_PATTERN; asm __volatile__ ("ssync;");#endif /* comment by mhfan */// printk("net isr --->\n");/* //--- if((GEDR2 & 0x40000000) == 0) return; GEDR2 |= 0x40000000; */ if (!dev) { DMFE_DBUG(1, "dmfe_interrupt() without DEVICE arg", 0); return IRQ_NONE; } tintrflag++; /* A real interrupt coming */ db = (board_info_t *) dev->priv;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -