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