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