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