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