1 /*
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
7 * @(#)if_ec.c 8.1 (Berkeley) 06/11/93
8 */
9
10
11 /* WARNING -- THIS DRIVER DOES NOT WORK YET -- It is merely a sketch */
12
13 #include "ec.h"
14 #if NEC > 0
15
16 /*
17 * Intel 82586/3com Etherlink II controller.
18 */
19 #include <sys/param.h>
20 #include <sys/systm.h>
21 #include <sys/mbuf.h>
22 #include <sys/buf.h>
23 #include <sys/protosw.h>
24 #include <sys/socket.h>
25 #include <sys/syslog.h>
26 #include <sys/ioctl.h>
27 #include <sys/errno.h>
28
29 #include <net/if.h>
30 #include <net/netisr.h>
31 #include <net/route.h>
32
33 #ifdef INET
34 #include <netinet/in.h>
35 #include <netinet/in_systm.h>
36 #include <netinet/in_var.h>
37 #include <netinet/ip.h>
38 #include <netinet/if_ether.h>
39 #endif
40
41 #ifdef NS
42 #include <netns/ns.h>
43 #include <netns/ns_if.h>
44 #endif
45
46 #ifdef ISO
47 extern char all_es_snpa[], all_is_snpa[], all_l1is_snpa[], all_l2is_snpa[];
48 #endif
49
50 #include <i386/isa/if_ecreg.h>
51
52 #if NBPFILTER > 0
53 #include <net/bpf.h>
54 #include <net/bpfdesc.h>
55 #endif
56
57 int ecdebug = 1; /* console error messages */
58
59 int ecintr(), ecinit(), ecioctl(), ecstart(), ether_output();
60 int ecattach(), ecprobe(), ecreset(), ecwatchdog();
61 void ec_idpattern(), ec_reset_all(), ec_getnmdata(), ecread();
62
63 struct mbuf *m_devget();
64 extern struct ifnet loif;
65 struct ec_82586params ec_82586defaults =
66 { 11, 0xc8, ECMINSIZE, 0x2e, 0, 0x60, 0, 2, 0, 0, 0x40};
67 /* 2e == no source insert */
68
69 /*
70 * Ethernet software status per interface.
71 *
72 * Each interface is referenced by a network interface structure,
73 * sc_if, which the routing code uses to locate the interface.
74 * This structure contains the output queue for the interface, its address, ...
75 */
76 struct ec_softc {
77 struct arpcom sc_ac; /* common Ethernet structures */
78 #define sc_if sc_ac.ac_if /* network-visible interface */
79 #define sc_addr sc_ac.ac_enaddr /* hardware Ethernet address */
80 caddr_t sc_device; /* e.g. isa_device */
81 caddr_t sc_bpf; /* for packet filter */
82 struct ec_ports *sc_ports; /* control ports for this unit */
83 struct ec_mem *sc_hmem; /* Host addr for shared memory */
84 struct ec_mem *sc_dmem; /* Device (chip) addr for shared mem */
85 int sc_msize; /* How much memory is mapped? */
86 int sc_iflags; /* copy of sc_if.if_flags for state */
87 int sc_rxnum; /* Last receiver dx we looked at */
88 int sc_txnum; /* Last tranmistter dx we stomped on */
89 int sc_txcnt; /* Number of packets queued for tx*/
90 int sc_xint;
91 /* errors */
92 int sc_txbusy; /* we're confused */
93 int sc_uflo; /* DMA Late */
94 int sc_runt; /* too short */
95 int sc_txbad;
96 int sc_rxlen;
97 } ec_softc[NEC];
98
99 #include <i386/isa/isa_device.h>
100
101 struct isa_driver ecdriver = {
102 ecprobe, ecattach, "ec",
103 };
104
105
106 #define TIMO 10000 /* used in ec_uprim */
107
ecprobe(id)108 ecprobe(id)
109 register struct isa_device *id;
110 {
111 int unit = id->id_unit, msize = id->id_msize;
112 struct ec_ports *reg = (struct ec_ports *)id->id_iobase;
113 register struct ec_softc *ec = ec_softc + unit;
114 u_char data[6];
115
116 ec_reset_all();
117 bzero((caddr_t)data, sizeof(data));
118 ec_getnmdata(reg, R_ECID, data);
119 if (bcmp((caddr_t)data, "*3COM*", sizeof(data)) != 0) {
120 if (ecdebug) {
121 printf("ecprobe: ec%d not matched: %s\n",
122 unit, ether_sprintf(data));
123 }
124 return 0;
125 }
126 ec_getnmdata(reg, R_ETHER, ec->sc_addr);
127 ec_getnmdata(reg, R_REV, data);
128 ec->sc_hmem = (struct ec_mem *) (id->id_maddr);
129 ec->sc_dmem = (struct ec_mem *) (0x10000 - msize);
130 ec->sc_msize = msize;
131 ec->sc_device = (caddr_t) id;
132 ec->sc_ports = reg;
133 printf("ec%d: hardware address %s, rev info %s\n",
134 unit, ether_sprintf(ec->sc_addr), ether_sprintf(data));
135 return 1;
136 }
137
138 void
ec_idpattern()139 ec_idpattern()
140 {
141 int i = 255, n;
142 register caddr_t p = (caddr_t)0x100;
143 for (n = 255; n > 0; n--) {
144 outb(p, i);
145 if ((i <<= 1) & 0x100)
146 i ^= 0xe7;
147 }
148 }
149
150 void
ec_reset_all()151 ec_reset_all()
152 {
153 register caddr_t p = (caddr_t)0x100;
154 outb(p, 0);
155 ec_idpattern();
156 outb(p, 0);
157 }
158 extern int cpuspeed;
159 #define ECWR(p, e, d) outb(&(p->e), d)
160 #define ECRD(p, e) inb(&(p->e))
161 #define SET_CA ECWR(ec->sc_ports, port_ca, 0)
162 #define UNLATCH_INT ECWR(ec->sc_ports, port_ic, 0);
163
164 void
ec_getnmdata(p,which,data)165 ec_getnmdata(p, which, data)
166 register struct ec_ports *p;
167 int which;
168 register u_char *data;
169 {
170 register int i;
171
172 ECWR(p, creg, which);
173 DELAY(2);
174 for (i = 0; i < 6; i++) {
175 DELAY(2);
176 data[i] = ECRD(p, data[i]);
177 }
178 }
179
ecreset(unit)180 ecreset(unit)
181 register int unit;
182 {
183 register struct ec_softc *ec = &ec_softc[unit];
184 struct ec_ports *p = ec->sc_ports;
185 struct ec_mem *hmem = ec->sc_hmem;
186 int timo;
187
188 ECWR(p, creg, R_LPB); DELAY(10);
189 if ((ec->sc_if.if_flags & IFF_RUNNING) == 0)
190 return 0;
191 if (ecdebug)
192 printf("ec%dreset\n", unit);
193 ec_meminit(ec);
194 ECWR(p, creg, R_NORST); DELAY(10);
195 hmem->iscp.busy = 1;
196 ECWR(p, port_ca, 0); DELAY(10);
197 for (timo = TIMO; hmem->iscp.busy; )
198 timo--;
199 if (timo == 0) {
200 printf("ec(%d)reset: iscp failed\n", unit);
201 return 0;
202 }
203 hmem->scb.command = CU_START;
204 ECWR(p, port_ca, 0); DELAY(10);
205 for (timo = TIMO; (hmem->scb.status & CU_STATE) == CUS_ACTIVE;)
206 timo--;
207 if (timo == 0 || (hmem->scb.status & CU_STATE) != CUS_IDLE) {
208 printf("ec(%d)reset: setup failed\n", unit);
209 return 0;
210 }
211 ECWR(p, port_ic, 0); DELAY(10);
212 ECWR(p, creg, R_NORST|R_IEN);
213 hmem->scb.command = RU_START | (hmem->scb.status & 0xf000);
214 ECWR(p, port_ca, 0); DELAY(10);
215 ec->sc_if.if_timer = 5;
216 return 0; /* Keep GCC Happy! */
217 }
218
219 /*
220 * Interface exists: make available by filling in network interface
221 * record. System will initialize the interface when it is ready
222 * to accept packets.
223 */
224
ecattach(id)225 ecattach(id)
226 register struct isa_device *id;
227 {
228 int unit = id->id_unit;
229 struct ec_softc *ec = &ec_softc[unit];
230 struct ifnet *ifp = &ec->sc_if;
231
232 ifp->if_unit = unit;
233 ifp->if_name = "ec";
234 ifp->if_mtu = ETHERMTU;
235 ifp->if_init = ecinit;
236 ifp->if_init = ecreset;
237 ifp->if_ioctl = ecioctl;
238 ifp->if_watchdog = ecwatchdog;
239 ifp->if_output = ether_output;
240 ifp->if_start = ecstart;
241 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
242 #if NBPFILTER > 0
243 bpfattach(&ec->sc_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
244 #endif
245 if_attach(ifp);
246 return (1);
247 }
248 #define OFF(e) ((u_short)&(((struct ec_mem *)0)->e))
249
ec_meminit(ec)250 ec_meminit(ec)
251 register struct ec_softc *ec;
252 {
253 register struct ec_mem *hmem = ec->sc_hmem;
254 register int i;
255 struct ec_rfd *rc = hmem->rcom;
256 struct ec_transmit *tc = hmem->tcom;
257 caddr_t cp;
258
259 bzero((caddr_t)hmem, ec->sc_msize);
260 *(struct ec_mem **)
261 (ec->sc_msize - 4 + (caddr_t)ec->sc_hmem) = ec->sc_dmem;
262
263 hmem->iscp.scb_off = OFF(scb);
264 hmem->iscp.scb_base = (caddr_t)ec->sc_dmem;
265
266 hmem->scb.rfa_off = OFF(rcom[0]);
267 hmem->scb.cbl_off = OFF(config);
268
269 hmem->config.com1 = COM1_CONFIGURE;
270 bcopy((caddr_t)&ec_82586defaults, (caddr_t)&hmem->config.modes,
271 sizeof(hmem->config.modes));
272 #if NBPFILTER > 0
273 if (ec->sc_if.if_flags & IFF_PROMISC)
274 hmem->config.modes.promisc |= M_PROMISC;
275 #endif
276 hmem->config.next_off = OFF(iasetup);
277
278 bcopy((caddr_t)ec->sc_addr, (caddr_t)hmem->iasetup.srcaddr, 6);
279 #ifndef ISO
280 hmem->iasetup.com1 = COM1_IASETUP | COM1_S | COM1_EL;
281 #else
282 hmem->iasetup.com1 = COM1_IASETUP;
283 hmem->iasetup.next_off = OFF(mcsetup);
284
285 hmem->mcsetup.com1 = COM1_MCSETUP | COM1_S | COM1_EL;
286 hmem->mcsetup.count = 24;
287 cp = (caddr_t)hmem->txbuf[0];
288 bcopy((caddr_t)all_es_snpa, cp, 6); cp += 6;
289 bcopy((caddr_t)all_is_snpa, cp, 6); cp += 6;
290 bcopy((caddr_t)all_l1is_snpa, cp, 6); cp += 6;
291 bcopy((caddr_t)all_l2is_snpa, cp, 6); cp += 6;
292 #endif
293 for (i = 0; i < NTXBUF; i++) {
294 tc->tbd_off = OFF(tcom[i].count);
295 tc->buffer = ec->sc_dmem->txbuf[i];
296 (tc++)->com1 = COM1_TRANSMIT | COM1_S | COM1_EL | COM1_I;
297 }
298 for (i = 0; i < NRXBUF; i++) {
299 rc->next_off = OFF(rcom[i + 1]);
300 rc->rbd_off = OFF(rcom[i].count);
301 rc->buffer = ec->sc_dmem->rxbuf[i];
302 (rc++)->size = ECMTU | COM1_EL;
303 }
304 (--rc)->next_off = OFF(rcom[0]);
305 }
306 /*
307 * Initialization of interface
308 */
ecinit(unit)309 ecinit(unit)
310 int unit;
311 {
312 register struct ifnet *ifp = &ec_softc[unit].sc_if;
313 register struct ifaddr *ifa;
314 int s;
315
316 /* not yet, if address still unknown */
317 for (ifa = ifp->if_addrlist;; ifa = ifa->ifa_next)
318 if (ifa == 0)
319 return 0;
320 else if (ifa->ifa_addr && ifa->ifa_addr->sa_family != AF_LINK)
321 break;
322 if ((ifp->if_flags & IFF_RUNNING) == 0) {
323 s = splimp();
324 ifp->if_flags |= IFF_RUNNING;
325 ecreset(unit);
326 (void) ecstart(ifp);
327 splx(s);
328 }
329 return 0;
330 }
331
332 /*
333 * Timeout: for now check for a transmit command taking more than 10 seconds.
334 */
ecwatchdog(unit)335 ecwatchdog(unit)
336 int unit;
337 {
338 register struct ec_softc *ec = ec_softc + unit;
339 if (ec->sc_iflags & IFF_OACTIVE) {
340 ec->sc_if.if_flags &= ~IFF_RUNNING;
341 ecinit(unit);
342 } else if (ec->sc_txcnt > 0)
343 ec->sc_iflags |= IFF_OACTIVE;
344 ec->sc_if.if_timer = 5;
345 }
346
347
348
ec_txstart(ec)349 ec_txstart(ec)
350 register struct ec_softc *ec;
351 {
352 struct ec_mem *hmem = ec->sc_hmem;
353 int i;
354
355 if ((i = ec->sc_txnum - ec->sc_txcnt) < 0) i += NTXBUF;
356 hmem->scb.cbl_off = OFF(tcom[i]);
357 hmem->scb.command = CU_START;
358 hmem->scb.status = 0;
359 SET_CA;
360 }
361 /*
362 * Start output on interface. Get another datagram to send
363 * off of the interface queue, and copy it to the interface
364 * before starting the output.
365 */
366 ecstart(ifp)
367 struct ifnet *ifp;
368 {
369 register struct ec_softc *ec = &ec_softc[ifp->if_unit];
370 register struct ec_transmit *tmd;
371 register struct mbuf *m;
372 int len;
373
374 again:
375 if ((ec->sc_if.if_flags & IFF_RUNNING) == 0 || ec->sc_txcnt >= NTXBUF)
376 return (0);
377 tmd = ec->sc_hmem->tcom + ec->sc_txnum;
378 if (tmd->com0 & (COM0_B | COM0_C))
379 return (ec->sc_txbusy++, 0);
380 IF_DEQUEUE(&ec->sc_if.if_snd, m);
381 if (m == 0)
382 return (0);
383 len = ecput(ec->sc_hmem->txbuf[ec->sc_txnum], m);
384 #if NBPFILTER > 0
385 /*
386 * If bpf is listening on this interface, let it
387 * see the packet before we commit it to the wire.
388 */
389 if (ec->sc_bpf)
390 bpf_tap(ec->sc_bpf, ec->sc_hmem->txbuf[ec->sc_txnum], len);
391 #endif
392 tmd->com0 = 0;
393 tmd->count = len | COM1_EL;
394 if (ec->sc_txcnt == 0)
395 ec_txstart(ec);
396 if (++ec->sc_txnum >= NTXBUF)
397 ec->sc_txnum = 0;
398 if (++ec->sc_txcnt >= NTXBUF) {
399 ec->sc_txcnt = NTXBUF;
400 ec->sc_if.if_flags |= IFF_OACTIVE;
401 }
402 goto again;
403 }
404 int ECC_intr, ECC_rint, ECC_xint, ECC_unready;
405
ecintr(unit)406 ecintr(unit)
407 register int unit;
408 {
409 struct ec_softc *ec = &ec_softc[unit];
410 struct ec_mem *hmem = ec->sc_hmem;
411 register int stat = hmem->scb.status;
412
413 hmem->scb.command = stat & 0xf000; /* Ack interrupt cause */
414 SET_CA;
415 if (stat & FR)
416 ecrint(unit);
417 if (stat & CX)
418 ecxint(unit);
419 ECC_intr++;
420 if ((stat & RU_STATE) != RUS_READY)
421 ECC_unready++;
422 UNLATCH_INT;
423 }
424
425 /*
426 * Ethernet interface transmitter interrupt.
427 * Start another output if more data to send.
428 */
ecxint(unit)429 ecxint(unit)
430 register int unit;
431 {
432 register struct ec_softc *ec = &ec_softc[unit];
433 register struct ec_transmit *tmd;
434 int i;
435
436 ECC_rint++;
437 if (ec->sc_txcnt == 0) {
438 ec->sc_xint++; /* unexpected transmit interrupt */
439 return;
440 }
441 ec->sc_iflags &= ~IFF_OACTIVE; /* clear deadman indication */
442 if ((i = ec->sc_txnum - ec->sc_txcnt) < 0) i += NTXBUF;
443 tmd = ec->sc_hmem->tcom + i;
444 if (tmd->com0 & COM0_B)
445 return;
446 ec->sc_if.if_collisions += tmd->com0 & 0xf;
447 if ((tmd->com0 & EXCOL) && (tmd->com0 & 0xf) == 0)
448 ec->sc_if.if_collisions += 16;
449 if ((tmd->com0 & COM0_OK) == 0) {
450 ecxerror(unit);
451 ec->sc_if.if_oerrors++;
452 if (tmd->com0 & DMALATE) {
453 ec->sc_uflo++;
454 (void) ecreset(unit);
455 return;
456 }
457 } else
458 ec->sc_if.if_opackets++;
459 tmd->com0 = 0;
460 if (--ec->sc_txcnt > 0)
461 ec_txstart(ec);
462 if (ec->sc_txcnt < 0) {
463 ec->sc_txbad++;
464 ec->sc_txcnt = 0;
465 }
466 ec->sc_if.if_flags &= ~IFF_OACTIVE;
467 (void) ecstart(&ec->sc_if);
468 }
469
470 #define ECNEXTRCOM \
471 if (++bix == NRXBUF) bix = 0, rmd = ec->sc_hmem->rcom; else ++rmd
472
473 /*
474 * Ethernet interface receiver interrupt.
475 * If input error just drop packet.
476 * Decapsulate packet based on type and pass to type specific
477 * higher-level input routine.
478 */
ecrint(unit)479 ecrint(unit)
480 int unit;
481 {
482 register struct ec_softc *ec = &ec_softc[unit];
483 register int bix = ec->sc_rxnum;
484 register struct ec_rfd *rmd = ec->sc_hmem->rcom + bix;
485
486 /*
487 * Out of sync with hardware, should never happen?
488 */
489 ECC_xint++;
490 if ((rmd->rfd0 & COM0_C) == 0 || (rmd->count & RBD_F) == 0) {
491 ecrerror(unit, "out of sync, resetting");
492 return ecreset(unit);
493 }
494 /*
495 * Process all buffers with valid data
496 */
497 while ((rmd->rfd0 & COM0_C) && (rmd->count & RBD_F)) {
498 if (rmd->rfd0 & (COM0_C|COM0_B|COM0_OK) != (COM0_C|COM0_OK)) {
499 ec->sc_rxnum = bix;
500 ecrerror(unit, "bad packet");
501 ec->sc_if.if_ierrors++;
502 }
503 if ((rmd->count & (RBD_F|RBD_EOF)) != (RBD_F|RBD_EOF)) {
504 ecrerror(unit, "chained buffer");
505 ec->sc_rxlen++;
506 ec->sc_if.if_ierrors++;
507 } else
508 ecread(ec, ec->sc_hmem->txbuf[bix], rmd->count & 0x2f);
509 rmd->count = 0;
510 rmd->rfd0 = 0;
511 ECNEXTRCOM;
512 ec->sc_rxnum = bix;
513 }
514 }
515
516 void
ecread(ec,buf,len)517 ecread(ec, buf, len)
518 register struct ec_softc *ec;
519 char *buf;
520 int len;
521 {
522 struct ether_header *et, eh;
523 struct mbuf *m;
524 int off, resid, unit = ec->sc_if.if_unit;
525
526 ec->sc_if.if_ipackets++;
527 et = (struct ether_header *)buf;
528 et->ether_type = ntohs((u_short)et->ether_type);
529 bcopy((caddr_t)et, &eh, sizeof(eh));
530 /* adjust input length to account for header */
531 len = len - sizeof(struct ether_header);
532
533 #define ecdataaddr(et, off, type) ((type)(((caddr_t)((et)+1)+(off))))
534 if (et->ether_type >= ETHERTYPE_TRAIL &&
535 et->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
536 off = (et->ether_type - ETHERTYPE_TRAIL) * 512;
537 if (off >= ETHERMTU)
538 return; /* sanity */
539 et->ether_type = ntohs(*ecdataaddr(et, off, u_short *));
540 resid = ntohs(*(ecdataaddr(et, off+2, u_short *)));
541 if (off + resid > len)
542 return; /* sanity */
543 len = off + resid;
544 } else
545 off = 0;
546
547 if (len <= 0) {
548 if (ecdebug)
549 log(LOG_WARNING,
550 "ec%d: ierror(runt packet): from %s: len=%d\n",
551 unit, ether_sprintf(et->ether_shost), len);
552 ec->sc_runt++;
553 ec->sc_if.if_ierrors++;
554 return;
555 }
556 #if NBPFILTER > 0
557 /*
558 * Check if there's a bpf filter listening on this interface.
559 * If so, hand off the raw packet to bpf, which must deal with
560 * trailers in its own way.
561 */
562 if (ec->sc_bpf)
563 bpf_tap(ec->sc_bpf, buf, len + sizeof(struct ether_header));
564 #endif
565 #if defined(ISO) || NBPFILTER > 0
566 /*
567 * Note that the interface cannot be in promiscuous mode if
568 * there are no bpf listeners. If we are in promiscuous
569 * mode, we have to check if this packet is really ours.
570 * However, there may be appropriate multicate addresses involved
571 */
572 #define NOT_TO(p) (bcmp(et->ether_dhost, p, sizeof(et->ether_dhost)) != 0)
573 if (et->ether_dhost[0] & 1) {
574 if (NOT_TO(etherbroadcastaddr)
575 #ifdef ISO
576 && NOT_TO(all_es_snpa) && NOT_TO(all_is_snpa)
577 && NOT_TO(all_l1is_snpa) && NOT_TO(all_l2is_snpa)
578 #endif
579 ) return;
580 } else if ((ec->sc_if.if_flags & IFF_PROMISC) && NOT_TO(ec->sc_addr))
581 return;
582 #endif
583 /*
584 * Pull packet off interface. Off is nonzero if packet
585 * has trailing header; m_devget will then force this header
586 * information to be at the front, but we still have to drop
587 * the type and length which are at the front of any trailer data.
588 */
589 m = m_devget((char *)(et + 1), len, off, &ec->sc_if, 0);
590 if (m == 0)
591 return;
592 ether_input(&ec->sc_if, &eh, m);
593 }
594
595 /*
596 * Routine to copy from mbuf chain to transmit
597 * buffer in board local memory.
598 */
ecput(ecbuf,m)599 ecput(ecbuf, m)
600 register char *ecbuf;
601 register struct mbuf *m;
602 {
603 register struct mbuf *mp;
604 register int len, tlen = 0;
605
606 for (mp = m; mp; mp = mp->m_next) {
607 len = mp->m_len;
608 if (len == 0)
609 continue;
610 tlen += len;
611 bcopy(mtod(mp, char *), ecbuf, len);
612 ecbuf += len;
613 }
614 m_freem(m);
615 if (tlen < ECMINSIZE) {
616 bzero(ecbuf, ECMINSIZE - tlen);
617 tlen = ECMINSIZE;
618 }
619 return(tlen);
620 }
621
622 /*
623 * Process an ioctl request.
624 */
ecioctl(ifp,cmd,data)625 ecioctl(ifp, cmd, data)
626 register struct ifnet *ifp;
627 int cmd;
628 caddr_t data;
629 {
630 register struct ifaddr *ifa = (struct ifaddr *)data;
631 struct ec_softc *ec = &ec_softc[ifp->if_unit];
632 int s = splimp(), error = 0;
633
634 switch (cmd) {
635
636 case SIOCSIFADDR:
637 ifp->if_flags |= IFF_UP;
638 switch (ifa->ifa_addr->sa_family) {
639 #ifdef INET
640 case AF_INET:
641 ecinit(ifp->if_unit); /* before arpwhohas */
642 ((struct arpcom *)ifp)->ac_ipaddr =
643 IA_SIN(ifa)->sin_addr;
644 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
645 break;
646 #endif
647 #ifdef NS
648 case AF_NS:
649 {
650 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
651
652 if (ns_nullhost(*ina))
653 ina->x_host = *(union ns_host *)(ec->sc_addr);
654 else {
655 ifp->if_flags &= ~IFF_RUNNING;
656 bcopy((caddr_t)ina->x_host.c_host,
657 (caddr_t)ec->sc_addr, sizeof(ec->sc_addr));
658 }
659 ecinit(ifp->if_unit);
660 break;
661 }
662 #endif
663 default:
664 ecinit(ifp->if_unit);
665 break;
666 }
667 break;
668
669 case SIOCSIFFLAGS:
670 if ((ifp->if_flags & IFF_UP) == 0 &&
671 ifp->if_flags & IFF_RUNNING) {
672 ifp->if_flags &= ~IFF_RUNNING;
673 ecreset(ifp->if_unit);
674 } else if (ifp->if_flags & IFF_UP &&
675 (ifp->if_flags & IFF_RUNNING) == 0)
676 ecinit(ifp->if_unit);
677 /*
678 * If the state of the promiscuous bit changes, the interface
679 * must be reset to effect the change.
680 */
681 if (((ifp->if_flags ^ ec->sc_iflags) & IFF_PROMISC) &&
682 (ifp->if_flags & IFF_RUNNING)) {
683 ec->sc_iflags = ifp->if_flags & ~IFF_OACTIVE;
684 ecreset(ifp->if_unit);
685 ecstart(ifp);
686 }
687 break;
688
689 default:
690 error = EINVAL;
691 }
692 splx(s);
693 return (error);
694 }
695
ecrerror(unit,msg)696 ecrerror(unit, msg)
697 int unit;
698 char *msg;
699 {
700 register struct ec_softc *ec = &ec_softc[unit];
701 register struct ec_rfd *rmd;
702 int len;
703
704 if (!ecdebug)
705 return;
706
707 rmd = &ec->sc_hmem->rcom[ec->sc_rxnum];
708 len = rmd->count;
709 log(LOG_WARNING,
710 "ec%d: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n",
711 unit, msg,
712 len > 11 ? ether_sprintf(&ec->sc_hmem->rxbuf[ec->sc_rxnum][6]) : "unknown",
713 ec->sc_rxnum, len,
714 rmd->rfd0, "\14\14LEN\13CRC\12ALGN\11NBUF\10DMAL\07SHRT");
715 }
716
ecxerror(unit)717 ecxerror(unit)
718 int unit;
719 {
720 register struct ec_softc *ec = &ec_softc[unit];
721 register struct ec_transmit *tmd;
722 int len;
723
724 if (!ecdebug)
725 return;
726
727 tmd = &ec->sc_hmem->tcom[ec->sc_txnum];
728 len = tmd->count;
729 log(LOG_WARNING,
730 "ec%d: oerror: to %s: buf=%d, len=%d, com0=%b\n",
731 unit,
732 len > 5 ? ether_sprintf(ec->sc_hmem->txbuf[ec->sc_txnum]) : "unknown",
733 ec->sc_txnum, len,
734 tmd->com0,
735 "\14\14ABRT\13LCOLL\12NCAR\11NCTS\10DMAL\07TDEF\06HRBT\05XCOL");
736 }
737 #endif
738