if_ie.c revision 1.39.4.2 1 /* $NetBSD: if_ie.c,v 1.39.4.2 2005/05/31 21:26:39 riz 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 <sys/cdefs.h>
101 __KERNEL_RCSID(0, "$NetBSD: if_ie.c,v 1.39.4.2 2005/05/31 21:26:39 riz Exp $");
102
103 #include "opt_inet.h"
104 #include "opt_ns.h"
105 #include "bpfilter.h"
106
107 #include <sys/param.h>
108 #include <sys/systm.h>
109 #include <sys/mbuf.h>
110 #include <sys/buf.h>
111 #include <sys/protosw.h>
112 #include <sys/socket.h>
113 #include <sys/ioctl.h>
114 #include <sys/errno.h>
115 #include <sys/syslog.h>
116 #include <sys/device.h>
117
118 #include <net/if.h>
119 #include <net/if_types.h>
120 #include <net/if_dl.h>
121 #include <net/if_ether.h>
122
123 #if NBPFILTER > 0
124 #include <net/bpf.h>
125 #include <net/bpfdesc.h>
126 #endif
127
128 #ifdef INET
129 #include <netinet/in.h>
130 #include <netinet/in_systm.h>
131 #include <netinet/in_var.h>
132 #include <netinet/ip.h>
133 #include <netinet/if_inarp.h>
134 #endif
135
136 #ifdef NS
137 #include <netns/ns.h>
138 #include <netns/ns_if.h>
139 #endif
140
141 #include <uvm/uvm_extern.h>
142
143 #include <machine/autoconf.h>
144 #include <machine/cpu.h>
145 #include <machine/pmap.h>
146
147 /*
148 * ugly byte-order hack for SUNs
149 */
150
151 #define XSWAP(y) ( (((y)&0xff00) >> 8) | (((y)&0xff) << 8) )
152 #define SWAP(x) ((u_short)(XSWAP((u_short)(x))))
153
154 #include "i82586.h"
155 #include "if_iereg.h"
156 #include "if_ievar.h"
157
158 /* #define IEDEBUG XXX */
159
160 /*
161 * IED: ie debug flags
162 */
163
164 #define IED_RINT 0x01
165 #define IED_TINT 0x02
166 #define IED_RNR 0x04
167 #define IED_CNA 0x08
168 #define IED_READFRAME 0x10
169 #define IED_ENQ 0x20
170 #define IED_XMIT 0x40
171 #define IED_ALL 0x7f
172
173 #ifdef IEDEBUG
174 #define inline /* not */
175 void print_rbd __P((volatile struct ie_recv_buf_desc *));
176 int in_ierint = 0;
177 int in_ietint = 0;
178 int ie_debug_flags = 0;
179 #endif
180
181 /* XXX - Skip TDR for now - it always complains... */
182 int ie_run_tdr = 0;
183
184 static void iewatchdog __P((struct ifnet *));
185 static int ieinit __P((struct ie_softc *));
186 static int ieioctl __P((struct ifnet *, u_long, caddr_t));
187 static void iestart __P((struct ifnet *));
188 static void iereset __P((struct ie_softc *));
189 static int ie_setupram __P((struct ie_softc *sc));
190
191 static int cmd_and_wait __P((struct ie_softc *, int, void *, int));
192
193 static void ie_drop_packet_buffer __P((struct ie_softc *));
194 static void ie_readframe __P((struct ie_softc *, int));
195 static inline void ie_setup_config __P((struct ie_config_cmd *, int, int));
196
197 static void ierint __P((struct ie_softc *));
198 static void iestop __P((struct ie_softc *));
199 static void ietint __P((struct ie_softc *));
200 static void iexmit __P((struct ie_softc *));
201
202 static int mc_setup __P((struct ie_softc *, void *));
203 static void mc_reset __P((struct ie_softc *));
204 static void run_tdr __P((struct ie_softc *, struct ie_tdr_cmd *));
205 static void iememinit __P((struct ie_softc *));
206
207 static inline char * Align __P((char *));
208 static inline u_int Swap32 __P((u_int x));
209 static inline u_int vtop24 __P((struct ie_softc *, void *));
210 static inline u_short vtop16sw __P((struct ie_softc *, void *));
211
212 static inline void ie_ack __P((struct ie_softc *, u_int));
213 static inline u_short ether_cmp __P((u_char *, u_char *));
214 static inline int check_eh __P((struct ie_softc *,
215 struct ether_header *eh, int *));
216 static inline int ie_buflen __P((struct ie_softc *, int));
217 static inline int ie_packet_len __P((struct ie_softc *));
218 static inline struct mbuf * ieget __P((struct ie_softc *sc, int *to_bpf));
219
220
221 /*
222 * Here are a few useful functions. We could have done these as macros,
223 * but since we have the inline facility, it makes sense to use that
224 * instead.
225 */
226
227 /* KVA to 24 bit device address */
228 static inline u_int
229 vtop24(sc, ptr)
230 struct ie_softc *sc;
231 void *ptr;
232 {
233 u_int pa;
234
235 pa = ((caddr_t)ptr) - sc->sc_iobase;
236 #ifdef IEDEBUG
237 if (pa & ~0xffFFff)
238 panic("ie:vtop24");
239 #endif
240 return (pa);
241 }
242
243 /* KVA to 16 bit offset, swapped */
244 static inline u_short
245 vtop16sw(sc, ptr)
246 struct ie_softc *sc;
247 void *ptr;
248 {
249 u_int pa;
250
251 pa = ((caddr_t)ptr) - sc->sc_maddr;
252 #ifdef IEDEBUG
253 if (pa & ~0xFFff)
254 panic("ie:vtop16");
255 #endif
256
257 return (SWAP(pa));
258 }
259
260 static inline u_int
261 Swap32(x)
262 u_int x;
263 {
264 u_int y;
265
266 y = x & 0xFF;
267 y <<= 8; x >>= 8;
268 y |= x & 0xFF;
269 y <<= 8; x >>= 8;
270 y |= x & 0xFF;
271 y <<= 8; x >>= 8;
272 y |= x & 0xFF;
273
274 return (y);
275 }
276
277 static inline char *
278 Align(ptr)
279 caddr_t ptr;
280 {
281 u_long l = (u_long)ptr;
282
283 l = (l + 3) & ~3L;
284 return ((char *)l);
285 }
286
287
288 static inline void
289 ie_ack(sc, mask)
290 struct ie_softc *sc;
291 u_int mask;
292 {
293 volatile struct ie_sys_ctl_block *scb = sc->scb;
294
295 cmd_and_wait(sc, scb->ie_status & mask, 0, 0);
296 }
297
298
299 /*
300 * Taken almost exactly from Bill's if_is.c,
301 * then modified beyond recognition...
302 */
303 void
304 ie_attach(sc)
305 struct ie_softc *sc;
306 {
307 struct ifnet *ifp = &sc->sc_if;
308
309 /* MD code has done its part before calling this. */
310 printf(": macaddr %s\n", ether_sprintf(sc->sc_addr));
311
312 /*
313 * Compute number of transmit and receive buffers.
314 * Tx buffers take 1536 bytes, and fixed in number.
315 * Rx buffers are 512 bytes each, variable number.
316 * Need at least 1 frame for each 3 rx buffers.
317 * The ratio 3bufs:2frames is a compromise.
318 */
319 sc->ntxbuf = NTXBUF; /* XXX - Fix me... */
320 switch (sc->sc_msize) {
321 case 16384:
322 sc->nframes = 8 * 4;
323 sc->nrxbuf = 8 * 6;
324 break;
325 case 32768:
326 sc->nframes = 16 * 4;
327 sc->nrxbuf = 16 * 6;
328 break;
329 case 65536:
330 sc->nframes = 32 * 4;
331 sc->nrxbuf = 32 * 6;
332 break;
333 default:
334 sc->nframes = 0;
335 }
336 if (sc->nframes > MXFRAMES)
337 sc->nframes = MXFRAMES;
338 if (sc->nrxbuf > MXRXBUF)
339 sc->nrxbuf = MXRXBUF;
340
341 #ifdef IEDEBUG
342 printf("%s: %dK memory, %d tx frames, %d rx frames, %d rx bufs\n",
343 sc->sc_dev.dv_xname, (sc->sc_msize >> 10),
344 sc->ntxbuf, sc->nframes, sc->nrxbuf);
345 #endif
346
347 if ((sc->nframes <= 0) || (sc->nrxbuf <= 0))
348 panic("ie_attach: weird memory size");
349
350 /*
351 * Setup RAM for transmit/receive
352 */
353 if (ie_setupram(sc) == 0) {
354 printf(": RAM CONFIG FAILED!\n");
355 /* XXX should reclaim resources? */
356 return;
357 }
358
359 /*
360 * Initialize and attach S/W interface
361 */
362 strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
363 ifp->if_softc = sc;
364 ifp->if_start = iestart;
365 ifp->if_ioctl = ieioctl;
366 ifp->if_watchdog = iewatchdog;
367 ifp->if_flags =
368 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
369
370 /* Attach the interface. */
371 if_attach(ifp);
372 ether_ifattach(ifp, sc->sc_addr);
373 }
374
375 /*
376 * Setup IE's ram space.
377 */
378 static int
379 ie_setupram(sc)
380 struct ie_softc *sc;
381 {
382 volatile struct ie_sys_conf_ptr *scp;
383 volatile struct ie_int_sys_conf_ptr *iscp;
384 volatile struct ie_sys_ctl_block *scb;
385 int off;
386
387 /*
388 * Allocate from end of buffer space for
389 * ISCP, SCB, and other small stuff.
390 */
391 off = sc->buf_area_sz;
392 off &= ~3;
393
394 /* SCP (address already chosen). */
395 scp = sc->scp;
396 (sc->sc_memset)((char *) scp, 0, sizeof(*scp));
397
398 /* ISCP */
399 off -= sizeof(*iscp);
400 iscp = (volatile void *) (sc->buf_area + off);
401 (sc->sc_memset)((char *) iscp, 0, sizeof(*iscp));
402 sc->iscp = iscp;
403
404 /* SCB */
405 off -= sizeof(*scb);
406 scb = (volatile void *) (sc->buf_area + off);
407 (sc->sc_memset)((char *) scb, 0, sizeof(*scb));
408 sc->scb = scb;
409
410 /* Remainder is for buffers, etc. */
411 sc->buf_area_sz = off;
412
413 /*
414 * Now fill in the structures we just allocated.
415 */
416
417 /* SCP: main thing is 24-bit ptr to ISCP */
418 scp->ie_bus_use = 0; /* 16-bit */
419 scp->ie_iscp_ptr = Swap32(vtop24(sc, (void*)iscp));
420
421 /* ISCP */
422 iscp->ie_busy = 1; /* ie_busy == char */
423 iscp->ie_scb_offset = vtop16sw(sc, (void*)scb);
424 iscp->ie_base = Swap32(vtop24(sc, sc->sc_maddr));
425
426 /* SCB */
427 scb->ie_command_list = SWAP(0xffff);
428 scb->ie_recv_list = SWAP(0xffff);
429
430 /* Other stuff is done in ieinit() */
431 (sc->reset_586) (sc);
432 (sc->chan_attn) (sc);
433
434 delay(100); /* wait a while... */
435
436 if (iscp->ie_busy) {
437 return 0;
438 }
439 /*
440 * Acknowledge any interrupts we may have caused...
441 */
442 ie_ack(sc, IE_ST_WHENCE);
443
444 return 1;
445 }
446
447 /*
448 * Device timeout/watchdog routine. Entered if the device neglects to
449 * generate an interrupt after a transmit has been started on it.
450 */
451 static void
452 iewatchdog(ifp)
453 struct ifnet *ifp;
454 {
455 struct ie_softc *sc = ifp->if_softc;
456
457 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
458 ++ifp->if_oerrors;
459 iereset(sc);
460 }
461
462 /*
463 * What to do upon receipt of an interrupt.
464 */
465 int
466 ie_intr(arg)
467 void *arg;
468 {
469 struct ie_softc *sc = arg;
470 u_short status;
471 int loopcnt;
472
473 /*
474 * check for parity error
475 */
476 if (sc->hard_type == IE_VME) {
477 volatile struct ievme *iev = (volatile struct ievme *)sc->sc_reg;
478 if (iev->status & IEVME_PERR) {
479 printf("%s: parity error (ctrl 0x%x @ 0x%02x%04x)\n",
480 sc->sc_dev.dv_xname, iev->pectrl,
481 iev->pectrl & IEVME_HADDR, iev->peaddr);
482 iev->pectrl = iev->pectrl | IEVME_PARACK;
483 }
484 }
485
486 status = sc->scb->ie_status;
487 if ((status & IE_ST_WHENCE) == 0)
488 return 0;
489
490 loopcnt = sc->nframes;
491 loop:
492 /* Ack interrupts FIRST in case we receive more during the ISR. */
493 ie_ack(sc, IE_ST_WHENCE & status);
494
495 if (status & (IE_ST_RECV | IE_ST_RNR)) {
496 #ifdef IEDEBUG
497 in_ierint++;
498 if (sc->sc_debug & IED_RINT)
499 printf("%s: rint\n", sc->sc_dev.dv_xname);
500 #endif
501 ierint(sc);
502 #ifdef IEDEBUG
503 in_ierint--;
504 #endif
505 }
506
507 if (status & IE_ST_DONE) {
508 #ifdef IEDEBUG
509 in_ietint++;
510 if (sc->sc_debug & IED_TINT)
511 printf("%s: tint\n", sc->sc_dev.dv_xname);
512 #endif
513 ietint(sc);
514 #ifdef IEDEBUG
515 in_ietint--;
516 #endif
517 }
518
519 /*
520 * Receiver not ready (RNR) just means it has
521 * run out of resources (buffers or frames).
522 * One can easily cause this with (i.e.) spray.
523 * This is not a serious error, so be silent.
524 */
525 if (status & IE_ST_RNR) {
526 #ifdef IEDEBUG
527 printf("%s: receiver not ready\n", sc->sc_dev.dv_xname);
528 #endif
529 sc->sc_if.if_ierrors++;
530 iereset(sc);
531 }
532
533 #ifdef IEDEBUG
534 if ((status & IE_ST_ALLDONE) && (sc->sc_debug & IED_CNA))
535 printf("%s: cna\n", sc->sc_dev.dv_xname);
536 #endif
537
538 status = sc->scb->ie_status;
539 if (status & IE_ST_WHENCE) {
540 /* It still wants service... */
541 if (--loopcnt > 0)
542 goto loop;
543 /* ... but we've been here long enough. */
544 log(LOG_ERR, "%s: interrupt stuck?\n",
545 sc->sc_dev.dv_xname);
546 iereset(sc);
547 }
548 return 1;
549 }
550
551 /*
552 * Process a received-frame interrupt.
553 */
554 void
555 ierint(sc)
556 struct ie_softc *sc;
557 {
558 volatile struct ie_sys_ctl_block *scb = sc->scb;
559 int i, status;
560 static int timesthru = 1024;
561
562 i = sc->rfhead;
563 for (;;) {
564 status = sc->rframes[i]->ie_fd_status;
565
566 if ((status & IE_FD_COMPLETE) && (status & IE_FD_OK)) {
567 if (!--timesthru) {
568 sc->sc_if.if_ierrors +=
569 SWAP(scb->ie_err_crc) +
570 SWAP(scb->ie_err_align) +
571 SWAP(scb->ie_err_resource) +
572 SWAP(scb->ie_err_overrun);
573 scb->ie_err_crc = 0;
574 scb->ie_err_align = 0;
575 scb->ie_err_resource = 0;
576 scb->ie_err_overrun = 0;
577 timesthru = 1024;
578 }
579 ie_readframe(sc, i);
580 } else {
581 if ((status & IE_FD_RNR) != 0 &&
582 (scb->ie_status & IE_RU_READY) == 0) {
583 sc->rframes[0]->ie_fd_buf_desc =
584 vtop16sw(sc, (void*) sc->rbuffs[0]);
585 scb->ie_recv_list =
586 vtop16sw(sc, (void*) sc->rframes[0]);
587 cmd_and_wait(sc, IE_RU_START, 0, 0);
588 }
589 break;
590 }
591 i = (i + 1) % sc->nframes;
592 }
593 }
594
595 /*
596 * Process a command-complete interrupt. These are only generated by the
597 * transmission of frames. This routine is deceptively simple, since most
598 * of the real work is done by iestart().
599 */
600 void
601 ietint(sc)
602 struct ie_softc *sc;
603 {
604 struct ifnet *ifp;
605 int status;
606
607 ifp = &sc->sc_if;
608
609 ifp->if_timer = 0;
610 ifp->if_flags &= ~IFF_OACTIVE;
611
612 status = sc->xmit_cmds[sc->xctail]->ie_xmit_status;
613
614 if (!(status & IE_STAT_COMPL) || (status & IE_STAT_BUSY))
615 printf("ietint: command still busy!\n");
616
617 if (status & IE_STAT_OK) {
618 ifp->if_opackets++;
619 ifp->if_collisions +=
620 SWAP(status & IE_XS_MAXCOLL);
621 } else {
622 ifp->if_oerrors++;
623 /*
624 * XXX
625 * Check SQE and DEFERRED?
626 * What if more than one bit is set?
627 */
628 if (status & IE_STAT_ABORT)
629 printf("%s: send aborted\n", sc->sc_dev.dv_xname);
630 if (status & IE_XS_LATECOLL)
631 printf("%s: late collision\n", sc->sc_dev.dv_xname);
632 if (status & IE_XS_NOCARRIER)
633 printf("%s: no carrier\n", sc->sc_dev.dv_xname);
634 if (status & IE_XS_LOSTCTS)
635 printf("%s: lost CTS\n", sc->sc_dev.dv_xname);
636 if (status & IE_XS_UNDERRUN)
637 printf("%s: DMA underrun\n", sc->sc_dev.dv_xname);
638 if (status & IE_XS_EXCMAX) {
639 /* Do not print this one (too noisy). */
640 ifp->if_collisions += 16;
641 }
642 }
643
644 /*
645 * If multicast addresses were added or deleted while we
646 * were transmitting, mc_reset() set the want_mcsetup flag
647 * indicating that we should do it.
648 */
649 if (sc->want_mcsetup) {
650 mc_setup(sc, (caddr_t)sc->xmit_cbuffs[sc->xctail]);
651 sc->want_mcsetup = 0;
652 }
653
654 /* Done with the buffer. */
655 sc->xmit_busy--;
656 sc->xctail = (sc->xctail + 1) % NTXBUF;
657
658 /* Start the next packet, if any, transmitting. */
659 if (sc->xmit_busy > 0)
660 iexmit(sc);
661
662 iestart(ifp);
663 }
664
665 /*
666 * Compare two Ether/802 addresses for equality, inlined and
667 * unrolled for speed. I'd love to have an inline assembler
668 * version of this... XXX: Who wanted that? mycroft?
669 * I wrote one, but the following is just as efficient.
670 * This expands to 10 short m68k instructions! -gwr
671 * Note: use this like bcmp()
672 */
673 static inline u_short
674 ether_cmp(one, two)
675 u_char *one, *two;
676 {
677 u_short *a = (u_short *) one;
678 u_short *b = (u_short *) two;
679 u_short diff;
680
681 diff = *a++ - *b++;
682 diff |= *a++ - *b++;
683 diff |= *a++ - *b++;
684
685 return (diff);
686 }
687 #define ether_equal !ether_cmp
688
689 /*
690 * Check for a valid address. to_bpf is filled in with one of the following:
691 * 0 -> BPF doesn't get this packet
692 * 1 -> BPF does get this packet
693 * 2 -> BPF does get this packet, but we don't
694 * Return value is true if the packet is for us, and false otherwise.
695 *
696 * This routine is a mess, but it's also critical that it be as fast
697 * as possible. It could be made cleaner if we can assume that the
698 * only client which will fiddle with IFF_PROMISC is BPF. This is
699 * probably a good assumption, but we do not make it here. (Yet.)
700 */
701 static inline int
702 check_eh(sc, eh, to_bpf)
703 struct ie_softc *sc;
704 struct ether_header *eh;
705 int *to_bpf;
706 {
707 #if NBPFILTER > 0
708 struct ifnet *ifp;
709
710 ifp = &sc->sc_if;
711 *to_bpf = (ifp->if_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, NULL);
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 if (m0->m_pkthdr.len < ETHER_MIN_LEN - ETHER_CRC_LEN) {
1125 sc->sc_memset(buffer, 0,
1126 ETHER_MIN_LEN - ETHER_CRC_LEN - m0->m_pkthdr.len);
1127 len = ETHER_MIN_LEN - ETHER_CRC_LEN;
1128 } else
1129 len = m0->m_pkthdr.len;
1130
1131 m_freem(m0);
1132 sc->xmit_buffs[sc->xchead]->ie_xmit_flags = SWAP(len);
1133
1134 /* Start the first packet transmitting. */
1135 if (sc->xmit_busy == 0)
1136 iexmit(sc);
1137
1138 sc->xchead = (sc->xchead + 1) % sc->ntxbuf;
1139 sc->xmit_busy++;
1140 }
1141 }
1142
1143 static void
1144 iereset(sc)
1145 struct ie_softc *sc;
1146 {
1147 int s = splnet();
1148
1149 /* No message here. The caller does that. */
1150 iestop(sc);
1151
1152 /*
1153 * Stop i82586 dead in its tracks.
1154 */
1155 if (cmd_and_wait(sc, IE_RU_ABORT | IE_CU_ABORT, 0, 0))
1156 printf("%s: abort commands timed out\n", sc->sc_dev.dv_xname);
1157
1158 if (cmd_and_wait(sc, IE_RU_DISABLE | IE_CU_STOP, 0, 0))
1159 printf("%s: disable commands timed out\n", sc->sc_dev.dv_xname);
1160
1161 ieinit(sc);
1162
1163 splx(s);
1164 }
1165
1166 /*
1167 * Send a command to the controller and wait for it to either
1168 * complete or be accepted, depending on the command. If the
1169 * command pointer is null, then pretend that the command is
1170 * not an action command. If the command pointer is not null,
1171 * and the command is an action command, wait for
1172 * ((volatile struct ie_cmd_common *)pcmd)->ie_cmd_status & MASK
1173 * to become true.
1174 */
1175 static int
1176 cmd_and_wait(sc, cmd, pcmd, mask)
1177 struct ie_softc *sc;
1178 int cmd;
1179 void *pcmd; /* XXX - Was volatile */
1180 int mask;
1181 {
1182 volatile struct ie_cmd_common *cc = pcmd;
1183 volatile struct ie_sys_ctl_block *scb = sc->scb;
1184 int tmo;
1185
1186 scb->ie_command = (u_short)cmd;
1187 (sc->chan_attn)(sc);
1188
1189 /* Wait for the command to be accepted by the CU. */
1190 tmo = 10;
1191 while (scb->ie_command && --tmo)
1192 delay(10);
1193 if (scb->ie_command) {
1194 #ifdef IEDEBUG
1195 printf("%s: cmd_and_wait, CU stuck (1)\n",
1196 sc->sc_dev.dv_xname);
1197 #endif
1198 return -1; /* timed out */
1199 }
1200
1201 /*
1202 * If asked, also wait for it to finish.
1203 */
1204 if (IE_ACTION_COMMAND(cmd) && pcmd) {
1205
1206 /*
1207 * According to the packet driver, the minimum timeout should
1208 * be .369 seconds, which we round up to .4.
1209 */
1210 tmo = 36900;
1211
1212 /*
1213 * Now spin-lock waiting for status. This is not a very nice
1214 * thing to do, but I haven't figured out how, or indeed if, we
1215 * can put the process waiting for action to sleep. (We may
1216 * be getting called through some other timeout running in the
1217 * kernel.)
1218 */
1219 while (((cc->ie_cmd_status & mask) == 0) && --tmo)
1220 delay(10);
1221
1222 if ((cc->ie_cmd_status & mask) == 0) {
1223 #ifdef IEDEBUG
1224 printf("%s: cmd_and_wait, CU stuck (2)\n",
1225 sc->sc_dev.dv_xname);
1226 #endif
1227 return -1; /* timed out */
1228 }
1229 }
1230 return 0;
1231 }
1232
1233 /*
1234 * Run the time-domain reflectometer.
1235 */
1236 static void
1237 run_tdr(sc, cmd)
1238 struct ie_softc *sc;
1239 struct ie_tdr_cmd *cmd;
1240 {
1241 int result;
1242
1243 cmd->com.ie_cmd_status = SWAP(0);
1244 cmd->com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST;
1245 cmd->com.ie_cmd_link = SWAP(0xffff);
1246
1247 sc->scb->ie_command_list = vtop16sw(sc, cmd);
1248 cmd->ie_tdr_time = SWAP(0);
1249
1250 if (cmd_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
1251 !(cmd->com.ie_cmd_status & IE_STAT_OK))
1252 result = 0x10000; /* impossible value */
1253 else
1254 result = cmd->ie_tdr_time;
1255
1256 ie_ack(sc, IE_ST_WHENCE);
1257
1258 if (result & IE_TDR_SUCCESS)
1259 return;
1260
1261 if (result & 0x10000) {
1262 printf("%s: TDR command failed\n", sc->sc_dev.dv_xname);
1263 } else if (result & IE_TDR_XCVR) {
1264 printf("%s: transceiver problem\n", sc->sc_dev.dv_xname);
1265 } else if (result & IE_TDR_OPEN) {
1266 printf("%s: TDR detected an open %d clocks away\n",
1267 sc->sc_dev.dv_xname, SWAP(result & IE_TDR_TIME));
1268 } else if (result & IE_TDR_SHORT) {
1269 printf("%s: TDR detected a short %d clocks away\n",
1270 sc->sc_dev.dv_xname, SWAP(result & IE_TDR_TIME));
1271 } else {
1272 printf("%s: TDR returned unknown status 0x%x\n",
1273 sc->sc_dev.dv_xname, result);
1274 }
1275 }
1276
1277 /*
1278 * iememinit: set up the buffers
1279 *
1280 * we have a block of KVA at sc->buf_area which is of size sc->buf_area_sz.
1281 * this is to be used for the buffers. the chip indexs its control data
1282 * structures with 16 bit offsets, and it indexes actual buffers with
1283 * 24 bit addresses. so we should allocate control buffers first so that
1284 * we don't overflow the 16 bit offset field. The number of transmit
1285 * buffers is fixed at compile time.
1286 *
1287 * note: this function was written to be easy to understand, rather than
1288 * highly efficient (it isn't in the critical path).
1289 *
1290 * The memory layout is: tbufs, rbufs, (gap), control blocks
1291 * [tbuf0, tbuf1] [rbuf0,...rbufN] gap [rframes] [tframes]
1292 * XXX - This needs review...
1293 */
1294 static void
1295 iememinit(sc)
1296 struct ie_softc *sc;
1297 {
1298 char *ptr;
1299 int i;
1300 u_short nxt;
1301
1302 /* First, zero all the memory. */
1303 ptr = sc->buf_area;
1304 (sc->sc_memset)(ptr, 0, sc->buf_area_sz);
1305
1306 /* Allocate tx/rx buffers. */
1307 for (i = 0; i < NTXBUF; i++) {
1308 sc->xmit_cbuffs[i] = ptr;
1309 ptr += IE_TBUF_SIZE;
1310 }
1311 for (i = 0; i < sc->nrxbuf; i++) {
1312 sc->cbuffs[i] = ptr;
1313 ptr += IE_RBUF_SIZE;
1314 }
1315
1316 /* Small pad (Don't trust the chip...) */
1317 ptr += 16;
1318
1319 /* Allocate and fill in xmit buffer descriptors. */
1320 for (i = 0; i < NTXBUF; i++) {
1321 sc->xmit_buffs[i] = (volatile void *) ptr;
1322 ptr = Align(ptr + sizeof(*sc->xmit_buffs[i]));
1323 sc->xmit_buffs[i]->ie_xmit_buf =
1324 Swap32(vtop24(sc, sc->xmit_cbuffs[i]));
1325 sc->xmit_buffs[i]->ie_xmit_next = SWAP(0xffff);
1326 }
1327
1328 /* Allocate and fill in recv buffer descriptors. */
1329 for (i = 0; i < sc->nrxbuf; i++) {
1330 sc->rbuffs[i] = (volatile void *) ptr;
1331 ptr = Align(ptr + sizeof(*sc->rbuffs[i]));
1332 sc->rbuffs[i]->ie_rbd_buffer =
1333 Swap32(vtop24(sc, sc->cbuffs[i]));
1334 sc->rbuffs[i]->ie_rbd_length = SWAP(IE_RBUF_SIZE);
1335 }
1336
1337 /* link together recv bufs and set EOL on last */
1338 i = sc->nrxbuf - 1;
1339 sc->rbuffs[i]->ie_rbd_length |= IE_RBD_LAST;
1340 nxt = vtop16sw(sc, (void*) sc->rbuffs[0]);
1341 do {
1342 sc->rbuffs[i]->ie_rbd_next = nxt;
1343 nxt = vtop16sw(sc, (void*) sc->rbuffs[i]);
1344 } while (--i >= 0);
1345
1346 /* Allocate transmit commands. */
1347 for (i = 0; i < NTXBUF; i++) {
1348 sc->xmit_cmds[i] = (volatile void *) ptr;
1349 ptr = Align(ptr + sizeof(*sc->xmit_cmds[i]));
1350 sc->xmit_cmds[i]->com.ie_cmd_link = SWAP(0xffff);
1351 }
1352
1353 /* Allocate receive frames. */
1354 for (i = 0; i < sc->nframes; i++) {
1355 sc->rframes[i] = (volatile void *) ptr;
1356 ptr = Align(ptr + sizeof(*sc->rframes[i]));
1357 }
1358
1359 /* Link together recv frames and set EOL on last */
1360 i = sc->nframes - 1;
1361 sc->rframes[i]->ie_fd_last |= IE_FD_LAST;
1362 nxt = vtop16sw(sc, (void*) sc->rframes[0]);
1363 do {
1364 sc->rframes[i]->ie_fd_next = nxt;
1365 nxt = vtop16sw(sc, (void*) sc->rframes[i]);
1366 } while (--i >= 0);
1367
1368
1369 /* Pointers to last packet sent and next available transmit buffer. */
1370 sc->xchead = sc->xctail = 0;
1371
1372 /* Clear transmit-busy flag. */
1373 sc->xmit_busy = 0;
1374
1375 /*
1376 * Set the head and tail pointers on receive to keep track of
1377 * the order in which RFDs and RBDs are used. link the
1378 * recv frames and buffer into the scb.
1379 */
1380 sc->rfhead = 0;
1381 sc->rftail = sc->nframes - 1;
1382 sc->rbhead = 0;
1383 sc->rbtail = sc->nrxbuf - 1;
1384
1385 sc->scb->ie_recv_list =
1386 vtop16sw(sc, (void*) sc->rframes[0]);
1387 sc->rframes[0]->ie_fd_buf_desc =
1388 vtop16sw(sc, (void*) sc->rbuffs[0]);
1389
1390 i = (ptr - sc->buf_area);
1391 #ifdef IEDEBUG
1392 printf("IE_DEBUG: used %d of %d bytes\n", i, sc->buf_area_sz);
1393 #endif
1394 if (i > sc->buf_area_sz)
1395 panic("ie: iememinit, out of space");
1396 }
1397
1398 /*
1399 * Run the multicast setup command.
1400 * Called at splnet().
1401 */
1402 static int
1403 mc_setup(sc, ptr)
1404 struct ie_softc *sc;
1405 void *ptr;
1406 {
1407 struct ie_mcast_cmd *cmd = ptr; /* XXX - Was volatile */
1408
1409 cmd->com.ie_cmd_status = SWAP(0);
1410 cmd->com.ie_cmd_cmd = IE_CMD_MCAST | IE_CMD_LAST;
1411 cmd->com.ie_cmd_link = SWAP(0xffff);
1412
1413 (sc->sc_memcpy)((caddr_t)cmd->ie_mcast_addrs,
1414 (caddr_t)sc->mcast_addrs,
1415 sc->mcast_count * sizeof *sc->mcast_addrs);
1416
1417 cmd->ie_mcast_bytes =
1418 SWAP(sc->mcast_count * ETHER_ADDR_LEN); /* grrr... */
1419
1420 sc->scb->ie_command_list = vtop16sw(sc, cmd);
1421 if (cmd_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
1422 !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
1423 printf("%s: multicast address setup command failed\n",
1424 sc->sc_dev.dv_xname);
1425 return 0;
1426 }
1427 return 1;
1428 }
1429
1430 static inline void
1431 ie_setup_config(cmd, promiscuous, manchester)
1432 struct ie_config_cmd *cmd; /* XXX - was volatile */
1433 int promiscuous, manchester;
1434 {
1435
1436 /*
1437 * these are all char's so no need to byte-swap
1438 */
1439 cmd->ie_config_count = 0x0c;
1440 cmd->ie_fifo = 8;
1441 cmd->ie_save_bad = 0x40;
1442 cmd->ie_addr_len = 0x2e;
1443 cmd->ie_priority = 0;
1444 cmd->ie_ifs = 0x60;
1445 cmd->ie_slot_low = 0;
1446 cmd->ie_slot_high = 0xf2;
1447 cmd->ie_promisc = promiscuous | manchester << 2;
1448 cmd->ie_crs_cdt = 0;
1449 cmd->ie_min_len = 64;
1450 cmd->ie_junk = 0xff;
1451 }
1452
1453 /*
1454 * This routine inits the ie.
1455 * This includes executing the CONFIGURE, IA-SETUP, and MC-SETUP commands,
1456 * starting the receiver unit, and clearing interrupts.
1457 *
1458 * THIS ROUTINE MUST BE CALLED AT splnet() OR HIGHER.
1459 */
1460 static int
1461 ieinit(sc)
1462 struct ie_softc *sc;
1463 {
1464 volatile struct ie_sys_ctl_block *scb = sc->scb;
1465 void *ptr;
1466 struct ifnet *ifp;
1467
1468 ifp = &sc->sc_if;
1469 ptr = sc->buf_area; /* XXX - Use scb instead? */
1470
1471 /*
1472 * Send the configure command first.
1473 */
1474 {
1475 struct ie_config_cmd *cmd = ptr; /* XXX - Was volatile */
1476
1477 scb->ie_command_list = vtop16sw(sc, cmd);
1478 cmd->com.ie_cmd_status = SWAP(0);
1479 cmd->com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST;
1480 cmd->com.ie_cmd_link = SWAP(0xffff);
1481
1482 ie_setup_config(cmd, (sc->promisc != 0), 0);
1483
1484 if (cmd_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
1485 !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
1486 printf("%s: configure command failed\n",
1487 sc->sc_dev.dv_xname);
1488 return 0;
1489 }
1490 }
1491
1492 /*
1493 * Now send the Individual Address Setup command.
1494 */
1495 {
1496 struct ie_iasetup_cmd *cmd = ptr; /* XXX - Was volatile */
1497
1498 scb->ie_command_list = vtop16sw(sc, cmd);
1499 cmd->com.ie_cmd_status = SWAP(0);
1500 cmd->com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST;
1501 cmd->com.ie_cmd_link = SWAP(0xffff);
1502
1503 (sc->sc_memcpy)((caddr_t)&cmd->ie_address,
1504 LLADDR(ifp->if_sadl), sizeof(cmd->ie_address));
1505
1506 if (cmd_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
1507 !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
1508 printf("%s: individual address setup command failed\n",
1509 sc->sc_dev.dv_xname);
1510 return 0;
1511 }
1512 }
1513
1514 /*
1515 * Now run the time-domain reflectometer.
1516 */
1517 if (ie_run_tdr)
1518 run_tdr(sc, ptr);
1519
1520 /*
1521 * Acknowledge any interrupts we have generated thus far.
1522 */
1523 ie_ack(sc, IE_ST_WHENCE);
1524
1525 /*
1526 * Set up the transmit and recv buffers.
1527 */
1528 iememinit(sc);
1529
1530 /* tell higher levels that we are here */
1531 ifp->if_flags |= IFF_RUNNING;
1532 ifp->if_flags &= ~IFF_OACTIVE;
1533
1534 sc->scb->ie_recv_list =
1535 vtop16sw(sc, (void*) sc->rframes[0]);
1536 cmd_and_wait(sc, IE_RU_START, 0, 0);
1537
1538 ie_ack(sc, IE_ST_WHENCE);
1539
1540 if (sc->run_586)
1541 (sc->run_586)(sc);
1542
1543 return 0;
1544 }
1545
1546 static void
1547 iestop(sc)
1548 struct ie_softc *sc;
1549 {
1550
1551 cmd_and_wait(sc, IE_RU_DISABLE, 0, 0);
1552 }
1553
1554 static int
1555 ieioctl(ifp, cmd, data)
1556 struct ifnet *ifp;
1557 u_long cmd;
1558 caddr_t data;
1559 {
1560 struct ie_softc *sc = ifp->if_softc;
1561 struct ifaddr *ifa = (struct ifaddr *)data;
1562 struct ifreq *ifr = (struct ifreq *)data;
1563 int s, error = 0;
1564
1565 s = splnet();
1566
1567 switch (cmd) {
1568
1569 case SIOCSIFADDR:
1570 ifp->if_flags |= IFF_UP;
1571
1572 switch (ifa->ifa_addr->sa_family) {
1573 #ifdef INET
1574 case AF_INET:
1575 ieinit(sc);
1576 arp_ifinit(ifp, ifa);
1577 break;
1578 #endif
1579 #ifdef NS
1580 /* XXX - This code is probably wrong. */
1581 case AF_NS:
1582 {
1583 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
1584
1585 if (ns_nullhost(*ina))
1586 ina->x_host =
1587 *(union ns_host *)LLADDR(ifp->if_sadl);
1588 else
1589 memcpy(LLADDR(ifp->if_sadl),
1590 ina->x_host.c_host, ETHER_ADDR_LEN);
1591 /* Set new address. */
1592 ieinit(sc);
1593 break;
1594 }
1595 #endif /* NS */
1596 default:
1597 ieinit(sc);
1598 break;
1599 }
1600 break;
1601
1602 case SIOCSIFFLAGS:
1603 sc->promisc = ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
1604
1605 if ((ifp->if_flags & IFF_UP) == 0 &&
1606 (ifp->if_flags & IFF_RUNNING) != 0) {
1607 /*
1608 * If interface is marked down and it is running, then
1609 * stop it.
1610 */
1611 iestop(sc);
1612 ifp->if_flags &= ~IFF_RUNNING;
1613 } else if ((ifp->if_flags & IFF_UP) != 0 &&
1614 (ifp->if_flags & IFF_RUNNING) == 0) {
1615 /*
1616 * If interface is marked up and it is stopped, then
1617 * start it.
1618 */
1619 ieinit(sc);
1620 } else {
1621 /*
1622 * Reset the interface to pick up changes in any other
1623 * flags that affect hardware registers.
1624 */
1625 iestop(sc);
1626 ieinit(sc);
1627 }
1628 #ifdef IEDEBUG
1629 if (ifp->if_flags & IFF_DEBUG)
1630 sc->sc_debug = IED_ALL;
1631 else
1632 sc->sc_debug = ie_debug_flags;
1633 #endif
1634 break;
1635
1636 case SIOCADDMULTI:
1637 case SIOCDELMULTI:
1638 error = (cmd == SIOCADDMULTI) ?
1639 ether_addmulti(ifr, &sc->sc_ethercom) :
1640 ether_delmulti(ifr, &sc->sc_ethercom);
1641
1642 if (error == ENETRESET) {
1643 /*
1644 * Multicast list has changed; set the hardware filter
1645 * accordingly.
1646 */
1647 if (ifp->if_flags & IFF_RUNNING)
1648 mc_reset(sc);
1649 error = 0;
1650 }
1651 break;
1652
1653 default:
1654 error = EINVAL;
1655 }
1656 splx(s);
1657 return error;
1658 }
1659
1660 static void
1661 mc_reset(sc)
1662 struct ie_softc *sc;
1663 {
1664 struct ether_multi *enm;
1665 struct ether_multistep step;
1666 struct ifnet *ifp;
1667
1668 ifp = &sc->sc_if;
1669
1670 /*
1671 * Step through the list of addresses.
1672 */
1673 sc->mcast_count = 0;
1674 ETHER_FIRST_MULTI(step, &sc->sc_ethercom, enm);
1675 while (enm) {
1676 if (sc->mcast_count >= MAXMCAST ||
1677 ether_cmp(enm->enm_addrlo, enm->enm_addrhi) != 0) {
1678 ifp->if_flags |= IFF_ALLMULTI;
1679 ieioctl(ifp, SIOCSIFFLAGS, (void *)0);
1680 goto setflag;
1681 }
1682 memcpy(&sc->mcast_addrs[sc->mcast_count], enm->enm_addrlo,
1683 ETHER_ADDR_LEN);
1684 sc->mcast_count++;
1685 ETHER_NEXT_MULTI(step, enm);
1686 }
1687 setflag:
1688 sc->want_mcsetup = 1;
1689 }
1690
1691 #ifdef IEDEBUG
1692 void
1693 print_rbd(rbd)
1694 volatile struct ie_recv_buf_desc *rbd;
1695 {
1696
1697 printf("RBD at %08lx:\nactual %04x, next %04x, buffer %08x\n"
1698 "length %04x, mbz %04x\n", (u_long)rbd, rbd->ie_rbd_actual,
1699 rbd->ie_rbd_next, rbd->ie_rbd_buffer, rbd->ie_rbd_length,
1700 rbd->mbz);
1701 }
1702 #endif
1703