1 /* $NetBSD: nhpib.c,v 1.26 2002/10/02 05:15:53 thorpej 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.26 2002/10/02 05:15:53 thorpej 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 CFATTACH_DECL(nhpib, sizeof(struct nhpib_softc), 162 nhpibmatch, nhpibattach, NULL, NULL); 163 164 int 165 nhpibmatch(parent, match, aux) 166 struct device *parent; 167 struct cfdata *match; 168 void *aux; 169 { 170 struct dio_attach_args *da = aux; 171 172 if (da->da_id == DIO_DEVICE_ID_NHPIB || 173 da->da_id == DIO_DEVICE_ID_IHPIB) 174 return (1); 175 176 return (0); 177 } 178 179 void 180 nhpibattach(parent, self, aux) 181 struct device *parent, *self; 182 void *aux; 183 { 184 struct nhpib_softc *sc = (struct nhpib_softc *)self; 185 struct dio_attach_args *da = aux; 186 struct hpibdev_attach_args ha; 187 const char *desc; 188 int ipl, type = HPIBA; 189 190 sc->sc_regs = (struct nhpibdevice *)iomap(dio_scodetopa(da->da_scode), 191 da->da_size); 192 if (sc->sc_regs == NULL) { 193 printf("\n%s: can't map registers\n", self->dv_xname); 194 return; 195 } 196 197 ipl = DIO_IPL(sc->sc_regs); 198 199 if (da->da_scode == 7 && internalhpib) 200 desc = DIO_DEVICE_DESC_IHPIB; 201 else if (da->da_id == DIO_DEVICE_ID_NHPIB) { 202 type = HPIBB; 203 desc = DIO_DEVICE_DESC_NHPIB; 204 } else 205 desc = "unknown HP-IB!"; 206 207 printf(" ipl %d: %s\n", ipl, desc); 208 209 /* Establish the interrupt handler. */ 210 (void) dio_intr_establish(nhpibintr, sc, ipl, IPL_BIO); 211 212 callout_init(&sc->sc_read_ch); 213 callout_init(&sc->sc_ppwatch_ch); 214 215 ha.ha_ops = &nhpib_controller; 216 ha.ha_type = type; /* XXX */ 217 ha.ha_ba = (type == HPIBA) ? HPIBA_BA : 218 (sc->sc_regs->hpib_csa & CSA_BA); 219 ha.ha_softcpp = &sc->sc_hpibbus; /* XXX */ 220 (void)config_found(self, &ha, hpibdevprint); 221 } 222 223 void 224 nhpibreset(hs) 225 struct hpibbus_softc *hs; 226 { 227 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent; 228 struct nhpibdevice *hd = sc->sc_regs; 229 230 hd->hpib_acr = AUX_SSWRST; 231 hd->hpib_ar = hs->sc_ba; 232 hd->hpib_lim = LIS_ERR; 233 hd->hpib_mim = 0; 234 hd->hpib_acr = AUX_CDAI; 235 hd->hpib_acr = AUX_CSHDW; 236 hd->hpib_acr = AUX_SSTD1; 237 hd->hpib_acr = AUX_SVSTD1; 238 hd->hpib_acr = AUX_CPP; 239 hd->hpib_acr = AUX_CHDFA; 240 hd->hpib_acr = AUX_CHDFE; 241 hd->hpib_acr = AUX_RHDF; 242 hd->hpib_acr = AUX_CSWRST; 243 nhpibifc(hd); 244 hd->hpib_ie = IDS_IE; 245 hd->hpib_data = C_DCL_P; 246 DELAY(100000); 247 } 248 249 void 250 nhpibifc(hd) 251 struct nhpibdevice *hd; 252 { 253 hd->hpib_acr = AUX_TCA; 254 hd->hpib_acr = AUX_CSRE; 255 hd->hpib_acr = AUX_SSIC; 256 DELAY(100); 257 hd->hpib_acr = AUX_CSIC; 258 hd->hpib_acr = AUX_SSRE; 259 } 260 261 int 262 nhpibsend(hs, slave, sec, ptr, origcnt) 263 struct hpibbus_softc *hs; 264 int slave, sec, origcnt; 265 void *ptr; 266 { 267 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent; 268 struct nhpibdevice *hd = sc->sc_regs; 269 int cnt = origcnt; 270 char *addr = ptr; 271 272 hd->hpib_acr = AUX_TCA; 273 hd->hpib_data = C_UNL_P; 274 if (nhpibwait(hd, MIS_BO)) 275 goto senderror; 276 hd->hpib_data = talker_par[hs->sc_ba]; 277 hd->hpib_acr = AUX_STON; 278 if (nhpibwait(hd, MIS_BO)) 279 goto senderror; 280 hd->hpib_data = listnr_par[slave]; 281 if (nhpibwait(hd, MIS_BO)) 282 goto senderror; 283 if (sec >= 0 || sec == -2) { 284 if (sec == -2) /* selected device clear KLUDGE */ 285 hd->hpib_data = C_SDC_P; 286 else 287 hd->hpib_data = sec_par[sec]; 288 if (nhpibwait(hd, MIS_BO)) 289 goto senderror; 290 } 291 hd->hpib_acr = AUX_GTS; 292 if (cnt) { 293 while (--cnt > 0) { 294 hd->hpib_data = *addr++; 295 if (nhpibwait(hd, MIS_BO)) 296 goto senderror; 297 } 298 hd->hpib_acr = AUX_EOI; 299 hd->hpib_data = *addr; 300 if (nhpibwait(hd, MIS_BO)) 301 goto senderror; 302 hd->hpib_acr = AUX_TCA; 303 #if 0 304 /* 305 * May be causing 345 disks to hang due to interference 306 * with PPOLL mechanism. 307 */ 308 hd->hpib_data = C_UNL_P; 309 (void) nhpibwait(hd, MIS_BO); 310 #endif 311 } 312 return(origcnt); 313 314 senderror: 315 nhpibifc(hd); 316 return(origcnt - cnt - 1); 317 } 318 319 int 320 nhpibrecv(hs, slave, sec, ptr, origcnt) 321 struct hpibbus_softc *hs; 322 int slave, sec, origcnt; 323 void *ptr; 324 { 325 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent; 326 struct nhpibdevice *hd = sc->sc_regs; 327 int cnt = origcnt; 328 char *addr = ptr; 329 330 /* 331 * Slave < 0 implies continuation of a previous receive 332 * that probably timed out. 333 */ 334 if (slave >= 0) { 335 hd->hpib_acr = AUX_TCA; 336 hd->hpib_data = C_UNL_P; 337 if (nhpibwait(hd, MIS_BO)) 338 goto recverror; 339 hd->hpib_data = listnr_par[hs->sc_ba]; 340 hd->hpib_acr = AUX_SLON; 341 if (nhpibwait(hd, MIS_BO)) 342 goto recverror; 343 hd->hpib_data = talker_par[slave]; 344 if (nhpibwait(hd, MIS_BO)) 345 goto recverror; 346 if (sec >= 0) { 347 hd->hpib_data = sec_par[sec]; 348 if (nhpibwait(hd, MIS_BO)) 349 goto recverror; 350 } 351 hd->hpib_acr = AUX_RHDF; 352 hd->hpib_acr = AUX_GTS; 353 } 354 if (cnt) { 355 while (--cnt >= 0) { 356 if (nhpibwait(hd, MIS_BI)) 357 goto recvbyteserror; 358 *addr++ = hd->hpib_data; 359 } 360 hd->hpib_acr = AUX_TCA; 361 hd->hpib_data = (slave == 31) ? C_UNA_P : C_UNT_P; 362 (void) nhpibwait(hd, MIS_BO); 363 } 364 return(origcnt); 365 366 recverror: 367 nhpibifc(hd); 368 recvbyteserror: 369 return(origcnt - cnt - 1); 370 } 371 372 void 373 nhpibgo(hs, slave, sec, ptr, count, rw, timo) 374 struct hpibbus_softc *hs; 375 int slave, sec, count, rw, timo; 376 void *ptr; 377 { 378 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent; 379 struct nhpibdevice *hd = sc->sc_regs; 380 char *addr = ptr; 381 382 hs->sc_flags |= HPIBF_IO; 383 if (timo) 384 hs->sc_flags |= HPIBF_TIMO; 385 if (rw == B_READ) 386 hs->sc_flags |= HPIBF_READ; 387 #ifdef DEBUG 388 else if (hs->sc_flags & HPIBF_READ) { 389 printf("nhpibgo: HPIBF_READ still set\n"); 390 hs->sc_flags &= ~HPIBF_READ; 391 } 392 #endif 393 hs->sc_count = count; 394 hs->sc_addr = addr; 395 if (hs->sc_flags & HPIBF_READ) { 396 hs->sc_curcnt = count; 397 dmago(hs->sc_dq->dq_chan, addr, count, DMAGO_BYTE|DMAGO_READ); 398 nhpibrecv(hs, slave, sec, 0, 0); 399 hd->hpib_mim = MIS_END; 400 } else { 401 hd->hpib_mim = 0; 402 if (count < hpibdmathresh) { 403 hs->sc_curcnt = count; 404 nhpibsend(hs, slave, sec, addr, count); 405 nhpibdone(hs); 406 return; 407 } 408 hs->sc_curcnt = --count; 409 dmago(hs->sc_dq->dq_chan, addr, count, DMAGO_BYTE); 410 nhpibsend(hs, slave, sec, 0, 0); 411 } 412 hd->hpib_ie = IDS_IE | IDS_DMA(hs->sc_dq->dq_chan); 413 } 414 415 /* 416 * This timeout can only happen if a DMA read finishes DMAing with the read 417 * still pending (more data in read transaction than the driver was prepared 418 * to accept). At the moment, variable-record tape drives are the only things 419 * capabale of doing this. We repeat the necessary code from nhpibintr() - 420 * easier and quicker than calling nhpibintr() for this special case. 421 */ 422 void 423 nhpibreadtimo(arg) 424 void *arg; 425 { 426 struct hpibbus_softc *hs = arg; 427 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent; 428 int s = splbio(); 429 430 if (hs->sc_flags & HPIBF_IO) { 431 struct nhpibdevice *hd = sc->sc_regs; 432 struct hpibqueue *hq; 433 434 hd->hpib_mim = 0; 435 hd->hpib_acr = AUX_TCA; 436 hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO); 437 dmafree(hs->sc_dq); 438 439 hq = hs->sc_queue.tqh_first; 440 (hq->hq_intr)(hq->hq_softc); 441 } 442 splx(s); 443 } 444 445 void 446 nhpibdone(hs) 447 struct hpibbus_softc *hs; 448 { 449 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent; 450 struct nhpibdevice *hd = sc->sc_regs; 451 int cnt; 452 453 cnt = hs->sc_curcnt; 454 hs->sc_addr += cnt; 455 hs->sc_count -= cnt; 456 hs->sc_flags |= HPIBF_DONE; 457 hd->hpib_ie = IDS_IE; 458 if (hs->sc_flags & HPIBF_READ) { 459 if ((hs->sc_flags & HPIBF_TIMO) && 460 (hd->hpib_ids & IDS_IR) == 0) 461 callout_reset(&sc->sc_read_ch, hz >> 2, 462 nhpibreadtimo, hs); 463 } else { 464 if (hs->sc_count == 1) { 465 (void) nhpibwait(hd, MIS_BO); 466 hd->hpib_acr = AUX_EOI; 467 hd->hpib_data = *hs->sc_addr; 468 hd->hpib_mim = MIS_BO; 469 } 470 #ifdef DEBUG 471 else if (hs->sc_count) 472 panic("nhpibdone"); 473 #endif 474 } 475 } 476 477 int 478 nhpibintr(arg) 479 void *arg; 480 { 481 struct nhpib_softc *sc = arg; 482 struct hpibbus_softc *hs = sc->sc_hpibbus; 483 struct nhpibdevice *hd = sc->sc_regs; 484 struct hpibqueue *hq; 485 int stat0; 486 int stat1; 487 488 #ifdef lint 489 if (stat1 = unit) return(1); 490 #endif 491 if ((hd->hpib_ids & IDS_IR) == 0) 492 return(0); 493 stat0 = hd->hpib_mis; 494 stat1 = hd->hpib_lis; 495 496 hq = hs->sc_queue.tqh_first; 497 498 if (hs->sc_flags & HPIBF_IO) { 499 hd->hpib_mim = 0; 500 if ((hs->sc_flags & HPIBF_DONE) == 0) { 501 hs->sc_flags &= ~HPIBF_TIMO; 502 dmastop(hs->sc_dq->dq_chan); 503 } else if (hs->sc_flags & HPIBF_TIMO) 504 callout_stop(&sc->sc_read_ch); 505 hd->hpib_acr = AUX_TCA; 506 hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO); 507 508 dmafree(hs->sc_dq); 509 (hq->hq_intr)(hq->hq_softc); 510 } else if (hs->sc_flags & HPIBF_PPOLL) { 511 hd->hpib_mim = 0; 512 stat0 = nhpibppoll(hs); 513 if (stat0 & (0x80 >> hq->hq_slave)) { 514 hs->sc_flags &= ~HPIBF_PPOLL; 515 (hq->hq_intr)(hq->hq_softc); 516 } 517 #ifdef DEBUG 518 else 519 printf("%s: PPOLL intr bad status %x\n", 520 hs->sc_dev.dv_xname, stat0); 521 #endif 522 } 523 return(1); 524 } 525 526 int 527 nhpibppoll(hs) 528 struct hpibbus_softc *hs; 529 { 530 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent; 531 struct nhpibdevice *hd = sc->sc_regs; 532 int ppoll; 533 534 hd->hpib_acr = AUX_SPP; 535 DELAY(25); 536 ppoll = hd->hpib_cpt; 537 hd->hpib_acr = AUX_CPP; 538 return(ppoll); 539 } 540 541 #ifdef DEBUG 542 int nhpibreporttimo = 0; 543 #endif 544 545 int 546 nhpibwait(hd, x) 547 struct nhpibdevice *hd; 548 int x; 549 { 550 int timo = hpibtimeout; 551 552 while ((hd->hpib_mis & x) == 0 && --timo) 553 DELAY(1); 554 if (timo == 0) { 555 #ifdef DEBUG 556 if (nhpibreporttimo) 557 printf("hpib0: %s timo\n", x==MIS_BO?"OUT":"IN"); 558 #endif 559 return(-1); 560 } 561 return(0); 562 } 563 564 void 565 nhpibppwatch(arg) 566 void *arg; 567 { 568 struct hpibbus_softc *hs = arg; 569 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent; 570 571 if ((hs->sc_flags & HPIBF_PPOLL) == 0) 572 return; 573 again: 574 if (nhpibppoll(hs) & (0x80 >> hs->sc_queue.tqh_first->hq_slave)) 575 sc->sc_regs->hpib_mim = MIS_BO; 576 else if (cold) 577 /* timeouts not working yet */ 578 goto again; 579 else 580 callout_reset(&sc->sc_ppwatch_ch, 1, nhpibppwatch, hs); 581 } 582