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