summaryrefslogtreecommitdiffstats
path: root/bsps/shared/net/i82586.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/shared/net/i82586.c')
-rw-r--r--bsps/shared/net/i82586.c2198
1 files changed, 0 insertions, 2198 deletions
diff --git a/bsps/shared/net/i82586.c b/bsps/shared/net/i82586.c
deleted file mode 100644
index 8933ddf3c4..0000000000
--- a/bsps/shared/net/i82586.c
+++ /dev/null
@@ -1,2198 +0,0 @@
-/* $NetBSD: i82586.c,v 1.38 2001/07/07 05:35:39 thorpej Exp $ */
-
-/*-
- * Copyright (c) 1998 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Paul Kranenburg and Charles M. Hannum.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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 the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * 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.
- */
-
-/*-
- * Copyright (c) 1997 Paul Kranenburg.
- * Copyright (c) 1992, 1993, University of Vermont and State
- * Agricultural College.
- * Copyright (c) 1992, 1993, Garrett A. Wollman.
- *
- * Portions:
- * Copyright (c) 1994, 1995, Rafal K. Boni
- * Copyright (c) 1990, 1991, William F. Jolitz
- * Copyright (c) 1990, The Regents of the University of California
- *
- * RTEMS:
- * Copyright (c) 2001, Chris Johns, Cybertec Pty Ltd,
- * http://www.cybertec.com.au/.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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 the University of Vermont
- * and State Agricultural College and Garrett A. Wollman, by William F.
- * Jolitz, and by the University of California, Berkeley, Lawrence
- * Berkeley Laboratory, and its contributors.
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR AUTHORS 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.
- */
-
-/*
- * Intel 82586 Ethernet chip
- * Register, bit, and structure definitions.
- *
- * Original StarLAN driver written by Garrett Wollman with reference to the
- * Clarkson Packet Driver code for this chip written by Russ Nelson and others.
- *
- * BPF support code taken from hpdev/if_le.c, supplied with tcpdump.
- *
- * 3C507 support is loosely based on code donated to NetBSD by Rafal Boni.
- *
- * Majorly cleaned up and 3C507 code merged by Charles Hannum.
- *
- * Converted to SUN ie driver by Charles D. Cranor,
- * October 1994, January 1995.
- * This sun version based on i386 version 1.30.
- */
-
-/*
- * The i82586 is a very painful chip, found in sun3's, sun-4/100's
- * sun-4/200's, and VME based suns. The byte order is all wrong for a
- * SUN, making life difficult. Programming this chip is mostly the same,
- * but certain details differ from system to system. This driver is
- * written so that different "ie" interfaces can be controled by the same
- * driver.
- */
-
-/*
-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
- 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 can be sent off
- quickly.
-
- We configure the adapter in AL-LOC = 1 mode, which means that the
- Ethernet/802.3 MAC header is placed at the beginning of the receive
- buffer rather than being split off into various fields in the RFD.
- This also means that we must include this header in the transmit
- buffer as well.
-
- By convention, all transmit commands, and only transmit commands,
- shall have the I (IE_CMD_INTR) bit set in the command. This way,
- when an interrupt arrives at i82586_intr(), it is immediately possible
- to tell what precisely caused it. ANY OTHER command-sending
- routines should run at splnet(), and should post an acknowledgement
- to every interrupt they generate.
-
- To save the expense of shipping a command to 82586 every time we
- want to send a frame, we use a linked list of commands consisting
- of alternate XMIT and NOP commands. The links of these elements
- are manipulated (in iexmit()) such that the NOP command loops back
- to itself whenever the following XMIT command is not yet ready to
- go. Whenever an XMIT is ready, the preceding NOP link is pointed
- at it, while its own link field points to the following NOP command.
- Thus, a single transmit command sets off an interlocked traversal
- of the xmit command chain, with the host processor in control of
- the synchronization.
-*/
-
-#include <machine/rtems-bsd-kernel-space.h>
-
-#include <rtems.h>
-#include <rtems/error.h>
-#include <rtems/rtems_bsdnet.h>
-
-#include <ctype.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <inttypes.h>
-
-#include <sys/param.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/sockio.h>
-
-#include <net/ethernet.h>
-#include <net/if.h>
-#include <net/if_types.h>
-#include <net/if_dl.h>
-
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
-
-#include "i82586reg.h"
-#include <libchip/i82586var.h>
-
-#if defined(ALIGNBYTES) && defined(ALIGN)
-/* FIXME: Redefine because some versions of
- * RTEMS newlib and the BSDs ship a broken ALIGN */
-#undef ALIGN
-#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) & ~ALIGNBYTES)
-#else
-#define ALIGN(p) (p)
-#endif
-
-/*
- * A global way to change all async cmd requests at once. For RTEMS and running
- * as tasks I wanted to see if the tx race condition is effected by this.
- */
-#define ASYNC_OPTION (1)
-
-void i82586_reset (struct ie_softc *, int);
-void i82586_watchdog (struct ifnet *);
-void i82586_init (void *);
-int i82586_ioctl (struct ifnet *, ioctl_command_t cmd, caddr_t data);
-void i82586_start (struct ifnet *);
-
-void i82586_stop (struct ifnet *, int);
-int i82586_rint (struct ie_softc *, int);
-int i82586_tint (struct ie_softc *, int);
-
-int i82586_mediachange (struct ifnet *);
-void i82586_mediastatus (struct ifnet *, struct ifmediareq *);
-
-static void i82586_tx_task(void *arg);
-static void i82586_start_tx(struct ie_softc *sc);
-
-static int ie_readframe (struct ie_softc *, int);
-static struct mbuf *ieget (struct ie_softc *, int, int);
-static int i82586_get_rbd_list (struct ie_softc *, u_int16_t*,
- u_int16_t*, int *);
-static void i82586_release_rbd_list (struct ie_softc *,
- u_int16_t, u_int16_t);
-static int i82586_drop_frames (struct ie_softc *);
-static int i82586_chk_rx_ring (struct ie_softc *);
-
-static __inline__ void ie_ack (struct ie_softc *, u_int);
-static __inline__ void iexmit (struct ie_softc *);
-static void i82586_start_transceiver (struct ie_softc *);
-
-static void i82586_count_errors (struct ie_softc *);
-static void i82586_rx_errors (struct ie_softc *, int, int);
-static void i82586_setup_bufs (struct ie_softc *);
-static void setup_simple_command (struct ie_softc *, int, int);
-static int ie_cfg_setup (struct ie_softc *, int, int, int);
-static int ie_ia_setup (struct ie_softc *, int);
-static void ie_run_tdr (struct ie_softc *, int);
-static int ie_mc_setup (struct ie_softc *, int);
-static void ie_mc_reset (struct ie_softc *);
-static int i82586_start_cmd (struct ie_softc *, int, int, int, int);
-static int i82586_cmd_wait (struct ie_softc *);
-
-#if I82586_DEBUG
-static void print_softie(struct ie_softc *sc);
-static void print_rbd (struct ie_softc *, int);
-#endif
-
-#define min(l,r) ((l) < (r) ? (l) : (r))
-#define max(l,r) ((l) > (r) ? (l) : (r))
-
-#define delay(p) rtems_task_wake_after (RTEMS_MICROSECONDS_TO_TICKS (p))
-
-#define i82586_WAKE_EVENT RTEMS_EVENT_1
-#define i82586_TX_EVENT RTEMS_EVENT_2
-
-static char *
-bitmask_snprintf(unsigned long value, const char *format, char *buf, int blen)
-{
- char *b = buf;
- int bit = 31;
-
- while (bit-- > *format)
- value <<= 1;
-
- format++;
-
- while (*format)
- {
- if (value & 0x80000000)
- while (isalnum((unsigned char)*format))
- *b++ = *format;
- else
- *b++ = '0';
-
- *b++ = ',';
-
- while (bit-- > *format)
- value <<= 1;
-
- format++;
- }
-
- *b = '\0';
- return buf;
-}
-
-/*
- * Front-ends call this function to attach to the MI driver.
- *
- * The front-end has responsibility for managing the ICP and ISCP
- * structures. Both of these are opaque to us. Also, the front-end
- * chooses a location for the SCB which is expected to be addressable
- * (through `sc->scb') as an offset against the shared-memory bus handle.
- *
- * The following MD interface function must be setup by the front-end
- * before calling here:
- *
- * hwreset - board dependent reset
- * hwinit - board dependent initialization
- * chan_attn - channel attention
- * intrhook - board dependent interrupt processing
- * memcopyin - shared memory copy: board to KVA
- * memcopyout - shared memory copy: KVA to board
- * ie_bus_read16 - read a sixteen-bit i82586 pointer
- * ie_bus_write16 - write a sixteen-bit i82586 pointer
- * ie_bus_write24 - write a twenty-four-bit i82586 pointer
- *
- */
-int
-i82586_attach(struct rtems_bsdnet_ifconfig *config, int attaching)
-{
- struct ie_softc *sc;
- struct ifnet *ifp;
- char *name;
- int unit;
- int mtu;
-
- /*
- * Parse driver name
- */
-
- if ((unit = rtems_bsdnet_parse_driver_name (config, &name)) < 0)
- return 0;
-
- sc = config->drv_ctrl;
- ifp = &sc->arpcom.ac_if;
-
-#if I82586_DEBUG
- sc->sc_debug = 0; /*IED_TINT | IED_XMIT; */
-#endif
-
- if (attaching)
- {
- if (ifp->if_softc)
- {
- printf ("Driver `%s' already in use.\n", config->name);
- return 0;
- }
-
- /*
- * Process options
- */
-
- memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
-
- if (config->mtu)
- mtu = config->mtu;
- else
- mtu = ETHERMTU;
-
- ifp->if_softc = sc;
- ifp->if_unit = unit;
- ifp->if_name = name;
- ifp->if_mtu = mtu;
- ifp->if_init = i82586_init;
- ifp->if_ioctl = i82586_ioctl;
- ifp->if_start = i82586_start;
- ifp->if_output = ether_output;
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
-
- if (ifp->if_snd.ifq_maxlen == 0)
- ifp->if_snd.ifq_maxlen = ifqmaxlen;
-
- /* Attach the interface. */
- if_attach(ifp);
- ether_ifattach(ifp);
- return 1;
- }
- return 0;
-}
-
-
-/*
- * Interrupt Acknowledge. Mask in native byte-order.
- */
-static __inline__ void
-ie_ack(struct ie_softc *sc, u_int mask)
-{
- u_int status;
-
- IE_BUS_BARRIER(sc, 0, 0, BUS_SPACE_BARRIER_READ);
- status = sc->ie_bus_read16(sc, IE_SCB_STATUS(sc->scb));
- i82586_start_cmd(sc, status & mask, 0, 0, 0);
- if (sc->intrhook)
- sc->intrhook(sc, INTR_ACK);
-}
-
-
-/*
- * Read data off the interface, and turn it into an mbuf chain.
- *
- * This code is DRAMATICALLY different from the previous version; this
- * version tries to allocate the entire mbuf chain up front, given the
- * length of the data available. This enables us to allocate mbuf
- * clusters in many situations where before we would have had a long
- * chain of partially-full mbufs. This should help to speed up the
- * operation considerably. (Provided that it works, of course.)
- */
-static __inline struct mbuf *
-ieget(struct ie_softc *sc, int head, int totlen)
-{
- struct mbuf *m, *m0, *newm;
- int len, resid;
- int thisrboff, thismboff;
- struct ether_header eh;
-
- /*
- * Snarf the Ethernet header.
- */
- (sc->memcopyin)(sc, &eh, IE_RBUF_ADDR(sc, head),
- sizeof(struct ether_header));
-
- resid = totlen;
-
- MGETHDR(m0, M_DONTWAIT, MT_DATA);
- if (m0 == 0)
- return (0);
- m0->m_pkthdr.rcvif = &sc->arpcom.ac_if;
- m0->m_pkthdr.len = totlen;
- len = MHLEN;
- m = m0;
-
- /*
- * This loop goes through and allocates mbufs for all the data we will
- * be copying in. It does not actually do the copying yet.
- */
- while (totlen > 0) {
- if (totlen >= MINCLSIZE) {
- MCLGET(m, M_DONTWAIT);
- if ((m->m_flags & M_EXT) == 0)
- goto bad;
- len = MCLBYTES;
- }
-
- if (m == m0) {
- caddr_t newdata = (caddr_t)
- ALIGN(m->m_data + sizeof(struct ether_header)) -
- sizeof(struct ether_header);
- len -= newdata - m->m_data;
- m->m_data = newdata;
- }
-
- m->m_len = len = min(totlen, len);
-
- totlen -= len;
- if (totlen > 0) {
- MGET(newm, M_DONTWAIT, MT_DATA);
- if (newm == 0)
- goto bad;
- len = MLEN;
- m = m->m_next = newm;
- }
- }
-
- m = m0;
- thismboff = 0;
-
- /*
- * Copy the Ethernet header into the mbuf chain.
- */
- memcpy(mtod(m, caddr_t), &eh, sizeof(struct ether_header));
- thismboff = sizeof(struct ether_header);
- thisrboff = sizeof(struct ether_header);
- resid -= sizeof(struct ether_header);
-
- /*
- * Now we take the mbuf chain (hopefully only one mbuf most of the
- * time) and stuff the data into it. There are no possible failures
- * at or after this point.
- */
- while (resid > 0) {
- int thisrblen = IE_RBUF_SIZE - thisrboff,
- thismblen = m->m_len - thismboff;
- len = min(thisrblen, thismblen);
-
- (sc->memcopyin)(sc, mtod(m, caddr_t) + thismboff,
- IE_RBUF_ADDR(sc,head) + thisrboff,
- (u_int)len);
- resid -= len;
-
- if (len == thismblen) {
- m = m->m_next;
- thismboff = 0;
- } else
- thismboff += len;
-
- if (len == thisrblen) {
- if (++head == sc->nrxbuf)
- head = 0;
- thisrboff = 0;
- } else
- thisrboff += len;
- }
-
- /*
- * Unless something changed strangely while we were doing the copy,
- * we have now copied everything in from the shared memory.
- * This means that we are done.
- */
- return (m0);
-
- bad:
- m_freem(m0);
- return (0);
-}
-
-/*
- * Setup all necessary artifacts for an XMIT command, and then pass the XMIT
- * command to the chip to be executed.
- */
-static __inline__ void
-iexmit(struct ie_softc *sc)
-{
- int off;
- int cur, prev;
-
- cur = sc->xctail;
-
-#if I82586_DEBUG
- I82586_TRACE(sc, I82586_TX_EMIT, cur);
-#endif
-
-#if I82586_DEBUG
- if (sc->sc_debug & IED_XMIT)
- printf("%s: xmit buffer %d\n", sc->arpcom.ac_if.if_name, cur);
-#endif
-
- /*
- * Setup the transmit command.
- */
- sc->ie_bus_write16(sc, IE_CMD_XMIT_DESC(sc->xmit_cmds, cur),
- IE_XBD_ADDR(sc->xbds, cur));
-
- sc->ie_bus_write16(sc, IE_CMD_XMIT_STATUS(sc->xmit_cmds, cur), 0);
-
- if (sc->do_xmitnopchain) {
- /*
- * Gate this XMIT command to the following NOP
- */
- sc->ie_bus_write16(sc, IE_CMD_XMIT_LINK(sc->xmit_cmds, cur),
- IE_CMD_NOP_ADDR(sc->nop_cmds, cur));
- sc->ie_bus_write16(sc, IE_CMD_XMIT_CMD(sc->xmit_cmds, cur),
- IE_CMD_XMIT | IE_CMD_INTR);
-
- /*
- * Loopback at following NOP
- */
- sc->ie_bus_write16(sc, IE_CMD_NOP_STATUS(sc->nop_cmds, cur), 0);
- sc->ie_bus_write16(sc, IE_CMD_NOP_LINK(sc->nop_cmds, cur),
- IE_CMD_NOP_ADDR(sc->nop_cmds, cur));
-
- /*
- * Gate preceding NOP to this XMIT command
- */
- prev = (cur + NTXBUF - 1) % NTXBUF;
- sc->ie_bus_write16(sc, IE_CMD_NOP_STATUS(sc->nop_cmds, prev), 0);
- sc->ie_bus_write16(sc, IE_CMD_NOP_LINK(sc->nop_cmds, prev),
- IE_CMD_XMIT_ADDR(sc->xmit_cmds, cur));
-
- off = IE_SCB_STATUS(sc->scb);
- IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ);
- if ((sc->ie_bus_read16(sc, off) & IE_CUS_ACTIVE) == 0) {
- printf("iexmit: CU not active\n");
- i82586_start_transceiver(sc);
- }
- } else {
- sc->ie_bus_write16(sc, IE_CMD_XMIT_LINK(sc->xmit_cmds,cur),
- 0xffff);
-
- sc->ie_bus_write16(sc, IE_CMD_XMIT_CMD(sc->xmit_cmds, cur),
- IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST);
-
- off = IE_SCB_CMDLST(sc->scb);
- sc->ie_bus_write16(sc, off, IE_CMD_XMIT_ADDR(sc->xmit_cmds, cur));
- IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ);
-
- if (i82586_start_cmd(sc, IE_CUC_START, 0, 0, ASYNC_OPTION))
- printf("%s: iexmit: start xmit command timed out\n",
- sc->arpcom.ac_if.if_name);
- }
-
- sc->arpcom.ac_if.if_timer = 5;
-}
-
-
-/*
- * Device timeout/watchdog routine.
- * Entered if the device neglects to generate an interrupt after a
- * transmit has been started on it.
- */
-void
-i82586_watchdog(struct ifnet *ifp)
-{
- struct ie_softc *sc = ifp->if_softc;
- printf("%s: device timeout\n", ifp->if_name);
- ++ifp->if_oerrors;
- i82586_reset(sc, 1);
-}
-
-static int
-i82586_cmd_wait(struct ie_softc *sc)
-{
- /* spin on i82586 command acknowledge; wait at most 0.9 (!) seconds */
- int i, off;
- u_int16_t cmd;
-
- for (i = 0; i < 900000; i++) {
- /* Read the command word */
- off = IE_SCB_CMD(sc->scb);
-
- IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ);
- if ((cmd = sc->ie_bus_read16(sc, off)) == 0)
- return (0);
- delay(1);
- }
-
- off = IE_SCB_STATUS(sc->scb);
- printf("i82586_cmd_wait: timo(%ssync): scb status: 0x%x, cmd: 0x%x\n",
- sc->async_cmd_inprogress?"a":"",
- sc->ie_bus_read16(sc, off), cmd);
-
- return (1); /* Timeout */
-}
-
-/*
- * Send a command to the controller and wait for it to either complete
- * or be accepted, depending on the command. If the command pointer
- * is null, then pretend that the command is not an action command.
- * If the command pointer is not null, and the command is an action
- * command, wait for one of the MASK bits to turn on in the command's
- * status field.
- * If ASYNC is set, we just call the chip's attention and return.
- * We may have to wait for the command's acceptance later though.
- */
-static int
-i82586_start_cmd(struct ie_softc *sc, int cmd, int iecmdbuf, int mask, int async)
-{
- int i;
- int off;
-
- if (sc->async_cmd_inprogress != 0) {
- /*
- * If previous command was issued asynchronously, wait
- * for it now.
- */
- if (i82586_cmd_wait(sc) != 0)
- return (1);
- sc->async_cmd_inprogress = 0;
- }
-
- off = IE_SCB_CMD(sc->scb);
- sc->ie_bus_write16(sc, off, cmd);
- IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_WRITE);
- (sc->chan_attn)(sc, CARD_RESET);
-
- if (async != 0) {
- sc->async_cmd_inprogress = 1;
- return (0);
- }
-
- if (IE_ACTION_COMMAND(cmd) && iecmdbuf) {
- int status;
- /*
- * Now spin-lock waiting for status. This is not a very nice
- * thing to do, and can kill performance pretty well...
- * According to the packet driver, the minimum timeout
- * should be .369 seconds.
- */
- for (i = 0; i < 369000; i++) {
- /* Read the command status */
- off = IE_CMD_COMMON_STATUS(iecmdbuf);
- IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ);
- status = sc->ie_bus_read16(sc, off);
- if (status & mask)
- return (0);
- delay(1);
- }
-
- } else {
- /*
- * Otherwise, just wait for the command to be accepted.
- */
- return (i82586_cmd_wait(sc));
- }
-
- /* Timeout */
- return (1);
-}
-
-
-/*
- * Transfer accumulated chip error counters to IF.
- */
-static __inline void
-i82586_count_errors(struct ie_softc *sc)
-{
- int scb = sc->scb;
-
- sc->arpcom.ac_if.if_ierrors +=
- sc->ie_bus_read16(sc, IE_SCB_ERRCRC(scb)) +
- sc->ie_bus_read16(sc, IE_SCB_ERRALN(scb)) +
- sc->ie_bus_read16(sc, IE_SCB_ERRRES(scb)) +
- sc->ie_bus_read16(sc, IE_SCB_ERROVR(scb));
-
- /* Clear error counters */
- sc->ie_bus_write16(sc, IE_SCB_ERRCRC(scb), 0);
- sc->ie_bus_write16(sc, IE_SCB_ERRALN(scb), 0);
- sc->ie_bus_write16(sc, IE_SCB_ERRRES(scb), 0);
- sc->ie_bus_write16(sc, IE_SCB_ERROVR(scb), 0);
-}
-
-
-static void
-i82586_rx_errors(struct ie_softc *sc, int fn, int status)
-{
- char bits[128];
-
- printf("%s: rx error (frame# %d): %s\n", sc->arpcom.ac_if.if_name, fn,
- bitmask_snprintf(status, IE_FD_STATUSBITS, bits, sizeof(bits)));
-}
-
-/*
- * i82586 interrupt entry point.
- */
-rtems_isr
-i82586_intr(rtems_vector_number vec, void *arg)
-{
- struct ie_softc *sc = arg;
-
-#if I82586_DEBUG
- static unsigned long icnt = 0;
- I82586_TRACE(sc, I82586_INTS_REQ, icnt++);
-#endif
-
- /*
- * Implementation dependent interrupt handling. It must at least
- * disabled interrupts from the i82586. It is hoped this can
- * happen somewhere outside the i82586.
- */
- if (sc->intrhook)
- (sc->intrhook)(sc, INTR_ENTER);
-
- /*
- * Wake the task to handle the interrupt. It will
- * enabled the interrupts when it has finished.
- */
- rtems_bsdnet_event_send (sc->intr_task, i82586_WAKE_EVENT);
-}
-
-/*
- * i82586 interrupt task. The task is actually an extension of the interrupt
- * with a context switch in the middle. The RTEMS TCP/IP stack requires a task
- * be used to talk to the stack as a network semaphore is claimed. This
- * cannot happen during an interrupt.
- */
-static void
-i82586_intr_task(void *arg)
-{
- struct ie_softc *sc = arg;
- rtems_event_set events;
- u_int status;
- int off;
- int reset;
-
- /*
- * Not sure this is a good idea but as a out path exists and
- * roads lead to it, it seems ok.
- */
- for (;;) {
- rtems_bsdnet_event_receive (i82586_WAKE_EVENT,
- RTEMS_WAIT | RTEMS_EVENT_ANY,
- 0, &events);
-
- off = IE_SCB_STATUS(sc->scb);
- IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ);
- status = sc->ie_bus_read16(sc, off) & IE_ST_WHENCE;
-
-#if I82586_DEBUG
- I82586_TRACE(sc, I82586_INTS_IN, status);
-#endif
-
- reset = 0;
-
- while ((status & IE_ST_WHENCE) != 0) {
-#if I82586_DEBUG
- if (sc->sc_debug)
- printf ("%s: -------\n%s: scbstatus=0x%x\n",
- sc->arpcom.ac_if.if_name, sc->arpcom.ac_if.if_name, status);
-#endif
-
-#if 1
- /* Ack interrupts FIRST in case we receive more during the ISR. */
- ie_ack(sc, status & IE_ST_WHENCE);
-#endif
-
- i82586_start_cmd(sc, status & IE_ST_WHENCE, 0, 0, ASYNC_OPTION);
-
- if (status & (IE_ST_FR | IE_ST_RNR))
- if (i82586_rint(sc, status) != 0) {
- reset = 1;
- break;
- }
-
- if (status & IE_ST_CX)
- if (i82586_tint(sc, status) != 0) {
- reset = 1;
- break;
- }
-
-#if I82586_DEBUG
- if ((status & IE_ST_CNA) && (sc->sc_debug & IED_CNA))
- printf("%s: cna; status=0x%x\n", sc->arpcom.ac_if.if_name, status);
-#endif
-
-#if 0
- if (sc->intrhook)
- (sc->intrhook)(sc, INTR_LOOP);
-#endif
-
-#if 1
- /*
- * Interrupt ACK was posted asynchronously; wait for
- * completion here before reading SCB status again.
- *
- * If ACK fails, try to reset the chip, in hopes that
- * it helps.
- */
- if (i82586_cmd_wait(sc) != 0) {
- reset = 1;
- break;
- }
-#endif
-
- IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ);
- status = sc->ie_bus_read16(sc, off);
-#if I82586_DEBUG
- I82586_TRACE(sc, I82586_INTS_LOOPS, status);
-#endif
- }
-
- if (reset) {
-#if I82586_DEBUG
- printf("%s: intr reset; status=0x%x\n", sc->arpcom.ac_if.if_name, status);
-#endif
- i82586_cmd_wait(sc);
- i82586_reset(sc, 1);
- }
-
-#if I82586_DEBUG
- I82586_TRACE(sc, I82586_INTS_OUT, status);
-#endif
-
- if (sc->intrhook)
- (sc->intrhook)(sc, INTR_EXIT);
- }
-}
-
-/*
- * Process a received-frame interrupt.
- */
-int
-i82586_rint(struct ie_softc *sc, int scbstatus)
-{
- static int timesthru = 1024;
- int i, status, off;
-
-#if I82586_DEBUG
- I82586_TRACE(sc, I82586_RX_INT, scbstatus);
-
- if (sc->sc_debug & IED_RINT)
- printf("%s: rint: status 0x%x\n",
- sc->arpcom.ac_if.if_name, scbstatus);
-#endif
-
- for (;;) {
- int drop = 0;
-
- i = sc->rfhead;
- off = IE_RFRAME_STATUS(sc->rframes, i);
- IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ);
- status = sc->ie_bus_read16(sc, off);
-
-#if I82586_DEBUG
- if (sc->sc_debug & IED_RINT)
- printf("%s: rint: frame(%d) status 0x%x\n",
- sc->arpcom.ac_if.if_name, i, status);
-#endif
- if ((status & IE_FD_COMPLETE) == 0) {
- if ((status & IE_FD_OK) != 0) {
- printf("%s: rint: weird: ",
- sc->arpcom.ac_if.if_name);
- i82586_rx_errors(sc, i, status);
-#if I82586_DEBUG
- I82586_TRACE(sc, I82586_RX_ERR, status);
-#endif
- break;
- }
- if (--timesthru == 0) {
- /* Account the accumulated errors */
- i82586_count_errors(sc);
- timesthru = 1024;
- }
- break;
- } else if ((status & IE_FD_OK) == 0) {
- /*
- * If the chip is configured to automatically
- * discard bad frames, the only reason we can
- * get here is an "out-of-resource" condition.
- */
- i82586_rx_errors(sc, i, status);
- drop = 1;
-
-#if I82586_DEBUG
- I82586_TRACE(sc, I82586_RX_DROP, status);
-#endif
- }
-
-#if I82586_DEBUG
- if ((status & IE_FD_BUSY) != 0)
- printf("%s: rint: frame(%d) busy; status=0x%x\n",
- sc->arpcom.ac_if.if_name, i, status);
-#endif
-
- /*
- * Advance the RFD list, since we're done with
- * this descriptor.
- */
-
- /* Clear frame status */
- sc->ie_bus_write16(sc, off, 0);
-
- /* Put fence at this frame (the head) */
- off = IE_RFRAME_LAST(sc->rframes, i);
- sc->ie_bus_write16(sc, off, IE_FD_EOL|IE_FD_SUSP);
-
- /* and clear RBD field */
- off = IE_RFRAME_BUFDESC(sc->rframes, i);
- sc->ie_bus_write16(sc, off, 0xffff);
-
- /* Remove fence from current tail */
- off = IE_RFRAME_LAST(sc->rframes, sc->rftail);
- sc->ie_bus_write16(sc, off, 0);
-
- if (++sc->rftail == sc->nframes)
- sc->rftail = 0;
- if (++sc->rfhead == sc->nframes)
- sc->rfhead = 0;
-
- /* Pull the frame off the board */
- if (drop) {
- i82586_drop_frames(sc);
- if ((status & IE_FD_RNR) != 0)
- sc->rnr_expect = 1;
- sc->arpcom.ac_if.if_ierrors++;
- } else if (ie_readframe(sc, i) != 0)
- return (1);
- }
-
- if ((scbstatus & IE_ST_RNR) != 0) {
-
- /*
- * Receiver went "Not Ready". We try to figure out
- * whether this was an expected event based on past
- * frame status values.
- */
-
- if ((scbstatus & IE_RUS_SUSPEND) != 0) {
- /*
- * We use the "suspend on last frame" flag.
- * Send a RU RESUME command in response, since
- * we should have dealt with all completed frames
- * by now.
- */
- printf("RINT: SUSPENDED; scbstatus=0x%x\n",
- scbstatus);
- if (i82586_start_cmd(sc, IE_RUC_RESUME, 0, 0, 0) == 0)
- return (0);
- printf("%s: RU RESUME command timed out\n",
- sc->arpcom.ac_if.if_name);
- return (1); /* Ask for a reset */
- }
-
- if (sc->rnr_expect != 0) {
- /*
- * The RNR condition was announced in the previously
- * completed frame. Assume the receive ring is Ok,
- * so restart the receiver without further delay.
- */
- i82586_start_transceiver(sc);
- sc->rnr_expect = 0;
- return (0);
-
- } else if ((scbstatus & IE_RUS_NOSPACE) != 0) {
- /*
- * We saw no previous IF_FD_RNR flag.
- * We check our ring invariants and, if ok,
- * just restart the receiver at the current
- * point in the ring.
- */
- if (i82586_chk_rx_ring(sc) != 0)
- return (1);
-
- i82586_start_transceiver(sc);
- sc->arpcom.ac_if.if_ierrors++;
- return (0);
- } else
- printf("%s: receiver not ready; scbstatus=0x%x\n",
- sc->arpcom.ac_if.if_name, scbstatus);
-
- sc->arpcom.ac_if.if_ierrors++;
- return (1); /* Ask for a reset */
- }
-
- return (0);
-}
-
-/*
- * Process a command-complete interrupt. These are only generated by the
- * transmission of frames. This routine is deceptively simple, since most
- * of the real work is done by i82586_start().
- */
-int
-i82586_tint(struct ie_softc *sc, int scbstatus)
-{
- struct ifnet *ifp = &sc->arpcom.ac_if;
- int status;
-
-#if I82586_DEBUG
- I82586_TRACE(sc, I82586_TX_INT, sc->xmit_busy);
-#endif
-
-#if I82586_DEBUG
- if (sc->xmit_busy <= 0) {
- printf("i82586_tint: (%d), WEIRD: xmit_busy=%d, xctail=%d, xchead=%d\n",
- sc->trace_flow_in / 2, sc->xmit_busy, sc->xctail, sc->xchead);
- I82586_TRACE(sc, I82586_TX_BAD, sc->xctail);
- return (0);
- }
-#endif
-
- ifp->if_timer = 0;
- ifp->if_flags &= ~IFF_OACTIVE;
-
- status = sc->ie_bus_read16(sc, IE_CMD_XMIT_STATUS(sc->xmit_cmds,
- sc->xctail));
-
-#if I82586_DEBUG
- if (sc->sc_debug & IED_TINT)
- printf("%s: tint: SCB status 0x%x; xmit status 0x%x\n",
- sc->arpcom.ac_if.if_name, scbstatus, status);
-#endif
-
- if ((status & IE_STAT_COMPL) == 0 || (status & IE_STAT_BUSY)) {
- printf("i82586_tint: (%d) command still busy; status=0x%x; tail=%d\n",
- sc->trace_flow_in / 2, status, sc->xctail);
- printf("iestatus = 0x%x\n", scbstatus);
-/* sc->sc_debug = IED_ALL; */
- }
-
- if (status & IE_STAT_OK) {
- ifp->if_opackets++;
- ifp->if_collisions += (status & IE_XS_MAXCOLL);
- } else {
- ifp->if_oerrors++;
- /*
- * Check SQE and DEFERRED?
- * What if more than one bit is set?
- */
- if (status & IE_STAT_ABORT)
- printf("%s: send aborted\n", sc->arpcom.ac_if.if_name);
- else if (status & IE_XS_NOCARRIER)
- printf("%s: no carrier\n", sc->arpcom.ac_if.if_name);
- else if (status & IE_XS_LOSTCTS)
- printf("%s: lost CTS\n", sc->arpcom.ac_if.if_name);
- else if (status & IE_XS_UNDERRUN)
- printf("%s: DMA underrun\n", sc->arpcom.ac_if.if_name);
- else if (status & IE_XS_EXCMAX) {
- printf("%s: too many collisions\n",
- sc->arpcom.ac_if.if_name);
- sc->arpcom.ac_if.if_collisions += 16;
- }
- }
-
- /*
- * If multicast addresses were added or deleted while transmitting,
- * ie_mc_reset() set the want_mcsetup flag indicating that we
- * should do it.
- */
- if (sc->want_mcsetup) {
- ie_mc_setup(sc, IE_XBUF_ADDR(sc, sc->xctail));
- sc->want_mcsetup = 0;
- }
-
- /* Done with the buffer. */
- sc->xmit_busy--;
- sc->xctail = (sc->xctail + 1) % NTXBUF;
-
- /* Start the next packet, if any, transmitting. */
- if (sc->xmit_busy > 0)
- iexmit(sc);
-
- i82586_start_tx(sc);
- return (0);
-}
-
-/*
- * Get a range of receive buffer descriptors that represent one packet.
- */
-static int
-i82586_get_rbd_list(struct ie_softc *sc, u_int16_t *start, u_int16_t *end, int *pktlen)
-{
- int off, rbbase = sc->rbds;
- int rbindex, count = 0;
- int plen = 0;
- int rbdstatus;
-
- *start = rbindex = sc->rbhead;
-
- do {
- off = IE_RBD_STATUS(rbbase, rbindex);
- IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ);
- rbdstatus = sc->ie_bus_read16(sc, off);
- if ((rbdstatus & IE_RBD_USED) == 0) {
- /*
- * This means we are somehow out of sync. So, we
- * reset the adapter.
- */
-#if I82586_DEBUG
- print_rbd(sc, rbindex);
-#endif
- printf("%s: receive descriptors out of sync at %d\n",
- sc->arpcom.ac_if.if_name, rbindex);
- return (0);
- }
- plen += (rbdstatus & IE_RBD_CNTMASK);
-
- if (++rbindex == sc->nrxbuf)
- rbindex = 0;
-
- ++count;
- } while ((rbdstatus & IE_RBD_LAST) == 0);
- *end = rbindex;
- *pktlen = plen;
- return (count);
-}
-
-
-/*
- * Release a range of receive buffer descriptors after we've copied the packet.
- */
-static void
-i82586_release_rbd_list(struct ie_softc *sc, u_int16_t start, u_int16_t end)
-{
- int off, rbbase = sc->rbds;
- int rbindex = start;
-
- do {
- /* Clear buffer status */
- off = IE_RBD_STATUS(rbbase, rbindex);
- sc->ie_bus_write16(sc, off, 0);
- if (++rbindex == sc->nrxbuf)
- rbindex = 0;
- } while (rbindex != end);
-
- /* Mark EOL at new tail */
- rbindex = ((rbindex == 0) ? sc->nrxbuf : rbindex) - 1;
- off = IE_RBD_BUFLEN(rbbase, rbindex);
- sc->ie_bus_write16(sc, off, IE_RBUF_SIZE|IE_RBD_EOL);
-
- /* Remove EOL from current tail */
- off = IE_RBD_BUFLEN(rbbase, sc->rbtail);
- sc->ie_bus_write16(sc, off, IE_RBUF_SIZE);
-
- /* New head & tail pointer */
-/* hmm, why have both? head is always (tail + 1) % NRXBUF */
- sc->rbhead = end;
- sc->rbtail = rbindex;
-}
-
-/*
- * Drop the packet at the head of the RX buffer ring.
- * Called if the frame descriptor reports an error on this packet.
- * Returns 1 if the buffer descriptor ring appears to be corrupt;
- * and 0 otherwise.
- */
-static int
-i82586_drop_frames(struct ie_softc *sc)
-{
- u_int16_t bstart, bend;
- int pktlen;
-
- if (i82586_get_rbd_list(sc, &bstart, &bend, &pktlen) == 0)
- return (1);
- i82586_release_rbd_list(sc, bstart, bend);
- return (0);
-}
-
-/*
- * Check the RX frame & buffer descriptor lists for our invariants,
- * i.e.: EOL bit set iff. it is pointed at by the r*tail pointer.
- *
- * Called when the receive unit has stopped unexpectedly.
- * Returns 1 if an inconsistency is detected; 0 otherwise.
- *
- * The Receive Unit is expected to be NOT RUNNING.
- */
-static int
-i82586_chk_rx_ring(struct ie_softc *sc)
-{
- int n, off, val;
-
- for (n = 0; n < sc->nrxbuf; n++) {
- off = IE_RBD_BUFLEN(sc->rbds, n);
- val = sc->ie_bus_read16(sc, off);
- if ((n == sc->rbtail) ^ ((val & IE_RBD_EOL) != 0)) {
- /* `rbtail' and EOL flag out of sync */
- printf("%s: rx buffer descriptors out of sync at %d\n",
- sc->arpcom.ac_if.if_name, n);
- return (1);
- }
-
- /* Take the opportunity to clear the status fields here ? */
- }
-
- for (n = 0; n < sc->nframes; n++) {
- off = IE_RFRAME_LAST(sc->rframes, n);
- val = sc->ie_bus_read16(sc, off);
- if ((n == sc->rftail) ^ ((val & (IE_FD_EOL|IE_FD_SUSP)) != 0)) {
- /* `rftail' and EOL flag out of sync */
- printf("%s: rx frame list out of sync at %d\n",
- sc->arpcom.ac_if.if_name, n);
- return (1);
- }
- }
-
- return (0);
-}
-
-
-/*
- * Read frame NUM from unit UNIT (pre-cached as IE).
- *
- * This routine reads the RFD at NUM, and copies in the buffers from the list
- * of RBD, then rotates the RBD list so that the receiver doesn't start
- * complaining. Trailers are DROPPED---there's no point in wasting time
- * on confusing code to deal with them. Hopefully, this machine will
- * never ARP for trailers anyway.
- */
-static int
-ie_readframe(struct ie_softc *sc, int num) /* frame number to read */
-{
- struct ether_header *eh;
- struct mbuf *m;
- u_int16_t bstart, bend;
- int pktlen;
-
- if (i82586_get_rbd_list(sc, &bstart, &bend, &pktlen) == 0) {
- sc->arpcom.ac_if.if_ierrors++;
- return (1);
- }
-
- m = ieget(sc, bstart, pktlen);
- i82586_release_rbd_list(sc, bstart, bend);
-
- if (m == 0) {
- sc->arpcom.ac_if.if_ierrors++;
- return (0);
- }
-
- /*
- * Remove the mac header. This is different from the NetBSD
- * stack.
- */
- eh = mtod(m, struct ether_header *);
- m->m_data += sizeof (struct ether_header);
- m->m_len -= sizeof (struct ether_header);
- m->m_pkthdr.len -= sizeof (struct ether_header);
-
-#if I82586_DEBUG
- if (sc->sc_debug & IED_READFRAME) {
-
- printf("%s: frame from ether %s type 0x%x len %d\n",
- sc->arpcom.ac_if.if_name,
- ether_sprintf(eh->ether_shost),
- (u_int)ntohs(eh->ether_type),
- pktlen);
- }
-#endif
-
-#if NBPFILTER > 0
- /* Check for a BPF filter; if so, hand it up. */
- if (sc->arpcom.ac_if.if_bpf != 0)
- /* Pass it up. */
- bpf_mtap(sc->arpcom.ac_if.if_bpf, m);
-#endif /* NBPFILTER > 0 */
-
- /*
- * Finally pass this packet up to higher layers.
- */
- ether_input (&sc->arpcom.ac_if, eh, m);
- sc->arpcom.ac_if.if_ipackets++;
-
-#if I82586_DEBUG
- I82586_TRACE(sc, I82586_RX_OK, sc->arpcom.ac_if.if_ipackets);
-#endif
-
- return (0);
-}
-
-/*
- * Start transmission on an interface.
- */
-void
-i82586_start(struct ifnet *ifp)
-{
- struct ie_softc *sc = ifp->if_softc;
-
- if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
- return;
-
-#if I82586_DEBUG
- I82586_TRACE(sc, I82586_TX_REQ, sc->xmit_busy);
-#endif
-
- rtems_bsdnet_event_send (sc->tx_task, i82586_TX_EVENT);
-}
-
-static void
-i82586_tx_task(void *arg)
-{
- struct ie_softc *sc = arg;
- rtems_event_set events;
-
- for (;;) {
- rtems_bsdnet_event_receive (i82586_TX_EVENT,
- RTEMS_WAIT | RTEMS_EVENT_ANY,
- 0, &events);
-
-#if I82586_DEBUG
- I82586_TRACE(sc, I82586_TX_EVT, sc->xmit_busy);
-
- if (sc->sc_debug)
- printf ("%s: =======\n", sc->arpcom.ac_if.if_name);
-#endif
-
- i82586_start_tx(sc);
- }
-}
-
-static void
-i82586_start_tx(struct ie_softc *sc)
-{
- struct ifnet *ifp = &sc->arpcom.ac_if;
- struct mbuf *m0, *m;
- int buffer, head, xbase;
- u_short len;
- int s;
-
-#if I82586_DEBUG
- I82586_TRACE(sc, I82586_START_TX, sc->xmit_busy);
-#endif
-
- if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
- {
-#if I82586_DEBUG
- I82586_TRACE(sc, I82586_TX_ACTIVE, ifp->if_snd.ifq_len);
-#endif
- return;
- }
-
- for (;;) {
- if (sc->xmit_busy == NTXBUF) {
- ifp->if_flags |= IFF_OACTIVE;
- break;
- }
-
- head = sc->xchead;
- xbase = sc->xbds;
-
- IF_DEQUEUE(&ifp->if_snd, m0);
- if (m0 == 0)
- break;
-
- /* We need to use m->m_pkthdr.len, so require the header */
- if ((m0->m_flags & M_PKTHDR) == 0)
- panic("i82586_start: no header mbuf");
-
-#if NBPFILTER > 0
- /* Tap off here if there is a BPF listener. */
- if (ifp->if_bpf)
- bpf_mtap(ifp->if_bpf, m0);
-#endif
-
-#if I82586_DEBUG
- if (sc->sc_debug & IED_ENQ)
- printf("%s: fill buffer %d\n", sc->arpcom.ac_if.if_name,
- sc->xchead);
-#endif
-
- if (m0->m_pkthdr.len > IE_TBUF_SIZE)
- printf("%s: tbuf overflow\n", sc->arpcom.ac_if.if_name);
-
- buffer = IE_XBUF_ADDR(sc, head);
- for (m = m0; m != 0; m = m->m_next) {
- (sc->memcopyout)(sc, mtod(m,caddr_t), buffer, m->m_len);
- buffer += m->m_len;
- }
-
- len = max(m0->m_pkthdr.len, ETHER_MIN_LEN);
- m_freem(m0);
-
- /*
- * Setup the transmit buffer descriptor here, while we
- * know the packet's length.
- */
- sc->ie_bus_write16(sc, IE_XBD_FLAGS(xbase, head),
- len | IE_TBD_EOL);
- sc->ie_bus_write16(sc, IE_XBD_NEXT(xbase, head), 0xffff);
- sc->ie_bus_write24(sc, IE_XBD_BUF(xbase, head),
- IE_XBUF_ADDR(sc, head));
-
- if (++head == NTXBUF)
- head = 0;
- sc->xchead = head;
-
-#if I82586_DEBUG
- I82586_TRACE(sc, I82586_TX_START, sc->xmit_busy);
-#endif
-
- s = splnet();
- /* Start the first packet transmitting. */
- if (sc->xmit_busy == 0)
- iexmit(sc);
-
- sc->xmit_busy++;
-
- splx(s);
- }
-}
-
-/*
- * Probe IE's ram setup [ Move all this into MD front-end!? ]
- * Use only if SCP and ISCP represent offsets into shared ram space.
- */
-int
-i82586_proberam(struct ie_softc *sc)
-{
- int result, off;
-
- /* Put in 16-bit mode */
- off = IE_SCP_BUS_USE(sc->scp);
- sc->ie_bus_write16(sc, off, 0);
- IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_WRITE);
-
- /* Set the ISCP `busy' bit */
- off = IE_ISCP_BUSY(sc->iscp);
- sc->ie_bus_write16(sc, off, 1);
- IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_WRITE);
-
- if (sc->hwreset)
- (sc->hwreset)(sc, CHIP_PROBE);
-
- (sc->chan_attn) (sc, CHIP_PROBE);
-
- delay(100); /* wait a while... */
-
- /* Read back the ISCP `busy' bit; it should be clear by now */
- off = IE_ISCP_BUSY(sc->iscp);
- IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ);
- result = sc->ie_bus_read16(sc, off) == 0;
-
- /* Acknowledge any interrupts we may have caused. */
- ie_ack(sc, IE_ST_WHENCE);
-
- return (result);
-}
-
-void
-i82586_reset(struct ie_softc *sc, int hard)
-{
- int s = splnet();
-
- if (hard)
- printf("%s: reset\n", sc->arpcom.ac_if.if_name);
-
- /* Clear OACTIVE in case we're called from watchdog (frozen xmit). */
- sc->arpcom.ac_if.if_timer = 0;
- sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
-
- /*
- * Stop i82586 dead in its tracks.
- */
- if (i82586_start_cmd(sc, IE_RUC_ABORT | IE_CUC_ABORT, 0, 0, 0))
- printf("%s: abort commands timed out\n", sc->arpcom.ac_if.if_name);
-
- /*
- * This can really slow down the i82586_reset() on some cards, but it's
- * necessary to unwedge other ones (eg, the Sun VME ones) from certain
- * lockups.
- */
- if (hard && sc->hwreset)
- (sc->hwreset)(sc, CARD_RESET);
-
- delay(100);
- ie_ack(sc, IE_ST_WHENCE);
-
- if ((sc->arpcom.ac_if.if_flags & IFF_UP) != 0) {
- i82586_init(&sc->arpcom.ac_if);
- }
-
- splx(s);
-}
-
-static void
-setup_simple_command(struct ie_softc *sc, int cmd, int cmdbuf)
-{
- /* Setup a simple command */
- sc->ie_bus_write16(sc, IE_CMD_COMMON_STATUS(cmdbuf), 0);
- sc->ie_bus_write16(sc, IE_CMD_COMMON_CMD(cmdbuf), cmd | IE_CMD_LAST);
- sc->ie_bus_write16(sc, IE_CMD_COMMON_LINK(cmdbuf), 0xffff);
-
- /* Assign the command buffer to the SCB command list */
- sc->ie_bus_write16(sc, IE_SCB_CMDLST(sc->scb), cmdbuf);
-}
-
-/*
- * Run the time-domain reflectometer.
- */
-static void
-ie_run_tdr(struct ie_softc *sc, int cmd)
-{
- uint32_t result;
-
- setup_simple_command(sc, IE_CMD_TDR, cmd);
- sc->ie_bus_write16(sc, IE_CMD_TDR_TIME(cmd), 0);
-
- if (i82586_start_cmd(sc, IE_CUC_START, cmd, IE_STAT_COMPL, 0) ||
- (sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmd)) & IE_STAT_OK) == 0)
- result = 0x10000; /* XXX */
- else
- result = sc->ie_bus_read16(sc, IE_CMD_TDR_TIME(cmd));
-
- /* Squash any pending interrupts */
- ie_ack(sc, IE_ST_WHENCE);
-
- if (result & IE_TDR_SUCCESS)
- return;
-
- if (result & 0x10000)
- printf("%s: TDR command failed\n", sc->arpcom.ac_if.if_name);
- else if (result & IE_TDR_XCVR)
- printf("%s: transceiver problem\n", sc->arpcom.ac_if.if_name);
- else if (result & IE_TDR_OPEN)
- printf("%s: TDR detected incorrect termination %" PRId32 " clocks away\n",
- sc->arpcom.ac_if.if_name, result & IE_TDR_TIME);
- else if (result & IE_TDR_SHORT)
- printf("%s: TDR detected a short circuit %" PRId32 " clocks away\n",
- sc->arpcom.ac_if.if_name, result & IE_TDR_TIME);
- else
- printf("%s: TDR returned unknown status 0x%" PRIx32 "\n",
- sc->arpcom.ac_if.if_name, result);
-}
-
-
-/*
- * i82586_setup_bufs: set up the buffers
- *
- * We have a block of KVA at sc->buf_area which is of size sc->buf_area_sz.
- * this is to be used for the buffers. The chip indexs its control data
- * structures with 16 bit offsets, and it indexes actual buffers with
- * 24 bit addresses. So we should allocate control buffers first so that
- * we don't overflow the 16 bit offset field. The number of transmit
- * buffers is fixed at compile time.
- *
- */
-static void
-i82586_setup_bufs(struct ie_softc *sc)
-{
- int ptr = sc->buf_area; /* memory pool */
- int n, r;
-
- /*
- * step 0: zero memory and figure out how many recv buffers and
- * frames we can have.
- */
- ptr = (ptr + 3) & ~3; /* set alignment and stick with it */
-
-
- /*
- * step 1: lay out data structures in the shared-memory area
- */
-
- /* The no-op commands; used if "nop-chaining" is in effect */
- sc->nop_cmds = ptr;
- ptr += NTXBUF * IE_CMD_NOP_SZ;
-
- /* The transmit commands */
- sc->xmit_cmds = ptr;
- ptr += NTXBUF * IE_CMD_XMIT_SZ;
-
- /* The transmit buffers descriptors */
- sc->xbds = ptr;
- ptr += NTXBUF * IE_XBD_SZ;
-
- /* The transmit buffers */
- sc->xbufs = ptr;
- ptr += NTXBUF * IE_TBUF_SIZE;
-
- ptr = (ptr + 3) & ~3; /* re-align.. just in case */
-
- /* Compute free space for RECV stuff */
- n = sc->buf_area_sz - (ptr - sc->buf_area);
-
- /* Compute size of one RECV frame */
- r = IE_RFRAME_SZ + ((IE_RBD_SZ + IE_RBUF_SIZE) * B_PER_F);
-
- sc->nframes = n / r;
-
- if (sc->nframes <= 0)
- panic("ie: bogus buffer calc\n");
-
- sc->nrxbuf = sc->nframes * B_PER_F;
-
- /* The receice frame descriptors */
- sc->rframes = ptr;
- ptr += sc->nframes * IE_RFRAME_SZ;
-
- /* The receive buffer descriptors */
- sc->rbds = ptr;
- ptr += sc->nrxbuf * IE_RBD_SZ;
-
- /* The receive buffers */
- sc->rbufs = ptr;
- ptr += sc->nrxbuf * IE_RBUF_SIZE;
-
-#if I82586_DEBUG
- printf("%s: %d frames %d bufs\n", sc->arpcom.ac_if.if_name, sc->nframes,
- sc->nrxbuf);
-#endif
-
- /*
- * step 2: link together the recv frames and set EOL on last one
- */
- for (n = 0; n < sc->nframes; n++) {
- int m = (n == sc->nframes - 1) ? 0 : n + 1;
-
- /* Clear status */
- sc->ie_bus_write16(sc, IE_RFRAME_STATUS(sc->rframes,n), 0);
-
- /* RBD link = NULL */
- sc->ie_bus_write16(sc, IE_RFRAME_BUFDESC(sc->rframes,n),
- 0xffff);
-
- /* Make a circular list */
- sc->ie_bus_write16(sc, IE_RFRAME_NEXT(sc->rframes,n),
- IE_RFRAME_ADDR(sc->rframes,m));
-
- /* Mark last as EOL */
- sc->ie_bus_write16(sc, IE_RFRAME_LAST(sc->rframes,n),
- ((m==0)? (IE_FD_EOL|IE_FD_SUSP) : 0));
- }
-
- /*
- * step 3: link the RBDs and set EOL on last one
- */
- for (n = 0; n < sc->nrxbuf; n++) {
- int m = (n == sc->nrxbuf - 1) ? 0 : n + 1;
-
- /* Clear status */
- sc->ie_bus_write16(sc, IE_RBD_STATUS(sc->rbds,n), 0);
-
- /* Make a circular list */
- sc->ie_bus_write16(sc, IE_RBD_NEXT(sc->rbds,n),
- IE_RBD_ADDR(sc->rbds,m));
-
- /* Link to data buffers */
- sc->ie_bus_write24(sc, IE_RBD_BUFADDR(sc->rbds, n),
- IE_RBUF_ADDR(sc, n));
- sc->ie_bus_write16(sc, IE_RBD_BUFLEN(sc->rbds,n),
- IE_RBUF_SIZE | ((m==0)?IE_RBD_EOL:0));
- }
-
- /*
- * step 4: all xmit no-op commands loopback onto themselves
- */
- for (n = 0; n < NTXBUF; n++) {
- sc->ie_bus_write16(sc, IE_CMD_NOP_STATUS(sc->nop_cmds, n), 0);
-
- sc->ie_bus_write16(sc, IE_CMD_NOP_CMD(sc->nop_cmds, n),
- IE_CMD_NOP);
-
- sc->ie_bus_write16(sc, IE_CMD_NOP_LINK(sc->nop_cmds, n),
- IE_CMD_NOP_ADDR(sc->nop_cmds, n));
- }
-
-
- /*
- * step 6: set the head and tail pointers on receive to keep track of
- * the order in which RFDs and RBDs are used.
- */
-
- /* Pointers to last packet sent and next available transmit buffer. */
- sc->xchead = sc->xctail = 0;
-
- /* Clear transmit-busy flag and set number of free transmit buffers. */
- sc->xmit_busy = 0;
-
- /*
- * Pointers to first and last receive frame.
- * The RFD pointed to by rftail is the only one that has EOL set.
- */
- sc->rfhead = 0;
- sc->rftail = sc->nframes - 1;
-
- /*
- * Pointers to first and last receive descriptor buffer.
- * The RBD pointed to by rbtail is the only one that has EOL set.
- */
- sc->rbhead = 0;
- sc->rbtail = sc->nrxbuf - 1;
-
-/* link in recv frames * and buffer into the scb. */
-#if I82586_DEBUG
- printf("%s: reserved %d bytes\n",
- sc->arpcom.ac_if.if_name, ptr - sc->buf_area);
-#endif
-}
-
-static int
-ie_cfg_setup(struct ie_softc *sc, int cmd, int promiscuous, int manchester)
-{
- int cmdresult, status;
- u_int8_t buf[IE_CMD_CFG_SZ]; /* XXX malloc? */
-
- *IE_CMD_CFG_CNT(buf) = 0x0c;
- *IE_CMD_CFG_FIFO(buf) = 8;
- *IE_CMD_CFG_SAVEBAD(buf) = 0x40;
- *IE_CMD_CFG_ADDRLEN(buf) = 0x2e;
- *IE_CMD_CFG_PRIORITY(buf) = 0;
- *IE_CMD_CFG_IFS(buf) = 0x60;
- *IE_CMD_CFG_SLOT_LOW(buf) = 0;
- *IE_CMD_CFG_SLOT_HIGH(buf) = 0xf2;
- *IE_CMD_CFG_PROMISC(buf) = (!!promiscuous) | (manchester << 2);
- *IE_CMD_CFG_CRSCDT(buf) = 0;
- *IE_CMD_CFG_MINLEN(buf) = 64;
- *IE_CMD_CFG_JUNK(buf) = 0xff;
- sc->memcopyout(sc, buf, cmd, IE_CMD_CFG_SZ);
- setup_simple_command(sc, IE_CMD_CONFIG, cmd);
- IE_BUS_BARRIER(sc, cmd, IE_CMD_CFG_SZ, BUS_SPACE_BARRIER_WRITE);
-
- cmdresult = i82586_start_cmd(sc, IE_CUC_START, cmd, IE_STAT_COMPL, 0);
- status = sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmd));
- if (cmdresult != 0) {
- printf("%s: configure command timed out; status %x\n",
- sc->arpcom.ac_if.if_name, status);
- return (0);
- }
- if ((status & IE_STAT_OK) == 0) {
- printf("%s: configure command failed; status %x\n",
- sc->arpcom.ac_if.if_name, status);
- return (0);
- }
-
- /* Squash any pending interrupts */
- ie_ack(sc, IE_ST_WHENCE);
- return (1);
-}
-
-static int
-ie_ia_setup(struct ie_softc *sc, int cmdbuf)
-{
- int cmdresult, status;
-
- setup_simple_command(sc, IE_CMD_IASETUP, cmdbuf);
-
- (sc->memcopyout)(sc, sc->arpcom.ac_enaddr,
- IE_CMD_IAS_EADDR(cmdbuf), ETHER_ADDR_LEN);
-
- cmdresult = i82586_start_cmd(sc, IE_CUC_START, cmdbuf, IE_STAT_COMPL, 0);
- status = sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmdbuf));
- if (cmdresult != 0) {
- printf("%s: individual address command timed out; status %x\n",
- sc->arpcom.ac_if.if_name, status);
- return (0);
- }
- if ((status & IE_STAT_OK) == 0) {
- printf("%s: individual address command failed; status %x\n",
- sc->arpcom.ac_if.if_name, status);
- return (0);
- }
-
- /* Squash any pending interrupts */
- ie_ack(sc, IE_ST_WHENCE);
- return (1);
-}
-
-/*
- * Run the multicast setup command.
- * Called at splnet().
- */
-static int
-ie_mc_setup(struct ie_softc *sc, int cmdbuf)
-{
- int cmdresult, status;
-
- if (sc->mcast_count == 0)
- return (1);
-
- setup_simple_command(sc, IE_CMD_MCAST, cmdbuf);
-
- (sc->memcopyout)(sc, (caddr_t)sc->mcast_addrs,
- IE_CMD_MCAST_MADDR(cmdbuf),
- sc->mcast_count * ETHER_ADDR_LEN);
-
- sc->ie_bus_write16(sc, IE_CMD_MCAST_BYTES(cmdbuf),
- sc->mcast_count * ETHER_ADDR_LEN);
-
- /* Start the command */
- cmdresult = i82586_start_cmd(sc, IE_CUC_START, cmdbuf, IE_STAT_COMPL, 0);
- status = sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmdbuf));
- if (cmdresult != 0) {
- printf("%s: multicast setup command timed out; status %x\n",
- sc->arpcom.ac_if.if_name, status);
- return (0);
- }
- if ((status & IE_STAT_OK) == 0) {
- printf("%s: multicast setup command failed; status %x\n",
- sc->arpcom.ac_if.if_name, status);
- return (0);
- }
-
- /* Squash any pending interrupts */
- ie_ack(sc, IE_ST_WHENCE);
- return (1);
-}
-
-/*
- * This routine takes the environment generated by check_ie_present() and adds
- * to it all the other structures we need to operate the adapter. This
- * includes executing the CONFIGURE, IA-SETUP, and MC-SETUP commands, starting
- * the receiver unit, and clearing interrupts.
- *
- * THIS ROUTINE MUST BE CALLED AT splnet() OR HIGHER.
- */
-void
-i82586_init(void *arg)
-{
- struct ie_softc *sc = arg;
- struct ifnet *ifp = &sc->arpcom.ac_if;
- int cmd;
-
- sc->async_cmd_inprogress = 0;
- sc->xmit_busy = 0;
-
-#if I82586_DEBUG
- memset(sc->trace_flow, 0, sizeof(sc->trace_flow));
- sc->trace_flow_wrap = 0;
-#endif
- sc->trace_flow_in = 0;
-
- cmd = sc->buf_area;
-
-#if I82586_DEBUG
- printf ("%s: sc_debug at 0x%08x\n", sc->arpcom.ac_if.if_name, (unsigned int) &sc->sc_debug);
-#endif
-
- /*
- * Send the configure command first.
- */
- if (ie_cfg_setup(sc, cmd, sc->promisc, 0) == 0)
- return;
-
- /*
- * Send the Individual Address Setup command.
- */
- if (ie_ia_setup(sc, cmd) == 0)
- return;
-
- /*
- * Run the time-domain reflectometer.
- */
- ie_run_tdr(sc, cmd);
-
- /*
- * Set the multi-cast filter, if any
- */
- if (ie_mc_setup(sc, cmd) == 0)
- return;
-
- /*
- * If no tasks exist, create them. Need to add something to allow
- * different names for the different devices.
- */
- if (sc->intr_task == 0)
- sc->intr_task = rtems_bsdnet_newproc ("IEi0", 2048, i82586_intr_task, sc);
- if (sc->tx_task == 0)
- sc->tx_task = rtems_bsdnet_newproc ("IEt0", 2048, i82586_tx_task, sc);
-
-
- /*
- * Acknowledge any interrupts we have generated thus far.
- */
- ie_ack(sc, IE_ST_WHENCE);
-
- /*
- * Set up the transmit and recv buffers.
- */
- i82586_setup_bufs(sc);
-
- if (sc->hwinit)
- (sc->hwinit)(sc);
-
- ifp->if_flags |= IFF_RUNNING;
- ifp->if_flags &= ~IFF_OACTIVE;
-
- if (NTXBUF < 2)
- sc->do_xmitnopchain = 0;
-
- i82586_start_transceiver(sc);
-}
-
-/*
- * Start the RU and possibly the CU unit
- */
-static void
-i82586_start_transceiver(struct ie_softc *sc)
-{
-#if I82586_DEBUG
- I82586_TRACE(sc, I82586_RX_START, 0);
-#endif
-
- /*
- * Start RU at current position in frame & RBD lists.
- */
- sc->ie_bus_write16(sc, IE_RFRAME_BUFDESC(sc->rframes,sc->rfhead),
- IE_RBD_ADDR(sc->rbds, sc->rbhead));
-
- sc->ie_bus_write16(sc, IE_SCB_RCVLST(sc->scb),
- IE_RFRAME_ADDR(sc->rframes,sc->rfhead));
-
- if (sc->do_xmitnopchain) {
- /* Stop transmit command chain */
- if (i82586_start_cmd(sc, IE_CUC_SUSPEND|IE_RUC_SUSPEND, 0, 0, 0))
- printf("%s: CU/RU stop command timed out\n",
- sc->arpcom.ac_if.if_name);
-
- /* Start the receiver & transmitter chain */
- /* sc->scb->ie_command_list =
- IEADDR(sc->nop_cmds[(sc->xctail+NTXBUF-1) % NTXBUF]);*/
- sc->ie_bus_write16(sc, IE_SCB_CMDLST(sc->scb),
- IE_CMD_NOP_ADDR(
- sc->nop_cmds,
- (sc->xctail + NTXBUF - 1) % NTXBUF));
-
- if (i82586_start_cmd(sc, IE_CUC_START|IE_RUC_START, 0, 0, 0))
- printf("%s: CU/RU command timed out\n",
- sc->arpcom.ac_if.if_name);
- } else {
- if (i82586_start_cmd(sc, IE_RUC_START, 0, 0, 0))
- printf("%s: RU command timed out\n",
- sc->arpcom.ac_if.if_name);
- }
-}
-
-void
-i82586_stop(struct ifnet *ifp, int disable)
-{
- struct ie_softc *sc = ifp->if_softc;
-
- if (i82586_start_cmd(sc, IE_RUC_SUSPEND | IE_CUC_SUSPEND, 0, 0, 0))
- printf("%s: iestop: disable commands timed out\n",
- sc->arpcom.ac_if.if_name);
-}
-
-int
-i82586_ioctl(struct ifnet *ifp, ioctl_command_t cmd, caddr_t data)
-{
- struct ie_softc *sc = ifp->if_softc;
-/* struct ifreq *ifr = (struct ifreq *)data; */
- int s;
- int error = 0;
-
- s = splnet();
- switch(cmd) {
- case SIOCGIFMEDIA:
- case SIOCSIFMEDIA:
- break;
- case SIO_RTEMS_SHOW_STATS:
-#if I82586_DEBUG
- print_softie(sc);
-#endif
- break;
- default:
- error = ether_ioctl(ifp, cmd, data);
- if (error == ENETRESET) {
- /*
- * Multicast list has changed; set the hardware filter
- * accordingly.
- */
- ie_mc_reset(sc);
- error = 0;
- }
- break;
- }
-#if I82586_DEBUG
- if (cmd == SIOCSIFFLAGS)
- sc->sc_debug = (ifp->if_flags & IFF_DEBUG) ? IED_ALL : 0;
-#endif
- splx(s);
- return (error);
-}
-
-static void
-ie_mc_reset(struct ie_softc *sc)
-{
- struct ether_multi *enm;
- struct ether_multistep step;
- int size;
-
- /*
- * Step through the list of addresses.
- */
- again:
- size = 0;
- sc->mcast_count = 0;
- ETHER_FIRST_MULTI(step, &sc->arpcom, enm);
- while (enm) {
- size += 6;
- if (sc->mcast_count >= IE_MAXMCAST ||
- memcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
- sc->arpcom.ac_if.if_flags |= IFF_ALLMULTI;
- i82586_ioctl(&sc->arpcom.ac_if,
- SIOCSIFFLAGS, (void *)0);
- return;
- }
- ETHER_NEXT_MULTI(step, enm);
- }
-
- if (size > sc->mcast_addrs_size) {
- /* Need to allocate more space */
- if (sc->mcast_addrs_size)
- free(sc->mcast_addrs, M_IPMADDR);
- sc->mcast_addrs = (char *)
- malloc(size, M_IPMADDR, M_WAITOK);
- sc->mcast_addrs_size = size;
- }
-
- /*
- * We've got the space; now copy the addresses
- */
- ETHER_FIRST_MULTI(step, &sc->arpcom, enm);
- while (enm) {
- if (sc->mcast_count >= IE_MAXMCAST)
- goto again; /* Just in case */
-
- memcpy(&sc->mcast_addrs[sc->mcast_count], enm->enm_addrlo, 6);
- sc->mcast_count++;
- ETHER_NEXT_MULTI(step, enm);
- }
- sc->want_mcsetup = 1;
-}
-
-/*
- * Media change callback.
- */
-int
-i82586_mediachange(struct ifnet *ifp)
-{
- struct ie_softc *sc = ifp->if_softc;
-
- if (sc->sc_mediachange)
- return ((*sc->sc_mediachange)(sc));
- return (0);
-}
-
-/*
- * Media status callback.
- */
-void
-i82586_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
-{
- struct ie_softc *sc = ifp->if_softc;
-
- if (sc->sc_mediastatus)
- (*sc->sc_mediastatus)(sc, ifmr);
-}
-
-#if I82586_DEBUG
-static void
-print_softie(struct ie_softc *sc)
-{
- static char *trace_labels[] = {
- "INTS_REQ",
- "INTS_IN",
- "INTS_LOOPS",
- "INTS_OUT",
- "RX_INT",
- "RX_DROP",
- "RX_ERR",
- "RX_OK",
- "RX_START",
- "START_TX",
- "TX_START",
- "TX_INT",
- "TX_REQ",
- "TX_EVT",
- "TX_EMIT",
- "TX_BAD",
- "TX_ACTIVE",
- "TRACE_CNT"
- };
-
- int i;
-
- printf("i82586 %s:\n", sc->arpcom.ac_if.if_name);
-
- printf(" iobase=%p\n", sc->sc_iobase);
-
- printf(" scp=0x%08x\t\tiscp=0x%08x\t\tscb=0x%08x\n",
- sc->scp, sc->iscp, sc->scb);
- printf(" buf_area=0x%08x\tbuf_area_sz=0x%08x\n",
- sc->buf_area, sc->buf_area_sz);
- printf(" rframes=0x%08x\trbds=0x%08x\t\trbufs=0x%08x\n",
- sc->rframes, sc->rbds, sc->rbufs);
- printf(" nop_cmds=0x%08x\txmit_cmds=0x%08x\n",
- sc->nop_cmds, sc->xmit_cmds);
- printf(" xbds=0x%08x\txbufs=0x%08x\n\n",
- sc->xbds, sc->xbufs);
- printf(" rfhead=%d\trftail=%d\n",
- sc->rfhead, sc->rftail);
- printf(" rbhead=%d\trbtail=%d\n",
- sc->rbhead, sc->rbtail);
- printf(" nframes=%d\tnrxbuf=%d\trnr_expect=%d\n",
- sc->nframes, sc->nrxbuf, sc->rnr_expect);
- printf(" xchead=%d\txctail=%d\n",
- sc->xchead, sc->xctail);
- printf(" xmit_busy=%d\txmit_req=%d\tdo_xmitnopchain=%d\n",
- sc->xmit_busy, sc->xmit_req, sc->do_xmitnopchain);
- printf(" promisc=%d\tasync_cmd_inprogress=%d\n\n",
- sc->promisc, sc->async_cmd_inprogress);
-
- {
- int cnt;
- int in;
- int lfdone = 0;
- char *tabs;
-
- if (!sc->trace_flow_wrap) {
- cnt = sc->trace_flow_in;
- in = 0;
- }
- else {
- cnt = I82586_TRACE_FLOW;
- in = sc->trace_flow_in;
- }
-
- sc->trace_flow_in = sc->trace_flow_wrap = 0;
-
- cnt /= 2;
-
- for (i = 0; i < cnt; i++) {
- if (!lfdone) {
- switch (sc->trace_flow[in]) {
- case I82586_INTS_REQ:
- case I82586_INTS_IN:
- printf("\n");
- }
- }
-
- lfdone = 0;
-
- if (strlen(trace_labels[sc->trace_flow[in]]) < 8)
- tabs = "\t\t";
- else
- tabs = "\t";
-
- printf(" %d\t%s%s0x%08x (%d)\n",
- i, trace_labels[sc->trace_flow[in]], tabs,
- sc->trace_flow[in + 1], sc->trace_flow[in + 1]);
-
- switch (sc->trace_flow[in]) {
- case I82586_INTS_REQ:
- case I82586_INTS_OUT:
- lfdone = 1;
- printf("\n");
- }
-
- in += 2;
-
- if (in >= I82586_TRACE_FLOW)
- in = 0;
- }
- }
-}
-
-static void
-print_rbd(struct ie_softc *sc, int n)
-{
- printf("RBD at %08x:\n status %04x, next %04x, buffer %lx\n"
- "length/EOL %04x\n", IE_RBD_ADDR(sc->rbds,n),
- sc->ie_bus_read16(sc, IE_RBD_STATUS(sc->rbds,n)),
- sc->ie_bus_read16(sc, IE_RBD_NEXT(sc->rbds,n)),
- (u_long)0,/*bus_space_read_4(sc->bt, sc->bh, IE_RBD_BUFADDR(sc->rbds,n)),-* XXX */
- sc->ie_bus_read16(sc, IE_RBD_BUFLEN(sc->rbds,n)));
-}
-
-#endif