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

Cache object: c555d154e2530784e6dd98c91b837e80


[ 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.