Home | History | Annotate | Line # | Download | only in dev
if_ie.c revision 1.17
      1 /*	$NetBSD: if_ie.c,v 1.17 1997/02/13 20:48:36 gwr Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 1993, 1994, 1995 Charles Hannum.
      5  * Copyright (c) 1992, 1993, University of Vermont and State
      6  *  Agricultural College.
      7  * Copyright (c) 1992, 1993, Garrett A. Wollman.
      8  *
      9  * Portions:
     10  * Copyright (c) 1994, 1995, Rafal K. Boni
     11  * Copyright (c) 1990, 1991, William F. Jolitz
     12  * Copyright (c) 1990, The Regents of the University of California
     13  *
     14  * All rights reserved.
     15  *
     16  * Redistribution and use in source and binary forms, with or without
     17  * modification, are permitted provided that the following conditions
     18  * are met:
     19  * 1. Redistributions of source code must retain the above copyright
     20  *    notice, this list of conditions and the following disclaimer.
     21  * 2. Redistributions in binary form must reproduce the above copyright
     22  *    notice, this list of conditions and the following disclaimer in the
     23  *    documentation and/or other materials provided with the distribution.
     24  * 3. All advertising materials mentioning features or use of this software
     25  *    must display the following acknowledgement:
     26  *	This product includes software developed by Charles Hannum, by the
     27  *	University of Vermont and State Agricultural College and Garrett A.
     28  *	Wollman, by William F. Jolitz, and by the University of California,
     29  *	Berkeley, Lawrence Berkeley Laboratory, and its contributors.
     30  * 4. Neither the names of the Universities nor the names of the authors
     31  *    may be used to endorse or promote products derived from this software
     32  *    without specific prior written permission.
     33  *
     34  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     35  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     36  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     37  * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR AUTHORS BE LIABLE
     38  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     39  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     40  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     41  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     42  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     43  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     44  * SUCH DAMAGE.
     45  */
     46 
     47 /*
     48  * Intel 82586 Ethernet chip
     49  * Register, bit, and structure definitions.
     50  *
     51  * Original StarLAN driver written by Garrett Wollman with reference to the
     52  * Clarkson Packet Driver code for this chip written by Russ Nelson and others.
     53  *
     54  * BPF support code taken from hpdev/if_le.c, supplied with tcpdump.
     55  *
     56  * 3C507 support is loosely based on code donated to NetBSD by Rafal Boni.
     57  *
     58  * Majorly cleaned up and 3C507 code merged by Charles Hannum.
     59  *
     60  * Converted to SUN ie driver by Charles D. Cranor,
     61  *		October 1994, January 1995.
     62  * This sun version based on i386 version 1.30.
     63  * [ see sys/dev/isa/if_ie.c ]
     64  */
     65 
     66 /*
     67  * The i82586 is a very painful chip, found in sun3's, sun-4/100's
     68  * sun-4/200's, and VME based suns.  The byte order is all wrong for a
     69  * SUN, making life difficult.  Programming this chip is mostly the same,
     70  * but certain details differ from system to system.  This driver is
     71  * written so that different "ie" interfaces can be controled by the same
     72  * driver.
     73  */
     74 
     75 /*
     76    Mode of operation:
     77 
     78    We run the 82586 in a standard Ethernet mode.  We keep NFRAMES
     79    received frame descriptors around for the receiver to use, and
     80    NRXBUF associated receive buffer descriptors, both in a circular
     81    list.  Whenever a frame is received, we rotate both lists as
     82    necessary.  (The 586 treats both lists as a simple queue.)  We also
     83    keep a transmit command around so that packets can be sent off
     84    quickly.
     85 
     86    We configure the adapter in AL-LOC = 1 mode, which means that the
     87    Ethernet/802.3 MAC header is placed at the beginning of the receive
     88    buffer rather than being split off into various fields in the RFD.
     89    This also means that we must include this header in the transmit
     90    buffer as well.
     91 
     92    By convention, all transmit commands, and only transmit commands,
     93    shall have the I (IE_CMD_INTR) bit set in the command.  This way,
     94    when an interrupt arrives at ieintr(), it is immediately possible
     95    to tell what precisely caused it.  ANY OTHER command-sending
     96    routines should run at splnet(), and should post an acknowledgement
     97    to every interrupt they generate.
     98 */
     99 
    100 #include "bpfilter.h"
    101 
    102 #include <sys/param.h>
    103 #include <sys/systm.h>
    104 #include <sys/mbuf.h>
    105 #include <sys/buf.h>
    106 #include <sys/protosw.h>
    107 #include <sys/socket.h>
    108 #include <sys/ioctl.h>
    109 #include <sys/errno.h>
    110 #include <sys/syslog.h>
    111 #include <sys/device.h>
    112 
    113 #include <net/if.h>
    114 #include <net/if_types.h>
    115 #include <net/if_dl.h>
    116 #include <net/netisr.h>
    117 #include <net/route.h>
    118 
    119 #if NBPFILTER > 0
    120 #include <net/bpf.h>
    121 #include <net/bpfdesc.h>
    122 #endif
    123 
    124 #ifdef INET
    125 #include <netinet/in.h>
    126 #include <netinet/in_systm.h>
    127 #include <netinet/in_var.h>
    128 #include <netinet/ip.h>
    129 #include <netinet/if_ether.h>
    130 #endif
    131 
    132 #ifdef NS
    133 #include <netns/ns.h>
    134 #include <netns/ns_if.h>
    135 #endif
    136 
    137 #include <vm/vm.h>
    138 
    139 #include <machine/autoconf.h>
    140 #include <machine/cpu.h>
    141 #include <machine/pmap.h>
    142 
    143 /*
    144  * ugly byte-order hack for SUNs
    145  */
    146 
    147 #define XSWAP(y)	( (((y)&0xff00) >> 8) | (((y)&0xff) << 8) )
    148 #define SWAP(x)		((u_short)(XSWAP((u_short)(x))))
    149 
    150 #include "i82586.h"
    151 #include "if_iereg.h"
    152 #include "if_ievar.h"
    153 
    154 #define	IEDEBUG	XXX
    155 
    156 /*
    157  * IED: ie debug flags
    158  */
    159 
    160 #define	IED_RINT	0x01
    161 #define	IED_TINT	0x02
    162 #define	IED_RNR		0x04
    163 #define	IED_CNA		0x08
    164 #define	IED_READFRAME	0x10
    165 #define	IED_ENQ		0x20
    166 #define	IED_XMIT	0x40
    167 #define	IED_ALL		0x7f
    168 
    169 #define	ETHER_MIN_LEN	64
    170 #define	ETHER_MAX_LEN	1518
    171 #define	ETHER_ADDR_LEN	6
    172 
    173 #ifdef	IEDEBUG
    174 #define	inline	/* not */
    175 void print_rbd __P((volatile struct ie_recv_buf_desc *));
    176 int     in_ierint = 0;
    177 int     in_ietint = 0;
    178 int     ie_debug_flags = 0;
    179 #endif
    180 
    181 static void iewatchdog __P((struct ifnet *));
    182 static int ieinit __P((struct ie_softc *));
    183 static int ieioctl __P((struct ifnet *, u_long, caddr_t));
    184 static void iestart __P((struct ifnet *));
    185 static void iereset __P((struct ie_softc *));
    186 static int ie_setupram __P((struct ie_softc *sc));
    187 
    188 static int cmd_and_wait __P((struct ie_softc *, int, void *, int));
    189 
    190 static void ie_drop_packet_buffer __P((struct ie_softc *));
    191 static void ie_readframe __P((struct ie_softc *, int));
    192 static inline void ie_setup_config __P((struct ie_config_cmd *, int, int));
    193 
    194 static void ierint __P((struct ie_softc *));
    195 static void iestop __P((struct ie_softc *));
    196 static void ietint __P((struct ie_softc *));
    197 static void iexmit __P((struct ie_softc *));
    198 
    199 static int mc_setup __P((struct ie_softc *, void *));
    200 static void mc_reset __P((struct ie_softc *));
    201 static void run_tdr __P((struct ie_softc *, struct ie_tdr_cmd *));
    202 static void iememinit __P((struct ie_softc *));
    203 
    204 static inline char * Align __P((char *));
    205 static inline u_int Swap32 __P((u_int x));
    206 static inline u_int vtop24 __P((struct ie_softc *, void *));
    207 static inline u_short vtop16sw __P((struct ie_softc *, void *));
    208 
    209 static inline void ie_ack __P((struct ie_softc *, u_int));
    210 static inline u_short ether_cmp __P((u_char *, u_char *));
    211 static inline int check_eh __P((struct ie_softc *,
    212 		struct ether_header *eh, int *));
    213 static inline int ie_buflen __P((struct ie_softc *, int));
    214 static inline int ie_packet_len __P((struct ie_softc *));
    215 static inline struct mbuf * ieget __P((struct ie_softc *sc,
    216 		struct ether_header *ehp, int *to_bpf));
    217 
    218 
    219 struct cfdriver ie_cd = {
    220 	NULL, "ie", DV_IFNET
    221 };
    222 
    223 /*
    224  * Here are a few useful functions.  We could have done these as macros,
    225  * but since we have the inline facility, it makes sense to use that
    226  * instead.
    227  */
    228 
    229 /* KVA to 24 bit device address */
    230 static inline u_int
    231 vtop24(sc, ptr)
    232 	struct ie_softc *sc;
    233 	void *ptr;
    234 {
    235 	u_int pa;
    236 
    237 	pa = ((caddr_t)ptr) - sc->sc_iobase;
    238 #ifdef	IEDEBUG
    239 	if (pa & ~0xffFFff)
    240 		panic("ie:vtop24");
    241 #endif
    242 	return (pa);
    243 }
    244 
    245 /* KVA to 16 bit offset, swapped */
    246 static inline u_short
    247 vtop16sw(sc, ptr)
    248 	struct ie_softc *sc;
    249 	void *ptr;
    250 {
    251 	u_int pa;
    252 
    253 	pa = ((caddr_t)ptr) - sc->sc_maddr;
    254 #ifdef	IEDEBUG
    255 	if (pa & ~0xFFff)
    256 		panic("ie:vtop16");
    257 #endif
    258 
    259 	return (SWAP(pa));
    260 }
    261 
    262 static inline u_int
    263 Swap32(x)
    264 	u_int x;
    265 {
    266 	u_int y;
    267 
    268 	y = x & 0xFF;
    269 	y <<= 8; x >>= 8;
    270 	y |= x & 0xFF;
    271 	y <<= 8; x >>= 8;
    272 	y |= x & 0xFF;
    273 	y <<= 8; x >>= 8;
    274 	y |= x & 0xFF;
    275 
    276 	return (y);
    277 }
    278 
    279 static inline char *
    280 Align(ptr)
    281 	caddr_t ptr;
    282 {
    283 	u_long  l = (u_long)ptr;
    284 
    285 	l = (l + 3) & ~3L;
    286 	return ((char *)l);
    287 }
    288 
    289 
    290 static inline void
    291 ie_ack(sc, mask)
    292 	struct ie_softc *sc;
    293 	u_int mask;
    294 {
    295 	volatile struct ie_sys_ctl_block *scb = sc->scb;
    296 
    297 	cmd_and_wait(sc, scb->ie_status & mask, 0, 0);
    298 }
    299 
    300 
    301 /*
    302  * Taken almost exactly from Bill's if_is.c,
    303  * then modified beyond recognition...
    304  */
    305 void
    306 ie_attach(sc)
    307 	struct ie_softc *sc;
    308 {
    309 	struct ifnet *ifp = &sc->sc_if;
    310 
    311 	/* MD code has done its part before calling this. */
    312 	printf(": macaddr %s\n", ether_sprintf(sc->sc_addr));
    313 
    314 	/*
    315 	 * Compute number of transmit and receive buffers.
    316 	 * Tx buffers take 1536 bytes, and fixed in number.
    317 	 * Rx buffers are 512 bytes each, variable number.
    318 	 * Need at least 1 frame for each 3 rx buffers.
    319 	 * The ratio 3bufs:2frames is a compromise.
    320 	 */
    321 	sc->ntxbuf = NTXBUF;	/* XXX - Fix me... */
    322 	switch (sc->sc_msize) {
    323 	case 16384:
    324 		sc->nframes = 8 * 4;
    325 		sc->nrxbuf  = 8 * 6;
    326 		break;
    327 	case 32768:
    328 		sc->nframes = 16 * 4;
    329 		sc->nrxbuf  = 16 * 6;
    330 		break;
    331 	case 65536:
    332 		sc->nframes = 32 * 4;
    333 		sc->nrxbuf  = 32 * 6;
    334 		break;
    335 	default:
    336 		sc->nframes = 0;
    337 	}
    338 	if (sc->nframes > MXFRAMES)
    339 		sc->nframes = MXFRAMES;
    340 	if (sc->nrxbuf > MXRXBUF)
    341 		sc->nrxbuf = MXRXBUF;
    342 
    343 	printf("%s: %dK memory, %d tx frames, %d rx frames, %d rx bufs\n",
    344 	    sc->sc_dev.dv_xname, (sc->sc_msize >> 10),
    345 	    sc->ntxbuf, sc->nframes, sc->nrxbuf);
    346 
    347 	if ((sc->nframes <= 0) || (sc->nrxbuf <= 0))
    348 		panic("ie_attach: weird memory size");
    349 
    350 	/*
    351 	 * Setup RAM for transmit/receive
    352 	 */
    353 	if (ie_setupram(sc) == 0) {
    354 		printf(": RAM CONFIG FAILED!\n");
    355 		/* XXX should reclaim resources? */
    356 		return;
    357 	}
    358 
    359 	/*
    360 	 * Initialize and attach S/W interface
    361 	 */
    362 	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
    363 	ifp->if_softc = sc;
    364 	ifp->if_start = iestart;
    365 	ifp->if_ioctl = ieioctl;
    366 	ifp->if_watchdog = iewatchdog;
    367 	ifp->if_flags =
    368 	    IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
    369 
    370 	/* Attach the interface. */
    371 	if_attach(ifp);
    372 	ether_ifattach(ifp);
    373 #if NBPFILTER > 0
    374 	bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
    375 #endif
    376 }
    377 
    378 /*
    379  * Setup IE's ram space.
    380  */
    381 static int
    382 ie_setupram(sc)
    383 	struct ie_softc *sc;
    384 {
    385 	volatile struct ie_sys_conf_ptr *scp;
    386 	volatile struct ie_int_sys_conf_ptr *iscp;
    387 	volatile struct ie_sys_ctl_block *scb;
    388 	int off;
    389 
    390 	/*
    391 	 * Allocate from end of buffer space for
    392 	 * ISCP, SCB, and other small stuff.
    393 	 */
    394 	off = sc->buf_area_sz;
    395 	off &= ~3;
    396 
    397 	/* SCP (address already chosen). */
    398 	scp = sc->scp;
    399 	(sc->sc_bzero)((char *) scp, sizeof(*scp));
    400 
    401 	/* ISCP */
    402 	off -= sizeof(*iscp);
    403 	iscp = (volatile void *) (sc->buf_area + off);
    404 	(sc->sc_bzero)((char *) iscp, sizeof(*iscp));
    405 	sc->iscp = iscp;
    406 
    407 	/* SCB */
    408 	off -= sizeof(*scb);
    409 	scb  = (volatile void *) (sc->buf_area + off);
    410 	(sc->sc_bzero)((char *) scb, sizeof(*scb));
    411 	sc->scb = scb;
    412 
    413 	/* Remainder is for buffers, etc. */
    414 	sc->buf_area_sz = off;
    415 
    416 	/*
    417 	 * Now fill in the structures we just allocated.
    418 	 */
    419 
    420 	/* SCP: main thing is 24-bit ptr to ISCP */
    421 	scp->ie_bus_use = 0;	/* 16-bit */
    422 	scp->ie_iscp_ptr = Swap32(vtop24(sc, (void*)iscp));
    423 
    424 	/* ISCP */
    425 	iscp->ie_busy = 1;	/* ie_busy == char */
    426 	iscp->ie_scb_offset = vtop16sw(sc, (void*)scb);
    427 	iscp->ie_base = Swap32(vtop24(sc, sc->sc_maddr));
    428 
    429 	/* SCB */
    430 	scb->ie_command_list = SWAP(0xffff);
    431 	scb->ie_recv_list    = SWAP(0xffff);
    432 
    433 	/* Other stuff is done in ieinit() */
    434 	(sc->reset_586) (sc);
    435 	(sc->chan_attn) (sc);
    436 
    437 	delay(100);		/* wait a while... */
    438 
    439 	if (iscp->ie_busy) {
    440 		return 0;
    441 	}
    442 	/*
    443 	 * Acknowledge any interrupts we may have caused...
    444 	 */
    445 	ie_ack(sc, IE_ST_WHENCE);
    446 
    447 	return 1;
    448 }
    449 
    450 /*
    451  * Device timeout/watchdog routine.  Entered if the device neglects to
    452  * generate an interrupt after a transmit has been started on it.
    453  */
    454 static void
    455 iewatchdog(ifp)
    456 	struct ifnet *ifp;
    457 {
    458 	struct ie_softc *sc = ifp->if_softc;
    459 
    460 	log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
    461 	++sc->sc_arpcom.ac_if.if_oerrors;
    462 	iereset(sc);
    463 }
    464 
    465 /*
    466  * What to do upon receipt of an interrupt.
    467  */
    468 int
    469 ie_intr(arg)
    470 	void *arg;
    471 {
    472 	struct ie_softc *sc = arg;
    473 	register u_short status;
    474 	int loopcnt;
    475 
    476 	/*
    477 	 * check for parity error
    478 	 */
    479 	if (sc->hard_type == IE_VME) {
    480 		volatile struct ievme *iev = (volatile struct ievme *)sc->sc_reg;
    481 		if (iev->status & IEVME_PERR) {
    482 			printf("%s: parity error (ctrl %x @ %02x%04x)\n",
    483 			    sc->sc_dev.dv_xname, iev->pectrl,
    484 			    iev->pectrl & IEVME_HADDR, iev->peaddr);
    485 			iev->pectrl = iev->pectrl | IEVME_PARACK;
    486 		}
    487 	}
    488 
    489 	status = sc->scb->ie_status & IE_ST_WHENCE;
    490 	if (status == 0)
    491 		return 0;
    492 
    493 	loopcnt = 5;
    494 loop:
    495 	/* Ack interrupts FIRST in case we receive more during the ISR. */
    496 	ie_ack(sc, status);
    497 
    498 	if (status & (IE_ST_RECV | IE_ST_RNR)) {
    499 #ifdef IEDEBUG
    500 		in_ierint++;
    501 		if (sc->sc_debug & IED_RINT)
    502 			printf("%s: rint\n", sc->sc_dev.dv_xname);
    503 #endif
    504 		ierint(sc);
    505 #ifdef IEDEBUG
    506 		in_ierint--;
    507 #endif
    508 	}
    509 
    510 	if (status & IE_ST_DONE) {
    511 #ifdef IEDEBUG
    512 		in_ietint++;
    513 		if (sc->sc_debug & IED_TINT)
    514 			printf("%s: tint\n", sc->sc_dev.dv_xname);
    515 #endif
    516 		ietint(sc);
    517 #ifdef IEDEBUG
    518 		in_ietint--;
    519 #endif
    520 	}
    521 
    522 	/*
    523 	 * Receiver not ready (RNR) just means it is
    524 	 * out of resources (buffers or frames).
    525 	 * You can cause this with spray if desired.
    526 	 * XXX: Maybe this error should be silent...
    527 	 */
    528 	if (status & IE_ST_RNR) {
    529 		printf("%s: receiver not ready\n", sc->sc_dev.dv_xname);
    530 		sc->sc_arpcom.ac_if.if_ierrors++;
    531 		iereset(sc);
    532 	}
    533 
    534 #ifdef IEDEBUG
    535 	if ((status & IE_ST_ALLDONE) && (sc->sc_debug & IED_CNA))
    536 		printf("%s: cna\n", sc->sc_dev.dv_xname);
    537 #endif
    538 
    539 	status = sc->scb->ie_status & IE_ST_WHENCE;
    540 	if (status) {
    541 		if (--loopcnt > 0)
    542 			goto loop;
    543 		printf("%s: interrupt stuck?\n", sc->sc_dev.dv_xname);
    544 		iereset(sc);
    545 	}
    546 	return 1;
    547 }
    548 
    549 /*
    550  * Process a received-frame interrupt.
    551  */
    552 void
    553 ierint(sc)
    554 	struct ie_softc *sc;
    555 {
    556 	volatile struct ie_sys_ctl_block *scb = sc->scb;
    557 	int i, status;
    558 	static int timesthru = 1024;
    559 
    560 	i = sc->rfhead;
    561 	for (;;) {
    562 		status = sc->rframes[i]->ie_fd_status;
    563 
    564 		if ((status & IE_FD_COMPLETE) && (status & IE_FD_OK)) {
    565 			if (!--timesthru) {
    566 				sc->sc_arpcom.ac_if.if_ierrors +=
    567 				    SWAP(scb->ie_err_crc) +
    568 				    SWAP(scb->ie_err_align) +
    569 				    SWAP(scb->ie_err_resource) +
    570 				    SWAP(scb->ie_err_overrun);
    571 				scb->ie_err_crc = 0;
    572 				scb->ie_err_align = 0;
    573 				scb->ie_err_resource = 0;
    574 				scb->ie_err_overrun = 0;
    575 				timesthru = 1024;
    576 			}
    577 			ie_readframe(sc, i);
    578 		} else {
    579 			if ((status & IE_FD_RNR) != 0 &&
    580 			    (scb->ie_status & IE_RU_READY) == 0) {
    581 				sc->rframes[0]->ie_fd_buf_desc =
    582 					vtop16sw(sc, (void*) sc->rbuffs[0]);
    583 				scb->ie_recv_list =
    584 					vtop16sw(sc, (void*) sc->rframes[0]);
    585 				cmd_and_wait(sc, IE_RU_START, 0, 0);
    586 			}
    587 			break;
    588 		}
    589 		i = (i + 1) % sc->nframes;
    590 	}
    591 }
    592 
    593 /*
    594  * Process a command-complete interrupt.  These are only generated by the
    595  * transmission of frames.  This routine is deceptively simple, since most
    596  * of the real work is done by iestart().
    597  */
    598 void
    599 ietint(sc)
    600 	struct ie_softc *sc;
    601 {
    602 	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
    603 	int status;
    604 
    605 	ifp->if_timer = 0;
    606 	ifp->if_flags &= ~IFF_OACTIVE;
    607 
    608 	status = sc->xmit_cmds[sc->xctail]->ie_xmit_status;
    609 
    610 	if (!(status & IE_STAT_COMPL) || (status & IE_STAT_BUSY))
    611 		printf("ietint: command still busy!\n");
    612 
    613 	if (status & IE_STAT_OK) {
    614 		ifp->if_opackets++;
    615 		ifp->if_collisions +=
    616 		  SWAP(status & IE_XS_MAXCOLL);
    617 	} else {
    618 		ifp->if_oerrors++;
    619 		/*
    620 		 * XXX
    621 		 * Check SQE and DEFERRED?
    622 		 * What if more than one bit is set?
    623 		 */
    624 		if (status & IE_STAT_ABORT)
    625 			printf("%s: send aborted\n", sc->sc_dev.dv_xname);
    626 		if (status & IE_XS_LATECOLL)
    627 			printf("%s: late collision\n", sc->sc_dev.dv_xname);
    628 		if (status & IE_XS_NOCARRIER)
    629 			printf("%s: no carrier\n", sc->sc_dev.dv_xname);
    630 		if (status & IE_XS_LOSTCTS)
    631 			printf("%s: lost CTS\n", sc->sc_dev.dv_xname);
    632 		if (status & IE_XS_UNDERRUN)
    633 			printf("%s: DMA underrun\n", sc->sc_dev.dv_xname);
    634 		if (status & IE_XS_EXCMAX) {
    635 			printf("%s: too many collisions\n", sc->sc_dev.dv_xname);
    636 			ifp->if_collisions += 16;
    637 		}
    638 	}
    639 
    640 	/*
    641 	 * If multicast addresses were added or deleted while we
    642 	 * were transmitting, mc_reset() set the want_mcsetup flag
    643 	 * indicating that we should do it.
    644 	 */
    645 	if (sc->want_mcsetup) {
    646 		mc_setup(sc, (caddr_t)sc->xmit_cbuffs[sc->xctail]);
    647 		sc->want_mcsetup = 0;
    648 	}
    649 
    650 	/* Done with the buffer. */
    651 	sc->xmit_busy--;
    652 	sc->xctail = (sc->xctail + 1) % NTXBUF;
    653 
    654 	/* Start the next packet, if any, transmitting. */
    655 	if (sc->xmit_busy > 0)
    656 		iexmit(sc);
    657 
    658 	iestart(ifp);
    659 }
    660 
    661 /*
    662  * Compare two Ether/802 addresses for equality, inlined and
    663  * unrolled for speed.  I'd love to have an inline assembler
    664  * version of this...   XXX: Who wanted that? mycroft?
    665  * I wrote one, but the following is just as efficient.
    666  * This expands to 10 short m68k instructions! -gwr
    667  * Note: use this like bcmp()
    668  */
    669 static inline u_short
    670 ether_cmp(one, two)
    671 	u_char *one, *two;
    672 {
    673 	register u_short *a = (u_short *) one;
    674 	register u_short *b = (u_short *) two;
    675 	register u_short diff;
    676 
    677 	diff  = *a++ - *b++;
    678 	diff |= *a++ - *b++;
    679 	diff |= *a++ - *b++;
    680 
    681 	return (diff);
    682 }
    683 #define	ether_equal !ether_cmp
    684 
    685 /*
    686  * Check for a valid address.  to_bpf is filled in with one of the following:
    687  *   0 -> BPF doesn't get this packet
    688  *   1 -> BPF does get this packet
    689  *   2 -> BPF does get this packet, but we don't
    690  * Return value is true if the packet is for us, and false otherwise.
    691  *
    692  * This routine is a mess, but it's also critical that it be as fast
    693  * as possible.  It could be made cleaner if we can assume that the
    694  * only client which will fiddle with IFF_PROMISC is BPF.  This is
    695  * probably a good assumption, but we do not make it here.  (Yet.)
    696  */
    697 static inline int
    698 check_eh(sc, eh, to_bpf)
    699 	struct ie_softc *sc;
    700 	struct ether_header *eh;
    701 	int *to_bpf;
    702 {
    703 	int i;
    704 
    705 	switch (sc->promisc) {
    706 	case IFF_ALLMULTI:
    707 		/*
    708 		 * Receiving all multicasts, but no unicasts except those
    709 		 * destined for us.
    710 		 */
    711 #if NBPFILTER > 0
    712 		/* BPF gets this packet if anybody cares */
    713 		*to_bpf = (sc->sc_arpcom.ac_if.if_bpf != 0);
    714 #endif
    715 		if (eh->ether_dhost[0] & 1)
    716 			return 1;
    717 		if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr))
    718 			return 1;
    719 		return 0;
    720 
    721 	case IFF_PROMISC:
    722 		/*
    723 		 * Receiving all packets.  These need to be passed on to BPF.
    724 		 */
    725 #if NBPFILTER > 0
    726 		*to_bpf = (sc->sc_arpcom.ac_if.if_bpf != 0);
    727 #endif
    728 		/* If for us, accept and hand up to BPF */
    729 		if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr))
    730 			return 1;
    731 
    732 #if NBPFILTER > 0
    733 		if (*to_bpf)
    734 			*to_bpf = 2;	/* we don't need to see it */
    735 #endif
    736 
    737 		/*
    738 		 * Not a multicast, so BPF wants to see it but we don't.
    739 		 */
    740 		if (!(eh->ether_dhost[0] & 1))
    741 			return 1;
    742 
    743 		/*
    744 		 * If it's one of our multicast groups, accept it and pass it
    745 		 * up.
    746 		 */
    747 		for (i = 0; i < sc->mcast_count; i++) {
    748 			if (ether_equal(eh->ether_dhost,
    749 			    (u_char *)&sc->mcast_addrs[i])) {
    750 #if NBPFILTER > 0
    751 				if (*to_bpf)
    752 					*to_bpf = 1;
    753 #endif
    754 				return 1;
    755 			}
    756 		}
    757 		return 1;
    758 
    759 	case IFF_ALLMULTI | IFF_PROMISC:
    760 		/*
    761 		 * Acting as a multicast router, and BPF running at the same
    762 		 * time.  Whew!  (Hope this is a fast machine...)
    763 		 */
    764 #if NBPFILTER > 0
    765 		*to_bpf = (sc->sc_arpcom.ac_if.if_bpf != 0);
    766 #endif
    767 		/* We want to see multicasts. */
    768 		if (eh->ether_dhost[0] & 1)
    769 			return 1;
    770 
    771 		/* We want to see our own packets */
    772 		if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr))
    773 			return 1;
    774 
    775 		/* Anything else goes to BPF but nothing else. */
    776 #if NBPFILTER > 0
    777 		if (*to_bpf)
    778 			*to_bpf = 2;
    779 #endif
    780 		return 1;
    781 
    782 	case 0:
    783 		/*
    784 		 * Only accept unicast packets destined for us, or multicasts
    785 		 * for groups that we belong to.  For now, we assume that the
    786 		 * '586 will only return packets that we asked it for.  This
    787 		 * isn't strictly true (it uses hashing for the multicast filter),
    788 		 * but it will do in this case, and we want to get out of here
    789 		 * as quickly as possible.
    790 		 */
    791 #if NBPFILTER > 0
    792 		*to_bpf = (sc->sc_arpcom.ac_if.if_bpf != 0);
    793 #endif
    794 		return 1;
    795 	}
    796 #ifdef	DIAGNOSTIC
    797 	panic("ie: check_eh, impossible");
    798 #endif
    799 	return 0;
    800 }
    801 
    802 /*
    803  * We want to isolate the bits that have meaning...  This assumes that
    804  * IE_RBUF_SIZE is an even power of two.  If somehow the act_len exceeds
    805  * the size of the buffer, then we are screwed anyway.
    806  */
    807 static inline int
    808 ie_buflen(sc, head)
    809 	struct ie_softc *sc;
    810 	int head;
    811 {
    812 	register int len;
    813 
    814 	len = SWAP(sc->rbuffs[head]->ie_rbd_actual);
    815 	len &= (IE_RBUF_SIZE | (IE_RBUF_SIZE - 1));
    816 	return (len);
    817 }
    818 
    819 static inline int
    820 ie_packet_len(sc)
    821 	struct ie_softc *sc;
    822 {
    823 	int i;
    824 	int head = sc->rbhead;
    825 	int acc = 0;
    826 
    827 	do {
    828 		if (!(sc->rbuffs[sc->rbhead]->ie_rbd_actual & IE_RBD_USED)) {
    829 #ifdef IEDEBUG
    830 			print_rbd(sc->rbuffs[sc->rbhead]);
    831 #endif
    832 			log(LOG_ERR, "%s: receive descriptors out of sync at %d\n",
    833 			    sc->sc_dev.dv_xname, sc->rbhead);
    834 			iereset(sc);
    835 			return -1;
    836 		}
    837 
    838 		i = sc->rbuffs[head]->ie_rbd_actual & IE_RBD_LAST;
    839 
    840 		acc += ie_buflen(sc, head);
    841 		head = (head + 1) % sc->nrxbuf;
    842 	} while (!i);
    843 
    844 	return acc;
    845 }
    846 
    847 /*
    848  * Setup all necessary artifacts for an XMIT command, and then pass the XMIT
    849  * command to the chip to be executed.  On the way, if we have a BPF listener
    850  * also give him a copy.
    851  */
    852 static void
    853 iexmit(sc)
    854 	struct ie_softc *sc;
    855 {
    856 
    857 #ifdef IEDEBUG
    858 	if (sc->sc_debug & IED_XMIT)
    859 		printf("%s: xmit buffer %d\n", sc->sc_dev.dv_xname,
    860 		    sc->xctail);
    861 #endif
    862 
    863 #if NBPFILTER > 0
    864 	/*
    865 	 * If BPF is listening on this interface, let it see the packet before
    866 	 * we push it on the wire.
    867 	 */
    868 	if (sc->sc_arpcom.ac_if.if_bpf)
    869 		bpf_tap(sc->sc_arpcom.ac_if.if_bpf,
    870 		    sc->xmit_cbuffs[sc->xctail],
    871 		    SWAP(sc->xmit_buffs[sc->xctail]->ie_xmit_flags));
    872 #endif
    873 
    874 	sc->xmit_buffs[sc->xctail]->ie_xmit_flags |= IE_XMIT_LAST;
    875 	sc->xmit_buffs[sc->xctail]->ie_xmit_next = SWAP(0xffff);
    876 	sc->xmit_buffs[sc->xctail]->ie_xmit_buf =
    877 	    Swap32(vtop24(sc, sc->xmit_cbuffs[sc->xctail]));
    878 
    879 	sc->xmit_cmds[sc->xctail]->com.ie_cmd_link = SWAP(0xffff);
    880 	sc->xmit_cmds[sc->xctail]->com.ie_cmd_cmd =
    881 	    IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST;
    882 
    883 	sc->xmit_cmds[sc->xctail]->ie_xmit_status = SWAP(0);
    884 	sc->xmit_cmds[sc->xctail]->ie_xmit_desc =
    885 	    vtop16sw(sc, (void*) sc->xmit_buffs[sc->xctail]);
    886 
    887 	sc->scb->ie_command_list =
    888 	    vtop16sw(sc, (void*) sc->xmit_cmds[sc->xctail]);
    889 	cmd_and_wait(sc, IE_CU_START, 0, 0);
    890 
    891 	sc->sc_arpcom.ac_if.if_timer = 5;
    892 }
    893 
    894 /*
    895  * Read data off the interface, and turn it into an mbuf chain.
    896  *
    897  * This code is DRAMATICALLY different from the previous version; this
    898  * version tries to allocate the entire mbuf chain up front, given the
    899  * length of the data available.  This enables us to allocate mbuf
    900  * clusters in many situations where before we would have had a long
    901  * chain of partially-full mbufs.  This should help to speed up the
    902  * operation considerably.  (Provided that it works, of course.)
    903  */
    904 static inline struct mbuf *
    905 ieget(sc, ehp, to_bpf)
    906 	struct ie_softc *sc;
    907 	struct ether_header *ehp;
    908 	int *to_bpf;
    909 {
    910 	struct mbuf *top, **mp, *m;
    911 	int len, totlen, resid;
    912 	int thisrboff, thismboff;
    913 	int head;
    914 
    915 	totlen = ie_packet_len(sc);
    916 	if (totlen <= 0)
    917 		return 0;
    918 
    919 	head = sc->rbhead;
    920 
    921 	/*
    922 	 * Snarf the Ethernet header.
    923 	 */
    924 	(sc->sc_bcopy)((caddr_t)sc->cbuffs[head], (caddr_t)ehp, sizeof *ehp);
    925 
    926 	/*
    927 	 * As quickly as possible, check if this packet is for us.
    928 	 * If not, don't waste a single cycle copying the rest of the
    929 	 * packet in.
    930 	 * This is only a consideration when FILTER is defined; i.e., when
    931 	 * we are either running BPF or doing multicasting.
    932 	 */
    933 	if (!check_eh(sc, ehp, to_bpf)) {
    934 		/* just this case, it's not an error */
    935 		sc->sc_arpcom.ac_if.if_ierrors--;
    936 		return 0;
    937 	}
    938 
    939 	resid = totlen -= (thisrboff = sizeof *ehp);
    940 
    941 	MGETHDR(m, M_DONTWAIT, MT_DATA);
    942 	if (m == 0)
    943 		return 0;
    944 
    945 	m->m_pkthdr.rcvif = &sc->sc_arpcom.ac_if;
    946 	m->m_pkthdr.len = totlen;
    947 	len = MHLEN;
    948 	top = 0;
    949 	mp = &top;
    950 
    951 	/*
    952 	 * This loop goes through and allocates mbufs for all the data we will
    953 	 * be copying in.  It does not actually do the copying yet.
    954 	 */
    955 	while (totlen > 0) {
    956 		if (top) {
    957 			MGET(m, M_DONTWAIT, MT_DATA);
    958 			if (m == 0) {
    959 				m_freem(top);
    960 				return 0;
    961 			}
    962 			len = MLEN;
    963 		}
    964 		if (totlen >= MINCLSIZE) {
    965 			MCLGET(m, M_DONTWAIT);
    966 			if (m->m_flags & M_EXT)
    967 				len = MCLBYTES;
    968 		}
    969 		m->m_len = len = min(totlen, len);
    970 		totlen -= len;
    971 		*mp = m;
    972 		mp = &m->m_next;
    973 	}
    974 
    975 	m = top;
    976 	thismboff = 0;
    977 
    978 	/*
    979 	 * Now we take the mbuf chain (hopefully only one mbuf most of the
    980 	 * time) and stuff the data into it.  There are no possible failures
    981 	 * at or after this point.
    982 	 */
    983 	while (resid > 0) {
    984 		int thisrblen = ie_buflen(sc, head) - thisrboff;
    985 		int thismblen = m->m_len - thismboff;
    986 
    987 		len = min(thisrblen, thismblen);
    988 		(sc->sc_bcopy)((caddr_t)(sc->cbuffs[head] + thisrboff),
    989 		    mtod(m, caddr_t) + thismboff, (u_int)len);
    990 		resid -= len;
    991 
    992 		if (len == thismblen) {
    993 			m = m->m_next;
    994 			thismboff = 0;
    995 		} else
    996 			thismboff += len;
    997 
    998 		if (len == thisrblen) {
    999 			head = (head + 1) % sc->nrxbuf;
   1000 			thisrboff = 0;
   1001 		} else
   1002 			thisrboff += len;
   1003 	}
   1004 
   1005 	/*
   1006 	 * Unless something changed strangely while we were doing the copy,
   1007 	 * we have now copied everything in from the shared memory.
   1008 	 * This means that we are done.
   1009 	 */
   1010 	return top;
   1011 }
   1012 
   1013 /*
   1014  * Read frame NUM from unit UNIT (pre-cached as IE).
   1015  *
   1016  * This routine reads the RFD at NUM, and copies in the buffers from
   1017  * the list of RBD, then rotates the RBD and RFD lists so that the receiver
   1018  * doesn't start complaining.  Trailers are DROPPED---there's no point
   1019  * in wasting time on confusing code to deal with them.  Hopefully,
   1020  * this machine will never ARP for trailers anyway.
   1021  */
   1022 static void
   1023 ie_readframe(sc, num)
   1024 	struct ie_softc *sc;
   1025 	int num;			/* frame number to read */
   1026 {
   1027 	int status;
   1028 	struct mbuf *m = 0;
   1029 	struct ether_header eh;
   1030 #if NBPFILTER > 0
   1031 	int bpf_gets_it = 0;
   1032 #endif
   1033 
   1034 	status = sc->rframes[num]->ie_fd_status;
   1035 
   1036 	/* Advance the RFD list, since we're done with this descriptor. */
   1037 	sc->rframes[num]->ie_fd_status = SWAP(0);
   1038 	sc->rframes[num]->ie_fd_last |= IE_FD_LAST;
   1039 	sc->rframes[sc->rftail]->ie_fd_last &= ~IE_FD_LAST;
   1040 	sc->rftail = (sc->rftail + 1) % sc->nframes;
   1041 	sc->rfhead = (sc->rfhead + 1) % sc->nframes;
   1042 
   1043 	if (status & IE_FD_OK) {
   1044 #if NBPFILTER > 0
   1045 		m = ieget(sc, &eh, &bpf_gets_it);
   1046 #else
   1047 		m = ieget(sc, &eh, 0);
   1048 #endif
   1049 		ie_drop_packet_buffer(sc);
   1050 	}
   1051 	if (m == 0) {
   1052 		sc->sc_arpcom.ac_if.if_ierrors++;
   1053 		return;
   1054 	}
   1055 
   1056 #ifdef IEDEBUG
   1057 	if (sc->sc_debug & IED_READFRAME)
   1058 		printf("%s: frame from ether %s type %x\n", sc->sc_dev.dv_xname,
   1059 		    ether_sprintf(eh.ether_shost), (u_int)eh.ether_type);
   1060 #endif
   1061 
   1062 #if NBPFILTER > 0
   1063 	/*
   1064 	 * Check for a BPF filter; if so, hand it up.
   1065 	 * Note that we have to stick an extra mbuf up front, because
   1066 	 * bpf_mtap expects to have the ether header at the front.
   1067 	 * It doesn't matter that this results in an ill-formatted mbuf chain,
   1068 	 * since BPF just looks at the data.  (It doesn't try to free the mbuf,
   1069 	 * tho' it will make a copy for tcpdump.)
   1070 	 */
   1071 	if (bpf_gets_it) {
   1072 		struct mbuf m0;
   1073 		m0.m_len = sizeof eh;
   1074 		m0.m_data = (caddr_t)&eh;
   1075 		m0.m_next = m;
   1076 
   1077 		/* Pass it up. */
   1078 		bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, &m0);
   1079 
   1080 		/*
   1081 		 * A signal passed up from the filtering code indicating that
   1082 		 * the packet is intended for BPF but not for the protocol
   1083 		 * machinery.  We can save a few cycles by not handing it off
   1084 		 * to them.
   1085 		 */
   1086 		if (bpf_gets_it == 2) {
   1087 			m_freem(m);
   1088 			return;
   1089 		}
   1090 	}
   1091 #endif	/* NBPFILTER > 0 */
   1092 
   1093 	/*
   1094 	 * In here there used to be code to check destination addresses upon
   1095 	 * receipt of a packet.  We have deleted that code, and replaced it
   1096 	 * with code to check the address much earlier in the cycle, before
   1097 	 * copying the data in; this saves us valuable cycles when operating
   1098 	 * as a multicast router or when using BPF.
   1099 	 */
   1100 
   1101 	/*
   1102 	 * Finally pass this packet up to higher layers.
   1103 	 */
   1104 	ether_input(&sc->sc_arpcom.ac_if, &eh, m);
   1105 	sc->sc_arpcom.ac_if.if_ipackets++;
   1106 }
   1107 
   1108 static void
   1109 ie_drop_packet_buffer(sc)
   1110 	struct ie_softc *sc;
   1111 {
   1112 	int i;
   1113 
   1114 	do {
   1115 		/*
   1116 		 * This means we are somehow out of sync.  So, we reset the
   1117 		 * adapter.
   1118 		 */
   1119 		if (!(sc->rbuffs[sc->rbhead]->ie_rbd_actual & IE_RBD_USED)) {
   1120 #ifdef IEDEBUG
   1121 			print_rbd(sc->rbuffs[sc->rbhead]);
   1122 #endif
   1123 			log(LOG_ERR, "%s: receive descriptors out of sync at %d\n",
   1124 			    sc->sc_dev.dv_xname, sc->rbhead);
   1125 			iereset(sc);
   1126 			return;
   1127 		}
   1128 
   1129 		i = sc->rbuffs[sc->rbhead]->ie_rbd_actual & IE_RBD_LAST;
   1130 
   1131 		sc->rbuffs[sc->rbhead]->ie_rbd_length |= IE_RBD_LAST;
   1132 		sc->rbuffs[sc->rbhead]->ie_rbd_actual = SWAP(0);
   1133 		sc->rbhead = (sc->rbhead + 1) % sc->nrxbuf;
   1134 		sc->rbuffs[sc->rbtail]->ie_rbd_length &= ~IE_RBD_LAST;
   1135 		sc->rbtail = (sc->rbtail + 1) % sc->nrxbuf;
   1136 	} while (!i);
   1137 }
   1138 
   1139 /*
   1140  * Start transmission on an interface.
   1141  */
   1142 static void
   1143 iestart(ifp)
   1144 	struct ifnet *ifp;
   1145 {
   1146 	struct ie_softc *sc = ifp->if_softc;
   1147 	struct mbuf *m0, *m;
   1148 	u_char *buffer;
   1149 	u_short len;
   1150 
   1151 	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
   1152 		return;
   1153 
   1154 	for (;;) {
   1155 		if (sc->xmit_busy == sc->ntxbuf) {
   1156 			ifp->if_flags |= IFF_OACTIVE;
   1157 			break;
   1158 		}
   1159 
   1160 		IF_DEQUEUE(&ifp->if_snd, m0);
   1161 		if (m0 == 0)
   1162 			break;
   1163 
   1164 		/* We need to use m->m_pkthdr.len, so require the header */
   1165 		if ((m0->m_flags & M_PKTHDR) == 0)
   1166 			panic("iestart: no header mbuf");
   1167 
   1168 #if NBPFILTER > 0
   1169 		/* Tap off here if there is a BPF listener. */
   1170 		if (ifp->if_bpf)
   1171 			bpf_mtap(ifp->if_bpf, m0);
   1172 #endif
   1173 
   1174 #ifdef IEDEBUG
   1175 		if (sc->sc_debug & IED_ENQ)
   1176 			printf("%s: fill buffer %d\n", sc->sc_dev.dv_xname,
   1177 			    sc->xchead);
   1178 #endif
   1179 
   1180 		buffer = sc->xmit_cbuffs[sc->xchead];
   1181 		for (m = m0; m != 0; m = m->m_next) {
   1182 			(sc->sc_bcopy)(mtod(m, caddr_t), buffer, m->m_len);
   1183 			buffer += m->m_len;
   1184 		}
   1185 		len = max(m0->m_pkthdr.len, ETHER_MIN_LEN);
   1186 
   1187 		m_freem(m0);
   1188 		sc->xmit_buffs[sc->xchead]->ie_xmit_flags = SWAP(len);
   1189 
   1190 		/* Start the first packet transmitting. */
   1191 		if (sc->xmit_busy == 0)
   1192 			iexmit(sc);
   1193 
   1194 		sc->xchead = (sc->xchead + 1) % sc->ntxbuf;
   1195 		sc->xmit_busy++;
   1196 	}
   1197 }
   1198 
   1199 static void
   1200 iereset(sc)
   1201 	struct ie_softc *sc;
   1202 {
   1203 	int s = splnet();
   1204 
   1205 #if 1	/* XXX */
   1206 	printf("%s: reset\n", sc->sc_dev.dv_xname);
   1207 #endif
   1208 	iestop(sc);
   1209 
   1210 	/*
   1211 	 * Stop i82586 dead in its tracks.
   1212 	 */
   1213 	if (cmd_and_wait(sc, IE_RU_ABORT | IE_CU_ABORT, 0, 0))
   1214 		printf("%s: abort commands timed out\n", sc->sc_dev.dv_xname);
   1215 
   1216 	if (cmd_and_wait(sc, IE_RU_DISABLE | IE_CU_STOP, 0, 0))
   1217 		printf("%s: disable commands timed out\n", sc->sc_dev.dv_xname);
   1218 
   1219 	ieinit(sc);
   1220 
   1221 	splx(s);
   1222 }
   1223 
   1224 /*
   1225  * Send a command to the controller and wait for it to either
   1226  * complete or be accepted, depending on the command.  If the
   1227  * command pointer is null, then pretend that the command is
   1228  * not an action command.  If the command pointer is not null,
   1229  * and the command is an action command, wait for
   1230  * ((volatile struct ie_cmd_common *)pcmd)->ie_cmd_status & MASK
   1231  * to become true.
   1232  */
   1233 static int
   1234 cmd_and_wait(sc, cmd, pcmd, mask)
   1235 	struct ie_softc *sc;
   1236 	int cmd;
   1237 	void *pcmd;	/* XXX - Was volatile */
   1238 	int mask;
   1239 {
   1240 	volatile struct ie_cmd_common *cc = pcmd;
   1241 	volatile struct ie_sys_ctl_block *scb = sc->scb;
   1242 	int tmo;
   1243 
   1244 	scb->ie_command = (u_short)cmd;
   1245 	(sc->chan_attn)(sc);
   1246 
   1247 	/* Wait for the command to be accepted by the CU. */
   1248 	tmo = 10;
   1249 	while (scb->ie_command && --tmo)
   1250 		delay(10);
   1251 	if (scb->ie_command) {
   1252 #ifdef	IEDEBUG
   1253 		printf("%s: cmd_and_wait, CU stuck (1)\n",
   1254 		    sc->sc_dev.dv_xname);
   1255 #endif
   1256 		return -1;	/* timed out */
   1257 	}
   1258 
   1259 	/*
   1260 	 * If asked, also wait for it to finish.
   1261 	 */
   1262 	if (IE_ACTION_COMMAND(cmd) && pcmd) {
   1263 
   1264 		/*
   1265 		 * According to the packet driver, the minimum timeout should
   1266 		 * be .369 seconds, which we round up to .4.
   1267 		 */
   1268 		tmo = 36900;
   1269 
   1270 		/*
   1271 		 * Now spin-lock waiting for status.  This is not a very nice
   1272 		 * thing to do, but I haven't figured out how, or indeed if, we
   1273 		 * can put the process waiting for action to sleep.  (We may
   1274 		 * be getting called through some other timeout running in the
   1275 		 * kernel.)
   1276 		 */
   1277 		while (((cc->ie_cmd_status & mask) == 0) && --tmo)
   1278 			delay(10);
   1279 
   1280 		if ((cc->ie_cmd_status & mask) == 0) {
   1281 #ifdef	IEDEBUG
   1282 			printf("%s: cmd_and_wait, CU stuck (2)\n",
   1283 				   sc->sc_dev.dv_xname);
   1284 #endif
   1285 			return -1;	/* timed out */
   1286 		}
   1287 	}
   1288 	return 0;
   1289 }
   1290 
   1291 /*
   1292  * Run the time-domain reflectometer.
   1293  */
   1294 static void
   1295 run_tdr(sc, cmd)
   1296 	struct ie_softc *sc;
   1297 	struct ie_tdr_cmd *cmd;
   1298 {
   1299 	int result;
   1300 
   1301 	cmd->com.ie_cmd_status = SWAP(0);
   1302 	cmd->com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST;
   1303 	cmd->com.ie_cmd_link = SWAP(0xffff);
   1304 
   1305 	sc->scb->ie_command_list = vtop16sw(sc, cmd);
   1306 	cmd->ie_tdr_time = SWAP(0);
   1307 
   1308 	if (cmd_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
   1309 	    !(cmd->com.ie_cmd_status & IE_STAT_OK))
   1310 		result = 0x10000;	/* impossible value */
   1311 	else
   1312 		result = cmd->ie_tdr_time;
   1313 
   1314 	ie_ack(sc, IE_ST_WHENCE);
   1315 
   1316 	if (result & IE_TDR_SUCCESS)
   1317 		return;
   1318 
   1319 	if (result & 0x10000) {
   1320 		printf("%s: TDR command failed\n", sc->sc_dev.dv_xname);
   1321 	} else if (result & IE_TDR_XCVR) {
   1322 		printf("%s: transceiver problem\n", sc->sc_dev.dv_xname);
   1323 	} else if (result & IE_TDR_OPEN) {
   1324 		printf("%s: TDR detected an open %d clocks away\n",
   1325 		    sc->sc_dev.dv_xname, SWAP(result & IE_TDR_TIME));
   1326 	} else if (result & IE_TDR_SHORT) {
   1327 		printf("%s: TDR detected a short %d clocks away\n",
   1328 		    sc->sc_dev.dv_xname, SWAP(result & IE_TDR_TIME));
   1329 	} else {
   1330 		printf("%s: TDR returned unknown status %x\n",
   1331 		    sc->sc_dev.dv_xname, result);
   1332 	}
   1333 }
   1334 
   1335 /*
   1336  * iememinit: set up the buffers
   1337  *
   1338  * we have a block of KVA at sc->buf_area which is of size sc->buf_area_sz.
   1339  * this is to be used for the buffers.  the chip indexs its control data
   1340  * structures with 16 bit offsets, and it indexes actual buffers with
   1341  * 24 bit addresses.   so we should allocate control buffers first so that
   1342  * we don't overflow the 16 bit offset field.   The number of transmit
   1343  * buffers is fixed at compile time.
   1344  *
   1345  * note: this function was written to be easy to understand, rather than
   1346  *       highly efficient (it isn't in the critical path).
   1347  *
   1348  * The memory layout is: tbufs, rbufs, (gap), control blocks
   1349  * [tbuf0, tbuf1] [rbuf0,...rbufN] gap [rframes] [tframes]
   1350  * XXX - This needs review...
   1351  */
   1352 static void
   1353 iememinit(sc)
   1354 	struct ie_softc *sc;
   1355 {
   1356 	char *ptr;
   1357 	int i;
   1358 	u_short nxt;
   1359 
   1360 	/* First, zero all the memory. */
   1361 	ptr = sc->buf_area;
   1362 	(sc->sc_bzero)(ptr, sc->buf_area_sz);
   1363 
   1364 	/* Allocate tx/rx buffers. */
   1365 	for (i = 0; i < NTXBUF; i++) {
   1366 		sc->xmit_cbuffs[i] = ptr;
   1367 		ptr += IE_TBUF_SIZE;
   1368 	}
   1369 	for (i = 0; i < sc->nrxbuf; i++) {
   1370 		sc->cbuffs[i] = ptr;
   1371 		ptr += IE_RBUF_SIZE;
   1372 	}
   1373 
   1374 	/* Small pad (Don't trust the chip...) */
   1375 	ptr += 16;
   1376 
   1377 	/* Allocate and fill in xmit buffer descriptors. */
   1378 	for (i = 0; i < NTXBUF; i++) {
   1379 		sc->xmit_buffs[i] = (volatile void *) ptr;
   1380 		ptr = Align(ptr + sizeof(*sc->xmit_buffs[i]));
   1381 		sc->xmit_buffs[i]->ie_xmit_buf =
   1382 		    Swap32(vtop24(sc, sc->xmit_cbuffs[i]));
   1383 		sc->xmit_buffs[i]->ie_xmit_next = SWAP(0xffff);
   1384 	}
   1385 
   1386 	/* Allocate and fill in recv buffer descriptors. */
   1387 	for (i = 0; i < sc->nrxbuf; i++) {
   1388 		sc->rbuffs[i] = (volatile void *) ptr;
   1389 		ptr = Align(ptr + sizeof(*sc->rbuffs[i]));
   1390 		sc->rbuffs[i]->ie_rbd_buffer =
   1391 			Swap32(vtop24(sc, sc->cbuffs[i]));
   1392 		sc->rbuffs[i]->ie_rbd_length = SWAP(IE_RBUF_SIZE);
   1393 	}
   1394 
   1395 	/* link together recv bufs and set EOL on last */
   1396 	i = sc->nrxbuf - 1;
   1397 	sc->rbuffs[i]->ie_rbd_length |= IE_RBD_LAST;
   1398 	nxt = vtop16sw(sc, (void*) sc->rbuffs[0]);
   1399 	do {
   1400 		sc->rbuffs[i]->ie_rbd_next = nxt;
   1401 		nxt = vtop16sw(sc, (void*) sc->rbuffs[i]);
   1402 	} while (--i >= 0);
   1403 
   1404 	/* Allocate transmit commands. */
   1405 	for (i = 0; i < NTXBUF; i++) {
   1406 		sc->xmit_cmds[i] = (volatile void *) ptr;
   1407 		ptr = Align(ptr + sizeof(*sc->xmit_cmds[i]));
   1408 		sc->xmit_cmds[i]->com.ie_cmd_link = SWAP(0xffff);
   1409 	}
   1410 
   1411 	/* Allocate receive frames. */
   1412 	for (i = 0; i < sc->nframes; i++) {
   1413 		sc->rframes[i] = (volatile void *) ptr;
   1414 		ptr = Align(ptr + sizeof(*sc->rframes[i]));
   1415 	}
   1416 
   1417 	/* Link together recv frames and set EOL on last */
   1418 	i = sc->nframes - 1;
   1419 	sc->rframes[i]->ie_fd_last |= IE_FD_LAST;
   1420 	nxt = vtop16sw(sc, (void*) sc->rframes[0]);
   1421 	do {
   1422 		sc->rframes[i]->ie_fd_next = nxt;
   1423 		nxt = vtop16sw(sc, (void*) sc->rframes[i]);
   1424 	} while (--i >= 0);
   1425 
   1426 
   1427 	/* Pointers to last packet sent and next available transmit buffer. */
   1428 	sc->xchead = sc->xctail = 0;
   1429 
   1430 	/* Clear transmit-busy flag. */
   1431 	sc->xmit_busy = 0;
   1432 
   1433 	/*
   1434 	 * Set the head and tail pointers on receive to keep track of
   1435 	 * the order in which RFDs and RBDs are used.   link the
   1436 	 * recv frames and buffer into the scb.
   1437 	 */
   1438 	sc->rfhead = 0;
   1439 	sc->rftail = sc->nframes - 1;
   1440 	sc->rbhead = 0;
   1441 	sc->rbtail = sc->nrxbuf - 1;
   1442 
   1443 	sc->scb->ie_recv_list =
   1444 	    vtop16sw(sc, (void*) sc->rframes[0]);
   1445 	sc->rframes[0]->ie_fd_buf_desc =
   1446 	    vtop16sw(sc, (void*) sc->rbuffs[0]);
   1447 
   1448 	i = (ptr - sc->buf_area);
   1449 #ifdef IEDEBUG
   1450 	printf("IE_DEBUG: used %d of %d bytes\n", i, sc->buf_area_sz);
   1451 #endif
   1452 	if (i > sc->buf_area_sz)
   1453 		panic("ie: iememinit, out of space");
   1454 }
   1455 
   1456 /*
   1457  * Run the multicast setup command.
   1458  * Called at splnet().
   1459  */
   1460 static int
   1461 mc_setup(sc, ptr)
   1462 	struct ie_softc *sc;
   1463 	void *ptr;
   1464 {
   1465 	struct ie_mcast_cmd *cmd = ptr;	/* XXX - Was volatile */
   1466 
   1467 	cmd->com.ie_cmd_status = SWAP(0);
   1468 	cmd->com.ie_cmd_cmd = IE_CMD_MCAST | IE_CMD_LAST;
   1469 	cmd->com.ie_cmd_link = SWAP(0xffff);
   1470 
   1471 	(sc->sc_bcopy)((caddr_t)sc->mcast_addrs, (caddr_t)cmd->ie_mcast_addrs,
   1472 	    sc->mcast_count * sizeof *sc->mcast_addrs);
   1473 
   1474 	cmd->ie_mcast_bytes =
   1475 		SWAP(sc->mcast_count * ETHER_ADDR_LEN);	/* grrr... */
   1476 
   1477 	sc->scb->ie_command_list = vtop16sw(sc, cmd);
   1478 	if (cmd_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
   1479 	    !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
   1480 		printf("%s: multicast address setup command failed\n",
   1481 		    sc->sc_dev.dv_xname);
   1482 		return 0;
   1483 	}
   1484 	return 1;
   1485 }
   1486 
   1487 static inline void
   1488 ie_setup_config(cmd, promiscuous, manchester)
   1489 	struct ie_config_cmd *cmd;	/* XXX - was volatile */
   1490 	int promiscuous, manchester;
   1491 {
   1492 
   1493 	/*
   1494 	 * these are all char's so no need to byte-swap
   1495 	 */
   1496 	cmd->ie_config_count = 0x0c;
   1497 	cmd->ie_fifo = 8;
   1498 	cmd->ie_save_bad = 0x40;
   1499 	cmd->ie_addr_len = 0x2e;
   1500 	cmd->ie_priority = 0;
   1501 	cmd->ie_ifs = 0x60;
   1502 	cmd->ie_slot_low = 0;
   1503 	cmd->ie_slot_high = 0xf2;
   1504 	cmd->ie_promisc = promiscuous | manchester << 2;
   1505 	cmd->ie_crs_cdt = 0;
   1506 	cmd->ie_min_len = 64;
   1507 	cmd->ie_junk = 0xff;
   1508 }
   1509 
   1510 /*
   1511  * This routine inits the ie.
   1512  * This includes executing the CONFIGURE, IA-SETUP, and MC-SETUP commands,
   1513  * starting the receiver unit, and clearing interrupts.
   1514  *
   1515  * THIS ROUTINE MUST BE CALLED AT splnet() OR HIGHER.
   1516  */
   1517 static int
   1518 ieinit(sc)
   1519 	struct ie_softc *sc;
   1520 {
   1521 	volatile struct ie_sys_ctl_block *scb = sc->scb;
   1522 	void *ptr;
   1523 
   1524 	ptr = sc->buf_area;	/* XXX - Use scb instead? */
   1525 
   1526 	/*
   1527 	 * Send the configure command first.
   1528 	 */
   1529 	{
   1530 		struct ie_config_cmd *cmd = ptr;	/* XXX - Was volatile */
   1531 
   1532 		scb->ie_command_list = vtop16sw(sc, cmd);
   1533 		cmd->com.ie_cmd_status = SWAP(0);
   1534 		cmd->com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST;
   1535 		cmd->com.ie_cmd_link = SWAP(0xffff);
   1536 
   1537 		ie_setup_config(cmd, (sc->promisc != 0), 0);
   1538 
   1539 		if (cmd_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
   1540 		    !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
   1541 			printf("%s: configure command failed\n",
   1542 			    sc->sc_dev.dv_xname);
   1543 			return 0;
   1544 		}
   1545 	}
   1546 
   1547 	/*
   1548 	 * Now send the Individual Address Setup command.
   1549 	 */
   1550 	{
   1551 		struct ie_iasetup_cmd *cmd = ptr;	/* XXX - Was volatile */
   1552 
   1553 		scb->ie_command_list = vtop16sw(sc, cmd);
   1554 		cmd->com.ie_cmd_status = SWAP(0);
   1555 		cmd->com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST;
   1556 		cmd->com.ie_cmd_link = SWAP(0xffff);
   1557 
   1558 		(sc->sc_bcopy)(sc->sc_arpcom.ac_enaddr,
   1559 		    (caddr_t)&cmd->ie_address, sizeof(cmd->ie_address));
   1560 
   1561 		if (cmd_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
   1562 		    !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
   1563 			printf("%s: individual address setup command failed\n",
   1564 			    sc->sc_dev.dv_xname);
   1565 			return 0;
   1566 		}
   1567 	}
   1568 
   1569 	/*
   1570 	 * Now run the time-domain reflectometer.
   1571 	 */
   1572 	run_tdr(sc, ptr);
   1573 
   1574 	/*
   1575 	 * Acknowledge any interrupts we have generated thus far.
   1576 	 */
   1577 	ie_ack(sc, IE_ST_WHENCE);
   1578 
   1579 	/*
   1580 	 * Set up the transmit and recv buffers.
   1581 	 */
   1582 	iememinit(sc);
   1583 
   1584 	/* tell higher levels that we are here */
   1585 	sc->sc_arpcom.ac_if.if_flags |= IFF_RUNNING;
   1586 	sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
   1587 
   1588 	sc->scb->ie_recv_list =
   1589 	    vtop16sw(sc, (void*) sc->rframes[0]);
   1590 	cmd_and_wait(sc, IE_RU_START, 0, 0);
   1591 
   1592 	ie_ack(sc, IE_ST_WHENCE);
   1593 
   1594 	if (sc->run_586)
   1595 		(sc->run_586)(sc);
   1596 
   1597 	return 0;
   1598 }
   1599 
   1600 static void
   1601 iestop(sc)
   1602 	struct ie_softc *sc;
   1603 {
   1604 
   1605 	cmd_and_wait(sc, IE_RU_DISABLE, 0, 0);
   1606 }
   1607 
   1608 static int
   1609 ieioctl(ifp, cmd, data)
   1610 	register struct ifnet *ifp;
   1611 	u_long cmd;
   1612 	caddr_t data;
   1613 {
   1614 	struct ie_softc *sc = ifp->if_softc;
   1615 	struct ifaddr *ifa = (struct ifaddr *)data;
   1616 	struct ifreq *ifr = (struct ifreq *)data;
   1617 	int s, error = 0;
   1618 
   1619 	s = splnet();
   1620 
   1621 	switch (cmd) {
   1622 
   1623 	case SIOCSIFADDR:
   1624 		ifp->if_flags |= IFF_UP;
   1625 
   1626 		switch (ifa->ifa_addr->sa_family) {
   1627 #ifdef INET
   1628 		case AF_INET:
   1629 			ieinit(sc);
   1630 			arp_ifinit(&sc->sc_arpcom, ifa);
   1631 			break;
   1632 #endif
   1633 #ifdef NS
   1634 		/* XXX - This code is probably wrong. */
   1635 		case AF_NS:
   1636 		    {
   1637 			struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
   1638 
   1639 			if (ns_nullhost(*ina))
   1640 				ina->x_host =
   1641 				    *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
   1642 			else
   1643 				bcopy(ina->x_host.c_host,
   1644 				    sc->sc_arpcom.ac_enaddr,
   1645 				    sizeof(sc->sc_arpcom.ac_enaddr));
   1646 			/* Set new address. */
   1647 			ieinit(sc);
   1648 			break;
   1649 		    }
   1650 #endif /* NS */
   1651 		default:
   1652 			ieinit(sc);
   1653 			break;
   1654 		}
   1655 		break;
   1656 
   1657 	case SIOCSIFFLAGS:
   1658 		sc->promisc = ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
   1659 
   1660 		if ((ifp->if_flags & IFF_UP) == 0 &&
   1661 		    (ifp->if_flags & IFF_RUNNING) != 0) {
   1662 			/*
   1663 			 * If interface is marked down and it is running, then
   1664 			 * stop it.
   1665 			 */
   1666 			iestop(sc);
   1667 			ifp->if_flags &= ~IFF_RUNNING;
   1668 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
   1669 			(ifp->if_flags & IFF_RUNNING) == 0) {
   1670 			/*
   1671 			 * If interface is marked up and it is stopped, then
   1672 			 * start it.
   1673 			 */
   1674 			ieinit(sc);
   1675 		} else {
   1676 			/*
   1677 			 * Reset the interface to pick up changes in any other
   1678 			 * flags that affect hardware registers.
   1679 			 */
   1680 			iestop(sc);
   1681 			ieinit(sc);
   1682 		}
   1683 #ifdef IEDEBUG
   1684 		if (ifp->if_flags & IFF_DEBUG)
   1685 			sc->sc_debug = IED_ALL;
   1686 		else
   1687 			sc->sc_debug = ie_debug_flags;
   1688 #endif
   1689 		break;
   1690 
   1691 	case SIOCADDMULTI:
   1692 	case SIOCDELMULTI:
   1693 		error = (cmd == SIOCADDMULTI) ?
   1694 		    ether_addmulti(ifr, &sc->sc_arpcom) :
   1695 		    ether_delmulti(ifr, &sc->sc_arpcom);
   1696 
   1697 		if (error == ENETRESET) {
   1698 			/*
   1699 			 * Multicast list has changed; set the hardware filter
   1700 			 * accordingly.
   1701 			 */
   1702 			mc_reset(sc);
   1703 			error = 0;
   1704 		}
   1705 		break;
   1706 
   1707 	default:
   1708 		error = EINVAL;
   1709 	}
   1710 	splx(s);
   1711 	return error;
   1712 }
   1713 
   1714 static void
   1715 mc_reset(sc)
   1716 	struct ie_softc *sc;
   1717 {
   1718 	struct ether_multi *enm;
   1719 	struct ether_multistep step;
   1720 
   1721 	/*
   1722 	 * Step through the list of addresses.
   1723 	 */
   1724 	sc->mcast_count = 0;
   1725 	ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm);
   1726 	while (enm) {
   1727 		if (sc->mcast_count >= MAXMCAST ||
   1728 		    bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
   1729 			sc->sc_arpcom.ac_if.if_flags |= IFF_ALLMULTI;
   1730 			ieioctl(&sc->sc_arpcom.ac_if, SIOCSIFFLAGS, (void *)0);
   1731 			goto setflag;
   1732 		}
   1733 		bcopy(enm->enm_addrlo, &sc->mcast_addrs[sc->mcast_count], 6);
   1734 		sc->mcast_count++;
   1735 		ETHER_NEXT_MULTI(step, enm);
   1736 	}
   1737 setflag:
   1738 	sc->want_mcsetup = 1;
   1739 }
   1740 
   1741 #ifdef IEDEBUG
   1742 void
   1743 print_rbd(rbd)
   1744 	volatile struct ie_recv_buf_desc *rbd;
   1745 {
   1746 
   1747 	printf("RBD at %08lx:\nactual %04x, next %04x, buffer %08x\n"
   1748 	    "length %04x, mbz %04x\n", (u_long)rbd, rbd->ie_rbd_actual,
   1749 	    rbd->ie_rbd_next, rbd->ie_rbd_buffer, rbd->ie_rbd_length,
   1750 	    rbd->mbz);
   1751 }
   1752 #endif
   1753