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