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 (at) users.sourceforge.net) 09/28/2003 17 Relocation support added by Ken Yap (ken_yap (at) users.sourceforge.net) 28/12/02 18 3c503 support added by Bill Paul (wpaul (at) ctr.columbia.edu) on 11/15/94 19 SMC8416 support added by Bill Paul (wpaul (at) ctr.columbia.edu) on 12/25/94 20 3c503 PIO support added by Jim Hague (jim.hague (at) acm.org) on 2/17/98 21 RX overrun by Klaus Espenlaub (espenlaub (at) 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 (at) zip.com.au) on 4/3/02 24 based on the Linux 8390 driver (by Donald Becker and Paul Gortmaker) 25 26 **************************************************************************/ 27 28 FILE_LICENCE ( BSD2 ); 29 30 /* #warning "ns8390.c: FIXME: split ISA and PCI, clean up" */ 31 32 #if 1 33 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 39 #endif 40 41 #include "etherboot.h" 42 #include "nic.h" 43 #include "ns8390.h" 44 #include <gpxe/ethernet.h> 45 #ifdef INCLUDE_NS8390 46 #include <gpxe/pci.h> 47 #else 48 #include <gpxe/isa.h> 49 #endif 50 51 static unsigned char eth_vendor, eth_flags; 52 #ifdef INCLUDE_WD 53 static unsigned char eth_laar; 54 #endif 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; 59 60 #ifdef INCLUDE_WD 61 static struct wd_board { 62 const char *name; 63 char id; 64 char flags; 65 char memsize; 66 } wd_boards[] = { 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}, 73 {"WD8003EP/WD8013EP", 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}, 82 {NULL, 0, 0, 0} 83 }; 84 #endif 85 86 #ifdef INCLUDE_3C503 87 static unsigned char t503_output; /* AUI or internal xcvr (Thinnet) */ 88 #endif 89 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 95 #endif 96 #endif 97 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 102 #endif 103 #endif 104 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 109 #endif 110 #endif 111 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 116 #endif 117 #endif 118 119 #if defined(INCLUDE_3C503) 120 #define ASIC_PIO _3COM_RFMSB 121 #else 122 #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) 123 #define ASIC_PIO NE_DATA 124 #endif 125 #endif 126 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) 132 { 133 #ifdef INCLUDE_WD 134 outb(src & 0xff, eth_asic_base + WD_GP2); 135 outb(src >> 8, eth_asic_base + WD_GP2); 136 #else 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); 145 146 #ifdef INCLUDE_3C503 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); 150 #endif 151 #endif 152 153 if (eth_flags & FLAG_16BIT) 154 cnt = (cnt + 1) >> 1; 155 156 while(cnt--) { 157 #ifdef INCLUDE_3C503 158 while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0) 159 ; 160 #endif 161 162 if (eth_flags & FLAG_16BIT) { 163 *((unsigned short *)dst) = inw(eth_asic_base + ASIC_PIO); 164 dst += 2; 165 } 166 else 167 *(dst++) = inb(eth_asic_base + ASIC_PIO); 168 } 169 170 #ifdef INCLUDE_3C503 171 outb(t503_output, eth_asic_base + _3COM_CR); 172 #endif 173 } 174 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) 179 { 180 #ifdef COMPEX_RL2000_FIX 181 unsigned int x; 182 #endif /* COMPEX_RL2000_FIX */ 183 #ifdef INCLUDE_WD 184 outb(dst & 0xff, eth_asic_base + WD_GP2); 185 outb(dst >> 8, eth_asic_base + WD_GP2); 186 #else 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); 196 197 #ifdef INCLUDE_3C503 198 outb(dst & 0xff, eth_asic_base + _3COM_DALSB); 199 outb(dst >> 8, eth_asic_base + _3COM_DAMSB); 200 201 outb(t503_output | _3COM_CR_DDIR | _3COM_CR_START, eth_asic_base + _3COM_CR); 202 #endif 203 #endif 204 205 if (eth_flags & FLAG_16BIT) 206 cnt = (cnt + 1) >> 1; 207 208 while(cnt--) 209 { 210 #ifdef INCLUDE_3C503 211 while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0) 212 ; 213 #endif 214 215 if (eth_flags & FLAG_16BIT) { 216 outw(*((unsigned short *)src), eth_asic_base + ASIC_PIO); 217 src += 2; 218 } 219 else 220 outb(*(src++), eth_asic_base + ASIC_PIO); 221 } 222 223 #ifdef INCLUDE_3C503 224 outb(t503_output, eth_asic_base + _3COM_CR); 225 #else 226 #ifdef COMPEX_RL2000_FIX 227 for (x = 0; 228 x < COMPEX_RL2000_TRIES && 229 (inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC) 230 != D8390_ISR_RDC; 231 ++x); 232 if (x >= COMPEX_RL2000_TRIES) 233 printf("Warning: Compex RL2000 aborted wait!\n"); 234 #endif /* COMPEX_RL2000_FIX */ 235 #ifndef INCLUDE_WD 236 while((inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC) 237 != D8390_ISR_RDC); 238 #endif 239 #endif 240 } 241 #else 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) {} 246 #endif 247 248 249 /************************************************************************** 250 enable_multycast - Enable Multicast 251 **************************************************************************/ 252 static void enable_multicast(unsigned short eth_nic_base) 253 { 254 unsigned char mcfilter[8]; 255 int i; 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); 259 for(i=0;i<8;i++) 260 { 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); 264 } 265 outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS0, eth_nic_base + D8390_P0_COMMAND); 266 outb(4 | 0x08, eth_nic_base+D8390_P0_RCR); 267 } 268 269 /************************************************************************** 270 NS8390_RESET - Reset adapter 271 **************************************************************************/ 272 static void ns8390_reset(struct nic *nic) 273 { 274 int i; 275 276 eth_drain_receiver = 0; 277 #ifdef INCLUDE_WD 278 if (eth_flags & FLAG_790) 279 outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND); 280 else 281 #endif 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); 286 else 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); 294 #ifdef INCLUDE_WD 295 if (eth_flags & FLAG_790) { 296 #ifdef WD_790_PIO 297 outb(0x10, eth_asic_base + 0x06); /* disable interrupts, enable PIO */ 298 outb(0x01, eth_nic_base + 0x09); /* enable ring read auto-wrap */ 299 #else 300 outb(0, eth_nic_base + 0x09); 301 #endif 302 } 303 #endif 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); 308 #ifdef INCLUDE_WD 309 if (eth_flags & FLAG_790) 310 outb(D8390_COMMAND_PS1 | 311 D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND); 312 else 313 #endif 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); 321 #ifdef INCLUDE_WD 322 if (eth_flags & FLAG_790) 323 outb(D8390_COMMAND_PS0 | 324 D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND); 325 else 326 #endif 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 */ 332 333 enable_multicast(eth_nic_base); 334 335 #ifdef INCLUDE_3C503 336 /* 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. 341 */ 342 t503_output = (nic->flags) ? 0 : _3COM_CR_XSEL; 343 outb(t503_output, eth_asic_base + _3COM_CR); 344 #endif 345 } 346 347 static int ns8390_poll(struct nic *nic, int retrieve); 348 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) 354 { 355 int start_time; 356 357 #ifdef INCLUDE_WD 358 if (eth_flags & FLAG_790) 359 outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND); 360 else 361 #endif 362 outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 | 363 D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND); 364 365 /* wait for at least 1.6ms - we wait one timer tick */ 366 start_time = currticks(); 367 while (currticks() - start_time <= 1) 368 /* Nothing */; 369 370 outb(0, eth_nic_base+D8390_P0_RBCR0); /* reset byte counter */ 371 outb(0, eth_nic_base+D8390_P0_RBCR1); 372 373 /* 374 * Linux driver checks for interrupted TX here. This is not necessary, 375 * because the transmit routine waits until the frame is sent. 376 */ 377 378 /* enter loopback mode and restart NIC */ 379 outb(2, eth_nic_base+D8390_P0_TCR); 380 #ifdef INCLUDE_WD 381 if (eth_flags & FLAG_790) 382 outb(D8390_COMMAND_PS0 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND); 383 else 384 #endif 385 outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 | 386 D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND); 387 388 /* clear the RX ring, acknowledge overrun interrupt */ 389 eth_drain_receiver = 1; 390 while (ns8390_poll(nic, 1)) 391 /* Nothing */; 392 eth_drain_receiver = 0; 393 outb(D8390_ISR_OVW, eth_nic_base+D8390_P0_ISR); 394 395 /* leave loopback mode - no packets to be resent (see Linux driver) */ 396 outb(0, eth_nic_base+D8390_P0_TCR); 397 } 398 #endif /* INCLUDE_3C503 */ 399 400 /************************************************************************** 401 NS8390_TRANSMIT - Transmit a frame 402 **************************************************************************/ 403 static void ns8390_transmit( 404 struct nic *nic, 405 const char *d, /* Destination */ 406 unsigned int t, /* Type */ 407 unsigned int s, /* size */ 408 const char *p) /* Packet */ 409 { 410 #if defined(INCLUDE_3C503) || (defined(INCLUDE_WD) && ! defined(WD_790_PIO)) 411 Address eth_vmem = bus_to_virt(eth_bmem); 412 #endif 413 #ifdef INCLUDE_3C503 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); 420 s += ETH_HLEN; 421 while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0; 422 } 423 #endif 424 425 #ifdef INCLUDE_WD 426 if (eth_flags & FLAG_16BIT) { 427 outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR); 428 inb(0x84); 429 } 430 #ifndef WD_790_PIO 431 /* Memory interface */ 432 if (eth_flags & FLAG_790) { 433 outb(WD_MSR_MENB, eth_asic_base + WD_MSR); 434 inb(0x84); 435 } 436 inb(0x84); 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); 442 s += ETH_HLEN; 443 while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0; 444 if (eth_flags & FLAG_790) { 445 outb(0, eth_asic_base + WD_MSR); 446 inb(0x84); 447 } 448 #else 449 inb(0x84); 450 #endif 451 #endif 452 453 #if defined(INCLUDE_3C503) 454 if (eth_flags & FLAG_PIO) 455 #endif 456 #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO)) 457 { 458 /* Programmed I/O */ 459 unsigned short type; 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); 466 s += ETH_HLEN; 467 if (s < ETH_ZLEN) s = ETH_ZLEN; 468 } 469 #endif 470 #if defined(INCLUDE_3C503) 471 #endif 472 473 #ifdef INCLUDE_WD 474 if (eth_flags & FLAG_16BIT) { 475 outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR); 476 inb(0x84); 477 } 478 if (eth_flags & FLAG_790) 479 outb(D8390_COMMAND_PS0 | 480 D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND); 481 else 482 #endif 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); 488 #ifdef INCLUDE_WD 489 if (eth_flags & FLAG_790) 490 outb(D8390_COMMAND_PS0 | 491 D8390_COMMAND_TXP | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND); 492 else 493 #endif 494 outb(D8390_COMMAND_PS0 | 495 D8390_COMMAND_TXP | D8390_COMMAND_RD2 | 496 D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND); 497 } 498 499 /************************************************************************** 500 NS8390_POLL - Wait for a frame 501 **************************************************************************/ 502 static int ns8390_poll(struct nic *nic, int retrieve) 503 { 504 int ret = 0; 505 unsigned char rstat, curr, next; 506 unsigned short len, frag; 507 unsigned short pktoff; 508 unsigned char *p; 509 struct ringbuffer pkthdr; 510 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)) { 514 eth_rx_overrun(nic); 515 return(0); 516 } 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); 527 528 if ( ! retrieve ) return 1; 529 530 #ifdef INCLUDE_WD 531 if (eth_flags & FLAG_16BIT) { 532 outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR); 533 inb(0x84); 534 } 535 #ifndef WD_790_PIO 536 if (eth_flags & FLAG_790) { 537 outb(WD_MSR_MENB, eth_asic_base + WD_MSR); 538 inb(0x84); 539 } 540 #endif 541 inb(0x84); 542 #endif 543 pktoff = next << 8; 544 if (eth_flags & FLAG_PIO) 545 eth_pio_read(pktoff, (unsigned char *)&pkthdr, 4); 546 else 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"); 554 return (0); 555 } 556 else { 557 p = nic->packet; 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); 564 else 565 memcpy(p, bus_to_virt(eth_rmem + pktoff), frag); 566 pktoff = eth_rx_start << 8; 567 p += frag; 568 len -= frag; 569 } 570 /* read second part */ 571 if (eth_flags & FLAG_PIO) 572 eth_pio_read(pktoff, p, len); 573 else 574 memcpy(p, bus_to_virt(eth_rmem + pktoff), len); 575 ret = 1; 576 } 577 #ifdef INCLUDE_WD 578 #ifndef WD_790_PIO 579 if (eth_flags & FLAG_790) { 580 outb(0, eth_asic_base + WD_MSR); 581 inb(0x84); 582 } 583 #endif 584 if (eth_flags & FLAG_16BIT) { 585 outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR); 586 inb(0x84); 587 } 588 inb(0x84); 589 #endif 590 next = pkthdr.next; /* frame number of next packet */ 591 if (next == eth_rx_start) 592 next = eth_memsize; 593 outb(next-1, eth_nic_base+D8390_P0_BOUND); 594 return(ret); 595 } 596 597 /************************************************************************** 598 NS8390_DISABLE - Turn off adapter 599 **************************************************************************/ 600 static void ns8390_disable ( struct nic *nic ) { 601 ns8390_reset(nic); 602 } 603 604 /************************************************************************** 605 NS8390_IRQ - Enable, Disable, or Force interrupts 606 **************************************************************************/ 607 static void ns8390_irq(struct nic *nic __unused, irq_action_t action __unused) 608 { 609 switch ( action ) { 610 case DISABLE : 611 break; 612 case ENABLE : 613 break; 614 case FORCE : 615 break; 616 } 617 } 618 619 static struct nic_operations ns8390_operations; 620 static struct nic_operations ns8390_operations = { 621 .connect = dummy_connect, 622 .poll = ns8390_poll, 623 .transmit = ns8390_transmit, 624 .irq = ns8390_irq, 625 }; 626 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) 632 #else 633 static int eth_probe (struct dev *dev, unsigned short *probe_addrs __unused) 634 #endif 635 { 636 int i; 637 #ifdef INCLUDE_NS8390 638 unsigned short pci_probe_addrs[] = { pci->ioaddr, 0 }; 639 unsigned short *probe_addrs = pci_probe_addrs; 640 #endif 641 eth_vendor = VENDOR_NONE; 642 eth_drain_receiver = 0; 643 644 nic->irqno = 0; 645 646 #ifdef INCLUDE_WD 647 { 648 /****************************************************************** 649 Search for WD/SMC cards 650 ******************************************************************/ 651 struct wd_board *brd; 652 unsigned short chksum; 653 unsigned char c; 654 for (eth_asic_base = WD_LOW_BASE; eth_asic_base <= WD_HIGH_BASE; 655 eth_asic_base += 0x20) { 656 chksum = 0; 657 for (i=8; i<16; i++) 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) 663 break; 664 } 665 if (eth_asic_base > WD_HIGH_BASE) 666 return (0); 667 /* We've found a board */ 668 eth_vendor = VENDOR_WD; 669 eth_nic_base = eth_asic_base + WD_NIC_ADDR; 670 671 nic->ioaddr = eth_nic_base; 672 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; 676 if (!brd->name) { 677 printf("Unknown WD/SMC NIC type %hhX\n", c); 678 return (0); /* Unknown type */ 679 } 680 eth_flags = brd->flags; 681 eth_memsize = brd->memsize; 682 eth_tx_start = 0; 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; 688 } 689 if ((c & WD_SOFTCONFIG) && (!(eth_flags & FLAG_790))) { 690 eth_bmem = (0x80000 | 691 ((inb(eth_asic_base + WD_MSR) & 0x3F) << 13)); 692 } else 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) { 698 brd += 2; 699 eth_memsize = brd->memsize; 700 } 701 } 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); 705 } 706 DBG ( "\n%s base %4.4x", brd->name, eth_asic_base ); 707 if (eth_flags & FLAG_790) { 708 #ifdef WD_790_PIO 709 DBG ( ", PIO mode, addr %s\n", eth_ntoa ( nic->node_addr ) ); 710 eth_bmem = 0; 711 eth_flags |= FLAG_PIO; /* force PIO mode */ 712 outb(0, eth_asic_base+WD_MSR); 713 #else 714 DBG ( ", Memory %x, MAC Addr %s\n", eth_bmem, eth_ntoa ( nic->node_addr) ); 715 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); 724 #endif 725 } else { 726 727 DBG (", Memory %x, MAC Addr %s\n", eth_bmem, eth_ntoa ( nic->node_addr) ); 728 729 outb(((unsigned)(eth_bmem >> 13) & 0x3F) | 0x40, eth_asic_base+WD_MSR); 730 } 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); 735 } else { 736 outb((eth_laar = 737 WD_LAAR_L16EN | 1), eth_asic_base + WD_LAAR); 738 /* 739 The previous line used to be 740 WD_LAAR_M16EN | WD_LAAR_L16EN | 1)); 741 jluke (at) 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 745 */ 746 } 747 inb(0x84); 748 } 749 } 750 #endif 751 #ifdef INCLUDE_3C503 752 #ifdef T503_AUI 753 nic->flags = 1; /* aui */ 754 #else 755 nic->flags = 0; /* no aui */ 756 #endif 757 /****************************************************************** 758 Search for 3Com 3c503 if no WD/SMC cards 759 ******************************************************************/ 760 if (eth_vendor == VENDOR_NONE) { 761 int idx; 762 int iobase_reg, membase_reg; 763 static unsigned short base[] = { 764 0x300, 0x310, 0x330, 0x350, 765 0x250, 0x280, 0x2A0, 0x2E0, 0 }; 766 767 /* Loop through possible addresses checking each one */ 768 769 for (idx = 0; (eth_nic_base = base[idx]) != 0; ++idx) { 770 771 eth_asic_base = eth_nic_base + _3COM_ASIC_OFFSET; 772 /* 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. 776 */ 777 eth_memsize = MEM_16384; 778 eth_tx_start = 32; 779 eth_rx_start = 32 + D8390_TXBUF_SIZE; 780 781 /* Check our base address. iobase and membase should */ 782 /* both have a maximum of 1 bit set or be 0. */ 783 784 iobase_reg = inb(eth_asic_base + _3COM_BCFR); 785 membase_reg = inb(eth_asic_base + _3COM_PCFR); 786 787 if ((iobase_reg & (iobase_reg - 1)) || 788 (membase_reg & (membase_reg - 1))) 789 continue; /* nope */ 790 791 /* Now get the shared memory address */ 792 793 eth_flags = 0; 794 795 switch (membase_reg) { 796 case _3COM_PCFR_DC000: 797 eth_bmem = 0xdc000; 798 break; 799 case _3COM_PCFR_D8000: 800 eth_bmem = 0xd8000; 801 break; 802 case _3COM_PCFR_CC000: 803 eth_bmem = 0xcc000; 804 break; 805 case _3COM_PCFR_C8000: 806 eth_bmem = 0xc8000; 807 break; 808 case _3COM_PCFR_PIO: 809 eth_flags |= FLAG_PIO; 810 eth_bmem = 0; 811 break; 812 default: 813 continue; /* nope */ 814 } 815 break; 816 } 817 818 if (base[idx] == 0) /* not found */ 819 return (0); 820 #ifndef T503_SHMEM 821 eth_flags |= FLAG_PIO; /* force PIO mode */ 822 eth_bmem = 0; 823 #endif 824 eth_vendor = VENDOR_3COM; 825 826 827 /* Need this to make ns8390_poll() happy. */ 828 829 eth_rmem = eth_bmem - 0x2000; 830 831 /* Reset NIC and ASIC */ 832 833 outb(_3COM_CR_RST | _3COM_CR_XSEL, eth_asic_base + _3COM_CR ); 834 outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR ); 835 836 /* Get our ethernet address */ 837 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) 842 DBG ( "PIO mode" ); 843 else 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); 847 } 848 DBG ( ", %s, MAC Addr %s\n", nic->flags ? "AUI" : "internal xcvr", 849 eth_ntoa ( nic->node_addr ) ); 850 851 outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR); 852 /* 853 * Initialize GA configuration register. Set bank and enable shared 854 * mem. We always use bank 1. Disable interrupts. 855 */ 856 outb(_3COM_GACFR_RSEL | 857 _3COM_GACFR_MBS0 | _3COM_GACFR_TCM | _3COM_GACFR_NIM, eth_asic_base + _3COM_GACFR); 858 859 outb(0xff, eth_asic_base + _3COM_VPTR2); 860 outb(0xff, eth_asic_base + _3COM_VPTR1); 861 outb(0x00, eth_asic_base + _3COM_VPTR0); 862 /* 863 * Clear memory and verify that it worked (we use only 8K) 864 */ 865 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"); 871 return (0); 872 } 873 } 874 /* 875 * Initialize GA page/start/stop registers. 876 */ 877 outb(eth_tx_start, eth_asic_base + _3COM_PSTR); 878 outb(eth_memsize, eth_asic_base + _3COM_PSPR); 879 } 880 #endif 881 #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) 882 { 883 /****************************************************************** 884 Search for NE1000/2000 if no WD/SMC or 3com cards 885 ******************************************************************/ 886 unsigned char c; 887 if (eth_vendor == VENDOR_NONE) { 888 unsigned char romdata[16]; 889 unsigned char testbuf[32]; 890 int idx; 891 static unsigned char test[] = "NE*000 memory"; 892 static unsigned short base[] = { 893 #ifdef NE_SCAN 894 NE_SCAN, 895 #endif 896 0 }; 897 /* if no addresses supplied, fall back on defaults */ 898 if (probe_addrs == 0 || probe_addrs[0] == 0) 899 probe_addrs = base; 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; 905 eth_tx_start = 32; 906 eth_rx_start = 32 + D8390_TXBUF_SIZE; 907 c = inb(eth_asic_base + NE_RESET); 908 outb(c, eth_asic_base + NE_RESET); 909 (void) inb(0x84); 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 */ 918 #endif 919 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))) 923 break; 924 eth_flags |= FLAG_16BIT; 925 eth_memsize = MEM_32768; 926 eth_tx_start = 64; 927 eth_rx_start = 64 + D8390_TXBUF_SIZE; 928 outb(D8390_DCR_WTS | 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))) 935 break; 936 } 937 if (eth_nic_base == 0) 938 return (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)]; 945 } 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 ) ); 950 } 951 } 952 #endif 953 if (eth_vendor == VENDOR_NONE) 954 return(0); 955 if (eth_vendor != VENDOR_3COM) 956 eth_rmem = eth_bmem; 957 ns8390_reset(nic); 958 nic->nic_op = &ns8390_operations; 959 960 /* Based on PnP ISA map */ 961 #ifdef INCLUDE_WD 962 dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR); 963 dev->devid.device_id = htons(0x812a); 964 #endif 965 #ifdef INCLUDE_3C503 966 dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR); 967 dev->devid.device_id = htons(0x80f3); 968 #endif 969 #ifdef INCLUDE_NE 970 dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR); 971 dev->devid.device_id = htons(0x80d6); 972 #endif 973 return 1; 974 } 975 976 #ifdef INCLUDE_WD 977 struct isa_driver wd_driver __isa_driver = { 978 .type = NIC_DRIVER, 979 .name = "WD", 980 .probe = wd_probe, 981 .ioaddrs = 0, 982 }; 983 ISA_ROM("wd","WD8003/8013, SMC8216/8416, SMC 83c790 (EtherEZ)"); 984 #endif 985 986 #ifdef INCLUDE_3C503 987 struct isa_driver t503_driver __isa_driver = { 988 .type = NIC_DRIVER, 989 .name = "3C503", 990 .probe = t503_probe, 991 .ioaddrs = 0, 992 }; 993 ISA_ROM("3c503","3Com503, Etherlink II[/16]"); 994 #endif 995 996 #ifdef INCLUDE_NE 997 struct isa_driver ne_driver __isa_driver = { 998 .type = NIC_DRIVER, 999 .name = "NE*000", 1000 .probe = ne_probe, 1001 .ioaddrs = 0, 1002 }; 1003 ISA_ROM("ne","NE1000/2000 and clones"); 1004 #endif 1005 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), 1020 }; 1021 1022 PCI_DRIVER ( nepci_driver, nepci_nics, PCI_NO_CLASS ); 1023 1024 DRIVER ( "NE2000/PCI", nic_driver, pci_driver, nepci_driver, 1025 nepci_probe, ns8390_disable ); 1026 1027 #endif /* INCLUDE_NS8390 */ 1028 1029 #endif 1030 1031 /* 1032 * Local variables: 1033 * c-basic-offset: 8 1034 * c-indent-level: 8 1035 * tab-width: 8 1036 * End: 1037 */ 1038