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