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