📄 tlan.c
字号:
typedef u32 (TLanIntVectorFunc)( struct net_device *, u16 );/* For removing EISA devices */static struct net_device *TLan_Eisa_Devices;static int TLanDevicesInstalled;/* Set speed, duplex and aui settings */static int aui[MAX_TLAN_BOARDS];static int duplex[MAX_TLAN_BOARDS];static int speed[MAX_TLAN_BOARDS];static int boards_found;MODULE_AUTHOR("Maintainer: Torben Mathiasen <torben.mathiasen@compaq.com>");MODULE_DESCRIPTION("Driver for TI ThunderLAN based ethernet PCI adapters");MODULE_LICENSE("GPL");MODULE_PARM(aui, "1-" __MODULE_STRING(MAX_TLAN_BOARDS) "i");MODULE_PARM(duplex, "1-" __MODULE_STRING(MAX_TLAN_BOARDS) "i");MODULE_PARM(speed, "1-" __MODULE_STRING(MAX_TLAN_BOARDS) "i");MODULE_PARM(debug, "i");MODULE_PARM(bbuf, "i");MODULE_PARM_DESC(aui, "ThunderLAN use AUI port(s) (0-1)");MODULE_PARM_DESC(duplex, "ThunderLAN duplex setting(s) (0-default, 1-half, 2-full)");MODULE_PARM_DESC(speed, "ThunderLAN port speen setting(s) (0,10,100)");MODULE_PARM_DESC(debug, "ThunderLAN debug mask");MODULE_PARM_DESC(bbuf, "ThunderLAN use big buffer (0-1)");EXPORT_NO_SYMBOLS;/* Define this to enable Link beat monitoring */#undef MONITOR/* Turn on debugging. See linux/Documentation/networking/tlan.txt for details */static int debug;static int bbuf;static u8 *TLanPadBuffer;static char TLanSignature[] = "TLAN";static const char tlan_banner[] = "ThunderLAN driver v1.14a\n";static int tlan_have_pci;static int tlan_have_eisa;const char *media[] = { "10BaseT-HD ", "10BaseT-FD ","100baseTx-HD ", "100baseTx-FD", "100baseT4", 0};int media_map[] = { 0x0020, 0x0040, 0x0080, 0x0100, 0x0200,};static struct board { const char *deviceLabel; u32 flags; u16 addrOfs;} board_info[] __devinitdata = { { "Compaq Netelligent 10 T PCI UTP", TLAN_ADAPTER_ACTIVITY_LED, 0x83 }, { "Compaq Netelligent 10/100 TX PCI UTP", TLAN_ADAPTER_ACTIVITY_LED, 0x83 }, { "Compaq Integrated NetFlex-3/P", TLAN_ADAPTER_NONE, 0x83 }, { "Compaq NetFlex-3/P", TLAN_ADAPTER_UNMANAGED_PHY | TLAN_ADAPTER_BIT_RATE_PHY, 0x83 }, { "Compaq NetFlex-3/P", TLAN_ADAPTER_NONE, 0x83 }, { "Compaq Netelligent Integrated 10/100 TX UTP", TLAN_ADAPTER_ACTIVITY_LED, 0x83 }, { "Compaq Netelligent Dual 10/100 TX PCI UTP", TLAN_ADAPTER_NONE, 0x83 }, { "Compaq Netelligent 10/100 TX Embedded UTP", TLAN_ADAPTER_NONE, 0x83 }, { "Olicom OC-2183/2185", TLAN_ADAPTER_USE_INTERN_10, 0x83 }, { "Olicom OC-2325", TLAN_ADAPTER_UNMANAGED_PHY, 0xF8 }, { "Olicom OC-2326", TLAN_ADAPTER_USE_INTERN_10, 0xF8 }, { "Compaq Netelligent 10/100 TX UTP", TLAN_ADAPTER_ACTIVITY_LED, 0x83 }, { "Compaq Netelligent 10 T/2 PCI UTP/Coax", TLAN_ADAPTER_NONE, 0x83 }, { "Compaq NetFlex-3/E", TLAN_ADAPTER_ACTIVITY_LED | /* EISA card */ TLAN_ADAPTER_UNMANAGED_PHY | TLAN_ADAPTER_BIT_RATE_PHY, 0x83 }, { "Compaq NetFlex-3/E", TLAN_ADAPTER_ACTIVITY_LED, 0x83 }, /* EISA card */};static struct pci_device_id tlan_pci_tbl[] __devinitdata = { { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETFLEX3I, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_THUNDER, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETFLEX3B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100PI, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100I, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7 }, { PCI_VENDOR_ID_OLICOM, PCI_DEVICE_ID_OLICOM_OC2183, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, { PCI_VENDOR_ID_OLICOM, PCI_DEVICE_ID_OLICOM_OC2325, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9 }, { PCI_VENDOR_ID_OLICOM, PCI_DEVICE_ID_OLICOM_OC2326, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10_100_WS_5100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10_T2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 }, { 0,}};MODULE_DEVICE_TABLE(pci, tlan_pci_tbl); static void TLan_EisaProbe( void );static void TLan_Eisa_Cleanup( void );static int TLan_Init( struct net_device * );static int TLan_Open( struct net_device *dev );static int TLan_StartTx( struct sk_buff *, struct net_device *);static void TLan_HandleInterrupt( int, void *, struct pt_regs *);static int TLan_Close( struct net_device *);static struct net_device_stats *TLan_GetStats( struct net_device *);static void TLan_SetMulticastList( struct net_device *);static int TLan_ioctl( struct net_device *dev, struct ifreq *rq, int cmd);static int TLan_probe1( struct pci_dev *pdev, long ioaddr, int irq, int rev, const struct pci_device_id *ent);static void TLan_tx_timeout( struct net_device *dev);static int tlan_init_one( struct pci_dev *pdev, const struct pci_device_id *ent);static u32 TLan_HandleInvalid( struct net_device *, u16 );static u32 TLan_HandleTxEOF( struct net_device *, u16 );static u32 TLan_HandleStatOverflow( struct net_device *, u16 );static u32 TLan_HandleRxEOF( struct net_device *, u16 );static u32 TLan_HandleDummy( struct net_device *, u16 );static u32 TLan_HandleTxEOC( struct net_device *, u16 );static u32 TLan_HandleStatusCheck( struct net_device *, u16 );static u32 TLan_HandleRxEOC( struct net_device *, u16 );static void TLan_Timer( unsigned long );static void TLan_ResetLists( struct net_device * );static void TLan_FreeLists( struct net_device * );static void TLan_PrintDio( u16 );static void TLan_PrintList( TLanList *, char *, int );static void TLan_ReadAndClearStats( struct net_device *, int );static void TLan_ResetAdapter( struct net_device * );static void TLan_FinishReset( struct net_device * );static void TLan_SetMac( struct net_device *, int areg, char *mac );static void TLan_PhyPrint( struct net_device * );static void TLan_PhyDetect( struct net_device * );static void TLan_PhyPowerDown( struct net_device * );static void TLan_PhyPowerUp( struct net_device * );static void TLan_PhyReset( struct net_device * );static void TLan_PhyStartLink( struct net_device * );static void TLan_PhyFinishAutoNeg( struct net_device * );#ifdef MONITORstatic void TLan_PhyMonitor( struct net_device * );#endif/*static int TLan_PhyNop( struct net_device * );static int TLan_PhyInternalCheck( struct net_device * );static int TLan_PhyInternalService( struct net_device * );static int TLan_PhyDp83840aCheck( struct net_device * );*/static int TLan_MiiReadReg( struct net_device *, u16, u16, u16 * );static void TLan_MiiSendData( u16, u32, unsigned );static void TLan_MiiSync( u16 );static void TLan_MiiWriteReg( struct net_device *, u16, u16, u16 );static void TLan_EeSendStart( u16 );static int TLan_EeSendByte( u16, u8, int );static void TLan_EeReceiveByte( u16, u8 *, int );static int TLan_EeReadByte( struct net_device *, u8, u8 * );static TLanIntVectorFunc *TLanIntVector[TLAN_INT_NUMBER_OF_INTS] = { TLan_HandleInvalid, TLan_HandleTxEOF, TLan_HandleStatOverflow, TLan_HandleRxEOF, TLan_HandleDummy, TLan_HandleTxEOC, TLan_HandleStatusCheck, TLan_HandleRxEOC};static inline voidTLan_SetTimer( struct net_device *dev, u32 ticks, u32 type ){ TLanPrivateInfo *priv = dev->priv; unsigned long flags = 0; if (!in_irq()) spin_lock_irqsave(&priv->lock, flags); if ( priv->timer.function != NULL && priv->timerType != TLAN_TIMER_ACTIVITY ) { if (!in_irq()) spin_unlock_irqrestore(&priv->lock, flags); return; } priv->timer.function = &TLan_Timer; if (!in_irq()) spin_unlock_irqrestore(&priv->lock, flags); priv->timer.data = (unsigned long) dev; priv->timerSetAt = jiffies; priv->timerType = type; mod_timer(&priv->timer, jiffies + ticks); } /* TLan_SetTimer *//*********************************************************************************************************************************************************** ThunderLAN Driver Primary Functions These functions are more or less common to all Linux network drivers.***********************************************************************************************************************************************************/ /*************************************************************** * tlan_remove_one * * Returns: * Nothing * Parms: * None * * Goes through the TLanDevices list and frees the device * structs and memory associated with each device (lists * and buffers). It also ureserves the IO port regions * associated with this device. * **************************************************************/static void __devexit tlan_remove_one( struct pci_dev *pdev){ struct net_device *dev = pci_get_drvdata( pdev ); TLanPrivateInfo *priv = dev->priv; unregister_netdev( dev ); if ( priv->dmaStorage ) { kfree( priv->dmaStorage ); } release_region( dev->base_addr, 0x10 ); kfree( dev ); pci_set_drvdata( pdev, NULL );} static struct pci_driver tlan_driver = { name: "tlan", id_table: tlan_pci_tbl, probe: tlan_init_one, remove: tlan_remove_one, };static int __init tlan_probe(void){ static int pad_allocated; printk(KERN_INFO "%s", tlan_banner); TLanPadBuffer = (u8 *) kmalloc(TLAN_MIN_FRAME_SIZE, GFP_KERNEL); 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); 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_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -