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
This commit is contained in:
parent
c1aa7eb5f4
commit
5a2037874f
@ -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 @@ void ieintr(unit)
|
||||
&& (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 @@ static inline int ieget(unit, ie, mp, ehp, to_bpf)
|
||||
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;
|
||||
}
|
||||
|
@ -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 @@ void ieintr(unit)
|
||||
&& (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 @@ static inline int ieget(unit, ie, mp, ehp, to_bpf)
|
||||
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;
|
||||
}
|
||||
|
1634
sys/i386/isa/if_ix.c
1634
sys/i386/isa/if_ix.c
File diff suppressed because it is too large
Load Diff
@ -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;
|
Loading…
Reference in New Issue
Block a user