|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: * ! 6: * @(#)if_de.c 7.1 (Berkeley) 6/5/86 ! 7: */ ! 8: #include "de.h" ! 9: #if NDE > 0 ! 10: ! 11: /* ! 12: * DEC DEUNA interface ! 13: * ! 14: * Lou Salkind ! 15: * New York University ! 16: * ! 17: * TODO: ! 18: * timeout routine (get statistics) ! 19: */ ! 20: #include "../machine/pte.h" ! 21: ! 22: #include "param.h" ! 23: #include "systm.h" ! 24: #include "mbuf.h" ! 25: #include "buf.h" ! 26: #include "protosw.h" ! 27: #include "socket.h" ! 28: #include "vmmac.h" ! 29: #include "ioctl.h" ! 30: #include "errno.h" ! 31: #include "syslog.h" ! 32: ! 33: #include "../net/if.h" ! 34: #include "../net/netisr.h" ! 35: #include "../net/route.h" ! 36: ! 37: #ifdef INET ! 38: #include "../netinet/in.h" ! 39: #include "../netinet/in_systm.h" ! 40: #include "../netinet/in_var.h" ! 41: #include "../netinet/ip.h" ! 42: #include "../netinet/if_ether.h" ! 43: #endif ! 44: ! 45: #ifdef NS ! 46: #include "../netns/ns.h" ! 47: #include "../netns/ns_if.h" ! 48: #endif ! 49: ! 50: #include "../vax/cpu.h" ! 51: #include "../vax/mtpr.h" ! 52: #include "if_dereg.h" ! 53: #include "if_uba.h" ! 54: #include "../vaxuba/ubareg.h" ! 55: #include "../vaxuba/ubavar.h" ! 56: ! 57: #define NXMT 3 /* number of transmit buffers */ ! 58: #define NRCV 7 /* number of receive buffers (must be > 1) */ ! 59: ! 60: int dedebug = 0; ! 61: ! 62: int deprobe(), deattach(), deintr(); ! 63: struct uba_device *deinfo[NDE]; ! 64: u_short destd[] = { 0 }; ! 65: struct uba_driver dedriver = ! 66: { deprobe, 0, deattach, 0, destd, "de", deinfo }; ! 67: int deinit(),deoutput(),deioctl(),dereset(); ! 68: ! 69: ! 70: /* ! 71: * Ethernet software status per interface. ! 72: * ! 73: * Each interface is referenced by a network interface structure, ! 74: * ds_if, which the routing code uses to locate the interface. ! 75: * This structure contains the output queue for the interface, its address, ... ! 76: * We also have, for each interface, a UBA interface structure, which ! 77: * contains information about the UNIBUS resources held by the interface: ! 78: * map registers, buffered data paths, etc. Information is cached in this ! 79: * structure for use by the if_uba.c routines in running the interface ! 80: * efficiently. ! 81: */ ! 82: struct de_softc { ! 83: struct arpcom ds_ac; /* Ethernet common part */ ! 84: #define ds_if ds_ac.ac_if /* network-visible interface */ ! 85: #define ds_addr ds_ac.ac_enaddr /* hardware Ethernet address */ ! 86: int ds_flags; ! 87: #define DSF_LOCK 1 /* lock out destart */ ! 88: #define DSF_RUNNING 2 /* board is enabled */ ! 89: #define DSF_SETADDR 4 /* physical address is changed */ ! 90: int ds_ubaddr; /* map info for incore structs */ ! 91: struct ifubinfo ds_deuba; /* unibus resource structure */ ! 92: struct ifrw ds_ifr[NRCV]; /* unibus receive maps */ ! 93: struct ifxmt ds_ifw[NXMT]; /* unibus xmt maps */ ! 94: /* the following structures are always mapped in */ ! 95: struct de_pcbb ds_pcbb; /* port control block */ ! 96: struct de_ring ds_xrent[NXMT]; /* transmit ring entrys */ ! 97: struct de_ring ds_rrent[NRCV]; /* receive ring entrys */ ! 98: struct de_udbbuf ds_udbbuf; /* UNIBUS data buffer */ ! 99: /* end mapped area */ ! 100: #define INCORE_BASE(p) ((char *)&(p)->ds_pcbb) ! 101: #define RVAL_OFF(n) ((char *)&de_softc[0].n - INCORE_BASE(&de_softc[0])) ! 102: #define LVAL_OFF(n) ((char *)de_softc[0].n - INCORE_BASE(&de_softc[0])) ! 103: #define PCBB_OFFSET RVAL_OFF(ds_pcbb) ! 104: #define XRENT_OFFSET LVAL_OFF(ds_xrent) ! 105: #define RRENT_OFFSET LVAL_OFF(ds_rrent) ! 106: #define UDBBUF_OFFSET RVAL_OFF(ds_udbbuf) ! 107: #define INCORE_SIZE RVAL_OFF(ds_xindex) ! 108: int ds_xindex; /* UNA index into transmit chain */ ! 109: int ds_rindex; /* UNA index into receive chain */ ! 110: int ds_xfree; /* index for next transmit buffer */ ! 111: int ds_nxmit; /* # of transmits in progress */ ! 112: } de_softc[NDE]; ! 113: ! 114: deprobe(reg) ! 115: caddr_t reg; ! 116: { ! 117: register int br, cvec; /* r11, r10 value-result */ ! 118: register struct dedevice *addr = (struct dedevice *)reg; ! 119: register i; ! 120: ! 121: #ifdef lint ! 122: br = 0; cvec = br; br = cvec; ! 123: i = 0; derint(i); deintr(i); ! 124: #endif ! 125: ! 126: addr->pcsr0 = PCSR0_RSET; ! 127: while ((addr->pcsr0 & PCSR0_INTR) == 0) ! 128: ; ! 129: /* make board interrupt by executing a GETPCBB command */ ! 130: addr->pcsr0 = PCSR0_INTE; ! 131: addr->pcsr2 = 0; ! 132: addr->pcsr3 = 0; ! 133: addr->pcsr0 = PCSR0_INTE|CMD_GETPCBB; ! 134: DELAY(100000); ! 135: return(1); ! 136: } ! 137: ! 138: /* ! 139: * Interface exists: make available by filling in network interface ! 140: * record. System will initialize the interface when it is ready ! 141: * to accept packets. We get the ethernet address here. ! 142: */ ! 143: deattach(ui) ! 144: struct uba_device *ui; ! 145: { ! 146: register struct de_softc *ds = &de_softc[ui->ui_unit]; ! 147: register struct ifnet *ifp = &ds->ds_if; ! 148: register struct dedevice *addr = (struct dedevice *)ui->ui_addr; ! 149: ! 150: ifp->if_unit = ui->ui_unit; ! 151: ifp->if_name = "de"; ! 152: ifp->if_mtu = ETHERMTU; ! 153: ifp->if_flags = IFF_BROADCAST; ! 154: ! 155: /* ! 156: * Reset the board and temporarily map ! 157: * the pcbb buffer onto the Unibus. ! 158: */ ! 159: addr->pcsr0 = PCSR0_RSET; ! 160: (void)dewait(ui, "reset"); ! 161: ! 162: ds->ds_ubaddr = uballoc(ui->ui_ubanum, (char *)&ds->ds_pcbb, ! 163: sizeof (struct de_pcbb), 0); ! 164: addr->pcsr2 = ds->ds_ubaddr & 0xffff; ! 165: addr->pcsr3 = (ds->ds_ubaddr >> 16) & 0x3; ! 166: addr->pclow = CMD_GETPCBB; ! 167: (void)dewait(ui, "pcbb"); ! 168: ! 169: ds->ds_pcbb.pcbb0 = FC_RDPHYAD; ! 170: addr->pclow = CMD_GETCMD; ! 171: (void)dewait(ui, "read addr "); ! 172: ! 173: ubarelse(ui->ui_ubanum, &ds->ds_ubaddr); ! 174: bcopy((caddr_t)&ds->ds_pcbb.pcbb2, (caddr_t)ds->ds_addr, ! 175: sizeof (ds->ds_addr)); ! 176: printf("de%d: hardware address %s\n", ui->ui_unit, ! 177: ether_sprintf(ds->ds_addr)); ! 178: ifp->if_init = deinit; ! 179: ifp->if_output = deoutput; ! 180: ifp->if_ioctl = deioctl; ! 181: ifp->if_reset = dereset; ! 182: ds->ds_deuba.iff_flags = UBA_CANTWAIT; ! 183: #ifdef notdef ! 184: /* CAN WE USE BDP's ??? */ ! 185: ds->ds_deuba.iff_flags |= UBA_NEEDBDP; ! 186: #endif ! 187: if_attach(ifp); ! 188: } ! 189: ! 190: /* ! 191: * Reset of interface after UNIBUS reset. ! 192: * If interface is on specified uba, reset its state. ! 193: */ ! 194: dereset(unit, uban) ! 195: int unit, uban; ! 196: { ! 197: register struct uba_device *ui; ! 198: ! 199: if (unit >= NDE || (ui = deinfo[unit]) == 0 || ui->ui_alive == 0 || ! 200: ui->ui_ubanum != uban) ! 201: return; ! 202: printf(" de%d", unit); ! 203: de_softc[unit].ds_if.if_flags &= ~IFF_RUNNING; ! 204: de_softc[unit].ds_flags &= ~(DSF_LOCK | DSF_RUNNING); ! 205: deinit(unit); ! 206: } ! 207: ! 208: /* ! 209: * Initialization of interface; clear recorded pending ! 210: * operations, and reinitialize UNIBUS usage. ! 211: */ ! 212: deinit(unit) ! 213: int unit; ! 214: { ! 215: register struct de_softc *ds = &de_softc[unit]; ! 216: register struct uba_device *ui = deinfo[unit]; ! 217: register struct dedevice *addr; ! 218: register struct ifrw *ifrw; ! 219: register struct ifxmt *ifxp; ! 220: struct ifnet *ifp = &ds->ds_if; ! 221: int s; ! 222: struct de_ring *rp; ! 223: int incaddr; ! 224: ! 225: /* not yet, if address still unknown */ ! 226: if (ifp->if_addrlist == (struct ifaddr *)0) ! 227: return; ! 228: ! 229: if (ds->ds_flags & DSF_RUNNING) ! 230: return; ! 231: if ((ifp->if_flags & IFF_RUNNING) == 0) { ! 232: if (if_ubaminit(&ds->ds_deuba, ui->ui_ubanum, ! 233: sizeof (struct ether_header), (int)btoc(ETHERMTU), ! 234: ds->ds_ifr, NRCV, ds->ds_ifw, NXMT) == 0) { ! 235: printf("de%d: can't initialize\n", unit); ! 236: ds->ds_if.if_flags &= ~IFF_UP; ! 237: return; ! 238: } ! 239: ds->ds_ubaddr = uballoc(ui->ui_ubanum, INCORE_BASE(ds), ! 240: INCORE_SIZE, 0); ! 241: } ! 242: addr = (struct dedevice *)ui->ui_addr; ! 243: ! 244: /* set the pcbb block address */ ! 245: incaddr = ds->ds_ubaddr + PCBB_OFFSET; ! 246: addr->pcsr2 = incaddr & 0xffff; ! 247: addr->pcsr3 = (incaddr >> 16) & 0x3; ! 248: addr->pclow = CMD_GETPCBB; ! 249: (void)dewait(ui, "pcbb"); ! 250: ! 251: /* set the transmit and receive ring header addresses */ ! 252: incaddr = ds->ds_ubaddr + UDBBUF_OFFSET; ! 253: ds->ds_pcbb.pcbb0 = FC_WTRING; ! 254: ds->ds_pcbb.pcbb2 = incaddr & 0xffff; ! 255: ds->ds_pcbb.pcbb4 = (incaddr >> 16) & 0x3; ! 256: ! 257: incaddr = ds->ds_ubaddr + XRENT_OFFSET; ! 258: ds->ds_udbbuf.b_tdrbl = incaddr & 0xffff; ! 259: ds->ds_udbbuf.b_tdrbh = (incaddr >> 16) & 0x3; ! 260: ds->ds_udbbuf.b_telen = sizeof (struct de_ring) / sizeof (short); ! 261: ds->ds_udbbuf.b_trlen = NXMT; ! 262: incaddr = ds->ds_ubaddr + RRENT_OFFSET; ! 263: ds->ds_udbbuf.b_rdrbl = incaddr & 0xffff; ! 264: ds->ds_udbbuf.b_rdrbh = (incaddr >> 16) & 0x3; ! 265: ds->ds_udbbuf.b_relen = sizeof (struct de_ring) / sizeof (short); ! 266: ds->ds_udbbuf.b_rrlen = NRCV; ! 267: ! 268: addr->pclow = CMD_GETCMD; ! 269: (void)dewait(ui, "wtring"); ! 270: ! 271: /* initialize the mode - enable hardware padding */ ! 272: ds->ds_pcbb.pcbb0 = FC_WTMODE; ! 273: /* let hardware do padding - set MTCH bit on broadcast */ ! 274: ds->ds_pcbb.pcbb2 = MOD_TPAD|MOD_HDX; ! 275: addr->pclow = CMD_GETCMD; ! 276: (void)dewait(ui, "wtmode"); ! 277: ! 278: /* set up the receive and transmit ring entries */ ! 279: ifxp = &ds->ds_ifw[0]; ! 280: for (rp = &ds->ds_xrent[0]; rp < &ds->ds_xrent[NXMT]; rp++) { ! 281: rp->r_segbl = ifxp->ifw_info & 0xffff; ! 282: rp->r_segbh = (ifxp->ifw_info >> 16) & 0x3; ! 283: rp->r_flags = 0; ! 284: ifxp++; ! 285: } ! 286: ifrw = &ds->ds_ifr[0]; ! 287: for (rp = &ds->ds_rrent[0]; rp < &ds->ds_rrent[NRCV]; rp++) { ! 288: rp->r_slen = sizeof (struct de_buf); ! 289: rp->r_segbl = ifrw->ifrw_info & 0xffff; ! 290: rp->r_segbh = (ifrw->ifrw_info >> 16) & 0x3; ! 291: rp->r_flags = RFLG_OWN; /* hang receive */ ! 292: ifrw++; ! 293: } ! 294: ! 295: /* start up the board (rah rah) */ ! 296: s = splimp(); ! 297: ds->ds_rindex = ds->ds_xindex = ds->ds_xfree = ds->ds_nxmit = 0; ! 298: ds->ds_if.if_flags |= IFF_RUNNING; ! 299: destart(unit); /* queue output packets */ ! 300: addr->pclow = PCSR0_INTE; /* avoid interlock */ ! 301: ds->ds_flags |= DSF_RUNNING; /* need before de_setaddr */ ! 302: if (ds->ds_flags & DSF_SETADDR) ! 303: de_setaddr(ds->ds_addr, unit); ! 304: addr->pclow = CMD_START | PCSR0_INTE; ! 305: splx(s); ! 306: } ! 307: ! 308: /* ! 309: * Setup output on interface. ! 310: * Get another datagram to send off of the interface queue, ! 311: * and map it to the interface before starting the output. ! 312: */ ! 313: destart(unit) ! 314: int unit; ! 315: { ! 316: int len; ! 317: struct uba_device *ui = deinfo[unit]; ! 318: struct dedevice *addr = (struct dedevice *)ui->ui_addr; ! 319: register struct de_softc *ds = &de_softc[unit]; ! 320: register struct de_ring *rp; ! 321: struct mbuf *m; ! 322: register int nxmit; ! 323: ! 324: /* ! 325: * the following test is necessary, since ! 326: * the code is not reentrant and we have ! 327: * multiple transmission buffers. ! 328: */ ! 329: if (ds->ds_flags & DSF_LOCK) ! 330: return; ! 331: for (nxmit = ds->ds_nxmit; nxmit < NXMT; nxmit++) { ! 332: IF_DEQUEUE(&ds->ds_if.if_snd, m); ! 333: if (m == 0) ! 334: break; ! 335: rp = &ds->ds_xrent[ds->ds_xfree]; ! 336: if (rp->r_flags & XFLG_OWN) ! 337: panic("deuna xmit in progress"); ! 338: len = if_ubaput(&ds->ds_deuba, &ds->ds_ifw[ds->ds_xfree], m); ! 339: if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) ! 340: UBAPURGE(ds->ds_deuba.iff_uba, ! 341: ds->ds_ifw[ds->ds_xfree].ifw_bdp); ! 342: rp->r_slen = len; ! 343: rp->r_tdrerr = 0; ! 344: rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN; ! 345: ! 346: ds->ds_xfree++; ! 347: if (ds->ds_xfree == NXMT) ! 348: ds->ds_xfree = 0; ! 349: } ! 350: if (ds->ds_nxmit != nxmit) { ! 351: ds->ds_nxmit = nxmit; ! 352: if (ds->ds_flags & DSF_RUNNING) ! 353: addr->pclow = PCSR0_INTE|CMD_PDMD; ! 354: } ! 355: } ! 356: ! 357: /* ! 358: * Command done interrupt. ! 359: */ ! 360: deintr(unit) ! 361: int unit; ! 362: { ! 363: struct uba_device *ui = deinfo[unit]; ! 364: register struct dedevice *addr = (struct dedevice *)ui->ui_addr; ! 365: register struct de_softc *ds = &de_softc[unit]; ! 366: register struct de_ring *rp; ! 367: register struct ifxmt *ifxp; ! 368: short csr0; ! 369: ! 370: /* save flags right away - clear out interrupt bits */ ! 371: csr0 = addr->pcsr0; ! 372: addr->pchigh = csr0 >> 8; ! 373: ! 374: ! 375: ds->ds_flags |= DSF_LOCK; /* prevent entering destart */ ! 376: /* ! 377: * if receive, put receive buffer on mbuf ! 378: * and hang the request again ! 379: */ ! 380: derecv(unit); ! 381: ! 382: /* ! 383: * Poll transmit ring and check status. ! 384: * Be careful about loopback requests. ! 385: * Then free buffer space and check for ! 386: * more transmit requests. ! 387: */ ! 388: for ( ; ds->ds_nxmit > 0; ds->ds_nxmit--) { ! 389: rp = &ds->ds_xrent[ds->ds_xindex]; ! 390: if (rp->r_flags & XFLG_OWN) ! 391: break; ! 392: ds->ds_if.if_opackets++; ! 393: ifxp = &ds->ds_ifw[ds->ds_xindex]; ! 394: /* check for unusual conditions */ ! 395: if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) { ! 396: if (rp->r_flags & XFLG_ERRS) { ! 397: /* output error */ ! 398: ds->ds_if.if_oerrors++; ! 399: if (dedebug) ! 400: printf("de%d: oerror, flags=%b tdrerr=%b (len=%d)\n", ! 401: unit, rp->r_flags, XFLG_BITS, ! 402: rp->r_tdrerr, XERR_BITS, rp->r_slen); ! 403: } else if (rp->r_flags & XFLG_ONE) { ! 404: /* one collision */ ! 405: ds->ds_if.if_collisions++; ! 406: } else if (rp->r_flags & XFLG_MORE) { ! 407: /* more than one collision */ ! 408: ds->ds_if.if_collisions += 2; /* guess */ ! 409: } else if (rp->r_flags & XFLG_MTCH) { ! 410: /* received our own packet */ ! 411: ds->ds_if.if_ipackets++; ! 412: deread(ds, &ifxp->ifrw, ! 413: rp->r_slen - sizeof (struct ether_header)); ! 414: } ! 415: } ! 416: if (ifxp->ifw_xtofree) { ! 417: m_freem(ifxp->ifw_xtofree); ! 418: ifxp->ifw_xtofree = 0; ! 419: } ! 420: /* check if next transmit buffer also finished */ ! 421: ds->ds_xindex++; ! 422: if (ds->ds_xindex == NXMT) ! 423: ds->ds_xindex = 0; ! 424: } ! 425: ds->ds_flags &= ~DSF_LOCK; ! 426: destart(unit); ! 427: ! 428: if (csr0 & PCSR0_RCBI) { ! 429: if (dedebug) ! 430: log(LOG_WARNING, "de%d: buffer unavailable\n", unit); ! 431: addr->pclow = PCSR0_INTE|CMD_PDMD; ! 432: } ! 433: } ! 434: ! 435: /* ! 436: * Ethernet interface receiver interface. ! 437: * If input error just drop packet. ! 438: * Otherwise purge input buffered data path and examine ! 439: * packet to determine type. If can't determine length ! 440: * from type, then have to drop packet. Othewise decapsulate ! 441: * packet based on type and pass to type specific higher-level ! 442: * input routine. ! 443: */ ! 444: derecv(unit) ! 445: int unit; ! 446: { ! 447: register struct de_softc *ds = &de_softc[unit]; ! 448: register struct de_ring *rp; ! 449: int len; ! 450: ! 451: rp = &ds->ds_rrent[ds->ds_rindex]; ! 452: while ((rp->r_flags & RFLG_OWN) == 0) { ! 453: ds->ds_if.if_ipackets++; ! 454: if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) ! 455: UBAPURGE(ds->ds_deuba.iff_uba, ! 456: ds->ds_ifr[ds->ds_rindex].ifrw_bdp); ! 457: len = (rp->r_lenerr&RERR_MLEN) - sizeof (struct ether_header) ! 458: - 4; /* don't forget checksum! */ ! 459: /* check for errors */ ! 460: if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) || ! 461: (rp->r_flags&(RFLG_STP|RFLG_ENP)) != (RFLG_STP|RFLG_ENP) || ! 462: (rp->r_lenerr & (RERR_BUFL|RERR_UBTO|RERR_NCHN)) || ! 463: len < ETHERMIN || len > ETHERMTU) { ! 464: ds->ds_if.if_ierrors++; ! 465: if (dedebug) ! 466: printf("de%d: ierror, flags=%b lenerr=%b (len=%d)\n", ! 467: unit, rp->r_flags, RFLG_BITS, rp->r_lenerr, ! 468: RERR_BITS, len); ! 469: } else ! 470: deread(ds, &ds->ds_ifr[ds->ds_rindex], len); ! 471: ! 472: /* hang the receive buffer again */ ! 473: rp->r_lenerr = 0; ! 474: rp->r_flags = RFLG_OWN; ! 475: ! 476: /* check next receive buffer */ ! 477: ds->ds_rindex++; ! 478: if (ds->ds_rindex == NRCV) ! 479: ds->ds_rindex = 0; ! 480: rp = &ds->ds_rrent[ds->ds_rindex]; ! 481: } ! 482: } ! 483: ! 484: /* ! 485: * Pass a packet to the higher levels. ! 486: * We deal with the trailer protocol here. ! 487: */ ! 488: deread(ds, ifrw, len) ! 489: register struct de_softc *ds; ! 490: struct ifrw *ifrw; ! 491: int len; ! 492: { ! 493: struct ether_header *eh; ! 494: struct mbuf *m; ! 495: int off, resid; ! 496: int s; ! 497: register struct ifqueue *inq; ! 498: ! 499: /* ! 500: * Deal with trailer protocol: if type is trailer type ! 501: * get true type from first 16-bit word past data. ! 502: * Remember that type was trailer by setting off. ! 503: */ ! 504: eh = (struct ether_header *)ifrw->ifrw_addr; ! 505: eh->ether_type = ntohs((u_short)eh->ether_type); ! 506: #define dedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off)))) ! 507: if (eh->ether_type >= ETHERTYPE_TRAIL && ! 508: eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { ! 509: off = (eh->ether_type - ETHERTYPE_TRAIL) * 512; ! 510: if (off >= ETHERMTU) ! 511: return; /* sanity */ ! 512: eh->ether_type = ntohs(*dedataaddr(eh, off, u_short *)); ! 513: resid = ntohs(*(dedataaddr(eh, off+2, u_short *))); ! 514: if (off + resid > len) ! 515: return; /* sanity */ ! 516: len = off + resid; ! 517: } else ! 518: off = 0; ! 519: if (len == 0) ! 520: return; ! 521: ! 522: /* ! 523: * Pull packet off interface. Off is nonzero if packet ! 524: * has trailing header; if_ubaget will then force this header ! 525: * information to be at the front, but we still have to drop ! 526: * the type and length which are at the front of any trailer data. ! 527: */ ! 528: m = if_ubaget(&ds->ds_deuba, ifrw, len, off, &ds->ds_if); ! 529: if (m == 0) ! 530: return; ! 531: if (off) { ! 532: struct ifnet *ifp; ! 533: ! 534: ifp = *(mtod(m, struct ifnet **)); ! 535: m->m_off += 2 * sizeof (u_short); ! 536: m->m_len -= 2 * sizeof (u_short); ! 537: *(mtod(m, struct ifnet **)) = ifp; ! 538: } ! 539: switch (eh->ether_type) { ! 540: ! 541: #ifdef INET ! 542: case ETHERTYPE_IP: ! 543: schednetisr(NETISR_IP); ! 544: inq = &ipintrq; ! 545: break; ! 546: ! 547: case ETHERTYPE_ARP: ! 548: arpinput(&ds->ds_ac, m); ! 549: return; ! 550: #endif ! 551: #ifdef NS ! 552: case ETHERTYPE_NS: ! 553: schednetisr(NETISR_NS); ! 554: inq = &nsintrq; ! 555: break; ! 556: ! 557: #endif ! 558: default: ! 559: m_freem(m); ! 560: return; ! 561: } ! 562: ! 563: s = splimp(); ! 564: if (IF_QFULL(inq)) { ! 565: IF_DROP(inq); ! 566: splx(s); ! 567: m_freem(m); ! 568: return; ! 569: } ! 570: IF_ENQUEUE(inq, m); ! 571: splx(s); ! 572: } ! 573: ! 574: /* ! 575: * Ethernet output routine. ! 576: * Encapsulate a packet of type family for the local net. ! 577: * Use trailer local net encapsulation if enough data in first ! 578: * packet leaves a multiple of 512 bytes of data in remainder. ! 579: */ ! 580: deoutput(ifp, m0, dst) ! 581: struct ifnet *ifp; ! 582: struct mbuf *m0; ! 583: struct sockaddr *dst; ! 584: { ! 585: int type, s, error; ! 586: u_char edst[6]; ! 587: struct in_addr idst; ! 588: register struct de_softc *ds = &de_softc[ifp->if_unit]; ! 589: register struct mbuf *m = m0; ! 590: register struct ether_header *eh; ! 591: register int off; ! 592: int usetrailers; ! 593: ! 594: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { ! 595: error = ENETDOWN; ! 596: goto bad; ! 597: } ! 598: switch (dst->sa_family) { ! 599: ! 600: #ifdef INET ! 601: case AF_INET: ! 602: idst = ((struct sockaddr_in *)dst)->sin_addr; ! 603: if (!arpresolve(&ds->ds_ac, m, &idst, edst, &usetrailers)) ! 604: return (0); /* if not yet resolved */ ! 605: off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; ! 606: if (usetrailers && off > 0 && (off & 0x1ff) == 0 && ! 607: m->m_off >= MMINOFF + 2 * sizeof (u_short)) { ! 608: type = ETHERTYPE_TRAIL + (off>>9); ! 609: m->m_off -= 2 * sizeof (u_short); ! 610: m->m_len += 2 * sizeof (u_short); ! 611: *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP); ! 612: *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); ! 613: goto gottrailertype; ! 614: } ! 615: type = ETHERTYPE_IP; ! 616: off = 0; ! 617: goto gottype; ! 618: #endif ! 619: #ifdef NS ! 620: case AF_NS: ! 621: type = ETHERTYPE_NS; ! 622: bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), ! 623: (caddr_t)edst, sizeof (edst)); ! 624: off = 0; ! 625: goto gottype; ! 626: #endif ! 627: ! 628: case AF_UNSPEC: ! 629: eh = (struct ether_header *)dst->sa_data; ! 630: bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); ! 631: type = eh->ether_type; ! 632: goto gottype; ! 633: ! 634: default: ! 635: printf("de%d: can't handle af%d\n", ifp->if_unit, ! 636: dst->sa_family); ! 637: error = EAFNOSUPPORT; ! 638: goto bad; ! 639: } ! 640: ! 641: gottrailertype: ! 642: /* ! 643: * Packet to be sent as trailer: move first packet ! 644: * (control information) to end of chain. ! 645: */ ! 646: while (m->m_next) ! 647: m = m->m_next; ! 648: m->m_next = m0; ! 649: m = m0->m_next; ! 650: m0->m_next = 0; ! 651: m0 = m; ! 652: ! 653: gottype: ! 654: /* ! 655: * Add local net header. If no space in first mbuf, ! 656: * allocate another. ! 657: */ ! 658: if (m->m_off > MMAXOFF || ! 659: MMINOFF + sizeof (struct ether_header) > m->m_off) { ! 660: m = m_get(M_DONTWAIT, MT_HEADER); ! 661: if (m == 0) { ! 662: error = ENOBUFS; ! 663: goto bad; ! 664: } ! 665: m->m_next = m0; ! 666: m->m_off = MMINOFF; ! 667: m->m_len = sizeof (struct ether_header); ! 668: } else { ! 669: m->m_off -= sizeof (struct ether_header); ! 670: m->m_len += sizeof (struct ether_header); ! 671: } ! 672: eh = mtod(m, struct ether_header *); ! 673: eh->ether_type = htons((u_short)type); ! 674: bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); ! 675: /* DEUNA fills in source address */ ! 676: ! 677: /* ! 678: * Queue message on interface, and start output if interface ! 679: * not yet active. ! 680: */ ! 681: s = splimp(); ! 682: if (IF_QFULL(&ifp->if_snd)) { ! 683: IF_DROP(&ifp->if_snd); ! 684: splx(s); ! 685: m_freem(m); ! 686: return (ENOBUFS); ! 687: } ! 688: IF_ENQUEUE(&ifp->if_snd, m); ! 689: destart(ifp->if_unit); ! 690: splx(s); ! 691: return (0); ! 692: ! 693: bad: ! 694: m_freem(m0); ! 695: return (error); ! 696: } ! 697: ! 698: /* ! 699: * Process an ioctl request. ! 700: */ ! 701: deioctl(ifp, cmd, data) ! 702: register struct ifnet *ifp; ! 703: int cmd; ! 704: caddr_t data; ! 705: { ! 706: register struct ifaddr *ifa = (struct ifaddr *)data; ! 707: register struct de_softc *ds = &de_softc[ifp->if_unit]; ! 708: int s = splimp(), error = 0; ! 709: ! 710: switch (cmd) { ! 711: ! 712: case SIOCSIFADDR: ! 713: ifp->if_flags |= IFF_UP; ! 714: deinit(ifp->if_unit); ! 715: ! 716: switch (ifa->ifa_addr.sa_family) { ! 717: #ifdef INET ! 718: case AF_INET: ! 719: ((struct arpcom *)ifp)->ac_ipaddr = ! 720: IA_SIN(ifa)->sin_addr; ! 721: arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); ! 722: break; ! 723: #endif ! 724: #ifdef NS ! 725: case AF_NS: ! 726: { ! 727: register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); ! 728: ! 729: if (ns_nullhost(*ina)) ! 730: ina->x_host = *(union ns_host *)(ds->ds_addr); ! 731: else ! 732: de_setaddr(ina->x_host.c_host,ifp->if_unit); ! 733: break; ! 734: } ! 735: #endif ! 736: } ! 737: break; ! 738: ! 739: case SIOCSIFFLAGS: ! 740: if ((ifp->if_flags & IFF_UP) == 0 && ! 741: ds->ds_flags & DSF_RUNNING) { ! 742: ((struct dedevice *) ! 743: (deinfo[ifp->if_unit]->ui_addr))->pclow = PCSR0_RSET; ! 744: ds->ds_flags &= ~(DSF_LOCK | DSF_RUNNING); ! 745: } else if (ifp->if_flags & IFF_UP && ! 746: (ds->ds_flags & DSF_RUNNING) == 0) ! 747: deinit(ifp->if_unit); ! 748: break; ! 749: ! 750: default: ! 751: error = EINVAL; ! 752: } ! 753: splx(s); ! 754: return (error); ! 755: } ! 756: ! 757: /* ! 758: * set ethernet address for unit ! 759: */ ! 760: de_setaddr(physaddr, unit) ! 761: u_char *physaddr; ! 762: int unit; ! 763: { ! 764: register struct de_softc *ds = &de_softc[unit]; ! 765: struct uba_device *ui = deinfo[unit]; ! 766: register struct dedevice *addr= (struct dedevice *)ui->ui_addr; ! 767: ! 768: if (! (ds->ds_flags & DSF_RUNNING)) ! 769: return; ! 770: ! 771: bcopy(physaddr, &ds->ds_pcbb.pcbb2, 6); ! 772: ds->ds_pcbb.pcbb0 = FC_WTPHYAD; ! 773: addr->pclow = PCSR0_INTE|CMD_GETCMD; ! 774: if (dewait(ui, "address change") == 0) { ! 775: ds->ds_flags |= DSF_SETADDR; ! 776: bcopy(physaddr, ds->ds_addr, 6); ! 777: } ! 778: } ! 779: ! 780: /* ! 781: * Await completion of the named function ! 782: * and check for errors. ! 783: */ ! 784: dewait(ui, fn) ! 785: register struct uba_device *ui; ! 786: char *fn; ! 787: { ! 788: register struct dedevice *addr = (struct dedevice *)ui->ui_addr; ! 789: register csr0; ! 790: ! 791: while ((addr->pcsr0 & PCSR0_INTR) == 0) ! 792: ; ! 793: csr0 = addr->pcsr0; ! 794: addr->pchigh = csr0 >> 8; ! 795: if (csr0 & PCSR0_PCEI) ! 796: printf("de%d: %s failed, csr0=%b csr1=%b\n", ! 797: ui->ui_unit, fn, csr0, PCSR0_BITS, ! 798: addr->pcsr1, PCSR1_BITS); ! 799: return (csr0 & PCSR0_PCEI); ! 800: } ! 801: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.