#include "etherboot.h"#include "nic.h"#include "ns8390.h"#include <gpxe/ethernet.h>#include <gpxe/pci.h>Go to the source code of this file.
Defines | |
| #define | INCLUDE_NS8390 1 |
| #define | eth_probe nepci_probe |
| #define | ASIC_PIO NE_DATA |
Functions | |
| FILE_LICENCE (BSD2) | |
| static void | eth_pio_read (unsigned int src, unsigned char *dst, unsigned int cnt) |
| static void | eth_pio_write (const unsigned char *src, unsigned int dst, unsigned int cnt) |
| static void | enable_multicast (unsigned short eth_nic_base) |
| static void | ns8390_reset (struct nic *nic) |
| static int | ns8390_poll (struct nic *nic, int retrieve) |
| static void | eth_rx_overrun (struct nic *nic) |
| static void | ns8390_transmit (struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p) |
| static void | ns8390_disable (struct nic *nic) |
| static void | ns8390_irq (struct nic *nic __unused, irq_action_t action __unused) |
| static int | eth_probe (struct nic *nic, struct pci_device *pci) |
| PCI_DRIVER (nepci_driver, nepci_nics, PCI_NO_CLASS) | |
| DRIVER ("NE2000/PCI", nic_driver, pci_driver, nepci_driver, nepci_probe, ns8390_disable) | |
Variables | |
| static unsigned char | eth_vendor |
| static unsigned char | eth_flags |
| static unsigned short | eth_nic_base |
| static unsigned short | eth_asic_base |
| static unsigned char | eth_memsize |
| static unsigned char | eth_rx_start |
| static unsigned char | eth_tx_start |
| static Address | eth_bmem |
| static Address | eth_rmem |
| static unsigned char | eth_drain_receiver |
| static struct nic_operations | ns8390_operations |
| static struct pci_device_id | nepci_nics [] |
| FILE_LICENCE | ( | BSD2 | ) |
| static void eth_pio_read | ( | unsigned int | src, | |
| unsigned char * | dst, | |||
| unsigned int | cnt | |||
| ) | [static] |
Definition at line 131 of file ns8390.c.
References _3COM_CR, _3COM_CR_START, _3COM_DALSB, _3COM_DAMSB, _3COM_STREG, _3COM_STREG_DPRDY, ASIC_PIO, D8390_COMMAND_RD0, D8390_COMMAND_RD2, D8390_COMMAND_STA, D8390_P0_COMMAND, D8390_P0_RBCR0, D8390_P0_RBCR1, D8390_P0_RSAR0, D8390_P0_RSAR1, eth_asic_base, eth_flags, eth_nic_base, FLAG_16BIT, inb, inw, outb, and WD_GP2.
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 }
| static void eth_pio_write | ( | const unsigned char * | src, | |
| unsigned int | dst, | |||
| unsigned int | cnt | |||
| ) | [static] |
Definition at line 178 of file ns8390.c.
References _3COM_CR, _3COM_CR_DDIR, _3COM_CR_START, _3COM_DALSB, _3COM_DAMSB, _3COM_STREG, _3COM_STREG_DPRDY, ASIC_PIO, COMPEX_RL2000_TRIES, D8390_COMMAND_RD1, D8390_COMMAND_RD2, D8390_COMMAND_STA, D8390_ISR_RDC, D8390_P0_COMMAND, D8390_P0_ISR, D8390_P0_RBCR0, D8390_P0_RBCR1, D8390_P0_RSAR0, D8390_P0_RSAR1, eth_asic_base, eth_flags, eth_nic_base, FLAG_16BIT, inb, outb, outw, printf(), and WD_GP2.
00179 { 00180 #ifdef COMPEX_RL2000_FIX 00181 unsigned int x; 00182 #endif /* COMPEX_RL2000_FIX */ 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 /* COMPEX_RL2000_FIX */ 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 }
| static void enable_multicast | ( | unsigned short | eth_nic_base | ) | [static] |
Definition at line 252 of file ns8390.c.
References D8390_COMMAND_PS0, D8390_COMMAND_PS1, D8390_COMMAND_RD2, D8390_P0_COMMAND, D8390_P0_RCR, inb, memset(), outb, and printf().
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 }
| static void ns8390_reset | ( | struct nic * | nic | ) | [static] |
Definition at line 272 of file ns8390.c.
References _3COM_CR, _3COM_CR_XSEL, D8390_COMMAND_PS0, D8390_COMMAND_PS1, D8390_COMMAND_RD2, D8390_COMMAND_STA, D8390_COMMAND_STP, D8390_P0_BOUND, D8390_P0_COMMAND, D8390_P0_DCR, D8390_P0_IMR, D8390_P0_ISR, D8390_P0_PSTART, D8390_P0_PSTOP, D8390_P0_RBCR0, D8390_P0_RBCR1, D8390_P0_RCR, D8390_P0_TCR, D8390_P0_TPSR, D8390_P1_CURR, D8390_P1_MAR0, D8390_P1_PAR0, enable_multicast(), ETH_ALEN, eth_asic_base, eth_drain_receiver, eth_flags, eth_memsize, eth_nic_base, eth_rx_start, eth_tx_start, FLAG_16BIT, FLAG_790, nic::flags, nic::node_addr, and outb.
Referenced by eth_probe(), and ns8390_disable().
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); /* monitor mode */ 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); /* disable interrupts, enable PIO */ 00298 outb(0x01, eth_nic_base + 0x09); /* enable ring read auto-wrap */ 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); /* transmitter on */ 00331 outb(4, eth_nic_base+D8390_P0_RCR); /* allow rx broadcast frames */ 00332 00333 enable_multicast(eth_nic_base); 00334 00335 #ifdef INCLUDE_3C503 00336 /* 00337 * No way to tell whether or not we're supposed to use 00338 * the 3Com's transceiver unless the user tells us. 00339 * 'flags' should have some compile time default value 00340 * which can be changed from the command menu. 00341 */ 00342 t503_output = (nic->flags) ? 0 : _3COM_CR_XSEL; 00343 outb(t503_output, eth_asic_base + _3COM_CR); 00344 #endif 00345 }
| static int ns8390_poll | ( | struct nic * | nic, | |
| int | retrieve | |||
| ) | [static] |
Definition at line 502 of file ns8390.c.
References bus_to_virt(), D8390_COMMAND_PS0, D8390_COMMAND_PS1, D8390_ISR_OVW, D8390_P0_BOUND, D8390_P0_COMMAND, D8390_P0_ISR, D8390_P0_RSR, D8390_P1_CURR, D8390_RSTAT_PRX, eth_asic_base, eth_drain_receiver, eth_flags, ETH_FRAME_LEN, eth_memsize, eth_nic_base, eth_pio_read(), eth_rmem, eth_rx_overrun(), eth_rx_start, ETH_ZLEN, FLAG_16BIT, FLAG_790, FLAG_PIO, inb, memcpy, outb, nic::packet, nic::packetlen, printf(), WD_LAAR, WD_LAAR_M16EN, WD_MSR, and WD_MSR_MENB.
Referenced by eth_rx_overrun().
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 /* avoid infinite recursion: see eth_rx_overrun() */ 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 /* INCLUDE_3C503 */ 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 /* incoming length includes FCS so must sub 4 */ 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; /* available to caller */ 00559 frag = (eth_memsize << 8) - pktoff; 00560 if (len > frag) { /* We have a wrap-around */ 00561 /* read first part */ 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 /* read second part */ 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; /* frame number of next packet */ 00591 if (next == eth_rx_start) 00592 next = eth_memsize; 00593 outb(next-1, eth_nic_base+D8390_P0_BOUND); 00594 return(ret); 00595 }
| static void eth_rx_overrun | ( | struct nic * | nic | ) | [static] |
Definition at line 353 of file ns8390.c.
References currticks(), D8390_COMMAND_PS0, D8390_COMMAND_RD2, D8390_COMMAND_STA, D8390_COMMAND_STP, D8390_ISR_OVW, D8390_P0_COMMAND, D8390_P0_ISR, D8390_P0_RBCR0, D8390_P0_RBCR1, D8390_P0_TCR, eth_drain_receiver, eth_flags, eth_nic_base, FLAG_790, ns8390_poll(), and outb.
Referenced by ns8390_poll().
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 /* wait for at least 1.6ms - we wait one timer tick */ 00366 start_time = currticks(); 00367 while (currticks() - start_time <= 1) 00368 /* Nothing */; 00369 00370 outb(0, eth_nic_base+D8390_P0_RBCR0); /* reset byte counter */ 00371 outb(0, eth_nic_base+D8390_P0_RBCR1); 00372 00373 /* 00374 * Linux driver checks for interrupted TX here. This is not necessary, 00375 * because the transmit routine waits until the frame is sent. 00376 */ 00377 00378 /* enter loopback mode and restart NIC */ 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 /* clear the RX ring, acknowledge overrun interrupt */ 00389 eth_drain_receiver = 1; 00390 while (ns8390_poll(nic, 1)) 00391 /* Nothing */; 00392 eth_drain_receiver = 0; 00393 outb(D8390_ISR_OVW, eth_nic_base+D8390_P0_ISR); 00394 00395 /* leave loopback mode - no packets to be resent (see Linux driver) */ 00396 outb(0, eth_nic_base+D8390_P0_TCR); 00397 }
| static void ns8390_transmit | ( | struct nic * | nic, | |
| const char * | d, | |||
| unsigned int | t, | |||
| unsigned int | s, | |||
| const char * | p | |||
| ) | [static] |
Definition at line 403 of file ns8390.c.
References bus_to_virt(), D8390_COMMAND_PS0, D8390_COMMAND_RD2, D8390_COMMAND_STA, D8390_COMMAND_TXP, D8390_P0_COMMAND, D8390_P0_TBCR0, D8390_P0_TBCR1, D8390_P0_TPSR, ETH_ALEN, eth_asic_base, eth_bmem, eth_flags, ETH_HLEN, eth_nic_base, eth_pio_write(), eth_tx_start, ETH_ZLEN, FLAG_16BIT, FLAG_790, FLAG_PIO, inb, memcpy, nic::node_addr, outb, WD_LAAR, WD_LAAR_M16EN, WD_MSR, and WD_MSR_MENB.
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); /* dst */ 00416 memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */ 00417 *((char *)eth_vmem+12) = t>>8; /* type */ 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 /* Memory interface */ 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); /* dst */ 00438 memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */ 00439 *((char *)eth_vmem+12) = t>>8; /* type */ 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 /* Programmed I/O */ 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 /* bcc generates worse code without (const+const) below */ 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 }
| static void ns8390_disable | ( | struct nic * | nic | ) | [static] |
Definition at line 600 of file ns8390.c.
References ns8390_reset().
00600 { 00601 ns8390_reset(nic); 00602 }
| static void ns8390_irq | ( | struct nic *nic | __unused, | |
| irq_action_t action | __unused | |||
| ) | [static] |
| static int eth_probe | ( | struct nic * | nic, | |
| struct pci_device * | pci | |||
| ) | [static] |
Definition at line 631 of file ns8390.c.
References _3COM_ASIC_OFFSET, _3COM_BCFR, _3COM_CR, _3COM_CR_EALO, _3COM_CR_RST, _3COM_CR_XSEL, _3COM_GACFR, _3COM_GACFR_MBS0, _3COM_GACFR_NIM, _3COM_GACFR_RSEL, _3COM_GACFR_TCM, _3COM_PCFR, _3COM_PCFR_C8000, _3COM_PCFR_CC000, _3COM_PCFR_D8000, _3COM_PCFR_DC000, _3COM_PCFR_PIO, _3COM_PSPR, _3COM_PSTR, _3COM_VPTR0, _3COM_VPTR1, _3COM_VPTR2, bus_to_virt(), D8390_COMMAND_RD2, D8390_COMMAND_STP, D8390_DCR_FT1, D8390_DCR_LS, D8390_DCR_WTS, D8390_P0_COMMAND, D8390_P0_DCR, D8390_P0_PSTART, D8390_P0_PSTOP, D8390_P0_RCR, D8390_RCR_MON, D8390_TXBUF_SIZE, DBG, ETH_ALEN, eth_asic_base, eth_bmem, eth_drain_receiver, eth_flags, eth_memsize, eth_nic_base, eth_ntoa(), eth_pio_read(), eth_pio_write(), eth_rmem, eth_rx_start, eth_tx_start, eth_vendor, FLAG_16BIT, FLAG_790, FLAG_PIO, nic::flags, GENERIC_ISAPNP_VENDOR, htons, inb, nic::ioaddr, pci_device::ioaddr, nic::irqno, ISA_MAX_ADDR, MEM_16384, MEM_32768, MEM_8192, memcmp(), memset(), NE_ASIC_OFFSET, NE_RESET, nic::nic_op, nic::node_addr, ns8390_reset(), outb, printf(), test, TYPE_SMC8216C, TYPE_SMC8216T, TYPE_WD8013EP, VENDOR_3COM, VENDOR_NONE, VENDOR_NOVELL, VENDOR_WD, WD_BID, WD_DEFAULT_MEM, WD_HIGH_BASE, WD_ICR, WD_ICR_16BIT, WD_LAAR, WD_LAAR_L16EN, WD_LAAR_M16EN, WD_LAR, WD_LOW_BASE, WD_MSR, WD_MSR_MENB, WD_NIC_ADDR, and WD_SOFTCONFIG.
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 Search for WD/SMC cards 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 /* Extra checks to avoid soundcard */ 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 /* We've found a board */ 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); /* Get board id */ 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); /* Unknown type */ 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 /* from Linux driver, 8416BT detects as 8216 sometimes */ 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); /* Reset */ 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; /* force PIO mode */ 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 The previous line used to be 00740 WD_LAAR_M16EN | WD_LAAR_L16EN | 1)); 00741 jluke@deakin.edu.au reported that removing WD_LAAR_M16EN made 00742 it work for WD8013s. This seems to work for my 8013 boards. I 00743 don't know what is really happening. I wish I had data sheets 00744 or more time to decode the Linux driver. - Ken 00745 */ 00746 } 00747 inb(0x84); 00748 } 00749 } 00750 #endif 00751 #ifdef INCLUDE_3C503 00752 #ifdef T503_AUI 00753 nic->flags = 1; /* aui */ 00754 #else 00755 nic->flags = 0; /* no aui */ 00756 #endif 00757 /****************************************************************** 00758 Search for 3Com 3c503 if no WD/SMC cards 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 /* Loop through possible addresses checking each one */ 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 * Note that we use the same settings for both 8 and 16 bit cards: 00774 * both have an 8K bank of memory at page 1 while only the 16 bit 00775 * cards have a bank at page 0. 00776 */ 00777 eth_memsize = MEM_16384; 00778 eth_tx_start = 32; 00779 eth_rx_start = 32 + D8390_TXBUF_SIZE; 00780 00781 /* Check our base address. iobase and membase should */ 00782 /* both have a maximum of 1 bit set or be 0. */ 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; /* nope */ 00790 00791 /* Now get the shared memory address */ 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; /* nope */ 00814 } 00815 break; 00816 } 00817 00818 if (base[idx] == 0) /* not found */ 00819 return (0); 00820 #ifndef T503_SHMEM 00821 eth_flags |= FLAG_PIO; /* force PIO mode */ 00822 eth_bmem = 0; 00823 #endif 00824 eth_vendor = VENDOR_3COM; 00825 00826 00827 /* Need this to make ns8390_poll() happy. */ 00828 00829 eth_rmem = eth_bmem - 0x2000; 00830 00831 /* Reset NIC and ASIC */ 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 /* Get our ethernet address */ 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 * Initialize GA configuration register. Set bank and enable shared 00854 * mem. We always use bank 1. Disable interrupts. 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 * Clear memory and verify that it worked (we use only 8K) 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 * Initialize GA page/start/stop registers. 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 Search for NE1000/2000 if no WD/SMC or 3com cards 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 /* if no addresses supplied, fall back on defaults */ 00898 if (probe_addrs == 0 || probe_addrs[0] == 0) 00899 probe_addrs = base; 00900 eth_bmem = 0; /* No shared memory */ 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; /* force 16-bit mode */ 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) /* PCI probably */ 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 /* Based on PnP ISA map */ 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 }
| PCI_DRIVER | ( | nepci_driver | , | |
| nepci_nics | , | |||
| PCI_NO_CLASS | ||||
| ) |
| DRIVER | ( | "NE2000/PCI" | , | |
| nic_driver | , | |||
| pci_driver | , | |||
| nepci_driver | , | |||
| nepci_probe | , | |||
| ns8390_disable | ||||
| ) |
unsigned char eth_vendor [static] |
unsigned short eth_nic_base [static] |
unsigned short eth_asic_base [static] |
unsigned char eth_memsize [static] |
unsigned char eth_rx_start [static] |
unsigned char eth_tx_start [static] |
unsigned char eth_drain_receiver [static] |
static struct nic_operations ns8390_operations [static, read] |
Initial value:
{
.connect = dummy_connect,
.poll = ns8390_poll,
.transmit = ns8390_transmit,
.irq = ns8390_irq,
}
struct pci_device_id nepci_nics[] [static] |
Initial value:
{
PCI_ROM(0x10ec, 0x8029, "rtl8029", "Realtek 8029", 0),
PCI_ROM(0x1186, 0x0300, "dlink-528", "D-Link DE-528", 0),
PCI_ROM(0x1050, 0x0940, "winbond940", "Winbond NE2000-PCI", 0),
PCI_ROM(0x1050, 0x5a5a, "winbond940f", "Winbond W89c940F", 0),
PCI_ROM(0x11f6, 0x1401, "compexrl2000", "Compex ReadyLink 2000", 0),
PCI_ROM(0x8e2e, 0x3000, "ktiet32p2", "KTI ET32P2", 0),
PCI_ROM(0x4a14, 0x5000, "nv5000sc", "NetVin NV5000SC", 0),
PCI_ROM(0x12c3, 0x0058, "holtek80232", "Holtek HT80232", 0),
PCI_ROM(0x12c3, 0x5598, "holtek80229", "Holtek HT80229", 0),
PCI_ROM(0x10bd, 0x0e34, "surecom-ne34", "Surecom NE34", 0),
PCI_ROM(0x1106, 0x0926, "via86c926", "Via 86c926", 0),
}
1.5.7.1