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