VirtualBox

source: vbox/trunk/src/VBox/Devices/PC/Etherboot-src/drivers/net/3c515.c@ 1

Last change on this file since 1 was 1, checked in by vboxsync, 55 years ago

import

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette