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