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
Multicast support added by Timothy Legge (timlegge@users.sourceforge.net) 09/28/2003
17
Relocation support added by Ken Yap (ken_yap@users.sourceforge.net) 28/12/02
18
3c503 support added by Bill Paul (wpaul@ctr.columbia.edu) on 11/15/94
19
SMC8416 support added by Bill Paul (wpaul@ctr.columbia.edu) on 12/25/94
20
3c503 PIO support added by Jim Hague (jim.hague@acm.org) on 2/17/98
21
RX overrun by Klaus Espenlaub (espenlaub@informatik.uni-ulm.de) on 3/10/99
22
parts taken from the Linux 8390 driver (by Donald Becker and Paul Gortmaker)
23
SMC8416 PIO support added by Andrew Bettison (andrewb@zip.com.au) on 4/3/02
24
based on the Linux 8390 driver (by Donald Becker and Paul Gortmaker)
26
**************************************************************************/
28
FILE_LICENCE ( BSD2 );
30
/* #warning "ns8390.c: FIXME: split ISA and PCI, clean up" */
34
#if !defined(INCLUDE_NS8390) && !defined(INCLUDE_WD) && \
35
!defined(INCLUDE_NE) && !defined(INCLUDE_3C503)
36
/* The driver named ns8390 is the PCI driver, often called
37
"PCI ne2000 clones". */
38
# define INCLUDE_NS8390 1
41
#include "etherboot.h"
44
#include <ipxe/ethernet.h>
51
static unsigned char eth_vendor, eth_flags;
53
static unsigned char eth_laar;
55
static unsigned short eth_nic_base, eth_asic_base;
56
static unsigned char eth_memsize, eth_rx_start, eth_tx_start;
57
static Address eth_bmem, eth_rmem;
58
static unsigned char eth_drain_receiver;
61
static struct wd_board {
67
{"WD8003S", TYPE_WD8003S, 0, MEM_8192},
68
{"WD8003E", TYPE_WD8003E, 0, MEM_8192},
69
{"WD8013EBT", TYPE_WD8013EBT, FLAG_16BIT, MEM_16384},
70
{"WD8003W", TYPE_WD8003W, 0, MEM_8192},
71
{"WD8003EB", TYPE_WD8003EB, 0, MEM_8192},
72
{"WD8013W", TYPE_WD8013W, FLAG_16BIT, MEM_16384},
74
TYPE_WD8013EP, 0, MEM_8192},
75
{"WD8013WC", TYPE_WD8013WC, FLAG_16BIT, MEM_16384},
76
{"WD8013EPC", TYPE_WD8013EPC, FLAG_16BIT, MEM_16384},
77
{"SMC8216T", TYPE_SMC8216T, FLAG_16BIT | FLAG_790, MEM_16384},
78
{"SMC8216C", TYPE_SMC8216C, FLAG_16BIT | FLAG_790, MEM_16384},
79
{"SMC8416T", TYPE_SMC8416T, FLAG_16BIT | FLAG_790, MEM_8192},
80
{"SMC8416C/BT", TYPE_SMC8416C, FLAG_16BIT | FLAG_790, MEM_8192},
81
{"SMC8013EBP", TYPE_SMC8013EBP,FLAG_16BIT, MEM_16384},
87
static unsigned char t503_output; /* AUI or internal xcvr (Thinnet) */
90
#if defined(INCLUDE_WD)
91
#define ASIC_PIO WD_IAR
92
#define eth_probe wd_probe
93
#if defined(INCLUDE_3C503) || defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
94
Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
98
#if defined(INCLUDE_3C503)
99
#define eth_probe t503_probe
100
#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || defined(INCLUDE_WD)
101
Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
105
#if defined(INCLUDE_NE)
106
#define eth_probe ne_probe
107
#if defined(INCLUDE_NS8390) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
108
Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
112
#if defined(INCLUDE_NS8390)
113
#define eth_probe nepci_probe
114
#if defined(INCLUDE_NE) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
115
Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
119
#if defined(INCLUDE_3C503)
120
#define ASIC_PIO _3COM_RFMSB
122
#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
123
#define ASIC_PIO NE_DATA
127
#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO))
128
/**************************************************************************
129
ETH_PIO_READ - Read a frame via Programmed I/O
130
**************************************************************************/
131
static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt)
134
outb(src & 0xff, eth_asic_base + WD_GP2);
135
outb(src >> 8, eth_asic_base + WD_GP2);
137
outb(D8390_COMMAND_RD2 |
138
D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
139
outb(cnt, eth_nic_base + D8390_P0_RBCR0);
140
outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1);
141
outb(src, eth_nic_base + D8390_P0_RSAR0);
142
outb(src>>8, eth_nic_base + D8390_P0_RSAR1);
143
outb(D8390_COMMAND_RD0 |
144
D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
147
outb(src & 0xff, eth_asic_base + _3COM_DALSB);
148
outb(src >> 8, eth_asic_base + _3COM_DAMSB);
149
outb(t503_output | _3COM_CR_START, eth_asic_base + _3COM_CR);
153
if (eth_flags & FLAG_16BIT)
154
cnt = (cnt + 1) >> 1;
158
while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
162
if (eth_flags & FLAG_16BIT) {
163
*((unsigned short *)dst) = inw(eth_asic_base + ASIC_PIO);
167
*(dst++) = inb(eth_asic_base + ASIC_PIO);
171
outb(t503_output, eth_asic_base + _3COM_CR);
175
/**************************************************************************
176
ETH_PIO_WRITE - Write a frame via Programmed I/O
177
**************************************************************************/
178
static void eth_pio_write(const unsigned char *src, unsigned int dst, unsigned int cnt)
180
#ifdef COMPEX_RL2000_FIX
182
#endif /* COMPEX_RL2000_FIX */
184
outb(dst & 0xff, eth_asic_base + WD_GP2);
185
outb(dst >> 8, eth_asic_base + WD_GP2);
187
outb(D8390_COMMAND_RD2 |
188
D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
189
outb(D8390_ISR_RDC, eth_nic_base + D8390_P0_ISR);
190
outb(cnt, eth_nic_base + D8390_P0_RBCR0);
191
outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1);
192
outb(dst, eth_nic_base + D8390_P0_RSAR0);
193
outb(dst>>8, eth_nic_base + D8390_P0_RSAR1);
194
outb(D8390_COMMAND_RD1 |
195
D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
198
outb(dst & 0xff, eth_asic_base + _3COM_DALSB);
199
outb(dst >> 8, eth_asic_base + _3COM_DAMSB);
201
outb(t503_output | _3COM_CR_DDIR | _3COM_CR_START, eth_asic_base + _3COM_CR);
205
if (eth_flags & FLAG_16BIT)
206
cnt = (cnt + 1) >> 1;
211
while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
215
if (eth_flags & FLAG_16BIT) {
216
outw(*((unsigned short *)src), eth_asic_base + ASIC_PIO);
220
outb(*(src++), eth_asic_base + ASIC_PIO);
224
outb(t503_output, eth_asic_base + _3COM_CR);
226
#ifdef COMPEX_RL2000_FIX
228
x < COMPEX_RL2000_TRIES &&
229
(inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
232
if (x >= COMPEX_RL2000_TRIES)
233
printf("Warning: Compex RL2000 aborted wait!\n");
234
#endif /* COMPEX_RL2000_FIX */
236
while((inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
242
/**************************************************************************
243
ETH_PIO_READ - Dummy routine when NE2000 not compiled in
244
**************************************************************************/
245
static void eth_pio_read(unsigned int src __unused, unsigned char *dst __unused, unsigned int cnt __unused) {}
249
/**************************************************************************
250
enable_multycast - Enable Multicast
251
**************************************************************************/
252
static void enable_multicast(unsigned short eth_nic_base)
254
unsigned char mcfilter[8];
256
memset(mcfilter, 0xFF, 8);
257
outb(4, eth_nic_base+D8390_P0_RCR);
258
outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS1, eth_nic_base + D8390_P0_COMMAND);
261
outb(mcfilter[i], eth_nic_base + 8 + i);
262
if(inb(eth_nic_base + 8 + i)!=mcfilter[i])
263
printf("Error SMC 83C690 Multicast filter read/write mishap %d\n",i);
265
outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS0, eth_nic_base + D8390_P0_COMMAND);
266
outb(4 | 0x08, eth_nic_base+D8390_P0_RCR);
269
/**************************************************************************
270
NS8390_RESET - Reset adapter
271
**************************************************************************/
272
static void ns8390_reset(struct nic *nic)
276
eth_drain_receiver = 0;
278
if (eth_flags & FLAG_790)
279
outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
282
outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
283
D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
284
if (eth_flags & FLAG_16BIT)
285
outb(0x49, eth_nic_base+D8390_P0_DCR);
287
outb(0x48, eth_nic_base+D8390_P0_DCR);
288
outb(0, eth_nic_base+D8390_P0_RBCR0);
289
outb(0, eth_nic_base+D8390_P0_RBCR1);
290
outb(0x20, eth_nic_base+D8390_P0_RCR); /* monitor mode */
291
outb(2, eth_nic_base+D8390_P0_TCR);
292
outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
293
outb(eth_rx_start, eth_nic_base+D8390_P0_PSTART);
295
if (eth_flags & FLAG_790) {
297
outb(0x10, eth_asic_base + 0x06); /* disable interrupts, enable PIO */
298
outb(0x01, eth_nic_base + 0x09); /* enable ring read auto-wrap */
300
outb(0, eth_nic_base + 0x09);
304
outb(eth_memsize, eth_nic_base+D8390_P0_PSTOP);
305
outb(eth_memsize - 1, eth_nic_base+D8390_P0_BOUND);
306
outb(0xFF, eth_nic_base+D8390_P0_ISR);
307
outb(0, eth_nic_base+D8390_P0_IMR);
309
if (eth_flags & FLAG_790)
310
outb(D8390_COMMAND_PS1 |
311
D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
314
outb(D8390_COMMAND_PS1 |
315
D8390_COMMAND_RD2 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
316
for (i=0; i<ETH_ALEN; i++)
317
outb(nic->node_addr[i], eth_nic_base+D8390_P1_PAR0+i);
318
for (i=0; i<ETH_ALEN; i++)
319
outb(0xFF, eth_nic_base+D8390_P1_MAR0+i);
320
outb(eth_rx_start, eth_nic_base+D8390_P1_CURR);
322
if (eth_flags & FLAG_790)
323
outb(D8390_COMMAND_PS0 |
324
D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
327
outb(D8390_COMMAND_PS0 |
328
D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
329
outb(0xFF, eth_nic_base+D8390_P0_ISR);
330
outb(0, eth_nic_base+D8390_P0_TCR); /* transmitter on */
331
outb(4, eth_nic_base+D8390_P0_RCR); /* allow rx broadcast frames */
333
enable_multicast(eth_nic_base);
337
* No way to tell whether or not we're supposed to use
338
* the 3Com's transceiver unless the user tells us.
339
* 'flags' should have some compile time default value
340
* which can be changed from the command menu.
342
t503_output = (nic->flags) ? 0 : _3COM_CR_XSEL;
343
outb(t503_output, eth_asic_base + _3COM_CR);
347
static int ns8390_poll(struct nic *nic, int retrieve);
349
#ifndef INCLUDE_3C503
350
/**************************************************************************
351
ETH_RX_OVERRUN - Bring adapter back to work after an RX overrun
352
**************************************************************************/
353
static void eth_rx_overrun(struct nic *nic)
358
if (eth_flags & FLAG_790)
359
outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
362
outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
363
D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
365
/* wait for at least 1.6ms - we wait one timer tick */
366
start_time = currticks();
367
while (currticks() - start_time <= 1)
370
outb(0, eth_nic_base+D8390_P0_RBCR0); /* reset byte counter */
371
outb(0, eth_nic_base+D8390_P0_RBCR1);
374
* Linux driver checks for interrupted TX here. This is not necessary,
375
* because the transmit routine waits until the frame is sent.
378
/* enter loopback mode and restart NIC */
379
outb(2, eth_nic_base+D8390_P0_TCR);
381
if (eth_flags & FLAG_790)
382
outb(D8390_COMMAND_PS0 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
385
outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
386
D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
388
/* clear the RX ring, acknowledge overrun interrupt */
389
eth_drain_receiver = 1;
390
while (ns8390_poll(nic, 1))
392
eth_drain_receiver = 0;
393
outb(D8390_ISR_OVW, eth_nic_base+D8390_P0_ISR);
395
/* leave loopback mode - no packets to be resent (see Linux driver) */
396
outb(0, eth_nic_base+D8390_P0_TCR);
398
#endif /* INCLUDE_3C503 */
400
/**************************************************************************
401
NS8390_TRANSMIT - Transmit a frame
402
**************************************************************************/
403
static void ns8390_transmit(
405
const char *d, /* Destination */
406
unsigned int t, /* Type */
407
unsigned int s, /* size */
408
const char *p) /* Packet */
410
#if defined(INCLUDE_3C503) || (defined(INCLUDE_WD) && ! defined(WD_790_PIO))
411
Address eth_vmem = bus_to_virt(eth_bmem);
414
if (!(eth_flags & FLAG_PIO)) {
415
memcpy((char *)eth_vmem, d, ETH_ALEN); /* dst */
416
memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
417
*((char *)eth_vmem+12) = t>>8; /* type */
418
*((char *)eth_vmem+13) = t;
419
memcpy((char *)eth_vmem+ETH_HLEN, p, s);
421
while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0;
426
if (eth_flags & FLAG_16BIT) {
427
outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
431
/* Memory interface */
432
if (eth_flags & FLAG_790) {
433
outb(WD_MSR_MENB, eth_asic_base + WD_MSR);
437
memcpy((char *)eth_vmem, d, ETH_ALEN); /* dst */
438
memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
439
*((char *)eth_vmem+12) = t>>8; /* type */
440
*((char *)eth_vmem+13) = t;
441
memcpy((char *)eth_vmem+ETH_HLEN, p, s);
443
while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0;
444
if (eth_flags & FLAG_790) {
445
outb(0, eth_asic_base + WD_MSR);
453
#if defined(INCLUDE_3C503)
454
if (eth_flags & FLAG_PIO)
456
#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO))
460
type = (t >> 8) | (t << 8);
461
eth_pio_write( (unsigned char *) d, eth_tx_start<<8, ETH_ALEN);
462
eth_pio_write(nic->node_addr, (eth_tx_start<<8)+ETH_ALEN, ETH_ALEN);
463
/* bcc generates worse code without (const+const) below */
464
eth_pio_write((unsigned char *)&type, (eth_tx_start<<8)+(ETH_ALEN+ETH_ALEN), 2);
465
eth_pio_write( (unsigned char *) p, (eth_tx_start<<8)+ETH_HLEN, s);
467
if (s < ETH_ZLEN) s = ETH_ZLEN;
470
#if defined(INCLUDE_3C503)
474
if (eth_flags & FLAG_16BIT) {
475
outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
478
if (eth_flags & FLAG_790)
479
outb(D8390_COMMAND_PS0 |
480
D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
483
outb(D8390_COMMAND_PS0 |
484
D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
485
outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
486
outb(s, eth_nic_base+D8390_P0_TBCR0);
487
outb(s>>8, eth_nic_base+D8390_P0_TBCR1);
489
if (eth_flags & FLAG_790)
490
outb(D8390_COMMAND_PS0 |
491
D8390_COMMAND_TXP | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
494
outb(D8390_COMMAND_PS0 |
495
D8390_COMMAND_TXP | D8390_COMMAND_RD2 |
496
D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
499
/**************************************************************************
500
NS8390_POLL - Wait for a frame
501
**************************************************************************/
502
static int ns8390_poll(struct nic *nic, int retrieve)
505
unsigned char rstat, curr, next;
506
unsigned short len, frag;
507
unsigned short pktoff;
509
struct ringbuffer pkthdr;
511
#ifndef INCLUDE_3C503
512
/* avoid infinite recursion: see eth_rx_overrun() */
513
if (!eth_drain_receiver && (inb(eth_nic_base+D8390_P0_ISR) & D8390_ISR_OVW)) {
517
#endif /* INCLUDE_3C503 */
518
rstat = inb(eth_nic_base+D8390_P0_RSR);
519
if (!(rstat & D8390_RSTAT_PRX)) return(0);
520
next = inb(eth_nic_base+D8390_P0_BOUND)+1;
521
if (next >= eth_memsize) next = eth_rx_start;
522
outb(D8390_COMMAND_PS1, eth_nic_base+D8390_P0_COMMAND);
523
curr = inb(eth_nic_base+D8390_P1_CURR);
524
outb(D8390_COMMAND_PS0, eth_nic_base+D8390_P0_COMMAND);
525
if (curr >= eth_memsize) curr=eth_rx_start;
526
if (curr == next) return(0);
528
if ( ! retrieve ) return 1;
531
if (eth_flags & FLAG_16BIT) {
532
outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
536
if (eth_flags & FLAG_790) {
537
outb(WD_MSR_MENB, eth_asic_base + WD_MSR);
544
if (eth_flags & FLAG_PIO)
545
eth_pio_read(pktoff, (unsigned char *)&pkthdr, 4);
547
memcpy(&pkthdr, bus_to_virt(eth_rmem + pktoff), 4);
548
pktoff += sizeof(pkthdr);
549
/* incoming length includes FCS so must sub 4 */
550
len = pkthdr.len - 4;
551
if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || len < ETH_ZLEN
552
|| len > ETH_FRAME_LEN) {
553
printf("Bogus packet, ignoring\n");
558
nic->packetlen = len; /* available to caller */
559
frag = (eth_memsize << 8) - pktoff;
560
if (len > frag) { /* We have a wrap-around */
561
/* read first part */
562
if (eth_flags & FLAG_PIO)
563
eth_pio_read(pktoff, p, frag);
565
memcpy(p, bus_to_virt(eth_rmem + pktoff), frag);
566
pktoff = eth_rx_start << 8;
570
/* read second part */
571
if (eth_flags & FLAG_PIO)
572
eth_pio_read(pktoff, p, len);
574
memcpy(p, bus_to_virt(eth_rmem + pktoff), len);
579
if (eth_flags & FLAG_790) {
580
outb(0, eth_asic_base + WD_MSR);
584
if (eth_flags & FLAG_16BIT) {
585
outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
590
next = pkthdr.next; /* frame number of next packet */
591
if (next == eth_rx_start)
593
outb(next-1, eth_nic_base+D8390_P0_BOUND);
597
/**************************************************************************
598
NS8390_DISABLE - Turn off adapter
599
**************************************************************************/
600
static void ns8390_disable ( struct nic *nic ) {
604
/**************************************************************************
605
NS8390_IRQ - Enable, Disable, or Force interrupts
606
**************************************************************************/
607
static void ns8390_irq(struct nic *nic __unused, irq_action_t action __unused)
619
static struct nic_operations ns8390_operations;
620
static struct nic_operations ns8390_operations = {
621
.connect = dummy_connect,
623
.transmit = ns8390_transmit,
627
/**************************************************************************
628
ETH_PROBE - Look for an adapter
629
**************************************************************************/
630
#ifdef INCLUDE_NS8390
631
static int eth_probe (struct nic *nic, struct pci_device *pci)
633
static int eth_probe (struct dev *dev, unsigned short *probe_addrs __unused)
637
#ifdef INCLUDE_NS8390
638
unsigned short pci_probe_addrs[] = { pci->ioaddr, 0 };
639
unsigned short *probe_addrs = pci_probe_addrs;
641
eth_vendor = VENDOR_NONE;
642
eth_drain_receiver = 0;
648
/******************************************************************
649
Search for WD/SMC cards
650
******************************************************************/
651
struct wd_board *brd;
652
unsigned short chksum;
654
for (eth_asic_base = WD_LOW_BASE; eth_asic_base <= WD_HIGH_BASE;
655
eth_asic_base += 0x20) {
658
chksum += inb(eth_asic_base+i);
659
/* Extra checks to avoid soundcard */
660
if ((chksum & 0xFF) == 0xFF &&
661
inb(eth_asic_base+8) != 0xFF &&
662
inb(eth_asic_base+9) != 0xFF)
665
if (eth_asic_base > WD_HIGH_BASE)
667
/* We've found a board */
668
eth_vendor = VENDOR_WD;
669
eth_nic_base = eth_asic_base + WD_NIC_ADDR;
671
nic->ioaddr = eth_nic_base;
673
c = inb(eth_asic_base+WD_BID); /* Get board id */
674
for (brd = wd_boards; brd->name; brd++)
675
if (brd->id == c) break;
677
printf("Unknown WD/SMC NIC type %hhX\n", c);
678
return (0); /* Unknown type */
680
eth_flags = brd->flags;
681
eth_memsize = brd->memsize;
683
eth_rx_start = D8390_TXBUF_SIZE;
684
if ((c == TYPE_WD8013EP) &&
685
(inb(eth_asic_base + WD_ICR) & WD_ICR_16BIT)) {
686
eth_flags = FLAG_16BIT;
687
eth_memsize = MEM_16384;
689
if ((c & WD_SOFTCONFIG) && (!(eth_flags & FLAG_790))) {
690
eth_bmem = (0x80000 |
691
((inb(eth_asic_base + WD_MSR) & 0x3F) << 13));
693
eth_bmem = WD_DEFAULT_MEM;
694
if (brd->id == TYPE_SMC8216T || brd->id == TYPE_SMC8216C) {
695
/* from Linux driver, 8416BT detects as 8216 sometimes */
696
unsigned int addr = inb(eth_asic_base + 0xb);
697
if (((addr >> 4) & 3) == 0) {
699
eth_memsize = brd->memsize;
702
outb(0x80, eth_asic_base + WD_MSR); /* Reset */
703
for (i=0; i<ETH_ALEN; i++) {
704
nic->node_addr[i] = inb(i+eth_asic_base+WD_LAR);
706
DBG ( "\n%s base %4.4x", brd->name, eth_asic_base );
707
if (eth_flags & FLAG_790) {
709
DBG ( ", PIO mode, addr %s\n", eth_ntoa ( nic->node_addr ) );
711
eth_flags |= FLAG_PIO; /* force PIO mode */
712
outb(0, eth_asic_base+WD_MSR);
714
DBG ( ", Memory %x, MAC Addr %s\n", eth_bmem, eth_ntoa ( nic->node_addr) );
716
outb(WD_MSR_MENB, eth_asic_base+WD_MSR);
717
outb((inb(eth_asic_base+0x04) |
718
0x80), eth_asic_base+0x04);
719
outb(((unsigned)(eth_bmem >> 13) & 0x0F) |
720
((unsigned)(eth_bmem >> 11) & 0x40) |
721
(inb(eth_asic_base+0x0B) & 0xB0), eth_asic_base+0x0B);
722
outb((inb(eth_asic_base+0x04) &
723
~0x80), eth_asic_base+0x04);
727
DBG (", Memory %x, MAC Addr %s\n", eth_bmem, eth_ntoa ( nic->node_addr) );
729
outb(((unsigned)(eth_bmem >> 13) & 0x3F) | 0x40, eth_asic_base+WD_MSR);
731
if (eth_flags & FLAG_16BIT) {
732
if (eth_flags & FLAG_790) {
733
eth_laar = inb(eth_asic_base + WD_LAAR);
734
outb(WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
737
WD_LAAR_L16EN | 1), eth_asic_base + WD_LAAR);
739
The previous line used to be
740
WD_LAAR_M16EN | WD_LAAR_L16EN | 1));
741
jluke@deakin.edu.au reported that removing WD_LAAR_M16EN made
742
it work for WD8013s. This seems to work for my 8013 boards. I
743
don't know what is really happening. I wish I had data sheets
744
or more time to decode the Linux driver. - Ken
753
nic->flags = 1; /* aui */
755
nic->flags = 0; /* no aui */
757
/******************************************************************
758
Search for 3Com 3c503 if no WD/SMC cards
759
******************************************************************/
760
if (eth_vendor == VENDOR_NONE) {
762
int iobase_reg, membase_reg;
763
static unsigned short base[] = {
764
0x300, 0x310, 0x330, 0x350,
765
0x250, 0x280, 0x2A0, 0x2E0, 0 };
767
/* Loop through possible addresses checking each one */
769
for (idx = 0; (eth_nic_base = base[idx]) != 0; ++idx) {
771
eth_asic_base = eth_nic_base + _3COM_ASIC_OFFSET;
773
* Note that we use the same settings for both 8 and 16 bit cards:
774
* both have an 8K bank of memory at page 1 while only the 16 bit
775
* cards have a bank at page 0.
777
eth_memsize = MEM_16384;
779
eth_rx_start = 32 + D8390_TXBUF_SIZE;
781
/* Check our base address. iobase and membase should */
782
/* both have a maximum of 1 bit set or be 0. */
784
iobase_reg = inb(eth_asic_base + _3COM_BCFR);
785
membase_reg = inb(eth_asic_base + _3COM_PCFR);
787
if ((iobase_reg & (iobase_reg - 1)) ||
788
(membase_reg & (membase_reg - 1)))
791
/* Now get the shared memory address */
795
switch (membase_reg) {
796
case _3COM_PCFR_DC000:
799
case _3COM_PCFR_D8000:
802
case _3COM_PCFR_CC000:
805
case _3COM_PCFR_C8000:
809
eth_flags |= FLAG_PIO;
818
if (base[idx] == 0) /* not found */
821
eth_flags |= FLAG_PIO; /* force PIO mode */
824
eth_vendor = VENDOR_3COM;
827
/* Need this to make ns8390_poll() happy. */
829
eth_rmem = eth_bmem - 0x2000;
831
/* Reset NIC and ASIC */
833
outb(_3COM_CR_RST | _3COM_CR_XSEL, eth_asic_base + _3COM_CR );
834
outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR );
836
/* Get our ethernet address */
838
outb(_3COM_CR_EALO | _3COM_CR_XSEL, eth_asic_base + _3COM_CR);
839
nic->ioaddr = eth_nic_base;
840
DBG ( "\n3Com 3c503 base %4.4x, ", eth_nic_base );
841
if (eth_flags & FLAG_PIO)
844
DBG ( "memory %4.4x", eth_bmem );
845
for (i=0; i<ETH_ALEN; i++) {
846
nic->node_addr[i] = inb(eth_nic_base+i);
848
DBG ( ", %s, MAC Addr %s\n", nic->flags ? "AUI" : "internal xcvr",
849
eth_ntoa ( nic->node_addr ) );
851
outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR);
853
* Initialize GA configuration register. Set bank and enable shared
854
* mem. We always use bank 1. Disable interrupts.
856
outb(_3COM_GACFR_RSEL |
857
_3COM_GACFR_MBS0 | _3COM_GACFR_TCM | _3COM_GACFR_NIM, eth_asic_base + _3COM_GACFR);
859
outb(0xff, eth_asic_base + _3COM_VPTR2);
860
outb(0xff, eth_asic_base + _3COM_VPTR1);
861
outb(0x00, eth_asic_base + _3COM_VPTR0);
863
* Clear memory and verify that it worked (we use only 8K)
866
if (!(eth_flags & FLAG_PIO)) {
867
memset(bus_to_virt(eth_bmem), 0, 0x2000);
868
for(i = 0; i < 0x2000; ++i)
869
if (*((char *)(bus_to_virt(eth_bmem+i)))) {
870
printf ("Failed to clear 3c503 shared mem.\n");
875
* Initialize GA page/start/stop registers.
877
outb(eth_tx_start, eth_asic_base + _3COM_PSTR);
878
outb(eth_memsize, eth_asic_base + _3COM_PSPR);
881
#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
883
/******************************************************************
884
Search for NE1000/2000 if no WD/SMC or 3com cards
885
******************************************************************/
887
if (eth_vendor == VENDOR_NONE) {
888
unsigned char romdata[16];
889
unsigned char testbuf[32];
891
static unsigned char test[] = "NE*000 memory";
892
static unsigned short base[] = {
897
/* if no addresses supplied, fall back on defaults */
898
if (probe_addrs == NULL || probe_addrs[0] == 0)
900
eth_bmem = 0; /* No shared memory */
901
for (idx = 0; (eth_nic_base = probe_addrs[idx]) != 0; ++idx) {
902
eth_flags = FLAG_PIO;
903
eth_asic_base = eth_nic_base + NE_ASIC_OFFSET;
904
eth_memsize = MEM_16384;
906
eth_rx_start = 32 + D8390_TXBUF_SIZE;
907
c = inb(eth_asic_base + NE_RESET);
908
outb(c, eth_asic_base + NE_RESET);
910
outb(D8390_COMMAND_STP |
911
D8390_COMMAND_RD2, eth_nic_base + D8390_P0_COMMAND);
912
outb(D8390_RCR_MON, eth_nic_base + D8390_P0_RCR);
913
outb(D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
914
outb(MEM_8192, eth_nic_base + D8390_P0_PSTART);
915
outb(MEM_16384, eth_nic_base + D8390_P0_PSTOP);
916
#ifdef NS8390_FORCE_16BIT
917
eth_flags |= FLAG_16BIT; /* force 16-bit mode */
920
eth_pio_write( (unsigned char *) test, 8192, sizeof(test));
921
eth_pio_read(8192, testbuf, sizeof(test));
922
if (!memcmp(test, testbuf, sizeof(test)))
924
eth_flags |= FLAG_16BIT;
925
eth_memsize = MEM_32768;
927
eth_rx_start = 64 + D8390_TXBUF_SIZE;
929
D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
930
outb(MEM_16384, eth_nic_base + D8390_P0_PSTART);
931
outb(MEM_32768, eth_nic_base + D8390_P0_PSTOP);
932
eth_pio_write( (unsigned char *) test, 16384, sizeof(test));
933
eth_pio_read(16384, testbuf, sizeof(test));
934
if (!memcmp(testbuf, test, sizeof(test)))
937
if (eth_nic_base == 0)
939
if (eth_nic_base > ISA_MAX_ADDR) /* PCI probably */
940
eth_flags |= FLAG_16BIT;
941
eth_vendor = VENDOR_NOVELL;
942
eth_pio_read(0, romdata, sizeof(romdata));
943
for (i=0; i<ETH_ALEN; i++) {
944
nic->node_addr[i] = romdata[i + ((eth_flags & FLAG_16BIT) ? i : 0)];
946
nic->ioaddr = eth_nic_base;
947
DBG ( "\nNE%c000 base %4.4x, MAC Addr %s\n",
948
(eth_flags & FLAG_16BIT) ? '2' : '1', eth_nic_base,
949
eth_ntoa ( nic->node_addr ) );
953
if (eth_vendor == VENDOR_NONE)
955
if (eth_vendor != VENDOR_3COM)
958
nic->nic_op = &ns8390_operations;
960
/* Based on PnP ISA map */
962
dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
963
dev->devid.device_id = htons(0x812a);
966
dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
967
dev->devid.device_id = htons(0x80f3);
970
dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
971
dev->devid.device_id = htons(0x80d6);
977
struct isa_driver wd_driver __isa_driver = {
983
ISA_ROM("wd","WD8003/8013, SMC8216/8416, SMC 83c790 (EtherEZ)");
987
struct isa_driver t503_driver __isa_driver = {
993
ISA_ROM("3c503","3Com503, Etherlink II[/16]");
997
struct isa_driver ne_driver __isa_driver = {
1003
ISA_ROM("ne","NE1000/2000 and clones");
1006
#ifdef INCLUDE_NS8390
1007
static struct pci_device_id nepci_nics[] = {
1008
/* A few NE2000 PCI clones, list not exhaustive */
1009
PCI_ROM(0x10ec, 0x8029, "rtl8029", "Realtek 8029", 0),
1010
PCI_ROM(0x1186, 0x0300, "dlink-528", "D-Link DE-528", 0),
1011
PCI_ROM(0x1050, 0x0940, "winbond940", "Winbond NE2000-PCI", 0), /* Winbond 86C940 / 89C940 */
1012
PCI_ROM(0x1050, 0x5a5a, "winbond940f", "Winbond W89c940F", 0), /* Winbond 89C940F */
1013
PCI_ROM(0x11f6, 0x1401, "compexrl2000", "Compex ReadyLink 2000", 0),
1014
PCI_ROM(0x8e2e, 0x3000, "ktiet32p2", "KTI ET32P2", 0),
1015
PCI_ROM(0x4a14, 0x5000, "nv5000sc", "NetVin NV5000SC", 0),
1016
PCI_ROM(0x12c3, 0x0058, "holtek80232", "Holtek HT80232", 0),
1017
PCI_ROM(0x12c3, 0x5598, "holtek80229", "Holtek HT80229", 0),
1018
PCI_ROM(0x10bd, 0x0e34, "surecom-ne34", "Surecom NE34", 0),
1019
PCI_ROM(0x1106, 0x0926, "via86c926", "Via 86c926", 0),
1022
PCI_DRIVER ( nepci_driver, nepci_nics, PCI_NO_CLASS );
1024
DRIVER ( "NE2000/PCI", nic_driver, pci_driver, nepci_driver,
1025
nepci_probe, ns8390_disable );
1027
#endif /* INCLUDE_NS8390 */