📄 tlan.c
字号:
/******************************************************************************* * * Linux ThunderLAN Driver * * tlan.c * by James Banks * * (C) 1997-1998 Caldera, Inc. * (C) 1998 James Banks * (C) 1999, 2000 Torben Mathiasen * * This software may be used and distributed according to the terms * of the GNU Public License, incorporated herein by reference. * ** This file is best viewed/edited with columns>=132. * ** Useful (if not required) reading: * * Texas Instruments, ThunderLAN Programmer's Guide, * TI Literature Number SPWU013A * available in PDF format from www.ti.com * Level One, LXT901 and LXT970 Data Sheets * available in PDF format from www.level1.com * National Semiconductor, DP83840A Data Sheet * available in PDF format from www.national.com * Microchip Technology, 24C01A/02A/04A Data Sheet * available in PDF format from www.microchip.com * * Change History * * Tigran Aivazian <tigran@sco.com>: TLan_PciProbe() now uses * new PCI BIOS interface. * Alan Cox <alan@redhat.com>: Fixed the out of memory * handling. * * Torben Mathiasen <torben.mathiasen@compaq.com> New Maintainer! * * v1.1 Dec 20, 1999 - Removed linux version checking * Patch from Tigran Aivazian. * - v1.1 includes Alan's SMP updates. * - We still have problems on SMP though, * but I'm looking into that. * * v1.2 Jan 02, 2000 - Hopefully fixed the SMP deadlock. * - Removed dependency of HZ being 100. * - We now allow higher priority timers to * overwrite timers like TLAN_TIMER_ACTIVITY * Patch from John Cagle <john.cagle@compaq.com>. * - Fixed a few compiler warnings. * * v1.3 Feb 04, 2000 - Fixed the remaining HZ issues. * - Removed call to pci_present(). * - Removed SA_INTERRUPT flag from irq handler. * - Added __init and __initdata to reduce resisdent * code size. * - Driver now uses module_init/module_exit. * - Rewrote init_module and tlan_probe to * share a lot more code. We now use tlan_probe * with builtin and module driver. * - Driver ported to new net API. * - tlan.txt has been reworked to reflect current * driver (almost) * - Other minor stuff * * v1.4 Feb 10, 2000 - Updated with more changes required after Dave's * network cleanup in 2.3.43pre7 (Tigran & myself) * - Minor stuff. * * v1.5 March 22, 2000 - Fixed another timer bug that would hang the driver * if no cable/link were present. * - Cosmetic changes. * - TODO: Port completely to new PCI/DMA API * Auto-Neg fallback. * * v1.6 April 04, 2000 - Fixed driver support for kernel-parameters. Haven't * tested it though, as the kernel support is currently * broken (2.3.99p4p3). * - Updated tlan.txt accordingly. * - Adjusted minimum/maximum frame length. * - There is now a TLAN website up at * http://tlan.kernel.dk * * v1.7 April 07, 2000 - Started to implement custom ioctls. Driver now * reports PHY information when used with Donald * Beckers userspace MII diagnostics utility. * * v1.8 April 23, 2000 - Fixed support for forced speed/duplex settings. * - Added link information to Auto-Neg and forced * modes. When NIC operates with auto-neg the driver * will report Link speed & duplex modes as well as * link partner abilities. When forced link is used, * the driver will report status of the established * link. * Please read tlan.txt for additional information. * - Removed call to check_region(), and used * return value of request_region() instead. * * v1.8a May 28, 2000 - Minor updates. * * v1.9 July 25, 2000 - Fixed a few remaining Full-Duplex issues. * - Updated with timer fixes from Andrew Morton. * - Fixed module race in TLan_Open. * - Added routine to monitor PHY status. * - Added activity led support for Proliant devices. * * v1.10 Aug 30, 2000 - Added support for EISA based tlan controllers * like the Compaq NetFlex3/E. * - Rewrote tlan_probe to better handle multiple * bus probes. Probing and device setup is now * done through TLan_Probe and TLan_init_one. Actual * hardware probe is done with kernel API and * TLan_EisaProbe. * - Adjusted debug information for probing. * - Fixed bug that would cause general debug information * to be printed after driver removal. * - Added transmit timeout handling. * - Fixed OOM return values in tlan_probe. * - Fixed possible mem leak in tlan_exit * (now tlan_remove_one). * - Fixed timer bug in TLan_phyMonitor. * - This driver version is alpha quality, please * send me any bug issues you may encounter. * * v1.11 Aug 31, 2000 - Do not try to register irq 0 if no irq line was * set for EISA cards. * - Added support for NetFlex3/E with nibble-rate * 10Base-T PHY. This is untestet as I haven't got * one of these cards. * - Fixed timer being added twice. * - Disabled PhyMonitoring by default as this is * work in progress. Define MONITOR to enable it. * - Now we don't display link info with PHYs that * doesn't support it (level1). * - Incresed tx_timeout beacuse of auto-neg. * - Adjusted timers for forced speeds. * * v1.12 Oct 12, 2000 - Minor fixes (memleak, init, etc.) * *******************************************************************************/ #include <linux/module.h>#include "tlan.h"#include <linux/init.h>#include <linux/ioport.h>#include <linux/pci.h>#include <linux/etherdevice.h>#include <linux/delay.h>#include <linux/spinlock.h>typedef u32 (TLanIntVectorFunc)( struct net_device *, u16 );/* For removing EISA devices */static struct net_device *TLan_Eisa_Devices;static int TLanDevicesInstalled;/* Force speed, duplex and aui settings */static int aui;static int duplex; static int speed;MODULE_AUTHOR("Maintainer: Torben Mathiasen <torben.mathiasen@compaq.com>");MODULE_DESCRIPTION("Driver for TI ThunderLAN based ethernet PCI adapters");MODULE_PARM(aui, "i");MODULE_PARM(duplex, "i");MODULE_PARM(speed, "i");MODULE_PARM(debug, "i");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.12\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_NETELLIGENT_10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10_100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETFLEX_3P_INTEGRATED, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETFLEX_3P, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETFLEX_3P_BNC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10_100_PROLIANT, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10_100_DUAL, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_DESKPRO_4000_5233MMX, 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 = (TLanPrivateInfo *) dev->priv; unsigned long flags; spin_lock_irqsave(&priv->lock, flags); if ( priv->timer.function != NULL && priv->timerType != TLAN_TIMER_ACTIVITY ) { spin_unlock_irqrestore(&priv->lock, flags); return; } priv->timer.function = &TLan_Timer; 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 = pdev->driver_data; TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; unregister_netdev( dev ); if ( priv->dmaStorage ) { kfree( priv->dmaStorage ); } release_region( dev->base_addr, 0x10 ); kfree( dev ); } 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 = 0; printk(KERN_INFO "%s", tlan_banner); TLanPadBuffer = (u8 *) kmalloc(TLAN_MIN_FRAME_SIZE, (GFP_KERNEL | GFP_DMA)); 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_module_init(&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); return ((TLanDevicesInstalled > 0) ? 0 : -ENODEV);} static int __devinit tlan_init_one( struct pci_dev *pdev, const struct pci_device_id *ent){ return TLan_probe1( pdev, pci_resource_start(pdev, 0), pdev->irq, 0, ent);}/* *************************************************************** * tlan_probe1
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -