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