1 /* $NetBSD: nhpib.c,v 1.17 1997/05/05 21:06:41 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1996, 1997 Jason R. Thorpe. All rights reserved. 5 * Copyright (c) 1982, 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)nhpib.c 8.2 (Berkeley) 1/12/94 37 */ 38 39 /* 40 * Internal/98624 HPIB driver 41 */ 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/kernel.h> 46 #include <sys/buf.h> 47 #include <sys/device.h> 48 49 #include <machine/autoconf.h> 50 #include <machine/intr.h> 51 52 #include <hp300/dev/dioreg.h> 53 #include <hp300/dev/diovar.h> 54 #include <hp300/dev/diodevs.h> 55 56 #include <hp300/dev/dmavar.h> 57 58 #include <hp300/dev/nhpibreg.h> 59 #include <hp300/dev/hpibvar.h> 60 61 /* 62 * ODD parity table for listen and talk addresses and secondary commands. 63 * The TI9914A doesn't produce the parity bit. 64 */ 65 static u_char listnr_par[] = { 66 0040,0241,0242,0043,0244,0045,0046,0247, 67 0250,0051,0052,0253,0054,0255,0256,0057, 68 0260,0061,0062,0263,0064,0265,0266,0067, 69 0070,0271,0272,0073,0274,0075,0076,0277, 70 }; 71 static u_char talker_par[] = { 72 0100,0301,0302,0103,0304,0105,0106,0307, 73 0310,0111,0112,0313,0114,0315,0316,0117, 74 0320,0121,0122,0323,0124,0325,0326,0127, 75 0130,0331,0332,0133,0334,0135,0136,0337, 76 }; 77 static u_char sec_par[] = { 78 0340,0141,0142,0343,0144,0345,0346,0147, 79 0150,0351,0352,0153,0354,0155,0156,0357, 80 0160,0361,0362,0163,0364,0165,0166,0367, 81 0370,0171,0172,0373,0174,0375,0376,0177 82 }; 83 84 void nhpibifc __P((struct nhpibdevice *)); 85 void nhpibreadtimo __P((void *)); 86 int nhpibwait __P((struct nhpibdevice *, int)); 87 88 void nhpibreset __P((struct hpibbus_softc *)); 89 int nhpibsend __P((struct hpibbus_softc *, int, int, void *, int)); 90 int nhpibrecv __P((struct hpibbus_softc *, int, int, void *, int)); 91 int nhpibppoll __P((struct hpibbus_softc *)); 92 void nhpibppwatch __P((void *)); 93 void nhpibgo __P((struct hpibbus_softc *, int, int, void *, int, int, int)); 94 void nhpibdone __P((struct hpibbus_softc *)); 95 int nhpibintr __P((void *)); 96 97 /* 98 * Our controller ops structure. 99 */ 100 struct hpib_controller nhpib_controller = { 101 nhpibreset, 102 nhpibsend, 103 nhpibrecv, 104 nhpibppoll, 105 nhpibppwatch, 106 nhpibgo, 107 nhpibdone, 108 nhpibintr 109 }; 110 111 struct nhpib_softc { 112 struct device sc_dev; /* generic device glue */ 113 struct nhpibdevice *sc_regs; /* device registers */ 114 struct hpibbus_softc *sc_hpibbus; /* XXX */ 115 }; 116 117 int nhpibmatch __P((struct device *, struct cfdata *, void *)); 118 void nhpibattach __P((struct device *, struct device *, void *)); 119 120 struct cfattach nhpib_ca = { 121 sizeof(struct nhpib_softc), nhpibmatch, nhpibattach 122 }; 123 124 struct cfdriver nhpib_cd = { 125 NULL, "nhpib", DV_DULL 126 }; 127 128 int 129 nhpibmatch(parent, match, aux) 130 struct device *parent; 131 struct cfdata *match; 132 void *aux; 133 { 134 struct dio_attach_args *da = aux; 135 136 /* 137 * Internal HP-IB doesn't always return a device ID, 138 * so we rely on the sysflags. 139 */ 140 if (da->da_scode == 7 && internalhpib) 141 return (1); 142 143 if (da->da_id == DIO_DEVICE_ID_NHPIB) 144 return (1); 145 146 return (0); 147 } 148 149 void 150 nhpibattach(parent, self, aux) 151 struct device *parent, *self; 152 void *aux; 153 { 154 struct nhpib_softc *sc = (struct nhpib_softc *)self; 155 struct dio_attach_args *da = aux; 156 struct hpibdev_attach_args ha; 157 const char *desc; 158 int ipl, type = HPIBA; 159 160 sc->sc_regs = (struct nhpibdevice *)iomap(dio_scodetopa(da->da_scode), 161 da->da_size); 162 if (sc->sc_regs == NULL) { 163 printf("\n%s: can't map registers\n", self->dv_xname); 164 return; 165 } 166 167 ipl = DIO_IPL(sc->sc_regs); 168 169 if (da->da_scode == 7 && internalhpib) 170 desc = DIO_DEVICE_DESC_IHPIB; 171 else if (da->da_id == DIO_DEVICE_ID_NHPIB) { 172 type = HPIBB; 173 desc = DIO_DEVICE_DESC_NHPIB; 174 } else 175 desc = "unknown HP-IB!"; 176 177 printf(" ipl %d: %s\n", ipl, desc); 178 179 /* Establish the interrupt handler. */ 180 (void) dio_intr_establish(nhpibintr, sc, ipl, IPL_BIO); 181 182 ha.ha_ops = &nhpib_controller; 183 ha.ha_type = type; /* XXX */ 184 ha.ha_ba = (type == HPIBA) ? HPIBA_BA : 185 (sc->sc_regs->hpib_csa & CSA_BA); 186 ha.ha_softcpp = &sc->sc_hpibbus; /* XXX */ 187 (void)config_found(self, &ha, hpibdevprint); 188 } 189 190 void 191 nhpibreset(hs) 192 struct hpibbus_softc *hs; 193 { 194 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent; 195 struct nhpibdevice *hd = sc->sc_regs; 196 197 hd->hpib_acr = AUX_SSWRST; 198 hd->hpib_ar = hs->sc_ba; 199 hd->hpib_lim = LIS_ERR; 200 hd->hpib_mim = 0; 201 hd->hpib_acr = AUX_CDAI; 202 hd->hpib_acr = AUX_CSHDW; 203 hd->hpib_acr = AUX_SSTD1; 204 hd->hpib_acr = AUX_SVSTD1; 205 hd->hpib_acr = AUX_CPP; 206 hd->hpib_acr = AUX_CHDFA; 207 hd->hpib_acr = AUX_CHDFE; 208 hd->hpib_acr = AUX_RHDF; 209 hd->hpib_acr = AUX_CSWRST; 210 nhpibifc(hd); 211 hd->hpib_ie = IDS_IE; 212 hd->hpib_data = C_DCL_P; 213 DELAY(100000); 214 } 215 216 void 217 nhpibifc(hd) 218 struct nhpibdevice *hd; 219 { 220 hd->hpib_acr = AUX_TCA; 221 hd->hpib_acr = AUX_CSRE; 222 hd->hpib_acr = AUX_SSIC; 223 DELAY(100); 224 hd->hpib_acr = AUX_CSIC; 225 hd->hpib_acr = AUX_SSRE; 226 } 227 228 int 229 nhpibsend(hs, slave, sec, ptr, origcnt) 230 struct hpibbus_softc *hs; 231 int slave, sec, origcnt; 232 void *ptr; 233 { 234 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent; 235 struct nhpibdevice *hd = sc->sc_regs; 236 int cnt = origcnt; 237 char *addr = ptr; 238 239 hd->hpib_acr = AUX_TCA; 240 hd->hpib_data = C_UNL_P; 241 if (nhpibwait(hd, MIS_BO)) 242 goto senderror; 243 hd->hpib_data = talker_par[hs->sc_ba]; 244 hd->hpib_acr = AUX_STON; 245 if (nhpibwait(hd, MIS_BO)) 246 goto senderror; 247 hd->hpib_data = listnr_par[slave]; 248 if (nhpibwait(hd, MIS_BO)) 249 goto senderror; 250 if (sec >= 0 || sec == -2) { 251 if (sec == -2) /* selected device clear KLUDGE */ 252 hd->hpib_data = C_SDC_P; 253 else 254 hd->hpib_data = sec_par[sec]; 255 if (nhpibwait(hd, MIS_BO)) 256 goto senderror; 257 } 258 hd->hpib_acr = AUX_GTS; 259 if (cnt) { 260 while (--cnt > 0) { 261 hd->hpib_data = *addr++; 262 if (nhpibwait(hd, MIS_BO)) 263 goto senderror; 264 } 265 hd->hpib_acr = AUX_EOI; 266 hd->hpib_data = *addr; 267 if (nhpibwait(hd, MIS_BO)) 268 goto senderror; 269 hd->hpib_acr = AUX_TCA; 270 #if 0 271 /* 272 * May be causing 345 disks to hang due to interference 273 * with PPOLL mechanism. 274 */ 275 hd->hpib_data = C_UNL_P; 276 (void) nhpibwait(hd, MIS_BO); 277 #endif 278 } 279 return(origcnt); 280 281 senderror: 282 nhpibifc(hd); 283 return(origcnt - cnt - 1); 284 } 285 286 int 287 nhpibrecv(hs, slave, sec, ptr, origcnt) 288 struct hpibbus_softc *hs; 289 int slave, sec, origcnt; 290 void *ptr; 291 { 292 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent; 293 struct nhpibdevice *hd = sc->sc_regs; 294 int cnt = origcnt; 295 char *addr = ptr; 296 297 /* 298 * Slave < 0 implies continuation of a previous receive 299 * that probably timed out. 300 */ 301 if (slave >= 0) { 302 hd->hpib_acr = AUX_TCA; 303 hd->hpib_data = C_UNL_P; 304 if (nhpibwait(hd, MIS_BO)) 305 goto recverror; 306 hd->hpib_data = listnr_par[hs->sc_ba]; 307 hd->hpib_acr = AUX_SLON; 308 if (nhpibwait(hd, MIS_BO)) 309 goto recverror; 310 hd->hpib_data = talker_par[slave]; 311 if (nhpibwait(hd, MIS_BO)) 312 goto recverror; 313 if (sec >= 0) { 314 hd->hpib_data = sec_par[sec]; 315 if (nhpibwait(hd, MIS_BO)) 316 goto recverror; 317 } 318 hd->hpib_acr = AUX_RHDF; 319 hd->hpib_acr = AUX_GTS; 320 } 321 if (cnt) { 322 while (--cnt >= 0) { 323 if (nhpibwait(hd, MIS_BI)) 324 goto recvbyteserror; 325 *addr++ = hd->hpib_data; 326 } 327 hd->hpib_acr = AUX_TCA; 328 hd->hpib_data = (slave == 31) ? C_UNA_P : C_UNT_P; 329 (void) nhpibwait(hd, MIS_BO); 330 } 331 return(origcnt); 332 333 recverror: 334 nhpibifc(hd); 335 recvbyteserror: 336 return(origcnt - cnt - 1); 337 } 338 339 void 340 nhpibgo(hs, slave, sec, ptr, count, rw, timo) 341 struct hpibbus_softc *hs; 342 int slave, sec, count, rw, timo; 343 void *ptr; 344 { 345 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent; 346 struct nhpibdevice *hd = sc->sc_regs; 347 char *addr = ptr; 348 349 hs->sc_flags |= HPIBF_IO; 350 if (timo) 351 hs->sc_flags |= HPIBF_TIMO; 352 if (rw == B_READ) 353 hs->sc_flags |= HPIBF_READ; 354 #ifdef DEBUG 355 else if (hs->sc_flags & HPIBF_READ) { 356 printf("nhpibgo: HPIBF_READ still set\n"); 357 hs->sc_flags &= ~HPIBF_READ; 358 } 359 #endif 360 hs->sc_count = count; 361 hs->sc_addr = addr; 362 if (hs->sc_flags & HPIBF_READ) { 363 hs->sc_curcnt = count; 364 dmago(hs->sc_dq->dq_chan, addr, count, DMAGO_BYTE|DMAGO_READ); 365 nhpibrecv(hs, slave, sec, 0, 0); 366 hd->hpib_mim = MIS_END; 367 } else { 368 hd->hpib_mim = 0; 369 if (count < hpibdmathresh) { 370 hs->sc_curcnt = count; 371 nhpibsend(hs, slave, sec, addr, count); 372 nhpibdone(hs); 373 return; 374 } 375 hs->sc_curcnt = --count; 376 dmago(hs->sc_dq->dq_chan, addr, count, DMAGO_BYTE); 377 nhpibsend(hs, slave, sec, 0, 0); 378 } 379 hd->hpib_ie = IDS_IE | IDS_DMA(hs->sc_dq->dq_chan); 380 } 381 382 /* 383 * This timeout can only happen if a DMA read finishes DMAing with the read 384 * still pending (more data in read transaction than the driver was prepared 385 * to accept). At the moment, variable-record tape drives are the only things 386 * capabale of doing this. We repeat the necessary code from nhpibintr() - 387 * easier and quicker than calling nhpibintr() for this special case. 388 */ 389 void 390 nhpibreadtimo(arg) 391 void *arg; 392 { 393 struct hpibbus_softc *hs = arg; 394 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent; 395 int s = splbio(); 396 397 if (hs->sc_flags & HPIBF_IO) { 398 struct nhpibdevice *hd = sc->sc_regs; 399 struct hpibqueue *hq; 400 401 hd->hpib_mim = 0; 402 hd->hpib_acr = AUX_TCA; 403 hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO); 404 dmafree(hs->sc_dq); 405 406 hq = hs->sc_queue.tqh_first; 407 (hq->hq_intr)(hq->hq_softc); 408 } 409 splx(s); 410 } 411 412 void 413 nhpibdone(hs) 414 struct hpibbus_softc *hs; 415 { 416 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent; 417 struct nhpibdevice *hd = sc->sc_regs; 418 int cnt; 419 420 cnt = hs->sc_curcnt; 421 hs->sc_addr += cnt; 422 hs->sc_count -= cnt; 423 hs->sc_flags |= HPIBF_DONE; 424 hd->hpib_ie = IDS_IE; 425 if (hs->sc_flags & HPIBF_READ) { 426 if ((hs->sc_flags & HPIBF_TIMO) && 427 (hd->hpib_ids & IDS_IR) == 0) 428 timeout(nhpibreadtimo, hs, hz >> 2); 429 } else { 430 if (hs->sc_count == 1) { 431 (void) nhpibwait(hd, MIS_BO); 432 hd->hpib_acr = AUX_EOI; 433 hd->hpib_data = *hs->sc_addr; 434 hd->hpib_mim = MIS_BO; 435 } 436 #ifdef DEBUG 437 else if (hs->sc_count) 438 panic("nhpibdone"); 439 #endif 440 } 441 } 442 443 int 444 nhpibintr(arg) 445 void *arg; 446 { 447 struct nhpib_softc *sc = arg; 448 struct hpibbus_softc *hs = sc->sc_hpibbus; 449 struct nhpibdevice *hd = sc->sc_regs; 450 struct hpibqueue *hq; 451 int stat0; 452 int stat1; 453 454 #ifdef lint 455 if (stat1 = unit) return(1); 456 #endif 457 if ((hd->hpib_ids & IDS_IR) == 0) 458 return(0); 459 stat0 = hd->hpib_mis; 460 stat1 = hd->hpib_lis; 461 462 hq = hs->sc_queue.tqh_first; 463 464 if (hs->sc_flags & HPIBF_IO) { 465 hd->hpib_mim = 0; 466 if ((hs->sc_flags & HPIBF_DONE) == 0) { 467 hs->sc_flags &= ~HPIBF_TIMO; 468 dmastop(hs->sc_dq->dq_chan); 469 } else if (hs->sc_flags & HPIBF_TIMO) 470 untimeout(nhpibreadtimo, hs); 471 hd->hpib_acr = AUX_TCA; 472 hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO); 473 474 dmafree(hs->sc_dq); 475 (hq->hq_intr)(hq->hq_softc); 476 } else if (hs->sc_flags & HPIBF_PPOLL) { 477 hd->hpib_mim = 0; 478 stat0 = nhpibppoll(hs); 479 if (stat0 & (0x80 >> hq->hq_slave)) { 480 hs->sc_flags &= ~HPIBF_PPOLL; 481 (hq->hq_intr)(hq->hq_softc); 482 } 483 #ifdef DEBUG 484 else 485 printf("%s: PPOLL intr bad status %x\n", 486 hs->sc_dev.dv_xname, stat0); 487 #endif 488 } 489 return(1); 490 } 491 492 int 493 nhpibppoll(hs) 494 struct hpibbus_softc *hs; 495 { 496 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent; 497 struct nhpibdevice *hd = sc->sc_regs; 498 int ppoll; 499 500 hd->hpib_acr = AUX_SPP; 501 DELAY(25); 502 ppoll = hd->hpib_cpt; 503 hd->hpib_acr = AUX_CPP; 504 return(ppoll); 505 } 506 507 #ifdef DEBUG 508 int nhpibreporttimo = 0; 509 #endif 510 511 int 512 nhpibwait(hd, x) 513 struct nhpibdevice *hd; 514 int x; 515 { 516 int timo = hpibtimeout; 517 518 while ((hd->hpib_mis & x) == 0 && --timo) 519 DELAY(1); 520 if (timo == 0) { 521 #ifdef DEBUG 522 if (nhpibreporttimo) 523 printf("hpib0: %s timo\n", x==MIS_BO?"OUT":"IN"); 524 #endif 525 return(-1); 526 } 527 return(0); 528 } 529 530 void 531 nhpibppwatch(arg) 532 void *arg; 533 { 534 struct hpibbus_softc *hs = arg; 535 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent; 536 extern int cold; 537 538 if ((hs->sc_flags & HPIBF_PPOLL) == 0) 539 return; 540 again: 541 if (nhpibppoll(hs) & (0x80 >> hs->sc_queue.tqh_first->hq_slave)) 542 sc->sc_regs->hpib_mim = MIS_BO; 543 else if (cold) 544 /* timeouts not working yet */ 545 goto again; 546 else 547 timeout(nhpibppwatch, hs, 1); 548 } 549