📄 tlan.c
字号:
* * Returns: * 0 on success, error code on error * Parms: * none * * The name is lower case to fit in with all the rest of * the netcard_probe names. This function looks for * another TLan based adapter, setting it up with the * allocated device struct if one is found. * tlan_probe has been ported to the new net API and * now allocates its own device structure. This function * is also used by modules. * **************************************************************/static int __devinit TLan_probe1(struct pci_dev *pdev, long ioaddr, int irq, int rev, const struct pci_device_id *ent ){ struct net_device *dev; TLanPrivateInfo *priv; u8 pci_rev; u16 device_id; dev = init_etherdev(NULL, sizeof(TLanPrivateInfo)); if (dev == NULL) { printk(KERN_ERR "TLAN: Could not allocate memory for device.\n"); return -ENOMEM; } SET_MODULE_OWNER(dev); priv = dev->priv; dev->base_addr = ioaddr; dev->irq = irq; /* Is this a PCI device? */ if (pdev) { priv->adapter = &board_info[ent->driver_data]; if (pci_enable_device(pdev)) { unregister_netdev(dev); kfree(dev); return -1; } pci_read_config_byte ( pdev, PCI_REVISION_ID, &pci_rev); priv->adapterRev = pci_rev; pci_set_master(pdev); pdev->driver_data = dev; } else { /* EISA card */ /* This is a hack. We need to know which board structure * is suited for this adapter */ device_id = inw(ioaddr + EISA_ID2); priv->is_eisa = 1; if (device_id == 0x20F1) { priv->adapter = &board_info[13]; /* NetFlex-3/E */ priv->adapterRev = 23; /* TLAN 2.3 */ } else { priv->adapter = &board_info[14]; priv->adapterRev = 10; /* TLAN 1.0 */ } } /* Kernel parameters */ if (dev->mem_start) { priv->aui = dev->mem_start & 0x01; priv->duplex = ((dev->mem_start & 0x06) == 0x06) ? 0 : (dev->mem_start & 0x06) >> 1; priv->speed = ((dev->mem_start & 0x18) == 0x18) ? 0 : (dev->mem_start & 0x18) >> 3; if (priv->speed == 0x1) { priv->speed = TLAN_SPEED_10; } else if (priv->speed == 0x2) { priv->speed = TLAN_SPEED_100; } debug = priv->debug = dev->mem_end; } else { if ( ( duplex != 1 ) && ( duplex != 2 ) ) duplex = 0; priv->duplex = duplex; if ( ( speed != 10 ) && ( speed != 100 ) ) speed = 0; priv->aui = aui; priv->speed = speed; priv->debug = debug; } spin_lock_init(&priv->lock); if (TLan_Init(dev)) { printk(KERN_ERR "TLAN: Could not register device.\n"); unregister_netdev(dev); kfree(dev); return -EAGAIN; } else { TLanDevicesInstalled++; /* pdev is NULL if this is an EISA device */ if (pdev) tlan_have_pci++; else { priv->nextDevice = TLan_Eisa_Devices; TLan_Eisa_Devices = dev; tlan_have_eisa++; } printk(KERN_INFO "TLAN: %s irq=%2d, io=%04x, %s, Rev. %d\n", dev->name, (int) dev->irq, (int) dev->base_addr, priv->adapter->deviceLabel, priv->adapterRev); return 0; }}static void TLan_Eisa_Cleanup(void){ struct net_device *dev; TLanPrivateInfo *priv; while( tlan_have_eisa ) { dev = TLan_Eisa_Devices; priv = (TLanPrivateInfo *) dev->priv; if (priv->dmaStorage) { kfree(priv->dmaStorage); } release_region( dev->base_addr, 0x10); unregister_netdev( dev ); TLan_Eisa_Devices = priv->nextDevice; kfree( dev ); tlan_have_eisa--; }} static void __exit tlan_exit(void){ if (tlan_have_pci) pci_unregister_driver(&tlan_driver); if (tlan_have_eisa) TLan_Eisa_Cleanup(); kfree( TLanPadBuffer );}/* Module loading/unloading */module_init(tlan_probe);module_exit(tlan_exit); /************************************************************** * TLan_EisaProbe * * Returns: 0 on success, 1 otherwise * * Parms: None * * * This functions probes for EISA devices and calls * TLan_probe1 when one is found. * *************************************************************/static void __init TLan_EisaProbe (void) { long ioaddr; int rc = -ENODEV; int irq; u16 device_id; if (!EISA_bus) { TLAN_DBG(TLAN_DEBUG_PROBE, "No EISA bus present\n"); return; } /* Loop through all slots of the EISA bus */ for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) { TLAN_DBG(TLAN_DEBUG_PROBE,"EISA_ID 0x%4x: 0x%4x\n", (int) ioaddr + 0xC80, inw(ioaddr + EISA_ID)); TLAN_DBG(TLAN_DEBUG_PROBE,"EISA_ID 0x%4x: 0x%4x\n", (int) ioaddr + 0xC82, inw(ioaddr + EISA_ID2)); TLAN_DBG(TLAN_DEBUG_PROBE, "Probing for EISA adapter at IO: 0x%4x : ", (int) ioaddr); if (request_region(ioaddr, 0x10, TLanSignature) == NULL) goto out; if (inw(ioaddr + EISA_ID) != 0x110E) { release_region(ioaddr, 0x10); goto out; } device_id = inw(ioaddr + EISA_ID2); if (device_id != 0x20F1 && device_id != 0x40F1) { release_region (ioaddr, 0x10); goto out; } if (inb(ioaddr + EISA_CR) != 0x1) { /* Check if adapter is enabled */ release_region (ioaddr, 0x10); goto out2; } if (debug == 0x10) printk("Found one\n"); /* Get irq from board */ switch (inb(ioaddr + 0xCC0)) { case(0x10): irq=5; break; case(0x20): irq=9; break; case(0x40): irq=10; break; case(0x80): irq=11; break; default: goto out; } /* Setup the newly found eisa adapter */ rc = TLan_probe1( NULL, ioaddr, irq, 12, NULL); continue; out: if (debug == 0x10) printk("None found\n"); continue; out2: if (debug == 0x10) printk("Card found but it is not enabled, skipping\n"); continue; }} /* TLan_EisaProbe */ /*************************************************************** * TLan_Init * * Returns: * 0 on success, error code otherwise. * Parms: * dev The structure of the device to be * init'ed. * * This function completes the initialization of the * device structure and driver. It reserves the IO * addresses, allocates memory for the lists and bounce * buffers, retrieves the MAC address from the eeprom * and assignes the device's methods. * **************************************************************/static int TLan_Init( struct net_device *dev ){ int dma_size; int err; int i; TLanPrivateInfo *priv; priv = (TLanPrivateInfo *) dev->priv; if (!priv->is_eisa) /* EISA devices have already requested IO */ if (!request_region( dev->base_addr, 0x10, TLanSignature )) { printk(KERN_ERR "TLAN: %s: IO port region 0x%lx size 0x%x in use.\n", dev->name, dev->base_addr, 0x10 ); return -EIO; } if ( bbuf ) { dma_size = ( TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS ) * ( sizeof(TLanList) + TLAN_MAX_FRAME_SIZE ); } else { dma_size = ( TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS ) * ( sizeof(TLanList) ); } priv->dmaStorage = kmalloc(dma_size, GFP_KERNEL | GFP_DMA); if ( priv->dmaStorage == NULL ) { printk(KERN_ERR "TLAN: Could not allocate lists and buffers for %s.\n", dev->name ); return -ENOMEM; } memset( priv->dmaStorage, 0, dma_size ); priv->rxList = (TLanList *) ( ( ( (u32) priv->dmaStorage ) + 7 ) & 0xFFFFFFF8 ); priv->txList = priv->rxList + TLAN_NUM_RX_LISTS; if ( bbuf ) { priv->rxBuffer = (u8 *) ( priv->txList + TLAN_NUM_TX_LISTS ); priv->txBuffer = priv->rxBuffer + ( TLAN_NUM_RX_LISTS * TLAN_MAX_FRAME_SIZE ); } err = 0; for ( i = 0; i < 6 ; i++ ) err |= TLan_EeReadByte( dev, (u8) priv->adapter->addrOfs + i, (u8 *) &dev->dev_addr[i] ); if ( err ) { printk(KERN_ERR "TLAN: %s: Error reading MAC from eeprom: %d\n", dev->name, err ); } dev->addr_len = 6; /* Device methods */ dev->open = &TLan_Open; dev->hard_start_xmit = &TLan_StartTx; dev->stop = &TLan_Close; dev->get_stats = &TLan_GetStats; dev->set_multicast_list = &TLan_SetMulticastList; dev->do_ioctl = &TLan_ioctl; dev->tx_timeout = &TLan_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; return 0;} /* TLan_Init */ /*************************************************************** * TLan_Open * * Returns: * 0 on success, error code otherwise. * Parms: * dev Structure of device to be opened. * * This routine puts the driver and TLAN adapter in a * state where it is ready to send and receive packets. * It allocates the IRQ, resets and brings the adapter * out of reset, and allows interrupts. It also delays * the startup for autonegotiation or sends a Rx GO * command to the adapter, as appropriate. * **************************************************************/static int TLan_Open( struct net_device *dev ){ TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; int err; priv->tlanRev = TLan_DioRead8( dev->base_addr, TLAN_DEF_REVISION ); err = request_irq( dev->irq, TLan_HandleInterrupt, SA_SHIRQ, TLanSignature, dev ); if ( err ) { printk(KERN_ERR "TLAN: Cannot open %s because IRQ %d is already in use.\n", dev->name, dev->irq ); return err; } init_timer(&priv->timer); netif_start_queue(dev); /* NOTE: It might not be necessary to read the stats before a reset if you don't care what the values are. */ TLan_ResetLists( dev ); TLan_ReadAndClearStats( dev, TLAN_IGNORE ); TLan_ResetAdapter( dev ); TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Opened. TLAN Chip Rev: %x\n", dev->name, priv->tlanRev ); return 0;} /* TLan_Open */ /************************************************************** * TLan_ioctl * * Returns: * 0 on success, error code otherwise * Params: * dev structure of device to receive ioctl. * * rq ifreq structure to hold userspace data. * * cmd ioctl command. * * *************************************************************/static int TLan_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){ TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; u16 *data = (u16 *)&rq->ifr_data; u32 phy = priv->phy[priv->phyNum]; if (!priv->phyOnline) return -EAGAIN; switch(cmd) { case SIOCDEVPRIVATE: data[0] = phy; case SIOCDEVPRIVATE+1: /* Read MII register */ TLan_MiiReadReg(dev, data[0], data[1], &data[3]); return 0; case SIOCDEVPRIVATE+2: /* Write MII register */ if (!capable(CAP_NET_ADMIN)) return -EPERM; TLan_MiiWriteReg(dev, data[0], data[1], data[2]); return 0; default: return -EOPNOTSUPP; }} /* tlan_ioctl */ /*************************************************************** * TLan_tx_timeout * * Returns: nothing * * Params:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -