00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 FILE_LICENCE ( BSD2 );
00029
00030
00031
00032 #if 1
00033
00034 #if !defined(INCLUDE_NS8390) && !defined(INCLUDE_WD) && \
00035 !defined(INCLUDE_NE) && !defined(INCLUDE_3C503)
00036
00037
00038 # define INCLUDE_NS8390 1
00039 #endif
00040
00041 #include "etherboot.h"
00042 #include "nic.h"
00043 #include "ns8390.h"
00044 #include <gpxe/ethernet.h>
00045 #ifdef INCLUDE_NS8390
00046 #include <gpxe/pci.h>
00047 #else
00048 #include <gpxe/isa.h>
00049 #endif
00050
00051 static unsigned char eth_vendor, eth_flags;
00052 #ifdef INCLUDE_WD
00053 static unsigned char eth_laar;
00054 #endif
00055 static unsigned short eth_nic_base, eth_asic_base;
00056 static unsigned char eth_memsize, eth_rx_start, eth_tx_start;
00057 static Address eth_bmem, eth_rmem;
00058 static unsigned char eth_drain_receiver;
00059
00060 #ifdef INCLUDE_WD
00061 static struct wd_board {
00062 const char *name;
00063 char id;
00064 char flags;
00065 char memsize;
00066 } wd_boards[] = {
00067 {"WD8003S", TYPE_WD8003S, 0, MEM_8192},
00068 {"WD8003E", TYPE_WD8003E, 0, MEM_8192},
00069 {"WD8013EBT", TYPE_WD8013EBT, FLAG_16BIT, MEM_16384},
00070 {"WD8003W", TYPE_WD8003W, 0, MEM_8192},
00071 {"WD8003EB", TYPE_WD8003EB, 0, MEM_8192},
00072 {"WD8013W", TYPE_WD8013W, FLAG_16BIT, MEM_16384},
00073 {"WD8003EP/WD8013EP",
00074 TYPE_WD8013EP, 0, MEM_8192},
00075 {"WD8013WC", TYPE_WD8013WC, FLAG_16BIT, MEM_16384},
00076 {"WD8013EPC", TYPE_WD8013EPC, FLAG_16BIT, MEM_16384},
00077 {"SMC8216T", TYPE_SMC8216T, FLAG_16BIT | FLAG_790, MEM_16384},
00078 {"SMC8216C", TYPE_SMC8216C, FLAG_16BIT | FLAG_790, MEM_16384},
00079 {"SMC8416T", TYPE_SMC8416T, FLAG_16BIT | FLAG_790, MEM_8192},
00080 {"SMC8416C/BT", TYPE_SMC8416C, FLAG_16BIT | FLAG_790, MEM_8192},
00081 {"SMC8013EBP", TYPE_SMC8013EBP,FLAG_16BIT, MEM_16384},
00082 {NULL, 0, 0, 0}
00083 };
00084 #endif
00085
00086 #ifdef INCLUDE_3C503
00087 static unsigned char t503_output;
00088 #endif
00089
00090 #if defined(INCLUDE_WD)
00091 #define ASIC_PIO WD_IAR
00092 #define eth_probe wd_probe
00093 #if defined(INCLUDE_3C503) || defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
00094 Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
00095 #endif
00096 #endif
00097
00098 #if defined(INCLUDE_3C503)
00099 #define eth_probe t503_probe
00100 #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || defined(INCLUDE_WD)
00101 Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
00102 #endif
00103 #endif
00104
00105 #if defined(INCLUDE_NE)
00106 #define eth_probe ne_probe
00107 #if defined(INCLUDE_NS8390) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
00108 Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
00109 #endif
00110 #endif
00111
00112 #if defined(INCLUDE_NS8390)
00113 #define eth_probe nepci_probe
00114 #if defined(INCLUDE_NE) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
00115 Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
00116 #endif
00117 #endif
00118
00119 #if defined(INCLUDE_3C503)
00120 #define ASIC_PIO _3COM_RFMSB
00121 #else
00122 #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
00123 #define ASIC_PIO NE_DATA
00124 #endif
00125 #endif
00126
00127 #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO))
00128
00129
00130
00131 static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt)
00132 {
00133 #ifdef INCLUDE_WD
00134 outb(src & 0xff, eth_asic_base + WD_GP2);
00135 outb(src >> 8, eth_asic_base + WD_GP2);
00136 #else
00137 outb(D8390_COMMAND_RD2 |
00138 D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
00139 outb(cnt, eth_nic_base + D8390_P0_RBCR0);
00140 outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1);
00141 outb(src, eth_nic_base + D8390_P0_RSAR0);
00142 outb(src>>8, eth_nic_base + D8390_P0_RSAR1);
00143 outb(D8390_COMMAND_RD0 |
00144 D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
00145
00146 #ifdef INCLUDE_3C503
00147 outb(src & 0xff, eth_asic_base + _3COM_DALSB);
00148 outb(src >> 8, eth_asic_base + _3COM_DAMSB);
00149 outb(t503_output | _3COM_CR_START, eth_asic_base + _3COM_CR);
00150 #endif
00151 #endif
00152
00153 if (eth_flags & FLAG_16BIT)
00154 cnt = (cnt + 1) >> 1;
00155
00156 while(cnt--) {
00157 #ifdef INCLUDE_3C503
00158 while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
00159 ;
00160 #endif
00161
00162 if (eth_flags & FLAG_16BIT) {
00163 *((unsigned short *)dst) = inw(eth_asic_base + ASIC_PIO);
00164 dst += 2;
00165 }
00166 else
00167 *(dst++) = inb(eth_asic_base + ASIC_PIO);
00168 }
00169
00170 #ifdef INCLUDE_3C503
00171 outb(t503_output, eth_asic_base + _3COM_CR);
00172 #endif
00173 }
00174
00175
00176
00177
00178 static void eth_pio_write(const unsigned char *src, unsigned int dst, unsigned int cnt)
00179 {
00180 #ifdef COMPEX_RL2000_FIX
00181 unsigned int x;
00182 #endif
00183 #ifdef INCLUDE_WD
00184 outb(dst & 0xff, eth_asic_base + WD_GP2);
00185 outb(dst >> 8, eth_asic_base + WD_GP2);
00186 #else
00187 outb(D8390_COMMAND_RD2 |
00188 D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
00189 outb(D8390_ISR_RDC, eth_nic_base + D8390_P0_ISR);
00190 outb(cnt, eth_nic_base + D8390_P0_RBCR0);
00191 outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1);
00192 outb(dst, eth_nic_base + D8390_P0_RSAR0);
00193 outb(dst>>8, eth_nic_base + D8390_P0_RSAR1);
00194 outb(D8390_COMMAND_RD1 |
00195 D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
00196
00197 #ifdef INCLUDE_3C503
00198 outb(dst & 0xff, eth_asic_base + _3COM_DALSB);
00199 outb(dst >> 8, eth_asic_base + _3COM_DAMSB);
00200
00201 outb(t503_output | _3COM_CR_DDIR | _3COM_CR_START, eth_asic_base + _3COM_CR);
00202 #endif
00203 #endif
00204
00205 if (eth_flags & FLAG_16BIT)
00206 cnt = (cnt + 1) >> 1;
00207
00208 while(cnt--)
00209 {
00210 #ifdef INCLUDE_3C503
00211 while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
00212 ;
00213 #endif
00214
00215 if (eth_flags & FLAG_16BIT) {
00216 outw(*((unsigned short *)src), eth_asic_base + ASIC_PIO);
00217 src += 2;
00218 }
00219 else
00220 outb(*(src++), eth_asic_base + ASIC_PIO);
00221 }
00222
00223 #ifdef INCLUDE_3C503
00224 outb(t503_output, eth_asic_base + _3COM_CR);
00225 #else
00226 #ifdef COMPEX_RL2000_FIX
00227 for (x = 0;
00228 x < COMPEX_RL2000_TRIES &&
00229 (inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
00230 != D8390_ISR_RDC;
00231 ++x);
00232 if (x >= COMPEX_RL2000_TRIES)
00233 printf("Warning: Compex RL2000 aborted wait!\n");
00234 #endif
00235 #ifndef INCLUDE_WD
00236 while((inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
00237 != D8390_ISR_RDC);
00238 #endif
00239 #endif
00240 }
00241 #else
00242
00243
00244
00245 static void eth_pio_read(unsigned int src __unused, unsigned char *dst __unused, unsigned int cnt __unused) {}
00246 #endif
00247
00248
00249
00250
00251
00252 static void enable_multicast(unsigned short eth_nic_base)
00253 {
00254 unsigned char mcfilter[8];
00255 int i;
00256 memset(mcfilter, 0xFF, 8);
00257 outb(4, eth_nic_base+D8390_P0_RCR);
00258 outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS1, eth_nic_base + D8390_P0_COMMAND);
00259 for(i=0;i<8;i++)
00260 {
00261 outb(mcfilter[i], eth_nic_base + 8 + i);
00262 if(inb(eth_nic_base + 8 + i)!=mcfilter[i])
00263 printf("Error SMC 83C690 Multicast filter read/write mishap %d\n",i);
00264 }
00265 outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS0, eth_nic_base + D8390_P0_COMMAND);
00266 outb(4 | 0x08, eth_nic_base+D8390_P0_RCR);
00267 }
00268
00269
00270
00271
00272 static void ns8390_reset(struct nic *nic)
00273 {
00274 int i;
00275
00276 eth_drain_receiver = 0;
00277 #ifdef INCLUDE_WD
00278 if (eth_flags & FLAG_790)
00279 outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
00280 else
00281 #endif
00282 outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
00283 D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
00284 if (eth_flags & FLAG_16BIT)
00285 outb(0x49, eth_nic_base+D8390_P0_DCR);
00286 else
00287 outb(0x48, eth_nic_base+D8390_P0_DCR);
00288 outb(0, eth_nic_base+D8390_P0_RBCR0);
00289 outb(0, eth_nic_base+D8390_P0_RBCR1);
00290 outb(0x20, eth_nic_base+D8390_P0_RCR);
00291 outb(2, eth_nic_base+D8390_P0_TCR);
00292 outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
00293 outb(eth_rx_start, eth_nic_base+D8390_P0_PSTART);
00294 #ifdef INCLUDE_WD
00295 if (eth_flags & FLAG_790) {
00296 #ifdef WD_790_PIO
00297 outb(0x10, eth_asic_base + 0x06);
00298 outb(0x01, eth_nic_base + 0x09);
00299 #else
00300 outb(0, eth_nic_base + 0x09);
00301 #endif
00302 }
00303 #endif
00304 outb(eth_memsize, eth_nic_base+D8390_P0_PSTOP);
00305 outb(eth_memsize - 1, eth_nic_base+D8390_P0_BOUND);
00306 outb(0xFF, eth_nic_base+D8390_P0_ISR);
00307 outb(0, eth_nic_base+D8390_P0_IMR);
00308 #ifdef INCLUDE_WD
00309 if (eth_flags & FLAG_790)
00310 outb(D8390_COMMAND_PS1 |
00311 D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
00312 else
00313 #endif
00314 outb(D8390_COMMAND_PS1 |
00315 D8390_COMMAND_RD2 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
00316 for (i=0; i<ETH_ALEN; i++)
00317 outb(nic->node_addr[i], eth_nic_base+D8390_P1_PAR0+i);
00318 for (i=0; i<ETH_ALEN; i++)
00319 outb(0xFF, eth_nic_base+D8390_P1_MAR0+i);
00320 outb(eth_rx_start, eth_nic_base+D8390_P1_CURR);
00321 #ifdef INCLUDE_WD
00322 if (eth_flags & FLAG_790)
00323 outb(D8390_COMMAND_PS0 |
00324 D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
00325 else
00326 #endif
00327 outb(D8390_COMMAND_PS0 |
00328 D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
00329 outb(0xFF, eth_nic_base+D8390_P0_ISR);
00330 outb(0, eth_nic_base+D8390_P0_TCR);
00331 outb(4, eth_nic_base+D8390_P0_RCR);
00332
00333 enable_multicast(eth_nic_base);
00334
00335 #ifdef INCLUDE_3C503
00336
00337
00338
00339
00340
00341
00342 t503_output = (nic->flags) ? 0 : _3COM_CR_XSEL;
00343 outb(t503_output, eth_asic_base + _3COM_CR);
00344 #endif
00345 }
00346
00347 static int ns8390_poll(struct nic *nic, int retrieve);
00348
00349 #ifndef INCLUDE_3C503
00350
00351
00352
00353 static void eth_rx_overrun(struct nic *nic)
00354 {
00355 int start_time;
00356
00357 #ifdef INCLUDE_WD
00358 if (eth_flags & FLAG_790)
00359 outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
00360 else
00361 #endif
00362 outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
00363 D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
00364
00365
00366 start_time = currticks();
00367 while (currticks() - start_time <= 1)
00368 ;
00369
00370 outb(0, eth_nic_base+D8390_P0_RBCR0);
00371 outb(0, eth_nic_base+D8390_P0_RBCR1);
00372
00373
00374
00375
00376
00377
00378
00379 outb(2, eth_nic_base+D8390_P0_TCR);
00380 #ifdef INCLUDE_WD
00381 if (eth_flags & FLAG_790)
00382 outb(D8390_COMMAND_PS0 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
00383 else
00384 #endif
00385 outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
00386 D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
00387
00388
00389 eth_drain_receiver = 1;
00390 while (ns8390_poll(nic, 1))
00391 ;
00392 eth_drain_receiver = 0;
00393 outb(D8390_ISR_OVW, eth_nic_base+D8390_P0_ISR);
00394
00395
00396 outb(0, eth_nic_base+D8390_P0_TCR);
00397 }
00398 #endif
00399
00400
00401
00402
00403 static void ns8390_transmit(
00404 struct nic *nic,
00405 const char *d,
00406 unsigned int t,
00407 unsigned int s,
00408 const char *p)
00409 {
00410 #if defined(INCLUDE_3C503) || (defined(INCLUDE_WD) && ! defined(WD_790_PIO))
00411 Address eth_vmem = bus_to_virt(eth_bmem);
00412 #endif
00413 #ifdef INCLUDE_3C503
00414 if (!(eth_flags & FLAG_PIO)) {
00415 memcpy((char *)eth_vmem, d, ETH_ALEN);
00416 memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN);
00417 *((char *)eth_vmem+12) = t>>8;
00418 *((char *)eth_vmem+13) = t;
00419 memcpy((char *)eth_vmem+ETH_HLEN, p, s);
00420 s += ETH_HLEN;
00421 while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0;
00422 }
00423 #endif
00424
00425 #ifdef INCLUDE_WD
00426 if (eth_flags & FLAG_16BIT) {
00427 outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
00428 inb(0x84);
00429 }
00430 #ifndef WD_790_PIO
00431
00432 if (eth_flags & FLAG_790) {
00433 outb(WD_MSR_MENB, eth_asic_base + WD_MSR);
00434 inb(0x84);
00435 }
00436 inb(0x84);
00437 memcpy((char *)eth_vmem, d, ETH_ALEN);
00438 memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN);
00439 *((char *)eth_vmem+12) = t>>8;
00440 *((char *)eth_vmem+13) = t;
00441 memcpy((char *)eth_vmem+ETH_HLEN, p, s);
00442 s += ETH_HLEN;
00443 while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0;
00444 if (eth_flags & FLAG_790) {
00445 outb(0, eth_asic_base + WD_MSR);
00446 inb(0x84);
00447 }
00448 #else
00449 inb(0x84);
00450 #endif
00451 #endif
00452
00453 #if defined(INCLUDE_3C503)
00454 if (eth_flags & FLAG_PIO)
00455 #endif
00456 #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO))
00457 {
00458
00459 unsigned short type;
00460 type = (t >> 8) | (t << 8);
00461 eth_pio_write( (unsigned char *) d, eth_tx_start<<8, ETH_ALEN);
00462 eth_pio_write(nic->node_addr, (eth_tx_start<<8)+ETH_ALEN, ETH_ALEN);
00463
00464 eth_pio_write((unsigned char *)&type, (eth_tx_start<<8)+(ETH_ALEN+ETH_ALEN), 2);
00465 eth_pio_write( (unsigned char *) p, (eth_tx_start<<8)+ETH_HLEN, s);
00466 s += ETH_HLEN;
00467 if (s < ETH_ZLEN) s = ETH_ZLEN;
00468 }
00469 #endif
00470 #if defined(INCLUDE_3C503)
00471 #endif
00472
00473 #ifdef INCLUDE_WD
00474 if (eth_flags & FLAG_16BIT) {
00475 outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
00476 inb(0x84);
00477 }
00478 if (eth_flags & FLAG_790)
00479 outb(D8390_COMMAND_PS0 |
00480 D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
00481 else
00482 #endif
00483 outb(D8390_COMMAND_PS0 |
00484 D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
00485 outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
00486 outb(s, eth_nic_base+D8390_P0_TBCR0);
00487 outb(s>>8, eth_nic_base+D8390_P0_TBCR1);
00488 #ifdef INCLUDE_WD
00489 if (eth_flags & FLAG_790)
00490 outb(D8390_COMMAND_PS0 |
00491 D8390_COMMAND_TXP | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
00492 else
00493 #endif
00494 outb(D8390_COMMAND_PS0 |
00495 D8390_COMMAND_TXP | D8390_COMMAND_RD2 |
00496 D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
00497 }
00498
00499
00500
00501
00502 static int ns8390_poll(struct nic *nic, int retrieve)
00503 {
00504 int ret = 0;
00505 unsigned char rstat, curr, next;
00506 unsigned short len, frag;
00507 unsigned short pktoff;
00508 unsigned char *p;
00509 struct ringbuffer pkthdr;
00510
00511 #ifndef INCLUDE_3C503
00512
00513 if (!eth_drain_receiver && (inb(eth_nic_base+D8390_P0_ISR) & D8390_ISR_OVW)) {
00514 eth_rx_overrun(nic);
00515 return(0);
00516 }
00517 #endif
00518 rstat = inb(eth_nic_base+D8390_P0_RSR);
00519 if (!(rstat & D8390_RSTAT_PRX)) return(0);
00520 next = inb(eth_nic_base+D8390_P0_BOUND)+1;
00521 if (next >= eth_memsize) next = eth_rx_start;
00522 outb(D8390_COMMAND_PS1, eth_nic_base+D8390_P0_COMMAND);
00523 curr = inb(eth_nic_base+D8390_P1_CURR);
00524 outb(D8390_COMMAND_PS0, eth_nic_base+D8390_P0_COMMAND);
00525 if (curr >= eth_memsize) curr=eth_rx_start;
00526 if (curr == next) return(0);
00527
00528 if ( ! retrieve ) return 1;
00529
00530 #ifdef INCLUDE_WD
00531 if (eth_flags & FLAG_16BIT) {
00532 outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
00533 inb(0x84);
00534 }
00535 #ifndef WD_790_PIO
00536 if (eth_flags & FLAG_790) {
00537 outb(WD_MSR_MENB, eth_asic_base + WD_MSR);
00538 inb(0x84);
00539 }
00540 #endif
00541 inb(0x84);
00542 #endif
00543 pktoff = next << 8;
00544 if (eth_flags & FLAG_PIO)
00545 eth_pio_read(pktoff, (unsigned char *)&pkthdr, 4);
00546 else
00547 memcpy(&pkthdr, bus_to_virt(eth_rmem + pktoff), 4);
00548 pktoff += sizeof(pkthdr);
00549
00550 len = pkthdr.len - 4;
00551 if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || len < ETH_ZLEN
00552 || len > ETH_FRAME_LEN) {
00553 printf("Bogus packet, ignoring\n");
00554 return (0);
00555 }
00556 else {
00557 p = nic->packet;
00558 nic->packetlen = len;
00559 frag = (eth_memsize << 8) - pktoff;
00560 if (len > frag) {
00561
00562 if (eth_flags & FLAG_PIO)
00563 eth_pio_read(pktoff, p, frag);
00564 else
00565 memcpy(p, bus_to_virt(eth_rmem + pktoff), frag);
00566 pktoff = eth_rx_start << 8;
00567 p += frag;
00568 len -= frag;
00569 }
00570
00571 if (eth_flags & FLAG_PIO)
00572 eth_pio_read(pktoff, p, len);
00573 else
00574 memcpy(p, bus_to_virt(eth_rmem + pktoff), len);
00575 ret = 1;
00576 }
00577 #ifdef INCLUDE_WD
00578 #ifndef WD_790_PIO
00579 if (eth_flags & FLAG_790) {
00580 outb(0, eth_asic_base + WD_MSR);
00581 inb(0x84);
00582 }
00583 #endif
00584 if (eth_flags & FLAG_16BIT) {
00585 outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
00586 inb(0x84);
00587 }
00588 inb(0x84);
00589 #endif
00590 next = pkthdr.next;
00591 if (next == eth_rx_start)
00592 next = eth_memsize;
00593 outb(next-1, eth_nic_base+D8390_P0_BOUND);
00594 return(ret);
00595 }
00596
00597
00598
00599
00600 static void ns8390_disable ( struct nic *nic ) {
00601 ns8390_reset(nic);
00602 }
00603
00604
00605
00606
00607 static void ns8390_irq(struct nic *nic __unused, irq_action_t action __unused)
00608 {
00609 switch ( action ) {
00610 case DISABLE :
00611 break;
00612 case ENABLE :
00613 break;
00614 case FORCE :
00615 break;
00616 }
00617 }
00618
00619 static struct nic_operations ns8390_operations;
00620 static struct nic_operations ns8390_operations = {
00621 .connect = dummy_connect,
00622 .poll = ns8390_poll,
00623 .transmit = ns8390_transmit,
00624 .irq = ns8390_irq,
00625 };
00626
00627
00628
00629
00630 #ifdef INCLUDE_NS8390
00631 static int eth_probe (struct nic *nic, struct pci_device *pci)
00632 #else
00633 static int eth_probe (struct dev *dev, unsigned short *probe_addrs __unused)
00634 #endif
00635 {
00636 int i;
00637 #ifdef INCLUDE_NS8390
00638 unsigned short pci_probe_addrs[] = { pci->ioaddr, 0 };
00639 unsigned short *probe_addrs = pci_probe_addrs;
00640 #endif
00641 eth_vendor = VENDOR_NONE;
00642 eth_drain_receiver = 0;
00643
00644 nic->irqno = 0;
00645
00646 #ifdef INCLUDE_WD
00647 {
00648
00649
00650
00651 struct wd_board *brd;
00652 unsigned short chksum;
00653 unsigned char c;
00654 for (eth_asic_base = WD_LOW_BASE; eth_asic_base <= WD_HIGH_BASE;
00655 eth_asic_base += 0x20) {
00656 chksum = 0;
00657 for (i=8; i<16; i++)
00658 chksum += inb(eth_asic_base+i);
00659
00660 if ((chksum & 0xFF) == 0xFF &&
00661 inb(eth_asic_base+8) != 0xFF &&
00662 inb(eth_asic_base+9) != 0xFF)
00663 break;
00664 }
00665 if (eth_asic_base > WD_HIGH_BASE)
00666 return (0);
00667
00668 eth_vendor = VENDOR_WD;
00669 eth_nic_base = eth_asic_base + WD_NIC_ADDR;
00670
00671 nic->ioaddr = eth_nic_base;
00672
00673 c = inb(eth_asic_base+WD_BID);
00674 for (brd = wd_boards; brd->name; brd++)
00675 if (brd->id == c) break;
00676 if (!brd->name) {
00677 printf("Unknown WD/SMC NIC type %hhX\n", c);
00678 return (0);
00679 }
00680 eth_flags = brd->flags;
00681 eth_memsize = brd->memsize;
00682 eth_tx_start = 0;
00683 eth_rx_start = D8390_TXBUF_SIZE;
00684 if ((c == TYPE_WD8013EP) &&
00685 (inb(eth_asic_base + WD_ICR) & WD_ICR_16BIT)) {
00686 eth_flags = FLAG_16BIT;
00687 eth_memsize = MEM_16384;
00688 }
00689 if ((c & WD_SOFTCONFIG) && (!(eth_flags & FLAG_790))) {
00690 eth_bmem = (0x80000 |
00691 ((inb(eth_asic_base + WD_MSR) & 0x3F) << 13));
00692 } else
00693 eth_bmem = WD_DEFAULT_MEM;
00694 if (brd->id == TYPE_SMC8216T || brd->id == TYPE_SMC8216C) {
00695
00696 unsigned int addr = inb(eth_asic_base + 0xb);
00697 if (((addr >> 4) & 3) == 0) {
00698 brd += 2;
00699 eth_memsize = brd->memsize;
00700 }
00701 }
00702 outb(0x80, eth_asic_base + WD_MSR);
00703 for (i=0; i<ETH_ALEN; i++) {
00704 nic->node_addr[i] = inb(i+eth_asic_base+WD_LAR);
00705 }
00706 DBG ( "\n%s base %4.4x", brd->name, eth_asic_base );
00707 if (eth_flags & FLAG_790) {
00708 #ifdef WD_790_PIO
00709 DBG ( ", PIO mode, addr %s\n", eth_ntoa ( nic->node_addr ) );
00710 eth_bmem = 0;
00711 eth_flags |= FLAG_PIO;
00712 outb(0, eth_asic_base+WD_MSR);
00713 #else
00714 DBG ( ", Memory %x, MAC Addr %s\n", eth_bmem, eth_ntoa ( nic->node_addr) );
00715
00716 outb(WD_MSR_MENB, eth_asic_base+WD_MSR);
00717 outb((inb(eth_asic_base+0x04) |
00718 0x80), eth_asic_base+0x04);
00719 outb(((unsigned)(eth_bmem >> 13) & 0x0F) |
00720 ((unsigned)(eth_bmem >> 11) & 0x40) |
00721 (inb(eth_asic_base+0x0B) & 0xB0), eth_asic_base+0x0B);
00722 outb((inb(eth_asic_base+0x04) &
00723 ~0x80), eth_asic_base+0x04);
00724 #endif
00725 } else {
00726
00727 DBG (", Memory %x, MAC Addr %s\n", eth_bmem, eth_ntoa ( nic->node_addr) );
00728
00729 outb(((unsigned)(eth_bmem >> 13) & 0x3F) | 0x40, eth_asic_base+WD_MSR);
00730 }
00731 if (eth_flags & FLAG_16BIT) {
00732 if (eth_flags & FLAG_790) {
00733 eth_laar = inb(eth_asic_base + WD_LAAR);
00734 outb(WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
00735 } else {
00736 outb((eth_laar =
00737 WD_LAAR_L16EN | 1), eth_asic_base + WD_LAAR);
00738
00739
00740
00741
00742
00743
00744
00745
00746 }
00747 inb(0x84);
00748 }
00749 }
00750 #endif
00751 #ifdef INCLUDE_3C503
00752 #ifdef T503_AUI
00753 nic->flags = 1;
00754 #else
00755 nic->flags = 0;
00756 #endif
00757
00758
00759
00760 if (eth_vendor == VENDOR_NONE) {
00761 int idx;
00762 int iobase_reg, membase_reg;
00763 static unsigned short base[] = {
00764 0x300, 0x310, 0x330, 0x350,
00765 0x250, 0x280, 0x2A0, 0x2E0, 0 };
00766
00767
00768
00769 for (idx = 0; (eth_nic_base = base[idx]) != 0; ++idx) {
00770
00771 eth_asic_base = eth_nic_base + _3COM_ASIC_OFFSET;
00772
00773
00774
00775
00776
00777 eth_memsize = MEM_16384;
00778 eth_tx_start = 32;
00779 eth_rx_start = 32 + D8390_TXBUF_SIZE;
00780
00781
00782
00783
00784 iobase_reg = inb(eth_asic_base + _3COM_BCFR);
00785 membase_reg = inb(eth_asic_base + _3COM_PCFR);
00786
00787 if ((iobase_reg & (iobase_reg - 1)) ||
00788 (membase_reg & (membase_reg - 1)))
00789 continue;
00790
00791
00792
00793 eth_flags = 0;
00794
00795 switch (membase_reg) {
00796 case _3COM_PCFR_DC000:
00797 eth_bmem = 0xdc000;
00798 break;
00799 case _3COM_PCFR_D8000:
00800 eth_bmem = 0xd8000;
00801 break;
00802 case _3COM_PCFR_CC000:
00803 eth_bmem = 0xcc000;
00804 break;
00805 case _3COM_PCFR_C8000:
00806 eth_bmem = 0xc8000;
00807 break;
00808 case _3COM_PCFR_PIO:
00809 eth_flags |= FLAG_PIO;
00810 eth_bmem = 0;
00811 break;
00812 default:
00813 continue;
00814 }
00815 break;
00816 }
00817
00818 if (base[idx] == 0)
00819 return (0);
00820 #ifndef T503_SHMEM
00821 eth_flags |= FLAG_PIO;
00822 eth_bmem = 0;
00823 #endif
00824 eth_vendor = VENDOR_3COM;
00825
00826
00827
00828
00829 eth_rmem = eth_bmem - 0x2000;
00830
00831
00832
00833 outb(_3COM_CR_RST | _3COM_CR_XSEL, eth_asic_base + _3COM_CR );
00834 outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR );
00835
00836
00837
00838 outb(_3COM_CR_EALO | _3COM_CR_XSEL, eth_asic_base + _3COM_CR);
00839 nic->ioaddr = eth_nic_base;
00840 DBG ( "\n3Com 3c503 base %4.4x, ", eth_nic_base );
00841 if (eth_flags & FLAG_PIO)
00842 DBG ( "PIO mode" );
00843 else
00844 DBG ( "memory %4.4x", eth_bmem );
00845 for (i=0; i<ETH_ALEN; i++) {
00846 nic->node_addr[i] = inb(eth_nic_base+i);
00847 }
00848 DBG ( ", %s, MAC Addr %s\n", nic->flags ? "AUI" : "internal xcvr",
00849 eth_ntoa ( nic->node_addr ) );
00850
00851 outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR);
00852
00853
00854
00855
00856 outb(_3COM_GACFR_RSEL |
00857 _3COM_GACFR_MBS0 | _3COM_GACFR_TCM | _3COM_GACFR_NIM, eth_asic_base + _3COM_GACFR);
00858
00859 outb(0xff, eth_asic_base + _3COM_VPTR2);
00860 outb(0xff, eth_asic_base + _3COM_VPTR1);
00861 outb(0x00, eth_asic_base + _3COM_VPTR0);
00862
00863
00864
00865
00866 if (!(eth_flags & FLAG_PIO)) {
00867 memset(bus_to_virt(eth_bmem), 0, 0x2000);
00868 for(i = 0; i < 0x2000; ++i)
00869 if (*((char *)(bus_to_virt(eth_bmem+i)))) {
00870 printf ("Failed to clear 3c503 shared mem.\n");
00871 return (0);
00872 }
00873 }
00874
00875
00876
00877 outb(eth_tx_start, eth_asic_base + _3COM_PSTR);
00878 outb(eth_memsize, eth_asic_base + _3COM_PSPR);
00879 }
00880 #endif
00881 #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
00882 {
00883
00884
00885
00886 unsigned char c;
00887 if (eth_vendor == VENDOR_NONE) {
00888 unsigned char romdata[16];
00889 unsigned char testbuf[32];
00890 int idx;
00891 static unsigned char test[] = "NE*000 memory";
00892 static unsigned short base[] = {
00893 #ifdef NE_SCAN
00894 NE_SCAN,
00895 #endif
00896 0 };
00897
00898 if (probe_addrs == 0 || probe_addrs[0] == 0)
00899 probe_addrs = base;
00900 eth_bmem = 0;
00901 for (idx = 0; (eth_nic_base = probe_addrs[idx]) != 0; ++idx) {
00902 eth_flags = FLAG_PIO;
00903 eth_asic_base = eth_nic_base + NE_ASIC_OFFSET;
00904 eth_memsize = MEM_16384;
00905 eth_tx_start = 32;
00906 eth_rx_start = 32 + D8390_TXBUF_SIZE;
00907 c = inb(eth_asic_base + NE_RESET);
00908 outb(c, eth_asic_base + NE_RESET);
00909 (void) inb(0x84);
00910 outb(D8390_COMMAND_STP |
00911 D8390_COMMAND_RD2, eth_nic_base + D8390_P0_COMMAND);
00912 outb(D8390_RCR_MON, eth_nic_base + D8390_P0_RCR);
00913 outb(D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
00914 outb(MEM_8192, eth_nic_base + D8390_P0_PSTART);
00915 outb(MEM_16384, eth_nic_base + D8390_P0_PSTOP);
00916 #ifdef NS8390_FORCE_16BIT
00917 eth_flags |= FLAG_16BIT;
00918 #endif
00919
00920 eth_pio_write( (unsigned char *) test, 8192, sizeof(test));
00921 eth_pio_read(8192, testbuf, sizeof(test));
00922 if (!memcmp(test, testbuf, sizeof(test)))
00923 break;
00924 eth_flags |= FLAG_16BIT;
00925 eth_memsize = MEM_32768;
00926 eth_tx_start = 64;
00927 eth_rx_start = 64 + D8390_TXBUF_SIZE;
00928 outb(D8390_DCR_WTS |
00929 D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
00930 outb(MEM_16384, eth_nic_base + D8390_P0_PSTART);
00931 outb(MEM_32768, eth_nic_base + D8390_P0_PSTOP);
00932 eth_pio_write( (unsigned char *) test, 16384, sizeof(test));
00933 eth_pio_read(16384, testbuf, sizeof(test));
00934 if (!memcmp(testbuf, test, sizeof(test)))
00935 break;
00936 }
00937 if (eth_nic_base == 0)
00938 return (0);
00939 if (eth_nic_base > ISA_MAX_ADDR)
00940 eth_flags |= FLAG_16BIT;
00941 eth_vendor = VENDOR_NOVELL;
00942 eth_pio_read(0, romdata, sizeof(romdata));
00943 for (i=0; i<ETH_ALEN; i++) {
00944 nic->node_addr[i] = romdata[i + ((eth_flags & FLAG_16BIT) ? i : 0)];
00945 }
00946 nic->ioaddr = eth_nic_base;
00947 DBG ( "\nNE%c000 base %4.4x, MAC Addr %s\n",
00948 (eth_flags & FLAG_16BIT) ? '2' : '1', eth_nic_base,
00949 eth_ntoa ( nic->node_addr ) );
00950 }
00951 }
00952 #endif
00953 if (eth_vendor == VENDOR_NONE)
00954 return(0);
00955 if (eth_vendor != VENDOR_3COM)
00956 eth_rmem = eth_bmem;
00957 ns8390_reset(nic);
00958 nic->nic_op = &ns8390_operations;
00959
00960
00961 #ifdef INCLUDE_WD
00962 dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
00963 dev->devid.device_id = htons(0x812a);
00964 #endif
00965 #ifdef INCLUDE_3C503
00966 dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
00967 dev->devid.device_id = htons(0x80f3);
00968 #endif
00969 #ifdef INCLUDE_NE
00970 dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
00971 dev->devid.device_id = htons(0x80d6);
00972 #endif
00973 return 1;
00974 }
00975
00976 #ifdef INCLUDE_WD
00977 struct isa_driver wd_driver __isa_driver = {
00978 .type = NIC_DRIVER,
00979 .name = "WD",
00980 .probe = wd_probe,
00981 .ioaddrs = 0,
00982 };
00983 ISA_ROM("wd","WD8003/8013, SMC8216/8416, SMC 83c790 (EtherEZ)");
00984 #endif
00985
00986 #ifdef INCLUDE_3C503
00987 struct isa_driver t503_driver __isa_driver = {
00988 .type = NIC_DRIVER,
00989 .name = "3C503",
00990 .probe = t503_probe,
00991 .ioaddrs = 0,
00992 };
00993 ISA_ROM("3c503","3Com503, Etherlink II[/16]");
00994 #endif
00995
00996 #ifdef INCLUDE_NE
00997 struct isa_driver ne_driver __isa_driver = {
00998 .type = NIC_DRIVER,
00999 .name = "NE*000",
01000 .probe = ne_probe,
01001 .ioaddrs = 0,
01002 };
01003 ISA_ROM("ne","NE1000/2000 and clones");
01004 #endif
01005
01006 #ifdef INCLUDE_NS8390
01007 static struct pci_device_id nepci_nics[] = {
01008
01009 PCI_ROM(0x10ec, 0x8029, "rtl8029", "Realtek 8029", 0),
01010 PCI_ROM(0x1186, 0x0300, "dlink-528", "D-Link DE-528", 0),
01011 PCI_ROM(0x1050, 0x0940, "winbond940", "Winbond NE2000-PCI", 0),
01012 PCI_ROM(0x1050, 0x5a5a, "winbond940f", "Winbond W89c940F", 0),
01013 PCI_ROM(0x11f6, 0x1401, "compexrl2000", "Compex ReadyLink 2000", 0),
01014 PCI_ROM(0x8e2e, 0x3000, "ktiet32p2", "KTI ET32P2", 0),
01015 PCI_ROM(0x4a14, 0x5000, "nv5000sc", "NetVin NV5000SC", 0),
01016 PCI_ROM(0x12c3, 0x0058, "holtek80232", "Holtek HT80232", 0),
01017 PCI_ROM(0x12c3, 0x5598, "holtek80229", "Holtek HT80229", 0),
01018 PCI_ROM(0x10bd, 0x0e34, "surecom-ne34", "Surecom NE34", 0),
01019 PCI_ROM(0x1106, 0x0926, "via86c926", "Via 86c926", 0),
01020 };
01021
01022 PCI_DRIVER ( nepci_driver, nepci_nics, PCI_NO_CLASS );
01023
01024 DRIVER ( "NE2000/PCI", nic_driver, pci_driver, nepci_driver,
01025 nepci_probe, ns8390_disable );
01026
01027 #endif
01028
01029 #endif
01030
01031
01032
01033
01034
01035
01036
01037