1
/* ne2k-diag.c: Diagnostic program for NE2000 ethercards. */
3
static const char version_msg[] =
4
"ne2k-diag.c:v2.00 4/19/2000 Donald Becker (becker@scyld.com)\n";
5
static const char usage_msg[] =
6
"\t[Short] [Long arg] [Options] - [definition]\n"
7
"\t-a --show-registers - show chip status (-aa for more)\n"
8
"\t-D --debug - describe program internal state\n"
9
"\t-e --show-eeprom - show EEPROM contents (-ee for more)\n"
10
"\t-p --base-address 0xNNN - specify card base address\n"
11
"\t-v --verbose - verbose mode\n"
12
"\t-w --write - commit the new values to the EEPROM\n"
13
"\t-h --help - display this usage message\n"
14
"\t-V --version - display version\n\n"
15
"\t-P --new-address 0xNNN - new card base address\n"
16
"\t-Q --new-irq IRQ - new card IRQ\n"
17
"\t-X --new-xcvr N - new transceiver index.\n"
21
Written 1993,1994,1999,2000 by Donald Becker.
22
Copyright 1994,1999-2000 Donald Becker
23
Copyright 1993 United States Government as represented by the
24
Director, National Security Agency.
26
This software may be used and distributed according to the terms of
27
the GNU General Public License (GPL), incorporated herein by reference.
28
http://scyld.com/expert/license.html
29
No substitution of license terms are permitted.
31
The author may be reached as becker@scyld.com, or C/O
32
Scyld Computing Corporation
33
410 Severn Ave., Suite 210
36
This program is used to diagnose detection ("probe") problems with NE1000
37
NE2000 work-alike cards. The probe routine is very similar to that
38
used in the Linux NE2000 driver, and should work with any NE2000
41
See the bottom of this file for the compile command.
42
Do not forget the "-O"!
44
Some of the names and comments for the #defines came from Crynwr.
46
1999/Mar/18 James Bourne <jbourne@affinity-systems.ab.ca>
47
Fixed -h --help and -V --version flags
49
RTL8019 datasheet, http://www.realtek.com.tw/cn/cn.html
53
#warning You must compile this program with the correct options!
54
#warning See the last lines of the source file for the suggested command.
55
#error You must compile this driver with "-O".
63
#if defined(__linux__) && __GNU_LIBRARY__ == 1
73
#define NS_CMD (dev->base_addr)
74
#define NS_BASE (dev->base_addr)
75
#define NS_DATAPORT 0x10 /* NatSemi-defined port window offset. */
76
#define NE_DATAPORT 0x10 /* NatSemi-defined port window offset. */
77
#define NS_RESET 0x1f /* Issue a read to reset, a write to clear. */
79
#define NE1SM_START_PG 0x20 /* First page of TX buffer */
80
#define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */
81
#define NESM_START_PG 0x40 /* First page of TX buffer */
82
#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
84
#define E8390_CMD 0x00 /* The command register (for all pages) */
85
#define E8390_STOP 0x01 /* Stop and reset the chip */
86
#define E8390_START 0x02 /* Start the chip, clear reset */
87
#define E8390_RREAD 0x08 /* Remote read */
88
#define E8390_NODMA 0x20 /* Remote DMA */
89
#define E8390_PAGE0 0x00 /* Select page chip registers */
90
#define E8390_PAGE1 0x40 /* using the two high-order bits */
91
#define E8390_PAGE2 0x80
92
#define E8390_PAGE3 0xC0 /* Page 3 is invalid on the real 8390. */
94
#define E8390_RXOFF 0x20 /* EN0_RXCR: Accept no packets */
95
#define E8390_TXOFF 0x02 /* EN0_TXCR: Transmitter off */
97
/* Page 0 register offsets. */
98
#define EN0_CLDALO 0x01 /* Low byte of current local dma addr RD */
99
#define EN0_STARTPG 0x01 /* Starting page of ring bfr WR */
100
#define EN0_CLDAHI 0x02 /* High byte of current local dma addr RD */
101
#define EN0_STOPPG 0x02 /* Ending page +1 of ring bfr WR */
102
#define EN0_BOUNDARY 0x03 /* Boundary page of ring bfr RD WR */
103
#define EN0_TSR 0x04 /* Transmit status reg RD */
104
#define EN0_TPSR 0x04 /* Transmit starting page WR */
105
#define EN0_NCR 0x05 /* Number of collision reg RD */
106
#define EN0_TCNTLO 0x05 /* Low byte of tx byte count WR */
107
#define EN0_FIFO 0x06 /* FIFO RD */
108
#define EN0_TCNTHI 0x06 /* High byte of tx byte count WR */
109
#define EN0_ISR 0x07 /* Interrupt status reg RD WR */
110
#define EN0_CRDALO 0x08 /* low byte of current remote dma address RD */
111
#define EN0_RSARLO 0x08 /* Remote start address reg 0 */
112
#define EN0_CRDAHI 0x09 /* high byte, current remote dma address RD */
113
#define EN0_RSARHI 0x09 /* Remote start address reg 1 */
114
#define EN0_RCNTLO 0x0a /* Remote byte count reg WR */
115
#define EN0_RCNTHI 0x0b /* Remote byte count reg WR */
116
#define EN0_RSR 0x0c /* rx status reg RD */
117
#define EN0_RXCR 0x0c /* RX configuration reg WR */
118
#define EN0_TXCR 0x0d /* TX configuration reg WR */
119
#define EN0_COUNTER0 0x0d /* Rcv alignment error counter RD */
120
#define EN0_DCFG 0x0e /* Data configuration reg WR */
121
#define EN0_COUNTER1 0x0e /* Rcv CRC error counter RD */
122
#define EN0_IMR 0x0f /* Interrupt mask reg WR */
123
#define EN0_COUNTER2 0x0f /* Rcv missed frame error counter RD */
126
void write_EEPROM(int port_base, int regA, int regB, int regC);
127
static int do_probe(long ioaddr);
128
static void rtl8019(long ioaddr);
130
int opt_a = 0, debug = 0, show_eeprom = 0, opt_F = 0, new_irq = 0;
131
int new_port_base = 0;
133
int do_write_eeprom = 0;
135
struct option longopts[] = {
136
/* { name has_arg *flag val } */
137
{"show-registers", 0, 0, 'a'},
138
{"debug", 0, 0, 'D'},
139
{"show-eeprom", 0, 0, 'e'},
140
{"base-address", 1, 0, 'p'}, /* Base address */
141
{"help", 0, 0, 'h'}, /* Give help */
142
{"verbose", 0, 0, 'v'}, /* Verbose mode */
143
{"version", 0, 0, 'V'}, /* Display version number */
144
{"interface", 1, 0, 'F'}, /* New transceiver index (10baseT, AUI) */
145
{"new-address", 1, 0, 'P'}, /* Base address */
146
{"new-irq", 1, 0, 'Q'}, /* New interrupt number */
151
/* Probe for various non-shared-memory ethercards.
153
NEx000-clone boards have a Station Address PROM (SAPROM) in the packet
154
buffer memory space. NE2000 clones have 0x57,0x57 in bytes 0x0e,0x0f of
155
the SAPROM, while other supposed NE2000 clones must be detected by their
158
Reading the SAPROM from a word-wide card with the 8390 set in byte-wide
159
mode results in doubled values, which can be detected and compensated for.
161
The probe is also responsible for initializing the card and filling
162
in the 'dev' and 'ei_status' structures.
164
We use the minimum memory size for some ethercard product lines, iff we can't
165
distinguish models. You can increase the packet buffer size by setting
166
PACKETBUF_MEMSIZE. Reported Cabletron packet buffer locations are:
167
E1010 starts at 0x100 and ends at 0x2000.
168
E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory")
169
E2010 starts at 0x100 and ends at 0x4000.
170
E2010-x starts at 0x100 and ends at 0xffff. */
172
static void usage(char *prog)
174
fprintf(stderr, "%s: %s", prog, version_msg);
175
fprintf(stderr, "Usage: %s [-p 0xNNN] [-i IRQ] [-f N] [-v] [-h] [-V]\n",
177
fprintf(stderr, usage_msg);
180
int main(int argc, char *argv[])
182
int show_version = 0, errflag = 0;
183
int port_base = 0x300;
187
int option_index = 0;
189
while ((c = getopt_long(argc,argv, "aDeF:i:p:P:Q:svwX:Vh",
190
longopts, &option_index))
193
case 'a': opt_a++; break;
194
case 'D': debug++; break;
195
case 'e': show_eeprom++; break;
197
case 'X': opt_F++; interface = atoi(optarg); break;
198
case 'p': port_base = strtol(optarg, NULL, 16); break;
199
case 'P': new_port_base = strtol(optarg, NULL, 16); break;
201
new_irq = atoi(optarg);
202
/* On ISA IRQ2 == IRQ9, with IRQ9 the proper name. */
203
if (new_irq < 2 || new_irq > 15 || new_irq == 6 || new_irq == 8) {
204
fprintf(stderr, "Invalid new IRQ %#x. Valid values: "
205
"3-5,7,9-15.\n", new_irq);
209
case 'v': verbose++; break;
210
case 'V': show_version++; break;
211
case 'w': do_write_eeprom++; break;
218
fprintf(stderr, usage_msg);
222
if (verbose || show_version)
225
if (ioperm(port_base, 32, 1)) {
226
perror("ne2k-diag: ioperm()");
227
fprintf(stderr, "This program must be run as root.\n");
230
/* The following is needed for SLOW_DOWN_IO. */
231
if (ioperm(0x80, 1, 1)) {
236
printf("Checking the ethercard at %#3x.\n", port_base);
238
long ioaddr = port_base;
240
outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
241
regd = inb_p(ioaddr + 0x0d);
242
printk(" Receive alignment error counter (%#x) is %2.2x\n",
243
ioaddr + 0x0d, regd);
244
outb_p(0xff, ioaddr + 0x0d);
245
outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
246
inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
247
if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
248
outb(regd, ioaddr + 0x0d); /* Restore the old values. */
249
printk(" Failed initial NE2000 probe, value %2.2x.\n",
250
inb(ioaddr + EN0_COUNTER0));
252
printk(" Passed initial NE2000 probe, value %2.2x.\n",
253
inb(ioaddr + EN0_COUNTER0));
261
static int do_probe(long ioaddr)
264
int neX000, ctron, dlink;
265
unsigned char SA_prom[32];
268
int start_page, stop_page;
270
struct {char value, offset; } program_seq[] = {
271
{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
272
{0x48, EN0_DCFG}, /* Set byte-wide (0x48) access. */
273
{0x00, EN0_RCNTLO}, /* Clear the count regs. */
275
{0x00, EN0_IMR}, /* Mask completion irq. */
277
{E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */
278
{E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */
281
{0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */
283
{E8390_RREAD+E8390_START, E8390_CMD},
286
/* Read the 16 bytes of station address prom, returning 1 for
287
an eight-bit interface and 2 for a 16-bit interface.
288
We must first initialize registers, similar to NS8390_init(eifdev, 0).
289
We can't reliably read the SAPROM address without this.
290
(I learned the hard way!). */
291
for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++)
292
outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
294
for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
295
SA_prom[i] = inb_p(ioaddr + NE_DATAPORT);
296
SA_prom[i+1] = inb_p(ioaddr + NE_DATAPORT);
297
if (SA_prom[i] != SA_prom[i+1])
301
printk("Station Address PROM 0:");
302
for(i = 0; i < sizeof(SA_prom)/2; i++)
303
printk(" %2.2x", SA_prom[i]);
304
printk("\nStation Address PROM %#2x:", i);
305
for(; i < sizeof(SA_prom); i++)
306
printk(" %2.2x", SA_prom[i]);
309
if (wordlength == 2) {
310
/* We must set the 8390 for word mode, AND RESET IT. */
312
outb_p(0x49, ioaddr + EN0_DCFG);
313
tmp = inb_p(ioaddr + NS_RESET);
314
outb(tmp, ioaddr + NS_RESET);
315
/* Un-double the SA_prom values. */
316
for (i = 0; i < 16; i++)
317
SA_prom[i] = SA_prom[i+i];
320
neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57);
321
ctron = (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
322
dlink = (SA_prom[0] == 0x00 && SA_prom[1] == 0xDE && SA_prom[2] == 0x01);
324
/* Set up the rest of the parameters. */
325
if (neX000 || dlink) {
326
if (wordlength == 2) {
327
name = dlink ? "DE200" : "NE2000";
328
start_page = NESM_START_PG;
329
stop_page = NESM_STOP_PG;
331
name = dlink ? "DE100" : "D-Link";
332
start_page = NE1SM_START_PG;
333
stop_page = NE1SM_STOP_PG;
338
stop_page = (wordlength == 2) ? 0x40 : 0x20;
340
printk(" Invalid signature found, wordlength %d.\n", wordlength);
344
printk(" %s found at %#x, using start page %#x and end page %#x.\n",
345
name, ioaddr, start_page, stop_page);
347
outb_p(E8390_NODMA + E8390_PAGE1, ioaddr + E8390_CMD);
348
printf("The current MAC stations address is ");
349
for (i = 1; i < 6; i++)
350
printf("%2.2X:", inb(ioaddr + i));
351
printf("%2.2X.\n", inb(ioaddr + i));
355
for (page = 0; page < 4; page++) {
356
printf("8390 page %d:", page);
357
outb_p(E8390_NODMA + (page << 6), ioaddr + E8390_CMD);
358
for(i = 0; i < 16; i++)
359
printf(" %2.2x", inb_p(ioaddr + i));
364
outb_p(E8390_NODMA + E8390_PAGE0, ioaddr + E8390_CMD);
365
/* Check for a RealTek 8019 chip. */
366
if (inb(ioaddr + 10) == 'P' && inb(ioaddr + 11) == 'p')
372
/* Serial EEPROM section. */
373
/* The description of EEPROM access. */
374
struct ee_ctrl_bits {
376
unsigned char shift_clk, /* Bit that drives SK (shift clock) pin */
377
read_bit, /* Mask bit for DO pin value */
378
write_0, write_1, /* Enable chip and drive DI pin with 0 / 1 */
379
disable; /* Disable chip. */
382
/* The EEPROM commands include the alway-set leading bit. */
383
enum EEPROM_Cmds { EE_WriteCmd=5, EE_ReadCmd=6, EE_EraseCmd=7, };
385
/* This executes a generic EEPROM command, typically a write or write enable.
386
It returns the data output from the EEPROM, and thus may also be used for
387
reads and EEPROM sizing. */
388
static int do_eeprom_cmd(struct ee_ctrl_bits *ee, long ioaddr, int cmd,
391
long ee_addr = ioaddr + ee->offset;
395
printf(" EEPROM op 0x%x: ", cmd);
397
/* Shift the command bits out. */
399
short dataval = (cmd & (1 << cmd_len)) ? ee->write_1 : ee->write_0;
400
outb(dataval, ee_addr);
402
printf("%X", inb(ee_addr) & 15);
403
outb(dataval |ee->shift_clk, ee_addr);
404
retval = (retval << 1) | ((inb(ee_addr) & ee->read_bit) ? 1 : 0);
405
} while (--cmd_len >= 0);
406
outb(ee->write_0, ee_addr);
408
/* Terminate the EEPROM access. */
409
outb(ee->disable, ee_addr);
411
printf(" EEPROM result is 0x%5.5x.\n", retval);
415
/* Wait for the EEPROM to finish what it is doing. */
416
static int eeprom_busy_poll(struct ee_ctrl_bits *ee, long ioaddr)
418
int ee_addr = ioaddr + ee->offset;
421
outb(ee->write_0, ee_addr);
422
for (i = 0; i < 10000; i++) /* Typical 2000 ticks */
423
if (inb(ee_addr) & ee->read_bit)
428
/* The abstracted functions for EEPROM access. */
429
static int read_eeprom(struct ee_ctrl_bits *ee, long ioaddr, int location)
432
return do_eeprom_cmd(ee, ioaddr, ((EE_ReadCmd << addr_len) | location) << 16,
433
3 + addr_len + 16) & 0xffff;
436
static void write_eeprom(struct ee_ctrl_bits *eebits, long ioaddr, int index,
442
/* Poll for previous op finished. */
443
eeprom_busy_poll(eebits, ioaddr);
445
/* Enable programming modes. */
446
do_eeprom_cmd(eebits, ioaddr, (0x4f << (addr_len-4)), 3 + addr_len);
447
/* Do the actual write. */
448
do_eeprom_cmd(eebits, ioaddr,
449
(((EE_WriteCmd<<addr_len) | index)<<16) | (value & 0xffff),
451
i = eeprom_busy_poll(eebits, ioaddr);
453
printf(" Write finished after %d ticks.\n", i);
454
/* Disable programming. Note: this command is not instantaneous, but
455
we check for busy before the next write. */
456
do_eeprom_cmd(eebits, ioaddr, (0x40 << (addr_len-4)), 3 + addr_len);
461
/* The RealTek RTL8019 specific routines. */
462
static const char irqmap[] = { 9, 3, 4, 5, 10, 11, 12, 15 };
463
static const char irq2config_map[16] = {
464
-1,-1,0x00,0x10, 0x20,0x30,-1,-1, -1,0x00,0x40,0x50, 0x60,-1,-1,0x70};
465
static const int iomap[] = {
466
0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0,
467
0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0 };
468
static const char *const xcvr_modes[4] = {
469
"10baseT or coax, selected on 10baseT link beat",
470
"10baseT with link test disabled", "10base5 / AUI", "10base2"};
471
struct ee_ctrl_bits rtl_ee_tbl = {0x01, 0x04, 0x01, 0x88, 0x8A, 0x00 };
472
#define EEPROM_SIZE 64
474
static void rtl8019(long ioaddr)
476
int config0, config1, config2, config3, eeword0, eeword1;
479
/* The rtl8019-specific registers are on page 3. */
480
outb(E8390_NODMA+E8390_PAGE3, ioaddr + E8390_CMD);
481
/* We do not use symbolic names for the Realtek-specific registers. */
482
config0 = inb(ioaddr + 3);
483
config1 = inb(ioaddr + 4);
484
config2 = inb(ioaddr + 5);
485
config3 = inb(ioaddr + 6);
486
printf("This is a RTL8019%s chip in jumper%s%s mode.\n",
487
config0 & 0xC0 ? "" : "AS", config0 & 0x08 ? "ed" : "less",
488
(config0 & 0x08) == 0 && (config3 & 0x80) ? " PnP" :"");
489
printf(" The current settings are: IRQ %d (%sabled, I/O address 0x%x,\n",
490
irqmap[(config1>>4) & 7], config1 & 0x80 ? "en" : "dis",
491
iomap[config1 & 15]);
492
printf(" The transceiver is set to %s,\n"
493
" The chip is set to %s duplex.\n",
494
xcvr_modes[config2 >> 6], config3 & 0x40 ? "full" : "half");
495
eeword0 = read_eeprom(&rtl_ee_tbl, ioaddr, 0);
496
eeword1 = read_eeprom(&rtl_ee_tbl, ioaddr, 1);
498
config2 = eeword0 >> 8;
500
printf(" The EEPROM settings are: IRQ %d, I/O address 0x%x, %sPnP mode.\n"
501
" The transceiver is set to %s,\n"
502
" The chip is set to %s duplex.\n",
503
irqmap[(config1>>4) & 7], iomap[config1 & 15],
504
(config3 & 0x80) ? "" :"non-",
505
xcvr_modes[config2 >> 6], config3 & 0x40 ? "full" : "half");
507
unsigned short sum = 0, val;
509
printf("EEPROM contents:");
510
for (i = 0; i < EEPROM_SIZE; i++) {
511
val = read_eeprom(&rtl_ee_tbl, ioaddr, i);
512
printf("%s %4.4x", (i & 7) == 0 ? "\n ":"", val);
515
printf("\n The word-wide EEPROM checksum is %#4.4x.\n", sum);
517
if (opt_F || new_irq > 0 || new_port_base > 0) {
518
int newval0 = eeword0;
519
if (opt_F && interface >= 0 && interface < 4) {
521
newval0 |= interface << 14;
523
if (new_irq > 0 && new_irq < 16 && irq2config_map[new_irq] > 0) {
525
newval0 |= irq2config_map[new_irq];
528
for (i = 0; i < 16; i++)
529
if (iomap[i] == new_port_base) {
534
if (do_write_eeprom) {
535
printf(" Writing 0x%4.4x to EEPROM word 0.\n", newval0);
536
write_eeprom(&rtl_ee_tbl, ioaddr, 0, newval0);
538
printf(" Would write 0x%4.4x to EEPROM word 0 with '-w'.\n",
545
* compile-command: "gcc -Wall -O6 -o ne2k-diag ne2k-diag.c"