|
|
1.1 root 1: /* */
2: /* if_ace: ACC VERSAbus Ethernet controler (v/eiu) */
3: /* */
4:
5: #include "ace.h"
6: #define ACEBPTE 64
7: #if NACE > 0
8: #define ACEDEBUG
9:
10: #include "../machine/pte.h"
11:
12: #include "../h/param.h"
13: #include "../h/systm.h"
14: #include "../h/mbuf.h"
15: #include "../h/buf.h"
16: #include "../h/protosw.h"
17: #include "../h/socket.h"
18: #include "../h/vmmac.h"
19: #include "../h/ioctl.h"
20: #include "../h/errno.h"
21:
22: #include "../net/if.h"
23: #define LONET 127
24: #include "../net/netisr.h"
25: #include "../net/route.h"
26: #include "../netinet/in.h"
27: #include "../netinet/in_systm.h"
28: #include "../netinet/ip.h"
29: #include "../netinet/ip_var.h"
30: #include "../netinet/if_ether.h"
31: #include "../netpup/pup.h"
32:
33: #include "../machine/mtpr.h"
34: #include "../tahoeif/if_ace.h"
35: #include "../tahoeif/if_acereg.h"
36: #define LOHOST 2 /* no conflict with loop */
37: #include "../vba/vbavar.h"
38: #define TRUE 1
39: #define FALSE 0
40:
41: /* configuration table, for 2 units */
42: /* should be defined by config */
43: #define ACEVECTOR 0x90
44: long acestd[] = { 0x0ff0000, 0xff0100 }; /* controller */
45: extern char ace0utl[], ace1utl[]; /* dpm */
46: char *acemap[]= { ace0utl, ace1utl };
47: extern long ACE0map[], ACE1map[];
48: long *ACEmap[] = {ACE0map, ACE1map };
49: long ACEmapa[] = {0xff780000,0xff790000};
50: char ace_station[6*NACE] = { /* addresses */
51: ~0x8,~0x0,~0x3,~0x0,~0x0,~0x1,
52: #if (NACE > 1)
53: ~0x8,~0x0,~0x3,~0x0,~0x0,~0x2,
54: #if (NACE > 2)
55: ~0x8,~0x0,~0x3,~0x0,~0x0,~0x3,
56: ~0x8,~0x0,~0x3,~0x0,~0x0,~0x4,
57: #endif (NACE > 2)
58: #endif (NACE > 1)
59: };
60:
61: char ace_hash_code[8*NACE]={ /* hash tables */
62: ~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,/*u 0*/
63: #if (NACE > 1)
64: ~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,/*u 1*/
65: #if (NACE > 2)
66: ~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,/*u 2*/
67: ~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF /*u 3*/
68: #endif (NACE > 2)
69: #endif (NACE > 1)
70: };
71:
72: short random_mask_tbl[16] = { /* backoff table*/
73: 0x0040, 0x00C0, 0x01C0, 0x03C0,
74: 0x07C0, 0x0FC0, 0x1FC0, 0x3FC0,
75: 0x7FC0, 0xFFC0, 0xFFC0, 0xFFC0,
76: 0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0 };
77:
78: int aceprobe(), aceattach(), acerint(), acecint();
79: struct vba_device *aceinfo[NACE];
80: struct vba_driver acedriver =
81: { aceprobe, 0,aceattach,0,acestd,"ace",aceinfo,"v/eiu",0 };
82:
83: #define ACEUNIT(x) minor(x)
84: int aceinit(),aceoutput(),aceioctl(),acereset();
85: struct mbuf *aceget();
86:
87: /*
88: * Ethernet software status per interface.
89: *
90: * Each interface is referenced by a network interface structure,
91: * is_if, which the routing code uses to locate the interface.
92: * This structure contains the output queue for the interface, its address, ...
93: */
94: struct ace_softc {
95: struct arpcom is_ac; /* Ethernet common part */
96: #define is_if is_ac.ac_if /* network-visible interface */
97: #define is_addr is_ac.ac_enaddr /* hardware Ethernet address */
98: char *is_dpm;
99: short is_flags;
100: #define ACEF_OACTIVE 0x1 /* output is active */
101: #define ACEF_RCVPENDING 0x2 /* start rcv in acecint */
102: short is_promiscuous; /* true is enabled */
103: short is_segboundry; /* first TX Seg in dpm */
104: short is_eictr; /* Rx segment tracking ctr */
105: short is_eoctr; /* Tx segment tracking ctr */
106: short is_txnext; /* Next available Tx segment */
107: short is_currnd; /* current random backoff */
108: struct ace_stats is_stats; /* holds board statistics */
109: } ace_softc[NACE];
110:
111: aceprobe(reg)
112: caddr_t reg;
113: {
114: register struct acedevice *addr = (struct acedevice *)reg;
115: register i;
116: #ifdef ACEDEBUG
117: printf("aceprobe: veiu @%X\n",reg);
118: #endif ACEDEBUG
119:
120: #ifdef lint
121: i = 0; acerint(i); acecint(i);
122: #endif
123:
124: if (badaddr(reg,2)) return(0);
125: addr->csr = CSR_RESET;
126: DELAY(10000);
127: return (1);
128:
129: }
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 *pData0,i;
145: register char *pData1;
146: struct sockaddr_in *sin;
147: #ifdef ACEDEBUG
148: printf("ace%dattach: ui %X\n",unit,ui);
149: #endif ACEDEBUG
150:
151: ifp->if_unit = unit;
152: ifp->if_name = "ace";
153: ifp->if_mtu = ETHERMTU;
154:
155: /*
156: * Reset the board and map the statistics
157: * buffer onto the Unibus.
158: */
159: addr->csr = CSR_RESET;
160: /* set the station address */
161: for (pData0 = (short *)addr->rar.station_addr,
162: pData1 = &ace_station[unit * 6], i = 6;
163: --i >= 0;)
164: *(pData0++) = *(pData1++);
165: /* Copy to arp structure */
166: for (pData0 = (short *)addr->rar.station_addr,
167: pData1 = (char *)(is->is_addr), i = 6;
168: --i >= 0;)
169: *(pData1++) = ~(*(pData0++));
170: #ifdef ACEDEBUG
171: printf("ace%d: addr=%x:%x:%x:%x:%x:%x\n",
172: unit,
173: is->is_addr[0]&0xff, is->is_addr[1]&0xff,
174: is->is_addr[2]&0xff, is->is_addr[3]&0xff,
175: is->is_addr[4]&0xff, is->is_addr[5]&0xff);
176: #endif ACEDEBUG
177:
178: is->is_promiscuous = (TRUE)? CSR_PROMISCUOUS: 0;
179: for (pData0 = (short *)addr->rar.mcast_hash_code,
180: pData1 = &ace_hash_code[unit * 8], i = 8;
181: --i >= 0;)
182: *(pData0++) = *(pData1++);
183:
184: addr->rar.broadcast_en[0] = ~0xffff;
185: addr->rar.broadcast_en[1] = ~0xffff;
186:
187: is->is_dpm = acemap[unit];
188: ioaccess(ACEmap[unit],ACEmapa[unit],ACEBPTE);
189: for (pData0 = (short *)is->is_dpm, i = 16384; --i >= 0;)
190: *(pData0++) = 0;
191:
192: is->is_segboundry = 8;
193: for (pData1 = (char*)((int)is->is_dpm + (is->is_segboundry << 11)),
194: i = (SEG_MAX + 1) - is->is_segboundry;
195: (--i >= 0);
196: pData1 += sizeof (struct tx_segment))
197: {
198: ((struct tx_segment*)pData1)->tx_csr = 15;
199: }
200:
201: is->is_eictr = 0;
202: is->is_eoctr = is->is_txnext = is->is_segboundry;
203: is->is_currnd = 49123;
204: for (pData1 = (char *)&is->is_stats,i = sizeof (struct ace_stats);
205: (--i != 0);)
206: *(pData1++) = 0;
207:
208: sin = (struct sockaddr_in *)&ifp->if_addr;
209: sin->sin_family = AF_INET;
210: sin->sin_addr = arpmyaddr((struct arpcom *)0);
211: ifp->if_init = aceinit;
212: ifp->if_output = aceoutput;
213: ifp->if_ioctl = aceioctl;
214: ifp->if_reset = acereset;
215: if_attach(ifp);
216: #ifdef ACEDEBUG
217: printf("aceattach: ifattach complete\n");
218: #endif ACEDEBUG
219: }
220:
221: /*
222: * Reset of interface after "system" reset.
223: */
224: acereset(unit, vban)
225: int unit, vban;
226: {
227: register struct vba_device *ui;
228: #ifdef ACEDEBUG
229: printf("ace%dreset:\n",unit,vban);
230: #endif ACEDEBUG
231:
232: if (unit >= NACE || (ui = aceinfo[unit]) == 0 || ui->ui_alive == 0 ||
233: ui->ui_vbanum != vban)
234: return;
235: printf(" ace%d", unit);
236: aceinit(unit);
237: }
238:
239: /*
240: * Initialization of interface; clear recorded pending operations
241: */
242: aceinit(unit)
243: int unit;
244: {
245: register struct ace_softc *is = &ace_softc[unit];
246: register struct vba_device *ui = aceinfo[unit];
247: register struct acedevice *addr;
248: register struct ifnet *ifp = &is->is_if;
249: register struct sockaddr_in *sin;
250: register int i,s;
251: #ifdef ACEDEBUG
252: printf("ace%dinit:\n",unit);
253: #endif ACEDEBUG
254:
255: sin = (struct sockaddr_in *)&ifp->if_addr;
256: if (sin->sin_addr.s_addr == 0) /* address still unknown */
257: {
258: #ifdef ACEDEBUG
259: printf("ace%dinit: no address assigned\n",unit);
260: #endif ACEDEBUG
261: return;
262: }
263:
264: if (!(ifp->if_flags & IFF_RUNNING))
265: {
266:
267: /*
268: * Reset the controller, initialize the recieve buffers,
269: * and turn the controller on again and set board online.
270: */
271: addr = (struct acedevice *)ui->ui_addr;
272: s = splimp();
273: addr->csr = CSR_GO;
274:
275: if (addr->csr & CSR_ACTIVE)
276: {
277: addr->ivct = ACEVECTOR + (unit*8);
278: addr->csr |= CSR_ENINT | is->is_promiscuous;
279: if (ifp->if_net == LONET)
280: addr->csr |= (CSR_LOOP3);
281: is->is_flags = ACEF_OACTIVE;
282: is->is_if.if_flags |= IFF_UP|IFF_RUNNING;
283: #ifdef ACEDEBUG
284: printf("aceinit: csr %x, segb %x, tseg %x, rseg %x\n",
285: (addr->csr & 0xffff),
286: ((addr->segb >> 11) & 0xf),
287: ((addr->tseg >> 11) & 0xf),
288: ((addr->rseg >> 11) & 0xf));
289: #endif ACEDEBUG
290: acecint(unit);
291: }
292: #ifdef ACEDEBUG
293: else
294: {
295: printf("ace%dinit: would not go active\n",unit);
296: }
297: #endif ACEDEBUG
298: splx(s);
299: }
300: if_rtinit(&is->is_if, RTF_UP);
301: arpattach(&is->is_ac);
302: arpwhohas(&is->is_ac, &sin->sin_addr);
303: }
304:
305: /*
306: * Start output on interface.
307: * Get another datagram to send off of the interface queue,
308: * and map it to the interface before starting the output.
309: */
310: acestart(dev)
311: dev_t dev;
312: {
313: int unit = ACEUNIT(dev), len;
314: struct vba_device *ui = aceinfo[unit];
315: register struct ace_softc *is = &ace_softc[unit];
316: register struct tx_segment *txs;
317: struct mbuf *m;
318: short retries,idx;
319: #ifdef ACEDEBUG
320: printf("ace%dstart: dev %X, tx seg %x\n",unit,dev,is->is_txnext);
321: #endif ACEDEBUG
322:
323: txs = (struct tx_segment*)(is->is_dpm + (is->is_txnext << 11));
324: if (txs->tx_csr & TCS_TBFULL) return;
325: IF_DEQUEUE(&is->is_if.if_snd, m);
326: if (m == 0)
327: {
328: if (TRUE) return;
329: }
330: len = aceput(txs->tx_data, m);
331: #ifdef ACEDEBUG
332: printf("sending[");
333: for (idx = 0;(idx < len);idx++)
334: {
335: printf("%x ",txs->tx_data[idx] & 0xff);
336: }
337: printf("]\n");
338: #endif ACEDEBUG
339: retries = (txs->tx_csr & TCS_RTC);
340: acebakoff(is,txs,retries);
341: /*
342: * Ensure minimum packet length.
343: * This makes the safe assumtion that there are no virtual holes
344: * after the data.
345: * For security, it might be wise to zero out the added bytes,
346: * but we're mainly interested in speed at the moment.
347: */
348: if (len - sizeof(struct ether_header) < ETHERMIN)
349: len = ETHERMIN + sizeof(struct ether_header);
350: if ((is->is_txnext += 1) > SEG_MAX)
351: is->is_txnext = is->is_segboundry;
352: txs->tx_csr = (TCS_TBFULL|len);
353: is->is_if.if_opackets++;
354: #ifdef ACEDEBUG
355: printf("sending %x bytes,retries fixed %x\n",
356: (txs->tx_csr & 0xffff),retries);
357: #endif ACEDEBUG
358: is->is_flags |= ACEF_OACTIVE;
359: }
360:
361: /*
362: * Command done interrupt.
363: */
364: acecint(unit)
365: int unit;
366: {
367: register struct ace_softc *is = &ace_softc[unit];
368: struct vba_device *ui = aceinfo[unit];
369: register struct acedevice *addr = (struct acedevice *)ui->ui_addr;
370: register struct tx_segment *txseg; /* ptr to V/EIU tx seg */
371: short eostat;
372: #ifdef ACEDEBUG
373: printf("ace%dcint: \n",unit);
374: #endif ACEDEBUG
375:
376: if ((is->is_flags & ACEF_OACTIVE) == 0)
377: {
378: printf("ace%dcint: stray xmit interrupt\n", unit);
379: return;
380: }
381:
382: is->is_flags &= ~ACEF_OACTIVE;
383: txseg = (struct tx_segment *)((is->is_eoctr << 11) + is->is_dpm);
384: if (((eostat = txseg->tx_csr) & TCS_TBFULL) == 0)
385: {
386: is->is_stats.tx_retries += (eostat & TCS_RTC);
387: if (eostat & TCS_RTFAIL)
388: {
389: is->is_stats.tx_discarded++;
390: is->is_if.if_oerrors++;
391: }
392: else
393: is->is_stats.tx_datagrams++;
394: if (++is->is_eoctr >= 16)
395: is->is_eoctr = is->is_segboundry;
396: }
397: #ifdef ACEDEBUG
398: else
399: {
400: printf("ace%dcint: tx segment %X busy\n",unit,is->is_eoctr);
401: }
402: #endif ACEDEBUG
403: acestart(unit);
404: }
405:
406: /*
407: * Ethernet interface receiver interrupt.
408: * If input error just drop packet.
409: * Otherwise purge input buffered data path and examine
410: * packet to determine type. If can't determine length
411: * from type, then have to drop packet. Othewise decapsulate
412: * packet based on type and pass to type specific higher-level
413: * input routine.
414: */
415: acerint(unit)
416: int unit;
417: {
418: register struct ace_softc *is = &ace_softc[unit];
419: struct acedevice *addr = (struct acedevice *)aceinfo[unit]->ui_addr;
420: register struct ifqueue *inq;
421: register struct ace_rheader *ace;
422: register struct rx_segment *rxseg; /* ptr to V/EIU rx seg */
423: short eistat;
424: struct mbuf *m;
425: int len, off, resid;
426: #ifdef ACEDEBUG
427: printf("ace%xrint: rxseg %x\n",unit,is->is_eictr);
428: #endif ACEDEBUG
429:
430: is->is_if.if_ipackets++;
431: rxseg = (struct rx_segment *)((is->is_eictr << 11) + is->is_dpm);
432: if (++is->is_eictr >= is->is_segboundry)
433: is->is_eictr = 0;
434: #ifdef ACEDEBUG
435: printf("[(%x)",(rxseg->rx_csr & 0xffff));
436: for (off = 0;(off < 64);off++)
437: {
438: printf("%x ",rxseg->rx_data[off] & 0xff);
439: }
440: printf("]\n");
441: #endif ACEDEBUG
442: if ((eistat = rxseg->rx_csr) & RCS_RBFULL)
443: {
444: len = (eistat & RCS_RBC);
445: if ((eistat & (RCS_ROVRN | RCS_RCRC | RCS_RODD)) ||
446: (len < ET_MINLEN) || (len > (ET_MAXLEN+CRC_SIZE)))
447: {
448: if (eistat & RCS_ROVRN) is->is_stats.rx_overruns++;
449: if (eistat & RCS_RCRC) is->is_stats.rx_crc_errors++;
450: if (eistat & RCS_RODD) is->is_stats.rx_align_errors++;
451: if (len < ET_MINLEN) is->is_stats.rx_underruns++;
452: if (len > (ET_MAXLEN+CRC_SIZE)) is->is_stats.rx_overruns++;
453: is->is_if.if_ierrors++;
454: #ifdef ACEDEBUG
455: if (is->is_if.if_ierrors % 100 == 0)
456: printf("ace%d: += 100 input errors\n", unit);
457: #endif
458: rxseg->rx_csr = 0;
459: return;
460: }
461: else
462: {
463: is->is_stats.rx_datagrams++;
464: }
465: }
466: #ifdef ACEDEBUG
467: else
468: {
469: printf("ace%d: stray recv interrupt\n", unit);
470: return;
471: }
472: #endif ACEDEBUG
473: ace = (struct ace_rheader *)(rxseg->rx_data);
474: len = ace->acer_length - sizeof(struct ace_rheader);
475:
476: /*
477: * Deal with trailer protocol: if type is PUP trailer
478: * get true type from first 16-bit word past data.
479: * Remember that type was trailer by setting off.
480: */
481: ace->acer_type = ntohs((u_short)ace->acer_type);
482: #define acedataaddr(ace, off, type) ((type)(((caddr_t)((ace)+1)+(off))))
483: if (ace->acer_type >= ETHERPUP_TRAIL &&
484: ace->acer_type < ETHERPUP_TRAIL+ETHERPUP_NTRAILER) {
485: off = (ace->acer_type - ETHERPUP_TRAIL) * 512;
486: if (off >= ETHERMTU)
487: goto setup; /* sanity */
488: ace->acer_type = ntohs(*acedataaddr(ace, off, u_short *));
489: resid = ntohs(*(acedataaddr(ace, off+2, u_short *)));
490: if (off + resid > len)
491: goto setup; /* sanity */
492: len = off + resid;
493: } else
494: off = 0;
495: if (len == 0)
496: goto setup;
497:
498: /*
499: * Pull packet off interface. Off is nonzero if packet
500: * has trailing header; aceget will then force this header
501: * information to be at the front, but we still have to drop
502: * the type and length which are at the front of any trailer data.
503: */
504: m = aceget(rxseg->rx_data, len, off);
505: if (m == 0)
506: goto setup;
507: if (off) {
508: m->m_off += 2 * sizeof (u_short);
509: m->m_len -= 2 * sizeof (u_short);
510: }
511: switch (ace->acer_type) {
512:
513: #ifdef INET
514: case ETHERPUP_IPTYPE:
515: schednetisr(NETISR_IP);
516: inq = &ipintrq;
517: break;
518:
519: case ETHERPUP_ARPTYPE:
520: arpinput(&is->is_ac, m);
521: goto setup;
522: #endif
523: default:
524: m_freem(m);
525: goto setup;
526: }
527:
528: if (IF_QFULL(inq)) {
529: IF_DROP(inq);
530: m_freem(m);
531: goto setup;
532: }
533: IF_ENQUEUE(inq, m);
534:
535: setup:
536: rxseg->rx_csr = 0;
537: }
538:
539: /*
540: * Ethernet output routine.
541: * Encapsulate a packet of type family for the local net.
542: * Use trailer local net encapsulation if enough data in first
543: * packet leaves a multiple of 512 bytes of data in remainder.
544: */
545: aceoutput(ifp, m0, dst)
546: struct ifnet *ifp;
547: struct mbuf *m0;
548: struct sockaddr *dst;
549: {
550: register short unit = ifp->if_unit;
551: register struct ace_softc *is = &ace_softc[unit];
552: register struct mbuf *m = m0;
553: register struct ether_header *ace;
554: register int off;
555: int type, s, error;
556: u_char edst[6];
557: struct in_addr idst;
558: #ifdef ACEDEBUG
559: printf("ace%doutput: ifp %X, m0 %X, dst %X\n",unit,ifp,m0,dst);
560: #endif ACEDEBUG
561:
562: switch (dst->sa_family) {
563:
564: #ifdef INET
565: case AF_INET:
566: idst = ((struct sockaddr_in *)dst)->sin_addr;
567: if (!arpresolve(&is->is_ac, m, &idst, edst))
568: return (0); /* if not yet resolved */
569: off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
570: /* need per host negotiation */
571: if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
572: if (off > 0 && (off & 0x1ff) == 0 &&
573: m->m_off >= MMINOFF + 2 * sizeof (u_short))
574: {
575: type = ETHERPUP_TRAIL + (off>>9);
576: m->m_off -= 2 * sizeof (u_short);
577: m->m_len += 2 * sizeof (u_short);
578: *mtod(m, u_short *) = htons((u_short)ETHERPUP_IPTYPE);
579: *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
580: goto gottrailertype;
581: }
582: type = ETHERPUP_IPTYPE;
583: off = 0;
584: goto gottype;
585: #endif
586:
587: case AF_UNSPEC:
588: ace = (struct ether_header *)dst->sa_data;
589: bcopy((caddr_t)ace->ether_dhost, (caddr_t)edst, sizeof (edst));
590: type = ace->ether_type;
591: goto gottype;
592:
593: default:
594: printf("ace%d: can't handle af%d\n", unit,dst->sa_family);
595: error = EAFNOSUPPORT;
596: goto bad;
597: }
598:
599: gottrailertype:
600: /*
601: * Packet to be sent as trailer: move first packet
602: * (control information) to end of chain.
603: */
604: while (m->m_next)
605: m = m->m_next;
606: m->m_next = m0;
607: m = m0->m_next;
608: m0->m_next = 0;
609: m0 = m;
610:
611: gottype:
612: /*
613: * Add local net header. If no space in first mbuf,
614: * allocate another.
615: */
616: if (m->m_off > MMAXOFF ||
617: MMINOFF + sizeof (struct ether_header) > m->m_off) {
618: m = m_get(M_DONTWAIT, MT_HEADER);
619: if (m == 0) {
620: error = ENOBUFS;
621: goto bad;
622: }
623: m->m_next = m0;
624: m->m_off = MMINOFF;
625: m->m_len = sizeof (struct ether_header);
626: } else {
627: m->m_off -= sizeof (struct ether_header);
628: m->m_len += sizeof (struct ether_header);
629: }
630: ace = mtod(m, struct ether_header *);
631: ace->ether_type = htons((u_short)type);
632: bcopy((caddr_t)edst, (caddr_t)ace->ether_dhost, sizeof (edst));
633: bcopy((caddr_t)is->is_addr, (caddr_t)ace->ether_shost, 6);
634:
635: /*
636: * Queue message on interface, and start output if interface
637: * not yet active.
638: */
639: s = splimp();
640: if (IF_QFULL(&ifp->if_snd)) {
641: IF_DROP(&ifp->if_snd);
642: splx(s);
643: m_freem(m);
644: return (ENOBUFS);
645: }
646: IF_ENQUEUE(&ifp->if_snd, m);
647: acestart(unit);
648: splx(s);
649: return (0);
650:
651: bad:
652: m_freem(m0);
653: return (error);
654: }
655:
656: /*
657: * Routine to copy from mbuf chain to transmit buffer on the VERSAbus
658: * If packet size is less than the minimum legal size,
659: * the buffer is expanded. We probably should zero out the extra
660: * bytes for security, but that would slow things down.
661: */
662: aceput(txbuf, m)
663: u_char *txbuf;
664: struct mbuf *m;
665: {
666: register struct mbuf *mp;
667: register int off,total;
668: u_char *bp;
669: #ifdef ACEDEBUG
670: printf("aceput: txbuf %X, mbuf %X\n",txbuf,mp);
671: #endif ACEDEBUG
672:
673: total = 0;
674: /* Leave room for the destination */
675: off = 0;
676: bp = (u_char *)(txbuf + off);
677: for (mp = m;(mp); mp = mp->m_next)
678: {
679: register unsigned len = mp->m_len;
680: u_char *mcp;
681:
682: if (len == 0)
683: continue;
684: total += len;
685: mcp = mtod(mp, u_char *);
686: if ((unsigned)bp & 01) {
687: *bp++ = *mcp++;
688: len--;
689: }
690: if (off = (len >> 1)) {
691: register u_short *to, *from;
692:
693: to = (u_short *)bp;
694: from = (u_short *)mcp;
695: do
696: *to++ = *from++;
697: while (--off > 0);
698: bp = (u_char *)to,
699: mcp = (u_char *)from;
700: }
701: if (len & 01)
702: *bp++ = *mcp++;
703: }
704: m_freem(m);
705: return(total);
706: }
707:
708: /*
709: * Routine to copy from VERSAbus memory into mbufs.
710: *
711: * Warning: This makes the fairly safe assumption that
712: * mbufs have even lengths.
713: */
714: struct mbuf *
715: aceget(rxbuf, totlen, off0)
716: u_char *rxbuf;
717: int totlen, off0;
718: {
719: register struct mbuf *m;
720: struct mbuf *top = 0, **mp = ⊤
721: register int off = off0, len;
722: u_char *cp;
723: #ifdef ACEDEBUG
724: printf("aceget: rxbuf %X\n",rxbuf);
725: #endif ACEDEBUG
726:
727: cp = rxbuf + sizeof (struct ether_header);
728: while (totlen > 0)
729: {
730: register int words;
731: u_char *mcp;
732:
733: MGET(m, M_DONTWAIT, MT_DATA);
734: if (m == 0)
735: goto bad;
736: if (off) {
737: len = totlen - off;
738: cp = rxbuf +
739: sizeof (struct ether_header) + off;
740: } else
741: len = totlen;
742: if (len >= CLBYTES) {
743: struct mbuf *p;
744:
745: MCLGET(p, 1);
746: if (p != 0) {
747: m->m_len = len = CLBYTES;
748: m->m_off = (int)p - (int)m;
749: } else {
750: m->m_len = len = MIN(MLEN, len);
751: m->m_off = MMINOFF;
752: }
753: } else {
754: m->m_len = len = MIN(MLEN, len);
755: m->m_off = MMINOFF;
756: }
757: mcp = mtod(m, u_char *);
758: if (words = (len >> 1)) {
759: register u_short *to, *from;
760:
761: to = (u_short *)mcp;
762: from = (u_short *)cp;
763: do
764: *to++ = *from++;
765: while (--words > 0);
766: mcp = (u_char *)to;
767: cp = (u_char *)from;
768: }
769: if (len & 01)
770: *mcp++ = *cp++;
771: *mp = m;
772: mp = &m->m_next;
773: if (off == 0) {
774: totlen -= len;
775: continue;
776: }
777: off += len;
778: if (off == totlen) {
779: cp = rxbuf + sizeof (struct ether_header);
780: off = 0;
781: totlen = off0;
782: }
783: }
784: return (top);
785: bad:
786: m_freem(top);
787: return (0);
788: }
789:
790: /*+procedure */
791: /* */
792:
793: acebakoff(is, txseg, retries)
794: struct ace_softc *is; /* ptr to UCB for this device */
795: struct tx_segment *txseg; /* ptr to V/EIU tx seg */
796: register int retries; /* # of randoms to generate */
797: {
798: short *pMask; /* ptr to mask table. */
799: register short *pBakNum; /* ptr to # entry in Tx seg table */
800: register short random_num; /* random number value. */
801:
802:
803: pMask = &random_mask_tbl[0];
804: pBakNum = &txseg->tx_backoff[0];
805:
806: for (; --retries >= 0;)
807: {
808: random_num = (is->is_currnd = (is->is_currnd * 18741)-13849);
809: random_num &= *(pMask++);
810: *(pBakNum++) = random_num ^ (short)(0xFF00 | 0x00FC);
811: }
812: }
813:
814: /*
815: * Process an ioctl request.
816: */
817: aceioctl(ifp, cmd, data)
818: register struct ifnet *ifp;
819: int cmd;
820: caddr_t data;
821: {
822: register struct ifreq *ifr = (struct ifreq *)data;
823: int s = splimp(), error = 0;
824: #ifdef ACEDEBUG
825: printf("aceioctl: ifp %X, cmd %X, data %X\n",ifp,cmd,data);
826: #endif ACEDEBUG
827:
828: switch (cmd) {
829:
830: case SIOCSIFADDR:
831: if (ifp->if_flags & IFF_RUNNING)
832: if_rtinit(ifp, -1); /* delete previous route */
833: acesetaddr(ifp, (struct sockaddr_in *)&ifr->ifr_addr);
834: aceinit(ifp->if_unit);
835: break;
836:
837: default:
838: error = EINVAL;
839: }
840: splx(s);
841: return (error);
842: }
843:
844: acesetaddr(ifp, sin)
845: register struct ifnet *ifp;
846: register struct sockaddr_in *sin;
847: {
848: #ifdef ACEDEBUG
849: printf("acesetaddr: ifp %X, sin %X\n",ifp,sin);
850: #endif ACEDEBUG
851:
852: ifp->if_addr = *(struct sockaddr *)sin;
853: ifp->if_net = in_netof(sin->sin_addr);
854: ifp->if_host[0] = in_lnaof(sin->sin_addr);
855: sin = (struct sockaddr_in *)&ifp->if_broadaddr;
856: sin->sin_family = AF_INET;
857: sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY);
858: ifp->if_flags |= IFF_BROADCAST;
859: }
860: #endif NACE > 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.