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