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