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