Home | History | Annotate | Line # | Download | only in dev
if_ie.c revision 1.68
      1 /*	$NetBSD: if_ie.c,v 1.68 2019/05/23 10:57:27 msaitoh 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 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 <sys/cdefs.h>
    101 __KERNEL_RCSID(0, "$NetBSD: if_ie.c,v 1.68 2019/05/23 10:57:27 msaitoh 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 	++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 		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 				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 	ifp->if_flags &= ~IFF_OACTIVE;
    587 
    588 	status = sc->xmit_cmds[sc->xctail]->ie_xmit_status;
    589 
    590 	if (!(status & IE_STAT_COMPL) || (status & IE_STAT_BUSY))
    591 		printf("%s: command still busy!\n", __func__);
    592 
    593 	if (status & IE_STAT_OK) {
    594 		ifp->if_opackets++;
    595 		ifp->if_collisions += SWAP(status & IE_XS_MAXCOLL);
    596 	} else {
    597 		ifp->if_oerrors++;
    598 		/*
    599 		 * XXX
    600 		 * Check SQE and DEFERRED?
    601 		 * What if more than one bit is set?
    602 		 */
    603 		if (status & IE_STAT_ABORT)
    604 			printf("%s: send aborted\n", device_xname(sc->sc_dev));
    605 		if (status & IE_XS_LATECOLL)
    606 			printf("%s: late collision\n",
    607 			    device_xname(sc->sc_dev));
    608 		if (status & IE_XS_NOCARRIER)
    609 			printf("%s: no carrier\n", device_xname(sc->sc_dev));
    610 		if (status & IE_XS_LOSTCTS)
    611 			printf("%s: lost CTS\n", device_xname(sc->sc_dev));
    612 		if (status & IE_XS_UNDERRUN)
    613 			printf("%s: DMA underrun\n", device_xname(sc->sc_dev));
    614 		if (status & IE_XS_EXCMAX) {
    615 			/* Do not print this one (too noisy). */
    616 			ifp->if_collisions += 16;
    617 		}
    618 	}
    619 
    620 	/*
    621 	 * If multicast addresses were added or deleted while we
    622 	 * were transmitting, mc_reset() set the want_mcsetup flag
    623 	 * indicating that we should do it.
    624 	 */
    625 	if (sc->want_mcsetup) {
    626 		mc_setup(sc, (void *)sc->xmit_cbuffs[sc->xctail]);
    627 		sc->want_mcsetup = 0;
    628 	}
    629 
    630 	/* Done with the buffer. */
    631 	sc->xmit_busy--;
    632 	sc->xctail = (sc->xctail + 1) % NTXBUF;
    633 
    634 	/* Start the next packet, if any, transmitting. */
    635 	if (sc->xmit_busy > 0)
    636 		iexmit(sc);
    637 
    638 	if_schedule_deferred_start(ifp);
    639 }
    640 
    641 /*
    642  * Compare two Ether/802 addresses for equality, inlined and
    643  * unrolled for speed.  I'd love to have an inline assembler
    644  * version of this...   XXX: Who wanted that? mycroft?
    645  * I wrote one, but the following is just as efficient.
    646  * This expands to 10 short m68k instructions! -gwr
    647  * Note: use this like memcmp()
    648  */
    649 static inline uint16_t
    650 ether_cmp(uint8_t *one, uint8_t *two)
    651 {
    652 	uint16_t *a = (uint16_t *)one;
    653 	uint16_t *b = (uint16_t *)two;
    654 	uint16_t diff;
    655 
    656 	diff  = *a++ - *b++;
    657 	diff |= *a++ - *b++;
    658 	diff |= *a++ - *b++;
    659 
    660 	return diff;
    661 }
    662 #define	ether_equal !ether_cmp
    663 
    664 /*
    665  * We want to isolate the bits that have meaning...  This assumes that
    666  * IE_RBUF_SIZE is an even power of two.  If somehow the act_len exceeds
    667  * the size of the buffer, then we are screwed anyway.
    668  */
    669 static inline int
    670 ie_buflen(struct ie_softc *sc, int head)
    671 {
    672 	int len;
    673 
    674 	len = SWAP(sc->rbuffs[head]->ie_rbd_actual);
    675 	len &= (IE_RBUF_SIZE | (IE_RBUF_SIZE - 1));
    676 	return len;
    677 }
    678 
    679 static inline int
    680 ie_packet_len(struct ie_softc *sc)
    681 {
    682 	int i;
    683 	int head = sc->rbhead;
    684 	int acc = 0;
    685 
    686 	do {
    687 		if ((sc->rbuffs[sc->rbhead]->ie_rbd_actual & IE_RBD_USED)
    688 		    == 0) {
    689 #ifdef IEDEBUG
    690 			print_rbd(sc->rbuffs[sc->rbhead]);
    691 #endif
    692 			log(LOG_ERR,
    693 			    "%s: receive descriptors out of sync at %d\n",
    694 			    device_xname(sc->sc_dev), sc->rbhead);
    695 			iereset(sc);
    696 			return -1;
    697 		}
    698 
    699 		i = sc->rbuffs[head]->ie_rbd_actual & IE_RBD_LAST;
    700 
    701 		acc += ie_buflen(sc, head);
    702 		head = (head + 1) % sc->nrxbuf;
    703 	} while (i == 0);
    704 
    705 	return acc;
    706 }
    707 
    708 /*
    709  * Setup all necessary artifacts for an XMIT command, and then pass the XMIT
    710  * command to the chip to be executed.  On the way, if we have a BPF listener
    711  * also give him a copy.
    712  */
    713 static void
    714 iexmit(struct ie_softc *sc)
    715 {
    716 	struct ifnet *ifp;
    717 
    718 	ifp = &sc->sc_if;
    719 
    720 #ifdef IEDEBUG
    721 	if (sc->sc_debug & IED_XMIT)
    722 		printf("%s: xmit buffer %d\n", device_xname(sc->sc_dev),
    723 		    sc->xctail);
    724 #endif
    725 
    726 	sc->xmit_buffs[sc->xctail]->ie_xmit_flags |= IE_XMIT_LAST;
    727 	sc->xmit_buffs[sc->xctail]->ie_xmit_next = SWAP(0xffff);
    728 	sc->xmit_buffs[sc->xctail]->ie_xmit_buf =
    729 	    Swap32(vtop24(sc, sc->xmit_cbuffs[sc->xctail]));
    730 
    731 	sc->xmit_cmds[sc->xctail]->com.ie_cmd_link = SWAP(0xffff);
    732 	sc->xmit_cmds[sc->xctail]->com.ie_cmd_cmd =
    733 	    IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST;
    734 
    735 	sc->xmit_cmds[sc->xctail]->ie_xmit_status = SWAP(0);
    736 	sc->xmit_cmds[sc->xctail]->ie_xmit_desc =
    737 	    vtop16sw(sc, __UNVOLATILE(sc->xmit_buffs[sc->xctail]));
    738 
    739 	sc->scb->ie_command_list =
    740 	    vtop16sw(sc, __UNVOLATILE(sc->xmit_cmds[sc->xctail]));
    741 	cmd_and_wait(sc, IE_CU_START, 0, 0);
    742 
    743 	ifp->if_timer = 5;
    744 }
    745 
    746 /*
    747  * Read data off the interface, and turn it into an mbuf chain.
    748  *
    749  * This code is DRAMATICALLY different from the previous version; this
    750  * version tries to allocate the entire mbuf chain up front, given the
    751  * length of the data available.  This enables us to allocate mbuf
    752  * clusters in many situations where before we would have had a long
    753  * chain of partially-full mbufs.  This should help to speed up the
    754  * operation considerably.  (Provided that it works, of course.)
    755  */
    756 static inline struct mbuf *
    757 ieget(struct ie_softc *sc)
    758 {
    759 	struct mbuf *top, **mp, *m;
    760 	int len, totlen, resid;
    761 	int thisrboff, thismboff;
    762 	int head;
    763 	struct ether_header eh;
    764 
    765 	totlen = ie_packet_len(sc);
    766 	if (totlen <= 0)
    767 		return 0;
    768 
    769 	head = sc->rbhead;
    770 
    771 	/*
    772 	 * Snarf the Ethernet header.
    773 	 */
    774 	(sc->sc_memcpy)((void *)&eh, (void *)sc->cbuffs[head],
    775 	    sizeof(struct ether_header));
    776 
    777 	resid = totlen;
    778 
    779 	MGETHDR(m, M_DONTWAIT, MT_DATA);
    780 	if (m == 0)
    781 		return 0;
    782 
    783 	m_set_rcvif(m, &sc->sc_if);
    784 	m->m_pkthdr.len = totlen;
    785 	len = MHLEN;
    786 	top = 0;
    787 	mp = &top;
    788 
    789 	/*
    790 	 * This loop goes through and allocates mbufs for all the data we will
    791 	 * be copying in.  It does not actually do the copying yet.
    792 	 */
    793 	while (totlen > 0) {
    794 		if (top) {
    795 			MGET(m, M_DONTWAIT, MT_DATA);
    796 			if (m == 0) {
    797 				m_freem(top);
    798 				return 0;
    799 			}
    800 			len = MLEN;
    801 		}
    802 		if (totlen >= MINCLSIZE) {
    803 			MCLGET(m, M_DONTWAIT);
    804 			if (m->m_flags & M_EXT)
    805 				len = MCLBYTES;
    806 		}
    807 
    808 		if (mp == &top) {
    809 			char *newdata = (char *)
    810 			    ALIGN(m->m_data + sizeof(struct ether_header)) -
    811 			    sizeof(struct ether_header);
    812 			len -= newdata - m->m_data;
    813 			m->m_data = newdata;
    814 		}
    815 
    816 		m->m_len = len = uimin(totlen, len);
    817 
    818 		totlen -= len;
    819 		*mp = m;
    820 		mp = &m->m_next;
    821 	}
    822 
    823 	m = top;
    824 	thismboff = 0;
    825 
    826 	/*
    827 	 * Copy the Ethernet header into the mbuf chain.
    828 	 */
    829 	memcpy(mtod(m, void *), &eh, sizeof(struct ether_header));
    830 	thismboff = sizeof(struct ether_header);
    831 	thisrboff = sizeof(struct ether_header);
    832 	resid -= sizeof(struct ether_header);
    833 
    834 	/*
    835 	 * Now we take the mbuf chain (hopefully only one mbuf most of the
    836 	 * time) and stuff the data into it.  There are no possible failures
    837 	 * at or after this point.
    838 	 */
    839 	while (resid > 0) {
    840 		int thisrblen = ie_buflen(sc, head) - thisrboff;
    841 		int thismblen = m->m_len - thismboff;
    842 
    843 		len = uimin(thisrblen, thismblen);
    844 		(sc->sc_memcpy)(mtod(m, char *) + thismboff,
    845 		    (void *)(sc->cbuffs[head] + thisrboff),
    846 		    (u_int)len);
    847 		resid -= len;
    848 
    849 		if (len == thismblen) {
    850 			m = m->m_next;
    851 			thismboff = 0;
    852 		} else
    853 			thismboff += len;
    854 
    855 		if (len == thisrblen) {
    856 			head = (head + 1) % sc->nrxbuf;
    857 			thisrboff = 0;
    858 		} else
    859 			thisrboff += len;
    860 	}
    861 
    862 	/*
    863 	 * Unless something changed strangely while we were doing the copy,
    864 	 * we have now copied everything in from the shared memory.
    865 	 * This means that we are done.
    866 	 */
    867 	return top;
    868 }
    869 
    870 /*
    871  * Read frame NUM from unit UNIT (pre-cached as IE).
    872  *
    873  * This routine reads the RFD at NUM, and copies in the buffers from
    874  * the list of RBD, then rotates the RBD and RFD lists so that the receiver
    875  * doesn't start complaining.  Trailers are DROPPED---there's no point
    876  * in wasting time on confusing code to deal with them.  Hopefully,
    877  * this machine will never ARP for trailers anyway.
    878  */
    879 static void
    880 ie_readframe(struct ie_softc *sc, int num)
    881 {
    882 	int status;
    883 	struct mbuf *m = 0;
    884 
    885 	status = sc->rframes[num]->ie_fd_status;
    886 
    887 	/* Advance the RFD list, since we're done with this descriptor. */
    888 	sc->rframes[num]->ie_fd_status = SWAP(0);
    889 	sc->rframes[num]->ie_fd_last |= IE_FD_LAST;
    890 	sc->rframes[sc->rftail]->ie_fd_last &= ~IE_FD_LAST;
    891 	sc->rftail = (sc->rftail + 1) % sc->nframes;
    892 	sc->rfhead = (sc->rfhead + 1) % sc->nframes;
    893 
    894 	if (status & IE_FD_OK) {
    895 		m = ieget(sc);
    896 		ie_drop_packet_buffer(sc);
    897 	}
    898 	if (m == 0) {
    899 		sc->sc_if.if_ierrors++;
    900 		return;
    901 	}
    902 
    903 #ifdef IEDEBUG
    904 	if (sc->sc_debug & IED_READFRAME) {
    905 		struct ether_header *eh = mtod(m, struct ether_header *);
    906 
    907 		printf("%s: frame from ether %s type 0x%x\n",
    908 		    device_xname(sc->sc_dev),
    909 		    ether_sprintf(eh->ether_shost), (u_int)eh->ether_type);
    910 	}
    911 #endif
    912 
    913 	/*
    914 	 * Finally pass this packet up to higher layers.
    915 	 */
    916 	if_percpuq_enqueue((&sc->sc_if)->if_percpuq, m);
    917 }
    918 
    919 static void
    920 ie_drop_packet_buffer(struct ie_softc *sc)
    921 {
    922 	int i;
    923 
    924 	do {
    925 		/*
    926 		 * This means we are somehow out of sync.  So, we reset the
    927 		 * adapter.
    928 		 */
    929 		if ((sc->rbuffs[sc->rbhead]->ie_rbd_actual & IE_RBD_USED)
    930 		    == 0) {
    931 #ifdef IEDEBUG
    932 			print_rbd(sc->rbuffs[sc->rbhead]);
    933 #endif
    934 			log(LOG_ERR,
    935 			    "%s: receive descriptors out of sync at %d\n",
    936 			    device_xname(sc->sc_dev), sc->rbhead);
    937 			iereset(sc);
    938 			return;
    939 		}
    940 
    941 		i = sc->rbuffs[sc->rbhead]->ie_rbd_actual & IE_RBD_LAST;
    942 
    943 		sc->rbuffs[sc->rbhead]->ie_rbd_length |= IE_RBD_LAST;
    944 		sc->rbuffs[sc->rbhead]->ie_rbd_actual = SWAP(0);
    945 		sc->rbhead = (sc->rbhead + 1) % sc->nrxbuf;
    946 		sc->rbuffs[sc->rbtail]->ie_rbd_length &= ~IE_RBD_LAST;
    947 		sc->rbtail = (sc->rbtail + 1) % sc->nrxbuf;
    948 	} while (i == 0);
    949 }
    950 
    951 /*
    952  * Start transmission on an interface.
    953  */
    954 static void
    955 iestart(struct ifnet *ifp)
    956 {
    957 	struct ie_softc *sc = ifp->if_softc;
    958 	struct mbuf *m0, *m;
    959 	uint8_t *buffer;
    960 	uint16_t len;
    961 
    962 	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
    963 		return;
    964 
    965 	for (;;) {
    966 		if (sc->xmit_busy == sc->ntxbuf) {
    967 			ifp->if_flags |= IFF_OACTIVE;
    968 			break;
    969 		}
    970 
    971 		IF_DEQUEUE(&ifp->if_snd, m0);
    972 		if (m0 == 0)
    973 			break;
    974 
    975 		/* We need to use m->m_pkthdr.len, so require the header */
    976 		if ((m0->m_flags & M_PKTHDR) == 0)
    977 			panic("%s: no header mbuf", __func__);
    978 
    979 		/* Tap off here if there is a BPF listener. */
    980 		bpf_mtap(ifp, m0, BPF_D_OUT);
    981 
    982 #ifdef IEDEBUG
    983 		if (sc->sc_debug & IED_ENQ)
    984 			printf("%s: fill buffer %d\n", device_xname(sc->sc_dev),
    985 			    sc->xchead);
    986 #endif
    987 
    988 		buffer = sc->xmit_cbuffs[sc->xchead];
    989 		for (m = m0; m != 0; m = m->m_next) {
    990 			(sc->sc_memcpy)(buffer, mtod(m, void *), m->m_len);
    991 			buffer += m->m_len;
    992 		}
    993 		if (m0->m_pkthdr.len < ETHER_MIN_LEN - ETHER_CRC_LEN) {
    994 			sc->sc_memset(buffer, 0,
    995 			    ETHER_MIN_LEN - ETHER_CRC_LEN - m0->m_pkthdr.len);
    996 			len = ETHER_MIN_LEN - ETHER_CRC_LEN;
    997 		} else
    998 			len = m0->m_pkthdr.len;
    999 
   1000 		m_freem(m0);
   1001 		sc->xmit_buffs[sc->xchead]->ie_xmit_flags = SWAP(len);
   1002 
   1003 		/* Start the first packet transmitting. */
   1004 		if (sc->xmit_busy == 0)
   1005 			iexmit(sc);
   1006 
   1007 		sc->xchead = (sc->xchead + 1) % sc->ntxbuf;
   1008 		sc->xmit_busy++;
   1009 	}
   1010 }
   1011 
   1012 static void
   1013 iereset(struct ie_softc *sc)
   1014 {
   1015 	int s;
   1016 
   1017 	s = splnet();
   1018 
   1019 	/* No message here.  The caller does that. */
   1020 	iestop(sc);
   1021 
   1022 	/*
   1023 	 * Stop i82586 dead in its tracks.
   1024 	 */
   1025 	if (cmd_and_wait(sc, IE_RU_ABORT | IE_CU_ABORT, 0, 0))
   1026 		printf("%s: abort commands timed out\n",
   1027 		    device_xname(sc->sc_dev));
   1028 
   1029 	if (cmd_and_wait(sc, IE_RU_DISABLE | IE_CU_STOP, 0, 0))
   1030 		printf("%s: disable commands timed out\n",
   1031 		    device_xname(sc->sc_dev));
   1032 
   1033 	ieinit(sc);
   1034 
   1035 	splx(s);
   1036 }
   1037 
   1038 /*
   1039  * Send a command to the controller and wait for it to either
   1040  * complete or be accepted, depending on the command.  If the
   1041  * command pointer is null, then pretend that the command is
   1042  * not an action command.  If the command pointer is not null,
   1043  * and the command is an action command, wait for
   1044  * ((volatile struct ie_cmd_common *)pcmd)->ie_cmd_status & MASK
   1045  * to become true.
   1046  */
   1047 static int
   1048 cmd_and_wait(struct ie_softc *sc, int cmd, void *pcmd, int mask)
   1049 {
   1050 	volatile struct ie_cmd_common *cc = pcmd;
   1051 	volatile struct ie_sys_ctl_block *scb = sc->scb;
   1052 	int tmo;
   1053 
   1054 	scb->ie_command = (uint16_t)cmd;
   1055 	(sc->chan_attn)(sc);
   1056 
   1057 	/* Wait for the command to be accepted by the CU. */
   1058 	tmo = 10;
   1059 	while (scb->ie_command && --tmo)
   1060 		delay(10);
   1061 	if (scb->ie_command) {
   1062 #ifdef	IEDEBUG
   1063 		printf("%s: cmd_and_wait, CU stuck (1)\n",
   1064 		    device_xname(sc->sc_dev));
   1065 #endif
   1066 		return -1;	/* timed out */
   1067 	}
   1068 
   1069 	/*
   1070 	 * If asked, also wait for it to finish.
   1071 	 */
   1072 	if (IE_ACTION_COMMAND(cmd) && pcmd) {
   1073 
   1074 		/*
   1075 		 * According to the packet driver, the minimum timeout should
   1076 		 * be .369 seconds, which we round up to .4.
   1077 		 */
   1078 		tmo = 36900;
   1079 
   1080 		/*
   1081 		 * Now spin-lock waiting for status.  This is not a very nice
   1082 		 * thing to do, but I haven't figured out how, or indeed if, we
   1083 		 * can put the process waiting for action to sleep.  (We may
   1084 		 * be getting called through some other timeout running in the
   1085 		 * kernel.)
   1086 		 */
   1087 		while (((cc->ie_cmd_status & mask) == 0) && --tmo)
   1088 			delay(10);
   1089 
   1090 		if ((cc->ie_cmd_status & mask) == 0) {
   1091 #ifdef	IEDEBUG
   1092 			printf("%s: cmd_and_wait, CU stuck (2)\n",
   1093 			    device_xname(sc->sc_dev));
   1094 #endif
   1095 			return -1;	/* timed out */
   1096 		}
   1097 	}
   1098 	return 0;
   1099 }
   1100 
   1101 /*
   1102  * Run the time-domain reflectometer.
   1103  */
   1104 static void
   1105 run_tdr(struct ie_softc *sc, struct ie_tdr_cmd *cmd)
   1106 {
   1107 	int result;
   1108 
   1109 	cmd->com.ie_cmd_status = SWAP(0);
   1110 	cmd->com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST;
   1111 	cmd->com.ie_cmd_link = SWAP(0xffff);
   1112 
   1113 	sc->scb->ie_command_list = vtop16sw(sc, cmd);
   1114 	cmd->ie_tdr_time = SWAP(0);
   1115 
   1116 	if (cmd_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
   1117 	    (cmd->com.ie_cmd_status & IE_STAT_OK) == 0)
   1118 		result = 0x10000;	/* impossible value */
   1119 	else
   1120 		result = cmd->ie_tdr_time;
   1121 
   1122 	ie_ack(sc, IE_ST_WHENCE);
   1123 
   1124 	if (result & IE_TDR_SUCCESS)
   1125 		return;
   1126 
   1127 	if (result & 0x10000) {
   1128 		printf("%s: TDR command failed\n", device_xname(sc->sc_dev));
   1129 	} else if (result & IE_TDR_XCVR) {
   1130 		printf("%s: transceiver problem\n", device_xname(sc->sc_dev));
   1131 	} else if (result & IE_TDR_OPEN) {
   1132 		printf("%s: TDR detected an open %d clocks away\n",
   1133 		    device_xname(sc->sc_dev), SWAP(result & IE_TDR_TIME));
   1134 	} else if (result & IE_TDR_SHORT) {
   1135 		printf("%s: TDR detected a short %d clocks away\n",
   1136 		    device_xname(sc->sc_dev), SWAP(result & IE_TDR_TIME));
   1137 	} else {
   1138 		printf("%s: TDR returned unknown status 0x%x\n",
   1139 		    device_xname(sc->sc_dev), result);
   1140 	}
   1141 }
   1142 
   1143 /*
   1144  * iememinit: set up the buffers
   1145  *
   1146  * we have a block of KVA at sc->buf_area which is of size sc->buf_area_sz.
   1147  * this is to be used for the buffers.  the chip indexs its control data
   1148  * structures with 16 bit offsets, and it indexes actual buffers with
   1149  * 24 bit addresses.   so we should allocate control buffers first so that
   1150  * we don't overflow the 16 bit offset field.   The number of transmit
   1151  * buffers is fixed at compile time.
   1152  *
   1153  * note: this function was written to be easy to understand, rather than
   1154  *       highly efficient (it isn't in the critical path).
   1155  *
   1156  * The memory layout is: tbufs, rbufs, (gap), control blocks
   1157  * [tbuf0, tbuf1] [rbuf0,...rbufN] gap [rframes] [tframes]
   1158  * XXX - This needs review...
   1159  */
   1160 static void
   1161 iememinit(struct ie_softc *sc)
   1162 {
   1163 	uint8_t *ptr;
   1164 	int i;
   1165 	uint16_t nxt;
   1166 
   1167 	/* First, zero all the memory. */
   1168 	ptr = sc->buf_area;
   1169 	(sc->sc_memset)(ptr, 0, sc->buf_area_sz);
   1170 
   1171 	/* Allocate tx/rx buffers. */
   1172 	for (i = 0; i < NTXBUF; i++) {
   1173 		sc->xmit_cbuffs[i] = ptr;
   1174 		ptr += IE_TBUF_SIZE;
   1175 	}
   1176 	for (i = 0; i < sc->nrxbuf; i++) {
   1177 		sc->cbuffs[i] = ptr;
   1178 		ptr += IE_RBUF_SIZE;
   1179 	}
   1180 
   1181 	/* Small pad (Don't trust the chip...) */
   1182 	ptr += 16;
   1183 
   1184 	/* Allocate and fill in xmit buffer descriptors. */
   1185 	for (i = 0; i < NTXBUF; i++) {
   1186 		sc->xmit_buffs[i] = (volatile void *)ptr;
   1187 		ptr = Align(ptr + sizeof(*sc->xmit_buffs[i]));
   1188 		sc->xmit_buffs[i]->ie_xmit_buf =
   1189 		    Swap32(vtop24(sc, sc->xmit_cbuffs[i]));
   1190 		sc->xmit_buffs[i]->ie_xmit_next = SWAP(0xffff);
   1191 	}
   1192 
   1193 	/* Allocate and fill in recv buffer descriptors. */
   1194 	for (i = 0; i < sc->nrxbuf; i++) {
   1195 		sc->rbuffs[i] = (volatile void *)ptr;
   1196 		ptr = Align(ptr + sizeof(*sc->rbuffs[i]));
   1197 		sc->rbuffs[i]->ie_rbd_buffer =
   1198 		    Swap32(vtop24(sc, sc->cbuffs[i]));
   1199 		sc->rbuffs[i]->ie_rbd_length = SWAP(IE_RBUF_SIZE);
   1200 	}
   1201 
   1202 	/* link together recv bufs and set EOL on last */
   1203 	i = sc->nrxbuf - 1;
   1204 	sc->rbuffs[i]->ie_rbd_length |= IE_RBD_LAST;
   1205 	nxt = vtop16sw(sc, __UNVOLATILE(sc->rbuffs[0]));
   1206 	do {
   1207 		sc->rbuffs[i]->ie_rbd_next = nxt;
   1208 		nxt = vtop16sw(sc, __UNVOLATILE(sc->rbuffs[i]));
   1209 	} while (--i >= 0);
   1210 
   1211 	/* Allocate transmit commands. */
   1212 	for (i = 0; i < NTXBUF; i++) {
   1213 		sc->xmit_cmds[i] = (volatile void *)ptr;
   1214 		ptr = Align(ptr + sizeof(*sc->xmit_cmds[i]));
   1215 		sc->xmit_cmds[i]->com.ie_cmd_link = SWAP(0xffff);
   1216 	}
   1217 
   1218 	/* Allocate receive frames. */
   1219 	for (i = 0; i < sc->nframes; i++) {
   1220 		sc->rframes[i] = (volatile void *)ptr;
   1221 		ptr = Align(ptr + sizeof(*sc->rframes[i]));
   1222 	}
   1223 
   1224 	/* Link together recv frames and set EOL on last */
   1225 	i = sc->nframes - 1;
   1226 	sc->rframes[i]->ie_fd_last |= IE_FD_LAST;
   1227 	nxt = vtop16sw(sc, __UNVOLATILE(sc->rframes[0]));
   1228 	do {
   1229 		sc->rframes[i]->ie_fd_next = nxt;
   1230 		nxt = vtop16sw(sc, __UNVOLATILE(sc->rframes[i]));
   1231 	} while (--i >= 0);
   1232 
   1233 
   1234 	/* Pointers to last packet sent and next available transmit buffer. */
   1235 	sc->xchead = sc->xctail = 0;
   1236 
   1237 	/* Clear transmit-busy flag. */
   1238 	sc->xmit_busy = 0;
   1239 
   1240 	/*
   1241 	 * Set the head and tail pointers on receive to keep track of
   1242 	 * the order in which RFDs and RBDs are used.   link the
   1243 	 * recv frames and buffer into the scb.
   1244 	 */
   1245 	sc->rfhead = 0;
   1246 	sc->rftail = sc->nframes - 1;
   1247 	sc->rbhead = 0;
   1248 	sc->rbtail = sc->nrxbuf - 1;
   1249 
   1250 	sc->scb->ie_recv_list =
   1251 	    vtop16sw(sc, __UNVOLATILE(sc->rframes[0]));
   1252 	sc->rframes[0]->ie_fd_buf_desc =
   1253 	    vtop16sw(sc, __UNVOLATILE(sc->rbuffs[0]));
   1254 
   1255 	i = (ptr - sc->buf_area);
   1256 #ifdef IEDEBUG
   1257 	printf("IE_DEBUG: used %d of %d bytes\n", i, sc->buf_area_sz);
   1258 #endif
   1259 	if (i > sc->buf_area_sz)
   1260 		panic("ie: iememinit, out of space");
   1261 }
   1262 
   1263 /*
   1264  * Run the multicast setup command.
   1265  * Called at splnet().
   1266  */
   1267 static int
   1268 mc_setup(struct ie_softc *sc, void *ptr)
   1269 {
   1270 	struct ie_mcast_cmd *cmd = ptr;	/* XXX - Was volatile */
   1271 
   1272 	cmd->com.ie_cmd_status = SWAP(0);
   1273 	cmd->com.ie_cmd_cmd = IE_CMD_MCAST | IE_CMD_LAST;
   1274 	cmd->com.ie_cmd_link = SWAP(0xffff);
   1275 
   1276 	(sc->sc_memcpy)((void *)cmd->ie_mcast_addrs,
   1277 	    (void *)sc->mcast_addrs,
   1278 	    sc->mcast_count * sizeof *sc->mcast_addrs);
   1279 
   1280 	cmd->ie_mcast_bytes =
   1281 	    SWAP(sc->mcast_count * ETHER_ADDR_LEN);	/* grrr... */
   1282 
   1283 	sc->scb->ie_command_list = vtop16sw(sc, cmd);
   1284 	if (cmd_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
   1285 	    (cmd->com.ie_cmd_status & IE_STAT_OK) == 0) {
   1286 		printf("%s: multicast address setup command failed\n",
   1287 		    device_xname(sc->sc_dev));
   1288 		return 0;
   1289 	}
   1290 	return 1;
   1291 }
   1292 
   1293 static inline void
   1294 ie_setup_config(struct ie_config_cmd *cmd, int promiscuous, int manchester)
   1295 {
   1296 
   1297 	/*
   1298 	 * these are all char's so no need to byte-swap
   1299 	 */
   1300 	cmd->ie_config_count = 0x0c;
   1301 	cmd->ie_fifo = 8;
   1302 	cmd->ie_save_bad = 0x40;
   1303 	cmd->ie_addr_len = 0x2e;
   1304 	cmd->ie_priority = 0;
   1305 	cmd->ie_ifs = 0x60;
   1306 	cmd->ie_slot_low = 0;
   1307 	cmd->ie_slot_high = 0xf2;
   1308 	cmd->ie_promisc = promiscuous | manchester << 2;
   1309 	cmd->ie_crs_cdt = 0;
   1310 	cmd->ie_min_len = 64;
   1311 	cmd->ie_junk = 0xff;
   1312 }
   1313 
   1314 /*
   1315  * This routine inits the ie.
   1316  * This includes executing the CONFIGURE, IA-SETUP, and MC-SETUP commands,
   1317  * starting the receiver unit, and clearing interrupts.
   1318  *
   1319  * THIS ROUTINE MUST BE CALLED AT splnet() OR HIGHER.
   1320  */
   1321 static int
   1322 ieinit(struct ie_softc *sc)
   1323 {
   1324 	volatile struct ie_sys_ctl_block *scb = sc->scb;
   1325 	void *ptr;
   1326 	struct ifnet *ifp;
   1327 
   1328 	ifp = &sc->sc_if;
   1329 	ptr = sc->buf_area;	/* XXX - Use scb instead? */
   1330 
   1331 	/*
   1332 	 * Send the configure command first.
   1333 	 */
   1334 	{
   1335 		struct ie_config_cmd *cmd = ptr;	/* XXX - Was volatile */
   1336 
   1337 		scb->ie_command_list = vtop16sw(sc, cmd);
   1338 		cmd->com.ie_cmd_status = SWAP(0);
   1339 		cmd->com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST;
   1340 		cmd->com.ie_cmd_link = SWAP(0xffff);
   1341 
   1342 		ie_setup_config(cmd, (sc->promisc != 0), 0);
   1343 
   1344 		if (cmd_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
   1345 		    (cmd->com.ie_cmd_status & IE_STAT_OK) == 0) {
   1346 			printf("%s: configure command failed\n",
   1347 			    device_xname(sc->sc_dev));
   1348 			return 0;
   1349 		}
   1350 	}
   1351 
   1352 	/*
   1353 	 * Now send the Individual Address Setup command.
   1354 	 */
   1355 	{
   1356 		struct ie_iasetup_cmd *cmd = ptr;	/* XXX - Was volatile */
   1357 
   1358 		scb->ie_command_list = vtop16sw(sc, cmd);
   1359 		cmd->com.ie_cmd_status = SWAP(0);
   1360 		cmd->com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST;
   1361 		cmd->com.ie_cmd_link = SWAP(0xffff);
   1362 
   1363 		(sc->sc_memcpy)((void *)&cmd->ie_address,
   1364 		    CLLADDR(ifp->if_sadl), sizeof(cmd->ie_address));
   1365 
   1366 		if (cmd_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
   1367 		    (cmd->com.ie_cmd_status & IE_STAT_OK) == 0) {
   1368 			printf("%s: individual address setup command failed\n",
   1369 			    device_xname(sc->sc_dev));
   1370 			return 0;
   1371 		}
   1372 	}
   1373 
   1374 	/*
   1375 	 * Now run the time-domain reflectometer.
   1376 	 */
   1377 	if (ie_run_tdr)
   1378 		run_tdr(sc, ptr);
   1379 
   1380 	/*
   1381 	 * Acknowledge any interrupts we have generated thus far.
   1382 	 */
   1383 	ie_ack(sc, IE_ST_WHENCE);
   1384 
   1385 	/*
   1386 	 * Set up the transmit and recv buffers.
   1387 	 */
   1388 	iememinit(sc);
   1389 
   1390 	/* tell higher levels that we are here */
   1391 	ifp->if_flags |= IFF_RUNNING;
   1392 	ifp->if_flags &= ~IFF_OACTIVE;
   1393 
   1394 	sc->scb->ie_recv_list =
   1395 	    vtop16sw(sc, __UNVOLATILE(sc->rframes[0]));
   1396 	cmd_and_wait(sc, IE_RU_START, 0, 0);
   1397 
   1398 	ie_ack(sc, IE_ST_WHENCE);
   1399 
   1400 	if (sc->run_586)
   1401 		(sc->run_586)(sc);
   1402 
   1403 	return 0;
   1404 }
   1405 
   1406 static void
   1407 iestop(struct ie_softc *sc)
   1408 {
   1409 
   1410 	cmd_and_wait(sc, IE_RU_DISABLE, 0, 0);
   1411 }
   1412 
   1413 static int
   1414 ieioctl(struct ifnet *ifp, u_long cmd, void *data)
   1415 {
   1416 	struct ie_softc *sc = ifp->if_softc;
   1417 	struct ifaddr *ifa = (struct ifaddr *)data;
   1418 	int s, error = 0;
   1419 
   1420 	s = splnet();
   1421 
   1422 	switch (cmd) {
   1423 
   1424 	case SIOCINITIFADDR:
   1425 		ifp->if_flags |= IFF_UP;
   1426 
   1427 		switch (ifa->ifa_addr->sa_family) {
   1428 #ifdef INET
   1429 		case AF_INET:
   1430 			ieinit(sc);
   1431 			arp_ifinit(ifp, ifa);
   1432 			break;
   1433 #endif
   1434 		default:
   1435 			ieinit(sc);
   1436 			break;
   1437 		}
   1438 		break;
   1439 
   1440 	case SIOCSIFFLAGS:
   1441 		if ((error = ifioctl_common(ifp, cmd, data)) != 0)
   1442 			break;
   1443 		sc->promisc = ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
   1444 
   1445 		switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
   1446 		case IFF_RUNNING:
   1447 			/*
   1448 			 * If interface is marked down and it is running, then
   1449 			 * stop it.
   1450 			 */
   1451 			iestop(sc);
   1452 			ifp->if_flags &= ~IFF_RUNNING;
   1453 			break;
   1454 		case IFF_UP:
   1455 			/*
   1456 			 * If interface is marked up and it is stopped, then
   1457 			 * start it.
   1458 			 */
   1459 			ieinit(sc);
   1460 			break;
   1461 		default:
   1462 			/*
   1463 			 * Reset the interface to pick up changes in any other
   1464 			 * flags that affect hardware registers.
   1465 			 */
   1466 			iestop(sc);
   1467 			ieinit(sc);
   1468 			break;
   1469 		}
   1470 #ifdef IEDEBUG
   1471 		if (ifp->if_flags & IFF_DEBUG)
   1472 			sc->sc_debug = IED_ALL;
   1473 		else
   1474 			sc->sc_debug = ie_debug_flags;
   1475 #endif
   1476 		break;
   1477 
   1478 	case SIOCADDMULTI:
   1479 	case SIOCDELMULTI:
   1480 		if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
   1481 			/*
   1482 			 * Multicast list has changed; set the hardware filter
   1483 			 * accordingly.
   1484 			 */
   1485 			if (ifp->if_flags & IFF_RUNNING)
   1486 				mc_reset(sc);
   1487 			error = 0;
   1488 		}
   1489 		break;
   1490 
   1491 	default:
   1492 		error = ether_ioctl(ifp, cmd, data);
   1493 		break;
   1494 	}
   1495 	splx(s);
   1496 	return error;
   1497 }
   1498 
   1499 static void
   1500 mc_reset(struct ie_softc *sc)
   1501 {
   1502 	struct ether_multi *enm;
   1503 	struct ether_multistep step;
   1504 	struct ifnet *ifp;
   1505 
   1506 	ifp = &sc->sc_if;
   1507 
   1508 	/*
   1509 	 * Step through the list of addresses.
   1510 	 */
   1511 	sc->mcast_count = 0;
   1512 	ETHER_FIRST_MULTI(step, &sc->sc_ethercom, enm);
   1513 	while (enm) {
   1514 		if (sc->mcast_count >= MAXMCAST ||
   1515 		    ether_cmp(enm->enm_addrlo, enm->enm_addrhi) != 0) {
   1516 			ifp->if_flags |= IFF_ALLMULTI;
   1517 			ieioctl(ifp, SIOCSIFFLAGS, NULL);
   1518 			goto setflag;
   1519 		}
   1520 		memcpy(&sc->mcast_addrs[sc->mcast_count], enm->enm_addrlo,
   1521 		    ETHER_ADDR_LEN);
   1522 		sc->mcast_count++;
   1523 		ETHER_NEXT_MULTI(step, enm);
   1524 	}
   1525 setflag:
   1526 	sc->want_mcsetup = 1;
   1527 }
   1528 
   1529 #ifdef IEDEBUG
   1530 void
   1531 print_rbd(volatile struct ie_recv_buf_desc *rbd)
   1532 {
   1533 
   1534 	printf("RBD at %08lx:\nactual %04x, next %04x, buffer %08x\n"
   1535 	    "length %04x, mbz %04x\n", (u_long)rbd, rbd->ie_rbd_actual,
   1536 	    rbd->ie_rbd_next, rbd->ie_rbd_buffer, rbd->ie_rbd_length,
   1537 	    rbd->mbz);
   1538 }
   1539 #endif
   1540