blob: e60498232b94f83dede6c6d4ae153d8d135d7b19 [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.
Alan Cox113aa832008-10-13 19:01:08 -070032 * Alan Cox <alan@lxorguk.ukuu.org.uk>:
33 * Fixed the out of memory
Linus Torvalds1da177e2005-04-16 15:20:36 -070034 * handling.
Jeff Garzik6aa20a22006-09-13 13:24:59 -040035 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070036 * Torben Mathiasen <torben.mathiasen@compaq.com> New Maintainer!
37 *
38 * v1.1 Dec 20, 1999 - Removed linux version checking
Jeff Garzik6aa20a22006-09-13 13:24:59 -040039 * Patch from Tigran Aivazian.
Linus Torvalds1da177e2005-04-16 15:20:36 -070040 * - v1.1 includes Alan's SMP updates.
41 * - We still have problems on SMP though,
Jeff Garzik6aa20a22006-09-13 13:24:59 -040042 * but I'm looking into that.
43 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 * v1.2 Jan 02, 2000 - Hopefully fixed the SMP deadlock.
45 * - Removed dependency of HZ being 100.
Jeff Garzik6aa20a22006-09-13 13:24:59 -040046 * - We now allow higher priority timers to
Linus Torvalds1da177e2005-04-16 15:20:36 -070047 * overwrite timers like TLAN_TIMER_ACTIVITY
48 * Patch from John Cagle <john.cagle@compaq.com>.
49 * - Fixed a few compiler warnings.
50 *
51 * v1.3 Feb 04, 2000 - Fixed the remaining HZ issues.
Jeff Garzik6aa20a22006-09-13 13:24:59 -040052 * - Removed call to pci_present().
Linus Torvalds1da177e2005-04-16 15:20:36 -070053 * - Removed SA_INTERRUPT flag from irq handler.
Jeff Garzik6aa20a22006-09-13 13:24:59 -040054 * - Added __init and __initdata to reduce resisdent
Linus Torvalds1da177e2005-04-16 15:20:36 -070055 * code size.
56 * - Driver now uses module_init/module_exit.
57 * - Rewrote init_module and tlan_probe to
58 * share a lot more code. We now use tlan_probe
59 * with builtin and module driver.
Jeff Garzik6aa20a22006-09-13 13:24:59 -040060 * - Driver ported to new net API.
61 * - tlan.txt has been reworked to reflect current
Linus Torvalds1da177e2005-04-16 15:20:36 -070062 * driver (almost)
63 * - Other minor stuff
64 *
65 * v1.4 Feb 10, 2000 - Updated with more changes required after Dave's
66 * network cleanup in 2.3.43pre7 (Tigran & myself)
67 * - Minor stuff.
68 *
69 * v1.5 March 22, 2000 - Fixed another timer bug that would hang the driver
70 * if no cable/link were present.
71 * - Cosmetic changes.
72 * - TODO: Port completely to new PCI/DMA API
73 * Auto-Neg fallback.
74 *
75 * v1.6 April 04, 2000 - Fixed driver support for kernel-parameters. Haven't
Jeff Garzik6aa20a22006-09-13 13:24:59 -040076 * tested it though, as the kernel support is currently
Linus Torvalds1da177e2005-04-16 15:20:36 -070077 * broken (2.3.99p4p3).
78 * - Updated tlan.txt accordingly.
79 * - Adjusted minimum/maximum frame length.
Jeff Garzik6aa20a22006-09-13 13:24:59 -040080 * - There is now a TLAN website up at
Linus Torvalds1da177e2005-04-16 15:20:36 -070081 * http://tlan.kernel.dk
82 *
83 * v1.7 April 07, 2000 - Started to implement custom ioctls. Driver now
84 * reports PHY information when used with Donald
85 * Beckers userspace MII diagnostics utility.
86 *
87 * v1.8 April 23, 2000 - Fixed support for forced speed/duplex settings.
88 * - Added link information to Auto-Neg and forced
89 * modes. When NIC operates with auto-neg the driver
90 * will report Link speed & duplex modes as well as
91 * link partner abilities. When forced link is used,
92 * the driver will report status of the established
93 * link.
Jeff Garzik6aa20a22006-09-13 13:24:59 -040094 * Please read tlan.txt for additional information.
95 * - Removed call to check_region(), and used
Linus Torvalds1da177e2005-04-16 15:20:36 -070096 * return value of request_region() instead.
Jeff Garzik6aa20a22006-09-13 13:24:59 -040097 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070098 * v1.8a May 28, 2000 - Minor updates.
99 *
100 * v1.9 July 25, 2000 - Fixed a few remaining Full-Duplex issues.
101 * - Updated with timer fixes from Andrew Morton.
102 * - Fixed module race in TLan_Open.
103 * - Added routine to monitor PHY status.
104 * - Added activity led support for Proliant devices.
105 *
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400106 * v1.10 Aug 30, 2000 - Added support for EISA based tlan controllers
107 * like the Compaq NetFlex3/E.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108 * - Rewrote tlan_probe to better handle multiple
109 * bus probes. Probing and device setup is now
110 * done through TLan_Probe and TLan_init_one. Actual
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400111 * hardware probe is done with kernel API and
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 * TLan_EisaProbe.
113 * - Adjusted debug information for probing.
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400114 * - Fixed bug that would cause general debug information
115 * to be printed after driver removal.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116 * - Added transmit timeout handling.
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400117 * - Fixed OOM return values in tlan_probe.
118 * - Fixed possible mem leak in tlan_exit
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119 * (now tlan_remove_one).
120 * - Fixed timer bug in TLan_phyMonitor.
121 * - This driver version is alpha quality, please
122 * send me any bug issues you may encounter.
123 *
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400124 * v1.11 Aug 31, 2000 - Do not try to register irq 0 if no irq line was
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 * set for EISA cards.
126 * - Added support for NetFlex3/E with nibble-rate
127 * 10Base-T PHY. This is untestet as I haven't got
128 * one of these cards.
129 * - Fixed timer being added twice.
130 * - Disabled PhyMonitoring by default as this is
131 * work in progress. Define MONITOR to enable it.
132 * - Now we don't display link info with PHYs that
133 * doesn't support it (level1).
134 * - Incresed tx_timeout beacuse of auto-neg.
135 * - Adjusted timers for forced speeds.
136 *
137 * v1.12 Oct 12, 2000 - Minor fixes (memleak, init, etc.)
138 *
139 * v1.13 Nov 28, 2000 - Stop flooding console with auto-neg issues
140 * when link can't be established.
141 * - Added the bbuf option as a kernel parameter.
142 * - Fixed ioaddr probe bug.
143 * - Fixed stupid deadlock with MII interrupts.
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400144 * - Added support for speed/duplex selection with
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 * multiple nics.
146 * - Added partly fix for TX Channel lockup with
147 * TLAN v1.0 silicon. This needs to be investigated
148 * further.
149 *
150 * v1.14 Dec 16, 2000 - Added support for servicing multiple frames per.
151 * interrupt. Thanks goes to
152 * Adam Keys <adam@ti.com>
153 * Denis Beaudoin <dbeaudoin@ti.com>
154 * for providing the patch.
155 * - Fixed auto-neg output when using multiple
156 * adapters.
157 * - Converted to use new taskq interface.
158 *
159 * v1.14a Jan 6, 2001 - Minor adjustments (spinlocks, etc.)
160 *
161 * Samuel Chessman <chessman@tux.org> New Maintainer!
162 *
163 * v1.15 Apr 4, 2002 - Correct operation when aui=1 to be
164 * 10T half duplex no loopback
165 * Thanks to Gunnar Eikman
166 *******************************************************************************/
167
168#include <linux/module.h>
169#include <linux/init.h>
170#include <linux/ioport.h>
171#include <linux/eisa.h>
172#include <linux/pci.h>
Domen Puncer1e7f0bd2005-06-26 18:22:14 -0400173#include <linux/dma-mapping.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174#include <linux/netdevice.h>
175#include <linux/etherdevice.h>
176#include <linux/delay.h>
177#include <linux/spinlock.h>
178#include <linux/workqueue.h>
179#include <linux/mii.h>
180
181#include "tlan.h"
182
183typedef u32 (TLanIntVectorFunc)( struct net_device *, u16 );
184
185
186/* For removing EISA devices */
187static struct net_device *TLan_Eisa_Devices;
188
189static int TLanDevicesInstalled;
190
191/* Set speed, duplex and aui settings */
192static int aui[MAX_TLAN_BOARDS];
193static int duplex[MAX_TLAN_BOARDS];
194static int speed[MAX_TLAN_BOARDS];
195static int boards_found;
Stephen Hemminger15efa9b2005-05-04 15:33:11 -0700196module_param_array(aui, int, NULL, 0);
197module_param_array(duplex, int, NULL, 0);
198module_param_array(speed, int, NULL, 0);
199MODULE_PARM_DESC(aui, "ThunderLAN use AUI port(s) (0-1)");
200MODULE_PARM_DESC(duplex, "ThunderLAN duplex setting(s) (0-default, 1-half, 2-full)");
201MODULE_PARM_DESC(speed, "ThunderLAN port speen setting(s) (0,10,100)");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202
203MODULE_AUTHOR("Maintainer: Samuel Chessman <chessman@tux.org>");
204MODULE_DESCRIPTION("Driver for TI ThunderLAN based ethernet PCI adapters");
205MODULE_LICENSE("GPL");
206
207
208/* Define this to enable Link beat monitoring */
209#undef MONITOR
210
211/* Turn on debugging. See Documentation/networking/tlan.txt for details */
212static int debug;
Stephen Hemminger15efa9b2005-05-04 15:33:11 -0700213module_param(debug, int, 0);
214MODULE_PARM_DESC(debug, "ThunderLAN debug mask");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215
216static int bbuf;
Stephen Hemminger15efa9b2005-05-04 15:33:11 -0700217module_param(bbuf, int, 0);
218MODULE_PARM_DESC(bbuf, "ThunderLAN use big buffer (0-1)");
219
Stephen Hemmingera3ccc782008-05-30 09:49:57 -0700220static const char TLanSignature[] = "TLAN";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221static const char tlan_banner[] = "ThunderLAN driver v1.15\n";
222static int tlan_have_pci;
223static int tlan_have_eisa;
224
225static const char *media[] = {
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400226 "10BaseT-HD ", "10BaseT-FD ","100baseTx-HD ",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 "100baseTx-FD", "100baseT4", NULL
228};
229
230static struct board {
231 const char *deviceLabel;
232 u32 flags;
233 u16 addrOfs;
234} board_info[] = {
235 { "Compaq Netelligent 10 T PCI UTP", TLAN_ADAPTER_ACTIVITY_LED, 0x83 },
236 { "Compaq Netelligent 10/100 TX PCI UTP", TLAN_ADAPTER_ACTIVITY_LED, 0x83 },
237 { "Compaq Integrated NetFlex-3/P", TLAN_ADAPTER_NONE, 0x83 },
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700238 { "Compaq NetFlex-3/P",
239 TLAN_ADAPTER_UNMANAGED_PHY | TLAN_ADAPTER_BIT_RATE_PHY, 0x83 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 { "Compaq NetFlex-3/P", TLAN_ADAPTER_NONE, 0x83 },
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700241 { "Compaq Netelligent Integrated 10/100 TX UTP",
242 TLAN_ADAPTER_ACTIVITY_LED, 0x83 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 { "Compaq Netelligent Dual 10/100 TX PCI UTP", TLAN_ADAPTER_NONE, 0x83 },
244 { "Compaq Netelligent 10/100 TX Embedded UTP", TLAN_ADAPTER_NONE, 0x83 },
245 { "Olicom OC-2183/2185", TLAN_ADAPTER_USE_INTERN_10, 0x83 },
246 { "Olicom OC-2325", TLAN_ADAPTER_UNMANAGED_PHY, 0xF8 },
247 { "Olicom OC-2326", TLAN_ADAPTER_USE_INTERN_10, 0xF8 },
248 { "Compaq Netelligent 10/100 TX UTP", TLAN_ADAPTER_ACTIVITY_LED, 0x83 },
249 { "Compaq Netelligent 10 T/2 PCI UTP/Coax", TLAN_ADAPTER_NONE, 0x83 },
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700250 { "Compaq NetFlex-3/E",
251 TLAN_ADAPTER_ACTIVITY_LED | /* EISA card */
252 TLAN_ADAPTER_UNMANAGED_PHY | TLAN_ADAPTER_BIT_RATE_PHY, 0x83 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 { "Compaq NetFlex-3/E", TLAN_ADAPTER_ACTIVITY_LED, 0x83 }, /* EISA card */
254};
255
256static struct pci_device_id tlan_pci_tbl[] = {
257 { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL10,
258 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
259 { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100,
260 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
261 { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETFLEX3I,
262 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
263 { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_THUNDER,
264 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 },
265 { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETFLEX3B,
266 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
267 { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100PI,
268 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 },
269 { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100D,
270 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 },
271 { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100I,
272 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7 },
273 { PCI_VENDOR_ID_OLICOM, PCI_DEVICE_ID_OLICOM_OC2183,
274 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
275 { PCI_VENDOR_ID_OLICOM, PCI_DEVICE_ID_OLICOM_OC2325,
276 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9 },
277 { PCI_VENDOR_ID_OLICOM, PCI_DEVICE_ID_OLICOM_OC2326,
278 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10 },
279 { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10_100_WS_5100,
280 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 },
281 { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10_T2,
282 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 },
283 { 0,}
284};
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400285MODULE_DEVICE_TABLE(pci, tlan_pci_tbl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286
287static void TLan_EisaProbe( void );
288static void TLan_Eisa_Cleanup( void );
289static int TLan_Init( struct net_device * );
290static int TLan_Open( struct net_device *dev );
291static int TLan_StartTx( struct sk_buff *, struct net_device *);
David Howells7d12e782006-10-05 14:55:46 +0100292static irqreturn_t TLan_HandleInterrupt( int, void *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293static int TLan_Close( struct net_device *);
294static struct net_device_stats *TLan_GetStats( struct net_device *);
295static void TLan_SetMulticastList( struct net_device *);
296static int TLan_ioctl( struct net_device *dev, struct ifreq *rq, int cmd);
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700297static int TLan_probe1( struct pci_dev *pdev, long ioaddr,
298 int irq, int rev, const struct pci_device_id *ent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299static void TLan_tx_timeout( struct net_device *dev);
David Howellsc4028952006-11-22 14:57:56 +0000300static void TLan_tx_timeout_work(struct work_struct *work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301static int tlan_init_one( struct pci_dev *pdev, const struct pci_device_id *ent);
302
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303static u32 TLan_HandleTxEOF( struct net_device *, u16 );
304static u32 TLan_HandleStatOverflow( struct net_device *, u16 );
305static u32 TLan_HandleRxEOF( struct net_device *, u16 );
306static u32 TLan_HandleDummy( struct net_device *, u16 );
307static u32 TLan_HandleTxEOC( struct net_device *, u16 );
308static u32 TLan_HandleStatusCheck( struct net_device *, u16 );
309static u32 TLan_HandleRxEOC( struct net_device *, u16 );
310
311static void TLan_Timer( unsigned long );
312
313static void TLan_ResetLists( struct net_device * );
314static void TLan_FreeLists( struct net_device * );
315static void TLan_PrintDio( u16 );
316static void TLan_PrintList( TLanList *, char *, int );
317static void TLan_ReadAndClearStats( struct net_device *, int );
318static void TLan_ResetAdapter( struct net_device * );
319static void TLan_FinishReset( struct net_device * );
320static void TLan_SetMac( struct net_device *, int areg, char *mac );
321
322static void TLan_PhyPrint( struct net_device * );
323static void TLan_PhyDetect( struct net_device * );
324static void TLan_PhyPowerDown( struct net_device * );
325static void TLan_PhyPowerUp( struct net_device * );
326static void TLan_PhyReset( struct net_device * );
327static void TLan_PhyStartLink( struct net_device * );
328static void TLan_PhyFinishAutoNeg( struct net_device * );
329#ifdef MONITOR
330static void TLan_PhyMonitor( struct net_device * );
331#endif
332
333/*
334static int TLan_PhyNop( struct net_device * );
335static int TLan_PhyInternalCheck( struct net_device * );
336static int TLan_PhyInternalService( struct net_device * );
337static int TLan_PhyDp83840aCheck( struct net_device * );
338*/
339
340static int TLan_MiiReadReg( struct net_device *, u16, u16, u16 * );
341static void TLan_MiiSendData( u16, u32, unsigned );
342static void TLan_MiiSync( u16 );
343static void TLan_MiiWriteReg( struct net_device *, u16, u16, u16 );
344
345static void TLan_EeSendStart( u16 );
346static int TLan_EeSendByte( u16, u8, int );
347static void TLan_EeReceiveByte( u16, u8 *, int );
348static int TLan_EeReadByte( struct net_device *, u8, u8 * );
349
350
Stephen Hemminger93e16842008-05-30 09:49:55 -0700351static inline void
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352TLan_StoreSKB( struct tlan_list_tag *tag, struct sk_buff *skb)
353{
354 unsigned long addr = (unsigned long)skb;
Stephen Hemminger93e16842008-05-30 09:49:55 -0700355 tag->buffer[9].address = addr;
356 tag->buffer[8].address = upper_32_bits(addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357}
358
Stephen Hemminger93e16842008-05-30 09:49:55 -0700359static inline struct sk_buff *
360TLan_GetSKB( const struct tlan_list_tag *tag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361{
Stephen Hemminger93e16842008-05-30 09:49:55 -0700362 unsigned long addr;
363
Robert Fitzsimons0d63bea2008-08-09 17:54:02 +0100364 addr = tag->buffer[9].address;
365 addr |= (tag->buffer[8].address << 16) << 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 return (struct sk_buff *) addr;
367}
368
369
370static TLanIntVectorFunc *TLanIntVector[TLAN_INT_NUMBER_OF_INTS] = {
Stephen Hemmingera3ccc782008-05-30 09:49:57 -0700371 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 TLan_HandleTxEOF,
373 TLan_HandleStatOverflow,
374 TLan_HandleRxEOF,
375 TLan_HandleDummy,
376 TLan_HandleTxEOC,
377 TLan_HandleStatusCheck,
378 TLan_HandleRxEOC
379};
380
381static inline void
382TLan_SetTimer( struct net_device *dev, u32 ticks, u32 type )
383{
384 TLanPrivateInfo *priv = netdev_priv(dev);
385 unsigned long flags = 0;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400386
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 if (!in_irq())
388 spin_lock_irqsave(&priv->lock, flags);
389 if ( priv->timer.function != NULL &&
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400390 priv->timerType != TLAN_TIMER_ACTIVITY ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 if (!in_irq())
392 spin_unlock_irqrestore(&priv->lock, flags);
393 return;
394 }
395 priv->timer.function = &TLan_Timer;
396 if (!in_irq())
397 spin_unlock_irqrestore(&priv->lock, flags);
398
399 priv->timer.data = (unsigned long) dev;
400 priv->timerSetAt = jiffies;
401 priv->timerType = type;
402 mod_timer(&priv->timer, jiffies + ticks);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400403
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404} /* TLan_SetTimer */
405
406
407/*****************************************************************************
408******************************************************************************
409
410 ThunderLAN Driver Primary Functions
411
412 These functions are more or less common to all Linux network drivers.
413
414******************************************************************************
415*****************************************************************************/
416
417
418
419
420
421 /***************************************************************
422 * tlan_remove_one
423 *
424 * Returns:
425 * Nothing
426 * Parms:
427 * None
428 *
429 * Goes through the TLanDevices list and frees the device
430 * structs and memory associated with each device (lists
431 * and buffers). It also ureserves the IO port regions
432 * associated with this device.
433 *
434 **************************************************************/
435
436
437static void __devexit tlan_remove_one( struct pci_dev *pdev)
438{
439 struct net_device *dev = pci_get_drvdata( pdev );
440 TLanPrivateInfo *priv = netdev_priv(dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400441
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 unregister_netdev( dev );
443
444 if ( priv->dmaStorage ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700445 pci_free_consistent(priv->pciDev,
446 priv->dmaSize, priv->dmaStorage,
447 priv->dmaStorageDMA );
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 }
449
450#ifdef CONFIG_PCI
451 pci_release_regions(pdev);
452#endif
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400453
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 free_netdev( dev );
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400455
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 pci_set_drvdata( pdev, NULL );
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400457}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458
459static struct pci_driver tlan_driver = {
460 .name = "tlan",
461 .id_table = tlan_pci_tbl,
462 .probe = tlan_init_one,
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400463 .remove = __devexit_p(tlan_remove_one),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464};
465
466static int __init tlan_probe(void)
467{
Leonardo Potenza6c04a512008-02-04 23:47:16 -0800468 int rc = -ENODEV;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400469
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 printk(KERN_INFO "%s", tlan_banner);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400471
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 TLAN_DBG(TLAN_DEBUG_PROBE, "Starting PCI Probe....\n");
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400473
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 /* Use new style PCI probing. Now the kernel will
475 do most of this for us */
Leonardo Potenza6c04a512008-02-04 23:47:16 -0800476 rc = pci_register_driver(&tlan_driver);
477
478 if (rc != 0) {
479 printk(KERN_ERR "TLAN: Could not register pci driver.\n");
480 goto err_out_pci_free;
481 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482
483 TLAN_DBG(TLAN_DEBUG_PROBE, "Starting EISA Probe....\n");
484 TLan_EisaProbe();
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400485
486 printk(KERN_INFO "TLAN: %d device%s installed, PCI: %d EISA: %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 TLanDevicesInstalled, TLanDevicesInstalled == 1 ? "" : "s",
488 tlan_have_pci, tlan_have_eisa);
489
490 if (TLanDevicesInstalled == 0) {
Leonardo Potenza6c04a512008-02-04 23:47:16 -0800491 rc = -ENODEV;
492 goto err_out_pci_unreg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 }
494 return 0;
Leonardo Potenza6c04a512008-02-04 23:47:16 -0800495
496err_out_pci_unreg:
497 pci_unregister_driver(&tlan_driver);
498err_out_pci_free:
Leonardo Potenza6c04a512008-02-04 23:47:16 -0800499 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500}
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400501
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
503static int __devinit tlan_init_one( struct pci_dev *pdev,
504 const struct pci_device_id *ent)
505{
506 return TLan_probe1( pdev, -1, -1, 0, ent);
507}
508
509
510/*
511 ***************************************************************
512 * tlan_probe1
513 *
514 * Returns:
515 * 0 on success, error code on error
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400516 * Parms:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 * none
518 *
519 * The name is lower case to fit in with all the rest of
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400520 * the netcard_probe names. This function looks for
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 * another TLan based adapter, setting it up with the
522 * allocated device struct if one is found.
523 * tlan_probe has been ported to the new net API and
524 * now allocates its own device structure. This function
525 * is also used by modules.
526 *
527 **************************************************************/
528
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400529static int __devinit TLan_probe1(struct pci_dev *pdev,
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700530 long ioaddr, int irq, int rev,
531 const struct pci_device_id *ent )
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532{
533
534 struct net_device *dev;
535 TLanPrivateInfo *priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 u16 device_id;
537 int reg, rc = -ENODEV;
538
Adrian Bunkad9f6712006-02-05 00:37:47 +0100539#ifdef CONFIG_PCI
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 if (pdev) {
541 rc = pci_enable_device(pdev);
542 if (rc)
543 return rc;
544
545 rc = pci_request_regions(pdev, TLanSignature);
546 if (rc) {
547 printk(KERN_ERR "TLAN: Could not reserve IO regions\n");
548 goto err_out;
549 }
550 }
Adrian Bunkad9f6712006-02-05 00:37:47 +0100551#endif /* CONFIG_PCI */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552
553 dev = alloc_etherdev(sizeof(TLanPrivateInfo));
554 if (dev == NULL) {
555 printk(KERN_ERR "TLAN: Could not allocate memory for device.\n");
556 rc = -ENOMEM;
557 goto err_out_regions;
558 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 SET_NETDEV_DEV(dev, &pdev->dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400560
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 priv = netdev_priv(dev);
562
563 priv->pciDev = pdev;
David Howellsc4028952006-11-22 14:57:56 +0000564 priv->dev = dev;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400565
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 /* Is this a PCI device? */
567 if (pdev) {
568 u32 pci_io_base = 0;
569
570 priv->adapter = &board_info[ent->driver_data];
571
Domen Puncer1e7f0bd2005-06-26 18:22:14 -0400572 rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 if (rc) {
574 printk(KERN_ERR "TLAN: No suitable PCI mapping available.\n");
575 goto err_out_free_dev;
576 }
577
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 for ( reg= 0; reg <= 5; reg ++ ) {
579 if (pci_resource_flags(pdev, reg) & IORESOURCE_IO) {
580 pci_io_base = pci_resource_start(pdev, reg);
581 TLAN_DBG( TLAN_DEBUG_GNRL, "IO mapping is available at %x.\n",
582 pci_io_base);
583 break;
584 }
585 }
586 if (!pci_io_base) {
587 printk(KERN_ERR "TLAN: No IO mappings available\n");
588 rc = -EIO;
589 goto err_out_free_dev;
590 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400591
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 dev->base_addr = pci_io_base;
593 dev->irq = pdev->irq;
Auke Kok44c10132007-06-08 15:46:36 -0700594 priv->adapterRev = pdev->revision;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 pci_set_master(pdev);
596 pci_set_drvdata(pdev, dev);
597
598 } else { /* EISA card */
599 /* This is a hack. We need to know which board structure
600 * is suited for this adapter */
601 device_id = inw(ioaddr + EISA_ID2);
602 priv->is_eisa = 1;
603 if (device_id == 0x20F1) {
604 priv->adapter = &board_info[13]; /* NetFlex-3/E */
605 priv->adapterRev = 23; /* TLAN 2.3 */
606 } else {
607 priv->adapter = &board_info[14];
608 priv->adapterRev = 10; /* TLAN 1.0 */
609 }
610 dev->base_addr = ioaddr;
611 dev->irq = irq;
612 }
613
614 /* Kernel parameters */
615 if (dev->mem_start) {
616 priv->aui = dev->mem_start & 0x01;
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700617 priv->duplex = ((dev->mem_start & 0x06) == 0x06) ? 0
618 : (dev->mem_start & 0x06) >> 1;
619 priv->speed = ((dev->mem_start & 0x18) == 0x18) ? 0
620 : (dev->mem_start & 0x18) >> 3;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400621
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 if (priv->speed == 0x1) {
623 priv->speed = TLAN_SPEED_10;
624 } else if (priv->speed == 0x2) {
625 priv->speed = TLAN_SPEED_100;
626 }
627 debug = priv->debug = dev->mem_end;
628 } else {
629 priv->aui = aui[boards_found];
630 priv->speed = speed[boards_found];
631 priv->duplex = duplex[boards_found];
632 priv->debug = debug;
633 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400634
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 /* This will be used when we get an adapter error from
636 * within our irq handler */
David Howellsc4028952006-11-22 14:57:56 +0000637 INIT_WORK(&priv->tlan_tqueue, TLan_tx_timeout_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638
639 spin_lock_init(&priv->lock);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400640
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 rc = TLan_Init(dev);
642 if (rc) {
643 printk(KERN_ERR "TLAN: Could not set up device.\n");
644 goto err_out_free_dev;
645 }
646
647 rc = register_netdev(dev);
648 if (rc) {
649 printk(KERN_ERR "TLAN: Could not register device.\n");
650 goto err_out_uninit;
651 }
652
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400653
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 TLanDevicesInstalled++;
655 boards_found++;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400656
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 /* pdev is NULL if this is an EISA device */
658 if (pdev)
659 tlan_have_pci++;
660 else {
661 priv->nextDevice = TLan_Eisa_Devices;
662 TLan_Eisa_Devices = dev;
663 tlan_have_eisa++;
664 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400665
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 printk(KERN_INFO "TLAN: %s irq=%2d, io=%04x, %s, Rev. %d\n",
667 dev->name,
668 (int) dev->irq,
669 (int) dev->base_addr,
670 priv->adapter->deviceLabel,
671 priv->adapterRev);
672 return 0;
673
674err_out_uninit:
675 pci_free_consistent(priv->pciDev, priv->dmaSize, priv->dmaStorage,
676 priv->dmaStorageDMA );
677err_out_free_dev:
678 free_netdev(dev);
679err_out_regions:
680#ifdef CONFIG_PCI
681 if (pdev)
682 pci_release_regions(pdev);
683#endif
684err_out:
685 if (pdev)
686 pci_disable_device(pdev);
687 return rc;
688}
689
690
691static void TLan_Eisa_Cleanup(void)
692{
693 struct net_device *dev;
694 TLanPrivateInfo *priv;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400695
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 while( tlan_have_eisa ) {
697 dev = TLan_Eisa_Devices;
698 priv = netdev_priv(dev);
699 if (priv->dmaStorage) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700700 pci_free_consistent(priv->pciDev, priv->dmaSize,
701 priv->dmaStorage, priv->dmaStorageDMA );
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 }
703 release_region( dev->base_addr, 0x10);
704 unregister_netdev( dev );
705 TLan_Eisa_Devices = priv->nextDevice;
706 free_netdev( dev );
707 tlan_have_eisa--;
708 }
709}
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400710
711
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712static void __exit tlan_exit(void)
713{
714 pci_unregister_driver(&tlan_driver);
715
716 if (tlan_have_eisa)
717 TLan_Eisa_Cleanup();
718
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719}
720
721
722/* Module loading/unloading */
723module_init(tlan_probe);
724module_exit(tlan_exit);
725
726
727
728 /**************************************************************
729 * TLan_EisaProbe
730 *
731 * Returns: 0 on success, 1 otherwise
732 *
733 * Parms: None
734 *
735 *
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400736 * This functions probes for EISA devices and calls
737 * TLan_probe1 when one is found.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 *
739 *************************************************************/
740
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400741static void __init TLan_EisaProbe (void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742{
743 long ioaddr;
744 int rc = -ENODEV;
745 int irq;
746 u16 device_id;
747
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400748 if (!EISA_bus) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 TLAN_DBG(TLAN_DEBUG_PROBE, "No EISA bus present\n");
750 return;
751 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400752
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 /* Loop through all slots of the EISA bus */
754 for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400755
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700756 TLAN_DBG(TLAN_DEBUG_PROBE,"EISA_ID 0x%4x: 0x%4x\n",
757 (int) ioaddr + 0xC80, inw(ioaddr + EISA_ID));
758 TLAN_DBG(TLAN_DEBUG_PROBE,"EISA_ID 0x%4x: 0x%4x\n",
759 (int) ioaddr + 0xC82, inw(ioaddr + EISA_ID2));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760
761
762 TLAN_DBG(TLAN_DEBUG_PROBE, "Probing for EISA adapter at IO: 0x%4x : ",
763 (int) ioaddr);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400764 if (request_region(ioaddr, 0x10, TLanSignature) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 goto out;
766
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400767 if (inw(ioaddr + EISA_ID) != 0x110E) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 release_region(ioaddr, 0x10);
769 goto out;
770 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400771
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 device_id = inw(ioaddr + EISA_ID2);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400773 if (device_id != 0x20F1 && device_id != 0x40F1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 release_region (ioaddr, 0x10);
775 goto out;
776 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400777
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 if (inb(ioaddr + EISA_CR) != 0x1) { /* Check if adapter is enabled */
779 release_region (ioaddr, 0x10);
780 goto out2;
781 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400782
783 if (debug == 0x10)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 printk("Found one\n");
785
786
787 /* Get irq from board */
788 switch (inb(ioaddr + 0xCC0)) {
789 case(0x10):
790 irq=5;
791 break;
792 case(0x20):
793 irq=9;
794 break;
795 case(0x40):
796 irq=10;
797 break;
798 case(0x80):
799 irq=11;
800 break;
801 default:
802 goto out;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400803 }
804
805
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 /* Setup the newly found eisa adapter */
807 rc = TLan_probe1( NULL, ioaddr, irq,
808 12, NULL);
809 continue;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400810
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 out:
812 if (debug == 0x10)
813 printk("None found\n");
814 continue;
815
816 out2: if (debug == 0x10)
817 printk("Card found but it is not enabled, skipping\n");
818 continue;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400819
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 }
821
822} /* TLan_EisaProbe */
823
824#ifdef CONFIG_NET_POLL_CONTROLLER
825static void TLan_Poll(struct net_device *dev)
826{
827 disable_irq(dev->irq);
David Howells7d12e782006-10-05 14:55:46 +0100828 TLan_HandleInterrupt(dev->irq, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 enable_irq(dev->irq);
830}
831#endif
832
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400833
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834
835
836 /***************************************************************
837 * TLan_Init
838 *
839 * Returns:
840 * 0 on success, error code otherwise.
841 * Parms:
842 * dev The structure of the device to be
843 * init'ed.
844 *
845 * This function completes the initialization of the
846 * device structure and driver. It reserves the IO
847 * addresses, allocates memory for the lists and bounce
848 * buffers, retrieves the MAC address from the eeprom
849 * and assignes the device's methods.
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400850 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 **************************************************************/
852
853static int TLan_Init( struct net_device *dev )
854{
855 int dma_size;
856 int err;
857 int i;
858 TLanPrivateInfo *priv;
859
860 priv = netdev_priv(dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400861
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 if ( bbuf ) {
863 dma_size = ( TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS )
864 * ( sizeof(TLanList) + TLAN_MAX_FRAME_SIZE );
865 } else {
866 dma_size = ( TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS )
867 * ( sizeof(TLanList) );
868 }
Stephen Hemminger93e16842008-05-30 09:49:55 -0700869 priv->dmaStorage = pci_alloc_consistent(priv->pciDev,
870 dma_size, &priv->dmaStorageDMA);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 priv->dmaSize = dma_size;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400872
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 if ( priv->dmaStorage == NULL ) {
874 printk(KERN_ERR "TLAN: Could not allocate lists and buffers for %s.\n",
875 dev->name );
876 return -ENOMEM;
877 }
878 memset( priv->dmaStorage, 0, dma_size );
Stephen Hemminger93e16842008-05-30 09:49:55 -0700879 priv->rxList = (TLanList *) ALIGN((unsigned long)priv->dmaStorage, 8);
880 priv->rxListDMA = ALIGN(priv->dmaStorageDMA, 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 priv->txList = priv->rxList + TLAN_NUM_RX_LISTS;
882 priv->txListDMA = priv->rxListDMA + sizeof(TLanList) * TLAN_NUM_RX_LISTS;
Stephen Hemminger93e16842008-05-30 09:49:55 -0700883
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 if ( bbuf ) {
885 priv->rxBuffer = (u8 *) ( priv->txList + TLAN_NUM_TX_LISTS );
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700886 priv->rxBufferDMA =priv->txListDMA
887 + sizeof(TLanList) * TLAN_NUM_TX_LISTS;
888 priv->txBuffer = priv->rxBuffer
889 + ( TLAN_NUM_RX_LISTS * TLAN_MAX_FRAME_SIZE );
890 priv->txBufferDMA = priv->rxBufferDMA
891 + ( TLAN_NUM_RX_LISTS * TLAN_MAX_FRAME_SIZE );
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 }
893
894 err = 0;
895 for ( i = 0; i < 6 ; i++ )
896 err |= TLan_EeReadByte( dev,
897 (u8) priv->adapter->addrOfs + i,
898 (u8 *) &dev->dev_addr[i] );
899 if ( err ) {
900 printk(KERN_ERR "TLAN: %s: Error reading MAC from eeprom: %d\n",
901 dev->name,
902 err );
903 }
904 dev->addr_len = 6;
905
906 netif_carrier_off(dev);
907
908 /* Device methods */
909 dev->open = &TLan_Open;
910 dev->hard_start_xmit = &TLan_StartTx;
911 dev->stop = &TLan_Close;
912 dev->get_stats = &TLan_GetStats;
913 dev->set_multicast_list = &TLan_SetMulticastList;
914 dev->do_ioctl = &TLan_ioctl;
915#ifdef CONFIG_NET_POLL_CONTROLLER
916 dev->poll_controller = &TLan_Poll;
917#endif
918 dev->tx_timeout = &TLan_tx_timeout;
919 dev->watchdog_timeo = TX_TIMEOUT;
920
921 return 0;
922
923} /* TLan_Init */
924
925
926
927
928 /***************************************************************
929 * TLan_Open
930 *
931 * Returns:
932 * 0 on success, error code otherwise.
933 * Parms:
934 * dev Structure of device to be opened.
935 *
936 * This routine puts the driver and TLAN adapter in a
937 * state where it is ready to send and receive packets.
938 * It allocates the IRQ, resets and brings the adapter
939 * out of reset, and allows interrupts. It also delays
940 * the startup for autonegotiation or sends a Rx GO
941 * command to the adapter, as appropriate.
942 *
943 **************************************************************/
944
945static int TLan_Open( struct net_device *dev )
946{
947 TLanPrivateInfo *priv = netdev_priv(dev);
948 int err;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400949
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 priv->tlanRev = TLan_DioRead8( dev->base_addr, TLAN_DEF_REVISION );
Stephen Hemmingera3ccc782008-05-30 09:49:57 -0700951 err = request_irq( dev->irq, TLan_HandleInterrupt, IRQF_SHARED,
952 dev->name, dev );
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400953
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 if ( err ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700955 pr_err("TLAN: Cannot open %s because IRQ %d is already in use.\n",
956 dev->name, dev->irq );
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 return err;
958 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400959
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 init_timer(&priv->timer);
961 netif_start_queue(dev);
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400962
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 /* NOTE: It might not be necessary to read the stats before a
964 reset if you don't care what the values are.
965 */
966 TLan_ResetLists( dev );
967 TLan_ReadAndClearStats( dev, TLAN_IGNORE );
968 TLan_ResetAdapter( dev );
969
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -0700970 TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Opened. TLAN Chip Rev: %x\n",
971 dev->name, priv->tlanRev );
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972
973 return 0;
974
975} /* TLan_Open */
976
977
978
979 /**************************************************************
980 * TLan_ioctl
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400981 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 * Returns:
983 * 0 on success, error code otherwise
984 * Params:
985 * dev structure of device to receive ioctl.
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400986 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 * rq ifreq structure to hold userspace data.
988 *
989 * cmd ioctl command.
990 *
991 *
992 *************************************************************/
993
994static int TLan_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
995{
996 TLanPrivateInfo *priv = netdev_priv(dev);
997 struct mii_ioctl_data *data = if_mii(rq);
998 u32 phy = priv->phy[priv->phyNum];
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400999
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 if (!priv->phyOnline)
1001 return -EAGAIN;
1002
1003 switch(cmd) {
1004 case SIOCGMIIPHY: /* Get address of MII PHY in use. */
1005 data->phy_id = phy;
1006
1007
1008 case SIOCGMIIREG: /* Read MII PHY register. */
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001009 TLan_MiiReadReg(dev, data->phy_id & 0x1f,
1010 data->reg_num & 0x1f, &data->val_out);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 return 0;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001012
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013
1014 case SIOCSMIIREG: /* Write MII PHY register. */
1015 if (!capable(CAP_NET_ADMIN))
1016 return -EPERM;
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001017 TLan_MiiWriteReg(dev, data->phy_id & 0x1f,
1018 data->reg_num & 0x1f, data->val_in);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 return 0;
1020 default:
1021 return -EOPNOTSUPP;
1022 }
1023} /* tlan_ioctl */
1024
1025
1026 /***************************************************************
1027 * TLan_tx_timeout
1028 *
1029 * Returns: nothing
1030 *
1031 * Params:
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001032 * dev structure of device which timed out
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 * during transmit.
1034 *
1035 **************************************************************/
1036
1037static void TLan_tx_timeout(struct net_device *dev)
1038{
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001039
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Transmit timed out.\n", dev->name);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001041
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 /* Ok so we timed out, lets see what we can do about it...*/
1043 TLan_FreeLists( dev );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001044 TLan_ResetLists( dev );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 TLan_ReadAndClearStats( dev, TLAN_IGNORE );
1046 TLan_ResetAdapter( dev );
1047 dev->trans_start = jiffies;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001048 netif_wake_queue( dev );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049
1050}
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001051
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052
David Howellsc4028952006-11-22 14:57:56 +00001053 /***************************************************************
1054 * TLan_tx_timeout_work
1055 *
1056 * Returns: nothing
1057 *
1058 * Params:
1059 * work work item of device which timed out
1060 *
1061 **************************************************************/
1062
1063static void TLan_tx_timeout_work(struct work_struct *work)
1064{
1065 TLanPrivateInfo *priv =
1066 container_of(work, TLanPrivateInfo, tlan_tqueue);
1067
1068 TLan_tx_timeout(priv->dev);
1069}
1070
1071
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072
1073 /***************************************************************
1074 * TLan_StartTx
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001075 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 * Returns:
1077 * 0 on success, non-zero on failure.
1078 * Parms:
1079 * skb A pointer to the sk_buff containing the
1080 * frame to be sent.
1081 * dev The device to send the data on.
1082 *
1083 * This function adds a frame to the Tx list to be sent
1084 * ASAP. First it verifies that the adapter is ready and
1085 * there is room in the queue. Then it sets up the next
1086 * available list, copies the frame to the corresponding
1087 * buffer. If the adapter Tx channel is idle, it gives
1088 * the adapter a Tx Go command on the list, otherwise it
1089 * sets the forward address of the previous list to point
1090 * to this one. Then it frees the sk_buff.
1091 *
1092 **************************************************************/
1093
1094static int TLan_StartTx( struct sk_buff *skb, struct net_device *dev )
1095{
1096 TLanPrivateInfo *priv = netdev_priv(dev);
1097 TLanList *tail_list;
1098 dma_addr_t tail_list_phys;
1099 u8 *tail_buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 unsigned long flags;
Sakari Ailus8953f122008-12-16 01:44:05 -08001101 unsigned int txlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102
1103 if ( ! priv->phyOnline ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001104 TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT: %s PHY is not ready\n",
1105 dev->name );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 dev_kfree_skb_any(skb);
1107 return 0;
1108 }
1109
Stephen Hemminger41873e92008-05-30 09:49:52 -07001110 if (skb_padto(skb, TLAN_MIN_FRAME_SIZE))
1111 return 0;
Sakari Ailus8953f122008-12-16 01:44:05 -08001112 txlen = max(skb->len, (unsigned int)TLAN_MIN_FRAME_SIZE);
Stephen Hemminger41873e92008-05-30 09:49:52 -07001113
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 tail_list = priv->txList + priv->txTail;
1115 tail_list_phys = priv->txListDMA + sizeof(TLanList) * priv->txTail;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001116
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 if ( tail_list->cStat != TLAN_CSTAT_UNUSED ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001118 TLAN_DBG( TLAN_DEBUG_TX,
1119 "TRANSMIT: %s is busy (Head=%d Tail=%d)\n",
1120 dev->name, priv->txHead, priv->txTail );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 netif_stop_queue(dev);
1122 priv->txBusyCount++;
1123 return 1;
1124 }
1125
1126 tail_list->forward = 0;
1127
1128 if ( bbuf ) {
1129 tail_buffer = priv->txBuffer + ( priv->txTail * TLAN_MAX_FRAME_SIZE );
Sakari Ailus8953f122008-12-16 01:44:05 -08001130 skb_copy_from_linear_data(skb, tail_buffer, txlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 } else {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001132 tail_list->buffer[0].address = pci_map_single(priv->pciDev,
Sakari Ailus8953f122008-12-16 01:44:05 -08001133 skb->data, txlen,
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001134 PCI_DMA_TODEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 TLan_StoreSKB(tail_list, skb);
1136 }
1137
Sakari Ailus8953f122008-12-16 01:44:05 -08001138 tail_list->frameSize = (u16) txlen;
1139 tail_list->buffer[0].count = TLAN_LAST_BUFFER | (u32) txlen;
Stephen Hemminger41873e92008-05-30 09:49:52 -07001140 tail_list->buffer[1].count = 0;
1141 tail_list->buffer[1].address = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
1143 spin_lock_irqsave(&priv->lock, flags);
1144 tail_list->cStat = TLAN_CSTAT_READY;
1145 if ( ! priv->txInProgress ) {
1146 priv->txInProgress = 1;
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001147 TLAN_DBG( TLAN_DEBUG_TX,
1148 "TRANSMIT: Starting TX on buffer %d\n", priv->txTail );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 outl( tail_list_phys, dev->base_addr + TLAN_CH_PARM );
1150 outl( TLAN_HC_GO, dev->base_addr + TLAN_HOST_CMD );
1151 } else {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001152 TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT: Adding buffer %d to TX channel\n",
1153 priv->txTail );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 if ( priv->txTail == 0 ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001155 ( priv->txList + ( TLAN_NUM_TX_LISTS - 1 ) )->forward
1156 = tail_list_phys;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 } else {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001158 ( priv->txList + ( priv->txTail - 1 ) )->forward
1159 = tail_list_phys;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 }
1161 }
1162 spin_unlock_irqrestore(&priv->lock, flags);
1163
1164 CIRC_INC( priv->txTail, TLAN_NUM_TX_LISTS );
1165
1166 if ( bbuf )
1167 dev_kfree_skb_any(skb);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001168
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 dev->trans_start = jiffies;
1170 return 0;
1171
1172} /* TLan_StartTx */
1173
1174
1175
1176
1177 /***************************************************************
1178 * TLan_HandleInterrupt
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001179 *
1180 * Returns:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 * Nothing
1182 * Parms:
1183 * irq The line on which the interrupt
1184 * occurred.
1185 * dev_id A pointer to the device assigned to
1186 * this irq line.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 *
1188 * This function handles an interrupt generated by its
1189 * assigned TLAN adapter. The function deactivates
1190 * interrupts on its adapter, records the type of
1191 * interrupt, executes the appropriate subhandler, and
1192 * acknowdges the interrupt to the adapter (thus
1193 * re-enabling adapter interrupts.
1194 *
1195 **************************************************************/
1196
David Howells7d12e782006-10-05 14:55:46 +01001197static irqreturn_t TLan_HandleInterrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198{
Stephen Hemmingera3ccc782008-05-30 09:49:57 -07001199 struct net_device *dev = dev_id;
1200 TLanPrivateInfo *priv = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 u16 host_int;
Stephen Hemmingera3ccc782008-05-30 09:49:57 -07001202 u16 type;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203
1204 spin_lock(&priv->lock);
1205
1206 host_int = inw( dev->base_addr + TLAN_HOST_INT );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 type = ( host_int & TLAN_HI_IT_MASK ) >> 2;
Stephen Hemmingera3ccc782008-05-30 09:49:57 -07001208 if ( type ) {
1209 u32 ack;
1210 u32 host_cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211
Stephen Hemmingera3ccc782008-05-30 09:49:57 -07001212 outw( host_int, dev->base_addr + TLAN_HOST_INT );
1213 ack = TLanIntVector[type]( dev, host_int );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214
Stephen Hemmingera3ccc782008-05-30 09:49:57 -07001215 if ( ack ) {
1216 host_cmd = TLAN_HC_ACK | ack | ( type << 18 );
1217 outl( host_cmd, dev->base_addr + TLAN_HOST_CMD );
1218 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 }
1220
1221 spin_unlock(&priv->lock);
1222
Stephen Hemmingera3ccc782008-05-30 09:49:57 -07001223 return IRQ_RETVAL(type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224} /* TLan_HandleInterrupts */
1225
1226
1227
1228
1229 /***************************************************************
1230 * TLan_Close
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001231 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 * Returns:
1233 * An error code.
1234 * Parms:
1235 * dev The device structure of the device to
1236 * close.
1237 *
1238 * This function shuts down the adapter. It records any
1239 * stats, puts the adapter into reset state, deactivates
1240 * its time as needed, and frees the irq it is using.
1241 *
1242 **************************************************************/
1243
1244static int TLan_Close(struct net_device *dev)
1245{
1246 TLanPrivateInfo *priv = netdev_priv(dev);
1247
1248 netif_stop_queue(dev);
1249 priv->neg_be_verbose = 0;
1250
1251 TLan_ReadAndClearStats( dev, TLAN_RECORD );
1252 outl( TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD );
1253 if ( priv->timer.function != NULL ) {
1254 del_timer_sync( &priv->timer );
1255 priv->timer.function = NULL;
1256 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001257
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 free_irq( dev->irq, dev );
1259 TLan_FreeLists( dev );
1260 TLAN_DBG( TLAN_DEBUG_GNRL, "Device %s closed.\n", dev->name );
1261
1262 return 0;
1263
1264} /* TLan_Close */
1265
1266
1267
1268
1269 /***************************************************************
1270 * TLan_GetStats
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001271 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 * Returns:
1273 * A pointer to the device's statistics structure.
1274 * Parms:
1275 * dev The device structure to return the
1276 * stats for.
1277 *
1278 * This function updates the devices statistics by reading
1279 * the TLAN chip's onboard registers. Then it returns the
1280 * address of the statistics structure.
1281 *
1282 **************************************************************/
1283
1284static struct net_device_stats *TLan_GetStats( struct net_device *dev )
1285{
1286 TLanPrivateInfo *priv = netdev_priv(dev);
1287 int i;
1288
1289 /* Should only read stats if open ? */
1290 TLan_ReadAndClearStats( dev, TLAN_RECORD );
1291
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001292 TLAN_DBG( TLAN_DEBUG_RX, "RECEIVE: %s EOC count = %d\n", dev->name,
1293 priv->rxEocCount );
1294 TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT: %s Busy count = %d\n", dev->name,
1295 priv->txBusyCount );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 if ( debug & TLAN_DEBUG_GNRL ) {
1297 TLan_PrintDio( dev->base_addr );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001298 TLan_PhyPrint( dev );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 }
1300 if ( debug & TLAN_DEBUG_LIST ) {
1301 for ( i = 0; i < TLAN_NUM_RX_LISTS; i++ )
1302 TLan_PrintList( priv->rxList + i, "RX", i );
1303 for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ )
1304 TLan_PrintList( priv->txList + i, "TX", i );
1305 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001306
Stephen Hemmingerf8f31542008-05-30 09:49:53 -07001307 return &dev->stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308
1309} /* TLan_GetStats */
1310
1311
1312
1313
1314 /***************************************************************
1315 * TLan_SetMulticastList
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001316 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 * Returns:
1318 * Nothing
1319 * Parms:
1320 * dev The device structure to set the
1321 * multicast list for.
1322 *
1323 * This function sets the TLAN adaptor to various receive
1324 * modes. If the IFF_PROMISC flag is set, promiscuous
1325 * mode is acitviated. Otherwise, promiscuous mode is
1326 * turned off. If the IFF_ALLMULTI flag is set, then
1327 * the hash table is set to receive all group addresses.
1328 * Otherwise, the first three multicast addresses are
1329 * stored in AREG_1-3, and the rest are selected via the
1330 * hash table, as necessary.
1331 *
1332 **************************************************************/
1333
1334static void TLan_SetMulticastList( struct net_device *dev )
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001335{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 struct dev_mc_list *dmi = dev->mc_list;
1337 u32 hash1 = 0;
1338 u32 hash2 = 0;
1339 int i;
1340 u32 offset;
1341 u8 tmp;
1342
1343 if ( dev->flags & IFF_PROMISC ) {
1344 tmp = TLan_DioRead8( dev->base_addr, TLAN_NET_CMD );
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001345 TLan_DioWrite8( dev->base_addr,
1346 TLAN_NET_CMD, tmp | TLAN_NET_CMD_CAF );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 } else {
1348 tmp = TLan_DioRead8( dev->base_addr, TLAN_NET_CMD );
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001349 TLan_DioWrite8( dev->base_addr,
1350 TLAN_NET_CMD, tmp & ~TLAN_NET_CMD_CAF );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 if ( dev->flags & IFF_ALLMULTI ) {
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001352 for ( i = 0; i < 3; i++ )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 TLan_SetMac( dev, i + 1, NULL );
1354 TLan_DioWrite32( dev->base_addr, TLAN_HASH_1, 0xFFFFFFFF );
1355 TLan_DioWrite32( dev->base_addr, TLAN_HASH_2, 0xFFFFFFFF );
1356 } else {
1357 for ( i = 0; i < dev->mc_count; i++ ) {
1358 if ( i < 3 ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001359 TLan_SetMac( dev, i + 1,
1360 (char *) &dmi->dmi_addr );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 } else {
1362 offset = TLan_HashFunc( (u8 *) &dmi->dmi_addr );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001363 if ( offset < 32 )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 hash1 |= ( 1 << offset );
1365 else
1366 hash2 |= ( 1 << ( offset - 32 ) );
1367 }
1368 dmi = dmi->next;
1369 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001370 for ( ; i < 3; i++ )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 TLan_SetMac( dev, i + 1, NULL );
1372 TLan_DioWrite32( dev->base_addr, TLAN_HASH_1, hash1 );
1373 TLan_DioWrite32( dev->base_addr, TLAN_HASH_2, hash2 );
1374 }
1375 }
1376
1377} /* TLan_SetMulticastList */
1378
1379
1380
1381/*****************************************************************************
1382******************************************************************************
1383
1384 ThunderLAN Driver Interrupt Vectors and Table
1385
1386 Please see Chap. 4, "Interrupt Handling" of the "ThunderLAN
1387 Programmer's Guide" for more informations on handling interrupts
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001388 generated by TLAN based adapters.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389
1390******************************************************************************
1391*****************************************************************************/
1392
1393
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394
1395
1396 /***************************************************************
1397 * TLan_HandleTxEOF
1398 *
1399 * Returns:
1400 * 1
1401 * Parms:
1402 * dev Device assigned the IRQ that was
1403 * raised.
1404 * host_int The contents of the HOST_INT
1405 * port.
1406 *
1407 * This function handles Tx EOF interrupts which are raised
1408 * by the adapter when it has completed sending the
1409 * contents of a buffer. If detemines which list/buffer
1410 * was completed and resets it. If the buffer was the last
1411 * in the channel (EOC), then the function checks to see if
1412 * another buffer is ready to send, and if so, sends a Tx
1413 * Go command. Finally, the driver activates/continues the
1414 * activity LED.
1415 *
1416 **************************************************************/
1417
Harvey Harrison98e0f522008-02-18 10:04:38 -08001418static u32 TLan_HandleTxEOF( struct net_device *dev, u16 host_int )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419{
1420 TLanPrivateInfo *priv = netdev_priv(dev);
1421 int eoc = 0;
1422 TLanList *head_list;
1423 dma_addr_t head_list_phys;
1424 u32 ack = 0;
1425 u16 tmpCStat;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001426
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001427 TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT: Handling TX EOF (Head=%d Tail=%d)\n",
1428 priv->txHead, priv->txTail );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 head_list = priv->txList + priv->txHead;
1430
1431 while (((tmpCStat = head_list->cStat ) & TLAN_CSTAT_FRM_CMP) && (ack < 255)) {
1432 ack++;
1433 if ( ! bbuf ) {
1434 struct sk_buff *skb = TLan_GetSKB(head_list);
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001435 pci_unmap_single(priv->pciDev, head_list->buffer[0].address,
Sakari Ailusbb5f1332008-12-16 15:22:41 -08001436 max(skb->len,
1437 (unsigned int)TLAN_MIN_FRAME_SIZE),
1438 PCI_DMA_TODEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 dev_kfree_skb_any(skb);
1440 head_list->buffer[8].address = 0;
1441 head_list->buffer[9].address = 0;
1442 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001443
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444 if ( tmpCStat & TLAN_CSTAT_EOC )
1445 eoc = 1;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001446
Stephen Hemmingerf8f31542008-05-30 09:49:53 -07001447 dev->stats.tx_bytes += head_list->frameSize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448
1449 head_list->cStat = TLAN_CSTAT_UNUSED;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001450 netif_start_queue(dev);
1451 CIRC_INC( priv->txHead, TLAN_NUM_TX_LISTS );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 head_list = priv->txList + priv->txHead;
1453 }
1454
1455 if (!ack)
1456 printk(KERN_INFO "TLAN: Received interrupt for uncompleted TX frame.\n");
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001457
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 if ( eoc ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001459 TLAN_DBG( TLAN_DEBUG_TX,
1460 "TRANSMIT: Handling TX EOC (Head=%d Tail=%d)\n",
1461 priv->txHead, priv->txTail );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 head_list = priv->txList + priv->txHead;
1463 head_list_phys = priv->txListDMA + sizeof(TLanList) * priv->txHead;
1464 if ( ( head_list->cStat & TLAN_CSTAT_READY ) == TLAN_CSTAT_READY ) {
1465 outl(head_list_phys, dev->base_addr + TLAN_CH_PARM );
1466 ack |= TLAN_HC_GO;
1467 } else {
1468 priv->txInProgress = 0;
1469 }
1470 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001471
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 if ( priv->adapter->flags & TLAN_ADAPTER_ACTIVITY_LED ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001473 TLan_DioWrite8( dev->base_addr,
1474 TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475 if ( priv->timer.function == NULL ) {
1476 priv->timer.function = &TLan_Timer;
1477 priv->timer.data = (unsigned long) dev;
1478 priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY;
1479 priv->timerSetAt = jiffies;
1480 priv->timerType = TLAN_TIMER_ACTIVITY;
1481 add_timer(&priv->timer);
1482 } else if ( priv->timerType == TLAN_TIMER_ACTIVITY ) {
1483 priv->timerSetAt = jiffies;
1484 }
1485 }
1486
1487 return ack;
1488
1489} /* TLan_HandleTxEOF */
1490
1491
1492
1493
1494 /***************************************************************
1495 * TLan_HandleStatOverflow
1496 *
1497 * Returns:
1498 * 1
1499 * Parms:
1500 * dev Device assigned the IRQ that was
1501 * raised.
1502 * host_int The contents of the HOST_INT
1503 * port.
1504 *
1505 * This function handles the Statistics Overflow interrupt
1506 * which means that one or more of the TLAN statistics
1507 * registers has reached 1/2 capacity and needs to be read.
1508 *
1509 **************************************************************/
1510
Harvey Harrison98e0f522008-02-18 10:04:38 -08001511static u32 TLan_HandleStatOverflow( struct net_device *dev, u16 host_int )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512{
1513 TLan_ReadAndClearStats( dev, TLAN_RECORD );
1514
1515 return 1;
1516
1517} /* TLan_HandleStatOverflow */
1518
1519
1520
1521
1522 /***************************************************************
1523 * TLan_HandleRxEOF
1524 *
1525 * Returns:
1526 * 1
1527 * Parms:
1528 * dev Device assigned the IRQ that was
1529 * raised.
1530 * host_int The contents of the HOST_INT
1531 * port.
1532 *
1533 * This function handles the Rx EOF interrupt which
1534 * indicates a frame has been received by the adapter from
1535 * the net and the frame has been transferred to memory.
1536 * The function determines the bounce buffer the frame has
1537 * been loaded into, creates a new sk_buff big enough to
1538 * hold the frame, and sends it to protocol stack. It
1539 * then resets the used buffer and appends it to the end
1540 * of the list. If the frame was the last in the Rx
1541 * channel (EOC), the function restarts the receive channel
1542 * by sending an Rx Go command to the adapter. Then it
1543 * activates/continues the activity LED.
1544 *
1545 **************************************************************/
1546
Harvey Harrison98e0f522008-02-18 10:04:38 -08001547static u32 TLan_HandleRxEOF( struct net_device *dev, u16 host_int )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548{
1549 TLanPrivateInfo *priv = netdev_priv(dev);
1550 u32 ack = 0;
1551 int eoc = 0;
1552 u8 *head_buffer;
1553 TLanList *head_list;
1554 struct sk_buff *skb;
1555 TLanList *tail_list;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 u16 tmpCStat;
1557 dma_addr_t head_list_phys;
1558
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001559 TLAN_DBG( TLAN_DEBUG_RX, "RECEIVE: Handling RX EOF (Head=%d Tail=%d)\n",
1560 priv->rxHead, priv->rxTail );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561 head_list = priv->rxList + priv->rxHead;
1562 head_list_phys = priv->rxListDMA + sizeof(TLanList) * priv->rxHead;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001563
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564 while (((tmpCStat = head_list->cStat) & TLAN_CSTAT_FRM_CMP) && (ack < 255)) {
Stephen Hemminger9ded65a2008-05-30 09:49:56 -07001565 dma_addr_t frameDma = head_list->buffer[0].address;
1566 u32 frameSize = head_list->frameSize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567 ack++;
1568 if (tmpCStat & TLAN_CSTAT_EOC)
1569 eoc = 1;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001570
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571 if (bbuf) {
Stephen Hemminger9ded65a2008-05-30 09:49:56 -07001572 skb = netdev_alloc_skb(dev, frameSize + 7);
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001573 if ( !skb )
1574 goto drop_and_reuse;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001575
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001576 head_buffer = priv->rxBuffer
1577 + (priv->rxHead * TLAN_MAX_FRAME_SIZE);
1578 skb_reserve(skb, 2);
1579 pci_dma_sync_single_for_cpu(priv->pciDev,
1580 frameDma, frameSize,
1581 PCI_DMA_FROMDEVICE);
1582 skb_copy_from_linear_data(skb, head_buffer, frameSize);
1583 skb_put(skb, frameSize);
1584 dev->stats.rx_bytes += frameSize;
1585
1586 skb->protocol = eth_type_trans( skb, dev );
1587 netif_rx( skb );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 } else {
1589 struct sk_buff *new_skb;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001590
Stephen Hemminger9ded65a2008-05-30 09:49:56 -07001591 new_skb = netdev_alloc_skb(dev, TLAN_MAX_FRAME_SIZE + 7 );
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001592 if ( !new_skb )
1593 goto drop_and_reuse;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001595 skb = TLan_GetSKB(head_list);
1596 pci_unmap_single(priv->pciDev, frameDma,
1597 TLAN_MAX_FRAME_SIZE, PCI_DMA_FROMDEVICE);
1598 skb_put( skb, frameSize );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001600 dev->stats.rx_bytes += frameSize;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001601
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001602 skb->protocol = eth_type_trans( skb, dev );
1603 netif_rx( skb );
Stephen Hemminger93e16842008-05-30 09:49:55 -07001604
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001605 skb_reserve( new_skb, NET_IP_ALIGN );
1606 head_list->buffer[0].address = pci_map_single(priv->pciDev,
1607 new_skb->data,
1608 TLAN_MAX_FRAME_SIZE,
1609 PCI_DMA_FROMDEVICE);
1610
1611 TLan_StoreSKB(head_list, new_skb);
Stephen Hemminger9ded65a2008-05-30 09:49:56 -07001612
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 }
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001614drop_and_reuse:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 head_list->forward = 0;
1616 head_list->cStat = 0;
1617 tail_list = priv->rxList + priv->rxTail;
1618 tail_list->forward = head_list_phys;
1619
1620 CIRC_INC( priv->rxHead, TLAN_NUM_RX_LISTS );
1621 CIRC_INC( priv->rxTail, TLAN_NUM_RX_LISTS );
1622 head_list = priv->rxList + priv->rxHead;
1623 head_list_phys = priv->rxListDMA + sizeof(TLanList) * priv->rxHead;
1624 }
1625
1626 if (!ack)
1627 printk(KERN_INFO "TLAN: Received interrupt for uncompleted RX frame.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628
1629
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001630 if ( eoc ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001631 TLAN_DBG( TLAN_DEBUG_RX,
1632 "RECEIVE: Handling RX EOC (Head=%d Tail=%d)\n",
1633 priv->rxHead, priv->rxTail );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 head_list = priv->rxList + priv->rxHead;
1635 head_list_phys = priv->rxListDMA + sizeof(TLanList) * priv->rxHead;
1636 outl(head_list_phys, dev->base_addr + TLAN_CH_PARM );
1637 ack |= TLAN_HC_GO | TLAN_HC_RT;
1638 priv->rxEocCount++;
1639 }
1640
1641 if ( priv->adapter->flags & TLAN_ADAPTER_ACTIVITY_LED ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001642 TLan_DioWrite8( dev->base_addr,
1643 TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 if ( priv->timer.function == NULL ) {
1645 priv->timer.function = &TLan_Timer;
1646 priv->timer.data = (unsigned long) dev;
1647 priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY;
1648 priv->timerSetAt = jiffies;
1649 priv->timerType = TLAN_TIMER_ACTIVITY;
1650 add_timer(&priv->timer);
1651 } else if ( priv->timerType == TLAN_TIMER_ACTIVITY ) {
1652 priv->timerSetAt = jiffies;
1653 }
1654 }
1655
1656 dev->last_rx = jiffies;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001657
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 return ack;
1659
1660} /* TLan_HandleRxEOF */
1661
1662
1663
1664
1665 /***************************************************************
1666 * TLan_HandleDummy
1667 *
1668 * Returns:
1669 * 1
1670 * Parms:
1671 * dev Device assigned the IRQ that was
1672 * raised.
1673 * host_int The contents of the HOST_INT
1674 * port.
1675 *
1676 * This function handles the Dummy interrupt, which is
1677 * raised whenever a test interrupt is generated by setting
1678 * the Req_Int bit of HOST_CMD to 1.
1679 *
1680 **************************************************************/
1681
Harvey Harrison98e0f522008-02-18 10:04:38 -08001682static u32 TLan_HandleDummy( struct net_device *dev, u16 host_int )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683{
1684 printk( "TLAN: Test interrupt on %s.\n", dev->name );
1685 return 1;
1686
1687} /* TLan_HandleDummy */
1688
1689
1690
1691
1692 /***************************************************************
1693 * TLan_HandleTxEOC
1694 *
1695 * Returns:
1696 * 1
1697 * Parms:
1698 * dev Device assigned the IRQ that was
1699 * raised.
1700 * host_int The contents of the HOST_INT
1701 * port.
1702 *
1703 * This driver is structured to determine EOC occurrences by
1704 * reading the CSTAT member of the list structure. Tx EOC
1705 * interrupts are disabled via the DIO INTDIS register.
1706 * However, TLAN chips before revision 3.0 didn't have this
1707 * functionality, so process EOC events if this is the
1708 * case.
1709 *
1710 **************************************************************/
1711
Harvey Harrison98e0f522008-02-18 10:04:38 -08001712static u32 TLan_HandleTxEOC( struct net_device *dev, u16 host_int )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713{
1714 TLanPrivateInfo *priv = netdev_priv(dev);
1715 TLanList *head_list;
1716 dma_addr_t head_list_phys;
1717 u32 ack = 1;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001718
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 host_int = 0;
1720 if ( priv->tlanRev < 0x30 ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001721 TLAN_DBG( TLAN_DEBUG_TX,
1722 "TRANSMIT: Handling TX EOC (Head=%d Tail=%d) -- IRQ\n",
1723 priv->txHead, priv->txTail );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724 head_list = priv->txList + priv->txHead;
1725 head_list_phys = priv->txListDMA + sizeof(TLanList) * priv->txHead;
1726 if ( ( head_list->cStat & TLAN_CSTAT_READY ) == TLAN_CSTAT_READY ) {
1727 netif_stop_queue(dev);
1728 outl( head_list_phys, dev->base_addr + TLAN_CH_PARM );
1729 ack |= TLAN_HC_GO;
1730 } else {
1731 priv->txInProgress = 0;
1732 }
1733 }
1734
1735 return ack;
1736
1737} /* TLan_HandleTxEOC */
1738
1739
1740
1741
1742 /***************************************************************
1743 * TLan_HandleStatusCheck
1744 *
1745 * Returns:
1746 * 0 if Adapter check, 1 if Network Status check.
1747 * Parms:
1748 * dev Device assigned the IRQ that was
1749 * raised.
1750 * host_int The contents of the HOST_INT
1751 * port.
1752 *
1753 * This function handles Adapter Check/Network Status
1754 * interrupts generated by the adapter. It checks the
1755 * vector in the HOST_INT register to determine if it is
1756 * an Adapter Check interrupt. If so, it resets the
1757 * adapter. Otherwise it clears the status registers
1758 * and services the PHY.
1759 *
1760 **************************************************************/
1761
Harvey Harrison98e0f522008-02-18 10:04:38 -08001762static u32 TLan_HandleStatusCheck( struct net_device *dev, u16 host_int )
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001763{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 TLanPrivateInfo *priv = netdev_priv(dev);
1765 u32 ack;
1766 u32 error;
1767 u8 net_sts;
1768 u32 phy;
1769 u16 tlphy_ctl;
1770 u16 tlphy_sts;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001771
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 ack = 1;
1773 if ( host_int & TLAN_HI_IV_MASK ) {
1774 netif_stop_queue( dev );
1775 error = inl( dev->base_addr + TLAN_CH_PARM );
1776 printk( "TLAN: %s: Adaptor Error = 0x%x\n", dev->name, error );
1777 TLan_ReadAndClearStats( dev, TLAN_RECORD );
1778 outl( TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD );
1779
1780 schedule_work(&priv->tlan_tqueue);
1781
1782 netif_wake_queue(dev);
1783 ack = 0;
1784 } else {
1785 TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Status Check\n", dev->name );
1786 phy = priv->phy[priv->phyNum];
1787
1788 net_sts = TLan_DioRead8( dev->base_addr, TLAN_NET_STS );
1789 if ( net_sts ) {
1790 TLan_DioWrite8( dev->base_addr, TLAN_NET_STS, net_sts );
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001791 TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Net_Sts = %x\n",
1792 dev->name, (unsigned) net_sts );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793 }
1794 if ( ( net_sts & TLAN_NET_STS_MIRQ ) && ( priv->phyNum == 0 ) ) {
1795 TLan_MiiReadReg( dev, phy, TLAN_TLPHY_STS, &tlphy_sts );
1796 TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tlphy_ctl );
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001797 if ( ! ( tlphy_sts & TLAN_TS_POLOK ) &&
1798 ! ( tlphy_ctl & TLAN_TC_SWAPOL ) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799 tlphy_ctl |= TLAN_TC_SWAPOL;
1800 TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tlphy_ctl);
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001801 } else if ( ( tlphy_sts & TLAN_TS_POLOK )
1802 && ( tlphy_ctl & TLAN_TC_SWAPOL ) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 tlphy_ctl &= ~TLAN_TC_SWAPOL;
1804 TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tlphy_ctl);
1805 }
1806
1807 if (debug) {
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001808 TLan_PhyPrint( dev );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 }
1810 }
1811 }
1812
1813 return ack;
1814
1815} /* TLan_HandleStatusCheck */
1816
1817
1818
1819
1820 /***************************************************************
1821 * TLan_HandleRxEOC
1822 *
1823 * Returns:
1824 * 1
1825 * Parms:
1826 * dev Device assigned the IRQ that was
1827 * raised.
1828 * host_int The contents of the HOST_INT
1829 * port.
1830 *
1831 * This driver is structured to determine EOC occurrences by
1832 * reading the CSTAT member of the list structure. Rx EOC
1833 * interrupts are disabled via the DIO INTDIS register.
1834 * However, TLAN chips before revision 3.0 didn't have this
1835 * CSTAT member or a INTDIS register, so if this chip is
1836 * pre-3.0, process EOC interrupts normally.
1837 *
1838 **************************************************************/
1839
Harvey Harrison98e0f522008-02-18 10:04:38 -08001840static u32 TLan_HandleRxEOC( struct net_device *dev, u16 host_int )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841{
1842 TLanPrivateInfo *priv = netdev_priv(dev);
1843 dma_addr_t head_list_phys;
1844 u32 ack = 1;
1845
1846 if ( priv->tlanRev < 0x30 ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001847 TLAN_DBG( TLAN_DEBUG_RX,
1848 "RECEIVE: Handling RX EOC (Head=%d Tail=%d) -- IRQ\n",
1849 priv->rxHead, priv->rxTail );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850 head_list_phys = priv->rxListDMA + sizeof(TLanList) * priv->rxHead;
1851 outl( head_list_phys, dev->base_addr + TLAN_CH_PARM );
1852 ack |= TLAN_HC_GO | TLAN_HC_RT;
1853 priv->rxEocCount++;
1854 }
1855
1856 return ack;
1857
1858} /* TLan_HandleRxEOC */
1859
1860
1861
1862
1863/*****************************************************************************
1864******************************************************************************
1865
1866 ThunderLAN Driver Timer Function
1867
1868******************************************************************************
1869*****************************************************************************/
1870
1871
1872 /***************************************************************
1873 * TLan_Timer
1874 *
1875 * Returns:
1876 * Nothing
1877 * Parms:
1878 * data A value given to add timer when
1879 * add_timer was called.
1880 *
1881 * This function handles timed functionality for the
1882 * TLAN driver. The two current timer uses are for
1883 * delaying for autonegotionation and driving the ACT LED.
1884 * - Autonegotiation requires being allowed about
1885 * 2 1/2 seconds before attempting to transmit a
1886 * packet. It would be a very bad thing to hang
1887 * the kernel this long, so the driver doesn't
1888 * allow transmission 'til after this time, for
1889 * certain PHYs. It would be much nicer if all
1890 * PHYs were interrupt-capable like the internal
1891 * PHY.
1892 * - The ACT LED, which shows adapter activity, is
1893 * driven by the driver, and so must be left on
1894 * for a short period to power up the LED so it
1895 * can be seen. This delay can be changed by
1896 * changing the TLAN_TIMER_ACT_DELAY in tlan.h,
1897 * if desired. 100 ms produces a slightly
1898 * sluggish response.
1899 *
1900 **************************************************************/
1901
Harvey Harrison98e0f522008-02-18 10:04:38 -08001902static void TLan_Timer( unsigned long data )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903{
1904 struct net_device *dev = (struct net_device *) data;
1905 TLanPrivateInfo *priv = netdev_priv(dev);
1906 u32 elapsed;
1907 unsigned long flags = 0;
1908
1909 priv->timer.function = NULL;
1910
1911 switch ( priv->timerType ) {
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001912#ifdef MONITOR
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 case TLAN_TIMER_LINK_BEAT:
1914 TLan_PhyMonitor( dev );
1915 break;
1916#endif
1917 case TLAN_TIMER_PHY_PDOWN:
1918 TLan_PhyPowerDown( dev );
1919 break;
1920 case TLAN_TIMER_PHY_PUP:
1921 TLan_PhyPowerUp( dev );
1922 break;
1923 case TLAN_TIMER_PHY_RESET:
1924 TLan_PhyReset( dev );
1925 break;
1926 case TLAN_TIMER_PHY_START_LINK:
1927 TLan_PhyStartLink( dev );
1928 break;
1929 case TLAN_TIMER_PHY_FINISH_AN:
1930 TLan_PhyFinishAutoNeg( dev );
1931 break;
1932 case TLAN_TIMER_FINISH_RESET:
1933 TLan_FinishReset( dev );
1934 break;
1935 case TLAN_TIMER_ACTIVITY:
1936 spin_lock_irqsave(&priv->lock, flags);
1937 if ( priv->timer.function == NULL ) {
1938 elapsed = jiffies - priv->timerSetAt;
1939 if ( elapsed >= TLAN_TIMER_ACT_DELAY ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001940 TLan_DioWrite8( dev->base_addr,
1941 TLAN_LED_REG, TLAN_LED_LINK );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942 } else {
1943 priv->timer.function = &TLan_Timer;
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001944 priv->timer.expires = priv->timerSetAt
1945 + TLAN_TIMER_ACT_DELAY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946 spin_unlock_irqrestore(&priv->lock, flags);
1947 add_timer( &priv->timer );
1948 break;
1949 }
1950 }
1951 spin_unlock_irqrestore(&priv->lock, flags);
1952 break;
1953 default:
1954 break;
1955 }
1956
1957} /* TLan_Timer */
1958
1959
1960
1961
1962/*****************************************************************************
1963******************************************************************************
1964
1965 ThunderLAN Driver Adapter Related Routines
1966
1967******************************************************************************
1968*****************************************************************************/
1969
1970
1971 /***************************************************************
1972 * TLan_ResetLists
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001973 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974 * Returns:
1975 * Nothing
1976 * Parms:
1977 * dev The device structure with the list
1978 * stuctures to be reset.
1979 *
1980 * This routine sets the variables associated with managing
1981 * the TLAN lists to their initial values.
1982 *
1983 **************************************************************/
1984
Harvey Harrison98e0f522008-02-18 10:04:38 -08001985static void TLan_ResetLists( struct net_device *dev )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986{
1987 TLanPrivateInfo *priv = netdev_priv(dev);
1988 int i;
1989 TLanList *list;
1990 dma_addr_t list_phys;
1991 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992
1993 priv->txHead = 0;
1994 priv->txTail = 0;
1995 for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ ) {
1996 list = priv->txList + i;
1997 list->cStat = TLAN_CSTAT_UNUSED;
1998 if ( bbuf ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07001999 list->buffer[0].address = priv->txBufferDMA
2000 + ( i * TLAN_MAX_FRAME_SIZE );
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 } else {
2002 list->buffer[0].address = 0;
2003 }
2004 list->buffer[2].count = 0;
2005 list->buffer[2].address = 0;
2006 list->buffer[8].address = 0;
2007 list->buffer[9].address = 0;
2008 }
2009
2010 priv->rxHead = 0;
2011 priv->rxTail = TLAN_NUM_RX_LISTS - 1;
2012 for ( i = 0; i < TLAN_NUM_RX_LISTS; i++ ) {
2013 list = priv->rxList + i;
2014 list_phys = priv->rxListDMA + sizeof(TLanList) * i;
2015 list->cStat = TLAN_CSTAT_READY;
2016 list->frameSize = TLAN_MAX_FRAME_SIZE;
2017 list->buffer[0].count = TLAN_MAX_FRAME_SIZE | TLAN_LAST_BUFFER;
2018 if ( bbuf ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002019 list->buffer[0].address = priv->rxBufferDMA
2020 + ( i * TLAN_MAX_FRAME_SIZE );
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021 } else {
Stephen Hemminger9ded65a2008-05-30 09:49:56 -07002022 skb = netdev_alloc_skb(dev, TLAN_MAX_FRAME_SIZE + 7 );
2023 if ( !skb ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002024 pr_err("TLAN: out of memory for received data.\n" );
Stephen Hemminger9ded65a2008-05-30 09:49:56 -07002025 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026 }
Stephen Hemminger9ded65a2008-05-30 09:49:56 -07002027
2028 skb_reserve( skb, NET_IP_ALIGN );
Robert Fitzsimons0d63bea2008-08-09 17:54:02 +01002029 list->buffer[0].address = pci_map_single(priv->pciDev,
2030 skb->data,
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002031 TLAN_MAX_FRAME_SIZE,
2032 PCI_DMA_FROMDEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 TLan_StoreSKB(list, skb);
2034 }
2035 list->buffer[1].count = 0;
2036 list->buffer[1].address = 0;
Stephen Hemminger9ded65a2008-05-30 09:49:56 -07002037 list->forward = list_phys + sizeof(TLanList);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 }
2039
Stephen Hemminger9ded65a2008-05-30 09:49:56 -07002040 /* in case ran out of memory early, clear bits */
2041 while (i < TLAN_NUM_RX_LISTS) {
2042 TLan_StoreSKB(priv->rxList + i, NULL);
2043 ++i;
2044 }
2045 list->forward = 0;
2046
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047} /* TLan_ResetLists */
2048
2049
Harvey Harrison98e0f522008-02-18 10:04:38 -08002050static void TLan_FreeLists( struct net_device *dev )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051{
2052 TLanPrivateInfo *priv = netdev_priv(dev);
2053 int i;
2054 TLanList *list;
2055 struct sk_buff *skb;
2056
2057 if ( ! bbuf ) {
2058 for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ ) {
2059 list = priv->txList + i;
2060 skb = TLan_GetSKB(list);
2061 if ( skb ) {
Sakari Ailusbb5f1332008-12-16 15:22:41 -08002062 pci_unmap_single(
2063 priv->pciDev,
2064 list->buffer[0].address,
2065 max(skb->len,
2066 (unsigned int)TLAN_MIN_FRAME_SIZE),
2067 PCI_DMA_TODEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068 dev_kfree_skb_any( skb );
2069 list->buffer[8].address = 0;
2070 list->buffer[9].address = 0;
2071 }
2072 }
2073
2074 for ( i = 0; i < TLAN_NUM_RX_LISTS; i++ ) {
2075 list = priv->rxList + i;
2076 skb = TLan_GetSKB(list);
2077 if ( skb ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002078 pci_unmap_single(priv->pciDev,
2079 list->buffer[0].address,
2080 TLAN_MAX_FRAME_SIZE,
2081 PCI_DMA_FROMDEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082 dev_kfree_skb_any( skb );
2083 list->buffer[8].address = 0;
2084 list->buffer[9].address = 0;
2085 }
2086 }
2087 }
2088} /* TLan_FreeLists */
2089
2090
2091
2092
2093 /***************************************************************
2094 * TLan_PrintDio
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002095 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096 * Returns:
2097 * Nothing
2098 * Parms:
2099 * io_base Base IO port of the device of
2100 * which to print DIO registers.
2101 *
2102 * This function prints out all the internal (DIO)
2103 * registers of a TLAN chip.
2104 *
2105 **************************************************************/
2106
Harvey Harrison98e0f522008-02-18 10:04:38 -08002107static void TLan_PrintDio( u16 io_base )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108{
2109 u32 data0, data1;
2110 int i;
2111
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002112 printk( "TLAN: Contents of internal registers for io base 0x%04hx.\n",
2113 io_base );
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 printk( "TLAN: Off. +0 +4\n" );
2115 for ( i = 0; i < 0x4C; i+= 8 ) {
2116 data0 = TLan_DioRead32( io_base, i );
2117 data1 = TLan_DioRead32( io_base, i + 0x4 );
2118 printk( "TLAN: 0x%02x 0x%08x 0x%08x\n", i, data0, data1 );
2119 }
2120
2121} /* TLan_PrintDio */
2122
2123
2124
2125
2126 /***************************************************************
2127 * TLan_PrintList
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002128 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129 * Returns:
2130 * Nothing
2131 * Parms:
2132 * list A pointer to the TLanList structure to
2133 * be printed.
2134 * type A string to designate type of list,
2135 * "Rx" or "Tx".
2136 * num The index of the list.
2137 *
2138 * This function prints out the contents of the list
2139 * pointed to by the list parameter.
2140 *
2141 **************************************************************/
2142
Harvey Harrison98e0f522008-02-18 10:04:38 -08002143static void TLan_PrintList( TLanList *list, char *type, int num)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144{
2145 int i;
2146
Stephen Hemminger93e16842008-05-30 09:49:55 -07002147 printk( "TLAN: %s List %d at %p\n", type, num, list );
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148 printk( "TLAN: Forward = 0x%08x\n", list->forward );
2149 printk( "TLAN: CSTAT = 0x%04hx\n", list->cStat );
2150 printk( "TLAN: Frame Size = 0x%04hx\n", list->frameSize );
2151 /* for ( i = 0; i < 10; i++ ) { */
2152 for ( i = 0; i < 2; i++ ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002153 printk( "TLAN: Buffer[%d].count, addr = 0x%08x, 0x%08x\n",
2154 i, list->buffer[i].count, list->buffer[i].address );
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155 }
2156
2157} /* TLan_PrintList */
2158
2159
2160
2161
2162 /***************************************************************
2163 * TLan_ReadAndClearStats
2164 *
2165 * Returns:
2166 * Nothing
2167 * Parms:
2168 * dev Pointer to device structure of adapter
2169 * to which to read stats.
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002170 * record Flag indicating whether to add
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 *
2172 * This functions reads all the internal status registers
2173 * of the TLAN chip, which clears them as a side effect.
2174 * It then either adds the values to the device's status
2175 * struct, or discards them, depending on whether record
2176 * is TLAN_RECORD (!=0) or TLAN_IGNORE (==0).
2177 *
2178 **************************************************************/
2179
Harvey Harrison98e0f522008-02-18 10:04:38 -08002180static void TLan_ReadAndClearStats( struct net_device *dev, int record )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182 u32 tx_good, tx_under;
2183 u32 rx_good, rx_over;
2184 u32 def_tx, crc, code;
2185 u32 multi_col, single_col;
2186 u32 excess_col, late_col, loss;
2187
2188 outw( TLAN_GOOD_TX_FRMS, dev->base_addr + TLAN_DIO_ADR );
2189 tx_good = inb( dev->base_addr + TLAN_DIO_DATA );
2190 tx_good += inb( dev->base_addr + TLAN_DIO_DATA + 1 ) << 8;
2191 tx_good += inb( dev->base_addr + TLAN_DIO_DATA + 2 ) << 16;
2192 tx_under = inb( dev->base_addr + TLAN_DIO_DATA + 3 );
2193
2194 outw( TLAN_GOOD_RX_FRMS, dev->base_addr + TLAN_DIO_ADR );
2195 rx_good = inb( dev->base_addr + TLAN_DIO_DATA );
2196 rx_good += inb( dev->base_addr + TLAN_DIO_DATA + 1 ) << 8;
2197 rx_good += inb( dev->base_addr + TLAN_DIO_DATA + 2 ) << 16;
2198 rx_over = inb( dev->base_addr + TLAN_DIO_DATA + 3 );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002199
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 outw( TLAN_DEFERRED_TX, dev->base_addr + TLAN_DIO_ADR );
2201 def_tx = inb( dev->base_addr + TLAN_DIO_DATA );
2202 def_tx += inb( dev->base_addr + TLAN_DIO_DATA + 1 ) << 8;
2203 crc = inb( dev->base_addr + TLAN_DIO_DATA + 2 );
2204 code = inb( dev->base_addr + TLAN_DIO_DATA + 3 );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002205
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 outw( TLAN_MULTICOL_FRMS, dev->base_addr + TLAN_DIO_ADR );
2207 multi_col = inb( dev->base_addr + TLAN_DIO_DATA );
2208 multi_col += inb( dev->base_addr + TLAN_DIO_DATA + 1 ) << 8;
2209 single_col = inb( dev->base_addr + TLAN_DIO_DATA + 2 );
2210 single_col += inb( dev->base_addr + TLAN_DIO_DATA + 3 ) << 8;
2211
2212 outw( TLAN_EXCESSCOL_FRMS, dev->base_addr + TLAN_DIO_ADR );
2213 excess_col = inb( dev->base_addr + TLAN_DIO_DATA );
2214 late_col = inb( dev->base_addr + TLAN_DIO_DATA + 1 );
2215 loss = inb( dev->base_addr + TLAN_DIO_DATA + 2 );
2216
2217 if ( record ) {
Stephen Hemmingerf8f31542008-05-30 09:49:53 -07002218 dev->stats.rx_packets += rx_good;
2219 dev->stats.rx_errors += rx_over + crc + code;
2220 dev->stats.tx_packets += tx_good;
2221 dev->stats.tx_errors += tx_under + loss;
2222 dev->stats.collisions += multi_col + single_col + excess_col + late_col;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223
Stephen Hemmingerf8f31542008-05-30 09:49:53 -07002224 dev->stats.rx_over_errors += rx_over;
2225 dev->stats.rx_crc_errors += crc;
2226 dev->stats.rx_frame_errors += code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227
Stephen Hemmingerf8f31542008-05-30 09:49:53 -07002228 dev->stats.tx_aborted_errors += tx_under;
2229 dev->stats.tx_carrier_errors += loss;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002231
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232} /* TLan_ReadAndClearStats */
2233
2234
2235
2236
2237 /***************************************************************
2238 * TLan_Reset
2239 *
2240 * Returns:
2241 * 0
2242 * Parms:
2243 * dev Pointer to device structure of adapter
2244 * to be reset.
2245 *
2246 * This function resets the adapter and it's physical
2247 * device. See Chap. 3, pp. 9-10 of the "ThunderLAN
2248 * Programmer's Guide" for details. The routine tries to
2249 * implement what is detailed there, though adjustments
2250 * have been made.
2251 *
2252 **************************************************************/
2253
Harvey Harrison98e0f522008-02-18 10:04:38 -08002254static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255TLan_ResetAdapter( struct net_device *dev )
2256{
2257 TLanPrivateInfo *priv = netdev_priv(dev);
2258 int i;
2259 u32 addr;
2260 u32 data;
2261 u8 data8;
2262
2263 priv->tlanFullDuplex = FALSE;
2264 priv->phyOnline=0;
2265 netif_carrier_off(dev);
2266
2267/* 1. Assert reset bit. */
2268
2269 data = inl(dev->base_addr + TLAN_HOST_CMD);
2270 data |= TLAN_HC_AD_RST;
2271 outl(data, dev->base_addr + TLAN_HOST_CMD);
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002272
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 udelay(1000);
2274
2275/* 2. Turn off interrupts. ( Probably isn't necessary ) */
2276
2277 data = inl(dev->base_addr + TLAN_HOST_CMD);
2278 data |= TLAN_HC_INT_OFF;
2279 outl(data, dev->base_addr + TLAN_HOST_CMD);
2280
2281/* 3. Clear AREGs and HASHs. */
2282
2283 for ( i = TLAN_AREG_0; i <= TLAN_HASH_2; i += 4 ) {
2284 TLan_DioWrite32( dev->base_addr, (u16) i, 0 );
2285 }
2286
2287/* 4. Setup NetConfig register. */
2288
2289 data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
2290 TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, (u16) data );
2291
2292/* 5. Load Ld_Tmr and Ld_Thr in HOST_CMD. */
2293
2294 outl( TLAN_HC_LD_TMR | 0x3f, dev->base_addr + TLAN_HOST_CMD );
2295 outl( TLAN_HC_LD_THR | 0x9, dev->base_addr + TLAN_HOST_CMD );
2296
2297/* 6. Unreset the MII by setting NMRST (in NetSio) to 1. */
2298
2299 outw( TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR );
2300 addr = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO;
2301 TLan_SetBit( TLAN_NET_SIO_NMRST, addr );
2302
2303/* 7. Setup the remaining registers. */
2304
2305 if ( priv->tlanRev >= 0x30 ) {
2306 data8 = TLAN_ID_TX_EOC | TLAN_ID_RX_EOC;
2307 TLan_DioWrite8( dev->base_addr, TLAN_INT_DIS, data8 );
2308 }
2309 TLan_PhyDetect( dev );
2310 data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002311
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 if ( priv->adapter->flags & TLAN_ADAPTER_BIT_RATE_PHY ) {
2313 data |= TLAN_NET_CFG_BIT;
2314 if ( priv->aui == 1 ) {
2315 TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x0a );
2316 } else if ( priv->duplex == TLAN_DUPLEX_FULL ) {
2317 TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x00 );
2318 priv->tlanFullDuplex = TRUE;
2319 } else {
2320 TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x08 );
2321 }
2322 }
2323
2324 if ( priv->phyNum == 0 ) {
2325 data |= TLAN_NET_CFG_PHY_EN;
2326 }
2327 TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, (u16) data );
2328
2329 if ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) {
2330 TLan_FinishReset( dev );
2331 } else {
2332 TLan_PhyPowerDown( dev );
2333 }
2334
2335} /* TLan_ResetAdapter */
2336
2337
2338
2339
Harvey Harrison98e0f522008-02-18 10:04:38 -08002340static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341TLan_FinishReset( struct net_device *dev )
2342{
2343 TLanPrivateInfo *priv = netdev_priv(dev);
2344 u8 data;
2345 u32 phy;
2346 u8 sio;
2347 u16 status;
2348 u16 partner;
2349 u16 tlphy_ctl;
2350 u16 tlphy_par;
2351 u16 tlphy_id1, tlphy_id2;
2352 int i;
2353
2354 phy = priv->phy[priv->phyNum];
2355
2356 data = TLAN_NET_CMD_NRESET | TLAN_NET_CMD_NWRAP;
2357 if ( priv->tlanFullDuplex ) {
2358 data |= TLAN_NET_CMD_DUPLEX;
2359 }
2360 TLan_DioWrite8( dev->base_addr, TLAN_NET_CMD, data );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002361 data = TLAN_NET_MASK_MASK4 | TLAN_NET_MASK_MASK5;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362 if ( priv->phyNum == 0 ) {
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002363 data |= TLAN_NET_MASK_MASK7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364 }
2365 TLan_DioWrite8( dev->base_addr, TLAN_NET_MASK, data );
2366 TLan_DioWrite16( dev->base_addr, TLAN_MAX_RX, ((1536)+7)&~7 );
2367 TLan_MiiReadReg( dev, phy, MII_GEN_ID_HI, &tlphy_id1 );
2368 TLan_MiiReadReg( dev, phy, MII_GEN_ID_LO, &tlphy_id2 );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002369
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002370 if ( ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) ||
2371 ( priv->aui ) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 status = MII_GS_LINK;
2373 printk( "TLAN: %s: Link forced.\n", dev->name );
2374 } else {
2375 TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
2376 udelay( 1000 );
2377 TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002378 if ( (status & MII_GS_LINK) &&
2379 /* We only support link info on Nat.Sem. PHY's */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380 (tlphy_id1 == NAT_SEM_ID1) &&
2381 (tlphy_id2 == NAT_SEM_ID2) ) {
2382 TLan_MiiReadReg( dev, phy, MII_AN_LPA, &partner );
2383 TLan_MiiReadReg( dev, phy, TLAN_TLPHY_PAR, &tlphy_par );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002384
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385 printk( "TLAN: %s: Link active with ", dev->name );
2386 if (!(tlphy_par & TLAN_PHY_AN_EN_STAT)) {
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002387 printk( "forced 10%sMbps %s-Duplex\n",
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002388 tlphy_par & TLAN_PHY_SPEED_100 ? "" : "0",
2389 tlphy_par & TLAN_PHY_DUPLEX_FULL ? "Full" : "Half");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390 } else {
2391 printk( "AutoNegotiation enabled, at 10%sMbps %s-Duplex\n",
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002392 tlphy_par & TLAN_PHY_SPEED_100 ? "" : "0",
2393 tlphy_par & TLAN_PHY_DUPLEX_FULL ? "Full" : "Half");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002394 printk("TLAN: Partner capability: ");
2395 for (i = 5; i <= 10; i++)
2396 if (partner & (1<<i))
2397 printk("%s",media[i-5]);
2398 printk("\n");
2399 }
2400
2401 TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002402#ifdef MONITOR
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403 /* We have link beat..for now anyway */
2404 priv->link = 1;
2405 /*Enabling link beat monitoring */
2406 TLan_SetTimer( dev, (10*HZ), TLAN_TIMER_LINK_BEAT );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002407#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408 } else if (status & MII_GS_LINK) {
2409 printk( "TLAN: %s: Link active\n", dev->name );
2410 TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK );
2411 }
2412 }
2413
2414 if ( priv->phyNum == 0 ) {
2415 TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tlphy_ctl );
2416 tlphy_ctl |= TLAN_TC_INTEN;
2417 TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tlphy_ctl );
2418 sio = TLan_DioRead8( dev->base_addr, TLAN_NET_SIO );
2419 sio |= TLAN_NET_SIO_MINTEN;
2420 TLan_DioWrite8( dev->base_addr, TLAN_NET_SIO, sio );
2421 }
2422
2423 if ( status & MII_GS_LINK ) {
2424 TLan_SetMac( dev, 0, dev->dev_addr );
2425 priv->phyOnline = 1;
2426 outb( ( TLAN_HC_INT_ON >> 8 ), dev->base_addr + TLAN_HOST_CMD + 1 );
2427 if ( debug >= 1 && debug != TLAN_DEBUG_PROBE ) {
2428 outb( ( TLAN_HC_REQ_INT >> 8 ), dev->base_addr + TLAN_HOST_CMD + 1 );
2429 }
2430 outl( priv->rxListDMA, dev->base_addr + TLAN_CH_PARM );
2431 outl( TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD );
2432 netif_carrier_on(dev);
2433 } else {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002434 printk( "TLAN: %s: Link inactive, will retry in 10 secs...\n",
2435 dev->name );
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 TLan_SetTimer( dev, (10*HZ), TLAN_TIMER_FINISH_RESET );
2437 return;
2438 }
James Harper562faf42005-05-05 15:14:18 -07002439 TLan_SetMulticastList(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440
2441} /* TLan_FinishReset */
2442
2443
2444
2445
2446 /***************************************************************
2447 * TLan_SetMac
2448 *
2449 * Returns:
2450 * Nothing
2451 * Parms:
2452 * dev Pointer to device structure of adapter
2453 * on which to change the AREG.
2454 * areg The AREG to set the address in (0 - 3).
2455 * mac A pointer to an array of chars. Each
2456 * element stores one byte of the address.
2457 * IE, it isn't in ascii.
2458 *
2459 * This function transfers a MAC address to one of the
2460 * TLAN AREGs (address registers). The TLAN chip locks
2461 * the register on writing to offset 0 and unlocks the
2462 * register after writing to offset 5. If NULL is passed
2463 * in mac, then the AREG is filled with 0's.
2464 *
2465 **************************************************************/
2466
Harvey Harrison98e0f522008-02-18 10:04:38 -08002467static void TLan_SetMac( struct net_device *dev, int areg, char *mac )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468{
2469 int i;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002470
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471 areg *= 6;
2472
2473 if ( mac != NULL ) {
2474 for ( i = 0; i < 6; i++ )
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002475 TLan_DioWrite8( dev->base_addr,
2476 TLAN_AREG_0 + areg + i, mac[i] );
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 } else {
2478 for ( i = 0; i < 6; i++ )
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002479 TLan_DioWrite8( dev->base_addr,
2480 TLAN_AREG_0 + areg + i, 0 );
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481 }
2482
2483} /* TLan_SetMac */
2484
2485
2486
2487
2488/*****************************************************************************
2489******************************************************************************
2490
2491 ThunderLAN Driver PHY Layer Routines
2492
2493******************************************************************************
2494*****************************************************************************/
2495
2496
2497
2498 /*********************************************************************
2499 * TLan_PhyPrint
2500 *
2501 * Returns:
2502 * Nothing
2503 * Parms:
2504 * dev A pointer to the device structure of the
2505 * TLAN device having the PHYs to be detailed.
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002506 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507 * This function prints the registers a PHY (aka transceiver).
2508 *
2509 ********************************************************************/
2510
Harvey Harrison98e0f522008-02-18 10:04:38 -08002511static void TLan_PhyPrint( struct net_device *dev )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512{
2513 TLanPrivateInfo *priv = netdev_priv(dev);
2514 u16 i, data0, data1, data2, data3, phy;
2515
2516 phy = priv->phy[priv->phyNum];
2517
2518 if ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) {
2519 printk( "TLAN: Device %s, Unmanaged PHY.\n", dev->name );
2520 } else if ( phy <= TLAN_PHY_MAX_ADDR ) {
2521 printk( "TLAN: Device %s, PHY 0x%02x.\n", dev->name, phy );
2522 printk( "TLAN: Off. +0 +1 +2 +3 \n" );
2523 for ( i = 0; i < 0x20; i+= 4 ) {
2524 printk( "TLAN: 0x%02x", i );
2525 TLan_MiiReadReg( dev, phy, i, &data0 );
2526 printk( " 0x%04hx", data0 );
2527 TLan_MiiReadReg( dev, phy, i + 1, &data1 );
2528 printk( " 0x%04hx", data1 );
2529 TLan_MiiReadReg( dev, phy, i + 2, &data2 );
2530 printk( " 0x%04hx", data2 );
2531 TLan_MiiReadReg( dev, phy, i + 3, &data3 );
2532 printk( " 0x%04hx\n", data3 );
2533 }
2534 } else {
2535 printk( "TLAN: Device %s, Invalid PHY.\n", dev->name );
2536 }
2537
2538} /* TLan_PhyPrint */
2539
2540
2541
2542
2543 /*********************************************************************
2544 * TLan_PhyDetect
2545 *
2546 * Returns:
2547 * Nothing
2548 * Parms:
2549 * dev A pointer to the device structure of the adapter
2550 * for which the PHY needs determined.
2551 *
2552 * So far I've found that adapters which have external PHYs
2553 * may also use the internal PHY for part of the functionality.
2554 * (eg, AUI/Thinnet). This function finds out if this TLAN
2555 * chip has an internal PHY, and then finds the first external
2556 * PHY (starting from address 0) if it exists).
2557 *
2558 ********************************************************************/
2559
Harvey Harrison98e0f522008-02-18 10:04:38 -08002560static void TLan_PhyDetect( struct net_device *dev )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561{
2562 TLanPrivateInfo *priv = netdev_priv(dev);
2563 u16 control;
2564 u16 hi;
2565 u16 lo;
2566 u32 phy;
2567
2568 if ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) {
2569 priv->phyNum = 0xFFFF;
2570 return;
2571 }
2572
2573 TLan_MiiReadReg( dev, TLAN_PHY_MAX_ADDR, MII_GEN_ID_HI, &hi );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002574
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575 if ( hi != 0xFFFF ) {
2576 priv->phy[0] = TLAN_PHY_MAX_ADDR;
2577 } else {
2578 priv->phy[0] = TLAN_PHY_NONE;
2579 }
2580
2581 priv->phy[1] = TLAN_PHY_NONE;
2582 for ( phy = 0; phy <= TLAN_PHY_MAX_ADDR; phy++ ) {
2583 TLan_MiiReadReg( dev, phy, MII_GEN_CTL, &control );
2584 TLan_MiiReadReg( dev, phy, MII_GEN_ID_HI, &hi );
2585 TLan_MiiReadReg( dev, phy, MII_GEN_ID_LO, &lo );
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002586 if ( ( control != 0xFFFF ) ||
2587 ( hi != 0xFFFF ) || ( lo != 0xFFFF ) ) {
2588 TLAN_DBG( TLAN_DEBUG_GNRL,
2589 "PHY found at %02x %04x %04x %04x\n",
2590 phy, control, hi, lo );
2591 if ( ( priv->phy[1] == TLAN_PHY_NONE ) &&
2592 ( phy != TLAN_PHY_MAX_ADDR ) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593 priv->phy[1] = phy;
2594 }
2595 }
2596 }
2597
2598 if ( priv->phy[1] != TLAN_PHY_NONE ) {
2599 priv->phyNum = 1;
2600 } else if ( priv->phy[0] != TLAN_PHY_NONE ) {
2601 priv->phyNum = 0;
2602 } else {
2603 printk( "TLAN: Cannot initialize device, no PHY was found!\n" );
2604 }
2605
2606} /* TLan_PhyDetect */
2607
2608
2609
2610
Harvey Harrison98e0f522008-02-18 10:04:38 -08002611static void TLan_PhyPowerDown( struct net_device *dev )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612{
2613 TLanPrivateInfo *priv = netdev_priv(dev);
2614 u16 value;
2615
2616 TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Powering down PHY(s).\n", dev->name );
2617 value = MII_GC_PDOWN | MII_GC_LOOPBK | MII_GC_ISOLATE;
2618 TLan_MiiSync( dev->base_addr );
2619 TLan_MiiWriteReg( dev, priv->phy[priv->phyNum], MII_GEN_CTL, value );
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002620 if ( ( priv->phyNum == 0 ) &&
2621 ( priv->phy[1] != TLAN_PHY_NONE ) &&
2622 ( ! ( priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10 ) ) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623 TLan_MiiSync( dev->base_addr );
2624 TLan_MiiWriteReg( dev, priv->phy[1], MII_GEN_CTL, value );
2625 }
2626
2627 /* Wait for 50 ms and powerup
2628 * This is abitrary. It is intended to make sure the
2629 * transceiver settles.
2630 */
2631 TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_PUP );
2632
2633} /* TLan_PhyPowerDown */
2634
2635
2636
2637
Harvey Harrison98e0f522008-02-18 10:04:38 -08002638static void TLan_PhyPowerUp( struct net_device *dev )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639{
2640 TLanPrivateInfo *priv = netdev_priv(dev);
2641 u16 value;
2642
2643 TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Powering up PHY.\n", dev->name );
2644 TLan_MiiSync( dev->base_addr );
2645 value = MII_GC_LOOPBK;
2646 TLan_MiiWriteReg( dev, priv->phy[priv->phyNum], MII_GEN_CTL, value );
2647 TLan_MiiSync(dev->base_addr);
2648 /* Wait for 500 ms and reset the
2649 * transceiver. The TLAN docs say both 50 ms and
2650 * 500 ms, so do the longer, just in case.
2651 */
2652 TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_RESET );
2653
2654} /* TLan_PhyPowerUp */
2655
2656
2657
2658
Harvey Harrison98e0f522008-02-18 10:04:38 -08002659static void TLan_PhyReset( struct net_device *dev )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660{
2661 TLanPrivateInfo *priv = netdev_priv(dev);
2662 u16 phy;
2663 u16 value;
2664
2665 phy = priv->phy[priv->phyNum];
2666
2667 TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Reseting PHY.\n", dev->name );
2668 TLan_MiiSync( dev->base_addr );
2669 value = MII_GC_LOOPBK | MII_GC_RESET;
2670 TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, value );
2671 TLan_MiiReadReg( dev, phy, MII_GEN_CTL, &value );
2672 while ( value & MII_GC_RESET ) {
2673 TLan_MiiReadReg( dev, phy, MII_GEN_CTL, &value );
2674 }
2675
2676 /* Wait for 500 ms and initialize.
2677 * I don't remember why I wait this long.
2678 * I've changed this to 50ms, as it seems long enough.
2679 */
2680 TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_START_LINK );
2681
2682} /* TLan_PhyReset */
2683
2684
2685
2686
Harvey Harrison98e0f522008-02-18 10:04:38 -08002687static void TLan_PhyStartLink( struct net_device *dev )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688{
2689 TLanPrivateInfo *priv = netdev_priv(dev);
2690 u16 ability;
2691 u16 control;
2692 u16 data;
2693 u16 phy;
2694 u16 status;
2695 u16 tctl;
2696
2697 phy = priv->phy[priv->phyNum];
2698 TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Trying to activate link.\n", dev->name );
2699 TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
2700 TLan_MiiReadReg( dev, phy, MII_GEN_STS, &ability );
2701
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002702 if ( ( status & MII_GS_AUTONEG ) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703 ( ! priv->aui ) ) {
2704 ability = status >> 11;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002705 if ( priv->speed == TLAN_SPEED_10 &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706 priv->duplex == TLAN_DUPLEX_HALF) {
2707 TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x0000);
2708 } else if ( priv->speed == TLAN_SPEED_10 &&
2709 priv->duplex == TLAN_DUPLEX_FULL) {
2710 priv->tlanFullDuplex = TRUE;
2711 TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x0100);
2712 } else if ( priv->speed == TLAN_SPEED_100 &&
2713 priv->duplex == TLAN_DUPLEX_HALF) {
2714 TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x2000);
2715 } else if ( priv->speed == TLAN_SPEED_100 &&
2716 priv->duplex == TLAN_DUPLEX_FULL) {
2717 priv->tlanFullDuplex = TRUE;
2718 TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x2100);
2719 } else {
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002720
Linus Torvalds1da177e2005-04-16 15:20:36 -07002721 /* Set Auto-Neg advertisement */
2722 TLan_MiiWriteReg( dev, phy, MII_AN_ADV, (ability << 5) | 1);
2723 /* Enablee Auto-Neg */
2724 TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1000 );
2725 /* Restart Auto-Neg */
2726 TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1200 );
2727 /* Wait for 4 sec for autonegotiation
2728 * to complete. The max spec time is less than this
2729 * but the card need additional time to start AN.
2730 * .5 sec should be plenty extra.
2731 */
2732 printk( "TLAN: %s: Starting autonegotiation.\n", dev->name );
2733 TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_PHY_FINISH_AN );
2734 return;
2735 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002736
2737 }
2738
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739 if ( ( priv->aui ) && ( priv->phyNum != 0 ) ) {
2740 priv->phyNum = 0;
2741 data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
2742 TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, data );
2743 TLan_SetTimer( dev, (40*HZ/1000), TLAN_TIMER_PHY_PDOWN );
2744 return;
2745 } else if ( priv->phyNum == 0 ) {
2746 control = 0;
2747 TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tctl );
2748 if ( priv->aui ) {
2749 tctl |= TLAN_TC_AUISEL;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002750 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751 tctl &= ~TLAN_TC_AUISEL;
2752 if ( priv->duplex == TLAN_DUPLEX_FULL ) {
2753 control |= MII_GC_DUPLEX;
2754 priv->tlanFullDuplex = TRUE;
2755 }
2756 if ( priv->speed == TLAN_SPEED_100 ) {
2757 control |= MII_GC_SPEEDSEL;
2758 }
2759 }
2760 TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, control );
2761 TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tctl );
2762 }
2763
2764 /* Wait for 2 sec to give the transceiver time
2765 * to establish link.
2766 */
2767 TLan_SetTimer( dev, (4*HZ), TLAN_TIMER_FINISH_RESET );
2768
2769} /* TLan_PhyStartLink */
2770
2771
2772
2773
Harvey Harrison98e0f522008-02-18 10:04:38 -08002774static void TLan_PhyFinishAutoNeg( struct net_device *dev )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775{
2776 TLanPrivateInfo *priv = netdev_priv(dev);
2777 u16 an_adv;
2778 u16 an_lpa;
2779 u16 data;
2780 u16 mode;
2781 u16 phy;
2782 u16 status;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002783
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784 phy = priv->phy[priv->phyNum];
2785
2786 TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
2787 udelay( 1000 );
2788 TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
2789
2790 if ( ! ( status & MII_GS_AUTOCMPLT ) ) {
2791 /* Wait for 8 sec to give the process
2792 * more time. Perhaps we should fail after a while.
2793 */
2794 if (!priv->neg_be_verbose++) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002795 pr_info("TLAN: Giving autonegotiation more time.\n");
2796 pr_info("TLAN: Please check that your adapter has\n");
2797 pr_info("TLAN: been properly connected to a HUB or Switch.\n");
2798 pr_info("TLAN: Trying to establish link in the background...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799 }
2800 TLan_SetTimer( dev, (8*HZ), TLAN_TIMER_PHY_FINISH_AN );
2801 return;
2802 }
2803
2804 printk( "TLAN: %s: Autonegotiation complete.\n", dev->name );
2805 TLan_MiiReadReg( dev, phy, MII_AN_ADV, &an_adv );
2806 TLan_MiiReadReg( dev, phy, MII_AN_LPA, &an_lpa );
2807 mode = an_adv & an_lpa & 0x03E0;
2808 if ( mode & 0x0100 ) {
2809 priv->tlanFullDuplex = TRUE;
2810 } else if ( ! ( mode & 0x0080 ) && ( mode & 0x0040 ) ) {
2811 priv->tlanFullDuplex = TRUE;
2812 }
2813
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002814 if ( ( ! ( mode & 0x0180 ) ) &&
2815 ( priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10 ) &&
2816 ( priv->phyNum != 0 ) ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817 priv->phyNum = 0;
2818 data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
2819 TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, data );
2820 TLan_SetTimer( dev, (400*HZ/1000), TLAN_TIMER_PHY_PDOWN );
2821 return;
2822 }
2823
2824 if ( priv->phyNum == 0 ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002825 if ( ( priv->duplex == TLAN_DUPLEX_FULL ) ||
2826 ( an_adv & an_lpa & 0x0040 ) ) {
2827 TLan_MiiWriteReg( dev, phy, MII_GEN_CTL,
2828 MII_GC_AUTOENB | MII_GC_DUPLEX );
2829 pr_info("TLAN: Starting internal PHY with FULL-DUPLEX\n" );
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830 } else {
2831 TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, MII_GC_AUTOENB );
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07002832 pr_info( "TLAN: Starting internal PHY with HALF-DUPLEX\n" );
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833 }
2834 }
2835
2836 /* Wait for 100 ms. No reason in partiticular.
2837 */
2838 TLan_SetTimer( dev, (HZ/10), TLAN_TIMER_FINISH_RESET );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002839
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840} /* TLan_PhyFinishAutoNeg */
2841
2842#ifdef MONITOR
2843
2844 /*********************************************************************
2845 *
2846 * TLan_phyMonitor
2847 *
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002848 * Returns:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849 * None
2850 *
2851 * Params:
2852 * dev The device structure of this device.
2853 *
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002854 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855 * This function monitors PHY condition by reading the status
2856 * register via the MII bus. This can be used to give info
2857 * about link changes (up/down), and possible switch to alternate
2858 * media.
2859 *
2860 * ******************************************************************/
2861
2862void TLan_PhyMonitor( struct net_device *dev )
2863{
2864 TLanPrivateInfo *priv = netdev_priv(dev);
2865 u16 phy;
2866 u16 phy_status;
2867
2868 phy = priv->phy[priv->phyNum];
2869
2870 /* Get PHY status register */
2871 TLan_MiiReadReg( dev, phy, MII_GEN_STS, &phy_status );
2872
2873 /* Check if link has been lost */
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002874 if (!(phy_status & MII_GS_LINK)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002875 if (priv->link) {
2876 priv->link = 0;
2877 printk(KERN_DEBUG "TLAN: %s has lost link\n", dev->name);
7d17c1d2005-05-12 19:45:25 -04002878 netif_carrier_off(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879 TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_LINK_BEAT );
2880 return;
2881 }
2882 }
2883
2884 /* Link restablished? */
2885 if ((phy_status & MII_GS_LINK) && !priv->link) {
2886 priv->link = 1;
2887 printk(KERN_DEBUG "TLAN: %s has reestablished link\n", dev->name);
7d17c1d2005-05-12 19:45:25 -04002888 netif_carrier_on(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889 }
2890
2891 /* Setup a new monitor */
2892 TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_LINK_BEAT );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002893}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002894
2895#endif /* MONITOR */
2896
2897
2898/*****************************************************************************
2899******************************************************************************
2900
2901 ThunderLAN Driver MII Routines
2902
2903 These routines are based on the information in Chap. 2 of the
2904 "ThunderLAN Programmer's Guide", pp. 15-24.
2905
2906******************************************************************************
2907*****************************************************************************/
2908
2909
2910 /***************************************************************
2911 * TLan_MiiReadReg
2912 *
2913 * Returns:
2914 * 0 if ack received ok
2915 * 1 otherwise.
2916 *
2917 * Parms:
2918 * dev The device structure containing
2919 * The io address and interrupt count
2920 * for this device.
2921 * phy The address of the PHY to be queried.
2922 * reg The register whose contents are to be
Matt Mackall4a4efbd2006-01-03 13:27:11 +01002923 * retrieved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924 * val A pointer to a variable to store the
2925 * retrieved value.
2926 *
Matt Mackall4a4efbd2006-01-03 13:27:11 +01002927 * This function uses the TLAN's MII bus to retrieve the contents
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928 * of a given register on a PHY. It sends the appropriate info
2929 * and then reads the 16-bit register value from the MII bus via
2930 * the TLAN SIO register.
2931 *
2932 **************************************************************/
2933
Harvey Harrison98e0f522008-02-18 10:04:38 -08002934static int TLan_MiiReadReg( struct net_device *dev, u16 phy, u16 reg, u16 *val )
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935{
2936 u8 nack;
2937 u16 sio, tmp;
2938 u32 i;
2939 int err;
2940 int minten;
2941 TLanPrivateInfo *priv = netdev_priv(dev);
2942 unsigned long flags = 0;
2943
2944 err = FALSE;
2945 outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR);
2946 sio = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002947
Linus Torvalds1da177e2005-04-16 15:20:36 -07002948 if (!in_irq())
2949 spin_lock_irqsave(&priv->lock, flags);
2950
2951 TLan_MiiSync(dev->base_addr);
2952
2953 minten = TLan_GetBit( TLAN_NET_SIO_MINTEN, sio );
2954 if ( minten )
2955 TLan_ClearBit(TLAN_NET_SIO_MINTEN, sio);
2956
2957 TLan_MiiSendData( dev->base_addr, 0x1, 2 ); /* Start ( 01b ) */
2958 TLan_MiiSendData( dev->base_addr, 0x2, 2 ); /* Read ( 10b ) */
2959 TLan_MiiSendData( dev->base_addr, phy, 5 ); /* Device # */
2960 TLan_MiiSendData( dev->base_addr, reg, 5 ); /* Register # */
2961
2962
2963 TLan_ClearBit(TLAN_NET_SIO_MTXEN, sio); /* Change direction */
2964
2965 TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); /* Clock Idle bit */
2966 TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
2967 TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); /* Wait 300ns */
2968
2969 nack = TLan_GetBit(TLAN_NET_SIO_MDATA, sio); /* Check for ACK */
2970 TLan_SetBit(TLAN_NET_SIO_MCLK, sio); /* Finish ACK */
2971 if (nack) { /* No ACK, so fake it */
2972 for (i = 0; i < 16; i++) {
2973 TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
2974 TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
2975 }
2976 tmp = 0xffff;
2977 err = TRUE;
2978 } else { /* ACK, so read data */
2979 for (tmp = 0, i = 0x8000; i; i >>= 1) {
2980 TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
2981 if (TLan_GetBit(TLAN_NET_SIO_MDATA, sio))
2982 tmp |= i;
2983 TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
2984 }
2985 }
2986
2987
2988 TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); /* Idle cycle */
2989 TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
2990
2991 if ( minten )
2992 TLan_SetBit(TLAN_NET_SIO_MINTEN, sio);
2993
2994 *val = tmp;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04002995
Linus Torvalds1da177e2005-04-16 15:20:36 -07002996 if (!in_irq())
2997 spin_unlock_irqrestore(&priv->lock, flags);
2998
2999 return err;
3000
3001} /* TLan_MiiReadReg */
3002
3003
3004
3005
3006 /***************************************************************
3007 * TLan_MiiSendData
3008 *
3009 * Returns:
3010 * Nothing
3011 * Parms:
3012 * base_port The base IO port of the adapter in
3013 * question.
3014 * dev The address of the PHY to be queried.
3015 * data The value to be placed on the MII bus.
3016 * num_bits The number of bits in data that are to
3017 * be placed on the MII bus.
3018 *
3019 * This function sends on sequence of bits on the MII
3020 * configuration bus.
3021 *
3022 **************************************************************/
3023
Harvey Harrison98e0f522008-02-18 10:04:38 -08003024static void TLan_MiiSendData( u16 base_port, u32 data, unsigned num_bits )
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025{
3026 u16 sio;
3027 u32 i;
3028
3029 if ( num_bits == 0 )
3030 return;
3031
3032 outw( TLAN_NET_SIO, base_port + TLAN_DIO_ADR );
3033 sio = base_port + TLAN_DIO_DATA + TLAN_NET_SIO;
3034 TLan_SetBit( TLAN_NET_SIO_MTXEN, sio );
3035
3036 for ( i = ( 0x1 << ( num_bits - 1 ) ); i; i >>= 1 ) {
3037 TLan_ClearBit( TLAN_NET_SIO_MCLK, sio );
3038 (void) TLan_GetBit( TLAN_NET_SIO_MCLK, sio );
3039 if ( data & i )
3040 TLan_SetBit( TLAN_NET_SIO_MDATA, sio );
3041 else
3042 TLan_ClearBit( TLAN_NET_SIO_MDATA, sio );
3043 TLan_SetBit( TLAN_NET_SIO_MCLK, sio );
3044 (void) TLan_GetBit( TLAN_NET_SIO_MCLK, sio );
3045 }
3046
3047} /* TLan_MiiSendData */
3048
3049
3050
3051
3052 /***************************************************************
3053 * TLan_MiiSync
3054 *
3055 * Returns:
3056 * Nothing
3057 * Parms:
3058 * base_port The base IO port of the adapter in
3059 * question.
3060 *
3061 * This functions syncs all PHYs in terms of the MII configuration
3062 * bus.
3063 *
3064 **************************************************************/
3065
Harvey Harrison98e0f522008-02-18 10:04:38 -08003066static void TLan_MiiSync( u16 base_port )
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067{
3068 int i;
3069 u16 sio;
3070
3071 outw( TLAN_NET_SIO, base_port + TLAN_DIO_ADR );
3072 sio = base_port + TLAN_DIO_DATA + TLAN_NET_SIO;
3073
3074 TLan_ClearBit( TLAN_NET_SIO_MTXEN, sio );
3075 for ( i = 0; i < 32; i++ ) {
3076 TLan_ClearBit( TLAN_NET_SIO_MCLK, sio );
3077 TLan_SetBit( TLAN_NET_SIO_MCLK, sio );
3078 }
3079
3080} /* TLan_MiiSync */
3081
3082
3083
3084
3085 /***************************************************************
3086 * TLan_MiiWriteReg
3087 *
3088 * Returns:
3089 * Nothing
3090 * Parms:
3091 * dev The device structure for the device
3092 * to write to.
3093 * phy The address of the PHY to be written to.
3094 * reg The register whose contents are to be
3095 * written.
3096 * val The value to be written to the register.
3097 *
3098 * This function uses the TLAN's MII bus to write the contents of a
3099 * given register on a PHY. It sends the appropriate info and then
3100 * writes the 16-bit register value from the MII configuration bus
3101 * via the TLAN SIO register.
3102 *
3103 **************************************************************/
3104
Harvey Harrison98e0f522008-02-18 10:04:38 -08003105static void TLan_MiiWriteReg( struct net_device *dev, u16 phy, u16 reg, u16 val )
Linus Torvalds1da177e2005-04-16 15:20:36 -07003106{
3107 u16 sio;
3108 int minten;
3109 unsigned long flags = 0;
3110 TLanPrivateInfo *priv = netdev_priv(dev);
3111
3112 outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR);
3113 sio = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04003114
Linus Torvalds1da177e2005-04-16 15:20:36 -07003115 if (!in_irq())
3116 spin_lock_irqsave(&priv->lock, flags);
3117
3118 TLan_MiiSync( dev->base_addr );
3119
3120 minten = TLan_GetBit( TLAN_NET_SIO_MINTEN, sio );
3121 if ( minten )
3122 TLan_ClearBit( TLAN_NET_SIO_MINTEN, sio );
3123
3124 TLan_MiiSendData( dev->base_addr, 0x1, 2 ); /* Start ( 01b ) */
3125 TLan_MiiSendData( dev->base_addr, 0x1, 2 ); /* Write ( 01b ) */
3126 TLan_MiiSendData( dev->base_addr, phy, 5 ); /* Device # */
3127 TLan_MiiSendData( dev->base_addr, reg, 5 ); /* Register # */
3128
3129 TLan_MiiSendData( dev->base_addr, 0x2, 2 ); /* Send ACK */
3130 TLan_MiiSendData( dev->base_addr, val, 16 ); /* Send Data */
3131
3132 TLan_ClearBit( TLAN_NET_SIO_MCLK, sio ); /* Idle cycle */
3133 TLan_SetBit( TLAN_NET_SIO_MCLK, sio );
3134
3135 if ( minten )
3136 TLan_SetBit( TLAN_NET_SIO_MINTEN, sio );
Jeff Garzik6aa20a22006-09-13 13:24:59 -04003137
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138 if (!in_irq())
3139 spin_unlock_irqrestore(&priv->lock, flags);
3140
3141} /* TLan_MiiWriteReg */
3142
3143
3144
3145
3146/*****************************************************************************
3147******************************************************************************
3148
3149 ThunderLAN Driver Eeprom routines
3150
3151 The Compaq Netelligent 10 and 10/100 cards use a Microchip 24C02A
3152 EEPROM. These functions are based on information in Microchip's
3153 data sheet. I don't know how well this functions will work with
3154 other EEPROMs.
3155
3156******************************************************************************
3157*****************************************************************************/
3158
3159
3160 /***************************************************************
3161 * TLan_EeSendStart
3162 *
3163 * Returns:
3164 * Nothing
Jeff Garzik6aa20a22006-09-13 13:24:59 -04003165 * Parms:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003166 * io_base The IO port base address for the
3167 * TLAN device with the EEPROM to
3168 * use.
3169 *
3170 * This function sends a start cycle to an EEPROM attached
3171 * to a TLAN chip.
3172 *
3173 **************************************************************/
3174
Harvey Harrison98e0f522008-02-18 10:04:38 -08003175static void TLan_EeSendStart( u16 io_base )
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176{
3177 u16 sio;
3178
3179 outw( TLAN_NET_SIO, io_base + TLAN_DIO_ADR );
3180 sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
3181
3182 TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
3183 TLan_SetBit( TLAN_NET_SIO_EDATA, sio );
3184 TLan_SetBit( TLAN_NET_SIO_ETXEN, sio );
3185 TLan_ClearBit( TLAN_NET_SIO_EDATA, sio );
3186 TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
3187
3188} /* TLan_EeSendStart */
3189
3190
3191
3192
3193 /***************************************************************
3194 * TLan_EeSendByte
3195 *
3196 * Returns:
3197 * If the correct ack was received, 0, otherwise 1
3198 * Parms: io_base The IO port base address for the
3199 * TLAN device with the EEPROM to
3200 * use.
3201 * data The 8 bits of information to
3202 * send to the EEPROM.
3203 * stop If TLAN_EEPROM_STOP is passed, a
3204 * stop cycle is sent after the
3205 * byte is sent after the ack is
3206 * read.
3207 *
3208 * This function sends a byte on the serial EEPROM line,
3209 * driving the clock to send each bit. The function then
3210 * reverses transmission direction and reads an acknowledge
3211 * bit.
3212 *
3213 **************************************************************/
3214
Harvey Harrison98e0f522008-02-18 10:04:38 -08003215static int TLan_EeSendByte( u16 io_base, u8 data, int stop )
Linus Torvalds1da177e2005-04-16 15:20:36 -07003216{
3217 int err;
3218 u8 place;
3219 u16 sio;
3220
3221 outw( TLAN_NET_SIO, io_base + TLAN_DIO_ADR );
3222 sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
3223
3224 /* Assume clock is low, tx is enabled; */
3225 for ( place = 0x80; place != 0; place >>= 1 ) {
3226 if ( place & data )
3227 TLan_SetBit( TLAN_NET_SIO_EDATA, sio );
3228 else
3229 TLan_ClearBit( TLAN_NET_SIO_EDATA, sio );
3230 TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
3231 TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
3232 }
3233 TLan_ClearBit( TLAN_NET_SIO_ETXEN, sio );
3234 TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
3235 err = TLan_GetBit( TLAN_NET_SIO_EDATA, sio );
3236 TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
3237 TLan_SetBit( TLAN_NET_SIO_ETXEN, sio );
3238
3239 if ( ( ! err ) && stop ) {
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07003240 /* STOP, raise data while clock is high */
3241 TLan_ClearBit( TLAN_NET_SIO_EDATA, sio );
Linus Torvalds1da177e2005-04-16 15:20:36 -07003242 TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
3243 TLan_SetBit( TLAN_NET_SIO_EDATA, sio );
3244 }
3245
3246 return ( err );
3247
3248} /* TLan_EeSendByte */
3249
3250
3251
3252
3253 /***************************************************************
3254 * TLan_EeReceiveByte
3255 *
3256 * Returns:
3257 * Nothing
3258 * Parms:
3259 * io_base The IO port base address for the
3260 * TLAN device with the EEPROM to
3261 * use.
3262 * data An address to a char to hold the
3263 * data sent from the EEPROM.
3264 * stop If TLAN_EEPROM_STOP is passed, a
3265 * stop cycle is sent after the
3266 * byte is received, and no ack is
3267 * sent.
3268 *
3269 * This function receives 8 bits of data from the EEPROM
3270 * over the serial link. It then sends and ack bit, or no
3271 * ack and a stop bit. This function is used to retrieve
3272 * data after the address of a byte in the EEPROM has been
3273 * sent.
3274 *
3275 **************************************************************/
3276
Harvey Harrison98e0f522008-02-18 10:04:38 -08003277static void TLan_EeReceiveByte( u16 io_base, u8 *data, int stop )
Linus Torvalds1da177e2005-04-16 15:20:36 -07003278{
3279 u8 place;
3280 u16 sio;
3281
3282 outw( TLAN_NET_SIO, io_base + TLAN_DIO_ADR );
3283 sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
3284 *data = 0;
3285
3286 /* Assume clock is low, tx is enabled; */
3287 TLan_ClearBit( TLAN_NET_SIO_ETXEN, sio );
3288 for ( place = 0x80; place; place >>= 1 ) {
3289 TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
3290 if ( TLan_GetBit( TLAN_NET_SIO_EDATA, sio ) )
3291 *data |= place;
3292 TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
3293 }
3294
3295 TLan_SetBit( TLAN_NET_SIO_ETXEN, sio );
3296 if ( ! stop ) {
3297 TLan_ClearBit( TLAN_NET_SIO_EDATA, sio ); /* Ack = 0 */
3298 TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
3299 TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
3300 } else {
3301 TLan_SetBit( TLAN_NET_SIO_EDATA, sio ); /* No ack = 1 (?) */
3302 TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
3303 TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
Stephen Hemmingerdfc2c0a2008-05-30 09:49:58 -07003304 /* STOP, raise data while clock is high */
3305 TLan_ClearBit( TLAN_NET_SIO_EDATA, sio );
Linus Torvalds1da177e2005-04-16 15:20:36 -07003306 TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
3307 TLan_SetBit( TLAN_NET_SIO_EDATA, sio );
3308 }
3309
3310} /* TLan_EeReceiveByte */
3311
3312
3313
3314
3315 /***************************************************************
3316 * TLan_EeReadByte
3317 *
3318 * Returns:
3319 * No error = 0, else, the stage at which the error
3320 * occurred.
3321 * Parms:
3322 * io_base The IO port base address for the
3323 * TLAN device with the EEPROM to
3324 * use.
3325 * ee_addr The address of the byte in the
3326 * EEPROM whose contents are to be
3327 * retrieved.
3328 * data An address to a char to hold the
3329 * data obtained from the EEPROM.
3330 *
3331 * This function reads a byte of information from an byte
3332 * cell in the EEPROM.
3333 *
3334 **************************************************************/
3335
Harvey Harrison98e0f522008-02-18 10:04:38 -08003336static int TLan_EeReadByte( struct net_device *dev, u8 ee_addr, u8 *data )
Linus Torvalds1da177e2005-04-16 15:20:36 -07003337{
3338 int err;
3339 TLanPrivateInfo *priv = netdev_priv(dev);
3340 unsigned long flags = 0;
3341 int ret=0;
3342
3343 spin_lock_irqsave(&priv->lock, flags);
3344
3345 TLan_EeSendStart( dev->base_addr );
3346 err = TLan_EeSendByte( dev->base_addr, 0xA0, TLAN_EEPROM_ACK );
3347 if (err)
3348 {
3349 ret=1;
3350 goto fail;
3351 }
3352 err = TLan_EeSendByte( dev->base_addr, ee_addr, TLAN_EEPROM_ACK );
3353 if (err)
3354 {
3355 ret=2;
3356 goto fail;
3357 }
3358 TLan_EeSendStart( dev->base_addr );
3359 err = TLan_EeSendByte( dev->base_addr, 0xA1, TLAN_EEPROM_ACK );
3360 if (err)
3361 {
3362 ret=3;
3363 goto fail;
3364 }
3365 TLan_EeReceiveByte( dev->base_addr, data, TLAN_EEPROM_STOP );
3366fail:
3367 spin_unlock_irqrestore(&priv->lock, flags);
3368
3369 return ret;
3370
3371} /* TLan_EeReadByte */
3372
3373
3374