/************************************************************************** NETBOOT - BOOTP/TFTP Bootstrap Program Author: Martin Renters Date: May/94 This code is based heavily on David Greenman's if_ed.c driver Copyright (C) 1993-1994, David Greenman, Martin Renters. This software may be used, modified, copied, distributed, and sold, in both source and binary form provided that the above copyright and these terms are retained. Under no circumstances are the authors responsible for the proper functioning of this software, nor do the authors assume any responsibility for damages incurred with its use. 3c503 support added by Bill Paul (wpaul@ctr.columbia.edu) on 11/15/94 SMC8416 support added by Bill Paul (wpaul@ctr.columbia.edu) on 12/25/94 **************************************************************************/ #if defined(INCLUDE_NE) || defined(INCLUDE_NEPCI) || defined(INCLUDE_WD) || defined(INCLUDE_T503) #include "netboot.h" #include "nic.h" #include "ns8390.h" static unsigned char eth_vendor, eth_flags, eth_laar; static unsigned short eth_nic_base, eth_asic_base; static unsigned char eth_memsize, eth_rx_start, eth_tx_start; static Address eth_bmem, eth_rmem; #if defined(INCLUDE_WD) #define eth_probe wd_probe #else #if defined(INCLUDE_T503) #define eth_probe t503_probe #else #if defined(INCLUDE_NE) #define eth_probe ne_probe #else #if defined(INCLUDE_NEPCI) #define eth_probe nepci_probe #else Error you must define one of the above #endif #endif #endif #endif static void net_bcopy (char *s, char *d, int l) { while (l--) *d++ = *s++; } #if defined(INCLUDE_NE) || defined(INCLUDE_NEPCI) /************************************************************************** ETH_PIO_READ - Read a frame via Programmed I/O **************************************************************************/ static void eth_pio_read(src, dst, cnt) unsigned int src; unsigned char *dst; unsigned int cnt; { if (eth_flags & FLAG_16BIT) { ++cnt; cnt &= ~1; } outb(eth_nic_base + D8390_P0_COMMAND, D8390_COMMAND_RD2 | D8390_COMMAND_STA); outb(eth_nic_base + D8390_P0_RBCR0, cnt); outb(eth_nic_base + D8390_P0_RBCR1, cnt>>8); outb(eth_nic_base + D8390_P0_RSAR0, src); outb(eth_nic_base + D8390_P0_RSAR1, src>>8); outb(eth_nic_base + D8390_P0_COMMAND, D8390_COMMAND_RD0 | D8390_COMMAND_STA); if (eth_flags & FLAG_16BIT) { cnt >>= 1; /* number of words */ while (cnt--) { *((unsigned short *)dst) = inw(eth_asic_base + NE_DATA); dst += 2; } } else { while (cnt--) *(dst++) = inb(eth_asic_base + NE_DATA); } } /************************************************************************** ETH_PIO_WRITE - Write a frame via Programmed I/O **************************************************************************/ static void eth_pio_write(src, dst, cnt) unsigned char *src; unsigned int dst; unsigned int cnt; { if (eth_flags & FLAG_16BIT) { ++cnt; cnt &= ~1; } outb(eth_nic_base + D8390_P0_COMMAND, D8390_COMMAND_RD2 | D8390_COMMAND_STA); outb(eth_nic_base + D8390_P0_ISR, D8390_ISR_RDC); outb(eth_nic_base + D8390_P0_RBCR0, cnt); outb(eth_nic_base + D8390_P0_RBCR1, cnt>>8); outb(eth_nic_base + D8390_P0_RSAR0, dst); outb(eth_nic_base + D8390_P0_RSAR1, dst>>8); outb(eth_nic_base + D8390_P0_COMMAND, D8390_COMMAND_RD1 | D8390_COMMAND_STA); if (eth_flags & FLAG_16BIT) { cnt >>= 1; /* number of words */ while (cnt--) { outw_p(eth_asic_base + NE_DATA, *((unsigned short *)src)); src += 2; } } else { while (cnt--) outb_p(eth_asic_base + NE_DATA, *(src++)); } while((inb_p(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC) != D8390_ISR_RDC); } #else /************************************************************************** ETH_PIO_READ - Dummy routine when NE2000 not compiled in **************************************************************************/ static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt) {} #endif /************************************************************************** ETH_RESET - Reset adapter **************************************************************************/ static void eth_reset(struct nic *nic) { int i; if (eth_flags & FLAG_790) outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0 | D8390_COMMAND_STP); else outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0 | D8390_COMMAND_RD2 | D8390_COMMAND_STP); if (eth_flags & FLAG_16BIT) outb(eth_nic_base+D8390_P0_DCR, 0x49); else outb(eth_nic_base+D8390_P0_DCR, 0x48); outb(eth_nic_base+D8390_P0_RBCR0, 0); outb(eth_nic_base+D8390_P0_RBCR1, 0); outb(eth_nic_base+D8390_P0_RCR, 0x20); /* monitor mode */ outb(eth_nic_base+D8390_P0_TCR, 2); outb(eth_nic_base+D8390_P0_TPSR, eth_tx_start); outb(eth_nic_base+D8390_P0_PSTART, eth_rx_start); if (eth_flags & FLAG_790) outb(eth_nic_base + 0x09, 0); outb(eth_nic_base+D8390_P0_PSTOP, eth_memsize); outb(eth_nic_base+D8390_P0_BOUND, eth_memsize - 1); outb(eth_nic_base+D8390_P0_ISR, 0xFF); outb(eth_nic_base+D8390_P0_IMR, 0); if (eth_flags & FLAG_790) outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS1 | D8390_COMMAND_STP); else outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS1 | D8390_COMMAND_RD2 | D8390_COMMAND_STP); for (i=0; inode_addr[i]); for (i=0; iaui) outb(eth_asic_base + _3COM_CR, 0); else outb(eth_asic_base + _3COM_CR, _3COM_CR_XSEL); } #endif } /************************************************************************** ETH_TRANSMIT - Transmit a frame **************************************************************************/ static void eth_transmit( struct nic *nic, char *d, /* Destination */ unsigned int t, /* Type */ unsigned int s, /* size */ char *p) /* Packet */ { int c; /* used in NETBOOT16 */ #ifdef INCLUDE_T503 if (eth_vendor == VENDOR_3COM) { #ifdef NETBOOT32 net_bcopy(d, (void *)eth_bmem, ETHER_ADDR_SIZE); /* dst */ net_bcopy(nic->node_addr, (void *)eth_bmem+ETHER_ADDR_SIZE, ETHER_ADDR_SIZE); /* src */ *((char *)eth_bmem+12) = t>>8; /* type */ *((char *)eth_bmem+13) = t; net_bcopy(p, (void *)eth_bmem+ETHER_HDR_SIZE, s); s += ETHER_HDR_SIZE; while (s < ETH_MIN_PACKET) *((char *)eth_bmem+(s++)) = 0; #endif #ifdef NETBOOT16 bcopyf(d, eth_bmem, ETHER_ADDR_SIZE); bcopyf(nic->node_addr, eth_bmem+ETHER_ADDR_SIZE, ETHER_ADDR_SIZE); c = t >> 8; bcopyf(&c, eth_bmem+12, 1); c = t; bcopyf(&c, eth_bmem+13, 1); bcopyf(p, (Address)(eth_bmem+ETHER_HDR_SIZE), s); s += ETHER_HDR_SIZE; if (s < ETH_MIN_PACKET) bzerof(eth_bmem+s, ETH_MIN_PACKET-s), s = ETH_MIN_PACKET; #endif } #endif #ifdef INCLUDE_WD if (eth_vendor == VENDOR_WD) { /* Memory interface */ if (eth_flags & FLAG_16BIT) { outb(eth_asic_base + WD_LAAR, eth_laar | WD_LAAR_M16EN); inb(0x84); } if (eth_flags & FLAG_790) { outb(eth_asic_base + WD_MSR, WD_MSR_MENB); inb(0x84); } inb(0x84); #ifdef NETBOOT32 net_bcopy(d, (void *)eth_bmem, ETHER_ADDR_SIZE); /* dst */ net_bcopy(nic->node_addr, (void *)eth_bmem+ETHER_ADDR_SIZE, ETHER_ADDR_SIZE); /* src */ *((char *)eth_bmem+12) = t>>8; /* type */ *((char *)eth_bmem+13) = t; net_bcopy(p, (void *)eth_bmem+ETHER_HDR_SIZE, s); s += ETHER_HDR_SIZE; while (s < ETH_MIN_PACKET) *((char *)eth_bmem+(s++)) = 0; #endif #ifdef NETBOOT16 bcopyf(d, eth_bmem, ETHER_ADDR_SIZE); bcopyf(nic->node_addr, eth_bmem+ETHER_ADDR_SIZE, ETHER_ADDR_SIZE); c = t >> 8; /* bcc generates worse code without (const+const) below */ bcopyf(&c, eth_bmem+(ETHER_ADDR_SIZE+ETHER_ADDR_SIZE), 1); c = t; bcopyf(&c, eth_bmem+(ETHER_ADDR_SIZE+ETHER_ADDR_SIZE+1), 1); bcopyf(p, (Address)(eth_bmem+ETHER_HDR_SIZE), s); s += ETHER_HDR_SIZE; if (s < ETH_MIN_PACKET) bzerof(eth_bmem+s, ETH_MIN_PACKET-s), s = ETH_MIN_PACKET; #endif if (eth_flags & FLAG_790) { outb(eth_asic_base + WD_MSR, 0); inb(0x84); } if (eth_flags & FLAG_16BIT) { outb(eth_asic_base + WD_LAAR, eth_laar & ~WD_LAAR_M16EN); inb(0x84); } } #endif #if defined(INCLUDE_NE) || defined(INCLUDE_NEPCI) if (eth_vendor == VENDOR_NOVELL) { /* Programmed I/O */ unsigned short type; type = (t >> 8) | (t << 8); eth_pio_write(d, eth_tx_start<<8, ETHER_ADDR_SIZE); eth_pio_write(nic->node_addr, (eth_tx_start<<8)+ETHER_ADDR_SIZE, ETHER_ADDR_SIZE); /* bcc generates worse code without (const+const) below */ eth_pio_write((unsigned char *)&type, (eth_tx_start<<8)+(ETHER_ADDR_SIZE+ETHER_ADDR_SIZE), 2); eth_pio_write(p, (eth_tx_start<<8)+ETHER_HDR_SIZE, s); s += ETHER_HDR_SIZE; if (s < ETH_MIN_PACKET) s = ETH_MIN_PACKET; } #endif if (eth_flags & FLAG_790) outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0 | D8390_COMMAND_STA); else outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0 | D8390_COMMAND_RD2 | D8390_COMMAND_STA); outb(eth_nic_base+D8390_P0_TPSR, eth_tx_start); outb(eth_nic_base+D8390_P0_TBCR0, s); outb(eth_nic_base+D8390_P0_TBCR1, s>>8); if (eth_flags & FLAG_790) outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0 | D8390_COMMAND_TXP | D8390_COMMAND_STA); else outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0 | D8390_COMMAND_TXP | D8390_COMMAND_RD2 | D8390_COMMAND_STA); } /************************************************************************** ETH_POLL - Wait for a frame **************************************************************************/ static int eth_poll(struct nic *nic) { int ret = 0; unsigned char rstat, curr, next; unsigned short len, frag; unsigned short pktoff; unsigned char *p; struct ringbuffer pkthdr; rstat = inb(eth_nic_base+D8390_P0_RSR); if (rstat & D8390_RSTAT_OVER) { eth_reset(nic); return(0); } if (!(rstat & D8390_RSTAT_PRX)) return(0); next = inb(eth_nic_base+D8390_P0_BOUND)+1; if (next >= eth_memsize) next = eth_rx_start; outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS1); curr = inb(eth_nic_base+D8390_P1_CURR); outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0); if (curr >= eth_memsize) curr=eth_rx_start; if (curr == next) return(0); if (eth_vendor == VENDOR_WD) { if (eth_flags & FLAG_16BIT) { outb(eth_asic_base + WD_LAAR, eth_laar | WD_LAAR_M16EN); inb(0x84); } if (eth_flags & FLAG_790) { outb(eth_asic_base + WD_MSR, WD_MSR_MENB); inb(0x84); } inb(0x84); } pktoff = next << 8; if (eth_flags & FLAG_PIO) eth_pio_read(pktoff, (char *)&pkthdr, 4); else #ifdef NETBOOT32 net_bcopy((void *)eth_rmem + pktoff, &pkthdr, 4); #endif #ifdef NETBOOT16 fnet_bcopy(eth_rmem + pktoff, &pkthdr, 4); #endif pktoff += sizeof(pkthdr); len = pkthdr.len - 4; /* sub CRC */ if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || pkthdr.len < ETH_MIN_PACKET || pkthdr.len > ETH_MAX_PACKET) { printf("B"); return (0); } else { p = nic->packet; nic->packetlen = len; /* available to caller */ frag = (eth_memsize << 8) - pktoff; if (len > frag) { /* We have a wrap-around */ /* read first part */ if (eth_flags & FLAG_PIO) eth_pio_read(pktoff, p, frag); else #ifdef NETBOOT32 net_bcopy((void *)eth_rmem + pktoff, p, frag); #endif #ifdef NETBOOT16 fnet_bcopy(eth_rmem + pktoff, p, frag); #endif pktoff = eth_rx_start << 8; p += frag; len -= frag; } /* read second part */ if (eth_flags & FLAG_PIO) eth_pio_read(pktoff, p, len); else #ifdef NETBOOT32 net_bcopy((void *)eth_rmem + pktoff, p, len); #endif #ifdef NETBOOT16 fnet_bcopy(eth_rmem + pktoff, p, len); #endif ret = 1; } if (eth_vendor == VENDOR_WD) { if (eth_flags & FLAG_790) { outb(eth_asic_base + WD_MSR, 0); inb(0x84); } if (eth_flags & FLAG_16BIT) { outb(eth_asic_base + WD_LAAR, eth_laar & ~WD_LAAR_M16EN); inb(0x84); } inb(0x84); } next = pkthdr.next; /* frame number of next packet */ if (next == eth_rx_start) next = eth_memsize; outb(eth_nic_base+D8390_P0_BOUND, next-1); return(ret); } /************************************************************************** ETH_DISABLE - Turn off adapter **************************************************************************/ static void eth_disable(struct nic *nic) { } /************************************************************************** ETH_PROBE - Look for an adapter **************************************************************************/ struct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs) { int i; struct wd_board *brd; unsigned short chksum; unsigned char c; #if defined(INCLUDE_WD) && defined(NETBOOT16) unsigned char bmem13, bmem11; #endif eth_vendor = VENDOR_NONE; #ifdef INCLUDE_WD /****************************************************************** Search for WD/SMC cards ******************************************************************/ for (eth_asic_base = WD_LOW_BASE; eth_asic_base <= WD_HIGH_BASE; eth_asic_base += 0x20) { chksum = 0; for (i=8; i<16; i++) chksum += inb(i+eth_asic_base); if ((chksum & 0x00FF) == 0x00FF) break; } if (eth_asic_base <= WD_HIGH_BASE) { /* We've found a board */ eth_vendor = VENDOR_WD; eth_nic_base = eth_asic_base + WD_NIC_ADDR; c = inb(eth_asic_base+WD_BID); /* Get board id */ for (brd = wd_boards; brd->name; brd++) if (brd->id == c) break; if (!brd->name) { printf("\r\nUnknown Ethernet type %x\r\n", c); return(0); /* Unknown type */ } eth_flags = brd->flags; eth_memsize = brd->memsize; eth_tx_start = 0; eth_rx_start = D8390_TXBUF_SIZE; if ((c == TYPE_WD8013EP) && (inb(eth_asic_base + WD_ICR) & WD_ICR_16BIT)) { eth_flags = FLAG_16BIT; eth_memsize = MEM_16384; } if ((c & WD_SOFTCONFIG) && (!(eth_flags & FLAG_790))) { #ifdef NETBOOT32 eth_bmem = (0x80000 | ((inb(eth_asic_base + WD_MSR) & 0x3F) << 13)); #endif #ifdef NETBOOT16 eth_bmem = inb(eth_asic_base + WD_MSR) & 0x3F; eth_bmem <<= 13; eth_bmem |= 0x80000; #endif } else eth_bmem = WD_DEFAULT_MEM; #ifdef NETBOOT16 /* cast is to force evaluation in long precision */ bmem13 = (Address)eth_bmem >> 13; bmem11 = (Address)eth_bmem >> 11; #endif #ifdef NETBOOT32 if (brd->id == TYPE_SMC8216T || brd->id == TYPE_SMC8216C) { *((unsigned int *)(eth_bmem + 8192)) = (unsigned int)0; if (*((unsigned int *)(eth_bmem + 8192))) { brd += 2; eth_memsize = brd->memsize; } } #endif #ifdef NETBOOT16 if (brd->id == TYPE_SMC8216T || brd->id == TYPE_SMC8216C) { i = 0; bcopyf(&i, eth_bmem + 8192, sizeof(i)); if (!fbsame(eth_bmem + 8192, 0, sizeof(i))) { brd += 2; eth_memsize = brd->memsize; } } #endif outb(eth_asic_base + WD_MSR, 0x80); /* Reset */ printf("\r\n%s base 0x%x, memory 0x%x, addr ", brd->name, eth_asic_base, eth_bmem); for (i=0; inode_addr[i] = inb(i+eth_asic_base+WD_LAR)) & 0xff)); if (i < ETHER_ADDR_SIZE-1) printf (":"); } if (eth_flags & FLAG_790) { outb(eth_asic_base+WD_MSR, WD_MSR_MENB); outb(eth_asic_base+0x04, (inb(eth_asic_base+0x04) | 0x80)); #ifdef NETBOOT32 outb(eth_asic_base+0x0B, (((unsigned)eth_bmem >> 13) & 0x0F) | (((unsigned)eth_bmem >> 11) & 0x40) | (inb(eth_asic_base+0x0B) & 0xB0)); #endif #ifdef NETBOOT16 outb(eth_asic_base+0x0B, (bmem13 & 0x0F) | (bmem11 & 0x40) | (inb(eth_asic_base+0x0B) & 0xB0)); #endif outb(eth_asic_base+0x04, (inb(eth_asic_base+0x04) & ~0x80)); } else { #ifdef NETBOOT32 outb(eth_asic_base+WD_MSR, (((unsigned)eth_bmem >> 13) & 0x3F) | 0x40); #endif #ifdef NETBOOT16 outb(eth_asic_base+WD_MSR, (bmem13 & 0x3F) | 0x40); #endif } if (eth_flags & FLAG_16BIT) { if (eth_flags & FLAG_790) { eth_laar = inb(eth_asic_base + WD_LAAR); outb(eth_asic_base + WD_LAAR, WD_LAAR_M16EN); inb(0x84); } else { outb(eth_asic_base + WD_LAAR, (eth_laar = WD_LAAR_M16EN | WD_LAAR_L16EN | 1)); } } printf("\r\n"); } #endif #ifdef INCLUDE_T503 /****************************************************************** Search for 3Com 3c503 if no WD/SMC cards ******************************************************************/ if (eth_vendor == VENDOR_NONE) { int idx; static unsigned short base[] = { 0x300, 0x310, 0x330, 0x350, 0x250, 0x280, 0x2A0, 0x2E0, 0 }; /* this must parallel the table above */ static unsigned char bcfr[] = { _3COM_BCFR_300, _3COM_BCFR_310, _3COM_BCFR_330, _3COM_BCFR_350, _3COM_BCFR_250, _3COM_BCFR_280, _3COM_BCFR_2A0, _3COM_BCFR_2E0, 0 }; /* Loop through possible addresses checking each one */ for (idx = 0; (eth_nic_base = base[idx]) != 0; ++idx) { eth_asic_base = eth_nic_base + _3COM_ASIC_OFFSET; /* * Note that we use the same settings for both 8 and 16 bit cards: * both have an 8K bank of memory at page 1 while only the 16 bit * cards have a bank at page 0. */ eth_memsize = MEM_16384; eth_tx_start = 32; eth_rx_start = 32 + D8390_TXBUF_SIZE; /* Check our base address */ if (inb(eth_asic_base + _3COM_BCFR) != bcfr[idx]) continue; /* nope */ /* Now get the shared memory address */ switch (inb(eth_asic_base + _3COM_PCFR)) { case _3COM_PCFR_DC000: eth_bmem = 0xdc000; break; case _3COM_PCFR_D8000: eth_bmem = 0xd8000; break; case _3COM_PCFR_CC000: eth_bmem = 0xcc000; break; case _3COM_PCFR_C8000: eth_bmem = 0xc8000; break; default: continue; /* nope */ } break; } if (base[idx] == 0) /* not found */ return (0); eth_vendor = VENDOR_3COM; /* Need this to make eth_poll() happy. */ eth_rmem = eth_bmem - 0x2000; /* Reset NIC and ASIC */ outb (eth_asic_base + _3COM_CR , _3COM_CR_RST | _3COM_CR_XSEL); outb (eth_asic_base + _3COM_CR , _3COM_CR_XSEL); /* Get our ethernet address */ outb(eth_asic_base + _3COM_CR, _3COM_CR_EALO | _3COM_CR_XSEL); printf("\r\n3Com 3c503 base 0x%x, memory 0x%X addr ", eth_nic_base, eth_bmem); for (i=0; inode_addr[i] = inb(eth_nic_base+i))); if (i < ETHER_ADDR_SIZE-1) printf (":"); } outb(eth_asic_base + _3COM_CR, _3COM_CR_XSEL); /* * Initialize GA configuration register. Set bank and enable shared * mem. We always use bank 1. */ outb(eth_asic_base + _3COM_GACFR, _3COM_GACFR_RSEL | _3COM_GACFR_MBS0); outb(eth_asic_base + _3COM_VPTR2, 0xff); outb(eth_asic_base + _3COM_VPTR1, 0xff); outb(eth_asic_base + _3COM_VPTR0, 0x00); /* * Clear memory and verify that it worked (we use only 8K) */ #ifdef NETBOOT32 bzero((char *)eth_bmem, 0x2000); for(i = 0; i < 0x2000; ++i) if (*(((char *)eth_bmem)+i)) { printf ("Failed to clear 3c503 shared mem.\r\n"); return (0); } #endif #ifdef NETBOOT16 bzerof(eth_bmem, 0x2000); if (!fbsame(eth_bmem, 0, 0x2000)) { printf ("Failed to clear 3c503 shared mem.\r\n"); return (0); } #endif /* * Initialize GA page/start/stop registers. */ outb(eth_asic_base + _3COM_PSTR, eth_tx_start); outb(eth_asic_base + _3COM_PSPR, eth_memsize); printf ("\r\n"); } #endif #if defined(INCLUDE_NE) || defined(INCLUDE_NEPCI) /****************************************************************** Search for NE1000/2000 if no WD/SMC or 3com cards ******************************************************************/ if (eth_vendor == VENDOR_NONE) { char romdata[16], testbuf[32]; int idx; static char test[] = "NE1000/2000 memory"; #ifndef NE_SCAN #define NE_SCAN 0 #endif static unsigned short base[] = {NE_SCAN, 0}; /* if no addresses supplied, fall back on defaults */ if (probe_addrs == 0 || probe_addrs[0] == 0) probe_addrs = base; eth_bmem = 0; /* No shared memory */ for (idx = 0; (eth_nic_base = probe_addrs[idx]) != 0; ++idx) { eth_flags = FLAG_PIO; eth_asic_base = eth_nic_base + NE_ASIC_OFFSET; eth_memsize = MEM_16384; eth_tx_start = 32; eth_rx_start = 32 + D8390_TXBUF_SIZE; c = inb(eth_asic_base + NE_RESET); outb(eth_asic_base + NE_RESET, c); inb(0x84); outb(eth_nic_base + D8390_P0_COMMAND, D8390_COMMAND_STP | D8390_COMMAND_RD2); outb(eth_nic_base + D8390_P0_RCR, D8390_RCR_MON); outb(eth_nic_base + D8390_P0_DCR, D8390_DCR_FT1 | D8390_DCR_LS); outb(eth_nic_base + D8390_P0_PSTART, MEM_8192); outb(eth_nic_base + D8390_P0_PSTOP, MEM_16384); eth_pio_write(test, 8192, sizeof(test)); eth_pio_read(8192, testbuf, sizeof(test)); if (!bcmp(test, testbuf, sizeof(test))) break; eth_flags |= FLAG_16BIT; eth_memsize = MEM_32768; eth_tx_start = 64; eth_rx_start = 64 + D8390_TXBUF_SIZE; outb(eth_nic_base + D8390_P0_DCR, D8390_DCR_WTS | D8390_DCR_FT1 | D8390_DCR_LS); outb(eth_nic_base + D8390_P0_PSTART, MEM_16384); outb(eth_nic_base + D8390_P0_PSTOP, MEM_32768); eth_pio_write(test, 16384, sizeof(test)); eth_pio_read(16384, testbuf, sizeof(test)); if (!bcmp(testbuf, test, sizeof(test))) break; } if (eth_nic_base == 0) return (0); if (eth_nic_base > ISA_MAX_ADDR) /* PCI probably */ eth_flags |= FLAG_16BIT; eth_vendor = VENDOR_NOVELL; eth_pio_read(0, romdata, 16); printf("\r\nNE*000 base 0x%x, addr ", eth_nic_base); for (i=0; inode_addr[i] = romdata[i + ((eth_flags & FLAG_16BIT) ? i : 0)])); if (i < ETHER_ADDR_SIZE-1) printf (":"); } printf("\r\n"); } #endif if (eth_vendor == VENDOR_NONE) return(0); if (eth_vendor != VENDOR_3COM) eth_rmem = eth_bmem; eth_reset(nic); nic->reset = eth_reset; nic->poll = eth_poll; nic->transmit = eth_transmit; nic->disable = eth_disable; return(nic); } #endif /* * Local variables: * c-basic-offset: 8 * End: */