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