summaryrefslogtreecommitdiffstats
path: root/sys/i386/boot/netboot
diff options
context:
space:
mode:
authormartin <martin@FreeBSD.org>1995-04-12 20:15:33 +0000
committermartin <martin@FreeBSD.org>1995-04-12 20:15:33 +0000
commit669ed5b46ea62e3997fc8495702ddc9078fa7031 (patch)
treedec6b61a819c56055fd0a9d76b463dd654b30e35 /sys/i386/boot/netboot
parente3bdb075c7943144df547cff34aec0f6d3523f1d (diff)
downloadFreeBSD-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/i386/boot/netboot')
-rw-r--r--sys/i386/boot/netboot/3c509.c602
-rw-r--r--sys/i386/boot/netboot/3c509.h388
-rw-r--r--sys/i386/boot/netboot/Makefile58
-rw-r--r--sys/i386/boot/netboot/bootmenu.c35
-rw-r--r--sys/i386/boot/netboot/main.c13
-rw-r--r--sys/i386/boot/netboot/makerom.c13
-rw-r--r--sys/i386/boot/netboot/netboot.h15
-rw-r--r--sys/i386/boot/netboot/ns8390.c634
-rw-r--r--sys/i386/boot/netboot/ns8390.h246
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;
+};
OpenPOWER on IntegriCloud