|
|
1.1 ! root 1: #include "enp.h" ! 2: #define ENPBPTE 128 ! 3: #if NENP > 0 ! 4: ! 5: /* ! 6: * Modified 3 Com Ethernet Controller interface ! 7: * enp modifications added S. F. Holmgren ! 8: */ ! 9: ! 10: #include "../h/param.h" ! 11: #include "../h/systm.h" ! 12: #include "../h/mbuf.h" ! 13: #include "../h/buf.h" ! 14: #include "../h/protosw.h" ! 15: #include "../h/socket.h" ! 16: #include "../h/vmmac.h" ! 17: #include "../h/errno.h" ! 18: #include "../h/time.h" ! 19: #include "../h/kernel.h" ! 20: #include "../h/uio.h" ! 21: #include "../net/if.h" ! 22: #include "../net/netisr.h" ! 23: #include "../net/route.h" ! 24: #include "../netinet/in.h" ! 25: #include "../h/ioctl.h" ! 26: ! 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: #include "../vba/vbavar.h" ! 33: #include "../tahoeif/if_enp.h" ! 34: #include "../machine/mtpr.h" ! 35: #include "../tahoeif/if_debug.h" ! 36: ! 37: #define ENP0_PHYSADDR 0xf40000 /* board # 0 physical base addr */ ! 38: #define ENP1_PHYSADDR 0xf60000 /* board # 1 physical base addr */ ! 39: #define ENPSTART 0xf02000 /* standard enp start addr */ ! 40: ! 41: int enpprobe(), enpattach(), enpintr(); ! 42: extern nulldev(); ! 43: caddr_t vtoph(); ! 44: struct mbuf *m_tofree(); ! 45: struct vba_device *enpinfo[ NENP ]; ! 46: ! 47: /* Maximun 2 controllers per system supported */ ! 48: ! 49: long enpstd[] = { ENP0_PHYSADDR+0x1000,ENP1_PHYSADDR+0x1000, 0 }; ! 50: extern char enp0utl[], enp1utl[]; /* enp accessible ram map */ ! 51: char *enpmap[]= { enp0utl, enp1utl }; ! 52: extern long ENP0map[], ENP1map[]; ! 53: long *ENPmap[] = {ENP0map, ENP1map}; ! 54: long ENPmapa[] = {0xfff41000, 0xfff61000}; ! 55: long enpismapped[NENP]; ! 56: ! 57: unsigned short intvec[4] = ! 58: { 0xc1, 0xc2, 0xc3, 0xc4 }; /* intrvec of upto 4 enps */ ! 59: ! 60: struct vba_driver enpdriver = ! 61: { ! 62: /* use of prom based version ! 63: enpprobe, 0, enpattach, 0, 0, enpintr, ! 64: */ ! 65: enpprobe, 0, nulldev, 0, ! 66: enpstd, "enp", enpinfo, "ENP 20", 0 ! 67: }; ! 68: ! 69: int enpinit(), ! 70: enpioctl(), ! 71: enpoutput(), ! 72: enpreset(), ! 73: enpbroadcast(), ! 74: enptimeout(); ! 75: ! 76: int enpcopy(); ! 77: ! 78: struct mbuf *enpget(); ! 79: ! 80: extern struct ifnet loif; ! 81: ! 82: /* ! 83: * Ethernet software status per interface. ! 84: * ! 85: * Each interface is referenced by a network interface structure, ! 86: * es_if, which the routing code uses to locate the interface. ! 87: * This structure contains the output queue for the interface, its address, ... ! 88: */ ! 89: ! 90: struct enp_softc enp_softc[NENP]; ! 91: long stat_addr[NENP]; /* enp statistic addr (for nstat use) */ ! 92: long ring_addr[NENP]; /* enp dev ring addresses (for nstat use) */ ! 93: int numenp = NENP; ! 94: int enp_intr = 0, /* no. of enp_to_host interrupts */ ! 95: host_intr = 0; /* no. of host_to_enp interrupts */ ! 96: short enpram[NENP]; /* open/close flags for enp devices */ ! 97: /* Debugging tools, used to trace input packets */ ! 98: extern int printerror; /* error print flag, from if_ace.c */ ! 99: int save_enp_inpkt = 0; ! 100: #define ENPTRACE(X) if (save_enp_inpkt) X; ! 101: ! 102: struct inp_err enperr[NENP]; ! 103: ! 104: /* ! 105: * Probe for device. ! 106: */ ! 107: ! 108: enpprobe(reg) ! 109: caddr_t reg; ! 110: { ! 111: static int unit=0; ! 112: register ENPDEVICE *addr = (ENPDEVICE *)reg; ! 113: ! 114: if( (badaddr( addr, 2 ) ) || (badaddr( &addr->enp_ram[0], 2 ) ) ) ! 115: return( 0 ); ! 116: addr->enp_state = S_ENPRESET; /* controller is reset by vbus reset */ ! 117: /* save address of statistic area for nstat uses */ ! 118: ! 119: stat_addr[unit] = (long) &(addr->enp_stat); ! 120: ring_addr[unit++] = (long) &(addr->enp_toenp); ! 121: ! 122: return( ENPSIZE ); ! 123: } ! 124: ! 125: /* ! 126: * Interface exists: make available by filling in network interface ! 127: * record. System will initialize the interface when it is ready ! 128: * to accept packets. ! 129: */ ! 130: ! 131: enpattach( md ) ! 132: register struct vba_device *md; ! 133: { ! 134: struct enp_softc *es = &enp_softc[md->ui_unit]; ! 135: register struct ifnet *ifp = &es->es_if; ! 136: register ENPDEVICE *addr = (ENPDEVICE *)md->ui_addr; ! 137: struct sockaddr_in *sin; ! 138: ! 139: enpgetaddr( md->ui_unit ); ! 140: ! 141: ifp->if_unit = md->ui_unit; ! 142: ifp->if_name = "enp"; ! 143: ifp->if_mtu = ETHERMTU; ! 144: ! 145: /* bcopy(&es->es_boardaddr, es->es_enaddr, sizeof(es->es_enaddr)); */ ! 146: ! 147: sin = (struct sockaddr_in *)&es->es_if.if_addr; ! 148: sin->sin_family = AF_INET; ! 149: ! 150: ifp->if_init = enpinit; ! 151: ifp->if_ioctl = enpioctl; ! 152: ifp->if_output = enpoutput; ! 153: ifp->if_reset = enpreset; ! 154: if_attach(ifp); ! 155: } ! 156: ! 157: ! 158: /* ! 159: * Reset of interface after UNIBUS reset. ! 160: */ ! 161: enpreset(unit) ! 162: int unit; ! 163: { ! 164: register struct vba_device *md; ! 165: ! 166: if (unit >= NENP || (md = enpinfo[unit]) == 0 || md->ui_alive == 0) ! 167: return(ENODEV); ! 168: ! 169: enpinit(unit); ! 170: } ! 171: ! 172: /* ! 173: * Initialization of interface; clear recorded pending ! 174: * operations. ! 175: */ ! 176: ! 177: enpinit( unit ) ! 178: int unit; ! 179: { ! 180: struct enp_softc *es = &enp_softc[unit]; ! 181: ENPDEVICE *addr; ! 182: int i, s; ! 183: u_char *cp, *ap; ! 184: register struct ifnet *ifp = &es->es_if; ! 185: register struct sockaddr_in *sin, *sinb; ! 186: ! 187: sin = (struct sockaddr_in *)&ifp->if_addr; ! 188: ! 189: if ( !enpismapped[unit] ) { ! 190: ioaccess(ENPmap[unit],ENPmapa[unit],ENPBPTE); ! 191: ++enpismapped[unit]; ! 192: } ! 193: if ((addr = (ENPDEVICE *)enpinfo[unit]->ui_addr) == (ENPDEVICE *)0) ! 194: return(ENODEV); ! 195: s = splimp(); ! 196: RESET_ENP( addr ); ! 197: DELAY( 200000 ); ! 198: ! 199: #ifdef notdef ! 200: /* only needed if not downloading ( ie, ROM-resident ENP code) */ ! 201: addr->enp_intrvec = intvec[unit]; ! 202: ENP_GO( addr,ENPSTART ); ! 203: DELAY( 200000 ); ! 204: /* end of ROM-resident */ ! 205: #endif notdef ! 206: ! 207: es->es_if.if_flags |= IFF_UP|IFF_RUNNING; /* open for business*/ ! 208: splx(s); ! 209: ! 210: if_rtinit( &es->es_if,RTF_UP ); ! 211: arpwhohas(&es->es_ac, &sin->sin_addr); ! 212: } ! 213: ! 214: ! 215: /* ! 216: * Ethernet interface interrupt. ! 217: */ ! 218: ! 219: enpintr( unit ) ! 220: { ! 221: register ENPDEVICE *addr; ! 222: register BCB *bcbp; ! 223: register struct vba_device *md; ! 224: ! 225: enp_intr++; ! 226: ! 227: if (unit >= NENP || (md = enpinfo[unit]) == 0) ! 228: return; ! 229: ! 230: addr = (ENPDEVICE *)md->ui_addr; ! 231: ! 232: if( IS_ENP_INTR(addr) == 0 ) ! 233: return; ! 234: ! 235: ACK_ENP_INTR( addr ); ! 236: ! 237: while( (bcbp = (BCB *)ringget( &addr->enp_tohost )) != 0 ) ! 238: { ! 239: enpread( &enp_softc[ unit ],bcbp, unit ); ! 240: ringput( &addr->enp_enpfree,bcbp ); ! 241: } ! 242: return(0); ! 243: } ! 244: ! 245: #define MAXBLEN 1500 ! 246: char errpkt[MAXBLEN]; ! 247: int bufptr = 0; ! 248: int maxl_tosave = 200; /* save only the first 200 bytes */ ! 249: ! 250: saverrpkt(errbuf, errtype, len) ! 251: register u_char *errbuf; ! 252: int errtype, len; ! 253: { ! 254: int remain, newptr; ! 255: ! 256: remain = MAXBLEN - bufptr; ! 257: if (remain < 50) /* if too small */ ! 258: return; /* no space avail */ ! 259: len = (len > maxl_tosave || len <= 0) ? maxl_tosave : len; ! 260: len = len > remain ? (remain - 2*sizeof(len)): len; ! 261: newptr = bufptr + len + 2*sizeof(len); ! 262: if (newptr <= MAXBLEN) { ! 263: enpcopy((char *)&len, &errpkt[bufptr], sizeof(len)); ! 264: enpcopy((char *)&errtype, &errpkt[bufptr+sizeof(len)], ! 265: sizeof(errtype)); ! 266: enpcopy(errbuf, &errpkt[bufptr+(2*sizeof(len))], len); ! 267: } ! 268: bufptr = newptr; ! 269: } ! 270: ! 271: /* ! 272: * Read input packet, examine its packet type, and enqueue it. ! 273: */ ! 274: ! 275: enpread( es, bcbp, unit ) ! 276: struct enp_softc *es; ! 277: register BCB *bcbp; ! 278: int unit; ! 279: { ! 280: register struct ether_header *enp; ! 281: struct mbuf *m; ! 282: long int s, v; ! 283: register short *vp = (short *)&v, ! 284: *sp; ! 285: int len, off, resid, enptype; ! 286: register struct ifqueue *inq; ! 287: ! 288: es->es_if.if_ipackets++; ! 289: ! 290: /* ! 291: * Get input data length. ! 292: * Get pointer to ethernet header (in input buffer). ! 293: * Deal with trailer protocol: if type is PUP trailer ! 294: * get true type from first 16-bit word past data. ! 295: * Remember that type was trailer by setting off. ! 296: */ ! 297: ! 298: len = bcbp->b_msglen - SIZEOF_ETHEADER; ! 299: #ifdef TAHOE ! 300: sp = (short *)&bcbp->b_addr; ! 301: *vp = *sp; vp[1] = sp[1]; ! 302: enp = (struct ether_header *) v; ! 303: #else ! 304: enp = (struct ether_header *)bcbp->b_addr; ! 305: #endif TAHOE ! 306: ! 307: #define enpdataaddr(enp, off, type) ((type)(((caddr_t)(((char *)enp)+SIZEOF_ETHEADER)+(off)))) ! 308: ! 309: enptype = enp->ether_type; ! 310: if (enptype >= ETHERPUP_TRAIL && enptype < ETHERPUP_TRAIL+ETHERPUP_NTRAILER) ! 311: { ! 312: off = (enptype - ETHERPUP_TRAIL) * 512; ! 313: if (off >= ETHERMTU) { ! 314: enperr[unit].bad_offset++; ! 315: ENPTRACE(saverrpkt((char *)enp, B_OFFSET, bcbp->b_msglen)); ! 316: ! 317: goto badinput; ! 318: } ! 319: enptype = *enpdataaddr(enp, off, u_short *); ! 320: resid = *(enpdataaddr(enp, off+2, u_short *)); ! 321: ! 322: if (off + resid > len) { ! 323: enperr[unit].bad_length++; ! 324: ENPTRACE(saverrpkt((char *)enp, B_LENGTH, bcbp->b_msglen)); ! 325: goto badinput; ! 326: } ! 327: len = off + resid; ! 328: } ! 329: else ! 330: off = 0; ! 331: ! 332: if( len == 0 ) { ! 333: enperr[unit].bad_length++; ! 334: ENPTRACE(saverrpkt((char *)enp, B_LENGTH, bcbp->b_msglen)); ! 335: goto badinput; ! 336: } ! 337: /* ! 338: * Pull packet off interface. Off is nonzero if packet ! 339: * has trailing header; enpget will then force this header ! 340: * information to be at the front, but we still have to drop ! 341: * the type and length which are at the front of any trailer data. ! 342: */ ! 343: ! 344: m = enpget(bcbp, len, off); ! 345: if( m == 0 ) { ! 346: enperr[unit].h_nobuffer++; /* host runs out of buf */ ! 347: goto badinput; ! 348: } ! 349: if( off ) ! 350: { ! 351: m->m_off += 2 * sizeof (u_short); ! 352: m->m_len -= 2 * sizeof (u_short); ! 353: } ! 354: ! 355: switch (enptype) ! 356: { ! 357: #ifdef INET ! 358: case ETHERPUP_IPTYPE: ! 359: #ifdef notdef ! 360: arpipin(enp, m); ! 361: #endif notdef ! 362: schednetisr(NETISR_IP); ! 363: inq = &ipintrq; ! 364: break; ! 365: ! 366: case ETHERPUP_ARPTYPE: ! 367: arpinput(&es->es_ac, m); ! 368: return(0); ! 369: #endif ! 370: default: /* unrecognized ethernet header */ ! 371: enperr[unit].bad_packetype++; ! 372: if (printerror) { ! 373: printf("\nenp%d: Undefined packet type 0x%x ", unit, ! 374: enp->ether_type); ! 375: printf("from host: %x.%x.%x.%x.%x.%x\n", ! 376: enp->ether_shost[0], enp->ether_shost[1], ! 377: enp->ether_shost[2], enp->ether_shost[3], ! 378: enp->ether_shost[4], enp->ether_shost[5]); ! 379: } /* end debugging aid */ ! 380: ENPTRACE(saverrpkt((char *)enp, B_PACKETYPE, bcbp->b_msglen)); ! 381: m_freem(m); ! 382: goto badinput; ! 383: } ! 384: ! 385: if (IF_QFULL(inq)) ! 386: { ! 387: enperr[unit].inq_full++; ! 388: IF_DROP(inq); ! 389: m_freem(m); ! 390: return(0); ! 391: } ! 392: s = splimp(); ! 393: IF_ENQUEUE(inq, m); ! 394: splx(s); ! 395: badinput: ! 396: return(0); /* sanity */ ! 397: } ! 398: ! 399: /* ! 400: * Ethernet output routine. (called by user) ! 401: * Encapsulate a packet of type family for the local net. ! 402: * Use trailer local net encapsulation if enough data in first ! 403: * packet leaves a multiple of 512 bytes of data in remainder. ! 404: * If destination is this address or broadcast, send packet to ! 405: * loop device to kludge around the fact that 3com interfaces can't ! 406: * talk to themselves. ! 407: */ ! 408: ! 409: enpoutput(ifp, m0, dst) ! 410: struct ifnet *ifp; ! 411: struct mbuf *m0; ! 412: struct sockaddr *dst; ! 413: { ! 414: int type, s, error; ! 415: struct ether_addr edst; ! 416: struct in_addr idst; ! 417: ! 418: register struct enp_softc *es = &enp_softc[ifp->if_unit]; ! 419: register struct mbuf *m = m0; ! 420: register struct ether_header *enp; ! 421: register int off, i; ! 422: ! 423: struct mbuf *mcopy = (struct mbuf *) 0; /* Null */ ! 424: int unit = ifp->if_unit; ! 425: ! 426: switch( dst->sa_family ) ! 427: { ! 428: #ifdef INET ! 429: case AF_INET: ! 430: idst = ((struct sockaddr_in *)dst)->sin_addr; ! 431: ! 432: /* translate internet to ethernet address */ ! 433: ! 434: switch(arpresolve(&es->es_ac, m, &idst, &edst)) { ! 435: ! 436: case ARPRESOLVE_WILLSEND: ! 437: return (0); /* if not yet resolved */ ! 438: case ARPRESOLVE_BROADCAST: ! 439: mcopy = m_copy(m, 0, (int)M_COPYALL); ! 440: if (mcopy) ! 441: looutput(&loif, mcopy, dst); ! 442: ! 443: /* falls through ... */ ! 444: case ARPRESOLVE_OK: ! 445: break; ! 446: } ! 447: off = ((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; ! 448: if ((ifp->if_flags & IFF_NOTRAILERS) == 0) ! 449: if (off > 0 && (off & 0x1ff) == 0 && ! 450: m->m_off >= MMINOFF + 2 * sizeof (u_short)) ! 451: { ! 452: type = ETHERPUP_TRAIL + (off>>9); ! 453: m->m_off -= 2 * sizeof (u_short); ! 454: m->m_len += 2 * sizeof (u_short); ! 455: *mtod(m, u_short *) = ETHERPUP_IPTYPE; ! 456: *(mtod(m, u_short *) + 1) = m->m_len; ! 457: goto gottrailertype; ! 458: } ! 459: ! 460: type = ETHERPUP_IPTYPE; ! 461: off = 0; ! 462: goto gottype; ! 463: #endif ! 464: ! 465: #ifdef notdef ! 466: case AF_RAW: ! 467: enp = mtod(m, struct ether_header *); ! 468: if (m->m_len < sizeof *enp) ! 469: { ! 470: error = EMSGSIZE; ! 471: goto bad; ! 472: } ! 473: goto gotheader; ! 474: #endif ! 475: ! 476: case AF_UNSPEC: ! 477: enp = (struct ether_header *)dst->sa_data; ! 478: bcopy( enp->ether_dhost, &edst, sizeof(edst)); ! 479: type = enp->ether_type; ! 480: goto gottype; ! 481: ! 482: default: ! 483: if (printerror) ! 484: printf("enp%d: can't handle af%d\n", unit,dst->sa_family); ! 485: error = EAFNOSUPPORT; ! 486: goto bad; ! 487: } ! 488: ! 489: gottrailertype: ! 490: /* ! 491: * Packet to be sent as trailer: move first packet ! 492: * (control information) to end of chain. ! 493: */ ! 494: while (m->m_next) ! 495: m = m->m_next; ! 496: m->m_next = m0; ! 497: m = m0->m_next; ! 498: m0->m_next = 0; ! 499: m0 = m; ! 500: ! 501: gottype: ! 502: /* ! 503: * Add local net header. If no space in first mbuf, ! 504: * allocate another. ! 505: */ ! 506: if (m->m_off > MMAXOFF || ! 507: MMINOFF + SIZEOF_ETHEADER > m->m_off) ! 508: { ! 509: m = m_get(M_DONTWAIT, MT_HEADER); ! 510: if (m == 0) ! 511: { ! 512: enperr[unit].h_nobuffer++; /* host runs out of buf */ ! 513: error = ENOBUFS; ! 514: goto bad; ! 515: } ! 516: m->m_next = m0; ! 517: m->m_off = MMINOFF; ! 518: m->m_len = SIZEOF_ETHEADER; ! 519: } ! 520: else ! 521: { ! 522: m->m_off -= SIZEOF_ETHEADER; ! 523: m->m_len += SIZEOF_ETHEADER; ! 524: } ! 525: enp = mtod(m, struct ether_header *); ! 526: bcopy( &edst, enp->ether_dhost, sizeof(enp->ether_dhost) ); ! 527: enp->ether_type = type; ! 528: gotheader: ! 529: bcopy( es->es_enaddr, enp->ether_shost, sizeof(enp->ether_shost)); ! 530: ! 531: /* ! 532: * Queue message on interface if possible ! 533: */ ! 534: ! 535: s = splimp(); ! 536: if( enpput( unit,m ) ) ! 537: { ! 538: error = ENOBUFS; ! 539: enperr[unit].c_nobuffer++; /* controller runs out of buf */ ! 540: goto qfull; ! 541: } ! 542: splx( s ); ! 543: es->es_if.if_opackets++; ! 544: return(0); ! 545: qfull: ! 546: splx( s ); ! 547: m0 = m; ! 548: bad: ! 549: m_freem(m0); ! 550: return(error); ! 551: } ! 552: ! 553: /* ! 554: * Routine to copy from mbuf chain to transmitter ! 555: * buffer in Multibus memory. ! 556: */ ! 557: ! 558: enpput( unit,m ) ! 559: int unit; ! 560: struct mbuf *m; ! 561: { ! 562: register BCB *bcbp; ! 563: register ENPDEVICE *addr; ! 564: register struct mbuf *mp; ! 565: register u_char *bp; ! 566: int ctr = 0; ! 567: long int v; ! 568: register short *vp = (short *)&v, ! 569: *sp; ! 570: ! 571: addr = (ENPDEVICE *)enpinfo[ unit ]->ui_addr; ! 572: ! 573: if ( ringempty( &addr->enp_hostfree ) ) ! 574: return( 1 ); ! 575: ! 576: bcbp = (BCB *)ringget( &addr->enp_hostfree ); ! 577: bcbp->b_len = 0; ! 578: #ifdef TAHOE ! 579: sp = (short *)&bcbp->b_addr; ! 580: *vp = *sp; vp[1] = sp[1]; ! 581: bp = (u_char *)v; ! 582: #else ! 583: bp = (u_char *)bcbp->b_addr; ! 584: #endif TAHOE ! 585: for (mp = m; mp; mp = mp->m_next) ! 586: { ! 587: register unsigned len; ! 588: u_char *mcp; ! 589: ! 590: len = mp->m_len; ! 591: if( len == 0 ) ! 592: continue; ! 593: mcp = mtod( mp,u_char * ); ! 594: enpcopy( mcp,bp,len ); ! 595: bp += len; ! 596: bcbp->b_len += len; ! 597: } ! 598: bcbp->b_len = max( MINPKTSIZE,bcbp->b_len ); ! 599: bcbp->b_reserved = 0; ! 600: if ( ringput( &addr->enp_toenp,bcbp ) == 1 ) { ! 601: host_intr++; ! 602: INTR_ENP( addr ); ! 603: } ! 604: m_freem(m); ! 605: return( 0 ); ! 606: } ! 607: ! 608: /* ! 609: * Routine to copy from Multibus memory into mbufs. ! 610: * ! 611: * Warning: This makes the fairly safe assumption that ! 612: * mbufs have even lengths. ! 613: */ ! 614: struct mbuf * ! 615: enpget( bcbp, totlen, off0 ) ! 616: register BCB *bcbp; ! 617: int totlen, off0; ! 618: { ! 619: register struct mbuf *m; ! 620: register int off = off0; ! 621: register unsigned char *cp; ! 622: long int v; ! 623: register short *vp = (short *)&v, ! 624: *sp; ! 625: ! 626: int len; ! 627: struct mbuf *top = 0; ! 628: struct mbuf **mp = ⊤ ! 629: ! 630: #ifdef TAHOE ! 631: sp = (short *)&bcbp->b_addr; ! 632: *vp = *sp; vp[1] = sp[1]; ! 633: cp = (unsigned char *)v + SIZEOF_ETHEADER; ! 634: #else ! 635: cp = (unsigned char *)bcbp->b_addr + SIZEOF_ETHEADER; ! 636: #endif TAHOE ! 637: ! 638: while( totlen > 0 ) ! 639: { ! 640: u_char *mcp; ! 641: ! 642: MGET(m, M_DONTWAIT, MT_DATA); ! 643: if (m == 0) ! 644: goto bad; ! 645: if( off ) ! 646: { ! 647: len = totlen - off; ! 648: #ifdef TAHOE ! 649: sp = (short *)&bcbp->b_addr; ! 650: *vp = *sp; vp[1] = sp[1]; ! 651: cp = (unsigned char *)v + SIZEOF_ETHEADER ! 652: + off; ! 653: #else ! 654: cp = (unsigned char *)bcbp->b_addr + ! 655: SIZEOF_ETHEADER + off; ! 656: #endif TAHOE ! 657: } ! 658: else ! 659: len = totlen; ! 660: ! 661: ! 662: if (len >= CLBYTES) { ! 663: struct mbuf *p; ! 664: ! 665: MCLGET(p, 1); ! 666: if (p != 0) { ! 667: m->m_len = len = CLBYTES; ! 668: m->m_off = (int)p - (int)m; ! 669: } else { ! 670: m->m_len = len = MIN(MLEN, len); ! 671: m->m_off = MMINOFF; ! 672: } ! 673: } else { ! 674: m->m_len = len = MIN(MLEN, len); ! 675: m->m_off = MMINOFF; ! 676: } ! 677: ! 678: mcp = mtod(m, u_char *); ! 679: enpcopy(cp, mcp, len); ! 680: cp += len; ! 681: *mp = m; ! 682: mp = &m->m_next; ! 683: if (off == 0) ! 684: { ! 685: totlen -= len; ! 686: continue; ! 687: } ! 688: off += len; ! 689: if (off == totlen) ! 690: { ! 691: #ifdef TAHOE ! 692: sp = (short *)&bcbp->b_addr; ! 693: *vp = *sp; vp[1] = sp[1]; ! 694: cp = (unsigned char *)v + SIZEOF_ETHEADER; ! 695: #else ! 696: cp = (unsigned char *)bcbp->b_addr + SIZEOF_ETHEADER; ! 697: #endif TAHOE ! 698: off = 0; ! 699: totlen = off0; ! 700: } ! 701: } ! 702: return (top); ! 703: bad: ! 704: m_freem(top); ! 705: return (0); ! 706: } ! 707: ! 708: /* ! 709: * Process an ioctl request. ! 710: * this can be called via the "socket" route for SIOCSIFADDR or ! 711: * by the cdev/inode route for SIOCSIFCCFWR/RD ! 712: * ! 713: */ ! 714: ! 715: enpioctl(ifp, cmd, data) ! 716: register struct ifnet *ifp; ! 717: int cmd; ! 718: caddr_t data; ! 719: { ! 720: register int unit = ifp->if_unit; ! 721: register struct vba_device *md; ! 722: int s, error = 0; ! 723: struct sockaddr_in *sin; ! 724: struct sockaddr *sa; ! 725: struct enp_softc *es = &enp_softc[ifp->if_unit]; ! 726: ENPDEVICE *addr; ! 727: struct config_entry *cf; ! 728: struct ifreq *ifr = (struct ifreq *)data; ! 729: struct sockaddr_in *et_addr; ! 730: int code, i; ! 731: ! 732: ! 733: if (unit >= NENP || (md = enpinfo[unit]) == 0 || md->ui_alive == 0) ! 734: return(ENODEV); ! 735: ! 736: switch (cmd) { ! 737: ! 738: case SIOCSIFADDR: ! 739: s = splimp(); ! 740: sa = (struct sockaddr *)&ifr->ifr_addr; ! 741: if (sa->sa_family == AF_UNSPEC ) { ! 742: if (sa->sa_data[0] & 1){ /*broad or multi-cast*/ ! 743: splx( s ); ! 744: return( EINVAL ); ! 745: } ! 746: bcopy(sa->sa_data,es->es_enaddr,sizeof(es->es_enaddr)); ! 747: enpinit( ifp->if_unit); ! 748: break; ! 749: } ! 750: sin = (struct sockaddr_in *)&ifr->ifr_addr; ! 751: if (sin->sin_family != AF_INET){ ! 752: splx( s ); ! 753: return( EINVAL ); ! 754: } ! 755: if (ifp->if_flags & IFF_RUNNING) ! 756: if_rtinit(ifp, -1); /* delete previous route */ ! 757: enpsetaddr(ifp, sin); ! 758: enpinit(ifp->if_unit); ! 759: enpgetaddr( ifp->if_unit ); ! 760: splx(s); ! 761: break; ! 762: ! 763: ! 764: case SIOCSETETADDR: /* Set Ethernet station address */ ! 765: s = splimp(); ! 766: ifp->if_flags &= (~IFF_RUNNING | IFF_UP); ! 767: et_addr = (struct sockaddr_in *)&ifr->ifr_addr; ! 768: addr = (ENPDEVICE *)enpinfo[ifp->if_unit]->ui_addr; ! 769: ! 770: /* Set station address and reset controller board */ ! 771: { ! 772: u_char *to = &addr->enp_addr.e_baseaddr.ea_addr[0]; ! 773: char *from = &et_addr->sin_zero[2]; ! 774: int i; ! 775: ! 776: for (i = 0 ; i < ETHADDR_SIZE; i++) ! 777: *to++ = (u_char) (~(*from++ & 0xff)); ! 778: } ! 779: enpcopy(&addr->enp_addr.e_listsize, &code, sizeof(code)); ! 780: code |= E_ADDR_SUPP; ! 781: enpcopy(&code, &addr->enp_addr.e_listsize, sizeof(code)); ! 782: enpreset(ifp->if_unit); /* Re-initialize */ ! 783: enpgetaddr(ifp->if_unit); ! 784: splx(s); ! 785: break; ! 786: ! 787: case SIOCGETETADDR: /* Get Foreign Hosts' Ethernet addresses */ ! 788: arpwhohas(&es->es_ac, (struct in_addr *)ifr->ifr_data); ! 789: break; ! 790: ! 791: default: ! 792: error = EINVAL; ! 793: } ! 794: return(error); ! 795: } ! 796: ! 797: enpsetaddr(ifp, sin) ! 798: register struct ifnet *ifp; ! 799: register struct sockaddr_in *sin; ! 800: { ! 801: ! 802: ifp->if_addr = *(struct sockaddr *)sin; ! 803: ifp->if_net = in_netof(sin->sin_addr); ! 804: ifp->if_host[0] = in_lnaof(sin->sin_addr); ! 805: sin = (struct sockaddr_in *)&ifp->if_broadaddr; ! 806: sin->sin_family = AF_INET; ! 807: sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY); ! 808: ifp->if_flags |= IFF_BROADCAST; ! 809: } ! 810: ! 811: ! 812: /* ! 813: * Get the ethernet addr, store it and print it ! 814: * Read the ethernet address off the board, one byte at a time. ! 815: * put it in enp_softc ! 816: */ ! 817: ! 818: ! 819: enpgetaddr( unit ) ! 820: int unit; ! 821: { ! 822: register struct enp_softc *es = &enp_softc[unit]; ! 823: register ENPDEVICE *addr =(ENPDEVICE *)enpinfo[unit]->ui_addr; ! 824: int i; ! 825: ! 826: #ifdef TAHOE ! 827: enpcopy(&addr->enp_addr.e_baseaddr, &es->es_boardaddr, sizeof(es->es_boardaddr)); ! 828: #else ! 829: es->es_boardaddr = addr->enp_addr.e_baseaddr; ! 830: #endif TAHOE ! 831: bcopy(&es->es_boardaddr, es->es_enaddr, ETHADDR_SIZE); ! 832: return( 1 ); ! 833: } ! 834: ! 835: /* ! 836: * enpram device ! 837: * ! 838: */ ! 839: ! 840: enpr_open( dev ) ! 841: { ! 842: register int unit = minor(dev); ! 843: register struct vba_device *md; ! 844: register ENPDEVICE *addr; ! 845: ! 846: if (unit >= NENP || (md = enpinfo[unit]) == 0 || md->ui_alive == 0 || ! 847: (addr = (ENPDEVICE *)md->ui_addr) == (ENPDEVICE *)0) ! 848: return(ENODEV); ! 849: if (addr->enp_state != S_ENPRESET) ! 850: return(EACCES); /* enp is not in reset state, don't open */ ! 851: if ( !enpismapped[unit] ) { ! 852: ioaccess(ENPmap[unit],ENPmapa[unit],ENPBPTE); ! 853: ++enpismapped[unit]; ! 854: } ! 855: enpram[unit] = ENP_OPEN; ! 856: return( 0 ); ! 857: } ! 858: ! 859: enpr_close(dev) ! 860: { ! 861: enpram[minor(dev)] = ENP_CLOSE; ! 862: return( 0 ); ! 863: } ! 864: ! 865: enpr_read( dev,uio ) ! 866: int dev; ! 867: register struct uio *uio; ! 868: { ! 869: register ENPDEVICE *addr; ! 870: register struct iovec *iov; ! 871: register r=0; ! 872: ! 873: if (enpram[minor(dev)] != ENP_OPEN) ! 874: return(EACCES); ! 875: if ( uio->uio_offset > RAM_SIZE ) ! 876: return( ENODEV ); ! 877: if ( uio->uio_offset + iov->iov_len > RAM_SIZE ) ! 878: iov->iov_len = RAM_SIZE - uio->uio_offset; ! 879: addr = (ENPDEVICE *)enpinfo[ minor( dev ) ]->ui_addr; ! 880: iov = uio->uio_iov; ! 881: ! 882: if( r = enpcopyout( &addr->enp_ram[ uio->uio_offset ], iov->iov_base, ! 883: iov->iov_len ) ) ! 884: return( r ); ! 885: ! 886: uio->uio_resid -= iov->iov_len; ! 887: iov->iov_len = 0; ! 888: ! 889: return( 0 ); ! 890: } ! 891: ! 892: enpr_write( dev,uio ) ! 893: int dev; ! 894: register struct uio *uio; ! 895: { ! 896: register ENPDEVICE *addr; ! 897: register struct iovec *iov; ! 898: register r=0; ! 899: ! 900: if (enpram[minor(dev)] != ENP_OPEN) ! 901: return(EACCES); ! 902: addr = (ENPDEVICE *)enpinfo[ minor( dev ) ]->ui_addr; ! 903: iov = uio->uio_iov; ! 904: ! 905: if ( uio->uio_offset > RAM_SIZE ) ! 906: return( ENODEV ); ! 907: if ( uio->uio_offset + iov->iov_len > RAM_SIZE ) ! 908: iov->iov_len = RAM_SIZE - uio->uio_offset; ! 909: if( r = enpcopyin( iov->iov_base, &addr->enp_ram[ uio->uio_offset ], ! 910: iov->iov_len ) ) ! 911: return( r ); ! 912: ! 913: uio->uio_resid -= iov->iov_len; ! 914: iov->iov_len = 0; ! 915: ! 916: return( 0 ); ! 917: } ! 918: ! 919: enpr_ioctl( dev,cmd,arg,fflag ) ! 920: dev_t dev; ! 921: caddr_t *arg; ! 922: { ! 923: register ENPDEVICE *addr; ! 924: long int v; ! 925: register short *vp = (short *)&v, *sp; ! 926: register unit = minor(dev); ! 927: register struct vba_device *md; ! 928: ! 929: if (unit >= NENP || (md = enpinfo[unit]) == 0 || md->ui_alive == 0 || ! 930: (addr = (ENPDEVICE *)md->ui_addr) == (ENPDEVICE *)0) ! 931: return(ENODEV); ! 932: switch( cmd ) ! 933: { ! 934: case ENPIOGO: ! 935: /* not needed if prom based version */ ! 936: #ifdef TAHOE ! 937: sp = (short *)&addr->enp_base; ! 938: v = (int)addr; ! 939: *sp = *vp; sp[1] = vp[1]; ! 940: #else ! 941: addr->enp_base = (int)addr; ! 942: #endif TAHOE ! 943: addr->enp_intrvec = intvec[ unit ]; ! 944: ENP_GO( addr, ENPSTART ); ! 945: DELAY( 200000 ); ! 946: enpattach( enpinfo[ unit ] ); ! 947: enpinit( unit ); ! 948: addr->enp_state = S_ENPRUN; /* it is running now */ ! 949: /* end of not needed */ ! 950: ! 951: break; ! 952: ! 953: case ENPIORESET: ! 954: RESET_ENP( addr ); ! 955: addr->enp_state = S_ENPRESET; /* it is reset now */ ! 956: DELAY( 100000 ); ! 957: break; ! 958: } ! 959: return( 0 ); ! 960: } ! 961: ! 962: /* ! 963: * routines to synchronize enp and host ! 964: */ ! 965: ! 966: static ! 967: ringinit( rp,size ) ! 968: register RING *rp; ! 969: { ! 970: register int i; ! 971: register short *sp; ! 972: ! 973: rp->r_rdidx = rp->r_wrtidx = 0; ! 974: rp->r_size = size; ! 975: } ! 976: ! 977: static ! 978: ringempty( rp ) ! 979: register RING *rp; ! 980: { ! 981: return( rp->r_rdidx == rp->r_wrtidx ); ! 982: } ! 983: ! 984: static ! 985: ringfull( rp ) ! 986: register RING *rp; ! 987: { ! 988: register short idx; ! 989: ! 990: idx = (rp->r_wrtidx + 1) & (rp->r_size-1); ! 991: return( idx == rp->r_rdidx ); ! 992: } ! 993: ! 994: static ! 995: ringput( rp,v ) ! 996: register RING *rp; ! 997: { ! 998: register int idx; ! 999: register short *vp = (short *)&v, ! 1000: *sp; ! 1001: ! 1002: idx = (rp->r_wrtidx + 1) & (rp->r_size-1); ! 1003: if( idx != rp->r_rdidx ) ! 1004: { ! 1005: #ifdef TAHOE ! 1006: sp = (short *)&rp->r_slot[ rp->r_wrtidx ]; ! 1007: *sp = *vp; sp[1] = vp[1]; ! 1008: #else ! 1009: rp->r_slot[ rp->r_wrtidx ] = v; ! 1010: #endif TAHOE ! 1011: rp->r_wrtidx = idx; ! 1012: if( (idx -= rp->r_rdidx) < 0 ) ! 1013: idx += rp->r_size; ! 1014: return( idx ); /* num ring entries */ ! 1015: } ! 1016: return( 0 ); ! 1017: } ! 1018: ! 1019: static ! 1020: ringget( rp ) ! 1021: register RING *rp; ! 1022: { ! 1023: register int i = 0; ! 1024: long int v; ! 1025: register short *vp = (short *)&v, ! 1026: *sp; ! 1027: ! 1028: if( rp->r_rdidx != rp->r_wrtidx ) ! 1029: { ! 1030: #ifdef TAHOE ! 1031: sp = (short *)&rp->r_slot[ rp->r_rdidx ]; ! 1032: *vp = *sp; vp[1] = sp[1]; ! 1033: i = v; ! 1034: #else ! 1035: i = rp->r_slot[ rp->r_rdidx ]; ! 1036: #endif TAHOE ! 1037: rp->r_rdidx = (++rp->r_rdidx) & (rp->r_size-1); ! 1038: } ! 1039: return( i ); ! 1040: } ! 1041: ! 1042: #ifdef notdef ! 1043: struct mbuf * ! 1044: m_tofree( rp ) ! 1045: register RING *rp; ! 1046: { ! 1047: long int v = 0; ! 1048: register short *vp = (short *)&v, ! 1049: *sp; ! 1050: ! 1051: if( rp->r_rdidx != rp->r_wrtidx ) ! 1052: { ! 1053: #ifdef TAHOE ! 1054: sp = (short *)&rp->r_slot[ rp->r_rdidx ]; ! 1055: *vp = *sp; vp[1] = sp[1]; ! 1056: /* *sp = 0xffff; sp[1] = 0xffff; */ ! 1057: #else ! 1058: v = rp->r_slot[ rp->r_rdidx ]; ! 1059: #endif TAHOE ! 1060: rp->r_rdidx = (++rp->r_rdidx) & (rp->r_size-1); ! 1061: } ! 1062: return( (struct mbuf *)v ); ! 1063: } ! 1064: #endif ! 1065: static ! 1066: fir( rp ) ! 1067: register RING *rp; ! 1068: { ! 1069: long int v; ! 1070: register short *vp = (short *)&v, ! 1071: *sp; ! 1072: ! 1073: if( rp->r_rdidx != rp->r_wrtidx ) ! 1074: #ifdef TAHOE ! 1075: { ! 1076: sp = (short *)&rp->r_slot[ rp->r_rdidx ]; ! 1077: *vp = *sp; vp[1] = sp[1]; ! 1078: return( v ); ! 1079: } ! 1080: #else ! 1081: return( rp->r_slot[ rp->r_rdidx ] ); ! 1082: #endif TAHOE ! 1083: else ! 1084: return( 0 ); ! 1085: } ! 1086: ! 1087: ! 1088: static ! 1089: prtbytes( addr ) ! 1090: register char *addr; ! 1091: { ! 1092: register int i; ! 1093: ! 1094: for( i = 0; i < 12; i++ ) ! 1095: { ! 1096: printf("%X ",*addr&0377); ! 1097: addr++; ! 1098: } ! 1099: printf("\n"); ! 1100: } ! 1101: ! 1102: static ! 1103: enpcopy(from, to, cnt) ! 1104: register char *from, *to; ! 1105: register cnt; ! 1106: { ! 1107: register c; ! 1108: register short *f, *t; ! 1109: ! 1110: if (((int)from & 01) && ((int)to & 01)) { ! 1111: /* source & dest at odd addresses */ ! 1112: *to++ = *from++; ! 1113: --cnt; ! 1114: } ! 1115: if (cnt > 1 && (((int)to & 01)==0) && (((int)from & 01)==0)) { ! 1116: t = (short *) to; ! 1117: f = (short *) from; ! 1118: for( c = cnt>>1; c; --c) /* even address copy */ ! 1119: *t++ = *f++; ! 1120: cnt &= 1; ! 1121: if ( cnt ) { /* odd len */ ! 1122: from = (char *) f; ! 1123: to = (char *) t; ! 1124: *to = *from; ! 1125: } ! 1126: } ! 1127: while (cnt-- > 0) /* one of the address(es) must be odd */ ! 1128: *to++ = *from++; ! 1129: ! 1130: } ! 1131: ! 1132: static ! 1133: enpcopyin(userv, kernv, cnt) ! 1134: { ! 1135: ! 1136: if (useracc(userv, cnt, 1)) { ! 1137: enpcopy( userv, kernv, cnt ); ! 1138: return( 0 ); ! 1139: } ! 1140: else return( EFAULT ); ! 1141: } ! 1142: ! 1143: ! 1144: static ! 1145: enpcopyout(kernv, userv, cnt) ! 1146: { ! 1147: ! 1148: if (useracc(userv, cnt, 0)) { ! 1149: enpcopy( kernv, userv, cnt ); ! 1150: return( 0 ); ! 1151: } ! 1152: else return( EFAULT ); ! 1153: } ! 1154: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.