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