static void write_av9110(lmc_softc_t *sc, u_int32_t n, u_int32_t m, u_int32_t v, u_int32_t x, u_int32_t r) { int i; #if 0 printf(LMC_PRINTF_FMT ": speed %u, %d %d %d %d %d\n", LMC_PRINTF_ARGS, sc->ictl.clock_rate, n, m, v, x, r); #endif sc->lmc_gpio |= LMC_GEP_SSI_GENERATOR; sc->lmc_gpio &= ~(LMC_GEP_SERIAL | LMC_GEP_SERIALCLK); LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); /* * Set the TXCLOCK, GENERATOR, SERIAL, and SERIALCLK * as outputs. */ lmc_gpio_mkoutput(sc, (LMC_GEP_SERIAL | LMC_GEP_SERIALCLK | LMC_GEP_SSI_GENERATOR)); sc->lmc_gpio &= ~(LMC_GEP_SSI_GENERATOR); LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); /* * a shifting we will go... */ for (i = 0 ; i < 7 ; i++) write_av9110_bit(sc, n >> i); for (i = 0 ; i < 7 ; i++) write_av9110_bit(sc, m >> i); for (i = 0 ; i < 1 ; i++) write_av9110_bit(sc, v >> i); for (i = 0 ; i < 2 ; i++) write_av9110_bit(sc, x >> i); for (i = 0 ; i < 2 ; i++) write_av9110_bit(sc, r >> i); for (i = 0 ; i < 5 ; i++) write_av9110_bit(sc, 0x17 >> i); /* * stop driving serial-related signals */ lmc_gpio_mkinput(sc, (LMC_GEP_SERIAL | LMC_GEP_SERIALCLK | LMC_GEP_SSI_GENERATOR)); }
void lmc_reset(lmc_softc_t * const sc) { 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_DP | LMC_GEP_RESET); /* * drive DP and RESET low to force configuration. This also forces * the transmitter clock to be internal, but we expect to reset * that later anyway. */ sc->lmc_gpio &= ~(LMC_GEP_DP | LMC_GEP_RESET); LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); /* * hold for more than 10 microseconds */ DELAY(50); /* * stop driving Xilinx-related signals */ lmc_gpio_mkinput(sc, LMC_GEP_DP | LMC_GEP_RESET); /* * busy wait for the chip to reset */ while ((LMC_CSR_READ(sc, csr_gp) & LMC_GEP_DP) == 0); /* * Call media specific init routine */ sc->lmc_media->init(sc); }
int lmc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { lmc_softc_t *sc = dev_to_sc(dev); lmc_ctl_t ctl; int ret = -EOPNOTSUPP; u16 regVal; unsigned long flags; lmc_trace(dev, "lmc_ioctl in"); switch (cmd) { case LMCIOCGINFO: if (copy_to_user(ifr->ifr_data, &sc->ictl, sizeof(lmc_ctl_t))) ret = -EFAULT; else ret = 0; break; case LMCIOCSINFO: if (!capable(CAP_NET_ADMIN)) { ret = -EPERM; break; } if(dev->flags & IFF_UP){ ret = -EBUSY; break; } if (copy_from_user(&ctl, ifr->ifr_data, sizeof(lmc_ctl_t))) { ret = -EFAULT; break; } spin_lock_irqsave(&sc->lmc_lock, flags); sc->lmc_media->set_status (sc, &ctl); if(ctl.crc_length != sc->ictl.crc_length) { sc->lmc_media->set_crc_length(sc, ctl.crc_length); if (sc->ictl.crc_length == LMC_CTL_CRC_LENGTH_16) sc->TxDescriptControlInit |= LMC_TDES_ADD_CRC_DISABLE; else sc->TxDescriptControlInit &= ~LMC_TDES_ADD_CRC_DISABLE; } spin_unlock_irqrestore(&sc->lmc_lock, flags); ret = 0; break; case LMCIOCIFTYPE: { u16 old_type = sc->if_type; u16 new_type; if (!capable(CAP_NET_ADMIN)) { ret = -EPERM; break; } if (copy_from_user(&new_type, ifr->ifr_data, sizeof(u16))) { ret = -EFAULT; break; } if (new_type == old_type) { ret = 0 ; break; } spin_lock_irqsave(&sc->lmc_lock, flags); lmc_proto_close(sc); sc->if_type = new_type; lmc_proto_attach(sc); ret = lmc_proto_open(sc); spin_unlock_irqrestore(&sc->lmc_lock, flags); break; } case LMCIOCGETXINFO: spin_lock_irqsave(&sc->lmc_lock, flags); sc->lmc_xinfo.Magic0 = 0xBEEFCAFE; sc->lmc_xinfo.PciCardType = sc->lmc_cardtype; sc->lmc_xinfo.PciSlotNumber = 0; sc->lmc_xinfo.DriverMajorVersion = DRIVER_MAJOR_VERSION; sc->lmc_xinfo.DriverMinorVersion = DRIVER_MINOR_VERSION; sc->lmc_xinfo.DriverSubVersion = DRIVER_SUB_VERSION; sc->lmc_xinfo.XilinxRevisionNumber = lmc_mii_readreg (sc, 0, 3) & 0xf; sc->lmc_xinfo.MaxFrameSize = LMC_PKT_BUF_SZ; sc->lmc_xinfo.link_status = sc->lmc_media->get_link_status (sc); sc->lmc_xinfo.mii_reg16 = lmc_mii_readreg (sc, 0, 16); spin_unlock_irqrestore(&sc->lmc_lock, flags); sc->lmc_xinfo.Magic1 = 0xDEADBEEF; if (copy_to_user(ifr->ifr_data, &sc->lmc_xinfo, sizeof(struct lmc_xinfo))) ret = -EFAULT; else ret = 0; break; case LMCIOCGETLMCSTATS: spin_lock_irqsave(&sc->lmc_lock, flags); if (sc->lmc_cardtype == LMC_CARDTYPE_T1) { lmc_mii_writereg(sc, 0, 17, T1FRAMER_FERR_LSB); sc->extra_stats.framingBitErrorCount += lmc_mii_readreg(sc, 0, 18) & 0xff; lmc_mii_writereg(sc, 0, 17, T1FRAMER_FERR_MSB); sc->extra_stats.framingBitErrorCount += (lmc_mii_readreg(sc, 0, 18) & 0xff) << 8; lmc_mii_writereg(sc, 0, 17, T1FRAMER_LCV_LSB); sc->extra_stats.lineCodeViolationCount += lmc_mii_readreg(sc, 0, 18) & 0xff; lmc_mii_writereg(sc, 0, 17, T1FRAMER_LCV_MSB); sc->extra_stats.lineCodeViolationCount += (lmc_mii_readreg(sc, 0, 18) & 0xff) << 8; lmc_mii_writereg(sc, 0, 17, T1FRAMER_AERR); regVal = lmc_mii_readreg(sc, 0, 18) & 0xff; sc->extra_stats.lossOfFrameCount += (regVal & T1FRAMER_LOF_MASK) >> 4; sc->extra_stats.changeOfFrameAlignmentCount += (regVal & T1FRAMER_COFA_MASK) >> 2; sc->extra_stats.severelyErroredFrameCount += regVal & T1FRAMER_SEF_MASK; } spin_unlock_irqrestore(&sc->lmc_lock, flags); if (copy_to_user(ifr->ifr_data, &sc->lmc_device->stats, sizeof(sc->lmc_device->stats)) || copy_to_user(ifr->ifr_data + sizeof(sc->lmc_device->stats), &sc->extra_stats, sizeof(sc->extra_stats))) ret = -EFAULT; else ret = 0; break; case LMCIOCCLEARLMCSTATS: if (!capable(CAP_NET_ADMIN)) { ret = -EPERM; break; } spin_lock_irqsave(&sc->lmc_lock, flags); memset(&sc->lmc_device->stats, 0, sizeof(sc->lmc_device->stats)); memset(&sc->extra_stats, 0, sizeof(sc->extra_stats)); sc->extra_stats.check = STATCHECK; sc->extra_stats.version_size = (DRIVER_VERSION << 16) + sizeof(sc->lmc_device->stats) + sizeof(sc->extra_stats); sc->extra_stats.lmc_cardtype = sc->lmc_cardtype; spin_unlock_irqrestore(&sc->lmc_lock, flags); ret = 0; break; case LMCIOCSETCIRCUIT: if (!capable(CAP_NET_ADMIN)){ ret = -EPERM; break; } if(dev->flags & IFF_UP){ ret = -EBUSY; break; } if (copy_from_user(&ctl, ifr->ifr_data, sizeof(lmc_ctl_t))) { ret = -EFAULT; break; } spin_lock_irqsave(&sc->lmc_lock, flags); sc->lmc_media->set_circuit_type(sc, ctl.circuit_type); sc->ictl.circuit_type = ctl.circuit_type; spin_unlock_irqrestore(&sc->lmc_lock, flags); ret = 0; break; case LMCIOCRESET: if (!capable(CAP_NET_ADMIN)){ ret = -EPERM; break; } spin_lock_irqsave(&sc->lmc_lock, flags); printk (" REG16 before reset +%04x\n", lmc_mii_readreg (sc, 0, 16)); lmc_running_reset (dev); printk (" REG16 after reset +%04x\n", lmc_mii_readreg (sc, 0, 16)); LMC_EVENT_LOG(LMC_EVENT_FORCEDRESET, LMC_CSR_READ (sc, csr_status), lmc_mii_readreg (sc, 0, 16)); spin_unlock_irqrestore(&sc->lmc_lock, flags); ret = 0; break; #ifdef DEBUG case LMCIOCDUMPEVENTLOG: if (copy_to_user(ifr->ifr_data, &lmcEventLogIndex, sizeof(u32))) { ret = -EFAULT; break; } if (copy_to_user(ifr->ifr_data + sizeof(u32), lmcEventLogBuf, sizeof(lmcEventLogBuf))) ret = -EFAULT; else ret = 0; break; #endif case LMCIOCT1CONTROL: if (sc->lmc_cardtype != LMC_CARDTYPE_T1){ ret = -EOPNOTSUPP; break; } break; case LMCIOCXILINX: { struct lmc_xilinx_control xc; if (!capable(CAP_NET_ADMIN)){ ret = -EPERM; break; } netif_stop_queue(dev); if (copy_from_user(&xc, ifr->ifr_data, sizeof(struct lmc_xilinx_control))) { ret = -EFAULT; break; } switch(xc.command){ case lmc_xilinx_reset: { u16 mii; spin_lock_irqsave(&sc->lmc_lock, flags); mii = lmc_mii_readreg (sc, 0, 16); lmc_gpio_mkinput(sc, 0xff); lmc_gpio_mkoutput(sc, LMC_GEP_RESET); sc->lmc_gpio &= ~LMC_GEP_RESET; LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); udelay(50); sc->lmc_gpio |= LMC_GEP_RESET; LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); lmc_gpio_mkinput(sc, 0xff); sc->lmc_media->set_link_status (sc, 1); sc->lmc_media->set_status (sc, NULL); { int i; for(i = 0; i < 5; i++){ lmc_led_on(sc, LMC_DS3_LED0); mdelay(100); lmc_led_off(sc, LMC_DS3_LED0); lmc_led_on(sc, LMC_DS3_LED1); mdelay(100); lmc_led_off(sc, LMC_DS3_LED1); lmc_led_on(sc, LMC_DS3_LED3); mdelay(100); lmc_led_off(sc, LMC_DS3_LED3); lmc_led_on(sc, LMC_DS3_LED2); mdelay(100); lmc_led_off(sc, LMC_DS3_LED2); } } spin_unlock_irqrestore(&sc->lmc_lock, flags); ret = 0x0; } break; case lmc_xilinx_load_prom: { u16 mii; int timeout = 500000; spin_lock_irqsave(&sc->lmc_lock, flags); mii = lmc_mii_readreg (sc, 0, 16); lmc_gpio_mkinput(sc, 0xff); lmc_gpio_mkoutput(sc, LMC_GEP_DP | LMC_GEP_RESET); sc->lmc_gpio &= ~(LMC_GEP_RESET | LMC_GEP_DP); LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); udelay(50); sc->lmc_gpio |= LMC_GEP_DP | LMC_GEP_RESET; LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); while( (LMC_CSR_READ(sc, csr_gp) & LMC_GEP_INIT) == 0 && (timeout-- > 0)) cpu_relax(); lmc_gpio_mkinput(sc, 0xff); spin_unlock_irqrestore(&sc->lmc_lock, flags); ret = 0x0; break; } case lmc_xilinx_load: { char *data; int pos; int timeout = 500000; if (!xc.data) { ret = -EINVAL; break; } data = kmalloc(xc.len, GFP_KERNEL); if (!data) { ret = -ENOMEM; break; } if(copy_from_user(data, xc.data, xc.len)) { kfree(data); ret = -ENOMEM; break; } printk("%s: Starting load of data Len: %d at 0x%p == 0x%p\n", dev->name, xc.len, xc.data, data); spin_lock_irqsave(&sc->lmc_lock, flags); lmc_gpio_mkinput(sc, 0xff); sc->lmc_gpio = 0x00; sc->lmc_gpio &= ~LMC_GEP_DP; sc->lmc_gpio &= ~LMC_GEP_RESET; sc->lmc_gpio |= LMC_GEP_MODE; LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); lmc_gpio_mkoutput(sc, LMC_GEP_MODE | LMC_GEP_DP | LMC_GEP_RESET); udelay(50); lmc_gpio_mkinput(sc, LMC_GEP_DP | LMC_GEP_RESET); sc->lmc_gpio = 0x00; sc->lmc_gpio |= LMC_GEP_MODE; sc->lmc_gpio |= LMC_GEP_DATA; sc->lmc_gpio |= LMC_GEP_CLK; LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); lmc_gpio_mkoutput(sc, LMC_GEP_DATA | LMC_GEP_CLK | LMC_GEP_MODE ); while( (LMC_CSR_READ(sc, csr_gp) & LMC_GEP_INIT) == 0 && (timeout-- > 0)) cpu_relax(); printk(KERN_DEBUG "%s: Waited %d for the Xilinx to clear it's memory\n", dev->name, 500000-timeout); for(pos = 0; pos < xc.len; pos++){ switch(data[pos]){ case 0: sc->lmc_gpio &= ~LMC_GEP_DATA; break; case 1: sc->lmc_gpio |= LMC_GEP_DATA; break; default: printk(KERN_WARNING "%s Bad data in xilinx programming data at %d, got %d wanted 0 or 1\n", dev->name, pos, data[pos]); sc->lmc_gpio |= LMC_GEP_DATA; } sc->lmc_gpio &= ~LMC_GEP_CLK; sc->lmc_gpio |= LMC_GEP_MODE; LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); udelay(1); sc->lmc_gpio |= LMC_GEP_CLK; sc->lmc_gpio |= LMC_GEP_MODE; LMC_CSR_WRITE(sc, csr_gp, sc->lmc_gpio); udelay(1); } if((LMC_CSR_READ(sc, csr_gp) & LMC_GEP_INIT) == 0){ printk(KERN_WARNING "%s: Reprogramming FAILED. Needs to be reprogrammed. (corrupted data)\n", dev->name); } else if((LMC_CSR_READ(sc, csr_gp) & LMC_GEP_DP) == 0){ printk(KERN_WARNING "%s: Reprogramming FAILED. Needs to be reprogrammed. (done)\n", dev->name); } else { printk(KERN_DEBUG "%s: Done reprogramming Xilinx, %d bits, good luck!\n", dev->name, pos); } lmc_gpio_mkinput(sc, 0xff); 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); spin_unlock_irqrestore(&sc->lmc_lock, flags); kfree(data); ret = 0; break; } default: ret = -EBADE; break; } netif_wake_queue(dev); sc->lmc_txfull = 0; } break; default: ret = lmc_proto_ioctl (sc, ifr, cmd); break; }
static void lmc_pci_attach(struct device * const parent, struct device * const self, void * const aux) { u_int32_t revinfo, cfdainfo, id, ssid; pci_intr_handle_t intrhandle; const char *intrstr; unsigned csroffset = LMC_PCI_CSROFFSET; unsigned csrsize = LMC_PCI_CSRSIZE; lmc_csrptr_t csr_base; lmc_spl_t s; lmc_intrfunc_t (*intr_rtn)(void *) = lmc_intr_normal; lmc_softc_t * const sc = (lmc_softc_t *) self; struct pci_attach_args * const pa = (struct pci_attach_args *) aux; extern lmc_media_t lmc_hssi_media; extern lmc_media_t lmc_ds3_media; extern lmc_media_t lmc_t1_media; extern lmc_media_t lmc_ssi_media; revinfo = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CFRV) & 0xFF; id = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CFID); cfdainfo = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CFDA); ssid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SSID); switch (PCI_CHIPID(ssid)) { case PCI_PRODUCT_LMC_HSSI: printf(": HSSI\n"); sc->lmc_media = &lmc_hssi_media; break; case PCI_PRODUCT_LMC_HSSIC: printf(": HSSIc\n"); sc->lmc_media = &lmc_hssi_media; break; case PCI_PRODUCT_LMC_DS3: printf(": DS3\n"); sc->lmc_media = &lmc_ds3_media; break; case PCI_PRODUCT_LMC_SSI: printf(": SSI\n"); sc->lmc_media = &lmc_ssi_media; break; case PCI_PRODUCT_LMC_DS1: printf(": T1\n"); sc->lmc_media = &lmc_t1_media; break; } sc->lmc_pci_busno = parent; sc->lmc_pci_devno = pa->pa_device; sc->lmc_chipid = LMC_21140A; sc->lmc_features |= LMC_HAVE_STOREFWD; if (sc->lmc_chipid == LMC_21140A && revinfo <= 0x22) sc->lmc_features |= LMC_HAVE_RXBADOVRFLW; if (cfdainfo & (TULIP_CFDA_SLEEP | TULIP_CFDA_SNOOZE)) { cfdainfo &= ~(TULIP_CFDA_SLEEP | TULIP_CFDA_SNOOZE); pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_CFDA, cfdainfo); DELAY(11 * 1000); } bcopy(self->dv_xname, sc->lmc_if.if_xname, IFNAMSIZ); sc->lmc_if.if_softc = sc; sc->lmc_pc = pa->pa_pc; sc->lmc_revinfo = revinfo; sc->lmc_if.if_softc = sc; csr_base = 0; { bus_space_tag_t iot, memt; bus_space_handle_t ioh, memh; int ioh_valid, memh_valid; ioh_valid = (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0, &iot, &ioh, NULL, NULL, 0) == 0); memh_valid = (pci_mapreg_map(pa, PCI_CBMA, PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &memt, &memh, NULL, NULL, 0) == 0); if (memh_valid) { sc->lmc_bustag = memt; sc->lmc_bushandle = memh; } else if (ioh_valid) { sc->lmc_bustag = iot; sc->lmc_bushandle = ioh; } else { printf("%s: unable to map device registers\n", sc->lmc_dev.dv_xname); return; } } sc->lmc_dmatag = pa->pa_dmat; if ((lmc_busdma_init(sc)) != 0) { printf("error initing bus_dma\n"); return; } lmc_initcsrs(sc, csr_base + csroffset, csrsize); lmc_initring(sc, &sc->lmc_rxinfo, sc->lmc_rxdescs, LMC_RXDESCS); lmc_initring(sc, &sc->lmc_txinfo, sc->lmc_txdescs, LMC_TXDESCS); 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_DOWN); /* down */ /* * Make sure there won't be any interrupts or such... */ LMC_CSR_WRITE(sc, csr_busmode, TULIP_BUSMODE_SWRESET); /* * Wait 10 microseconds (actually 50 PCI cycles but at * 33MHz that comes to two microseconds but wait a * bit longer anyways) */ DELAY(100); lmc_read_macaddr(sc); if (pci_intr_map(pa, &intrhandle)) { printf("%s: couldn't map interrupt\n", sc->lmc_dev.dv_xname); return; } intrstr = pci_intr_string(pa->pa_pc, intrhandle); sc->lmc_ih = pci_intr_establish(pa->pa_pc, intrhandle, IPL_NET, intr_rtn, sc, self->dv_xname); if (sc->lmc_ih == NULL) { printf("%s: couldn't establish interrupt", sc->lmc_dev.dv_xname); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); return; } printf("%s: pass %d.%d, serial " LMC_EADDR_FMT ", %s\n", sc->lmc_dev.dv_xname, (sc->lmc_revinfo & 0xF0) >> 4, sc->lmc_revinfo & 0x0F, LMC_EADDR_ARGS(sc->lmc_enaddr), intrstr); sc->lmc_ats = shutdownhook_establish(lmc_shutdown, sc); if (sc->lmc_ats == NULL) printf("%s: warning: couldn't establish shutdown hook\n", sc->lmc_xname); s = LMC_RAISESPL(); lmc_dec_reset(sc); lmc_reset(sc); lmc_attach(sc); LMC_RESTORESPL(s); }