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