📄 lmc_main.c
字号:
return 0;}static struct net_device_stats *lmc_get_stats (struct net_device *dev) /*fold00*/{ lmc_softc_t *sc = dev->priv; unsigned long flags; lmc_trace(dev, "lmc_get_stats in"); spin_lock_irqsave(&sc->lmc_lock, flags); sc->stats.rx_missed_errors += LMC_CSR_READ (sc, csr_missed_frames) & 0xffff; spin_unlock_irqrestore(&sc->lmc_lock, flags); lmc_trace(dev, "lmc_get_stats out"); return (struct net_device_stats *) &sc->stats;}static struct pci_driver lmc_driver = { .name = "lmc", .id_table = lmc_pci_tbl, .probe = lmc_init_one, .remove = __devexit_p(lmc_remove_one),};static int __init init_lmc(void){ return pci_module_init(&lmc_driver);}static void __exit exit_lmc(void){ pci_unregister_driver(&lmc_driver);}module_init(init_lmc);module_exit(exit_lmc);unsigned lmc_mii_readreg (lmc_softc_t * const sc, unsigned devaddr, unsigned regno) /*fold00*/{ int i; int command = (0xf6 << 10) | (devaddr << 5) | regno; int retval = 0; lmc_trace(sc->lmc_device, "lmc_mii_readreg in"); LMC_MII_SYNC (sc); lmc_trace(sc->lmc_device, "lmc_mii_readreg: done sync"); for (i = 15; i >= 0; i--) { int dataval = (command & (1 << i)) ? 0x20000 : 0; LMC_CSR_WRITE (sc, csr_9, dataval); lmc_delay (); /* __SLOW_DOWN_IO; */ LMC_CSR_WRITE (sc, csr_9, dataval | 0x10000); lmc_delay (); /* __SLOW_DOWN_IO; */ } lmc_trace(sc->lmc_device, "lmc_mii_readreg: done1"); for (i = 19; i > 0; i--) { LMC_CSR_WRITE (sc, csr_9, 0x40000); lmc_delay (); /* __SLOW_DOWN_IO; */ retval = (retval << 1) | ((LMC_CSR_READ (sc, csr_9) & 0x80000) ? 1 : 0); LMC_CSR_WRITE (sc, csr_9, 0x40000 | 0x10000); lmc_delay (); /* __SLOW_DOWN_IO; */ } lmc_trace(sc->lmc_device, "lmc_mii_readreg out"); return (retval >> 1) & 0xffff;}void lmc_mii_writereg (lmc_softc_t * const sc, unsigned devaddr, unsigned regno, unsigned data) /*fold00*/{ int i = 32; int command = (0x5002 << 16) | (devaddr << 23) | (regno << 18) | data; lmc_trace(sc->lmc_device, "lmc_mii_writereg in"); LMC_MII_SYNC (sc); i = 31; while (i >= 0) { int datav; if (command & (1 << i)) datav = 0x20000; else datav = 0x00000; LMC_CSR_WRITE (sc, csr_9, datav); lmc_delay (); /* __SLOW_DOWN_IO; */ LMC_CSR_WRITE (sc, csr_9, (datav | 0x10000)); lmc_delay (); /* __SLOW_DOWN_IO; */ i--; } i = 2; while (i > 0) { LMC_CSR_WRITE (sc, csr_9, 0x40000); lmc_delay (); /* __SLOW_DOWN_IO; */ LMC_CSR_WRITE (sc, csr_9, 0x50000); lmc_delay (); /* __SLOW_DOWN_IO; */ i--; } lmc_trace(sc->lmc_device, "lmc_mii_writereg out");}static void lmc_softreset (lmc_softc_t * const sc) /*fold00*/{ int i; lmc_trace(sc->lmc_device, "lmc_softreset in"); /* Initialize the receive rings and buffers. */ sc->lmc_txfull = 0; sc->lmc_next_rx = 0; sc->lmc_next_tx = 0; sc->lmc_taint_rx = 0; sc->lmc_taint_tx = 0; /* * Setup each one of the receiver buffers * allocate an skbuff for each one, setup the descriptor table * and point each buffer at the next one */ for (i = 0; i < LMC_RXDESCS; i++) { struct sk_buff *skb; if (sc->lmc_rxq[i] == NULL) { skb = dev_alloc_skb (LMC_PKT_BUF_SZ + 2); if(skb == NULL){ printk(KERN_WARNING "%s: Failed to allocate receiver ring, will try again\n", sc->name); sc->failed_ring = 1; break; } else{ sc->lmc_rxq[i] = skb; } } else { skb = sc->lmc_rxq[i]; } skb->dev = sc->lmc_device; /* owned by 21140 */ sc->lmc_rxring[i].status = 0x80000000; /* used to be PKT_BUF_SZ now uses skb since we lose some to head room */ sc->lmc_rxring[i].length = skb->end - skb->data; /* use to be tail which is dumb since you're thinking why write * to the end of the packj,et but since there's nothing there tail == data */ sc->lmc_rxring[i].buffer1 = virt_to_bus (skb->data); /* This is fair since the structure is static and we have the next address */ sc->lmc_rxring[i].buffer2 = virt_to_bus (&sc->lmc_rxring[i + 1]); } /* * Sets end of ring */ sc->lmc_rxring[i - 1].length |= 0x02000000; /* Set end of buffers flag */ sc->lmc_rxring[i - 1].buffer2 = virt_to_bus (&sc->lmc_rxring[0]); /* Point back to the start */ LMC_CSR_WRITE (sc, csr_rxlist, virt_to_bus (sc->lmc_rxring)); /* write base address */ /* Initialize the transmit rings and buffers */ for (i = 0; i < LMC_TXDESCS; i++) { if (sc->lmc_txq[i] != NULL){ /* have buffer */ dev_kfree_skb(sc->lmc_txq[i]); /* free it */ sc->stats.tx_dropped++; /* We just dropped a packet */ } sc->lmc_txq[i] = NULL; sc->lmc_txring[i].status = 0x00000000; sc->lmc_txring[i].buffer2 = virt_to_bus (&sc->lmc_txring[i + 1]); } sc->lmc_txring[i - 1].buffer2 = virt_to_bus (&sc->lmc_txring[0]); LMC_CSR_WRITE (sc, csr_txlist, virt_to_bus (sc->lmc_txring)); lmc_trace(sc->lmc_device, "lmc_softreset out");}void lmc_gpio_mkinput(lmc_softc_t * const sc, u_int32_t bits) /*fold00*/{ lmc_trace(sc->lmc_device, "lmc_gpio_mkinput in"); sc->lmc_gpio_io &= ~bits; LMC_CSR_WRITE(sc, csr_gp, TULIP_GP_PINSET | (sc->lmc_gpio_io)); lmc_trace(sc->lmc_device, "lmc_gpio_mkinput out");}void lmc_gpio_mkoutput(lmc_softc_t * const sc, u_int32_t bits) /*fold00*/{ lmc_trace(sc->lmc_device, "lmc_gpio_mkoutput in"); sc->lmc_gpio_io |= bits; LMC_CSR_WRITE(sc, csr_gp, TULIP_GP_PINSET | (sc->lmc_gpio_io)); lmc_trace(sc->lmc_device, "lmc_gpio_mkoutput out");}void lmc_led_on(lmc_softc_t * const sc, u_int32_t led) /*fold00*/{ lmc_trace(sc->lmc_device, "lmc_led_on in"); if((~sc->lmc_miireg16) & led){ /* Already on! */ lmc_trace(sc->lmc_device, "lmc_led_on aon out"); return; } sc->lmc_miireg16 &= ~led; lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16); lmc_trace(sc->lmc_device, "lmc_led_on out");}void lmc_led_off(lmc_softc_t * const sc, u_int32_t led) /*fold00*/{ lmc_trace(sc->lmc_device, "lmc_led_off in"); if(sc->lmc_miireg16 & led){ /* Already set don't do anything */ lmc_trace(sc->lmc_device, "lmc_led_off aoff out"); return; } sc->lmc_miireg16 |= led; lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16); lmc_trace(sc->lmc_device, "lmc_led_off out");}static void lmc_reset(lmc_softc_t * const sc) /*fold00*/{ lmc_trace(sc->lmc_device, "lmc_reset in"); sc->lmc_miireg16 |= LMC_MII16_FIFO_RESET; lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16); sc->lmc_miireg16 &= ~LMC_MII16_FIFO_RESET; lmc_mii_writereg(sc, 0, 16, sc->lmc_miireg16); /* * make some of the GPIO pins be outputs */ lmc_gpio_mkoutput(sc, LMC_GEP_RESET); /* * RESET low to force state reset. This also forces * the transmitter clock to be internal, but we expect to reset * that later anyway. */ sc->lmc_gpio &= ~(LMC_GEP_RESET); LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); /* * hold for more than 10 microseconds */ udelay(50); /* * stop driving Xilinx-related signals */ lmc_gpio_mkinput(sc, LMC_GEP_RESET); /* * Call media specific init routine */ sc->lmc_media->init(sc); sc->stats.resetCount++; lmc_trace(sc->lmc_device, "lmc_reset out");}static void lmc_dec_reset(lmc_softc_t * const sc) /*fold00*/{ u_int32_t val; lmc_trace(sc->lmc_device, "lmc_dec_reset in"); /* * disable all interrupts */ sc->lmc_intrmask = 0; LMC_CSR_WRITE(sc, csr_intr, sc->lmc_intrmask); /* * Reset the chip with a software reset command. * Wait 10 microseconds (actually 50 PCI cycles but at * 33MHz that comes to two microseconds but wait a * bit longer anyways) */ LMC_CSR_WRITE(sc, csr_busmode, TULIP_BUSMODE_SWRESET); udelay(25);#ifdef __sparc__ sc->lmc_busmode = LMC_CSR_READ(sc, csr_busmode); sc->lmc_busmode = 0x00100000; sc->lmc_busmode &= ~TULIP_BUSMODE_SWRESET; LMC_CSR_WRITE(sc, csr_busmode, sc->lmc_busmode);#endif sc->lmc_cmdmode = LMC_CSR_READ(sc, csr_command); /* * We want: * no ethernet address in frames we write * disable padding (txdesc, padding disable) * ignore runt frames (rdes0 bit 15) * no receiver watchdog or transmitter jabber timer * (csr15 bit 0,14 == 1) * if using 16-bit CRC, turn off CRC (trans desc, crc disable) */ sc->lmc_cmdmode |= ( TULIP_CMD_PROMISCUOUS | TULIP_CMD_FULLDUPLEX | TULIP_CMD_PASSBADPKT | TULIP_CMD_NOHEARTBEAT | TULIP_CMD_PORTSELECT | TULIP_CMD_RECEIVEALL | TULIP_CMD_MUSTBEONE ); sc->lmc_cmdmode &= ~( TULIP_CMD_OPERMODE | TULIP_CMD_THRESHOLDCTL | TULIP_CMD_STOREFWD | TULIP_CMD_TXTHRSHLDCTL ); LMC_CSR_WRITE(sc, csr_command, sc->lmc_cmdmode); /* * disable receiver watchdog and transmit jabber */ val = LMC_CSR_READ(sc, csr_sia_general); val |= (TULIP_WATCHDOG_TXDISABLE | TULIP_WATCHDOG_RXDISABLE); LMC_CSR_WRITE(sc, csr_sia_general, val); lmc_trace(sc->lmc_device, "lmc_dec_reset out");}static void lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base, /*fold00*/ size_t csr_size){ lmc_trace(sc->lmc_device, "lmc_initcsrs in"); sc->lmc_csrs.csr_busmode = csr_base + 0 * csr_size; sc->lmc_csrs.csr_txpoll = csr_base + 1 * csr_size; sc->lmc_csrs.csr_rxpoll = csr_base + 2 * csr_size; sc->lmc_csrs.csr_rxlist = csr_base + 3 * csr_size; sc->lmc_csrs.csr_txlist = csr_base + 4 * csr_size; sc->lmc_csrs.csr_status = csr_base + 5 * csr_size; sc->lmc_csrs.csr_command = csr_base + 6 * csr_size; sc->lmc_csrs.csr_intr = csr_base + 7 * csr_size; sc->lmc_csrs.csr_missed_frames = csr_base + 8 * csr_size; sc->lmc_csrs.csr_9 = csr_base + 9 * csr_size; sc->lmc_csrs.csr_10 = csr_base + 10 * csr_size; sc->lmc_csrs.csr_11 = csr_base + 11 * csr_size; sc->lmc_csrs.csr_12 = csr_base + 12 * csr_size; sc->lmc_csrs.csr_13 = csr_base + 13 * csr_size; sc->lmc_csrs.csr_14 = csr_base + 14 * csr_size; sc->lmc_csrs.csr_15 = csr_base + 15 * csr_size; lmc_trace(sc->lmc_device, "lmc_initcsrs out");}static void lmc_driver_timeout(struct net_device *dev) { /*fold00*/ lmc_softc_t *sc; u32 csr6; unsigned long flags; lmc_trace(dev, "lmc_driver_timeout in"); sc = dev->priv; spin_lock_irqsave(&sc->lmc_lock, flags); printk("%s: Xmitter busy|\n", dev->name); sc->stats.tx_tbusy_calls++ ; if (jiffies - dev->trans_start < TX_TIMEOUT) { goto bug_out; } /* * Chip seems to have locked up * Reset it * This whips out all our decriptor * table and starts from scartch */ LMC_EVENT_LOG(LMC_EVENT_XMTPRCTMO, LMC_CSR_READ (sc, csr_status), sc->stats.tx_ProcTimeout); lmc_running_reset (dev); LMC_EVENT_LOG(LMC_EVENT_RESET1, LMC_CSR_READ (sc, csr_status), 0); LMC_EVENT_LOG(LMC_EVENT_RESET2, lmc_mii_readreg (sc, 0, 16), lmc_mii_readreg (sc, 0, 17)); /* restart the tx processes */ csr6 = LMC_CSR_READ (sc, csr_command); LMC_CSR_WRITE (sc, csr_command, csr6 | 0x0002); LMC_CSR_WRITE (sc, csr_command, csr6 | 0x2002); /* immediate transmit */ LMC_CSR_WRITE (sc, csr_txpoll, 0); sc->stats.tx_errors++; sc->stats.tx_ProcTimeout++; /* -baz */ dev->trans_start = jiffies;bug_out: spin_unlock_irqrestore(&sc->lmc_lock, flags); lmc_trace(dev, "lmc_driver_timout out");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -