예제 #1
0
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);
}
예제 #2
0
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));
}
예제 #3
0
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);
}
예제 #4
0
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);
}
예제 #5
0
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;
    }