📄 lmc_main.c
字号:
/* * 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); /* Just fill in the entries for the device */ dev->init = lmc_init; dev->type = ARPHRD_HDLC; dev->hard_start_xmit = lmc_start_xmit; dev->open = lmc_open; dev->stop = lmc_close; dev->get_stats = lmc_get_stats; dev->do_ioctl = lmc_ioctl; dev->set_config = lmc_set_config;#if LINUX_VERSION_CODE >= 0x20363 dev->tx_timeout = lmc_driver_timeout; dev->watchdog_timeo = (HZ); /* 1 second */#endif /* * 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); LMC_SETUP_20_DEV; printk ("%s: detected at %lx, irq %d\n", dev->name, ioaddr, dev->irq); if (register_netdev (dev) != 0) { printk (KERN_ERR "%s: register_netdev failed.\n", dev->name); lmc_proto_detach(sc); kfree (dev->priv); kfree (dev); return NULL; } /* * Request the region of registers we need, so that * later on, no one else will take our card away from * us. */ request_region (ioaddr, LMC_REG_RANGE, dev->name); sc->lmc_cardtype = LMC_CARDTYPE_UNKNOWN; sc->lmc_timing = LMC_CTL_CLOCK_SOURCE_EXT; switch (subdevice) { case PCI_PRODUCT_LMC_HSSI: printk ("%s: LMC HSSI\n", dev->name); sc->lmc_cardtype = LMC_CARDTYPE_HSSI; sc->lmc_media = &lmc_hssi_media; break; case PCI_PRODUCT_LMC_DS3: printk ("%s: LMC DS3\n", dev->name); sc->lmc_cardtype = LMC_CARDTYPE_DS3; sc->lmc_media = &lmc_ds3_media; break; case PCI_PRODUCT_LMC_SSI: printk ("%s: LMC SSI\n", dev->name); sc->lmc_cardtype = LMC_CARDTYPE_SSI; sc->lmc_media = &lmc_ssi_media; break; case PCI_PRODUCT_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_PRODUCT_LMC_T1) || /* detect LMC1200 */ (AdapModelNum == LMC_ADAP_SSI && subdevice == PCI_PRODUCT_LMC_SSI) || /* detect LMC1000 */ (AdapModelNum == LMC_ADAP_DS3 && subdevice == PCI_PRODUCT_LMC_DS3) || /* detect LMC5245 */ (AdapModelNum == LMC_ADAP_HSSI && subdevice == PCI_PRODUCT_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 = board_idx; memset (&sc->stats, 0, sizeof (struct lmc_statistics)); 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_probe1 out"); return dev;}/* This is the entry point. This is what is called immediatly. *//* This goes out and finds the card */int lmc_probe_fake(struct net_device *dev) /*fold00*/{ lmc_probe(NULL); /* Return 1 to unloaded bogus device */ return 1;}int lmc_probe (struct net_device *dev) /*fold00*/{ int pci_index = 0; unsigned long pci_ioaddr; unsigned int pci_irq_line; u16 vendor, subvendor, device, subdevice; u32 foundaddr = 0; unsigned char pci_bus, pci_device_fn; u8 intcf = 0; /* The card is only available on PCI, so if we don't have a * PCI bus, we are in trouble. */ if (!LMC_PCI_PRESENT()) {/* printk ("%s: We really want a pci bios!\n", dev->name);*/ return -1; } /* Loop basically until we don't find anymore. */ while (pci_index < 0xff){ struct pci_dev *pdev; /* The tulip is considered an ethernet class of card... */ if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index, &pci_bus, &pci_device_fn) != PCIBIOS_SUCCESSFUL) { /* No card found on this pass */ break; } /* Read the info we need to determine if this is * our card or not */ pdev = pci_find_slot (pci_bus, pci_device_fn); if (!pdev) break; if (pci_enable_device(pdev)) break; vendor = pdev->vendor; device = pdev->device; pci_irq_line = pdev->irq; pci_ioaddr = pci_resource_start (pdev, 0); subvendor = pdev->subsystem_vendor; subdevice = pdev->subsystem_device; pci_set_master (pdev); /* * Make sure it's the correct card. CHECK SUBVENDOR ID! * There are lots of tulip's out there. * Also check the region of registers we will soon be * poking, to make sure no one else has reserved them. * This prevents taking someone else's device. * * Check either the subvendor or the subdevice, some systems reverse * the setting in the bois, seems to be version and arch dependant? * Fix the two variables * */ if (!(check_region (pci_ioaddr, LMC_REG_RANGE)) && (vendor == CORRECT_VENDOR_ID) && (device == CORRECT_DEV_ID) && ((subvendor == PCI_VENDOR_LMC) || (subdevice == PCI_VENDOR_LMC))){ struct net_device *cur, *prev = NULL; /* Fix the error, exchange the two values */ if(subdevice == PCI_VENDOR_LMC){ subdevice = subvendor; subvendor = PCI_VENDOR_LMC ; } /* Make the call to actually setup this card */ dev = lmc_probe1 (dev, pci_ioaddr, pci_irq_line, device, subdevice, cards_found); if (dev == NULL) { printk ("lmc_probe: lmc_probe1 failed\n"); goto lmc_probe_next_card; } /* insert the device into the chain of lmc devices */ for (cur = Lmc_root_dev; cur != NULL; cur = ((lmc_softc_t *) cur->priv)->next_module) { prev = cur; } if (prev == NULL) Lmc_root_dev = dev; else ((lmc_softc_t *) prev->priv)->next_module = dev; ((lmc_softc_t *) dev->priv)->next_module = NULL; /* end insert */ foundaddr = dev->base_addr; cards_found++; intcf++; } lmc_probe_next_card: pci_index++; } if (cards_found < 1) return -1;#if LINUX_VERSION_CODE >= 0x20200 return foundaddr;#else return 0;#endif}/* 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; LMC_XMITTER_INIT(dev); #if LINUX_VERSION_CODE < 0x20363 dev->start = 1;#endif sc->stats.tx_tbusy0++ ; MOD_INC_USE_COUNT; /* * 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); //dev->flags |= IFF_RUNNING; LMC_XMITTER_FREE(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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -