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