blob: ec871f646766dc7294101fe5ad7f789b66d3f0bb [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*******************************************************************************
2 *
3 * Linux ThunderLAN Driver
4 *
5 * tlan.c
6 * by James Banks
7 *
8 * (C) 1997-1998 Caldera, Inc.
9 * (C) 1998 James Banks
10 * (C) 1999-2001 Torben Mathiasen
11 * (C) 2002 Samuel Chessman
12 *
13 * This software may be used and distributed according to the terms
14 * of the GNU General Public License, incorporated herein by reference.
15 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070016 ** Useful (if not required) reading:
17 *
18 * Texas Instruments, ThunderLAN Programmer's Guide,
19 * TI Literature Number SPWU013A
20 * available in PDF format from www.ti.com
21 * Level One, LXT901 and LXT970 Data Sheets
22 * available in PDF format from www.level1.com
23 * National Semiconductor, DP83840A Data Sheet
24 * available in PDF format from www.national.com
25 * Microchip Technology, 24C01A/02A/04A Data Sheet
26 * available in PDF format from www.microchip.com
27 *
28 * Change History
29 *
30 * Tigran Aivazian <tigran@sco.com>: TLan_PciProbe() now uses
31 * new PCI BIOS interface.
32 * Alan Cox <alan@redhat.com>: Fixed the out of memory
33 * handling.
Jeff Garzik6aa20a22006-09-13 13:24:59 -040034 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070035 * Torben Mathiasen <torben.mathiasen@compaq.com> New Maintainer!
36 *
37 * v1.1 Dec 20, 1999 - Removed linux version checking
Jeff Garzik6aa20a22006-09-13 13:24:59 -040038 * Patch from Tigran Aivazian.
Linus Torvalds1da177e2005-04-16 15:20:36 -070039 * - v1.1 includes Alan's SMP updates.
40 * - We still have problems on SMP though,
Jeff Garzik6aa20a22006-09-13 13:24:59 -040041 * but I'm looking into that.
42 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070043 * v1.2 Jan 02, 2000 - Hopefully fixed the SMP deadlock.
44 * - Removed dependency of HZ being 100.
Jeff Garzik6aa20a22006-09-13 13:24:59 -040045 * - We now allow higher priority timers to
Linus Torvalds1da177e2005-04-16 15:20:36 -070046 * overwrite timers like TLAN_TIMER_ACTIVITY
47 * Patch from John Cagle <john.cagle@compaq.com>.
48 * - Fixed a few compiler warnings.
49 *
50 * v1.3 Feb 04, 2000 - Fixed the remaining HZ issues.
Jeff Garzik6aa20a22006-09-13 13:24:59 -040051 * - Removed call to pci_present().
Linus Torvalds1da177e2005-04-16 15:20:36 -070052 * - Removed SA_INTERRUPT flag from irq handler.
Jeff Garzik6aa20a22006-09-13 13:24:59 -040053 * - Added __init and __initdata to reduce resisdent
Linus Torvalds1da177e2005-04-16 15:20:36 -070054 * code size.
55 * - Driver now uses module_init/module_exit.
56 * - Rewrote init_module and tlan_probe to
57 * share a lot more code. We now use tlan_probe
58 * with builtin and module driver.
Jeff Garzik6aa20a22006-09-13 13:24:59 -040059 * - Driver ported to new net API.
60 * - tlan.txt has been reworked to reflect current
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 * driver (almost)
62 * - Other minor stuff
63 *
64 * v1.4 Feb 10, 2000 - Updated with more changes required after Dave's
65 * network cleanup in 2.3.43pre7 (Tigran & myself)
66 * - Minor stuff.
67 *
68 * v1.5 March 22, 2000 - Fixed another timer bug that would hang the driver
69 * if no cable/link were present.
70 * - Cosmetic changes.
71 * - TODO: Port completely to new PCI/DMA API
72 * Auto-Neg fallback.
73 *
74 * v1.6 April 04, 2000 - Fixed driver support for kernel-parameters. Haven't
Jeff Garzik6aa20a22006-09-13 13:24:59 -040075 * tested it though, as the kernel support is currently
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 * broken (2.3.99p4p3).
77 * - Updated tlan.txt accordingly.
78 * - Adjusted minimum/maximum frame length.
Jeff Garzik6aa20a22006-09-13 13:24:59 -040079 * - There is now a TLAN website up at
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 * http://tlan.kernel.dk
81 *
82 * v1.7 April 07, 2000 - Started to implement custom ioctls. Driver now
83 * reports PHY information when used with Donald
84 * Beckers userspace MII diagnostics utility.
85 *
86 * v1.8 April 23, 2000 - Fixed support for forced speed/duplex settings.
87 * - Added link information to Auto-Neg and forced
88 * modes. When NIC operates with auto-neg the driver
89 * will report Link speed & duplex modes as well as
90 * link partner abilities. When forced link is used,
91 * the driver will report status of the established
92 * link.
Jeff Garzik6aa20a22006-09-13 13:24:59 -040093 * Please read tlan.txt for additional information.
94 * - Removed call to check_region(), and used
Linus Torvalds1da177e2005-04-16 15:20:36 -070095 * return value of request_region() instead.
Jeff Garzik6aa20a22006-09-13 13:24:59 -040096 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070097 * v1.8a May 28, 2000 - Minor updates.
98 *
99 * v1.9 July 25, 2000 - Fixed a few remaining Full-Duplex issues.
100 * - Updated with timer fixes from Andrew Morton.
101 * - Fixed module race in TLan_Open.
102 * - Added routine to monitor PHY status.
103 * - Added activity led support for Proliant devices.
104 *
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400105 * v1.10 Aug 30, 2000 - Added support for EISA based tlan controllers
106 * like the Compaq NetFlex3/E.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 * - Rewrote tlan_probe to better handle multiple
108 * bus probes. Probing and device setup is now
109 * done through TLan_Probe and TLan_init_one. Actual
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400110 * hardware probe is done with kernel API and
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 * TLan_EisaProbe.
112 * - Adjusted debug information for probing.
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400113 * - Fixed bug that would cause general debug information
114 * to be printed after driver removal.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 * - Added transmit timeout handling.
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400116 * - Fixed OOM return values in tlan_probe.
117 * - Fixed possible mem leak in tlan_exit
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 * (now tlan_remove_one).
119 * - Fixed timer bug in TLan_phyMonitor.
120 * - This driver version is alpha quality, please
121 * send me any bug issues you may encounter.
122 *
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400123 * v1.11 Aug 31, 2000 - Do not try to register irq 0 if no irq line was
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 * set for EISA cards.
125 * - Added support for NetFlex3/E with nibble-rate
126 * 10Base-T PHY. This is untestet as I haven't got
127 * one of these cards.
128 * - Fixed timer being added twice.
129 * - Disabled PhyMonitoring by default as this is
130 * work in progress. Define MONITOR to enable it.
131 * - Now we don't display link info with PHYs that
132 * doesn't support it (level1).
133 * - Incresed tx_timeout beacuse of auto-neg.
134 * - Adjusted timers for forced speeds.
135 *
136 * v1.12 Oct 12, 2000 - Minor fixes (memleak, init, etc.)
137 *
138 * v1.13 Nov 28, 2000 - Stop flooding console with auto-neg issues
139 * when link can't be established.
140 * - Added the bbuf option as a kernel parameter.
141 * - Fixed ioaddr probe bug.
142 * - Fixed stupid deadlock with MII interrupts.
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400143 * - Added support for speed/duplex selection with
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 * multiple nics.
145 * - Added partly fix for TX Channel lockup with
146 * TLAN v1.0 silicon. This needs to be investigated
147 * further.
148 *
149 * v1.14 Dec 16, 2000 - Added support for servicing multiple frames per.
150 * interrupt. Thanks goes to
151 * Adam Keys <adam@ti.com>
152 * Denis Beaudoin <dbeaudoin@ti.com>
153 * for providing the patch.
154 * - Fixed auto-neg output when using multiple
155 * adapters.
156 * - Converted to use new taskq interface.
157 *
158 * v1.14a Jan 6, 2001 - Minor adjustments (spinlocks, etc.)
159 *
160 * Samuel Chessman <chessman@tux.org> New Maintainer!
161 *
162 * v1.15 Apr 4, 2002 - Correct operation when aui=1 to be
163 * 10T half duplex no loopback
164 * Thanks to Gunnar Eikman
165 *******************************************************************************/
166
167#include <linux/module.h>
168#include <linux/init.h>
169#include <linux/ioport.h>
170#include <linux/eisa.h>
171#include <linux/pci.h>
Domen Puncer1e7f0bd2005-06-26 18:22:14 -0400172#include <linux/dma-mapping.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173#include <linux/netdevice.h>
174#include <linux/etherdevice.h>
175#include <linux/delay.h>
176#include <linux/spinlock.h>
177#include <linux/workqueue.h>
178#include <linux/mii.h>
179
180#include "tlan.h"
181
182typedef u32 (TLanIntVectorFunc)( struct net_device *, u16 );
183
184
185/* For removing EISA devices */
186static struct net_device *TLan_Eisa_Devices;
187
188static int TLanDevicesInstalled;
189
190/* Set speed, duplex and aui settings */
191static int aui[MAX_TLAN_BOARDS];
192static int duplex[MAX_TLAN_BOARDS];
193static int speed[MAX_TLAN_BOARDS];
194static int boards_found;
Stephen Hemminger15efa9b2005-05-04 15:33:11 -0700195module_param_array(aui, int, NULL, 0);
196module_param_array(duplex, int, NULL, 0);
197module_param_array(speed, int, NULL, 0);
198MODULE_PARM_DESC(aui, "ThunderLAN use AUI port(s) (0-1)");
199MODULE_PARM_DESC(duplex, "ThunderLAN duplex setting(s) (0-default, 1-half, 2-full)");
200MODULE_PARM_DESC(speed, "ThunderLAN port speen setting(s) (0,10,100)");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201
202MODULE_AUTHOR("Maintainer: Samuel Chessman <chessman@tux.org>");
203MODULE_DESCRIPTION("Driver for TI ThunderLAN based ethernet PCI adapters");
204MODULE_LICENSE("GPL");
205
206
207/* Define this to enable Link beat monitoring */
208#undef MONITOR
209
210/* Turn on debugging. See Documentation/networking/tlan.txt for details */
211static int debug;
Stephen Hemminger15efa9b2005-05-04 15:33:11 -0700212module_param(debug, int, 0);
213MODULE_PARM_DESC(debug, "ThunderLAN debug mask");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214
215static int bbuf;
Stephen Hemminger15efa9b2005-05-04 15:33:11 -0700216module_param(bbuf, int, 0);
217MODULE_PARM_DESC(bbuf, "ThunderLAN use big buffer (0-1)");
218
Stephen Hemmingera3ccc782008-05-30 09:49:57 -0700219static const char TLanSignature[] = "TLAN";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220static const char tlan_banner[] = "ThunderLAN driver v1.15\n";
221static int tlan_have_pci;
222static int tlan_have_eisa;
223
224static const char *media[] = {
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400225 "10BaseT-HD ", "10BaseT-FD ","100baseTx-HD ",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 "100baseTx-FD", "100baseT4", NULL
227};
228
229static struct board {
230 const char *deviceLabel;
231 u32 flags;
232 u16 addrOfs;
233} board_info[] = {
234 { "Compaq Netelligent 10 T PCI UTP", TLAN_ADAPTER_ACTIVITY_LED, 0x83 },
235 { "Compaq Netelligent 10/100 TX PCI UTP", TLAN_ADAPTER_ACTIVITY_LED, 0x83 },
236 { "Compaq Integrated NetFlex-3/P", TLAN_ADAPTER_NONE, 0x83 },
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700237 { "Compaq NetFlex-3/P",
238 TLAN_ADAPTER_UNMANAGED_PHY | TLAN_ADAPTER_BIT_RATE_PHY, 0x83 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 { "Compaq NetFlex-3/P", TLAN_ADAPTER_NONE, 0x83 },
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700240 { "Compaq Netelligent Integrated 10/100 TX UTP",
241 TLAN_ADAPTER_ACTIVITY_LED, 0x83 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 { "Compaq Netelligent Dual 10/100 TX PCI UTP", TLAN_ADAPTER_NONE, 0x83 },
243 { "Compaq Netelligent 10/100 TX Embedded UTP", TLAN_ADAPTER_NONE, 0x83 },
244 { "Olicom OC-2183/2185", TLAN_ADAPTER_USE_INTERN_10, 0x83 },
245 { "Olicom OC-2325", TLAN_ADAPTER_UNMANAGED_PHY, 0xF8 },
246 { "Olicom OC-2326", TLAN_ADAPTER_USE_INTERN_10, 0xF8 },
247 { "Compaq Netelligent 10/100 TX UTP", TLAN_ADAPTER_ACTIVITY_LED, 0x83 },
248 { "Compaq Netelligent 10 T/2 PCI UTP/Coax", TLAN_ADAPTER_NONE, 0x83 },
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700249 { "Compaq NetFlex-3/E",
250 TLAN_ADAPTER_ACTIVITY_LED | /* EISA card */
251 TLAN_ADAPTER_UNMANAGED_PHY | TLAN_ADAPTER_BIT_RATE_PHY, 0x83 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 { "Compaq NetFlex-3/E", TLAN_ADAPTER_ACTIVITY_LED, 0x83 }, /* EISA card */
253};
254
255static struct pci_device_id tlan_pci_tbl[] = {
256 { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL10,
257 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
258 { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100,
259 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
260 { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETFLEX3I,
261 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
262 { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_THUNDER,
263 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 },
264 { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETFLEX3B,
265 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
266 { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100PI,
267 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 },
268 { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100D,
269 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 },
270 { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100I,
271 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7 },
272 { PCI_VENDOR_ID_OLICOM, PCI_DEVICE_ID_OLICOM_OC2183,
273 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
274 { PCI_VENDOR_ID_OLICOM, PCI_DEVICE_ID_OLICOM_OC2325,
275 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9 },
276 { PCI_VENDOR_ID_OLICOM, PCI_DEVICE_ID_OLICOM_OC2326,
277 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10 },
278 { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10_100_WS_5100,
279 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 },
280 { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10_T2,
281 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 },
282 { 0,}
283};
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400284MODULE_DEVICE_TABLE(pci, tlan_pci_tbl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
286static void TLan_EisaProbe( void );
287static void TLan_Eisa_Cleanup( void );
288static int TLan_Init( struct net_device * );
289static int TLan_Open( struct net_device *dev );
290static int TLan_StartTx( struct sk_buff *, struct net_device *);
David Howells7d12e782006-10-05 14:55:46 +0100291static irqreturn_t TLan_HandleInterrupt( int, void *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292static int TLan_Close( struct net_device *);
293static struct net_device_stats *TLan_GetStats( struct net_device *);
294static void TLan_SetMulticastList( struct net_device *);
295static int TLan_ioctl( struct net_device *dev, struct ifreq *rq, int cmd);
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700296static int TLan_probe1( struct pci_dev *pdev, long ioaddr,
297 int irq, int rev, const struct pci_device_id *ent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298static void TLan_tx_timeout( struct net_device *dev);
David Howellsc4028952006-11-22 14:57:56 +0000299static void TLan_tx_timeout_work(struct work_struct *work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300static int tlan_init_one( struct pci_dev *pdev, const struct pci_device_id *ent);
301
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302static u32 TLan_HandleTxEOF( struct net_device *, u16 );
303static u32 TLan_HandleStatOverflow( struct net_device *, u16 );
304static u32 TLan_HandleRxEOF( struct net_device *, u16 );
305static u32 TLan_HandleDummy( struct net_device *, u16 );
306static u32 TLan_HandleTxEOC( struct net_device *, u16 );
307static u32 TLan_HandleStatusCheck( struct net_device *, u16 );
308static u32 TLan_HandleRxEOC( struct net_device *, u16 );
309
310static void TLan_Timer( unsigned long );
311
312static void TLan_ResetLists( struct net_device * );
313static void TLan_FreeLists( struct net_device * );
314static void TLan_PrintDio( u16 );
315static void TLan_PrintList( TLanList *, char *, int );
316static void TLan_ReadAndClearStats( struct net_device *, int );
317static void TLan_ResetAdapter( struct net_device * );
318static void TLan_FinishReset( struct net_device * );
319static void TLan_SetMac( struct net_device *, int areg, char *mac );
320
321static void TLan_PhyPrint( struct net_device * );
322static void TLan_PhyDetect( struct net_device * );
323static void TLan_PhyPowerDown( struct net_device * );
324static void TLan_PhyPowerUp( struct net_device * );
325static void TLan_PhyReset( struct net_device * );
326static void TLan_PhyStartLink( struct net_device * );
327static void TLan_PhyFinishAutoNeg( struct net_device * );
328#ifdef MONITOR
329static void TLan_PhyMonitor( struct net_device * );
330#endif
331
332/*
333static int TLan_PhyNop( struct net_device * );
334static int TLan_PhyInternalCheck( struct net_device * );
335static int TLan_PhyInternalService( struct net_device * );
336static int TLan_PhyDp83840aCheck( struct net_device * );
337*/
338
339static int TLan_MiiReadReg( struct net_device *, u16, u16, u16 * );
340static void TLan_MiiSendData( u16, u32, unsigned );
341static void TLan_MiiSync( u16 );
342static void TLan_MiiWriteReg( struct net_device *, u16, u16, u16 );
343
344static void TLan_EeSendStart( u16 );
345static int TLan_EeSendByte( u16, u8, int );
346static void TLan_EeReceiveByte( u16, u8 *, int );
347static int TLan_EeReadByte( struct net_device *, u8, u8 * );
348
349
Stephen Hemminger93e16842008-05-30 09:49:55 -0700350static inline void
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351TLan_StoreSKB( struct tlan_list_tag *tag, struct sk_buff *skb)
352{
353 unsigned long addr = (unsigned long)skb;
Stephen Hemminger93e16842008-05-30 09:49:55 -0700354 tag->buffer[9].address = addr;
355 tag->buffer[8].address = upper_32_bits(addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356}
357
Stephen Hemminger93e16842008-05-30 09:49:55 -0700358static inline struct sk_buff *
359TLan_GetSKB( const struct tlan_list_tag *tag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360{
Stephen Hemminger93e16842008-05-30 09:49:55 -0700361 unsigned long addr;
362
Robert Fitzsimons0d63bea2008-08-09 17:54:02 +0100363 addr = tag->buffer[9].address;
364 addr |= (tag->buffer[8].address << 16) << 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 return (struct sk_buff *) addr;
366}
367
368
369static TLanIntVectorFunc *TLanIntVector[TLAN_INT_NUMBER_OF_INTS] = {
Stephen Hemmingera3ccc782008-05-30 09:49:57 -0700370 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 TLan_HandleTxEOF,
372 TLan_HandleStatOverflow,
373 TLan_HandleRxEOF,
374 TLan_HandleDummy,
375 TLan_HandleTxEOC,
376 TLan_HandleStatusCheck,
377 TLan_HandleRxEOC
378};
379
380static inline void
381TLan_SetTimer( struct net_device *dev, u32 ticks, u32 type )
382{
383 TLanPrivateInfo *priv = netdev_priv(dev);
384 unsigned long flags = 0;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400385
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 if (!in_irq())
387 spin_lock_irqsave(&priv->lock, flags);
388 if ( priv->timer.function != NULL &&
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400389 priv->timerType != TLAN_TIMER_ACTIVITY ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 if (!in_irq())
391 spin_unlock_irqrestore(&priv->lock, flags);
392 return;
393 }
394 priv->timer.function = &TLan_Timer;
395 if (!in_irq())
396 spin_unlock_irqrestore(&priv->lock, flags);
397
398 priv->timer.data = (unsigned long) dev;
399 priv->timerSetAt = jiffies;
400 priv->timerType = type;
401 mod_timer(&priv->timer, jiffies + ticks);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400402
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403} /* TLan_SetTimer */
404
405
406/*****************************************************************************
407******************************************************************************
408
409 ThunderLAN Driver Primary Functions
410
411 These functions are more or less common to all Linux network drivers.
412
413******************************************************************************
414*****************************************************************************/
415
416
417
418
419
420 /***************************************************************
421 * tlan_remove_one
422 *
423 * Returns:
424 * Nothing
425 * Parms:
426 * None
427 *
428 * Goes through the TLanDevices list and frees the device
429 * structs and memory associated with each device (lists
430 * and buffers). It also ureserves the IO port regions
431 * associated with this device.
432 *
433 **************************************************************/
434
435
436static void __devexit tlan_remove_one( struct pci_dev *pdev)
437{
438 struct net_device *dev = pci_get_drvdata( pdev );
439 TLanPrivateInfo *priv = netdev_priv(dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400440
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 unregister_netdev( dev );
442
443 if ( priv->dmaStorage ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700444 pci_free_consistent(priv->pciDev,
445 priv->dmaSize, priv->dmaStorage,
446 priv->dmaStorageDMA );
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 }
448
449#ifdef CONFIG_PCI
450 pci_release_regions(pdev);
451#endif
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400452
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 free_netdev( dev );
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400454
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 pci_set_drvdata( pdev, NULL );
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400456}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457
458static struct pci_driver tlan_driver = {
459 .name = "tlan",
460 .id_table = tlan_pci_tbl,
461 .probe = tlan_init_one,
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400462 .remove = __devexit_p(tlan_remove_one),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463};
464
465static int __init tlan_probe(void)
466{
Leonardo Potenza6c04a512008-02-04 23:47:16 -0800467 int rc = -ENODEV;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400468
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 printk(KERN_INFO "%s", tlan_banner);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400470
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 TLAN_DBG(TLAN_DEBUG_PROBE, "Starting PCI Probe....\n");
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400472
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 /* Use new style PCI probing. Now the kernel will
474 do most of this for us */
Leonardo Potenza6c04a512008-02-04 23:47:16 -0800475 rc = pci_register_driver(&tlan_driver);
476
477 if (rc != 0) {
478 printk(KERN_ERR "TLAN: Could not register pci driver.\n");
479 goto err_out_pci_free;
480 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481
482 TLAN_DBG(TLAN_DEBUG_PROBE, "Starting EISA Probe....\n");
483 TLan_EisaProbe();
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400484
485 printk(KERN_INFO "TLAN: %d device%s installed, PCI: %d EISA: %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 TLanDevicesInstalled, TLanDevicesInstalled == 1 ? "" : "s",
487 tlan_have_pci, tlan_have_eisa);
488
489 if (TLanDevicesInstalled == 0) {
Leonardo Potenza6c04a512008-02-04 23:47:16 -0800490 rc = -ENODEV;
491 goto err_out_pci_unreg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 }
493 return 0;
Leonardo Potenza6c04a512008-02-04 23:47:16 -0800494
495err_out_pci_unreg:
496 pci_unregister_driver(&tlan_driver);
497err_out_pci_free:
Leonardo Potenza6c04a512008-02-04 23:47:16 -0800498 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499}
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400500
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501
502static int __devinit tlan_init_one( struct pci_dev *pdev,
503 const struct pci_device_id *ent)
504{
505 return TLan_probe1( pdev, -1, -1, 0, ent);
506}
507
508
509/*
510 ***************************************************************
511 * tlan_probe1
512 *
513 * Returns:
514 * 0 on success, error code on error
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400515 * Parms:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 * none
517 *
518 * The name is lower case to fit in with all the rest of
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400519 * the netcard_probe names. This function looks for
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 * another TLan based adapter, setting it up with the
521 * allocated device struct if one is found.
522 * tlan_probe has been ported to the new net API and
523 * now allocates its own device structure. This function
524 * is also used by modules.
525 *
526 **************************************************************/
527
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400528static int __devinit TLan_probe1(struct pci_dev *pdev,
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700529 long ioaddr, int irq, int rev,
530 const struct pci_device_id *ent )
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531{
532
533 struct net_device *dev;
534 TLanPrivateInfo *priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 u16 device_id;
536 int reg, rc = -ENODEV;
537
Adrian Bunkad9f6712006-02-05 00:37:47 +0100538#ifdef CONFIG_PCI
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 if (pdev) {
540 rc = pci_enable_device(pdev);
541 if (rc)
542 return rc;
543
544 rc = pci_request_regions(pdev, TLanSignature);
545 if (rc) {
546 printk(KERN_ERR "TLAN: Could not reserve IO regions\n");
547 goto err_out;
548 }
549 }
Adrian Bunkad9f6712006-02-05 00:37:47 +0100550#endif /* CONFIG_PCI */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551
552 dev = alloc_etherdev(sizeof(TLanPrivateInfo));
553 if (dev == NULL) {
554 printk(KERN_ERR "TLAN: Could not allocate memory for device.\n");
555 rc = -ENOMEM;
556 goto err_out_regions;
557 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 SET_NETDEV_DEV(dev, &pdev->dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400559
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 priv = netdev_priv(dev);
561
562 priv->pciDev = pdev;
David Howellsc4028952006-11-22 14:57:56 +0000563 priv->dev = dev;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400564
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 /* Is this a PCI device? */
566 if (pdev) {
567 u32 pci_io_base = 0;
568
569 priv->adapter = &board_info[ent->driver_data];
570
Domen Puncer1e7f0bd2005-06-26 18:22:14 -0400571 rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 if (rc) {
573 printk(KERN_ERR "TLAN: No suitable PCI mapping available.\n");
574 goto err_out_free_dev;
575 }
576
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 for ( reg= 0; reg <= 5; reg ++ ) {
578 if (pci_resource_flags(pdev, reg) & IORESOURCE_IO) {
579 pci_io_base = pci_resource_start(pdev, reg);
580 TLAN_DBG( TLAN_DEBUG_GNRL, "IO mapping is available at %x.\n",
581 pci_io_base);
582 break;
583 }
584 }
585 if (!pci_io_base) {
586 printk(KERN_ERR "TLAN: No IO mappings available\n");
587 rc = -EIO;
588 goto err_out_free_dev;
589 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400590
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 dev->base_addr = pci_io_base;
592 dev->irq = pdev->irq;
Auke Kok44c10132007-06-08 15:46:36 -0700593 priv->adapterRev = pdev->revision;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 pci_set_master(pdev);
595 pci_set_drvdata(pdev, dev);
596
597 } else { /* EISA card */
598 /* This is a hack. We need to know which board structure
599 * is suited for this adapter */
600 device_id = inw(ioaddr + EISA_ID2);
601 priv->is_eisa = 1;
602 if (device_id == 0x20F1) {
603 priv->adapter = &board_info[13]; /* NetFlex-3/E */
604 priv->adapterRev = 23; /* TLAN 2.3 */
605 } else {
606 priv->adapter = &board_info[14];
607 priv->adapterRev = 10; /* TLAN 1.0 */
608 }
609 dev->base_addr = ioaddr;
610 dev->irq = irq;
611 }
612
613 /* Kernel parameters */
614 if (dev->mem_start) {
615 priv->aui = dev->mem_start & 0x01;
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700616 priv->duplex = ((dev->mem_start & 0x06) == 0x06) ? 0
617 : (dev->mem_start & 0x06) >> 1;
618 priv->speed = ((dev->mem_start & 0x18) == 0x18) ? 0
619 : (dev->mem_start & 0x18) >> 3;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400620
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 if (priv->speed == 0x1) {
622 priv->speed = TLAN_SPEED_10;
623 } else if (priv->speed == 0x2) {
624 priv->speed = TLAN_SPEED_100;
625 }
626 debug = priv->debug = dev->mem_end;
627 } else {
628 priv->aui = aui[boards_found];
629 priv->speed = speed[boards_found];
630 priv->duplex = duplex[boards_found];
631 priv->debug = debug;
632 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400633
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 /* This will be used when we get an adapter error from
635 * within our irq handler */
David Howellsc4028952006-11-22 14:57:56 +0000636 INIT_WORK(&priv->tlan_tqueue, TLan_tx_timeout_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637
638 spin_lock_init(&priv->lock);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400639
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 rc = TLan_Init(dev);
641 if (rc) {
642 printk(KERN_ERR "TLAN: Could not set up device.\n");
643 goto err_out_free_dev;
644 }
645
646 rc = register_netdev(dev);
647 if (rc) {
648 printk(KERN_ERR "TLAN: Could not register device.\n");
649 goto err_out_uninit;
650 }
651
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400652
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 TLanDevicesInstalled++;
654 boards_found++;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400655
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 /* pdev is NULL if this is an EISA device */
657 if (pdev)
658 tlan_have_pci++;
659 else {
660 priv->nextDevice = TLan_Eisa_Devices;
661 TLan_Eisa_Devices = dev;
662 tlan_have_eisa++;
663 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400664
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 printk(KERN_INFO "TLAN: %s irq=%2d, io=%04x, %s, Rev. %d\n",
666 dev->name,
667 (int) dev->irq,
668 (int) dev->base_addr,
669 priv->adapter->deviceLabel,
670 priv->adapterRev);
671 return 0;
672
673err_out_uninit:
674 pci_free_consistent(priv->pciDev, priv->dmaSize, priv->dmaStorage,
675 priv->dmaStorageDMA );
676err_out_free_dev:
677 free_netdev(dev);
678err_out_regions:
679#ifdef CONFIG_PCI
680 if (pdev)
681 pci_release_regions(pdev);
682#endif
683err_out:
684 if (pdev)
685 pci_disable_device(pdev);
686 return rc;
687}
688
689
690static void TLan_Eisa_Cleanup(void)
691{
692 struct net_device *dev;
693 TLanPrivateInfo *priv;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400694
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 while( tlan_have_eisa ) {
696 dev = TLan_Eisa_Devices;
697 priv = netdev_priv(dev);
698 if (priv->dmaStorage) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700699 pci_free_consistent(priv->pciDev, priv->dmaSize,
700 priv->dmaStorage, priv->dmaStorageDMA );
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 }
702 release_region( dev->base_addr, 0x10);
703 unregister_netdev( dev );
704 TLan_Eisa_Devices = priv->nextDevice;
705 free_netdev( dev );
706 tlan_have_eisa--;
707 }
708}
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400709
710
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711static void __exit tlan_exit(void)
712{
713 pci_unregister_driver(&tlan_driver);
714
715 if (tlan_have_eisa)
716 TLan_Eisa_Cleanup();
717
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718}
719
720
721/* Module loading/unloading */
722module_init(tlan_probe);
723module_exit(tlan_exit);
724
725
726
727 /**************************************************************
728 * TLan_EisaProbe
729 *
730 * Returns: 0 on success, 1 otherwise
731 *
732 * Parms: None
733 *
734 *
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400735 * This functions probes for EISA devices and calls
736 * TLan_probe1 when one is found.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 *
738 *************************************************************/
739
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400740static void __init TLan_EisaProbe (void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741{
742 long ioaddr;
743 int rc = -ENODEV;
744 int irq;
745 u16 device_id;
746
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400747 if (!EISA_bus) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 TLAN_DBG(TLAN_DEBUG_PROBE, "No EISA bus present\n");
749 return;
750 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400751
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 /* Loop through all slots of the EISA bus */
753 for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400754
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700755 TLAN_DBG(TLAN_DEBUG_PROBE,"EISA_ID 0x%4x: 0x%4x\n",
756 (int) ioaddr + 0xC80, inw(ioaddr + EISA_ID));
757 TLAN_DBG(TLAN_DEBUG_PROBE,"EISA_ID 0x%4x: 0x%4x\n",
758 (int) ioaddr + 0xC82, inw(ioaddr + EISA_ID2));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759
760
761 TLAN_DBG(TLAN_DEBUG_PROBE, "Probing for EISA adapter at IO: 0x%4x : ",
762 (int) ioaddr);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400763 if (request_region(ioaddr, 0x10, TLanSignature) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 goto out;
765
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400766 if (inw(ioaddr + EISA_ID) != 0x110E) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767 release_region(ioaddr, 0x10);
768 goto out;
769 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400770
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 device_id = inw(ioaddr + EISA_ID2);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400772 if (device_id != 0x20F1 && device_id != 0x40F1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 release_region (ioaddr, 0x10);
774 goto out;
775 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400776
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 if (inb(ioaddr + EISA_CR) != 0x1) { /* Check if adapter is enabled */
778 release_region (ioaddr, 0x10);
779 goto out2;
780 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400781
782 if (debug == 0x10)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 printk("Found one\n");
784
785
786 /* Get irq from board */
787 switch (inb(ioaddr + 0xCC0)) {
788 case(0x10):
789 irq=5;
790 break;
791 case(0x20):
792 irq=9;
793 break;
794 case(0x40):
795 irq=10;
796 break;
797 case(0x80):
798 irq=11;
799 break;
800 default:
801 goto out;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400802 }
803
804
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 /* Setup the newly found eisa adapter */
806 rc = TLan_probe1( NULL, ioaddr, irq,
807 12, NULL);
808 continue;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400809
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 out:
811 if (debug == 0x10)
812 printk("None found\n");
813 continue;
814
815 out2: if (debug == 0x10)
816 printk("Card found but it is not enabled, skipping\n");
817 continue;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400818
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 }
820
821} /* TLan_EisaProbe */
822
823#ifdef CONFIG_NET_POLL_CONTROLLER
824static void TLan_Poll(struct net_device *dev)
825{
826 disable_irq(dev->irq);
David Howells7d12e782006-10-05 14:55:46 +0100827 TLan_HandleInterrupt(dev->irq, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 enable_irq(dev->irq);
829}
830#endif
831
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400832
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833
834
835 /***************************************************************
836 * TLan_Init
837 *
838 * Returns:
839 * 0 on success, error code otherwise.
840 * Parms:
841 * dev The structure of the device to be
842 * init'ed.
843 *
844 * This function completes the initialization of the
845 * device structure and driver. It reserves the IO
846 * addresses, allocates memory for the lists and bounce
847 * buffers, retrieves the MAC address from the eeprom
848 * and assignes the device's methods.
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400849 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 **************************************************************/
851
852static int TLan_Init( struct net_device *dev )
853{
854 int dma_size;
855 int err;
856 int i;
857 TLanPrivateInfo *priv;
858
859 priv = netdev_priv(dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400860
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 if ( bbuf ) {
862 dma_size = ( TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS )
863 * ( sizeof(TLanList) + TLAN_MAX_FRAME_SIZE );
864 } else {
865 dma_size = ( TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS )
866 * ( sizeof(TLanList) );
867 }
Stephen Hemminger93e16842008-05-30 09:49:55 -0700868 priv->dmaStorage = pci_alloc_consistent(priv->pciDev,
869 dma_size, &priv->dmaStorageDMA);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 priv->dmaSize = dma_size;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400871
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 if ( priv->dmaStorage == NULL ) {
873 printk(KERN_ERR "TLAN: Could not allocate lists and buffers for %s.\n",
874 dev->name );
875 return -ENOMEM;
876 }
877 memset( priv->dmaStorage, 0, dma_size );
Stephen Hemminger93e16842008-05-30 09:49:55 -0700878 priv->rxList = (TLanList *) ALIGN((unsigned long)priv->dmaStorage, 8);
879 priv->rxListDMA = ALIGN(priv->dmaStorageDMA, 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 priv->txList = priv->rxList + TLAN_NUM_RX_LISTS;
881 priv->txListDMA = priv->rxListDMA + sizeof(TLanList) * TLAN_NUM_RX_LISTS;
Stephen Hemminger93e16842008-05-30 09:49:55 -0700882
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 if ( bbuf ) {
884 priv->rxBuffer = (u8 *) ( priv->txList + TLAN_NUM_TX_LISTS );
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700885 priv->rxBufferDMA =priv->txListDMA
886 + sizeof(TLanList) * TLAN_NUM_TX_LISTS;
887 priv->txBuffer = priv->rxBuffer
888 + ( TLAN_NUM_RX_LISTS * TLAN_MAX_FRAME_SIZE );
889 priv->txBufferDMA = priv->rxBufferDMA
890 + ( TLAN_NUM_RX_LISTS * TLAN_MAX_FRAME_SIZE );
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 }
892
893 err = 0;
894 for ( i = 0; i < 6 ; i++ )
895 err |= TLan_EeReadByte( dev,
896 (u8) priv->adapter->addrOfs + i,
897 (u8 *) &dev->dev_addr[i] );
898 if ( err ) {
899 printk(KERN_ERR "TLAN: %s: Error reading MAC from eeprom: %d\n",
900 dev->name,
901 err );
902 }
903 dev->addr_len = 6;
904
905 netif_carrier_off(dev);
906
907 /* Device methods */
908 dev->open = &TLan_Open;
909 dev->hard_start_xmit = &TLan_StartTx;
910 dev->stop = &TLan_Close;
911 dev->get_stats = &TLan_GetStats;
912 dev->set_multicast_list = &TLan_SetMulticastList;
913 dev->do_ioctl = &TLan_ioctl;
914#ifdef CONFIG_NET_POLL_CONTROLLER
915 dev->poll_controller = &TLan_Poll;
916#endif
917 dev->tx_timeout = &TLan_tx_timeout;
918 dev->watchdog_timeo = TX_TIMEOUT;
919
920 return 0;
921
922} /* TLan_Init */
923
924
925
926
927 /***************************************************************
928 * TLan_Open
929 *
930 * Returns:
931 * 0 on success, error code otherwise.
932 * Parms:
933 * dev Structure of device to be opened.
934 *
935 * This routine puts the driver and TLAN adapter in a
936 * state where it is ready to send and receive packets.
937 * It allocates the IRQ, resets and brings the adapter
938 * out of reset, and allows interrupts. It also delays
939 * the startup for autonegotiation or sends a Rx GO
940 * command to the adapter, as appropriate.
941 *
942 **************************************************************/
943
944static int TLan_Open( struct net_device *dev )
945{
946 TLanPrivateInfo *priv = netdev_priv(dev);
947 int err;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400948
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 priv->tlanRev = TLan_DioRead8( dev->base_addr, TLAN_DEF_REVISION );
Stephen Hemmingera3ccc782008-05-30 09:49:57 -0700950 err = request_irq( dev->irq, TLan_HandleInterrupt, IRQF_SHARED,
951 dev->name, dev );
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400952
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 if ( err ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700954 pr_err("TLAN: Cannot open %s because IRQ %d is already in use.\n",
955 dev->name, dev->irq );
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 return err;
957 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400958
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959 init_timer(&priv->timer);
960 netif_start_queue(dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400961
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 /* NOTE: It might not be necessary to read the stats before a
963 reset if you don't care what the values are.
964 */
965 TLan_ResetLists( dev );
966 TLan_ReadAndClearStats( dev, TLAN_IGNORE );
967 TLan_ResetAdapter( dev );
968
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700969 TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Opened. TLAN Chip Rev: %x\n",
970 dev->name, priv->tlanRev );
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971
972 return 0;
973
974} /* TLan_Open */
975
976
977
978 /**************************************************************
979 * TLan_ioctl
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400980 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 * Returns:
982 * 0 on success, error code otherwise
983 * Params:
984 * dev structure of device to receive ioctl.
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400985 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 * rq ifreq structure to hold userspace data.
987 *
988 * cmd ioctl command.
989 *
990 *
991 *************************************************************/
992
993static int TLan_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
994{
995 TLanPrivateInfo *priv = netdev_priv(dev);
996 struct mii_ioctl_data *data = if_mii(rq);
997 u32 phy = priv->phy[priv->phyNum];
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400998
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 if (!priv->phyOnline)
1000 return -EAGAIN;
1001
1002 switch(cmd) {
1003 case SIOCGMIIPHY: /* Get address of MII PHY in use. */
1004 data->phy_id = phy;
1005
1006
1007 case SIOCGMIIREG: /* Read MII PHY register. */
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001008 TLan_MiiReadReg(dev, data->phy_id & 0x1f,
1009 data->reg_num & 0x1f, &data->val_out);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 return 0;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001011
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012
1013 case SIOCSMIIREG: /* Write MII PHY register. */
1014 if (!capable(CAP_NET_ADMIN))
1015 return -EPERM;
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001016 TLan_MiiWriteReg(dev, data->phy_id & 0x1f,
1017 data->reg_num & 0x1f, data->val_in);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 return 0;
1019 default:
1020 return -EOPNOTSUPP;
1021 }
1022} /* tlan_ioctl */
1023
1024
1025 /***************************************************************
1026 * TLan_tx_timeout
1027 *
1028 * Returns: nothing
1029 *
1030 * Params:
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001031 * dev structure of device which timed out
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 * during transmit.
1033 *
1034 **************************************************************/
1035
1036static void TLan_tx_timeout(struct net_device *dev)
1037{
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001038
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Transmit timed out.\n", dev->name);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001040
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 /* Ok so we timed out, lets see what we can do about it...*/
1042 TLan_FreeLists( dev );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001043 TLan_ResetLists( dev );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 TLan_ReadAndClearStats( dev, TLAN_IGNORE );
1045 TLan_ResetAdapter( dev );
1046 dev->trans_start = jiffies;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001047 netif_wake_queue( dev );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048
1049}
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001050
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051
David Howellsc4028952006-11-22 14:57:56 +00001052 /***************************************************************
1053 * TLan_tx_timeout_work
1054 *
1055 * Returns: nothing
1056 *
1057 * Params:
1058 * work work item of device which timed out
1059 *
1060 **************************************************************/
1061
1062static void TLan_tx_timeout_work(struct work_struct *work)
1063{
1064 TLanPrivateInfo *priv =
1065 container_of(work, TLanPrivateInfo, tlan_tqueue);
1066
1067 TLan_tx_timeout(priv->dev);
1068}
1069
1070
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071
1072 /***************************************************************
1073 * TLan_StartTx
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001074 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 * Returns:
1076 * 0 on success, non-zero on failure.
1077 * Parms:
1078 * skb A pointer to the sk_buff containing the
1079 * frame to be sent.
1080 * dev The device to send the data on.
1081 *
1082 * This function adds a frame to the Tx list to be sent
1083 * ASAP. First it verifies that the adapter is ready and
1084 * there is room in the queue. Then it sets up the next
1085 * available list, copies the frame to the corresponding
1086 * buffer. If the adapter Tx channel is idle, it gives
1087 * the adapter a Tx Go command on the list, otherwise it
1088 * sets the forward address of the previous list to point
1089 * to this one. Then it frees the sk_buff.
1090 *
1091 **************************************************************/
1092
1093static int TLan_StartTx( struct sk_buff *skb, struct net_device *dev )
1094{
1095 TLanPrivateInfo *priv = netdev_priv(dev);
1096 TLanList *tail_list;
1097 dma_addr_t tail_list_phys;
1098 u8 *tail_buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 unsigned long flags;
1100
1101 if ( ! priv->phyOnline ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001102 TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT: %s PHY is not ready\n",
1103 dev->name );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 dev_kfree_skb_any(skb);
1105 return 0;
1106 }
1107
Stephen Hemminger41873e92008-05-30 09:49:52 -07001108 if (skb_padto(skb, TLAN_MIN_FRAME_SIZE))
1109 return 0;
1110
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 tail_list = priv->txList + priv->txTail;
1112 tail_list_phys = priv->txListDMA + sizeof(TLanList) * priv->txTail;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001113
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 if ( tail_list->cStat != TLAN_CSTAT_UNUSED ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001115 TLAN_DBG( TLAN_DEBUG_TX,
1116 "TRANSMIT: %s is busy (Head=%d Tail=%d)\n",
1117 dev->name, priv->txHead, priv->txTail );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 netif_stop_queue(dev);
1119 priv->txBusyCount++;
1120 return 1;
1121 }
1122
1123 tail_list->forward = 0;
1124
1125 if ( bbuf ) {
1126 tail_buffer = priv->txBuffer + ( priv->txTail * TLAN_MAX_FRAME_SIZE );
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03001127 skb_copy_from_linear_data(skb, tail_buffer, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 } else {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001129 tail_list->buffer[0].address = pci_map_single(priv->pciDev,
1130 skb->data, skb->len,
1131 PCI_DMA_TODEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 TLan_StoreSKB(tail_list, skb);
1133 }
1134
Stephen Hemminger41873e92008-05-30 09:49:52 -07001135 tail_list->frameSize = (u16) skb->len;
1136 tail_list->buffer[0].count = TLAN_LAST_BUFFER | (u32) skb->len;
1137 tail_list->buffer[1].count = 0;
1138 tail_list->buffer[1].address = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139
1140 spin_lock_irqsave(&priv->lock, flags);
1141 tail_list->cStat = TLAN_CSTAT_READY;
1142 if ( ! priv->txInProgress ) {
1143 priv->txInProgress = 1;
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001144 TLAN_DBG( TLAN_DEBUG_TX,
1145 "TRANSMIT: Starting TX on buffer %d\n", priv->txTail );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 outl( tail_list_phys, dev->base_addr + TLAN_CH_PARM );
1147 outl( TLAN_HC_GO, dev->base_addr + TLAN_HOST_CMD );
1148 } else {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001149 TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT: Adding buffer %d to TX channel\n",
1150 priv->txTail );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 if ( priv->txTail == 0 ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001152 ( priv->txList + ( TLAN_NUM_TX_LISTS - 1 ) )->forward
1153 = tail_list_phys;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 } else {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001155 ( priv->txList + ( priv->txTail - 1 ) )->forward
1156 = tail_list_phys;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 }
1158 }
1159 spin_unlock_irqrestore(&priv->lock, flags);
1160
1161 CIRC_INC( priv->txTail, TLAN_NUM_TX_LISTS );
1162
1163 if ( bbuf )
1164 dev_kfree_skb_any(skb);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001165
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 dev->trans_start = jiffies;
1167 return 0;
1168
1169} /* TLan_StartTx */
1170
1171
1172
1173
1174 /***************************************************************
1175 * TLan_HandleInterrupt
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001176 *
1177 * Returns:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 * Nothing
1179 * Parms:
1180 * irq The line on which the interrupt
1181 * occurred.
1182 * dev_id A pointer to the device assigned to
1183 * this irq line.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 *
1185 * This function handles an interrupt generated by its
1186 * assigned TLAN adapter. The function deactivates
1187 * interrupts on its adapter, records the type of
1188 * interrupt, executes the appropriate subhandler, and
1189 * acknowdges the interrupt to the adapter (thus
1190 * re-enabling adapter interrupts.
1191 *
1192 **************************************************************/
1193
David Howells7d12e782006-10-05 14:55:46 +01001194static irqreturn_t TLan_HandleInterrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195{
Stephen Hemmingera3ccc782008-05-30 09:49:57 -07001196 struct net_device *dev = dev_id;
1197 TLanPrivateInfo *priv = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 u16 host_int;
Stephen Hemmingera3ccc782008-05-30 09:49:57 -07001199 u16 type;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200
1201 spin_lock(&priv->lock);
1202
1203 host_int = inw( dev->base_addr + TLAN_HOST_INT );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 type = ( host_int & TLAN_HI_IT_MASK ) >> 2;
Stephen Hemmingera3ccc782008-05-30 09:49:57 -07001205 if ( type ) {
1206 u32 ack;
1207 u32 host_cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208
Stephen Hemmingera3ccc782008-05-30 09:49:57 -07001209 outw( host_int, dev->base_addr + TLAN_HOST_INT );
1210 ack = TLanIntVector[type]( dev, host_int );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211
Stephen Hemmingera3ccc782008-05-30 09:49:57 -07001212 if ( ack ) {
1213 host_cmd = TLAN_HC_ACK | ack | ( type << 18 );
1214 outl( host_cmd, dev->base_addr + TLAN_HOST_CMD );
1215 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 }
1217
1218 spin_unlock(&priv->lock);
1219
Stephen Hemmingera3ccc782008-05-30 09:49:57 -07001220 return IRQ_RETVAL(type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221} /* TLan_HandleInterrupts */
1222
1223
1224
1225
1226 /***************************************************************
1227 * TLan_Close
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001228 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 * Returns:
1230 * An error code.
1231 * Parms:
1232 * dev The device structure of the device to
1233 * close.
1234 *
1235 * This function shuts down the adapter. It records any
1236 * stats, puts the adapter into reset state, deactivates
1237 * its time as needed, and frees the irq it is using.
1238 *
1239 **************************************************************/
1240
1241static int TLan_Close(struct net_device *dev)
1242{
1243 TLanPrivateInfo *priv = netdev_priv(dev);
1244
1245 netif_stop_queue(dev);
1246 priv->neg_be_verbose = 0;
1247
1248 TLan_ReadAndClearStats( dev, TLAN_RECORD );
1249 outl( TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD );
1250 if ( priv->timer.function != NULL ) {
1251 del_timer_sync( &priv->timer );
1252 priv->timer.function = NULL;
1253 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001254
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 free_irq( dev->irq, dev );
1256 TLan_FreeLists( dev );
1257 TLAN_DBG( TLAN_DEBUG_GNRL, "Device %s closed.\n", dev->name );
1258
1259 return 0;
1260
1261} /* TLan_Close */
1262
1263
1264
1265
1266 /***************************************************************
1267 * TLan_GetStats
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001268 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269 * Returns:
1270 * A pointer to the device's statistics structure.
1271 * Parms:
1272 * dev The device structure to return the
1273 * stats for.
1274 *
1275 * This function updates the devices statistics by reading
1276 * the TLAN chip's onboard registers. Then it returns the
1277 * address of the statistics structure.
1278 *
1279 **************************************************************/
1280
1281static struct net_device_stats *TLan_GetStats( struct net_device *dev )
1282{
1283 TLanPrivateInfo *priv = netdev_priv(dev);
1284 int i;
1285
1286 /* Should only read stats if open ? */
1287 TLan_ReadAndClearStats( dev, TLAN_RECORD );
1288
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001289 TLAN_DBG( TLAN_DEBUG_RX, "RECEIVE: %s EOC count = %d\n", dev->name,
1290 priv->rxEocCount );
1291 TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT: %s Busy count = %d\n", dev->name,
1292 priv->txBusyCount );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 if ( debug & TLAN_DEBUG_GNRL ) {
1294 TLan_PrintDio( dev->base_addr );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001295 TLan_PhyPrint( dev );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 }
1297 if ( debug & TLAN_DEBUG_LIST ) {
1298 for ( i = 0; i < TLAN_NUM_RX_LISTS; i++ )
1299 TLan_PrintList( priv->rxList + i, "RX", i );
1300 for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ )
1301 TLan_PrintList( priv->txList + i, "TX", i );
1302 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001303
Stephen Hemmingerf8f31542008-05-30 09:49:53 -07001304 return &dev->stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305
1306} /* TLan_GetStats */
1307
1308
1309
1310
1311 /***************************************************************
1312 * TLan_SetMulticastList
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001313 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 * Returns:
1315 * Nothing
1316 * Parms:
1317 * dev The device structure to set the
1318 * multicast list for.
1319 *
1320 * This function sets the TLAN adaptor to various receive
1321 * modes. If the IFF_PROMISC flag is set, promiscuous
1322 * mode is acitviated. Otherwise, promiscuous mode is
1323 * turned off. If the IFF_ALLMULTI flag is set, then
1324 * the hash table is set to receive all group addresses.
1325 * Otherwise, the first three multicast addresses are
1326 * stored in AREG_1-3, and the rest are selected via the
1327 * hash table, as necessary.
1328 *
1329 **************************************************************/
1330
1331static void TLan_SetMulticastList( struct net_device *dev )
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001332{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 struct dev_mc_list *dmi = dev->mc_list;
1334 u32 hash1 = 0;
1335 u32 hash2 = 0;
1336 int i;
1337 u32 offset;
1338 u8 tmp;
1339
1340 if ( dev->flags & IFF_PROMISC ) {
1341 tmp = TLan_DioRead8( dev->base_addr, TLAN_NET_CMD );
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001342 TLan_DioWrite8( dev->base_addr,
1343 TLAN_NET_CMD, tmp | TLAN_NET_CMD_CAF );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 } else {
1345 tmp = TLan_DioRead8( dev->base_addr, TLAN_NET_CMD );
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001346 TLan_DioWrite8( dev->base_addr,
1347 TLAN_NET_CMD, tmp & ~TLAN_NET_CMD_CAF );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 if ( dev->flags & IFF_ALLMULTI ) {
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001349 for ( i = 0; i < 3; i++ )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 TLan_SetMac( dev, i + 1, NULL );
1351 TLan_DioWrite32( dev->base_addr, TLAN_HASH_1, 0xFFFFFFFF );
1352 TLan_DioWrite32( dev->base_addr, TLAN_HASH_2, 0xFFFFFFFF );
1353 } else {
1354 for ( i = 0; i < dev->mc_count; i++ ) {
1355 if ( i < 3 ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001356 TLan_SetMac( dev, i + 1,
1357 (char *) &dmi->dmi_addr );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 } else {
1359 offset = TLan_HashFunc( (u8 *) &dmi->dmi_addr );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001360 if ( offset < 32 )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 hash1 |= ( 1 << offset );
1362 else
1363 hash2 |= ( 1 << ( offset - 32 ) );
1364 }
1365 dmi = dmi->next;
1366 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001367 for ( ; i < 3; i++ )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368 TLan_SetMac( dev, i + 1, NULL );
1369 TLan_DioWrite32( dev->base_addr, TLAN_HASH_1, hash1 );
1370 TLan_DioWrite32( dev->base_addr, TLAN_HASH_2, hash2 );
1371 }
1372 }
1373
1374} /* TLan_SetMulticastList */
1375
1376
1377
1378/*****************************************************************************
1379******************************************************************************
1380
1381 ThunderLAN Driver Interrupt Vectors and Table
1382
1383 Please see Chap. 4, "Interrupt Handling" of the "ThunderLAN
1384 Programmer's Guide" for more informations on handling interrupts
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001385 generated by TLAN based adapters.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
1387******************************************************************************
1388*****************************************************************************/
1389
1390
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391
1392
1393 /***************************************************************
1394 * TLan_HandleTxEOF
1395 *
1396 * Returns:
1397 * 1
1398 * Parms:
1399 * dev Device assigned the IRQ that was
1400 * raised.
1401 * host_int The contents of the HOST_INT
1402 * port.
1403 *
1404 * This function handles Tx EOF interrupts which are raised
1405 * by the adapter when it has completed sending the
1406 * contents of a buffer. If detemines which list/buffer
1407 * was completed and resets it. If the buffer was the last
1408 * in the channel (EOC), then the function checks to see if
1409 * another buffer is ready to send, and if so, sends a Tx
1410 * Go command. Finally, the driver activates/continues the
1411 * activity LED.
1412 *
1413 **************************************************************/
1414
Harvey Harrison98e0f522008-02-18 10:04:38 -08001415static u32 TLan_HandleTxEOF( struct net_device *dev, u16 host_int )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416{
1417 TLanPrivateInfo *priv = netdev_priv(dev);
1418 int eoc = 0;
1419 TLanList *head_list;
1420 dma_addr_t head_list_phys;
1421 u32 ack = 0;
1422 u16 tmpCStat;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001423
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001424 TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT: Handling TX EOF (Head=%d Tail=%d)\n",
1425 priv->txHead, priv->txTail );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 head_list = priv->txList + priv->txHead;
1427
1428 while (((tmpCStat = head_list->cStat ) & TLAN_CSTAT_FRM_CMP) && (ack < 255)) {
1429 ack++;
1430 if ( ! bbuf ) {
1431 struct sk_buff *skb = TLan_GetSKB(head_list);
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001432 pci_unmap_single(priv->pciDev, head_list->buffer[0].address,
1433 skb->len, PCI_DMA_TODEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 dev_kfree_skb_any(skb);
1435 head_list->buffer[8].address = 0;
1436 head_list->buffer[9].address = 0;
1437 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001438
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 if ( tmpCStat & TLAN_CSTAT_EOC )
1440 eoc = 1;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001441
Stephen Hemmingerf8f31542008-05-30 09:49:53 -07001442 dev->stats.tx_bytes += head_list->frameSize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443
1444 head_list->cStat = TLAN_CSTAT_UNUSED;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001445 netif_start_queue(dev);
1446 CIRC_INC( priv->txHead, TLAN_NUM_TX_LISTS );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 head_list = priv->txList + priv->txHead;
1448 }
1449
1450 if (!ack)
1451 printk(KERN_INFO "TLAN: Received interrupt for uncompleted TX frame.\n");
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001452
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 if ( eoc ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001454 TLAN_DBG( TLAN_DEBUG_TX,
1455 "TRANSMIT: Handling TX EOC (Head=%d Tail=%d)\n",
1456 priv->txHead, priv->txTail );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 head_list = priv->txList + priv->txHead;
1458 head_list_phys = priv->txListDMA + sizeof(TLanList) * priv->txHead;
1459 if ( ( head_list->cStat & TLAN_CSTAT_READY ) == TLAN_CSTAT_READY ) {
1460 outl(head_list_phys, dev->base_addr + TLAN_CH_PARM );
1461 ack |= TLAN_HC_GO;
1462 } else {
1463 priv->txInProgress = 0;
1464 }
1465 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001466
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 if ( priv->adapter->flags & TLAN_ADAPTER_ACTIVITY_LED ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001468 TLan_DioWrite8( dev->base_addr,
1469 TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 if ( priv->timer.function == NULL ) {
1471 priv->timer.function = &TLan_Timer;
1472 priv->timer.data = (unsigned long) dev;
1473 priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY;
1474 priv->timerSetAt = jiffies;
1475 priv->timerType = TLAN_TIMER_ACTIVITY;
1476 add_timer(&priv->timer);
1477 } else if ( priv->timerType == TLAN_TIMER_ACTIVITY ) {
1478 priv->timerSetAt = jiffies;
1479 }
1480 }
1481
1482 return ack;
1483
1484} /* TLan_HandleTxEOF */
1485
1486
1487
1488
1489 /***************************************************************
1490 * TLan_HandleStatOverflow
1491 *
1492 * Returns:
1493 * 1
1494 * Parms:
1495 * dev Device assigned the IRQ that was
1496 * raised.
1497 * host_int The contents of the HOST_INT
1498 * port.
1499 *
1500 * This function handles the Statistics Overflow interrupt
1501 * which means that one or more of the TLAN statistics
1502 * registers has reached 1/2 capacity and needs to be read.
1503 *
1504 **************************************************************/
1505
Harvey Harrison98e0f522008-02-18 10:04:38 -08001506static u32 TLan_HandleStatOverflow( struct net_device *dev, u16 host_int )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507{
1508 TLan_ReadAndClearStats( dev, TLAN_RECORD );
1509
1510 return 1;
1511
1512} /* TLan_HandleStatOverflow */
1513
1514
1515
1516
1517 /***************************************************************
1518 * TLan_HandleRxEOF
1519 *
1520 * Returns:
1521 * 1
1522 * Parms:
1523 * dev Device assigned the IRQ that was
1524 * raised.
1525 * host_int The contents of the HOST_INT
1526 * port.
1527 *
1528 * This function handles the Rx EOF interrupt which
1529 * indicates a frame has been received by the adapter from
1530 * the net and the frame has been transferred to memory.
1531 * The function determines the bounce buffer the frame has
1532 * been loaded into, creates a new sk_buff big enough to
1533 * hold the frame, and sends it to protocol stack. It
1534 * then resets the used buffer and appends it to the end
1535 * of the list. If the frame was the last in the Rx
1536 * channel (EOC), the function restarts the receive channel
1537 * by sending an Rx Go command to the adapter. Then it
1538 * activates/continues the activity LED.
1539 *
1540 **************************************************************/
1541
Harvey Harrison98e0f522008-02-18 10:04:38 -08001542static u32 TLan_HandleRxEOF( struct net_device *dev, u16 host_int )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543{
1544 TLanPrivateInfo *priv = netdev_priv(dev);
1545 u32 ack = 0;
1546 int eoc = 0;
1547 u8 *head_buffer;
1548 TLanList *head_list;
1549 struct sk_buff *skb;
1550 TLanList *tail_list;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551 u16 tmpCStat;
1552 dma_addr_t head_list_phys;
1553
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001554 TLAN_DBG( TLAN_DEBUG_RX, "RECEIVE: Handling RX EOF (Head=%d Tail=%d)\n",
1555 priv->rxHead, priv->rxTail );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 head_list = priv->rxList + priv->rxHead;
1557 head_list_phys = priv->rxListDMA + sizeof(TLanList) * priv->rxHead;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001558
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 while (((tmpCStat = head_list->cStat) & TLAN_CSTAT_FRM_CMP) && (ack < 255)) {
Stephen Hemminger9ded65a2008-05-30 09:49:56 -07001560 dma_addr_t frameDma = head_list->buffer[0].address;
1561 u32 frameSize = head_list->frameSize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 ack++;
1563 if (tmpCStat & TLAN_CSTAT_EOC)
1564 eoc = 1;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001565
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 if (bbuf) {
Stephen Hemminger9ded65a2008-05-30 09:49:56 -07001567 skb = netdev_alloc_skb(dev, frameSize + 7);
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001568 if ( !skb )
1569 goto drop_and_reuse;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001570
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001571 head_buffer = priv->rxBuffer
1572 + (priv->rxHead * TLAN_MAX_FRAME_SIZE);
1573 skb_reserve(skb, 2);
1574 pci_dma_sync_single_for_cpu(priv->pciDev,
1575 frameDma, frameSize,
1576 PCI_DMA_FROMDEVICE);
1577 skb_copy_from_linear_data(skb, head_buffer, frameSize);
1578 skb_put(skb, frameSize);
1579 dev->stats.rx_bytes += frameSize;
1580
1581 skb->protocol = eth_type_trans( skb, dev );
1582 netif_rx( skb );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583 } else {
1584 struct sk_buff *new_skb;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001585
Stephen Hemminger9ded65a2008-05-30 09:49:56 -07001586 new_skb = netdev_alloc_skb(dev, TLAN_MAX_FRAME_SIZE + 7 );
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001587 if ( !new_skb )
1588 goto drop_and_reuse;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001590 skb = TLan_GetSKB(head_list);
1591 pci_unmap_single(priv->pciDev, frameDma,
1592 TLAN_MAX_FRAME_SIZE, PCI_DMA_FROMDEVICE);
1593 skb_put( skb, frameSize );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001595 dev->stats.rx_bytes += frameSize;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001596
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001597 skb->protocol = eth_type_trans( skb, dev );
1598 netif_rx( skb );
Stephen Hemminger93e16842008-05-30 09:49:55 -07001599
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001600 skb_reserve( new_skb, NET_IP_ALIGN );
1601 head_list->buffer[0].address = pci_map_single(priv->pciDev,
1602 new_skb->data,
1603 TLAN_MAX_FRAME_SIZE,
1604 PCI_DMA_FROMDEVICE);
1605
1606 TLan_StoreSKB(head_list, new_skb);
Stephen Hemminger9ded65a2008-05-30 09:49:56 -07001607
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 }
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001609drop_and_reuse:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 head_list->forward = 0;
1611 head_list->cStat = 0;
1612 tail_list = priv->rxList + priv->rxTail;
1613 tail_list->forward = head_list_phys;
1614
1615 CIRC_INC( priv->rxHead, TLAN_NUM_RX_LISTS );
1616 CIRC_INC( priv->rxTail, TLAN_NUM_RX_LISTS );
1617 head_list = priv->rxList + priv->rxHead;
1618 head_list_phys = priv->rxListDMA + sizeof(TLanList) * priv->rxHead;
1619 }
1620
1621 if (!ack)
1622 printk(KERN_INFO "TLAN: Received interrupt for uncompleted RX frame.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623
1624
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001625 if ( eoc ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001626 TLAN_DBG( TLAN_DEBUG_RX,
1627 "RECEIVE: Handling RX EOC (Head=%d Tail=%d)\n",
1628 priv->rxHead, priv->rxTail );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 head_list = priv->rxList + priv->rxHead;
1630 head_list_phys = priv->rxListDMA + sizeof(TLanList) * priv->rxHead;
1631 outl(head_list_phys, dev->base_addr + TLAN_CH_PARM );
1632 ack |= TLAN_HC_GO | TLAN_HC_RT;
1633 priv->rxEocCount++;
1634 }
1635
1636 if ( priv->adapter->flags & TLAN_ADAPTER_ACTIVITY_LED ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001637 TLan_DioWrite8( dev->base_addr,
1638 TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 if ( priv->timer.function == NULL ) {
1640 priv->timer.function = &TLan_Timer;
1641 priv->timer.data = (unsigned long) dev;
1642 priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY;
1643 priv->timerSetAt = jiffies;
1644 priv->timerType = TLAN_TIMER_ACTIVITY;
1645 add_timer(&priv->timer);
1646 } else if ( priv->timerType == TLAN_TIMER_ACTIVITY ) {
1647 priv->timerSetAt = jiffies;
1648 }
1649 }
1650
1651 dev->last_rx = jiffies;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001652
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653 return ack;
1654
1655} /* TLan_HandleRxEOF */
1656
1657
1658
1659
1660 /***************************************************************
1661 * TLan_HandleDummy
1662 *
1663 * Returns:
1664 * 1
1665 * Parms:
1666 * dev Device assigned the IRQ that was
1667 * raised.
1668 * host_int The contents of the HOST_INT
1669 * port.
1670 *
1671 * This function handles the Dummy interrupt, which is
1672 * raised whenever a test interrupt is generated by setting
1673 * the Req_Int bit of HOST_CMD to 1.
1674 *
1675 **************************************************************/
1676
Harvey Harrison98e0f522008-02-18 10:04:38 -08001677static u32 TLan_HandleDummy( struct net_device *dev, u16 host_int )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678{
1679 printk( "TLAN: Test interrupt on %s.\n", dev->name );
1680 return 1;
1681
1682} /* TLan_HandleDummy */
1683
1684
1685
1686
1687 /***************************************************************
1688 * TLan_HandleTxEOC
1689 *
1690 * Returns:
1691 * 1
1692 * Parms:
1693 * dev Device assigned the IRQ that was
1694 * raised.
1695 * host_int The contents of the HOST_INT
1696 * port.
1697 *
1698 * This driver is structured to determine EOC occurrences by
1699 * reading the CSTAT member of the list structure. Tx EOC
1700 * interrupts are disabled via the DIO INTDIS register.
1701 * However, TLAN chips before revision 3.0 didn't have this
1702 * functionality, so process EOC events if this is the
1703 * case.
1704 *
1705 **************************************************************/
1706
Harvey Harrison98e0f522008-02-18 10:04:38 -08001707static u32 TLan_HandleTxEOC( struct net_device *dev, u16 host_int )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708{
1709 TLanPrivateInfo *priv = netdev_priv(dev);
1710 TLanList *head_list;
1711 dma_addr_t head_list_phys;
1712 u32 ack = 1;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001713
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714 host_int = 0;
1715 if ( priv->tlanRev < 0x30 ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001716 TLAN_DBG( TLAN_DEBUG_TX,
1717 "TRANSMIT: Handling TX EOC (Head=%d Tail=%d) -- IRQ\n",
1718 priv->txHead, priv->txTail );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 head_list = priv->txList + priv->txHead;
1720 head_list_phys = priv->txListDMA + sizeof(TLanList) * priv->txHead;
1721 if ( ( head_list->cStat & TLAN_CSTAT_READY ) == TLAN_CSTAT_READY ) {
1722 netif_stop_queue(dev);
1723 outl( head_list_phys, dev->base_addr + TLAN_CH_PARM );
1724 ack |= TLAN_HC_GO;
1725 } else {
1726 priv->txInProgress = 0;
1727 }
1728 }
1729
1730 return ack;
1731
1732} /* TLan_HandleTxEOC */
1733
1734
1735
1736
1737 /***************************************************************
1738 * TLan_HandleStatusCheck
1739 *
1740 * Returns:
1741 * 0 if Adapter check, 1 if Network Status check.
1742 * Parms:
1743 * dev Device assigned the IRQ that was
1744 * raised.
1745 * host_int The contents of the HOST_INT
1746 * port.
1747 *
1748 * This function handles Adapter Check/Network Status
1749 * interrupts generated by the adapter. It checks the
1750 * vector in the HOST_INT register to determine if it is
1751 * an Adapter Check interrupt. If so, it resets the
1752 * adapter. Otherwise it clears the status registers
1753 * and services the PHY.
1754 *
1755 **************************************************************/
1756
Harvey Harrison98e0f522008-02-18 10:04:38 -08001757static u32 TLan_HandleStatusCheck( struct net_device *dev, u16 host_int )
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001758{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 TLanPrivateInfo *priv = netdev_priv(dev);
1760 u32 ack;
1761 u32 error;
1762 u8 net_sts;
1763 u32 phy;
1764 u16 tlphy_ctl;
1765 u16 tlphy_sts;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001766
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767 ack = 1;
1768 if ( host_int & TLAN_HI_IV_MASK ) {
1769 netif_stop_queue( dev );
1770 error = inl( dev->base_addr + TLAN_CH_PARM );
1771 printk( "TLAN: %s: Adaptor Error = 0x%x\n", dev->name, error );
1772 TLan_ReadAndClearStats( dev, TLAN_RECORD );
1773 outl( TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD );
1774
1775 schedule_work(&priv->tlan_tqueue);
1776
1777 netif_wake_queue(dev);
1778 ack = 0;
1779 } else {
1780 TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Status Check\n", dev->name );
1781 phy = priv->phy[priv->phyNum];
1782
1783 net_sts = TLan_DioRead8( dev->base_addr, TLAN_NET_STS );
1784 if ( net_sts ) {
1785 TLan_DioWrite8( dev->base_addr, TLAN_NET_STS, net_sts );
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001786 TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Net_Sts = %x\n",
1787 dev->name, (unsigned) net_sts );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788 }
1789 if ( ( net_sts & TLAN_NET_STS_MIRQ ) && ( priv->phyNum == 0 ) ) {
1790 TLan_MiiReadReg( dev, phy, TLAN_TLPHY_STS, &tlphy_sts );
1791 TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tlphy_ctl );
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001792 if ( ! ( tlphy_sts & TLAN_TS_POLOK ) &&
1793 ! ( tlphy_ctl & TLAN_TC_SWAPOL ) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794 tlphy_ctl |= TLAN_TC_SWAPOL;
1795 TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tlphy_ctl);
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001796 } else if ( ( tlphy_sts & TLAN_TS_POLOK )
1797 && ( tlphy_ctl & TLAN_TC_SWAPOL ) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798 tlphy_ctl &= ~TLAN_TC_SWAPOL;
1799 TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tlphy_ctl);
1800 }
1801
1802 if (debug) {
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001803 TLan_PhyPrint( dev );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804 }
1805 }
1806 }
1807
1808 return ack;
1809
1810} /* TLan_HandleStatusCheck */
1811
1812
1813
1814
1815 /***************************************************************
1816 * TLan_HandleRxEOC
1817 *
1818 * Returns:
1819 * 1
1820 * Parms:
1821 * dev Device assigned the IRQ that was
1822 * raised.
1823 * host_int The contents of the HOST_INT
1824 * port.
1825 *
1826 * This driver is structured to determine EOC occurrences by
1827 * reading the CSTAT member of the list structure. Rx EOC
1828 * interrupts are disabled via the DIO INTDIS register.
1829 * However, TLAN chips before revision 3.0 didn't have this
1830 * CSTAT member or a INTDIS register, so if this chip is
1831 * pre-3.0, process EOC interrupts normally.
1832 *
1833 **************************************************************/
1834
Harvey Harrison98e0f522008-02-18 10:04:38 -08001835static u32 TLan_HandleRxEOC( struct net_device *dev, u16 host_int )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836{
1837 TLanPrivateInfo *priv = netdev_priv(dev);
1838 dma_addr_t head_list_phys;
1839 u32 ack = 1;
1840
1841 if ( priv->tlanRev < 0x30 ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001842 TLAN_DBG( TLAN_DEBUG_RX,
1843 "RECEIVE: Handling RX EOC (Head=%d Tail=%d) -- IRQ\n",
1844 priv->rxHead, priv->rxTail );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845 head_list_phys = priv->rxListDMA + sizeof(TLanList) * priv->rxHead;
1846 outl( head_list_phys, dev->base_addr + TLAN_CH_PARM );
1847 ack |= TLAN_HC_GO | TLAN_HC_RT;
1848 priv->rxEocCount++;
1849 }
1850
1851 return ack;
1852
1853} /* TLan_HandleRxEOC */
1854
1855
1856
1857
1858/*****************************************************************************
1859******************************************************************************
1860
1861 ThunderLAN Driver Timer Function
1862
1863******************************************************************************
1864*****************************************************************************/
1865
1866
1867 /***************************************************************
1868 * TLan_Timer
1869 *
1870 * Returns:
1871 * Nothing
1872 * Parms:
1873 * data A value given to add timer when
1874 * add_timer was called.
1875 *
1876 * This function handles timed functionality for the
1877 * TLAN driver. The two current timer uses are for
1878 * delaying for autonegotionation and driving the ACT LED.
1879 * - Autonegotiation requires being allowed about
1880 * 2 1/2 seconds before attempting to transmit a
1881 * packet. It would be a very bad thing to hang
1882 * the kernel this long, so the driver doesn't
1883 * allow transmission 'til after this time, for
1884 * certain PHYs. It would be much nicer if all
1885 * PHYs were interrupt-capable like the internal
1886 * PHY.
1887 * - The ACT LED, which shows adapter activity, is
1888 * driven by the driver, and so must be left on
1889 * for a short period to power up the LED so it
1890 * can be seen. This delay can be changed by
1891 * changing the TLAN_TIMER_ACT_DELAY in tlan.h,
1892 * if desired. 100 ms produces a slightly
1893 * sluggish response.
1894 *
1895 **************************************************************/
1896
Harvey Harrison98e0f522008-02-18 10:04:38 -08001897static void TLan_Timer( unsigned long data )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898{
1899 struct net_device *dev = (struct net_device *) data;
1900 TLanPrivateInfo *priv = netdev_priv(dev);
1901 u32 elapsed;
1902 unsigned long flags = 0;
1903
1904 priv->timer.function = NULL;
1905
1906 switch ( priv->timerType ) {
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001907#ifdef MONITOR
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908 case TLAN_TIMER_LINK_BEAT:
1909 TLan_PhyMonitor( dev );
1910 break;
1911#endif
1912 case TLAN_TIMER_PHY_PDOWN:
1913 TLan_PhyPowerDown( dev );
1914 break;
1915 case TLAN_TIMER_PHY_PUP:
1916 TLan_PhyPowerUp( dev );
1917 break;
1918 case TLAN_TIMER_PHY_RESET:
1919 TLan_PhyReset( dev );
1920 break;
1921 case TLAN_TIMER_PHY_START_LINK:
1922 TLan_PhyStartLink( dev );
1923 break;
1924 case TLAN_TIMER_PHY_FINISH_AN:
1925 TLan_PhyFinishAutoNeg( dev );
1926 break;
1927 case TLAN_TIMER_FINISH_RESET:
1928 TLan_FinishReset( dev );
1929 break;
1930 case TLAN_TIMER_ACTIVITY:
1931 spin_lock_irqsave(&priv->lock, flags);
1932 if ( priv->timer.function == NULL ) {
1933 elapsed = jiffies - priv->timerSetAt;
1934 if ( elapsed >= TLAN_TIMER_ACT_DELAY ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001935 TLan_DioWrite8( dev->base_addr,
1936 TLAN_LED_REG, TLAN_LED_LINK );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937 } else {
1938 priv->timer.function = &TLan_Timer;
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001939 priv->timer.expires = priv->timerSetAt
1940 + TLAN_TIMER_ACT_DELAY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941 spin_unlock_irqrestore(&priv->lock, flags);
1942 add_timer( &priv->timer );
1943 break;
1944 }
1945 }
1946 spin_unlock_irqrestore(&priv->lock, flags);
1947 break;
1948 default:
1949 break;
1950 }
1951
1952} /* TLan_Timer */
1953
1954
1955
1956
1957/*****************************************************************************
1958******************************************************************************
1959
1960 ThunderLAN Driver Adapter Related Routines
1961
1962******************************************************************************
1963*****************************************************************************/
1964
1965
1966 /***************************************************************
1967 * TLan_ResetLists
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001968 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 * Returns:
1970 * Nothing
1971 * Parms:
1972 * dev The device structure with the list
1973 * stuctures to be reset.
1974 *
1975 * This routine sets the variables associated with managing
1976 * the TLAN lists to their initial values.
1977 *
1978 **************************************************************/
1979
Harvey Harrison98e0f522008-02-18 10:04:38 -08001980static void TLan_ResetLists( struct net_device *dev )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981{
1982 TLanPrivateInfo *priv = netdev_priv(dev);
1983 int i;
1984 TLanList *list;
1985 dma_addr_t list_phys;
1986 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987
1988 priv->txHead = 0;
1989 priv->txTail = 0;
1990 for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ ) {
1991 list = priv->txList + i;
1992 list->cStat = TLAN_CSTAT_UNUSED;
1993 if ( bbuf ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001994 list->buffer[0].address = priv->txBufferDMA
1995 + ( i * TLAN_MAX_FRAME_SIZE );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996 } else {
1997 list->buffer[0].address = 0;
1998 }
1999 list->buffer[2].count = 0;
2000 list->buffer[2].address = 0;
2001 list->buffer[8].address = 0;
2002 list->buffer[9].address = 0;
2003 }
2004
2005 priv->rxHead = 0;
2006 priv->rxTail = TLAN_NUM_RX_LISTS - 1;
2007 for ( i = 0; i < TLAN_NUM_RX_LISTS; i++ ) {
2008 list = priv->rxList + i;
2009 list_phys = priv->rxListDMA + sizeof(TLanList) * i;
2010 list->cStat = TLAN_CSTAT_READY;
2011 list->frameSize = TLAN_MAX_FRAME_SIZE;
2012 list->buffer[0].count = TLAN_MAX_FRAME_SIZE | TLAN_LAST_BUFFER;
2013 if ( bbuf ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002014 list->buffer[0].address = priv->rxBufferDMA
2015 + ( i * TLAN_MAX_FRAME_SIZE );
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016 } else {
Stephen Hemminger9ded65a2008-05-30 09:49:56 -07002017 skb = netdev_alloc_skb(dev, TLAN_MAX_FRAME_SIZE + 7 );
2018 if ( !skb ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002019 pr_err("TLAN: out of memory for received data.\n" );
Stephen Hemminger9ded65a2008-05-30 09:49:56 -07002020 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021 }
Stephen Hemminger9ded65a2008-05-30 09:49:56 -07002022
2023 skb_reserve( skb, NET_IP_ALIGN );
Robert Fitzsimons0d63bea2008-08-09 17:54:02 +01002024 list->buffer[0].address = pci_map_single(priv->pciDev,
2025 skb->data,
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002026 TLAN_MAX_FRAME_SIZE,
2027 PCI_DMA_FROMDEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028 TLan_StoreSKB(list, skb);
2029 }
2030 list->buffer[1].count = 0;
2031 list->buffer[1].address = 0;
Stephen Hemminger9ded65a2008-05-30 09:49:56 -07002032 list->forward = list_phys + sizeof(TLanList);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 }
2034
Stephen Hemminger9ded65a2008-05-30 09:49:56 -07002035 /* in case ran out of memory early, clear bits */
2036 while (i < TLAN_NUM_RX_LISTS) {
2037 TLan_StoreSKB(priv->rxList + i, NULL);
2038 ++i;
2039 }
2040 list->forward = 0;
2041
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042} /* TLan_ResetLists */
2043
2044
Harvey Harrison98e0f522008-02-18 10:04:38 -08002045static void TLan_FreeLists( struct net_device *dev )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046{
2047 TLanPrivateInfo *priv = netdev_priv(dev);
2048 int i;
2049 TLanList *list;
2050 struct sk_buff *skb;
2051
2052 if ( ! bbuf ) {
2053 for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ ) {
2054 list = priv->txList + i;
2055 skb = TLan_GetSKB(list);
2056 if ( skb ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002057 pci_unmap_single(priv->pciDev,
2058 list->buffer[0].address, skb->len,
2059 PCI_DMA_TODEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060 dev_kfree_skb_any( skb );
2061 list->buffer[8].address = 0;
2062 list->buffer[9].address = 0;
2063 }
2064 }
2065
2066 for ( i = 0; i < TLAN_NUM_RX_LISTS; i++ ) {
2067 list = priv->rxList + i;
2068 skb = TLan_GetSKB(list);
2069 if ( skb ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002070 pci_unmap_single(priv->pciDev,
2071 list->buffer[0].address,
2072 TLAN_MAX_FRAME_SIZE,
2073 PCI_DMA_FROMDEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 dev_kfree_skb_any( skb );
2075 list->buffer[8].address = 0;
2076 list->buffer[9].address = 0;
2077 }
2078 }
2079 }
2080} /* TLan_FreeLists */
2081
2082
2083
2084
2085 /***************************************************************
2086 * TLan_PrintDio
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002087 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088 * Returns:
2089 * Nothing
2090 * Parms:
2091 * io_base Base IO port of the device of
2092 * which to print DIO registers.
2093 *
2094 * This function prints out all the internal (DIO)
2095 * registers of a TLAN chip.
2096 *
2097 **************************************************************/
2098
Harvey Harrison98e0f522008-02-18 10:04:38 -08002099static void TLan_PrintDio( u16 io_base )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100{
2101 u32 data0, data1;
2102 int i;
2103
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002104 printk( "TLAN: Contents of internal registers for io base 0x%04hx.\n",
2105 io_base );
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 printk( "TLAN: Off. +0 +4\n" );
2107 for ( i = 0; i < 0x4C; i+= 8 ) {
2108 data0 = TLan_DioRead32( io_base, i );
2109 data1 = TLan_DioRead32( io_base, i + 0x4 );
2110 printk( "TLAN: 0x%02x 0x%08x 0x%08x\n", i, data0, data1 );
2111 }
2112
2113} /* TLan_PrintDio */
2114
2115
2116
2117
2118 /***************************************************************
2119 * TLan_PrintList
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002120 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 * Returns:
2122 * Nothing
2123 * Parms:
2124 * list A pointer to the TLanList structure to
2125 * be printed.
2126 * type A string to designate type of list,
2127 * "Rx" or "Tx".
2128 * num The index of the list.
2129 *
2130 * This function prints out the contents of the list
2131 * pointed to by the list parameter.
2132 *
2133 **************************************************************/
2134
Harvey Harrison98e0f522008-02-18 10:04:38 -08002135static void TLan_PrintList( TLanList *list, char *type, int num)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136{
2137 int i;
2138
Stephen Hemminger93e16842008-05-30 09:49:55 -07002139 printk( "TLAN: %s List %d at %p\n", type, num, list );
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140 printk( "TLAN: Forward = 0x%08x\n", list->forward );
2141 printk( "TLAN: CSTAT = 0x%04hx\n", list->cStat );
2142 printk( "TLAN: Frame Size = 0x%04hx\n", list->frameSize );
2143 /* for ( i = 0; i < 10; i++ ) { */
2144 for ( i = 0; i < 2; i++ ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002145 printk( "TLAN: Buffer[%d].count, addr = 0x%08x, 0x%08x\n",
2146 i, list->buffer[i].count, list->buffer[i].address );
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147 }
2148
2149} /* TLan_PrintList */
2150
2151
2152
2153
2154 /***************************************************************
2155 * TLan_ReadAndClearStats
2156 *
2157 * Returns:
2158 * Nothing
2159 * Parms:
2160 * dev Pointer to device structure of adapter
2161 * to which to read stats.
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002162 * record Flag indicating whether to add
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 *
2164 * This functions reads all the internal status registers
2165 * of the TLAN chip, which clears them as a side effect.
2166 * It then either adds the values to the device's status
2167 * struct, or discards them, depending on whether record
2168 * is TLAN_RECORD (!=0) or TLAN_IGNORE (==0).
2169 *
2170 **************************************************************/
2171
Harvey Harrison98e0f522008-02-18 10:04:38 -08002172static void TLan_ReadAndClearStats( struct net_device *dev, int record )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174 u32 tx_good, tx_under;
2175 u32 rx_good, rx_over;
2176 u32 def_tx, crc, code;
2177 u32 multi_col, single_col;
2178 u32 excess_col, late_col, loss;
2179
2180 outw( TLAN_GOOD_TX_FRMS, dev->base_addr + TLAN_DIO_ADR );
2181 tx_good = inb( dev->base_addr + TLAN_DIO_DATA );
2182 tx_good += inb( dev->base_addr + TLAN_DIO_DATA + 1 ) << 8;
2183 tx_good += inb( dev->base_addr + TLAN_DIO_DATA + 2 ) << 16;
2184 tx_under = inb( dev->base_addr + TLAN_DIO_DATA + 3 );
2185
2186 outw( TLAN_GOOD_RX_FRMS, dev->base_addr + TLAN_DIO_ADR );
2187 rx_good = inb( dev->base_addr + TLAN_DIO_DATA );
2188 rx_good += inb( dev->base_addr + TLAN_DIO_DATA + 1 ) << 8;
2189 rx_good += inb( dev->base_addr + TLAN_DIO_DATA + 2 ) << 16;
2190 rx_over = inb( dev->base_addr + TLAN_DIO_DATA + 3 );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002191
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 outw( TLAN_DEFERRED_TX, dev->base_addr + TLAN_DIO_ADR );
2193 def_tx = inb( dev->base_addr + TLAN_DIO_DATA );
2194 def_tx += inb( dev->base_addr + TLAN_DIO_DATA + 1 ) << 8;
2195 crc = inb( dev->base_addr + TLAN_DIO_DATA + 2 );
2196 code = inb( dev->base_addr + TLAN_DIO_DATA + 3 );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002197
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 outw( TLAN_MULTICOL_FRMS, dev->base_addr + TLAN_DIO_ADR );
2199 multi_col = inb( dev->base_addr + TLAN_DIO_DATA );
2200 multi_col += inb( dev->base_addr + TLAN_DIO_DATA + 1 ) << 8;
2201 single_col = inb( dev->base_addr + TLAN_DIO_DATA + 2 );
2202 single_col += inb( dev->base_addr + TLAN_DIO_DATA + 3 ) << 8;
2203
2204 outw( TLAN_EXCESSCOL_FRMS, dev->base_addr + TLAN_DIO_ADR );
2205 excess_col = inb( dev->base_addr + TLAN_DIO_DATA );
2206 late_col = inb( dev->base_addr + TLAN_DIO_DATA + 1 );
2207 loss = inb( dev->base_addr + TLAN_DIO_DATA + 2 );
2208
2209 if ( record ) {
Stephen Hemmingerf8f31542008-05-30 09:49:53 -07002210 dev->stats.rx_packets += rx_good;
2211 dev->stats.rx_errors += rx_over + crc + code;
2212 dev->stats.tx_packets += tx_good;
2213 dev->stats.tx_errors += tx_under + loss;
2214 dev->stats.collisions += multi_col + single_col + excess_col + late_col;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215
Stephen Hemmingerf8f31542008-05-30 09:49:53 -07002216 dev->stats.rx_over_errors += rx_over;
2217 dev->stats.rx_crc_errors += crc;
2218 dev->stats.rx_frame_errors += code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219
Stephen Hemmingerf8f31542008-05-30 09:49:53 -07002220 dev->stats.tx_aborted_errors += tx_under;
2221 dev->stats.tx_carrier_errors += loss;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002223
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224} /* TLan_ReadAndClearStats */
2225
2226
2227
2228
2229 /***************************************************************
2230 * TLan_Reset
2231 *
2232 * Returns:
2233 * 0
2234 * Parms:
2235 * dev Pointer to device structure of adapter
2236 * to be reset.
2237 *
2238 * This function resets the adapter and it's physical
2239 * device. See Chap. 3, pp. 9-10 of the "ThunderLAN
2240 * Programmer's Guide" for details. The routine tries to
2241 * implement what is detailed there, though adjustments
2242 * have been made.
2243 *
2244 **************************************************************/
2245
Harvey Harrison98e0f522008-02-18 10:04:38 -08002246static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247TLan_ResetAdapter( struct net_device *dev )
2248{
2249 TLanPrivateInfo *priv = netdev_priv(dev);
2250 int i;
2251 u32 addr;
2252 u32 data;
2253 u8 data8;
2254
2255 priv->tlanFullDuplex = FALSE;
2256 priv->phyOnline=0;
2257 netif_carrier_off(dev);
2258
2259/* 1. Assert reset bit. */
2260
2261 data = inl(dev->base_addr + TLAN_HOST_CMD);
2262 data |= TLAN_HC_AD_RST;
2263 outl(data, dev->base_addr + TLAN_HOST_CMD);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002264
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 udelay(1000);
2266
2267/* 2. Turn off interrupts. ( Probably isn't necessary ) */
2268
2269 data = inl(dev->base_addr + TLAN_HOST_CMD);
2270 data |= TLAN_HC_INT_OFF;
2271 outl(data, dev->base_addr + TLAN_HOST_CMD);
2272
2273/* 3. Clear AREGs and HASHs. */
2274
2275 for ( i = TLAN_AREG_0; i <= TLAN_HASH_2; i += 4 ) {
2276 TLan_DioWrite32( dev->base_addr, (u16) i, 0 );
2277 }
2278
2279/* 4. Setup NetConfig register. */
2280
2281 data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
2282 TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, (u16) data );
2283
2284/* 5. Load Ld_Tmr and Ld_Thr in HOST_CMD. */
2285
2286 outl( TLAN_HC_LD_TMR | 0x3f, dev->base_addr + TLAN_HOST_CMD );
2287 outl( TLAN_HC_LD_THR | 0x9, dev->base_addr + TLAN_HOST_CMD );
2288
2289/* 6. Unreset the MII by setting NMRST (in NetSio) to 1. */
2290
2291 outw( TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR );
2292 addr = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO;
2293 TLan_SetBit( TLAN_NET_SIO_NMRST, addr );
2294
2295/* 7. Setup the remaining registers. */
2296
2297 if ( priv->tlanRev >= 0x30 ) {
2298 data8 = TLAN_ID_TX_EOC | TLAN_ID_RX_EOC;
2299 TLan_DioWrite8( dev->base_addr, TLAN_INT_DIS, data8 );
2300 }
2301 TLan_PhyDetect( dev );
2302 data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002303
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 if ( priv->adapter->flags & TLAN_ADAPTER_BIT_RATE_PHY ) {
2305 data |= TLAN_NET_CFG_BIT;
2306 if ( priv->aui == 1 ) {
2307 TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x0a );
2308 } else if ( priv->duplex == TLAN_DUPLEX_FULL ) {
2309 TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x00 );
2310 priv->tlanFullDuplex = TRUE;
2311 } else {
2312 TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x08 );
2313 }
2314 }
2315
2316 if ( priv->phyNum == 0 ) {
2317 data |= TLAN_NET_CFG_PHY_EN;
2318 }
2319 TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, (u16) data );
2320
2321 if ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) {
2322 TLan_FinishReset( dev );
2323 } else {
2324 TLan_PhyPowerDown( dev );
2325 }
2326
2327} /* TLan_ResetAdapter */
2328
2329
2330
2331
Harvey Harrison98e0f522008-02-18 10:04:38 -08002332static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333TLan_FinishReset( struct net_device *dev )
2334{
2335 TLanPrivateInfo *priv = netdev_priv(dev);
2336 u8 data;
2337 u32 phy;
2338 u8 sio;
2339 u16 status;
2340 u16 partner;
2341 u16 tlphy_ctl;
2342 u16 tlphy_par;
2343 u16 tlphy_id1, tlphy_id2;
2344 int i;
2345
2346 phy = priv->phy[priv->phyNum];
2347
2348 data = TLAN_NET_CMD_NRESET | TLAN_NET_CMD_NWRAP;
2349 if ( priv->tlanFullDuplex ) {
2350 data |= TLAN_NET_CMD_DUPLEX;
2351 }
2352 TLan_DioWrite8( dev->base_addr, TLAN_NET_CMD, data );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002353 data = TLAN_NET_MASK_MASK4 | TLAN_NET_MASK_MASK5;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 if ( priv->phyNum == 0 ) {
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002355 data |= TLAN_NET_MASK_MASK7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 }
2357 TLan_DioWrite8( dev->base_addr, TLAN_NET_MASK, data );
2358 TLan_DioWrite16( dev->base_addr, TLAN_MAX_RX, ((1536)+7)&~7 );
2359 TLan_MiiReadReg( dev, phy, MII_GEN_ID_HI, &tlphy_id1 );
2360 TLan_MiiReadReg( dev, phy, MII_GEN_ID_LO, &tlphy_id2 );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002361
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002362 if ( ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) ||
2363 ( priv->aui ) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364 status = MII_GS_LINK;
2365 printk( "TLAN: %s: Link forced.\n", dev->name );
2366 } else {
2367 TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
2368 udelay( 1000 );
2369 TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002370 if ( (status & MII_GS_LINK) &&
2371 /* We only support link info on Nat.Sem. PHY's */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 (tlphy_id1 == NAT_SEM_ID1) &&
2373 (tlphy_id2 == NAT_SEM_ID2) ) {
2374 TLan_MiiReadReg( dev, phy, MII_AN_LPA, &partner );
2375 TLan_MiiReadReg( dev, phy, TLAN_TLPHY_PAR, &tlphy_par );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002376
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377 printk( "TLAN: %s: Link active with ", dev->name );
2378 if (!(tlphy_par & TLAN_PHY_AN_EN_STAT)) {
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002379 printk( "forced 10%sMbps %s-Duplex\n",
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002380 tlphy_par & TLAN_PHY_SPEED_100 ? "" : "0",
2381 tlphy_par & TLAN_PHY_DUPLEX_FULL ? "Full" : "Half");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382 } else {
2383 printk( "AutoNegotiation enabled, at 10%sMbps %s-Duplex\n",
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002384 tlphy_par & TLAN_PHY_SPEED_100 ? "" : "0",
2385 tlphy_par & TLAN_PHY_DUPLEX_FULL ? "Full" : "Half");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386 printk("TLAN: Partner capability: ");
2387 for (i = 5; i <= 10; i++)
2388 if (partner & (1<<i))
2389 printk("%s",media[i-5]);
2390 printk("\n");
2391 }
2392
2393 TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002394#ifdef MONITOR
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395 /* We have link beat..for now anyway */
2396 priv->link = 1;
2397 /*Enabling link beat monitoring */
2398 TLan_SetTimer( dev, (10*HZ), TLAN_TIMER_LINK_BEAT );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002399#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400 } else if (status & MII_GS_LINK) {
2401 printk( "TLAN: %s: Link active\n", dev->name );
2402 TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK );
2403 }
2404 }
2405
2406 if ( priv->phyNum == 0 ) {
2407 TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tlphy_ctl );
2408 tlphy_ctl |= TLAN_TC_INTEN;
2409 TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tlphy_ctl );
2410 sio = TLan_DioRead8( dev->base_addr, TLAN_NET_SIO );
2411 sio |= TLAN_NET_SIO_MINTEN;
2412 TLan_DioWrite8( dev->base_addr, TLAN_NET_SIO, sio );
2413 }
2414
2415 if ( status & MII_GS_LINK ) {
2416 TLan_SetMac( dev, 0, dev->dev_addr );
2417 priv->phyOnline = 1;
2418 outb( ( TLAN_HC_INT_ON >> 8 ), dev->base_addr + TLAN_HOST_CMD + 1 );
2419 if ( debug >= 1 && debug != TLAN_DEBUG_PROBE ) {
2420 outb( ( TLAN_HC_REQ_INT >> 8 ), dev->base_addr + TLAN_HOST_CMD + 1 );
2421 }
2422 outl( priv->rxListDMA, dev->base_addr + TLAN_CH_PARM );
2423 outl( TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD );
2424 netif_carrier_on(dev);
2425 } else {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002426 printk( "TLAN: %s: Link inactive, will retry in 10 secs...\n",
2427 dev->name );
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 TLan_SetTimer( dev, (10*HZ), TLAN_TIMER_FINISH_RESET );
2429 return;
2430 }
James Harper562faf42005-05-05 15:14:18 -07002431 TLan_SetMulticastList(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432
2433} /* TLan_FinishReset */
2434
2435
2436
2437
2438 /***************************************************************
2439 * TLan_SetMac
2440 *
2441 * Returns:
2442 * Nothing
2443 * Parms:
2444 * dev Pointer to device structure of adapter
2445 * on which to change the AREG.
2446 * areg The AREG to set the address in (0 - 3).
2447 * mac A pointer to an array of chars. Each
2448 * element stores one byte of the address.
2449 * IE, it isn't in ascii.
2450 *
2451 * This function transfers a MAC address to one of the
2452 * TLAN AREGs (address registers). The TLAN chip locks
2453 * the register on writing to offset 0 and unlocks the
2454 * register after writing to offset 5. If NULL is passed
2455 * in mac, then the AREG is filled with 0's.
2456 *
2457 **************************************************************/
2458
Harvey Harrison98e0f522008-02-18 10:04:38 -08002459static void TLan_SetMac( struct net_device *dev, int areg, char *mac )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460{
2461 int i;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002462
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 areg *= 6;
2464
2465 if ( mac != NULL ) {
2466 for ( i = 0; i < 6; i++ )
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002467 TLan_DioWrite8( dev->base_addr,
2468 TLAN_AREG_0 + areg + i, mac[i] );
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 } else {
2470 for ( i = 0; i < 6; i++ )
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002471 TLan_DioWrite8( dev->base_addr,
2472 TLAN_AREG_0 + areg + i, 0 );
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473 }
2474
2475} /* TLan_SetMac */
2476
2477
2478
2479
2480/*****************************************************************************
2481******************************************************************************
2482
2483 ThunderLAN Driver PHY Layer Routines
2484
2485******************************************************************************
2486*****************************************************************************/
2487
2488
2489
2490 /*********************************************************************
2491 * TLan_PhyPrint
2492 *
2493 * Returns:
2494 * Nothing
2495 * Parms:
2496 * dev A pointer to the device structure of the
2497 * TLAN device having the PHYs to be detailed.
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002498 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499 * This function prints the registers a PHY (aka transceiver).
2500 *
2501 ********************************************************************/
2502
Harvey Harrison98e0f522008-02-18 10:04:38 -08002503static void TLan_PhyPrint( struct net_device *dev )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504{
2505 TLanPrivateInfo *priv = netdev_priv(dev);
2506 u16 i, data0, data1, data2, data3, phy;
2507
2508 phy = priv->phy[priv->phyNum];
2509
2510 if ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) {
2511 printk( "TLAN: Device %s, Unmanaged PHY.\n", dev->name );
2512 } else if ( phy <= TLAN_PHY_MAX_ADDR ) {
2513 printk( "TLAN: Device %s, PHY 0x%02x.\n", dev->name, phy );
2514 printk( "TLAN: Off. +0 +1 +2 +3 \n" );
2515 for ( i = 0; i < 0x20; i+= 4 ) {
2516 printk( "TLAN: 0x%02x", i );
2517 TLan_MiiReadReg( dev, phy, i, &data0 );
2518 printk( " 0x%04hx", data0 );
2519 TLan_MiiReadReg( dev, phy, i + 1, &data1 );
2520 printk( " 0x%04hx", data1 );
2521 TLan_MiiReadReg( dev, phy, i + 2, &data2 );
2522 printk( " 0x%04hx", data2 );
2523 TLan_MiiReadReg( dev, phy, i + 3, &data3 );
2524 printk( " 0x%04hx\n", data3 );
2525 }
2526 } else {
2527 printk( "TLAN: Device %s, Invalid PHY.\n", dev->name );
2528 }
2529
2530} /* TLan_PhyPrint */
2531
2532
2533
2534
2535 /*********************************************************************
2536 * TLan_PhyDetect
2537 *
2538 * Returns:
2539 * Nothing
2540 * Parms:
2541 * dev A pointer to the device structure of the adapter
2542 * for which the PHY needs determined.
2543 *
2544 * So far I've found that adapters which have external PHYs
2545 * may also use the internal PHY for part of the functionality.
2546 * (eg, AUI/Thinnet). This function finds out if this TLAN
2547 * chip has an internal PHY, and then finds the first external
2548 * PHY (starting from address 0) if it exists).
2549 *
2550 ********************************************************************/
2551
Harvey Harrison98e0f522008-02-18 10:04:38 -08002552static void TLan_PhyDetect( struct net_device *dev )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553{
2554 TLanPrivateInfo *priv = netdev_priv(dev);
2555 u16 control;
2556 u16 hi;
2557 u16 lo;
2558 u32 phy;
2559
2560 if ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) {
2561 priv->phyNum = 0xFFFF;
2562 return;
2563 }
2564
2565 TLan_MiiReadReg( dev, TLAN_PHY_MAX_ADDR, MII_GEN_ID_HI, &hi );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002566
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567 if ( hi != 0xFFFF ) {
2568 priv->phy[0] = TLAN_PHY_MAX_ADDR;
2569 } else {
2570 priv->phy[0] = TLAN_PHY_NONE;
2571 }
2572
2573 priv->phy[1] = TLAN_PHY_NONE;
2574 for ( phy = 0; phy <= TLAN_PHY_MAX_ADDR; phy++ ) {
2575 TLan_MiiReadReg( dev, phy, MII_GEN_CTL, &control );
2576 TLan_MiiReadReg( dev, phy, MII_GEN_ID_HI, &hi );
2577 TLan_MiiReadReg( dev, phy, MII_GEN_ID_LO, &lo );
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002578 if ( ( control != 0xFFFF ) ||
2579 ( hi != 0xFFFF ) || ( lo != 0xFFFF ) ) {
2580 TLAN_DBG( TLAN_DEBUG_GNRL,
2581 "PHY found at %02x %04x %04x %04x\n",
2582 phy, control, hi, lo );
2583 if ( ( priv->phy[1] == TLAN_PHY_NONE ) &&
2584 ( phy != TLAN_PHY_MAX_ADDR ) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585 priv->phy[1] = phy;
2586 }
2587 }
2588 }
2589
2590 if ( priv->phy[1] != TLAN_PHY_NONE ) {
2591 priv->phyNum = 1;
2592 } else if ( priv->phy[0] != TLAN_PHY_NONE ) {
2593 priv->phyNum = 0;
2594 } else {
2595 printk( "TLAN: Cannot initialize device, no PHY was found!\n" );
2596 }
2597
2598} /* TLan_PhyDetect */
2599
2600
2601
2602
Harvey Harrison98e0f522008-02-18 10:04:38 -08002603static void TLan_PhyPowerDown( struct net_device *dev )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604{
2605 TLanPrivateInfo *priv = netdev_priv(dev);
2606 u16 value;
2607
2608 TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Powering down PHY(s).\n", dev->name );
2609 value = MII_GC_PDOWN | MII_GC_LOOPBK | MII_GC_ISOLATE;
2610 TLan_MiiSync( dev->base_addr );
2611 TLan_MiiWriteReg( dev, priv->phy[priv->phyNum], MII_GEN_CTL, value );
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002612 if ( ( priv->phyNum == 0 ) &&
2613 ( priv->phy[1] != TLAN_PHY_NONE ) &&
2614 ( ! ( priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10 ) ) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615 TLan_MiiSync( dev->base_addr );
2616 TLan_MiiWriteReg( dev, priv->phy[1], MII_GEN_CTL, value );
2617 }
2618
2619 /* Wait for 50 ms and powerup
2620 * This is abitrary. It is intended to make sure the
2621 * transceiver settles.
2622 */
2623 TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_PUP );
2624
2625} /* TLan_PhyPowerDown */
2626
2627
2628
2629
Harvey Harrison98e0f522008-02-18 10:04:38 -08002630static void TLan_PhyPowerUp( struct net_device *dev )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631{
2632 TLanPrivateInfo *priv = netdev_priv(dev);
2633 u16 value;
2634
2635 TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Powering up PHY.\n", dev->name );
2636 TLan_MiiSync( dev->base_addr );
2637 value = MII_GC_LOOPBK;
2638 TLan_MiiWriteReg( dev, priv->phy[priv->phyNum], MII_GEN_CTL, value );
2639 TLan_MiiSync(dev->base_addr);
2640 /* Wait for 500 ms and reset the
2641 * transceiver. The TLAN docs say both 50 ms and
2642 * 500 ms, so do the longer, just in case.
2643 */
2644 TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_RESET );
2645
2646} /* TLan_PhyPowerUp */
2647
2648
2649
2650
Harvey Harrison98e0f522008-02-18 10:04:38 -08002651static void TLan_PhyReset( struct net_device *dev )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652{
2653 TLanPrivateInfo *priv = netdev_priv(dev);
2654 u16 phy;
2655 u16 value;
2656
2657 phy = priv->phy[priv->phyNum];
2658
2659 TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Reseting PHY.\n", dev->name );
2660 TLan_MiiSync( dev->base_addr );
2661 value = MII_GC_LOOPBK | MII_GC_RESET;
2662 TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, value );
2663 TLan_MiiReadReg( dev, phy, MII_GEN_CTL, &value );
2664 while ( value & MII_GC_RESET ) {
2665 TLan_MiiReadReg( dev, phy, MII_GEN_CTL, &value );
2666 }
2667
2668 /* Wait for 500 ms and initialize.
2669 * I don't remember why I wait this long.
2670 * I've changed this to 50ms, as it seems long enough.
2671 */
2672 TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_START_LINK );
2673
2674} /* TLan_PhyReset */
2675
2676
2677
2678
Harvey Harrison98e0f522008-02-18 10:04:38 -08002679static void TLan_PhyStartLink( struct net_device *dev )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680{
2681 TLanPrivateInfo *priv = netdev_priv(dev);
2682 u16 ability;
2683 u16 control;
2684 u16 data;
2685 u16 phy;
2686 u16 status;
2687 u16 tctl;
2688
2689 phy = priv->phy[priv->phyNum];
2690 TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Trying to activate link.\n", dev->name );
2691 TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
2692 TLan_MiiReadReg( dev, phy, MII_GEN_STS, &ability );
2693
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002694 if ( ( status & MII_GS_AUTONEG ) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695 ( ! priv->aui ) ) {
2696 ability = status >> 11;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002697 if ( priv->speed == TLAN_SPEED_10 &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698 priv->duplex == TLAN_DUPLEX_HALF) {
2699 TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x0000);
2700 } else if ( priv->speed == TLAN_SPEED_10 &&
2701 priv->duplex == TLAN_DUPLEX_FULL) {
2702 priv->tlanFullDuplex = TRUE;
2703 TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x0100);
2704 } else if ( priv->speed == TLAN_SPEED_100 &&
2705 priv->duplex == TLAN_DUPLEX_HALF) {
2706 TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x2000);
2707 } else if ( priv->speed == TLAN_SPEED_100 &&
2708 priv->duplex == TLAN_DUPLEX_FULL) {
2709 priv->tlanFullDuplex = TRUE;
2710 TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x2100);
2711 } else {
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002712
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713 /* Set Auto-Neg advertisement */
2714 TLan_MiiWriteReg( dev, phy, MII_AN_ADV, (ability << 5) | 1);
2715 /* Enablee Auto-Neg */
2716 TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1000 );
2717 /* Restart Auto-Neg */
2718 TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1200 );
2719 /* Wait for 4 sec for autonegotiation
2720 * to complete. The max spec time is less than this
2721 * but the card need additional time to start AN.
2722 * .5 sec should be plenty extra.
2723 */
2724 printk( "TLAN: %s: Starting autonegotiation.\n", dev->name );
2725 TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_PHY_FINISH_AN );
2726 return;
2727 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002728
2729 }
2730
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731 if ( ( priv->aui ) && ( priv->phyNum != 0 ) ) {
2732 priv->phyNum = 0;
2733 data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
2734 TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, data );
2735 TLan_SetTimer( dev, (40*HZ/1000), TLAN_TIMER_PHY_PDOWN );
2736 return;
2737 } else if ( priv->phyNum == 0 ) {
2738 control = 0;
2739 TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tctl );
2740 if ( priv->aui ) {
2741 tctl |= TLAN_TC_AUISEL;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002742 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743 tctl &= ~TLAN_TC_AUISEL;
2744 if ( priv->duplex == TLAN_DUPLEX_FULL ) {
2745 control |= MII_GC_DUPLEX;
2746 priv->tlanFullDuplex = TRUE;
2747 }
2748 if ( priv->speed == TLAN_SPEED_100 ) {
2749 control |= MII_GC_SPEEDSEL;
2750 }
2751 }
2752 TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, control );
2753 TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tctl );
2754 }
2755
2756 /* Wait for 2 sec to give the transceiver time
2757 * to establish link.
2758 */
2759 TLan_SetTimer( dev, (4*HZ), TLAN_TIMER_FINISH_RESET );
2760
2761} /* TLan_PhyStartLink */
2762
2763
2764
2765
Harvey Harrison98e0f522008-02-18 10:04:38 -08002766static void TLan_PhyFinishAutoNeg( struct net_device *dev )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767{
2768 TLanPrivateInfo *priv = netdev_priv(dev);
2769 u16 an_adv;
2770 u16 an_lpa;
2771 u16 data;
2772 u16 mode;
2773 u16 phy;
2774 u16 status;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002775
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776 phy = priv->phy[priv->phyNum];
2777
2778 TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
2779 udelay( 1000 );
2780 TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
2781
2782 if ( ! ( status & MII_GS_AUTOCMPLT ) ) {
2783 /* Wait for 8 sec to give the process
2784 * more time. Perhaps we should fail after a while.
2785 */
2786 if (!priv->neg_be_verbose++) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002787 pr_info("TLAN: Giving autonegotiation more time.\n");
2788 pr_info("TLAN: Please check that your adapter has\n");
2789 pr_info("TLAN: been properly connected to a HUB or Switch.\n");
2790 pr_info("TLAN: Trying to establish link in the background...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791 }
2792 TLan_SetTimer( dev, (8*HZ), TLAN_TIMER_PHY_FINISH_AN );
2793 return;
2794 }
2795
2796 printk( "TLAN: %s: Autonegotiation complete.\n", dev->name );
2797 TLan_MiiReadReg( dev, phy, MII_AN_ADV, &an_adv );
2798 TLan_MiiReadReg( dev, phy, MII_AN_LPA, &an_lpa );
2799 mode = an_adv & an_lpa & 0x03E0;
2800 if ( mode & 0x0100 ) {
2801 priv->tlanFullDuplex = TRUE;
2802 } else if ( ! ( mode & 0x0080 ) && ( mode & 0x0040 ) ) {
2803 priv->tlanFullDuplex = TRUE;
2804 }
2805
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002806 if ( ( ! ( mode & 0x0180 ) ) &&
2807 ( priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10 ) &&
2808 ( priv->phyNum != 0 ) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002809 priv->phyNum = 0;
2810 data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
2811 TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, data );
2812 TLan_SetTimer( dev, (400*HZ/1000), TLAN_TIMER_PHY_PDOWN );
2813 return;
2814 }
2815
2816 if ( priv->phyNum == 0 ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002817 if ( ( priv->duplex == TLAN_DUPLEX_FULL ) ||
2818 ( an_adv & an_lpa & 0x0040 ) ) {
2819 TLan_MiiWriteReg( dev, phy, MII_GEN_CTL,
2820 MII_GC_AUTOENB | MII_GC_DUPLEX );
2821 pr_info("TLAN: Starting internal PHY with FULL-DUPLEX\n" );
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822 } else {
2823 TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, MII_GC_AUTOENB );
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002824 pr_info( "TLAN: Starting internal PHY with HALF-DUPLEX\n" );
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825 }
2826 }
2827
2828 /* Wait for 100 ms. No reason in partiticular.
2829 */
2830 TLan_SetTimer( dev, (HZ/10), TLAN_TIMER_FINISH_RESET );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002831
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832} /* TLan_PhyFinishAutoNeg */
2833
2834#ifdef MONITOR
2835
2836 /*********************************************************************
2837 *
2838 * TLan_phyMonitor
2839 *
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002840 * Returns:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841 * None
2842 *
2843 * Params:
2844 * dev The device structure of this device.
2845 *
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002846 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847 * This function monitors PHY condition by reading the status
2848 * register via the MII bus. This can be used to give info
2849 * about link changes (up/down), and possible switch to alternate
2850 * media.
2851 *
2852 * ******************************************************************/
2853
2854void TLan_PhyMonitor( struct net_device *dev )
2855{
2856 TLanPrivateInfo *priv = netdev_priv(dev);
2857 u16 phy;
2858 u16 phy_status;
2859
2860 phy = priv->phy[priv->phyNum];
2861
2862 /* Get PHY status register */
2863 TLan_MiiReadReg( dev, phy, MII_GEN_STS, &phy_status );
2864
2865 /* Check if link has been lost */
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002866 if (!(phy_status & MII_GS_LINK)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867 if (priv->link) {
2868 priv->link = 0;
2869 printk(KERN_DEBUG "TLAN: %s has lost link\n", dev->name);
7d17c1d2005-05-12 19:45:25 -04002870 netif_carrier_off(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002871 TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_LINK_BEAT );
2872 return;
2873 }
2874 }
2875
2876 /* Link restablished? */
2877 if ((phy_status & MII_GS_LINK) && !priv->link) {
2878 priv->link = 1;
2879 printk(KERN_DEBUG "TLAN: %s has reestablished link\n", dev->name);
7d17c1d2005-05-12 19:45:25 -04002880 netif_carrier_on(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881 }
2882
2883 /* Setup a new monitor */
2884 TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_LINK_BEAT );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002885}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002886
2887#endif /* MONITOR */
2888
2889
2890/*****************************************************************************
2891******************************************************************************
2892
2893 ThunderLAN Driver MII Routines
2894
2895 These routines are based on the information in Chap. 2 of the
2896 "ThunderLAN Programmer's Guide", pp. 15-24.
2897
2898******************************************************************************
2899*****************************************************************************/
2900
2901
2902 /***************************************************************
2903 * TLan_MiiReadReg
2904 *
2905 * Returns:
2906 * 0 if ack received ok
2907 * 1 otherwise.
2908 *
2909 * Parms:
2910 * dev The device structure containing
2911 * The io address and interrupt count
2912 * for this device.
2913 * phy The address of the PHY to be queried.
2914 * reg The register whose contents are to be
Matt Mackall4a4efbd2006-01-03 13:27:11 +01002915 * retrieved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916 * val A pointer to a variable to store the
2917 * retrieved value.
2918 *
Matt Mackall4a4efbd2006-01-03 13:27:11 +01002919 * This function uses the TLAN's MII bus to retrieve the contents
Linus Torvalds1da177e2005-04-16 15:20:36 -07002920 * of a given register on a PHY. It sends the appropriate info
2921 * and then reads the 16-bit register value from the MII bus via
2922 * the TLAN SIO register.
2923 *
2924 **************************************************************/
2925
Harvey Harrison98e0f522008-02-18 10:04:38 -08002926static int TLan_MiiReadReg( struct net_device *dev, u16 phy, u16 reg, u16 *val )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002927{
2928 u8 nack;
2929 u16 sio, tmp;
2930 u32 i;
2931 int err;
2932 int minten;
2933 TLanPrivateInfo *priv = netdev_priv(dev);
2934 unsigned long flags = 0;
2935
2936 err = FALSE;
2937 outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR);
2938 sio = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002939
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940 if (!in_irq())
2941 spin_lock_irqsave(&priv->lock, flags);
2942
2943 TLan_MiiSync(dev->base_addr);
2944
2945 minten = TLan_GetBit( TLAN_NET_SIO_MINTEN, sio );
2946 if ( minten )
2947 TLan_ClearBit(TLAN_NET_SIO_MINTEN, sio);
2948
2949 TLan_MiiSendData( dev->base_addr, 0x1, 2 ); /* Start ( 01b ) */
2950 TLan_MiiSendData( dev->base_addr, 0x2, 2 ); /* Read ( 10b ) */
2951 TLan_MiiSendData( dev->base_addr, phy, 5 ); /* Device # */
2952 TLan_MiiSendData( dev->base_addr, reg, 5 ); /* Register # */
2953
2954
2955 TLan_ClearBit(TLAN_NET_SIO_MTXEN, sio); /* Change direction */
2956
2957 TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); /* Clock Idle bit */
2958 TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
2959 TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); /* Wait 300ns */
2960
2961 nack = TLan_GetBit(TLAN_NET_SIO_MDATA, sio); /* Check for ACK */
2962 TLan_SetBit(TLAN_NET_SIO_MCLK, sio); /* Finish ACK */
2963 if (nack) { /* No ACK, so fake it */
2964 for (i = 0; i < 16; i++) {
2965 TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
2966 TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
2967 }
2968 tmp = 0xffff;
2969 err = TRUE;
2970 } else { /* ACK, so read data */
2971 for (tmp = 0, i = 0x8000; i; i >>= 1) {
2972 TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
2973 if (TLan_GetBit(TLAN_NET_SIO_MDATA, sio))
2974 tmp |= i;
2975 TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
2976 }
2977 }
2978
2979
2980 TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); /* Idle cycle */
2981 TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
2982
2983 if ( minten )
2984 TLan_SetBit(TLAN_NET_SIO_MINTEN, sio);
2985
2986 *val = tmp;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002987
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988 if (!in_irq())
2989 spin_unlock_irqrestore(&priv->lock, flags);
2990
2991 return err;
2992
2993} /* TLan_MiiReadReg */
2994
2995
2996
2997
2998 /***************************************************************
2999 * TLan_MiiSendData
3000 *
3001 * Returns:
3002 * Nothing
3003 * Parms:
3004 * base_port The base IO port of the adapter in
3005 * question.
3006 * dev The address of the PHY to be queried.
3007 * data The value to be placed on the MII bus.
3008 * num_bits The number of bits in data that are to
3009 * be placed on the MII bus.
3010 *
3011 * This function sends on sequence of bits on the MII
3012 * configuration bus.
3013 *
3014 **************************************************************/
3015
Harvey Harrison98e0f522008-02-18 10:04:38 -08003016static void TLan_MiiSendData( u16 base_port, u32 data, unsigned num_bits )
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017{
3018 u16 sio;
3019 u32 i;
3020
3021 if ( num_bits == 0 )
3022 return;
3023
3024 outw( TLAN_NET_SIO, base_port + TLAN_DIO_ADR );
3025 sio = base_port + TLAN_DIO_DATA + TLAN_NET_SIO;
3026 TLan_SetBit( TLAN_NET_SIO_MTXEN, sio );
3027
3028 for ( i = ( 0x1 << ( num_bits - 1 ) ); i; i >>= 1 ) {
3029 TLan_ClearBit( TLAN_NET_SIO_MCLK, sio );
3030 (void) TLan_GetBit( TLAN_NET_SIO_MCLK, sio );
3031 if ( data & i )
3032 TLan_SetBit( TLAN_NET_SIO_MDATA, sio );
3033 else
3034 TLan_ClearBit( TLAN_NET_SIO_MDATA, sio );
3035 TLan_SetBit( TLAN_NET_SIO_MCLK, sio );
3036 (void) TLan_GetBit( TLAN_NET_SIO_MCLK, sio );
3037 }
3038
3039} /* TLan_MiiSendData */
3040
3041
3042
3043
3044 /***************************************************************
3045 * TLan_MiiSync
3046 *
3047 * Returns:
3048 * Nothing
3049 * Parms:
3050 * base_port The base IO port of the adapter in
3051 * question.
3052 *
3053 * This functions syncs all PHYs in terms of the MII configuration
3054 * bus.
3055 *
3056 **************************************************************/
3057
Harvey Harrison98e0f522008-02-18 10:04:38 -08003058static void TLan_MiiSync( u16 base_port )
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059{
3060 int i;
3061 u16 sio;
3062
3063 outw( TLAN_NET_SIO, base_port + TLAN_DIO_ADR );
3064 sio = base_port + TLAN_DIO_DATA + TLAN_NET_SIO;
3065
3066 TLan_ClearBit( TLAN_NET_SIO_MTXEN, sio );
3067 for ( i = 0; i < 32; i++ ) {
3068 TLan_ClearBit( TLAN_NET_SIO_MCLK, sio );
3069 TLan_SetBit( TLAN_NET_SIO_MCLK, sio );
3070 }
3071
3072} /* TLan_MiiSync */
3073
3074
3075
3076
3077 /***************************************************************
3078 * TLan_MiiWriteReg
3079 *
3080 * Returns:
3081 * Nothing
3082 * Parms:
3083 * dev The device structure for the device
3084 * to write to.
3085 * phy The address of the PHY to be written to.
3086 * reg The register whose contents are to be
3087 * written.
3088 * val The value to be written to the register.
3089 *
3090 * This function uses the TLAN's MII bus to write the contents of a
3091 * given register on a PHY. It sends the appropriate info and then
3092 * writes the 16-bit register value from the MII configuration bus
3093 * via the TLAN SIO register.
3094 *
3095 **************************************************************/
3096
Harvey Harrison98e0f522008-02-18 10:04:38 -08003097static void TLan_MiiWriteReg( struct net_device *dev, u16 phy, u16 reg, u16 val )
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098{
3099 u16 sio;
3100 int minten;
3101 unsigned long flags = 0;
3102 TLanPrivateInfo *priv = netdev_priv(dev);
3103
3104 outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR);
3105 sio = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04003106
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107 if (!in_irq())
3108 spin_lock_irqsave(&priv->lock, flags);
3109
3110 TLan_MiiSync( dev->base_addr );
3111
3112 minten = TLan_GetBit( TLAN_NET_SIO_MINTEN, sio );
3113 if ( minten )
3114 TLan_ClearBit( TLAN_NET_SIO_MINTEN, sio );
3115
3116 TLan_MiiSendData( dev->base_addr, 0x1, 2 ); /* Start ( 01b ) */
3117 TLan_MiiSendData( dev->base_addr, 0x1, 2 ); /* Write ( 01b ) */
3118 TLan_MiiSendData( dev->base_addr, phy, 5 ); /* Device # */
3119 TLan_MiiSendData( dev->base_addr, reg, 5 ); /* Register # */
3120
3121 TLan_MiiSendData( dev->base_addr, 0x2, 2 ); /* Send ACK */
3122 TLan_MiiSendData( dev->base_addr, val, 16 ); /* Send Data */
3123
3124 TLan_ClearBit( TLAN_NET_SIO_MCLK, sio ); /* Idle cycle */
3125 TLan_SetBit( TLAN_NET_SIO_MCLK, sio );
3126
3127 if ( minten )
3128 TLan_SetBit( TLAN_NET_SIO_MINTEN, sio );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04003129
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130 if (!in_irq())
3131 spin_unlock_irqrestore(&priv->lock, flags);
3132
3133} /* TLan_MiiWriteReg */
3134
3135
3136
3137
3138/*****************************************************************************
3139******************************************************************************
3140
3141 ThunderLAN Driver Eeprom routines
3142
3143 The Compaq Netelligent 10 and 10/100 cards use a Microchip 24C02A
3144 EEPROM. These functions are based on information in Microchip's
3145 data sheet. I don't know how well this functions will work with
3146 other EEPROMs.
3147
3148******************************************************************************
3149*****************************************************************************/
3150
3151
3152 /***************************************************************
3153 * TLan_EeSendStart
3154 *
3155 * Returns:
3156 * Nothing
Jeff Garzik6aa20a22006-09-13 13:24:59 -04003157 * Parms:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158 * io_base The IO port base address for the
3159 * TLAN device with the EEPROM to
3160 * use.
3161 *
3162 * This function sends a start cycle to an EEPROM attached
3163 * to a TLAN chip.
3164 *
3165 **************************************************************/
3166
Harvey Harrison98e0f522008-02-18 10:04:38 -08003167static void TLan_EeSendStart( u16 io_base )
Linus Torvalds1da177e2005-04-16 15:20:36 -07003168{
3169 u16 sio;
3170
3171 outw( TLAN_NET_SIO, io_base + TLAN_DIO_ADR );
3172 sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
3173
3174 TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
3175 TLan_SetBit( TLAN_NET_SIO_EDATA, sio );
3176 TLan_SetBit( TLAN_NET_SIO_ETXEN, sio );
3177 TLan_ClearBit( TLAN_NET_SIO_EDATA, sio );
3178 TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
3179
3180} /* TLan_EeSendStart */
3181
3182
3183
3184
3185 /***************************************************************
3186 * TLan_EeSendByte
3187 *
3188 * Returns:
3189 * If the correct ack was received, 0, otherwise 1
3190 * Parms: io_base The IO port base address for the
3191 * TLAN device with the EEPROM to
3192 * use.
3193 * data The 8 bits of information to
3194 * send to the EEPROM.
3195 * stop If TLAN_EEPROM_STOP is passed, a
3196 * stop cycle is sent after the
3197 * byte is sent after the ack is
3198 * read.
3199 *
3200 * This function sends a byte on the serial EEPROM line,
3201 * driving the clock to send each bit. The function then
3202 * reverses transmission direction and reads an acknowledge
3203 * bit.
3204 *
3205 **************************************************************/
3206
Harvey Harrison98e0f522008-02-18 10:04:38 -08003207static int TLan_EeSendByte( u16 io_base, u8 data, int stop )
Linus Torvalds1da177e2005-04-16 15:20:36 -07003208{
3209 int err;
3210 u8 place;
3211 u16 sio;
3212
3213 outw( TLAN_NET_SIO, io_base + TLAN_DIO_ADR );
3214 sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
3215
3216 /* Assume clock is low, tx is enabled; */
3217 for ( place = 0x80; place != 0; place >>= 1 ) {
3218 if ( place & data )
3219 TLan_SetBit( TLAN_NET_SIO_EDATA, sio );
3220 else
3221 TLan_ClearBit( TLAN_NET_SIO_EDATA, sio );
3222 TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
3223 TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
3224 }
3225 TLan_ClearBit( TLAN_NET_SIO_ETXEN, sio );
3226 TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
3227 err = TLan_GetBit( TLAN_NET_SIO_EDATA, sio );
3228 TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
3229 TLan_SetBit( TLAN_NET_SIO_ETXEN, sio );
3230
3231 if ( ( ! err ) && stop ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07003232 /* STOP, raise data while clock is high */
3233 TLan_ClearBit( TLAN_NET_SIO_EDATA, sio );
Linus Torvalds1da177e2005-04-16 15:20:36 -07003234 TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
3235 TLan_SetBit( TLAN_NET_SIO_EDATA, sio );
3236 }
3237
3238 return ( err );
3239
3240} /* TLan_EeSendByte */
3241
3242
3243
3244
3245 /***************************************************************
3246 * TLan_EeReceiveByte
3247 *
3248 * Returns:
3249 * Nothing
3250 * Parms:
3251 * io_base The IO port base address for the
3252 * TLAN device with the EEPROM to
3253 * use.
3254 * data An address to a char to hold the
3255 * data sent from the EEPROM.
3256 * stop If TLAN_EEPROM_STOP is passed, a
3257 * stop cycle is sent after the
3258 * byte is received, and no ack is
3259 * sent.
3260 *
3261 * This function receives 8 bits of data from the EEPROM
3262 * over the serial link. It then sends and ack bit, or no
3263 * ack and a stop bit. This function is used to retrieve
3264 * data after the address of a byte in the EEPROM has been
3265 * sent.
3266 *
3267 **************************************************************/
3268
Harvey Harrison98e0f522008-02-18 10:04:38 -08003269static void TLan_EeReceiveByte( u16 io_base, u8 *data, int stop )
Linus Torvalds1da177e2005-04-16 15:20:36 -07003270{
3271 u8 place;
3272 u16 sio;
3273
3274 outw( TLAN_NET_SIO, io_base + TLAN_DIO_ADR );
3275 sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
3276 *data = 0;
3277
3278 /* Assume clock is low, tx is enabled; */
3279 TLan_ClearBit( TLAN_NET_SIO_ETXEN, sio );
3280 for ( place = 0x80; place; place >>= 1 ) {
3281 TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
3282 if ( TLan_GetBit( TLAN_NET_SIO_EDATA, sio ) )
3283 *data |= place;
3284 TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
3285 }
3286
3287 TLan_SetBit( TLAN_NET_SIO_ETXEN, sio );
3288 if ( ! stop ) {
3289 TLan_ClearBit( TLAN_NET_SIO_EDATA, sio ); /* Ack = 0 */
3290 TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
3291 TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
3292 } else {
3293 TLan_SetBit( TLAN_NET_SIO_EDATA, sio ); /* No ack = 1 (?) */
3294 TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
3295 TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07003296 /* STOP, raise data while clock is high */
3297 TLan_ClearBit( TLAN_NET_SIO_EDATA, sio );
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298 TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
3299 TLan_SetBit( TLAN_NET_SIO_EDATA, sio );
3300 }
3301
3302} /* TLan_EeReceiveByte */
3303
3304
3305
3306
3307 /***************************************************************
3308 * TLan_EeReadByte
3309 *
3310 * Returns:
3311 * No error = 0, else, the stage at which the error
3312 * occurred.
3313 * Parms:
3314 * io_base The IO port base address for the
3315 * TLAN device with the EEPROM to
3316 * use.
3317 * ee_addr The address of the byte in the
3318 * EEPROM whose contents are to be
3319 * retrieved.
3320 * data An address to a char to hold the
3321 * data obtained from the EEPROM.
3322 *
3323 * This function reads a byte of information from an byte
3324 * cell in the EEPROM.
3325 *
3326 **************************************************************/
3327
Harvey Harrison98e0f522008-02-18 10:04:38 -08003328static int TLan_EeReadByte( struct net_device *dev, u8 ee_addr, u8 *data )
Linus Torvalds1da177e2005-04-16 15:20:36 -07003329{
3330 int err;
3331 TLanPrivateInfo *priv = netdev_priv(dev);
3332 unsigned long flags = 0;
3333 int ret=0;
3334
3335 spin_lock_irqsave(&priv->lock, flags);
3336
3337 TLan_EeSendStart( dev->base_addr );
3338 err = TLan_EeSendByte( dev->base_addr, 0xA0, TLAN_EEPROM_ACK );
3339 if (err)
3340 {
3341 ret=1;
3342 goto fail;
3343 }
3344 err = TLan_EeSendByte( dev->base_addr, ee_addr, TLAN_EEPROM_ACK );
3345 if (err)
3346 {
3347 ret=2;
3348 goto fail;
3349 }
3350 TLan_EeSendStart( dev->base_addr );
3351 err = TLan_EeSendByte( dev->base_addr, 0xA1, TLAN_EEPROM_ACK );
3352 if (err)
3353 {
3354 ret=3;
3355 goto fail;
3356 }
3357 TLan_EeReceiveByte( dev->base_addr, data, TLAN_EEPROM_STOP );
3358fail:
3359 spin_unlock_irqrestore(&priv->lock, flags);
3360
3361 return ret;
3362
3363} /* TLan_EeReadByte */
3364
3365
3366