|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1988 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_css.c 7.8 (Berkeley) 6/28/90 ! 21: */ ! 22: ! 23: #include "css.h" ! 24: #if NCSS > 0 ! 25: ! 26: /* ! 27: * DEC/CSS IMP11-A ARPAnet IMP interface driver. ! 28: * Since "imp11a" is such a mouthful, it is called ! 29: * "css" after the LH/DH being called "acc". ! 30: * ! 31: * Configuration notes: ! 32: * ! 33: * As delivered from DEC/CSS, it ! 34: * is addressed and vectored as two DR11-B's. This makes ! 35: * Autoconfig almost IMPOSSIBLE. To make it work, the ! 36: * interrupt vectors must be restrapped to make the vectors ! 37: * consecutive. The 020 hole between the CSR addresses is ! 38: * tolerated, althought that could be cleaned-up also. ! 39: * ! 40: * Additionally, the TRANSMIT side of the IMP11-A has the ! 41: * lower address of the two subunits, so the vector ordering ! 42: * in the CONFIG file is reversed from most other devices. ! 43: * It should be: ! 44: * ! 45: * device css0 .... cssxint cssrint ! 46: * ! 47: * If you get it wrong, it will still autoconfig, but will just ! 48: * sit there with RECEIVE IDLE indicated on the front panel. ! 49: */ ! 50: #include "param.h" ! 51: #include "systm.h" ! 52: #include "mbuf.h" ! 53: #include "buf.h" ! 54: #include "protosw.h" ! 55: #include "socket.h" ! 56: #include "vmmac.h" ! 57: ! 58: #include "machine/pte.h" ! 59: ! 60: #include "../net/if.h" ! 61: #include "../netimp/if_imp.h" ! 62: ! 63: #include "../vax/cpu.h" ! 64: #include "../vax/mtpr.h" ! 65: #include "if_cssreg.h" ! 66: #include "if_uba.h" ! 67: #include "../vaxuba/ubareg.h" ! 68: #include "../vaxuba/ubavar.h" ! 69: ! 70: int cssprobe(), cssattach(), cssrint(), cssxint(); ! 71: struct uba_device *cssinfo[NCSS]; ! 72: u_short cssstd[] = { 0 }; ! 73: struct uba_driver cssdriver = ! 74: { cssprobe, 0, cssattach, 0, cssstd, "css", cssinfo }; ! 75: ! 76: int cssinit(), cssoutput(), cssdown(), cssreset(); ! 77: ! 78: /* ! 79: * "Lower half" of IMP interface driver. ! 80: * ! 81: * Each IMP interface is handled by a common module which handles ! 82: * the IMP-host protocol and a hardware driver which manages the ! 83: * hardware specific details of talking with the IMP. ! 84: * ! 85: * The hardware portion of the IMP driver handles DMA and related ! 86: * management of UNIBUS resources. The IMP protocol module interprets ! 87: * contents of these messages and "controls" the actions of the ! 88: * hardware module during IMP resets, but not, for instance, during ! 89: * UNIBUS resets. ! 90: * ! 91: * The two modules are coupled at "attach time", and ever after, ! 92: * through the imp interface structure. Higher level protocols, ! 93: * e.g. IP, interact with the IMP driver, rather than the CSS. ! 94: */ ! 95: struct css_softc { ! 96: struct imp_softc *css_imp; /* pointer to IMP's imp_softc struct */ ! 97: struct ifuba css_ifuba; /* UNIBUS resources */ ! 98: struct mbuf *css_iq; /* input reassembly queue */ ! 99: short css_olen; /* size of last message sent */ ! 100: char css_flush; /* flush remainder of message */ ! 101: } css_softc[NCSS]; ! 102: ! 103: /* ! 104: * Reset the IMP and cause a transmitter interrupt by ! 105: * performing a null DMA. ! 106: */ ! 107: cssprobe(reg) ! 108: caddr_t reg; ! 109: { ! 110: register int br, cvec; /* r11, r10 value-result */ ! 111: register struct cssdevice *addr = (struct cssdevice *)reg; ! 112: ! 113: #ifdef lint ! 114: br = 0; cvec = br; br = cvec; ! 115: cssrint(0); cssxint(0); ! 116: #endif ! 117: ! 118: addr->css_icsr = CSS_CLR; ! 119: addr->css_ocsr = CSS_CLR; ! 120: DELAY(50000); ! 121: addr->css_icsr = 0; ! 122: addr->css_ocsr = 0; ! 123: DELAY(50000); ! 124: ! 125: addr->css_oba = 0; ! 126: addr->css_owc = -1; ! 127: addr->css_ocsr = CSS_IE | CSS_GO; /* enable interrupts */ ! 128: DELAY(50000); ! 129: addr->css_ocsr = 0; ! 130: ! 131: return (1); ! 132: } ! 133: ! 134: /* ! 135: * Call the IMP module to allow it to set up its internal ! 136: * state, then tie the two modules together by setting up ! 137: * the back pointers to common data structures. ! 138: */ ! 139: cssattach(ui) ! 140: register struct uba_device *ui; ! 141: { ! 142: register struct css_softc *sc = &css_softc[ui->ui_unit]; ! 143: register struct impcb *ip; ! 144: ! 145: if ((sc->css_imp = impattach(ui->ui_driver->ud_dname, ui->ui_unit, ! 146: cssreset)) == 0) ! 147: return; ! 148: ip = &sc->css_imp->imp_cb; ! 149: ip->ic_init = cssinit; ! 150: ip->ic_output = cssoutput; ! 151: ip->ic_down = cssdown; ! 152: sc->css_ifuba.ifu_flags = UBA_CANTWAIT | UBA_NEED16; ! 153: #ifdef notdef ! 154: sc->css_ifuba.ifu_flags |= UBA_NEEDBDP; ! 155: #endif ! 156: } ! 157: ! 158: /* ! 159: * Reset interface after UNIBUS reset. ! 160: * If interface is on specified uba, reset its state. ! 161: */ ! 162: cssreset(unit, uban) ! 163: int unit, uban; ! 164: { ! 165: register struct uba_device *ui; ! 166: register struct css_softc *sc; ! 167: ! 168: if (unit >= NCSS || (ui = cssinfo[unit]) == 0 || ui->ui_alive == 0 || ! 169: ui->ui_ubanum != uban) ! 170: return; ! 171: printf(" css%d", unit); ! 172: sc = &css_softc[unit]; ! 173: sc->css_imp->imp_if.if_flags &= ~IFF_RUNNING; ! 174: cssoflush(unit); ! 175: /* must go through IMP to allow it to set state */ ! 176: (*sc->css_imp->imp_if.if_init)(sc->css_imp->imp_if.if_unit); ! 177: } ! 178: ! 179: /* ! 180: * Initialize interface: clear recorded pending operations, ! 181: * and retrieve, and reinitialize UNIBUS resources. ! 182: */ ! 183: cssinit(unit) ! 184: int unit; ! 185: { ! 186: register struct css_softc *sc; ! 187: register struct uba_device *ui; ! 188: register struct cssdevice *addr; ! 189: int x, info; ! 190: ! 191: if (unit >= NCSS || (ui = cssinfo[unit]) == 0 || ui->ui_alive == 0) { ! 192: printf("css%d: not alive\n", unit); ! 193: return(0); ! 194: } ! 195: sc = &css_softc[unit]; ! 196: ! 197: /* ! 198: * Header length is 0 to if_ubainit since we have to pass ! 199: * the IMP leader up to the protocol interpretaion ! 200: * routines. If we had the deader length as ! 201: * sizeof(struct imp_leader), then the if_ routines ! 202: * would assume we handle it on input and output. ! 203: */ ! 204: ! 205: if ((sc->css_imp->imp_if.if_flags & IFF_RUNNING) == 0 && ! 206: if_ubainit(&sc->css_ifuba, ui->ui_ubanum, 0, ! 207: (int)btoc(IMP_RCVBUF)) == 0) { ! 208: printf("css%d: can't initialize\n", unit); ! 209: ui->ui_alive = 0; ! 210: sc->css_imp->imp_if.if_flags &= ~(IFF_UP | IFF_RUNNING); ! 211: return(0); ! 212: } ! 213: sc->css_imp->imp_if.if_flags |= IFF_RUNNING; ! 214: addr = (struct cssdevice *)ui->ui_addr; ! 215: ! 216: /* reset the imp interface. */ ! 217: x = spl5(); ! 218: addr->css_icsr = CSS_CLR; ! 219: addr->css_ocsr = CSS_CLR; ! 220: DELAY(100); ! 221: addr->css_icsr = 0; ! 222: addr->css_ocsr = 0; ! 223: addr->css_icsr = IN_HRDY; /* close the relay */ ! 224: DELAY(5000); ! 225: splx(x); ! 226: ! 227: /* ! 228: * This may hang if the imp isn't really there. ! 229: * Will test and verify safe operation. ! 230: */ ! 231: ! 232: x = 500; ! 233: while (x-- > 0) { ! 234: if ((addr->css_icsr & (IN_HRDY|IN_IMPNR)) == IN_HRDY) ! 235: break; ! 236: addr->css_icsr = IN_HRDY; /* close the relay */ ! 237: DELAY(5000); ! 238: } ! 239: ! 240: if (x <= 0) { ! 241: printf("css%d: imp doesn't respond, icsr=%b\n", unit, ! 242: CSS_INBITS, addr->css_icsr); ! 243: goto down; ! 244: } ! 245: ! 246: /* ! 247: * Put up a read. We can't restart any outstanding writes ! 248: * until we're back in synch with the IMP (i.e. we've flushed ! 249: * the NOOPs it throws at us). ! 250: * Note: IMP_RCVBUF includes the leader. ! 251: */ ! 252: ! 253: x = spl5(); ! 254: info = sc->css_ifuba.ifu_r.ifrw_info; ! 255: addr->css_iba = (u_short)info; ! 256: addr->css_iwc = -(IMP_RCVBUF >> 1); ! 257: addr->css_icsr = ! 258: IN_HRDY | CSS_IE | IN_WEN | ((info & 0x30000) >> 12) | CSS_GO; ! 259: splx(x); ! 260: return(1); ! 261: ! 262: down: ! 263: ui->ui_alive = 0; ! 264: return(0); ! 265: } ! 266: ! 267: /* ! 268: * Drop the host ready line to mark host down. ! 269: * UNTESTED. ! 270: */ ! 271: cssdown(unit) ! 272: int unit; ! 273: { ! 274: register struct cssdevice *addr; ! 275: ! 276: addr = (struct cssdevice *)(cssinfo[unit]->ui_addr); ! 277: /* reset the imp interface. */ ! 278: addr->css_icsr = CSS_CLR; ! 279: addr->css_ocsr = CSS_CLR; ! 280: DELAY(100); ! 281: addr->css_icsr = 0; ! 282: addr->css_ocsr = 0; ! 283: cssoflush(unit); ! 284: return (1); ! 285: } ! 286: ! 287: cssoflush(unit) ! 288: int unit; ! 289: { ! 290: register struct css_softc *sc = &css_softc[unit]; ! 291: ! 292: sc->css_imp->imp_cb.ic_oactive = 0; ! 293: if (sc->css_ifuba.ifu_xtofree) { ! 294: m_freem(sc->css_ifuba.ifu_xtofree); ! 295: sc->css_ifuba.ifu_xtofree = 0; ! 296: } ! 297: } ! 298: ! 299: /* ! 300: * Start output on an interface. ! 301: */ ! 302: cssoutput(unit, m) ! 303: int unit; ! 304: struct mbuf *m; ! 305: { ! 306: int info; ! 307: struct uba_device *ui = cssinfo[unit]; ! 308: register struct css_softc *sc = &css_softc[unit]; ! 309: register struct cssdevice *addr; ! 310: ! 311: sc->css_olen = if_wubaput(&sc->css_ifuba, m); ! 312: /* ! 313: * Have request mapped to UNIBUS for transmission. ! 314: * Purge any stale data from the BDP, and start the output. ! 315: */ ! 316: if (sc->css_ifuba.ifu_flags & UBA_NEEDBDP) ! 317: UBAPURGE(sc->css_ifuba.ifu_uba, sc->css_ifuba.ifu_w.ifrw_bdp); ! 318: addr = (struct cssdevice *)ui->ui_addr; ! 319: info = sc->css_ifuba.ifu_w.ifrw_info; ! 320: addr->css_oba = (u_short)info; ! 321: addr->css_owc = -((sc->css_olen + 1) >> 1); ! 322: addr->css_ocsr = ! 323: (u_short)(CSS_IE | OUT_ENLB | ((info & 0x30000) >> 12) | CSS_GO); ! 324: sc->css_imp->imp_cb.ic_oactive = 1; ! 325: } ! 326: ! 327: /* ! 328: * Output interrupt handler. ! 329: */ ! 330: cssxint(unit) ! 331: { ! 332: register struct uba_device *ui = cssinfo[unit]; ! 333: register struct css_softc *sc = &css_softc[unit]; ! 334: register struct cssdevice *addr; ! 335: ! 336: addr = (struct cssdevice *)ui->ui_addr; ! 337: if (sc->css_imp->imp_cb.ic_oactive == 0) { ! 338: printf("css%d: stray output interrupt csr=%b\n", ! 339: unit, addr->css_ocsr, CSS_OUTBITS); ! 340: return; ! 341: } ! 342: sc->css_imp->imp_if.if_opackets++; ! 343: sc->css_imp->imp_cb.ic_oactive = 0; ! 344: if (addr->css_ocsr & CSS_ERR){ ! 345: sc->css_imp->imp_if.if_oerrors++; ! 346: printf("css%d: output error, ocsr=%b icsr=%b\n", unit, ! 347: addr->css_ocsr, CSS_OUTBITS, ! 348: addr->css_icsr, CSS_INBITS); ! 349: } ! 350: if (sc->css_ifuba.ifu_xtofree) { ! 351: m_freem(sc->css_ifuba.ifu_xtofree); ! 352: sc->css_ifuba.ifu_xtofree = 0; ! 353: } ! 354: impstart(sc->css_imp); ! 355: } ! 356: ! 357: /* ! 358: * Input interrupt handler ! 359: */ ! 360: cssrint(unit) ! 361: { ! 362: register struct css_softc *sc = &css_softc[unit]; ! 363: register struct cssdevice *addr; ! 364: struct mbuf *m; ! 365: int len, info; ! 366: ! 367: sc->css_imp->imp_if.if_ipackets++; ! 368: ! 369: /* ! 370: * Purge BDP; flush message if error indicated. ! 371: */ ! 372: ! 373: addr = (struct cssdevice *)cssinfo[unit]->ui_addr; ! 374: if (sc->css_ifuba.ifu_flags & UBA_NEEDBDP) ! 375: UBAPURGE(sc->css_ifuba.ifu_uba, sc->css_ifuba.ifu_r.ifrw_bdp); ! 376: if (addr->css_icsr & CSS_ERR) { ! 377: printf("css%d: recv error, csr=%b\n", unit, ! 378: addr->css_icsr, CSS_INBITS); ! 379: sc->css_imp->imp_if.if_ierrors++; ! 380: sc->css_flush = 1; ! 381: } ! 382: ! 383: if (sc->css_flush) { ! 384: if (addr->css_icsr & IN_EOM) ! 385: sc->css_flush = 0; ! 386: goto setup; ! 387: } ! 388: ! 389: len = IMP_RCVBUF + (addr->css_iwc << 1); ! 390: if (len < 0 || len > IMP_RCVBUF) { ! 391: printf("css%d: bad length=%d\n", len); ! 392: sc->css_imp->imp_if.if_ierrors++; ! 393: goto setup; ! 394: } ! 395: ! 396: /* ! 397: * The offset parameter is always 0 since using ! 398: * trailers on the ARPAnet is insane. ! 399: */ ! 400: m = if_rubaget(&sc->css_ifuba, len, 0, &sc->css_imp->imp_if); ! 401: if (m == 0) ! 402: goto setup; ! 403: if ((addr->css_icsr & IN_EOM) == 0) { ! 404: if (sc->css_iq) ! 405: m_cat(sc->css_iq, m); ! 406: else ! 407: sc->css_iq = m; ! 408: goto setup; ! 409: } ! 410: if (sc->css_iq) { ! 411: m_cat(sc->css_iq, m); ! 412: m = sc->css_iq; ! 413: sc->css_iq = 0; ! 414: } ! 415: impinput(unit, m); ! 416: ! 417: setup: ! 418: /* ! 419: * Setup for next message. ! 420: */ ! 421: info = sc->css_ifuba.ifu_r.ifrw_info; ! 422: addr->css_iba = (u_short)info; ! 423: addr->css_iwc = - (IMP_RCVBUF >> 1); ! 424: addr->css_icsr = ! 425: IN_HRDY | CSS_IE | IN_WEN | ((info & 0x30000) >> 12) | CSS_GO; ! 426: } ! 427: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.