// attach void lmc_proto_attach(lmc_softc_t *sc) /*FOLD00*/ { lmc_trace(sc->lmc_device, "lmc_proto_attach in"); switch(sc->if_type){ case LMC_PPP: { struct net_device *dev = sc->lmc_device; SPPP_attach(sc); dev->do_ioctl = lmc_ioctl; } break; case LMC_NET: { struct net_device *dev = sc->lmc_device; /* * They set a few basics because they don't use sync_ppp */ dev->flags |= IFF_POINTOPOINT; dev->hard_header = 0; dev->hard_header_len = 0; dev->addr_len = 0; } case LMC_RAW: /* Setup the task queue, maybe we should notify someone? */ { } default: break; } lmc_trace(sc->lmc_device, "lmc_proto_attach out"); }
void lmc_proto_close(lmc_softc_t *sc) { lmc_trace(sc->lmc_device, "lmc_proto_close in"); if (sc->if_type == LMC_PPP) hdlc_close(sc->lmc_device); lmc_trace(sc->lmc_device, "lmc_proto_close out"); }
// ioctl int lmc_proto_ioctl(lmc_softc_t *sc, struct ifreq *ifr, int cmd) /*FOLD00*/ { lmc_trace(sc->lmc_device, "lmc_proto_ioctl out"); switch(sc->if_type){ case LMC_PPP: return SPPP_do_ioctl (sc, ifr, cmd); break; default: return -EOPNOTSUPP; break; } lmc_trace(sc->lmc_device, "lmc_proto_ioctl out"); }
void lmc_proto_netif(lmc_softc_t *sc, struct sk_buff *skb) /*FOLD00*/ { lmc_trace(sc->lmc_device, "lmc_proto_netif in"); switch(sc->if_type){ case LMC_PPP: case LMC_NET: default: netif_rx(skb); break; case LMC_RAW: break; } lmc_trace(sc->lmc_device, "lmc_proto_netif out"); }
void lmc_proto_close(lmc_softc_t *sc) /*FOLD00*/ { lmc_trace(sc->lmc_device, "lmc_proto_close in"); switch(sc->if_type){ case LMC_PPP: SPPP_close(sc); break; case LMC_RAW: /* Interface going down */ break; default: break; } lmc_trace(sc->lmc_device, "lmc_proto_close out"); }
// reopen void lmc_proto_reopen(lmc_softc_t *sc) /*FOLD00*/ { lmc_trace(sc->lmc_device, "lmc_proto_reopen in"); switch(sc->if_type){ case LMC_PPP: SPPP_reopen(sc); break; case LMC_RAW: /* Reset the interface after being down, prerape to receive packets again */ break; default: break; } lmc_trace(sc->lmc_device, "lmc_proto_reopen out"); }
// attach void lmc_proto_attach(lmc_softc_t *sc) /*FOLD00*/ { lmc_trace(sc->lmc_device, "lmc_proto_attach in"); if (sc->if_type == LMC_NET) { struct net_device *dev = sc->lmc_device; /* * They set a few basics because they don't use HDLC */ dev->flags |= IFF_POINTOPOINT; dev->hard_header_len = 0; dev->addr_len = 0; } lmc_trace(sc->lmc_device, "lmc_proto_attach out"); }
int lmc_proto_open(lmc_softc_t *sc) { int ret = 0; lmc_trace(sc->lmc_device, "lmc_proto_open in"); if (sc->if_type == LMC_PPP) { ret = hdlc_open(sc->lmc_device); if (ret < 0) printk(KERN_WARNING "%s: HDLC open failed: %d\n", sc->name, ret); } lmc_trace(sc->lmc_device, "lmc_proto_open out"); return ret; }
int lmc_proto_ioctl(lmc_softc_t *sc, struct ifreq *ifr, int cmd) { lmc_trace(sc->lmc_device, "lmc_proto_ioctl"); if (sc->if_type == LMC_PPP) return hdlc_ioctl(sc->lmc_device, ifr, cmd); return -EOPNOTSUPP; }
// open void lmc_proto_open(lmc_softc_t *sc) /*FOLD00*/ { int ret; lmc_trace(sc->lmc_device, "lmc_proto_open in"); switch(sc->if_type){ case LMC_PPP: ret = SPPP_open(sc); if(ret < 0) printk("%s: syncPPP open failed: %d\n", sc->name, ret); break; case LMC_RAW: /* We're about to start getting packets! */ break; default: break; } lmc_trace(sc->lmc_device, "lmc_proto_open out"); }
// init void lmc_proto_init(lmc_softc_t *sc) /*FOLD00*/ { lmc_trace(sc->lmc_device, "lmc_proto_init in"); switch(sc->if_type){ case LMC_PPP: sc->pd = kmalloc(sizeof(struct ppp_device), GFP_KERNEL); if (!sc->pd) { printk("lmc_proto_init(): kmalloc failure!\n"); return; } sc->pd->dev = sc->lmc_device; sc->if_ptr = sc->pd; break; case LMC_RAW: break; default: break; } lmc_trace(sc->lmc_device, "lmc_proto_init out"); }
unsigned short lmc_proto_type(lmc_softc_t *sc, struct sk_buff *skb) /*FOLD00*/ { lmc_trace(sc->lmc_device, "lmc_proto_type in"); switch(sc->if_type){ case LMC_PPP: return htons(ETH_P_WAN_PPP); break; case LMC_NET: return htons(ETH_P_802_2); break; case LMC_RAW: /* Packet type for skbuff kind of useless */ return htons(ETH_P_802_2); break; default: printk(KERN_WARNING "%s: No protocol set for this interface, assuming 802.2 (which is wrong!!)\n", sc->name); return htons(ETH_P_802_2); break; } lmc_trace(sc->lmc_device, "lmc_proto_tye out"); }
__be16 lmc_proto_type(lmc_softc_t *sc, struct sk_buff *skb) /*FOLD00*/ { lmc_trace(sc->lmc_device, "lmc_proto_type in"); switch(sc->if_type){ case LMC_PPP: return hdlc_type_trans(skb, sc->lmc_device); break; case LMC_NET: return htons(ETH_P_802_2); break; case LMC_RAW: /* Packet type for skbuff kind of useless */ return htons(ETH_P_802_2); break; default: ; return htons(ETH_P_802_2); break; } lmc_trace(sc->lmc_device, "lmc_proto_tye out"); }
// init void lmc_proto_init(lmc_softc_t *sc) /*FOLD00*/ { lmc_trace(sc->lmc_device, "lmc_proto_init in"); switch(sc->if_type){ case LMC_PPP: if(lmc_first_ppp_load == 0) #ifndef MODULE SYNC_PPP_init(); #endif #if LINUX_VERSION_CODE >= 0x20363 sc->pd = kmalloc(sizeof(struct ppp_device), GFP_KERNEL); sc->pd->dev = sc->lmc_device; #endif sc->if_ptr = sc->pd; break; case LMC_RAW: break; default: break; } lmc_trace(sc->lmc_device, "lmc_proto_init out"); }
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; }