summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>1997-04-14 00:37:53 +0000
committergibbs <gibbs@FreeBSD.org>1997-04-14 00:37:53 +0000
commita35f2233319c3f681246314ae3399e81d0943fdb (patch)
tree9d134091254d79fdf1b90835d31a6027807b2ada /sys
parentf1730f3a0ad9ba7560c9baf9e04abc106b4fcdcc (diff)
downloadFreeBSD-src-a35f2233319c3f681246314ae3399e81d0943fdb.zip
FreeBSD-src-a35f2233319c3f681246314ae3399e81d0943fdb.tar.gz
Add Intel EtherExpress16 support into the ie driver, removing the need
for the ix driver. Add a shutdown hook that resets the etherexpress so that Windoze can find the card after a warm boot. Submitted by: Aaron Smith <aaron@tau.veritas.com> Obtained From: NetBSD
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ie/if_ie.c596
-rw-r--r--sys/i386/isa/if_ie.c596
-rw-r--r--sys/i386/isa/if_ix.c1634
-rw-r--r--sys/i386/isa/if_ixreg.h359
4 files changed, 992 insertions, 2193 deletions
diff --git a/sys/dev/ie/if_ie.c b/sys/dev/ie/if_ie.c
index 083ffae..023e9d3 100644
--- a/sys/dev/ie/if_ie.c
+++ b/sys/dev/ie/if_ie.c
@@ -10,6 +10,10 @@
* 3Com 3C507 support:
* Copyright (c) 1993, 1994, Charles M. Hannum
*
+ * EtherExpress 16 support:
+ * Copyright (c) 1993, 1994, 1995, Rodney W. Grimes
+ * Copyright (c) 1997, Aaron C. Smith
+ *
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,10 +27,10 @@
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
- * Vermont and State Agricultural College and Garrett A. Wollman,
- * by William F. Jolitz, by the University of California,
- * Berkeley, by Larwence Berkeley Laboratory, by Charles M. Hannum,
- * and their contributors.
+ * Vermont and State Agricultural College and Garrett A. Wollman, by
+ * William F. Jolitz, by the University of California, Berkeley,
+ * Lawrence Berkeley Laboratory, and their contributors, by
+ * Charles M. Hannum, by Rodney W. Grimes, and by Aaron C. Smith.
* 4. Neither the names of the Universities nor the names of the authors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@@ -43,7 +47,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: if_ie.c,v 1.39 1997/02/22 09:36:29 peter Exp $
+ * $Id: if_ie.c,v 1.40 1997/03/24 11:32:51 bde Exp $
*/
/*
@@ -53,23 +57,21 @@
* Written by GAW with reference to the Clarkson Packet Driver code for this
* chip written by Russ Nelson and others.
*
- * BPF support code stolen directly from hpdev/if_le.c, supplied with
- * tcpdump.
+ * Intel EtherExpress 16 support from if_ix.c, written by Rodney W. Grimes.
*/
/*
* The i82586 is a very versatile chip, found in many implementations.
* Programming this chip is mostly the same, but certain details differ
* from card to card. This driver is written so that different cards
- * can be automatically detected at run-time. Currently, only the
- * AT&T EN100/StarLAN 10 series are supported.
+ * can be automatically detected at run-time.
*/
/*
Mode of operation:
We run the 82586 in a standard Ethernet mode. We keep NFRAMES received
-frame descriptors around for the receiver to use, and NBUFFS associated
+frame descriptors around for the receiver to use, and NRXBUF associated
receive buffer descriptors, both in a circular list. Whenever a frame is
received, we rotate both lists as necessary. (The 586 treats both lists
as a simple queue.) We also keep a transmit command around so that packets
@@ -87,20 +89,20 @@ what precisely caused it. ANY OTHER command-sending routines should
run at splimp(), and should post an acknowledgement to every interrupt
they generate.
-The 82586 has a 24-bit address space internally, and the adaptor's
-memory is located at the top of this region. However, the value we are
-given in configuration is normally the *bottom* of the adaptor RAM. So,
-we must go through a few gyrations to come up with a kernel virtual address
-which represents the actual beginning of the 586 address space. First,
-we autosize the RAM by running through several possible sizes and trying
-to initialize the adapter under the assumption that the selected size
-is correct. Then, knowing the correct RAM size, we set up our pointers
-in ie_softc[unit]. `iomem' represents the computed base of the 586
-address space. `iomembot' represents the actual configured base
-of adapter RAM. Finally, `iosize' represents the calculated size
-of 586 RAM. Then, when laying out commands, we use the interval
-[iomembot, iomembot + iosize); to make 24-pointers, we subtract
-iomem, and to make 16-pointers, we subtract iomem and and with 0xffff.
+The 82586 has a 24-bit address space internally, and the adaptor's memory
+is located at the top of this region. However, the value we are given in
+configuration is normally the *bottom* of the adaptor RAM. So, we must go
+through a few gyrations to come up with a kernel virtual address which
+represents the actual beginning of the 586 address space. First, we
+autosize the RAM by running through several possible sizes and trying to
+initialize the adapter under the assumption that the selected size is
+correct. Then, knowing the correct RAM size, we set up our pointers in
+ie_softc[unit]. `iomem' represents the computed base of the 586 address
+space. `iomembot' represents the actual configured base of adapter RAM.
+Finally, `iosize' represents the calculated size of 586 RAM. Then, when
+laying out commands, we use the interval [iomembot, iomembot + iosize); to
+make 24-pointers, we subtract iomem, and to make 16-pointers, we subtract
+iomem and and with 0xffff.
*/
@@ -148,8 +150,10 @@ iomem, and to make 16-pointers, we subtract iomem and and with 0xffff.
#include <i386/isa/isa_device.h>
#include <i386/isa/ic/i82586.h>
+#include <i386/isa/icu.h>
#include <i386/isa/if_iereg.h>
#include <i386/isa/if_ie507.h>
+#include <i386/isa/if_iee16.h>
#include <i386/isa/elink.h>
#include <vm/vm.h>
@@ -159,38 +163,57 @@ iomem, and to make 16-pointers, we subtract iomem and and with 0xffff.
#include <net/bpfdesc.h>
#endif
-static int check_ie_present __P((int unit, caddr_t where, unsigned size));
-
-static struct mbuf *last_not_for_us;
-
#ifdef DEBUG
-#define IED_RINT 1
-#define IED_TINT 2
-#define IED_RNR 4
-#define IED_CNA 8
-#define IED_READFRAME 16
+#define IED_RINT 0x01
+#define IED_TINT 0x02
+#define IED_RNR 0x04
+#define IED_CNA 0x08
+#define IED_READFRAME 0x10
int ie_debug = IED_RNR;
#endif
-#ifndef ETHERMINLEN
-#define ETHERMINLEN 60
+#if 0
+/* these values are defined in net/ethernet.h -acs */
+#define ETHER_MIN_LEN 60
+#define ETHER_MAX_LEN 1512
+#define ETHER_ADDR_LEN 6
#endif
-#define IE_BUF_LEN 1512 /* length of transmit buffer */
+#define IE_BUF_LEN ETHER_MAX_LEN /* length of transmit buffer */
/* Forward declaration */
struct ie_softc;
+static struct mbuf *last_not_for_us;
+
static int ieprobe(struct isa_device *dvp);
static int ieattach(struct isa_device *dvp);
+static int sl_probe(struct isa_device *dvp);
+static int el_probe(struct isa_device *dvp);
+static int ni_probe(struct isa_device *dvp);
+static int ee16_probe(struct isa_device *dvp);
+
+static int check_ie_present __P((int unit, caddr_t where, unsigned size));
static void ieinit(int unit);
static void ie_stop __P((int unit));
-static int ieioctl(struct ifnet *ifp, int command, caddr_t data);
+static int ieioctl(struct ifnet *ifp, int command, caddr_t data);
static void iestart(struct ifnet *ifp);
+
static void el_reset_586(int unit);
static void el_chan_attn(int unit);
+
static void sl_reset_586(int unit);
static void sl_chan_attn(int unit);
+
+static void ee16_reset_586(int unit);
+static void ee16_chan_attn(int unit);
+static void ee16_interrupt_enable __P((struct ie_softc *ie));
+static void ee16_eeprom_outbits __P((struct ie_softc *ie, int edata, int cnt));
+static void ee16_eeprom_clock __P((struct ie_softc *ie, int state));
+static u_short ee16_read_eeprom __P((struct ie_softc *ie, int location));
+static int ee16_eeprom_inbits __P((struct ie_softc *ie));
+static void ee16_shutdown(int howto, void *sc);
+
static void iereset(int unit);
static void ie_readframe(int unit, struct ie_softc *ie, int bufno);
static void ie_drop_packet_buffer(int unit, struct ie_softc *ie);
@@ -229,6 +252,7 @@ enum ie_hardware {
IE_SLFIBER,
IE_3C507,
IE_NI5210,
+ IE_EE16,
IE_UNKNOWN
};
@@ -238,6 +262,7 @@ static const char *ie_hardware_names[] = {
"StarLAN Fiber",
"3C507",
"NI5210",
+ "EtherExpress 16",
"Unknown"
};
@@ -251,12 +276,12 @@ sizeof(transmit buffer desc) == 8
-----
1946
-NBUFFS * sizeof(rbd) == NBUFFS*(2+2+4+2+2) == NBUFFS*12
-NBUFFS * IE_RBUF_SIZE == NBUFFS*256
+NRXBUF * sizeof(rbd) == NRXBUF*(2+2+4+2+2) == NRXBUF*12
+NRXBUF * IE_RBUF_SIZE == NRXBUF*256
-NBUFFS should be (16384 - 1946) / (256 + 12) == 14438 / 268 == 53
+NRXBUF should be (16384 - 1946) / (256 + 12) == 14438 / 268 == 53
-With NBUFFS == 48, this leaves us 1574 bytes for another command or
+With NRXBUF == 48, this leaves us 1574 bytes for another command or
more buffers. Another transmit command would be 18+8+1512 == 1538
---just barely fits!
@@ -265,9 +290,12 @@ With a larger memory, it would be possible to roughly double the number of
both transmit and receive buffers.
*/
-#define NFRAMES 16 /* number of frames to allow for receive */
-#define NBUFFS 48 /* number of buffers to allocate */
-#define IE_RBUF_SIZE 256 /* size of each buffer, MUST BE POWER OF TWO */
+#define NFRAMES 16 /* number of receive frames */
+#define NRXBUF 48 /* number of buffers to allocate */
+#define IE_RBUF_SIZE 256 /* size of each buffer,
+ MUST BE POWER OF TWO */
+#define NTXBUF 2 /* number of transmit commands */
+#define IE_TBUF_SIZE ETHER_MAX_LEN /* size of transmit buffer */
/*
* Ethernet status, per interface.
@@ -279,9 +307,9 @@ static struct ie_softc {
enum ie_hardware hard_type;
int hard_vers;
- u_short port;
- caddr_t iomem;
- caddr_t iomembot;
+ u_short port; /* i/o base address for this interface */
+ caddr_t iomem; /* memory size */
+ caddr_t iomembot; /* memory base address */
unsigned iosize;
int bus_use; /* 0 means 16bit, 1 means 8 bit adapter */
@@ -290,42 +318,44 @@ static struct ie_softc {
volatile struct ie_int_sys_conf_ptr *iscp;
volatile struct ie_sys_ctl_block *scb;
volatile struct ie_recv_frame_desc *rframes[NFRAMES];
- volatile struct ie_recv_buf_desc *rbuffs[NBUFFS];
- volatile char *cbuffs[NBUFFS];
+ volatile struct ie_recv_buf_desc *rbuffs[NRXBUF];
+ volatile char *cbuffs[NRXBUF];
int rfhead, rftail, rbhead, rbtail;
- volatile struct ie_xmit_cmd *xmit_cmds[2];
- volatile struct ie_xmit_buf *xmit_buffs[2];
+ volatile struct ie_xmit_cmd *xmit_cmds[NTXBUF];
+ volatile struct ie_xmit_buf *xmit_buffs[NTXBUF];
+ u_char *xmit_cbuffs[NTXBUF];
int xmit_count;
- u_char *xmit_cbuffs[2];
struct ie_en_addr mcast_addrs[MAXMCAST + 1];
int mcast_count;
+
+ u_short irq_encoded; /* encoded interrupt on IEE16 */
+
} ie_softc[NIE];
#define MK_24(base, ptr) ((caddr_t)((u_long)ptr - (u_long)base))
#define MK_16(base, ptr) ((u_short)(u_long)MK_24(base, ptr))
#define PORT ie_softc[unit].port
-#define MEM ie_softc[unit].iomem
+#define MEM ie_softc[unit].iomem
-static int sl_probe(struct isa_device *);
-static int el_probe(struct isa_device *);
-static int ni_probe(struct isa_device *);
-
-/* This routine written by Charles Martin Hannum. */
-int ieprobe(dvp)
- struct isa_device *dvp;
+int
+ieprobe(dvp)
+ struct isa_device *dvp;
{
int ret;
ret = sl_probe(dvp);
- if(!ret) ret = el_probe(dvp);
- if(!ret) ret = ni_probe(dvp);
- return(ret);
+ if (!ret) ret = el_probe(dvp);
+ if (!ret) ret = ni_probe(dvp);
+ if (!ret) ret = ee16_probe(dvp);
+
+ return (ret);
}
-static int sl_probe(dvp)
+static int
+sl_probe(dvp)
struct isa_device *dvp;
{
int unit = dvp->id_unit;
@@ -390,8 +420,9 @@ static int sl_probe(dvp)
return 1;
}
-/* This routine written by Charles Martin Hannum. */
-static int el_probe(dvp)
+
+static int
+el_probe(dvp)
struct isa_device *dvp;
{
struct ie_softc *sc = &ie_softc[dvp->id_unit];
@@ -538,6 +569,237 @@ static int ni_probe(dvp)
}
+static void
+ee16_shutdown(howto, sc)
+ int howto;
+ void *sc;
+{
+ struct ie_softc *ie = (struct ie_softc *)sc;
+ int unit = ie - &ie_softc[0];
+
+ ee16_reset_586(unit);
+ outb(PORT + IEE16_ECTRL, IEE16_RESET_ASIC);
+ outb(PORT + IEE16_ECTRL, 0);
+}
+
+
+/* Taken almost exactly from Rod's if_ix.c. */
+
+int
+ee16_probe(dvp)
+ struct isa_device *dvp;
+{
+ struct ie_softc *sc = &ie_softc[dvp->id_unit];
+
+ int i;
+ int unit = dvp->id_unit;
+ u_short board_id, id_var1, id_var2, checksum = 0;
+ u_short eaddrtemp, irq;
+ u_short pg, adjust, decode, edecode;
+ u_char bart_config;
+ u_long bd_maddr;
+
+ short irq_translate[] = {0, IRQ9, IRQ3, IRQ4, IRQ5, IRQ10, IRQ11, 0};
+ char irq_encode[] = { 0, 0, 0, 2, 3, 4, 0, 0,
+ 0, 1, 5, 6, 0, 0, 0, 0 };
+
+ /* Need this for part of the probe. */
+ sc->ie_reset_586 = ee16_reset_586;
+ sc->ie_chan_attn = ee16_chan_attn;
+
+ /* unsure if this is necessary */
+ sc->bus_use = 0;
+
+ /* reset any ee16 at the current iobase */
+ outb(dvp->id_iobase + IEE16_ECTRL, IEE16_RESET_ASIC);
+ outb(dvp->id_iobase + IEE16_ECTRL, 0);
+ DELAY(240);
+
+ /* now look for ee16. */
+ board_id = id_var1 = id_var2 = 0;
+ for (i=0; i<4 ; i++) {
+ id_var1 = inb(dvp->id_iobase + IEE16_ID_PORT);
+ id_var2 = ((id_var1 & 0x03) << 2);
+ board_id |= (( id_var1 >> 4) << id_var2);
+ }
+
+ if (board_id != IEE16_ID) {
+ printf("ie%d: unknown board_id: %x\n", unit, board_id);
+ return 0;
+ }
+
+ /* need sc->port for ee16_read_eeprom */
+ sc->port = dvp->id_iobase;
+ sc->hard_type = IE_EE16;
+
+ /*
+ * The shared RAM location on the EE16 is encoded into bits
+ * 3-7 of EEPROM location 6. We zero the upper byte, and
+ * shift the 5 bits right 3. The resulting number tells us
+ * the RAM location. Because the EE16 supports either 16k or 32k
+ * of shared RAM, we only worry about the 32k locations.
+ *
+ * NOTE: if a 64k EE16 exists, it should be added to this switch.
+ * then the ia->ia_msize would need to be set per case statement.
+ *
+ * value msize location
+ * ===== ===== ========
+ * 0x03 0x8000 0xCC000
+ * 0x06 0x8000 0xD0000
+ * 0x0C 0x8000 0xD4000
+ * 0x18 0x8000 0xD8000
+ *
+ */
+
+ bd_maddr = 0;
+ i = (ee16_read_eeprom(sc, 6) & 0x00ff ) >> 3;
+ switch(i) {
+ case 0x03:
+ bd_maddr = 0xCC000;
+ break;
+ case 0x06:
+ bd_maddr = 0xD0000;
+ break;
+ case 0x0c:
+ bd_maddr = 0xD4000;
+ break;
+ case 0x18:
+ bd_maddr = 0xD8000;
+ break;
+ default:
+ bd_maddr = 0 ;
+ break;
+ }
+ dvp->id_msize = 0x8000;
+ if (kvtop(dvp->id_maddr) != bd_maddr) {
+ printf("ie%d: kernel configured maddr %lx doesn't match board configured maddr %x\n",
+ unit, kvtop(dvp->id_maddr), bd_maddr);
+ }
+
+
+ sc->iomembot = dvp->id_maddr;
+ sc->iomem = 0; /* XXX some probes set this and some don't */
+ sc->iosize = dvp->id_msize;
+
+ /* need to put the 586 in RESET while we access the eeprom. */
+ outb( PORT + IEE16_ECTRL, IEE16_RESET_586);
+
+ /* read the eeprom and checksum it, should == IEE16_ID */
+ for(i = 0; i < 0x40; i++)
+ checksum += ee16_read_eeprom(sc, i);
+
+ if (checksum != IEE16_ID) {
+ printf("ie%d: invalid eeprom checksum: %x\n", unit, checksum);
+ return 0;
+ }
+
+ /*
+ * Size and test the memory on the board. The size of the memory
+ * can be one of 16k, 32k, 48k or 64k. It can be located in the
+ * address range 0xC0000 to 0xEFFFF on 16k boundaries.
+ *
+ * If the size does not match the passed in memory allocation size
+ * issue a warning, but continue with the minimum of the two sizes.
+ */
+
+ switch (dvp->id_msize) {
+ case 65536:
+ case 32768: /* XXX Only support 32k and 64k right now */
+ break;
+ case 16384:
+ case 49512:
+ default:
+ printf("ie%d: mapped memory size %d not supported\n", unit,
+ dvp->id_msize);
+ return 0;
+ break; /* NOTREACHED */
+ }
+
+ if ((kvtop(dvp->id_maddr) < 0xC0000) ||
+ (kvtop(dvp->id_maddr) + sc->iosize > 0xF0000)) {
+ printf("ie%d: mapped memory location %x out of range\n", unit,
+ dvp->id_maddr);
+ return 0;
+ }
+
+ pg = (kvtop(dvp->id_maddr) & 0x3C000) >> 14;
+ adjust = IEE16_MCTRL_FMCS16 | (pg & 0x3) << 2;
+ decode = ((1 << (sc->iosize / 16384)) - 1) << pg;
+ edecode = ((~decode >> 4) & 0xF0) | (decode >> 8);
+
+ /* ZZZ This should be checked against eeprom location 6, low byte */
+ outb(PORT + IEE16_MEMDEC, decode & 0xFF);
+ /* ZZZ This should be checked against eeprom location 1, low byte */
+ outb(PORT + IEE16_MCTRL, adjust);
+ /* ZZZ Now if I could find this one I would have it made */
+ outb(PORT + IEE16_MPCTRL, (~decode & 0xFF));
+ /* ZZZ I think this is location 6, high byte */
+ outb(PORT + IEE16_MECTRL, edecode); /*XXX disable Exxx */
+
+ (void)kvtop(dvp->id_maddr);
+
+ /*
+ * first prime the stupid bart DRAM controller so that it
+ * works, then zero out all of memory.
+ */
+ bzero(sc->iomembot, 32);
+ bzero(sc->iomembot, sc->iosize);
+
+ /*
+ * Get the encoded interrupt number from the EEPROM, check it
+ * against the passed in IRQ. Issue a warning if they do not
+ * match. Always use the passed in IRQ, not the one in the EEPROM.
+ */
+ irq = ee16_read_eeprom(sc, IEE16_EEPROM_CONFIG1);
+ irq = (irq & IEE16_EEPROM_IRQ) >> IEE16_EEPROM_IRQ_SHIFT;
+ irq = irq_translate[irq];
+ if (dvp->id_irq > 0) {
+ if (irq != dvp->id_irq) {
+ printf("ie%d: WARNING: board configured at irq %d, using %d\n",
+ dvp->id_unit, irq);
+ irq = dvp->id_unit;
+ }
+ } else {
+ dvp->id_irq = irq;
+ }
+ sc->irq_encoded = irq_encode[ffs(irq) - 1];
+
+ /*
+ * Get the hardware ethernet address from the EEPROM and
+ * save it in the softc for use by the 586 setup code.
+ */
+ eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_HIGH);
+ sc->arpcom.ac_enaddr[1] = eaddrtemp & 0xFF;
+ sc->arpcom.ac_enaddr[0] = eaddrtemp >> 8;
+ eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_MID);
+ sc->arpcom.ac_enaddr[3] = eaddrtemp & 0xFF;
+ sc->arpcom.ac_enaddr[2] = eaddrtemp >> 8;
+ eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_LOW);
+ sc->arpcom.ac_enaddr[5] = eaddrtemp & 0xFF;
+ sc->arpcom.ac_enaddr[4] = eaddrtemp >> 8;
+
+ /* disable the board interrupts */
+ outb(PORT + IEE16_IRQ, sc->irq_encoded);
+
+ /* enable loopback to keep bad packets off the wire */
+ if(sc->hard_type == IE_EE16) {
+ bart_config = inb(PORT + IEE16_CONFIG);
+ bart_config |= IEE16_BART_LOOPBACK;
+ bart_config |= IEE16_BART_MCS16_TEST; /*inb doesn't get bit! */
+ outb(PORT + IEE16_CONFIG, bart_config);
+ bart_config = inb(PORT + IEE16_CONFIG);
+ }
+
+ /* take the board out of reset state */
+ outb(PORT + IEE16_ECTRL, 0);
+ DELAY(100);
+
+ if (!check_ie_present(unit, dvp->id_maddr, sc->iosize))
+ return 0;
+
+ return 16; /* return the number of I/O ports */
+}
+
/*
* Taken almost exactly from Bill's if_is.c, then modified beyond recognition.
*/
@@ -553,7 +815,7 @@ ieattach(dvp)
ifp->if_unit = unit;
ifp->if_name = iedriver.name;
ifp->if_mtu = ETHERMTU;
- printf(" <%s R%d> ethernet address %6D\n",
+ printf("ie%d: <%s R%d> address %6D\n", unit,
ie_hardware_names[ie->hard_type],
ie->hard_vers + 1,
ie->arpcom.ac_enaddr, ":");
@@ -566,6 +828,9 @@ ieattach(dvp)
ifp->if_addrlen = 6;
ifp->if_hdrlen = 14;
+ if (ie->hard_type == IE_EE16)
+ at_shutdown(ee16_shutdown, ie, SHUTDOWN_POST_SYNC);
+
#if NBPFILTER > 0
bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
#endif
@@ -578,21 +843,22 @@ ieattach(dvp)
/*
* What to do upon receipt of an interrupt.
*/
-void ieintr(unit)
- int unit;
+void
+ieintr(unit)
+ int unit;
{
register struct ie_softc *ie = &ie_softc[unit];
register u_short status;
- status = ie->scb->ie_status;
+ /* Clear the interrupt latch on the 3C507. */
+ if (ie->hard_type == IE_3C507 && (inb(PORT + IE507_CTRL) & EL_CTRL_INTL))
+ outb(PORT + IE507_ICTRL, 1);
- /* This if statement written by Charles Martin Hannum. */
- if ((status & IE_ST_WHENCE) == 0) {
- /* Clear the interrupt latch on the 3C507. */
- if (ie->hard_type == IE_3C507 &&
- (inb(PORT + IE507_CTRL) & EL_CTRL_INTL))
- outb(PORT + IE507_ICTRL, 1);
- }
+ /* disable interrupts on the EE16. */
+ if (ie->hard_type == IE_EE16)
+ outb(PORT + IEE16_IRQ, ie->irq_encoded);
+
+ status = ie->scb->ie_status;
loop:
if(status & (IE_ST_RECV | IE_ST_RNR)) {
@@ -632,25 +898,30 @@ loop:
&& (ie_debug & IED_CNA))
printf("ie%d: cna\n", unit);
#endif
-
+
/* Don't ack interrupts which we didn't receive */
ie_ack(ie->scb, IE_ST_WHENCE & status, unit, ie->ie_chan_attn);
- if((status = ie->scb->ie_status) & IE_ST_WHENCE)
- goto loop;
+ if ((status = ie->scb->ie_status) & IE_ST_WHENCE)
+ goto loop;
- /* This comment and if statement written by Charles Martin Hannum. */
/* Clear the interrupt latch on the 3C507. */
if (ie->hard_type == IE_3C507)
- outb(PORT + IE507_ICTRL, 1);
+ outb(PORT + IE507_ICTRL, 1);
+
+ /* enable interrupts on the EE16. */
+ if (ie->hard_type == IE_EE16)
+ outb(PORT + IEE16_IRQ, ie->irq_encoded | IEE16_IRQ_ENABLE);
+
}
/*
* Process a received-frame interrupt.
*/
-static int ierint(unit, ie)
- int unit;
- struct ie_softc *ie;
+static int
+ierint(unit, ie)
+ int unit;
+ struct ie_softc *ie;
{
int i, status;
static int timesthru = 1024;
@@ -662,8 +933,9 @@ static int ierint(unit, ie)
if((status & IE_FD_COMPLETE) && (status & IE_FD_OK)) {
ie->arpcom.ac_if.if_ipackets++;
if(!--timesthru) {
- ie->arpcom.ac_if.if_ierrors += ie->scb->ie_err_crc + ie->scb->ie_err_align +
- ie->scb->ie_err_resource + ie->scb->ie_err_overrun;
+ ie->arpcom.ac_if.if_ierrors +=
+ ie->scb->ie_err_crc + ie->scb->ie_err_align +
+ ie->scb->ie_err_resource + ie->scb->ie_err_overrun;
ie->scb->ie_err_crc = 0;
ie->scb->ie_err_align = 0;
ie->scb->ie_err_resource = 0;
@@ -918,7 +1190,7 @@ static inline int ie_packet_len(int unit, struct ie_softc *ie) {
i = ie->rbuffs[head]->ie_rbd_actual & IE_RBD_LAST;
acc += ie_buflen(ie, head);
- head = (head + 1) % NBUFFS;
+ head = (head + 1) % NRXBUF;
} while(!i);
return acc;
@@ -1086,9 +1358,9 @@ nextbuf:
offset = 0;
ie->rbuffs[head]->ie_rbd_actual = 0;
ie->rbuffs[head]->ie_rbd_length |= IE_RBD_LAST;
- ie->rbhead = head = (head + 1) % NBUFFS;
+ ie->rbhead = head = (head + 1) % NRXBUF;
ie->rbuffs[ie->rbtail]->ie_rbd_length &= ~IE_RBD_LAST;
- ie->rbtail = (ie->rbtail + 1) % NBUFFS;
+ ie->rbtail = (ie->rbtail + 1) % NRXBUF;
}
/*
@@ -1223,9 +1495,9 @@ static void ie_drop_packet_buffer(int unit, struct ie_softc *ie) {
ie->rbuffs[ie->rbhead]->ie_rbd_length |= IE_RBD_LAST;
ie->rbuffs[ie->rbhead]->ie_rbd_actual = 0;
- ie->rbhead = (ie->rbhead + 1) % NBUFFS;
+ ie->rbhead = (ie->rbhead + 1) % NRXBUF;
ie->rbuffs[ie->rbtail]->ie_rbd_length &= ~IE_RBD_LAST;
- ie->rbtail = (ie->rbtail + 1) % NBUFFS;
+ ie->rbtail = (ie->rbtail + 1) % NRXBUF;
} while(!i);
}
@@ -1264,7 +1536,7 @@ iestart(ifp)
}
m_freem(m0);
- len = max(len, ETHERMINLEN);
+ len = max(len, ETHER_MIN_LEN);
#if NBPFILTER > 0
/*
@@ -1288,7 +1560,7 @@ iestart(ifp)
*bptr = MK_16(ie->iomem, ie->xmit_cmds[ie->xmit_count]);
bptr = &ie->xmit_cmds[ie->xmit_count]->com.ie_cmd_link;
ie->xmit_count++;
- } while(ie->xmit_count < 2);
+ } while (ie->xmit_count < NTXBUF);
/*
* If we queued up anything for transmission, send it.
@@ -1433,6 +1705,16 @@ void sl_reset_586(unit)
outb(PORT + IEATT_RESET, 0);
}
+void
+ee16_reset_586(unit)
+ int unit;
+{
+ outb(PORT + IEE16_ECTRL, IEE16_RESET_586);
+ DELAY(100);
+ outb(PORT + IEE16_ECTRL, 0);
+ DELAY(100);
+}
+
void el_chan_attn(unit)
int unit;
{
@@ -1445,6 +1727,105 @@ void sl_chan_attn(unit)
outb(PORT + IEATT_ATTN, 0);
}
+void
+ee16_chan_attn(unit)
+ int unit;
+{
+ outb(PORT + IEE16_ATTN, 0);
+}
+
+u_short
+ee16_read_eeprom(sc, location)
+ struct ie_softc *sc;
+ int location;
+{
+ int ectrl, edata;
+
+ ectrl = inb(sc->port + IEE16_ECTRL);
+ ectrl &= IEE16_ECTRL_MASK;
+ ectrl |= IEE16_ECTRL_EECS;
+ outb(sc->port + IEE16_ECTRL, ectrl);
+
+ ee16_eeprom_outbits(sc, IEE16_EEPROM_READ, IEE16_EEPROM_OPSIZE1);
+ ee16_eeprom_outbits(sc, location, IEE16_EEPROM_ADDR_SIZE);
+ edata = ee16_eeprom_inbits(sc);
+ ectrl = inb(sc->port + IEE16_ECTRL);
+ ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EEDI | IEE16_ECTRL_EECS);
+ outb(sc->port + IEE16_ECTRL, ectrl);
+ ee16_eeprom_clock(sc, 1);
+ ee16_eeprom_clock(sc, 0);
+ return edata;
+}
+
+void
+ee16_eeprom_outbits(sc, edata, count)
+ struct ie_softc *sc;
+ int edata, count;
+{
+ int ectrl, i;
+
+ ectrl = inb(sc->port + IEE16_ECTRL);
+ ectrl &= ~IEE16_RESET_ASIC;
+ for (i = count - 1; i >= 0; i--) {
+ ectrl &= ~IEE16_ECTRL_EEDI;
+ if (edata & (1 << i)) {
+ ectrl |= IEE16_ECTRL_EEDI;
+ }
+ outb(sc->port + IEE16_ECTRL, ectrl);
+ DELAY(1); /* eeprom data must be setup for 0.4 uSec */
+ ee16_eeprom_clock(sc, 1);
+ ee16_eeprom_clock(sc, 0);
+ }
+ ectrl &= ~IEE16_ECTRL_EEDI;
+ outb(sc->port + IEE16_ECTRL, ectrl);
+ DELAY(1); /* eeprom data must be held for 0.4 uSec */
+}
+
+int
+ee16_eeprom_inbits(sc)
+ struct ie_softc *sc;
+{
+ int ectrl, edata, i;
+
+ ectrl = inb(sc->port + IEE16_ECTRL);
+ ectrl &= ~IEE16_RESET_ASIC;
+ for (edata = 0, i = 0; i < 16; i++) {
+ edata = edata << 1;
+ ee16_eeprom_clock(sc, 1);
+ ectrl = inb(sc->port + IEE16_ECTRL);
+ if (ectrl & IEE16_ECTRL_EEDO) {
+ edata |= 1;
+ }
+ ee16_eeprom_clock(sc, 0);
+ }
+ return (edata);
+}
+
+void
+ee16_eeprom_clock(sc, state)
+ struct ie_softc *sc;
+ int state;
+{
+ int ectrl;
+
+ ectrl = inb(sc->port + IEE16_ECTRL);
+ ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EESK);
+ if (state) {
+ ectrl |= IEE16_ECTRL_EESK;
+ }
+ outb(sc->port + IEE16_ECTRL, ectrl);
+ DELAY(9); /* EESK must be stable for 8.38 uSec */
+}
+
+static inline void
+ee16_interrupt_enable(sc)
+ struct ie_softc *sc;
+{
+ DELAY(100);
+ outb(sc->port + IEE16_IRQ, sc->irq_encoded | IEE16_IRQ_ENABLE);
+ DELAY(100);
+}
+
void sl_read_ether(unit, addr)
int unit;
unsigned char addr[6];
@@ -1651,7 +2032,7 @@ static caddr_t setup_rfa(caddr_t ptr, struct ie_softc *ie) {
*/
rbd = (void *)ptr;
- for(i = 0; i < NBUFFS; i++) {
+ for(i = 0; i < NRXBUF; i++) {
ie->rbuffs[i] = rbd;
bzero((char *)rbd, sizeof *rbd); /* ignore cast-qual */
ptr = (caddr_t)Align(ptr + sizeof *rbd);
@@ -1663,19 +2044,19 @@ static caddr_t setup_rfa(caddr_t ptr, struct ie_softc *ie) {
}
/* Now link them together */
- for(i = 0; i < NBUFFS; i++) {
- ie->rbuffs[i]->ie_rbd_next = MK_16(MEM, ie->rbuffs[(i + 1) % NBUFFS]);
+ for(i = 0; i < NRXBUF; i++) {
+ ie->rbuffs[i]->ie_rbd_next = MK_16(MEM, ie->rbuffs[(i + 1) % NRXBUF]);
}
/* Tag EOF on the last one */
- ie->rbuffs[NBUFFS - 1]->ie_rbd_length |= IE_RBD_LAST;
+ ie->rbuffs[NRXBUF - 1]->ie_rbd_length |= IE_RBD_LAST;
/* We use the head and tail pointers on receive to keep track of
* the order in which RFDs and RBDs are used. */
ie->rfhead = 0;
ie->rftail = NFRAMES - 1;
ie->rbhead = 0;
- ie->rbtail = NBUFFS - 1;
+ ie->rbtail = NRXBUF - 1;
ie->scb->ie_recv_list = MK_16(MEM, ie->rframes[0]);
ie->rframes[0]->ie_fd_buf_desc = MK_16(MEM, ie->rbuffs[0]);
@@ -1780,6 +2161,21 @@ ieinit(unit)
*/
ie_ack(ie->scb, IE_ST_WHENCE, unit, ie->ie_chan_attn);
+ /* take the ee16 out of loopback */
+ {
+ u_char bart_config;
+
+ if(ie->hard_type == IE_EE16) {
+ bart_config = inb(PORT + IEE16_CONFIG);
+ bart_config &= ~IEE16_BART_LOOPBACK;
+ /* inb doesn't get bit! */
+ bart_config |= IEE16_BART_MCS16_TEST;
+ outb(PORT + IEE16_CONFIG, bart_config);
+ ee16_interrupt_enable(ie);
+ ee16_chan_attn(unit);
+ }
+ }
+
/*
* Set up the RFA.
*/
@@ -1819,7 +2215,7 @@ ieinit(unit)
*/
ie->xmit_cmds[0]->ie_xmit_status = IE_STAT_COMPL;
- ie->arpcom.ac_if.if_flags |= IFF_RUNNING; /* tell higher levels that we are here */
+ ie->arpcom.ac_if.if_flags |= IFF_RUNNING; /* tell higher levels we're here */
start_receiver(unit);
return;
}
diff --git a/sys/i386/isa/if_ie.c b/sys/i386/isa/if_ie.c
index 083ffae..023e9d3 100644
--- a/sys/i386/isa/if_ie.c
+++ b/sys/i386/isa/if_ie.c
@@ -10,6 +10,10 @@
* 3Com 3C507 support:
* Copyright (c) 1993, 1994, Charles M. Hannum
*
+ * EtherExpress 16 support:
+ * Copyright (c) 1993, 1994, 1995, Rodney W. Grimes
+ * Copyright (c) 1997, Aaron C. Smith
+ *
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,10 +27,10 @@
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
- * Vermont and State Agricultural College and Garrett A. Wollman,
- * by William F. Jolitz, by the University of California,
- * Berkeley, by Larwence Berkeley Laboratory, by Charles M. Hannum,
- * and their contributors.
+ * Vermont and State Agricultural College and Garrett A. Wollman, by
+ * William F. Jolitz, by the University of California, Berkeley,
+ * Lawrence Berkeley Laboratory, and their contributors, by
+ * Charles M. Hannum, by Rodney W. Grimes, and by Aaron C. Smith.
* 4. Neither the names of the Universities nor the names of the authors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@@ -43,7 +47,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: if_ie.c,v 1.39 1997/02/22 09:36:29 peter Exp $
+ * $Id: if_ie.c,v 1.40 1997/03/24 11:32:51 bde Exp $
*/
/*
@@ -53,23 +57,21 @@
* Written by GAW with reference to the Clarkson Packet Driver code for this
* chip written by Russ Nelson and others.
*
- * BPF support code stolen directly from hpdev/if_le.c, supplied with
- * tcpdump.
+ * Intel EtherExpress 16 support from if_ix.c, written by Rodney W. Grimes.
*/
/*
* The i82586 is a very versatile chip, found in many implementations.
* Programming this chip is mostly the same, but certain details differ
* from card to card. This driver is written so that different cards
- * can be automatically detected at run-time. Currently, only the
- * AT&T EN100/StarLAN 10 series are supported.
+ * can be automatically detected at run-time.
*/
/*
Mode of operation:
We run the 82586 in a standard Ethernet mode. We keep NFRAMES received
-frame descriptors around for the receiver to use, and NBUFFS associated
+frame descriptors around for the receiver to use, and NRXBUF associated
receive buffer descriptors, both in a circular list. Whenever a frame is
received, we rotate both lists as necessary. (The 586 treats both lists
as a simple queue.) We also keep a transmit command around so that packets
@@ -87,20 +89,20 @@ what precisely caused it. ANY OTHER command-sending routines should
run at splimp(), and should post an acknowledgement to every interrupt
they generate.
-The 82586 has a 24-bit address space internally, and the adaptor's
-memory is located at the top of this region. However, the value we are
-given in configuration is normally the *bottom* of the adaptor RAM. So,
-we must go through a few gyrations to come up with a kernel virtual address
-which represents the actual beginning of the 586 address space. First,
-we autosize the RAM by running through several possible sizes and trying
-to initialize the adapter under the assumption that the selected size
-is correct. Then, knowing the correct RAM size, we set up our pointers
-in ie_softc[unit]. `iomem' represents the computed base of the 586
-address space. `iomembot' represents the actual configured base
-of adapter RAM. Finally, `iosize' represents the calculated size
-of 586 RAM. Then, when laying out commands, we use the interval
-[iomembot, iomembot + iosize); to make 24-pointers, we subtract
-iomem, and to make 16-pointers, we subtract iomem and and with 0xffff.
+The 82586 has a 24-bit address space internally, and the adaptor's memory
+is located at the top of this region. However, the value we are given in
+configuration is normally the *bottom* of the adaptor RAM. So, we must go
+through a few gyrations to come up with a kernel virtual address which
+represents the actual beginning of the 586 address space. First, we
+autosize the RAM by running through several possible sizes and trying to
+initialize the adapter under the assumption that the selected size is
+correct. Then, knowing the correct RAM size, we set up our pointers in
+ie_softc[unit]. `iomem' represents the computed base of the 586 address
+space. `iomembot' represents the actual configured base of adapter RAM.
+Finally, `iosize' represents the calculated size of 586 RAM. Then, when
+laying out commands, we use the interval [iomembot, iomembot + iosize); to
+make 24-pointers, we subtract iomem, and to make 16-pointers, we subtract
+iomem and and with 0xffff.
*/
@@ -148,8 +150,10 @@ iomem, and to make 16-pointers, we subtract iomem and and with 0xffff.
#include <i386/isa/isa_device.h>
#include <i386/isa/ic/i82586.h>
+#include <i386/isa/icu.h>
#include <i386/isa/if_iereg.h>
#include <i386/isa/if_ie507.h>
+#include <i386/isa/if_iee16.h>
#include <i386/isa/elink.h>
#include <vm/vm.h>
@@ -159,38 +163,57 @@ iomem, and to make 16-pointers, we subtract iomem and and with 0xffff.
#include <net/bpfdesc.h>
#endif
-static int check_ie_present __P((int unit, caddr_t where, unsigned size));
-
-static struct mbuf *last_not_for_us;
-
#ifdef DEBUG
-#define IED_RINT 1
-#define IED_TINT 2
-#define IED_RNR 4
-#define IED_CNA 8
-#define IED_READFRAME 16
+#define IED_RINT 0x01
+#define IED_TINT 0x02
+#define IED_RNR 0x04
+#define IED_CNA 0x08
+#define IED_READFRAME 0x10
int ie_debug = IED_RNR;
#endif
-#ifndef ETHERMINLEN
-#define ETHERMINLEN 60
+#if 0
+/* these values are defined in net/ethernet.h -acs */
+#define ETHER_MIN_LEN 60
+#define ETHER_MAX_LEN 1512
+#define ETHER_ADDR_LEN 6
#endif
-#define IE_BUF_LEN 1512 /* length of transmit buffer */
+#define IE_BUF_LEN ETHER_MAX_LEN /* length of transmit buffer */
/* Forward declaration */
struct ie_softc;
+static struct mbuf *last_not_for_us;
+
static int ieprobe(struct isa_device *dvp);
static int ieattach(struct isa_device *dvp);
+static int sl_probe(struct isa_device *dvp);
+static int el_probe(struct isa_device *dvp);
+static int ni_probe(struct isa_device *dvp);
+static int ee16_probe(struct isa_device *dvp);
+
+static int check_ie_present __P((int unit, caddr_t where, unsigned size));
static void ieinit(int unit);
static void ie_stop __P((int unit));
-static int ieioctl(struct ifnet *ifp, int command, caddr_t data);
+static int ieioctl(struct ifnet *ifp, int command, caddr_t data);
static void iestart(struct ifnet *ifp);
+
static void el_reset_586(int unit);
static void el_chan_attn(int unit);
+
static void sl_reset_586(int unit);
static void sl_chan_attn(int unit);
+
+static void ee16_reset_586(int unit);
+static void ee16_chan_attn(int unit);
+static void ee16_interrupt_enable __P((struct ie_softc *ie));
+static void ee16_eeprom_outbits __P((struct ie_softc *ie, int edata, int cnt));
+static void ee16_eeprom_clock __P((struct ie_softc *ie, int state));
+static u_short ee16_read_eeprom __P((struct ie_softc *ie, int location));
+static int ee16_eeprom_inbits __P((struct ie_softc *ie));
+static void ee16_shutdown(int howto, void *sc);
+
static void iereset(int unit);
static void ie_readframe(int unit, struct ie_softc *ie, int bufno);
static void ie_drop_packet_buffer(int unit, struct ie_softc *ie);
@@ -229,6 +252,7 @@ enum ie_hardware {
IE_SLFIBER,
IE_3C507,
IE_NI5210,
+ IE_EE16,
IE_UNKNOWN
};
@@ -238,6 +262,7 @@ static const char *ie_hardware_names[] = {
"StarLAN Fiber",
"3C507",
"NI5210",
+ "EtherExpress 16",
"Unknown"
};
@@ -251,12 +276,12 @@ sizeof(transmit buffer desc) == 8
-----
1946
-NBUFFS * sizeof(rbd) == NBUFFS*(2+2+4+2+2) == NBUFFS*12
-NBUFFS * IE_RBUF_SIZE == NBUFFS*256
+NRXBUF * sizeof(rbd) == NRXBUF*(2+2+4+2+2) == NRXBUF*12
+NRXBUF * IE_RBUF_SIZE == NRXBUF*256
-NBUFFS should be (16384 - 1946) / (256 + 12) == 14438 / 268 == 53
+NRXBUF should be (16384 - 1946) / (256 + 12) == 14438 / 268 == 53
-With NBUFFS == 48, this leaves us 1574 bytes for another command or
+With NRXBUF == 48, this leaves us 1574 bytes for another command or
more buffers. Another transmit command would be 18+8+1512 == 1538
---just barely fits!
@@ -265,9 +290,12 @@ With a larger memory, it would be possible to roughly double the number of
both transmit and receive buffers.
*/
-#define NFRAMES 16 /* number of frames to allow for receive */
-#define NBUFFS 48 /* number of buffers to allocate */
-#define IE_RBUF_SIZE 256 /* size of each buffer, MUST BE POWER OF TWO */
+#define NFRAMES 16 /* number of receive frames */
+#define NRXBUF 48 /* number of buffers to allocate */
+#define IE_RBUF_SIZE 256 /* size of each buffer,
+ MUST BE POWER OF TWO */
+#define NTXBUF 2 /* number of transmit commands */
+#define IE_TBUF_SIZE ETHER_MAX_LEN /* size of transmit buffer */
/*
* Ethernet status, per interface.
@@ -279,9 +307,9 @@ static struct ie_softc {
enum ie_hardware hard_type;
int hard_vers;
- u_short port;
- caddr_t iomem;
- caddr_t iomembot;
+ u_short port; /* i/o base address for this interface */
+ caddr_t iomem; /* memory size */
+ caddr_t iomembot; /* memory base address */
unsigned iosize;
int bus_use; /* 0 means 16bit, 1 means 8 bit adapter */
@@ -290,42 +318,44 @@ static struct ie_softc {
volatile struct ie_int_sys_conf_ptr *iscp;
volatile struct ie_sys_ctl_block *scb;
volatile struct ie_recv_frame_desc *rframes[NFRAMES];
- volatile struct ie_recv_buf_desc *rbuffs[NBUFFS];
- volatile char *cbuffs[NBUFFS];
+ volatile struct ie_recv_buf_desc *rbuffs[NRXBUF];
+ volatile char *cbuffs[NRXBUF];
int rfhead, rftail, rbhead, rbtail;
- volatile struct ie_xmit_cmd *xmit_cmds[2];
- volatile struct ie_xmit_buf *xmit_buffs[2];
+ volatile struct ie_xmit_cmd *xmit_cmds[NTXBUF];
+ volatile struct ie_xmit_buf *xmit_buffs[NTXBUF];
+ u_char *xmit_cbuffs[NTXBUF];
int xmit_count;
- u_char *xmit_cbuffs[2];
struct ie_en_addr mcast_addrs[MAXMCAST + 1];
int mcast_count;
+
+ u_short irq_encoded; /* encoded interrupt on IEE16 */
+
} ie_softc[NIE];
#define MK_24(base, ptr) ((caddr_t)((u_long)ptr - (u_long)base))
#define MK_16(base, ptr) ((u_short)(u_long)MK_24(base, ptr))
#define PORT ie_softc[unit].port
-#define MEM ie_softc[unit].iomem
+#define MEM ie_softc[unit].iomem
-static int sl_probe(struct isa_device *);
-static int el_probe(struct isa_device *);
-static int ni_probe(struct isa_device *);
-
-/* This routine written by Charles Martin Hannum. */
-int ieprobe(dvp)
- struct isa_device *dvp;
+int
+ieprobe(dvp)
+ struct isa_device *dvp;
{
int ret;
ret = sl_probe(dvp);
- if(!ret) ret = el_probe(dvp);
- if(!ret) ret = ni_probe(dvp);
- return(ret);
+ if (!ret) ret = el_probe(dvp);
+ if (!ret) ret = ni_probe(dvp);
+ if (!ret) ret = ee16_probe(dvp);
+
+ return (ret);
}
-static int sl_probe(dvp)
+static int
+sl_probe(dvp)
struct isa_device *dvp;
{
int unit = dvp->id_unit;
@@ -390,8 +420,9 @@ static int sl_probe(dvp)
return 1;
}
-/* This routine written by Charles Martin Hannum. */
-static int el_probe(dvp)
+
+static int
+el_probe(dvp)
struct isa_device *dvp;
{
struct ie_softc *sc = &ie_softc[dvp->id_unit];
@@ -538,6 +569,237 @@ static int ni_probe(dvp)
}
+static void
+ee16_shutdown(howto, sc)
+ int howto;
+ void *sc;
+{
+ struct ie_softc *ie = (struct ie_softc *)sc;
+ int unit = ie - &ie_softc[0];
+
+ ee16_reset_586(unit);
+ outb(PORT + IEE16_ECTRL, IEE16_RESET_ASIC);
+ outb(PORT + IEE16_ECTRL, 0);
+}
+
+
+/* Taken almost exactly from Rod's if_ix.c. */
+
+int
+ee16_probe(dvp)
+ struct isa_device *dvp;
+{
+ struct ie_softc *sc = &ie_softc[dvp->id_unit];
+
+ int i;
+ int unit = dvp->id_unit;
+ u_short board_id, id_var1, id_var2, checksum = 0;
+ u_short eaddrtemp, irq;
+ u_short pg, adjust, decode, edecode;
+ u_char bart_config;
+ u_long bd_maddr;
+
+ short irq_translate[] = {0, IRQ9, IRQ3, IRQ4, IRQ5, IRQ10, IRQ11, 0};
+ char irq_encode[] = { 0, 0, 0, 2, 3, 4, 0, 0,
+ 0, 1, 5, 6, 0, 0, 0, 0 };
+
+ /* Need this for part of the probe. */
+ sc->ie_reset_586 = ee16_reset_586;
+ sc->ie_chan_attn = ee16_chan_attn;
+
+ /* unsure if this is necessary */
+ sc->bus_use = 0;
+
+ /* reset any ee16 at the current iobase */
+ outb(dvp->id_iobase + IEE16_ECTRL, IEE16_RESET_ASIC);
+ outb(dvp->id_iobase + IEE16_ECTRL, 0);
+ DELAY(240);
+
+ /* now look for ee16. */
+ board_id = id_var1 = id_var2 = 0;
+ for (i=0; i<4 ; i++) {
+ id_var1 = inb(dvp->id_iobase + IEE16_ID_PORT);
+ id_var2 = ((id_var1 & 0x03) << 2);
+ board_id |= (( id_var1 >> 4) << id_var2);
+ }
+
+ if (board_id != IEE16_ID) {
+ printf("ie%d: unknown board_id: %x\n", unit, board_id);
+ return 0;
+ }
+
+ /* need sc->port for ee16_read_eeprom */
+ sc->port = dvp->id_iobase;
+ sc->hard_type = IE_EE16;
+
+ /*
+ * The shared RAM location on the EE16 is encoded into bits
+ * 3-7 of EEPROM location 6. We zero the upper byte, and
+ * shift the 5 bits right 3. The resulting number tells us
+ * the RAM location. Because the EE16 supports either 16k or 32k
+ * of shared RAM, we only worry about the 32k locations.
+ *
+ * NOTE: if a 64k EE16 exists, it should be added to this switch.
+ * then the ia->ia_msize would need to be set per case statement.
+ *
+ * value msize location
+ * ===== ===== ========
+ * 0x03 0x8000 0xCC000
+ * 0x06 0x8000 0xD0000
+ * 0x0C 0x8000 0xD4000
+ * 0x18 0x8000 0xD8000
+ *
+ */
+
+ bd_maddr = 0;
+ i = (ee16_read_eeprom(sc, 6) & 0x00ff ) >> 3;
+ switch(i) {
+ case 0x03:
+ bd_maddr = 0xCC000;
+ break;
+ case 0x06:
+ bd_maddr = 0xD0000;
+ break;
+ case 0x0c:
+ bd_maddr = 0xD4000;
+ break;
+ case 0x18:
+ bd_maddr = 0xD8000;
+ break;
+ default:
+ bd_maddr = 0 ;
+ break;
+ }
+ dvp->id_msize = 0x8000;
+ if (kvtop(dvp->id_maddr) != bd_maddr) {
+ printf("ie%d: kernel configured maddr %lx doesn't match board configured maddr %x\n",
+ unit, kvtop(dvp->id_maddr), bd_maddr);
+ }
+
+
+ sc->iomembot = dvp->id_maddr;
+ sc->iomem = 0; /* XXX some probes set this and some don't */
+ sc->iosize = dvp->id_msize;
+
+ /* need to put the 586 in RESET while we access the eeprom. */
+ outb( PORT + IEE16_ECTRL, IEE16_RESET_586);
+
+ /* read the eeprom and checksum it, should == IEE16_ID */
+ for(i = 0; i < 0x40; i++)
+ checksum += ee16_read_eeprom(sc, i);
+
+ if (checksum != IEE16_ID) {
+ printf("ie%d: invalid eeprom checksum: %x\n", unit, checksum);
+ return 0;
+ }
+
+ /*
+ * Size and test the memory on the board. The size of the memory
+ * can be one of 16k, 32k, 48k or 64k. It can be located in the
+ * address range 0xC0000 to 0xEFFFF on 16k boundaries.
+ *
+ * If the size does not match the passed in memory allocation size
+ * issue a warning, but continue with the minimum of the two sizes.
+ */
+
+ switch (dvp->id_msize) {
+ case 65536:
+ case 32768: /* XXX Only support 32k and 64k right now */
+ break;
+ case 16384:
+ case 49512:
+ default:
+ printf("ie%d: mapped memory size %d not supported\n", unit,
+ dvp->id_msize);
+ return 0;
+ break; /* NOTREACHED */
+ }
+
+ if ((kvtop(dvp->id_maddr) < 0xC0000) ||
+ (kvtop(dvp->id_maddr) + sc->iosize > 0xF0000)) {
+ printf("ie%d: mapped memory location %x out of range\n", unit,
+ dvp->id_maddr);
+ return 0;
+ }
+
+ pg = (kvtop(dvp->id_maddr) & 0x3C000) >> 14;
+ adjust = IEE16_MCTRL_FMCS16 | (pg & 0x3) << 2;
+ decode = ((1 << (sc->iosize / 16384)) - 1) << pg;
+ edecode = ((~decode >> 4) & 0xF0) | (decode >> 8);
+
+ /* ZZZ This should be checked against eeprom location 6, low byte */
+ outb(PORT + IEE16_MEMDEC, decode & 0xFF);
+ /* ZZZ This should be checked against eeprom location 1, low byte */
+ outb(PORT + IEE16_MCTRL, adjust);
+ /* ZZZ Now if I could find this one I would have it made */
+ outb(PORT + IEE16_MPCTRL, (~decode & 0xFF));
+ /* ZZZ I think this is location 6, high byte */
+ outb(PORT + IEE16_MECTRL, edecode); /*XXX disable Exxx */
+
+ (void)kvtop(dvp->id_maddr);
+
+ /*
+ * first prime the stupid bart DRAM controller so that it
+ * works, then zero out all of memory.
+ */
+ bzero(sc->iomembot, 32);
+ bzero(sc->iomembot, sc->iosize);
+
+ /*
+ * Get the encoded interrupt number from the EEPROM, check it
+ * against the passed in IRQ. Issue a warning if they do not
+ * match. Always use the passed in IRQ, not the one in the EEPROM.
+ */
+ irq = ee16_read_eeprom(sc, IEE16_EEPROM_CONFIG1);
+ irq = (irq & IEE16_EEPROM_IRQ) >> IEE16_EEPROM_IRQ_SHIFT;
+ irq = irq_translate[irq];
+ if (dvp->id_irq > 0) {
+ if (irq != dvp->id_irq) {
+ printf("ie%d: WARNING: board configured at irq %d, using %d\n",
+ dvp->id_unit, irq);
+ irq = dvp->id_unit;
+ }
+ } else {
+ dvp->id_irq = irq;
+ }
+ sc->irq_encoded = irq_encode[ffs(irq) - 1];
+
+ /*
+ * Get the hardware ethernet address from the EEPROM and
+ * save it in the softc for use by the 586 setup code.
+ */
+ eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_HIGH);
+ sc->arpcom.ac_enaddr[1] = eaddrtemp & 0xFF;
+ sc->arpcom.ac_enaddr[0] = eaddrtemp >> 8;
+ eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_MID);
+ sc->arpcom.ac_enaddr[3] = eaddrtemp & 0xFF;
+ sc->arpcom.ac_enaddr[2] = eaddrtemp >> 8;
+ eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_LOW);
+ sc->arpcom.ac_enaddr[5] = eaddrtemp & 0xFF;
+ sc->arpcom.ac_enaddr[4] = eaddrtemp >> 8;
+
+ /* disable the board interrupts */
+ outb(PORT + IEE16_IRQ, sc->irq_encoded);
+
+ /* enable loopback to keep bad packets off the wire */
+ if(sc->hard_type == IE_EE16) {
+ bart_config = inb(PORT + IEE16_CONFIG);
+ bart_config |= IEE16_BART_LOOPBACK;
+ bart_config |= IEE16_BART_MCS16_TEST; /*inb doesn't get bit! */
+ outb(PORT + IEE16_CONFIG, bart_config);
+ bart_config = inb(PORT + IEE16_CONFIG);
+ }
+
+ /* take the board out of reset state */
+ outb(PORT + IEE16_ECTRL, 0);
+ DELAY(100);
+
+ if (!check_ie_present(unit, dvp->id_maddr, sc->iosize))
+ return 0;
+
+ return 16; /* return the number of I/O ports */
+}
+
/*
* Taken almost exactly from Bill's if_is.c, then modified beyond recognition.
*/
@@ -553,7 +815,7 @@ ieattach(dvp)
ifp->if_unit = unit;
ifp->if_name = iedriver.name;
ifp->if_mtu = ETHERMTU;
- printf(" <%s R%d> ethernet address %6D\n",
+ printf("ie%d: <%s R%d> address %6D\n", unit,
ie_hardware_names[ie->hard_type],
ie->hard_vers + 1,
ie->arpcom.ac_enaddr, ":");
@@ -566,6 +828,9 @@ ieattach(dvp)
ifp->if_addrlen = 6;
ifp->if_hdrlen = 14;
+ if (ie->hard_type == IE_EE16)
+ at_shutdown(ee16_shutdown, ie, SHUTDOWN_POST_SYNC);
+
#if NBPFILTER > 0
bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
#endif
@@ -578,21 +843,22 @@ ieattach(dvp)
/*
* What to do upon receipt of an interrupt.
*/
-void ieintr(unit)
- int unit;
+void
+ieintr(unit)
+ int unit;
{
register struct ie_softc *ie = &ie_softc[unit];
register u_short status;
- status = ie->scb->ie_status;
+ /* Clear the interrupt latch on the 3C507. */
+ if (ie->hard_type == IE_3C507 && (inb(PORT + IE507_CTRL) & EL_CTRL_INTL))
+ outb(PORT + IE507_ICTRL, 1);
- /* This if statement written by Charles Martin Hannum. */
- if ((status & IE_ST_WHENCE) == 0) {
- /* Clear the interrupt latch on the 3C507. */
- if (ie->hard_type == IE_3C507 &&
- (inb(PORT + IE507_CTRL) & EL_CTRL_INTL))
- outb(PORT + IE507_ICTRL, 1);
- }
+ /* disable interrupts on the EE16. */
+ if (ie->hard_type == IE_EE16)
+ outb(PORT + IEE16_IRQ, ie->irq_encoded);
+
+ status = ie->scb->ie_status;
loop:
if(status & (IE_ST_RECV | IE_ST_RNR)) {
@@ -632,25 +898,30 @@ loop:
&& (ie_debug & IED_CNA))
printf("ie%d: cna\n", unit);
#endif
-
+
/* Don't ack interrupts which we didn't receive */
ie_ack(ie->scb, IE_ST_WHENCE & status, unit, ie->ie_chan_attn);
- if((status = ie->scb->ie_status) & IE_ST_WHENCE)
- goto loop;
+ if ((status = ie->scb->ie_status) & IE_ST_WHENCE)
+ goto loop;
- /* This comment and if statement written by Charles Martin Hannum. */
/* Clear the interrupt latch on the 3C507. */
if (ie->hard_type == IE_3C507)
- outb(PORT + IE507_ICTRL, 1);
+ outb(PORT + IE507_ICTRL, 1);
+
+ /* enable interrupts on the EE16. */
+ if (ie->hard_type == IE_EE16)
+ outb(PORT + IEE16_IRQ, ie->irq_encoded | IEE16_IRQ_ENABLE);
+
}
/*
* Process a received-frame interrupt.
*/
-static int ierint(unit, ie)
- int unit;
- struct ie_softc *ie;
+static int
+ierint(unit, ie)
+ int unit;
+ struct ie_softc *ie;
{
int i, status;
static int timesthru = 1024;
@@ -662,8 +933,9 @@ static int ierint(unit, ie)
if((status & IE_FD_COMPLETE) && (status & IE_FD_OK)) {
ie->arpcom.ac_if.if_ipackets++;
if(!--timesthru) {
- ie->arpcom.ac_if.if_ierrors += ie->scb->ie_err_crc + ie->scb->ie_err_align +
- ie->scb->ie_err_resource + ie->scb->ie_err_overrun;
+ ie->arpcom.ac_if.if_ierrors +=
+ ie->scb->ie_err_crc + ie->scb->ie_err_align +
+ ie->scb->ie_err_resource + ie->scb->ie_err_overrun;
ie->scb->ie_err_crc = 0;
ie->scb->ie_err_align = 0;
ie->scb->ie_err_resource = 0;
@@ -918,7 +1190,7 @@ static inline int ie_packet_len(int unit, struct ie_softc *ie) {
i = ie->rbuffs[head]->ie_rbd_actual & IE_RBD_LAST;
acc += ie_buflen(ie, head);
- head = (head + 1) % NBUFFS;
+ head = (head + 1) % NRXBUF;
} while(!i);
return acc;
@@ -1086,9 +1358,9 @@ nextbuf:
offset = 0;
ie->rbuffs[head]->ie_rbd_actual = 0;
ie->rbuffs[head]->ie_rbd_length |= IE_RBD_LAST;
- ie->rbhead = head = (head + 1) % NBUFFS;
+ ie->rbhead = head = (head + 1) % NRXBUF;
ie->rbuffs[ie->rbtail]->ie_rbd_length &= ~IE_RBD_LAST;
- ie->rbtail = (ie->rbtail + 1) % NBUFFS;
+ ie->rbtail = (ie->rbtail + 1) % NRXBUF;
}
/*
@@ -1223,9 +1495,9 @@ static void ie_drop_packet_buffer(int unit, struct ie_softc *ie) {
ie->rbuffs[ie->rbhead]->ie_rbd_length |= IE_RBD_LAST;
ie->rbuffs[ie->rbhead]->ie_rbd_actual = 0;
- ie->rbhead = (ie->rbhead + 1) % NBUFFS;
+ ie->rbhead = (ie->rbhead + 1) % NRXBUF;
ie->rbuffs[ie->rbtail]->ie_rbd_length &= ~IE_RBD_LAST;
- ie->rbtail = (ie->rbtail + 1) % NBUFFS;
+ ie->rbtail = (ie->rbtail + 1) % NRXBUF;
} while(!i);
}
@@ -1264,7 +1536,7 @@ iestart(ifp)
}
m_freem(m0);
- len = max(len, ETHERMINLEN);
+ len = max(len, ETHER_MIN_LEN);
#if NBPFILTER > 0
/*
@@ -1288,7 +1560,7 @@ iestart(ifp)
*bptr = MK_16(ie->iomem, ie->xmit_cmds[ie->xmit_count]);
bptr = &ie->xmit_cmds[ie->xmit_count]->com.ie_cmd_link;
ie->xmit_count++;
- } while(ie->xmit_count < 2);
+ } while (ie->xmit_count < NTXBUF);
/*
* If we queued up anything for transmission, send it.
@@ -1433,6 +1705,16 @@ void sl_reset_586(unit)
outb(PORT + IEATT_RESET, 0);
}
+void
+ee16_reset_586(unit)
+ int unit;
+{
+ outb(PORT + IEE16_ECTRL, IEE16_RESET_586);
+ DELAY(100);
+ outb(PORT + IEE16_ECTRL, 0);
+ DELAY(100);
+}
+
void el_chan_attn(unit)
int unit;
{
@@ -1445,6 +1727,105 @@ void sl_chan_attn(unit)
outb(PORT + IEATT_ATTN, 0);
}
+void
+ee16_chan_attn(unit)
+ int unit;
+{
+ outb(PORT + IEE16_ATTN, 0);
+}
+
+u_short
+ee16_read_eeprom(sc, location)
+ struct ie_softc *sc;
+ int location;
+{
+ int ectrl, edata;
+
+ ectrl = inb(sc->port + IEE16_ECTRL);
+ ectrl &= IEE16_ECTRL_MASK;
+ ectrl |= IEE16_ECTRL_EECS;
+ outb(sc->port + IEE16_ECTRL, ectrl);
+
+ ee16_eeprom_outbits(sc, IEE16_EEPROM_READ, IEE16_EEPROM_OPSIZE1);
+ ee16_eeprom_outbits(sc, location, IEE16_EEPROM_ADDR_SIZE);
+ edata = ee16_eeprom_inbits(sc);
+ ectrl = inb(sc->port + IEE16_ECTRL);
+ ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EEDI | IEE16_ECTRL_EECS);
+ outb(sc->port + IEE16_ECTRL, ectrl);
+ ee16_eeprom_clock(sc, 1);
+ ee16_eeprom_clock(sc, 0);
+ return edata;
+}
+
+void
+ee16_eeprom_outbits(sc, edata, count)
+ struct ie_softc *sc;
+ int edata, count;
+{
+ int ectrl, i;
+
+ ectrl = inb(sc->port + IEE16_ECTRL);
+ ectrl &= ~IEE16_RESET_ASIC;
+ for (i = count - 1; i >= 0; i--) {
+ ectrl &= ~IEE16_ECTRL_EEDI;
+ if (edata & (1 << i)) {
+ ectrl |= IEE16_ECTRL_EEDI;
+ }
+ outb(sc->port + IEE16_ECTRL, ectrl);
+ DELAY(1); /* eeprom data must be setup for 0.4 uSec */
+ ee16_eeprom_clock(sc, 1);
+ ee16_eeprom_clock(sc, 0);
+ }
+ ectrl &= ~IEE16_ECTRL_EEDI;
+ outb(sc->port + IEE16_ECTRL, ectrl);
+ DELAY(1); /* eeprom data must be held for 0.4 uSec */
+}
+
+int
+ee16_eeprom_inbits(sc)
+ struct ie_softc *sc;
+{
+ int ectrl, edata, i;
+
+ ectrl = inb(sc->port + IEE16_ECTRL);
+ ectrl &= ~IEE16_RESET_ASIC;
+ for (edata = 0, i = 0; i < 16; i++) {
+ edata = edata << 1;
+ ee16_eeprom_clock(sc, 1);
+ ectrl = inb(sc->port + IEE16_ECTRL);
+ if (ectrl & IEE16_ECTRL_EEDO) {
+ edata |= 1;
+ }
+ ee16_eeprom_clock(sc, 0);
+ }
+ return (edata);
+}
+
+void
+ee16_eeprom_clock(sc, state)
+ struct ie_softc *sc;
+ int state;
+{
+ int ectrl;
+
+ ectrl = inb(sc->port + IEE16_ECTRL);
+ ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EESK);
+ if (state) {
+ ectrl |= IEE16_ECTRL_EESK;
+ }
+ outb(sc->port + IEE16_ECTRL, ectrl);
+ DELAY(9); /* EESK must be stable for 8.38 uSec */
+}
+
+static inline void
+ee16_interrupt_enable(sc)
+ struct ie_softc *sc;
+{
+ DELAY(100);
+ outb(sc->port + IEE16_IRQ, sc->irq_encoded | IEE16_IRQ_ENABLE);
+ DELAY(100);
+}
+
void sl_read_ether(unit, addr)
int unit;
unsigned char addr[6];
@@ -1651,7 +2032,7 @@ static caddr_t setup_rfa(caddr_t ptr, struct ie_softc *ie) {
*/
rbd = (void *)ptr;
- for(i = 0; i < NBUFFS; i++) {
+ for(i = 0; i < NRXBUF; i++) {
ie->rbuffs[i] = rbd;
bzero((char *)rbd, sizeof *rbd); /* ignore cast-qual */
ptr = (caddr_t)Align(ptr + sizeof *rbd);
@@ -1663,19 +2044,19 @@ static caddr_t setup_rfa(caddr_t ptr, struct ie_softc *ie) {
}
/* Now link them together */
- for(i = 0; i < NBUFFS; i++) {
- ie->rbuffs[i]->ie_rbd_next = MK_16(MEM, ie->rbuffs[(i + 1) % NBUFFS]);
+ for(i = 0; i < NRXBUF; i++) {
+ ie->rbuffs[i]->ie_rbd_next = MK_16(MEM, ie->rbuffs[(i + 1) % NRXBUF]);
}
/* Tag EOF on the last one */
- ie->rbuffs[NBUFFS - 1]->ie_rbd_length |= IE_RBD_LAST;
+ ie->rbuffs[NRXBUF - 1]->ie_rbd_length |= IE_RBD_LAST;
/* We use the head and tail pointers on receive to keep track of
* the order in which RFDs and RBDs are used. */
ie->rfhead = 0;
ie->rftail = NFRAMES - 1;
ie->rbhead = 0;
- ie->rbtail = NBUFFS - 1;
+ ie->rbtail = NRXBUF - 1;
ie->scb->ie_recv_list = MK_16(MEM, ie->rframes[0]);
ie->rframes[0]->ie_fd_buf_desc = MK_16(MEM, ie->rbuffs[0]);
@@ -1780,6 +2161,21 @@ ieinit(unit)
*/
ie_ack(ie->scb, IE_ST_WHENCE, unit, ie->ie_chan_attn);
+ /* take the ee16 out of loopback */
+ {
+ u_char bart_config;
+
+ if(ie->hard_type == IE_EE16) {
+ bart_config = inb(PORT + IEE16_CONFIG);
+ bart_config &= ~IEE16_BART_LOOPBACK;
+ /* inb doesn't get bit! */
+ bart_config |= IEE16_BART_MCS16_TEST;
+ outb(PORT + IEE16_CONFIG, bart_config);
+ ee16_interrupt_enable(ie);
+ ee16_chan_attn(unit);
+ }
+ }
+
/*
* Set up the RFA.
*/
@@ -1819,7 +2215,7 @@ ieinit(unit)
*/
ie->xmit_cmds[0]->ie_xmit_status = IE_STAT_COMPL;
- ie->arpcom.ac_if.if_flags |= IFF_RUNNING; /* tell higher levels that we are here */
+ ie->arpcom.ac_if.if_flags |= IFF_RUNNING; /* tell higher levels we're here */
start_receiver(unit);
return;
}
diff --git a/sys/i386/isa/if_ix.c b/sys/i386/isa/if_ix.c
deleted file mode 100644
index 998f690..0000000
--- a/sys/i386/isa/if_ix.c
+++ /dev/null
@@ -1,1634 +0,0 @@
-/*
- * Copyright (c) 1993, 1994, 1995
- * Rodney W. Grimes, Milwaukie, Oregon 97222. 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 as
- * the first lines of this file unmodified.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Rodney W. Grimes.
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY RODNEY W. GRIMES ``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 RODNEY W. GRIMES 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.
- *
- * $Id: if_ix.c,v 1.25 1997/02/22 09:36:31 peter Exp $
- */
-
-#include "ix.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/sockio.h>
-#include <sys/errno.h>
-#include <sys/syslog.h>
-
-#include <machine/clock.h>
-#include <machine/md_var.h>
-
-#include <net/if.h>
-#include <net/if_types.h>
-#include <net/if_dl.h>
-
-#ifdef INET
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/in_var.h>
-#include <netinet/ip.h>
-#include <netinet/if_ether.h>
-#endif /* INET */
-
-#ifdef IPX /*ZZZ no work done on this, this is just here to remind me*/
-#include <netipx/ipx.h>
-#include <netipx/ipx_if.h>
-#endif /* IPX */
-
-#ifdef NS /*ZZZ no work done on this, this is just here to remind me*/
-#include <netns/ns.h>
-#include <netns/ns_if.h>
-#endif /* NS */
-
-#ifdef ISO /*ZZZ no work done on this, this is just here to remind me*/
-#include <netiso/iso.h>
-#include <netiso/iso_var.h>
-extern char all_es_snpa[], all_is_snpa[], all_l1is_snpa[], all_l2is_snpa[];
-#endif /* ISO */
-
-/*ZZZ no work done on this, this is just here to remind me*/
-#include "bpfilter.h"
-#if NBPFILTER > 0
-#include <net/bpf.h>
-#include <net/bpfdesc.h>
-#endif /* NBPFILTER > 0 */
-
-#include <i386/isa/isa_device.h>
-#include <i386/isa/icu.h>
-#include <i386/isa/if_ixreg.h>
-
-static ix_softc_t ix_softc[NIX];
-
-#define DEBUGNONE 0x0000
-#define DEBUGPROBE 0x0001
-#define DEBUGATTACH (DEBUGPROBE << 1)
-#define DEBUGINIT (DEBUGATTACH << 1)
-#define DEBUGINIT_RFA (DEBUGINIT << 1)
-#define DEBUGINIT_TFA (DEBUGINIT_RFA << 1)
-#define DEBUGINTR (DEBUGINIT_TFA << 1)
-#define DEBUGINTR_FR (DEBUGINTR << 1)
-#define DEBUGINTR_CX (DEBUGINTR_FR << 1)
-#define DEBUGSTART (DEBUGINTR_CX << 1)
-#define DEBUGSTOP (DEBUGSTART << 1)
-#define DEBUGRESET (DEBUGSTOP << 1)
-#define DEBUGDONE (DEBUGRESET << 1)
-#define DEBUGIOCTL (DEBUGDONE << 1)
-#define DEBUGACK (DEBUGIOCTL << 1)
-#define DEBUGCA (DEBUGACK << 1)
-#define DEBUGCB_WAIT (DEBUGCA << 1)
-#define DEBUGALL 0xFFFFFFFF
-
-/*
-#define IXDEBUG (DEBUGPROBE | DEBUGINIT | DEBUGSTOP | DEBUGCB_WAIT)
-*/
-
-#ifdef IXDEBUG
-int ixdebug=IXDEBUG;
-#define DEBUGBEGIN(flag) \
- {\
- if (ixdebug & flag)\
- {
-#define DEBUGEND \
- }\
- }
-#define DEBUGDO(x) x
-
-#else /* IXDEBUG */
-
-#define DEBUGBEGIN(flag)
-#define DEBUGEND
-#define DEBUGDO(x)
-#endif /* IXDEBUG */
-
-/*
- * Enable the exteneded ixcounters by using #define IXCOUNTERS, note that
- * this requires a modification to the ifnet structure to add the counters
- * in. Some day a standard extended ifnet structure will be done so that
- * additional statistics can be gathered for any board that supports these
- * counters.
- */
-#ifdef IXCOUNTERS
-#define IXCOUNTER(x) x
-#else /* IXCOUNTERS */
-#define IXCOUNTER(x)
-#endif /* IXCOUNTERS */
-
-/*
- * Function Prototypes
- */
-static inline void ixinterrupt_enable(int);
-static inline void ixinterrupt_disable(int);
-static inline void ixchannel_attention(int);
-static u_short ixacknowledge(int);
-static int ix_cb_wait(cb_t *, char *);
-static int ix_scb_wait(scb_t *, u_short, char *);
-static int ixprobe(struct isa_device *);
-static int ixattach(struct isa_device *);
-static void ixinit(int);
-static void ixinit_rfa(int);
-static void ixinit_tfa(int);
-static inline void ixintr_cx(int);
-static inline void ixintr_cx_free(int, cb_t *);
-static inline void ixintr_fr(int);
-static inline void ixintr_fr_copy(int, rfd_t *);
-static inline void ixintr_fr_free(int, rfd_t *);
-static void ixstart(struct ifnet *);
-static int ixstop(struct ifnet *);
-static int ixdone(struct ifnet *);
-static int ixioctl(struct ifnet *, int, caddr_t);
-static void ixreset(int);
-static void ixwatchdog(struct ifnet *);
-static u_short ixeeprom_read(int, int);
-static void ixeeprom_outbits(int, int, int);
-static int ixeeprom_inbits(int);
-static void ixeeprom_clock(int, int);
-/*
-RRR */
-
-struct isa_driver ixdriver = {ixprobe, ixattach, "ix"};
-
-/*
- * Enable the interrupt signal on the board so that it may interrupt
- * the host.
- */
-static inline void
-ixinterrupt_enable(int unit) {
- ix_softc_t *sc = &ix_softc[unit];
-
- outb(sc->iobase + sel_irq, sc->irq_encoded | IRQ_ENABLE);
-}
-
-/*
- * Disable the interrupt signal on the board so that it will not interrupt
- * the host.
- */
-static inline void
-ixinterrupt_disable(int unit) {
- ix_softc_t *sc = &ix_softc[unit];
-
- outb(sc->iobase + sel_irq, sc->irq_encoded);
-}
-
-/*
- * Send a channel attention to the 82586 chip
- */
-static inline void
-ixchannel_attention(int unit) {
- DEBUGBEGIN(DEBUGCA)
- DEBUGDO(printf("ca");)
- DEBUGEND
- outb(ix_softc[unit].iobase + ca_ctrl, 0);
-}
-
-u_short
-ixacknowledge(int unit) {
- ix_softc_t *sc = &ix_softc[unit];
- scb_t *scb = (scb_t *)(sc->maddr + SCB_ADDR);
- u_short status;
- int i;
-
- DEBUGBEGIN(DEBUGACK)
- DEBUGDO(printf("ack:");)
- DEBUGEND
- status = scb->status;
- scb->command = status & SCB_ACK_MASK;
- if ((status & SCB_ACK_MASK) != 0) {
- ixchannel_attention(unit);
- for (i = 1000000; scb->command && (i > 0); i--); /*ZZZ timeout*/
- if (i == 0) {
- printf(".TO=%x:", scb->command);
- printf("\nshutting down\n");
- ixinterrupt_disable(unit);
- sc->flags = IXF_NONE;
- status = 0;
- } else {
- DEBUGBEGIN(DEBUGACK)
- DEBUGDO(printf(".ok:");)
- DEBUGEND
- }
- } else {
- /* nothing to acknowledge */
- DEBUGBEGIN(DEBUGACK)
- DEBUGDO(printf("NONE:");)
- DEBUGEND
- }
- DEBUGBEGIN(DEBUGACK)
- DEBUGDO(printf("%x ", status);)
- DEBUGEND
- return(status);
-}
-
-int
-ix_cb_wait(cb_t *cb, char *message) {
- int i;
- int status;
-
- for (i=1000000; i>0; i--) {
- if (cb->status & CB_COMPLETE) break; /* Wait for done */
- }
- if (i == 0) {
- printf("%s timeout cb->status = %x\n", message, cb->status);
- status = 1;
- } else {
- DEBUGBEGIN(DEBUGCB_WAIT)
- DEBUGDO(printf("%s cb ok count = %d\n", message, i);)
- DEBUGEND
- status = 0;
- }
- return (status);
-}
-
-int
-ix_scb_wait(scb_t *scb, u_short expect, char *message) {
- int i;
- int status;
-
- for (i=1000000; i>0; i--) {
- if (scb->status == expect) break; /* Wait for done */
- }
- if (i == 0) {
- printf("%s timeout scb->status = %x\n", message, scb->status);
- status = 1;
- } else {
- DEBUGBEGIN(DEBUGINIT)
- DEBUGDO(printf("%s scb ok count = %d\n", message, i);)
- DEBUGEND
- status = 0;
- }
- return (status);
-}
-
-int
-ixprobe(struct isa_device *dvp) {
- int unit = dvp->id_unit;
- ix_softc_t *sc = &ix_softc[unit];
- char tempid, idstate;
- int i;
- int status = 0;
- u_short boardid,
- checksum,
- connector,
- eaddrtemp,
- irq;
- /* ZZZ irq_translate should really be unsigned, but until
- * isa_device.h and all uses are fixed we have to live with it */
- short irq_translate[] = {0, IRQ9, IRQ3, IRQ4, IRQ5, IRQ10, IRQ11, 0};
- char irq_encode[] = { 0, 0, 0, 2, 3, 4, 0, 0, 0, 1, 5, 6, 0, 0, 0, 0 };
-
- DEBUGBEGIN(DEBUGPROBE)
- DEBUGDO(printf ("ixprobe:");)
- DEBUGEND
-
- /*
- * Since Intel gives us such a nice way to ID this board lets
- * see if we really have one at this I/O address
- */
- idstate = inb(dvp->id_iobase + autoid) & 0x03;
- for (i=0, boardid=0; i < 4; i++) {
- tempid = inb(dvp->id_iobase + autoid);
- boardid |= ((tempid & 0xF0) >> 4) << ((tempid & 0x03) << 2);
- if ((tempid & 0x03) != (++idstate & 0x03)) {
- /* out of sequence, destroy boardid and bail out */
- boardid = 0;
- break;
- }
- }
- DEBUGBEGIN(DEBUGPROBE)
- DEBUGDO(printf("boardid = %x\n", boardid);)
- DEBUGEND
- if (boardid != BOARDID) {
- goto ixprobe_exit;
- }
-
- /*
- * We now know that we have a board, so save the I/O base
- * address in the softc and use the softc from here on out
- */
- sc->iobase = dvp->id_iobase;
-
- /*
- * Reset the Bart ASIC by pulsing the reset bit and waiting
- * the required 240 uSecounds. Also place the 82856 in the reset
- * mode so that we can access the EEPROM
- */
- outb(sc->iobase + ee_ctrl, GA_RESET);
- outb(sc->iobase + ee_ctrl, 0);
- DELAY(240);
- outb(sc->iobase + ee_ctrl, I586_RESET);
-
- /*
- * Checksum the EEPROM, should be equal to BOARDID
- */
- for (i=0, checksum=0; i<64; i++) {
- checksum += ixeeprom_read(unit, i);
- }
- DEBUGBEGIN(DEBUGPROBE)
- DEBUGDO(printf ("checksum = %x\n", checksum);)
- DEBUGEND
- if (checksum != BOARDID) {
- goto ixprobe_exit;
- }
-
- /*
- * Do the I/O channel ready test
- */
- {
- u_char lock_bit;
-
- lock_bit = ixeeprom_read(unit, eeprom_lock_address);
- if (lock_bit & EEPROM_LOCKED) {
- DEBUGBEGIN(DEBUGPROBE)
- DEBUGDO(printf ("lockbit set, no doing io channel ready test\n");)
- DEBUGEND
- } else {
- u_char bart_config,
- junk;
-
- bart_config = inb(sc->iobase + config);
- bart_config |= BART_IOCHRDY_LATE | BART_IO_TEST_EN;
- outb(sc->iobase + config, bart_config);
- junk = inb(sc->iobase + 0x4000); /*XXX read junk */
- bart_config = inb(sc->iobase + config);
- outb(sc->iobase + config, bart_config & ~(BART_IO_TEST_EN));
- if (bart_config & BART_IO_RESULT) {
- printf ("iochannel ready test failed!!\n");
- } else {
- DEBUGBEGIN(DEBUGPROBE)
- DEBUGDO(printf ("iochannel ready test passed\n");)
- DEBUGEND
- }
- }
- }
-
- /*
- * Size and test the memory on the board. The size of the memory
- * can be one of 16k, 32k, 48k or 64k. It can be located in the
- * address range 0xC0000 to 0xEFFFF on 16k boundaries. Although
- * the board can be configured for 0xEC0000 to 0xEEFFFF,
- * or 0xFC0000 to 0xFFFFFF these ranges are not supported by 386bsd.
- *
- * If the size does not match the passed in memory allocation size
- * issue a warning, but continue with the minimum of the two sizes.
- */
- {
- u_short memory_page;
- u_short memory_adjust;
- u_short memory_decode;
- u_short memory_edecode;
-
- switch (dvp->id_msize) {
- case 65536:
- case 32768: /* XXX Only support 32k and 64k right now */
- { break; }
- case 16384:
- case 49512:
- default: {
- printf("ixprobe mapped memory size out of range\n");
- goto ixprobe_exit;
- }
- }
-
- if ((kvtop(dvp->id_maddr) < 0xC0000) ||
- (kvtop(dvp->id_maddr) + dvp->id_msize > 0xF0000)) {
- printf("ixprobe mapped memory address out of range\n");
- goto ixprobe_exit;
- }
-
- memory_page = (kvtop(dvp->id_maddr) & 0x3C000) >> 14;
- memory_adjust = MEMCTRL_FMCS16 | (memory_page & 0x3) << 2;
- memory_decode = ((1 << (dvp->id_msize / 16384)) - 1) << memory_page;
- memory_edecode = ((~memory_decode >> 4) & 0xF0) | (memory_decode >> 8);
-
- /* ZZZ This should be checked against eeprom location 6, low byte */
- outb(sc->iobase + memdec, memory_decode & 0xFF);
- /* ZZZ This should be checked against eeprom location 1, low byte */
- outb(sc->iobase + memctrl, memory_adjust);
- /* ZZZ Now if I could find this one I would have it made */
- outb(sc->iobase + mempc, (~memory_decode & 0xFF));
- /* ZZZ I think this is location 6, high byte */
- outb(sc->iobase + memectrl, memory_edecode); /*XXX disable Exxx */
-
- sc->maddr = dvp->id_maddr;
- sc->msize = dvp->id_msize;
-
- DEBUGBEGIN(DEBUGPROBE)
- DEBUGDO(printf("Physical address = %lx\n", kvtop(sc->maddr));)
- DEBUGEND
- }
-
- /*
- * first prime the stupid bart DRAM controller so that it
- * works, then zero out all or memory.
- */
- bzero(sc->maddr, 32);
- bzero(sc->maddr, sc->msize);
-
- /*
- * Get the type of connector used, either AUI, BNC or TPE.
- */
- connector = ixeeprom_read(unit, eeprom_config1);
- if (connector & CONNECT_BNCTPE) {
- connector = ixeeprom_read(unit, eeprom_config2);
- if (connector & CONNECT_TPE) {
- sc->connector = TPE;
- DEBUGBEGIN(DEBUGPROBE)
- DEBUGDO(printf ("Using TPE connector\n");)
- DEBUGEND
- } else {
- sc->connector = BNC;
- DEBUGBEGIN(DEBUGPROBE)
- DEBUGDO(printf ("Using BNC connector\n");)
- DEBUGEND
- }
- } else {
- sc->connector = AUI;
- DEBUGBEGIN(DEBUGPROBE)
- DEBUGDO(printf ("Using AUI connector\n");)
- DEBUGEND
- }
-
- /*
- * Get the encoded interrupt number from the EEPROM, check it
- * against the passed in IRQ. Issue a warning if they do not
- * match. Always use the passed in IRQ, not the one in the EEPROM.
- */
- irq = ixeeprom_read(unit, eeprom_config1);
- irq = (irq & IRQ) >> IRQ_SHIFT;
- irq = irq_translate[irq];
- if (dvp->id_irq > 0) {
- if (irq != dvp->id_irq) {
- printf("ix%d: WARNING: board is configured for IRQ %d, using %d\n",
- unit, ffs(irq) - 1, ffs(dvp->id_irq) - 1);
- irq = dvp->id_irq;
- }
- } else {
- dvp->id_irq = irq;
- }
- sc->irq_encoded = irq_encode[ffs(irq) - 1];
- if (sc->irq_encoded == 0) {
- printf("ix%d: invalid irq (%d)\n", unit, ffs(irq) - 1);
- goto ixprobe_exit;
- }
-
- /*
- * Get the slot width, either 8 bit or 16 bit.
- */
- if (inb(sc->iobase + config) & SLOT_WIDTH) {
- sc->width = WIDTH_16;
- DEBUGBEGIN(DEBUGPROBE)
- DEBUGDO(printf("Using 16-bit slot\n");)
- DEBUGEND
- } else {
- sc->width = WIDTH_8;
- DEBUGBEGIN(DEBUGPROBE)
- DEBUGDO(printf("Using 8-bit slot\n");)
- DEBUGEND
- }
-
- /*
- * Get the hardware ethernet address from the EEPROM and
- * save it in the softc for use by the 586 setup code.
- */
- eaddrtemp = ixeeprom_read(unit, eeprom_enetaddr_high);
- sc->arpcom.ac_enaddr[1] = eaddrtemp & 0xFF;
- sc->arpcom.ac_enaddr[0] = eaddrtemp >> 8;
- eaddrtemp = ixeeprom_read(unit, eeprom_enetaddr_mid);
- sc->arpcom.ac_enaddr[3] = eaddrtemp & 0xFF;
- sc->arpcom.ac_enaddr[2] = eaddrtemp >> 8;
- eaddrtemp = ixeeprom_read(unit, eeprom_enetaddr_low);
- sc->arpcom.ac_enaddr[5] = eaddrtemp & 0xFF;
- sc->arpcom.ac_enaddr[4] = eaddrtemp >> 8;
-
- sc->flags = IXF_NONE; /* make sure the flag word is NONE */
- status = IX_IO_PORTS;
-
-ixprobe_exit:
- DEBUGBEGIN(DEBUGPROBE)
- DEBUGDO(printf ("ixprobe exited\n");)
- DEBUGEND
- return(status);
-}
-
-int
-ixattach(struct isa_device *dvp) {
- int unit = dvp->id_unit;
- ix_softc_t *sc = &ix_softc[unit];
- struct ifnet *ifp = &sc->arpcom.ac_if;
-
- DEBUGBEGIN(DEBUGATTACH)
- DEBUGDO(printf("ixattach:");)
- DEBUGEND
-
- /*
- * Fill in the interface parameters for if_attach
- * Note: We could save some code here by first using a
- * bzero(ifp, sizeof(ifp)); and then not doing all
- * the = 0;'s
- * Infact we should bzero this just to make sure
- * that something does not get missed.
- * Further note by GW:
- * Actually, it's a complete waste of time to zero any of
- * this stuff because the C language guarantees that it's
- * already zeroed. If this code is changed to do dynamic
- * allocation, this will have to get revisited.
- */
- bzero(ifp, sizeof(ifp));
- ifp->if_softc = sc;
- ifp->if_name = ixdriver.name;
- ifp->if_unit = unit;
- ifp->if_mtu = ETHERMTU;
- ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST;
- ifp->if_output = ether_output;
- ifp->if_start = ixstart;
- ifp->if_done = ixdone;
- ifp->if_ioctl = ixioctl;
- ifp->if_watchdog = ixwatchdog;
- ifp->if_type = IFT_ETHER;
- ifp->if_addrlen = ETHER_ADDR_LEN;
- ifp->if_hdrlen = ETHER_HDR_LEN;
-#ifdef IXCOUNTERS
- /*
- * ZZZ more counters added, but bzero gets them
- */
-#endif /* IXCOUNTERS */
-
- if_attach(ifp);
- ether_ifattach(ifp);
-
- printf("ix%d: address %6D\n", unit, sc->arpcom.ac_enaddr, ":");
- return(0);
-}
-
-void
-ixinit(int unit) {
- ix_softc_t *sc = &ix_softc[unit];
- struct ifnet *ifp = &sc->arpcom.ac_if;
- scp_t *scp = (scp_t *)(sc->maddr + SCP_ADDR);
- iscp_t *iscp = (iscp_t *)(sc->maddr + ISCP_ADDR);
- scb_t *scb = (scb_t *)(sc->maddr + SCB_ADDR);
- cb_t *cb;
- tbd_t *tbd;
- int i;
- u_char bart_config; /* bart config byte */
- int status = 0;
-
- DEBUGBEGIN(DEBUGINIT)
- DEBUGDO(printf("ixinit:");)
- DEBUGEND
-
- /* Put bart into loopback until we are done intializing to
- * make sure that packets don't hit the wire */
- bart_config = inb(sc->iobase + config);
- bart_config |= BART_LOOPBACK;
- bart_config |= BART_MCS16_TEST; /* inb does not get this bit! */
- outb(sc->iobase + config, bart_config);
- bart_config = inb(sc->iobase + config);
-
- scp->unused1 = 0; /* Intel says to put zeros in it */
- scp->sysbus = sc->width; /* ZZZ need to fix for 596 */
- scp->unused2 = 0; /* Intel says to put zeros in it */
- scp->unused3 = 0; /* Intel says to put zeros in it */
- scp->iscp = ISCP_ADDR;
-
- iscp->busy = ISCP_BUSY;
- iscp->scb_offset = SCB_ADDR;
- iscp->scb_base = TFA_START;
-
- scb->status = SCB_STAT_NULL;
- scb->command = SCB_RESET;
- scb->cbl_offset = TFA_START;
- scb->rfa_offset = RFA_START;
- scb->crc_errors = 0;
- scb->aln_errors = 0;
- scb->rsc_errors = 0;
- scb->ovr_errors = 0;
-
- ixinit_tfa(unit);
- ixinit_rfa(unit);
- cb = sc->cb_head;
- tbd = sc->tbd_head;
-
- /*
- * remove the reset signal and start the 586 up, the 586 well read
- * the SCP, ISCP and the reset CB. This should put it into a
- * known state: RESET!
- */
- outb(sc->iobase + ee_ctrl, EENORMAL);
- ixchannel_attention(unit);
-
- for (i=100000; iscp->busy && (i>0); i--); /* Wait for done */
- if (i == 0) {
- printf("iscp->busy time out\n");
- status = 1;
- } else {
- DEBUGBEGIN(DEBUGINIT)
- DEBUGDO(printf ("iscp->busy did not timeout = %d\n", i);)
- DEBUGEND
- }
-
- status |= ix_scb_wait(scb, (u_short)(SCB_STAT_CX | SCB_STAT_CNA),
- "Reset");
- ixacknowledge(unit);
-
-/* XXX this belongs some place else, run diagnostics on the 586 */
- {
- cb_diagnose_t *cb_diag = (cb_diagnose_t *)(cb);
-
- cb_diag->common.status = 0;
- cb_diag->common.command = CB_CMD_EL | CB_CMD_DIAGNOSE;
- scb->command = SCB_CUC_START;
- ixchannel_attention(unit);
- status |= ix_cb_wait((cb_t *)cb_diag, "Diagnose");
- status |= ix_scb_wait(scb, (u_short)SCB_STAT_CNA, "Diagnose");
- ixacknowledge(unit);
- }
-/* XXX end this belongs some place else, run diagnostics on the 586 */
-
-/* XXX this belongs some place else, run configure on the 586 */
- {
- cb_configure_t *cb_conf = (cb_configure_t *)(cb);
-
- cb_conf->common.status = 0;
- cb_conf->common.command = CB_CMD_EL | CB_CMD_CONF;
- cb_conf->byte[0] = 12; /* 12 byte configure block */
- cb_conf->byte[1] = 8; /* fifo limit at 8 bytes */
- cb_conf->byte[2] = 0x40; /* don't save bad frames,
- srdy/ardy is srdy */
- cb_conf->byte[3] = 0x2E; /* address length is 6 bytes,
- address and length are in tb,
- preamble length is 8 bytes,
- internal loopback off,
- external loopback off */
- cb_conf->byte[4] = 0; /* linear priority is 0,
- ACR (Exponential priorty) is 0,
- exponential backoff is 802.3 */
- cb_conf->byte[5] = 96; /* interframe spacing in TxC clocks */
- cb_conf->byte[6] = 0; /* lower 8 bits of slot time */
- cb_conf->byte[7] = 0xf2; /* upper slot time (512 bits),
- 15 transmision retries */
- cb_conf->byte[8] = 0; /* promiscuous mode off,
- broadcast enabled,
- nrz encodeing,
- cease transmission if ^CRS,
- insert crc,
- end of carrier mode bit stuffing,
- no padding */
- cb_conf->byte[9] = 0; /* carrier sense filter = 0 bits,
- carrier sense source external,
- collision detect filter = 0 bits,
- collision detect source external */
- cb_conf->byte[10] = 60; /* minimum number of bytes is a frame */
- cb_conf->byte[11] = 0; /* unused */
-
- scb->command = SCB_CUC_START;
- ixchannel_attention(unit);
- status |= ix_cb_wait((cb_t *)cb_conf, "Configure");
- status |= ix_scb_wait(scb, (u_short)SCB_STAT_CNA, "Configure");
- ixacknowledge(unit);
- }
-/* XXX end this belongs some place else, run configure on the 586 */
-
-/* XXX this belongs some place else, run ias on the 586 */
- {
- cb_ias_t *cb_ias = (cb_ias_t *)(cb);
-
- cb_ias->common.status = 0;
- cb_ias->common.command = CB_CMD_EL | CB_CMD_IAS;
- bcopy(sc->arpcom.ac_enaddr, cb_ias->source, ETHER_ADDR_LEN);
- scb->command = SCB_CUC_START;
- ixchannel_attention(unit);
- status |= ix_cb_wait((cb_t *)cb_ias, "IAS");
- status |= ix_scb_wait(scb, (u_short)SCB_STAT_CNA, "IAS");
- ixacknowledge(unit);
- }
-/* XXX end this belongs some place else, run ias on the 586 */
-
- if (status == 0) {
- /* Take bart out of loopback as we are done intializing */
- bart_config = inb(sc->iobase + config);
- bart_config &= ~BART_LOOPBACK;
- bart_config |= BART_MCS16_TEST; /* inb does not get this bit! */
- outb(sc->iobase + config, bart_config);
-
- /* The above code screwed with the tfa, reinit it! */
- ixinit_tfa(unit);
- scb->command = SCB_RUC_START; /* start up the receive unit */
- ixchannel_attention(unit);
- sc->flags |= IXF_INITED; /* we have been initialized */
- ifp->if_flags |= IFF_RUNNING;
- ifp->if_flags &= ~IFF_OACTIVE;
- ixinterrupt_enable(unit); /* Let err fly!!! */
- }
-
- DEBUGBEGIN(DEBUGINIT)
- DEBUGDO(printf("ixinit exited\n");)
- DEBUGEND
- return;
-}
-
-/*
- * ixinit_rfa(int unit)
- *
- * This routine initializes the Receive Frame Area for the 82586
- *
- * input the unit number to build the RFA for
- * access the softc for memory address
- * output an initialized RFA, ready for packet receiption
- * the following queue pointers in the softc structure are
- * also initialize
- * sc->rfd_head sc->rfd_tail
- * sc->rbd_head sc->rbd_tail
- * defines RFA_START the starting offset of the RFA
- * RFA_SIZE size of the RFA area
- * RB_SIZE size of the receive buffer, this must
- * be even and should be greater than the
- * minumum packet size and less than the
- * maximum packet size
- */
-
-void
-ixinit_rfa(int unit) {
- ix_softc_t *sc = &ix_softc[unit];
- rfd_t *rfd;
- rbd_t *rbd;
- caddr_t rb;
- int i,
- complete_frame_size,
- how_many_frames;
-
- DEBUGBEGIN(DEBUGINIT_RFA)
- DEBUGDO(printf("\nix%d: ixinit_rfa\n", unit);)
- DEBUGEND
-
- complete_frame_size = sizeof(rfd_t) + sizeof(rbd_t) + RB_SIZE;
- how_many_frames = RFA_SIZE / complete_frame_size;
-
- /* build the list of rfd's, rbd's and rb's */
- rfd = (rfd_t *)(sc->maddr + RFA_START);
- rbd = (rbd_t *)(sc->maddr +
- RFA_START +
- (how_many_frames * sizeof(rfd_t)));
- rb = sc->maddr + RFA_START +
- (how_many_frames * (sizeof(rfd_t) + sizeof(rbd_t)));
- sc->rfd_head = rfd;
- sc->rbd_head = rbd;
- for (i = 0; i < how_many_frames; i++, rfd++, rbd++, rb += RB_SIZE) {
- rfd->status = 0;
- rfd->command = 0;
- rfd->next = KVTOBOARD(rfd) + sizeof(rfd_t);
- rfd->rbd_offset = INTEL586NULL;
- /* ZZZ could bzero this, but just leave a note for now */
- /* ZZZ bzero(rfd->destination); */
- /* ZZZ bzero(rfd->source); */
- rfd->length = 0;
-
- rbd->act_count = 0;
- rbd->next = KVTOBOARD(rbd) + sizeof(rbd_t);
- rbd->buffer = KVTOBOARD(rb);
- rbd->size = RB_SIZE;
-
- /*
- * handle the boundary conditions here. for the zeroth
- * rfd we must set the rbd_offset to point at the zeroth
- * rbd. for the last rfd and rbd we need to close the
- * list into a ring and set the end of list bits.
- */
-
- if (i == 0) {
- rfd->rbd_offset = KVTOBOARD(rbd);
- }
- if (i == how_many_frames - 1) {
- rfd->command = RFD_CMD_EL | RFD_CMD_SUSP;
- rfd->next = KVTOBOARD(sc->rfd_head);
-
- rbd->next = KVTOBOARD(sc->rbd_head);
- rbd->size = RBD_SIZE_EL | RB_SIZE;
- }
-
- }
- sc->rfd_tail = (--rfd);
- sc->rbd_tail = (--rbd);
-
-#ifdef IXDEBUG
- DEBUGBEGIN(DEBUGINIT_RFA)
- rfd = (rfd_t *)(sc->maddr + RFA_START);
- rbd = (rbd_t *)(sc->maddr +
- RFA_START +
- (how_many_frames * sizeof(rfd_t)));
- rb = sc->maddr + RFA_START +
- (how_many_frames * (sizeof(rfd_t) + sizeof(rbd_t)));
- printf(" complete_frame_size = %d\n", complete_frame_size);
- printf(" how_many_frames = %d\n", how_many_frames);
- printf(" rfd_head = %lx\t\trfd_tail = %lx\n",
- kvtop(sc->rfd_head), kvtop(sc->rfd_tail));
- printf(" rbd_head = %lx\t\trbd_tail = %lx\n",
- kvtop(sc->rbd_head), kvtop(sc->rbd_tail));
- for (i = 0; i < how_many_frames; i++, rfd++, rbd++, rb += RB_SIZE) {
- printf(" %d:\trfd = %lx\t\trbd = %lx\t\trb = %lx\n",
- i, kvtop(rfd), kvtop(rbd), kvtop(rb));
- printf("\trfd->command = %x\n", rfd->command);
- printf("\trfd->next = %x\trfd->rbd_offset = %x\n",
- rfd->next, rfd->rbd_offset);
- printf("\trbd->next = %x\trbd->size = %x",
- rbd->next, rbd->size);
- printf("\trbd->buffer = %lx\n\n",
- rbd->buffer);
- }
- DEBUGEND
-#endif /* IXDEBUG */
-
- /*
- * ZZZ need to add sanity check to see if last rb runs into
- * the stuff after it in memory, this should not be possible
- * but if someone screws up with the defines it can happen
- */
- DEBUGBEGIN(DEBUGINIT_RFA)
- DEBUGDO(printf (" next rb would be at %lx\n", kvtop(rb));)
- DEBUGDO(printf("ix%d: ixinit_rfa exit\n", unit);)
- DEBUGEND
-}
-
-/*
- * ixinit_tfa(int unit)
- *
- * This routine initializes the Transmit Frame Area for the 82586
- *
- * input the unit number to build the TFA for
- * access the softc for memory address
- * output an initialized TFA, ready for packet transmission
- * the following queue pointers in the softc structure are
- * also initialize
- * sc->cb_head sc->cb_tail
- * sc->tbd_head sc->tbd_tail
- * defines TB_COUNT home many transmit buffers to create
- * TB_SIZE size of the tranmit buffer, this must
- * be even and should be greater than the
- * minumum packet size and less than the
- * maximum packet size
- * TFA_START the starting offset of the TFA
- */
-
-void
-ixinit_tfa(int unit) {
- ix_softc_t *sc = &ix_softc[unit];
- cb_transmit_t *cb;
- tbd_t *tbd;
- caddr_t tb;
- int i;
-
- DEBUGBEGIN(DEBUGINIT_TFA)
- DEBUGDO(printf("\nix%d: ixinit_tfa\n", unit);)
- DEBUGEND
-
- /* build the list of cb's, tbd's and tb's */
- cb = (cb_transmit_t *)(sc->maddr + TFA_START);
- tbd = (tbd_t *)(sc->maddr +
- TFA_START +
- (TB_COUNT * sizeof(cb_transmit_t)));
- tb = sc->maddr + TFA_START +
- (TB_COUNT * (sizeof(cb_transmit_t) + sizeof(tbd_t)));
- sc->cb_head = (cb_t *)cb;
- sc->tbd_head = tbd;
- for (i = 0; i < TB_COUNT; i++, cb++, tbd++, tb += TB_SIZE) {
- cb->common.status = 0;
- cb->common.command = CB_CMD_NOP;
- cb->common.next = KVTOBOARD(cb) + sizeof(cb_transmit_t);
- cb->tbd_offset = KVTOBOARD(tbd);
- /* ZZZ could bzero this, but just leave a note for now */
- /* ZZZ bzero(cb->destination); */
- cb->length = 0;
-
- tbd->act_count = 0;
- tbd->act_count = TBD_STAT_EOF;
- tbd->next = KVTOBOARD(tbd) + sizeof(tbd_t);
- tbd->buffer = KVTOBOARD(tb);
-
- /*
- * handle the boundary conditions here.
- */
-
- if (i == TB_COUNT - 1) {
- cb->common.command = CB_CMD_EL | CB_CMD_NOP;
- cb->common.next = INTEL586NULL; /*RRR KVTOBOARD(sc->cb_head);*/
- tbd->next = INTEL586NULL; /*RRR KVTOBOARD(sc->tbd_head);*/
- }
- }
- sc->cb_tail = (cb_t *)(--cb);
- sc->tbd_tail = (--tbd);
-
-#ifdef IXDEBUG
- DEBUGBEGIN(DEBUGINIT_TFA)
- cb = (cb_transmit_t *)(sc->maddr + TFA_START);
- tbd = (tbd_t *)(sc->maddr +
- TFA_START +
- (TB_COUNT * sizeof(cb_transmit_t)));
- tb = sc->maddr + TFA_START +
- (TB_COUNT * (sizeof(cb_transmit_t) + sizeof(tbd_t)));
- printf(" TB_COUNT = %d\n", TB_COUNT);
- printf(" cb_head = %lx\t\tcb_tail = %lx\n",
- kvtop(sc->cb_head), kvtop(sc->cb_tail));
- printf(" tbd_head = %lx\t\ttbd_tail = %lx\n",
- kvtop(sc->tbd_head), kvtop(sc->tbd_tail));
- for (i = 0; i < TB_COUNT; i++, cb++, tbd++, tb += TB_SIZE) {
- printf(" %d:\tcb = %lx\t\ttbd = %lx\t\ttb = %lx\n",
- i, kvtop(cb), kvtop(tbd), kvtop(tb));
- printf("\tcb->common.command = %x\n", cb->common.command);
- printf("\tcb->common.next = %x\tcb->tbd_offset = %x\n",
- cb->common.next, cb->tbd_offset);
- printf("\ttbd->act_count = %x", tbd->act_count);
- printf("\ttbd->next = %x", tbd->next);
- printf("\ttbd->buffer = %lx\n\n",
- tbd->buffer);
- }
- DEBUGEND
-#endif /* IXDEBUG */
-
- /*
- * ZZZ need to add sanity check to see if last tb runs into
- * the stuff after it in memory, this should not be possible
- * but if someone screws up with the defines it can happen
- */
- DEBUGBEGIN(DEBUGINIT_TFA)
- DEBUGDO(printf (" next tb would be at %lx\n", kvtop(tb));)
- DEBUGDO(printf("ix%d: ixinit_tfa exit\n", unit);)
- DEBUGEND
-}
-
-void
-ixintr(int unit) {
- ix_softc_t *sc = &ix_softc[unit];
- struct ifnet *ifp = &sc->arpcom.ac_if;
- scb_t *scb = (scb_t *)(sc->maddr + SCB_ADDR);
- int check_queue; /* flag to tell us to check the queue */
- u_short status;
-
- DEBUGBEGIN(DEBUGINTR)
- DEBUGDO(printf("ixintr: ");)
- DEBUGEND
-
- if ((sc->flags & IXF_INITED) == 0) {
- printf ("\n ixintr without being inited!!\n"); /* ZZZ */
- ixinterrupt_disable(unit);
- goto ixintr_exit;
- }
- if (ifp->if_flags & IFF_RUNNING == 0) {
- printf("\n ixintr when device not running!!\n"); /* ZZZ */
- ixinterrupt_disable(unit);
- goto ixintr_exit;
- }
-
- /* The sequence, disable ints, status=ack must be done
- * as quick as possible to avoid missing things */
- ixinterrupt_disable(unit);
- status = ixacknowledge(unit);
- check_queue = 0;
- while ((status & SCB_STAT_MASK) != 0) {
- if (status & SCB_STAT_FR) {
- ixintr_fr(unit);
- }
- if (status & SCB_STAT_CX) {
- ixintr_cx(unit);
- check_queue++;
- }
- if (status & SCB_STAT_CNA) {
- DEBUGBEGIN(DEBUGINTR)
- DEBUGDO(printf("cna:");)
- DEBUGEND
- }
- if ((status & SCB_STAT_RNR) ||
- ((status & SCB_RUS_MASK) == SCB_RUS_NRSC)) {
- DEBUGBEGIN(DEBUGINTR)
- printf("RNR:"); /* ZZZ this means trouble */
- DEBUGEND
- IXCOUNTER(ifp->if_rnr++;)
- ixinit_rfa(unit);
- scb->status = SCB_STAT_NULL;
- scb->command = SCB_RUC_START;
- scb->rfa_offset = RFA_START;
- ixchannel_attention(unit);
- }
- if (scb->status & SCB_STAT_MASK) {
- status = ixacknowledge(unit);
- } else {
- status = 0;
- }
- }
-
- ixinterrupt_enable(unit);
- if (check_queue && ifp->if_snd.ifq_head != 0) {
- ixstart(ifp); /* we have stuff on the queue */
- }
-
-ixintr_exit:
- DEBUGBEGIN(DEBUGINTR)
- DEBUGDO(printf(" ixintr exited\n");)
- DEBUGEND
-}
-
-static inline void
-ixintr_cx(int unit) {
- ix_softc_t *sc = &ix_softc[unit];
- struct ifnet *ifp = &sc->arpcom.ac_if;
- cb_t *cb;
-
- DEBUGBEGIN(DEBUGINTR_CX)
- DEBUGDO(printf("cx:");)
- DEBUGEND
- cb = sc->cb_head;
- do {
- if (cb->status & CB_BUSY) {
- IXCOUNTER(ifp->if_busy++;)
- printf("ix.cx.busy"); /* This should never occur */
- }
- if (cb->status & CB_COMPLETE) {
- IXCOUNTER(ifp->if_complete++;)
- switch(cb->command & CB_CMD_MASK) {
- case CB_CMD_NOP: { break; }
- case CB_CMD_IAS: { break; }
- case CB_CMD_CONF: { break; }
- case CB_CMD_MCAS: { break; }
- case CB_CMD_TRANSMIT: {
- if (cb->status & CB_OK) {
- ifp->if_opackets++;
- IXCOUNTER(ifp->if_ok++;)
- } else {
- if (cb->status & CB_ABORT) {
- IXCOUNTER(ifp->if_abort++;)
- printf("ix.cx.abort");
- }
- if (cb->status & CB_LATECOLL) {
- IXCOUNTER(ifp->if_latecoll++;)
- printf("ix.cx.latecoll");
- }
- if (cb->status & CB_NOCS) {
- IXCOUNTER(ifp->if_nocs++;)
- printf("ix.cx.nocs");
- }
- if (cb->status & CB_NOCTS) {
- IXCOUNTER(ifp->if_nocts++;)
- printf("ix.cx.nocts");
- }
- if (cb->status & CB_DMAUNDER) {
- IXCOUNTER(ifp->if_dmaunder++;)
- printf("ix.cx.dmaunder");
- }
- if (cb->status & CB_DEFER) {
- IXCOUNTER(ifp->if_defer++;)
- printf("ix.cx.defer");
- }
- if (cb->status & CB_HEARTBEAT) {
- IXCOUNTER(ifp->if_heartbeat++;)
- printf("ix.cx.heartbeat");
- }
- if (cb->status & CB_EXCESSCOLL) {
- IXCOUNTER(ifp->if_excesscoll++;)
- printf("ix.cx.excesscoll");
- }
- ifp->if_oerrors++;
- }
- ifp->if_collisions += cb->status & CB_COLLISIONS;
- ifp->if_timer = 0; /* clear watchdog timeout */
- break;
- }
- case CB_CMD_TDR: { break; }
- case CB_CMD_DUMP: { break; }
- case CB_CMD_DIAGNOSE: { break; }
- default: { break; }
- }
- ixintr_cx_free(unit, cb);
- } else {
- }
- if (cb->next == INTEL586NULL) {
- break;
- } else {
- cb = (cb_t *)BOARDTOKV(cb->next);
- }
- }
- while (1);
- /*
- * clear the IFF_OACTIVE flag because the CU should now be
- * idle, this only holds true as long as the last CB is the
- * only one with the CB_CMD_INT bit set. If the start routine
- * violates this rule this code well have to change.
- */
- ifp->if_flags &= ~IFF_OACTIVE;
- }
-
-static inline void
-ixintr_cx_free(int unit, cb_t *cb) {
-
- DEBUGBEGIN(DEBUGINTR_CX)
- DEBUGDO(ix_softc_t *sc = &ix_softc[unit];)
- DEBUGDO(printf("cb=%x:cb->status=%x:", KVTOBOARD(cb), cb->status);)
- DEBUGEND
-/*1*/ cb->command = CB_CMD_EL | CB_CMD_NOP;
-/*2*/ cb->status = 0;
-}
-
-static inline void
-ixintr_fr(int unit) {
- ix_softc_t *sc = &ix_softc[unit];
-
- DEBUGBEGIN(DEBUGINTR_FR)
- DEBUGDO(printf("fr:");)
- DEBUGEND
- /* find each frame in the rfa and copy it up, then free it */
- while ((sc->rfd_head->status & (RFD_COMPLETE | RFD_BUSY)) == RFD_COMPLETE) {
- ixintr_fr_copy(unit, sc->rfd_head);
- ixintr_fr_free(unit, sc->rfd_head);
- }
-}
-
-static inline void
-ixintr_fr_copy(int unit, rfd_t *rfd) {
- ix_softc_t *sc = &ix_softc[unit];
- struct ifnet *ifp = &sc->arpcom.ac_if;
- rbd_t *rbd;
- caddr_t rb;
- struct mbuf *m0, *m;
- struct ether_header *eh;
- int length,
- bytesleft;
-
- rbd = (rbd_t *)(sc->maddr + rfd->rbd_offset);
- rb = (caddr_t)(sc->maddr + rbd->buffer);
- DEBUGBEGIN(DEBUGINTR_FR)
- DEBUGDO(int i;)
- DEBUGDO(printf("rfd=%x:", KVTOBOARD(rfd));)
- DEBUGDO(printf("rfd->status=%x:", rfd->status);)
- DEBUGDO(printf("rbd->act_count=%x:", rbd->act_count);)
- DEBUGDO(printf("data=");)
- DEBUGDO(for (i = 0; i < 16; i ++) printf ("%02x", rb[i] & 0xFF);)
- DEBUGDO(printf(":");)
- DEBUGEND
- /* trickery here, eh points right at memory on
- * the board. eh is only used by ether_input,
- * it is not passed to the upper layer */
- eh = (struct ether_header *)rb;
-
- /* here we go, lets build an mbuf chain up to hold all this */
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == 0) {
- printf ("MGETHDR:"); /* ZZZ need to add drop counters */
- return;
- }
- m0 = m;
- length = rbd->act_count & RBD_STAT_SIZE;
- bytesleft = length - sizeof(struct ether_header);
- rb += sizeof(struct ether_header);
- m->m_pkthdr.rcvif = ifp;
- m->m_pkthdr.len = bytesleft;
- m->m_len = MHLEN;
- while (bytesleft > 0) {
- if (bytesleft > MINCLSIZE) {
- MCLGET(m, M_DONTWAIT);
- if (m->m_flags & M_EXT) {
- m->m_len = MCLBYTES;
- } else {
- printf ("MCLGET:");
- m_freem(m0); /* ZZZ need to add drop counters */
- return;
- }
- }
- m->m_len = min(m->m_len, bytesleft);
- bcopy(rb, mtod(m, caddr_t), m->m_len);
- rb += m->m_len;
- bytesleft -= m->m_len;
- if (bytesleft > 0) {
- MGET(m->m_next, M_DONTWAIT, MT_DATA);
- if (m->m_next == 0) {
- printf ("MGET");
- m_freem(m0); /* ZZZ need to add drop counters */
- return;
- }
- m = m->m_next;
- m->m_len = MLEN;
- }
- }
-
- ether_input(ifp, eh, m0);
- ifp->if_ipackets++;
- return;
-}
-
-static inline void
-ixintr_fr_free(int unit, rfd_t *rfd) {
- ix_softc_t *sc = &ix_softc[unit];
- rbd_t *rbd;
-
- rbd = (rbd_t *)(sc->maddr + rfd->rbd_offset);
-
- /* XXX this still needs work, does not handle chained rbd's */
-/*1*/ rbd->act_count = 0;
-/*2*/ rbd->size = RBD_SIZE_EL | RB_SIZE;
-/*3*/ sc->rbd_tail->size = RB_SIZE;
-/*4*/ sc->rbd_tail = rbd;
-
- /* Free the rfd buy putting it back on the rfd queue */
-/*1*/ rfd->command = RFD_CMD_EL | RFD_CMD_SUSP;
-/*2*/ rfd->status = 0;
-/*3*/ rfd->rbd_offset = INTEL586NULL;
-/*4*/ sc->rfd_head = (rfd_t *)BOARDTOKV(rfd->next);
-/*5*/ sc->rfd_tail->command &= ~(RFD_CMD_EL | RFD_CMD_SUSP);
-/*6*/ sc->rfd_tail = rfd;
-}
-
-/* Psuedo code:
- * Do consistency check:
- * IFF_UP should be set.
- * IFF_RUNNING should be set.
- * IFF_OACTIVE should be clear.
- * ifp->snd.ifq_head should point to an MBUF
- * I82586 CU should be in the idle state.
- * All cb's should have CUC = NOP.
- * The real work:
- * while there are packets to send & free cb's do:
- * build a cb, tbd, and tb
- * copy the MBUF chain to a tb
- * setup the scb for a start CU
- * start the CU
- * set IFF_OACTIVE
- * set ifp->if_timer for watchdog timeout
- * Exit:
- */
-void
-ixstart(struct ifnet *ifp) {
- int unit = ifp->if_unit;
- ix_softc_t *sc = ifp->if_softc;
- scb_t *scb = (scb_t *)BOARDTOKV(SCB_ADDR);
- cb_t *cb = sc->cb_head;
- tbd_t *tbd;
- caddr_t tb;
- struct mbuf *m, *m_temp;
- u_short length;
- IXCOUNTER(int queued;)
-
- DEBUGBEGIN(DEBUGSTART)
- DEBUGDO(printf("ixstart:");)
- DEBUGEND
-
- /* check that if is up and running */
- if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING)) {
- goto ixstart_exit;
- }
-
- /* check to see that we are not already active */
- if ((ifp->if_flags & IFF_OACTIVE) == IFF_OACTIVE) {
- goto ixstart_exit;
- }
-
- /* check that there are packets to send */
- if (ifp->if_snd.ifq_head == 0) {
- goto ixstart_exit;
- }
-
- /* check that the command unit is idle */
- if ((scb->status & SCB_CUS_MASK) != SCB_CUS_IDLE) {
- goto ixstart_exit;
- }
-
- /* check that all cb's on the list are free */
-#ifdef THISDONTDONOTHING
- cb = sc->cb_head;
- IXCOUNTER(ifp->if_could_queue = 0;)
- do {
- /* XXX this does nothing right now! */
- DEBUGBEGIN(DEBUGSTART)
- DEBUGDO(printf("chk_cb=%x:", KVTOBOARD(cb));)
- DEBUGEND
- IXCOUNTER(ifp->if_could_queue++;)
- if (cb->next == INTEL586NULL) {
- break;
- } else {
- cb = (cb_t *)BOARDTOKV(cb->next);
- }
- }
- while (1);
-#endif /* THISDONTDONOTHING */
-
- /* build as many cb's as we can */
- IXCOUNTER(queued = 0;)
- cb = sc->cb_head;
- do {
- cb->status = 0;
- cb->command = CB_CMD_TRANSMIT;
- tbd = (tbd_t *)BOARDTOKV(((cb_transmit_t *)cb)->tbd_offset);
- tb = (caddr_t)BOARDTOKV(tbd->buffer);
- DEBUGBEGIN(DEBUGSTART)
- DEBUGDO(printf("cb=%x:", KVTOBOARD(cb));)
- DEBUGDO(printf("tbd=%x:", KVTOBOARD(tbd));)
- DEBUGDO(printf("tb=%x:", KVTOBOARD(tb));)
- DEBUGEND
-
- IF_DEQUEUE(&ifp->if_snd, m);
- length = 0;
- for (m_temp = m; m_temp != 0; m_temp = m_temp->m_next) {
- bcopy(mtod(m_temp, caddr_t), tb, m_temp->m_len);
- tb += m_temp->m_len;
- length += m_temp->m_len;
- }
- m_freem(m);
- if (length < ETHER_MIN_LEN) length = ETHER_MIN_LEN;
-#ifdef DIAGNOSTIC
- if (length > ETHER_MAX_LEN) {
- /* XXX
- * This should never ever happen, if it does
- * we probable screwed up all sorts of board data
- * in the above bcopy's and should probably shut
- * down, but for now just issue a warning that
- * something is real wrong
- */
- printf("ix%d: ixstart: Packet length=%d > MTU=%d\n",
- unit, length, ETHER_MAX_LEN);
- }
-#endif /* DIAGNOSTIC */
- tbd->act_count = TBD_STAT_EOF | length;
- IXCOUNTER(queued++;)
- /* check to see if we have used the last cb */
- if (cb->next == INTEL586NULL) {
- IXCOUNTER(ifp->if_filled_queue++;)
- break;
- } else {
- cb = (cb_t *)BOARDTOKV(cb->next);
- }
- } while (ifp->if_snd.ifq_head != 0);
- IXCOUNTER(ifp->if_high_queue = max(ifp->if_high_queue, queued);)
-
- /* set the end of list and interrupt bits in the last cb */
- cb->command |= (CB_CMD_EL | CB_CMD_INT);
-
- /* build the scb */
- scb->status = SCB_STAT_NULL;
- scb->command = SCB_CUC_START;
- scb->cbl_offset = KVTOBOARD(sc->cb_head);/* This should not be needed */
-
- /* start the cu */
- ixchannel_attention(unit);
-
- /* mark the interface as having output active */
- ifp->if_flags |= IFF_OACTIVE;
-
- /*
- * set the watchdog timer so that if the board fails to interrupt
- * we will go clean up
- */
- ifp->if_timer = 2;
-
-ixstart_exit:
- DEBUGBEGIN(DEBUGSTART)
- DEBUGDO(printf("ixstart exited\n");)
- DEBUGEND
- return;
-}
-
-int
-ixstop(struct ifnet *ifp) {
- int unit = ifp->if_unit;
- ix_softc_t *sc = ifp->if_softc;
-
- DEBUGBEGIN(DEBUGSTOP)
- DEBUGDO(printf("ixstop:");)
- DEBUGEND
-
- /* XXX Need to find out what spl we are at, and maybe add splx */
-
- ifp->if_flags &= ~IFF_RUNNING;
- ixinterrupt_disable(unit);
-
- /* force the 82586 reset pin high */
- outb(sc->iobase + ee_ctrl, I586_RESET);
-
- DEBUGBEGIN(DEBUGSTOP)
- DEBUGDO(printf("ixstop exiting\n");)
- DEBUGEND
- return(0);
-}
-
-/*
- * I can't find any calls to if_done, it may be deprecated, but I left
- * it here until I find out. rwgrimes 1993/01/15
- */
-int
-ixdone(struct ifnet *ifp) {
- DEBUGBEGIN(DEBUGDONE)
- DEBUGDO(printf("ixdone:");)
- DEBUGEND
- DEBUGBEGIN(DEBUGDONE)
- DEBUGDO(printf("ixdone exited\n");)
- DEBUGEND
- return(0);
-}
-
-int
-ixioctl(struct ifnet *ifp, int cmd, caddr_t data) {
- int unit = ifp->if_unit;
- int status = 0;
- int s;
-
- DEBUGBEGIN(DEBUGIOCTL)
- DEBUGDO(printf("ixioctl:");)
- DEBUGEND
-
- s = splimp();
-
- switch(cmd) {
- case SIOCSIFADDR: {
- struct ifaddr *ifa = (struct ifaddr *)data;
-
- if (ifp->if_flags & IFF_RUNNING) ixstop(ifp);
- ifp->if_flags |= IFF_UP;
- ixinit(unit);
-
- switch(ifa->ifa_addr->sa_family) {
-#ifdef INET
- case AF_INET: {
- arp_ifinit((struct arpcom *)ifp, ifa);
- break;
- }
-#endif /* INET */
-#ifdef IPX
- case AF_IPX: {
- /*ZZZ*/printf("Address family IPX not supported by ixioctl\n");
- break;
- }
-#endif /* IPX */
-#ifdef NS
- case AF_NS: {
- /*ZZZ*/printf("Address family NS not supported by ixioctl\n");
- break;
- }
-#endif /* NS */
- default: {
- DEBUGBEGIN(DEBUGIOCTL)
- DEBUGDO(printf("Unknow Address Family in ixioctl\n");)
- DEBUGEND
- status = EINVAL;
- break;
- }
- }
- break;
- }
-
- case SIOCSIFFLAGS: {
- if (((ifp->if_flags & IFF_UP) == 0) &&
- (ifp->if_flags & IFF_RUNNING)) {
- ixstop(ifp);
- }
- else if ((ifp->if_flags & IFF_UP) &&
- ((ifp->if_flags & IFF_RUNNING) == 0)) {
- ixinit(unit);
- }
- break;
- }
-
- default: {
- DEBUGBEGIN(DEBUGIOCTL)
- DEBUGDO(printf("Unknown cmd in ixioctl\n");)
- DEBUGEND
- status = EINVAL;
- break;
- }
- }
- splx(s);
-
- DEBUGBEGIN(DEBUGIOCTL)
- DEBUGDO(printf("ixioctl exit\n");)
- DEBUGEND
- return(status);
-}
-
-void
-ixreset(int unit) {
- ix_softc_t *sc = &ix_softc[unit];
- struct ifnet *ifp = &sc->arpcom.ac_if;
- int s;
-
- s = splimp();
- DEBUGBEGIN(DEBUGRESET)
- DEBUGDO(printf("ixreset:");)
- DEBUGEND
-
- ixstop(ifp);
- ixinit(unit);
-
- DEBUGBEGIN(DEBUGRESET)
- DEBUGDO(printf("ixreset exit\n");)
- DEBUGEND
- (void) splx(s);
- return;
-}
-/*
- * The ixwatchdog routine gets called if the transmitter failed to interrupt
- * within ifp->if_timer XXXseconds. The interrupt service routine must reset
- * ifp->if_timer to 0 after an transmitter interrupt occurs to stop the
- * watchdog from happening.
- */
-void
-ixwatchdog(struct ifnet *ifp) {
- log(LOG_ERR, "ix%d: device timeout\n", ifp->if_unit);
- ifp->if_oerrors++;
- ixreset(ifp->if_unit);
- return;
-}
-
-u_short
-ixeeprom_read(int unit, int location) {
- int eeprom_control,
- data;
-
- eeprom_control = inb(ix_softc[unit].iobase + ee_ctrl);
- eeprom_control &= 0xB2; /* XXX fix 0xB2 */
- eeprom_control |= EECS;
- outb(ix_softc[unit].iobase + ee_ctrl, eeprom_control);
- ixeeprom_outbits(unit, eeprom_read_op, eeprom_opsize1);
- ixeeprom_outbits(unit, location, eeprom_addr_size);
- data = ixeeprom_inbits(unit);
- eeprom_control = inb(ix_softc[unit].iobase + ee_ctrl);
- eeprom_control &= ~(GA_RESET | EEDI | EECS);
- outb(ix_softc[unit].iobase + ee_ctrl, eeprom_control);
- ixeeprom_clock(unit, 1);
- ixeeprom_clock(unit, 0);
- return(data);
-}
-
-void
-ixeeprom_outbits(int unit, int data, int count) {
- int eeprom_control,
- i;
-
- eeprom_control = inb(ix_softc[unit].iobase + ee_ctrl);
- eeprom_control &= ~GA_RESET;
- for(i=count-1; i>=0; i--) {
- eeprom_control &= ~EEDI;
- if (data & (1 << i)) {
- eeprom_control |= EEDI;
- }
- outb(ix_softc[unit].iobase + ee_ctrl, eeprom_control);
- DELAY(1); /* eeprom data must be setup for 0.4 uSec */
- ixeeprom_clock(unit, 1);
- ixeeprom_clock(unit, 0);
- }
- eeprom_control &= ~EEDI;
- outb(ix_softc[unit].iobase + ee_ctrl, eeprom_control);
- DELAY(1); /* eeprom data must be held for 0.4 uSec */
-}
-
-int
-ixeeprom_inbits(int unit) {
- int eeprom_control,
- data,
- i;
-
- eeprom_control = inb(ix_softc[unit].iobase + ee_ctrl);
- eeprom_control &= ~GA_RESET;
- for(data=0, i=0; i<16; i++) {
- data = data << 1;
- ixeeprom_clock(unit, 1);
- eeprom_control = inb(ix_softc[unit].iobase + ee_ctrl);
- if (eeprom_control & EEDO) {
- data |= 1;
- }
- ixeeprom_clock(unit, 0);
- }
- return(data);
-}
-
-void
-ixeeprom_clock(int unit, int state) {
- int eeprom_control;
-
- eeprom_control = inb(ix_softc[unit].iobase + ee_ctrl);
- eeprom_control &= ~(GA_RESET | EESK);
- if (state) {
- eeprom_control = eeprom_control | EESK;
- }
- outb(ix_softc[unit].iobase + ee_ctrl, eeprom_control);
- DELAY(9); /* EESK must be stable for 8.38 uSec */
-}
diff --git a/sys/i386/isa/if_ixreg.h b/sys/i386/isa/if_ixreg.h
deleted file mode 100644
index 8b22c73..0000000
--- a/sys/i386/isa/if_ixreg.h
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- * Copyright (c) 1993, 1994, 1995
- * Rodney W. Grimes, Milwaukie, Oregon 97222. 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 as
- * the first lines of this file unmodified.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Rodney W. Grimes.
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY RODNEY W. GRIMES ``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 RODNEY W. GRIMES 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.
- *
- * $Id$
- */
-
-/*
- * These really belong some place else, but I can't find them right
- * now. I'll look again latter
- */
-
-#define IX_IO_PORTS 16 /* Number of I/O ports used, note
- * this is not true, due to shadow
- * ports at 400X,800X and C00X
- */
-
-#define dxreg 0x00 /* Data transfer register Word R/W */
-#define wrptr 0x02 /* Write address pointer Word R/W */
-#define rdptr 0x04 /* Read address pointer Word R/W */
-#define ca_ctrl 0x06 /* Channel attention control Byte R/W */
-#define sel_irq 0x07 /* IRQ select Byte R/W */
-#define IRQ_ENABLE 0x08 /* Enable board interrupts */
-#define smb_ptr 0x08 /* Shadow memory bank pointer Word R/W */
-#define memdec 0x0A /* Memory address decode Byte W */
-#define memctrl 0x0B /* Memory mapped control Byte R/W */
-#define MEMCTRL_UNUSED 0x83 /* Unused bits */
-#define MEMCTRL_MEMMEG 0x60 /* Which megabyte of memory, 0, E or F */
-#define MEMCTRL_FMCS16 0x10 /* MEMCS16- for F000 */
-#define MEMCTRL_MEMADJ 0xC0 /* memory adjust value */
-#define mempc 0x0C /* MEMCS16- page control Byte R/W */
-#define config 0x0D /* Configuration, test Byte R/W */
-#define BART_LINK 0x01 /* link integrity active, TPE */
-#define BART_LOOPBACK 0x02 /* Loopback, 0=none, 1=loopback */
-#define SLOT_WIDTH 0x04 /* 0 = 8bit, 1 = 16bit */
-#define BART_USEWIDTH 0x08 /* use SLOT_WIDTH for bus size */
-#define BART_IOCHRDY_LATE 0x10 /* iochrdy late control bit */
-#define BART_IO_TEST_EN 0x20 /* enable iochrdy timing test */
-#define BART_IO_RESULT 0x40 /* result of the iochrdy test */
-#define BART_MCS16_TEST 0x80 /* enable memcs16 select test */
-#define ee_ctrl 0x0E /* EEPROM control, reset Byte R/W */
-#define EENORMAL 0x00 /* normal state of ee_ctrl */
-#define EESK 0x01 /* EEPROM clock bit */
-#define EECS 0x02 /* EEPROM chip select */
-#define EEDI 0x04 /* EEPROM data in bit (write EEPROM) */
-#define EEDO 0x08 /* EEPROM data out bit (read EEPROM) */
-#define EEUNUSED 0x30 /* unused bits in ee_ctrl */
-#define GA_RESET 0x40 /* BART ASIC chip reset pin */
-#define I586_RESET 0x80 /* 82586 chip reset pin */
-#define memectrl 0x0F /* Memory control, E000h seg Byte W */
-#define autoid 0x0F /* Auto ID register Byte R */
-
-#define BOARDID 0xBABA /* Intel PCED board ID for EtherExpress */
-
-#define eeprom_opsize1 0x03 /* Size of opcodes for r/w/e */
-#define eeprom_read_op 0x06 /* EEPROM read op code */
-#define eeprom_write_op 0x05 /* EEPROM write op code */
-#define eeprom_erase_op 0x07 /* EEPROM erase op code */
-#define eeprom_opsize2 0x05 /* Size of opcodes for we/wdr */
-#define eeprom_wenable_op 0x13 /* EEPROM write enable op code */
-#define eeprom_wdisable_op 0x10 /* EEPROM write disable op code */
-
-#define eeprom_addr_size 0x06 /* Size of EEPROM address */
-
-/* These are the locations in the EEPROM */
-#define eeprom_config1 0x00 /* Configuration register 1 */
-#define CONNECT_BNCTPE 0x1000 /* 0 = AUI, 1 = BNC/TPE */
-#define IRQ 0xE000 /* Encoded IRQ */
-#define IRQ_SHIFT 13 /* To shift IRQ to lower bits */
-#define eeprom_lock_address 0x01 /* contains the lock bit */
-#define EEPROM_LOCKED 0x01 /* means that it is locked */
-#define eeprom_enetaddr_low 0x02 /* Ethernet address, low word */
-#define eeprom_enetaddr_mid 0x03 /* Ethernet address, middle word */
-#define eeprom_enetaddr_high 0x04 /* Ethernet address, high word */
-#define eeprom_config2 0x05 /* Configuration register 2 */
-#define CONNECT_TPE 0x0001 /* 0 = BNC, 1 = TPE */
-
-/* this converts a kernal virtual address to a board offset */
-#define KVTOBOARD(addr) ((int)addr - (int)sc->maddr)
-#define BOARDTOKV(addr) ((int)addr + (int)sc->maddr)
-
-/* XXX This belongs is ic/i825x6.h, but is here for editing for now */
-
-#define INTEL586NULL 0xFFFF /* NULL pointer for 82586 */
-#define INTEL596NULL 0xFFFFFFFF /* NULL pointer for 82596 */
-
-/*
- * Layout of memory for the 825x6 chip:
- * Low: Control Blocks
- * Transmit Frame Descriptor(s)
- * Transmit Frame Buffer(s)
- * Receive Frame Descriptors
- * Receive Frames
- * SCB_ADDR System Control Block
- * ISCP_ADDR Intermediate System Configuration Pointer
- * High: SCP_ADDR System Configuration Pointer
- */
-#define SCP_ADDR (sc->msize - sizeof(scp_t))
-#define ISCP_ADDR (SCP_ADDR - sizeof(iscp_t))
-#define SCB_ADDR (ISCP_ADDR - sizeof(scb_t))
-
-#define TB_COUNT 3 /* How many transfer buffers in the TFA */
-#define TB_SIZE (ETHER_MAX_LEN) /* size of transmit buffer */
-#define TFA_START 0x0000 /* Start of the TFA */
-#define TFA_SIZE (TB_COUNT * \
- (sizeof(cb_transmit_t) + sizeof(tbd_t) + TB_SIZE))
-
-#define RFA_START (TFA_SIZE)
-#define RFA_SIZE (SCP_ADDR - RFA_START)
-#define RB_SIZE (ETHER_MAX_LEN) /* size of receive buffer */
-
-typedef struct /* System Configuration Pointer */
- {
- u_short unused1; /* should be zeros for 82596 compatibility */
- u_short sysbus; /* width of the 82586 data bus 0=16, 1=8 */
- u_short unused2; /* should be zeros for 82596 compatibility */
- u_short unused3; /* should be zeros for 82596 compatibility */
- u_long iscp; /* iscp address (24bit 586, 32bit 596) */
- } scp_t;
-
-typedef struct /* Intermediate System Configuration Pointer */
- {
- volatile
- u_short busy; /* Set to 1 by host before its first CA,
- cleared by 82586 after reading */
-#define ISCP_BUSY 0x01 /* 82586 is busy reading the iscp */
- u_short scb_offset; /* Address of System Control Block */
- u_long scb_base; /* scb base address (24bit 586, 32bit 596) */
- } iscp_t;
-
-typedef struct /* System Control Block */
- {
- volatile
- u_short status; /* status bits */
-#define SCB_RUS_MASK 0x0070 /* receive unit status mask */
-#define SCB_RUS_IDLE 0x0000 /* receive unit status idle */
-#define SCB_RUS_SUSP 0x0010 /* receive unit status suspended */
-#define SCB_RUS_NRSC 0x0020 /* receive unit status no resources */
-#define SCB_RUS_READY 0x0040 /* receive unit status ready */
-#define SCB_CUS_MASK 0x0700 /* command unit status mask */
-#define SCB_CUS_IDLE 0x0000 /* command unit status idle */
-#define SCB_CUS_SUSP 0x0100 /* command unit status suspended */
-#define SCB_CUS_ACT 0x0200 /* command unit status active */
-#define SCB_STAT_MASK 0xF000 /* command unit status mask */
-#define SCB_STAT_RNR 0x1000 /* receive unit left the ready state */
-#define SCB_STAT_CNA 0x2000 /* command unit left the active state */
-#define SCB_STAT_FR 0x4000 /* the ru finished receiving a frame */
-#define SCB_STAT_CX 0x8000 /* the cu finished executing a command
- with its I (interrupt) bit set */
-#define SCB_STAT_NULL 0x0000 /* used to clear the status work */
- u_short command; /* command bits */
-#define SCB_RUC_MASK 0x0070 /* receive unit command mask */
-#define SCB_RUC_NOP 0x0000 /* receive unit command nop */
-#define SCB_RUC_START 0x0010 /* receive unit command start */
-#define SCB_RUC_RESUME 0x0020 /* receive unit command resume */
-#define SCB_RUC_SUSP 0x0030 /* receive unit command suspend */
-#define SCB_RUC_ABORT 0x0040 /* receive unit command abort */
-#define SCB_RESET 0x0080 /* reset the chip, same as hardware reset */
-#define SCB_CUC_MASK 0x0700 /* command unit command mask */
-#define SCB_CUC_NOP 0x0000 /* command unit command nop */
-#define SCB_CUC_START 0x0100 /* start execution of the first command */
-#define SCB_CUC_RESUME 0x0200 /* resume execution of the next command */
-#define SCB_CUC_SUSP 0x0300 /* suspend execution after the current command */
-#define SCB_CUC_ABORT 0x0400 /* abort execution of the current command */
-#define SCB_ACK_MASK 0xF000 /* command unit acknowledge mask */
-#define SCB_ACK_RNR 0x1000 /* ack receive unit left the ready state */
-#define SCB_ACK_CNA 0x2000 /* ack command unit left the active state */
-#define SCB_ACK_FR 0x4000 /* ack the ru finished receiving a frame */
-#define SCB_ACK_CX 0x8000 /* ack the cu finished executing a command
- with its I (interrupt) bit set */
- u_short cbl_offset; /* first command block on the cbl */
- u_short rfa_offset; /* receive frame area */
- volatile
- u_short crc_errors; /* frame was aligned, but bad crc */
- volatile
- u_short aln_errors; /* frame was not aligned, and had bad crc */
- volatile
- u_short rsc_errors; /* did not have resources to receive */
- volatile
- u_short ovr_errors; /* system bus was not available to receive */
- } scb_t;
-
-typedef struct /* command block - nop (also the common part of cb's */
- {
- volatile
- u_short status; /* status bits */
-#define CB_COLLISIONS 0x000F /* the number of collisions that occured */
-#define CB_BIT4 0x0010 /* reserved by intel */
-#define CB_EXCESSCOLL 0x0020 /* the number of collisions > MAX allowed */
-#define CB_HEARTBEAT 0x0040 /* */
-#define CB_DEFER 0x0080 /* had to defer due to trafic */
-#define CB_DMAUNDER 0x0100 /* dma underrun */
-#define CB_NOCTS 0x0200 /* lost clear to send */
-#define CB_NOCS 0x0400 /* lost carrier sense */
-#define CB_LATECOLL 0x0800 /* late collision occured (82596 only) */
-#define CB_ABORT 0x1000 /* command was aborted by CUC abort command */
-#define CB_OK 0x2000 /* command executed without error */
-#define CB_BUSY 0x4000 /* command is being executed */
-#define CB_COMPLETE 0x8000 /* command completed */
- u_short command; /* command bits */
-#define CB_CMD_MASK 0x0007 /* command mask */
-#define CB_CMD_NOP 0x0000 /* nop command */
-#define CB_CMD_IAS 0x0001 /* individual address setup command */
-#define CB_CMD_CONF 0x0002 /* configure command */
-#define CB_CMD_MCAS 0x0003 /* multicast address setup command */
-#define CB_CMD_TRANSMIT 0x0004 /* transmit command */
-#define CB_CMD_TDR 0x0005 /* time domain reflectometry command */
-#define CB_CMD_DUMP 0x0006 /* dump command */
-#define CB_CMD_DIAGNOSE 0x0007 /* diagnose command */
-#define CB_CMD_INT 0x2000 /* interrupt when command completed */
-#define CB_CMD_SUSP 0x4000 /* suspend CU when command completed */
-#define CB_CMD_EL 0x8000 /* end of the command block list */
- u_short next; /* pointer to the next cb */
- } cb_t;
-
-typedef struct /* command block - individual address setup command */
- {
- cb_t common; /* common part of all command blocks */
- u_char source[ETHER_ADDR_LEN];
- /* ethernet hardware address */
- } cb_ias_t;
-
-typedef struct /* command block - configure command */
- {
- cb_t common; /* common part of all command blocks */
- u_char byte[12]; /* ZZZ this is ugly, but it works */
- } cb_configure_t;
-
-typedef struct /* command block - multicast address setup command */
- {
- cb_t common; /* common part of all command blocks */
- } cb_mcas_t;
-
-typedef struct /* command block - transmit command */
- {
- cb_t common; /* common part of all command blocks */
- u_short tbd_offset; /* transmit buffer descriptor offset */
- u_char destination[ETHER_ADDR_LEN];
- /* ethernet destination address field */
- u_short length; /* ethernet length field */
- u_char byte[16]; /* XXX stupid fill tell I fix the ixinit
- * code for the special cb's */
- } cb_transmit_t;
-
-typedef struct /* command block - tdr command */
- {
- cb_t common; /* common part of all command blocks */
- } cb_tdr_t;
-
-typedef struct /* command block - dump command */
- {
- cb_t common; /* common part of all command blocks */
- } cb_dump_t;
-
-typedef struct /* command block - diagnose command */
- {
- cb_t common; /* common part of all command blocks */
- } cb_diagnose_t;
-
-typedef struct /* Transmit Buffer Descriptor */
- {
- volatile
- u_short act_count; /* size of buffer actual count of valid bytes */
-#define TBD_STAT_EOF 0x8000 /* end of frame */
- u_short next; /* pointer to the next tbd */
- u_long buffer; /* transmit buffer address (24bit 586, 32bit 596) */
- } tbd_t;
-
-typedef struct /* Receive Frame Descriptor */
- {
- volatile
- u_short status; /* status bits */
-#define RFD_BUSY 0x4000 /* frame is being received */
-#define RFD_COMPLETE 0x8000 /* this frame is complete */
- u_short command; /* command bits */
-#define RFD_CMD_SUSP 0x4000 /* suspend the ru after this rfd is used */
-#define RFD_CMD_EL 0x8000 /* end of the rfd list */
- u_short next; /* pointer to the next rfd */
- u_short rbd_offset; /* pointer to the first rbd for this frame */
- u_char destination[6]; /* ethernet destination address */
- u_char source[6]; /* ethernet source address */
- u_short length; /* ethernet length field */
- } rfd_t;
-
-typedef struct /* Receive Buffer Descriptor */
- {
- volatile
- u_short act_count; /* Actual Count (size) and status bits */
-#define RBD_STAT_SIZE 0x3FFF /* size mask */
-#define RBD_STAT_VALID 0x4000 /* act_count field is valid */
-#define RBD_STAT_EOF 0x8000 /* end of frame */
- u_short next; /* pointer to the next rbd */
- u_long buffer; /* receive buffer address */
- u_short size; /* size of buffer in bytes, must be even */
-#define RBD_SIZE_EL 0x8000 /* end of rbd list */
- } rbd_t;
-
-/*
- * Ethernet software status per interface.
- *
- * Each interface is referenced by a network interface structure,
- * arpcom.ac_if, which the routing code uses to locate the interface.
- * This structure contains the output queue for the interface, its address, ...
- */
-typedef struct
- {
- struct arpcom arpcom; /* Ethernet common part see net/if.h */
- int iobase; /* I/O base address for this interface */
- caddr_t maddr; /* Memory base address for this interface */
- int msize; /* Size of memory */
- int flags; /* Software state */
-#define IXF_NONE 0x00000000 /* Clear all flags */
-#define IXF_INITED 0x00000001 /* Device has been inited */
-#define IXF_BPFATTACHED 0x80000000 /* BPF has been attached */
- int connector; /* Type of connector used on board */
-#define AUI 0x00 /* Using AUI connector */
-#define BNC 0x01 /* Using BNC connector */
-#define TPE 0x02 /* Using TPE connector */
- u_short irq_encoded; /* Encoded interrupt for use on bart */
- int width; /* Width of slot the board is in, these
- * constants are defined to match what
- * the 82586/596 wants in scp->sysbus */
-#define WIDTH_8 0x01 /* 8-bit slot */
-#define WIDTH_16 0x00 /* 16-bit slot */
- cb_t *cb_head; /* head of cb list */
- cb_t *cb_tail; /* tail of cb list */
- tbd_t *tbd_head; /* head of the tbd list */
- tbd_t *tbd_tail; /* tail of the tbd list */
- rfd_t *rfd_head; /* head of the rfd list */
- rfd_t *rfd_tail; /* tail of the rfd list */
- rbd_t *rbd_head; /* head of the rbd list */
- rbd_t *rbd_tail; /* tail of the rbd list */
- } ix_softc_t;
OpenPOWER on IntegriCloud