1 /************************************************************************** 2 ETHERBOOT - BOOTP/TFTP Bootstrap Program 3 4 Author: Martin Renters 5 Date: May/94 6 7 This code is based heavily on David Greenman's if_ed.c driver 8 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. 15 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) 25 26 **************************************************************************/ 27 28 #include "etherboot.h" 29 #include "nic.h" 30 #include "ns8390.h" 31 #ifdef INCLUDE_NS8390 32 #include "pci.h" 33 #else 34 #include "isa.h" 35 #endif 36 37 static unsigned char eth_vendor, eth_flags; 38 #ifdef INCLUDE_WD 39 static unsigned char eth_laar; 40 #endif 41 static unsigned short eth_nic_base, eth_asic_base; 42 static unsigned char eth_memsize, eth_rx_start, eth_tx_start; 43 static Address eth_bmem, eth_rmem; 44 static unsigned char eth_drain_receiver; 45 46 #ifdef INCLUDE_WD 47 static struct wd_board { 48 const char *name; 49 char id; 50 char flags; 51 char memsize; 52 } wd_boards[] = { 53 {"WD8003S", TYPE_WD8003S, 0, MEM_8192}, 54 {"WD8003E", TYPE_WD8003E, 0, MEM_8192}, 55 {"WD8013EBT", TYPE_WD8013EBT, FLAG_16BIT, MEM_16384}, 56 {"WD8003W", TYPE_WD8003W, 0, MEM_8192}, 57 {"WD8003EB", TYPE_WD8003EB, 0, MEM_8192}, 58 {"WD8013W", TYPE_WD8013W, FLAG_16BIT, MEM_16384}, 59 {"WD8003EP/WD8013EP", 60 TYPE_WD8013EP, 0, MEM_8192}, 61 {"WD8013WC", TYPE_WD8013WC, FLAG_16BIT, MEM_16384}, 62 {"WD8013EPC", TYPE_WD8013EPC, FLAG_16BIT, MEM_16384}, 63 {"SMC8216T", TYPE_SMC8216T, FLAG_16BIT | FLAG_790, MEM_16384}, 64 {"SMC8216C", TYPE_SMC8216C, FLAG_16BIT | FLAG_790, MEM_16384}, 65 {"SMC8416T", TYPE_SMC8416T, FLAG_16BIT | FLAG_790, MEM_8192}, 66 {"SMC8416C/BT", TYPE_SMC8416C, FLAG_16BIT | FLAG_790, MEM_8192}, 67 {"SMC8013EBP", TYPE_SMC8013EBP,FLAG_16BIT, MEM_16384}, 68 {NULL, 0, 0, 0} 69 }; 70 #endif 71 72 #ifdef INCLUDE_3C503 73 static unsigned char t503_output; /* AUI or internal xcvr (Thinnet) */ 74 #endif 75 76 #if defined(INCLUDE_WD) 77 #define ASIC_PIO WD_IAR 78 #define eth_probe wd_probe 79 #if defined(INCLUDE_3C503) || defined(INCLUDE_NE) || defined(INCLUDE_NS8390) 80 Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390 81 #endif 82 #endif 83 84 #if defined(INCLUDE_3C503) 85 #define eth_probe t503_probe 86 #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || defined(INCLUDE_WD) 87 Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390 88 #endif 89 #endif 90 91 #if defined(INCLUDE_NE) 92 #define eth_probe ne_probe 93 #if defined(INCLUDE_NS8390) || defined(INCLUDE_3C503) || defined(INCLUDE_WD) 94 Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390 95 #endif 96 #endif 97 98 #if defined(INCLUDE_NS8390) 99 #define eth_probe nepci_probe 100 #if defined(INCLUDE_NE) || defined(INCLUDE_3C503) || defined(INCLUDE_WD) 101 Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390 102 #endif 103 #endif 104 105 #if defined(INCLUDE_3C503) 106 #define ASIC_PIO _3COM_RFMSB 107 #else 108 #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) 109 #define ASIC_PIO NE_DATA 110 #endif 111 #endif 112 113 #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO)) 114 /************************************************************************** 115 ETH_PIO_READ - Read a frame via Programmed I/O 116 **************************************************************************/ 117 static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt) 118 { 119 #ifdef INCLUDE_WD 120 outb(src & 0xff, eth_asic_base + WD_GP2); 121 outb(src >> 8, eth_asic_base + WD_GP2); 122 #else 123 outb(D8390_COMMAND_RD2 | 124 D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND); 125 outb(cnt, eth_nic_base + D8390_P0_RBCR0); 126 outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1); 127 outb(src, eth_nic_base + D8390_P0_RSAR0); 128 outb(src>>8, eth_nic_base + D8390_P0_RSAR1); 129 outb(D8390_COMMAND_RD0 | 130 D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND); 131 132 #ifdef INCLUDE_3C503 133 outb(src & 0xff, eth_asic_base + _3COM_DALSB); 134 outb(src >> 8, eth_asic_base + _3COM_DAMSB); 135 outb(t503_output | _3COM_CR_START, eth_asic_base + _3COM_CR); 136 #endif 137 #endif 138 139 if (eth_flags & FLAG_16BIT) 140 cnt = (cnt + 1) >> 1; 141 142 while(cnt--) { 143 #ifdef INCLUDE_3C503 144 while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0) 145 ; 146 #endif 147 148 if (eth_flags & FLAG_16BIT) { 149 *((unsigned short *)dst) = inw(eth_asic_base + ASIC_PIO); 150 dst += 2; 151 } 152 else 153 *(dst++) = inb(eth_asic_base + ASIC_PIO); 154 } 155 156 #ifdef INCLUDE_3C503 157 outb(t503_output, eth_asic_base + _3COM_CR); 158 #endif 159 } 160 161 /************************************************************************** 162 ETH_PIO_WRITE - Write a frame via Programmed I/O 163 **************************************************************************/ 164 static void eth_pio_write(const unsigned char *src, unsigned int dst, unsigned int cnt) 165 { 166 #ifdef COMPEX_RL2000_FIX 167 unsigned int x; 168 #endif /* COMPEX_RL2000_FIX */ 169 #ifdef INCLUDE_WD 170 outb(dst & 0xff, eth_asic_base + WD_GP2); 171 outb(dst >> 8, eth_asic_base + WD_GP2); 172 #else 173 outb(D8390_COMMAND_RD2 | 174 D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND); 175 outb(D8390_ISR_RDC, eth_nic_base + D8390_P0_ISR); 176 outb(cnt, eth_nic_base + D8390_P0_RBCR0); 177 outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1); 178 outb(dst, eth_nic_base + D8390_P0_RSAR0); 179 outb(dst>>8, eth_nic_base + D8390_P0_RSAR1); 180 outb(D8390_COMMAND_RD1 | 181 D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND); 182 183 #ifdef INCLUDE_3C503 184 outb(dst & 0xff, eth_asic_base + _3COM_DALSB); 185 outb(dst >> 8, eth_asic_base + _3COM_DAMSB); 186 187 outb(t503_output | _3COM_CR_DDIR | _3COM_CR_START, eth_asic_base + _3COM_CR); 188 #endif 189 #endif 190 191 if (eth_flags & FLAG_16BIT) 192 cnt = (cnt + 1) >> 1; 193 194 while(cnt--) 195 { 196 #ifdef INCLUDE_3C503 197 while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0) 198 ; 199 #endif 200 201 if (eth_flags & FLAG_16BIT) { 202 outw(*((unsigned short *)src), eth_asic_base + ASIC_PIO); 203 src += 2; 204 } 205 else 206 outb(*(src++), eth_asic_base + ASIC_PIO); 207 } 208 209 #ifdef INCLUDE_3C503 210 outb(t503_output, eth_asic_base + _3COM_CR); 211 #else 212 #ifdef COMPEX_RL2000_FIX 213 for (x = 0; 214 x < COMPEX_RL2000_TRIES && 215 (inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC) 216 != D8390_ISR_RDC; 217 ++x); 218 if (x >= COMPEX_RL2000_TRIES) 219 printf("Warning: Compex RL2000 aborted wait!\n"); 220 #endif /* COMPEX_RL2000_FIX */ 221 #ifndef INCLUDE_WD 222 while((inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC) 223 != D8390_ISR_RDC); 224 #endif 225 #endif 226 } 227 #else 228 /************************************************************************** 229 ETH_PIO_READ - Dummy routine when NE2000 not compiled in 230 **************************************************************************/ 231 static void eth_pio_read(unsigned int src __unused, unsigned char *dst __unused, unsigned int cnt __unused) {} 232 #endif 233 234 235 /************************************************************************** 236 enable_multycast - Enable Multicast 237 **************************************************************************/ 238 static void enable_multicast(unsigned short eth_nic_base) 239 { 240 unsigned char mcfilter[8]; 241 int i; 242 memset(mcfilter, 0xFF, 8); 243 outb(4, eth_nic_base+D8390_P0_RCR); 244 outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS1, eth_nic_base + D8390_P0_COMMAND); 245 for(i=0;i<8;i++) 246 { 247 outb(mcfilter[i], eth_nic_base + 8 + i); 248 if(inb(eth_nic_base + 8 + i)!=mcfilter[i]) 249 printf("Error SMC 83C690 Multicast filter read/write mishap %d\n",i); 250 } 251 outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS0, eth_nic_base + D8390_P0_COMMAND); 252 outb(4 | 0x08, eth_nic_base+D8390_P0_RCR); 253 } 254 255 /************************************************************************** 256 NS8390_RESET - Reset adapter 257 **************************************************************************/ 258 static void ns8390_reset(struct nic *nic) 259 { 260 int i; 261 262 eth_drain_receiver = 0; 263 #ifdef INCLUDE_WD 264 if (eth_flags & FLAG_790) 265 outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND); 266 else 267 #endif 268 outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 | 269 D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND); 270 if (eth_flags & FLAG_16BIT) 271 outb(0x49, eth_nic_base+D8390_P0_DCR); 272 else 273 outb(0x48, eth_nic_base+D8390_P0_DCR); 274 outb(0, eth_nic_base+D8390_P0_RBCR0); 275 outb(0, eth_nic_base+D8390_P0_RBCR1); 276 outb(0x20, eth_nic_base+D8390_P0_RCR); /* monitor mode */ 277 outb(2, eth_nic_base+D8390_P0_TCR); 278 outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR); 279 outb(eth_rx_start, eth_nic_base+D8390_P0_PSTART); 280 #ifdef INCLUDE_WD 281 if (eth_flags & FLAG_790) { 282 #ifdef WD_790_PIO 283 outb(0x10, eth_asic_base + 0x06); /* disable interrupts, enable PIO */ 284 outb(0x01, eth_nic_base + 0x09); /* enable ring read auto-wrap */ 285 #else 286 outb(0, eth_nic_base + 0x09); 287 #endif 288 } 289 #endif 290 outb(eth_memsize, eth_nic_base+D8390_P0_PSTOP); 291 outb(eth_memsize - 1, eth_nic_base+D8390_P0_BOUND); 292 outb(0xFF, eth_nic_base+D8390_P0_ISR); 293 outb(0, eth_nic_base+D8390_P0_IMR); 294 #ifdef INCLUDE_WD 295 if (eth_flags & FLAG_790) 296 outb(D8390_COMMAND_PS1 | 297 D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND); 298 else 299 #endif 300 outb(D8390_COMMAND_PS1 | 301 D8390_COMMAND_RD2 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND); 302 for (i=0; i<ETH_ALEN; i++) 303 outb(nic->node_addr[i], eth_nic_base+D8390_P1_PAR0+i); 304 for (i=0; i<ETH_ALEN; i++) 305 outb(0xFF, eth_nic_base+D8390_P1_MAR0+i); 306 outb(eth_rx_start, eth_nic_base+D8390_P1_CURR); 307 #ifdef INCLUDE_WD 308 if (eth_flags & FLAG_790) 309 outb(D8390_COMMAND_PS0 | 310 D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND); 311 else 312 #endif 313 outb(D8390_COMMAND_PS0 | 314 D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND); 315 outb(0xFF, eth_nic_base+D8390_P0_ISR); 316 outb(0, eth_nic_base+D8390_P0_TCR); /* transmitter on */ 317 outb(4, eth_nic_base+D8390_P0_RCR); /* allow rx broadcast frames */ 318 319 enable_multicast(eth_nic_base); 320 321 #ifdef INCLUDE_3C503 322 /* 323 * No way to tell whether or not we're supposed to use 324 * the 3Com's transceiver unless the user tells us. 325 * 'flags' should have some compile time default value 326 * which can be changed from the command menu. 327 */ 328 t503_output = (nic->flags) ? 0 : _3COM_CR_XSEL; 329 outb(t503_output, eth_asic_base + _3COM_CR); 330 #endif 331 } 332 333 static int ns8390_poll(struct nic *nic, int retrieve); 334 335 #ifndef INCLUDE_3C503 336 /************************************************************************** 337 ETH_RX_OVERRUN - Bring adapter back to work after an RX overrun 338 **************************************************************************/ 339 static void eth_rx_overrun(struct nic *nic) 340 { 341 int start_time; 342 343 #ifdef INCLUDE_WD 344 if (eth_flags & FLAG_790) 345 outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND); 346 else 347 #endif 348 outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 | 349 D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND); 350 351 /* wait for at least 1.6ms - we wait one timer tick */ 352 start_time = currticks(); 353 while (currticks() - start_time <= 1) 354 /* Nothing */; 355 356 outb(0, eth_nic_base+D8390_P0_RBCR0); /* reset byte counter */ 357 outb(0, eth_nic_base+D8390_P0_RBCR1); 358 359 /* 360 * Linux driver checks for interrupted TX here. This is not necessary, 361 * because the transmit routine waits until the frame is sent. 362 */ 363 364 /* enter loopback mode and restart NIC */ 365 outb(2, eth_nic_base+D8390_P0_TCR); 366 #ifdef INCLUDE_WD 367 if (eth_flags & FLAG_790) 368 outb(D8390_COMMAND_PS0 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND); 369 else 370 #endif 371 outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 | 372 D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND); 373 374 /* clear the RX ring, acknowledge overrun interrupt */ 375 eth_drain_receiver = 1; 376 while (ns8390_poll(nic, 1)) 377 /* Nothing */; 378 eth_drain_receiver = 0; 379 outb(D8390_ISR_OVW, eth_nic_base+D8390_P0_ISR); 380 381 /* leave loopback mode - no packets to be resent (see Linux driver) */ 382 outb(0, eth_nic_base+D8390_P0_TCR); 383 } 384 #endif /* INCLUDE_3C503 */ 385 386 /************************************************************************** 387 NS8390_TRANSMIT - Transmit a frame 388 **************************************************************************/ 389 static void ns8390_transmit( 390 struct nic *nic, 391 const char *d, /* Destination */ 392 unsigned int t, /* Type */ 393 unsigned int s, /* size */ 394 const char *p) /* Packet */ 395 { 396 #if defined(INCLUDE_3C503) || (defined(INCLUDE_WD) && ! defined(WD_790_PIO)) 397 Address eth_vmem = bus_to_virt(eth_bmem); 398 #endif 399 #ifdef INCLUDE_3C503 400 if (!(eth_flags & FLAG_PIO)) { 401 memcpy((char *)eth_vmem, d, ETH_ALEN); /* dst */ 402 memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */ 403 *((char *)eth_vmem+12) = t>>8; /* type */ 404 *((char *)eth_vmem+13) = t; 405 memcpy((char *)eth_vmem+ETH_HLEN, p, s); 406 s += ETH_HLEN; 407 while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0; 408 } 409 #endif 410 411 #ifdef INCLUDE_WD 412 if (eth_flags & FLAG_16BIT) { 413 outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR); 414 inb(0x84); 415 } 416 #ifndef WD_790_PIO 417 /* Memory interface */ 418 if (eth_flags & FLAG_790) { 419 outb(WD_MSR_MENB, eth_asic_base + WD_MSR); 420 inb(0x84); 421 } 422 inb(0x84); 423 memcpy((char *)eth_vmem, d, ETH_ALEN); /* dst */ 424 memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */ 425 *((char *)eth_vmem+12) = t>>8; /* type */ 426 *((char *)eth_vmem+13) = t; 427 memcpy((char *)eth_vmem+ETH_HLEN, p, s); 428 s += ETH_HLEN; 429 while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0; 430 if (eth_flags & FLAG_790) { 431 outb(0, eth_asic_base + WD_MSR); 432 inb(0x84); 433 } 434 #else 435 inb(0x84); 436 #endif 437 #endif 438 439 #if defined(INCLUDE_3C503) 440 if (eth_flags & FLAG_PIO) 441 #endif 442 #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO)) 443 { 444 /* Programmed I/O */ 445 unsigned short type; 446 type = (t >> 8) | (t << 8); 447 eth_pio_write(d, eth_tx_start<<8, ETH_ALEN); 448 eth_pio_write(nic->node_addr, (eth_tx_start<<8)+ETH_ALEN, ETH_ALEN); 449 /* bcc generates worse code without (const+const) below */ 450 eth_pio_write((unsigned char *)&type, (eth_tx_start<<8)+(ETH_ALEN+ETH_ALEN), 2); 451 eth_pio_write(p, (eth_tx_start<<8)+ETH_HLEN, s); 452 s += ETH_HLEN; 453 if (s < ETH_ZLEN) s = ETH_ZLEN; 454 } 455 #endif 456 #if defined(INCLUDE_3C503) 457 #endif 458 459 #ifdef INCLUDE_WD 460 if (eth_flags & FLAG_16BIT) { 461 outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR); 462 inb(0x84); 463 } 464 if (eth_flags & FLAG_790) 465 outb(D8390_COMMAND_PS0 | 466 D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND); 467 else 468 #endif 469 outb(D8390_COMMAND_PS0 | 470 D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND); 471 outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR); 472 outb(s, eth_nic_base+D8390_P0_TBCR0); 473 outb(s>>8, eth_nic_base+D8390_P0_TBCR1); 474 #ifdef INCLUDE_WD 475 if (eth_flags & FLAG_790) 476 outb(D8390_COMMAND_PS0 | 477 D8390_COMMAND_TXP | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND); 478 else 479 #endif 480 outb(D8390_COMMAND_PS0 | 481 D8390_COMMAND_TXP | D8390_COMMAND_RD2 | 482 D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND); 483 } 484 485 /************************************************************************** 486 NS8390_POLL - Wait for a frame 487 **************************************************************************/ 488 static int ns8390_poll(struct nic *nic, int retrieve) 489 { 490 int ret = 0; 491 unsigned char rstat, curr, next; 492 unsigned short len, frag; 493 unsigned short pktoff; 494 unsigned char *p; 495 struct ringbuffer pkthdr; 496 497 #ifndef INCLUDE_3C503 498 /* avoid infinite recursion: see eth_rx_overrun() */ 499 if (!eth_drain_receiver && (inb(eth_nic_base+D8390_P0_ISR) & D8390_ISR_OVW)) { 500 eth_rx_overrun(nic); 501 return(0); 502 } 503 #endif /* INCLUDE_3C503 */ 504 rstat = inb(eth_nic_base+D8390_P0_RSR); 505 if (!(rstat & D8390_RSTAT_PRX)) return(0); 506 next = inb(eth_nic_base+D8390_P0_BOUND)+1; 507 if (next >= eth_memsize) next = eth_rx_start; 508 outb(D8390_COMMAND_PS1, eth_nic_base+D8390_P0_COMMAND); 509 curr = inb(eth_nic_base+D8390_P1_CURR); 510 outb(D8390_COMMAND_PS0, eth_nic_base+D8390_P0_COMMAND); 511 if (curr >= eth_memsize) curr=eth_rx_start; 512 if (curr == next) return(0); 513 514 if ( ! retrieve ) return 1; 515 516 #ifdef INCLUDE_WD 517 if (eth_flags & FLAG_16BIT) { 518 outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR); 519 inb(0x84); 520 } 521 #ifndef WD_790_PIO 522 if (eth_flags & FLAG_790) { 523 outb(WD_MSR_MENB, eth_asic_base + WD_MSR); 524 inb(0x84); 525 } 526 #endif 527 inb(0x84); 528 #endif 529 pktoff = next << 8; 530 if (eth_flags & FLAG_PIO) 531 eth_pio_read(pktoff, (char *)&pkthdr, 4); 532 else 533 memcpy(&pkthdr, bus_to_virt(eth_rmem + pktoff), 4); 534 pktoff += sizeof(pkthdr); 535 /* incoming length includes FCS so must sub 4 */ 536 len = pkthdr.len - 4; 537 if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || len < ETH_ZLEN 538 || len > ETH_FRAME_LEN) { 539 printf("Bogus packet, ignoring\n"); 540 return (0); 541 } 542 else { 543 p = nic->packet; 544 nic->packetlen = len; /* available to caller */ 545 frag = (eth_memsize << 8) - pktoff; 546 if (len > frag) { /* We have a wrap-around */ 547 /* read first part */ 548 if (eth_flags & FLAG_PIO) 549 eth_pio_read(pktoff, p, frag); 550 else 551 memcpy(p, bus_to_virt(eth_rmem + pktoff), frag); 552 pktoff = eth_rx_start << 8; 553 p += frag; 554 len -= frag; 555 } 556 /* read second part */ 557 if (eth_flags & FLAG_PIO) 558 eth_pio_read(pktoff, p, len); 559 else 560 memcpy(p, bus_to_virt(eth_rmem + pktoff), len); 561 ret = 1; 562 } 563 #ifdef INCLUDE_WD 564 #ifndef WD_790_PIO 565 if (eth_flags & FLAG_790) { 566 outb(0, eth_asic_base + WD_MSR); 567 inb(0x84); 568 } 569 #endif 570 if (eth_flags & FLAG_16BIT) { 571 outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR); 572 inb(0x84); 573 } 574 inb(0x84); 575 #endif 576 next = pkthdr.next; /* frame number of next packet */ 577 if (next == eth_rx_start) 578 next = eth_memsize; 579 outb(next-1, eth_nic_base+D8390_P0_BOUND); 580 return(ret); 581 } 582 583 /************************************************************************** 584 NS8390_DISABLE - Turn off adapter 585 **************************************************************************/ 586 static void ns8390_disable(struct dev *dev) 587 { 588 struct nic *nic = (struct nic *)dev; 589 /* reset and disable merge */ 590 ns8390_reset(nic); 591 } 592 593 /************************************************************************** 594 NS8390_IRQ - Enable, Disable, or Force interrupts 595 **************************************************************************/ 596 static void ns8390_irq(struct nic *nic __unused, irq_action_t action __unused) 597 { 598 switch ( action ) { 599 case DISABLE : 600 break; 601 case ENABLE : 602 break; 603 case FORCE : 604 break; 605 } 606 } 607 608 /************************************************************************** 609 ETH_PROBE - Look for an adapter 610 **************************************************************************/ 611 #ifdef INCLUDE_NS8390 612 static int eth_probe (struct dev *dev, struct pci_device *pci) 613 #else 614 static int eth_probe (struct dev *dev, unsigned short *probe_addrs __unused) 615 #endif 616 { 617 struct nic *nic = (struct nic *)dev; 618 int i; 619 #ifdef INCLUDE_NS8390 620 unsigned short pci_probe_addrs[] = { pci->ioaddr, 0 }; 621 unsigned short *probe_addrs = pci_probe_addrs; 622 #endif 623 eth_vendor = VENDOR_NONE; 624 eth_drain_receiver = 0; 625 626 nic->irqno = 0; 627 628 #ifdef INCLUDE_WD 629 { 630 /****************************************************************** 631 Search for WD/SMC cards 632 ******************************************************************/ 633 struct wd_board *brd; 634 unsigned short chksum; 635 unsigned char c; 636 for (eth_asic_base = WD_LOW_BASE; eth_asic_base <= WD_HIGH_BASE; 637 eth_asic_base += 0x20) { 638 chksum = 0; 639 for (i=8; i<16; i++) 640 chksum += inb(eth_asic_base+i); 641 /* Extra checks to avoid soundcard */ 642 if ((chksum & 0xFF) == 0xFF && 643 inb(eth_asic_base+8) != 0xFF && 644 inb(eth_asic_base+9) != 0xFF) 645 break; 646 } 647 if (eth_asic_base > WD_HIGH_BASE) 648 return (0); 649 /* We've found a board */ 650 eth_vendor = VENDOR_WD; 651 eth_nic_base = eth_asic_base + WD_NIC_ADDR; 652 653 nic->ioaddr = eth_nic_base; 654 655 c = inb(eth_asic_base+WD_BID); /* Get board id */ 656 for (brd = wd_boards; brd->name; brd++) 657 if (brd->id == c) break; 658 if (!brd->name) { 659 printf("Unknown WD/SMC NIC type %hhX\n", c); 660 return (0); /* Unknown type */ 661 } 662 eth_flags = brd->flags; 663 eth_memsize = brd->memsize; 664 eth_tx_start = 0; 665 eth_rx_start = D8390_TXBUF_SIZE; 666 if ((c == TYPE_WD8013EP) && 667 (inb(eth_asic_base + WD_ICR) & WD_ICR_16BIT)) { 668 eth_flags = FLAG_16BIT; 669 eth_memsize = MEM_16384; 670 } 671 if ((c & WD_SOFTCONFIG) && (!(eth_flags & FLAG_790))) { 672 eth_bmem = (0x80000 | 673 ((inb(eth_asic_base + WD_MSR) & 0x3F) << 13)); 674 } else 675 eth_bmem = WD_DEFAULT_MEM; 676 if (brd->id == TYPE_SMC8216T || brd->id == TYPE_SMC8216C) { 677 /* from Linux driver, 8416BT detects as 8216 sometimes */ 678 unsigned int addr = inb(eth_asic_base + 0xb); 679 if (((addr >> 4) & 3) == 0) { 680 brd += 2; 681 eth_memsize = brd->memsize; 682 } 683 } 684 outb(0x80, eth_asic_base + WD_MSR); /* Reset */ 685 for (i=0; i<ETH_ALEN; i++) { 686 nic->node_addr[i] = inb(i+eth_asic_base+WD_LAR); 687 } 688 printf("\n%s base %#hx", brd->name, eth_asic_base); 689 if (eth_flags & FLAG_790) { 690 #ifdef WD_790_PIO 691 printf(", PIO mode, addr %!\n", nic->node_addr); 692 eth_bmem = 0; 693 eth_flags |= FLAG_PIO; /* force PIO mode */ 694 outb(0, eth_asic_base+WD_MSR); 695 #else 696 printf(", memory %#x, addr %!\n", eth_bmem, nic->node_addr); 697 outb(WD_MSR_MENB, eth_asic_base+WD_MSR); 698 outb((inb(eth_asic_base+0x04) | 699 0x80), eth_asic_base+0x04); 700 outb(((unsigned)(eth_bmem >> 13) & 0x0F) | 701 ((unsigned)(eth_bmem >> 11) & 0x40) | 702 (inb(eth_asic_base+0x0B) & 0xB0), eth_asic_base+0x0B); 703 outb((inb(eth_asic_base+0x04) & 704 ~0x80), eth_asic_base+0x04); 705 #endif 706 } else { 707 printf(", memory %#x, addr %!\n", eth_bmem, nic->node_addr); 708 outb(((unsigned)(eth_bmem >> 13) & 0x3F) | 0x40, eth_asic_base+WD_MSR); 709 } 710 if (eth_flags & FLAG_16BIT) { 711 if (eth_flags & FLAG_790) { 712 eth_laar = inb(eth_asic_base + WD_LAAR); 713 outb(WD_LAAR_M16EN, eth_asic_base + WD_LAAR); 714 } else { 715 outb((eth_laar = 716 WD_LAAR_L16EN | 1), eth_asic_base + WD_LAAR); 717 /* 718 The previous line used to be 719 WD_LAAR_M16EN | WD_LAAR_L16EN | 1)); 720 jluke@deakin.edu.au reported that removing WD_LAAR_M16EN made 721 it work for WD8013s. This seems to work for my 8013 boards. I 722 don't know what is really happening. I wish I had data sheets 723 or more time to decode the Linux driver. - Ken 724 */ 725 } 726 inb(0x84); 727 } 728 } 729 #endif 730 #ifdef INCLUDE_3C503 731 #ifdef T503_AUI 732 nic->flags = 1; /* aui */ 733 #else 734 nic->flags = 0; /* no aui */ 735 #endif 736 /****************************************************************** 737 Search for 3Com 3c503 if no WD/SMC cards 738 ******************************************************************/ 739 if (eth_vendor == VENDOR_NONE) { 740 int idx; 741 int iobase_reg, membase_reg; 742 static unsigned short base[] = { 743 0x300, 0x310, 0x330, 0x350, 744 0x250, 0x280, 0x2A0, 0x2E0, 0 }; 745 746 /* Loop through possible addresses checking each one */ 747 748 for (idx = 0; (eth_nic_base = base[idx]) != 0; ++idx) { 749 750 eth_asic_base = eth_nic_base + _3COM_ASIC_OFFSET; 751 /* 752 * Note that we use the same settings for both 8 and 16 bit cards: 753 * both have an 8K bank of memory at page 1 while only the 16 bit 754 * cards have a bank at page 0. 755 */ 756 eth_memsize = MEM_16384; 757 eth_tx_start = 32; 758 eth_rx_start = 32 + D8390_TXBUF_SIZE; 759 760 /* Check our base address. iobase and membase should */ 761 /* both have a maximum of 1 bit set or be 0. */ 762 763 iobase_reg = inb(eth_asic_base + _3COM_BCFR); 764 membase_reg = inb(eth_asic_base + _3COM_PCFR); 765 766 if ((iobase_reg & (iobase_reg - 1)) || 767 (membase_reg & (membase_reg - 1))) 768 continue; /* nope */ 769 770 /* Now get the shared memory address */ 771 772 eth_flags = 0; 773 774 switch (membase_reg) { 775 case _3COM_PCFR_DC000: 776 eth_bmem = 0xdc000; 777 break; 778 case _3COM_PCFR_D8000: 779 eth_bmem = 0xd8000; 780 break; 781 case _3COM_PCFR_CC000: 782 eth_bmem = 0xcc000; 783 break; 784 case _3COM_PCFR_C8000: 785 eth_bmem = 0xc8000; 786 break; 787 case _3COM_PCFR_PIO: 788 eth_flags |= FLAG_PIO; 789 eth_bmem = 0; 790 break; 791 default: 792 continue; /* nope */ 793 } 794 break; 795 } 796 797 if (base[idx] == 0) /* not found */ 798 return (0); 799 #ifndef T503_SHMEM 800 eth_flags |= FLAG_PIO; /* force PIO mode */ 801 eth_bmem = 0; 802 #endif 803 eth_vendor = VENDOR_3COM; 804 805 806 /* Need this to make ns8390_poll() happy. */ 807 808 eth_rmem = eth_bmem - 0x2000; 809 810 /* Reset NIC and ASIC */ 811 812 outb(_3COM_CR_RST | _3COM_CR_XSEL, eth_asic_base + _3COM_CR ); 813 outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR ); 814 815 /* Get our ethernet address */ 816 817 outb(_3COM_CR_EALO | _3COM_CR_XSEL, eth_asic_base + _3COM_CR); 818 nic->ioaddr = eth_nic_base; 819 printf("\n3Com 3c503 base %#hx, ", eth_nic_base); 820 if (eth_flags & FLAG_PIO) 821 printf("PIO mode"); 822 else 823 printf("memory %#x", eth_bmem); 824 for (i=0; i<ETH_ALEN; i++) { 825 nic->node_addr[i] = inb(eth_nic_base+i); 826 } 827 printf(", %s, addr %!\n", nic->flags ? "AUI" : "internal xcvr", 828 nic->node_addr); 829 outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR); 830 /* 831 * Initialize GA configuration register. Set bank and enable shared 832 * mem. We always use bank 1. Disable interrupts. 833 */ 834 outb(_3COM_GACFR_RSEL | 835 _3COM_GACFR_MBS0 | _3COM_GACFR_TCM | _3COM_GACFR_NIM, eth_asic_base + _3COM_GACFR); 836 837 outb(0xff, eth_asic_base + _3COM_VPTR2); 838 outb(0xff, eth_asic_base + _3COM_VPTR1); 839 outb(0x00, eth_asic_base + _3COM_VPTR0); 840 /* 841 * Clear memory and verify that it worked (we use only 8K) 842 */ 843 844 if (!(eth_flags & FLAG_PIO)) { 845 memset(bus_to_virt(eth_bmem), 0, 0x2000); 846 for(i = 0; i < 0x2000; ++i) 847 if (*((char *)(bus_to_virt(eth_bmem+i)))) { 848 printf ("Failed to clear 3c503 shared mem.\n"); 849 return (0); 850 } 851 } 852 /* 853 * Initialize GA page/start/stop registers. 854 */ 855 outb(eth_tx_start, eth_asic_base + _3COM_PSTR); 856 outb(eth_memsize, eth_asic_base + _3COM_PSPR); 857 } 858 #endif 859 #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) 860 { 861 /****************************************************************** 862 Search for NE1000/2000 if no WD/SMC or 3com cards 863 ******************************************************************/ 864 unsigned char c; 865 if (eth_vendor == VENDOR_NONE) { 866 char romdata[16], testbuf[32]; 867 int idx; 868 static char test[] = "NE*000 memory"; 869 static unsigned short base[] = { 870 #ifdef NE_SCAN 871 NE_SCAN, 872 #endif 873 0 }; 874 /* if no addresses supplied, fall back on defaults */ 875 if (probe_addrs == 0 || probe_addrs[0] == 0) 876 probe_addrs = base; 877 eth_bmem = 0; /* No shared memory */ 878 for (idx = 0; (eth_nic_base = probe_addrs[idx]) != 0; ++idx) { 879 eth_flags = FLAG_PIO; 880 eth_asic_base = eth_nic_base + NE_ASIC_OFFSET; 881 eth_memsize = MEM_16384; 882 eth_tx_start = 32; 883 eth_rx_start = 32 + D8390_TXBUF_SIZE; 884 c = inb(eth_asic_base + NE_RESET); 885 outb(c, eth_asic_base + NE_RESET); 886 inb(0x84); 887 outb(D8390_COMMAND_STP | 888 D8390_COMMAND_RD2, eth_nic_base + D8390_P0_COMMAND); 889 outb(D8390_RCR_MON, eth_nic_base + D8390_P0_RCR); 890 outb(D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR); 891 outb(MEM_8192, eth_nic_base + D8390_P0_PSTART); 892 outb(MEM_16384, eth_nic_base + D8390_P0_PSTOP); 893 #ifdef NS8390_FORCE_16BIT 894 eth_flags |= FLAG_16BIT; /* force 16-bit mode */ 895 #endif 896 897 eth_pio_write(test, 8192, sizeof(test)); 898 eth_pio_read(8192, testbuf, sizeof(test)); 899 if (!memcmp(test, testbuf, sizeof(test))) 900 break; 901 eth_flags |= FLAG_16BIT; 902 eth_memsize = MEM_32768; 903 eth_tx_start = 64; 904 eth_rx_start = 64 + D8390_TXBUF_SIZE; 905 outb(D8390_DCR_WTS | 906 D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR); 907 outb(MEM_16384, eth_nic_base + D8390_P0_PSTART); 908 outb(MEM_32768, eth_nic_base + D8390_P0_PSTOP); 909 eth_pio_write(test, 16384, sizeof(test)); 910 eth_pio_read(16384, testbuf, sizeof(test)); 911 if (!memcmp(testbuf, test, sizeof(test))) 912 break; 913 } 914 if (eth_nic_base == 0) 915 return (0); 916 if (eth_nic_base > ISA_MAX_ADDR) /* PCI probably */ 917 eth_flags |= FLAG_16BIT; 918 eth_vendor = VENDOR_NOVELL; 919 eth_pio_read(0, romdata, sizeof(romdata)); 920 for (i=0; i<ETH_ALEN; i++) { 921 nic->node_addr[i] = romdata[i + ((eth_flags & FLAG_16BIT) ? i : 0)]; 922 } 923 nic->ioaddr = eth_nic_base; 924 printf("\nNE%c000 base %#hx, addr %!\n", 925 (eth_flags & FLAG_16BIT) ? '2' : '1', eth_nic_base, 926 nic->node_addr); 927 } 928 } 929 #endif 930 if (eth_vendor == VENDOR_NONE) 931 return(0); 932 if (eth_vendor != VENDOR_3COM) 933 eth_rmem = eth_bmem; 934 ns8390_reset(nic); 935 936 dev->disable = ns8390_disable; 937 nic->poll = ns8390_poll; 938 nic->transmit = ns8390_transmit; 939 nic->irq = ns8390_irq; 940 941 /* Based on PnP ISA map */ 942 #ifdef INCLUDE_WD 943 dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR); 944 dev->devid.device_id = htons(0x812a); 945 #endif 946 #ifdef INCLUDE_3C503 947 dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR); 948 dev->devid.device_id = htons(0x80f3); 949 #endif 950 #ifdef INCLUDE_NE 951 dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR); 952 dev->devid.device_id = htons(0x80d6); 953 #endif 954 return 1; 955 } 956 957 #ifdef INCLUDE_WD 958 static struct isa_driver wd_driver __isa_driver = { 959 .type = NIC_DRIVER, 960 .name = "WD", 961 .probe = wd_probe, 962 .ioaddrs = 0, 963 }; 964 #endif 965 966 #ifdef INCLUDE_3C503 967 static struct isa_driver t503_driver __isa_driver = { 968 .type = NIC_DRIVER, 969 .name = "3C503", 970 .probe = t503_probe, 971 .ioaddrs = 0, 972 }; 973 #endif 974 975 #ifdef INCLUDE_NE 976 static struct isa_driver ne_driver __isa_driver = { 977 .type = NIC_DRIVER, 978 .name = "NE*000", 979 .probe = ne_probe, 980 .ioaddrs = 0, 981 }; 982 #endif 983 984 #ifdef INCLUDE_NS8390 985 static struct pci_id nepci_nics[] = { 986 /* A few NE2000 PCI clones, list not exhaustive */ 987 PCI_ROM(0x10ec, 0x8029, "rtl8029", "Realtek 8029"), 988 PCI_ROM(0x1186, 0x0300, "dlink-528", "D-Link DE-528"), 989 PCI_ROM(0x1050, 0x0940, "winbond940", "Winbond NE2000-PCI"), /* Winbond 86C940 / 89C940 */ 990 PCI_ROM(0x1050, 0x5a5a, "winbond940f", "Winbond W89c940F"), /* Winbond 89C940F */ 991 PCI_ROM(0x11f6, 0x1401, "compexrl2000", "Compex ReadyLink 2000"), 992 PCI_ROM(0x8e2e, 0x3000, "ktiet32p2", "KTI ET32P2"), 993 PCI_ROM(0x4a14, 0x5000, "nv5000sc", "NetVin NV5000SC"), 994 PCI_ROM(0x12c3, 0x0058, "holtek80232", "Holtek HT80232"), 995 PCI_ROM(0x12c3, 0x5598, "holtek80229", "Holtek HT80229"), 996 PCI_ROM(0x10bd, 0x0e34, "surecom-ne34", "Surecom NE34"), 997 PCI_ROM(0x1106, 0x0926, "via86c926", "Via 86c926"), 998 }; 999 1000 struct pci_driver nepci_driver = { 1001 .type = NIC_DRIVER, 1002 .name = "NE2000/PCI", 1003 .probe = nepci_probe, 1004 .ids = nepci_nics, 1005 .id_count = sizeof(nepci_nics)/sizeof(nepci_nics[0]), 1006 .class = 0, 1007 }; 1008 1009 #endif /* INCLUDE_NS8390 */ 1010 1011 /* 1012 * Local variables: 1013 * c-basic-offset: 8 1014 * End: 1015 */ 1016 1017