if_ie.c revision 1.38 1 /* $NetBSD: if_ie.c,v 1.38 2003/01/20 15:03:45 bouyer 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 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 mc_reset(sc);
1648 error = 0;
1649 }
1650 break;
1651
1652 default:
1653 error = EINVAL;
1654 }
1655 splx(s);
1656 return error;
1657 }
1658
1659 static void
1660 mc_reset(sc)
1661 struct ie_softc *sc;
1662 {
1663 struct ether_multi *enm;
1664 struct ether_multistep step;
1665 struct ifnet *ifp;
1666
1667 ifp = &sc->sc_if;
1668
1669 /*
1670 * Step through the list of addresses.
1671 */
1672 sc->mcast_count = 0;
1673 ETHER_FIRST_MULTI(step, &sc->sc_ethercom, enm);
1674 while (enm) {
1675 if (sc->mcast_count >= MAXMCAST ||
1676 ether_cmp(enm->enm_addrlo, enm->enm_addrhi) != 0) {
1677 ifp->if_flags |= IFF_ALLMULTI;
1678 ieioctl(ifp, SIOCSIFFLAGS, (void *)0);
1679 goto setflag;
1680 }
1681 memcpy(&sc->mcast_addrs[sc->mcast_count], enm->enm_addrlo,
1682 ETHER_ADDR_LEN);
1683 sc->mcast_count++;
1684 ETHER_NEXT_MULTI(step, enm);
1685 }
1686 setflag:
1687 sc->want_mcsetup = 1;
1688 }
1689
1690 #ifdef IEDEBUG
1691 void
1692 print_rbd(rbd)
1693 volatile struct ie_recv_buf_desc *rbd;
1694 {
1695
1696 printf("RBD at %08lx:\nactual %04x, next %04x, buffer %08x\n"
1697 "length %04x, mbz %04x\n", (u_long)rbd, rbd->ie_rbd_actual,
1698 rbd->ie_rbd_next, rbd->ie_rbd_buffer, rbd->ie_rbd_length,
1699 rbd->mbz);
1700 }
1701 #endif
1702