The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/i82586.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: i82586.c,v 1.48 2003/11/02 11:07:45 wiz Exp $  */
    2 
    3 /*-
    4  * Copyright (c) 1998 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Paul Kranenburg and Charles M. Hannum.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *        This product includes software developed by the NetBSD
   21  *        Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*-
   40  * Copyright (c) 1997 Paul Kranenburg.
   41  * Copyright (c) 1992, 1993, University of Vermont and State
   42  *  Agricultural College.
   43  * Copyright (c) 1992, 1993, Garrett A. Wollman.
   44  *
   45  * Portions:
   46  * Copyright (c) 1994, 1995, Rafal K. Boni
   47  * Copyright (c) 1990, 1991, William F. Jolitz
   48  * Copyright (c) 1990, The Regents of the University of California
   49  *
   50  * All rights reserved.
   51  *
   52  * Redistribution and use in source and binary forms, with or without
   53  * modification, are permitted provided that the following conditions
   54  * are met:
   55  * 1. Redistributions of source code must retain the above copyright
   56  *    notice, this list of conditions and the following disclaimer.
   57  * 2. Redistributions in binary form must reproduce the above copyright
   58  *    notice, this list of conditions and the following disclaimer in the
   59  *    documentation and/or other materials provided with the distribution.
   60  * 3. All advertising materials mentioning features or use of this software
   61  *    must display the following acknowledgement:
   62  *      This product includes software developed by the University of Vermont
   63  *      and State Agricultural College and Garrett A. Wollman, by William F.
   64  *      Jolitz, and by the University of California, Berkeley, Lawrence
   65  *      Berkeley Laboratory, and its contributors.
   66  * 4. Neither the names of the Universities nor the names of the authors
   67  *    may be used to endorse or promote products derived from this software
   68  *    without specific prior written permission.
   69  *
   70  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   71  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   72  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   73  * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR AUTHORS BE LIABLE
   74  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   75  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   76  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   77  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   78  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   79  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   80  * SUCH DAMAGE.
   81  */
   82 
   83 /*
   84  * Intel 82586 Ethernet chip
   85  * Register, bit, and structure definitions.
   86  *
   87  * Original StarLAN driver written by Garrett Wollman with reference to the
   88  * Clarkson Packet Driver code for this chip written by Russ Nelson and others.
   89  *
   90  * BPF support code taken from hpdev/if_le.c, supplied with tcpdump.
   91  *
   92  * 3C507 support is loosely based on code donated to NetBSD by Rafal Boni.
   93  *
   94  * Majorly cleaned up and 3C507 code merged by Charles Hannum.
   95  *
   96  * Converted to SUN ie driver by Charles D. Cranor,
   97  *              October 1994, January 1995.
   98  * This sun version based on i386 version 1.30.
   99  */
  100 
  101 /*
  102  * The i82586 is a very painful chip, found in sun3's, sun-4/100's
  103  * sun-4/200's, and VME based suns.  The byte order is all wrong for a
  104  * SUN, making life difficult.  Programming this chip is mostly the same,
  105  * but certain details differ from system to system.  This driver is
  106  * written so that different "ie" interfaces can be controled by the same
  107  * driver.
  108  */
  109 
  110 /*
  111 Mode of operation:
  112 
  113    We run the 82586 in a standard Ethernet mode.  We keep NFRAMES
  114    received frame descriptors around for the receiver to use, and
  115    NRXBUF associated receive buffer descriptors, both in a circular
  116    list.  Whenever a frame is received, we rotate both lists as
  117    necessary.  (The 586 treats both lists as a simple queue.)  We also
  118    keep a transmit command around so that packets can be sent off
  119    quickly.
  120 
  121    We configure the adapter in AL-LOC = 1 mode, which means that the
  122    Ethernet/802.3 MAC header is placed at the beginning of the receive
  123    buffer rather than being split off into various fields in the RFD.
  124    This also means that we must include this header in the transmit
  125    buffer as well.
  126 
  127    By convention, all transmit commands, and only transmit commands,
  128    shall have the I (IE_CMD_INTR) bit set in the command.  This way,
  129    when an interrupt arrives at i82586_intr(), it is immediately possible
  130    to tell what precisely caused it.  ANY OTHER command-sending
  131    routines should run at splnet(), and should post an acknowledgement
  132    to every interrupt they generate.
  133 
  134    To save the expense of shipping a command to 82586 every time we
  135    want to send a frame, we use a linked list of commands consisting
  136    of alternate XMIT and NOP commands. The links of these elements
  137    are manipulated (in iexmit()) such that the NOP command loops back
  138    to itself whenever the following XMIT command is not yet ready to
  139    go. Whenever an XMIT is ready, the preceding NOP link is pointed
  140    at it, while its own link field points to the following NOP command.
  141    Thus, a single transmit command sets off an interlocked traversal
  142    of the xmit command chain, with the host processor in control of
  143    the synchronization.
  144 */
  145 
  146 #include <sys/cdefs.h>
  147 __KERNEL_RCSID(0, "$NetBSD: i82586.c,v 1.48 2003/11/02 11:07:45 wiz Exp $");
  148 
  149 #include "bpfilter.h"
  150 
  151 #include <sys/param.h>
  152 #include <sys/systm.h>
  153 #include <sys/mbuf.h>
  154 #include <sys/socket.h>
  155 #include <sys/ioctl.h>
  156 #include <sys/errno.h>
  157 #include <sys/syslog.h>
  158 #include <sys/device.h>
  159 
  160 #include <net/if.h>
  161 #include <net/if_dl.h>
  162 #include <net/if_types.h>
  163 #include <net/if_media.h>
  164 #include <net/if_ether.h>
  165 
  166 #if NBPFILTER > 0
  167 #include <net/bpf.h>
  168 #include <net/bpfdesc.h>
  169 #endif
  170 
  171 #include <machine/bus.h>
  172 
  173 #include <dev/ic/i82586reg.h>
  174 #include <dev/ic/i82586var.h>
  175 
  176 void            i82586_reset    __P((struct ie_softc *, int));
  177 void            i82586_watchdog __P((struct ifnet *));
  178 int             i82586_init     __P((struct ifnet *));
  179 int             i82586_ioctl    __P((struct ifnet *, u_long, caddr_t));
  180 void            i82586_start    __P((struct ifnet *));
  181 void            i82586_stop     __P((struct ifnet *, int));
  182 
  183 
  184 int             i82586_rint     __P((struct ie_softc *, int));
  185 int             i82586_tint     __P((struct ie_softc *, int));
  186 
  187 int             i82586_mediachange      __P((struct ifnet *));
  188 void            i82586_mediastatus      __P((struct ifnet *,
  189                                                 struct ifmediareq *));
  190 
  191 static int      ie_readframe            __P((struct ie_softc *, int));
  192 static struct mbuf *ieget               __P((struct ie_softc *, int, int));
  193 static int      i82586_get_rbd_list     __P((struct ie_softc *,
  194                                              u_int16_t *, u_int16_t *, int *));
  195 static void     i82586_release_rbd_list __P((struct ie_softc *,
  196                                              u_int16_t, u_int16_t));
  197 static int      i82586_drop_frames      __P((struct ie_softc *));
  198 static int      i82586_chk_rx_ring      __P((struct ie_softc *));
  199 
  200 static __inline__ void  ie_ack          __P((struct ie_softc *, u_int));
  201 static __inline__ void  iexmit          __P((struct ie_softc *));
  202 static void             i82586_start_transceiver
  203                                         __P((struct ie_softc *));
  204 
  205 static void     i82586_count_errors     __P((struct ie_softc *));
  206 static void     i82586_rx_errors        __P((struct ie_softc *, int, int));
  207 static void     i82586_setup_bufs       __P((struct ie_softc *));
  208 static void     setup_simple_command    __P((struct ie_softc *, int, int));
  209 static int      ie_cfg_setup            __P((struct ie_softc *, int, int, int));
  210 static int      ie_ia_setup             __P((struct ie_softc *, int));
  211 static void     ie_run_tdr              __P((struct ie_softc *, int));
  212 static int      ie_mc_setup             __P((struct ie_softc *, int));
  213 static void     ie_mc_reset             __P((struct ie_softc *));
  214 static int      i82586_start_cmd        __P((struct ie_softc *,
  215                                             int, int, int, int));
  216 static int      i82586_cmd_wait         __P((struct ie_softc *));
  217 
  218 #if I82586_DEBUG
  219 void            print_rbd       __P((struct ie_softc *, int));
  220 #endif
  221 
  222 static char* padbuf = NULL;
  223 
  224 /*
  225  * Front-ends call this function to attach to the MI driver.
  226  *
  227  * The front-end has responsibility for managing the ICP and ISCP
  228  * structures. Both of these are opaque to us.  Also, the front-end
  229  * chooses a location for the SCB which is expected to be addressable
  230  * (through `sc->scb') as an offset against the shared-memory bus handle.
  231  *
  232  * The following MD interface function must be setup by the front-end
  233  * before calling here:
  234  *
  235  *      hwreset                 - board dependent reset
  236  *      hwinit                  - board dependent initialization
  237  *      chan_attn               - channel attention
  238  *      intrhook                - board dependent interrupt processing
  239  *      memcopyin               - shared memory copy: board to KVA
  240  *      memcopyout              - shared memory copy: KVA to board
  241  *      ie_bus_read16           - read a sixteen-bit i82586 pointer
  242  *      ie_bus_write16          - write a sixteen-bit i82586 pointer
  243  *      ie_bus_write24          - write a twenty-four-bit i82586 pointer
  244  *
  245  */
  246 void
  247 i82586_attach(sc, name, etheraddr, media, nmedia, defmedia)
  248         struct ie_softc *sc;
  249         char *name;
  250         u_int8_t *etheraddr;
  251         int *media, nmedia, defmedia;
  252 {
  253         int i;
  254         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  255 
  256         strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
  257         ifp->if_softc = sc;
  258         ifp->if_start = i82586_start;
  259         ifp->if_ioctl = i82586_ioctl;
  260         ifp->if_init = i82586_init;
  261         ifp->if_stop = i82586_stop;
  262         ifp->if_watchdog = i82586_watchdog;
  263         ifp->if_flags =
  264                 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
  265         IFQ_SET_READY(&ifp->if_snd);
  266 
  267         /* Initialize media goo. */
  268         ifmedia_init(&sc->sc_media, 0, i82586_mediachange, i82586_mediastatus);
  269         if (media != NULL) {
  270                 for (i = 0; i < nmedia; i++)
  271                         ifmedia_add(&sc->sc_media, media[i], 0, NULL);
  272                 ifmedia_set(&sc->sc_media, defmedia);
  273         } else {
  274                 ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
  275                 ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);
  276         }
  277 
  278         if (padbuf == NULL) {
  279                 padbuf = malloc(ETHER_MIN_LEN - ETHER_CRC_LEN, M_DEVBUF,
  280                     M_ZERO | M_NOWAIT);
  281                 if (padbuf == NULL) {
  282                          printf("%s: can't allocate pad buffer\n",
  283                              sc->sc_dev.dv_xname);
  284                          return;
  285                 }
  286         }
  287 
  288         /* Attach the interface. */
  289         if_attach(ifp);
  290         ether_ifattach(ifp, etheraddr);
  291 
  292         printf(" address %s, type %s\n", ether_sprintf(etheraddr), name);
  293 }
  294 
  295 
  296 /*
  297  * Device timeout/watchdog routine.
  298  * Entered if the device neglects to generate an interrupt after a
  299  * transmit has been started on it.
  300  */
  301 void
  302 i82586_watchdog(ifp)
  303         struct ifnet *ifp;
  304 {
  305         struct ie_softc *sc = ifp->if_softc;
  306 
  307         log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
  308         ++ifp->if_oerrors;
  309 
  310         i82586_reset(sc, 1);
  311 }
  312 
  313 static int
  314 i82586_cmd_wait(sc)
  315         struct ie_softc *sc;
  316 {
  317         /* spin on i82586 command acknowledge; wait at most 0.9 (!) seconds */
  318         int i, off;
  319         u_int16_t cmd;
  320 
  321         for (i = 0; i < 900000; i++) {
  322                 /* Read the command word */
  323                 off = IE_SCB_CMD(sc->scb);
  324 
  325                 IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ);
  326                 if ((cmd = sc->ie_bus_read16(sc, off)) == 0)
  327                         return (0);
  328                 delay(1);
  329         }
  330 
  331         off = IE_SCB_STATUS(sc->scb);
  332         printf("i82586_cmd_wait: timo(%ssync): scb status: 0x%x, cmd: 0x%x\n",
  333                 sc->async_cmd_inprogress?"a":"", 
  334                 sc->ie_bus_read16(sc, off), cmd);
  335 
  336         return (1);     /* Timeout */
  337 }
  338 
  339 /*
  340  * Send a command to the controller and wait for it to either complete
  341  * or be accepted, depending on the command.  If the command pointer
  342  * is null, then pretend that the command is not an action command.
  343  * If the command pointer is not null, and the command is an action
  344  * command, wait for one of the MASK bits to turn on in the command's
  345  * status field.
  346  * If ASYNC is set, we just call the chip's attention and return.
  347  * We may have to wait for the command's acceptance later though.
  348  */
  349 static int
  350 i82586_start_cmd(sc, cmd, iecmdbuf, mask, async)
  351         struct ie_softc *sc;
  352         int cmd;
  353         int iecmdbuf;
  354         int mask;
  355         int async;
  356 {
  357         int i;
  358         int off;
  359 
  360         if (sc->async_cmd_inprogress != 0) {
  361                 /*
  362                  * If previous command was issued asynchronously, wait
  363                  * for it now.
  364                  */
  365                 if (i82586_cmd_wait(sc) != 0)
  366                         return (1);
  367                 sc->async_cmd_inprogress = 0;
  368         }
  369 
  370         off = IE_SCB_CMD(sc->scb);
  371         sc->ie_bus_write16(sc, off, cmd);
  372         IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_WRITE);
  373         (sc->chan_attn)(sc, CARD_RESET);
  374 
  375         if (async != 0) {
  376                 sc->async_cmd_inprogress = 1;
  377                 return (0);
  378         }
  379 
  380         if (IE_ACTION_COMMAND(cmd) && iecmdbuf) {
  381                 int status;
  382                 /*
  383                  * Now spin-lock waiting for status.  This is not a very nice
  384                  * thing to do, and can kill performance pretty well...
  385                  * According to the packet driver, the minimum timeout
  386                  * should be .369 seconds.
  387                  */
  388                 for (i = 0; i < 369000; i++) {
  389                         /* Read the command status */
  390                         off = IE_CMD_COMMON_STATUS(iecmdbuf);
  391                         IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ);
  392                         status = sc->ie_bus_read16(sc, off);
  393                         if (status & mask)
  394                                 return (0);
  395                         delay(1);
  396                 }
  397 
  398         } else {
  399                 /*
  400                  * Otherwise, just wait for the command to be accepted.
  401                  */
  402                 return (i82586_cmd_wait(sc));
  403         }
  404 
  405         /* Timeout */
  406         return (1);
  407 }
  408 
  409 /*
  410  * Interrupt Acknowledge.
  411  */
  412 static __inline__ void
  413 ie_ack(sc, mask)
  414         struct ie_softc *sc;
  415         u_int mask;     /* in native byte-order */
  416 {
  417         u_int status;
  418 
  419         IE_BUS_BARRIER(sc, 0, 0, BUS_SPACE_BARRIER_READ);
  420         status = sc->ie_bus_read16(sc, IE_SCB_STATUS(sc->scb));
  421         i82586_start_cmd(sc, status & mask, 0, 0, 0);
  422         if (sc->intrhook)
  423                 sc->intrhook(sc, INTR_ACK);
  424 }
  425 
  426 /*
  427  * Transfer accumulated chip error counters to IF.
  428  */
  429 static __inline void
  430 i82586_count_errors(sc)
  431         struct ie_softc *sc;
  432 {
  433         int scb = sc->scb;
  434 
  435         sc->sc_ethercom.ec_if.if_ierrors +=
  436             sc->ie_bus_read16(sc, IE_SCB_ERRCRC(scb)) +
  437             sc->ie_bus_read16(sc, IE_SCB_ERRALN(scb)) +
  438             sc->ie_bus_read16(sc, IE_SCB_ERRRES(scb)) +
  439             sc->ie_bus_read16(sc, IE_SCB_ERROVR(scb));
  440 
  441         /* Clear error counters */
  442         sc->ie_bus_write16(sc, IE_SCB_ERRCRC(scb), 0);
  443         sc->ie_bus_write16(sc, IE_SCB_ERRALN(scb), 0);
  444         sc->ie_bus_write16(sc, IE_SCB_ERRRES(scb), 0);
  445         sc->ie_bus_write16(sc, IE_SCB_ERROVR(scb), 0);
  446 }
  447 
  448 static void
  449 i82586_rx_errors(sc, fn, status)
  450         struct ie_softc *sc;
  451         int fn;
  452         int status;
  453 {
  454         char bits[128];
  455 
  456         log(LOG_ERR, "%s: rx error (frame# %d): %s\n", sc->sc_dev.dv_xname, fn,
  457             bitmask_snprintf(status, IE_FD_STATUSBITS, bits, sizeof(bits)));
  458 }
  459 
  460 /*
  461  * i82586 interrupt entry point.
  462  */
  463 int
  464 i82586_intr(v)
  465         void *v;
  466 {
  467         struct ie_softc *sc = v;
  468         u_int status;
  469         int off;
  470 
  471         /*
  472          * Implementation dependent interrupt handling.
  473          */
  474         if (sc->intrhook)
  475                 (sc->intrhook)(sc, INTR_ENTER);
  476 
  477         off = IE_SCB_STATUS(sc->scb);
  478         IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ);
  479         status = sc->ie_bus_read16(sc, off) & IE_ST_WHENCE;
  480 
  481         if ((status & IE_ST_WHENCE) == 0) {
  482                 if (sc->intrhook)
  483                         (sc->intrhook)(sc, INTR_EXIT);
  484 
  485                 return (0);
  486         }
  487 
  488 loop:
  489         /* Ack interrupts FIRST in case we receive more during the ISR. */
  490 #if 0
  491         ie_ack(sc, status & IE_ST_WHENCE);
  492 #endif
  493         i82586_start_cmd(sc, status & IE_ST_WHENCE, 0, 0, 1);
  494 
  495         if (status & (IE_ST_FR | IE_ST_RNR))
  496                 if (i82586_rint(sc, status) != 0)
  497                         goto reset;
  498 
  499         if (status & IE_ST_CX)
  500                 if (i82586_tint(sc, status) != 0)
  501                         goto reset;
  502 
  503 #if I82586_DEBUG
  504         if ((status & IE_ST_CNA) && (sc->sc_debug & IED_CNA))
  505                 printf("%s: cna; status=0x%x\n", sc->sc_dev.dv_xname, status);
  506 #endif
  507         if (sc->intrhook)
  508                 (sc->intrhook)(sc, INTR_LOOP);
  509 
  510         /*
  511          * Interrupt ACK was posted asynchronously; wait for
  512          * completion here before reading SCB status again.
  513          * 
  514          * If ACK fails, try to reset the chip, in hopes that
  515          * it helps.
  516          */
  517         if (i82586_cmd_wait(sc) != 0)
  518                 goto reset;
  519 
  520         IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ);
  521         status = sc->ie_bus_read16(sc, off);
  522         if ((status & IE_ST_WHENCE) != 0)
  523                 goto loop;
  524 
  525 out:
  526         if (sc->intrhook)
  527                 (sc->intrhook)(sc, INTR_EXIT);
  528         return (1);
  529 
  530 reset:
  531         i82586_cmd_wait(sc);
  532         i82586_reset(sc, 1);
  533         goto out;
  534 
  535 }
  536 
  537 /*
  538  * Process a received-frame interrupt.
  539  */
  540 int
  541 i82586_rint(sc, scbstatus)
  542         struct  ie_softc *sc;
  543         int     scbstatus;
  544 {
  545 static  int timesthru = 1024;
  546         int i, status, off;
  547 
  548 #if I82586_DEBUG
  549         if (sc->sc_debug & IED_RINT)
  550                 printf("%s: rint: status 0x%x\n",
  551                         sc->sc_dev.dv_xname, scbstatus);
  552 #endif
  553 
  554         for (;;) {
  555                 int drop = 0;
  556 
  557                 i = sc->rfhead;
  558                 off = IE_RFRAME_STATUS(sc->rframes, i);
  559                 IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ);
  560                 status = sc->ie_bus_read16(sc, off);
  561 
  562 #if I82586_DEBUG
  563                 if (sc->sc_debug & IED_RINT)
  564                         printf("%s: rint: frame(%d) status 0x%x\n",
  565                                 sc->sc_dev.dv_xname, i, status);
  566 #endif
  567                 if ((status & IE_FD_COMPLETE) == 0) {
  568                         if ((status & IE_FD_OK) != 0) {
  569                                 printf("%s: rint: weird: ",
  570                                         sc->sc_dev.dv_xname);
  571                                 i82586_rx_errors(sc, i, status);
  572                                 break;
  573                         }
  574                         if (--timesthru == 0) {
  575                                 /* Account the accumulated errors */
  576                                 i82586_count_errors(sc);
  577                                 timesthru = 1024;
  578                         }
  579                         break;
  580                 } else if ((status & IE_FD_OK) == 0) {
  581                         /*
  582                          * If the chip is configured to automatically
  583                          * discard bad frames, the only reason we can
  584                          * get here is an "out-of-resource" condition.
  585                          */
  586                         i82586_rx_errors(sc, i, status);
  587                         drop = 1;
  588                 }
  589 
  590 #if I82586_DEBUG
  591                 if ((status & IE_FD_BUSY) != 0)
  592                         printf("%s: rint: frame(%d) busy; status=0x%x\n",
  593                                 sc->sc_dev.dv_xname, i, status);
  594 #endif
  595 
  596 
  597                 /*
  598                  * Advance the RFD list, since we're done with
  599                  * this descriptor.
  600                  */
  601 
  602                 /* Clear frame status */
  603                 sc->ie_bus_write16(sc, off, 0);
  604 
  605                 /* Put fence at this frame (the head) */
  606                 off = IE_RFRAME_LAST(sc->rframes, i);
  607                 sc->ie_bus_write16(sc, off, IE_FD_EOL|IE_FD_SUSP);
  608 
  609                 /* and clear RBD field */
  610                 off = IE_RFRAME_BUFDESC(sc->rframes, i);
  611                 sc->ie_bus_write16(sc, off, 0xffff);
  612 
  613                 /* Remove fence from current tail */
  614                 off = IE_RFRAME_LAST(sc->rframes, sc->rftail);
  615                 sc->ie_bus_write16(sc, off, 0);
  616 
  617                 if (++sc->rftail == sc->nframes)
  618                         sc->rftail = 0;
  619                 if (++sc->rfhead == sc->nframes)
  620                         sc->rfhead = 0;
  621 
  622                 /* Pull the frame off the board */
  623                 if (drop) {
  624                         i82586_drop_frames(sc);
  625                         if ((status & IE_FD_RNR) != 0)
  626                                 sc->rnr_expect = 1;
  627                         sc->sc_ethercom.ec_if.if_ierrors++;
  628                 } else if (ie_readframe(sc, i) != 0)
  629                         return (1);
  630         }
  631 
  632         if ((scbstatus & IE_ST_RNR) != 0) {
  633 
  634                 /*
  635                  * Receiver went "Not Ready". We try to figure out
  636                  * whether this was an expected event based on past
  637                  * frame status values.
  638                  */
  639 
  640                 if ((scbstatus & IE_RUS_SUSPEND) != 0) {
  641                         /*
  642                          * We use the "suspend on last frame" flag.
  643                          * Send a RU RESUME command in response, since
  644                          * we should have dealt with all completed frames
  645                          * by now.
  646                          */
  647                         printf("RINT: SUSPENDED; scbstatus=0x%x\n",
  648                                 scbstatus);
  649                         if (i82586_start_cmd(sc, IE_RUC_RESUME, 0, 0, 0) == 0)
  650                                 return (0);
  651                         printf("%s: RU RESUME command timed out\n",
  652                                 sc->sc_dev.dv_xname);
  653                         return (1);     /* Ask for a reset */
  654                 }
  655 
  656                 if (sc->rnr_expect != 0) {
  657                         /*
  658                          * The RNR condition was announced in the previously
  659                          * completed frame.  Assume the receive ring is Ok,
  660                          * so restart the receiver without further delay.
  661                          */
  662                         i82586_start_transceiver(sc);
  663                         sc->rnr_expect = 0;
  664                         return (0);
  665 
  666                 } else if ((scbstatus & IE_RUS_NOSPACE) != 0) {
  667                         /*
  668                          * We saw no previous IF_FD_RNR flag.
  669                          * We check our ring invariants and, if ok,
  670                          * just restart the receiver at the current
  671                          * point in the ring.
  672                          */
  673                         if (i82586_chk_rx_ring(sc) != 0)
  674                                 return (1);
  675 
  676                         i82586_start_transceiver(sc);
  677                         sc->sc_ethercom.ec_if.if_ierrors++;
  678                         return (0);
  679                 } else
  680                         printf("%s: receiver not ready; scbstatus=0x%x\n",
  681                                 sc->sc_dev.dv_xname, scbstatus);
  682 
  683                 sc->sc_ethercom.ec_if.if_ierrors++;
  684                 return (1);     /* Ask for a reset */
  685         }
  686 
  687         return (0);
  688 }
  689 
  690 /*
  691  * Process a command-complete interrupt.  These are only generated by the
  692  * transmission of frames.  This routine is deceptively simple, since most
  693  * of the real work is done by i82586_start().
  694  */
  695 int
  696 i82586_tint(sc, scbstatus)
  697         struct ie_softc *sc;
  698         int     scbstatus;
  699 {
  700         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  701         int status;
  702 
  703         ifp->if_timer = 0;
  704         ifp->if_flags &= ~IFF_OACTIVE;
  705 
  706 #if I82586_DEBUG
  707         if (sc->xmit_busy <= 0) {
  708             printf("i82586_tint: WEIRD: xmit_busy=%d, xctail=%d, xchead=%d\n",
  709                    sc->xmit_busy, sc->xctail, sc->xchead);
  710                 return (0);
  711         }
  712 #endif
  713 
  714         status = sc->ie_bus_read16(sc, IE_CMD_XMIT_STATUS(sc->xmit_cmds,
  715                                                           sc->xctail));
  716 
  717 #if I82586_DEBUG
  718         if (sc->sc_debug & IED_TINT)
  719                 printf("%s: tint: SCB status 0x%x; xmit status 0x%x\n",
  720                         sc->sc_dev.dv_xname, scbstatus, status);
  721 #endif
  722 
  723         if ((status & IE_STAT_COMPL) == 0 || (status & IE_STAT_BUSY)) {
  724             printf("i82586_tint: command still busy; status=0x%x; tail=%d\n",
  725                    status, sc->xctail);
  726             printf("iestatus = 0x%x\n", scbstatus);
  727         }
  728 
  729         if (status & IE_STAT_OK) {
  730                 ifp->if_opackets++;
  731                 ifp->if_collisions += (status & IE_XS_MAXCOLL);
  732         } else {
  733                 ifp->if_oerrors++;
  734                 /*
  735                  * Check SQE and DEFERRED?
  736                  * What if more than one bit is set?
  737                  */
  738                 if (status & IE_STAT_ABORT)
  739                         printf("%s: send aborted\n", sc->sc_dev.dv_xname);
  740                 else if (status & IE_XS_NOCARRIER)
  741                         printf("%s: no carrier\n", sc->sc_dev.dv_xname);
  742                 else if (status & IE_XS_LOSTCTS)
  743                         printf("%s: lost CTS\n", sc->sc_dev.dv_xname);
  744                 else if (status & IE_XS_UNDERRUN)
  745                         printf("%s: DMA underrun\n", sc->sc_dev.dv_xname);
  746                 else if (status & IE_XS_EXCMAX) {
  747                         printf("%s: too many collisions\n",
  748                                 sc->sc_dev.dv_xname);
  749                         sc->sc_ethercom.ec_if.if_collisions += 16;
  750                 }
  751         }
  752 
  753         /*
  754          * If multicast addresses were added or deleted while transmitting,
  755          * ie_mc_reset() set the want_mcsetup flag indicating that we
  756          * should do it.
  757          */
  758         if (sc->want_mcsetup) {
  759                 ie_mc_setup(sc, IE_XBUF_ADDR(sc, sc->xctail));
  760                 sc->want_mcsetup = 0;
  761         }
  762 
  763         /* Done with the buffer. */
  764         sc->xmit_busy--;
  765         sc->xctail = (sc->xctail + 1) % NTXBUF;
  766 
  767         /* Start the next packet, if any, transmitting. */
  768         if (sc->xmit_busy > 0)
  769                 iexmit(sc);
  770 
  771         i82586_start(ifp);
  772         return (0);
  773 }
  774 
  775 /*
  776  * Get a range of receive buffer descriptors that represent one packet.
  777  */
  778 static int
  779 i82586_get_rbd_list(sc, start, end, pktlen)
  780         struct ie_softc *sc;
  781         u_int16_t       *start;
  782         u_int16_t       *end;
  783         int             *pktlen;
  784 {
  785         int     off, rbbase = sc->rbds;
  786         int     rbindex, count = 0;
  787         int     plen = 0;
  788         int     rbdstatus;
  789 
  790         *start = rbindex = sc->rbhead;
  791 
  792         do {
  793                 off = IE_RBD_STATUS(rbbase, rbindex);
  794                 IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ);
  795                 rbdstatus = sc->ie_bus_read16(sc, off);
  796                 if ((rbdstatus & IE_RBD_USED) == 0) {
  797                         /*
  798                          * This means we are somehow out of sync.  So, we
  799                          * reset the adapter.
  800                          */
  801 #if I82586_DEBUG
  802                         print_rbd(sc, rbindex);
  803 #endif
  804                         log(LOG_ERR,
  805                             "%s: receive descriptors out of sync at %d\n",
  806                             sc->sc_dev.dv_xname, rbindex);
  807                         return (0);
  808                 }
  809                 plen += (rbdstatus & IE_RBD_CNTMASK);
  810 
  811                 if (++rbindex == sc->nrxbuf)
  812                         rbindex = 0;
  813 
  814                 ++count;
  815         } while ((rbdstatus & IE_RBD_LAST) == 0);
  816         *end = rbindex;
  817         *pktlen = plen;
  818         return (count);
  819 }
  820 
  821 
  822 /*
  823  * Release a range of receive buffer descriptors after we've copied the packet.
  824  */
  825 static void
  826 i82586_release_rbd_list(sc, start, end)
  827         struct ie_softc *sc;
  828         u_int16_t       start;
  829         u_int16_t       end;
  830 {
  831         int     off, rbbase = sc->rbds;
  832         int     rbindex = start;
  833 
  834         do {
  835                 /* Clear buffer status */
  836                 off = IE_RBD_STATUS(rbbase, rbindex);
  837                 sc->ie_bus_write16(sc, off, 0);
  838                 if (++rbindex == sc->nrxbuf)
  839                         rbindex = 0;
  840         } while (rbindex != end);
  841 
  842         /* Mark EOL at new tail */
  843         rbindex = ((rbindex == 0) ? sc->nrxbuf : rbindex) - 1;
  844         off = IE_RBD_BUFLEN(rbbase, rbindex);
  845         sc->ie_bus_write16(sc, off, IE_RBUF_SIZE|IE_RBD_EOL);
  846 
  847         /* Remove EOL from current tail */
  848         off = IE_RBD_BUFLEN(rbbase, sc->rbtail);
  849         sc->ie_bus_write16(sc, off, IE_RBUF_SIZE);
  850 
  851         /* New head & tail pointer */
  852 /* hmm, why have both? head is always (tail + 1) % NRXBUF */
  853         sc->rbhead = end;
  854         sc->rbtail = rbindex;
  855 }
  856 
  857 /*
  858  * Drop the packet at the head of the RX buffer ring.
  859  * Called if the frame descriptor reports an error on this packet.
  860  * Returns 1 if the buffer descriptor ring appears to be corrupt;
  861  * and 0 otherwise.
  862  */
  863 static int
  864 i82586_drop_frames(sc)
  865         struct ie_softc *sc;
  866 {
  867         u_int16_t bstart, bend;
  868         int pktlen;
  869 
  870         if (i82586_get_rbd_list(sc, &bstart, &bend, &pktlen) == 0)
  871                 return (1);
  872         i82586_release_rbd_list(sc, bstart, bend);
  873         return (0);
  874 }
  875 
  876 /*
  877  * Check the RX frame & buffer descriptor lists for our invariants,
  878  * i.e.: EOL bit set iff. it is pointed at by the r*tail pointer.
  879  *
  880  * Called when the receive unit has stopped unexpectedly.
  881  * Returns 1 if an inconsistency is detected; 0 otherwise.
  882  *
  883  * The Receive Unit is expected to be NOT RUNNING.
  884  */
  885 static int
  886 i82586_chk_rx_ring(sc)
  887         struct ie_softc *sc;
  888 {
  889         int n, off, val;
  890 
  891         for (n = 0; n < sc->nrxbuf; n++) {
  892                 off = IE_RBD_BUFLEN(sc->rbds, n);
  893                 val = sc->ie_bus_read16(sc, off);
  894                 if ((n == sc->rbtail) ^ ((val & IE_RBD_EOL) != 0)) {
  895                         /* `rbtail' and EOL flag out of sync */
  896                         log(LOG_ERR,
  897                             "%s: rx buffer descriptors out of sync at %d\n",
  898                             sc->sc_dev.dv_xname, n);
  899                         return (1);
  900                 }
  901 
  902                 /* Take the opportunity to clear the status fields here ? */
  903         }
  904 
  905         for (n = 0; n < sc->nframes; n++) {
  906                 off = IE_RFRAME_LAST(sc->rframes, n);
  907                 val = sc->ie_bus_read16(sc, off);
  908                 if ((n == sc->rftail) ^ ((val & (IE_FD_EOL|IE_FD_SUSP)) != 0)) {
  909                         /* `rftail' and EOL flag out of sync */
  910                         log(LOG_ERR,
  911                             "%s: rx frame list out of sync at %d\n",
  912                             sc->sc_dev.dv_xname, n);
  913                         return (1);
  914                 }
  915         }
  916 
  917         return (0);
  918 }
  919 
  920 /*
  921  * Read data off the interface, and turn it into an mbuf chain.
  922  *
  923  * This code is DRAMATICALLY different from the previous version; this
  924  * version tries to allocate the entire mbuf chain up front, given the
  925  * length of the data available.  This enables us to allocate mbuf
  926  * clusters in many situations where before we would have had a long
  927  * chain of partially-full mbufs.  This should help to speed up the
  928  * operation considerably.  (Provided that it works, of course.)
  929  */
  930 static __inline struct mbuf *
  931 ieget(sc, head, totlen)
  932         struct ie_softc *sc;
  933         int head;
  934         int totlen;
  935 {
  936         struct mbuf *m, *m0, *newm;
  937         int len, resid;
  938         int thisrboff, thismboff;
  939         struct ether_header eh;
  940 
  941         /*
  942          * Snarf the Ethernet header.
  943          */
  944         (sc->memcopyin)(sc, &eh, IE_RBUF_ADDR(sc, head),
  945             sizeof(struct ether_header));
  946 
  947         resid = totlen;
  948 
  949         MGETHDR(m0, M_DONTWAIT, MT_DATA);
  950         if (m0 == 0)
  951                 return (0);
  952         m0->m_pkthdr.rcvif = &sc->sc_ethercom.ec_if;
  953         m0->m_pkthdr.len = totlen;
  954         len = MHLEN;
  955         m = m0;
  956 
  957         /*
  958          * This loop goes through and allocates mbufs for all the data we will
  959          * be copying in.  It does not actually do the copying yet.
  960          */
  961         while (totlen > 0) {
  962                 if (totlen >= MINCLSIZE) {
  963                         MCLGET(m, M_DONTWAIT);
  964                         if ((m->m_flags & M_EXT) == 0)
  965                                 goto bad;
  966                         len = MCLBYTES;
  967                 }
  968 
  969                 if (m == m0) {
  970                         caddr_t newdata = (caddr_t)
  971                             ALIGN(m->m_data + sizeof(struct ether_header)) -
  972                             sizeof(struct ether_header);
  973                         len -= newdata - m->m_data;
  974                         m->m_data = newdata;
  975                 }
  976 
  977                 m->m_len = len = min(totlen, len);
  978 
  979                 totlen -= len;
  980                 if (totlen > 0) {
  981                         MGET(newm, M_DONTWAIT, MT_DATA);
  982                         if (newm == 0)
  983                                 goto bad;
  984                         len = MLEN;
  985                         m = m->m_next = newm;
  986                 }
  987         }
  988 
  989         m = m0;
  990         thismboff = 0;
  991 
  992         /*
  993          * Copy the Ethernet header into the mbuf chain.
  994          */
  995         memcpy(mtod(m, caddr_t), &eh, sizeof(struct ether_header));
  996         thismboff = sizeof(struct ether_header);
  997         thisrboff = sizeof(struct ether_header);
  998         resid -= sizeof(struct ether_header);
  999 
 1000         /*
 1001          * Now we take the mbuf chain (hopefully only one mbuf most of the
 1002          * time) and stuff the data into it.  There are no possible failures
 1003          * at or after this point.
 1004          */
 1005         while (resid > 0) {
 1006                 int thisrblen = IE_RBUF_SIZE - thisrboff,
 1007                     thismblen = m->m_len - thismboff;
 1008                 len = min(thisrblen, thismblen);
 1009 
 1010                 (sc->memcopyin)(sc, mtod(m, caddr_t) + thismboff,
 1011                                 IE_RBUF_ADDR(sc,head) + thisrboff,
 1012                                 (u_int)len);
 1013                 resid -= len;
 1014 
 1015                 if (len == thismblen) {
 1016                         m = m->m_next;
 1017                         thismboff = 0;
 1018                 } else
 1019                         thismboff += len;
 1020 
 1021                 if (len == thisrblen) {
 1022                         if (++head == sc->nrxbuf)
 1023                                 head = 0;
 1024                         thisrboff = 0;
 1025                 } else
 1026                         thisrboff += len;
 1027         }
 1028 
 1029         /*
 1030          * Unless something changed strangely while we were doing the copy,
 1031          * we have now copied everything in from the shared memory.
 1032          * This means that we are done.
 1033          */
 1034         return (m0);
 1035 
 1036 bad:
 1037         m_freem(m0);
 1038         return (0);
 1039 }
 1040 
 1041 /*
 1042  * Read frame NUM from unit UNIT (pre-cached as IE).
 1043  *
 1044  * This routine reads the RFD at NUM, and copies in the buffers from the list
 1045  * of RBD, then rotates the RBD list so that the receiver doesn't start
 1046  * complaining.  Trailers are DROPPED---there's no point in wasting time
 1047  * on confusing code to deal with them.  Hopefully, this machine will
 1048  * never ARP for trailers anyway.
 1049  */
 1050 static int
 1051 ie_readframe(sc, num)
 1052         struct ie_softc *sc;
 1053         int num;                /* frame number to read */
 1054 {
 1055         struct mbuf *m;
 1056         u_int16_t bstart, bend;
 1057         int pktlen;
 1058 
 1059         if (i82586_get_rbd_list(sc, &bstart, &bend, &pktlen) == 0) {
 1060                 sc->sc_ethercom.ec_if.if_ierrors++;
 1061                 return (1);
 1062         }
 1063 
 1064         m = ieget(sc, bstart, pktlen);
 1065         i82586_release_rbd_list(sc, bstart, bend);
 1066 
 1067         if (m == 0) {
 1068                 sc->sc_ethercom.ec_if.if_ierrors++;
 1069                 return (0);
 1070         }
 1071 
 1072 #if I82586_DEBUG
 1073         if (sc->sc_debug & IED_READFRAME) {
 1074                 struct ether_header *eh = mtod(m, struct ether_header *);
 1075 
 1076                 printf("%s: frame from ether %s type 0x%x len %d\n",
 1077                         sc->sc_dev.dv_xname,
 1078                         ether_sprintf(eh->ether_shost),
 1079                         (u_int)ntohs(eh->ether_type),
 1080                         pktlen);
 1081         }
 1082 #endif
 1083 
 1084 #if NBPFILTER > 0
 1085         /* Check for a BPF filter; if so, hand it up. */
 1086         if (sc->sc_ethercom.ec_if.if_bpf != 0)
 1087                 /* Pass it up. */
 1088                 bpf_mtap(sc->sc_ethercom.ec_if.if_bpf, m);
 1089 #endif /* NBPFILTER > 0 */
 1090 
 1091         /*
 1092          * Finally pass this packet up to higher layers.
 1093          */
 1094         (*sc->sc_ethercom.ec_if.if_input)(&sc->sc_ethercom.ec_if, m);
 1095         sc->sc_ethercom.ec_if.if_ipackets++;
 1096         return (0);
 1097 }
 1098 
 1099 
 1100 /*
 1101  * Setup all necessary artifacts for an XMIT command, and then pass the XMIT
 1102  * command to the chip to be executed.
 1103  */
 1104 static __inline__ void
 1105 iexmit(sc)
 1106         struct ie_softc *sc;
 1107 {
 1108         int off;
 1109         int cur, prev;
 1110 
 1111         cur = sc->xctail;
 1112 
 1113 #if I82586_DEBUG
 1114         if (sc->sc_debug & IED_XMIT)
 1115                 printf("%s: xmit buffer %d\n", sc->sc_dev.dv_xname, cur);
 1116 #endif
 1117 
 1118         /*
 1119          * Setup the transmit command.
 1120          */
 1121         sc->ie_bus_write16(sc, IE_CMD_XMIT_DESC(sc->xmit_cmds, cur),
 1122                                IE_XBD_ADDR(sc->xbds, cur));
 1123 
 1124         sc->ie_bus_write16(sc, IE_CMD_XMIT_STATUS(sc->xmit_cmds, cur), 0);
 1125 
 1126         if (sc->do_xmitnopchain) {
 1127                 /*
 1128                  * Gate this XMIT command to the following NOP
 1129                  */
 1130                 sc->ie_bus_write16(sc, IE_CMD_XMIT_LINK(sc->xmit_cmds, cur),
 1131                                        IE_CMD_NOP_ADDR(sc->nop_cmds, cur));
 1132                 sc->ie_bus_write16(sc, IE_CMD_XMIT_CMD(sc->xmit_cmds, cur),
 1133                                        IE_CMD_XMIT | IE_CMD_INTR);
 1134 
 1135                 /*
 1136                  * Loopback at following NOP
 1137                  */
 1138                 sc->ie_bus_write16(sc, IE_CMD_NOP_STATUS(sc->nop_cmds, cur), 0);
 1139                 sc->ie_bus_write16(sc, IE_CMD_NOP_LINK(sc->nop_cmds, cur),
 1140                                        IE_CMD_NOP_ADDR(sc->nop_cmds, cur));
 1141 
 1142                 /*
 1143                  * Gate preceding NOP to this XMIT command
 1144                  */
 1145                 prev = (cur + NTXBUF - 1) % NTXBUF;
 1146                 sc->ie_bus_write16(sc, IE_CMD_NOP_STATUS(sc->nop_cmds, prev), 0);
 1147                 sc->ie_bus_write16(sc, IE_CMD_NOP_LINK(sc->nop_cmds, prev),
 1148                                        IE_CMD_XMIT_ADDR(sc->xmit_cmds, cur));
 1149 
 1150                 off = IE_SCB_STATUS(sc->scb);
 1151                 IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ);
 1152                 if ((sc->ie_bus_read16(sc, off) & IE_CUS_ACTIVE) == 0) {
 1153                         printf("iexmit: CU not active\n");
 1154                         i82586_start_transceiver(sc);
 1155                 }
 1156         } else {
 1157                 sc->ie_bus_write16(sc, IE_CMD_XMIT_LINK(sc->xmit_cmds,cur),
 1158                                        0xffff);
 1159 
 1160                 sc->ie_bus_write16(sc, IE_CMD_XMIT_CMD(sc->xmit_cmds, cur),
 1161                                        IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST);
 1162 
 1163                 off = IE_SCB_CMDLST(sc->scb);
 1164                 sc->ie_bus_write16(sc, off, IE_CMD_XMIT_ADDR(sc->xmit_cmds, cur));
 1165                 IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ);
 1166 
 1167                 if (i82586_start_cmd(sc, IE_CUC_START, 0, 0, 1))
 1168                         printf("%s: iexmit: start xmit command timed out\n",
 1169                                 sc->sc_dev.dv_xname);
 1170         }
 1171 
 1172         sc->sc_ethercom.ec_if.if_timer = 5;
 1173 }
 1174 
 1175 
 1176 /*
 1177  * Start transmission on an interface.
 1178  */
 1179 void
 1180 i82586_start(ifp)
 1181         struct ifnet *ifp;
 1182 {
 1183         struct ie_softc *sc = ifp->if_softc;
 1184         struct mbuf *m0, *m;
 1185         int     buffer, head, xbase;
 1186         u_short len;
 1187         int     s;
 1188 
 1189         if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
 1190                 return;
 1191 
 1192         for (;;) {
 1193                 if (sc->xmit_busy == NTXBUF) {
 1194                         ifp->if_flags |= IFF_OACTIVE;
 1195                         break;
 1196                 }
 1197 
 1198                 head = sc->xchead;
 1199                 xbase = sc->xbds;
 1200 
 1201                 IFQ_DEQUEUE(&ifp->if_snd, m0);
 1202                 if (m0 == 0)
 1203                         break;
 1204 
 1205                 /* We need to use m->m_pkthdr.len, so require the header */
 1206                 if ((m0->m_flags & M_PKTHDR) == 0)
 1207                         panic("i82586_start: no header mbuf");
 1208 
 1209 #if NBPFILTER > 0
 1210                 /* Tap off here if there is a BPF listener. */
 1211                 if (ifp->if_bpf)
 1212                         bpf_mtap(ifp->if_bpf, m0);
 1213 #endif
 1214 
 1215 #if I82586_DEBUG
 1216                 if (sc->sc_debug & IED_ENQ)
 1217                         printf("%s: fill buffer %d\n", sc->sc_dev.dv_xname,
 1218                                 sc->xchead);
 1219 #endif
 1220 
 1221                 if (m0->m_pkthdr.len > IE_TBUF_SIZE)
 1222                         printf("%s: tbuf overflow\n", sc->sc_dev.dv_xname);
 1223 
 1224                 buffer = IE_XBUF_ADDR(sc, head);
 1225                 for (m = m0; m != 0; m = m->m_next) {
 1226                         (sc->memcopyout)(sc, mtod(m,caddr_t), buffer, m->m_len);
 1227                         buffer += m->m_len;
 1228                 }
 1229                 len = m0->m_pkthdr.len;
 1230                 if (len < ETHER_MIN_LEN - ETHER_CRC_LEN) {
 1231                         (sc->memcopyout)(sc, padbuf, buffer,
 1232                             ETHER_MIN_LEN - ETHER_CRC_LEN - len);
 1233                         buffer += ETHER_MIN_LEN -ETHER_CRC_LEN - len;
 1234                         len = ETHER_MIN_LEN - ETHER_CRC_LEN;
 1235                 }
 1236                 m_freem(m0);
 1237 
 1238                 /*
 1239                  * Setup the transmit buffer descriptor here, while we
 1240                  * know the packet's length.
 1241                  */
 1242                 sc->ie_bus_write16(sc, IE_XBD_FLAGS(xbase, head),
 1243                                        len | IE_TBD_EOL);
 1244                 sc->ie_bus_write16(sc, IE_XBD_NEXT(xbase, head), 0xffff);
 1245                 sc->ie_bus_write24(sc, IE_XBD_BUF(xbase, head),
 1246                                        IE_XBUF_ADDR(sc, head));
 1247 
 1248                 if (++head == NTXBUF)
 1249                         head = 0;
 1250                 sc->xchead = head;
 1251 
 1252                 s = splnet();
 1253                 /* Start the first packet transmitting. */
 1254                 if (sc->xmit_busy == 0)
 1255                         iexmit(sc);
 1256 
 1257                 sc->xmit_busy++;
 1258                 splx(s);
 1259         }
 1260 }
 1261 
 1262 /*
 1263  * Probe IE's ram setup   [ Move all this into MD front-end!? ]
 1264  * Use only if SCP and ISCP represent offsets into shared ram space.
 1265  */
 1266 int
 1267 i82586_proberam(sc)
 1268         struct ie_softc *sc;
 1269 {
 1270         int result, off;
 1271 
 1272         /* Put in 16-bit mode */
 1273         off = IE_SCP_BUS_USE(sc->scp);
 1274         sc->ie_bus_write16(sc, off, IE_SYSBUS_16BIT);
 1275         IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_WRITE);
 1276 
 1277         /* Set the ISCP `busy' bit */
 1278         off = IE_ISCP_BUSY(sc->iscp);
 1279         sc->ie_bus_write16(sc, off, 1);
 1280         IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_WRITE);
 1281 
 1282         if (sc->hwreset)
 1283                 (sc->hwreset)(sc, CHIP_PROBE);
 1284 
 1285         (sc->chan_attn) (sc, CHIP_PROBE);
 1286 
 1287         delay(100);             /* wait a while... */
 1288 
 1289         /* Read back the ISCP `busy' bit; it should be clear by now */
 1290         off = IE_ISCP_BUSY(sc->iscp);
 1291         IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ);
 1292         result = sc->ie_bus_read16(sc, off) == 0;
 1293 
 1294         /* Acknowledge any interrupts we may have caused. */
 1295         ie_ack(sc, IE_ST_WHENCE);
 1296 
 1297         return (result);
 1298 }
 1299 
 1300 void
 1301 i82586_reset(sc, hard)
 1302         struct ie_softc *sc;
 1303         int hard;
 1304 {
 1305         int s = splnet();
 1306 
 1307         if (hard)
 1308                 printf("%s: reset\n", sc->sc_dev.dv_xname);
 1309 
 1310         /* Clear OACTIVE in case we're called from watchdog (frozen xmit). */
 1311         sc->sc_ethercom.ec_if.if_timer = 0;
 1312         sc->sc_ethercom.ec_if.if_flags &= ~IFF_OACTIVE;
 1313 
 1314         /*
 1315          * Stop i82586 dead in its tracks.
 1316          */
 1317         if (i82586_start_cmd(sc, IE_RUC_ABORT | IE_CUC_ABORT, 0, 0, 0))
 1318                 printf("%s: abort commands timed out\n", sc->sc_dev.dv_xname);
 1319 
 1320         /*
 1321          * This can really slow down the i82586_reset() on some cards, but it's
 1322          * necessary to unwedge other ones (eg, the Sun VME ones) from certain
 1323          * lockups.
 1324          */
 1325         if (hard && sc->hwreset)
 1326                 (sc->hwreset)(sc, CARD_RESET);
 1327 
 1328         delay(100);
 1329         ie_ack(sc, IE_ST_WHENCE);
 1330 
 1331         if ((sc->sc_ethercom.ec_if.if_flags & IFF_UP) != 0) {
 1332                 int retries=0;  /* XXX - find out why init sometimes fails */
 1333                 while (retries++ < 2)
 1334                         if (i82586_init(&sc->sc_ethercom.ec_if) == 0)
 1335                                 break;
 1336         }
 1337 
 1338         splx(s);
 1339 }
 1340 
 1341 
 1342 static void
 1343 setup_simple_command(sc, cmd, cmdbuf)
 1344         struct ie_softc *sc;
 1345         int cmd;
 1346         int cmdbuf;
 1347 {
 1348         /* Setup a simple command */
 1349         sc->ie_bus_write16(sc, IE_CMD_COMMON_STATUS(cmdbuf), 0);
 1350         sc->ie_bus_write16(sc, IE_CMD_COMMON_CMD(cmdbuf), cmd | IE_CMD_LAST);
 1351         sc->ie_bus_write16(sc, IE_CMD_COMMON_LINK(cmdbuf), 0xffff);
 1352 
 1353         /* Assign the command buffer to the SCB command list */
 1354         sc->ie_bus_write16(sc, IE_SCB_CMDLST(sc->scb), cmdbuf);
 1355 }
 1356 
 1357 /*
 1358  * Run the time-domain reflectometer.
 1359  */
 1360 static void
 1361 ie_run_tdr(sc, cmd)
 1362         struct ie_softc *sc;
 1363         int cmd;
 1364 {
 1365         int result;
 1366 
 1367         setup_simple_command(sc, IE_CMD_TDR, cmd);
 1368         sc->ie_bus_write16(sc, IE_CMD_TDR_TIME(cmd), 0);
 1369 
 1370         if (i82586_start_cmd(sc, IE_CUC_START, cmd, IE_STAT_COMPL, 0) ||
 1371             (sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmd)) & IE_STAT_OK) == 0)
 1372                 result = 0x10000; /* XXX */
 1373         else
 1374                 result = sc->ie_bus_read16(sc, IE_CMD_TDR_TIME(cmd));
 1375 
 1376         /* Squash any pending interrupts */
 1377         ie_ack(sc, IE_ST_WHENCE);
 1378 
 1379         if (result & IE_TDR_SUCCESS)
 1380                 return;
 1381 
 1382         if (result & 0x10000)
 1383                 printf("%s: TDR command failed\n", sc->sc_dev.dv_xname);
 1384         else if (result & IE_TDR_XCVR)
 1385                 printf("%s: transceiver problem\n", sc->sc_dev.dv_xname);
 1386         else if (result & IE_TDR_OPEN)
 1387                 printf("%s: TDR detected incorrect termination %d clocks away\n",
 1388                         sc->sc_dev.dv_xname, result & IE_TDR_TIME);
 1389         else if (result & IE_TDR_SHORT)
 1390                 printf("%s: TDR detected a short circuit %d clocks away\n",
 1391                         sc->sc_dev.dv_xname, result & IE_TDR_TIME);
 1392         else
 1393                 printf("%s: TDR returned unknown status 0x%x\n",
 1394                         sc->sc_dev.dv_xname, result);
 1395 }
 1396 
 1397 
 1398 /*
 1399  * i82586_setup_bufs: set up the buffers
 1400  *
 1401  * We have a block of KVA at sc->buf_area which is of size sc->buf_area_sz.
 1402  * this is to be used for the buffers.  The chip indexs its control data
 1403  * structures with 16 bit offsets, and it indexes actual buffers with
 1404  * 24 bit addresses.   So we should allocate control buffers first so that
 1405  * we don't overflow the 16 bit offset field.   The number of transmit
 1406  * buffers is fixed at compile time.
 1407  *
 1408  */
 1409 static void
 1410 i82586_setup_bufs(sc)
 1411         struct ie_softc *sc;
 1412 {
 1413         int     ptr = sc->buf_area;     /* memory pool */
 1414         int     n, r;
 1415 
 1416         /*
 1417          * step 0: zero memory and figure out how many recv buffers and
 1418          * frames we can have.
 1419          */
 1420         ptr = (ptr + 3) & ~3;   /* set alignment and stick with it */
 1421 
 1422 
 1423         /*
 1424          *  step 1: lay out data structures in the shared-memory area
 1425          */
 1426 
 1427         /* The no-op commands; used if "nop-chaining" is in effect */
 1428         sc->nop_cmds = ptr;
 1429         ptr += NTXBUF * IE_CMD_NOP_SZ;
 1430 
 1431         /* The transmit commands */
 1432         sc->xmit_cmds = ptr;
 1433         ptr += NTXBUF * IE_CMD_XMIT_SZ;
 1434 
 1435         /* The transmit buffers descriptors */
 1436         sc->xbds = ptr;
 1437         ptr += NTXBUF * IE_XBD_SZ;
 1438 
 1439         /* The transmit buffers */
 1440         sc->xbufs = ptr;
 1441         ptr += NTXBUF * IE_TBUF_SIZE;
 1442 
 1443         ptr = (ptr + 3) & ~3;           /* re-align.. just in case */
 1444 
 1445         /* Compute free space for RECV stuff */
 1446         n = sc->buf_area_sz - (ptr - sc->buf_area);
 1447 
 1448         /* Compute size of one RECV frame */
 1449         r = IE_RFRAME_SZ + ((IE_RBD_SZ + IE_RBUF_SIZE) * B_PER_F);
 1450 
 1451         sc->nframes = n / r;
 1452 
 1453         if (sc->nframes <= 0)
 1454                 panic("ie: bogus buffer calc");
 1455 
 1456         sc->nrxbuf = sc->nframes * B_PER_F;
 1457 
 1458         /* The receive frame descriptors */
 1459         sc->rframes = ptr;
 1460         ptr += sc->nframes * IE_RFRAME_SZ;
 1461 
 1462         /* The receive buffer descriptors */
 1463         sc->rbds = ptr;
 1464         ptr += sc->nrxbuf * IE_RBD_SZ;
 1465 
 1466         /* The receive buffers */
 1467         sc->rbufs = ptr;
 1468         ptr += sc->nrxbuf * IE_RBUF_SIZE;
 1469 
 1470 #if I82586_DEBUG
 1471         printf("%s: %d frames %d bufs\n", sc->sc_dev.dv_xname, sc->nframes,
 1472                 sc->nrxbuf);
 1473 #endif
 1474 
 1475         /*
 1476          * step 2: link together the recv frames and set EOL on last one
 1477          */
 1478         for (n = 0; n < sc->nframes; n++) {
 1479                 int m = (n == sc->nframes - 1) ? 0 : n + 1;
 1480 
 1481                 /* Clear status */
 1482                 sc->ie_bus_write16(sc, IE_RFRAME_STATUS(sc->rframes,n), 0);
 1483 
 1484                 /* RBD link = NULL */
 1485                 sc->ie_bus_write16(sc, IE_RFRAME_BUFDESC(sc->rframes,n),
 1486                                        0xffff);
 1487 
 1488                 /* Make a circular list */
 1489                 sc->ie_bus_write16(sc, IE_RFRAME_NEXT(sc->rframes,n),
 1490                                        IE_RFRAME_ADDR(sc->rframes,m));
 1491 
 1492                 /* Mark last as EOL */
 1493                 sc->ie_bus_write16(sc, IE_RFRAME_LAST(sc->rframes,n),
 1494                                        ((m==0)? (IE_FD_EOL|IE_FD_SUSP) : 0));
 1495         }
 1496 
 1497         /*
 1498          * step 3: link the RBDs and set EOL on last one
 1499          */
 1500         for (n = 0; n < sc->nrxbuf; n++) {
 1501                 int m = (n == sc->nrxbuf - 1) ? 0 : n + 1;
 1502 
 1503                 /* Clear status */
 1504                 sc->ie_bus_write16(sc, IE_RBD_STATUS(sc->rbds,n), 0);
 1505 
 1506                 /* Make a circular list */
 1507                 sc->ie_bus_write16(sc, IE_RBD_NEXT(sc->rbds,n),
 1508                                        IE_RBD_ADDR(sc->rbds,m));
 1509 
 1510                 /* Link to data buffers */
 1511                 sc->ie_bus_write24(sc, IE_RBD_BUFADDR(sc->rbds, n),
 1512                                        IE_RBUF_ADDR(sc, n));
 1513                 sc->ie_bus_write16(sc, IE_RBD_BUFLEN(sc->rbds,n),
 1514                                        IE_RBUF_SIZE | ((m==0)?IE_RBD_EOL:0));
 1515         }
 1516 
 1517         /*
 1518          * step 4: all xmit no-op commands loopback onto themselves
 1519          */
 1520         for (n = 0; n < NTXBUF; n++) {
 1521                 sc->ie_bus_write16(sc, IE_CMD_NOP_STATUS(sc->nop_cmds, n), 0);
 1522 
 1523                 sc->ie_bus_write16(sc, IE_CMD_NOP_CMD(sc->nop_cmds, n),
 1524                                          IE_CMD_NOP);
 1525 
 1526                 sc->ie_bus_write16(sc, IE_CMD_NOP_LINK(sc->nop_cmds, n),
 1527                                          IE_CMD_NOP_ADDR(sc->nop_cmds, n));
 1528         }
 1529 
 1530 
 1531         /*
 1532          * step 6: set the head and tail pointers on receive to keep track of
 1533          * the order in which RFDs and RBDs are used.
 1534          */
 1535 
 1536         /* Pointers to last packet sent and next available transmit buffer. */
 1537         sc->xchead = sc->xctail = 0;
 1538 
 1539         /* Clear transmit-busy flag and set number of free transmit buffers. */
 1540         sc->xmit_busy = 0;
 1541 
 1542         /*
 1543          * Pointers to first and last receive frame.
 1544          * The RFD pointed to by rftail is the only one that has EOL set.
 1545          */
 1546         sc->rfhead = 0;
 1547         sc->rftail = sc->nframes - 1;
 1548 
 1549         /*
 1550          * Pointers to first and last receive descriptor buffer.
 1551          * The RBD pointed to by rbtail is the only one that has EOL set.
 1552          */
 1553         sc->rbhead = 0;
 1554         sc->rbtail = sc->nrxbuf - 1;
 1555 
 1556 /* link in recv frames * and buffer into the scb. */
 1557 #if I82586_DEBUG
 1558         printf("%s: reserved %d bytes\n",
 1559                 sc->sc_dev.dv_xname, ptr - sc->buf_area);
 1560 #endif
 1561 }
 1562 
 1563 static int
 1564 ie_cfg_setup(sc, cmd, promiscuous, manchester)
 1565         struct ie_softc *sc;
 1566         int cmd;
 1567         int promiscuous, manchester;
 1568 {
 1569         int cmdresult, status;
 1570         u_int8_t buf[IE_CMD_CFG_SZ]; /* XXX malloc? */
 1571 
 1572         *IE_CMD_CFG_CNT(buf)       = 0x0c;
 1573         *IE_CMD_CFG_FIFO(buf)      = 8;
 1574         *IE_CMD_CFG_SAVEBAD(buf)   = 0x40;
 1575         *IE_CMD_CFG_ADDRLEN(buf)   = 0x2e;
 1576         *IE_CMD_CFG_PRIORITY(buf)  = 0;
 1577         *IE_CMD_CFG_IFS(buf)       = 0x60;
 1578         *IE_CMD_CFG_SLOT_LOW(buf)  = 0;
 1579         *IE_CMD_CFG_SLOT_HIGH(buf) = 0xf2;
 1580         *IE_CMD_CFG_PROMISC(buf)   = !!promiscuous | manchester << 2;
 1581         *IE_CMD_CFG_CRSCDT(buf)    = 0;
 1582         *IE_CMD_CFG_MINLEN(buf)    = 64;
 1583         *IE_CMD_CFG_JUNK(buf)      = 0xff;
 1584         sc->memcopyout(sc, buf, cmd, IE_CMD_CFG_SZ);
 1585         setup_simple_command(sc, IE_CMD_CONFIG, cmd);
 1586         IE_BUS_BARRIER(sc, cmd, IE_CMD_CFG_SZ, BUS_SPACE_BARRIER_WRITE);
 1587 
 1588         cmdresult = i82586_start_cmd(sc, IE_CUC_START, cmd, IE_STAT_COMPL, 0);
 1589         status = sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmd));
 1590         if (cmdresult != 0) {
 1591                 printf("%s: configure command timed out; status %x\n",
 1592                         sc->sc_dev.dv_xname, status);
 1593                 return (0);
 1594         }
 1595         if ((status & IE_STAT_OK) == 0) {
 1596                 printf("%s: configure command failed; status %x\n",
 1597                         sc->sc_dev.dv_xname, status);
 1598                 return (0);
 1599         }
 1600 
 1601         /* Squash any pending interrupts */
 1602         ie_ack(sc, IE_ST_WHENCE);
 1603         return (1);
 1604 }
 1605 
 1606 static int
 1607 ie_ia_setup(sc, cmdbuf)
 1608         struct ie_softc *sc;
 1609         int cmdbuf;
 1610 {
 1611         int cmdresult, status;
 1612         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
 1613 
 1614         setup_simple_command(sc, IE_CMD_IASETUP, cmdbuf);
 1615 
 1616         (sc->memcopyout)(sc, LLADDR(ifp->if_sadl),
 1617                          IE_CMD_IAS_EADDR(cmdbuf), ETHER_ADDR_LEN);
 1618 
 1619         cmdresult = i82586_start_cmd(sc, IE_CUC_START, cmdbuf, IE_STAT_COMPL, 0);
 1620         status = sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmdbuf));
 1621         if (cmdresult != 0) {
 1622                 printf("%s: individual address command timed out; status %x\n",
 1623                         sc->sc_dev.dv_xname, status);
 1624                 return (0);
 1625         }
 1626         if ((status & IE_STAT_OK) == 0) {
 1627                 printf("%s: individual address command failed; status %x\n",
 1628                         sc->sc_dev.dv_xname, status);
 1629                 return (0);
 1630         }
 1631 
 1632         /* Squash any pending interrupts */
 1633         ie_ack(sc, IE_ST_WHENCE);
 1634         return (1);
 1635 }
 1636 
 1637 /*
 1638  * Run the multicast setup command.
 1639  * Called at splnet().
 1640  */
 1641 static int
 1642 ie_mc_setup(sc, cmdbuf)
 1643         struct ie_softc *sc;
 1644         int cmdbuf;
 1645 {
 1646         int cmdresult, status;
 1647 
 1648         if (sc->mcast_count == 0)
 1649                 return (1);
 1650 
 1651         setup_simple_command(sc, IE_CMD_MCAST, cmdbuf);
 1652 
 1653         (sc->memcopyout)(sc, (caddr_t)sc->mcast_addrs,
 1654                          IE_CMD_MCAST_MADDR(cmdbuf),
 1655                          sc->mcast_count * ETHER_ADDR_LEN);
 1656 
 1657         sc->ie_bus_write16(sc, IE_CMD_MCAST_BYTES(cmdbuf),
 1658                                sc->mcast_count * ETHER_ADDR_LEN);
 1659 
 1660         /* Start the command */
 1661         cmdresult = i82586_start_cmd(sc, IE_CUC_START, cmdbuf, IE_STAT_COMPL, 0);
 1662         status = sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmdbuf));
 1663         if (cmdresult != 0) {
 1664                 printf("%s: multicast setup command timed out; status %x\n",
 1665                         sc->sc_dev.dv_xname, status);
 1666                 return (0);
 1667         }
 1668         if ((status & IE_STAT_OK) == 0) {
 1669                 printf("%s: multicast setup command failed; status %x\n",
 1670                         sc->sc_dev.dv_xname, status);
 1671                 return (0);
 1672         }
 1673 
 1674         /* Squash any pending interrupts */
 1675         ie_ack(sc, IE_ST_WHENCE);
 1676         return (1);
 1677 }
 1678 
 1679 /*
 1680  * This routine takes the environment generated by check_ie_present() and adds
 1681  * to it all the other structures we need to operate the adapter.  This
 1682  * includes executing the CONFIGURE, IA-SETUP, and MC-SETUP commands, starting
 1683  * the receiver unit, and clearing interrupts.
 1684  *
 1685  * THIS ROUTINE MUST BE CALLED AT splnet() OR HIGHER.
 1686  */
 1687 int
 1688 i82586_init(ifp)
 1689         struct ifnet *ifp;
 1690 {
 1691         struct ie_softc *sc = ifp->if_softc;
 1692         int cmd;
 1693 
 1694         sc->async_cmd_inprogress = 0;
 1695 
 1696         cmd = sc->buf_area;
 1697 
 1698         /*
 1699          * Send the configure command first.
 1700          */
 1701         if (ie_cfg_setup(sc, cmd, sc->promisc, 0) == 0)
 1702                 return EIO;
 1703 
 1704         /*
 1705          * Send the Individual Address Setup command.
 1706          */
 1707         if (ie_ia_setup(sc, cmd) == 0)
 1708                 return EIO;
 1709 
 1710         /*
 1711          * Run the time-domain reflectometer.
 1712          */
 1713         ie_run_tdr(sc, cmd);
 1714 
 1715         /*
 1716          * Set the multi-cast filter, if any
 1717          */
 1718         if (ie_mc_setup(sc, cmd) == 0)
 1719                 return EIO;
 1720 
 1721         /*
 1722          * Acknowledge any interrupts we have generated thus far.
 1723          */
 1724         ie_ack(sc, IE_ST_WHENCE);
 1725 
 1726         /*
 1727          * Set up the transmit and recv buffers.
 1728          */
 1729         i82586_setup_bufs(sc);
 1730 
 1731         if (sc->hwinit)
 1732                 (sc->hwinit)(sc);
 1733 
 1734         ifp->if_flags |= IFF_RUNNING;
 1735         ifp->if_flags &= ~IFF_OACTIVE;
 1736 
 1737         if (NTXBUF < 2)
 1738                 sc->do_xmitnopchain = 0;
 1739 
 1740         i82586_start_transceiver(sc);
 1741         return (0);
 1742 }
 1743 
 1744 /*
 1745  * Start the RU and possibly the CU unit
 1746  */
 1747 static void
 1748 i82586_start_transceiver(sc)
 1749         struct ie_softc *sc;
 1750 {
 1751 
 1752         /*
 1753          * Start RU at current position in frame & RBD lists.
 1754          */
 1755         sc->ie_bus_write16(sc, IE_RFRAME_BUFDESC(sc->rframes,sc->rfhead),
 1756                                IE_RBD_ADDR(sc->rbds, sc->rbhead));
 1757 
 1758         sc->ie_bus_write16(sc, IE_SCB_RCVLST(sc->scb),
 1759                                IE_RFRAME_ADDR(sc->rframes,sc->rfhead));
 1760 
 1761         if (sc->do_xmitnopchain) {
 1762                 /* Stop transmit command chain */
 1763                 if (i82586_start_cmd(sc, IE_CUC_SUSPEND|IE_RUC_SUSPEND, 0, 0, 0))
 1764                         printf("%s: CU/RU stop command timed out\n",
 1765                                 sc->sc_dev.dv_xname);
 1766 
 1767                 /* Start the receiver & transmitter chain */
 1768                 /* sc->scb->ie_command_list =
 1769                         IEADDR(sc->nop_cmds[(sc->xctail+NTXBUF-1) % NTXBUF]);*/
 1770                 sc->ie_bus_write16(sc, IE_SCB_CMDLST(sc->scb),
 1771                                    IE_CMD_NOP_ADDR(
 1772                                         sc->nop_cmds,
 1773                                         (sc->xctail + NTXBUF - 1) % NTXBUF));
 1774 
 1775                 if (i82586_start_cmd(sc, IE_CUC_START|IE_RUC_START, 0, 0, 0))
 1776                         printf("%s: CU/RU command timed out\n",
 1777                                 sc->sc_dev.dv_xname);
 1778         } else {
 1779                 if (i82586_start_cmd(sc, IE_RUC_START, 0, 0, 0))
 1780                         printf("%s: RU command timed out\n",
 1781                                 sc->sc_dev.dv_xname);
 1782         }
 1783 }
 1784 
 1785 void
 1786 i82586_stop(ifp, disable)
 1787         struct ifnet *ifp;
 1788         int disable;
 1789 {
 1790         struct ie_softc *sc = ifp->if_softc;
 1791 
 1792         if (i82586_start_cmd(sc, IE_RUC_SUSPEND | IE_CUC_SUSPEND, 0, 0, 0))
 1793                 printf("%s: iestop: disable commands timed out\n",
 1794                         sc->sc_dev.dv_xname);
 1795 }
 1796 
 1797 int
 1798 i82586_ioctl(ifp, cmd, data)
 1799         struct ifnet *ifp;
 1800         u_long cmd;
 1801         caddr_t data;
 1802 {
 1803         struct ie_softc *sc = ifp->if_softc;
 1804         struct ifreq *ifr = (struct ifreq *)data;
 1805         int s, error = 0;
 1806 
 1807         s = splnet();
 1808         switch(cmd) {
 1809         case SIOCGIFMEDIA:
 1810         case SIOCSIFMEDIA:
 1811                 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
 1812                 break;
 1813         default:
 1814                 error = ether_ioctl(ifp, cmd, data);
 1815                 if (error == ENETRESET) {
 1816                         /*
 1817                          * Multicast list has changed; set the hardware filter
 1818                          * accordingly.
 1819                          */
 1820                         ie_mc_reset(sc);
 1821                         error = 0;
 1822                 }
 1823                 break;
 1824         }
 1825 #if I82586_DEBUG
 1826         if (cmd == SIOCSIFFLAGS)
 1827                 sc->sc_debug = (ifp->if_flags & IFF_DEBUG) ? IED_ALL : 0;
 1828 #endif
 1829         splx(s);
 1830         return (error);
 1831 }
 1832 
 1833 static void
 1834 ie_mc_reset(sc)
 1835         struct ie_softc *sc;
 1836 {
 1837         struct ether_multi *enm;
 1838         struct ether_multistep step;
 1839         int size;
 1840 
 1841         /*
 1842          * Step through the list of addresses.
 1843          */
 1844 again:
 1845         size = 0;
 1846         sc->mcast_count = 0;
 1847         ETHER_FIRST_MULTI(step, &sc->sc_ethercom, enm);
 1848         while (enm) {
 1849                 size += 6;
 1850                 if (sc->mcast_count >= IE_MAXMCAST ||
 1851                     memcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
 1852                         sc->sc_ethercom.ec_if.if_flags |= IFF_ALLMULTI;
 1853                         i82586_ioctl(&sc->sc_ethercom.ec_if,
 1854                                      SIOCSIFFLAGS, (void *)0);
 1855                         return;
 1856                 }
 1857                 ETHER_NEXT_MULTI(step, enm);
 1858         }
 1859 
 1860         if (size > sc->mcast_addrs_size) {
 1861                 /* Need to allocate more space */
 1862                 if (sc->mcast_addrs_size)
 1863                         free(sc->mcast_addrs, M_IFMADDR);
 1864                 sc->mcast_addrs = (char *)
 1865                         malloc(size, M_IFMADDR, M_WAITOK);
 1866                 sc->mcast_addrs_size = size;
 1867         }
 1868 
 1869         /*
 1870          * We've got the space; now copy the addresses
 1871          */
 1872         ETHER_FIRST_MULTI(step, &sc->sc_ethercom, enm);
 1873         while (enm) {
 1874                 if (sc->mcast_count >= IE_MAXMCAST)
 1875                         goto again; /* Just in case */
 1876 
 1877                 memcpy(&sc->mcast_addrs[sc->mcast_count], enm->enm_addrlo, 6);
 1878                 sc->mcast_count++;
 1879                 ETHER_NEXT_MULTI(step, enm);
 1880         }
 1881         sc->want_mcsetup = 1;
 1882 }
 1883 
 1884 /*
 1885  * Media change callback.
 1886  */
 1887 int
 1888 i82586_mediachange(ifp)
 1889         struct ifnet *ifp;
 1890 {
 1891         struct ie_softc *sc = ifp->if_softc;
 1892 
 1893         if (sc->sc_mediachange)
 1894                 return ((*sc->sc_mediachange)(sc));
 1895         return (0);
 1896 }
 1897 
 1898 /*
 1899  * Media status callback.
 1900  */
 1901 void
 1902 i82586_mediastatus(ifp, ifmr)
 1903         struct ifnet *ifp;
 1904         struct ifmediareq *ifmr;
 1905 {
 1906         struct ie_softc *sc = ifp->if_softc;
 1907 
 1908         if (sc->sc_mediastatus)
 1909                 (*sc->sc_mediastatus)(sc, ifmr);
 1910 }
 1911 
 1912 #if I82586_DEBUG
 1913 void
 1914 print_rbd(sc, n)
 1915         struct ie_softc *sc;
 1916         int n;
 1917 {
 1918 
 1919         printf("RBD at %08x:\n  status %04x, next %04x, buffer %lx\n"
 1920                 "length/EOL %04x\n", IE_RBD_ADDR(sc->rbds,n),
 1921                 sc->ie_bus_read16(sc, IE_RBD_STATUS(sc->rbds,n)),
 1922                 sc->ie_bus_read16(sc, IE_RBD_NEXT(sc->rbds,n)),
 1923                 (u_long)0,/*bus_space_read_4(sc->bt, sc->bh, IE_RBD_BUFADDR(sc->rbds,n)),-* XXX */
 1924                 sc->ie_bus_read16(sc, IE_RBD_BUFLEN(sc->rbds,n)));
 1925 }
 1926 #endif

Cache object: 81a73e69f749d59ab5047ec2eef14eaf


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.