static void lmc_hssi_init(lmc_softc_t * const sc) { sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC5200; lmc_gpio_mkoutput(sc, LMC_GEP_HSSI_CLOCK); }
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)); }
static void lmc_ssi_default(lmc_softc_t * const sc) { sc->lmc_miireg16 = LMC_MII16_LED_ALL; /* * make TXCLOCK always be an output */ lmc_gpio_mkoutput(sc, LMC_GEP_SSI_TXCLOCK); sc->lmc_media->set_link_status(sc, LMC_LINK_DOWN); sc->lmc_media->set_clock_source(sc, LMC_CTL_CLOCK_SOURCE_EXT); sc->lmc_media->set_speed(sc, NULL); sc->lmc_media->set_crc_length(sc, LMC_CTL_CRC_LENGTH_16); }
static void lmc_ssi_init(lmc_softc_t * const sc) { u_int16_t mii17; int cable; sc->ictl.cardtype = LMC_CTL_CARDTYPE_LMC1000; mii17 = lmc_mii_readreg(sc, 0, 17); cable = (mii17 & LMC_MII17_SSI_CABLE_MASK) >> LMC_MII17_SSI_CABLE_SHIFT; sc->ictl.cable_type = cable; lmc_gpio_mkoutput(sc, LMC_GEP_SSI_TXCLOCK); }
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; }