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