1 /*
2 * Copyright (c) 1982, 1986 Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
7 * @(#)if_ec.c 7.8 (Berkeley) 12/16/90
8 */
9
10 #include "ec.h"
11 #if NEC > 0
12
13 /*
14 * 3Com Ethernet Controller interface
15 */
16 #include "../include/pte.h"
17
18 #include "sys/param.h"
19 #include "sys/systm.h"
20 #include "sys/mbuf.h"
21 #include "sys/buf.h"
22 #include "sys/protosw.h"
23 #include "sys/socket.h"
24 #include "sys/syslog.h"
25 #include "sys/vmmac.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 #include "../include/cpu.h"
47 #include "../include/mtpr.h"
48 #include "if_ecreg.h"
49 #include "if_uba.h"
50 #include "../uba/ubareg.h"
51 #include "../uba/ubavar.h"
52
53 #if CLSIZE == 2
54 #define ECBUFSIZE 32 /* on-board memory, clusters */
55 #endif
56
57 int ecubamem(), ecprobe(), ecattach(), ecrint(), ecxint(), eccollide();
58 struct uba_device *ecinfo[NEC];
59 u_short ecstd[] = { 0 };
60 struct uba_driver ecdriver =
61 { ecprobe, 0, ecattach, 0, ecstd, "ec", ecinfo, 0, 0, 0, 0, ecubamem };
62
63 int ecinit(),ecioctl(),ecstart(),ecreset(),ether_output();
64 struct mbuf *ecget();
65
66 extern struct ifnet loif;
67
68 /*
69 * Ethernet software status per interface.
70 *
71 * Each interface is referenced by a network interface structure,
72 * es_if, which the routing code uses to locate the interface.
73 * This structure contains the output queue for the interface, its address, ...
74 * We also have, for each interface, a UBA interface structure, which
75 * contains information about the UNIBUS resources held by the interface:
76 * map registers, buffered data paths, etc. Information is cached in this
77 * structure for use by the if_uba.c routines in running the interface
78 * efficiently.
79 */
80 struct ec_softc {
81 struct arpcom es_ac; /* common Ethernet structures */
82 #define es_if es_ac.ac_if /* network-visible interface */
83 #define es_addr es_ac.ac_enaddr /* hardware Ethernet address */
84 struct ifuba es_ifuba; /* UNIBUS resources */
85 short es_mask; /* mask for current output delay */
86 u_char *es_buf[16]; /* virtual addresses of buffers */
87 } ec_softc[NEC];
88
89 /*
90 * Configure on-board memory for an interface.
91 * Called from autoconfig and after a uba reset.
92 * The address of the memory on the uba is supplied in the device flags.
93 */
ecubamem(ui,uban)94 ecubamem(ui, uban)
95 register struct uba_device *ui;
96 {
97 register caddr_t ecbuf = (caddr_t) &umem[uban][ui->ui_flags];
98 register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr;
99
100 /*
101 * Make sure csr is there (we run before ecprobe).
102 */
103 if (badaddr((caddr_t)addr, 2))
104 return (-1);
105 #if VAX780
106 if (cpu == VAX_780 && uba_hd[uban].uh_uba->uba_sr) {
107 uba_hd[uban].uh_uba->uba_sr = uba_hd[uban].uh_uba->uba_sr;
108 return (-1);
109 }
110 #endif
111 /*
112 * Make sure memory is turned on
113 */
114 addr->ec_rcr = EC_AROM;
115 /*
116 * Tell the system that the board has memory here, so it won't
117 * attempt to allocate the addresses later.
118 */
119 if (ubamem(uban, ui->ui_flags, ECBUFSIZE*CLSIZE, 1) == 0) {
120 printf("ec%d: cannot reserve uba addresses\n", ui->ui_unit);
121 addr->ec_rcr = EC_MDISAB; /* disable memory */
122 return (-1);
123 }
124 /*
125 * Check for existence of buffers on Unibus.
126 */
127 if (badaddr((caddr_t)ecbuf, 2)) {
128 bad:
129 printf("ec%d: buffer mem not found\n", ui->ui_unit);
130 (void) ubamem(uban, ui->ui_flags, ECBUFSIZE*2, 0);
131 addr->ec_rcr = EC_MDISAB; /* disable memory */
132 return (-1);
133 }
134 #if VAX780
135 if (cpu == VAX_780 && uba_hd[uban].uh_uba->uba_sr) {
136 uba_hd[uban].uh_uba->uba_sr = uba_hd[uban].uh_uba->uba_sr;
137 goto bad;
138 }
139 #endif
140 if (ui->ui_alive == 0) /* Only printf from autoconfig */
141 printf("ec%d: mem %x-%x\n", ui->ui_unit,
142 ui->ui_flags, ui->ui_flags + ECBUFSIZE*CLBYTES - 1);
143 ui->ui_type = 1; /* Memory on, allocated */
144 return (0);
145 }
146
147 /*
148 * Do output DMA to determine interface presence and
149 * interrupt vector. DMA is too short to disturb other hosts.
150 */
ecprobe(reg,ui)151 ecprobe(reg, ui)
152 caddr_t reg;
153 struct uba_device *ui;
154 {
155 register int br, cvec; /* r11, r10 value-result */
156 register struct ecdevice *addr = (struct ecdevice *)reg;
157 register caddr_t ecbuf = (caddr_t) &umem[ui->ui_ubanum][ui->ui_flags];
158
159 #ifdef lint
160 br = 0; cvec = br; br = cvec;
161 ecrint(0); ecxint(0); eccollide(0);
162 #endif
163
164 /*
165 * Check that buffer memory was found and enabled.
166 */
167 if (ui->ui_type == 0)
168 return(0);
169 /*
170 * Make a one byte packet in what should be buffer #0.
171 * Submit it for sending. This should cause an xmit interrupt.
172 * The xmit interrupt vector is 8 bytes after the receive vector,
173 * so adjust for this before returning.
174 */
175 *(u_short *)ecbuf = (u_short) 03777;
176 ecbuf[03777] = '\0';
177 addr->ec_xcr = EC_XINTEN|EC_XWBN;
178 DELAY(100000);
179 addr->ec_xcr = EC_XCLR;
180 if (cvec > 0 && cvec != 0x200) {
181 if (cvec & 04) { /* collision interrupt */
182 cvec -= 04;
183 br += 1; /* rcv is collision + 1 */
184 } else { /* xmit interrupt */
185 cvec -= 010;
186 br += 2; /* rcv is xmit + 2 */
187 }
188 }
189 return (1);
190 }
191
192 /*
193 * Interface exists: make available by filling in network interface
194 * record. System will initialize the interface when it is ready
195 * to accept packets.
196 */
197 ecattach(ui)
198 struct uba_device *ui;
199 {
200 struct ec_softc *es = &ec_softc[ui->ui_unit];
201 register struct ifnet *ifp = &es->es_if;
202 register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr;
203 int i, j;
204 u_char *cp;
205
206 ifp->if_unit = ui->ui_unit;
207 ifp->if_name = "ec";
208 ifp->if_mtu = ETHERMTU;
209
210 /*
211 * Read the ethernet address off the board, one nibble at a time.
212 */
213 addr->ec_xcr = EC_UECLR; /* zero address pointer */
214 addr->ec_rcr = EC_AROM;
215 cp = es->es_addr;
216 #define NEXTBIT addr->ec_rcr = EC_AROM|EC_ASTEP; addr->ec_rcr = EC_AROM
217 for (i=0; i < sizeof (es->es_addr); i++) {
218 *cp = 0;
219 for (j=0; j<=4; j+=4) {
220 *cp |= ((addr->ec_rcr >> 8) & 0xf) << j;
221 NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT;
222 }
223 cp++;
224 }
225 printf("ec%d: hardware address %s\n", ui->ui_unit,
226 ether_sprintf(es->es_addr));
227 ifp->if_init = ecinit;
228 ifp->if_ioctl = ecioctl;
229 ifp->if_output = ether_output;
230 ifp->if_start = ecstart;
231 ifp->if_reset = ecreset;
232 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
233 for (i=0; i<16; i++)
234 es->es_buf[i]
235 = (u_char *)&umem[ui->ui_ubanum][ui->ui_flags + 2048*i];
236 if_attach(ifp);
237 }
238
239 /*
240 * Reset of interface after UNIBUS reset.
241 * If interface is on specified uba, reset its state.
242 */
ecreset(unit,uban)243 ecreset(unit, uban)
244 int unit, uban;
245 {
246 register struct uba_device *ui;
247
248 if (unit >= NEC || (ui = ecinfo[unit]) == 0 || ui->ui_alive == 0 ||
249 ui->ui_ubanum != uban)
250 return;
251 printf(" ec%d", unit);
252 ec_softc[unit].es_if.if_flags &= ~IFF_RUNNING;
253 ecinit(unit);
254 }
255
256 /*
257 * Initialization of interface; clear recorded pending
258 * operations, and reinitialize UNIBUS usage.
259 */
ecinit(unit)260 ecinit(unit)
261 int unit;
262 {
263 struct ec_softc *es = &ec_softc[unit];
264 struct ecdevice *addr;
265 register struct ifnet *ifp = &es->es_if;
266 int i, s;
267
268 /* not yet, if address still unknown */
269 if (ifp->if_addrlist == (struct ifaddr *)0)
270 return;
271
272 /*
273 * Hang receive buffers and start any pending writes.
274 * Writing into the rcr also makes sure the memory
275 * is turned on.
276 */
277 if ((ifp->if_flags & IFF_RUNNING) == 0) {
278 u_short start_read;
279 addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
280 s = splimp();
281 /*
282 * write our ethernet address into the address recognition ROM
283 * so we can always use the same EC_READ bits (referencing ROM),
284 * in case we change the address sometime.
285 * Note that this is safe here as the receiver is NOT armed.
286 */
287 ec_setaddr(es->es_addr, unit);
288 /*
289 * Arm the receiver
290 #ifdef MULTI
291 if (es->es_if.if_flags & IFF_PROMISC)
292 start_read = EC_PROMISC;
293 else if (es->es_if.if_flags & IFF_MULTI)
294 start_read = EC_MULTI;
295 else
296 #endif MULTI
297 start_read = EC_READ;
298 */
299 for (i = ECRHBF; i >= ECRLBF; i--)
300 addr->ec_rcr = EC_READ | i;
301 es->es_if.if_flags &= ~IFF_OACTIVE;
302 es->es_mask = ~0;
303 es->es_if.if_flags |= IFF_RUNNING;
304 if (es->es_if.if_snd.ifq_head)
305 (void) ecstart(&es->es_if);
306 splx(s);
307 }
308 }
309
310 /*
311 * Start output on interface. Get another datagram to send
312 * off of the interface queue, and copy it to the interface
313 * before starting the output.
314 */
315 ecstart(ifp)
316 struct ifnet *ifp;
317 {
318 int unit = ifp->if_unit;
319 register struct ec_softc *es = &ec_softc[unit];
320 struct ecdevice *addr;
321 struct mbuf *m;
322
323 if ((es->es_if.if_flags & IFF_RUNNING) == 0)
324 return (0);
325 IF_DEQUEUE(&es->es_if.if_snd, m);
326 if (m == 0)
327 return (0);
328 ecput(es->es_buf[ECTBF], m);
329 addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
330 addr->ec_xcr = EC_WRITE|ECTBF;
331 es->es_if.if_flags |= IFF_OACTIVE;
332 return (0);
333 }
334
335 /*
336 * Ethernet interface transmitter interrupt.
337 * Start another output if more data to send.
338 */
ecxint(unit)339 ecxint(unit)
340 int unit;
341 {
342 register struct ec_softc *es = &ec_softc[unit];
343 register struct ecdevice *addr =
344 (struct ecdevice *)ecinfo[unit]->ui_addr;
345
346 if ((es->es_if.if_flags & IFF_OACTIVE) == 0)
347 return;
348 if ((addr->ec_xcr&EC_XDONE) == 0 || (addr->ec_xcr&EC_XBN) != ECTBF) {
349 printf("ec%d: stray xmit interrupt, xcr=%b\n", unit,
350 addr->ec_xcr, EC_XBITS);
351 es->es_if.if_flags &= ~IFF_OACTIVE;
352 addr->ec_xcr = EC_XCLR;
353 return;
354 }
355 es->es_if.if_opackets++;
356 es->es_if.if_flags &= ~IFF_OACTIVE;
357 es->es_mask = ~0;
358 addr->ec_xcr = EC_XCLR;
359 if (es->es_if.if_snd.ifq_head)
360 (void) ecstart(&es->es_if);
361 }
362
363 /*
364 * Collision on ethernet interface. Do exponential
365 * backoff, and retransmit. If have backed off all
366 * the way print warning diagnostic, and drop packet.
367 */
eccollide(unit)368 eccollide(unit)
369 int unit;
370 {
371 register struct ec_softc *es = &ec_softc[unit];
372 register struct ecdevice *addr =
373 (struct ecdevice *)ecinfo[unit]->ui_addr;
374 register i;
375 int delay;
376
377 es->es_if.if_collisions++;
378 if ((es->es_if.if_flags & IFF_OACTIVE) == 0)
379 return;
380
381 /*
382 * Es_mask is a 16 bit number with n low zero bits, with
383 * n the number of backoffs. When es_mask is 0 we have
384 * backed off 16 times, and give up.
385 */
386 if (es->es_mask == 0) {
387 u_short start_read;
388 es->es_if.if_oerrors++;
389 log(LOG_ERR, "ec%d: send error\n", unit);
390 /*
391 * Reset interface, then requeue rcv buffers.
392 * Some incoming packets may be lost, but that
393 * can't be helped.
394 */
395 addr->ec_xcr = EC_UECLR;
396 #ifdef MULTI
397 if (es->es_if.if_flags & IFF_PROMISC)
398 start_read = EC_PROMISC;
399 else if (es->es_if.if_flags & IFF_MULTI)
400 start_read = EC_MULTI;
401 else
402 #endif MULTI
403 start_read = EC_READ;
404 for (i=ECRHBF; i>=ECRLBF; i--)
405 addr->ec_rcr = start_read|i;
406 /*
407 * Reset and transmit next packet (if any).
408 */
409 es->es_if.if_flags &= ~IFF_OACTIVE;
410 es->es_mask = ~0;
411 if (es->es_if.if_snd.ifq_head)
412 (void) ecstart(&es->es_if);
413 return;
414 }
415 /*
416 * Do exponential backoff. Compute delay based on low bits
417 * of the interval timer (1 bit for each transmission attempt,
418 * but at most 5 bits). Then delay for that number of
419 * slot times. A slot time is 51.2 microseconds (rounded to 51).
420 * This does not take into account the time already used to
421 * process the interrupt.
422 */
423 es->es_mask <<= 1;
424 delay = mfpr(ICR) & 0x1f &~ es->es_mask;
425 DELAY(delay * 51);
426 /*
427 * Clear the controller's collision flag, thus enabling retransmit.
428 */
429 addr->ec_xcr = EC_CLEAR;
430 }
431
432 /*
433 * Ethernet interface receiver interrupt.
434 * If input error just drop packet.
435 * Otherwise examine
436 * packet to determine type. If can't determine length
437 * from type, then have to drop packet. Othewise decapsulate
438 * packet based on type and pass to type specific higher-level
439 * input routine.
440 */
ecrint(unit)441 ecrint(unit)
442 int unit;
443 {
444 struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
445
446 while (addr->ec_rcr & EC_RDONE)
447 ecread(unit);
448 }
449
ecread(unit)450 ecread(unit)
451 int unit;
452 {
453 register struct ec_softc *es = &ec_softc[unit];
454 struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
455 register struct ether_header *ec;
456 struct mbuf *m;
457 int len, off, resid, ecoff, rbuf;
458 register struct ifqueue *inq;
459 u_short start_read;
460 u_char *ecbuf;
461
462 es->es_if.if_ipackets++;
463 rbuf = addr->ec_rcr & EC_RBN;
464 if (rbuf < ECRLBF || rbuf > ECRHBF)
465 panic("ecrint");
466 ecbuf = es->es_buf[rbuf];
467 ecoff = *(short *)ecbuf;
468 if (ecoff <= ECRDOFF || ecoff > 2046) {
469 es->es_if.if_ierrors++;
470 #ifdef notdef
471 if (es->es_if.if_ierrors % 100 == 0)
472 printf("ec%d: += 100 input errors\n", unit);
473 #endif
474 goto setup;
475 }
476
477 /*
478 * Get input data length.
479 * Get pointer to ethernet header (in input buffer).
480 * Deal with trailer protocol: if type is trailer type
481 * get true type from first 16-bit word past data.
482 * Remember that type was trailer by setting off.
483 */
484 len = ecoff - ECRDOFF - sizeof (struct ether_header);
485 ec = (struct ether_header *)(ecbuf + ECRDOFF);
486 ec->ether_type = ntohs((u_short)ec->ether_type);
487 #define ecdataaddr(ec, off, type) ((type)(((caddr_t)((ec)+1)+(off))))
488 if (ec->ether_type >= ETHERTYPE_TRAIL &&
489 ec->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
490 off = (ec->ether_type - ETHERTYPE_TRAIL) * 512;
491 if (off >= ETHERMTU)
492 goto setup; /* sanity */
493 ec->ether_type = ntohs(*ecdataaddr(ec, off, u_short *));
494 resid = ntohs(*(ecdataaddr(ec, off+2, u_short *)));
495 if (off + resid > len)
496 goto setup; /* sanity */
497 len = off + resid;
498 } else
499 off = 0;
500 if (len == 0)
501 goto setup;
502
503 /*
504 * Pull packet off interface. Off is nonzero if packet
505 * has trailing header; ecget will then force this header
506 * information to be at the front, but we still have to drop
507 * the type and length which are at the front of any trailer data.
508 */
509 m = ecget(ecbuf, len, off, &es->es_if);
510 if (m)
511 ether_input(&es->es_if, ec, m);
512 /*
513 * Reset for next packet.
514 */
515 setup:
516 #ifdef MULTI
517 if (es->es_if.if_flags & IFF_PROMISC)
518 start_read = EC_PROMISC;
519 else if (es->es_if.if_flags & IFF_MULTI)
520 start_read = EC_MULTI;
521 else
522 #endif MULTI
523 start_read = EC_READ;
524 addr->ec_rcr = start_read|EC_RCLR|rbuf;
525 }
526
527 /*
528 * Routine to copy from mbuf chain to transmit
529 * buffer in UNIBUS memory.
530 * If packet size is less than the minimum legal size,
531 * the buffer is expanded. We probably should zero out the extra
532 * bytes for security, but that would slow things down.
533 */
ecput(ecbuf,m)534 ecput(ecbuf, m)
535 u_char *ecbuf;
536 struct mbuf *m;
537 {
538 register struct mbuf *mp;
539 register int off;
540 u_char *bp;
541
542 for (off = 2048, mp = m; mp; mp = mp->m_next)
543 off -= mp->m_len;
544 if (2048 - off < ETHERMIN + sizeof (struct ether_header))
545 off = 2048 - ETHERMIN - sizeof (struct ether_header);
546 *(u_short *)ecbuf = off;
547 bp = (u_char *)(ecbuf + off);
548 for (mp = m; mp; mp = mp->m_next) {
549 register unsigned len = mp->m_len;
550 u_char *mcp;
551
552 if (len == 0)
553 continue;
554 mcp = mtod(mp, u_char *);
555 if ((unsigned)bp & 01) {
556 *bp++ = *mcp++;
557 len--;
558 }
559 if (off = (len >> 1)) {
560 register u_short *to, *from;
561
562 to = (u_short *)bp;
563 from = (u_short *)mcp;
564 do
565 *to++ = *from++;
566 while (--off > 0);
567 bp = (u_char *)to,
568 mcp = (u_char *)from;
569 }
570 if (len & 01)
571 *bp++ = *mcp++;
572 }
573 m_freem(m);
574 }
575
576 /*
577 * Routine to copy from UNIBUS memory into mbufs.
578 * Similar in spirit to if_rubaget.
579 *
580 * Warning: This makes the fairly safe assumption that
581 * mbufs have even lengths.
582 */
583 struct mbuf *
ecget(ecbuf,totlen,off0,ifp)584 ecget(ecbuf, totlen, off0, ifp)
585 u_char *ecbuf;
586 int totlen, off0;
587 struct ifnet *ifp;
588 {
589 register struct mbuf *m;
590 struct mbuf *top = 0, **mp = ⊤
591 register int off = off0, len;
592 u_char *cp = (ecbuf += ECRDOFF + sizeof (struct ether_header));
593 u_char *packet_end = cp + totlen;
594
595 if (off) {
596 off += 2 * sizeof(u_short);
597 totlen -= 2 *sizeof(u_short);
598 cp += off;
599 }
600
601 MGETHDR(m, M_DONTWAIT, MT_DATA);
602 if (m == 0)
603 return (0);
604 m->m_pkthdr.rcvif = ifp;
605 m->m_pkthdr.len = totlen;
606 m->m_len = MHLEN;
607
608 while (totlen > 0) {
609 register int words;
610 u_char *mcp;
611
612 if (top) {
613 MGET(m, M_DONTWAIT, MT_DATA);
614 if (m == 0) {
615 m_freem(top);
616 return (0);
617 }
618 m->m_len = MLEN;
619 }
620 len = min(totlen, (packet_end - cp));
621 if (len >= MINCLSIZE) {
622 MCLGET(m, M_DONTWAIT);
623 if (m->m_flags & M_EXT)
624 m->m_len = len = min(len, MCLBYTES);
625 else
626 len = m->m_len;
627 } else {
628 /*
629 * Place initial small packet/header at end of mbuf.
630 */
631 if (len < m->m_len) {
632 if (top == 0 && len + max_linkhdr <= m->m_len)
633 m->m_data += max_linkhdr;
634 m->m_len = len;
635 } else
636 len = m->m_len;
637 }
638 mcp = mtod(m, u_char *);
639 if (words = (len >> 1)) {
640 register u_short *to, *from;
641
642 to = (u_short *)mcp;
643 from = (u_short *)cp;
644 do
645 *to++ = *from++;
646 while (--words > 0);
647 mcp = (u_char *)to;
648 cp = (u_char *)from;
649 }
650 if (len & 01)
651 *mcp++ = *cp++;
652 *mp = m;
653 mp = &m->m_next;
654 totlen -= len;
655 if (cp == packet_end)
656 cp = ecbuf;
657 }
658 return (top);
659 bad:
660 m_freem(top);
661 return (0);
662 }
663
664 /*
665 * Process an ioctl request.
666 */
ecioctl(ifp,cmd,data)667 ecioctl(ifp, cmd, data)
668 register struct ifnet *ifp;
669 int cmd;
670 caddr_t data;
671 {
672 register struct ifaddr *ifa = (struct ifaddr *)data;
673 struct ec_softc *es = &ec_softc[ifp->if_unit];
674 struct ecdevice *addr;
675 int s = splimp(), error = 0;
676
677 addr = (struct ecdevice *)(ecinfo[ifp->if_unit]->ui_addr);
678
679 switch (cmd) {
680
681 case SIOCSIFADDR:
682 ifp->if_flags |= IFF_UP;
683
684 switch (ifa->ifa_addr->sa_family) {
685 #ifdef INET
686 case AF_INET:
687 ecinit(ifp->if_unit); /* before arpwhohas */
688 ((struct arpcom *)ifp)->ac_ipaddr =
689 IA_SIN(ifa)->sin_addr;
690 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
691 break;
692 #endif
693 #ifdef NS
694 case AF_NS:
695 {
696 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
697
698 if (ns_nullhost(*ina))
699 ina->x_host = *(union ns_host *)(es->es_addr);
700 else {
701 /*
702 * The manual says we can't change the address
703 * while the receiver is armed,
704 * so reset everything
705 */
706 ifp->if_flags &= ~IFF_RUNNING;
707 bcopy((caddr_t)ina->x_host.c_host,
708 (caddr_t)es->es_addr, sizeof(es->es_addr));
709 }
710 ecinit(ifp->if_unit); /* does ec_setaddr() */
711 break;
712 }
713 #endif
714 default:
715 ecinit(ifp->if_unit);
716 break;
717 }
718 break;
719
720 case SIOCSIFFLAGS:
721 if ((ifp->if_flags & IFF_UP) == 0 &&
722 ifp->if_flags & IFF_RUNNING) {
723 addr->ec_xcr = EC_UECLR;
724 ifp->if_flags &= ~IFF_RUNNING;
725 } else if (ifp->if_flags & IFF_UP &&
726 (ifp->if_flags & IFF_RUNNING) == 0)
727 ecinit(ifp->if_unit);
728 break;
729
730 default:
731 error = EINVAL;
732 }
733 splx(s);
734 return (error);
735 }
736
ec_setaddr(physaddr,unit)737 ec_setaddr(physaddr,unit)
738 u_char *physaddr;
739 int unit;
740 {
741 struct ec_softc *es = &ec_softc[unit];
742 struct uba_device *ui = ecinfo[unit];
743 register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr;
744 register char nibble;
745 register int i, j;
746
747 /*
748 * Use the ethernet address supplied
749 * Note that we do a UECLR here, so the receive buffers
750 * must be requeued.
751 */
752
753 #ifdef DEBUG
754 printf("ec_setaddr: setting address for unit %d = %s",
755 unit, ether_sprintf(physaddr));
756 #endif
757 addr->ec_xcr = EC_UECLR;
758 addr->ec_rcr = 0;
759 /* load requested address */
760 for (i = 0; i < 6; i++) { /* 6 bytes of address */
761 es->es_addr[i] = physaddr[i];
762 nibble = physaddr[i] & 0xf; /* lower nibble */
763 addr->ec_rcr = (nibble << 8);
764 addr->ec_rcr = (nibble << 8) + EC_AWCLK; /* latch nibble */
765 addr->ec_rcr = (nibble << 8);
766 for (j=0; j < 4; j++) {
767 addr->ec_rcr = 0;
768 addr->ec_rcr = EC_ASTEP; /* step counter */
769 addr->ec_rcr = 0;
770 }
771 nibble = (physaddr[i] >> 4) & 0xf; /* upper nibble */
772 addr->ec_rcr = (nibble << 8);
773 addr->ec_rcr = (nibble << 8) + EC_AWCLK; /* latch nibble */
774 addr->ec_rcr = (nibble << 8);
775 for (j=0; j < 4; j++) {
776 addr->ec_rcr = 0;
777 addr->ec_rcr = EC_ASTEP; /* step counter */
778 addr->ec_rcr = 0;
779 }
780 }
781 #ifdef DEBUG
782 /*
783 * Read the ethernet address off the board, one nibble at a time.
784 */
785 addr->ec_xcr = EC_UECLR;
786 addr->ec_rcr = 0; /* read RAM */
787 cp = es->es_addr;
788 #undef NEXTBIT
789 #define NEXTBIT addr->ec_rcr = EC_ASTEP; addr->ec_rcr = 0
790 for (i=0; i < sizeof (es->es_addr); i++) {
791 *cp = 0;
792 for (j=0; j<=4; j+=4) {
793 *cp |= ((addr->ec_rcr >> 8) & 0xf) << j;
794 NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT;
795 }
796 cp++;
797 }
798 printf("ec_setaddr: RAM address for unit %d = %s",
799 unit, ether_sprintf(physaddr));
800 #endif
801 }
802 #endif
803