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/i386/isa/if_ie.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 /*-
    2  * Copyright (c) 1992, 1993, University of Vermont and State
    3  *  Agricultural College.
    4  * Copyright (c) 1992, 1993, Garrett A. Wollman.
    5  *
    6  * Portions:
    7  * Copyright (c) 1990, 1991, William F. Jolitz
    8  * Copyright (c) 1990, The Regents of the University of California
    9  *
   10  * 3Com 3C507 support:
   11  * Copyright (c) 1993, 1994, Charles M. Hannum
   12  *
   13  * EtherExpress 16 support:
   14  * Copyright (c) 1993, 1994, 1995, Rodney W. Grimes
   15  * Copyright (c) 1997, Aaron C. Smith
   16  *
   17  * All rights reserved.
   18  *
   19  * Redistribution and use in source and binary forms, with or without
   20  * modification, are permitted provided that the following conditions
   21  * are met:
   22  * 1. Redistributions of source code must retain the above copyright
   23  *    notice, this list of conditions and the following disclaimer.
   24  * 2. Redistributions in binary form must reproduce the above copyright
   25  *    notice, this list of conditions and the following disclaimer in the
   26  *    documentation and/or other materials provided with the distribution.
   27  * 3. All advertising materials mentioning features or use of this software
   28  *    must display the following acknowledgement:
   29  *      This product includes software developed by the University of
   30  *      Vermont and State Agricultural College and Garrett A. Wollman, by
   31  *      William F. Jolitz, by the University of California, Berkeley,
   32  *      Lawrence Berkeley Laboratory, and their contributors, by
   33  *      Charles M. Hannum, by Rodney W. Grimes, and by Aaron C. Smith.
   34  * 4. Neither the names of the Universities nor the names of the authors
   35  *    may be used to endorse or promote products derived from this software
   36  *    without specific prior written permission.
   37  *
   38  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   39  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   41  * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR AUTHORS BE LIABLE
   42  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   43  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   44  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   45  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   46  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   47  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   48  * SUCH DAMAGE.
   49  *
   50  * $FreeBSD$
   51  */
   52 
   53 /*
   54  * Intel 82586 Ethernet chip
   55  * Register, bit, and structure definitions.
   56  *
   57  * Written by GAW with reference to the Clarkson Packet Driver code for this
   58  * chip written by Russ Nelson and others.
   59  *
   60  * Intel EtherExpress 16 support from if_ix.c, written by Rodney W. Grimes.
   61  */
   62 
   63 /*
   64  * The i82586 is a very versatile chip, found in many implementations.
   65  * Programming this chip is mostly the same, but certain details differ
   66  * from card to card.  This driver is written so that different cards
   67  * can be automatically detected at run-time.
   68  */
   69 
   70 /*
   71 Mode of operation:
   72 
   73 We run the 82586 in a standard Ethernet mode.  We keep NFRAMES received
   74 frame descriptors around for the receiver to use, and NRXBUFS associated
   75 receive buffer descriptors, both in a circular list.  Whenever a frame is
   76 received, we rotate both lists as necessary.  (The 586 treats both lists
   77 as a simple queue.)  We also keep a transmit command around so that packets
   78 can be sent off quickly.
   79 
   80 We configure the adapter in AL-LOC = 1 mode, which means that the
   81 Ethernet/802.3 MAC header is placed at the beginning of the receive buffer
   82 rather than being split off into various fields in the RFD.  This also
   83 means that we must include this header in the transmit buffer as well.
   84 
   85 By convention, all transmit commands, and only transmit commands, shall
   86 have the I (IE_CMD_INTR) bit set in the command.  This way, when an
   87 interrupt arrives at ieintr(), it is immediately possible to tell
   88 what precisely caused it.  ANY OTHER command-sending routines should
   89 run at splimp(), and should post an acknowledgement to every interrupt
   90 they generate.
   91 
   92 The 82586 has a 24-bit address space internally, and the adaptor's memory
   93 is located at the top of this region.  However, the value we are given in
   94 configuration is normally the *bottom* of the adaptor RAM.  So, we must go
   95 through a few gyrations to come up with a kernel virtual address which
   96 represents the actual beginning of the 586 address space.  First, we
   97 autosize the RAM by running through several possible sizes and trying to
   98 initialize the adapter under the assumption that the selected size is
   99 correct.  Then, knowing the correct RAM size, we set up our pointers in
  100 ie_softc[unit].  `iomem' represents the computed base of the 586 address
  101 space.  `iomembot' represents the actual configured base of adapter RAM.
  102 Finally, `iosize' represents the calculated size of 586 RAM.  Then, when
  103 laying out commands, we use the interval [iomembot, iomembot + iosize); to
  104 make 24-pointers, we subtract iomem, and to make 16-pointers, we subtract
  105 iomem and and with 0xffff.
  106 
  107 */
  108 
  109 #include "ie.h"
  110 #if NIE > 0
  111 #include "opt_inet.h"
  112 #include "opt_ipx.h"
  113 
  114 #include <sys/param.h>
  115 #include <sys/systm.h>
  116 #include <sys/kernel.h>
  117 #include <sys/malloc.h>
  118 #include <sys/conf.h>
  119 #include <sys/mbuf.h>
  120 #include <sys/socket.h>
  121 #include <sys/sockio.h>
  122 #include <sys/syslog.h>
  123 
  124 #include <net/if.h>
  125 #include <net/if_types.h>
  126 #include <net/if_dl.h>
  127 
  128 #include "bpfilter.h"
  129 
  130 #ifdef INET
  131 #include <netinet/in.h>
  132 #include <netinet/if_ether.h>
  133 #endif
  134 
  135 #ifdef IPX
  136 #include <netipx/ipx.h>
  137 #include <netipx/ipx_if.h>
  138 #endif
  139 
  140 #ifdef NS
  141 #include <netns/ns.h>
  142 #include <netns/ns_if.h>
  143 #endif
  144 
  145 #include <machine/clock.h>
  146 #include <machine/md_var.h>
  147 
  148 #include <i386/isa/isa_device.h>
  149 #include <i386/isa/ic/i82586.h>
  150 #include <i386/isa/icu.h>
  151 #include <i386/isa/if_iereg.h>
  152 #include <i386/isa/if_ie507.h>
  153 #include <i386/isa/if_iee16.h>
  154 #include <i386/isa/elink.h>
  155 
  156 #if NBPFILTER > 0
  157 #include <net/bpf.h>
  158 #endif
  159 
  160 #ifdef DEBUG
  161 #define IED_RINT        0x01
  162 #define IED_TINT        0x02
  163 #define IED_RNR         0x04
  164 #define IED_CNA         0x08
  165 #define IED_READFRAME   0x10
  166 static int      ie_debug = IED_RNR;
  167 
  168 #endif
  169 
  170 #define IE_BUF_LEN      ETHER_MAX_LEN   /* length of transmit buffer */
  171 
  172 /* Forward declaration */
  173 struct ie_softc;
  174 
  175 static struct mbuf *last_not_for_us;
  176 
  177 static int      ieprobe(struct isa_device * dvp);
  178 static int      ieattach(struct isa_device * dvp);
  179 static ointhand2_t      ieintr;
  180 static int      sl_probe(struct isa_device * dvp);
  181 static int      el_probe(struct isa_device * dvp);
  182 static int      ni_probe(struct isa_device * dvp);
  183 static int      ee16_probe(struct isa_device * dvp);
  184 
  185 static int      check_ie_present(int unit, caddr_t where, unsigned size);
  186 static void     ieinit(int unit);
  187 static void     ie_stop(int unit);
  188 static int      ieioctl(struct ifnet * ifp, u_long command, caddr_t data);
  189 static void     iestart(struct ifnet * ifp);
  190 
  191 static void     el_reset_586(int unit);
  192 static void     el_chan_attn(int unit);
  193 
  194 static void     sl_reset_586(int unit);
  195 static void     sl_chan_attn(int unit);
  196 
  197 static void     ee16_reset_586(int unit);
  198 static void     ee16_chan_attn(int unit);
  199 static __inline void ee16_interrupt_enable(struct ie_softc * ie);
  200 static void     ee16_eeprom_outbits(struct ie_softc * ie, int edata, int cnt);
  201 static void     ee16_eeprom_clock(struct ie_softc * ie, int state);
  202 static u_short  ee16_read_eeprom(struct ie_softc * ie, int location);
  203 static int      ee16_eeprom_inbits(struct ie_softc * ie);
  204 static void     ee16_shutdown(int howto, void *sc);
  205 
  206 static void     iereset(int unit);
  207 static void     ie_readframe(int unit, struct ie_softc * ie, int bufno);
  208 static void     ie_drop_packet_buffer(int unit, struct ie_softc * ie);
  209 static void     sl_read_ether(int unit, unsigned char addr[6]);
  210 static void     find_ie_mem_size(int unit);
  211 static void     chan_attn_timeout(void *rock);
  212 static int      command_and_wait(int unit, int command,
  213                                  void volatile * pcmd, int);
  214 static void     run_tdr(int unit, struct ie_tdr_cmd * cmd);
  215 static int      ierint(int unit, struct ie_softc * ie);
  216 static int      ietint(int unit, struct ie_softc * ie);
  217 static int      iernr(int unit, struct ie_softc * ie);
  218 static void     start_receiver(int unit);
  219 static __inline int ieget(int, struct ie_softc *, struct mbuf **,
  220                           struct ether_header *, int *);
  221 static caddr_t  setup_rfa(caddr_t ptr, struct ie_softc * ie);
  222 static int      mc_setup(int, caddr_t, volatile struct ie_sys_ctl_block *);
  223 static void     ie_mc_reset(int unit);
  224 
  225 #ifdef DEBUG
  226 static void     print_rbd(volatile struct ie_recv_buf_desc * rbd);
  227 
  228 static int      in_ierint = 0;
  229 static int      in_ietint = 0;
  230 
  231 #endif
  232 
  233 /*
  234  * This tells the autoconf code how to set us up.
  235  */
  236 struct isa_driver iedriver = {
  237         ieprobe, ieattach, "ie",
  238 };
  239 
  240 enum ie_hardware {
  241         IE_STARLAN10,
  242         IE_EN100,
  243         IE_SLFIBER,
  244         IE_3C507,
  245         IE_NI5210,
  246         IE_EE16,
  247         IE_UNKNOWN
  248 };
  249 
  250 static const char *ie_hardware_names[] = {
  251         "StarLAN 10",
  252         "EN100",
  253         "StarLAN Fiber",
  254         "3C507",
  255         "NI5210",
  256         "EtherExpress 16",
  257         "Unknown"
  258 };
  259 
  260 /*
  261 sizeof(iscp) == 1+1+2+4 == 8
  262 sizeof(scb) == 2+2+2+2+2+2+2+2 == 16
  263 NFRAMES * sizeof(rfd) == NFRAMES*(2+2+2+2+6+6+2+2) == NFRAMES*24 == 384
  264 sizeof(xmit_cmd) == 2+2+2+2+6+2 == 18
  265 sizeof(transmit buffer) == 1512
  266 sizeof(transmit buffer desc) == 8
  267 -----
  268 1946
  269 
  270 NRXBUFS * sizeof(rbd) == NRXBUFS*(2+2+4+2+2) == NRXBUFS*12
  271 NRXBUFS * IE_RBUF_SIZE == NRXBUFS*256
  272 
  273 NRXBUFS should be (16384 - 1946) / (256 + 12) == 14438 / 268 == 53
  274 
  275 With NRXBUFS == 48, this leaves us 1574 bytes for another command or
  276 more buffers.  Another transmit command would be 18+8+1512 == 1538
  277 ---just barely fits!
  278 
  279 Obviously all these would have to be reduced for smaller memory sizes.
  280 With a larger memory, it would be possible to roughly double the number of
  281 both transmit and receive buffers.
  282 */
  283 
  284 #define NFRAMES         8       /* number of receive frames */
  285 #define NRXBUFS         48      /* number of buffers to allocate */
  286 #define IE_RBUF_SIZE    256     /* size of each buffer, MUST BE POWER OF TWO */
  287 #define NTXBUFS         2       /* number of transmit commands */
  288 #define IE_TBUF_SIZE    ETHER_MAX_LEN   /* size of transmit buffer */
  289 
  290 /*
  291  * Ethernet status, per interface.
  292  */
  293 static struct ie_softc {
  294         struct   arpcom arpcom;
  295         void     (*ie_reset_586) (int);
  296         void     (*ie_chan_attn) (int);
  297         enum     ie_hardware hard_type;
  298         int      hard_vers;
  299 
  300         u_short  port;          /* i/o base address for this interface */
  301         caddr_t  iomem;         /* memory size */
  302         caddr_t  iomembot;      /* memory base address */
  303         unsigned iosize;
  304         int      bus_use;       /* 0 means 16bit, 1 means 8 bit adapter */
  305 
  306         int      want_mcsetup;
  307         int      promisc;
  308         int      nframes;
  309         int      nrxbufs;
  310         int      ntxbufs;
  311         volatile struct ie_int_sys_conf_ptr *iscp;
  312         volatile struct ie_sys_ctl_block *scb;
  313         volatile struct ie_recv_frame_desc **rframes;   /* nframes worth */
  314         volatile struct ie_recv_buf_desc **rbuffs;      /* nrxbufs worth */
  315         volatile u_char **cbuffs;                       /* nrxbufs worth */
  316         int      rfhead, rftail, rbhead, rbtail;
  317 
  318         volatile struct ie_xmit_cmd **xmit_cmds;        /* ntxbufs worth */
  319         volatile struct ie_xmit_buf **xmit_buffs;       /* ntxbufs worth */
  320         u_char   **xmit_cbuffs;                         /* ntxbufs worth */
  321         int      xmit_count;
  322 
  323         struct   ie_en_addr mcast_addrs[MAXMCAST + 1];
  324         int      mcast_count;
  325 
  326         u_short  irq_encoded;   /* encoded interrupt on IEE16 */
  327 }       ie_softc[NIE];
  328 
  329 #define MK_24(base, ptr) ((caddr_t)((uintptr_t)ptr - (uintptr_t)base))
  330 #define MK_16(base, ptr) ((u_short)(uintptr_t)MK_24(base, ptr))
  331 
  332 #define PORT ie_softc[unit].port
  333 #define MEM  ie_softc[unit].iomem
  334 
  335 int
  336 ieprobe(struct isa_device *dvp)
  337 {
  338         int     ret;
  339 
  340         ret = sl_probe(dvp);
  341         if (!ret)
  342                 ret = el_probe(dvp);
  343         if (!ret)
  344                 ret = ni_probe(dvp);
  345         if (!ret)
  346                 ret = ee16_probe(dvp);
  347 
  348         return (ret);
  349 }
  350 
  351 static int
  352 sl_probe(struct isa_device *dvp)
  353 {
  354         int     unit = dvp->id_unit;
  355         u_char  c;
  356 
  357         ie_softc[unit].port = dvp->id_iobase;
  358         ie_softc[unit].iomembot = dvp->id_maddr;
  359         ie_softc[unit].iomem = 0;
  360         ie_softc[unit].bus_use = 0;
  361 
  362         c = inb(PORT + IEATT_REVISION);
  363         switch (SL_BOARD(c)) {
  364         case SL10_BOARD:
  365                 ie_softc[unit].hard_type = IE_STARLAN10;
  366                 ie_softc[unit].ie_reset_586 = sl_reset_586;
  367                 ie_softc[unit].ie_chan_attn = sl_chan_attn;
  368                 break;
  369         case EN100_BOARD:
  370                 ie_softc[unit].hard_type = IE_EN100;
  371                 ie_softc[unit].ie_reset_586 = sl_reset_586;
  372                 ie_softc[unit].ie_chan_attn = sl_chan_attn;
  373                 break;
  374         case SLFIBER_BOARD:
  375                 ie_softc[unit].hard_type = IE_SLFIBER;
  376                 ie_softc[unit].ie_reset_586 = sl_reset_586;
  377                 ie_softc[unit].ie_chan_attn = sl_chan_attn;
  378                 break;
  379 
  380                 /*
  381                  * Anything else is not recognized or cannot be used.
  382                  */
  383         default:
  384                 return (0);
  385         }
  386 
  387         ie_softc[unit].hard_vers = SL_REV(c);
  388 
  389         /*
  390          * Divine memory size on-board the card.  Ususally 16k.
  391          */
  392         find_ie_mem_size(unit);
  393 
  394         if (!ie_softc[unit].iosize) {
  395                 return (0);
  396         }
  397         dvp->id_msize = ie_softc[unit].iosize;
  398 
  399         switch (ie_softc[unit].hard_type) {
  400         case IE_EN100:
  401         case IE_STARLAN10:
  402         case IE_SLFIBER:
  403                 sl_read_ether(unit, ie_softc[unit].arpcom.ac_enaddr);
  404                 break;
  405 
  406         default:
  407                 if (bootverbose)
  408                         printf("ie%d: unknown AT&T board type code %d\n", unit,
  409                         ie_softc[unit].hard_type);
  410                 return (0);
  411         }
  412 
  413         return (1);
  414 }
  415 
  416 
  417 static int
  418 el_probe(struct isa_device *dvp)
  419 {
  420         struct ie_softc *sc = &ie_softc[dvp->id_unit];
  421         u_char  c;
  422         int     i;
  423         u_char  signature[] = "*3COM*";
  424         int     unit = dvp->id_unit;
  425 
  426         sc->port = dvp->id_iobase;
  427         sc->iomembot = dvp->id_maddr;
  428         sc->bus_use = 0;
  429 
  430         /* Need this for part of the probe. */
  431         sc->ie_reset_586 = el_reset_586;
  432         sc->ie_chan_attn = el_chan_attn;
  433 
  434         /* Reset and put card in CONFIG state without changing address. */
  435         elink_reset();
  436         outb(ELINK_ID_PORT, 0x00);
  437         elink_idseq(ELINK_507_POLY);
  438         elink_idseq(ELINK_507_POLY);
  439         outb(ELINK_ID_PORT, 0xff);
  440 
  441         c = inb(PORT + IE507_MADDR);
  442         if (c & 0x20) {
  443 #ifdef DEBUG
  444                 printf("ie%d: can't map 3C507 RAM in high memory\n", unit);
  445 #endif
  446                 return (0);
  447         }
  448         /* go to RUN state */
  449         outb(ELINK_ID_PORT, 0x00);
  450         elink_idseq(ELINK_507_POLY);
  451         outb(ELINK_ID_PORT, 0x00);
  452 
  453         outb(PORT + IE507_CTRL, EL_CTRL_NRST);
  454 
  455         for (i = 0; i < 6; i++)
  456                 if (inb(PORT + i) != signature[i])
  457                         return (0);
  458 
  459         c = inb(PORT + IE507_IRQ) & 0x0f;
  460 
  461         if (dvp->id_irq != (1 << c)) {
  462                 printf("ie%d: kernel configured irq %d "
  463                        "doesn't match board configured irq %d\n",
  464                        unit, ffs(dvp->id_irq) - 1, c);
  465                 return (0);
  466         }
  467         c = (inb(PORT + IE507_MADDR) & 0x1c) + 0xc0;
  468 
  469         if (kvtop(dvp->id_maddr) != ((int) c << 12)) {
  470                 printf("ie%d: kernel configured maddr %lx "
  471                        "doesn't match board configured maddr %x\n",
  472                        unit, kvtop(dvp->id_maddr), (int) c << 12);
  473                 return (0);
  474         }
  475         outb(PORT + IE507_CTRL, EL_CTRL_NORMAL);
  476 
  477         sc->hard_type = IE_3C507;
  478         sc->hard_vers = 0;      /* 3C507 has no version number. */
  479 
  480         /*
  481          * Divine memory size on-board the card.
  482          */
  483         find_ie_mem_size(unit);
  484 
  485         if (!sc->iosize) {
  486                 printf("ie%d: can't find shared memory\n", unit);
  487                 outb(PORT + IE507_CTRL, EL_CTRL_NRST);
  488                 return (0);
  489         }
  490         if (!dvp->id_msize)
  491                 dvp->id_msize = sc->iosize;
  492         else if (dvp->id_msize != sc->iosize) {
  493                 printf("ie%d: kernel configured msize %d "
  494                        "doesn't match board configured msize %d\n",
  495                        unit, dvp->id_msize, sc->iosize);
  496                 outb(PORT + IE507_CTRL, EL_CTRL_NRST);
  497                 return (0);
  498         }
  499         sl_read_ether(unit, ie_softc[unit].arpcom.ac_enaddr);
  500 
  501         /* Clear the interrupt latch just in case. */
  502         outb(PORT + IE507_ICTRL, 1);
  503 
  504         return (16);
  505 }
  506 
  507 
  508 static int
  509 ni_probe(struct isa_device *dvp)
  510 {
  511         int     unit = dvp->id_unit;
  512         int     boardtype, c;
  513 
  514         ie_softc[unit].port = dvp->id_iobase;
  515         ie_softc[unit].iomembot = dvp->id_maddr;
  516         ie_softc[unit].iomem = 0;
  517         ie_softc[unit].bus_use = 1;
  518 
  519         boardtype = inb(PORT + IEATT_REVISION);
  520         c = inb(PORT + IEATT_REVISION + 1);
  521         boardtype = boardtype + (c << 8);
  522         switch (boardtype) {
  523         case 0x5500:            /* This is the magic cookie for the NI5210 */
  524                 ie_softc[unit].hard_type = IE_NI5210;
  525                 ie_softc[unit].ie_reset_586 = sl_reset_586;
  526                 ie_softc[unit].ie_chan_attn = sl_chan_attn;
  527                 break;
  528 
  529                 /*
  530                  * Anything else is not recognized or cannot be used.
  531                  */
  532         default:
  533                 return (0);
  534         }
  535 
  536         ie_softc[unit].hard_vers = 0;
  537 
  538         /*
  539          * Divine memory size on-board the card.  Either 8 or 16k.
  540          */
  541         find_ie_mem_size(unit);
  542 
  543         if (!ie_softc[unit].iosize) {
  544                 return (0);
  545         }
  546         if (!dvp->id_msize)
  547                 dvp->id_msize = ie_softc[unit].iosize;
  548         else if (dvp->id_msize != ie_softc[unit].iosize) {
  549                 printf("ie%d: kernel configured msize %d "
  550                        "doesn't match board configured msize %d\n",
  551                        unit, dvp->id_msize, ie_softc[unit].iosize);
  552                 return (0);
  553         }
  554         sl_read_ether(unit, ie_softc[unit].arpcom.ac_enaddr);
  555 
  556         return (8);
  557 
  558 }
  559 
  560 
  561 static void
  562 ee16_shutdown(int howto, void *sc)
  563 {
  564         struct  ie_softc *ie = (struct ie_softc *)sc;
  565         int     unit = ie - &ie_softc[0];
  566 
  567         ee16_reset_586(unit);
  568         outb(PORT + IEE16_ECTRL, IEE16_RESET_ASIC);
  569         outb(PORT + IEE16_ECTRL, 0);
  570 }
  571 
  572 
  573 /* Taken almost exactly from Rod's if_ix.c. */
  574 
  575 int
  576 ee16_probe(struct isa_device *dvp)
  577 {
  578         struct ie_softc *sc = &ie_softc[dvp->id_unit];
  579 
  580         int     i;
  581         int     unit = dvp->id_unit;
  582         u_short board_id, id_var1, id_var2, checksum = 0;
  583         u_short eaddrtemp, irq;
  584         u_short pg, adjust, decode, edecode;
  585         u_char  bart_config;
  586         u_long  bd_maddr;
  587 
  588         short   irq_translate[] = {0, IRQ9, IRQ3, IRQ4, IRQ5, IRQ10, IRQ11, 0};
  589         char    irq_encode[] = {0, 0, 0, 2, 3, 4, 0, 0, 0, 1, 5, 6, 0, 0, 0, 0};
  590 
  591         /* Need this for part of the probe. */
  592         sc->ie_reset_586 = ee16_reset_586;
  593         sc->ie_chan_attn = ee16_chan_attn;
  594 
  595         /* unsure if this is necessary */
  596         sc->bus_use = 0;
  597 
  598         /* reset any ee16 at the current iobase */
  599         outb(dvp->id_iobase + IEE16_ECTRL, IEE16_RESET_ASIC);
  600         outb(dvp->id_iobase + IEE16_ECTRL, 0);
  601         DELAY(240);
  602 
  603         /* now look for ee16. */
  604         board_id = id_var1 = id_var2 = 0;
  605         for (i = 0; i < 4; i++) {
  606                 id_var1 = inb(dvp->id_iobase + IEE16_ID_PORT);
  607                 id_var2 = ((id_var1 & 0x03) << 2);
  608                 board_id |= ((id_var1 >> 4) << id_var2);
  609         }
  610 
  611         if (board_id != IEE16_ID) {
  612                 printf("ie%d: unknown board_id: %x\n", unit, board_id);
  613                 return (0);
  614         }
  615         /* need sc->port for ee16_read_eeprom */
  616         sc->port = dvp->id_iobase;
  617         sc->hard_type = IE_EE16;
  618 
  619         /*
  620          * The shared RAM location on the EE16 is encoded into bits 3-7 of
  621          * EEPROM location 6.  We zero the upper byte, and shift the 5 bits
  622          * right 3.  The resulting number tells us the RAM location.
  623          * Because the EE16 supports either 16k or 32k of shared RAM, we
  624          * only worry about the 32k locations.
  625          *
  626          * NOTE: if a 64k EE16 exists, it should be added to this switch. then
  627          * the ia->ia_msize would need to be set per case statement.
  628          *
  629          * value        msize   location =====  =====   ======== 0x03   0x8000
  630          * 0xCC000 0x06 0x8000  0xD0000 0x0C    0x8000  0xD4000 0x18
  631          * 0x8000       0xD8000
  632          *
  633          */
  634 
  635         bd_maddr = 0;
  636         i = (ee16_read_eeprom(sc, 6) & 0x00ff) >> 3;
  637         switch (i) {
  638         case 0x03:
  639                 bd_maddr = 0xCC000;
  640                 break;
  641         case 0x06:
  642                 bd_maddr = 0xD0000;
  643                 break;
  644         case 0x0c:
  645                 bd_maddr = 0xD4000;
  646                 break;
  647         case 0x18:
  648                 bd_maddr = 0xD8000;
  649                 break;
  650         default:
  651                 bd_maddr = 0;
  652                 break;
  653         }
  654         dvp->id_msize = 0x8000;
  655         if (kvtop(dvp->id_maddr) != bd_maddr) {
  656                 printf("ie%d: kernel configured maddr %lx "
  657                        "doesn't match board configured maddr %lx\n",
  658                        unit, kvtop(dvp->id_maddr), bd_maddr);
  659         }
  660         sc->iomembot = dvp->id_maddr;
  661         sc->iomem = 0;          /* XXX some probes set this and some don't */
  662         sc->iosize = dvp->id_msize;
  663 
  664         /* need to put the 586 in RESET while we access the eeprom. */
  665         outb(PORT + IEE16_ECTRL, IEE16_RESET_586);
  666 
  667         /* read the eeprom and checksum it, should == IEE16_ID */
  668         for (i = 0; i < 0x40; i++)
  669                 checksum += ee16_read_eeprom(sc, i);
  670 
  671         if (checksum != IEE16_ID) {
  672                 printf("ie%d: invalid eeprom checksum: %x\n", unit, checksum);
  673                 return (0);
  674         }
  675         /*
  676          * Size and test the memory on the board.  The size of the memory
  677          * can be one of 16k, 32k, 48k or 64k.  It can be located in the
  678          * address range 0xC0000 to 0xEFFFF on 16k boundaries.
  679          *
  680          * If the size does not match the passed in memory allocation size
  681          * issue a warning, but continue with the minimum of the two sizes.
  682          */
  683 
  684         switch (dvp->id_msize) {
  685         case 65536:
  686         case 32768:             /* XXX Only support 32k and 64k right now */
  687                 break;
  688         case 16384:
  689         case 49512:
  690         default:
  691                 printf("ie%d: mapped memory size %d not supported\n", unit,
  692                        dvp->id_msize);
  693                 return (0);
  694                 break;          /* NOTREACHED */
  695         }
  696 
  697         if ((kvtop(dvp->id_maddr) < 0xC0000) ||
  698             (kvtop(dvp->id_maddr) + sc->iosize > 0xF0000)) {
  699                 printf("ie%d: mapped memory location %p out of range\n", unit,
  700                        (void *)dvp->id_maddr);
  701                 return (0);
  702         }
  703         pg = (kvtop(dvp->id_maddr) & 0x3C000) >> 14;
  704         adjust = IEE16_MCTRL_FMCS16 | (pg & 0x3) << 2;
  705         decode = ((1 << (sc->iosize / 16384)) - 1) << pg;
  706         edecode = ((~decode >> 4) & 0xF0) | (decode >> 8);
  707 
  708         /* ZZZ This should be checked against eeprom location 6, low byte */
  709         outb(PORT + IEE16_MEMDEC, decode & 0xFF);
  710         /* ZZZ This should be checked against eeprom location 1, low byte */
  711         outb(PORT + IEE16_MCTRL, adjust);
  712         /* ZZZ Now if I could find this one I would have it made */
  713         outb(PORT + IEE16_MPCTRL, (~decode & 0xFF));
  714         /* ZZZ I think this is location 6, high byte */
  715         outb(PORT + IEE16_MECTRL, edecode);     /* XXX disable Exxx */
  716 
  717         (void) kvtop(dvp->id_maddr);
  718 
  719         /*
  720          * first prime the stupid bart DRAM controller so that it works,
  721          * then zero out all of memory.
  722          */
  723         bzero(sc->iomembot, 32);
  724         bzero(sc->iomembot, sc->iosize);
  725 
  726         /*
  727          * Get the encoded interrupt number from the EEPROM, check it
  728          * against the passed in IRQ.  Issue a warning if they do not match.
  729          * Always use the passed in IRQ, not the one in the EEPROM.
  730          */
  731         irq = ee16_read_eeprom(sc, IEE16_EEPROM_CONFIG1);
  732         irq = (irq & IEE16_EEPROM_IRQ) >> IEE16_EEPROM_IRQ_SHIFT;
  733         irq = irq_translate[irq];
  734         if (dvp->id_irq > 0) {
  735                 if (irq != dvp->id_irq) {
  736                         printf("ie%d: WARNING: board configured "
  737                                "at irq %u, using %u\n",
  738                                dvp->id_unit, dvp->id_irq, irq);
  739                         irq = dvp->id_unit;
  740                 }
  741         } else {
  742                 dvp->id_irq = irq;
  743         }
  744         sc->irq_encoded = irq_encode[ffs(irq) - 1];
  745 
  746         /*
  747          * Get the hardware ethernet address from the EEPROM and save it in
  748          * the softc for use by the 586 setup code.
  749          */
  750         eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_HIGH);
  751         sc->arpcom.ac_enaddr[1] = eaddrtemp & 0xFF;
  752         sc->arpcom.ac_enaddr[0] = eaddrtemp >> 8;
  753         eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_MID);
  754         sc->arpcom.ac_enaddr[3] = eaddrtemp & 0xFF;
  755         sc->arpcom.ac_enaddr[2] = eaddrtemp >> 8;
  756         eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_LOW);
  757         sc->arpcom.ac_enaddr[5] = eaddrtemp & 0xFF;
  758         sc->arpcom.ac_enaddr[4] = eaddrtemp >> 8;
  759 
  760         /* disable the board interrupts */
  761         outb(PORT + IEE16_IRQ, sc->irq_encoded);
  762 
  763         /* enable loopback to keep bad packets off the wire */
  764         if (sc->hard_type == IE_EE16) {
  765                 bart_config = inb(PORT + IEE16_CONFIG);
  766                 bart_config |= IEE16_BART_LOOPBACK;
  767                 bart_config |= IEE16_BART_MCS16_TEST;/* inb doesn't get bit! */
  768                 outb(PORT + IEE16_CONFIG, bart_config);
  769                 bart_config = inb(PORT + IEE16_CONFIG);
  770         }
  771         /* take the board out of reset state */
  772         outb(PORT + IEE16_ECTRL, 0);
  773         DELAY(100);
  774 
  775         if (!check_ie_present(unit, dvp->id_maddr, sc->iosize))
  776                 return (0);
  777 
  778         return (16);            /* return the number of I/O ports */
  779 }
  780 
  781 /*
  782  * Taken almost exactly from Bill's if_is.c, then modified beyond recognition.
  783  */
  784 int
  785 ieattach(struct isa_device *dvp)
  786 {
  787         int     factor;
  788         int     unit = dvp->id_unit;
  789         struct ie_softc *ie = &ie_softc[unit];
  790         struct ifnet *ifp = &ie->arpcom.ac_if;
  791         size_t  allocsize;
  792 
  793         dvp->id_ointr = ieintr;
  794 
  795         /*
  796          * based on the amount of memory we have, allocate our tx and rx
  797          * resources.
  798          */
  799         factor = dvp->id_msize / 16384;
  800         ie->nframes = factor * NFRAMES;
  801         ie->nrxbufs = factor * NRXBUFS;
  802         ie->ntxbufs = factor * NTXBUFS;
  803 
  804         /*
  805          * Since all of these guys are arrays of pointers, allocate as one
  806          * big chunk and dole out accordingly.
  807          */
  808         allocsize = sizeof(void *) * (ie->nframes
  809                                       + (ie->nrxbufs * 2)
  810                                       + (ie->ntxbufs * 3));
  811         ie->rframes = (volatile struct ie_recv_frame_desc **) malloc(allocsize,
  812                                                                      M_DEVBUF,
  813                                                                    M_NOWAIT);
  814         if (ie->rframes == NULL)
  815                 return (0);
  816         ie->rbuffs =
  817             (volatile struct ie_recv_buf_desc **)&ie->rframes[ie->nframes];
  818         ie->cbuffs = (volatile u_char **)&ie->rbuffs[ie->nrxbufs];
  819         ie->xmit_cmds =
  820             (volatile struct ie_xmit_cmd **)&ie->cbuffs[ie->nrxbufs];
  821         ie->xmit_buffs =
  822             (volatile struct ie_xmit_buf **)&ie->xmit_cmds[ie->ntxbufs];
  823         ie->xmit_cbuffs = (u_char **)&ie->xmit_buffs[ie->ntxbufs];
  824 
  825         ifp->if_softc = ie;
  826         ifp->if_unit = unit;
  827         ifp->if_name = iedriver.name;
  828         ifp->if_mtu = ETHERMTU;
  829         printf("ie%d: <%s R%d> address %6D\n", unit,
  830                ie_hardware_names[ie->hard_type],
  831                ie->hard_vers + 1,
  832                ie->arpcom.ac_enaddr, ":");
  833 
  834         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  835         ifp->if_output = ether_output;
  836         ifp->if_start = iestart;
  837         ifp->if_ioctl = ieioctl;
  838         ifp->if_type = IFT_ETHER;
  839         ifp->if_addrlen = 6;
  840         ifp->if_hdrlen = 14;
  841 
  842         if (ie->hard_type == IE_EE16)
  843                 at_shutdown(ee16_shutdown, ie, SHUTDOWN_POST_SYNC);
  844 
  845 #if NBPFILTER > 0
  846         bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
  847 #endif
  848 
  849         if_attach(ifp);
  850         ether_ifattach(ifp);
  851         return (1);
  852 }
  853 
  854 /*
  855  * What to do upon receipt of an interrupt.
  856  */
  857 static void
  858 ieintr(int unit)
  859 {
  860         register struct ie_softc *ie = &ie_softc[unit];
  861         register u_short status;
  862 
  863         /* Clear the interrupt latch on the 3C507. */
  864         if (ie->hard_type == IE_3C507
  865          && (inb(PORT + IE507_CTRL) & EL_CTRL_INTL))
  866                 outb(PORT + IE507_ICTRL, 1);
  867 
  868         /* disable interrupts on the EE16. */
  869         if (ie->hard_type == IE_EE16)
  870                 outb(PORT + IEE16_IRQ, ie->irq_encoded);
  871 
  872         status = ie->scb->ie_status;
  873 
  874 loop:
  875 
  876         /* Don't ack interrupts which we didn't receive */
  877         ie_ack(ie->scb, IE_ST_WHENCE & status, unit, ie->ie_chan_attn);
  878 
  879         if (status & (IE_ST_RECV | IE_ST_RNR)) {
  880 #ifdef DEBUG
  881                 in_ierint++;
  882                 if (ie_debug & IED_RINT)
  883                         printf("ie%d: rint\n", unit);
  884 #endif
  885                 ierint(unit, ie);
  886 #ifdef DEBUG
  887                 in_ierint--;
  888 #endif
  889         }
  890         if (status & IE_ST_DONE) {
  891 #ifdef DEBUG
  892                 in_ietint++;
  893                 if (ie_debug & IED_TINT)
  894                         printf("ie%d: tint\n", unit);
  895 #endif
  896                 ietint(unit, ie);
  897 #ifdef DEBUG
  898                 in_ietint--;
  899 #endif
  900         }
  901         if (status & IE_ST_RNR) {
  902 #ifdef DEBUG
  903                 if (ie_debug & IED_RNR)
  904                         printf("ie%d: rnr\n", unit);
  905 #endif
  906                 iernr(unit, ie);
  907         }
  908 #ifdef DEBUG
  909         if ((status & IE_ST_ALLDONE)
  910             && (ie_debug & IED_CNA))
  911                 printf("ie%d: cna\n", unit);
  912 #endif
  913 
  914         if ((status = ie->scb->ie_status) & IE_ST_WHENCE)
  915                 goto loop;
  916 
  917         /* Clear the interrupt latch on the 3C507. */
  918         if (ie->hard_type == IE_3C507)
  919                 outb(PORT + IE507_ICTRL, 1);
  920 
  921         /* enable interrupts on the EE16. */
  922         if (ie->hard_type == IE_EE16)
  923                 outb(PORT + IEE16_IRQ, ie->irq_encoded | IEE16_IRQ_ENABLE);
  924 
  925 }
  926 
  927 /*
  928  * Process a received-frame interrupt.
  929  */
  930 static int
  931 ierint(int unit, struct ie_softc *ie)
  932 {
  933         int     i, status;
  934         static int timesthru = 1024;
  935 
  936         i = ie->rfhead;
  937         while (1) {
  938                 status = ie->rframes[i]->ie_fd_status;
  939 
  940                 if ((status & IE_FD_COMPLETE) && (status & IE_FD_OK)) {
  941                         ie->arpcom.ac_if.if_ipackets++;
  942                         if (!--timesthru) {
  943                                 ie->arpcom.ac_if.if_ierrors +=
  944                                     ie->scb->ie_err_crc +
  945                                     ie->scb->ie_err_align +
  946                                     ie->scb->ie_err_resource +
  947                                     ie->scb->ie_err_overrun;
  948                                 ie->scb->ie_err_crc = 0;
  949                                 ie->scb->ie_err_align = 0;
  950                                 ie->scb->ie_err_resource = 0;
  951                                 ie->scb->ie_err_overrun = 0;
  952                                 timesthru = 1024;
  953                         }
  954                         ie_readframe(unit, ie, i);
  955                 } else {
  956                         if (status & IE_FD_RNR) {
  957                                 if (!(ie->scb->ie_status & IE_RU_READY)) {
  958                                         ie->rframes[0]->ie_fd_next =
  959                                             MK_16(MEM, ie->rbuffs[0]);
  960                                         ie->scb->ie_recv_list =
  961                                             MK_16(MEM, ie->rframes[0]);
  962                                         command_and_wait(unit, IE_RU_START,
  963                                                          0, 0);
  964                                 }
  965                         }
  966                         break;
  967                 }
  968                 i = (i + 1) % ie->nframes;
  969         }
  970         return (0);
  971 }
  972 
  973 /*
  974  * Process a command-complete interrupt.  These are only generated by
  975  * the transmission of frames.  This routine is deceptively simple, since
  976  * most of the real work is done by iestart().
  977  */
  978 static int
  979 ietint(int unit, struct ie_softc *ie)
  980 {
  981         int     status;
  982         int     i;
  983 
  984         ie->arpcom.ac_if.if_timer = 0;
  985         ie->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
  986 
  987         for (i = 0; i < ie->xmit_count; i++) {
  988                 status = ie->xmit_cmds[i]->ie_xmit_status;
  989 
  990                 if (status & IE_XS_LATECOLL) {
  991                         printf("ie%d: late collision\n", unit);
  992                         ie->arpcom.ac_if.if_collisions++;
  993                         ie->arpcom.ac_if.if_oerrors++;
  994                 } else if (status & IE_XS_NOCARRIER) {
  995                         printf("ie%d: no carrier\n", unit);
  996                         ie->arpcom.ac_if.if_oerrors++;
  997                 } else if (status & IE_XS_LOSTCTS) {
  998                         printf("ie%d: lost CTS\n", unit);
  999                         ie->arpcom.ac_if.if_oerrors++;
 1000                 } else if (status & IE_XS_UNDERRUN) {
 1001                         printf("ie%d: DMA underrun\n", unit);
 1002                         ie->arpcom.ac_if.if_oerrors++;
 1003                 } else if (status & IE_XS_EXCMAX) {
 1004                         printf("ie%d: too many collisions\n", unit);
 1005                         ie->arpcom.ac_if.if_collisions += 16;
 1006                         ie->arpcom.ac_if.if_oerrors++;
 1007                 } else {
 1008                         ie->arpcom.ac_if.if_opackets++;
 1009                         ie->arpcom.ac_if.if_collisions += status & IE_XS_MAXCOLL;
 1010                 }
 1011         }
 1012         ie->xmit_count = 0;
 1013 
 1014         /*
 1015          * If multicast addresses were added or deleted while we were
 1016          * transmitting, ie_mc_reset() set the want_mcsetup flag indicating
 1017          * that we should do it.
 1018          */
 1019         if (ie->want_mcsetup) {
 1020                 mc_setup(unit, (caddr_t) ie->xmit_cbuffs[0], ie->scb);
 1021                 ie->want_mcsetup = 0;
 1022         }
 1023         /* Wish I knew why this seems to be necessary... */
 1024         ie->xmit_cmds[0]->ie_xmit_status |= IE_STAT_COMPL;
 1025 
 1026         iestart(&ie->arpcom.ac_if);
 1027         return (0);             /* shouldn't be necessary */
 1028 }
 1029 
 1030 /*
 1031  * Process a receiver-not-ready interrupt.  I believe that we get these
 1032  * when there aren't enough buffers to go around.  For now (FIXME), we
 1033  * just restart the receiver, and hope everything's ok.
 1034  */
 1035 static int
 1036 iernr(int unit, struct ie_softc *ie)
 1037 {
 1038 #ifdef doesnt_work
 1039         setup_rfa((caddr_t) ie->rframes[0], ie);
 1040 
 1041         ie->scb->ie_recv_list = MK_16(MEM, ie_softc[unit].rframes[0]);
 1042         command_and_wait(unit, IE_RU_START, 0, 0);
 1043 #else
 1044         /* This doesn't work either, but it doesn't hang either. */
 1045         command_and_wait(unit, IE_RU_DISABLE, 0, 0);    /* just in case */
 1046         setup_rfa((caddr_t) ie->rframes[0], ie);        /* ignore cast-qual */
 1047 
 1048         ie->scb->ie_recv_list = MK_16(MEM, ie_softc[unit].rframes[0]);
 1049         command_and_wait(unit, IE_RU_START, 0, 0);      /* was ENABLE */
 1050 
 1051 #endif
 1052         ie_ack(ie->scb, IE_ST_WHENCE, unit, ie->ie_chan_attn);
 1053 
 1054         ie->arpcom.ac_if.if_ierrors++;
 1055         return (0);
 1056 }
 1057 
 1058 /*
 1059  * Compare two Ether/802 addresses for equality, inlined and
 1060  * unrolled for speed.  I'd love to have an inline assembler
 1061  * version of this...
 1062  */
 1063 static __inline int
 1064 ether_equal(u_char * one, u_char * two)
 1065 {
 1066         if (one[0] != two[0])
 1067                 return (0);
 1068         if (one[1] != two[1])
 1069                 return (0);
 1070         if (one[2] != two[2])
 1071                 return (0);
 1072         if (one[3] != two[3])
 1073                 return (0);
 1074         if (one[4] != two[4])
 1075                 return (0);
 1076         if (one[5] != two[5])
 1077                 return (0);
 1078         return 1;
 1079 }
 1080 
 1081 /*
 1082  * Check for a valid address.  to_bpf is filled in with one of the following:
 1083  *   0 -> BPF doesn't get this packet
 1084  *   1 -> BPF does get this packet
 1085  *   2 -> BPF does get this packet, but we don't
 1086  * Return value is true if the packet is for us, and false otherwise.
 1087  *
 1088  * This routine is a mess, but it's also critical that it be as fast
 1089  * as possible.  It could be made cleaner if we can assume that the
 1090  * only client which will fiddle with IFF_PROMISC is BPF.  This is
 1091  * probably a good assumption, but we do not make it here.  (Yet.)
 1092  */
 1093 static __inline int
 1094 check_eh(struct ie_softc * ie, struct ether_header * eh, int *to_bpf)
 1095 {
 1096         int     i;
 1097 
 1098         switch (ie->promisc) {
 1099         case IFF_ALLMULTI:
 1100                 /*
 1101                  * Receiving all multicasts, but no unicasts except those
 1102                  * destined for us.
 1103                  */
 1104 #if NBPFILTER > 0
 1105                 /* BPF gets this packet if anybody cares */
 1106                 *to_bpf = (ie->arpcom.ac_if.if_bpf != 0);
 1107 #endif
 1108                 if (eh->ether_dhost[0] & 1) {
 1109                         return (1);
 1110                 }
 1111                 if (ether_equal(eh->ether_dhost, ie->arpcom.ac_enaddr))
 1112                         return (1);
 1113                 return (0);
 1114 
 1115         case IFF_PROMISC:
 1116                 /*
 1117                  * Receiving all packets.  These need to be passed on to
 1118                  * BPF.
 1119                  */
 1120 #if NBPFILTER > 0
 1121                 *to_bpf = (ie->arpcom.ac_if.if_bpf != 0);
 1122 #endif
 1123                 /* If for us, accept and hand up to BPF */
 1124                 if (ether_equal(eh->ether_dhost, ie->arpcom.ac_enaddr))
 1125                         return (1);
 1126 
 1127 #if NBPFILTER > 0
 1128                 if (*to_bpf)
 1129                         *to_bpf = 2;    /* we don't need to see it */
 1130 #endif
 1131 
 1132                 /*
 1133                  * Not a multicast, so BPF wants to see it but we don't.
 1134                  */
 1135                 if (!(eh->ether_dhost[0] & 1))
 1136                         return (1);
 1137 
 1138                 /*
 1139                  * If it's one of our multicast groups, accept it and pass
 1140                  * it up.
 1141                  */
 1142                 for (i = 0; i < ie->mcast_count; i++) {
 1143                         if (ether_equal(eh->ether_dhost,
 1144                             (u_char *)&ie->mcast_addrs[i])) {
 1145 #if NBPFILTER > 0
 1146                                 if (*to_bpf)
 1147                                         *to_bpf = 1;
 1148 #endif
 1149                                 return (1);
 1150                         }
 1151                 }
 1152                 return (1);
 1153 
 1154         case IFF_ALLMULTI | IFF_PROMISC:
 1155                 /*
 1156                  * Acting as a multicast router, and BPF running at the same
 1157                  * time. Whew!  (Hope this is a fast machine...)
 1158                  */
 1159 #if NBPFILTER > 0
 1160                 *to_bpf = (ie->arpcom.ac_if.if_bpf != 0);
 1161 #endif
 1162                 /* We want to see multicasts. */
 1163                 if (eh->ether_dhost[0] & 1)
 1164                         return (1);
 1165 
 1166                 /* We want to see our own packets */
 1167                 if (ether_equal(eh->ether_dhost, ie->arpcom.ac_enaddr))
 1168                         return (1);
 1169 
 1170                 /* Anything else goes to BPF but nothing else. */
 1171 #if NBPFILTER > 0
 1172                 if (*to_bpf)
 1173                         *to_bpf = 2;
 1174 #endif
 1175                 return (1);
 1176 
 1177         default:
 1178                 /*
 1179                  * Only accept unicast packets destined for us, or
 1180                  * multicasts for groups that we belong to.  For now, we
 1181                  * assume that the '586 will only return packets that we
 1182                  * asked it for.  This isn't strictly true (it uses hashing
 1183                  * for the multicast filter), but it will do in this case,
 1184                  * and we want to get out of here as quickly as possible.
 1185                  */
 1186 #if NBPFILTER > 0
 1187                 *to_bpf = (ie->arpcom.ac_if.if_bpf != 0);
 1188 #endif
 1189                 return (1);
 1190         }
 1191         return (0);
 1192 }
 1193 
 1194 /*
 1195  * We want to isolate the bits that have meaning...  This assumes that
 1196  * IE_RBUF_SIZE is an even power of two.  If somehow the act_len exceeds
 1197  * the size of the buffer, then we are screwed anyway.
 1198  */
 1199 static __inline int
 1200 ie_buflen(struct ie_softc * ie, int head)
 1201 {
 1202         return (ie->rbuffs[head]->ie_rbd_actual
 1203                 & (IE_RBUF_SIZE | (IE_RBUF_SIZE - 1)));
 1204 }
 1205 
 1206 static __inline int
 1207 ie_packet_len(int unit, struct ie_softc * ie)
 1208 {
 1209         int     i;
 1210         int     head = ie->rbhead;
 1211         int     acc = 0;
 1212 
 1213         do {
 1214                 if (!(ie->rbuffs[ie->rbhead]->ie_rbd_actual & IE_RBD_USED)) {
 1215 #ifdef DEBUG
 1216                         print_rbd(ie->rbuffs[ie->rbhead]);
 1217 #endif
 1218                         log(LOG_ERR,
 1219                             "ie%d: receive descriptors out of sync at %d\n",
 1220                             unit, ie->rbhead);
 1221                         iereset(unit);
 1222                         return (-1);
 1223                 }
 1224                 i = ie->rbuffs[head]->ie_rbd_actual & IE_RBD_LAST;
 1225 
 1226                 acc += ie_buflen(ie, head);
 1227                 head = (head + 1) % ie->nrxbufs;
 1228         } while (!i);
 1229 
 1230         return (acc);
 1231 }
 1232 
 1233 /*
 1234  * Read data off the interface, and turn it into an mbuf chain.
 1235  *
 1236  * This code is DRAMATICALLY different from the previous version; this
 1237  * version tries to allocate the entire mbuf chain up front, given the
 1238  * length of the data available.  This enables us to allocate mbuf
 1239  * clusters in many situations where before we would have had a long
 1240  * chain of partially-full mbufs.  This should help to speed up the
 1241  * operation considerably.  (Provided that it works, of course.)
 1242  */
 1243 static __inline int
 1244 ieget(int unit, struct ie_softc *ie, struct mbuf **mp,
 1245       struct ether_header *ehp, int *to_bpf)
 1246 {
 1247         struct  mbuf *m, *top, **mymp;
 1248         int     i;
 1249         int     offset;
 1250         int     totlen, resid;
 1251         int     thismboff;
 1252         int     head;
 1253 
 1254         totlen = ie_packet_len(unit, ie);
 1255         if (totlen <= 0)
 1256                 return (-1);
 1257 
 1258         i = ie->rbhead;
 1259 
 1260         /*
 1261          * Snarf the Ethernet header.
 1262          */
 1263         bcopy((caddr_t) ie->cbuffs[i], (caddr_t) ehp, sizeof *ehp);
 1264         /* ignore cast-qual warning here */
 1265 
 1266         /*
 1267          * As quickly as possible, check if this packet is for us. If not,
 1268          * don't waste a single cycle copying the rest of the packet in.
 1269          * This is only a consideration when FILTER is defined; i.e., when
 1270          * we are either running BPF or doing multicasting.
 1271          */
 1272         if (!check_eh(ie, ehp, to_bpf)) {
 1273                 ie_drop_packet_buffer(unit, ie);
 1274                 ie->arpcom.ac_if.if_ierrors--;  /* just this case, it's not an
 1275                                                  * error
 1276                                                  */
 1277                 return (-1);
 1278         }
 1279         totlen -= (offset = sizeof *ehp);
 1280 
 1281         MGETHDR(*mp, M_DONTWAIT, MT_DATA);
 1282         if (!*mp) {
 1283                 ie_drop_packet_buffer(unit, ie);
 1284                 return (-1);
 1285         }
 1286         m = *mp;
 1287         m->m_pkthdr.rcvif = &ie->arpcom.ac_if;
 1288         m->m_len = MHLEN;
 1289         resid = m->m_pkthdr.len = totlen;
 1290         top = 0;
 1291         mymp = &top;
 1292 
 1293         /*
 1294          * This loop goes through and allocates mbufs for all the data we
 1295          * will be copying in.  It does not actually do the copying yet.
 1296          */
 1297         do {                    /* while(resid > 0) */
 1298                 /*
 1299                  * Try to allocate an mbuf to hold the data that we have.
 1300                  * If we already allocated one, just get another one and
 1301                  * stick it on the end (eventually).  If we don't already
 1302                  * have one, try to allocate an mbuf cluster big enough to
 1303                  * hold the whole packet, if we think it's reasonable, or a
 1304                  * single mbuf which may or may not be big enough. Got that?
 1305                  */
 1306                 if (top) {
 1307                         MGET(m, M_DONTWAIT, MT_DATA);
 1308                         if (!m) {
 1309                                 m_freem(top);
 1310                                 ie_drop_packet_buffer(unit, ie);
 1311                                 return (-1);
 1312                         }
 1313                         m->m_len = MLEN;
 1314                 }
 1315                 if (resid >= MINCLSIZE) {
 1316                         MCLGET(m, M_DONTWAIT);
 1317                         if (m->m_flags & M_EXT)
 1318                                 m->m_len = min(resid, MCLBYTES);
 1319                 } else {
 1320                         if (resid < m->m_len) {
 1321                                 if (!top && resid + max_linkhdr <= m->m_len)
 1322                                         m->m_data += max_linkhdr;
 1323                                 m->m_len = resid;
 1324                         }
 1325                 }
 1326                 resid -= m->m_len;
 1327                 *mymp = m;
 1328                 mymp = &m->m_next;
 1329         } while (resid > 0);
 1330 
 1331         resid = totlen;
 1332         m = top;
 1333         thismboff = 0;
 1334         head = ie->rbhead;
 1335 
 1336         /*
 1337          * Now we take the mbuf chain (hopefully only one mbuf most of the
 1338          * time) and stuff the data into it.  There are no possible failures
 1339          * at or after this point.
 1340          */
 1341         while (resid > 0) {     /* while there's stuff left */
 1342                 int     thislen = ie_buflen(ie, head) - offset;
 1343 
 1344                 /*
 1345                  * If too much data for the current mbuf, then fill the
 1346                  * current one up, go to the next one, and try again.
 1347                  */
 1348                 if (thislen > m->m_len - thismboff) {
 1349                         int     newlen = m->m_len - thismboff;
 1350 
 1351                         bcopy((caddr_t) (ie->cbuffs[head] + offset),
 1352                               mtod(m, caddr_t) +thismboff, (unsigned) newlen);
 1353                         /* ignore cast-qual warning */
 1354                         m = m->m_next;
 1355                         thismboff = 0;  /* new mbuf, so no offset */
 1356                         offset += newlen;       /* we are now this far into
 1357                                                  * the packet */
 1358                         resid -= newlen;        /* so there is this much left
 1359                                                  * to get */
 1360                         continue;
 1361                 }
 1362                 /*
 1363                  * If there is more than enough space in the mbuf to hold
 1364                  * the contents of this buffer, copy everything in, advance
 1365                  * pointers, and so on.
 1366                  */
 1367                 if (thislen < m->m_len - thismboff) {
 1368                         bcopy((caddr_t) (ie->cbuffs[head] + offset),
 1369                             mtod(m, caddr_t) +thismboff, (unsigned) thislen);
 1370                         thismboff += thislen;   /* we are this far into the
 1371                                                  * mbuf */
 1372                         resid -= thislen;       /* and this much is left */
 1373                         goto nextbuf;
 1374                 }
 1375                 /*
 1376                  * Otherwise, there is exactly enough space to put this
 1377                  * buffer's contents into the current mbuf.  Do the
 1378                  * combination of the above actions.
 1379                  */
 1380                 bcopy((caddr_t) (ie->cbuffs[head] + offset),
 1381                       mtod(m, caddr_t) + thismboff, (unsigned) thislen);
 1382                 m = m->m_next;
 1383                 thismboff = 0;          /* new mbuf, start at the beginning */
 1384                 resid -= thislen;       /* and we are this far through */
 1385 
 1386                 /*
 1387                  * Advance all the pointers.  We can get here from either of
 1388                  * the last two cases, but never the first.
 1389                  */
 1390 nextbuf:
 1391                 offset = 0;
 1392                 ie->rbuffs[head]->ie_rbd_actual = 0;
 1393                 ie->rbuffs[head]->ie_rbd_length |= IE_RBD_LAST;
 1394                 ie->rbhead = head = (head + 1) % ie->nrxbufs;
 1395                 ie->rbuffs[ie->rbtail]->ie_rbd_length &= ~IE_RBD_LAST;
 1396                 ie->rbtail = (ie->rbtail + 1) % ie->nrxbufs;
 1397         }
 1398 
 1399         /*
 1400          * Unless something changed strangely while we were doing the copy,
 1401          * we have now copied everything in from the shared memory. This
 1402          * means that we are done.
 1403          */
 1404         return (0);
 1405 }
 1406 
 1407 /*
 1408  * Read frame NUM from unit UNIT (pre-cached as IE).
 1409  *
 1410  * This routine reads the RFD at NUM, and copies in the buffers from
 1411  * the list of RBD, then rotates the RBD and RFD lists so that the receiver
 1412  * doesn't start complaining.  Trailers are DROPPED---there's no point
 1413  * in wasting time on confusing code to deal with them.  Hopefully,
 1414  * this machine will never ARP for trailers anyway.
 1415  */
 1416 static void
 1417 ie_readframe(int unit, struct ie_softc *ie, int num/* frame number to read */)
 1418 {
 1419         struct ie_recv_frame_desc rfd;
 1420         struct mbuf *m = 0;
 1421         struct ether_header eh;
 1422 
 1423 #if NBPFILTER > 0
 1424         int     bpf_gets_it = 0;
 1425 
 1426 #endif
 1427 
 1428         bcopy((caddr_t) (ie->rframes[num]), &rfd,
 1429               sizeof(struct ie_recv_frame_desc));
 1430 
 1431         /*
 1432          * Immediately advance the RFD list, since we we have copied ours
 1433          * now.
 1434          */
 1435         ie->rframes[num]->ie_fd_status = 0;
 1436         ie->rframes[num]->ie_fd_last |= IE_FD_LAST;
 1437         ie->rframes[ie->rftail]->ie_fd_last &= ~IE_FD_LAST;
 1438         ie->rftail = (ie->rftail + 1) % ie->nframes;
 1439         ie->rfhead = (ie->rfhead + 1) % ie->nframes;
 1440 
 1441         if (rfd.ie_fd_status & IE_FD_OK) {
 1442 #if NBPFILTER > 0
 1443                 if (ieget(unit, ie, &m, &eh, &bpf_gets_it)) {
 1444 #else
 1445                 if (ieget(unit, ie, &m, &eh, (int *)0)) {
 1446 #endif
 1447                         ie->arpcom.ac_if.if_ierrors++;  /* this counts as an
 1448                                                          * error */
 1449                         return;
 1450                 }
 1451         }
 1452 #ifdef DEBUG
 1453         if (ie_debug & IED_READFRAME) {
 1454                 printf("ie%d: frame from ether %6D type %x\n", unit,
 1455                        eh.ether_shost, ":", (unsigned) eh.ether_type);
 1456         }
 1457         if (ntohs(eh.ether_type) > ETHERTYPE_TRAIL
 1458             && ntohs(eh.ether_type) < (ETHERTYPE_TRAIL + ETHERTYPE_NTRAILER))
 1459                 printf("received trailer!\n");
 1460 #endif
 1461 
 1462         if (!m)
 1463                 return;
 1464 
 1465         if (last_not_for_us) {
 1466                 m_freem(last_not_for_us);
 1467                 last_not_for_us = 0;
 1468         }
 1469 #if NBPFILTER > 0
 1470         /*
 1471          * Check for a BPF filter; if so, hand it up. Note that we have to
 1472          * stick an extra mbuf up front, because bpf_mtap expects to have
 1473          * the ether header at the front. It doesn't matter that this
 1474          * results in an ill-formatted mbuf chain, since BPF just looks at
 1475          * the data.  (It doesn't try to free the mbuf, tho' it will make a
 1476          * copy for tcpdump.)
 1477          */
 1478         if (bpf_gets_it) {
 1479                 struct mbuf m0;
 1480 
 1481                 m0.m_len = sizeof eh;
 1482                 m0.m_data = (caddr_t)&eh;
 1483                 m0.m_next = m;
 1484 
 1485                 /* Pass it up */
 1486                 bpf_mtap(&ie->arpcom.ac_if, &m0);
 1487         }
 1488         /*
 1489          * A signal passed up from the filtering code indicating that the
 1490          * packet is intended for BPF but not for the protocol machinery. We
 1491          * can save a few cycles by not handing it off to them.
 1492          */
 1493         if (bpf_gets_it == 2) {
 1494                 last_not_for_us = m;
 1495                 return;
 1496         }
 1497 #endif                          /* NBPFILTER > 0 */
 1498         /*
 1499          * In here there used to be code to check destination addresses upon
 1500          * receipt of a packet.  We have deleted that code, and replaced it
 1501          * with code to check the address much earlier in the cycle, before
 1502          * copying the data in; this saves us valuable cycles when operating
 1503          * as a multicast router or when using BPF.
 1504          */
 1505 
 1506         /*
 1507          * Finally pass this packet up to higher layers.
 1508          */
 1509         ether_input(&ie->arpcom.ac_if, &eh, m);
 1510 }
 1511 
 1512 static void
 1513 ie_drop_packet_buffer(int unit, struct ie_softc * ie)
 1514 {
 1515         int     i;
 1516 
 1517         do {
 1518                 /*
 1519                  * This means we are somehow out of sync.  So, we reset the
 1520                  * adapter.
 1521                  */
 1522                 if (!(ie->rbuffs[ie->rbhead]->ie_rbd_actual & IE_RBD_USED)) {
 1523 #ifdef DEBUG
 1524                         print_rbd(ie->rbuffs[ie->rbhead]);
 1525 #endif
 1526                         log(LOG_ERR, "ie%d: receive descriptors out of sync at %d\n",
 1527                             unit, ie->rbhead);
 1528                         iereset(unit);
 1529                         return;
 1530                 }
 1531                 i = ie->rbuffs[ie->rbhead]->ie_rbd_actual & IE_RBD_LAST;
 1532 
 1533                 ie->rbuffs[ie->rbhead]->ie_rbd_length |= IE_RBD_LAST;
 1534                 ie->rbuffs[ie->rbhead]->ie_rbd_actual = 0;
 1535                 ie->rbhead = (ie->rbhead + 1) % ie->nrxbufs;
 1536                 ie->rbuffs[ie->rbtail]->ie_rbd_length &= ~IE_RBD_LAST;
 1537                 ie->rbtail = (ie->rbtail + 1) % ie->nrxbufs;
 1538         } while (!i);
 1539 }
 1540 
 1541 
 1542 /*
 1543  * Start transmission on an interface.
 1544  */
 1545 static void
 1546 iestart(struct ifnet *ifp)
 1547 {
 1548         struct   ie_softc *ie = ifp->if_softc;
 1549         struct   mbuf *m0, *m;
 1550         unsigned char *buffer;
 1551         u_short  len;
 1552 
 1553         /*
 1554          * This is not really volatile, in this routine, but it makes gcc
 1555          * happy.
 1556          */
 1557         volatile u_short *bptr = &ie->scb->ie_command_list;
 1558 
 1559         if (!(ifp->if_flags & IFF_RUNNING))
 1560                 return;
 1561         if (ifp->if_flags & IFF_OACTIVE)
 1562                 return;
 1563 
 1564         do {
 1565                 IF_DEQUEUE(&ie->arpcom.ac_if.if_snd, m);
 1566                 if (!m)
 1567                         break;
 1568 
 1569                 buffer = ie->xmit_cbuffs[ie->xmit_count];
 1570                 len = 0;
 1571 
 1572                 for (m0 = m; m && len < IE_BUF_LEN; m = m->m_next) {
 1573                         bcopy(mtod(m, caddr_t), buffer, m->m_len);
 1574                         buffer += m->m_len;
 1575                         len += m->m_len;
 1576                 }
 1577 
 1578                 m_freem(m0);
 1579                 len = max(len, ETHER_MIN_LEN);
 1580 
 1581 #if NBPFILTER > 0
 1582                 /*
 1583                  * See if bpf is listening on this interface, let it see the
 1584                  * packet before we commit it to the wire.
 1585                  */
 1586                 if (ie->arpcom.ac_if.if_bpf)
 1587                         bpf_tap(&ie->arpcom.ac_if,
 1588                                 ie->xmit_cbuffs[ie->xmit_count], len);
 1589 #endif
 1590 
 1591                 ie->xmit_buffs[ie->xmit_count]->ie_xmit_flags =
 1592                     IE_XMIT_LAST|len;
 1593                 ie->xmit_buffs[ie->xmit_count]->ie_xmit_next = 0xffff;
 1594                 ie->xmit_buffs[ie->xmit_count]->ie_xmit_buf =
 1595                     MK_24(ie->iomem, ie->xmit_cbuffs[ie->xmit_count]);
 1596 
 1597                 ie->xmit_cmds[ie->xmit_count]->com.ie_cmd_cmd = IE_CMD_XMIT;
 1598                 ie->xmit_cmds[ie->xmit_count]->ie_xmit_status = 0;
 1599                 ie->xmit_cmds[ie->xmit_count]->ie_xmit_desc =
 1600                     MK_16(ie->iomem, ie->xmit_buffs[ie->xmit_count]);
 1601 
 1602                 *bptr = MK_16(ie->iomem, ie->xmit_cmds[ie->xmit_count]);
 1603                 bptr = &ie->xmit_cmds[ie->xmit_count]->com.ie_cmd_link;
 1604                 ie->xmit_count++;
 1605         } while (ie->xmit_count < ie->ntxbufs);
 1606 
 1607         /*
 1608          * If we queued up anything for transmission, send it.
 1609          */
 1610         if (ie->xmit_count) {
 1611                 ie->xmit_cmds[ie->xmit_count - 1]->com.ie_cmd_cmd |=
 1612                     IE_CMD_LAST | IE_CMD_INTR;
 1613 
 1614                 /*
 1615                  * By passing the command pointer as a null, we tell
 1616                  * command_and_wait() to pretend that this isn't an action
 1617                  * command.  I wish I understood what was happening here.
 1618                  */
 1619                 command_and_wait(ifp->if_unit, IE_CU_START, 0, 0);
 1620                 ifp->if_flags |= IFF_OACTIVE;
 1621         }
 1622         return;
 1623 }
 1624 
 1625 /*
 1626  * Check to see if there's an 82586 out there.
 1627  */
 1628 static int
 1629 check_ie_present(int unit, caddr_t where, unsigned size)
 1630 {
 1631         volatile struct ie_sys_conf_ptr *scp;
 1632         volatile struct ie_int_sys_conf_ptr *iscp;
 1633         volatile struct ie_sys_ctl_block *scb;
 1634         u_long  realbase;
 1635         int     s;
 1636 
 1637         s = splimp();
 1638 
 1639         realbase = (uintptr_t) where + size - (1 << 24);
 1640 
 1641         scp = (volatile struct ie_sys_conf_ptr *) (uintptr_t)
 1642               (realbase + IE_SCP_ADDR);
 1643         bzero((char *) scp, sizeof *scp);
 1644 
 1645         /*
 1646          * First we put the ISCP at the bottom of memory; this tests to make
 1647          * sure that our idea of the size of memory is the same as the
 1648          * controller's. This is NOT where the ISCP will be in normal
 1649          * operation.
 1650          */
 1651         iscp = (volatile struct ie_int_sys_conf_ptr *) where;
 1652         bzero((char *)iscp, sizeof *iscp);
 1653 
 1654         scb = (volatile struct ie_sys_ctl_block *) where;
 1655         bzero((char *)scb, sizeof *scb);
 1656 
 1657         scp->ie_bus_use = ie_softc[unit].bus_use;       /* 8-bit or 16-bit */
 1658         scp->ie_iscp_ptr = (caddr_t) ((volatile caddr_t) iscp -
 1659                                       (volatile caddr_t) (volatile uintptr_t)
 1660                                       realbase);
 1661 
 1662         iscp->ie_busy = 1;
 1663         iscp->ie_scb_offset = MK_16(realbase, scb) + 256;
 1664 
 1665         (*ie_softc[unit].ie_reset_586) (unit);
 1666         (*ie_softc[unit].ie_chan_attn) (unit);
 1667 
 1668         DELAY(100);             /* wait a while... */
 1669 
 1670         if (iscp->ie_busy) {
 1671                 splx(s);
 1672                 return (0);
 1673         }
 1674         /*
 1675          * Now relocate the ISCP to its real home, and reset the controller
 1676          * again.
 1677          */
 1678         iscp = (void *) Align((caddr_t) (uintptr_t)
 1679                               (realbase + IE_SCP_ADDR -
 1680                                sizeof(struct ie_int_sys_conf_ptr)));
 1681         bzero((char *) iscp, sizeof *iscp);     /* ignore cast-qual */
 1682 
 1683         scp->ie_iscp_ptr = (caddr_t) ((caddr_t) iscp -
 1684                                       (caddr_t) (uintptr_t) realbase);
 1685         /* ignore cast-qual */
 1686 
 1687         iscp->ie_busy = 1;
 1688         iscp->ie_scb_offset = MK_16(realbase, scb);
 1689 
 1690         (*ie_softc[unit].ie_reset_586) (unit);
 1691         (*ie_softc[unit].ie_chan_attn) (unit);
 1692 
 1693         DELAY(100);
 1694 
 1695         if (iscp->ie_busy) {
 1696                 splx(s);
 1697                 return (0);
 1698         }
 1699         ie_softc[unit].iosize = size;
 1700         ie_softc[unit].iomem = (caddr_t) (uintptr_t) realbase;
 1701 
 1702         ie_softc[unit].iscp = iscp;
 1703         ie_softc[unit].scb = scb;
 1704 
 1705         /*
 1706          * Acknowledge any interrupts we may have caused...
 1707          */
 1708         ie_ack(scb, IE_ST_WHENCE, unit, ie_softc[unit].ie_chan_attn);
 1709         splx(s);
 1710 
 1711         return (1);
 1712 }
 1713 
 1714 /*
 1715  * Divine the memory size of ie board UNIT.
 1716  * Better hope there's nothing important hiding just below the ie card...
 1717  */
 1718 static void
 1719 find_ie_mem_size(int unit)
 1720 {
 1721         unsigned size;
 1722 
 1723         ie_softc[unit].iosize = 0;
 1724 
 1725         for (size = 65536; size >= 8192; size -= 8192) {
 1726                 if (check_ie_present(unit, ie_softc[unit].iomembot, size)) {
 1727                         return;
 1728                 }
 1729         }
 1730 
 1731         return;
 1732 }
 1733 
 1734 void
 1735 el_reset_586(int unit)
 1736 {
 1737         outb(PORT + IE507_CTRL, EL_CTRL_RESET);
 1738         DELAY(100);
 1739         outb(PORT + IE507_CTRL, EL_CTRL_NORMAL);
 1740         DELAY(100);
 1741 }
 1742 
 1743 void
 1744 sl_reset_586(int unit)
 1745 {
 1746         outb(PORT + IEATT_RESET, 0);
 1747 }
 1748 
 1749 void
 1750 ee16_reset_586(int unit)
 1751 {
 1752         outb(PORT + IEE16_ECTRL, IEE16_RESET_586);
 1753         DELAY(100);
 1754         outb(PORT + IEE16_ECTRL, 0);
 1755         DELAY(100);
 1756 }
 1757 
 1758 void
 1759 el_chan_attn(int unit)
 1760 {
 1761         outb(PORT + IE507_ATTN, 1);
 1762 }
 1763 
 1764 void
 1765 sl_chan_attn(int unit)
 1766 {
 1767         outb(PORT + IEATT_ATTN, 0);
 1768 }
 1769 
 1770 void
 1771 ee16_chan_attn(int unit)
 1772 {
 1773         outb(PORT + IEE16_ATTN, 0);
 1774 }
 1775 
 1776 u_short
 1777 ee16_read_eeprom(struct ie_softc *sc, int location)
 1778 {
 1779         int     ectrl, edata;
 1780 
 1781         ectrl = inb(sc->port + IEE16_ECTRL);
 1782         ectrl &= IEE16_ECTRL_MASK;
 1783         ectrl |= IEE16_ECTRL_EECS;
 1784         outb(sc->port + IEE16_ECTRL, ectrl);
 1785 
 1786         ee16_eeprom_outbits(sc, IEE16_EEPROM_READ, IEE16_EEPROM_OPSIZE1);
 1787         ee16_eeprom_outbits(sc, location, IEE16_EEPROM_ADDR_SIZE);
 1788         edata = ee16_eeprom_inbits(sc);
 1789         ectrl = inb(sc->port + IEE16_ECTRL);
 1790         ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EEDI | IEE16_ECTRL_EECS);
 1791         outb(sc->port + IEE16_ECTRL, ectrl);
 1792         ee16_eeprom_clock(sc, 1);
 1793         ee16_eeprom_clock(sc, 0);
 1794         return edata;
 1795 }
 1796 
 1797 void
 1798 ee16_eeprom_outbits(struct ie_softc *sc, int edata, int count)
 1799 {
 1800         int     ectrl, i;
 1801 
 1802         ectrl = inb(sc->port + IEE16_ECTRL);
 1803         ectrl &= ~IEE16_RESET_ASIC;
 1804         for (i = count - 1; i >= 0; i--) {
 1805                 ectrl &= ~IEE16_ECTRL_EEDI;
 1806                 if (edata & (1 << i)) {
 1807                         ectrl |= IEE16_ECTRL_EEDI;
 1808                 }
 1809                 outb(sc->port + IEE16_ECTRL, ectrl);
 1810                 DELAY(1);       /* eeprom data must be setup for 0.4 uSec */
 1811                 ee16_eeprom_clock(sc, 1);
 1812                 ee16_eeprom_clock(sc, 0);
 1813         }
 1814         ectrl &= ~IEE16_ECTRL_EEDI;
 1815         outb(sc->port + IEE16_ECTRL, ectrl);
 1816         DELAY(1);               /* eeprom data must be held for 0.4 uSec */
 1817 }
 1818 
 1819 int
 1820 ee16_eeprom_inbits(struct ie_softc *sc)
 1821 {
 1822         int     ectrl, edata, i;
 1823 
 1824         ectrl = inb(sc->port + IEE16_ECTRL);
 1825         ectrl &= ~IEE16_RESET_ASIC;
 1826         for (edata = 0, i = 0; i < 16; i++) {
 1827                 edata = edata << 1;
 1828                 ee16_eeprom_clock(sc, 1);
 1829                 ectrl = inb(sc->port + IEE16_ECTRL);
 1830                 if (ectrl & IEE16_ECTRL_EEDO) {
 1831                         edata |= 1;
 1832                 }
 1833                 ee16_eeprom_clock(sc, 0);
 1834         }
 1835         return (edata);
 1836 }
 1837 
 1838 void
 1839 ee16_eeprom_clock(struct ie_softc *sc, int state)
 1840 {
 1841         int     ectrl;
 1842 
 1843         ectrl = inb(sc->port + IEE16_ECTRL);
 1844         ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EESK);
 1845         if (state) {
 1846                 ectrl |= IEE16_ECTRL_EESK;
 1847         }
 1848         outb(sc->port + IEE16_ECTRL, ectrl);
 1849         DELAY(9);               /* EESK must be stable for 8.38 uSec */
 1850 }
 1851 
 1852 static __inline void
 1853 ee16_interrupt_enable(struct ie_softc *sc)
 1854 {
 1855         DELAY(100);
 1856         outb(sc->port + IEE16_IRQ, sc->irq_encoded | IEE16_IRQ_ENABLE);
 1857         DELAY(100);
 1858 }
 1859 
 1860 void
 1861 sl_read_ether(int unit, unsigned char addr[6])
 1862 {
 1863         int     i;
 1864 
 1865         for (i = 0; i < 6; i++)
 1866                 addr[i] = inb(PORT + i);
 1867 }
 1868 
 1869 
 1870 static void
 1871 iereset(int unit)
 1872 {
 1873         int     s = splimp();
 1874 
 1875         if (unit >= NIE) {
 1876                 splx(s);
 1877                 return;
 1878         }
 1879         printf("ie%d: reset\n", unit);
 1880         ie_softc[unit].arpcom.ac_if.if_flags &= ~IFF_UP;
 1881         ieioctl(&ie_softc[unit].arpcom.ac_if, SIOCSIFFLAGS, 0);
 1882 
 1883         /*
 1884          * Stop i82586 dead in its tracks.
 1885          */
 1886         if (command_and_wait(unit, IE_RU_ABORT | IE_CU_ABORT, 0, 0))
 1887                 printf("ie%d: abort commands timed out\n", unit);
 1888 
 1889         if (command_and_wait(unit, IE_RU_DISABLE | IE_CU_STOP, 0, 0))
 1890                 printf("ie%d: disable commands timed out\n", unit);
 1891 
 1892 #ifdef notdef
 1893         if (!check_ie_present(unit, ie_softc[unit].iomembot,
 1894                               e_softc[unit].iosize))
 1895                 panic("ie disappeared!");
 1896 #endif
 1897 
 1898         ie_softc[unit].arpcom.ac_if.if_flags |= IFF_UP;
 1899         ieioctl(&ie_softc[unit].arpcom.ac_if, SIOCSIFFLAGS, 0);
 1900 
 1901         splx(s);
 1902         return;
 1903 }
 1904 
 1905 /*
 1906  * This is called if we time out.
 1907  */
 1908 static void
 1909 chan_attn_timeout(void *rock)
 1910 {
 1911         *(int *) rock = 1;
 1912 }
 1913 
 1914 /*
 1915  * Send a command to the controller and wait for it to either
 1916  * complete or be accepted, depending on the command.  If the
 1917  * command pointer is null, then pretend that the command is
 1918  * not an action command.  If the command pointer is not null,
 1919  * and the command is an action command, wait for
 1920  * ((volatile struct ie_cmd_common *)pcmd)->ie_cmd_status & MASK
 1921  * to become true.
 1922  */
 1923 static int
 1924 command_and_wait(int unit, int cmd, volatile void *pcmd, int mask)
 1925 {
 1926         volatile struct ie_cmd_common *cc = pcmd;
 1927         volatile int timedout = 0;
 1928         struct   callout_handle ch;
 1929 
 1930         ie_softc[unit].scb->ie_command = (u_short) cmd;
 1931 
 1932         if (IE_ACTION_COMMAND(cmd) && pcmd) {
 1933                 (*ie_softc[unit].ie_chan_attn) (unit);
 1934 
 1935                 /*
 1936                  * According to the packet driver, the minimum timeout
 1937                  * should be .369 seconds, which we round up to .37.
 1938                  */
 1939                 ch = timeout(chan_attn_timeout, (caddr_t)&timedout,
 1940                              37 * hz / 100);
 1941                 /* ignore cast-qual */
 1942 
 1943                 /*
 1944                  * Now spin-lock waiting for status.  This is not a very
 1945                  * nice thing to do, but I haven't figured out how, or
 1946                  * indeed if, we can put the process waiting for action to
 1947                  * sleep.  (We may be getting called through some other
 1948                  * timeout running in the kernel.)
 1949                  */
 1950                 while (1) {
 1951                         if ((cc->ie_cmd_status & mask) || timedout)
 1952                                 break;
 1953                 }
 1954 
 1955                 untimeout(chan_attn_timeout, (caddr_t)&timedout, ch);
 1956                 /* ignore cast-qual */
 1957 
 1958                 return (timedout);
 1959         } else {
 1960 
 1961                 /*
 1962                  * Otherwise, just wait for the command to be accepted.
 1963                  */
 1964                 (*ie_softc[unit].ie_chan_attn) (unit);
 1965 
 1966                 while (ie_softc[unit].scb->ie_command); /* spin lock */
 1967 
 1968                 return (0);
 1969         }
 1970 }
 1971 
 1972 /*
 1973  * Run the time-domain reflectometer...
 1974  */
 1975 static void
 1976 run_tdr(int unit, struct ie_tdr_cmd *cmd)
 1977 {
 1978         int     result;
 1979 
 1980         cmd->com.ie_cmd_status = 0;
 1981         cmd->com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST;
 1982         cmd->com.ie_cmd_link = 0xffff;
 1983         cmd->ie_tdr_time = 0;
 1984 
 1985         ie_softc[unit].scb->ie_command_list = MK_16(MEM, cmd);
 1986         cmd->ie_tdr_time = 0;
 1987 
 1988         if (command_and_wait(unit, IE_CU_START, cmd, IE_STAT_COMPL))
 1989                 result = 0x2000;
 1990         else
 1991                 result = cmd->ie_tdr_time;
 1992 
 1993         ie_ack(ie_softc[unit].scb, IE_ST_WHENCE, unit,
 1994                ie_softc[unit].ie_chan_attn);
 1995 
 1996         if (result & IE_TDR_SUCCESS)
 1997                 return;
 1998 
 1999         if (result & IE_TDR_XCVR) {
 2000                 printf("ie%d: transceiver problem\n", unit);
 2001         } else if (result & IE_TDR_OPEN) {
 2002                 printf("ie%d: TDR detected an open %d clocks away\n", unit,
 2003                        result & IE_TDR_TIME);
 2004         } else if (result & IE_TDR_SHORT) {
 2005                 printf("ie%d: TDR detected a short %d clocks away\n", unit,
 2006                        result & IE_TDR_TIME);
 2007         } else {
 2008                 printf("ie%d: TDR returned unknown status %x\n", unit, result);
 2009         }
 2010 }
 2011 
 2012 static void
 2013 start_receiver(int unit)
 2014 {
 2015         int     s = splimp();
 2016 
 2017         ie_softc[unit].scb->ie_recv_list = MK_16(MEM, ie_softc[unit].rframes[0]);
 2018         command_and_wait(unit, IE_RU_START, 0, 0);
 2019 
 2020         ie_ack(ie_softc[unit].scb, IE_ST_WHENCE, unit, ie_softc[unit].ie_chan_attn);
 2021 
 2022         splx(s);
 2023 }
 2024 
 2025 /*
 2026  * Here is a helper routine for iernr() and ieinit().  This sets up
 2027  * the RFA.
 2028  */
 2029 static caddr_t
 2030 setup_rfa(caddr_t ptr, struct ie_softc * ie)
 2031 {
 2032         volatile struct ie_recv_frame_desc *rfd = (void *) ptr;
 2033         volatile struct ie_recv_buf_desc *rbd;
 2034         int     i;
 2035         int     unit = ie - &ie_softc[0];
 2036 
 2037         /* First lay them out */
 2038         for (i = 0; i < ie->nframes; i++) {
 2039                 ie->rframes[i] = rfd;
 2040                 bzero((char *) rfd, sizeof *rfd);       /* ignore cast-qual */
 2041                 rfd++;
 2042         }
 2043 
 2044         ptr = (caddr_t) Align((caddr_t) rfd);   /* ignore cast-qual */
 2045 
 2046         /* Now link them together */
 2047         for (i = 0; i < ie->nframes; i++) {
 2048                 ie->rframes[i]->ie_fd_next =
 2049                     MK_16(MEM, ie->rframes[(i + 1) % ie->nframes]);
 2050         }
 2051 
 2052         /* Finally, set the EOL bit on the last one. */
 2053         ie->rframes[ie->nframes - 1]->ie_fd_last |= IE_FD_LAST;
 2054 
 2055         /*
 2056          * Now lay out some buffers for the incoming frames.  Note that we
 2057          * set aside a bit of slop in each buffer, to make sure that we have
 2058          * enough space to hold a single frame in every buffer.
 2059          */
 2060         rbd = (void *) ptr;
 2061 
 2062         for (i = 0; i < ie->nrxbufs; i++) {
 2063                 ie->rbuffs[i] = rbd;
 2064                 bzero((char *)rbd, sizeof *rbd);
 2065                 ptr = (caddr_t) Align(ptr + sizeof *rbd);
 2066                 rbd->ie_rbd_length = IE_RBUF_SIZE;
 2067                 rbd->ie_rbd_buffer = MK_24(MEM, ptr);
 2068                 ie->cbuffs[i] = (void *) ptr;
 2069                 ptr += IE_RBUF_SIZE;
 2070                 rbd = (void *) ptr;
 2071         }
 2072 
 2073         /* Now link them together */
 2074         for (i = 0; i < ie->nrxbufs; i++) {
 2075                 ie->rbuffs[i]->ie_rbd_next =
 2076                     MK_16(MEM, ie->rbuffs[(i + 1) % ie->nrxbufs]);
 2077         }
 2078 
 2079         /* Tag EOF on the last one */
 2080         ie->rbuffs[ie->nrxbufs - 1]->ie_rbd_length |= IE_RBD_LAST;
 2081 
 2082         /*
 2083          * We use the head and tail pointers on receive to keep track of the
 2084          * order in which RFDs and RBDs are used.
 2085          */
 2086         ie->rfhead = 0;
 2087         ie->rftail = ie->nframes - 1;
 2088         ie->rbhead = 0;
 2089         ie->rbtail = ie->nrxbufs - 1;
 2090 
 2091         ie->scb->ie_recv_list = MK_16(MEM, ie->rframes[0]);
 2092         ie->rframes[0]->ie_fd_buf_desc = MK_16(MEM, ie->rbuffs[0]);
 2093 
 2094         ptr = Align(ptr);
 2095         return (ptr);
 2096 }
 2097 
 2098 /*
 2099  * Run the multicast setup command.
 2100  * Call at splimp().
 2101  */
 2102 static int
 2103 mc_setup(int unit, caddr_t ptr,
 2104          volatile struct ie_sys_ctl_block * scb)
 2105 {
 2106         struct ie_softc *ie = &ie_softc[unit];
 2107         volatile struct ie_mcast_cmd *cmd = (void *) ptr;
 2108 
 2109         cmd->com.ie_cmd_status = 0;
 2110         cmd->com.ie_cmd_cmd = IE_CMD_MCAST | IE_CMD_LAST;
 2111         cmd->com.ie_cmd_link = 0xffff;
 2112 
 2113         /* ignore cast-qual */
 2114         bcopy((caddr_t) ie->mcast_addrs, (caddr_t) cmd->ie_mcast_addrs,
 2115               ie->mcast_count * sizeof *ie->mcast_addrs);
 2116 
 2117         cmd->ie_mcast_bytes = ie->mcast_count * 6;      /* grrr... */
 2118 
 2119         scb->ie_command_list = MK_16(MEM, cmd);
 2120         if (command_and_wait(unit, IE_CU_START, cmd, IE_STAT_COMPL)
 2121             || !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
 2122                 printf("ie%d: multicast address setup command failed\n", unit);
 2123                 return (0);
 2124         }
 2125         return (1);
 2126 }
 2127 
 2128 /*
 2129  * This routine takes the environment generated by check_ie_present()
 2130  * and adds to it all the other structures we need to operate the adapter.
 2131  * This includes executing the CONFIGURE, IA-SETUP, and MC-SETUP commands,
 2132  * starting the receiver unit, and clearing interrupts.
 2133  *
 2134  * THIS ROUTINE MUST BE CALLED AT splimp() OR HIGHER.
 2135  */
 2136 static void
 2137 ieinit(int unit)
 2138 {
 2139         struct ie_softc *ie = &ie_softc[unit];
 2140         volatile struct ie_sys_ctl_block *scb = ie->scb;
 2141         caddr_t ptr;
 2142         int     i;
 2143 
 2144         ptr = (caddr_t) Align((caddr_t) scb + sizeof *scb);
 2145 
 2146         /*
 2147          * Send the configure command first.
 2148          */
 2149         {
 2150                 volatile struct ie_config_cmd *cmd = (void *) ptr;
 2151 
 2152                 ie_setup_config(cmd, ie->promisc,
 2153                                 ie->hard_type == IE_STARLAN10);
 2154                 cmd->com.ie_cmd_status = 0;
 2155                 cmd->com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST;
 2156                 cmd->com.ie_cmd_link = 0xffff;
 2157 
 2158                 scb->ie_command_list = MK_16(MEM, cmd);
 2159 
 2160                 if (command_and_wait(unit, IE_CU_START, cmd, IE_STAT_COMPL)
 2161                  || !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
 2162                         printf("ie%d: configure command failed\n", unit);
 2163                         return;
 2164                 }
 2165         }
 2166         /*
 2167          * Now send the Individual Address Setup command.
 2168          */
 2169         {
 2170                 volatile struct ie_iasetup_cmd *cmd = (void *) ptr;
 2171 
 2172                 cmd->com.ie_cmd_status = 0;
 2173                 cmd->com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST;
 2174                 cmd->com.ie_cmd_link = 0xffff;
 2175 
 2176                 bcopy((char *)ie_softc[unit].arpcom.ac_enaddr,
 2177                       (char *)&cmd->ie_address, sizeof cmd->ie_address);
 2178                 scb->ie_command_list = MK_16(MEM, cmd);
 2179                 if (command_and_wait(unit, IE_CU_START, cmd, IE_STAT_COMPL)
 2180                     || !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
 2181                         printf("ie%d: individual address "
 2182                                "setup command failed\n", unit);
 2183                         return;
 2184                 }
 2185         }
 2186 
 2187         /*
 2188          * Now run the time-domain reflectometer.
 2189          */
 2190         run_tdr(unit, (void *) ptr);
 2191 
 2192         /*
 2193          * Acknowledge any interrupts we have generated thus far.
 2194          */
 2195         ie_ack(ie->scb, IE_ST_WHENCE, unit, ie->ie_chan_attn);
 2196 
 2197         /*
 2198          * Set up the RFA.
 2199          */
 2200         ptr = setup_rfa(ptr, ie);
 2201 
 2202         /*
 2203          * Finally, the transmit command and buffer are the last little bit
 2204          * of work.
 2205          */
 2206 
 2207         /* transmit command buffers */
 2208         for (i = 0; i < ie->ntxbufs; i++) {
 2209                 ie->xmit_cmds[i] = (void *) ptr;
 2210                 ptr += sizeof *ie->xmit_cmds[i];
 2211                 ptr = Align(ptr);
 2212                 ie->xmit_buffs[i] = (void *)ptr;
 2213                 ptr += sizeof *ie->xmit_buffs[i];
 2214                 ptr = Align(ptr);
 2215         }
 2216 
 2217         /* transmit buffers */
 2218         for (i = 0; i < ie->ntxbufs - 1; i++) {
 2219                 ie->xmit_cbuffs[i] = (void *)ptr;
 2220                 ptr += IE_BUF_LEN;
 2221                 ptr = Align(ptr);
 2222         }
 2223         ie->xmit_cbuffs[ie->ntxbufs - 1] = (void *) ptr;
 2224 
 2225         for (i = 1; i < ie->ntxbufs; i++) {
 2226                 bzero((caddr_t) ie->xmit_cmds[i], sizeof *ie->xmit_cmds[i]);
 2227                 bzero((caddr_t) ie->xmit_buffs[i], sizeof *ie->xmit_buffs[i]);
 2228         }
 2229 
 2230         /*
 2231          * This must be coordinated with iestart() and ietint().
 2232          */
 2233         ie->xmit_cmds[0]->ie_xmit_status = IE_STAT_COMPL;
 2234 
 2235         /* take the ee16 out of loopback */
 2236         if (ie->hard_type == IE_EE16) {
 2237                 u_int8_t bart_config;
 2238 
 2239                 bart_config = inb(PORT + IEE16_CONFIG);
 2240                 bart_config &= ~IEE16_BART_LOOPBACK;
 2241                 /* inb doesn't get bit! */
 2242                 bart_config |= IEE16_BART_MCS16_TEST;
 2243                 outb(PORT + IEE16_CONFIG, bart_config);
 2244                 ee16_interrupt_enable(ie);
 2245                 ee16_chan_attn(unit);
 2246         }
 2247         ie->arpcom.ac_if.if_flags |= IFF_RUNNING;       /* tell higher levels
 2248                                                          * we're here */
 2249         start_receiver(unit);
 2250 
 2251         return;
 2252 }
 2253 
 2254 static void
 2255 ie_stop(int unit)
 2256 {
 2257         command_and_wait(unit, IE_RU_DISABLE, 0, 0);
 2258 }
 2259 
 2260 static int
 2261 ieioctl(struct ifnet *ifp, u_long command, caddr_t data)
 2262 {
 2263         struct ifaddr *ifa = (struct ifaddr *) data;
 2264 #if defined(IPX) || defined(NS)
 2265         struct ie_softc *ie = ifp->if_softc;
 2266 #endif
 2267         struct ifreq *ifr = (struct ifreq *) data;
 2268         int     s, error = 0;
 2269 
 2270         s = splimp();
 2271 
 2272         switch (command) {
 2273         case SIOCSIFADDR:
 2274                 ifp->if_flags |= IFF_UP;
 2275 
 2276                 switch (ifa->ifa_addr->sa_family) {
 2277 #ifdef INET
 2278                 case AF_INET:
 2279                         ieinit(ifp->if_unit);
 2280                         arp_ifinit((struct arpcom *) ifp, ifa);
 2281                         break;
 2282 #endif                          /* INET */
 2283 
 2284 #ifdef IPX
 2285                         /*
 2286                          * This magic copied from if_is.c; I don't use XNS,
 2287                          * so I have no way of telling if this actually
 2288                          * works or not.
 2289                          */
 2290                 case AF_IPX:
 2291                         {
 2292                                 struct ipx_addr *ina =
 2293                                     &(IA_SIPX(ifa)->sipx_addr);
 2294 
 2295                                 if (ipx_nullhost(*ina)) {
 2296                                         ina->x_host = *(union ipx_host *) (ie->arpcom.ac_enaddr);
 2297                                 } else {
 2298                                         ifp->if_flags &= ~IFF_RUNNING;
 2299                                         bcopy((caddr_t) ina->x_host.c_host,
 2300                                               (caddr_t) ie->arpcom.ac_enaddr,
 2301                                               sizeof ie->arpcom.ac_enaddr);
 2302                                 }
 2303 
 2304                                 ieinit(ifp->if_unit);
 2305                         }
 2306                         break;
 2307 #endif                          /* IPX */
 2308 
 2309 #ifdef NS
 2310                         /*
 2311                          * This magic copied from if_is.c; I don't use XNS,
 2312                          * so I have no way of telling if this actually
 2313                          * works or not.
 2314                          */
 2315                 case AF_NS:
 2316                         {
 2317                                 struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
 2318 
 2319                                 if (ns_nullhost(*ina)) {
 2320                                         ina->x_host = *(union ns_host *)(ie->arpcom.ac_enaddr);
 2321                                 } else {
 2322                                         ifp->if_flags &= ~IFF_RUNNING;
 2323                                         bcopy((caddr_t) ina->x_host.c_host,
 2324                                               (caddr_t) ie->arpcom.ac_enaddr,
 2325                                               sizeof ie->arpcom.ac_enaddr);
 2326                                 }
 2327 
 2328                                 ieinit(ifp->if_unit);
 2329                         }
 2330                         break;
 2331 #endif                          /* NS */
 2332 
 2333                 default:
 2334                         ieinit(ifp->if_unit);
 2335                         break;
 2336                 }
 2337                 break;
 2338 
 2339         case SIOCSIFFLAGS:
 2340                 /*
 2341                  * Note that this device doesn't have an "all multicast"
 2342                  * mode, so we must turn on promiscuous mode and do the
 2343                  * filtering manually.
 2344                  */
 2345                 if ((ifp->if_flags & IFF_UP) == 0 &&
 2346                     (ifp->if_flags & IFF_RUNNING)) {
 2347                         ifp->if_flags &= ~IFF_RUNNING;
 2348                         ie_stop(ifp->if_unit);
 2349                 } else if ((ifp->if_flags & IFF_UP) &&
 2350                            (ifp->if_flags & IFF_RUNNING) == 0) {
 2351                         ie_softc[ifp->if_unit].promisc =
 2352                             ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
 2353                         ieinit(ifp->if_unit);
 2354                 } else if (ie_softc[ifp->if_unit].promisc ^
 2355                            (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI))) {
 2356                         ie_softc[ifp->if_unit].promisc =
 2357                             ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
 2358                         ieinit(ifp->if_unit);
 2359                 }
 2360                 break;
 2361 
 2362         case SIOCADDMULTI:
 2363         case SIOCDELMULTI:
 2364                 /*
 2365                  * Update multicast listeners
 2366                  */
 2367                 /* reset multicast filtering */
 2368                 ie_mc_reset(ifp->if_unit);
 2369                 error = 0;
 2370                 break;
 2371 
 2372         case SIOCSIFMTU:
 2373                 /*
 2374                  * Set the interface MTU.
 2375                  */
 2376                 if (ifr->ifr_mtu > ETHERMTU) {
 2377                         error = EINVAL;
 2378                 } else {
 2379                         ifp->if_mtu = ifr->ifr_mtu;
 2380                 }
 2381                 break;
 2382 
 2383         default:
 2384                 error = EINVAL;
 2385         }
 2386 
 2387         splx(s);
 2388         return (error);
 2389 }
 2390 
 2391 static void
 2392 ie_mc_reset(int unit)
 2393 {
 2394         struct ie_softc *ie = &ie_softc[unit];
 2395         struct ifmultiaddr *ifma;
 2396 
 2397         /*
 2398          * Step through the list of addresses.
 2399          */
 2400         ie->mcast_count = 0;
 2401         for (ifma = ie->arpcom.ac_if.if_multiaddrs.lh_first; ifma;
 2402              ifma = ifma->ifma_link.le_next) {
 2403                 if (ifma->ifma_addr->sa_family != AF_LINK)
 2404                         continue;
 2405 
 2406                 /* XXX - this is broken... */
 2407                 if (ie->mcast_count >= MAXMCAST) {
 2408                         ie->arpcom.ac_if.if_flags |= IFF_ALLMULTI;
 2409                         ieioctl(&ie->arpcom.ac_if, SIOCSIFFLAGS, (void *) 0);
 2410                         goto setflag;
 2411                 }
 2412                 bcopy(LLADDR((struct sockaddr_dl *) ifma->ifma_addr),
 2413                       &(ie->mcast_addrs[ie->mcast_count]), 6);
 2414                 ie->mcast_count++;
 2415         }
 2416 
 2417 setflag:
 2418         ie->want_mcsetup = 1;
 2419 }
 2420 
 2421 
 2422 #ifdef DEBUG
 2423 static void
 2424 print_rbd(volatile struct ie_recv_buf_desc * rbd)
 2425 {
 2426         printf("RBD at %p:\n"
 2427                "actual %04x, next %04x, buffer %p\n"
 2428                "length %04x, mbz %04x\n",
 2429                (void *) rbd,
 2430                rbd->ie_rbd_actual, rbd->ie_rbd_next,
 2431                (void *) rbd->ie_rbd_buffer,
 2432                rbd->ie_rbd_length, rbd->mbz);
 2433 }
 2434 
 2435 #endif                          /* DEBUG */
 2436 #endif                          /* NIE > 0 */

Cache object: aa7101418026ab086880a8cde2582664


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