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