📄 tlan.c
字号:
memset(TLanPadBuffer, 0, TLAN_MIN_FRAME_SIZE); pad_allocated = 1; TLAN_DBG(TLAN_DEBUG_PROBE, "Starting PCI Probe....\n"); /* Use new style PCI probing. Now the kernel will do most of this for us */ pci_register_driver(&tlan_driver); TLAN_DBG(TLAN_DEBUG_PROBE, "Starting EISA Probe....\n"); TLan_EisaProbe(); printk(KERN_INFO "TLAN: %d device%s installed, PCI: %d EISA: %d\n", TLanDevicesInstalled, TLanDevicesInstalled == 1 ? "" : "s", tlan_have_pci, tlan_have_eisa); if (TLanDevicesInstalled == 0) { pci_unregister_driver(&tlan_driver); kfree(TLanPadBuffer); return -ENODEV; } return 0;} static int __devinit tlan_init_one( struct pci_dev *pdev, const struct pci_device_id *ent){ return TLan_probe1( pdev, -1, -1, 0, ent);}/* *************************************************************** * tlan_probe1 * * 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; int reg; if (pdev && pci_enable_device(pdev)) return -EIO; 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; /* Is this a PCI device? */ if (pdev) { u32 pci_io_base = 0; priv->adapter = &board_info[ent->driver_data]; pci_read_config_byte ( pdev, PCI_REVISION_ID, &pci_rev); for ( reg= 0; reg <= 5; reg ++ ) { if (pci_resource_flags(pdev, reg) & IORESOURCE_IO) { pci_io_base = pci_resource_start(pdev, reg); TLAN_DBG( TLAN_DEBUG_GNRL, "IO mapping is available at %x.\n", pci_io_base); break; } } if (!pci_io_base) { printk(KERN_ERR "TLAN: No IO mappings available\n"); unregister_netdev(dev); kfree(dev); return -ENODEV; } dev->base_addr = pci_io_base; dev->irq = pdev->irq; priv->adapterRev = pci_rev; pci_set_master(pdev); pci_set_drvdata(pdev, 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 */ } dev->base_addr = ioaddr; dev->irq = irq; } /* 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 { priv->aui = aui[boards_found]; priv->speed = speed[boards_found]; priv->duplex = duplex[boards_found]; priv->debug = debug; } /* This will be used when we get an adapter error from * within our irq handler */ INIT_LIST_HEAD(&priv->tlan_tqueue.list); priv->tlan_tqueue.sync = 0; priv->tlan_tqueue.routine = (void *)(void*)TLan_tx_timeout; priv->tlan_tqueue.data = dev; 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++; boards_found++; /* 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 = 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){ 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 = 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 ); release_region( dev->base_addr, 0x10 ); 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 = 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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -