Home | History | Annotate | Line # | Download | only in dev
      1 /*	$NetBSD: if_ie.c,v 1.74 2024/02/09 22:08:33 andvar Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 1993, 1994, 1995 Charles M. 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 M. 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 controlled 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 <sys/cdefs.h>
    101 __KERNEL_RCSID(0, "$NetBSD: if_ie.c,v 1.74 2024/02/09 22:08:33 andvar Exp $");
    102 
    103 #include "opt_inet.h"
    104 #include "opt_ns.h"
    105 
    106 #include <sys/param.h>
    107 #include <sys/systm.h>
    108 #include <sys/mbuf.h>
    109 #include <sys/buf.h>
    110 #include <sys/protosw.h>
    111 #include <sys/socket.h>
    112 #include <sys/ioctl.h>
    113 #include <sys/errno.h>
    114 #include <sys/syslog.h>
    115 #include <sys/device.h>
    116 
    117 #include <net/if.h>
    118 #include <net/if_types.h>
    119 #include <net/if_dl.h>
    120 #include <net/if_ether.h>
    121 #include <net/bpf.h>
    122 
    123 #ifdef INET
    124 #include <netinet/in.h>
    125 #include <netinet/in_systm.h>
    126 #include <netinet/in_var.h>
    127 #include <netinet/ip.h>
    128 #include <netinet/if_inarp.h>
    129 #endif
    130 
    131 #include <uvm/uvm_extern.h>
    132 
    133 #include <machine/autoconf.h>
    134 #include <machine/cpu.h>
    135 #include <machine/pmap.h>
    136 
    137 /*
    138  * ugly byte-order hack for SUNs
    139  */
    140 
    141 #define XSWAP(y)	( (((y) & 0xff00) >> 8) | (((y) & 0xff) << 8) )
    142 #define SWAP(x)		((u_short)(XSWAP((u_short)(x))))
    143 
    144 #include "i82586.h"
    145 #include "if_iereg.h"
    146 #include "if_ievar.h"
    147 
    148 /* #define	IEDEBUG	XXX */
    149 
    150 /*
    151  * IED: ie debug flags
    152  */
    153 
    154 #define	IED_RINT	0x01
    155 #define	IED_TINT	0x02
    156 #define	IED_RNR		0x04
    157 #define	IED_CNA		0x08
    158 #define	IED_READFRAME	0x10
    159 #define	IED_ENQ		0x20
    160 #define	IED_XMIT	0x40
    161 #define	IED_ALL		0x7f
    162 
    163 #ifdef	IEDEBUG
    164 #define	inline	/* not */
    165 void print_rbd(volatile struct ie_recv_buf_desc *);
    166 int	in_ierint = 0;
    167 int	in_ietint = 0;
    168 int	ie_debug_flags = 0;
    169 #endif
    170 
    171 /* XXX - Skip TDR for now - it always complains... */
    172 int	ie_run_tdr = 0;
    173 
    174 static void iewatchdog(struct ifnet *);
    175 static int ieinit(struct ie_softc *);
    176 static int ieioctl(struct ifnet *, u_long, void *);
    177 static void iestart(struct ifnet *);
    178 static void iereset(struct ie_softc *);
    179 static int ie_setupram(struct ie_softc *);
    180 
    181 static int cmd_and_wait(struct ie_softc *, int, void *, int);
    182 
    183 static void ie_drop_packet_buffer(struct ie_softc *);
    184 static void ie_readframe(struct ie_softc *, int);
    185 static inline void ie_setup_config(struct ie_config_cmd *, int, int);
    186 
    187 static void ierint(struct ie_softc *);
    188 static void iestop(struct ie_softc *);
    189 static void ietint(struct ie_softc *);
    190 static void iexmit(struct ie_softc *);
    191 
    192 static int mc_setup(struct ie_softc *, void *);
    193 static void mc_reset(struct ie_softc *);
    194 static void run_tdr(struct ie_softc *, struct ie_tdr_cmd *);
    195 static void iememinit(struct ie_softc *);
    196 
    197 static inline uint8_t *Align(char *);
    198 static inline u_int Swap32(u_int);
    199 static inline u_int vtop24(struct ie_softc *, void *);
    200 static inline uint16_t vtop16sw(struct ie_softc *, void *);
    201 
    202 static inline void ie_ack(struct ie_softc *, u_int);
    203 static inline u_short ether_cmp(u_char *, uint8_t *);
    204 static inline int ie_buflen(struct ie_softc *, int);
    205 static inline int ie_packet_len(struct ie_softc *);
    206 static inline struct mbuf * ieget(struct ie_softc *);
    207 
    208 
    209 /*
    210  * Here are a few useful functions.  We could have done these as macros,
    211  * but since we have the inline facility, it makes sense to use that
    212  * instead.
    213  */
    214 
    215 /* KVA to 24 bit device address */
    216 static inline u_int
    217 vtop24(struct ie_softc *sc, void *ptr)
    218 {
    219 	u_int pa;
    220 
    221 	pa = (vaddr_t)ptr - (vaddr_t)sc->sc_iobase;
    222 #ifdef	IEDEBUG
    223 	if (pa & ~0xffFFff)
    224 		panic("ie:vtop24");
    225 #endif
    226 	return pa;
    227 }
    228 
    229 /* KVA to 16 bit offset, swapped */
    230 static inline u_short
    231 vtop16sw(struct ie_softc *sc, void *ptr)
    232 {
    233 	u_int pa;
    234 
    235 	pa = (vaddr_t)ptr - (vaddr_t)sc->sc_maddr;
    236 #ifdef	IEDEBUG
    237 	if (pa & ~0xFFff)
    238 		panic("ie:vtop16");
    239 #endif
    240 
    241 	return SWAP(pa);
    242 }
    243 
    244 static inline u_int
    245 Swap32(u_int x)
    246 {
    247 	u_int y;
    248 
    249 	y = x & 0xFF;
    250 	y <<= 8; x >>= 8;
    251 	y |= x & 0xFF;
    252 	y <<= 8; x >>= 8;
    253 	y |= x & 0xFF;
    254 	y <<= 8; x >>= 8;
    255 	y |= x & 0xFF;
    256 
    257 	return y;
    258 }
    259 
    260 static inline uint8_t *
    261 Align(char *ptr)
    262 {
    263 	u_long  l = (u_long)ptr;
    264 
    265 	l = (l + 3) & ~3L;
    266 	return (uint8_t *)l;
    267 }
    268 
    269 
    270 static inline void
    271 ie_ack(struct ie_softc *sc, u_int mask)
    272 {
    273 	volatile struct ie_sys_ctl_block *scb = sc->scb;
    274 
    275 	cmd_and_wait(sc, scb->ie_status & mask, 0, 0);
    276 }
    277 
    278 
    279 /*
    280  * Taken almost exactly from Bill's if_is.c,
    281  * then modified beyond recognition...
    282  */
    283 void
    284 ie_attach(struct ie_softc *sc)
    285 {
    286 	struct ifnet *ifp = &sc->sc_if;
    287 
    288 	/* MD code has done its part before calling this. */
    289 	printf(": macaddr %s\n", ether_sprintf(sc->sc_addr));
    290 
    291 	/*
    292 	 * Compute number of transmit and receive buffers.
    293 	 * Tx buffers take 1536 bytes, and fixed in number.
    294 	 * Rx buffers are 512 bytes each, variable number.
    295 	 * Need at least 1 frame for each 3 rx buffers.
    296 	 * The ratio 3bufs:2frames is a compromise.
    297 	 */
    298 	sc->ntxbuf = NTXBUF;	/* XXX - Fix me... */
    299 	switch (sc->sc_msize) {
    300 	case 16384:
    301 		sc->nframes = 8 * 4;
    302 		sc->nrxbuf  = 8 * 6;
    303 		break;
    304 	case 32768:
    305 		sc->nframes = 16 * 4;
    306 		sc->nrxbuf  = 16 * 6;
    307 		break;
    308 	case 65536:
    309 		sc->nframes = 32 * 4;
    310 		sc->nrxbuf  = 32 * 6;
    311 		break;
    312 	default:
    313 		sc->nframes = 0;
    314 	}
    315 	if (sc->nframes > MXFRAMES)
    316 		sc->nframes = MXFRAMES;
    317 	if (sc->nrxbuf > MXRXBUF)
    318 		sc->nrxbuf = MXRXBUF;
    319 
    320 #ifdef	IEDEBUG
    321 	aprint_debug_dev(sc->sc_dev,
    322 	    "%dK memory, %d tx frames, %d rx frames, %d rx bufs\n",
    323 	    (sc->sc_msize >> 10), sc->ntxbuf, sc->nframes, sc->nrxbuf);
    324 #endif
    325 
    326 	if ((sc->nframes <= 0) || (sc->nrxbuf <= 0))
    327 		panic("%s: weird memory size", __func__);
    328 
    329 	/*
    330 	 * Setup RAM for transmit/receive
    331 	 */
    332 	if (ie_setupram(sc) == 0) {
    333 		aprint_error(": RAM CONFIG FAILED!\n");
    334 		/* XXX should reclaim resources? */
    335 		return;
    336 	}
    337 
    338 	/*
    339 	 * Initialize and attach S/W interface
    340 	 */
    341 	strcpy(ifp->if_xname, device_xname(sc->sc_dev));
    342 	ifp->if_softc = sc;
    343 	ifp->if_start = iestart;
    344 	ifp->if_ioctl = ieioctl;
    345 	ifp->if_watchdog = iewatchdog;
    346 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
    347 
    348 	/* Attach the interface. */
    349 	if_attach(ifp);
    350 	if_deferred_start_init(ifp, NULL);
    351 	ether_ifattach(ifp, sc->sc_addr);
    352 }
    353 
    354 /*
    355  * Setup IE's ram space.
    356  */
    357 static int
    358 ie_setupram(struct ie_softc *sc)
    359 {
    360 	volatile struct ie_sys_conf_ptr *scp;
    361 	volatile struct ie_int_sys_conf_ptr *iscp;
    362 	volatile struct ie_sys_ctl_block *scb;
    363 	int off;
    364 
    365 	/*
    366 	 * Allocate from end of buffer space for
    367 	 * ISCP, SCB, and other small stuff.
    368 	 */
    369 	off = sc->buf_area_sz;
    370 	off &= ~3;
    371 
    372 	/* SCP (address already chosen). */
    373 	scp = sc->scp;
    374 	(sc->sc_memset)(__UNVOLATILE(scp), 0, sizeof(*scp));
    375 
    376 	/* ISCP */
    377 	off -= sizeof(*iscp);
    378 	iscp = (volatile void *)(sc->buf_area + off);
    379 	(sc->sc_memset)(__UNVOLATILE(iscp), 0, sizeof(*iscp));
    380 	sc->iscp = iscp;
    381 
    382 	/* SCB */
    383 	off -= sizeof(*scb);
    384 	scb  = (volatile void *)(sc->buf_area + off);
    385 	(sc->sc_memset)(__UNVOLATILE(scb), 0, sizeof(*scb));
    386 	sc->scb = scb;
    387 
    388 	/* Remainder is for buffers, etc. */
    389 	sc->buf_area_sz = off;
    390 
    391 	/*
    392 	 * Now fill in the structures we just allocated.
    393 	 */
    394 
    395 	/* SCP: main thing is 24-bit ptr to ISCP */
    396 	scp->ie_bus_use = 0;	/* 16-bit */
    397 	scp->ie_iscp_ptr = Swap32(vtop24(sc, __UNVOLATILE(iscp)));
    398 
    399 	/* ISCP */
    400 	iscp->ie_busy = 1;	/* ie_busy == char */
    401 	iscp->ie_scb_offset = vtop16sw(sc, __UNVOLATILE(scb));
    402 	iscp->ie_base = Swap32(vtop24(sc, sc->sc_maddr));
    403 
    404 	/* SCB */
    405 	scb->ie_command_list = SWAP(0xffff);
    406 	scb->ie_recv_list    = SWAP(0xffff);
    407 
    408 	/* Other stuff is done in ieinit() */
    409 	(sc->reset_586)(sc);
    410 	(sc->chan_attn)(sc);
    411 
    412 	delay(100);		/* wait a while... */
    413 
    414 	if (iscp->ie_busy) {
    415 		return 0;
    416 	}
    417 	/*
    418 	 * Acknowledge any interrupts we may have caused...
    419 	 */
    420 	ie_ack(sc, IE_ST_WHENCE);
    421 
    422 	return 1;
    423 }
    424 
    425 /*
    426  * Device timeout/watchdog routine.  Entered if the device neglects to
    427  * generate an interrupt after a transmit has been started on it.
    428  */
    429 static void
    430 iewatchdog(struct ifnet *ifp)
    431 {
    432 	struct ie_softc *sc = ifp->if_softc;
    433 
    434 	log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev));
    435 	if_statinc(ifp, if_oerrors);
    436 	iereset(sc);
    437 }
    438 
    439 /*
    440  * What to do upon receipt of an interrupt.
    441  */
    442 int
    443 ie_intr(void *arg)
    444 {
    445 	struct ie_softc *sc = arg;
    446 	uint16_t status;
    447 	int loopcnt;
    448 
    449 	/*
    450 	 * check for parity error
    451 	 */
    452 	if (sc->hard_type == IE_VME) {
    453 		volatile struct ievme *iev =
    454 		    (volatile struct ievme *)sc->sc_reg;
    455 
    456 		if (iev->status & IEVME_PERR) {
    457 			printf("%s: parity error (ctrl 0x%x @ 0x%02x%04x)\n",
    458 			    device_xname(sc->sc_dev), iev->pectrl,
    459 			    iev->pectrl & IEVME_HADDR, iev->peaddr);
    460 			iev->pectrl = iev->pectrl | IEVME_PARACK;
    461 		}
    462 	}
    463 
    464 	status = sc->scb->ie_status;
    465 	if ((status & IE_ST_WHENCE) == 0)
    466 		return 0;
    467 
    468 	loopcnt = sc->nframes;
    469  loop:
    470 	/* Ack interrupts FIRST in case we receive more during the ISR. */
    471 	ie_ack(sc, IE_ST_WHENCE & status);
    472 
    473 	if (status & (IE_ST_RECV | IE_ST_RNR)) {
    474 #ifdef IEDEBUG
    475 		in_ierint++;
    476 		if (sc->sc_debug & IED_RINT)
    477 			printf("%s: rint\n", device_xname(sc->sc_dev));
    478 #endif
    479 		ierint(sc);
    480 #ifdef IEDEBUG
    481 		in_ierint--;
    482 #endif
    483 	}
    484 
    485 	if (status & IE_ST_DONE) {
    486 #ifdef IEDEBUG
    487 		in_ietint++;
    488 		if (sc->sc_debug & IED_TINT)
    489 			printf("%s: tint\n", device_xname(sc->sc_dev));
    490 #endif
    491 		ietint(sc);
    492 #ifdef IEDEBUG
    493 		in_ietint--;
    494 #endif
    495 	}
    496 
    497 	/*
    498 	 * Receiver not ready (RNR) just means it has
    499 	 * run out of resources (buffers or frames).
    500 	 * One can easily cause this with (i.e.) spray.
    501 	 * This is not a serious error, so be silent.
    502 	 */
    503 	if (status & IE_ST_RNR) {
    504 #ifdef IEDEBUG
    505 		printf("%s: receiver not ready\n", device_xname(sc->sc_dev));
    506 #endif
    507 		if_statinc(&sc->sc_if, if_ierrors);
    508 		iereset(sc);
    509 	}
    510 
    511 #ifdef IEDEBUG
    512 	if ((status & IE_ST_ALLDONE) && (sc->sc_debug & IED_CNA))
    513 		printf("%s: cna\n", device_xname(sc->sc_dev));
    514 #endif
    515 
    516 	status = sc->scb->ie_status;
    517 	if (status & IE_ST_WHENCE) {
    518 		/* It still wants service... */
    519 		if (--loopcnt > 0)
    520 			goto loop;
    521 		/* ... but we've been here long enough. */
    522 		log(LOG_ERR, "%s: interrupt stuck?\n",
    523 		    device_xname(sc->sc_dev));
    524 		iereset(sc);
    525 	}
    526 	return 1;
    527 }
    528 
    529 /*
    530  * Process a received-frame interrupt.
    531  */
    532 void
    533 ierint(struct ie_softc *sc)
    534 {
    535 	volatile struct ie_sys_ctl_block *scb = sc->scb;
    536 	int i, status;
    537 	static int timesthru = 1024;
    538 
    539 	i = sc->rfhead;
    540 	for (;;) {
    541 		status = sc->rframes[i]->ie_fd_status;
    542 
    543 		if ((status & IE_FD_COMPLETE) && (status & IE_FD_OK)) {
    544 			if (!--timesthru) {
    545 				if_statadd(&sc->sc_if, if_ierrors,
    546 				    SWAP(scb->ie_err_crc) +
    547 				    SWAP(scb->ie_err_align) +
    548 				    SWAP(scb->ie_err_resource) +
    549 				    SWAP(scb->ie_err_overrun));
    550 				scb->ie_err_crc = 0;
    551 				scb->ie_err_align = 0;
    552 				scb->ie_err_resource = 0;
    553 				scb->ie_err_overrun = 0;
    554 				timesthru = 1024;
    555 			}
    556 			ie_readframe(sc, i);
    557 		} else {
    558 			if ((status & IE_FD_RNR) != 0 &&
    559 			    (scb->ie_status & IE_RU_READY) == 0) {
    560 				sc->rframes[0]->ie_fd_buf_desc = vtop16sw(sc,
    561 				    __UNVOLATILE(sc->rbuffs[0]));
    562 				scb->ie_recv_list = vtop16sw(sc,
    563 				    __UNVOLATILE(sc->rframes[0]));
    564 				cmd_and_wait(sc, IE_RU_START, 0, 0);
    565 			}
    566 			break;
    567 		}
    568 		i = (i + 1) % sc->nframes;
    569 	}
    570 }
    571 
    572 /*
    573  * Process a command-complete interrupt.  These are only generated by the
    574  * transmission of frames.  This routine is deceptively simple, since most
    575  * of the real work is done by iestart().
    576  */
    577 void
    578 ietint(struct ie_softc *sc)
    579 {
    580 	struct ifnet *ifp;
    581 	int status;
    582 
    583 	ifp = &sc->sc_if;
    584 
    585 	ifp->if_timer = 0;
    586 
    587 	status = sc->xmit_cmds[sc->xctail]->ie_xmit_status;
    588 
    589 	if (!(status & IE_STAT_COMPL) || (status & IE_STAT_BUSY))
    590 		printf("%s: command still busy!\n", __func__);
    591 
    592 	if (status & IE_STAT_OK) {
    593 		if_statadd2(ifp, if_opackets, 1,
    594 			    if_collisions, SWAP(status & IE_XS_MAXCOLL));
    595 	} else {
    596 		if_statinc(ifp, if_oerrors);
    597 		/*
    598 		 * XXX
    599 		 * Check SQE and DEFERRED?
    600 		 * What if more than one bit is set?
    601 		 */
    602 		if (status & IE_STAT_ABORT)
    603 			printf("%s: send aborted\n", device_xname(sc->sc_dev));
    604 		if (status & IE_XS_LATECOLL)
    605 			printf("%s: late collision\n",
    606 			    device_xname(sc->sc_dev));
    607 		if (status & IE_XS_NOCARRIER)
    608 			printf("%s: no carrier\n", device_xname(sc->sc_dev));
    609 		if (status & IE_XS_LOSTCTS)
    610 			printf("%s: lost CTS\n", device_xname(sc->sc_dev));
    611 		if (status & IE_XS_UNDERRUN)
    612 			printf("%s: DMA underrun\n", device_xname(sc->sc_dev));
    613 		if (status & IE_XS_EXCMAX) {
    614 			/* Do not print this one (too noisy). */
    615 			if_statadd(ifp, if_collisions, 16);
    616 		}
    617 	}
    618 
    619 	/*
    620 	 * If multicast addresses were added or deleted while we
    621 	 * were transmitting, mc_reset() set the want_mcsetup flag
    622 	 * indicating that we should do it.
    623 	 */
    624 	if (sc->want_mcsetup) {
    625 		mc_setup(sc, (void *)sc->xmit_cbuffs[sc->xctail]);
    626 		sc->want_mcsetup = 0;
    627 	}
    628 
    629 	/* Done with the buffer. */
    630 	sc->xmit_busy--;
    631 	sc->xctail = (sc->xctail + 1) % NTXBUF;
    632 
    633 	/* Start the next packet, if any, transmitting. */
    634 	if (sc->xmit_busy > 0)
    635 		iexmit(sc);
    636 
    637 	if_schedule_deferred_start(ifp);
    638 }
    639 
    640 /*
    641  * Compare two Ether/802 addresses for equality, inlined and
    642  * unrolled for speed.  I'd love to have an inline assembler
    643  * version of this...   XXX: Who wanted that? mycroft?
    644  * I wrote one, but the following is just as efficient.
    645  * This expands to 10 short m68k instructions! -gwr
    646  * Note: use this like memcmp()
    647  */
    648 static inline uint16_t
    649 ether_cmp(uint8_t *one, uint8_t *two)
    650 {
    651 	uint16_t *a = (uint16_t *)one;
    652 	uint16_t *b = (uint16_t *)two;
    653 	uint16_t diff;
    654 
    655 	diff  = *a++ - *b++;
    656 	diff |= *a++ - *b++;
    657 	diff |= *a++ - *b++;
    658 
    659 	return diff;
    660 }
    661 #define	ether_equal !ether_cmp
    662 
    663 /*
    664  * We want to isolate the bits that have meaning...  This assumes that
    665  * IE_RBUF_SIZE is an even power of two.  If somehow the act_len exceeds
    666  * the size of the buffer, then we are screwed anyway.
    667  */
    668 static inline int
    669 ie_buflen(struct ie_softc *sc, int head)
    670 {
    671 	int len;
    672 
    673 	len = SWAP(sc->rbuffs[head]->ie_rbd_actual);
    674 	len &= (IE_RBUF_SIZE | (IE_RBUF_SIZE - 1));
    675 	return len;
    676 }
    677 
    678 static inline int
    679 ie_packet_len(struct ie_softc *sc)
    680 {
    681 	int i;
    682 	int head = sc->rbhead;
    683 	int acc = 0;
    684 
    685 	do {
    686 		if ((sc->rbuffs[sc->rbhead]->ie_rbd_actual & IE_RBD_USED)
    687 		    == 0) {
    688 #ifdef IEDEBUG
    689 			print_rbd(sc->rbuffs[sc->rbhead]);
    690 #endif
    691 			log(LOG_ERR,
    692 			    "%s: receive descriptors out of sync at %d\n",
    693 			    device_xname(sc->sc_dev), sc->rbhead);
    694 			iereset(sc);
    695 			return -1;
    696 		}
    697 
    698 		i = sc->rbuffs[head]->ie_rbd_actual & IE_RBD_LAST;
    699 
    700 		acc += ie_buflen(sc, head);
    701 		head = (head + 1) % sc->nrxbuf;
    702 	} while (i == 0);
    703 
    704 	return acc;
    705 }
    706 
    707 /*
    708  * Setup all necessary artifacts for an XMIT command, and then pass the XMIT
    709  * command to the chip to be executed.  On the way, if we have a BPF listener
    710  * also give him a copy.
    711  */
    712 static void
    713 iexmit(struct ie_softc *sc)
    714 {
    715 	struct ifnet *ifp;
    716 
    717 	ifp = &sc->sc_if;
    718 
    719 #ifdef IEDEBUG
    720 	if (sc->sc_debug & IED_XMIT)
    721 		printf("%s: xmit buffer %d\n", device_xname(sc->sc_dev),
    722 		    sc->xctail);
    723 #endif
    724 
    725 	sc->xmit_buffs[sc->xctail]->ie_xmit_flags |= IE_XMIT_LAST;
    726 	sc->xmit_buffs[sc->xctail]->ie_xmit_next = SWAP(0xffff);
    727 	sc->xmit_buffs[sc->xctail]->ie_xmit_buf =
    728 	    Swap32(vtop24(sc, sc->xmit_cbuffs[sc->xctail]));
    729 
    730 	sc->xmit_cmds[sc->xctail]->com.ie_cmd_link = SWAP(0xffff);
    731 	sc->xmit_cmds[sc->xctail]->com.ie_cmd_cmd =
    732 	    IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST;
    733 
    734 	sc->xmit_cmds[sc->xctail]->ie_xmit_status = SWAP(0);
    735 	sc->xmit_cmds[sc->xctail]->ie_xmit_desc =
    736 	    vtop16sw(sc, __UNVOLATILE(sc->xmit_buffs[sc->xctail]));
    737 
    738 	sc->scb->ie_command_list =
    739 	    vtop16sw(sc, __UNVOLATILE(sc->xmit_cmds[sc->xctail]));
    740 	cmd_and_wait(sc, IE_CU_START, 0, 0);
    741 
    742 	ifp->if_timer = 5;
    743 }
    744 
    745 /*
    746  * Read data off the interface, and turn it into an mbuf chain.
    747  *
    748  * This code is DRAMATICALLY different from the previous version; this
    749  * version tries to allocate the entire mbuf chain up front, given the
    750  * length of the data available.  This enables us to allocate mbuf
    751  * clusters in many situations where before we would have had a long
    752  * chain of partially-full mbufs.  This should help to speed up the
    753  * operation considerably.  (Provided that it works, of course.)
    754  */
    755 static inline struct mbuf *
    756 ieget(struct ie_softc *sc)
    757 {
    758 	struct mbuf *top, **mp, *m;
    759 	int len, totlen, resid;
    760 	int thisrboff, thismboff;
    761 	int head;
    762 	struct ether_header eh;
    763 
    764 	totlen = ie_packet_len(sc);
    765 	if (totlen <= 0)
    766 		return 0;
    767 
    768 	head = sc->rbhead;
    769 
    770 	/*
    771 	 * Snarf the Ethernet header.
    772 	 */
    773 	(sc->sc_memcpy)((void *)&eh, (void *)sc->cbuffs[head],
    774 	    sizeof(struct ether_header));
    775 
    776 	resid = totlen;
    777 
    778 	MGETHDR(m, M_DONTWAIT, MT_DATA);
    779 	if (m == 0)
    780 		return 0;
    781 
    782 	m_set_rcvif(m, &sc->sc_if);
    783 	m->m_pkthdr.len = totlen;
    784 	len = MHLEN;
    785 	top = 0;
    786 	mp = &top;
    787 
    788 	/*
    789 	 * This loop goes through and allocates mbufs for all the data we will
    790 	 * be copying in.  It does not actually do the copying yet.
    791 	 */
    792 	while (totlen > 0) {
    793 		if (top) {
    794 			MGET(m, M_DONTWAIT, MT_DATA);
    795 			if (m == 0) {
    796 				m_freem(top);
    797 				return 0;
    798 			}
    799 			len = MLEN;
    800 		}
    801 		if (totlen >= MINCLSIZE) {
    802 			MCLGET(m, M_DONTWAIT);
    803 			if (m->m_flags & M_EXT)
    804 				len = MCLBYTES;
    805 		}
    806 
    807 		if (mp == &top) {
    808 			char *newdata = (char *)
    809 			    ALIGN(m->m_data + sizeof(struct ether_header)) -
    810 			    sizeof(struct ether_header);
    811 			len -= newdata - m->m_data;
    812 			m->m_data = newdata;
    813 		}
    814 
    815 		m->m_len = len = uimin(totlen, len);
    816 
    817 		totlen -= len;
    818 		*mp = m;
    819 		mp = &m->m_next;
    820 	}
    821 
    822 	m = top;
    823 	thismboff = 0;
    824 
    825 	/*
    826 	 * Copy the Ethernet header into the mbuf chain.
    827 	 */
    828 	memcpy(mtod(m, void *), &eh, sizeof(struct ether_header));
    829 	thismboff = sizeof(struct ether_header);
    830 	thisrboff = sizeof(struct ether_header);
    831 	resid -= sizeof(struct ether_header);
    832 
    833 	/*
    834 	 * Now we take the mbuf chain (hopefully only one mbuf most of the
    835 	 * time) and stuff the data into it.  There are no possible failures
    836 	 * at or after this point.
    837 	 */
    838 	while (resid > 0) {
    839 		int thisrblen = ie_buflen(sc, head) - thisrboff;
    840 		int thismblen = m->m_len - thismboff;
    841 
    842 		len = uimin(thisrblen, thismblen);
    843 		(sc->sc_memcpy)(mtod(m, char *) + thismboff,
    844 		    (void *)(sc->cbuffs[head] + thisrboff),
    845 		    (u_int)len);
    846 		resid -= len;
    847 
    848 		if (len == thismblen) {
    849 			m = m->m_next;
    850 			thismboff = 0;
    851 		} else
    852 			thismboff += len;
    853 
    854 		if (len == thisrblen) {
    855 			head = (head + 1) % sc->nrxbuf;
    856 			thisrboff = 0;
    857 		} else
    858 			thisrboff += len;
    859 	}
    860 
    861 	/*
    862 	 * Unless something changed strangely while we were doing the copy,
    863 	 * we have now copied everything in from the shared memory.
    864 	 * This means that we are done.
    865 	 */
    866 	return top;
    867 }
    868 
    869 /*
    870  * Read frame NUM from unit UNIT (pre-cached as IE).
    871  *
    872  * This routine reads the RFD at NUM, and copies in the buffers from
    873  * the list of RBD, then rotates the RBD and RFD lists so that the receiver
    874  * doesn't start complaining.  Trailers are DROPPED---there's no point
    875  * in wasting time on confusing code to deal with them.  Hopefully,
    876  * this machine will never ARP for trailers anyway.
    877  */
    878 static void
    879 ie_readframe(struct ie_softc *sc, int num)
    880 {
    881 	int status;
    882 	struct mbuf *m = 0;
    883 
    884 	status = sc->rframes[num]->ie_fd_status;
    885 
    886 	/* Advance the RFD list, since we're done with this descriptor. */
    887 	sc->rframes[num]->ie_fd_status = SWAP(0);
    888 	sc->rframes[num]->ie_fd_last |= IE_FD_LAST;
    889 	sc->rframes[sc->rftail]->ie_fd_last &= ~IE_FD_LAST;
    890 	sc->rftail = (sc->rftail + 1) % sc->nframes;
    891 	sc->rfhead = (sc->rfhead + 1) % sc->nframes;
    892 
    893 	if (status & IE_FD_OK) {
    894 		m = ieget(sc);
    895 		ie_drop_packet_buffer(sc);
    896 	}
    897 	if (m == 0) {
    898 		if_statinc(&sc->sc_if, if_ierrors);
    899 		return;
    900 	}
    901 
    902 #ifdef IEDEBUG
    903 	if (sc->sc_debug & IED_READFRAME) {
    904 		struct ether_header *eh = mtod(m, struct ether_header *);
    905 
    906 		printf("%s: frame from ether %s type 0x%x\n",
    907 		    device_xname(sc->sc_dev),
    908 		    ether_sprintf(eh->ether_shost), (u_int)eh->ether_type);
    909 	}
    910 #endif
    911 
    912 	/*
    913 	 * Finally pass this packet up to higher layers.
    914 	 */
    915 	if_percpuq_enqueue((&sc->sc_if)->if_percpuq, m);
    916 }
    917 
    918 static void
    919 ie_drop_packet_buffer(struct ie_softc *sc)
    920 {
    921 	int i;
    922 
    923 	do {
    924 		/*
    925 		 * This means we are somehow out of sync.  So, we reset the
    926 		 * adapter.
    927 		 */
    928 		if ((sc->rbuffs[sc->rbhead]->ie_rbd_actual & IE_RBD_USED)
    929 		    == 0) {
    930 #ifdef IEDEBUG
    931 			print_rbd(sc->rbuffs[sc->rbhead]);
    932 #endif
    933 			log(LOG_ERR,
    934 			    "%s: receive descriptors out of sync at %d\n",
    935 			    device_xname(sc->sc_dev), sc->rbhead);
    936 			iereset(sc);
    937 			return;
    938 		}
    939 
    940 		i = sc->rbuffs[sc->rbhead]->ie_rbd_actual & IE_RBD_LAST;
    941 
    942 		sc->rbuffs[sc->rbhead]->ie_rbd_length |= IE_RBD_LAST;
    943 		sc->rbuffs[sc->rbhead]->ie_rbd_actual = SWAP(0);
    944 		sc->rbhead = (sc->rbhead + 1) % sc->nrxbuf;
    945 		sc->rbuffs[sc->rbtail]->ie_rbd_length &= ~IE_RBD_LAST;
    946 		sc->rbtail = (sc->rbtail + 1) % sc->nrxbuf;
    947 	} while (i == 0);
    948 }
    949 
    950 /*
    951  * Start transmission on an interface.
    952  */
    953 static void
    954 iestart(struct ifnet *ifp)
    955 {
    956 	struct ie_softc *sc = ifp->if_softc;
    957 	struct mbuf *m0, *m;
    958 	uint8_t *buffer;
    959 	uint16_t len;
    960 
    961 	if ((ifp->if_flags & IFF_RUNNING) != IFF_RUNNING)
    962 		return;
    963 
    964 	while (sc->xmit_busy < sc->ntxbuf) {
    965 		IF_DEQUEUE(&ifp->if_snd, m0);
    966 		if (m0 == 0)
    967 			break;
    968 
    969 		/* We need to use m->m_pkthdr.len, so require the header */
    970 		if ((m0->m_flags & M_PKTHDR) == 0)
    971 			panic("%s: no header mbuf", __func__);
    972 
    973 		/* Tap off here if there is a BPF listener. */
    974 		bpf_mtap(ifp, m0, BPF_D_OUT);
    975 
    976 #ifdef IEDEBUG
    977 		if (sc->sc_debug & IED_ENQ)
    978 			printf("%s: fill buffer %d\n", device_xname(sc->sc_dev),
    979 			    sc->xchead);
    980 #endif
    981 
    982 		buffer = sc->xmit_cbuffs[sc->xchead];
    983 		for (m = m0; m != 0; m = m->m_next) {
    984 			(sc->sc_memcpy)(buffer, mtod(m, void *), m->m_len);
    985 			buffer += m->m_len;
    986 		}
    987 		if (m0->m_pkthdr.len < ETHER_MIN_LEN - ETHER_CRC_LEN) {
    988 			sc->sc_memset(buffer, 0,
    989 			    ETHER_MIN_LEN - ETHER_CRC_LEN - m0->m_pkthdr.len);
    990 			len = ETHER_MIN_LEN - ETHER_CRC_LEN;
    991 		} else
    992 			len = m0->m_pkthdr.len;
    993 
    994 		m_freem(m0);
    995 		sc->xmit_buffs[sc->xchead]->ie_xmit_flags = SWAP(len);
    996 
    997 		/* Start the first packet transmitting. */
    998 		if (sc->xmit_busy == 0)
    999 			iexmit(sc);
   1000 
   1001 		sc->xchead = (sc->xchead + 1) % sc->ntxbuf;
   1002 		sc->xmit_busy++;
   1003 	}
   1004 }
   1005 
   1006 static void
   1007 iereset(struct ie_softc *sc)
   1008 {
   1009 	int s;
   1010 
   1011 	s = splnet();
   1012 
   1013 	/* No message here.  The caller does that. */
   1014 	iestop(sc);
   1015 
   1016 	/*
   1017 	 * Stop i82586 dead in its tracks.
   1018 	 */
   1019 	if (cmd_and_wait(sc, IE_RU_ABORT | IE_CU_ABORT, 0, 0))
   1020 		printf("%s: abort commands timed out\n",
   1021 		    device_xname(sc->sc_dev));
   1022 
   1023 	if (cmd_and_wait(sc, IE_RU_DISABLE | IE_CU_STOP, 0, 0))
   1024 		printf("%s: disable commands timed out\n",
   1025 		    device_xname(sc->sc_dev));
   1026 
   1027 	ieinit(sc);
   1028 
   1029 	splx(s);
   1030 }
   1031 
   1032 /*
   1033  * Send a command to the controller and wait for it to either
   1034  * complete or be accepted, depending on the command.  If the
   1035  * command pointer is null, then pretend that the command is
   1036  * not an action command.  If the command pointer is not null,
   1037  * and the command is an action command, wait for
   1038  * ((volatile struct ie_cmd_common *)pcmd)->ie_cmd_status & MASK
   1039  * to become true.
   1040  */
   1041 static int
   1042 cmd_and_wait(struct ie_softc *sc, int cmd, void *pcmd, int mask)
   1043 {
   1044 	volatile struct ie_cmd_common *cc = pcmd;
   1045 	volatile struct ie_sys_ctl_block *scb = sc->scb;
   1046 	int tmo;
   1047 
   1048 	scb->ie_command = (uint16_t)cmd;
   1049 	(sc->chan_attn)(sc);
   1050 
   1051 	/* Wait for the command to be accepted by the CU. */
   1052 	tmo = 10;
   1053 	while (scb->ie_command && --tmo)
   1054 		delay(10);
   1055 	if (scb->ie_command) {
   1056 #ifdef	IEDEBUG
   1057 		printf("%s: cmd_and_wait, CU stuck (1)\n",
   1058 		    device_xname(sc->sc_dev));
   1059 #endif
   1060 		return -1;	/* timed out */
   1061 	}
   1062 
   1063 	/*
   1064 	 * If asked, also wait for it to finish.
   1065 	 */
   1066 	if (IE_ACTION_COMMAND(cmd) && pcmd) {
   1067 
   1068 		/*
   1069 		 * According to the packet driver, the minimum timeout should
   1070 		 * be .369 seconds, which we round up to .4.
   1071 		 */
   1072 		tmo = 36900;
   1073 
   1074 		/*
   1075 		 * Now spin-lock waiting for status.  This is not a very nice
   1076 		 * thing to do, but I haven't figured out how, or indeed if, we
   1077 		 * can put the process waiting for action to sleep.  (We may
   1078 		 * be getting called through some other timeout running in the
   1079 		 * kernel.)
   1080 		 */
   1081 		while (((cc->ie_cmd_status & mask) == 0) && --tmo)
   1082 			delay(10);
   1083 
   1084 		if ((cc->ie_cmd_status & mask) == 0) {
   1085 #ifdef	IEDEBUG
   1086 			printf("%s: cmd_and_wait, CU stuck (2)\n",
   1087 			    device_xname(sc->sc_dev));
   1088 #endif
   1089 			return -1;	/* timed out */
   1090 		}
   1091 	}
   1092 	return 0;
   1093 }
   1094 
   1095 /*
   1096  * Run the time-domain reflectometer.
   1097  */
   1098 static void
   1099 run_tdr(struct ie_softc *sc, struct ie_tdr_cmd *cmd)
   1100 {
   1101 	int result;
   1102 
   1103 	cmd->com.ie_cmd_status = SWAP(0);
   1104 	cmd->com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST;
   1105 	cmd->com.ie_cmd_link = SWAP(0xffff);
   1106 
   1107 	sc->scb->ie_command_list = vtop16sw(sc, cmd);
   1108 	cmd->ie_tdr_time = SWAP(0);
   1109 
   1110 	if (cmd_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
   1111 	    (cmd->com.ie_cmd_status & IE_STAT_OK) == 0)
   1112 		result = 0x10000;	/* impossible value */
   1113 	else
   1114 		result = cmd->ie_tdr_time;
   1115 
   1116 	ie_ack(sc, IE_ST_WHENCE);
   1117 
   1118 	if (result & IE_TDR_SUCCESS)
   1119 		return;
   1120 
   1121 	if (result & 0x10000) {
   1122 		printf("%s: TDR command failed\n", device_xname(sc->sc_dev));
   1123 	} else if (result & IE_TDR_XCVR) {
   1124 		printf("%s: transceiver problem\n", device_xname(sc->sc_dev));
   1125 	} else if (result & IE_TDR_OPEN) {
   1126 		printf("%s: TDR detected an open %d clocks away\n",
   1127 		    device_xname(sc->sc_dev), SWAP(result & IE_TDR_TIME));
   1128 	} else if (result & IE_TDR_SHORT) {
   1129 		printf("%s: TDR detected a short %d clocks away\n",
   1130 		    device_xname(sc->sc_dev), SWAP(result & IE_TDR_TIME));
   1131 	} else {
   1132 		printf("%s: TDR returned unknown status 0x%x\n",
   1133 		    device_xname(sc->sc_dev), result);
   1134 	}
   1135 }
   1136 
   1137 /*
   1138  * iememinit: set up the buffers
   1139  *
   1140  * we have a block of KVA at sc->buf_area which is of size sc->buf_area_sz.
   1141  * this is to be used for the buffers.  the chip indexes its control data
   1142  * structures with 16 bit offsets, and it indexes actual buffers with
   1143  * 24 bit addresses.   so we should allocate control buffers first so that
   1144  * we don't overflow the 16 bit offset field.   The number of transmit
   1145  * buffers is fixed at compile time.
   1146  *
   1147  * note: this function was written to be easy to understand, rather than
   1148  *       highly efficient (it isn't in the critical path).
   1149  *
   1150  * The memory layout is: tbufs, rbufs, (gap), control blocks
   1151  * [tbuf0, tbuf1] [rbuf0,...rbufN] gap [rframes] [tframes]
   1152  * XXX - This needs review...
   1153  */
   1154 static void
   1155 iememinit(struct ie_softc *sc)
   1156 {
   1157 	uint8_t *ptr;
   1158 	int i;
   1159 	uint16_t nxt;
   1160 
   1161 	/* First, zero all the memory. */
   1162 	ptr = sc->buf_area;
   1163 	(sc->sc_memset)(ptr, 0, sc->buf_area_sz);
   1164 
   1165 	/* Allocate tx/rx buffers. */
   1166 	for (i = 0; i < NTXBUF; i++) {
   1167 		sc->xmit_cbuffs[i] = ptr;
   1168 		ptr += IE_TBUF_SIZE;
   1169 	}
   1170 	for (i = 0; i < sc->nrxbuf; i++) {
   1171 		sc->cbuffs[i] = ptr;
   1172 		ptr += IE_RBUF_SIZE;
   1173 	}
   1174 
   1175 	/* Small pad (Don't trust the chip...) */
   1176 	ptr += 16;
   1177 
   1178 	/* Allocate and fill in xmit buffer descriptors. */
   1179 	for (i = 0; i < NTXBUF; i++) {
   1180 		sc->xmit_buffs[i] = (volatile void *)ptr;
   1181 		ptr = Align(ptr + sizeof(*sc->xmit_buffs[i]));
   1182 		sc->xmit_buffs[i]->ie_xmit_buf =
   1183 		    Swap32(vtop24(sc, sc->xmit_cbuffs[i]));
   1184 		sc->xmit_buffs[i]->ie_xmit_next = SWAP(0xffff);
   1185 	}
   1186 
   1187 	/* Allocate and fill in recv buffer descriptors. */
   1188 	for (i = 0; i < sc->nrxbuf; i++) {
   1189 		sc->rbuffs[i] = (volatile void *)ptr;
   1190 		ptr = Align(ptr + sizeof(*sc->rbuffs[i]));
   1191 		sc->rbuffs[i]->ie_rbd_buffer =
   1192 		    Swap32(vtop24(sc, sc->cbuffs[i]));
   1193 		sc->rbuffs[i]->ie_rbd_length = SWAP(IE_RBUF_SIZE);
   1194 	}
   1195 
   1196 	/* link together recv bufs and set EOL on last */
   1197 	i = sc->nrxbuf - 1;
   1198 	sc->rbuffs[i]->ie_rbd_length |= IE_RBD_LAST;
   1199 	nxt = vtop16sw(sc, __UNVOLATILE(sc->rbuffs[0]));
   1200 	do {
   1201 		sc->rbuffs[i]->ie_rbd_next = nxt;
   1202 		nxt = vtop16sw(sc, __UNVOLATILE(sc->rbuffs[i]));
   1203 	} while (--i >= 0);
   1204 
   1205 	/* Allocate transmit commands. */
   1206 	for (i = 0; i < NTXBUF; i++) {
   1207 		sc->xmit_cmds[i] = (volatile void *)ptr;
   1208 		ptr = Align(ptr + sizeof(*sc->xmit_cmds[i]));
   1209 		sc->xmit_cmds[i]->com.ie_cmd_link = SWAP(0xffff);
   1210 	}
   1211 
   1212 	/* Allocate receive frames. */
   1213 	for (i = 0; i < sc->nframes; i++) {
   1214 		sc->rframes[i] = (volatile void *)ptr;
   1215 		ptr = Align(ptr + sizeof(*sc->rframes[i]));
   1216 	}
   1217 
   1218 	/* Link together recv frames and set EOL on last */
   1219 	i = sc->nframes - 1;
   1220 	sc->rframes[i]->ie_fd_last |= IE_FD_LAST;
   1221 	nxt = vtop16sw(sc, __UNVOLATILE(sc->rframes[0]));
   1222 	do {
   1223 		sc->rframes[i]->ie_fd_next = nxt;
   1224 		nxt = vtop16sw(sc, __UNVOLATILE(sc->rframes[i]));
   1225 	} while (--i >= 0);
   1226 
   1227 
   1228 	/* Pointers to last packet sent and next available transmit buffer. */
   1229 	sc->xchead = sc->xctail = 0;
   1230 
   1231 	/* Clear transmit-busy flag. */
   1232 	sc->xmit_busy = 0;
   1233 
   1234 	/*
   1235 	 * Set the head and tail pointers on receive to keep track of
   1236 	 * the order in which RFDs and RBDs are used.   link the
   1237 	 * recv frames and buffer into the scb.
   1238 	 */
   1239 	sc->rfhead = 0;
   1240 	sc->rftail = sc->nframes - 1;
   1241 	sc->rbhead = 0;
   1242 	sc->rbtail = sc->nrxbuf - 1;
   1243 
   1244 	sc->scb->ie_recv_list =
   1245 	    vtop16sw(sc, __UNVOLATILE(sc->rframes[0]));
   1246 	sc->rframes[0]->ie_fd_buf_desc =
   1247 	    vtop16sw(sc, __UNVOLATILE(sc->rbuffs[0]));
   1248 
   1249 	i = (ptr - sc->buf_area);
   1250 #ifdef IEDEBUG
   1251 	printf("IE_DEBUG: used %d of %d bytes\n", i, sc->buf_area_sz);
   1252 #endif
   1253 	if (i > sc->buf_area_sz)
   1254 		panic("ie: iememinit, out of space");
   1255 }
   1256 
   1257 /*
   1258  * Run the multicast setup command.
   1259  * Called at splnet().
   1260  */
   1261 static int
   1262 mc_setup(struct ie_softc *sc, void *ptr)
   1263 {
   1264 	struct ie_mcast_cmd *cmd = ptr;	/* XXX - Was volatile */
   1265 
   1266 	cmd->com.ie_cmd_status = SWAP(0);
   1267 	cmd->com.ie_cmd_cmd = IE_CMD_MCAST | IE_CMD_LAST;
   1268 	cmd->com.ie_cmd_link = SWAP(0xffff);
   1269 
   1270 	(sc->sc_memcpy)((void *)cmd->ie_mcast_addrs,
   1271 	    (void *)sc->mcast_addrs,
   1272 	    sc->mcast_count * sizeof *sc->mcast_addrs);
   1273 
   1274 	cmd->ie_mcast_bytes =
   1275 	    SWAP(sc->mcast_count * ETHER_ADDR_LEN);	/* grrr... */
   1276 
   1277 	sc->scb->ie_command_list = vtop16sw(sc, cmd);
   1278 	if (cmd_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
   1279 	    (cmd->com.ie_cmd_status & IE_STAT_OK) == 0) {
   1280 		printf("%s: multicast address setup command failed\n",
   1281 		    device_xname(sc->sc_dev));
   1282 		return 0;
   1283 	}
   1284 	return 1;
   1285 }
   1286 
   1287 static inline void
   1288 ie_setup_config(struct ie_config_cmd *cmd, int promiscuous, int manchester)
   1289 {
   1290 
   1291 	/*
   1292 	 * these are all char's so no need to byte-swap
   1293 	 */
   1294 	cmd->ie_config_count = 0x0c;
   1295 	cmd->ie_fifo = 8;
   1296 	cmd->ie_save_bad = 0x40;
   1297 	cmd->ie_addr_len = 0x2e;
   1298 	cmd->ie_priority = 0;
   1299 	cmd->ie_ifs = 0x60;
   1300 	cmd->ie_slot_low = 0;
   1301 	cmd->ie_slot_high = 0xf2;
   1302 	cmd->ie_promisc = promiscuous | manchester << 2;
   1303 	cmd->ie_crs_cdt = 0;
   1304 	cmd->ie_min_len = 64;
   1305 	cmd->ie_junk = 0xff;
   1306 }
   1307 
   1308 /*
   1309  * This routine inits the ie.
   1310  * This includes executing the CONFIGURE, IA-SETUP, and MC-SETUP commands,
   1311  * starting the receiver unit, and clearing interrupts.
   1312  *
   1313  * THIS ROUTINE MUST BE CALLED AT splnet() OR HIGHER.
   1314  */
   1315 static int
   1316 ieinit(struct ie_softc *sc)
   1317 {
   1318 	volatile struct ie_sys_ctl_block *scb = sc->scb;
   1319 	void *ptr;
   1320 	struct ifnet *ifp;
   1321 
   1322 	ifp = &sc->sc_if;
   1323 	ptr = sc->buf_area;	/* XXX - Use scb instead? */
   1324 
   1325 	/*
   1326 	 * Send the configure command first.
   1327 	 */
   1328 	{
   1329 		struct ie_config_cmd *cmd = ptr;	/* XXX - Was volatile */
   1330 
   1331 		scb->ie_command_list = vtop16sw(sc, cmd);
   1332 		cmd->com.ie_cmd_status = SWAP(0);
   1333 		cmd->com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST;
   1334 		cmd->com.ie_cmd_link = SWAP(0xffff);
   1335 
   1336 		ie_setup_config(cmd, (sc->promisc != 0), 0);
   1337 
   1338 		if (cmd_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
   1339 		    (cmd->com.ie_cmd_status & IE_STAT_OK) == 0) {
   1340 			printf("%s: configure command failed\n",
   1341 			    device_xname(sc->sc_dev));
   1342 			return 0;
   1343 		}
   1344 	}
   1345 
   1346 	/*
   1347 	 * Now send the Individual Address Setup command.
   1348 	 */
   1349 	{
   1350 		struct ie_iasetup_cmd *cmd = ptr;	/* XXX - Was volatile */
   1351 
   1352 		scb->ie_command_list = vtop16sw(sc, cmd);
   1353 		cmd->com.ie_cmd_status = SWAP(0);
   1354 		cmd->com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST;
   1355 		cmd->com.ie_cmd_link = SWAP(0xffff);
   1356 
   1357 		(sc->sc_memcpy)((void *)&cmd->ie_address,
   1358 		    CLLADDR(ifp->if_sadl), sizeof(cmd->ie_address));
   1359 
   1360 		if (cmd_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
   1361 		    (cmd->com.ie_cmd_status & IE_STAT_OK) == 0) {
   1362 			printf("%s: individual address setup command failed\n",
   1363 			    device_xname(sc->sc_dev));
   1364 			return 0;
   1365 		}
   1366 	}
   1367 
   1368 	/*
   1369 	 * Now run the time-domain reflectometer.
   1370 	 */
   1371 	if (ie_run_tdr)
   1372 		run_tdr(sc, ptr);
   1373 
   1374 	/*
   1375 	 * Acknowledge any interrupts we have generated thus far.
   1376 	 */
   1377 	ie_ack(sc, IE_ST_WHENCE);
   1378 
   1379 	/*
   1380 	 * Set up the transmit and recv buffers.
   1381 	 */
   1382 	iememinit(sc);
   1383 
   1384 	/* tell higher levels that we are here */
   1385 	ifp->if_flags |= IFF_RUNNING;
   1386 
   1387 	sc->scb->ie_recv_list =
   1388 	    vtop16sw(sc, __UNVOLATILE(sc->rframes[0]));
   1389 	cmd_and_wait(sc, IE_RU_START, 0, 0);
   1390 
   1391 	ie_ack(sc, IE_ST_WHENCE);
   1392 
   1393 	if (sc->run_586)
   1394 		(sc->run_586)(sc);
   1395 
   1396 	return 0;
   1397 }
   1398 
   1399 static void
   1400 iestop(struct ie_softc *sc)
   1401 {
   1402 
   1403 	cmd_and_wait(sc, IE_RU_DISABLE, 0, 0);
   1404 }
   1405 
   1406 static int
   1407 ieioctl(struct ifnet *ifp, u_long cmd, void *data)
   1408 {
   1409 	struct ie_softc *sc = ifp->if_softc;
   1410 	struct ifaddr *ifa = (struct ifaddr *)data;
   1411 	int s, error = 0;
   1412 
   1413 	s = splnet();
   1414 
   1415 	switch (cmd) {
   1416 
   1417 	case SIOCINITIFADDR:
   1418 		ifp->if_flags |= IFF_UP;
   1419 
   1420 		switch (ifa->ifa_addr->sa_family) {
   1421 #ifdef INET
   1422 		case AF_INET:
   1423 			ieinit(sc);
   1424 			arp_ifinit(ifp, ifa);
   1425 			break;
   1426 #endif
   1427 		default:
   1428 			ieinit(sc);
   1429 			break;
   1430 		}
   1431 		break;
   1432 
   1433 	case SIOCSIFFLAGS:
   1434 		if ((error = ifioctl_common(ifp, cmd, data)) != 0)
   1435 			break;
   1436 		sc->promisc = ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
   1437 
   1438 		switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
   1439 		case IFF_RUNNING:
   1440 			/*
   1441 			 * If interface is marked down and it is running, then
   1442 			 * stop it.
   1443 			 */
   1444 			iestop(sc);
   1445 			ifp->if_flags &= ~IFF_RUNNING;
   1446 			break;
   1447 		case IFF_UP:
   1448 			/*
   1449 			 * If interface is marked up and it is stopped, then
   1450 			 * start it.
   1451 			 */
   1452 			ieinit(sc);
   1453 			break;
   1454 		default:
   1455 			/*
   1456 			 * Reset the interface to pick up changes in any other
   1457 			 * flags that affect hardware registers.
   1458 			 */
   1459 			iestop(sc);
   1460 			ieinit(sc);
   1461 			break;
   1462 		}
   1463 #ifdef IEDEBUG
   1464 		if (ifp->if_flags & IFF_DEBUG)
   1465 			sc->sc_debug = IED_ALL;
   1466 		else
   1467 			sc->sc_debug = ie_debug_flags;
   1468 #endif
   1469 		break;
   1470 
   1471 	case SIOCADDMULTI:
   1472 	case SIOCDELMULTI:
   1473 		if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
   1474 			/*
   1475 			 * Multicast list has changed; set the hardware filter
   1476 			 * accordingly.
   1477 			 */
   1478 			if (ifp->if_flags & IFF_RUNNING)
   1479 				mc_reset(sc);
   1480 			error = 0;
   1481 		}
   1482 		break;
   1483 
   1484 	default:
   1485 		error = ether_ioctl(ifp, cmd, data);
   1486 		break;
   1487 	}
   1488 	splx(s);
   1489 	return error;
   1490 }
   1491 
   1492 static void
   1493 mc_reset(struct ie_softc *sc)
   1494 {
   1495 	struct ethercom *ec = &sc->sc_ethercom;
   1496 	struct ether_multi *enm;
   1497 	struct ether_multistep step;
   1498 	struct ifnet *ifp;
   1499 
   1500 	ifp = &sc->sc_if;
   1501 
   1502 	/*
   1503 	 * Step through the list of addresses.
   1504 	 */
   1505 	sc->mcast_count = 0;
   1506 	ETHER_FIRST_MULTI(step, ec, enm);
   1507 	while (enm) {
   1508 		if (sc->mcast_count >= MAXMCAST ||
   1509 		    ether_cmp(enm->enm_addrlo, enm->enm_addrhi) != 0) {
   1510 			ifp->if_flags |= IFF_ALLMULTI;
   1511 			ieioctl(ifp, SIOCSIFFLAGS, NULL);
   1512 			goto setflag;
   1513 		}
   1514 		memcpy(&sc->mcast_addrs[sc->mcast_count], enm->enm_addrlo,
   1515 		    ETHER_ADDR_LEN);
   1516 		sc->mcast_count++;
   1517 		ETHER_NEXT_MULTI(step, enm);
   1518 	}
   1519 setflag:
   1520 	ETHER_UNLOCK(ec);
   1521 	sc->want_mcsetup = 1;
   1522 }
   1523 
   1524 #ifdef IEDEBUG
   1525 void
   1526 print_rbd(volatile struct ie_recv_buf_desc *rbd)
   1527 {
   1528 
   1529 	printf("RBD at %08lx:\nactual %04x, next %04x, buffer %08x\n"
   1530 	    "length %04x, mbz %04x\n", (u_long)rbd, rbd->ie_rbd_actual,
   1531 	    rbd->ie_rbd_next, rbd->ie_rbd_buffer, rbd->ie_rbd_length,
   1532 	    rbd->mbz);
   1533 }
   1534 #endif
   1535