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.7 (Berkeley) 04/25/89 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 425