1 /* if_enp.c 1.2 86/11/29 */ 2 3 #include "enp.h" 4 #if NENP > 0 5 /* 6 * Modified 3Com Ethernet Controller interface 7 * enp modifications added S. F. Holmgren 8 * 9 * UNTESTED WITH 4.3 10 */ 11 #include "param.h" 12 #include "systm.h" 13 #include "mbuf.h" 14 #include "buf.h" 15 #include "protosw.h" 16 #include "socket.h" 17 #include "vmmac.h" 18 #include "ioctl.h" 19 #include "errno.h" 20 #include "vmparam.h" 21 #include "syslog.h" 22 #include "uio.h" 23 24 #include "../net/if.h" 25 #include "../net/netisr.h" 26 #include "../net/route.h" 27 #ifdef INET 28 #include "../netinet/in.h" 29 #include "../netinet/in_systm.h" 30 #include "../netinet/in_var.h" 31 #include "../netinet/ip.h" 32 #include "../netinet/ip_var.h" 33 #include "../netinet/if_ether.h" 34 #endif 35 #ifdef NS 36 #include "../netns/ns.h" 37 #include "../netns/ns_if.h" 38 #endif 39 40 #include "../tahoe/cpu.h" 41 #include "../tahoe/pte.h" 42 #include "../tahoe/mtpr.h" 43 44 #include "../tahoevba/vbavar.h" 45 #include "../tahoeif/if_enpreg.h" 46 47 #define ENPVEC 0xc1 48 #define ENPSTART 0xf02000 /* standard enp start addr */ 49 #define ENPUNIT(dev) (minor(dev)) /* for enp ram devices */ 50 51 int enpprobe(), enpattach(), enpintr(); 52 long enpstd[] = { 0xf41000, 0xf61000, 0 }; 53 struct vba_device *enpinfo[NENP]; 54 struct vba_driver enpdriver = 55 { enpprobe, 0, enpattach, 0, enpstd, "enp", enpinfo, "enp-20", 0 }; 56 57 int enpinit(), enpioctl(), enpreset(), enpoutput(); 58 struct mbuf *enpget(); 59 60 /* 61 * Ethernet software status per interface. 62 * 63 * Each interface is referenced by a network interface structure, 64 * es_if, which the routing code uses to locate the interface. 65 * This structure contains the output queue for the interface, its address, ... 66 */ 67 struct enp_softc { 68 struct arpcom es_ac; /* common ethernet structures */ 69 #define es_if es_ac.ac_if 70 #define es_enaddr es_ac.ac_enaddr 71 short es_flags; /* flags for devices */ 72 short es_ivec; /* interrupt vector */ 73 struct pte *es_map; /* map for dual ported memory */ 74 caddr_t es_ram; /* virtual address of mapped memory */ 75 } enp_softc[NENP]; 76 extern struct ifnet loif; 77 78 enpprobe(reg, vi) 79 caddr_t reg; 80 struct vba_device *vi; 81 { 82 register br, cvec; /* must be r12, r11 */ 83 register struct enpdevice *addr = (struct enpdevice *)reg; 84 struct enp_softc *es = &enp_softc[vi->ui_unit]; 85 86 #ifdef lint 87 enpintr(0); 88 #endif 89 if (badaddr(addr, 2) || badaddr(&addr->enp_ram[0], 2)) 90 return (0); 91 es->es_ivec = --vi->ui_hd->vh_lastiv; 92 addr->enp_state = S_ENPRESET; /* reset by VERSAbus reset */ 93 br = 0x14, cvec = es->es_ivec; /* XXX */ 94 return (sizeof (struct enpdevice)); 95 } 96 97 /* 98 * Interface exists: make available by filling in network interface 99 * record. System will initialize the interface when it is ready 100 * to accept packets. 101 */ 102 enpattach(ui) 103 register struct vba_device *ui; 104 { 105 struct enp_softc *es = &enp_softc[ui->ui_unit]; 106 register struct ifnet *ifp = &es->es_if; 107 register struct enpdevice *addr = (struct enpdevice *)ui->ui_addr; 108 109 ifp->if_unit = ui->ui_unit; 110 ifp->if_name = "enp"; 111 ifp->if_mtu = ETHERMTU; 112 /* 113 * Get station's addresses. 114 */ 115 enpcopy(&addr->enp_addr.e_baseaddr, es->es_enaddr, 116 sizeof (es->es_enaddr)); 117 printf("enp%d: hardware address %s\n", ui->ui_unit, 118 ether_sprintf(es->es_enaddr)); 119 /* 120 * Allocate and map ram. 121 */ 122 vbmemalloc(128, ((caddr_t)addr)+0x1000, &es->es_map, &es->es_ram); 123 124 ifp->if_init = enpinit; 125 ifp->if_ioctl = enpioctl; 126 ifp->if_output = enpoutput; 127 ifp->if_reset = enpreset; 128 ifp->if_flags = IFF_BROADCAST; 129 if_attach(ifp); 130 } 131 132 /* 133 * Reset of interface after "system" reset. 134 */ 135 enpreset(unit, vban) 136 int unit, vban; 137 { 138 register struct vba_device *ui; 139 140 if (unit >= NENP || (ui = enpinfo[unit]) == 0 || ui->ui_alive == 0 || 141 ui->ui_vbanum != vban) 142 return; 143 printf(" enp%d", unit); 144 enpinit(unit); 145 } 146 147 /* 148 * Initialization of interface; clear recorded pending operations. 149 */ 150 enpinit(unit) 151 int unit; 152 { 153 struct enp_softc *es = &enp_softc[unit]; 154 register struct vba_device *ui = enpinfo[unit]; 155 struct enpdevice *addr; 156 register struct ifnet *ifp = &es->es_if; 157 int s; 158 159 if (ifp->if_addrlist == (struct ifaddr *)0) 160 return; 161 if ((ifp->if_flags & IFF_RUNNING) == 0) { 162 addr = (struct enpdevice *)ui->ui_addr; 163 s = splimp(); 164 RESET_ENP(addr); 165 DELAY(200000); 166 addr->enp_intrvec = es->es_ivec; 167 es->es_if.if_flags |= IFF_RUNNING; 168 splx(s); 169 } 170 } 171 172 /* 173 * Ethernet interface interrupt. 174 */ 175 enpintr(unit) 176 int unit; 177 { 178 register struct enpdevice *addr; 179 register BCB *bcbp; 180 181 addr = (struct enpdevice *)enpinfo[unit]->ui_addr; 182 if (!IS_ENP_INTR(addr)) 183 return; 184 ACK_ENP_INTR(addr); 185 while ((bcbp = (BCB *)ringget(&addr->enp_tohost )) != 0) { 186 (void) enpread(&enp_softc[unit], bcbp, unit); 187 ringput(&addr->enp_enpfree, bcbp); 188 } 189 } 190 191 /* 192 * Read input packet, examine its packet type, and enqueue it. 193 */ 194 enpread(es, bcbp, unit) 195 struct enp_softc *es; 196 register BCB *bcbp; 197 int unit; 198 { 199 register struct ether_header *enp; 200 struct mbuf *m; 201 long int s; 202 int len, off, resid, enptype; 203 register struct ifqueue *inq; 204 205 es->es_if.if_ipackets++; 206 /* 207 * Get input data length. 208 * Get pointer to ethernet header (in input buffer). 209 * Deal with trailer protocol: if type is PUP trailer 210 * get true type from first 16-bit word past data. 211 * Remember that type was trailer by setting off. 212 */ 213 len = bcbp->b_msglen - sizeof (struct ether_header); 214 enp = (struct ether_header *)bcbp->b_addr; 215 #define enpdataaddr(enp, off, type) \ 216 ((type)(((caddr_t)(((char *)enp)+sizeof (struct ether_header))+(off)))) 217 enp->ether_type = ntohs((u_short)enp->ether_type); 218 if (enp->ether_type >= ETHERTYPE_TRAIL && 219 enp->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 220 off = (enp->ether_type - ETHERTYPE_TRAIL) * 512; 221 if (off >= ETHERMTU) 222 goto setup; 223 enp->ether_type = ntohs(*enpdataaddr(enp, off, u_short *)); 224 resid = ntohs(*(enpdataaddr(enp, off+2, u_short *))); 225 if (off + resid > len) 226 goto setup; 227 len = off + resid; 228 } else 229 off = 0; 230 if (len == 0) 231 goto setup; 232 233 /* 234 * Pull packet off interface. Off is nonzero if packet 235 * has trailing header; enpget will then force this header 236 * information to be at the front, but we still have to drop 237 * the type and length which are at the front of any trailer data. 238 */ 239 m = enpget(bcbp->b_addr, len, off, &es->es_if); 240 if (m == 0) 241 goto setup; 242 if (off) { 243 struct ifnet *ifp; 244 245 ifp = *(mtod(m, struct ifnet **)); 246 m->m_off += 2 * sizeof (u_short); 247 m->m_len -= 2 * sizeof (u_short); 248 *(mtod(m, struct ifnet **)) = ifp; 249 } 250 switch (enp->ether_type) { 251 252 #ifdef INET 253 case ETHERTYPE_IP: 254 schednetisr(NETISR_IP); 255 inq = &ipintrq; 256 break; 257 #endif 258 case ETHERTYPE_ARP: 259 arpinput(&es->es_ac, m); 260 goto setup; 261 262 #ifdef NS 263 case ETHERTYPE_NS: 264 schednetisr(NETISR_NS); 265 inq = &nsintrq; 266 break; 267 #endif 268 default: 269 m_freem(m); 270 goto setup; 271 } 272 if (IF_QFULL(inq)) { 273 IF_DROP(inq); 274 m_freem(m); 275 goto setup; 276 } 277 s = splimp(); 278 IF_ENQUEUE(inq, m); 279 splx(s); 280 setup: 281 return (0); 282 } 283 284 /* 285 * Ethernet output routine. (called by user) 286 * Encapsulate a packet of type family for the local net. 287 * Use trailer local net encapsulation if enough data in first 288 * packet leaves a multiple of 512 bytes of data in remainder. 289 * If destination is this address or broadcast, send packet to 290 * loop device to kludge around the fact that 3com interfaces can't 291 * talk to themselves. 292 */ 293 enpoutput(ifp, m0, dst) 294 struct ifnet *ifp; 295 struct mbuf *m0; 296 struct sockaddr *dst; 297 { 298 register struct enp_softc *es = &enp_softc[ifp->if_unit]; 299 register struct mbuf *m = m0; 300 register struct ether_header *enp; 301 register int off, i; 302 struct mbuf *mcopy = (struct mbuf *)0; 303 int type, s, error, usetrailers; 304 u_char edst[6]; 305 struct in_addr idst; 306 307 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 308 error = ENETDOWN; 309 goto bad; 310 } 311 switch (dst->sa_family) { 312 #ifdef INET 313 case AF_INET: 314 idst = ((struct sockaddr_in *)dst)->sin_addr; 315 if (!arpresolve(&es->es_ac, m, &idst, edst, &usetrailers)) 316 return (0); /* if not yet resolved */ 317 if (!bcmp((caddr_t)edst, (caddr_t)etherbroadcastaddr, 318 sizeof (edst))) 319 mcopy = m_copy(m, 0, (int)M_COPYALL); 320 off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; 321 if (usetrailers && off > 0 && (off & 0x1ff) == 0 && 322 m->m_off >= MMINOFF + 2 * sizeof (u_short)) { 323 type = ETHERTYPE_TRAIL + (off>>9); 324 m->m_off -= 2 * sizeof (u_short); 325 m->m_len += 2 * sizeof (u_short); 326 *mtod(m, u_short *) = ETHERTYPE_IP; 327 *(mtod(m, u_short *) + 1) = m->m_len; 328 goto gottrailertype; 329 } 330 type = ETHERTYPE_IP; 331 off = 0; 332 goto gottype; 333 #endif 334 #ifdef NS 335 case AF_NS: 336 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 337 (caddr_t)edst, sizeof (edst)); 338 if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof (edst))) 339 mcopy = m_copy(m, 0, (int)M_COPYALL); 340 else if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, 341 sizeof (edst))) 342 return (looutput(&loif, m, dst)); 343 type = ETHERTYPE_NS; 344 off = 0; 345 goto gottype; 346 #endif 347 case AF_UNSPEC: 348 enp = (struct ether_header *)dst->sa_data; 349 bcopy((caddr_t)enp->ether_dhost, (caddr_t)edst, sizeof (edst)); 350 type = enp->ether_type; 351 goto gottype; 352 353 default: 354 log(LOG_ERR, "enp%d: can't handle af%d\n", 355 ifp->if_unit, dst->sa_family); 356 error = EAFNOSUPPORT; 357 goto bad; 358 } 359 360 gottrailertype: 361 /* 362 * Packet to be sent as trailer: move first packet 363 * (control information) to end of chain. 364 */ 365 while (m->m_next) 366 m = m->m_next; 367 m->m_next = m0; 368 m = m0->m_next; 369 m0->m_next = 0; 370 m0 = m; 371 372 gottype: 373 /* 374 * Add local net header. If no space in first mbuf, 375 * allocate another. 376 */ 377 if (m->m_off > MMAXOFF || 378 MMINOFF + sizeof (struct ether_header) > m->m_off) { 379 m = m_get(M_DONTWAIT, MT_HEADER); 380 if (m == 0) { 381 error = ENOBUFS; 382 goto bad; 383 } 384 m->m_next = m0; 385 m->m_off = MMINOFF; 386 m->m_len = sizeof (struct ether_header); 387 } else { 388 m->m_off -= sizeof (struct ether_header); 389 m->m_len += sizeof (struct ether_header); 390 } 391 enp = mtod(m, struct ether_header *); 392 bcopy((caddr_t)edst, (caddr_t)enp->ether_dhost, sizeof (edst)); 393 bcopy((caddr_t)es->es_enaddr, (caddr_t)enp->ether_shost, 394 sizeof (es->es_enaddr)); 395 enp->ether_type = htons((u_short)type); 396 397 /* 398 * Queue message on interface if possible 399 */ 400 s = splimp(); 401 if (enpput(ifp->if_unit, m)) { 402 error = ENOBUFS; 403 goto qfull; 404 } 405 splx(s); 406 es->es_if.if_opackets++; 407 return (mcopy ? looutput(&loif, mcopy, dst) : 0); 408 qfull: 409 splx(s); 410 m0 = m; 411 bad: 412 m_freem(m0); 413 if (mcopy) 414 m_freem(mcopy); 415 return (error); 416 } 417 418 /* 419 * Routine to copy from mbuf chain to transmitter buffer on the VERSAbus. 420 */ 421 enpput(unit, m) 422 int unit; 423 struct mbuf *m; 424 { 425 register BCB *bcbp; 426 register struct enpdevice *addr; 427 register struct mbuf *mp; 428 register u_char *bp; 429 register u_int len; 430 u_char *mcp; 431 432 addr = (struct enpdevice *)enpinfo[unit]->ui_addr; 433 if (ringempty(&addr->enp_hostfree)) 434 return (1); 435 bcbp = (BCB *)ringget(&addr->enp_hostfree); 436 bcbp->b_len = 0; 437 bp = (u_char *)bcbp->b_addr; 438 for (mp = m; mp; mp = mp->m_next) { 439 len = mp->m_len; 440 if (len == 0) 441 continue; 442 mcp = mtod(mp, u_char *); 443 enpcopy(mcp, bp, len); 444 bp += len; 445 bcbp->b_len += len; 446 } 447 bcbp->b_len = max(ETHERMIN, bcbp->b_len); 448 bcbp->b_reserved = 0; 449 if (ringput(&addr->enp_toenp, bcbp) == 1) 450 INTR_ENP(addr); 451 m_freem(m); 452 return (0); 453 } 454 455 /* 456 * Routine to copy from VERSAbus memory into mbufs. 457 * 458 * Warning: This makes the fairly safe assumption that 459 * mbufs have even lengths. 460 */ 461 struct mbuf * 462 enpget(rxbuf, totlen, off0, ifp) 463 u_char *rxbuf; 464 int totlen, off0; 465 struct ifnet *ifp; 466 { 467 register u_char *cp, *mcp; 468 register struct mbuf *m; 469 struct mbuf *top = 0, **mp = ⊤ 470 int len, off = off0; 471 472 cp = rxbuf + sizeof (struct ether_header); 473 while (totlen > 0) { 474 MGET(m, M_DONTWAIT, MT_DATA); 475 if (m == 0) 476 goto bad; 477 if (off) { 478 len = totlen - off; 479 cp = rxbuf + sizeof (struct ether_header) + off; 480 } else 481 len = totlen; 482 if (len >= NBPG) { 483 struct mbuf *p; 484 485 MCLGET(m); 486 if (m->m_len == CLBYTES) 487 m->m_len = len = MIN(len, CLBYTES); 488 else 489 m->m_len = len = MIN(MLEN, len); 490 } else { 491 m->m_len = len = MIN(MLEN, len); 492 m->m_off = MMINOFF; 493 } 494 mcp = mtod(m, u_char *); 495 if (ifp) { 496 /* 497 * Prepend interface pointer to first mbuf. 498 */ 499 *(mtod(m, struct ifnet **)) = ifp; 500 mcp += sizeof (ifp); 501 len -= sizeof (ifp); 502 ifp = (struct ifnet *)0; 503 } 504 enpcopy(cp, mcp, len); 505 cp += len; 506 *mp = m; 507 mp = &m->m_next; 508 if (off == 0) { 509 totlen -= len; 510 continue; 511 } 512 off += len; 513 if (off == totlen) { 514 cp = rxbuf + sizeof (struct ether_header); 515 off = 0; 516 totlen = off0; 517 } 518 } 519 return (top); 520 bad: 521 m_freem(top); 522 return (0); 523 } 524 525 enpcopy(from, to, cnt) 526 register char *from, *to; 527 register cnt; 528 { 529 register c; 530 register short *f, *t; 531 532 if (((int)from&01) && ((int)to&01)) { 533 /* source & dest at odd addresses */ 534 *to++ = *from++; 535 --cnt; 536 } 537 if (cnt > 1 && (((int)to&01) == 0) && (((int)from&01) == 0)) { 538 t = (short *)to; 539 f = (short *)from; 540 for (c = cnt>>1; c; --c) /* even address copy */ 541 *t++ = *f++; 542 cnt &= 1; 543 if (cnt) { /* odd len */ 544 from = (char *)f; 545 to = (char *)t; 546 *to = *from; 547 } 548 } 549 while (cnt-- > 0) /* one of the address(es) must be odd */ 550 *to++ = *from++; 551 } 552 553 /* 554 * Process an ioctl request. 555 */ 556 enpioctl(ifp, cmd, data) 557 register struct ifnet *ifp; 558 int cmd; 559 caddr_t data; 560 { 561 register struct ifaddr *ifa = (struct ifaddr *)data; 562 struct enpdevice *addr; 563 int s = splimp(), error = 0; 564 565 switch (cmd) { 566 567 case SIOCSIFADDR: 568 ifp->if_flags |= IFF_UP; 569 switch (ifa->ifa_addr.sa_family) { 570 #ifdef INET 571 case AF_INET: 572 enpinit(ifp->if_unit); 573 ((struct arpcom *)ifp)->ac_ipaddr = 574 IA_SIN(ifa)->sin_addr; 575 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 576 break; 577 #endif 578 #ifdef NS 579 case AF_NS: { 580 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; 581 struct enp_softc *es = &enp_softc[ifp->if_unit]; 582 583 if (!ns_nullhost(*ina)) { 584 ifp->if_flags &= ~IFF_RUNNING; 585 addr = (struct enpdevice *) 586 enpinfo[ifp->if_unit]->ui_addr; 587 enpsetaddr(ifp->if_unit, addr, 588 ina->x_host.c_host); 589 } else 590 ina->x_host = *(union ns_host *)es->es_enaddr; 591 enpinit(ifp->if_unit); 592 break; 593 } 594 #endif 595 default: 596 enpinit(ifp->if_unit); 597 break; 598 } 599 break; 600 601 case SIOCSIFFLAGS: 602 if ((ifp->if_flags&IFF_UP) == 0 && ifp->if_flags&IFF_RUNNING) { 603 enpinit(ifp->if_unit); /* reset board */ 604 ifp->if_flags &= ~IFF_RUNNING; 605 } else if (ifp->if_flags&IFF_UP && 606 (ifp->if_flags&IFF_RUNNING) == 0) 607 enpinit(ifp->if_unit); 608 break; 609 610 default: 611 error = EINVAL; 612 } 613 splx(s); 614 return (error); 615 } 616 617 enpsetaddr(unit, addr, enaddr) 618 int unit; 619 struct enpdevice *addr; 620 u_char *enaddr; 621 { 622 u_char *cp; 623 int i, code; 624 625 cp = &addr->enp_addr.e_baseaddr.ea_addr[0]; 626 for (i = 0; i < 6; i++) 627 *cp++ = ~*enaddr++; 628 enpcopy(&addr->enp_addr.e_listsize, &code, sizeof (code)); 629 code |= E_ADDR_SUPP; 630 enpcopy(&code, &addr->enp_addr.e_listsize, sizeof (code)); 631 enpinit(unit); 632 } 633 634 /* 635 * Routines to synchronize enp and host. 636 */ 637 static 638 ringinit(rp, size) 639 register RING *rp; 640 { 641 register int i; 642 register short *sp; 643 644 rp->r_rdidx = rp->r_wrtidx = 0; 645 rp->r_size = size; 646 } 647 648 static 649 ringempty(rp) 650 register RING *rp; 651 { 652 653 return (rp->r_rdidx == rp->r_wrtidx); 654 } 655 656 static 657 ringfull(rp) 658 register RING *rp; 659 { 660 register short idx; 661 662 idx = (rp->r_wrtidx + 1) & (rp->r_size-1); 663 return (idx == rp->r_rdidx); 664 } 665 666 static 667 ringput(rp, v) 668 register RING *rp; 669 { 670 register int idx; 671 672 idx = (rp->r_wrtidx + 1) & (rp->r_size-1); 673 if (idx != rp->r_rdidx) { 674 rp->r_slot[rp->r_wrtidx] = v; 675 rp->r_wrtidx = idx; 676 if ((idx -= rp->r_rdidx) < 0) 677 idx += rp->r_size; 678 return (idx); /* num ring entries */ 679 } 680 return (0); 681 } 682 683 static 684 ringget(rp) 685 register RING *rp; 686 { 687 register int i = 0; 688 689 if (rp->r_rdidx != rp->r_wrtidx) { 690 i = rp->r_slot[rp->r_rdidx]; 691 rp->r_rdidx = (++rp->r_rdidx) & (rp->r_size-1); 692 } 693 return (i); 694 } 695 696 static 697 fir(rp) 698 register RING *rp; 699 { 700 701 return (rp->r_rdidx != rp->r_wrtidx ? rp->r_slot[rp->r_rdidx] : 0); 702 } 703 704 /* 705 * ENP Ram device. 706 */ 707 enpr_open(dev) 708 dev_t dev; 709 { 710 register int unit = ENPUNIT(dev); 711 struct vba_device *ui; 712 struct enpdevice *addr; 713 714 if (unit >= NENP || (ui = enpinfo[unit]) == 0 || ui->ui_alive == 0 || 715 (addr = (struct enpdevice *)ui->ui_addr) == 0) 716 return (ENODEV); 717 if (addr->enp_state != S_ENPRESET) 718 return (EACCES); /* enp is not in reset state, don't open */ 719 return (0); 720 } 721 722 enpr_close(dev) 723 dev_t dev; 724 { 725 726 return (0); 727 } 728 729 enpr_read(dev, uio) 730 dev_t dev; 731 register struct uio *uio; 732 { 733 register struct iovec *iov; 734 struct enpdevice *addr; 735 int error; 736 737 if (uio->uio_offset > RAM_SIZE) 738 return (ENODEV); 739 if (uio->uio_offset + iov->iov_len > RAM_SIZE) 740 iov->iov_len = RAM_SIZE - uio->uio_offset; 741 addr = (struct enpdevice *)enpinfo[ENPUNIT(dev)]->ui_addr; 742 iov = uio->uio_iov; 743 error = useracc(iov->iov_base, iov->iov_len, 0); 744 if (error) 745 return (error); 746 enpcopy(&addr->enp_ram[uio->uio_offset], iov->iov_base, iov->iov_len); 747 uio->uio_resid -= iov->iov_len; 748 iov->iov_len = 0; 749 return (0); 750 } 751 752 enpr_write(dev, uio) 753 dev_t dev; 754 register struct uio *uio; 755 { 756 register struct enpdevice *addr; 757 register struct iovec *iov; 758 register error; 759 760 addr = (struct enpdevice *)enpinfo[ENPUNIT(dev)]->ui_addr; 761 iov = uio->uio_iov; 762 if (uio->uio_offset > RAM_SIZE) 763 return (ENODEV); 764 if (uio->uio_offset + iov->iov_len > RAM_SIZE) 765 iov->iov_len = RAM_SIZE - uio->uio_offset; 766 error = useracc(iov->iov_base, iov->iov_len, 1); 767 if (error) 768 return (error); 769 enpcopy(iov->iov_base, &addr->enp_ram[uio->uio_offset], iov->iov_len); 770 uio->uio_resid -= iov->iov_len; 771 iov->iov_len = 0; 772 return (0); 773 } 774 775 enpr_ioctl(dev, cmd, data) 776 dev_t dev; 777 caddr_t data; 778 { 779 register struct enpdevice *addr; 780 register unit = ENPUNIT(dev); 781 register struct vba_device *ui; 782 783 addr = (struct enpdevice *)enpinfo[unit]->ui_addr; 784 switch(cmd) { 785 786 case ENPIOGO: 787 /* not needed if prom based version */ 788 addr->enp_base = (int)addr; 789 addr->enp_intrvec = enp_softc[unit].es_ivec; 790 ENP_GO(addr, ENPSTART); 791 DELAY(200000); 792 enpinit(unit); 793 addr->enp_state = S_ENPRUN; /* it is running now */ 794 /* end of not needed */ 795 break; 796 797 case ENPIORESET: 798 RESET_ENP(addr); 799 addr->enp_state = S_ENPRESET; /* it is reset now */ 800 DELAY(100000); 801 break; 802 } 803 return (0); 804 } 805 #endif 806