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