|
|
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.