diff options
author | martin <martin@FreeBSD.org> | 1995-04-12 20:15:33 +0000 |
---|---|---|
committer | martin <martin@FreeBSD.org> | 1995-04-12 20:15:33 +0000 |
commit | 669ed5b46ea62e3997fc8495702ddc9078fa7031 (patch) | |
tree | dec6b61a819c56055fd0a9d76b463dd654b30e35 /sys | |
parent | e3bdb075c7943144df547cff34aec0f6d3523f1d (diff) | |
download | FreeBSD-src-669ed5b46ea62e3997fc8495702ddc9078fa7031.zip FreeBSD-src-669ed5b46ea62e3997fc8495702ddc9078fa7031.tar.gz |
Break netboot into device specific versions.
nb8390.[cr]om for NS8390 boards (if_ed driver)
nb3c509.[cr]om for 3c509 boards (if_ep driver)
Submitted by: Serge Babkin (babkin@hq.icb.chel.su) [3c509 support]
Diffstat (limited to 'sys')
-rw-r--r-- | sys/i386/boot/netboot/3c509.c | 602 | ||||
-rw-r--r-- | sys/i386/boot/netboot/3c509.h | 388 | ||||
-rw-r--r-- | sys/i386/boot/netboot/Makefile | 58 | ||||
-rw-r--r-- | sys/i386/boot/netboot/bootmenu.c | 35 | ||||
-rw-r--r-- | sys/i386/boot/netboot/main.c | 13 | ||||
-rw-r--r-- | sys/i386/boot/netboot/makerom.c | 13 | ||||
-rw-r--r-- | sys/i386/boot/netboot/netboot.h | 15 | ||||
-rw-r--r-- | sys/i386/boot/netboot/ns8390.c | 634 | ||||
-rw-r--r-- | sys/i386/boot/netboot/ns8390.h | 246 |
9 files changed, 1930 insertions, 74 deletions
diff --git a/sys/i386/boot/netboot/3c509.c b/sys/i386/boot/netboot/3c509.c new file mode 100644 index 0000000..b729a46 --- /dev/null +++ b/sys/i386/boot/netboot/3c509.c @@ -0,0 +1,602 @@ +/************************************************************************** +NETBOOT - BOOTP/TFTP Bootstrap Program + +Author: Martin Renters. + Date: Mar 22 1995 + + This code is based heavily on David Greenman's if_ed.c driver and + Andres Vega Garcia's if_ep.c driver. + + Copyright (C) 1993-1994, David Greenman, Martin Renters. + Copyright (C) 1993-1995, Andres Vega Garcia. + Copyright (C) 1995, Serge Babkin. + 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. + +3c509 support added by Serge Babkin (babkin@hq.icb.chel.su) + +$Id: 3c509.c,v 1.1 1995/04/11 05:37:59 root Exp root $ + +***************************************************************************/ + +/* #define EDEBUG */ + +#include "netboot.h" +#include "3c509.h" + +short aui; +char bnc=0, utp=0; /* for 3C509 */ +unsigned short eth_nic_base; +unsigned short eth_asic_base; +unsigned short eth_base; +unsigned char eth_tx_start; +unsigned char eth_laar; +unsigned char eth_flags; +unsigned char eth_vendor; +unsigned char eth_memsize; +unsigned char *eth_bmem; +unsigned char *eth_rmem; +unsigned char *eth_node_addr; + +static send_ID_sequence(); +static get_eeprom_data(); +static get_e(); + +/************************************************************************** +The following two variables are used externally +***************************************************************************/ +char packet[ETH_MAX_PACKET]; +int packetlen; + +/*********************** Name of driver *********************************/ + +char eth_driver[]="ep0"; + +/************************************************************************** +ETH_PROBE - Look for an adapter +***************************************************************************/ +eth_probe() +{ + /* common variables */ + int i; + /* variables for 3C509 */ + int data, j, io_base, id_port = EP_ID_PORT; + int nisa = 0, neisa = 0; + u_short k; + int ep_current_tag = EP_LAST_TAG + 1; + short *p; + + eth_vendor = VENDOR_NONE; + + /********************************************************* + Search for 3Com 509 card + ***********************************************************/ + + /* Look for the EISA boards, leave them activated */ + /* search for the first card, ignore all others */ + for(j = 1; j < 16 && eth_vendor==VENDOR_NONE ; j++) { + io_base = (j * EP_EISA_START) | EP_EISA_W0; + if (inw(io_base + EP_W0_MFG_ID) != MFG_ID) + continue; + + /* we must found 0x1f if the board is EISA configurated */ + if ((inw(io_base + EP_W0_ADDRESS_CFG) & 0x1f) != 0x1f) + continue; + + /* Reset and Enable the card */ + outb(io_base + EP_W0_CONFIG_CTRL, W0_P4_CMD_RESET_ADAPTER); + DELAY(1000); /* we must wait at least 1 ms */ + outb(io_base + EP_W0_CONFIG_CTRL, W0_P4_CMD_ENABLE_ADAPTER); + + /* + * Once activated, all the registers are mapped in the range + * x000 - x00F, where x is the slot number. + */ + eth_base = j * EP_EISA_START; + eth_vendor = VENDOR_3C509; + } + ep_current_tag--; + + /* Look for the ISA boards. Init and leave them actived */ + /* search for the first card, ignore all others */ + outb(id_port, 0xc0); /* Global reset */ + DELAY(1000); + for (i = 0; i < EP_MAX_BOARDS && eth_vendor==VENDOR_NONE; i++) { + outb(id_port, 0); + outb(id_port, 0); + send_ID_sequence(id_port); + + data = get_eeprom_data(id_port, EEPROM_MFG_ID); + if (data != MFG_ID) + break; + + /* resolve contention using the Ethernet address */ + for (j = 0; j < 3; j++) + data = get_eeprom_data(id_port, j); + + eth_base = + (get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) * 0x10 + 0x200; + outb(id_port, ep_current_tag); /* tags board */ + outb(id_port, ACTIVATE_ADAPTER_TO_CONFIG); + eth_vendor = VENDOR_3C509; + ep_current_tag--; + } + + if(eth_vendor != VENDOR_3C509) + goto no3c509; + + /* + * The iobase was found and MFG_ID was 0x6d50. PROD_ID should be + * 0x9[0-f]50 + */ + GO_WINDOW(0); + k = get_e(EEPROM_PROD_ID); + if ((k & 0xf0ff) != (PROD_ID & 0xf0ff)) + goto no3c509; + + if(eth_base >= EP_EISA_START) { + printf("3C5x9 board on EISA at 0x%x - ",eth_base); + } else { + printf("3C5x9 board on ISA at 0x%x - ",eth_base); + } + + /* test for presence of connectors */ + i = inw(IS_BASE + EP_W0_CONFIG_CTRL); + j = inw(IS_BASE + EP_W0_ADDRESS_CFG) >> 14; + + switch(j) { + case 0: + if(i & IS_UTP) { + printf("10baseT\r\n"); + utp=1; + } + else { + printf("10baseT not present\r\n"); + eth_vendor=VENDOR_NONE; + goto no3c509; + } + + break; + case 1: + if(i & IS_AUI) + printf("10base5\r\n"); + else { + printf("10base5 not present\r\n"); + eth_vendor=VENDOR_NONE; + goto no3c509; + } + + break; + case 3: + if(i & IS_BNC) { + printf("10base2\r\n"); + bnc=1; + } + else { + printf("10base2 not present\r\n"); + eth_vendor=VENDOR_NONE; + goto no3c509; + } + + break; + default: + printf("unknown connector\r\n"); + eth_vendor=VENDOR_NONE; + goto no3c509; + } + /* + * Read the station address from the eeprom + */ + p = (u_short *) arptable[ARP_CLIENT].node; + for (i = 0; i < 3; i++) { + GO_WINDOW(0); + p[i] = htons(get_e(i)); + GO_WINDOW(2); + outw(BASE + EP_W2_ADDR_0 + (i * 2), ntohs(p[i])); + } + + printf("Ethernet address: "); + for(i=0; i<5; i++) { + printf("%b:",arptable[ARP_CLIENT].node[i]); + } + printf("%b\n",arptable[ARP_CLIENT].node[i]); + + eth_node_addr = arptable[ARP_CLIENT].node; + eth_reset(); + return eth_vendor; +no3c509: + eth_vendor = VENDOR_NONE; + + return VENDOR_NONE; +} + +/************************************************************************** +ETH_RESET - Reset adapter +***************************************************************************/ +eth_reset() +{ + int s, i; + + /*********************************************************** + Reset 3Com 509 card + *************************************************************/ + + if(eth_vendor != VENDOR_3C509) + goto no3c509; + + /* stop card */ + outw(BASE + EP_COMMAND, RX_DISABLE); + outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK); + while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS); + outw(BASE + EP_COMMAND, TX_DISABLE); + outw(BASE + EP_COMMAND, STOP_TRANSCEIVER); + outw(BASE + EP_COMMAND, RX_RESET); + outw(BASE + EP_COMMAND, TX_RESET); + outw(BASE + EP_COMMAND, C_INTR_LATCH); + outw(BASE + EP_COMMAND, SET_RD_0_MASK); + outw(BASE + EP_COMMAND, SET_INTR_MASK); + outw(BASE + EP_COMMAND, SET_RX_FILTER); + + /* + /* initialize card + */ + while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS); + + GO_WINDOW(0); + + /* Disable the card */ + outw(BASE + EP_W0_CONFIG_CTRL, 0); + + /* Configure IRQ to none */ + outw(BASE + EP_W0_RESOURCE_CFG, SET_IRQ(0)); + + /* Enable the card */ + outw(BASE + EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ); + + GO_WINDOW(2); + + /* Reload the ether_addr. */ + for (i = 0; i < 6; i++) + outb(BASE + EP_W2_ADDR_0 + i, arptable[ARP_CLIENT].node[i]); + + outw(BASE + EP_COMMAND, RX_RESET); + outw(BASE + EP_COMMAND, TX_RESET); + + /* Window 1 is operating window */ + GO_WINDOW(1); + for (i = 0; i < 31; i++) + inb(BASE + EP_W1_TX_STATUS); + + /* get rid of stray intr's */ + outw(BASE + EP_COMMAND, ACK_INTR | 0xff); + + outw(BASE + EP_COMMAND, SET_RD_0_MASK | S_5_INTS); + + outw(BASE + EP_COMMAND, SET_INTR_MASK | S_5_INTS); + + outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | + FIL_BRDCST); + + /* configure BNC */ + if(bnc) { + outw(BASE + EP_COMMAND, START_TRANSCEIVER); + DELAY(1000); + } + /* configure UTP */ + if(utp) { + GO_WINDOW(4); + outw(BASE + EP_W4_MEDIA_TYPE, ENABLE_UTP); + GO_WINDOW(1); + } + + /* start tranciever and receiver */ + outw(BASE + EP_COMMAND, RX_ENABLE); + outw(BASE + EP_COMMAND, TX_ENABLE); + + /* set early threshold for minimal packet length */ + outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | 64); + + outw(BASE + EP_COMMAND, SET_TX_START_THRESH | 16); + + return 1; +no3c509: + +} + +/************************************************************************** +ETH_TRANSMIT - Transmit a frame +***************************************************************************/ +static const char padmap[] = { + 0, 3, 2, 1}; + +eth_transmit(d,t,s,p) +char *d; /* Destination */ +unsigned short t; /* Type */ +unsigned short s; /* size */ +char *p; /* Packet */ +{ + register u_int len; + int pad; + int status; + unsigned char c; + + if(eth_vendor != VENDOR_3C509) + goto no3c509; + +#ifdef EDEBUG + printf("{l=%d,t=%x}",s+14,t); +#endif + + /* swap bytes of type */ + t=(( t&0xFF )<<8) | ((t>>8) & 0xFF); + + len=s+14; /* actual length of packet */ + pad = padmap[len & 3]; + + /* + * The 3c509 automatically pads short packets to minimum ethernet length, + * but we drop packets that are too large. Perhaps we should truncate + * them instead? + */ + if (len + pad > ETHER_MAX_LEN) { + return 0; + } + + /* drop acknowledgements */ + while(( status=inb(BASE + EP_W1_TX_STATUS) )& TXS_COMPLETE ) { + if(status & (TXS_UNDERRUN|TXS_MAX_COLLISION|TXS_STATUS_OVERFLOW)) { + outw(BASE + EP_COMMAND, TX_RESET); + outw(BASE + EP_COMMAND, TX_ENABLE); + } + + outb(BASE + EP_W1_TX_STATUS, 0x0); + } + + while (inw(BASE + EP_W1_FREE_TX) < len + pad + 4) { + /* no room in FIFO */ + } + + outw(BASE + EP_W1_TX_PIO_WR_1, len); + outw(BASE + EP_W1_TX_PIO_WR_1, 0x0); /* Second dword meaningless */ + + /* write packet */ + outsw(BASE + EP_W1_TX_PIO_WR_1, d, 3); + outsw(BASE + EP_W1_TX_PIO_WR_1, eth_node_addr, 3); + outw(BASE + EP_W1_TX_PIO_WR_1, t); + outsw(BASE + EP_W1_TX_PIO_WR_1, p, s / 2); + if (s & 1) + outb(BASE + EP_W1_TX_PIO_WR_1, *(p+s - 1)); + + while (pad--) + outb(BASE + EP_W1_TX_PIO_WR_1, 0); /* Padding */ + + /* timeout after sending */ + DELAY(1000); + return 0; +no3c509: +} + +/************************************************************************** +ETH_POLL - Wait for a frame +***************************************************************************/ +eth_poll() +{ + /* common variables */ + unsigned short type = 0; + unsigned short len; + /* variables for 3C509 */ + struct ether_header *eh; + int lenthisone; + short rx_fifo2, status, cst; + register short rx_fifo; + + if(eth_vendor!=VENDOR_3C509) + goto no3c509; + + cst=inw(BASE + EP_STATUS); + +#ifdef EDEBUG + if(cst & 0x1FFF) + printf("-%x-",cst); +#endif + + if( (cst & (S_RX_COMPLETE|S_RX_EARLY) )==0 ) { + /* acknowledge everything */ + outw(BASE + EP_COMMAND, ACK_INTR| (cst & S_5_INTS)); + outw(BASE + EP_COMMAND, C_INTR_LATCH); + + return 0; + } + + status = inw(BASE + EP_W1_RX_STATUS); +#ifdef EDEBUG + printf("*%x*",status); +#endif + + if (status & ERR_RX) { + outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK); + return 0; + } + + rx_fifo = status & RX_BYTES_MASK; + if (rx_fifo==0) + return 0; + + /* read packet */ +#ifdef EDEBUG + printf("[l=%d",rx_fifo); +#endif + insw(BASE + EP_W1_RX_PIO_RD_1, packet, rx_fifo / 2); + if(rx_fifo & 1) + packet[rx_fifo-1]=inb(BASE + EP_W1_RX_PIO_RD_1); + packetlen=rx_fifo; + + while(1) { + status = inw(BASE + EP_W1_RX_STATUS); +#ifdef EDEBUG + printf("*%x*",status); +#endif + rx_fifo = status & RX_BYTES_MASK; + + if(rx_fifo>0) { + insw(BASE + EP_W1_RX_PIO_RD_1, packet+packetlen, rx_fifo / 2); + if(rx_fifo & 1) + packet[packetlen+rx_fifo-1]=inb(BASE + EP_W1_RX_PIO_RD_1); + packetlen+=rx_fifo; +#ifdef EDEBUG + printf("+%d",rx_fifo); +#endif + } + + if(( status & RX_INCOMPLETE )==0) { +#ifdef EDEBUG + printf("=%d",packetlen); +#endif + break; + } + + DELAY(1000); + } + + /* acknowledge reception of packet */ + outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK); + while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS); + + type = (packet[12]<<8) | packet[13]; + +#ifdef EDEBUG + if(packet[0]+packet[1]+packet[2]+packet[3]+packet[4]+ + packet[5] == 0xFF*6) + printf(",t=0x%x,b]",type); + else + printf(",t=0x%x]",type); +#endif + + + if (type == ARP) { + struct arprequest *arpreq; + unsigned long reqip; + + arpreq = (struct arprequest *)&packet[ETHER_HDR_SIZE]; + +#ifdef EDEBUG + printf("(ARP %I->%I)",ntohl(*(int*)arpreq->sipaddr), + ntohl(*(int*)arpreq->tipaddr)); +#endif + + convert_ipaddr(&reqip, arpreq->tipaddr); + if ((ntohs(arpreq->opcode) == ARP_REQUEST) && + (reqip == arptable[ARP_CLIENT].ipaddr)) { + arpreq->opcode = htons(ARP_REPLY); + bcopy(arpreq->sipaddr, arpreq->tipaddr, 4); + bcopy(arpreq->shwaddr, arpreq->thwaddr, 6); + bcopy(arptable[ARP_CLIENT].node, arpreq->shwaddr, 6); + convert_ipaddr(arpreq->sipaddr, &reqip); + eth_transmit(arpreq->thwaddr, ARP, sizeof(struct arprequest), + arpreq); + return(0); + } + } else if(type==IP) { + struct iphdr *iph; + + iph = (struct iphdr *)&packet[ETHER_HDR_SIZE]; +#ifdef EDEBUG + printf("(IP %I-%d->%I)",ntohl(*(int*)iph->src), + ntohs(iph->protocol),ntohl(*(int*)iph->dest)); +#endif + } + + return 1; + +no3c509: +} + + +/************************************************************************* + 3Com 509 - specific routines +**************************************************************************/ + +static int +eeprom_rdy() +{ + int i; + + for (i = 0; is_eeprom_busy(IS_BASE) && i < MAX_EEPROMBUSY; i++); + if (i >= MAX_EEPROMBUSY) { + printf("3c509: eeprom failed to come ready.\r\n"); + return (0); + } + return (1); +} + +/* + * get_e: gets a 16 bits word from the EEPROM. we must have set the window + * before + */ +static int +get_e(offset) +int offset; +{ + if (!eeprom_rdy()) + return (0xffff); + outw(IS_BASE + EP_W0_EEPROM_COMMAND, EEPROM_CMD_RD | offset); + if (!eeprom_rdy()) + return (0xffff); + return (inw(IS_BASE + EP_W0_EEPROM_DATA)); +} + +static int +send_ID_sequence(port) +int port; +{ + int cx, al; + + for (al = 0xff, cx = 0; cx < 255; cx++) { + outb(port, al); + al <<= 1; + if (al & 0x100) + al ^= 0xcf; + } + return (1); +} + + +/* + * We get eeprom data from the id_port given an offset into the eeprom. + * Basically; after the ID_sequence is sent to all of the cards; they enter + * the ID_CMD state where they will accept command requests. 0x80-0xbf loads + * the eeprom data. We then read the port 16 times and with every read; the + * cards check for contention (ie: if one card writes a 0 bit and another + * writes a 1 bit then the host sees a 0. At the end of the cycle; each card + * compares the data on the bus; if there is a difference then that card goes + * into ID_WAIT state again). In the meantime; one bit of data is returned in + * the AX register which is conveniently returned to us by inb(). Hence; we + * read 16 times getting one bit of data with each read. + */ +static int +get_eeprom_data(id_port, offset) +int id_port; +int offset; +{ + int i, data = 0; + outb(id_port, 0x80 + offset); + DELAY(1000); + for (i = 0; i < 16; i++) + data = (data << 1) | (inw(id_port) & 1); + return (data); +} + +/* a surrogate */ + +DELAY(val) +{ + int c; + + for(c=0; c<val; c+=20) { + twiddle(); + } +} + diff --git a/sys/i386/boot/netboot/3c509.h b/sys/i386/boot/netboot/3c509.h new file mode 100644 index 0000000..049f235 --- /dev/null +++ b/sys/i386/boot/netboot/3c509.h @@ -0,0 +1,388 @@ +/* + * Copyright (c) 1993 Herb Peyerl (hpeyerl@novatel.ca) All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. 2. The name + * of the author may not be used to endorse or promote products derived from + * this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * if_epreg.h,v 1.4 1994/11/13 10:12:37 gibbs Exp Modified by: + * + October 2, 1994 + + Modified by: Andres Vega Garcia + + INRIA - Sophia Antipolis, France + e-mail: avega@sophia.inria.fr + finger: avega@pax.inria.fr + + */ + +/* + * Ethernet software status per interface. + */ +/* + * Some global constants + */ +#define ETHER_MIN_LEN 64 +#define ETHER_MAX_LEN 1518 +#define ETHER_ADDR_LEN 6 + +#define TX_INIT_RATE 16 +#define TX_INIT_MAX_RATE 64 +#define RX_INIT_LATENCY 64 +#define RX_INIT_EARLY_THRESH 64 +#define MIN_RX_EARLY_THRESHF 16 /* not less than ether_header */ +#define MIN_RX_EARLY_THRESHL 4 + +#define EEPROMSIZE 0x40 +#define MAX_EEPROMBUSY 1000 +#define EP_LAST_TAG 0xd7 +#define EP_MAX_BOARDS 16 +#define EP_ID_PORT 0x100 + +/* + * some macros to acces long named fields + */ +#define IS_BASE (eth_base) +#define BASE (eth_base) + +/* + * Commands to read/write EEPROM trough EEPROM command register (Window 0, + * Offset 0xa) + */ +#define EEPROM_CMD_RD 0x0080 /* Read: Address required (5 bits) */ +#define EEPROM_CMD_WR 0x0040 /* Write: Address required (5 bits) */ +#define EEPROM_CMD_ERASE 0x00c0 /* Erase: Address required (5 bits) */ +#define EEPROM_CMD_EWEN 0x0030 /* Erase/Write Enable: No data required */ + +#define EEPROM_BUSY (1<<15) +#define EEPROM_TST_MODE (1<<14) + +/* + * Some short functions, worth to let them be a macro + */ +#define is_eeprom_busy(b) (inw((b)+EP_W0_EEPROM_COMMAND)&EEPROM_BUSY) +#define GO_WINDOW(x) outw(BASE+EP_COMMAND, WINDOW_SELECT|(x)) + +/************************************************************************** + * * + * These define the EEPROM data structure. They are used in the probe + * function to verify the existance of the adapter after having sent + * the ID_Sequence. + * + * There are others but only the ones we use are defined here. + * + **************************************************************************/ + +#define EEPROM_NODE_ADDR_0 0x0 /* Word */ +#define EEPROM_NODE_ADDR_1 0x1 /* Word */ +#define EEPROM_NODE_ADDR_2 0x2 /* Word */ +#define EEPROM_PROD_ID 0x3 /* 0x9[0-f]50 */ +#define EEPROM_MFG_ID 0x7 /* 0x6d50 */ +#define EEPROM_ADDR_CFG 0x8 /* Base addr */ +#define EEPROM_RESOURCE_CFG 0x9 /* IRQ. Bits 12-15 */ + +/************************************************************************** + * * + * These are the registers for the 3Com 3c509 and their bit patterns when * + * applicable. They have been taken out the the "EtherLink III Parallel * + * Tasking EISA and ISA Technical Reference" "Beta Draft 10/30/92" manual * + * from 3com. * + * * + **************************************************************************/ + +#define EP_COMMAND 0x0e /* Write. BASE+0x0e is always a + * command reg. */ +#define EP_STATUS 0x0e /* Read. BASE+0x0e is always status + * reg. */ +#define EP_WINDOW 0x0f /* Read. BASE+0x0f is always window + * reg. */ +/* + * Window 0 registers. Setup. + */ +/* Write */ +#define EP_W0_EEPROM_DATA 0x0c +#define EP_W0_EEPROM_COMMAND 0x0a +#define EP_W0_RESOURCE_CFG 0x08 +#define EP_W0_ADDRESS_CFG 0x06 +#define EP_W0_CONFIG_CTRL 0x04 +/* Read */ +#define EP_W0_PRODUCT_ID 0x02 +#define EP_W0_MFG_ID 0x00 + +/* + * Window 1 registers. Operating Set. + */ +/* Write */ +#define EP_W1_TX_PIO_WR_2 0x02 +#define EP_W1_TX_PIO_WR_1 0x00 +/* Read */ +#define EP_W1_FREE_TX 0x0c +#define EP_W1_TX_STATUS 0x0b /* byte */ +#define EP_W1_TIMER 0x0a /* byte */ +#define EP_W1_RX_STATUS 0x08 +#define EP_W1_RX_PIO_RD_2 0x02 +#define EP_W1_RX_PIO_RD_1 0x00 + +/* + * Window 2 registers. Station Address Setup/Read + */ +/* Read/Write */ +#define EP_W2_ADDR_5 0x05 +#define EP_W2_ADDR_4 0x04 +#define EP_W2_ADDR_3 0x03 +#define EP_W2_ADDR_2 0x02 +#define EP_W2_ADDR_1 0x01 +#define EP_W2_ADDR_0 0x00 + +/* + * Window 3 registers. FIFO Management. + */ +/* Read */ +#define EP_W3_FREE_TX 0x0c +#define EP_W3_FREE_RX 0x0a + +/* + * Window 4 registers. Diagnostics. + */ +/* Read/Write */ +#define EP_W4_MEDIA_TYPE 0x0a +#define EP_W4_CTRLR_STATUS 0x08 +#define EP_W4_NET_DIAG 0x06 +#define EP_W4_FIFO_DIAG 0x04 +#define EP_W4_HOST_DIAG 0x02 +#define EP_W4_TX_DIAG 0x00 + +/* + * Window 5 Registers. Results and Internal status. + */ +/* Read */ +#define EP_W5_READ_0_MASK 0x0c +#define EP_W5_INTR_MASK 0x0a +#define EP_W5_RX_FILTER 0x08 +#define EP_W5_RX_EARLY_THRESH 0x06 +#define EP_W5_TX_AVAIL_THRESH 0x02 +#define EP_W5_TX_START_THRESH 0x00 + +/* + * Window 6 registers. Statistics. + */ +/* Read/Write */ +#define TX_TOTAL_OK 0x0c +#define RX_TOTAL_OK 0x0a +#define TX_DEFERRALS 0x08 +#define RX_FRAMES_OK 0x07 +#define TX_FRAMES_OK 0x06 +#define RX_OVERRUNS 0x05 +#define TX_COLLISIONS 0x04 +#define TX_AFTER_1_COLLISION 0x03 +#define TX_AFTER_X_COLLISIONS 0x02 +#define TX_NO_SQE 0x01 +#define TX_CD_LOST 0x00 + +/**************************************** + * + * Register definitions. + * + ****************************************/ + +/* + * Command register. All windows. + * + * 16 bit register. + * 15-11: 5-bit code for command to be executed. + * 10-0: 11-bit arg if any. For commands with no args; + * this can be set to anything. + */ +#define GLOBAL_RESET (u_short) 0x0000 /* Wait at least 1ms + * after issuing */ +#define WINDOW_SELECT (u_short) (0x1<<11) +#define START_TRANSCEIVER (u_short) (0x2<<11) /* Read ADDR_CFG reg to + * determine whether + * this is needed. If + * so; wait 800 uSec + * before using trans- + * ceiver. */ +#define RX_DISABLE (u_short) (0x3<<11) /* state disabled on + * power-up */ +#define RX_ENABLE (u_short) (0x4<<11) +#define RX_RESET (u_short) (0x5<<11) +#define RX_DISCARD_TOP_PACK (u_short) (0x8<<11) +#define TX_ENABLE (u_short) (0x9<<11) +#define TX_DISABLE (u_short) (0xa<<11) +#define TX_RESET (u_short) (0xb<<11) +#define REQ_INTR (u_short) (0xc<<11) +#define SET_INTR_MASK (u_short) (0xe<<11) +#define SET_RD_0_MASK (u_short) (0xf<<11) +#define SET_RX_FILTER (u_short) (0x10<<11) +#define FIL_INDIVIDUAL (u_short) (0x1) +#define FIL_GROUP (u_short) (0x2) +#define FIL_BRDCST (u_short) (0x4) +#define FIL_ALL (u_short) (0x8) +#define SET_RX_EARLY_THRESH (u_short) (0x11<<11) +#define SET_TX_AVAIL_THRESH (u_short) (0x12<<11) +#define SET_TX_START_THRESH (u_short) (0x13<<11) +#define STATS_ENABLE (u_short) (0x15<<11) +#define STATS_DISABLE (u_short) (0x16<<11) +#define STOP_TRANSCEIVER (u_short) (0x17<<11) +/* + * The following C_* acknowledge the various interrupts. Some of them don't + * do anything. See the manual. + */ +#define ACK_INTR (u_short) (0x6800) +#define C_INTR_LATCH (u_short) (ACK_INTR|0x1) +#define C_CARD_FAILURE (u_short) (ACK_INTR|0x2) +#define C_TX_COMPLETE (u_short) (ACK_INTR|0x4) +#define C_TX_AVAIL (u_short) (ACK_INTR|0x8) +#define C_RX_COMPLETE (u_short) (ACK_INTR|0x10) +#define C_RX_EARLY (u_short) (ACK_INTR|0x20) +#define C_INT_RQD (u_short) (ACK_INTR|0x40) +#define C_UPD_STATS (u_short) (ACK_INTR|0x80) + +/* + * Status register. All windows. + * + * 15-13: Window number(0-7). + * 12: Command_in_progress. + * 11: reserved. + * 10: reserved. + * 9: reserved. + * 8: reserved. + * 7: Update Statistics. + * 6: Interrupt Requested. + * 5: RX Early. + * 4: RX Complete. + * 3: TX Available. + * 2: TX Complete. + * 1: Adapter Failure. + * 0: Interrupt Latch. + */ +#define S_INTR_LATCH (u_short) (0x1) +#define S_CARD_FAILURE (u_short) (0x2) +#define S_TX_COMPLETE (u_short) (0x4) +#define S_TX_AVAIL (u_short) (0x8) +#define S_RX_COMPLETE (u_short) (0x10) +#define S_RX_EARLY (u_short) (0x20) +#define S_INT_RQD (u_short) (0x40) +#define S_UPD_STATS (u_short) (0x80) +#define S_5_INTS (S_CARD_FAILURE|S_TX_COMPLETE|\ + S_TX_AVAIL|S_RX_COMPLETE|S_RX_EARLY) +#define S_COMMAND_IN_PROGRESS (u_short) (0x1000) + +/* + * FIFO Registers. + * RX Status. Window 1/Port 08 + * + * 15: Incomplete or FIFO empty. + * 14: 1: Error in RX Packet 0: Incomplete or no error. + * 13-11: Type of error. + * 1000 = Overrun. + * 1011 = Run Packet Error. + * 1100 = Alignment Error. + * 1101 = CRC Error. + * 1001 = Oversize Packet Error (>1514 bytes) + * 0010 = Dribble Bits. + * (all other error codes, no errors.) + * + * 10-0: RX Bytes (0-1514) + */ +#define ERR_RX_INCOMPLETE (u_short) (0x1<<15) +#define ERR_RX (u_short) (0x1<<14) +#define ERR_RX_OVERRUN (u_short) (0x8<<11) +#define ERR_RX_RUN_PKT (u_short) (0xb<<11) +#define ERR_RX_ALIGN (u_short) (0xc<<11) +#define ERR_RX_CRC (u_short) (0xd<<11) +#define ERR_RX_OVERSIZE (u_short) (0x9<<11) +#define ERR_RX_DRIBBLE (u_short) (0x2<<11) + +/* + * FIFO Registers. + * TX Status. Window 1/Port 0B + * + * Reports the transmit status of a completed transmission. Writing this + * register pops the transmit completion stack. + * + * Window 1/Port 0x0b. + * + * 7: Complete + * 6: Interrupt on successful transmission requested. + * 5: Jabber Error (TP Only, TX Reset required. ) + * 4: Underrun (TX Reset required. ) + * 3: Maximum Collisions. + * 2: TX Status Overflow. + * 1-0: Undefined. + * + */ +#define TXS_COMPLETE 0x80 +#define TXS_SUCCES_INTR_REQ 0x40 +#define TXS_JABBER 0x20 +#define TXS_UNDERRUN 0x10 +#define TXS_MAX_COLLISION 0x8 +#define TXS_STATUS_OVERFLOW 0x4 + +/* + * Configuration control register. + * Window 0/Port 04 + */ +/* Read */ +#define IS_AUI (1<<13) +#define IS_BNC (1<<12) +#define IS_UTP (1<<9) +/* Write */ +#define ENABLE_DRQ_IRQ 0x0001 +#define W0_P4_CMD_RESET_ADAPTER 0x4 +#define W0_P4_CMD_ENABLE_ADAPTER 0x1 +/* + * Media type and status. + * Window 4/Port 0A + */ +#define ENABLE_UTP 0xc0 +#define DISABLE_UTP 0x0 + +/* + * Resource control register + */ + +#define SET_IRQ(i) ( ((i)<<12) | 0xF00) /* set IRQ i */ + +/* + * Receive status register + */ + +#define RX_BYTES_MASK (u_short) (0x07ff) +#define RX_ERROR 0x4000 +#define RX_INCOMPLETE 0x8000 + + +/* + * Misc defines for various things. + */ +#define ACTIVATE_ADAPTER_TO_CONFIG 0xff /* to the id_port */ +#define MFG_ID 0x6d50 /* in EEPROM and W0 ADDR_CONFIG */ +#define PROD_ID 0x9150 + +#define AUI 0x1 +#define BNC 0x2 +#define UTP 0x4 + +#define ETHER_ADDR_LEN 6 +#define ETHER_MAX 1536 +#define RX_BYTES_MASK (u_short) (0x07ff) + + /* EISA support */ +#define EP_EISA_START 0x1000 +#define EP_EISA_W0 0x0c80 diff --git a/sys/i386/boot/netboot/Makefile b/sys/i386/boot/netboot/Makefile index ded6b0c..51a8b5f 100644 --- a/sys/i386/boot/netboot/Makefile +++ b/sys/i386/boot/netboot/Makefile @@ -2,15 +2,15 @@ # # Makefile for NETBOOT # -# Options: +# Basic Options: # -DASK_BOOT - Ask "Boot from Network (Y/N) ?" at startup -# -DSMALL_ROM - Compile for 8K ROMS # -DROMSIZE - Size of EPROM - Must be set (even for .COM files) # -DRELOC - Relocation address (usually 0x90000) +# +# NS8390 Options: # -DINCLUDE_WD - Include Western Digital/SMC support # -DINCLUDE_NE - Include NE1000/NE2000 support # -DINCLUDE_3COM - Include 3c503 support -# -DINCLUDE_3C509 - Include 3c509 support # -D_3COM_USE_AUI - Disable transceiver on 3c503 by default # -DNE_BASE - Base I/O address for NE1000/NE2000 # -D_3COM_BASE - Base I/O address for 3c503 @@ -19,20 +19,18 @@ # changing an option. # -PROG= netboot.com +PROG= nb8390.com nb3c509.com nb8390.rom nb3c509.rom # Order is very important on the SRCS line for this prog -SRCS= start2.S main.c misc.c ether.c bootmenu.c rpc.c +SRCS= start2.S main.c misc.c bootmenu.c rpc.c BINDIR= /usr/mdec BINMODE= 555 CFLAGS= -O2 -DNFS -DROMSIZE=${ROMSIZE} -DRELOC=${RELOCADDR} -DASK_BOOT -CFLAGS+= -DINCLUDE_WD -DWD_DEFAULT_MEM=0xD0000 -CFLAGS+= -DINCLUDE_NE -DNE_BASE=0x320 -CFLAGS+= -DINCLUDE_3COM -D_3COM_BASE=0x300 -CFLAGS+= -DINCLUDE_3C509 -CLEANFILES+= netboot.com.nohdr netboot.com.strip -CLEANFILES+= netboot.rom.nohdr netboot.rom.strip netboot.rom -CLEANFILES+= makerom start2.ro +NS8390= -DINCLUDE_WD -DWD_DEFAULT_MEM=0xD0000 +NS8390+= -DINCLUDE_NE -DNE_BASE=0x320 +NS8390+= -DINCLUDE_3COM -D_3COM_BASE=0x300 +CLEANFILES+= netboot.com +CLEANFILES+= makerom start2.ro 3c509.o ns8390.o LDFLAGS+= -N -T ${RELOCADDR} -e _start -nostdlib NOSHARED= YES NOMAN= @@ -46,35 +44,35 @@ RELOCADDR=0x90000 .S.ro: ${CC} ${CFLAGS} -DBOOTROM -o ${.TARGET} -c ${.IMPSRC} +ns8390.o: ns8390.c + ${CC} $(CFLAGS) $(NS8390) -o ${.TARGET} -c $< + makerom: makerom.c ${CC} -o ${.TARGET} -DROMSIZE=${ROMSIZE} ${.CURDIR}/makerom.c -netboot.rom: makerom start2.ro ${SRCS:N*.h:R:S/$/.o/g} - ${LD} ${LDFLAGS} -o ${.TARGET} ${OBJS:S/start2.o/start2.ro/} - -netboot.rom.strip: netboot.rom - cp -p netboot.rom ${.TARGET} +nb8390.rom: makerom start2.ro ${SRCS:N*.h:R:S/$/.o/g} ns8390.o + ${LD} ${LDFLAGS} -o ${.TARGET} ${OBJS:S/start2.o/start2.ro/} ns8390.o strip ${.TARGET} size ${.TARGET} - -netboot.rom.nohdr: netboot.rom.strip - dd ibs=32 skip=1 if=netboot.rom.strip of=${.TARGET} ${.OBJDIR}/makerom ${.TARGET} -netboot.com.strip: netboot.com - cp -p netboot.com ${.TARGET} +nb3c509.rom: makerom start2.ro ${SRCS:N*.h:R:S/$/.o/g} 3c509.o + ${LD} ${LDFLAGS} -o ${.TARGET} ${OBJS:S/start2.o/start2.ro/} 3c509.o strip ${.TARGET} size ${.TARGET} + ${.OBJDIR}/makerom ${.TARGET} -netboot.com.nohdr: netboot.com.strip - dd ibs=32 skip=1 if=netboot.com.strip of=${.TARGET} +nb8390.com: makerom start2.ro ${SRCS:N*.h:R:S/$/.o/g} ns8390.o + ${LD} ${LDFLAGS} -o netboot.com ${OBJS} ns8390.o + strip netboot.com + size netboot.com + dd ibs=32 skip=1 if=netboot.com of=${.TARGET} -all: netboot.com.nohdr netboot.rom.nohdr +nb3c509.com: start2.o ${SRCS:N*.h:R:S/$/.o/g} 3c509.o + ${LD} ${LDFLAGS} -o netboot.com ${OBJS} 3c509.o + strip netboot.com + size netboot.com + dd ibs=32 skip=1 if=netboot.com of=${.TARGET} -install: - install ${COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE}\ - netboot.com.nohdr ${DESTDIR}${BINDIR}/netboot.com - install ${COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE}\ - netboot.rom.nohdr ${DESTDIR}${BINDIR}/netboot.rom .include <bsd.prog.mk> diff --git a/sys/i386/boot/netboot/bootmenu.c b/sys/i386/boot/netboot/bootmenu.c index 10fc5ca..32b266c 100644 --- a/sys/i386/boot/netboot/bootmenu.c +++ b/sys/i386/boot/netboot/bootmenu.c @@ -10,31 +10,13 @@ Author: Martin Renters extern struct nfs_diskless nfsdiskless; extern int hostnamelen; extern unsigned long netmask; +extern eth_reset(); +extern short aui; int cmd_ip(), cmd_server(), cmd_kernel(), cmd_help(), exit(); int cmd_rootfs(), cmd_swapfs(), cmd_interface(), cmd_hostname(); int cmd_netmask(), cmd_swapsize(), cmd_swapopts(), cmd_rootopts(); -#ifdef INCLUDE_3COM int cmd_aui(); -#endif - -#ifdef SMALL_ROM -struct bootcmds_t { - char *name; - int (*func)(); -} bootcmds[] = { - {"ip", cmd_ip}, - {"server", cmd_server}, - {"bootfile", cmd_bootfile}, - {"diskboot", exit}, - {"autoboot", NULL}, -#ifdef INCLUDE_3COM - {"trans", cmd_aui}, -#endif - {NULL, NULL} -}; - -#else /* !SMALL ROM */ struct bootcmds_t { char *name; @@ -55,14 +37,12 @@ struct bootcmds_t { {"rootopts", cmd_rootopts, "<options> root mount options"}, {"diskboot", exit, " boot from disk"}, {"autoboot", NULL, " continue"}, -#ifdef INCLUDE_3COM {"trans", cmd_aui, "<on|off> turn transceiver on|off"}, -#endif {NULL, NULL, NULL} }; /************************************************************************** -CMD_HELP - Display help screen - NOT FOR SMALL ROMS +CMD_HELP - Display help screen **************************************************************************/ cmd_help() { @@ -73,7 +53,6 @@ cmd_help() cmd++; } } -#endif /* SMALL ROM */ /************************************************************************** CMD_IP - Set my IP address @@ -88,9 +67,6 @@ cmd_ip(p) } else default_netmask(); } -#ifdef INCLUDE_3COM -extern short aui; -extern eth_reset(); /************************************************************************** CMD_AUI - Turn on-board transceiver on or off **************************************************************************/ @@ -109,7 +85,6 @@ cmd_aui(p) } printf ("Transceiver is %s\r\n",aui ? "off" : "on"); } -#endif /************************************************************************** CMD_SERVER - Set server's IP address @@ -314,11 +289,7 @@ execute(buf) } else cmd++; } -#ifdef SMALL_ROM - printf("invalid command\n\r"); -#else printf("bad command - type 'help' for list\n\r"); -#endif return(0); } diff --git a/sys/i386/boot/netboot/main.c b/sys/i386/boot/netboot/main.c index 641ab18..5cadf8f 100644 --- a/sys/i386/boot/netboot/main.c +++ b/sys/i386/boot/netboot/main.c @@ -16,13 +16,6 @@ struct exec head; char *loadpoint; char *kernel; char kernel_buf[128]; -#ifdef INCLUDE_3COM -#ifdef _3COM_USE_AUI -short aui = 1; -#else -short aui = 0; -#endif -#endif void (*kernelentry)(); struct nfs_diskless nfsdiskless; int hostnamelen; @@ -30,6 +23,7 @@ char config_buffer[512]; /* Max TFTP packet */ struct bootinfo bootinfo; unsigned long netmask; +extern char eth_driver[]; extern char packet[]; extern int packetlen, rpc_id; char broadcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; @@ -155,10 +149,7 @@ load() } /* Fill in nfsdiskless.myif */ - /* - sprintf(&nfsdiskless.myif.ifra_name,"ep0"); - */ - eth_fillname(&nfsdiskless.myif.ifra_name); + sprintf(&nfsdiskless.myif.ifra_name,eth_driver); nfsdiskless.myif.ifra_addr.sa_len = sizeof(struct sockaddr); nfsdiskless.myif.ifra_addr.sa_family = AF_INET; addr = htonl(arptable[ARP_CLIENT].ipaddr); diff --git a/sys/i386/boot/netboot/makerom.c b/sys/i386/boot/netboot/makerom.c index 98cc651..715e9b7 100644 --- a/sys/i386/boot/netboot/makerom.c +++ b/sys/i386/boot/netboot/makerom.c @@ -1,3 +1,10 @@ +/************************************************************************ + +Program to put ROM checksum in ROM image. + +This program strips off the FreeBSD a.out header! + +************************************************************************/ #include <stdio.h> #include <fcntl.h> @@ -17,6 +24,10 @@ main(argc,argv) exit(2); } bzero(rom, ROMSIZE); + if (lseek(fd, (off_t)32, SEEK_SET) < 0) { + perror("lseek error"); + exit(2); + } if (read(fd, rom, ROMSIZE) < 0) { perror("read error"); exit(2); @@ -29,7 +40,7 @@ main(argc,argv) sum += rom[i]; if (sum) printf("checksum fails.\n"); - if (lseek(fd, 0L, SEEK_SET) < 0) { + if (lseek(fd, (off_t)0, SEEK_SET) < 0) { perror("unable to seek"); exit(2); } diff --git a/sys/i386/boot/netboot/netboot.h b/sys/i386/boot/netboot/netboot.h index 205ee87..ae09cb4 100644 --- a/sys/i386/boot/netboot/netboot.h +++ b/sys/i386/boot/netboot/netboot.h @@ -49,8 +49,23 @@ Author: Martin Renters #define NULL ((void *)0) #endif +#define TRUE 1 +#define FALSE 0 + #define ETHER_ADDR_SIZE 6 /* Size of Ethernet address */ #define ETHER_HDR_SIZE 14 /* Size of ethernet header */ +#define ETH_MIN_PACKET 64 +#define ETH_MAX_PACKET 1518 + +#define VENDOR_NONE 0 +#define VENDOR_WD 1 +#define VENDOR_NOVELL 2 +#define VENDOR_3COM 3 +#define VENDOR_3C509 4 + +#define FLAG_PIO 0x01 +#define FLAG_16BIT 0x02 +#define FLAG_790 0x04 #define ARP_CLIENT 0 #define ARP_SERVER 1 diff --git a/sys/i386/boot/netboot/ns8390.c b/sys/i386/boot/netboot/ns8390.c new file mode 100644 index 0000000..10e8862 --- /dev/null +++ b/sys/i386/boot/netboot/ns8390.c @@ -0,0 +1,634 @@ + +/************************************************************************** +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 + +**************************************************************************/ + +#include "netboot.h" +#include "ns8390.h" + +#ifdef _3COM_USE_AUI +short aui=1; +#else +short aui=0; +#endif + +unsigned short eth_nic_base; +unsigned short eth_asic_base; +unsigned char eth_tx_start; +unsigned char eth_laar; +unsigned char eth_flags; +unsigned char eth_vendor; +unsigned char eth_memsize; +unsigned char *eth_bmem; +unsigned char *eth_rmem; +unsigned char *eth_node_addr; + +/************************************************************************** +The following two variables are used externally +**************************************************************************/ +char eth_driver[] = "ed0"; +char packet[ETH_MAX_PACKET]; +int packetlen; + +/************************************************************************** +ETH_PROBE - Look for an adapter +**************************************************************************/ +eth_probe() +{ + int i; + struct wd_board *brd; + char *name; + unsigned short chksum; + unsigned char c; + + 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; + 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))) { + eth_bmem = (char *)(0x80000 | + ((inb(eth_asic_base + WD_MSR) & 0x3F) << 13)); + } else + eth_bmem = (char *)WD_DEFAULT_MEM; + 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; + } + } + 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; i<6; i++) { + printf("%b",(int)(arptable[ARP_CLIENT].node[i] = + inb(i+eth_asic_base+WD_LAR))); + if (i < 5) 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)); + outb(eth_asic_base+0x0B, + (((unsigned)eth_bmem >> 13) & 0x0F) | + (((unsigned)eth_bmem >> 11) & 0x40) | + (inb(eth_asic_base+0x0B) & 0xB0)); + outb(eth_asic_base+0x04, (inb(eth_asic_base+0x04) & + ~0x80)); + } else { + outb(eth_asic_base+WD_MSR, + (((unsigned)eth_bmem >> 13) & 0x3F) | 0x40); + } + 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_3COM + /****************************************************************** + Search for 3Com 3c503 if no WD/SMC cards + ******************************************************************/ + if (eth_vendor == VENDOR_NONE) { + eth_asic_base = _3COM_BASE + _3COM_ASIC_OFFSET; + eth_nic_base = _3COM_BASE; + eth_vendor = VENDOR_3COM; + /* + * 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; + + /* Check our base address */ + + switch(inb(eth_asic_base + _3COM_BCFR)) { + case _3COM_BCFR_300: + if ((int)eth_nic_base != 0x300) + return(0); + break; + case _3COM_BCFR_310: + if ((int)eth_nic_base != 0x310) + return(0); + break; + case _3COM_BCFR_330: + if ((int)eth_nic_base != 0x330) + return(0); + break; + case _3COM_BCFR_350: + if ((int)eth_nic_base != 0x350) + return(0); + break; + case _3COM_BCFR_250: + if ((int)eth_nic_base != 0x250) + return(0); + break; + case _3COM_BCFR_280: + if ((int)eth_nic_base != 0x280) + return(0); + break; + case _3COM_BCFR_2A0: + if ((int)eth_nic_base != 0x2a0) + return(0); + break; + case _3COM_BCFR_2E0: + if ((int)eth_nic_base != 0x2e0) + return(0); + break; + default: + return (0); + } + + /* Now get the shared memory address */ + + switch (inb(eth_asic_base + _3COM_PCFR)) { + case _3COM_PCFR_DC000: + eth_bmem = (char *)0xdc000; + break; + case _3COM_PCFR_D8000: + eth_bmem = (char *)0xd8000; + break; + case _3COM_PCFR_CC000: + eth_bmem = (char *)0xcc000; + break; + case _3COM_PCFR_C8000: + eth_bmem = (char *)0xc8000; + break; + default: + return (0); + } + + /* 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; i<6; i++) { + printf("%b",(int)(arptable[ARP_CLIENT].node[i] = + inb(eth_nic_base+i))); + if (i < 5) 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) + */ + bzero(eth_bmem, 0x2000); + for(i = 0; i < 0x2000; ++i) + if (*((eth_bmem)+i)) { + printf ("Failed to clear 3c503 shared mem.\r\n"); + return (0); + } + /* + * 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 +#ifdef INCLUDE_NE + /****************************************************************** + Search for NE1000/2000 if no WD/SMC or 3com cards + ******************************************************************/ + if (eth_vendor == VENDOR_NONE) { + char romdata[16], testbuf[32]; + char test[] = "NE1000/2000 memory"; + eth_bmem = (char *)0; /* No shared memory */ + eth_asic_base = NE_BASE + NE_ASIC_OFFSET; + eth_nic_base = NE_BASE; + eth_vendor = VENDOR_NOVELL; + eth_flags = FLAG_PIO; + eth_memsize = MEM_16384; + eth_tx_start = 32; + 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 (!bcompare(test, testbuf, sizeof(test))) { + eth_flags |= FLAG_16BIT; + eth_memsize = MEM_32768; + eth_tx_start = 64; + 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 (!bcompare(testbuf, test, sizeof(test))) return (0); + } + eth_pio_read(0, romdata, 16); + printf("\r\nNE1000/NE2000 base 0x%x, addr ", eth_nic_base); + for (i=0; i<6; i++) { + printf("%b",(int)(arptable[ARP_CLIENT].node[i] = romdata[i + + ((eth_flags & FLAG_16BIT) ? i : 0)])); + if (i < 5) printf (":"); + } + printf("\r\n"); + } +#endif + if (eth_vendor == VENDOR_NONE) return(0); + + if (eth_vendor != VENDOR_3COM) eth_rmem = eth_bmem; + eth_node_addr = arptable[ARP_CLIENT].node; + eth_reset(); + return(eth_vendor); +} + +/************************************************************************** +ETH_RESET - Reset adapter +**************************************************************************/ +eth_reset() +{ + 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, 4); /* allow broadcast frames */ + 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_tx_start + D8390_TXBUF_SIZE); + 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_tx_start + D8390_TXBUF_SIZE); + 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; i<6; i++) + outb(eth_nic_base+D8390_P1_PAR0+i, eth_node_addr[i]); + for (i=0; i<6; i++) + outb(eth_nic_base+D8390_P1_MAR0+i, 0xFF); + outb(eth_nic_base+D8390_P1_CURR, eth_tx_start + D8390_TXBUF_SIZE+1); + 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_ISR, 0xFF); + outb(eth_nic_base+D8390_P0_TCR, 0); +#ifdef INCLUDE_3COM + if (eth_vendor == VENDOR_3COM) { + /* + * No way to tell whether or not we're supposed to use + * the 3Com's transceiver unless the user tells us. + * 'aui' should have some compile time default value + * which can be changed from the command menu. + */ + if (aui) + outb(eth_asic_base + _3COM_CR, 0); + else + outb(eth_asic_base + _3COM_CR, _3COM_CR_XSEL); + } +#endif + return(1); +} + +/************************************************************************** +ETH_TRANSMIT - Transmit a frame +**************************************************************************/ +eth_transmit(d,t,s,p) + char *d; /* Destination */ + unsigned short t; /* Type */ + unsigned short s; /* size */ + char *p; /* Packet */ +{ + unsigned char c; +#ifdef INCLUDE_3COM + if (eth_vendor == VENDOR_3COM) { + bcopy(d, eth_bmem, 6); /* dst */ + bcopy(eth_node_addr, eth_bmem+6, ETHER_ADDR_SIZE); /* src */ + *(eth_bmem+12) = t>>8; /* type */ + *(eth_bmem+13) = t; + bcopy(p, eth_bmem+14, s); + s += 14; + while (s < ETH_MIN_PACKET) *(eth_bmem+(s++)) = 0; + } +#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); + bcopy(d, eth_bmem, 6); /* dst */ + bcopy(eth_node_addr, eth_bmem+6, ETHER_ADDR_SIZE); /* src */ + *(eth_bmem+12) = t>>8; /* type */ + *(eth_bmem+13) = t; + bcopy(p, eth_bmem+14, s); + s += 14; + while (s < ETH_MIN_PACKET) *(eth_bmem+(s++)) = 0; + 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 +#ifdef INCLUDE_NE + if (eth_vendor == VENDOR_NOVELL) { /* Programmed I/O */ + unsigned short type; + type = (t >> 8) | (t << 8); + eth_pio_write(d, eth_tx_start<<8, 6); + eth_pio_write(eth_node_addr, (eth_tx_start<<8)+6, 6); + eth_pio_write(&type, (eth_tx_start<<8)+12, 2); + eth_pio_write(p, (eth_tx_start<<8)+14, s); + s += 14; + if (s < ETH_MIN_PACKET) s = ETH_MIN_PACKET; + } +#endif + twiddle(); + 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); + return(0); +} + +/************************************************************************** +ETH_POLL - Wait for a frame +**************************************************************************/ +eth_poll() +{ + int ret = 0; + unsigned short type = 0; + unsigned char bound,curr,rstat; + unsigned short len; + unsigned short pktoff; + unsigned char *p; + struct ringbuffer pkthdr; + rstat = inb(eth_nic_base+D8390_P0_RSR); + if (rstat & D8390_RSTAT_OVER) { + eth_reset(); + return(0); + } + if (!(rstat & D8390_RSTAT_PRX)) return(0); + bound = inb(eth_nic_base+D8390_P0_BOUND)+1; + if (bound == eth_memsize) bound = eth_tx_start + D8390_TXBUF_SIZE; + 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_tx_start + D8390_TXBUF_SIZE; + if (curr == bound) 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 = (bound << 8); + if (eth_flags & FLAG_PIO) + eth_pio_read(pktoff, &pkthdr, 4); + else + bcopy(eth_rmem + pktoff, &pkthdr, 4); + len = pkthdr.len - 4; /* sub CRC */ + pktoff += 4; + if (len > 1514) len = 1514; + bound = pkthdr.bound; /* New bound ptr */ + if ( (pkthdr.status & D8390_RSTAT_PRX) && (len > 14) && (len < 1518)) { + p = packet; + packetlen = len; + len = (eth_memsize << 8) - pktoff; + if (packetlen > len) { /* We have a wrap-around */ + if (eth_flags & FLAG_PIO) + eth_pio_read(pktoff, p, len); + else + bcopy(eth_rmem + pktoff, p, len); + pktoff = (eth_tx_start + D8390_TXBUF_SIZE) << 8; + p += len; + packetlen -= len; + } + if (eth_flags & FLAG_PIO) + eth_pio_read(pktoff, p, packetlen); + else + bcopy(eth_rmem + pktoff, p, packetlen); + + type = (packet[12]<<8) | packet[13]; + 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); + } + if (bound == (eth_tx_start + D8390_TXBUF_SIZE)) + bound = eth_memsize; + outb(eth_nic_base+D8390_P0_BOUND, bound-1); + if (ret && (type == ARP)) { + struct arprequest *arpreq; + unsigned long reqip; + arpreq = (struct arprequest *)&packet[ETHER_HDR_SIZE]; + convert_ipaddr(&reqip, arpreq->tipaddr); + if ((ntohs(arpreq->opcode) == ARP_REQUEST) && + (reqip == arptable[ARP_CLIENT].ipaddr)) { + arpreq->opcode = htons(ARP_REPLY); + bcopy(arpreq->sipaddr, arpreq->tipaddr, 4); + bcopy(arpreq->shwaddr, arpreq->thwaddr, 6); + bcopy(arptable[ARP_CLIENT].node, arpreq->shwaddr, 6); + convert_ipaddr(arpreq->sipaddr, &reqip); + eth_transmit(arpreq->thwaddr, ARP, sizeof(struct arprequest), + arpreq); + return(0); + } + } + return(ret); +} + +#ifdef INCLUDE_NE +/************************************************************************** +ETH_PIO_READ - Read a frame via Programmed I/O +**************************************************************************/ +eth_pio_read(src, dst, cnt, init) + unsigned short src; + unsigned char *dst; + unsigned short cnt; + int init; +{ + if (cnt & 1) cnt++; + 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) { + while (cnt) { + *((unsigned short *)dst) = inw(eth_asic_base + NE_DATA); + dst += 2; + cnt -= 2; + } + } + else { + while (cnt--) + *(dst++) = inb(eth_asic_base + NE_DATA); + } +} + +/************************************************************************** +ETH_PIO_WRITE - Write a frame via Programmed I/O +**************************************************************************/ +eth_pio_write(src, dst, cnt, init) + unsigned char *src; + unsigned short dst; + unsigned short cnt; + int init; +{ + 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) { + if (cnt & 1) cnt++; /* Round up */ + while (cnt) { + outw(eth_asic_base + NE_DATA, *((unsigned short *)src)); + src += 2; + cnt -= 2; + } + } + else { + while (cnt--) + outb(eth_asic_base + NE_DATA, *(src++)); + } + while((inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC) + != D8390_ISR_RDC); +} +#else +/************************************************************************** +ETH_PIO_READ - Dummy routine when NE2000 not compiled in +**************************************************************************/ +eth_pio_read() {} +#endif diff --git a/sys/i386/boot/netboot/ns8390.h b/sys/i386/boot/netboot/ns8390.h new file mode 100644 index 0000000..094cbae --- /dev/null +++ b/sys/i386/boot/netboot/ns8390.h @@ -0,0 +1,246 @@ +/************************************************************************** +NETBOOT - BOOTP/TFTP Bootstrap Program + +Author: Martin Renters + Date: Jun/94 + +**************************************************************************/ + +#define MEM_8192 32 +#define MEM_16384 64 +#define MEM_32768 128 + +/************************************************************************** +Western Digital/SMC Board Definitions +**************************************************************************/ +#define WD_LOW_BASE 0x200 +#define WD_HIGH_BASE 0x3e0 +#ifndef WD_DEFAULT_MEM +#define WD_DEFAULT_MEM 0xD0000 +#endif +#define WD_NIC_ADDR 0x10 + +/************************************************************************** +Western Digital/SMC ASIC Addresses +**************************************************************************/ +#define WD_MSR 0x00 +#define WD_ICR 0x01 +#define WD_IAR 0x02 +#define WD_BIO 0x03 +#define WD_IRR 0x04 +#define WD_LAAR 0x05 +#define WD_IJR 0x06 +#define WD_GP2 0x07 +#define WD_LAR 0x08 +#define WD_BID 0x0E + +#define WD_ICR_16BIT 0x01 + +#define WD_MSR_MENB 0x40 + +#define WD_LAAR_L16EN 0x40 +#define WD_LAAR_M16EN 0x80 + +#define WD_SOFTCONFIG 0x20 + +/************************************************************************** +Western Digital/SMC Board Types +**************************************************************************/ +#define TYPE_WD8003S 0x02 +#define TYPE_WD8003E 0x03 +#define TYPE_WD8013EBT 0x05 +#define TYPE_WD8003W 0x24 +#define TYPE_WD8003EB 0x25 +#define TYPE_WD8013W 0x26 +#define TYPE_WD8013EP 0x27 +#define TYPE_WD8013WC 0x28 +#define TYPE_WD8013EPC 0x29 +#define TYPE_SMC8216T 0x2a +#define TYPE_SMC8216C 0x2b +#define TYPE_SMC8416T 0x00 /* Bogus entries: the 8416 generates the */ +#define TYPE_SMC8416C 0x00 /* the same codes as the 8216. */ +#define TYPE_SMC8013EBP 0x2c + +#ifdef INCLUDE_WD +struct wd_board { + char *name; + char id; + char flags; + char memsize; +} wd_boards[] = { + {"WD8003S", TYPE_WD8003S, 0, MEM_8192}, + {"WD8003E", TYPE_WD8003E, 0, MEM_8192}, + {"WD8013EBT", TYPE_WD8013EBT, FLAG_16BIT, MEM_16384}, + {"WD8003W", TYPE_WD8003W, 0, MEM_8192}, + {"WD8003EB", TYPE_WD8003EB, 0, MEM_8192}, + {"WD8013W", TYPE_WD8013W, FLAG_16BIT, MEM_16384}, + {"WD8003EP/WD8013EP", + TYPE_WD8013EP, 0, MEM_8192}, + {"WD8013WC", TYPE_WD8013WC, FLAG_16BIT, MEM_16384}, + {"WD8013EPC", TYPE_WD8013EPC, FLAG_16BIT, MEM_16384}, + {"SMC8216T", TYPE_SMC8216T, FLAG_16BIT | FLAG_790, MEM_16384}, + {"SMC8216C", TYPE_SMC8216C, FLAG_16BIT | FLAG_790, MEM_16384}, + {"SMC8416T", TYPE_SMC8416T, FLAG_16BIT | FLAG_790, MEM_8192}, + {"SMC8416C/BT", TYPE_SMC8416C, FLAG_16BIT | FLAG_790, MEM_8192}, + {"SMC8013EBP", TYPE_SMC8013EBP,FLAG_16BIT, MEM_16384}, + {NULL, 0, 0} +}; +#endif +/************************************************************************** +3com 3c503 definitions +**************************************************************************/ + +#ifndef _3COM_BASE +#define _3COM_BASE 0x300 +#endif + +#define _3COM_TX_PAGE_OFFSET_8BIT 0x20 +#define _3COM_TX_PAGE_OFFSET_16BIT 0x0 +#define _3COM_RX_PAGE_OFFSET_16BIT 0x20 + +#define _3COM_ASIC_OFFSET 0x400 +#define _3COM_NIC_OFFSET 0x0 + +#define _3COM_PSTR 0 +#define _3COM_PSPR 1 + +#define _3COM_BCFR 3 +#define _3COM_BCFR_2E0 0x01 +#define _3COM_BCFR_2A0 0x02 +#define _3COM_BCFR_280 0x04 +#define _3COM_BCFR_250 0x08 +#define _3COM_BCFR_350 0x10 +#define _3COM_BCFR_330 0x20 +#define _3COM_BCFR_310 0x40 +#define _3COM_BCFR_300 0x80 +#define _3COM_PCFR 4 +#define _3COM_PCFR_C8000 0x10 +#define _3COM_PCFR_CC000 0x20 +#define _3COM_PCFR_D8000 0x40 +#define _3COM_PCFR_DC000 0x80 +#define _3COM_CR 6 +#define _3COM_CR_RST 0x01 /* Reset GA and NIC */ +#define _3COM_CR_XSEL 0x02 /* Transceiver select. BNC=1(def) AUI=0 */ +#define _3COM_CR_EALO 0x04 /* window EA PROM 0-15 to I/O base */ +#define _3COM_CR_EAHI 0x08 /* window EA PROM 16-31 to I/O base */ +#define _3COM_CR_SHARE 0x10 /* select interrupt sharing option */ +#define _3COM_CR_DBSEL 0x20 /* Double buffer select */ +#define _3COM_CR_DDIR 0x40 /* DMA direction select */ +#define _3COM_CR_START 0x80 /* Start DMA controller */ +#define _3COM_GACFR 5 +#define _3COM_GACFR_MBS0 0x01 +#define _3COM_GACFR_MBS1 0x02 +#define _3COM_GACFR_MBS2 0x04 +#define _3COM_GACFR_RSEL 0x08 /* enable shared memory */ +#define _3COM_GACFR_TEST 0x10 /* for GA testing */ +#define _3COM_GACFR_OWS 0x20 /* select 0WS access to GA */ +#define _3COM_GACFR_TCM 0x40 /* Mask DMA interrupts */ +#define _3COM_GACFR_NIM 0x80 /* Mask NIC interrupts */ +#define _3COM_STREG 7 +#define _3COM_STREG_REV 0x07 /* GA revision */ +#define _3COM_STREG_DIP 0x08 /* DMA in progress */ +#define _3COM_STREG_DTC 0x10 /* DMA terminal count */ +#define _3COM_STREG_OFLW 0x20 /* Overflow */ +#define _3COM_STREG_UFLW 0x40 /* Underflow */ +#define _3COM_STREG_DPRDY 0x80 /* Data port ready */ +#define _3COM_IDCFR 8 +#define _3COM_IDCFR_DRQ0 0x01 /* DMA request 1 select */ +#define _3COM_IDCFR_DRQ1 0x02 /* DMA request 2 select */ +#define _3COM_IDCFR_DRQ2 0x04 /* DMA request 3 select */ +#define _3COM_IDCFR_UNUSED 0x08 /* not used */ +#define _3COM_IDCFR_IRQ2 0x10 /* Interrupt request 2 select */ +#define _3COM_IDCFR_IRQ3 0x20 /* Interrupt request 3 select */ +#define _3COM_IDCFR_IRQ4 0x40 /* Interrupt request 4 select */ +#define _3COM_IDCFR_IRQ5 0x80 /* Interrupt request 5 select */ +#define _3COM_IRQ2 2 +#define _3COM_IRQ3 3 +#define _3COM_IRQ4 4 +#define _3COM_IRQ5 5 +#define _3COM_DAMSB 9 +#define _3COM_DALSB 0x0a +#define _3COM_VPTR2 0x0b +#define _3COM_VPTR1 0x0c +#define _3COM_VPTR0 0x0d +#define _3COM_RFMSB 0x0e +#define _3COM_RFLSB 0x0f + +/************************************************************************** +NE1000/2000 definitions +**************************************************************************/ +#ifndef NE_BASE +#define NE_BASE 0x320 +#endif +#define NE_ASIC_OFFSET 0x10 +#define NE_RESET 0x0F /* Used to reset card */ +#define NE_DATA 0x00 /* Used to read/write NIC mem */ + +/************************************************************************** +8390 Register Definitions +**************************************************************************/ +#define D8390_P0_COMMAND 0x00 +#define D8390_P0_PSTART 0x01 +#define D8390_P0_PSTOP 0x02 +#define D8390_P0_BOUND 0x03 +#define D8390_P0_TSR 0x04 +#define D8390_P0_TPSR 0x04 +#define D8390_P0_TBCR0 0x05 +#define D8390_P0_TBCR1 0x06 +#define D8390_P0_ISR 0x07 +#define D8390_P0_RSAR0 0x08 +#define D8390_P0_RSAR1 0x09 +#define D8390_P0_RBCR0 0x0A +#define D8390_P0_RBCR1 0x0B +#define D8390_P0_RSR 0x0C +#define D8390_P0_RCR 0x0C +#define D8390_P0_TCR 0x0D +#define D8390_P0_DCR 0x0E +#define D8390_P0_IMR 0x0F +#define D8390_P1_COMMAND 0x00 +#define D8390_P1_PAR0 0x01 +#define D8390_P1_PAR1 0x02 +#define D8390_P1_PAR2 0x03 +#define D8390_P1_PAR3 0x04 +#define D8390_P1_PAR4 0x05 +#define D8390_P1_PAR5 0x06 +#define D8390_P1_CURR 0x07 +#define D8390_P1_MAR0 0x08 + +#define D8390_COMMAND_PS0 0x0 /* Page 0 select */ +#define D8390_COMMAND_PS1 0x40 /* Page 1 select */ +#define D8390_COMMAND_PS2 0x80 /* Page 2 select */ +#define D8390_COMMAND_RD2 0x20 /* Remote DMA control */ +#define D8390_COMMAND_RD1 0x10 +#define D8390_COMMAND_RD0 0x08 +#define D8390_COMMAND_TXP 0x04 /* transmit packet */ +#define D8390_COMMAND_STA 0x02 /* start */ +#define D8390_COMMAND_STP 0x01 /* stop */ + +#define D8390_RCR_MON 0x20 /* monitor mode */ + +#define D8390_DCR_FT1 0x40 +#define D8390_DCR_LS 0x08 /* Loopback select */ +#define D8390_DCR_WTS 0x01 /* Word transfer select */ + +#define D8390_ISR_PRX 0x01 /* successful recv */ +#define D8390_ISR_PTX 0x02 /* successful xmit */ +#define D8390_ISR_RXE 0x04 /* receive error */ +#define D8390_ISR_TXE 0x08 /* transmit error */ +#define D8390_ISR_OVW 0x10 /* Overflow */ +#define D8390_ISR_CNT 0x20 /* Counter overflow */ +#define D8390_ISR_RDC 0x40 /* Remote DMA complete */ +#define D8390_ISR_RST 0x80 /* reset */ + +#define D8390_RSTAT_PRX 0x01 /* successful recv */ +#define D8390_RSTAT_CRC 0x02 /* CRC error */ +#define D8390_RSTAT_FAE 0x04 /* Frame alignment error */ +#define D8390_RSTAT_OVER 0x08 /* overflow */ + +#define D8390_TXBUF_SIZE 6 +#define D8390_RXBUF_END 32 +#define D8390_PAGE_SIZE 256 + +struct ringbuffer { + unsigned char status; + unsigned char bound; + unsigned short len; +}; |