|
|
1.1 root 1: /*
2: * Copyright (c) 1988 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that the above copyright notice and this paragraph are
7: * duplicated in all such forms and that any documentation,
8: * advertising materials, and other materials related to such
9: * distribution and use acknowledge that the software was developed
10: * by the University of California, Berkeley. The name of the
11: * University may not be used to endorse or promote products derived
12: * from this software without specific prior written permission.
13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16: *
17: * @(#)if_ace.c 7.2 (Berkeley) 6/29/88
18: */
19:
20: /*
21: * ACC VERSAbus Ethernet controller
22: */
23: #include "ace.h"
24: #if NACE > 0
25:
26: #include "param.h"
27: #include "systm.h"
28: #include "mbuf.h"
29: #include "buf.h"
30: #include "protosw.h"
31: #include "socket.h"
32: #include "vmmac.h"
33: #include "ioctl.h"
34: #include "errno.h"
35: #include "vmparam.h"
36: #include "syslog.h"
37:
38: #include "../net/if.h"
39: #include "../net/netisr.h"
40: #include "../net/route.h"
41: #ifdef INET
42: #include "../netinet/in.h"
43: #include "../netinet/in_systm.h"
44: #include "../netinet/in_var.h"
45: #include "../netinet/ip.h"
46: #include "../netinet/ip_var.h"
47: #include "../netinet/if_ether.h"
48: #endif
49: #ifdef NS
50: #include "../netns/ns.h"
51: #include "../netns/ns_if.h"
52: #endif
53:
54: #include "../machine/cpu.h"
55: #include "../machine/pte.h"
56:
57: #include "../tahoe/mtpr.h"
58: #include "../tahoeif/if_acereg.h"
59: #include "../tahoevba/vbavar.h"
60:
61: int aceprobe(), aceattach(), acerint(), acecint();
62: struct vba_device *aceinfo[NACE];
63: long acestd[] = { 0 };
64: struct vba_driver acedriver =
65: { aceprobe, 0, aceattach, 0, acestd, "ace", aceinfo, "v/eiu", 0 };
66:
67: int aceinit(), aceoutput(), aceioctl(), acereset();
68: struct mbuf *aceget();
69:
70: /*
71: * Ethernet software status per interface.
72: *
73: * Each interface is referenced by a network interface structure,
74: * is_if, which the routing code uses to locate the interface.
75: * This structure contains the output queue for the interface, its address, ...
76: */
77: struct ace_softc {
78: struct arpcom is_ac; /* Ethernet common part */
79: #define is_if is_ac.ac_if /* network-visible interface */
80: #define is_addr is_ac.ac_enaddr /* hardware Ethernet address */
81: short is_flags;
82: #define ACEF_OACTIVE 0x1 /* output is active */
83: #define ACEF_RCVPENDING 0x2 /* start rcv in acecint */
84: short is_promiscuous; /* true is enabled */
85: short is_segboundry; /* first TX Seg in dpm */
86: short is_eictr; /* Rx segment tracking ctr */
87: short is_eoctr; /* Tx segment tracking ctr */
88: short is_txnext; /* Next available Tx segment */
89: short is_currnd; /* current random backoff */
90: struct ace_stats is_stats; /* holds board statistics */
91: short is_xcnt; /* count xmitted segments to be acked
92: by the controller */
93: long is_ivec; /* autoconfig interrupt vector base */
94: struct pte *is_map; /* pte map for dual ported memory */
95: caddr_t is_dpm; /* address of mapped memory */
96: } ace_softc[NACE];
97: extern struct ifnet loif;
98:
99: aceprobe(reg, vi)
100: caddr_t reg;
101: struct vba_device *vi;
102: {
103: register br, cvec; /* must be r12, r11 */
104: struct acedevice *ap = (struct acedevice *)reg;
105: struct ace_softc *is = &ace_softc[vi->ui_unit];
106:
107: #ifdef lint
108: br = 0; cvec = br; br = cvec;
109: acerint(0); acecint(0);
110: #endif
111: if (badaddr(reg, 2))
112: return (0);
113: movow(&ap->csr, CSR_RESET);
114: DELAY(10000);
115: #ifdef notdef
116: /*
117: * Select two spaces for the interrupts aligned to an
118: * eight vector boundary and fitting in 8 bits (as
119: * required by the controller) -- YECH. The controller
120: * will be notified later at initialization time.
121: */
122: if ((vi->ui_hd->vh_lastiv -= 2) > 0xff)
123: vi->ui_hd->vh_lastiv = 0x200;
124: is->is_ivec = vi->ui_hd->vh_lastiv = vi->ui_hd->vh_lastiv &~ 0x7;
125: #else
126: is->is_ivec = 0x90+vi->ui_unit*8;
127: #endif
128: br = 0x14, cvec = is->is_ivec; /* XXX */
129: return (sizeof (*ap));
130: }
131:
132: /*
133: * Interface exists: make available by filling in network interface
134: * record. System will initialize the interface when it is ready
135: * to accept packets.
136: */
137: aceattach(ui)
138: struct vba_device *ui;
139: {
140: register short unit = ui->ui_unit;
141: register struct ace_softc *is = &ace_softc[unit];
142: register struct ifnet *ifp = &is->is_if;
143: register struct acedevice *addr = (struct acedevice *)ui->ui_addr;
144: register short *wp, i;
145:
146: ifp->if_unit = unit;
147: ifp->if_name = "ace";
148: ifp->if_mtu = ETHERMTU;
149: /*
150: * Get station's addresses and set multicast hash table.
151: */
152: for (wp = (short *)addr->station, i = 0; i < 6; i++)
153: is->is_addr[i] = ~*wp++;
154: printf("ace%d: hardware address %s\n", unit,
155: ether_sprintf(is->is_addr));
156: is->is_promiscuous = 0;
157: for (wp = (short *)addr->hash, i = 0; i < 8; i++)
158: movow(wp++, ~0xf);
159: movow(&addr->bcastena[0], ~0xffff);
160: movow(&addr->bcastena[1], ~0xffff);
161: /*
162: * Allocate and map dual ported VERSAbus memory.
163: */
164: if (vbmemalloc(32, (caddr_t)ui->ui_flags,
165: &is->is_map, &is->is_dpm) == 0) {
166: printf("ace%d: can't allocate VERSAbus memory map\n", unit);
167: return;
168: }
169:
170: ifp->if_init = aceinit;
171: ifp->if_output = aceoutput;
172: ifp->if_ioctl = aceioctl;
173: ifp->if_reset = acereset;
174: ifp->if_flags = IFF_BROADCAST;
175: if_attach(ifp);
176: }
177:
178: /*
179: * Reset of interface after "system" reset.
180: */
181: acereset(unit, vban)
182: int unit, vban;
183: {
184: register struct vba_device *ui;
185:
186: if (unit >= NACE || (ui = aceinfo[unit]) == 0 || ui->ui_alive == 0 ||
187: ui->ui_vbanum != vban)
188: return;
189: printf(" ace%d", unit);
190: aceinit(unit);
191: }
192:
193: /*
194: * Initialization of interface; clear recorded pending operations
195: */
196: aceinit(unit)
197: int unit;
198: {
199: register struct ace_softc *is = &ace_softc[unit];
200: register struct vba_device *ui = aceinfo[unit];
201: register struct acedevice *addr;
202: register struct ifnet *ifp = &is->is_if;
203: register short Csr;
204: register int s;
205:
206: if (ifp->if_addrlist == (struct ifaddr *)0)
207: return;
208: if ((ifp->if_flags & IFF_RUNNING) == 0) {
209: /*
210: * Reset the controller, initialize the recieve buffers,
211: * and turn the controller on again and set board online.
212: */
213: addr = (struct acedevice *)ui->ui_addr;
214: s = splimp();
215: movow(&addr->csr, CSR_RESET);
216: DELAY(10000);
217:
218: /*
219: * Clean up dpm since the controller might
220: * jumble dpm after reset.
221: */
222: acesetup(unit);
223: movow(&addr->csr, CSR_GO);
224: Csr = addr->csr;
225: if (Csr & CSR_ACTIVE) {
226: movow(&addr->ivct, is->is_ivec);
227: Csr |= CSR_IENA | is->is_promiscuous;
228: movow(&addr->csr, Csr);
229: is->is_flags = 0;
230: is->is_xcnt = 0;
231: is->is_if.if_flags |= IFF_RUNNING;
232: }
233: splx(s);
234: }
235: if (is->is_if.if_snd.ifq_head)
236: acestart(unit);
237: }
238:
239: /*
240: * Start output on interface.
241: * Get another datagram to send off of the interface queue,
242: * and map it to the interface before starting the output.
243: */
244: acestart(unit)
245: int unit;
246: {
247: register struct tx_segment *txs;
248: register long len;
249: register int s;
250: register struct ace_softc *is = &ace_softc[unit];
251: struct mbuf *m;
252: short retries;
253:
254: if (is->is_flags & ACEF_OACTIVE)
255: return;
256: is->is_flags |= ACEF_OACTIVE;
257: again:
258: txs = (struct tx_segment*)(is->is_dpm + (is->is_txnext << 11));
259: if (txs->tx_csr & TCS_TBFULL) {
260: is->is_stats.tx_busy++;
261: is->is_flags &= ~ACEF_OACTIVE;
262: return;
263: }
264: s = splimp();
265: IF_DEQUEUE(&is->is_if.if_snd, m);
266: splx(s);
267: if (m == 0) {
268: is->is_flags &= ~ACEF_OACTIVE;
269: return;
270: }
271: len = aceput(unit, txs->tx_data, m);
272: retries = txs->tx_csr & TCS_RTC;
273: if (retries > 0)
274: acebakoff(is, txs, retries);
275:
276: /*
277: * Ensure minimum packet length.
278: * This makes the safe assumtion that there are no virtual holes
279: * after the data.
280: * For security, it might be wise to zero out the added bytes,
281: * but we're mainly interested in speed at the moment.
282: */
283: if (len - sizeof (struct ether_header) < ETHERMIN)
284: len = ETHERMIN + sizeof (struct ether_header);
285: if (++is->is_txnext > SEG_MAX)
286: is->is_txnext = is->is_segboundry;
287: is->is_if.if_opackets++;
288: is->is_xcnt++;
289: len = (len & 0x7fff) | TCS_TBFULL;
290: movow(txs, len);
291: goto again;
292: }
293:
294: /*
295: * Transmit done interrupt.
296: */
297: acecint(unit)
298: int unit;
299: {
300: register struct ace_softc *is = &ace_softc[unit];
301: register struct tx_segment *txseg;
302: short eostat;
303:
304: if (is->is_xcnt <= 0) {
305: log(LOG_ERR, "ace%d: stray xmit interrupt, xcnt %d\n",
306: unit, is->is_xcnt);
307: is->is_xcnt = 0;
308: if (is->is_if.if_snd.ifq_head)
309: acestart(unit);
310: return;
311: }
312: is->is_xcnt--;
313: txseg = (struct tx_segment *)((is->is_eoctr << 11) + is->is_dpm);
314: eostat = txseg->tx_csr;
315: if ((eostat & TCS_TBFULL) == 0) {
316: is->is_stats.tx_retries += eostat & TCS_RTC;
317: if (eostat & TCS_RTFAIL) {
318: is->is_stats.tx_discarded++;
319: is->is_if.if_oerrors++;
320: } else
321: is->is_stats.tx_datagrams++;
322: if (++is->is_eoctr >= 16)
323: is->is_eoctr = is->is_segboundry;
324: }
325: if (is->is_if.if_snd.ifq_head)
326: acestart(unit);
327: }
328:
329: /*
330: * Ethernet interface receiver interrupt.
331: * If input error just drop packet.
332: * Otherwise purge input buffered data path and examine
333: * packet to determine type. If can't determine length
334: * from type, then have to drop packet. Othewise decapsulate
335: * packet based on type and pass to type specific higher-level
336: * input routine.
337: */
338: acerint(unit)
339: int unit;
340: {
341: register struct ace_softc *is = &ace_softc[unit];
342: register struct ifqueue *inq;
343: register struct ether_header *ace;
344: register struct rx_segment *rxseg;
345: int len, s, off, resid;
346: struct mbuf *m;
347: short eistat;
348:
349: if ((is->is_if.if_flags&IFF_RUNNING) == 0)
350: return;
351: again:
352: rxseg = (struct rx_segment *)((is->is_eictr << 11) + is->is_dpm);
353: eistat = rxseg->rx_csr;
354: if ((eistat & RCS_RBFULL) == 0)
355: return;
356: is->is_if.if_ipackets++;
357: if (++is->is_eictr >= is->is_segboundry)
358: is->is_eictr = 0;
359: len = eistat & RCS_RBC;
360: if ((eistat & (RCS_ROVRN | RCS_RCRC | RCS_RODD)) ||
361: len < ET_MINLEN || len > ET_MAXLEN+CRC_SIZE) {
362: if (eistat & RCS_ROVRN)
363: is->is_stats.rx_overruns++;
364: if (eistat & RCS_RCRC)
365: is->is_stats.rx_crc_errors++;
366: if (eistat & RCS_RODD)
367: is->is_stats.rx_align_errors++;
368: if (len < ET_MINLEN)
369: is->is_stats.rx_underruns++;
370: if (len > ET_MAXLEN+CRC_SIZE)
371: is->is_stats.rx_overruns++;
372: is->is_if.if_ierrors++;
373: rxseg->rx_csr = 0;
374: return;
375: } else
376: is->is_stats.rx_datagrams++;
377: ace = (struct ether_header *)rxseg->rx_data;
378: len -= sizeof (struct ether_header);
379: /*
380: * Deal with trailer protocol: if type is trailer
381: * get true type from first 16-bit word past data.
382: * Remember that type was trailer by setting off.
383: */
384: ace->ether_type = ntohs((u_short)ace->ether_type);
385: #define acedataaddr(ace, off, type) \
386: ((type)(((caddr_t)(((char *)ace)+sizeof (struct ether_header))+(off))))
387: if (ace->ether_type >= ETHERTYPE_TRAIL &&
388: ace->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
389: off = (ace->ether_type - ETHERTYPE_TRAIL) * 512;
390: if (off >= ETHERMTU)
391: goto setup; /* sanity */
392: ace->ether_type = ntohs(*acedataaddr(ace, off, u_short *));
393: resid = ntohs(*(acedataaddr(ace, off+2, u_short *)));
394: if (off + resid > len)
395: goto setup; /* sanity */
396: len = off + resid;
397: } else
398: off = 0;
399: if (len == 0)
400: goto setup;
401:
402: /*
403: * Pull packet off interface. Off is nonzero if packet
404: * has trailing header; aceget will then force this header
405: * information to be at the front, but we still have to drop
406: * the type and length which are at the front of any trailer data.
407: */
408: m = aceget((u_char *)rxseg->rx_data, len, off, &is->is_if);
409: if (m == 0)
410: goto setup;
411: if (off) {
412: struct ifnet *ifp;
413:
414: ifp = *(mtod(m, struct ifnet **));
415: m->m_off += 2 * sizeof (u_short);
416: m->m_len -= 2 * sizeof (u_short);
417: *(mtod(m, struct ifnet **)) = ifp;
418: }
419: switch (ace->ether_type) {
420:
421: #ifdef INET
422: case ETHERTYPE_IP:
423: schednetisr(NETISR_IP);
424: inq = &ipintrq;
425: break;
426: #endif
427:
428: case ETHERTYPE_ARP:
429: arpinput(&is->is_ac, m);
430: goto setup;
431: #ifdef NS
432: case ETHERTYPE_NS:
433: schednetisr(NETISR_NS);
434: inq = &nsintrq;
435: break;
436:
437: #endif
438: default:
439: m_freem(m);
440: goto setup;
441: }
442: if (IF_QFULL(inq)) {
443: IF_DROP(inq);
444: m_freem(m);
445: goto setup;
446: }
447: s = splimp();
448: IF_ENQUEUE(inq, m);
449: splx(s);
450: setup:
451: rxseg->rx_csr = 0;
452: goto again;
453: }
454:
455: /*
456: * Ethernet output routine.
457: * Encapsulate a packet of type family for the local net.
458: * Use trailer local net encapsulation if enough data in first
459: * packet leaves a multiple of 512 bytes of data in remainder.
460: */
461: aceoutput(ifp, m0, dst)
462: struct ifnet *ifp;
463: struct mbuf *m0;
464: struct sockaddr *dst;
465: {
466: register struct ace_softc *is = &ace_softc[ifp->if_unit];
467: register struct mbuf *m = m0;
468: register struct ether_header *ace;
469: register int off;
470: struct mbuf *mcopy = (struct mbuf *)0;
471: int type, s, error, usetrailers;
472: u_char edst[6];
473: struct in_addr idst;
474:
475: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
476: error = ENETDOWN;
477: goto bad;
478: }
479: switch (dst->sa_family) {
480:
481: #ifdef INET
482: case AF_INET:
483: idst = ((struct sockaddr_in *)dst)->sin_addr;
484: if (!arpresolve(&is->is_ac, m, &idst, edst, &usetrailers))
485: return (0); /* if not yet resolved */
486: if (!bcmp((caddr_t)edst, (caddr_t)etherbroadcastaddr,
487: sizeof (edst)))
488: mcopy = m_copy(m, 0, (int)M_COPYALL);
489: off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
490: if (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
491: m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
492: type = ETHERTYPE_TRAIL + (off>>9);
493: m->m_off -= 2 * sizeof (u_short);
494: m->m_len += 2 * sizeof (u_short);
495: *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP);
496: *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
497: goto gottrailertype;
498: }
499: type = ETHERTYPE_IP;
500: off = 0;
501: goto gottype;
502: #endif
503: #ifdef NS
504: case AF_NS:
505: bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
506: (caddr_t)edst, sizeof (edst));
507: if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost,sizeof(edst)))
508: mcopy = m_copy(m, 0, (int)M_COPYALL);
509: else if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost,
510: sizeof(edst)))
511: return(looutput(&loif, m, dst));
512: type = ETHERTYPE_NS;
513: off = 0;
514: goto gottype;
515: #endif
516: case AF_UNSPEC:
517: ace = (struct ether_header *)dst->sa_data;
518: bcopy((caddr_t)ace->ether_dhost, (caddr_t)edst, sizeof (edst));
519: type = ace->ether_type;
520: goto gottype;
521:
522: default:
523: log(LOG_ERR, "ace%d: can't handle af%d\n",
524: ifp->if_unit, dst->sa_family);
525: error = EAFNOSUPPORT;
526: goto bad;
527: }
528:
529: gottrailertype:
530: /*
531: * Packet to be sent as trailer: move first packet
532: * (control information) to end of chain.
533: */
534: while (m->m_next)
535: m = m->m_next;
536: m->m_next = m0;
537: m = m0->m_next;
538: m0->m_next = 0;
539: m0 = m;
540:
541: gottype:
542: /*
543: * Add local net header. If no space in first mbuf,
544: * allocate another.
545: */
546: if (m->m_off > MMAXOFF ||
547: MMINOFF + sizeof (struct ether_header) > m->m_off) {
548: m = m_get(M_DONTWAIT, MT_HEADER);
549: if (m == 0) {
550: error = ENOBUFS;
551: goto bad;
552: }
553: m->m_next = m0;
554: m->m_off = MMINOFF;
555: m->m_len = sizeof (struct ether_header);
556: } else {
557: m->m_off -= sizeof (struct ether_header);
558: m->m_len += sizeof (struct ether_header);
559: }
560: ace = mtod(m, struct ether_header *);
561: bcopy((caddr_t)edst, (caddr_t)ace->ether_dhost, sizeof (edst));
562: bcopy((caddr_t)is->is_addr, (caddr_t)ace->ether_shost,
563: sizeof (is->is_addr));
564: ace->ether_type = htons((u_short)type);
565:
566: /*
567: * Queue message on interface, and start output if interface
568: * not yet active.
569: */
570: s = splimp();
571: if (IF_QFULL(&ifp->if_snd)) {
572: IF_DROP(&ifp->if_snd);
573: error = ENOBUFS;
574: goto qfull;
575: }
576: IF_ENQUEUE(&ifp->if_snd, m);
577: splx(s);
578: acestart(ifp->if_unit);
579: return (mcopy ? looutput(&loif, mcopy, dst) : 0);
580: qfull:
581: m0 = m;
582: splx(s);
583: bad:
584: m_freem(m0);
585: if (mcopy)
586: m_freem(mcopy);
587: return (error);
588: }
589:
590: /*
591: * Routine to copy from mbuf chain to transmit buffer on the VERSAbus
592: * If packet size is less than the minimum legal size,
593: * the buffer is expanded. We probably should zero out the extra
594: * bytes for security, but that would slow things down.
595: */
596: /*ARGSUSED*/
597: aceput(unit, txbuf, m)
598: int unit;
599: char *txbuf;
600: struct mbuf *m;
601: {
602: register u_char *bp, *mcp;
603: register short *s1, *s2;
604: register u_int len;
605: register struct mbuf *mp;
606: int total;
607:
608: total = 0;
609: bp = (u_char *)txbuf;
610: for (mp = m; (mp); mp = mp->m_next) {
611: len = mp->m_len;
612: if (len == 0)
613: continue;
614: total += len;
615: mcp = mtod(mp, u_char *);
616: if (((int)mcp & 01) && ((int)bp & 01)) {
617: /* source & destination at odd addresses */
618: movob(bp++, *mcp++);
619: --len;
620: }
621: if (len > 1 && (((int)mcp & 01)==0) && (((int)bp & 01)==0)) {
622: register u_int l;
623:
624: s1 = (short *)bp;
625: s2 = (short *)mcp;
626: l = len >> 1; /* count # of shorts */
627: while (l-- != 0)
628: movow(s1++, *s2++);
629: len &= 1; /* # remaining bytes */
630: bp = (u_char *)s1;
631: mcp = (u_char *)s2;
632: }
633: while (len-- != 0)
634: movob(bp++, *mcp++);
635: }
636: m_freem(m);
637: return (total);
638: }
639:
640: /*
641: * Routine to copy from VERSAbus memory into mbufs.
642: *
643: * Warning: This makes the fairly safe assumption that
644: * mbufs have even lengths.
645: */
646: /*ARGSUSED*/
647: struct mbuf *
648: aceget(rxbuf, totlen, off0, ifp)
649: u_char *rxbuf;
650: int totlen, off0;
651: struct ifnet *ifp;
652: {
653: register u_char *cp, *mcp;
654: register int tlen;
655: register struct mbuf *m;
656: struct mbuf *top = 0, **mp = ⊤
657: int len, off = off0;
658:
659: cp = rxbuf + sizeof (struct ether_header);
660: while (totlen > 0) {
661: MGET(m, M_DONTWAIT, MT_DATA);
662: if (m == 0)
663: goto bad;
664: if (off) {
665: len = totlen - off;
666: cp = rxbuf + sizeof (struct ether_header) + off;
667: } else
668: len = totlen;
669: if (ifp)
670: len += sizeof(ifp);
671: if (len >= NBPG) {
672: MCLGET(m);
673: if (m->m_len == CLBYTES)
674: m->m_len = len = MIN(len, CLBYTES);
675: else
676: m->m_len = len = MIN(MLEN, len);
677: } else {
678: m->m_len = len = MIN(MLEN, len);
679: m->m_off = MMINOFF;
680: }
681: mcp = mtod(m, u_char *);
682: if (ifp) {
683: /*
684: * Prepend interface pointer to first mbuf.
685: */
686: *(mtod(m, struct ifnet **)) = ifp;
687: mcp += sizeof(ifp);
688: len -= sizeof(ifp);
689: ifp = (struct ifnet *)0;
690: }
691: /*bcopy((caddr_t)cp, (caddr_t)mcp, len);*/
692: /*cp += len; mcp += len;*/
693: tlen = len;
694: if (((int)mcp & 01) && ((int)cp & 01)) {
695: /* source & destination at odd addresses */
696: *mcp++ = *cp++;
697: --tlen;
698: }
699: if (tlen > 1 && (((int)mcp&01) == 0) && (((int)cp&01) == 0)) {
700: register short *s1, *s2;
701: register int l;
702:
703: s1 = (short *)mcp;
704: s2 = (short *)cp;
705: l = tlen >> 1; /* count # of shorts */
706: while (l-- > 0) /* copy shorts */
707: *s1++ = *s2++;
708: tlen &= 1; /* # remaining bytes */
709: mcp = (u_char *)s1;
710: cp = (u_char *)s2;
711: }
712: while (tlen-- > 0)
713: *mcp++ = *cp++;
714: *mp = m;
715: mp = &m->m_next;
716: if (off == 0) {
717: totlen -= len;
718: continue;
719: }
720: off += len;
721: if (off == totlen) {
722: cp = rxbuf + sizeof (struct ether_header);
723: off = 0;
724: totlen = off0;
725: }
726: }
727: return (top);
728: bad:
729: m_freem(top);
730: return (0);
731: }
732:
733: /* backoff table masks */
734: short random_mask_tbl[16] = {
735: 0x0040, 0x00c0, 0x01c0, 0x03c0, 0x07c0, 0x0fc0, 0x1fc0, 0x3fc0,
736: 0x7fc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0
737: };
738:
739: acebakoff(is, txseg, retries)
740: struct ace_softc *is;
741: struct tx_segment *txseg;
742: register int retries;
743: {
744: register short *pBakNum, random_num;
745: short *pMask;
746:
747: pMask = &random_mask_tbl[0];
748: pBakNum = &txseg->tx_backoff[0];
749: while (--retries >= 0) {
750: random_num = (is->is_currnd = (is->is_currnd * 18741)-13849);
751: random_num &= *pMask++;
752: *pBakNum++ = random_num ^ (short)(0xff00 | 0x00fc);
753: }
754: }
755:
756: /*
757: * Process an ioctl request.
758: */
759: aceioctl(ifp, cmd, data)
760: register struct ifnet *ifp;
761: int cmd;
762: caddr_t data;
763: {
764: register struct ifaddr *ifa = (struct ifaddr *)data;
765: struct acedevice *addr;
766: int s = splimp(), error = 0;
767:
768: switch (cmd) {
769:
770: case SIOCSIFADDR:
771: ifp->if_flags |= IFF_UP;
772: switch (ifa->ifa_addr.sa_family) {
773: #ifdef INET
774: case AF_INET:
775: aceinit(ifp->if_unit); /* before arpwhohas */
776: ((struct arpcom *)ifp)->ac_ipaddr =
777: IA_SIN(ifa)->sin_addr;
778: arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
779: break;
780: #endif
781: #ifdef NS
782: case AF_NS: {
783: struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
784: struct ace_softc *is = &ace_softc[ifp->if_unit];
785:
786: if (!ns_nullhost(*ina)) {
787: ifp->if_flags &= ~IFF_RUNNING;
788: addr = (struct acedevice *)
789: aceinfo[ifp->if_unit]->ui_addr;
790: movow(&addr->csr, CSR_RESET);
791: DELAY(10000);
792: /* set station address & copy addr to arp */
793: acesetaddr(ifp->if_unit, addr,
794: ina->x_host.c_host);
795: } else
796: ina->x_host = *(union ns_host *)is->is_addr;
797: aceinit(ifp->if_unit);
798: break;
799: }
800: #endif
801: default:
802: aceinit(ifp->if_unit);
803: break;
804: }
805: break;
806:
807: case SIOCSIFFLAGS:
808: if ((ifp->if_flags&IFF_UP) == 0 && ifp->if_flags&IFF_RUNNING) {
809: addr = (struct acedevice *)
810: (aceinfo[ifp->if_unit]->ui_addr);
811: movow(&addr->csr, CSR_RESET);
812: ifp->if_flags &= ~IFF_RUNNING;
813: } else if (ifp->if_flags&IFF_UP &&
814: (ifp->if_flags&IFF_RUNNING) == 0)
815: aceinit(ifp->if_unit);
816: break;
817:
818: default:
819: error = EINVAL;
820: }
821: splx(s);
822: return (error);
823: }
824:
825: /*
826: * Set the on-board station address, then read it back
827: * to initialize the address used by ARP (among others).
828: */
829: acesetaddr(unit, addr, station)
830: short unit;
831: struct acedevice *addr;
832: u_char *station;
833: {
834: struct ace_softc *is = &ace_softc[unit];
835: register short *wp, i;
836:
837: for (wp = (short *)addr->station, i = 0; i < 6; i++)
838: movow(wp++, ~*station++);
839: for (wp = (short *)addr->station, i = 0; i < 6; i++)
840: is->is_addr[i] = ~*wp++;
841: printf("ace%d: hardware address %s\n", unit,
842: ether_sprintf(is->is_addr));
843: }
844:
845: /*
846: * Setup the device for use. Initialize dual-ported memory,
847: * backoff parameters, and various other software state.
848: */
849: acesetup(unit)
850: int unit;
851: {
852: register struct ace_softc *is = &ace_softc[unit];
853: register char *pData1;
854: register short i;
855: struct acedevice *addr;
856:
857: bzero(is->is_dpm, 16384*2);
858: is->is_currnd = 49123;
859: addr = (struct acedevice *)aceinfo[unit]->ui_addr;
860: is->is_segboundry = (addr->segb >> 11) & 0xf;
861: pData1 = is->is_dpm + (is->is_segboundry << 11);
862: for (i = SEG_MAX + 1 - is->is_segboundry; --i >= 0;) {
863: acebakoff(is, (struct tx_segment *)pData1, 15);
864: pData1 += sizeof (struct tx_segment);
865: }
866: is->is_eictr = 0;
867: is->is_eoctr = is->is_txnext = is->is_segboundry;
868: bzero((char *)&is->is_stats, sizeof (is->is_stats));
869: }
870: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.