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