0bf275b93386e5783727b691929e5b8c3512fa7c
[people/lynusvaz/gpxe.git] / src / drivers / net / 3c515.c
1 /*
2 *    3c515.c -- 3COM 3C515 Fast Etherlink ISA 10/100BASE-TX driver for etherboot
3 *    Copyright (C) 2002 Timothy Legge <tlegge@rogers.com>
4 *
5 *    This program is free software; you can redistribute it and/or modify
6 *    it under the terms of the GNU General Public License as published by
7 *    the Free Software Foundation; either version 2 of the License, or
8 *    (at your option) any later version.
9 *
10 *    This program is distributed in the hope that it will be useful,
11 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 *    GNU General Public License for more details.
14 *
15 *    You should have received a copy of the GNU General Public License
16 *    along with this program; if not, write to the Free Software
17 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * Portions of this code:
20 * Copyright (C) 1997-2002 Donald Becker  3c515.c: A 3Com ISA EtherLink XL "Corkscrew" ethernet driver for linux.
21 * Copyright (C) 2001 P.J.H.Fox (fox@roestock.demon.co.uk) ISAPNP Tools
22 * Copyright (c) 2002 Jaroslav Kysela <perex@suse.cz>  ISA Plug & Play support Linux Kernel
23 * Copyright (C) 2000 Shusuke Nisiyama <shu@athena.qe.eng.hokudai.ac.jp> etherboot-5.0.5 3c595.c
24 * Coptright (C) 1995 Martin Renters etherboot-5.0.5 3c509.c
25 * Copyright (C) 1999 LightSys Technology Services, Inc. etherboot-5.0.5 3c90x.c
26 * Portions Copyright (C) 1999 Steve Smith etherboot-5.0.5 3c90x.c
27 *
28 * The probe and reset functions and defines are direct copies from the
29 * Becker code modified where necessary to make it work for etherboot
30 *
31 * The poll and transmit functions either contain code from or were written by referencing
32 * the above referenced etherboot drivers.  This driver would not have been
33 * possible without this prior work
34 *
35 * REVISION HISTORY:
36 * ================
37 * v0.10 4-17-2002       TJL     Initial implementation.
38 * v0.11 4-17-2002       TJL     Cleanup of the code
39 * v0.12 4-26-2002       TJL     Added ISA Plug and Play for Non-PNP Bioses
40 * v0.13 6-10-2002       TJL     Fixed ISA_PNP MAC Address problem
41 * v0.14 9-23-2003       TJL     Replaced delay with currticks
42 *
43 * Indent Options: indent -kr -i8
44 * *********************************************************/
45
46
47 #define ISA_PNP
48 /*#define EDEBUG1*/
49
50 /* to get some global routines like printf */
51 #include "etherboot.h"
52 /* to get the interface to the body of the program */
53 #include "nic.h"
54 #include "isa.h"
55 #include "timer.h"
56
57 #ifdef ISA_PNP
58
59 static void t3c515_wait(unsigned int nticks)
60 {
61         unsigned int to = currticks() + nticks;
62         while (currticks() < to)
63                 /* wait */ ;
64 }
65 #endif
66 /* TJL definations */
67 #define HZ      100
68 #define u16 unsigned short
69 #define u32 unsigned long
70 #define s16 signed short
71 #define s32 signed long
72 static unsigned short eth_nic_base;
73 #define BASE    (eth_nic_base)
74 static int if_port;
75 struct corkscrew_private *vp;
76 /* Brought directly from 3c515.c by Becker */
77 #define CORKSCREW 1
78
79 /* Maximum events (Rx packets, etc.) to handle at each interrupt.
80 static int max_interrupt_work = 20;
81 */
82
83 /* Enable the automatic media selection code -- usually set. */
84 #define AUTOMEDIA 1
85
86 /* Allow the use of fragment bus master transfers instead of only
87    programmed-I/O for Vortex cards.  Full-bus-master transfers are always
88    enabled by default on Boomerang cards.  If VORTEX_BUS_MASTER is defined,
89    the feature may be turned on using 'options'. */
90 #define VORTEX_BUS_MASTER
91
92 /* A few values that may be tweaked. */
93 /* Keep the ring sizes a power of two for efficiency. */
94 #define TX_RING_SIZE    16
95 #define RX_RING_SIZE    16
96 #define PKT_BUF_SZ              1536    /* Size of each temporary Rx buffer. */
97
98 /* "Knobs" for adjusting internal parameters. */
99 /* Put out somewhat more debugging messages. (0 - no msg, 1 minimal msgs). */
100 #define DRIVER_DEBUG 1
101 /* Some values here only for performance evaluation and path-coverage
102    debugging.
103 static int rx_nocopy, rx_copy, queued_packet;
104 */
105
106 #ifdef DRIVER_DEBUG
107 static int corkscrew_debug = DRIVER_DEBUG;
108 #else
109 static int corkscrew_debug = 1;
110 #endif
111
112 #define CORKSCREW_ID 10
113
114 #define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
115 #define EL3_CMD 0x0e
116 #define EL3_STATUS 0x0e
117 #define RX_BYTES_MASK                   (unsigned short) (0x07ff)
118
119 enum corkscrew_cmd {
120         TotalReset = 0 << 11, SelectWindow = 1 << 11, StartCoax = 2 << 11,
121         RxDisable = 3 << 11, RxEnable = 4 << 11, RxReset = 5 << 11,
122         UpStall = 6 << 11, UpUnstall = (6 << 11) + 1,
123         DownStall = (6 << 11) + 2, DownUnstall = (6 << 11) + 3,
124         RxDiscard = 8 << 11, TxEnable = 9 << 11, TxDisable =
125             10 << 11, TxReset = 11 << 11,
126         FakeIntr = 12 << 11, AckIntr = 13 << 11, SetIntrEnb = 14 << 11,
127         SetStatusEnb = 15 << 11, SetRxFilter = 16 << 11, SetRxThreshold =
128             17 << 11,
129         SetTxThreshold = 18 << 11, SetTxStart = 19 << 11,
130         StartDMAUp = 20 << 11, StartDMADown = (20 << 11) + 1, StatsEnable =
131             21 << 11,
132         StatsDisable = 22 << 11, StopCoax = 23 << 11,
133 };
134
135 /* The SetRxFilter command accepts the following classes: */
136 enum RxFilter {
137         RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8
138 };
139
140 /* Bits in the general status register. */
141 enum corkscrew_status {
142         IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
143         TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
144         IntReq = 0x0040, StatsFull = 0x0080,
145         DMADone = 1 << 8, DownComplete = 1 << 9, UpComplete = 1 << 10,
146         DMAInProgress = 1 << 11,        /* DMA controller is still busy. */
147         CmdInProgress = 1 << 12,        /* EL3_CMD is still busy. */
148 };
149
150 /* Register window 1 offsets, the window used in normal operation.
151    On the Corkscrew this window is always mapped at offsets 0x10-0x1f. */
152 enum Window1 {
153         TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14,
154         RxStatus = 0x18, Timer = 0x1A, TxStatus = 0x1B,
155         TxFree = 0x1C,          /* Remaining free bytes in Tx buffer. */
156 };
157 enum Window0 {
158         Wn0IRQ = 0x08,
159 #if defined(CORKSCREW)
160         Wn0EepromCmd = 0x200A,  /* Corkscrew EEPROM command register. */
161         Wn0EepromData = 0x200C, /* Corkscrew EEPROM results register. */
162 #else
163         Wn0EepromCmd = 10,      /* Window 0: EEPROM command register. */
164         Wn0EepromData = 12,     /* Window 0: EEPROM results register. */
165 #endif
166 };
167 enum Win0_EEPROM_bits {
168         EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0,
169         EEPROM_EWENB = 0x30,    /* Enable erasing/writing for 10 msec. */
170         EEPROM_EWDIS = 0x00,    /* Disable EWENB before 10 msec timeout. */
171 };
172
173 enum Window3 {                  /* Window 3: MAC/config bits. */
174         Wn3_Config = 0, Wn3_MAC_Ctrl = 6, Wn3_Options = 8,
175 };
176 union wn3_config {
177         int i;
178         struct w3_config_fields {
179                 unsigned int ram_size:3, ram_width:1, ram_speed:2,
180                     rom_size:2;
181                 int pad8:8;
182                 unsigned int ram_split:2, pad18:2, xcvr:3, pad21:1,
183                     autoselect:1;
184                 int pad24:7;
185         } u;
186 };
187
188 enum Window4 {
189         Wn4_NetDiag = 6, Wn4_Media = 10,        /* Window 4: Xcvr/media bits. */
190 };
191 enum Win4_Media_bits {
192         Media_SQE = 0x0008,     /* Enable SQE error counting for AUI. */
193         Media_10TP = 0x00C0,    /* Enable link beat and jabber for 10baseT. */
194         Media_Lnk = 0x0080,     /* Enable just link beat for 100TX/100FX. */
195         Media_LnkBeat = 0x0800,
196 };
197 enum Window7 {                  /* Window 7: Bus Master control. */
198         Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12,
199 };
200
201 /* Boomerang-style bus master control registers.  Note ISA aliases! */
202 enum MasterCtrl {
203         PktStatus = 0x400, DownListPtr = 0x404, FragAddr = 0x408, FragLen =
204             0x40c,
205         TxFreeThreshold = 0x40f, UpPktStatus = 0x410, UpListPtr = 0x418,
206 };
207
208 /* The Rx and Tx descriptor lists.
209    Caution Alpha hackers: these types are 32 bits!  Note also the 8 byte
210    alignment contraint on tx_ring[] and rx_ring[]. */
211 struct boom_rx_desc {
212         u32 next;
213         s32 status;
214         u32 addr;
215         s32 length;
216 };
217
218 /* Values for the Rx status entry. */
219 enum rx_desc_status {
220         RxDComplete = 0x00008000, RxDError = 0x4000,
221         /* See boomerang_rx() for actual error bits */
222 };
223
224 struct boom_tx_desc {
225         u32 next;
226         s32 status;
227         u32 addr;
228         s32 length;
229 };
230
231 struct corkscrew_private {
232         const char *product_name;
233         struct net_device *next_module;
234         /* The Rx and Tx rings are here to keep them quad-word-aligned. */
235         struct boom_rx_desc rx_ring[RX_RING_SIZE];
236         struct boom_tx_desc tx_ring[TX_RING_SIZE];
237         /* The addresses of transmit- and receive-in-place skbuffs. */
238         struct sk_buff *rx_skbuff[RX_RING_SIZE];
239         struct sk_buff *tx_skbuff[TX_RING_SIZE];
240         unsigned int cur_rx, cur_tx;    /* The next free ring entry */
241         unsigned int dirty_rx, dirty_tx;        /* The ring entries to be free()ed. */
242         struct sk_buff *tx_skb; /* Packet being eaten by bus master ctrl.  */
243         int capabilities;       /* Adapter capabilities word. */
244         int options;            /* User-settable misc. driver options. */
245         int last_rx_packets;    /* For media autoselection. */
246         unsigned int available_media:8, /* From Wn3_Options */
247          media_override:3,      /* Passed-in media type. */
248          default_media:3,       /* Read from the EEPROM. */
249          full_duplex:1, autoselect:1, bus_master:1,     /* Vortex can only do a fragment bus-m. */
250          full_bus_master_tx:1, full_bus_master_rx:1,    /* Boomerang  */
251          tx_full:1;
252 };
253
254 /* The action to take with a media selection timer tick.
255    Note that we deviate from the 3Com order by checking 10base2 before AUI.
256  */
257 enum xcvr_types {
258         XCVR_10baseT =
259             0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx,
260         XCVR_100baseFx, XCVR_MII = 6, XCVR_Default = 8,
261 };
262
263 static struct media_table {
264         char *name;
265         unsigned int media_bits:16,     /* Bits to set in Wn4_Media register. */
266          mask:8,                /* The transceiver-present bit in Wn3_Config. */
267          next:8;                /* The media type to try next. */
268         short wait;             /* Time before we check media status. */
269 } media_tbl[] = {
270         {
271         "10baseT", Media_10TP, 0x08, XCVR_10base2, (14 * HZ) / 10}
272         , {
273         "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1 * HZ) / 10}
274         , {
275         "undefined", 0, 0x80, XCVR_10baseT, 10000}
276         , {
277         "10base2", 0, 0x10, XCVR_AUI, (1 * HZ) / 10}
278         , {
279         "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx,
280                     (14 * HZ) / 10}
281         , {
282         "100baseFX", Media_Lnk, 0x04, XCVR_MII, (14 * HZ) / 10}
283         , {
284         "MII", 0, 0x40, XCVR_10baseT, 3 * HZ}
285         , {
286         "undefined", 0, 0x01, XCVR_10baseT, 10000}
287         , {
288         "Default", 0, 0xFF, XCVR_10baseT, 10000}
289 ,};
290
291 /* TILEG Modified to remove reference to dev */
292 static int corkscrew_found_device(int ioaddr, int irq, int product_index,
293                                   int options, struct nic *nic);
294 static int corkscrew_probe1(int ioaddr, int irq, int product_index,
295                             struct nic *nic);
296
297 /* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
298 /* Note: this is the only limit on the number of cards supported!! */
299 static int options[8] = { -1, -1, -1, -1, -1, -1, -1, -1, };
300
301 /* End Brought directly from 3c515.c by Becker */
302
303 /**************************************************************************
304 RESET - Reset adapter
305 ***************************************************************************/
306 static void t515_reset(struct nic *nic)
307 {
308         int ioaddr = BASE;
309         union wn3_config config;
310         int i;
311
312         /* Before initializing select the active media port. */
313         EL3WINDOW(3);
314         if (vp->full_duplex)
315                 outb(0x20, ioaddr + Wn3_MAC_Ctrl);      /* Set the full-duplex bit. */
316         config.i = inl(ioaddr + Wn3_Config);
317
318         if (vp->media_override != 7) {
319                 if (corkscrew_debug > 1)
320                         printf("Media override to transceiver %d (%s).\n",
321                                vp->media_override,
322                                media_tbl[vp->media_override].name);
323                 if_port = vp->media_override;
324         } else if (vp->autoselect) {
325                 /* Find first available media type, starting with 100baseTx. */
326                 if_port = 4;
327                 while (!(vp->available_media & media_tbl[if_port].mask))
328                         if_port = media_tbl[if_port].next;
329
330                 if (corkscrew_debug > 1)
331                         printf("Initial media type %s.\n",
332                                media_tbl[if_port].name);
333         } else
334                 if_port = vp->default_media;
335
336         config.u.xcvr = if_port;
337         outl(config.i, ioaddr + Wn3_Config);
338
339         if (corkscrew_debug > 1) {
340                 printf("corkscrew_open() InternalConfig 0x%hX.\n",
341                        config.i);
342         }
343
344         outw(TxReset, ioaddr + EL3_CMD);
345         for (i = 20; i >= 0; i--)
346                 if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
347                         break;
348
349         outw(RxReset, ioaddr + EL3_CMD);
350         /* Wait a few ticks for the RxReset command to complete. */
351         for (i = 20; i >= 0; i--)
352                 if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
353                         break;
354
355         outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
356
357         if (corkscrew_debug > 1) {
358                 EL3WINDOW(4);
359                 printf("FIXME: fix print for irq, not 9");
360                 printf("corkscrew_open() irq %d media status 0x%hX.\n",
361                        9, inw(ioaddr + Wn4_Media));
362         }
363
364         /* Set the station address and mask in window 2 each time opened. */
365         EL3WINDOW(2);
366         for (i = 0; i < 6; i++)
367                 outb(nic->node_addr[i], ioaddr + i);
368         for (; i < 12; i += 2)
369                 outw(0, ioaddr + i);
370
371         if (if_port == 3)
372                 /* Start the thinnet transceiver. We should really wait 50ms... */
373                 outw(StartCoax, ioaddr + EL3_CMD);
374         EL3WINDOW(4);
375         outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP | Media_SQE)) |
376              media_tbl[if_port].media_bits, ioaddr + Wn4_Media);
377
378         /* Switch to the stats window, and clear all stats by reading. */
379 /*      outw(StatsDisable, ioaddr + EL3_CMD);*/
380         EL3WINDOW(6);
381         for (i = 0; i < 10; i++)
382                 inb(ioaddr + i);
383         inw(ioaddr + 10);
384         inw(ioaddr + 12);
385         /* New: On the Vortex we must also clear the BadSSD counter. */
386         EL3WINDOW(4);
387         inb(ioaddr + 12);
388         /* ..and on the Boomerang we enable the extra statistics bits. */
389         outw(0x0040, ioaddr + Wn4_NetDiag);
390
391         /* Switch to register set 7 for normal use. */
392         EL3WINDOW(7);
393
394         /* Temporarily left in place.  If these FIXMEs are printed
395            it meand that special logic for that card may need to be added
396            see Becker's 3c515.c driver */
397         if (vp->full_bus_master_rx) {   /* Boomerang bus master. */
398                 printf("FIXME: Is this if necessary");
399                 vp->cur_rx = vp->dirty_rx = 0;
400                 if (corkscrew_debug > 2)
401                         printf("   Filling in the Rx ring.\n");
402                 for (i = 0; i < RX_RING_SIZE; i++) {
403                         printf("FIXME: Is this if necessary");
404                 }
405         }
406         if (vp->full_bus_master_tx) {   /* Boomerang bus master Tx. */
407                 vp->cur_tx = vp->dirty_tx = 0;
408                 outb(PKT_BUF_SZ >> 8, ioaddr + TxFreeThreshold);        /* Room for a packet. */
409                 /* Clear the Tx ring. */
410                 for (i = 0; i < TX_RING_SIZE; i++)
411                         vp->tx_skbuff[i] = 0;
412                 outl(0, ioaddr + DownListPtr);
413         }
414         /* Set receiver mode: presumably accept b-case and phys addr only. */
415         outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm,
416              ioaddr + EL3_CMD);
417
418         outw(RxEnable, ioaddr + EL3_CMD);       /* Enable the receiver. */
419         outw(TxEnable, ioaddr + EL3_CMD);       /* Enable transmitter. */
420         /* Allow status bits to be seen. */
421         outw(SetStatusEnb | AdapterFailure | IntReq | StatsFull |
422              (vp->full_bus_master_tx ? DownComplete : TxAvailable) |
423              (vp->full_bus_master_rx ? UpComplete : RxComplete) |
424              (vp->bus_master ? DMADone : 0), ioaddr + EL3_CMD);
425         /* Ack all pending events, and set active indicator mask. */
426         outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
427              ioaddr + EL3_CMD);
428         outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
429              | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete,
430              ioaddr + EL3_CMD);
431
432 }
433
434 /**************************************************************************
435 POLL - Wait for a frame
436 ***************************************************************************/
437 static int t515_poll(struct nic *nic, int retrieve)
438 {
439         short status, cst;
440         register short rx_fifo;
441
442         cst = inw(BASE + EL3_STATUS);
443
444         if ((cst & RxComplete) == 0) {
445                 /* Ack all pending events, and set active indicator mask. */
446                 outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
447                      BASE + EL3_CMD);
448                 outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete |
449                      StatsFull | (vp->
450                                   bus_master ? DMADone : 0) | UpComplete |
451                      DownComplete, BASE + EL3_CMD);
452                 return 0;
453         }
454         status = inw(BASE + RxStatus);
455
456         if (status & RxDError) {
457                 printf("RxDError\n");
458                 outw(RxDiscard, BASE + EL3_CMD);
459                 return 0;
460         }
461
462         rx_fifo = status & RX_BYTES_MASK;
463         if (rx_fifo == 0)
464                 return 0;
465
466         if ( ! retrieve ) return 1;
467
468 #ifdef EDEBUG
469         printf("[l=%d", rx_fifo);
470 #endif
471         insw(BASE + RX_FIFO, nic->packet, rx_fifo / 2);
472         if (rx_fifo & 1)
473                 nic->packet[rx_fifo - 1] = inb(BASE + RX_FIFO);
474         nic->packetlen = rx_fifo;
475
476         while (1) {
477                 status = inw(BASE + RxStatus);
478 #ifdef EDEBUG
479                 printf("0x%hX*", status);
480 #endif
481                 rx_fifo = status & RX_BYTES_MASK;
482
483                 if (rx_fifo > 0) {
484                         insw(BASE + RX_FIFO, nic->packet + nic->packetlen,
485                              rx_fifo / 2);
486                         if (rx_fifo & 1)
487                                 nic->packet[nic->packetlen + rx_fifo - 1] =
488                                     inb(BASE + RX_FIFO);
489                         nic->packetlen += rx_fifo;
490 #ifdef EDEBUG
491                         printf("+%d", rx_fifo);
492 #endif
493                 }
494                 if ((status & RxComplete) == 0) {
495 #ifdef EDEBUG
496                         printf("=%d", nic->packetlen);
497 #endif
498                         break;
499                 }
500                 udelay(1000);
501         }
502
503         /* acknowledge reception of packet */
504         outw(RxDiscard, BASE + EL3_CMD);
505         while (inw(BASE + EL3_STATUS) & CmdInProgress);
506 #ifdef EDEBUG
507         {
508                 unsigned short type = 0;
509                 type = (nic->packet[12] << 8) | nic->packet[13];
510                 if (nic->packet[0] + nic->packet[1] + nic->packet[2] +
511                     nic->packet[3] + nic->packet[4] + nic->packet[5] ==
512                     0xFF * ETH_ALEN)
513                         printf(",t=0x%hX,b]", type);
514                 else
515                         printf(",t=0x%hX]", type);
516         }
517 #endif
518
519         return 1;
520 }
521
522 /*************************************************************************
523         3Com 515 - specific routines
524 **************************************************************************/
525 static char padmap[] = {
526         0, 3, 2, 1
527 };
528 /**************************************************************************
529 TRANSMIT - Transmit a frame
530 ***************************************************************************/
531 static void t515_transmit(struct nic *nic, const char *d,       /* Destination */
532                           unsigned int t,       /* Type */
533                           unsigned int s,       /* size */
534                           const char *p)
535 {                               /* Packet */
536         register int len;
537         int pad;
538         int status;
539
540 #ifdef EDEBUG
541         printf("{l=%d,t=0x%hX}", s + ETH_HLEN, t);
542 #endif
543
544         /* swap bytes of type */
545         t = htons(t);
546
547         len = s + ETH_HLEN;     /* actual length of packet */
548         pad = padmap[len & 3];
549
550         /*
551          * The 3c515 automatically pads short packets to minimum ethernet length,
552          * but we drop packets that are too large. Perhaps we should truncate
553          * them instead?
554          Copied from 3c595.  Is this true for the 3c515?
555          */
556         if (len + pad > ETH_FRAME_LEN) {
557                 return;
558         }
559         /* drop acknowledgements */
560         while ((status = inb(BASE + TxStatus)) & TxComplete) {
561                 /*if(status & (TXS_UNDERRUN|0x88|TXS_STATUS_OVERFLOW)) { */
562                 outw(TxReset, BASE + EL3_CMD);
563                 outw(TxEnable, BASE + EL3_CMD);
564 /*              }                                                          */
565
566                 outb(0x0, BASE + TxStatus);
567         }
568
569         while (inw(BASE + TxFree) < len + pad + 4) {
570                 /* no room in FIFO */
571         }
572
573         outw(len, BASE + TX_FIFO);
574         outw(0x0, BASE + TX_FIFO);      /* Second dword meaningless */
575
576         /* write packet */
577         outsw(BASE + TX_FIFO, d, ETH_ALEN / 2);
578         outsw(BASE + TX_FIFO, nic->node_addr, ETH_ALEN / 2);
579         outw(t, BASE + TX_FIFO);
580         outsw(BASE + TX_FIFO, p, s / 2);
581
582         if (s & 1)
583                 outb(*(p + s - 1), BASE + TX_FIFO);
584
585         while (pad--)
586                 outb(0, BASE + TX_FIFO);        /* Padding */
587
588         /* wait for Tx complete */
589         while ((inw(BASE + EL3_STATUS) & CmdInProgress) != 0);
590 }
591
592 /**************************************************************************
593 DISABLE - Turn off ethernet interface
594 ***************************************************************************/
595 static void t515_disable ( struct nic *nic ) {
596
597         /* merge reset an disable */
598         t515_reset(nic);
599
600         /* This is a hack.  Since ltsp worked on my
601            system without any disable functionality I
602            have no way to determine if this works */
603
604         /* Disable the receiver and transmitter. */
605         outw(RxDisable, BASE + EL3_CMD);
606         outw(TxDisable, BASE + EL3_CMD);
607
608         if (if_port == XCVR_10base2)
609                 /* Turn off thinnet power.  Green! */
610                 outw(StopCoax, BASE + EL3_CMD);
611
612
613         outw(SetIntrEnb | 0x0000, BASE + EL3_CMD);
614 #ifdef ISA_PNP
615         /*Deactivate */
616 /*    ACTIVATE;
617     WRITE_DATA(0);
618     */
619 #endif
620         return;
621 }
622
623 static void t515_irq(struct nic *nic __unused, irq_action_t action __unused)
624 {
625   switch ( action ) {
626   case DISABLE :
627     break;
628   case ENABLE :
629     break;
630   case FORCE :
631     break;
632   }
633 }
634
635 /**************************************************************************
636 PROBE - Look for an adapter, this routine's visible to the outside
637 You should omit the last argument struct pci_device * for a non-PCI NIC
638 ***************************************************************************/
639 void config_pnp_device(void);
640
641 static int t515_probe(struct dev *dev,
642                       unsigned short *probe_addrs __unused)
643 {
644         struct nic *nic = (struct nic *) dev;
645         /* Direct copy from Beckers 3c515.c removing any ISAPNP sections */
646         int cards_found = 0;
647         static int ioaddr;
648 #ifdef ISA_PNP
649         config_pnp_device();
650 #endif
651         /* Check all locations on the ISA bus -- evil! */
652         for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x20) {
653                 int irq;
654
655                 /* Check the resource configuration for a matching ioaddr. */
656                 if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0))
657                         continue;
658                 /* Verify by reading the device ID from the EEPROM. */
659                 {
660                         int timer;
661                         outw(EEPROM_Read + 7, ioaddr + Wn0EepromCmd);
662                         /* Pause for at least 162 us. for the read to take place. */
663                         for (timer = 4; timer >= 0; timer--) {
664                                 t3c515_wait(1);
665                                 if ((inw(ioaddr + Wn0EepromCmd) & 0x0200)
666                                     == 0)
667                                         break;
668                         }
669                         if (inw(ioaddr + Wn0EepromData) != 0x6d50)
670                                 continue;
671                 }
672                 printf
673                     ("3c515 Resource configuration register 0x%hX, DCR 0x%hX.\n",
674                      inl(ioaddr + 0x2002), inw(ioaddr + 0x2000));
675                 irq = inw(ioaddr + 0x2002) & 15;
676                 BASE = ioaddr;
677                 corkscrew_found_device(BASE, irq, CORKSCREW_ID,
678                                        options[cards_found], nic);
679                 cards_found++;
680         }
681         if (corkscrew_debug)
682                 printf("%d 3c515 cards found.\n", cards_found);
683
684         if (cards_found > 0) {
685                 t515_reset(nic);
686
687                 nic->irqno    = 0;
688                 nic->ioaddr   = BASE;
689 static struct nic_operations t515_operations;
690 static struct nic_operations t515_operations = {
691         .connect        = dummy_connect,
692         .poll           = t515_poll,
693         .transmit       = t515_transmit,
694         .irq            = t515_irq,
695         .disable        = t515_disable,
696 };
697                 nic->nic_op     = &t515_operations;
698
699                 /* Based on PnP ISA map */
700                 dev->devid.vendor_id = htons(ISAPNP_VENDOR('T', 'C', 'M'));
701                 dev->devid.device_id = htons(0x5051);
702                 return 1;
703         } else
704                 return 0;
705
706 }
707
708 static int
709 corkscrew_found_device(int ioaddr, int irq,
710                        int product_index, int options, struct nic *nic)
711 {
712         /* Direct copy from Becker 3c515.c with unecessary parts removed */
713         vp->product_name = "3c515";
714         vp->options = options;
715         if (options >= 0) {
716                 vp->media_override =
717                     ((options & 7) == 2) ? 0 : options & 7;
718                 vp->full_duplex = (options & 8) ? 1 : 0;
719                 vp->bus_master = (options & 16) ? 1 : 0;
720         } else {
721                 vp->media_override = 7;
722                 vp->full_duplex = 0;
723                 vp->bus_master = 0;
724         }
725
726         corkscrew_probe1(ioaddr, irq, product_index, nic);
727         return 0;
728 }
729
730 static int
731 corkscrew_probe1(int ioaddr, int irq, int product_index __unused,
732                  struct nic *nic)
733 {
734         unsigned int eeprom[0x40], checksum = 0;        /* EEPROM contents */
735         int i;
736         ioaddr = BASE;
737
738         printf("3Com %s at 0x%hX, ", vp->product_name, ioaddr);
739
740         /* Read the station address from the EEPROM. */
741         EL3WINDOW(0);
742         for (i = 0; i < 0x18; i++) {
743                 short *phys_addr = (short *) nic->node_addr;
744                 int timer;
745                 outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);
746                 /* Pause for at least 162 us. for the read to take place. */
747                 for (timer = 4; timer >= 0; timer--) {
748                         t3c515_wait(1);
749                         if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0)
750                                 break;
751                 }
752                 eeprom[i] = inw(ioaddr + Wn0EepromData);
753 #ifdef EDEBUG1
754                 printf("Value %d: %hX        ", i, eeprom[i]);
755 #endif
756                 checksum ^= eeprom[i];
757                 if (i < 3)
758                         phys_addr[i] = htons(eeprom[i]);
759         }
760         checksum = (checksum ^ (checksum >> 8)) & 0xff;
761         if (checksum != 0x00)
762                 printf(" ***INVALID CHECKSUM 0x%hX*** ", checksum);
763
764         printf("%!", nic->node_addr);
765         if (eeprom[16] == 0x11c7) {     /* Corkscrew */
766
767         }
768         printf(", IRQ %d\n", irq);
769         /* Tell them about an invalid IRQ. */
770         if (corkscrew_debug && (irq <= 0 || irq > 15))
771                 printf
772                     (" *** Warning: this IRQ is unlikely to work! ***\n");
773
774         {
775                 char *ram_split[] = { "5:3", "3:1", "1:1", "3:5" };
776                 union wn3_config config;
777                 EL3WINDOW(3);
778                 vp->available_media = inw(ioaddr + Wn3_Options);
779                 config.i = inl(ioaddr + Wn3_Config);
780                 if (corkscrew_debug > 1)
781                         printf
782                             ("  Internal config register is %4.4x, transceivers 0x%hX.\n",
783                              config.i, inw(ioaddr + Wn3_Options));
784                 printf
785                     ("  %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
786                      8 << config.u.ram_size,
787                      config.u.ram_width ? "word" : "byte",
788                      ram_split[config.u.ram_split],
789                      config.u.autoselect ? "autoselect/" : "",
790                      media_tbl[config.u.xcvr].name);
791                 if_port = config.u.xcvr;
792                 vp->default_media = config.u.xcvr;
793                 vp->autoselect = config.u.autoselect;
794         }
795         if (vp->media_override != 7) {
796                 printf("  Media override to transceiver type %d (%s).\n",
797                        vp->media_override,
798                        media_tbl[vp->media_override].name);
799                 if_port = vp->media_override;
800         }
801
802         vp->capabilities = eeprom[16];
803         vp->full_bus_master_tx = (vp->capabilities & 0x20) ? 1 : 0;
804         /* Rx is broken at 10mbps, so we always disable it. */
805         /* vp->full_bus_master_rx = 0; */
806         vp->full_bus_master_rx = (vp->capabilities & 0x20) ? 1 : 0;
807
808         return 0;
809 }
810
811 static struct isa_driver t515_driver __isa_driver = {
812         .type = NIC_DRIVER,
813         .name = "3C515",
814         .probe = t515_probe,
815         .ioaddrs = 0,
816 };
817 ISA_ROM("3c515","3c515, Fast EtherLink ISA");