tlan.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,212 行 · 第 1/5 页
C
2,212 行
if ( priv->dmaStorage ) { pci_free_consistent(priv->pciDev, priv->dmaSize, priv->dmaStorage, priv->dmaStorageDMA ); }#ifdef CONFIG_PCI pci_release_regions(pdev);#endif free_netdev( dev ); pci_set_drvdata( pdev, NULL );} static struct pci_driver tlan_driver = { .name = "tlan", .id_table = tlan_pci_tbl, .probe = tlan_init_one, .remove = __devexit_p(tlan_remove_one), };static int __init tlan_probe(void){ static int pad_allocated; printk(KERN_INFO "%s", tlan_banner); TLanPadBuffer = (u8 *) pci_alloc_consistent(NULL, TLAN_MIN_FRAME_SIZE, &TLanPadBufferDMA); if (TLanPadBuffer == NULL) { printk(KERN_ERR "TLAN: Could not allocate memory for pad buffer.\n"); return -ENOMEM; } 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); pci_free_consistent(NULL, TLAN_MIN_FRAME_SIZE, TLanPadBuffer, TLanPadBufferDMA); 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, rc = -ENODEV; if (pdev) { rc = pci_enable_device(pdev); if (rc) return rc; rc = pci_request_regions(pdev, TLanSignature); if (rc) { printk(KERN_ERR "TLAN: Could not reserve IO regions\n"); goto err_out; } } dev = alloc_etherdev(sizeof(TLanPrivateInfo)); if (dev == NULL) { printk(KERN_ERR "TLAN: Could not allocate memory for device.\n"); rc = -ENOMEM; goto err_out_regions; } SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); priv = dev->priv; priv->pciDev = pdev; /* Is this a PCI device? */ if (pdev) { u32 pci_io_base = 0; priv->adapter = &board_info[ent->driver_data]; rc = pci_set_dma_mask(pdev, 0xFFFFFFFF); if (rc) { printk(KERN_ERR "TLAN: No suitable PCI mapping available.\n"); goto err_out_free_dev; } 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"); rc = -EIO; goto err_out_free_dev; } 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_WORK(&priv->tlan_tqueue, (void *)(void*)TLan_tx_timeout, dev); spin_lock_init(&priv->lock); rc = TLan_Init(dev); if (rc) { printk(KERN_ERR "TLAN: Could not set up device.\n"); goto err_out_free_dev; } rc = register_netdev(dev); if (rc) { printk(KERN_ERR "TLAN: Could not register device.\n"); goto err_out_uninit; } 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;err_out_uninit: pci_free_consistent(priv->pciDev, priv->dmaSize, priv->dmaStorage, priv->dmaStorageDMA );err_out_free_dev: free_netdev(dev);err_out_regions:#ifdef CONFIG_PCI if (pdev) pci_release_regions(pdev);#endiferr_out: if (pdev) pci_disable_device(pdev); return rc;}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) { pci_free_consistent(priv->pciDev, priv->dmaSize, priv->dmaStorage, priv->dmaStorageDMA ); } release_region( dev->base_addr, 0x10); unregister_netdev( dev ); TLan_Eisa_Devices = priv->nextDevice; free_netdev( dev ); tlan_have_eisa--; }} static void __exit tlan_exit(void){ pci_unregister_driver(&tlan_driver); if (tlan_have_eisa) TLan_Eisa_Cleanup(); pci_free_consistent(NULL, TLAN_MIN_FRAME_SIZE, TLanPadBuffer, TLanPadBufferDMA);}/* 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 */#ifdef CONFIG_NET_POLL_CONTROLLERstatic void TLan_Poll(struct net_device *dev){ disable_irq(dev->irq); TLan_HandleInterrupt(dev->irq, dev, NULL); enable_irq(dev->irq);}#endif /*************************************************************** * 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 ( 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 = pci_alloc_consistent(priv->pciDev, dma_size, &priv->dmaStorageDMA); priv->dmaSize = dma_size; 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->rxListDMA = ( ( ( (u32) priv->dmaStorageDMA ) + 7 ) & 0xFFFFFFF8 ); priv->txList = priv->rxList + TLAN_NUM_RX_LISTS; priv->txListDMA = priv->rxListDMA + sizeof(TLanList) * TLAN_NUM_RX_LISTS; if ( bbuf ) { priv->rxBuffer = (u8 *) ( priv->txList + TLAN_NUM_TX_LISTS ); priv->rxBufferDMA =priv->txListDMA + sizeof(TLanList) * TLAN_NUM_TX_LISTS; priv->txBuffer = priv->rxBuffer + ( TLAN_NUM_RX_LISTS * TLAN_MAX_FRAME_SIZE ); priv->txBufferDMA = priv->rxBufferDMA + ( TLAN_NUM_RX_LISTS * TLAN_MAX_FRAME_SIZE ); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?