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

Cache object: b8e1f1b30d23aca9bf5a2c46064fb1e3


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