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