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