|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1988 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * This code is derived from software contributed to Berkeley by ! 6: * Computer Consoles Inc. ! 7: * ! 8: * Redistribution and use in source and binary forms, with or without ! 9: * modification, are permitted provided that the following conditions ! 10: * are met: ! 11: * 1. Redistributions of source code must retain the above copyright ! 12: * notice, this list of conditions and the following disclaimer. ! 13: * 2. Redistributions in binary form must reproduce the above copyright ! 14: * notice, this list of conditions and the following disclaimer in the ! 15: * documentation and/or other materials provided with the distribution. ! 16: * 3. All advertising materials mentioning features or use of this software ! 17: * must display the following acknowledgement: ! 18: * This product includes software developed by the University of ! 19: * California, Berkeley and its contributors. ! 20: * 4. Neither the name of the University nor the names of its contributors ! 21: * may be used to endorse or promote products derived from this software ! 22: * without specific prior written permission. ! 23: * ! 24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 34: * SUCH DAMAGE. ! 35: * ! 36: * @(#)if_enp.c 7.8 (Berkeley) 12/16/90 ! 37: */ ! 38: ! 39: #include "enp.h" ! 40: #if NENP > 0 ! 41: /* ! 42: * CMC ENP-20 Ethernet Controller. ! 43: */ ! 44: #include "sys/param.h" ! 45: #include "sys/systm.h" ! 46: #include "sys/mbuf.h" ! 47: #include "sys/buf.h" ! 48: #include "sys/protosw.h" ! 49: #include "sys/socket.h" ! 50: #include "sys/vmmac.h" ! 51: #include "sys/ioctl.h" ! 52: #include "sys/errno.h" ! 53: #include "sys/vmparam.h" ! 54: #include "sys/syslog.h" ! 55: #include "sys/uio.h" ! 56: ! 57: #include "net/if.h" ! 58: #include "net/netisr.h" ! 59: #include "net/route.h" ! 60: #ifdef INET ! 61: #include "netinet/in.h" ! 62: #include "netinet/in_systm.h" ! 63: #include "netinet/in_var.h" ! 64: #include "netinet/ip.h" ! 65: #include "netinet/ip_var.h" ! 66: #include "netinet/if_ether.h" ! 67: #endif ! 68: #ifdef NS ! 69: #include "netns/ns.h" ! 70: #include "netns/ns_if.h" ! 71: #endif ! 72: ! 73: #include "../include/cpu.h" ! 74: #include "../include/pte.h" ! 75: #include "../include/mtpr.h" ! 76: ! 77: #include "../vba/vbavar.h" ! 78: #include "../if/if_enpreg.h" ! 79: ! 80: #define ENPSTART 0xf02000 /* standard enp start addr */ ! 81: #define ENPUNIT(dev) (minor(dev)) /* for enp ram devices */ ! 82: /* macros for dealing with longs in i/o space */ ! 83: #define ENPGETLONG(a) ((((u_short *)(a))[0] << 16)|(((u_short *)(a))[1])) ! 84: #define ENPSETLONG(a,v) \ ! 85: { register u_short *wp = (u_short *)(a); \ ! 86: wp[0] = ((u_short *)&(v))[0]; wp[1] = ((u_short *)&(v))[1];} ! 87: ! 88: int enpprobe(), enpattach(), enpintr(); ! 89: long enpstd[] = { 0xfff41000, 0xfff61000, 0 }; ! 90: struct vba_device *enpinfo[NENP]; ! 91: struct vba_driver enpdriver = ! 92: { enpprobe, 0, enpattach, 0, enpstd, "enp", enpinfo, "enp-20", 0 }; ! 93: ! 94: int enpinit(), enpioctl(), enpreset(), enpoutput(), enpstart(); ! 95: struct mbuf *enpget(); ! 96: ! 97: /* ! 98: * Ethernet software status per interface. ! 99: * ! 100: * Each interface is referenced by a network interface structure, ! 101: * es_if, which the routing code uses to locate the interface. ! 102: * This structure contains the output queue for the interface, its address, ... ! 103: */ ! 104: struct enp_softc { ! 105: struct arpcom es_ac; /* common ethernet structures */ ! 106: #define es_if es_ac.ac_if ! 107: #define es_addr es_ac.ac_enaddr ! 108: short es_ivec; /* interrupt vector */ ! 109: } enp_softc[NENP]; ! 110: extern struct ifnet loif; ! 111: ! 112: enpprobe(reg, vi) ! 113: caddr_t reg; ! 114: struct vba_device *vi; ! 115: { ! 116: register br, cvec; /* must be r12, r11 */ ! 117: register struct enpdevice *addr = (struct enpdevice *)reg; ! 118: struct enp_softc *es = &enp_softc[vi->ui_unit]; ! 119: ! 120: #ifdef lint ! 121: br = 0; cvec = br; br = cvec; ! 122: enpintr(0); ! 123: #endif ! 124: if (badaddr((caddr_t)addr, 2) || badaddr((caddr_t)&addr->enp_ram[0], 2)) ! 125: return (0); ! 126: es->es_ivec = --vi->ui_hd->vh_lastiv; ! 127: addr->enp_state = S_ENPRESET; /* reset by VERSAbus reset */ ! 128: br = 0x14, cvec = es->es_ivec; /* XXX */ ! 129: return (sizeof (struct enpdevice)); ! 130: } ! 131: ! 132: /* ! 133: * Interface exists: make available by filling in network interface ! 134: * record. System will initialize the interface when it is ready ! 135: * to accept packets. ! 136: */ ! 137: enpattach(ui) ! 138: register struct vba_device *ui; ! 139: { ! 140: struct enp_softc *es = &enp_softc[ui->ui_unit]; ! 141: register struct ifnet *ifp = &es->es_if; ! 142: ! 143: ifp->if_unit = ui->ui_unit; ! 144: ifp->if_name = "enp"; ! 145: ifp->if_mtu = ETHERMTU; ! 146: ifp->if_init = enpinit; ! 147: ifp->if_ioctl = enpioctl; ! 148: ifp->if_output = ether_output; ! 149: ifp->if_start = enpstart; ! 150: ifp->if_reset = enpreset; ! 151: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; ! 152: if_attach(ifp); ! 153: } ! 154: ! 155: /* ! 156: * Reset of interface after "system" reset. ! 157: */ ! 158: enpreset(unit, vban) ! 159: int unit, vban; ! 160: { ! 161: register struct vba_device *ui; ! 162: ! 163: if (unit >= NENP || (ui = enpinfo[unit]) == 0 || ui->ui_alive == 0 || ! 164: ui->ui_vbanum != vban) ! 165: return; ! 166: printf(" enp%d", unit); ! 167: enpinit(unit); ! 168: } ! 169: ! 170: /* ! 171: * Initialization of interface; clear recorded pending operations. ! 172: */ ! 173: enpinit(unit) ! 174: int unit; ! 175: { ! 176: struct enp_softc *es = &enp_softc[unit]; ! 177: register struct vba_device *ui = enpinfo[unit]; ! 178: struct enpdevice *addr; ! 179: register struct ifnet *ifp = &es->es_if; ! 180: int s; ! 181: ! 182: if (ifp->if_addrlist == (struct ifaddr *)0) ! 183: return; ! 184: if ((ifp->if_flags & IFF_RUNNING) == 0) { ! 185: addr = (struct enpdevice *)ui->ui_addr; ! 186: s = splimp(); ! 187: RESET_ENP(addr); ! 188: DELAY(200000); ! 189: es->es_if.if_flags |= IFF_RUNNING; ! 190: splx(s); ! 191: } ! 192: } ! 193: ! 194: /* ! 195: * Ethernet interface interrupt. ! 196: */ ! 197: enpintr(unit) ! 198: int unit; ! 199: { ! 200: register struct enpdevice *addr; ! 201: register BCB *bcbp; ! 202: ! 203: addr = (struct enpdevice *)enpinfo[unit]->ui_addr; ! 204: #if ENP == 30 ! 205: if (!IS_ENP_INTR(addr)) ! 206: return; ! 207: ACK_ENP_INTR(addr); ! 208: #endif ! 209: while ((bcbp = (BCB *)ringget((RING *)&addr->enp_tohost )) != 0) { ! 210: enpread(&enp_softc[unit], bcbp); ! 211: (void) ringput((RING *)&addr->enp_enpfree, bcbp); ! 212: } ! 213: } ! 214: ! 215: /* ! 216: * Read input packet, examine its packet type, and enqueue it. ! 217: */ ! 218: enpread(es, bcbp) ! 219: struct enp_softc *es; ! 220: register BCB *bcbp; ! 221: { ! 222: register struct ether_header *enp; ! 223: struct mbuf *m; ! 224: int s, len, off, resid; ! 225: ! 226: es->es_if.if_ipackets++; ! 227: /* ! 228: * Get input data length. ! 229: * Get pointer to ethernet header (in input buffer). ! 230: * Deal with trailer protocol: if type is PUP trailer ! 231: * get true type from first 16-bit word past data. ! 232: * Remember that type was trailer by setting off. ! 233: */ ! 234: len = bcbp->b_msglen - sizeof (struct ether_header); ! 235: enp = (struct ether_header *)ENPGETLONG(&bcbp->b_addr); ! 236: #define enpdataaddr(enp, off, type) \ ! 237: ((type)(((caddr_t)(((char *)enp)+sizeof (struct ether_header))+(off)))) ! 238: enp->ether_type = ntohs((u_short)enp->ether_type); ! 239: if (enp->ether_type >= ETHERTYPE_TRAIL && ! 240: enp->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { ! 241: off = (enp->ether_type - ETHERTYPE_TRAIL) * 512; ! 242: if (off >= ETHERMTU) ! 243: return; ! 244: enp->ether_type = ntohs(*enpdataaddr(enp, off, u_short *)); ! 245: resid = ntohs(*(enpdataaddr(enp, off+2, u_short *))); ! 246: if (off + resid > len) ! 247: return; ! 248: len = off + resid; ! 249: } else ! 250: off = 0; ! 251: if (len == 0) ! 252: return; ! 253: ! 254: /* ! 255: * Pull packet off interface. Off is nonzero if packet ! 256: * has trailing header; enpget will then force this header ! 257: * information to be at the front. ! 258: */ ! 259: m = enpget((u_char *)enp, len, off, &es->es_if); ! 260: if (m == 0) ! 261: return; ! 262: ether_input(&es->es_if, enp, m); ! 263: } ! 264: ! 265: enpstart(ifp) ! 266: struct ifnet *ifp; ! 267: { ! 268: ! 269: if (enpput(ifp)) ! 270: return (ENOBUFS); ! 271: else ! 272: return (0); ! 273: } ! 274: ! 275: /* ! 276: * Routine to copy from mbuf chain to transmitter buffer on the VERSAbus. ! 277: */ ! 278: enpput(ifp) ! 279: struct ifnet *ifp; ! 280: { ! 281: register BCB *bcbp; ! 282: register struct enpdevice *addr; ! 283: register struct mbuf *mp; ! 284: register u_char *bp; ! 285: register u_int len; ! 286: int unit = ifp->if_unit, ret = 1; ! 287: struct mbuf *m; ! 288: ! 289: addr = (struct enpdevice *)enpinfo[unit]->ui_addr; ! 290: again: ! 291: if (ringempty((RING *)&addr->enp_hostfree)) { ! 292: /* ifp->if_flags |= IFF_OACTIVE; */ ! 293: return (ret); ! 294: } ! 295: IF_DEQUEUE(&ifp->if_snd, m); ! 296: if (m == 0) { ! 297: ifp->if_flags &= ~IFF_OACTIVE; ! 298: return (0); ! 299: } ! 300: bcbp = (BCB *)ringget((RING *)&addr->enp_hostfree); ! 301: bcbp->b_len = 0; ! 302: bp = (u_char *)ENPGETLONG(&bcbp->b_addr); ! 303: for (mp = m; mp; mp = mp->m_next) { ! 304: len = mp->m_len; ! 305: if (len == 0) ! 306: continue; ! 307: enpcopy(mtod(mp, u_char *), bp, len); ! 308: bp += len; ! 309: bcbp->b_len += len; ! 310: } ! 311: bcbp->b_len = max(ETHERMIN+sizeof (struct ether_header), bcbp->b_len); ! 312: bcbp->b_reserved = 0; ! 313: if (ringput((RING *)&addr->enp_toenp, bcbp) == 1) ! 314: INTR_ENP(addr); ! 315: m_freem(m); ! 316: ret = 0; ! 317: goto again; ! 318: } ! 319: ! 320: /* ! 321: * Routine to copy from VERSAbus memory into mbufs. ! 322: * ! 323: * Warning: This makes the fairly safe assumption that ! 324: * mbufs have even lengths. ! 325: */ ! 326: struct mbuf * ! 327: enpget(rxbuf, totlen, off, ifp) ! 328: u_char *rxbuf; ! 329: int totlen, off; ! 330: struct ifnet *ifp; ! 331: { ! 332: register u_char *cp; ! 333: register struct mbuf *m; ! 334: struct mbuf *top = 0, **mp = ⊤ ! 335: int len; ! 336: u_char *packet_end; ! 337: ! 338: rxbuf += sizeof (struct ether_header); ! 339: cp = rxbuf; ! 340: packet_end = cp + totlen; ! 341: if (off) { ! 342: off += 2 * sizeof(u_short); ! 343: totlen -= 2 *sizeof(u_short); ! 344: cp = rxbuf + off; ! 345: } ! 346: ! 347: MGETHDR(m, M_DONTWAIT, MT_DATA); ! 348: if (m == 0) ! 349: return (0); ! 350: m->m_pkthdr.rcvif = ifp; ! 351: m->m_pkthdr.len = totlen; ! 352: m->m_len = MHLEN; ! 353: ! 354: while (totlen > 0) { ! 355: if (top) { ! 356: MGET(m, M_DONTWAIT, MT_DATA); ! 357: if (m == 0) { ! 358: m_freem(top); ! 359: return (0); ! 360: } ! 361: m->m_len = MLEN; ! 362: } ! 363: len = min(totlen, (packet_end - cp)); ! 364: if (len >= MINCLSIZE) { ! 365: MCLGET(m, M_DONTWAIT); ! 366: if (m->m_flags & M_EXT) ! 367: m->m_len = len = min(len, MCLBYTES); ! 368: else ! 369: len = m->m_len; ! 370: } else { ! 371: /* ! 372: * Place initial small packet/header at end of mbuf. ! 373: */ ! 374: if (len < m->m_len) { ! 375: if (top == 0 && len + max_linkhdr <= m->m_len) ! 376: m->m_data += max_linkhdr; ! 377: m->m_len = len; ! 378: } else ! 379: len = m->m_len; ! 380: } ! 381: enpcopy(cp, mtod(m, u_char *), (u_int)len); ! 382: *mp = m; ! 383: mp = &m->m_next; ! 384: totlen -= len; ! 385: cp += len; ! 386: if (cp == packet_end) ! 387: cp = rxbuf; ! 388: } ! 389: return (top); ! 390: } ! 391: ! 392: enpcopy(from, to, cnt) ! 393: register u_char *from, *to; ! 394: register u_int cnt; ! 395: { ! 396: register c; ! 397: register short *f, *t; ! 398: ! 399: if (((int)from&01) && ((int)to&01)) { ! 400: /* source & dest at odd addresses */ ! 401: *to++ = *from++; ! 402: --cnt; ! 403: } ! 404: if (cnt > 1 && (((int)to&01) == 0) && (((int)from&01) == 0)) { ! 405: t = (short *)to; ! 406: f = (short *)from; ! 407: for (c = cnt>>1; c; --c) /* even address copy */ ! 408: *t++ = *f++; ! 409: cnt &= 1; ! 410: if (cnt) { /* odd len */ ! 411: from = (u_char *)f; ! 412: to = (u_char *)t; ! 413: *to = *from; ! 414: } ! 415: } ! 416: while ((int)cnt-- > 0) /* one of the address(es) must be odd */ ! 417: *to++ = *from++; ! 418: } ! 419: ! 420: /* ! 421: * Process an ioctl request. ! 422: */ ! 423: enpioctl(ifp, cmd, data) ! 424: register struct ifnet *ifp; ! 425: int cmd; ! 426: caddr_t data; ! 427: { ! 428: register struct ifaddr *ifa = (struct ifaddr *)data; ! 429: struct enpdevice *addr; ! 430: int s = splimp(), error = 0; ! 431: ! 432: switch (cmd) { ! 433: ! 434: case SIOCSIFADDR: ! 435: ifp->if_flags |= IFF_UP; ! 436: switch (ifa->ifa_addr->sa_family) { ! 437: #ifdef INET ! 438: case AF_INET: ! 439: enpinit(ifp->if_unit); ! 440: ((struct arpcom *)ifp)->ac_ipaddr = ! 441: IA_SIN(ifa)->sin_addr; ! 442: arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); ! 443: break; ! 444: #endif ! 445: #ifdef NS ! 446: case AF_NS: { ! 447: struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; ! 448: struct enp_softc *es = &enp_softc[ifp->if_unit]; ! 449: ! 450: if (!ns_nullhost(*ina)) { ! 451: ifp->if_flags &= ~IFF_RUNNING; ! 452: addr = (struct enpdevice *) ! 453: enpinfo[ifp->if_unit]->ui_addr; ! 454: enpsetaddr(ifp->if_unit, addr, ! 455: ina->x_host.c_host); ! 456: } else ! 457: ina->x_host = *(union ns_host *)es->es_addr; ! 458: enpinit(ifp->if_unit); ! 459: break; ! 460: } ! 461: #endif ! 462: default: ! 463: enpinit(ifp->if_unit); ! 464: break; ! 465: } ! 466: break; ! 467: ! 468: case SIOCSIFFLAGS: ! 469: if ((ifp->if_flags&IFF_UP) == 0 && ifp->if_flags&IFF_RUNNING) { ! 470: enpinit(ifp->if_unit); /* reset board */ ! 471: ifp->if_flags &= ~IFF_RUNNING; ! 472: } else if (ifp->if_flags&IFF_UP && ! 473: (ifp->if_flags&IFF_RUNNING) == 0) ! 474: enpinit(ifp->if_unit); ! 475: break; ! 476: ! 477: default: ! 478: error = EINVAL; ! 479: } ! 480: splx(s); ! 481: return (error); ! 482: } ! 483: ! 484: enpsetaddr(unit, addr, enaddr) ! 485: int unit; ! 486: struct enpdevice *addr; ! 487: u_char *enaddr; ! 488: { ! 489: ! 490: enpcopy(enaddr, addr->enp_addr.e_baseaddr.ea_addr, ! 491: sizeof (struct ether_addr)); ! 492: enpinit(unit); ! 493: enpgetaddr(unit, addr); ! 494: } ! 495: ! 496: enpgetaddr(unit, addr) ! 497: int unit; ! 498: struct enpdevice *addr; ! 499: { ! 500: struct enp_softc *es = &enp_softc[unit]; ! 501: ! 502: enpcopy(addr->enp_addr.e_baseaddr.ea_addr, es->es_addr, ! 503: sizeof (struct ether_addr)); ! 504: printf("enp%d: hardware address %s\n", ! 505: unit, ether_sprintf(es->es_addr)); ! 506: } ! 507: ! 508: /* ! 509: * Routines to synchronize enp and host. ! 510: */ ! 511: #ifdef notdef ! 512: static ! 513: ringinit(rp, size) ! 514: register RING *rp; ! 515: { ! 516: ! 517: rp->r_rdidx = rp->r_wrtidx = 0; ! 518: rp->r_size = size; ! 519: } ! 520: ! 521: static ! 522: ringfull(rp) ! 523: register RING *rp; ! 524: { ! 525: register short idx; ! 526: ! 527: idx = (rp->r_wrtidx + 1) & (rp->r_size-1); ! 528: return (idx == rp->r_rdidx); ! 529: } ! 530: ! 531: static ! 532: fir(rp) ! 533: register RING *rp; ! 534: { ! 535: ! 536: return (rp->r_rdidx != rp->r_wrtidx ? rp->r_slot[rp->r_rdidx] : 0); ! 537: } ! 538: #endif ! 539: ! 540: static ! 541: ringempty(rp) ! 542: register RING *rp; ! 543: { ! 544: ! 545: return (rp->r_rdidx == rp->r_wrtidx); ! 546: } ! 547: ! 548: static ! 549: ringput(rp, v) ! 550: register RING *rp; ! 551: BCB *v; ! 552: { ! 553: register int idx; ! 554: ! 555: idx = (rp->r_wrtidx + 1) & (rp->r_size-1); ! 556: if (idx != rp->r_rdidx) { ! 557: ENPSETLONG(&rp->r_slot[rp->r_wrtidx], v); ! 558: rp->r_wrtidx = idx; ! 559: if ((idx -= rp->r_rdidx) < 0) ! 560: idx += rp->r_size; ! 561: return (idx); /* num ring entries */ ! 562: } ! 563: return (0); ! 564: } ! 565: ! 566: static ! 567: ringget(rp) ! 568: register RING *rp; ! 569: { ! 570: register int i = 0; ! 571: ! 572: if (rp->r_rdidx != rp->r_wrtidx) { ! 573: i = ENPGETLONG(&rp->r_slot[rp->r_rdidx]); ! 574: rp->r_rdidx = (++rp->r_rdidx) & (rp->r_size-1); ! 575: } ! 576: return (i); ! 577: } ! 578: ! 579: /* ! 580: * ENP Ram device. ! 581: */ ! 582: enpr_open(dev) ! 583: dev_t dev; ! 584: { ! 585: register int unit = ENPUNIT(dev); ! 586: struct vba_device *ui; ! 587: struct enpdevice *addr; ! 588: ! 589: if (unit >= NENP || (ui = enpinfo[unit]) == 0 || ui->ui_alive == 0 || ! 590: (addr = (struct enpdevice *)ui->ui_addr) == 0) ! 591: return (ENODEV); ! 592: if (addr->enp_state != S_ENPRESET) ! 593: return (EACCES); /* enp is not in reset state, don't open */ ! 594: return (0); ! 595: } ! 596: ! 597: /*ARGSUSED*/ ! 598: enpr_close(dev) ! 599: dev_t dev; ! 600: { ! 601: ! 602: return (0); ! 603: } ! 604: ! 605: enpr_read(dev, uio) ! 606: dev_t dev; ! 607: register struct uio *uio; ! 608: { ! 609: register struct iovec *iov; ! 610: struct enpdevice *addr; ! 611: ! 612: if (uio->uio_offset > RAM_SIZE) ! 613: return (ENODEV); ! 614: iov = uio->uio_iov; ! 615: if (uio->uio_offset + iov->iov_len > RAM_SIZE) ! 616: iov->iov_len = RAM_SIZE - uio->uio_offset; ! 617: addr = (struct enpdevice *)enpinfo[ENPUNIT(dev)]->ui_addr; ! 618: if (useracc(iov->iov_base, (unsigned)iov->iov_len, 0) == 0) ! 619: return (EFAULT); ! 620: enpcopy((u_char *)&addr->enp_ram[uio->uio_offset], ! 621: (u_char *)iov->iov_base, (u_int)iov->iov_len); ! 622: uio->uio_resid -= iov->iov_len; ! 623: iov->iov_len = 0; ! 624: return (0); ! 625: } ! 626: ! 627: enpr_write(dev, uio) ! 628: dev_t dev; ! 629: register struct uio *uio; ! 630: { ! 631: register struct enpdevice *addr; ! 632: register struct iovec *iov; ! 633: ! 634: addr = (struct enpdevice *)enpinfo[ENPUNIT(dev)]->ui_addr; ! 635: iov = uio->uio_iov; ! 636: if (uio->uio_offset > RAM_SIZE) ! 637: return (ENODEV); ! 638: if (uio->uio_offset + iov->iov_len > RAM_SIZE) ! 639: iov->iov_len = RAM_SIZE - uio->uio_offset; ! 640: if (useracc(iov->iov_base, (unsigned)iov->iov_len, 1) == 0) ! 641: return (EFAULT); ! 642: enpcopy((u_char *)iov->iov_base, ! 643: (u_char *)&addr->enp_ram[uio->uio_offset], (u_int)iov->iov_len); ! 644: uio->uio_resid -= iov->iov_len; ! 645: uio->uio_offset += iov->iov_len; ! 646: iov->iov_len = 0; ! 647: return (0); ! 648: } ! 649: ! 650: /*ARGSUSED*/ ! 651: enpr_ioctl(dev, cmd, data) ! 652: dev_t dev; ! 653: caddr_t data; ! 654: { ! 655: register unit = ENPUNIT(dev); ! 656: struct enpdevice *addr; ! 657: ! 658: addr = (struct enpdevice *)enpinfo[unit]->ui_addr; ! 659: switch(cmd) { ! 660: ! 661: case ENPIOGO: ! 662: ENPSETLONG(&addr->enp_base, addr); ! 663: addr->enp_intrvec = enp_softc[unit].es_ivec; ! 664: ENP_GO(addr, ENPSTART); ! 665: DELAY(200000); ! 666: enpinit(unit); ! 667: /* ! 668: * Fetch Ethernet address after link level ! 669: * is booted (firmware copies manufacturer's ! 670: * address from on-board ROM). ! 671: */ ! 672: enpgetaddr(unit, addr); ! 673: addr->enp_state = S_ENPRUN; ! 674: break; ! 675: ! 676: case ENPIORESET: ! 677: RESET_ENP(addr); ! 678: addr->enp_state = S_ENPRESET; ! 679: DELAY(100000); ! 680: break; ! 681: default: ! 682: return (EINVAL); ! 683: } ! 684: return (0); ! 685: } ! 686: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.