1
/**************************************************************************
2
ETHERBOOT - BOOTP/TFTP Bootstrap Program
7
This code is based heavily on David Greenman's if_ed.c driver
9
Copyright (C) 1993-1994, David Greenman, Martin Renters.
10
This software may be used, modified, copied, distributed, and sold, in
11
both source and binary form provided that the above copyright and these
12
terms are retained. Under no circumstances are the authors responsible for
13
the proper functioning of this software, nor do the authors assume any
14
responsibility for damages incurred with its use.
16
3c503 support added by Bill Paul (wpaul@ctr.columbia.edu) on 11/15/94
17
SMC8416 support added by Bill Paul (wpaul@ctr.columbia.edu) on 12/25/94
18
3c503 PIO support added by Jim Hague (jim.hague@acm.org) on 2/17/98
19
RX overrun by Klaus Espenlaub (espenlaub@informatik.uni-ulm.de) on 3/10/99
20
parts taken from the Linux 8390 driver (by Donald Becker and Paul Gortmaker)
22
**************************************************************************/
24
#include "etherboot.h"
32
static unsigned char eth_vendor, eth_flags, eth_laar;
33
static unsigned short eth_nic_base, eth_asic_base;
34
static unsigned char eth_memsize, eth_rx_start, eth_tx_start;
35
static Address eth_bmem, eth_rmem;
36
static unsigned char eth_drain_receiver;
39
static struct wd_board {
45
{"WD8003S", TYPE_WD8003S, 0, MEM_8192},
46
{"WD8003E", TYPE_WD8003E, 0, MEM_8192},
47
{"WD8013EBT", TYPE_WD8013EBT, FLAG_16BIT, MEM_16384},
48
{"WD8003W", TYPE_WD8003W, 0, MEM_8192},
49
{"WD8003EB", TYPE_WD8003EB, 0, MEM_8192},
50
{"WD8013W", TYPE_WD8013W, FLAG_16BIT, MEM_16384},
52
TYPE_WD8013EP, 0, MEM_8192},
53
{"WD8013WC", TYPE_WD8013WC, FLAG_16BIT, MEM_16384},
54
{"WD8013EPC", TYPE_WD8013EPC, FLAG_16BIT, MEM_16384},
55
{"SMC8216T", TYPE_SMC8216T, FLAG_16BIT | FLAG_790, MEM_16384},
56
{"SMC8216C", TYPE_SMC8216C, FLAG_16BIT | FLAG_790, MEM_16384},
57
{"SMC8416T", TYPE_SMC8416T, FLAG_16BIT | FLAG_790, MEM_8192},
58
{"SMC8416C/BT", TYPE_SMC8416C, FLAG_16BIT | FLAG_790, MEM_8192},
59
{"SMC8013EBP", TYPE_SMC8013EBP,FLAG_16BIT, MEM_16384},
65
static unsigned char t503_output; /* AUI or internal xcvr (Thinnet) */
68
#if defined(INCLUDE_WD)
69
#define eth_probe wd_probe
70
#if defined(INCLUDE_3C503) || defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
71
Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
75
#if defined(INCLUDE_3C503)
76
#define eth_probe t503_probe
77
#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || defined(INCLUDE_WD)
78
Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
82
#if defined(INCLUDE_NE)
83
#define eth_probe ne_probe
84
#if defined(INCLUDE_NS8390) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
85
Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
89
#if defined(INCLUDE_NS8390)
90
#define eth_probe nepci_probe
91
#if defined(INCLUDE_NE) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
92
Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
96
#if defined(INCLUDE_3C503)
97
#define ASIC_PIO _3COM_RFMSB
99
#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
100
#define ASIC_PIO NE_DATA
104
#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM))
105
/**************************************************************************
106
ETH_PIO_READ - Read a frame via Programmed I/O
107
**************************************************************************/
108
static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt)
110
if (eth_flags & FLAG_16BIT) { ++cnt; cnt &= ~1; }
111
outb(D8390_COMMAND_RD2 |
112
D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
113
outb(cnt, eth_nic_base + D8390_P0_RBCR0);
114
outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1);
115
outb(src, eth_nic_base + D8390_P0_RSAR0);
116
outb(src>>8, eth_nic_base + D8390_P0_RSAR1);
117
outb(D8390_COMMAND_RD0 |
118
D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
121
outb(src & 0xff, eth_asic_base + _3COM_DALSB);
122
outb(src >> 8, eth_asic_base + _3COM_DAMSB);
123
outb(t503_output | _3COM_CR_START, eth_asic_base + _3COM_CR);
126
if (eth_flags & FLAG_16BIT)
131
while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
135
if (eth_flags & FLAG_16BIT) {
136
*((unsigned short *)dst) = inw(eth_asic_base + ASIC_PIO);
140
*(dst++) = inb(eth_asic_base + ASIC_PIO);
144
outb(t503_output, eth_asic_base + _3COM_CR);
148
/**************************************************************************
149
ETH_PIO_WRITE - Write a frame via Programmed I/O
150
**************************************************************************/
151
static void eth_pio_write(const unsigned char *src, unsigned int dst, unsigned int cnt)
153
#ifdef COMPEX_RL2000_FIX
155
#endif /* COMPEX_RL2000_FIX */
156
if (eth_flags & FLAG_16BIT) { ++cnt; cnt &= ~1; }
157
outb(D8390_COMMAND_RD2 |
158
D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
159
outb(D8390_ISR_RDC, eth_nic_base + D8390_P0_ISR);
160
outb(cnt, eth_nic_base + D8390_P0_RBCR0);
161
outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1);
162
outb(dst, eth_nic_base + D8390_P0_RSAR0);
163
outb(dst>>8, eth_nic_base + D8390_P0_RSAR1);
164
outb(D8390_COMMAND_RD1 |
165
D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
168
outb(dst & 0xff, eth_asic_base + _3COM_DALSB);
169
outb(dst >> 8, eth_asic_base + _3COM_DAMSB);
171
outb(t503_output | _3COM_CR_DDIR | _3COM_CR_START, eth_asic_base + _3COM_CR);
174
if (eth_flags & FLAG_16BIT)
180
while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
184
if (eth_flags & FLAG_16BIT) {
185
outw(*((unsigned short *)src), eth_asic_base + ASIC_PIO);
189
outb(*(src++), eth_asic_base + ASIC_PIO);
193
outb(t503_output, eth_asic_base + _3COM_CR);
195
#ifdef COMPEX_RL2000_FIX
197
x < COMPEX_RL2000_TRIES &&
198
(inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
201
if (x >= COMPEX_RL2000_TRIES)
202
printf("Warning: Compex RL2000 aborted wait!\n");
203
#endif /* COMPEX_RL2000_FIX */
204
while((inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
209
/**************************************************************************
210
ETH_PIO_READ - Dummy routine when NE2000 not compiled in
211
**************************************************************************/
212
static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt) {}
215
/**************************************************************************
216
NS8390_RESET - Reset adapter
217
**************************************************************************/
218
static void ns8390_reset(struct nic *nic)
222
eth_drain_receiver = 0;
224
if (eth_flags & FLAG_790)
225
outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
228
outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
229
D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
230
if (eth_flags & FLAG_16BIT)
231
outb(0x49, eth_nic_base+D8390_P0_DCR);
233
outb(0x48, eth_nic_base+D8390_P0_DCR);
234
outb(0, eth_nic_base+D8390_P0_RBCR0);
235
outb(0, eth_nic_base+D8390_P0_RBCR1);
236
outb(0x20, eth_nic_base+D8390_P0_RCR); /* monitor mode */
237
outb(2, eth_nic_base+D8390_P0_TCR);
238
outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
239
outb(eth_rx_start, eth_nic_base+D8390_P0_PSTART);
241
if (eth_flags & FLAG_790) outb(0, eth_nic_base + 0x09);
243
outb(eth_memsize, eth_nic_base+D8390_P0_PSTOP);
244
outb(eth_memsize - 1, eth_nic_base+D8390_P0_BOUND);
245
outb(0xFF, eth_nic_base+D8390_P0_ISR);
246
outb(0, eth_nic_base+D8390_P0_IMR);
248
if (eth_flags & FLAG_790)
249
outb(D8390_COMMAND_PS1 |
250
D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
253
outb(D8390_COMMAND_PS1 |
254
D8390_COMMAND_RD2 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
255
for (i=0; i<ETH_ALEN; i++)
256
outb(nic->node_addr[i], eth_nic_base+D8390_P1_PAR0+i);
257
for (i=0; i<ETH_ALEN; i++)
258
outb(0xFF, eth_nic_base+D8390_P1_MAR0+i);
259
outb(eth_rx_start, eth_nic_base+D8390_P1_CURR);
261
if (eth_flags & FLAG_790)
262
outb(D8390_COMMAND_PS0 |
263
D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
266
outb(D8390_COMMAND_PS0 |
267
D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
268
outb(0xFF, eth_nic_base+D8390_P0_ISR);
269
outb(0, eth_nic_base+D8390_P0_TCR);
270
outb(4, eth_nic_base+D8390_P0_RCR); /* allow broadcast frames */
274
* No way to tell whether or not we're supposed to use
275
* the 3Com's transceiver unless the user tells us.
276
* 'flags' should have some compile time default value
277
* which can be changed from the command menu.
279
t503_output = (nic->flags) ? 0 : _3COM_CR_XSEL;
280
outb(t503_output, eth_asic_base + _3COM_CR);
284
static int ns8390_poll(struct nic *nic);
286
#ifndef INCLUDE_3C503
287
/**************************************************************************
288
ETH_RX_OVERRUN - Bring adapter back to work after an RX overrun
289
**************************************************************************/
290
static void eth_rx_overrun(struct nic *nic)
295
if (eth_flags & FLAG_790)
296
outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
299
outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
300
D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
302
/* wait for at least 1.6ms - we wait one timer tick */
303
start_time = currticks();
304
while (currticks() - start_time <= 1)
307
outb(0, eth_nic_base+D8390_P0_RBCR0); /* reset byte counter */
308
outb(0, eth_nic_base+D8390_P0_RBCR1);
311
* Linux driver checks for interrupted TX here. This is not necessary,
312
* because the transmit routine waits until the frame is sent.
315
/* enter loopback mode and restart NIC */
316
outb(2, eth_nic_base+D8390_P0_TCR);
318
if (eth_flags & FLAG_790)
319
outb(D8390_COMMAND_PS0 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
322
outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
323
D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
325
/* clear the RX ring, acknowledge overrun interrupt */
326
eth_drain_receiver = 1;
327
while (ns8390_poll(nic))
329
eth_drain_receiver = 0;
330
outb(D8390_ISR_OVW, eth_nic_base+D8390_P0_ISR);
332
/* leave loopback mode - no packets to be resent (see Linux driver) */
333
outb(0, eth_nic_base+D8390_P0_TCR);
335
#endif /* INCLUDE_3C503 */
337
/**************************************************************************
338
NS8390_TRANSMIT - Transmit a frame
339
**************************************************************************/
340
static void ns8390_transmit(
342
const char *d, /* Destination */
343
unsigned int t, /* Type */
344
unsigned int s, /* size */
345
const char *p) /* Packet */
348
if (!(eth_flags & FLAG_PIO)) {
349
memcpy((char *)eth_bmem, d, ETH_ALEN); /* dst */
350
memcpy((char *)eth_bmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
351
*((char *)eth_bmem+12) = t>>8; /* type */
352
*((char *)eth_bmem+13) = t;
353
memcpy((char *)eth_bmem+ETH_HLEN, p, s);
355
while (s < ETH_ZLEN) *((char *)eth_bmem+(s++)) = 0;
360
/* Memory interface */
361
if (eth_flags & FLAG_16BIT) {
362
outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
365
if (eth_flags & FLAG_790) {
366
outb(WD_MSR_MENB, eth_asic_base + WD_MSR);
370
memcpy((char *)eth_bmem, d, ETH_ALEN); /* dst */
371
memcpy((char *)eth_bmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
372
*((char *)eth_bmem+12) = t>>8; /* type */
373
*((char *)eth_bmem+13) = t;
374
memcpy((char *)eth_bmem+ETH_HLEN, p, s);
376
while (s < ETH_ZLEN) *((char *)eth_bmem+(s++)) = 0;
377
if (eth_flags & FLAG_790) {
378
outb(0, eth_asic_base + WD_MSR);
381
if (eth_flags & FLAG_16BIT) {
382
outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
387
#if defined(INCLUDE_3C503)
388
if (eth_flags & FLAG_PIO) {
390
#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM))
393
type = (t >> 8) | (t << 8);
394
eth_pio_write(d, eth_tx_start<<8, ETH_ALEN);
395
eth_pio_write(nic->node_addr, (eth_tx_start<<8)+ETH_ALEN, ETH_ALEN);
396
/* bcc generates worse code without (const+const) below */
397
eth_pio_write((unsigned char *)&type, (eth_tx_start<<8)+(ETH_ALEN+ETH_ALEN), 2);
398
eth_pio_write(p, (eth_tx_start<<8)+ETH_HLEN, s);
400
if (s < ETH_ZLEN) s = ETH_ZLEN;
402
#if defined(INCLUDE_3C503)
407
if (eth_flags & FLAG_790)
408
outb(D8390_COMMAND_PS0 |
409
D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
412
outb(D8390_COMMAND_PS0 |
413
D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
414
outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
415
outb(s, eth_nic_base+D8390_P0_TBCR0);
416
outb(s>>8, eth_nic_base+D8390_P0_TBCR1);
418
if (eth_flags & FLAG_790)
419
outb(D8390_COMMAND_PS0 |
420
D8390_COMMAND_TXP | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
423
outb(D8390_COMMAND_PS0 |
424
D8390_COMMAND_TXP | D8390_COMMAND_RD2 |
425
D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
428
/**************************************************************************
429
NS8390_POLL - Wait for a frame
430
**************************************************************************/
431
static int ns8390_poll(struct nic *nic)
434
unsigned char rstat, curr, next;
435
unsigned short len, frag;
436
unsigned short pktoff;
438
struct ringbuffer pkthdr;
440
#ifndef INCLUDE_3C503
441
/* avoid infinite recursion: see eth_rx_overrun() */
442
if (!eth_drain_receiver && (inb(eth_nic_base+D8390_P0_ISR) & D8390_ISR_OVW)) {
446
#endif /* INCLUDE_3C503 */
447
rstat = inb(eth_nic_base+D8390_P0_RSR);
448
if (!(rstat & D8390_RSTAT_PRX)) return(0);
449
next = inb(eth_nic_base+D8390_P0_BOUND)+1;
450
if (next >= eth_memsize) next = eth_rx_start;
451
outb(D8390_COMMAND_PS1, eth_nic_base+D8390_P0_COMMAND);
452
curr = inb(eth_nic_base+D8390_P1_CURR);
453
outb(D8390_COMMAND_PS0, eth_nic_base+D8390_P0_COMMAND);
454
if (curr >= eth_memsize) curr=eth_rx_start;
455
if (curr == next) return(0);
457
if (eth_flags & FLAG_16BIT) {
458
outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
461
if (eth_flags & FLAG_790) {
462
outb(WD_MSR_MENB, eth_asic_base + WD_MSR);
468
if (eth_flags & FLAG_PIO)
469
eth_pio_read(pktoff, (char *)&pkthdr, 4);
471
memcpy(&pkthdr, (char *)eth_rmem + pktoff, 4);
472
pktoff += sizeof(pkthdr);
473
/* incoming length includes FCS so must sub 4 */
474
len = pkthdr.len - 4;
475
if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || len < ETH_ZLEN
476
|| len > ETH_FRAME_LEN) {
477
printf("Bogus packet, ignoring\n");
482
nic->packetlen = len; /* available to caller */
483
frag = (eth_memsize << 8) - pktoff;
484
if (len > frag) { /* We have a wrap-around */
485
/* read first part */
486
if (eth_flags & FLAG_PIO)
487
eth_pio_read(pktoff, p, frag);
489
memcpy(p, (char *)eth_rmem + pktoff, frag);
490
pktoff = eth_rx_start << 8;
494
/* read second part */
495
if (eth_flags & FLAG_PIO)
496
eth_pio_read(pktoff, p, len);
498
memcpy(p, (char *)eth_rmem + pktoff, len);
502
if (eth_flags & FLAG_790) {
503
outb(0, eth_asic_base + WD_MSR);
506
if (eth_flags & FLAG_16BIT) {
507
outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
512
next = pkthdr.next; /* frame number of next packet */
513
if (next == eth_rx_start)
515
outb(next-1, eth_nic_base+D8390_P0_BOUND);
519
/**************************************************************************
520
NS8390_DISABLE - Turn off adapter
521
**************************************************************************/
522
static void ns8390_disable(struct nic *nic)
526
/**************************************************************************
527
ETH_PROBE - Look for an adapter
528
**************************************************************************/
529
#ifdef INCLUDE_NS8390
530
struct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs,
531
struct pci_device *pci)
533
struct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs)
537
struct wd_board *brd;
538
unsigned short chksum;
540
eth_vendor = VENDOR_NONE;
541
eth_drain_receiver = 0;
544
/******************************************************************
545
Search for WD/SMC cards
546
******************************************************************/
547
for (eth_asic_base = WD_LOW_BASE; eth_asic_base <= WD_HIGH_BASE;
548
eth_asic_base += 0x20) {
551
chksum += inb(eth_asic_base+i);
552
/* Extra checks to avoid soundcard */
553
if ((chksum & 0xFF) == 0xFF &&
554
inb(eth_asic_base+8) != 0xFF &&
555
inb(eth_asic_base+9) != 0xFF)
558
if (eth_asic_base > WD_HIGH_BASE)
560
/* We've found a board */
561
eth_vendor = VENDOR_WD;
562
eth_nic_base = eth_asic_base + WD_NIC_ADDR;
563
c = inb(eth_asic_base+WD_BID); /* Get board id */
564
for (brd = wd_boards; brd->name; brd++)
565
if (brd->id == c) break;
567
printf("Unknown WD/SMC NIC type %hhX\n", c);
568
return (0); /* Unknown type */
570
eth_flags = brd->flags;
571
eth_memsize = brd->memsize;
573
eth_rx_start = D8390_TXBUF_SIZE;
574
if ((c == TYPE_WD8013EP) &&
575
(inb(eth_asic_base + WD_ICR) & WD_ICR_16BIT)) {
576
eth_flags = FLAG_16BIT;
577
eth_memsize = MEM_16384;
579
if ((c & WD_SOFTCONFIG) && (!(eth_flags & FLAG_790))) {
580
eth_bmem = (0x80000 |
581
((inb(eth_asic_base + WD_MSR) & 0x3F) << 13));
583
eth_bmem = WD_DEFAULT_MEM;
584
if (brd->id == TYPE_SMC8216T || brd->id == TYPE_SMC8216C) {
585
*((unsigned int *)(eth_bmem + 8192)) = (unsigned int)0;
586
if (*((unsigned int *)(eth_bmem + 8192))) {
588
eth_memsize = brd->memsize;
591
outb(0x80, eth_asic_base + WD_MSR); /* Reset */
592
for (i=0; i<ETH_ALEN; i++) {
593
nic->node_addr[i] = inb(i+eth_asic_base+WD_LAR);
595
printf("\n%s base %#hx, memory %#hx, addr %!\n",
596
brd->name, eth_asic_base, eth_bmem, nic->node_addr);
597
if (eth_flags & FLAG_790) {
598
outb(WD_MSR_MENB, eth_asic_base+WD_MSR);
599
outb((inb(eth_asic_base+0x04) |
600
0x80), eth_asic_base+0x04);
601
outb((((unsigned)eth_bmem >> 13) & 0x0F) |
602
(((unsigned)eth_bmem >> 11) & 0x40) |
603
(inb(eth_asic_base+0x0B) & 0xB0), eth_asic_base+0x0B);
604
outb((inb(eth_asic_base+0x04) &
605
~0x80), eth_asic_base+0x04);
607
outb((((unsigned)eth_bmem >> 13) & 0x3F) | 0x40, eth_asic_base+WD_MSR);
609
if (eth_flags & FLAG_16BIT) {
610
if (eth_flags & FLAG_790) {
611
eth_laar = inb(eth_asic_base + WD_LAAR);
612
outb(WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
615
WD_LAAR_L16EN | 1), eth_asic_base + WD_LAAR);
617
The previous line used to be
618
WD_LAAR_M16EN | WD_LAAR_L16EN | 1));
619
jluke@deakin.edu.au reported that removing WD_LAAR_M16EN made
620
it work for WD8013s. This seems to work for my 8013 boards. I
621
don't know what is really happening. I wish I had data sheets
622
or more time to decode the Linux driver. - Ken
629
/******************************************************************
630
Search for 3Com 3c503 if no WD/SMC cards
631
******************************************************************/
632
if (eth_vendor == VENDOR_NONE) {
634
int iobase_reg, membase_reg;
635
static unsigned short base[] = {
636
0x300, 0x310, 0x330, 0x350,
637
0x250, 0x280, 0x2A0, 0x2E0, 0 };
639
/* Loop through possible addresses checking each one */
641
for (idx = 0; (eth_nic_base = base[idx]) != 0; ++idx) {
643
eth_asic_base = eth_nic_base + _3COM_ASIC_OFFSET;
645
* Note that we use the same settings for both 8 and 16 bit cards:
646
* both have an 8K bank of memory at page 1 while only the 16 bit
647
* cards have a bank at page 0.
649
eth_memsize = MEM_16384;
651
eth_rx_start = 32 + D8390_TXBUF_SIZE;
653
/* Check our base address. iobase and membase should */
654
/* both have a maximum of 1 bit set or be 0. */
656
iobase_reg = inb(eth_asic_base + _3COM_BCFR);
657
membase_reg = inb(eth_asic_base + _3COM_PCFR);
659
if ((iobase_reg & (iobase_reg - 1)) ||
660
(membase_reg & (membase_reg - 1)))
663
/* Now get the shared memory address */
667
switch (membase_reg) {
668
case _3COM_PCFR_DC000:
671
case _3COM_PCFR_D8000:
674
case _3COM_PCFR_CC000:
677
case _3COM_PCFR_C8000:
681
eth_flags |= FLAG_PIO;
690
if (base[idx] == 0) /* not found */
693
eth_flags |= FLAG_PIO; /* force PIO mode */
696
eth_vendor = VENDOR_3COM;
699
/* Need this to make ns8390_poll() happy. */
701
eth_rmem = eth_bmem - 0x2000;
703
/* Reset NIC and ASIC */
705
outb(_3COM_CR_RST | _3COM_CR_XSEL, eth_asic_base + _3COM_CR );
706
outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR );
708
/* Get our ethernet address */
710
outb(_3COM_CR_EALO | _3COM_CR_XSEL, eth_asic_base + _3COM_CR);
711
printf("\n3Com 3c503 base %#hx, ", eth_nic_base);
712
if (eth_flags & FLAG_PIO)
715
printf("memory %#hx", eth_bmem);
716
for (i=0; i<ETH_ALEN; i++) {
717
nic->node_addr[i] = inb(eth_nic_base+i);
719
printf(", %s, addr %!\n", nic->flags ? "AUI" : "internal xcvr",
721
outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR);
723
* Initialize GA configuration register. Set bank and enable shared
724
* mem. We always use bank 1. Disable interrupts.
726
outb(_3COM_GACFR_RSEL |
727
_3COM_GACFR_MBS0 | _3COM_GACFR_TCM | _3COM_GACFR_NIM, eth_asic_base + _3COM_GACFR);
729
outb(0xff, eth_asic_base + _3COM_VPTR2);
730
outb(0xff, eth_asic_base + _3COM_VPTR1);
731
outb(0x00, eth_asic_base + _3COM_VPTR0);
733
* Clear memory and verify that it worked (we use only 8K)
736
if (!(eth_flags & FLAG_PIO)) {
737
memset((char *)eth_bmem, 0, 0x2000);
738
for(i = 0; i < 0x2000; ++i)
739
if (*(((char *)eth_bmem)+i)) {
740
printf ("Failed to clear 3c503 shared mem.\n");
745
* Initialize GA page/start/stop registers.
747
outb(eth_tx_start, eth_asic_base + _3COM_PSTR);
748
outb(eth_memsize, eth_asic_base + _3COM_PSPR);
751
#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
752
/******************************************************************
753
Search for NE1000/2000 if no WD/SMC or 3com cards
754
******************************************************************/
755
if (eth_vendor == VENDOR_NONE) {
756
char romdata[16], testbuf[32];
758
static char test[] = "NE*000 memory";
759
static unsigned short base[] = {
764
/* if no addresses supplied, fall back on defaults */
765
if (probe_addrs == 0 || probe_addrs[0] == 0)
767
eth_bmem = 0; /* No shared memory */
768
for (idx = 0; (eth_nic_base = probe_addrs[idx]) != 0; ++idx) {
769
eth_flags = FLAG_PIO;
770
eth_asic_base = eth_nic_base + NE_ASIC_OFFSET;
771
eth_memsize = MEM_16384;
773
eth_rx_start = 32 + D8390_TXBUF_SIZE;
774
c = inb(eth_asic_base + NE_RESET);
775
outb(c, eth_asic_base + NE_RESET);
777
outb(D8390_COMMAND_STP |
778
D8390_COMMAND_RD2, eth_nic_base + D8390_P0_COMMAND);
779
outb(D8390_RCR_MON, eth_nic_base + D8390_P0_RCR);
780
outb(D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
781
outb(MEM_8192, eth_nic_base + D8390_P0_PSTART);
782
outb(MEM_16384, eth_nic_base + D8390_P0_PSTOP);
783
#ifdef NS8390_FORCE_16BIT
784
eth_flags |= FLAG_16BIT; /* force 16-bit mode */
787
eth_pio_write(test, 8192, sizeof(test));
788
eth_pio_read(8192, testbuf, sizeof(test));
789
if (!memcmp(test, testbuf, sizeof(test)))
791
eth_flags |= FLAG_16BIT;
792
eth_memsize = MEM_32768;
794
eth_rx_start = 64 + D8390_TXBUF_SIZE;
796
D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
797
outb(MEM_16384, eth_nic_base + D8390_P0_PSTART);
798
outb(MEM_32768, eth_nic_base + D8390_P0_PSTOP);
799
eth_pio_write(test, 16384, sizeof(test));
800
eth_pio_read(16384, testbuf, sizeof(test));
801
if (!memcmp(testbuf, test, sizeof(test)))
804
if (eth_nic_base == 0)
806
if (eth_nic_base > ISA_MAX_ADDR) /* PCI probably */
807
eth_flags |= FLAG_16BIT;
808
eth_vendor = VENDOR_NOVELL;
809
eth_pio_read(0, romdata, sizeof(romdata));
810
for (i=0; i<ETH_ALEN; i++) {
811
nic->node_addr[i] = romdata[i + ((eth_flags & FLAG_16BIT) ? i : 0)];
813
printf("\nNE%c000 base %#hx, addr %!\n",
814
(eth_flags & FLAG_16BIT) ? '2' : '1', eth_nic_base,
818
if (eth_vendor == VENDOR_NONE)
820
if (eth_vendor != VENDOR_3COM)
823
nic->reset = ns8390_reset;
824
nic->poll = ns8390_poll;
825
nic->transmit = ns8390_transmit;
826
nic->disable = ns8390_disable;