|
|
1.1 root 1: /* */
2: /* if_ace: ACC VERSAbus Ethernet controler (v/eiu) */
3: /* */
4: #include "ace.h"
5: #if NACE > 0
6:
7: #include "../machine/pte.h"
8:
9: #include "../h/param.h"
10: #include "../h/systm.h"
11: #include "../h/mbuf.h"
12: #include "../h/buf.h"
13: #include "../h/protosw.h"
14: #include "../h/socket.h"
15: #include "../h/vmmac.h"
16: #include "../h/ioctl.h"
17: #include "../h/errno.h"
18: #include "../h/vmparam.h"
19:
20: #include "../net/if.h"
21: #include "../net/netisr.h"
22: #include "../net/route.h"
23: #include "../netinet/in.h"
24: #include "../netinet/in_systm.h"
25: #include "../netinet/ip.h"
26: #include "../netinet/ip_var.h"
27: #include "../netinet/if_ether.h"
28: #include "../netpup/pup.h"
29:
30: #include "../machine/mtpr.h"
31: #include "../tahoeif/if_acereg.h"
32: #include "../vba/vbavar.h"
33:
34: #define LONET 124
35: #define LOHOST 1
36: #define TRUE 1
37: #define FALSE 0
38:
39: /* configuration table, for 2 units */
40: /* should be defined by config */
41: #define ACEVECTOR 0x90
42: long acestd[] = { 0x0ff0000, 0xff0100 }; /* controller */
43:
44: extern char ace0utl[], ace1utl[]; /* dpm */
45: char *acemap[]= { ace0utl, ace1utl };
46: extern long ACE0map[], ACE1map[];
47: long *ACEmap[] = {ACE0map, ACE1map };
48: long ACEmapa[] = {0xfff80000,0xfff90000};
49:
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:
85: int aceinit(),aceoutput(),aceioctl(),acereset();
86: struct mbuf *aceget();
87:
88: struct ace_softc ace_softc[NACE];
89: extern struct ifnet loif;
90:
91: int numace = NACE; /* for nstat unix command */
92:
93: /*------ debugging tools ------------*/
94: #ifdef ACEPRINTFS
95: int aceprintfs;
96: #define INTTRACE 1
97: #define RTINTRACE 2
98: #define STARTTRACE 4
99: #define ACEOTRACE 8
100: #define RTINTRACE1 0x10
101: #define IOCTLTRACE 0x20
102: #define ATRACE 0x40
103: #define SETETTRACE 0x80
104: #define ALLTRACE (INTTRACE | RTINTRACE | STARTTRACE | ACEOTRACE\
105: | RTINTRACE1 | IOCTLTRACE | ATRACE | SETETTRACE)
106:
107: #define ACETRACE(X,Y) {if (aceprintfs & X) Y}
108: #else ACEPRINTFS
109: #define ACETRACE(X,Y)
110: #endif ACEPRINTFS
111:
112: /*------ performance study tools ---------------*/
113: #ifdef NET_PERF
114: #define ACESTUDY(X) {X}
115: #else NET_PERF
116: #define ACESTUDY(X)
117: #endif
118:
119: aceprobe(reg)
120: caddr_t reg;
121: {
122: register struct acedevice *addr = (struct acedevice *)reg;
123: register i;
124:
125: ACETRACE(ALLTRACE, printf("aceprobe: veiu @%X\n",reg);)
126:
127:
128: #ifdef lint
129: i = 0; acerint(i); acecint(i);
130: #endif
131:
132: if (badaddr(reg,2)) return(0);
133: movew((short)CSR_RESET,&addr->csr);
134: DELAY(10000);
135: return (1);
136:
137: }
138:
139:
140: /*
141: * Interface exists: make available by filling in network interface
142: * record. System will initialize the interface when it is ready
143: * to accept packets.
144: */
145: aceattach(ui)
146: struct vba_device *ui;
147: {
148: register short unit = ui->ui_unit;
149: register struct ace_softc *is = &ace_softc[unit];
150: register struct ifnet *ifp = &is->is_if;
151: register struct acedevice *addr = (struct acedevice *)ui->ui_addr;
152: register short *pData0,i, data;
153: register char *pData1;
154: register short Csr;
155: struct sockaddr_in *sin;
156:
157: ACETRACE( ALLTRACE, printf("ace%dattach: ui %X\n",unit,ui);)
158:
159: ifp->if_unit = unit;
160: ifp->if_name = "ace";
161: ifp->if_mtu = ETHERMTU;
162:
163: /*
164: * Set vector,station's addresses,cleanup dpm.
165: */
166: /* set the station address, copy to arp structure */
167: acesetetaddr(unit,addr, &ace_station[unit * 6]);
168: /*
169: for (pData0 = (short *)addr->rar.station_addr,
170: pData1 = &ace_station[unit * 6], i = 6;
171: --i >= 0;) {
172: movew((short)(*pData1++),(pData0++));
173: }
174: for (pData0 = (short *)addr->rar.station_addr,
175: pData1 = (char *)(is->is_addr), i = 6;
176: --i >= 0;)
177: *(pData1++) = ~(*(pData0++));
178:
179: ACETRACE(ALLTRACE,
180: printf("ace%d: addr=%x:%x:%x:%x:%x:%x\n",
181: unit,
182: is->is_addr[0]&0xff, is->is_addr[1]&0xff,
183: is->is_addr[2]&0xff, is->is_addr[3]&0xff,
184: is->is_addr[4]&0xff, is->is_addr[5]&0xff);)
185: */
186:
187: is->is_promiscuous = (FALSE)? CSR_PROMISCUOUS: 0;
188: for (pData0 = (short *)addr->rar.mcast_hash_code,
189: pData1 = &ace_hash_code[unit * 8], i = 8;
190: --i >= 0;){
191: movew((short)(*pData1++),(pData0++));
192: }
193:
194: movew((short)~0xffff,&addr->rar.broadcast_en[0]);
195: movew((short)~0xffff,&addr->rar.broadcast_en[1]);
196:
197: aceclean((int)unit);
198:
199: sin = (struct sockaddr_in *)&ifp->if_addr;
200: sin->sin_family = AF_INET;
201: sin->sin_addr = arpmyaddr((struct arpcom *)0);
202: ifp->if_init = aceinit;
203: ifp->if_output = aceoutput;
204: ifp->if_ioctl = aceioctl;
205: ifp->if_reset = acereset;
206: if_attach(ifp);
207: }
208:
209: acesetetaddr(unit,addr,station_addr)
210: short unit;
211: struct acedevice *addr;
212: char *station_addr;
213: {
214: register short *pData0, i;
215: register char *pData1;
216: register struct ace_softc *is = &ace_softc[unit];
217:
218: for (pData0 = (short *)addr->rar.station_addr,
219: pData1 = station_addr, i = 6; --i >= 0;) {
220: movew((short)(*pData1++),(pData0++));
221: }
222: for (pData0 = (short *)addr->rar.station_addr,
223: pData1 = (char *)(is->is_addr), i = 6; --i >= 0;)
224: *(pData1++) = ~(*(pData0++));
225:
226: ACETRACE(SETETTRACE,
227: printf("ace%d: addr=%x:%x:%x:%x:%x:%x\n",
228: unit,
229: is->is_addr[0]&0xff, is->is_addr[1]&0xff,
230: is->is_addr[2]&0xff, is->is_addr[3]&0xff,
231: is->is_addr[4]&0xff, is->is_addr[5]&0xff);)
232: }
233:
234:
235: /*
236: * Reset of interface after "system" reset.
237: */
238: acereset(unit, vban)
239: int unit, vban;
240: {
241: register struct vba_device *ui;
242:
243: ACETRACE(ALLTRACE, printf("ace%dreset:\n",unit,vban);)
244:
245: if (unit >= NACE || (ui = aceinfo[unit]) == 0 || ui->ui_alive == 0 ||
246: ui->ui_vbanum != vban)
247: return;
248: printf(" ace%d", unit);
249: aceinit(unit);
250: }
251:
252: /*
253: * Initialization of interface; clear recorded pending operations
254: */
255: aceinit(unit)
256: int unit;
257: {
258: register struct ace_softc *is = &ace_softc[unit];
259: register struct vba_device *ui = aceinfo[unit];
260: register struct acedevice *addr;
261: register struct ifnet *ifp = &is->is_if;
262: register struct sockaddr_in *sin;
263: register short Csr;
264: register int i,s;
265:
266: ACETRACE(ALLTRACE, printf("ace%dinit:\n",unit);)
267:
268: sin = (struct sockaddr_in *)&ifp->if_addr;
269: if (sin->sin_addr.s_addr == 0) /* address still unknown */
270: return;
271: if (!(ifp->if_flags & IFF_RUNNING))
272: {
273:
274: /*
275: * Reset the controller, initialize the recieve buffers,
276: * and turn the controller on again and set board online.
277: */
278: addr = (struct acedevice *)ui->ui_addr;
279: s = splimp();
280: movew((short)CSR_RESET,&addr->csr);
281: DELAY(10000);
282:
283: /* clean up dpm since the controller might jumble dpm after
284: reset */
285: aceclean((int)unit);
286: movew((short)CSR_GO,&addr->csr); /* addr->csr = CSR_GO; */
287: Csr = addr->csr;
288: if (Csr & CSR_ACTIVE)
289: {
290: movew((short)(ACEVECTOR + (unit*8)),&addr->ivct);
291: Csr |= CSR_ENINT | is->is_promiscuous;
292: if (ifp->if_net == LONET)
293: Csr |= (CSR_LOOP3);
294: movew(Csr,&addr->csr);
295:
296: is->is_flags = 0;
297: is->is_xcnt = 0;
298: is->is_if.if_flags |= IFF_UP|IFF_RUNNING;
299: }
300: else
301: {
302: ACETRACE(ALLTRACE,
303: printf("ace%dinit: would not go active\n",unit);)
304: }
305: splx(s);
306: }
307:
308: if (is->is_if.if_flags & IFF_UP) {
309: if_rtinit(&is->is_if, RTF_UP);
310: aceStart((int)unit);
311: }
312: arpattach(&is->is_ac);
313: arpwhohas(&is->is_ac, &sin->sin_addr);
314: }
315:
316: /*
317: * Start output on interface.
318: * Get another datagram to send off of the interface queue,
319: * and map it to the interface before starting the output.
320: *
321: */
322: acestart(dev)
323: dev_t dev;
324: {
325: register struct tx_segment *txs;
326: register long len,x;
327: int unit = ACEUNIT(dev);
328: struct vba_device *ui = aceinfo[unit];
329: register struct acedevice *addr = (struct acedevice *)ui->ui_addr;
330: register struct ace_softc *is = &ace_softc[unit];
331: register long tripnum = 0;
332: struct mbuf *m;
333: short retries,idx;
334:
335: ACETRACE(STARTTRACE,
336: printf("ace%dstart: dev %X, txnext seg %x\n",unit,dev,
337: (addr->tseg >> 11) & 0xf);)
338:
339: ACESTUDY(is->is_stats.tx_startcnt++;)
340: again:
341: txs = (struct tx_segment*)(is->is_dpm + (is->is_txnext << 11));
342: if (txs->tx_csr & TCS_TBFULL) {
343: ACETRACE(ALLTRACE, printf("ace%dstart:segment %x is busy\n",
344: unit, is->is_txnext);)
345: is->is_stats.tx_busy++;
346: return;
347: }
348:
349: x = splimp();
350: IF_DEQUEUE(&is->is_if.if_snd, m);
351: splx(x);
352: if (m == 0)
353: return;
354:
355: len = aceput((int) unit, txs->tx_data, m);
356: retries = (txs->tx_csr & TCS_RTC);
357: acebakoff(is,txs,retries);
358:
359: /*
360: * Ensure minimum packet length.
361: * This makes the safe assumtion that there are no virtual holes
362: * after the data.
363: * For security, it might be wise to zero out the added bytes,
364: * but we're mainly interested in speed at the moment.
365: */
366: if (len - SIZEOF_ETHEADER < ETHERMIN)
367: len = ETHERMIN + SIZEOF_ETHEADER;
368: if (++is->is_txnext > SEG_MAX)
369: is->is_txnext = is->is_segboundry;
370: is->is_if.if_opackets++;
371: is->is_xcnt++;
372: len = (len & 0x7fff) | TCS_TBFULL;
373:
374: ACETRACE(STARTTRACE,
375: printf("ace%dstart GO [csr %x][%x,%x,%x,%x,%x,%x] [%x,%x,%x,%x,%x,%x] [%x] [%x] \n",unit,
376: (len & 0xffff),
377: (txs->tx_data[0] & 0xff),(txs->tx_data[1] & 0xff),
378: (txs->tx_data[2] & 0xff),(txs->tx_data[3] & 0xff),
379: (txs->tx_data[4] & 0xff),(txs->tx_data[5] & 0xff),
380: (txs->tx_data[6] & 0xff),(txs->tx_data[7] & 0xff),
381: (txs->tx_data[8] & 0xff),(txs->tx_data[9] & 0xff),
382: (txs->tx_data[10] & 0xff),(txs->tx_data[11] & 0xff),
383: (txs->tx_data[12] & 0xff),(txs->tx_data[13] & 0xff));)
384: movew((short)len,txs);
385:
386: goto again;
387: }
388:
389: /*
390: * Transmit done interrupt.
391: */
392: acecint(unit)
393: int unit;
394: {
395: register struct ace_softc *is = &ace_softc[unit];
396: struct vba_device *ui = aceinfo[unit];
397: register struct acedevice *addr = (struct acedevice *)ui->ui_addr;
398: register struct tx_segment *txseg; /* ptr to V/EIU tx seg */
399: short txidx,eostat;
400:
401: ACESTUDY(is->is_stats.tx_cintcnt++;)
402:
403: if (is->is_xcnt <= 0) {
404: txidx = ((addr->tseg >> 11) & 0xf);
405: printf("ace%dcint: stray xmit interrupt,xcnt %d\n",
406: unit,is->is_xcnt);
407: printf("\t**eoctr %d, ctlr's tseg %d\n",is->is_eoctr,txidx);
408: is->is_xcnt = 0;
409: aceStart((int)unit);
410: return;
411: }
412:
413: is->is_xcnt--;
414: txseg = (struct tx_segment *)((is->is_eoctr << 11) + is->is_dpm);
415: if (((eostat = txseg->tx_csr) & TCS_TBFULL) == 0) {
416: is->is_stats.tx_retries += (eostat & TCS_RTC);
417: if (eostat & TCS_RTFAIL) {
418: is->is_stats.tx_discarded++;
419: is->is_if.if_oerrors++;
420: }
421: else
422: is->is_stats.tx_datagrams++;
423:
424: if (++is->is_eoctr >= 16)
425: is->is_eoctr = is->is_segboundry;
426: }
427: else {
428: ACESTUDY(is->is_stats.tx_cbusy++;)
429: }
430:
431: aceStart((int)unit);
432: }
433:
434: /*
435: * Ethernet interface receiver interrupt.
436: * If input error just drop packet.
437: * Otherwise purge input buffered data path and examine
438: * packet to determine type. If can't determine length
439: * from type, then have to drop packet. Othewise decapsulate
440: * packet based on type and pass to type specific higher-level
441: * input routine.
442: */
443:
444:
445: acerint(unit)
446: int unit;
447: {
448: register struct ace_softc *is = &ace_softc[unit];
449: register struct ifqueue *inq;
450: register struct ether_header *ace;
451: register struct rx_segment *rxseg; /* ptr to V/EIU rx seg */
452: register long tripnum = 0;
453: struct acedevice *addr = (struct acedevice *)aceinfo[unit]->ui_addr;
454: short eistat;
455: struct mbuf *m;
456: int len, s, off, resid;
457:
458: ACESTUDY(is->is_stats.rx_rintcnt++;)
459: more:
460: rxseg = (struct rx_segment *)((is->is_eictr << 11) + is->is_dpm);
461:
462: if ((eistat = rxseg->rx_csr) & RCS_RBFULL)
463: {
464: is->is_if.if_ipackets++;
465: if (++is->is_eictr >= is->is_segboundry)
466: is->is_eictr = 0;
467:
468: ACETRACE(RTINTRACE, printf("ace%drint: is_eictr %x,[csr %x]\n",
469: unit,is->is_eictr,(eistat & 0xffff));)
470: ACESTUDY(if (tripnum) is->is_stats.rx_rwoint++;)
471:
472: len = (eistat & RCS_RBC);
473: if ((eistat & (RCS_ROVRN | RCS_RCRC | RCS_RODD)) ||
474: (len < ET_MINLEN) || (len > (ET_MAXLEN+CRC_SIZE)))
475: {
476: if (eistat & RCS_ROVRN) is->is_stats.rx_overruns++;
477: if (eistat & RCS_RCRC) is->is_stats.rx_crc_errors++;
478: if (eistat & RCS_RODD) is->is_stats.rx_align_errors++;
479: if (len < ET_MINLEN) is->is_stats.rx_underruns++;
480: if (len > (ET_MAXLEN+CRC_SIZE)) is->is_stats.rx_overruns++;
481: is->is_if.if_ierrors++;
482: rxseg->rx_csr = 0;
483:
484: ACETRACE( RTINTRACE,
485: if (is->is_if.if_ierrors % 100 == 0)
486: printf("ace%d: += 100 input errors\n", unit);)
487: return;
488: }
489: else is->is_stats.rx_datagrams++;
490: }
491: else
492: {
493: if (tripnum==0) {
494: ACESTUDY(is->is_stats.rx_busy++;)
495: }
496: return;
497: }
498: ace = (struct ether_header *)(rxseg->rx_data);
499: len -= SIZEOF_ETHEADER;
500:
501: /*
502: * Deal with trailer protocol: if type is PUP trailer
503: * get true type from first 16-bit word past data.
504: * Remember that type was trailer by setting off.
505: */
506: ace->ether_type = ntohs((u_short)ace->ether_type);
507: #define acedataaddr(ace, off, type) ((type)(((caddr_t)(((char *)ace)+SIZEOF_ETHEADER)+(off))))
508:
509: /* #define acedataaddr(ace, off, type) ((type)(((caddr_t)((ace)+1)+(off))))
510: */
511: if (ace->ether_type >= ETHERPUP_TRAIL &&
512: ace->ether_type < ETHERPUP_TRAIL+ETHERPUP_NTRAILER) {
513: off = (ace->ether_type - ETHERPUP_TRAIL) * 512;
514: if (off >= ETHERMTU)
515: goto setup; /* sanity */
516: ace->ether_type = ntohs(*acedataaddr(ace, off, u_short *));
517: resid = ntohs(*(acedataaddr(ace, off+2, u_short *)));
518: if (off + resid > len)
519: goto setup; /* sanity */
520: len = off + resid;
521: } else
522: off = 0;
523: if (len == 0)
524: goto setup;
525:
526: /*
527: * Pull packet off interface. Off is nonzero if packet
528: * has trailing header; aceget will then force this header
529: * information to be at the front, but we still have to drop
530: * the type and length which are at the front of any trailer data.
531: */
532: m = aceget((int)unit, rxseg->rx_data, len, off);
533: if (m == 0)
534: goto setup;
535: if (off) {
536: m->m_off += 2 * sizeof (u_short);
537: m->m_len -= 2 * sizeof (u_short);
538: }
539: switch (ace->ether_type) {
540:
541: #ifdef INET
542: case ETHERPUP_IPTYPE:
543: if (tripnum == 0) {
544: /* rely on the fact that ip_input() will drain
545: the incoming queue after the first software
546: interrupt */
547: schednetisr(NETISR_IP);
548: }
549: inq = &ipintrq;
550: break;
551:
552: case ETHERPUP_ARPTYPE:
553: arpinput(&is->is_ac, m);
554: goto setup;
555: #endif
556: default:
557: ACETRACE(RTINTRACE,
558: printf("\nUndefined packet type %d\n",ace->ether_type);)
559: m_freem(m);
560: goto setup;
561: }
562:
563: if (IF_QFULL(inq)) {
564: IF_DROP(inq);
565: m_freem(m);
566: goto setup;
567: }
568: s = splimp();
569: IF_ENQUEUE(inq, m);
570: splx(s);
571:
572: ACETRACE(RTINTRACE1,printf("acerint: enqlen %d: ",inq->ifq_len);)
573: ACETRACE(RTINTRACE1,aceprm(m);)
574: setup:
575: rxseg->rx_csr = 0;
576: goto more;
577: }
578:
579: /*
580: * Ethernet output routine.
581: * Encapsulate a packet of type family for the local net.
582: * Use trailer local net encapsulation if enough data in first
583: * packet leaves a multiple of 512 bytes of data in remainder.
584: */
585: aceoutput(ifp, m0, dst)
586: struct ifnet *ifp;
587: struct mbuf *m0;
588: struct sockaddr *dst;
589: {
590: register short unit = ifp->if_unit;
591: register struct ace_softc *is = &ace_softc[unit];
592: register struct mbuf *m = m0;
593: register struct ether_header *ace;
594: register int off;
595: register struct mbuf *mcopy;
596: int type, s, error;
597: u_char edst[6];
598: struct in_addr idst;
599:
600: #ifndef INET
601: ACETRACE(ACEOTRACE,
602: printf("ace%doutput: ifp %lx, m0 %lx, dst ADDR %lx: ",
603: unit,ifp,m0, dst);)
604: ACETRACE(ACEOTRACE,aceprm(m0);)
605: #endif
606:
607: switch (dst->sa_family) {
608:
609: #ifdef INET
610: case AF_INET:
611: idst = ((struct sockaddr_in *)dst)->sin_addr;
612: ACETRACE(ACEOTRACE,
613: printf("ace%doutput: ifp %lx, m0 %lx, dst %lx: ",
614: unit,ifp,m0, idst.S_un.S_addr);)
615: ACETRACE(ACEOTRACE,aceprm(m0);)
616:
617: /* translate internet to ethernet address */
618: switch(arpresolve(&is->is_ac, m, &idst, edst)) {
619: case ARPRESOLVE_WILLSEND:
620: return (0); /* if not yet resolved */
621: case ARPRESOLVE_BROADCAST:
622: mcopy = m_copy(m, 0, (int)M_COPYALL);
623: MBUFNULL(42, mcopy); /* for debugging */
624: if (mcopy)
625: looutput(&loif, mcopy, dst);
626:
627: /* falls through ... */
628: case ARPRESOLVE_OK:
629: break;
630: }
631:
632: off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
633:
634: /* need per host negotiation */
635: if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
636: if (off > 0 && (off & 0x1ff) == 0 &&
637: m->m_off >= MMINOFF + 2 * sizeof (u_short))
638: {
639: type = ETHERPUP_TRAIL + (off>>9);
640: m->m_off -= 2 * sizeof (u_short);
641: m->m_len += 2 * sizeof (u_short);
642: *mtod(m, u_short *) = htons((u_short)ETHERPUP_IPTYPE);
643: *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
644: goto gottrailertype;
645: }
646: type = ETHERPUP_IPTYPE;
647: off = 0;
648: goto gottype;
649: #endif
650:
651: case AF_UNSPEC:
652: ace = (struct ether_header *)dst->sa_data;
653: bcopy((caddr_t)ace->ether_dhost, (caddr_t)edst, sizeof (edst));
654: type = ace->ether_type;
655: goto gottype;
656:
657: default:
658: printf("ace%d: can't handle af%d\n", unit,dst->sa_family);
659: error = EAFNOSUPPORT;
660: goto bad;
661: }
662:
663: gottrailertype:
664: /*
665: * Packet to be sent as trailer: move first packet
666: * (control information) to end of chain.
667: */
668: while (m->m_next)
669: m = m->m_next;
670: m->m_next = m0;
671: m = m0->m_next;
672: m0->m_next = 0;
673: m0 = m;
674:
675: gottype:
676: /*
677: * Add local net header. If no space in first mbuf,
678: * allocate another.
679: */
680: if (m->m_off > MMAXOFF ||
681: MMINOFF + SIZEOF_ETHEADER > m->m_off) {
682: m = m_get(M_DONTWAIT, MT_HEADER);
683: MBUFNULL(30, m);
684: if (m == 0) {
685: error = ENOBUFS;
686: goto bad;
687: }
688: m->m_next = m0;
689: m->m_off = MMINOFF;
690: m->m_len = SIZEOF_ETHEADER;
691: } else {
692: m->m_off -= SIZEOF_ETHEADER;
693: m->m_len += SIZEOF_ETHEADER;
694: }
695: ace = mtod(m, struct ether_header *);
696: ace->ether_type = htons((u_short)type);
697: bcopy((caddr_t)edst, (caddr_t)ace->ether_dhost, sizeof (edst));
698: bcopy((caddr_t)is->is_addr, (caddr_t)ace->ether_shost, 6);
699:
700: /*
701: * Queue message on interface, and start output if interface
702: * not yet active.
703: */
704: s = splimp();
705: if (IF_QFULL(&ifp->if_snd)) {
706: IF_DROP(&ifp->if_snd);
707: splx(s);
708: m_freem(m);
709: return (ENOBUFS);
710: }
711: IF_ENQUEUE(&ifp->if_snd, m);
712: splx(s);
713:
714: ACETRACE (ACEOTRACE, printf("ace%doutput: enqu mbuf %lx: ",unit,m);)
715: ACETRACE (ACEOTRACE, aceprm(m);)
716: ACESTUDY (is->is_stats.tx_outcnt++;)
717:
718: aceStart((int)unit);
719: return (0);
720:
721: bad:
722: ACETRACE(ACEOTRACE, printf("ace%doutput: BAD.\n");)
723: m_freem(m0);
724: return (error);
725: }
726:
727: aceStart(unit)
728: int unit;
729: {
730: register struct ace_softc *is = &ace_softc[unit];
731:
732: if (!(is->is_flags & ACEF_OACTIVE)) {
733: is->is_flags |= ACEF_OACTIVE;
734: acestart((dev_t)unit);
735: is->is_flags &= ~ACEF_OACTIVE;
736: }
737: }
738:
739: /*
740: * Routine to copy from mbuf chain to transmit buffer on the VERSAbus
741: * If packet size is less than the minimum legal size,
742: * the buffer is expanded. We probably should zero out the extra
743: * bytes for security, but that would slow things down.
744: */
745: aceput(unit, txbuf, m)
746: int unit; /* for statistics collection */
747: u_char *txbuf;
748: struct mbuf *m;
749: {
750: register u_char *bp;
751: register u_char *mcp;
752: register short *s1;
753: register short *s2;
754: register unsigned len;
755: register struct mbuf *mp;
756: int total, idx;
757:
758: ACETRACE(STARTTRACE, printf("aceput: txbuf %X, mbuf %X, m->m_off %d\n",
759: txbuf,m,m->m_off);)
760: ACETRACE(STARTTRACE,aceprm(m);)
761:
762: total = 0;
763: bp = (u_char *)txbuf;
764: for (mp = m;(mp); mp = mp->m_next)
765: {
766: len = mp->m_len;
767: if (len == 0)
768: continue;
769:
770: total += len;
771: mcp = mtod(mp, u_char *);
772:
773: /*bcopy((caddr_t)mcp,(caddr_t)bp,len);*/
774: /*bp += len;*/
775:
776: if (((int)mcp & 01) && ((int)bp & 01)) {
777: /* source & destination at odd addresses */
778: /* *bp++ = *mcp++; */
779: asm("movob (r11),(r12)");
780: asm("addl2 $1,r12");
781: asm("addl2 $1,r11");
782: --len;
783: }
784: if (len > 1 && (((int)mcp & 01)==0) && (((int)bp & 01)==0)) {
785: register int l;
786:
787: s1 = (short *)bp;
788: s2 = (short *)mcp;
789: l = (len >> 1); /* count # of shorts */
790: while (l-->0) { /* copy shorts */
791: /* *s1++ = *s2++; */
792: asm("movow (r9),(r10)");
793: asm("addl2 $2,r10");
794: asm("addl2 $2,r9");
795: }
796: len &= 1; /* # remaining bytes */
797: bp = (u_char *)s1;
798: mcp = (u_char *)s2;
799: }
800: while (len-- > 0) {
801: /* *bp++ = *mcp++; */
802: asm("movob (r11),(r12)");
803: asm("addl2 $1,r12");
804: asm("addl2 $1,r11");
805: }
806: }
807: m_freem(m);
808: return(total);
809: }
810:
811: movew(data,to)
812: short data;
813: short *to;
814: {
815: asm("movow 6(fp),*8(fp)");
816: }
817:
818:
819: #ifdef ACEPRINTFS
820: aceprm(mp)
821: struct mbuf *mp;
822: {
823: register u_char *mcp;
824: register struct mbuf *mpp;
825: register long idx;
826: register long totlen,lx;
827:
828: for(totlen=0,mpp=mp->m_next; mpp; mpp=mpp->m_next)
829: totlen += mpp->m_len;
830:
831: mcp = mtod(mp, u_char *);
832: printf("mbuf[len %d,off %d],[next %lx,totlen %ld],[",
833: mp->m_len,mp->m_off,mp->m_next,totlen);
834: for (idx=0 ; (idx < 20 ); idx++)
835: {
836: printf("%x ",mcp[idx] & 0xff);
837: }
838: printf("]\n");
839: }
840: #endif ACEPRINTFS
841:
842: /*
843: * Routine to copy from VERSAbus memory into mbufs.
844: *
845: * Warning: This makes the fairly safe assumption that
846: * mbufs have even lengths.
847: */
848: struct mbuf *
849: aceget(unit, rxbuf, totlen, off0)
850: int unit; /* for statistics collection */
851: u_char *rxbuf;
852: int totlen, off0;
853: {
854: register u_char *cp;
855: register u_char *mcp;
856: register int tlen;
857: int len;
858:
859: register struct mbuf *m;
860: struct mbuf *top = 0, **mp = ⊤
861: int off = off0;
862:
863: ACETRACE(RTINTRACE, printf("aceget: rxbuf %lx, len %d, off %d\n",
864: rxbuf,totlen,off0);)
865:
866: cp = rxbuf + SIZEOF_ETHEADER;
867: while (totlen > 0)
868: {
869: register int words;
870:
871: MGET(m, M_DONTWAIT, MT_DATA);
872: MBUFNULL(33, m);
873: if (m == 0)
874: goto bad;
875: if (off) {
876: len = totlen - off;
877: cp = rxbuf +
878: SIZEOF_ETHEADER + off;
879: } else
880: len = totlen;
881:
882: if (len >= CLBYTES) {
883: struct mbuf *p;
884:
885: MCLGET(p, 1);
886: if (p != 0) {
887: m->m_len = len = CLBYTES;
888: m->m_off = (int)p - (int)m;
889: } else {
890: m->m_len = len = MIN(MLEN, len);
891: m->m_off = MMINOFF;
892: }
893: } else {
894: m->m_len = len = MIN(MLEN, len);
895: m->m_off = MMINOFF;
896: }
897:
898: mcp = mtod(m, u_char *);
899:
900: /*bcopy((caddr_t)cp, (caddr_t)mcp, len);*/
901: /*cp += len; mcp += len;*/
902:
903: tlen = len;
904: if (((int)mcp & 01) && ((int)cp & 01)) {
905: /* source & destination at odd addresses */
906: *mcp++ = *cp++;
907: --tlen;
908: }
909: if (tlen > 1 && (((int)mcp & 01)==0) && (((int)cp & 01)==0)) {
910: register short *s1;
911: register short *s2;
912: register int l;
913:
914: s1 = (short *)mcp;
915: s2 = (short *)cp;
916: l = (tlen >> 1); /* count # of shorts */
917: while (l-->0) /* copy shorts */
918: *s1++ = *s2++;
919: tlen &= 1; /* # remaining bytes */
920: mcp = (u_char *)s1;
921: cp = (u_char *)s2;
922: }
923: while (tlen-- > 0)
924: *mcp++ = *cp++;
925:
926: *mp = m;
927: mp = &m->m_next;
928: if (off == 0) {
929: totlen -= len;
930: continue;
931: }
932: off += len;
933: if (off == totlen) {
934: cp = rxbuf + SIZEOF_ETHEADER;
935: off = 0;
936: totlen = off0;
937: }
938: }
939: return (top);
940: bad:
941: m_freem(top);
942: return (0);
943: }
944:
945: /*+procedure */
946: /* */
947:
948: acebakoff(is, txseg, retries)
949: struct ace_softc *is; /* ptr to UCB for this device */
950: struct tx_segment *txseg; /* ptr to V/EIU tx seg */
951: register int retries; /* # of randoms to generate */
952: {
953: short *pMask; /* ptr to mask table. */
954: register short *pBakNum; /* ptr to # entry in Tx seg table */
955: register short random_num; /* random number value. */
956:
957:
958: pMask = &random_mask_tbl[0];
959: pBakNum = &txseg->tx_backoff[0];
960:
961: for (; --retries >= 0;)
962: {
963: random_num = (is->is_currnd = (is->is_currnd * 18741)-13849);
964: random_num &= *(pMask++);
965: *(pBakNum++) = random_num ^ (short)(0xFF00 | 0x00FC);
966: }
967: }
968:
969: /*
970: * Process an ioctl request.
971: */
972: aceioctl(ifp, cmd, data)
973: register struct ifnet *ifp;
974: int cmd;
975: caddr_t data;
976: {
977: register struct vba_device *ui;
978: register struct acedevice *addr;
979: register struct sockaddr_in *et_addr;
980: register struct ace_softc *is;
981: register struct ifreq *ifr = (struct ifreq *)data;
982: int s , error = 0;
983:
984: ACETRACE (IOCTLTRACE,
985: printf("aceioctl: ifp %X, cmd %X, data %X\n",ifp,cmd,data);)
986:
987: switch (cmd) {
988:
989: case SIOCSIFADDR:
990: s = splimp();
991: if (ifp->if_flags & IFF_RUNNING)
992: if_rtinit(ifp, -1); /* delete previous route */
993: acesetaddr(ifp, (struct sockaddr_in *)&ifr->ifr_addr);
994: aceinit(ifp->if_unit);
995: splx(s);
996: break;
997:
998: case SIOCSETETADDR: /* Set Ethernet station address */
999: s = splimp();
1000: ifp->if_flags &= (~IFF_RUNNING | IFF_UP);
1001: et_addr = (struct sockaddr_in *)&ifr->ifr_addr;
1002: ui = aceinfo[ifp->if_unit];
1003: addr = (struct acedevice *)ui->ui_addr;
1004: movew((short)CSR_RESET,&addr->csr); /* Reset again */
1005: DELAY(10000);
1006: /* Set station address and copy addr to arp struct */
1007: acesetetaddr(ifp->if_unit,addr,&et_addr->sin_zero[2]);
1008: aceinit(ifp->if_unit); /* Re-initialize */
1009: splx(s);
1010: break;
1011:
1012: default:
1013: error = EINVAL;
1014: }
1015: return (error);
1016: }
1017:
1018: acesetaddr(ifp, sin)
1019: register struct ifnet *ifp;
1020: register struct sockaddr_in *sin;
1021: {
1022:
1023: ACETRACE (IOCTLTRACE, printf("acesetaddr: ifp %X, sin %X\n",ifp,sin);)
1024:
1025: arpremove(&ifp->if_addr);
1026: ifp->if_addr = *(struct sockaddr *)sin;
1027: ifp->if_net = in_netof(sin->sin_addr);
1028: ifp->if_host[0] = in_lnaof(sin->sin_addr);
1029: sin = (struct sockaddr_in *)&ifp->if_broadaddr;
1030: sin->sin_family = AF_INET;
1031: sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY);
1032: ifp->if_flags |= IFF_BROADCAST;
1033: }
1034:
1035: aceclean(unit)
1036: int unit;
1037: {
1038: register struct ace_softc *is = &ace_softc[unit];
1039: register struct ifnet *ifp = &is->is_if;
1040: register struct vba_device *ui = aceinfo[unit];
1041: register struct acedevice *addr = (struct acedevice *)ui->ui_addr;
1042: register short i, data;
1043: register char *pData1;
1044:
1045: is->is_dpm = acemap[unit]; /* init dpm */
1046: ioaccess(ACEmap[unit],ACEmapa[unit],ACEBPTE);
1047: bzero((char *)is->is_dpm, (16384*2));
1048:
1049: is->is_currnd = 49123;
1050: is->is_segboundry = (addr->segb >> 11) & 0xf;
1051: for (pData1 = (char*)((int)is->is_dpm + (is->is_segboundry << 11)),
1052: i = (SEG_MAX + 1) - is->is_segboundry;
1053: (--i >= 0); pData1 += sizeof (struct tx_segment))
1054: acebakoff(is,((struct tx_segment*)pData1),15);
1055:
1056: is->is_eictr = 0;
1057: is->is_eoctr = is->is_txnext = is->is_segboundry;
1058: bzero((char *)&is->is_stats, sizeof(is->is_stats));
1059:
1060: }
1061: #endif NACE > 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.