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