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