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