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