📄 lmc_main.c
字号:
sc->if_type = LMC_PPP; sc->check = 0xBEAFCAFE; dev->base_addr = pci_resource_start(pdev, 0); dev->irq = pdev->irq; SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); /* * This will get the protocol layer ready and do any 1 time init's * Must have a valid sc and dev structure */ lmc_proto_init(sc); lmc_proto_attach(sc); /* * Why were we changing this??? dev->tx_queue_len = 100; */ /* Init the spin lock so can call it latter */ spin_lock_init(&sc->lmc_lock); pci_set_master(pdev); printk ("%s: detected at %lx, irq %d\n", dev->name, dev->base_addr, dev->irq); if (register_netdev (dev) != 0) { printk (KERN_ERR "%s: register_netdev failed.\n", dev->name); goto out4; } sc->lmc_cardtype = LMC_CARDTYPE_UNKNOWN; sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_EXT; /* * * Check either the subvendor or the subdevice, some systems reverse * the setting in the bois, seems to be version and arch dependent? * Fix the error, exchange the two values */ if ((subdevice = pdev->subsystem_device) == PCI_VENDOR_ID_LMC) subdevice = pdev->subsystem_vendor; switch (subdevice) { case PCI_DEVICE_ID_LMC_HSSI: printk ("%s: LMC HSSI\n", dev->name); sc->lmc_cardtype = LMC_CARDTYPE_HSSI; sc->lmc_media = &lmc_hssi_media; break; case PCI_DEVICE_ID_LMC_DS3: printk ("%s: LMC DS3\n", dev->name); sc->lmc_cardtype = LMC_CARDTYPE_DS3; sc->lmc_media = &lmc_ds3_media; break; case PCI_DEVICE_ID_LMC_SSI: printk ("%s: LMC SSI\n", dev->name); sc->lmc_cardtype = LMC_CARDTYPE_SSI; sc->lmc_media = &lmc_ssi_media; break; case PCI_DEVICE_ID_LMC_T1: printk ("%s: LMC T1\n", dev->name); sc->lmc_cardtype = LMC_CARDTYPE_T1; sc->lmc_media = &lmc_t1_media; break; default: printk (KERN_WARNING "%s: LMC UNKOWN CARD!\n", dev->name); break; } lmc_initcsrs (sc, dev->base_addr, 8); lmc_gpio_mkinput (sc, 0xff); sc->lmc_gpio = 0; /* drive no signals yet */ sc->lmc_media->defaults (sc); sc->lmc_media->set_link_status (sc, LMC_LINK_UP); /* verify that the PCI Sub System ID matches the Adapter Model number * from the MII register */ AdapModelNum = (lmc_mii_readreg (sc, 0, 3) & 0x3f0) >> 4; if ((AdapModelNum == LMC_ADAP_T1 && subdevice == PCI_DEVICE_ID_LMC_T1) || /* detect LMC1200 */ (AdapModelNum == LMC_ADAP_SSI && subdevice == PCI_DEVICE_ID_LMC_SSI) || /* detect LMC1000 */ (AdapModelNum == LMC_ADAP_DS3 && subdevice == PCI_DEVICE_ID_LMC_DS3) || /* detect LMC5245 */ (AdapModelNum == LMC_ADAP_HSSI && subdevice == PCI_DEVICE_ID_LMC_HSSI)) { /* detect LMC5200 */ } else { printk ("%s: Model number (%d) miscompare for PCI Subsystem ID = 0x%04x\n", dev->name, AdapModelNum, subdevice);// return (NULL); } /* * reset clock */ LMC_CSR_WRITE (sc, csr_gp_timer, 0xFFFFFFFFUL); sc->board_idx = cards_found++; sc->stats.check = STATCHECK; sc->stats.version_size = (DRIVER_VERSION << 16) + sizeof (struct lmc_statistics); sc->stats.lmc_cardtype = sc->lmc_cardtype; sc->lmc_ok = 0; sc->last_link_status = 0; lmc_trace(dev, "lmc_init_one out"); return 0; out4: lmc_proto_detach(sc); out3: if (pdev) { pci_release_regions(pdev); pci_set_drvdata(pdev, NULL); } out2: free_netdev(dev); out1: return err;}/* * Called from pci when removing module. */static void __devexit lmc_remove_one (struct pci_dev *pdev){ struct net_device *dev = pci_get_drvdata(pdev); if (dev) { lmc_softc_t *sc = dev->priv; printk("%s: removing...\n", dev->name); lmc_proto_detach(sc); unregister_netdev(dev); free_netdev(dev); pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); }}/* After this is called, packets can be sent. * Does not initialize the addresses */static int lmc_open (struct net_device *dev) /*fold00*/{ lmc_softc_t *sc = dev->priv; lmc_trace(dev, "lmc_open in"); lmc_led_on(sc, LMC_DS3_LED0); lmc_dec_reset (sc); lmc_reset (sc); 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)); if (sc->lmc_ok){ lmc_trace(dev, "lmc_open lmc_ok out"); return (0); } lmc_softreset (sc); /* Since we have to use PCI bus, this should work on x86,alpha,ppc */ if (request_irq (dev->irq, &lmc_interrupt, SA_SHIRQ, dev->name, dev)){ printk(KERN_WARNING "%s: could not get irq: %d\n", dev->name, dev->irq); lmc_trace(dev, "lmc_open irq failed out"); return -EAGAIN; } sc->got_irq = 1; /* Assert Terminal Active */ sc->lmc_miireg16 |= LMC_MII16_LED_ALL; sc->lmc_media->set_link_status (sc, LMC_LINK_UP); /* * reset to last state. */ sc->lmc_media->set_status (sc, NULL); /* setup default bits to be used in tulip_desc_t transmit descriptor * -baz */ sc->TxDescriptControlInit = ( LMC_TDES_INTERRUPT_ON_COMPLETION | LMC_TDES_FIRST_SEGMENT | LMC_TDES_LAST_SEGMENT | LMC_TDES_SECOND_ADDR_CHAINED | LMC_TDES_DISABLE_PADDING ); if (sc->ictl.crc_length == LMC_CTL_CRC_LENGTH_16) { /* disable 32 bit CRC generated by ASIC */ sc->TxDescriptControlInit |= LMC_TDES_ADD_CRC_DISABLE; } sc->lmc_media->set_crc_length(sc, sc->ictl.crc_length); /* Acknoledge the Terminal Active and light LEDs */ /* dev->flags |= IFF_UP; */ lmc_proto_open(sc); dev->do_ioctl = lmc_ioctl; netif_start_queue(dev); sc->stats.tx_tbusy0++ ; /* * select what interrupts we want to get */ sc->lmc_intrmask = 0; /* Should be using the default interrupt mask defined in the .h file. */ sc->lmc_intrmask |= (TULIP_STS_NORMALINTR | TULIP_STS_RXINTR | TULIP_STS_TXINTR | TULIP_STS_ABNRMLINTR | TULIP_STS_SYSERROR | TULIP_STS_TXSTOPPED | TULIP_STS_TXUNDERFLOW | TULIP_STS_RXSTOPPED | TULIP_STS_RXNOBUF ); LMC_CSR_WRITE (sc, csr_intr, sc->lmc_intrmask); sc->lmc_cmdmode |= TULIP_CMD_TXRUN; sc->lmc_cmdmode |= TULIP_CMD_RXRUN; LMC_CSR_WRITE (sc, csr_command, sc->lmc_cmdmode); sc->lmc_ok = 1; /* Run watchdog */ /* * Set the if up now - pfb */ sc->last_link_status = 1; /* * Setup a timer for the watchdog on probe, and start it running. * Since lmc_ok == 0, it will be a NOP for now. */ init_timer (&sc->timer); sc->timer.expires = jiffies + HZ; sc->timer.data = (unsigned long) dev; sc->timer.function = &lmc_watchdog; add_timer (&sc->timer); lmc_trace(dev, "lmc_open out"); return (0);}/* Total reset to compensate for the AdTran DSU doing bad things * under heavy load */static void lmc_running_reset (struct net_device *dev) /*fold00*/{ lmc_softc_t *sc = (lmc_softc_t *) dev->priv; lmc_trace(dev, "lmc_runnig_reset in"); /* stop interrupts */ /* Clear the interrupt mask */ LMC_CSR_WRITE (sc, csr_intr, 0x00000000); lmc_dec_reset (sc); lmc_reset (sc); lmc_softreset (sc); /* sc->lmc_miireg16 |= LMC_MII16_LED_ALL; */ sc->lmc_media->set_link_status (sc, 1); sc->lmc_media->set_status (sc, NULL); netif_wake_queue(dev); sc->lmc_txfull = 0; sc->stats.tx_tbusy0++ ; sc->lmc_intrmask = TULIP_DEFAULT_INTR_MASK; LMC_CSR_WRITE (sc, csr_intr, sc->lmc_intrmask); sc->lmc_cmdmode |= (TULIP_CMD_TXRUN | TULIP_CMD_RXRUN); LMC_CSR_WRITE (sc, csr_command, sc->lmc_cmdmode); lmc_trace(dev, "lmc_runnin_reset_out");}/* This is what is called when you ifconfig down a device. * This disables the timer for the watchdog and keepalives, * and disables the irq for dev. */static int lmc_close (struct net_device *dev) /*fold00*/{ /* not calling release_region() as we should */ lmc_softc_t *sc; lmc_trace(dev, "lmc_close in"); sc = dev->priv; sc->lmc_ok = 0; sc->lmc_media->set_link_status (sc, 0); del_timer (&sc->timer); lmc_proto_close(sc); lmc_ifdown (dev); lmc_trace(dev, "lmc_close out"); return 0;}/* Ends the transfer of packets *//* When the interface goes down, this is called */static int lmc_ifdown (struct net_device *dev) /*fold00*/{ lmc_softc_t *sc = dev->priv; u32 csr6; int i; lmc_trace(dev, "lmc_ifdown in"); /* Don't let anything else go on right now */ // dev->start = 0; netif_stop_queue(dev); sc->stats.tx_tbusy1++ ; /* stop interrupts */ /* Clear the interrupt mask */ LMC_CSR_WRITE (sc, csr_intr, 0x00000000); /* Stop Tx and Rx on the chip */ csr6 = LMC_CSR_READ (sc, csr_command); csr6 &= ~LMC_DEC_ST; /* Turn off the Transmission bit */ csr6 &= ~LMC_DEC_SR; /* Turn off the Receive bit */ LMC_CSR_WRITE (sc, csr_command, csr6); sc->stats.rx_missed_errors += LMC_CSR_READ (sc, csr_missed_frames) & 0xffff; /* release the interrupt */ if(sc->got_irq == 1){ free_irq (dev->irq, dev); sc->got_irq = 0; } /* free skbuffs in the Rx queue */ for (i = 0; i < LMC_RXDESCS; i++) { struct sk_buff *skb = sc->lmc_rxq[i]; sc->lmc_rxq[i] = NULL; sc->lmc_rxring[i].status = 0; sc->lmc_rxring[i].length = 0; sc->lmc_rxring[i].buffer1 = 0xDEADBEEF; if (skb != NULL) dev_kfree_skb(skb); sc->lmc_rxq[i] = NULL; } for (i = 0; i < LMC_TXDESCS; i++) { if (sc->lmc_txq[i] != NULL) dev_kfree_skb(sc->lmc_txq[i]); sc->lmc_txq[i] = NULL; } lmc_led_off (sc, LMC_MII16_LED_ALL); netif_wake_queue(dev); sc->stats.tx_tbusy0++ ; lmc_trace(dev, "lmc_ifdown out"); return 0;}/* Interrupt handling routine. This will take an incoming packet, or clean * up after a trasmit. */static irqreturn_t lmc_interrupt (int irq, void *dev_instance, struct pt_regs *regs) /*fold00*/{ struct net_device *dev = (struct net_device *) dev_instance; lmc_softc_t *sc; u32 csr; int i; s32 stat; unsigned int badtx; u32 firstcsr; int max_work = LMC_RXDESCS; int handled = 0; lmc_trace(dev, "lmc_interrupt in"); sc = dev->priv; spin_lock(&sc->lmc_lock); /* * Read the csr to find what interrupts we have (if any) */ csr = LMC_CSR_READ (sc, csr_status); /* * Make sure this is our interrupt */ if ( ! (csr & sc->lmc_intrmask)) { goto lmc_int_fail_out; } firstcsr = csr; /* always go through this loop at least once */ while (csr & sc->lmc_intrmask) { handled = 1; /* * Clear interrupt bits, we handle all case below */ LMC_CSR_WRITE (sc, csr_status, csr); /* * One of * - Transmit process timed out CSR5<1> * - Transmit jabber timeout CSR5<3>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -