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