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