1 /* 2 * Copyright (c) 1982, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)fhpib.c 8.2 (Berkeley) 01/12/94 8 */ 9 10 /* 11 * 98625A/B HPIB driver 12 */ 13 #include "hpib.h" 14 #if NHPIB > 0 15 16 #include <sys/param.h> 17 #include <sys/systm.h> 18 #include <sys/buf.h> 19 20 #include <hp/dev/device.h> 21 22 #include <hp300/dev/fhpibreg.h> 23 #include <hp300/dev/hpibvar.h> 24 #include <hp300/dev/dmavar.h> 25 26 /* 27 * Inline version of fhpibwait to be used in places where 28 * we don't worry about getting hung. 29 */ 30 #define FHPIBWAIT(hd, m) while (((hd)->hpib_intr & (m)) == 0) DELAY(1) 31 32 #ifdef DEBUG 33 int fhpibdebugunit = -1; 34 int fhpibdebug = 0; 35 #define FDB_FAIL 0x01 36 #define FDB_DMA 0x02 37 #define FDB_WAIT 0x04 38 #define FDB_PPOLL 0x08 39 40 int dopriodma = 0; /* use high priority DMA */ 41 int doworddma = 1; /* non-zero if we should attempt word dma */ 42 int doppollint = 1; /* use ppoll interrupts instead of watchdog */ 43 int fhpibppolldelay = 50; 44 45 long fhpibbadint[2] = { 0 }; 46 long fhpibtransfer[NHPIB] = { 0 }; 47 long fhpibnondma[NHPIB] = { 0 }; 48 long fhpibworddma[NHPIB] = { 0 }; 49 long fhpibppollfail[NHPIB] = { 0 }; 50 #endif 51 52 int fhpibcmd[NHPIB]; 53 54 fhpibtype(hc) 55 register struct hp_ctlr *hc; 56 { 57 register struct hpib_softc *hs = &hpib_softc[hc->hp_unit]; 58 register struct fhpibdevice *hd = (struct fhpibdevice *)hc->hp_addr; 59 60 if (hd->hpib_cid != HPIBC) 61 return(0); 62 hs->sc_type = HPIBC; 63 hs->sc_ba = HPIBC_BA; 64 hc->hp_ipl = HPIB_IPL(hd->hpib_ids); 65 return(1); 66 } 67 68 fhpibreset(unit) 69 int unit; 70 { 71 register struct hpib_softc *hs = &hpib_softc[unit]; 72 register struct fhpibdevice *hd; 73 74 hd = (struct fhpibdevice *)hs->sc_hc->hp_addr; 75 hd->hpib_cid = 0xFF; 76 DELAY(100); 77 hd->hpib_cmd = CT_8BIT; 78 hd->hpib_ar = AR_ARONC; 79 fhpibifc(hd); 80 hd->hpib_ie = IDS_IE; 81 hd->hpib_data = C_DCL; 82 DELAY(100000); 83 /* 84 * See if we can do word dma. 85 * If so, we should be able to write and read back the appropos bit. 86 */ 87 hd->hpib_ie |= IDS_WDMA; 88 if (hd->hpib_ie & IDS_WDMA) { 89 hd->hpib_ie &= ~IDS_WDMA; 90 hs->sc_flags |= HPIBF_DMA16; 91 #ifdef DEBUG 92 if (fhpibdebug & FDB_DMA) 93 printf("fhpibtype: unit %d has word dma\n", unit); 94 95 #endif 96 } 97 } 98 99 fhpibifc(hd) 100 register struct fhpibdevice *hd; 101 { 102 hd->hpib_cmd |= CT_IFC; 103 hd->hpib_cmd |= CT_INITFIFO; 104 DELAY(100); 105 hd->hpib_cmd &= ~CT_IFC; 106 hd->hpib_cmd |= CT_REN; 107 hd->hpib_stat = ST_ATN; 108 } 109 110 fhpibsend(unit, slave, sec, addr, origcnt) 111 int unit, slave, sec, origcnt; 112 register char *addr; 113 { 114 register struct hpib_softc *hs = &hpib_softc[unit]; 115 register struct fhpibdevice *hd; 116 register int cnt = origcnt; 117 register int timo; 118 119 hd = (struct fhpibdevice *)hs->sc_hc->hp_addr; 120 hd->hpib_stat = 0; 121 hd->hpib_imask = IM_IDLE | IM_ROOM; 122 if (fhpibwait(hd, IM_IDLE) < 0) 123 goto senderr; 124 hd->hpib_stat = ST_ATN; 125 hd->hpib_data = C_UNL; 126 hd->hpib_data = C_TAG + hs->sc_ba; 127 hd->hpib_data = C_LAG + slave; 128 if (sec != -1) 129 hd->hpib_data = C_SCG + sec; 130 if (fhpibwait(hd, IM_IDLE) < 0) 131 goto senderr; 132 if (cnt) { 133 hd->hpib_stat = ST_WRITE; 134 while (--cnt) { 135 hd->hpib_data = *addr++; 136 timo = hpibtimeout; 137 while ((hd->hpib_intr & IM_ROOM) == 0) { 138 if (--timo <= 0) 139 goto senderr; 140 DELAY(1); 141 } 142 } 143 hd->hpib_stat = ST_EOI; 144 hd->hpib_data = *addr; 145 FHPIBWAIT(hd, IM_ROOM); 146 hd->hpib_stat = ST_ATN; 147 /* XXX: HP-UX claims bug with CS80 transparent messages */ 148 if (sec == 0x12) 149 DELAY(150); 150 hd->hpib_data = C_UNL; 151 (void) fhpibwait(hd, IM_IDLE); 152 } 153 hd->hpib_imask = 0; 154 return (origcnt); 155 senderr: 156 hd->hpib_imask = 0; 157 fhpibifc(hd); 158 #ifdef DEBUG 159 if (fhpibdebug & FDB_FAIL) { 160 printf("hpib%d: fhpibsend failed: slave %d, sec %x, ", 161 unit, slave, sec); 162 printf("sent %d of %d bytes\n", origcnt-cnt-1, origcnt); 163 } 164 #endif 165 return(origcnt - cnt - 1); 166 } 167 168 fhpibrecv(unit, slave, sec, addr, origcnt) 169 int unit, slave, sec, origcnt; 170 register char *addr; 171 { 172 register struct hpib_softc *hs = &hpib_softc[unit]; 173 register struct fhpibdevice *hd; 174 register int cnt = origcnt; 175 register int timo; 176 177 hd = (struct fhpibdevice *)hs->sc_hc->hp_addr; 178 hd->hpib_stat = 0; 179 hd->hpib_imask = IM_IDLE | IM_ROOM | IM_BYTE; 180 if (fhpibwait(hd, IM_IDLE) < 0) 181 goto recverror; 182 hd->hpib_stat = ST_ATN; 183 hd->hpib_data = C_UNL; 184 hd->hpib_data = C_LAG + hs->sc_ba; 185 hd->hpib_data = C_TAG + slave; 186 if (sec != -1) 187 hd->hpib_data = C_SCG + sec; 188 if (fhpibwait(hd, IM_IDLE) < 0) 189 goto recverror; 190 hd->hpib_stat = ST_READ0; 191 hd->hpib_data = 0; 192 if (cnt) { 193 while (--cnt >= 0) { 194 timo = hpibtimeout; 195 while ((hd->hpib_intr & IM_BYTE) == 0) { 196 if (--timo == 0) 197 goto recvbyteserror; 198 DELAY(1); 199 } 200 *addr++ = hd->hpib_data; 201 } 202 FHPIBWAIT(hd, IM_ROOM); 203 hd->hpib_stat = ST_ATN; 204 hd->hpib_data = (slave == 31) ? C_UNA : C_UNT; 205 (void) fhpibwait(hd, IM_IDLE); 206 } 207 hd->hpib_imask = 0; 208 return (origcnt); 209 210 recverror: 211 fhpibifc(hd); 212 recvbyteserror: 213 hd->hpib_imask = 0; 214 #ifdef DEBUG 215 if (fhpibdebug & FDB_FAIL) { 216 printf("hpib%d: fhpibrecv failed: slave %d, sec %x, ", 217 unit, slave, sec); 218 printf("got %d of %d bytes\n", origcnt-cnt-1, origcnt); 219 } 220 #endif 221 return(origcnt - cnt - 1); 222 } 223 224 fhpibgo(unit, slave, sec, addr, count, rw) 225 register int unit; 226 int slave, sec, count, rw; 227 char *addr; 228 { 229 register struct hpib_softc *hs = &hpib_softc[unit]; 230 register struct fhpibdevice *hd; 231 register int i; 232 int flags = 0; 233 234 #ifdef lint 235 i = unit; if (i) return; 236 #endif 237 hd = (struct fhpibdevice *)hs->sc_hc->hp_addr; 238 hs->sc_flags |= HPIBF_IO; 239 if (rw == B_READ) 240 hs->sc_flags |= HPIBF_READ; 241 #ifdef DEBUG 242 else if (hs->sc_flags & HPIBF_READ) { 243 printf("fhpibgo: HPIBF_READ still set\n"); 244 hs->sc_flags &= ~HPIBF_READ; 245 } 246 #endif 247 hs->sc_count = count; 248 hs->sc_addr = addr; 249 #ifdef DEBUG 250 fhpibtransfer[unit]++; 251 #endif 252 if ((hs->sc_flags & HPIBF_DMA16) && 253 ((int)addr & 1) == 0 && count && (count & 1) == 0 254 #ifdef DEBUG 255 && doworddma 256 #endif 257 ) { 258 #ifdef DEBUG 259 fhpibworddma[unit]++; 260 #endif 261 flags |= DMAGO_WORD; 262 hd->hpib_latch = 0; 263 } 264 #ifdef DEBUG 265 if (dopriodma) 266 flags |= DMAGO_PRI; 267 #endif 268 if (hs->sc_flags & HPIBF_READ) { 269 fhpibcmd[unit] = CT_REN | CT_8BIT; 270 hs->sc_curcnt = count; 271 dmago(hs->sc_dq.dq_ctlr, addr, count, flags|DMAGO_READ); 272 if (fhpibrecv(unit, slave, sec, 0, 0) < 0) { 273 #ifdef DEBUG 274 printf("fhpibgo: recv failed, retrying...\n"); 275 #endif 276 (void) fhpibrecv(unit, slave, sec, 0, 0); 277 } 278 i = hd->hpib_cmd; 279 hd->hpib_cmd = fhpibcmd[unit]; 280 hd->hpib_ie = IDS_DMA(hs->sc_dq.dq_ctlr) | 281 ((flags & DMAGO_WORD) ? IDS_WDMA : 0); 282 return; 283 } 284 fhpibcmd[unit] = CT_REN | CT_8BIT | CT_FIFOSEL; 285 if (count < hpibdmathresh) { 286 #ifdef DEBUG 287 fhpibnondma[unit]++; 288 if (flags & DMAGO_WORD) 289 fhpibworddma[unit]--; 290 #endif 291 hs->sc_curcnt = count; 292 (void) fhpibsend(unit, slave, sec, addr, count); 293 fhpibdone(unit); 294 return; 295 } 296 count -= (flags & DMAGO_WORD) ? 2 : 1; 297 hs->sc_curcnt = count; 298 dmago(hs->sc_dq.dq_ctlr, addr, count, flags); 299 if (fhpibsend(unit, slave, sec, 0, 0) < 0) { 300 #ifdef DEBUG 301 printf("fhpibgo: send failed, retrying...\n"); 302 #endif 303 (void) fhpibsend(unit, slave, sec, 0, 0); 304 } 305 i = hd->hpib_cmd; 306 hd->hpib_cmd = fhpibcmd[unit]; 307 hd->hpib_ie = IDS_DMA(hs->sc_dq.dq_ctlr) | IDS_WRITE | 308 ((flags & DMAGO_WORD) ? IDS_WDMA : 0); 309 } 310 311 fhpibdone(unit) 312 int unit; 313 { 314 register struct hpib_softc *hs = &hpib_softc[unit]; 315 register struct fhpibdevice *hd; 316 register char *addr; 317 register int cnt; 318 319 hd = (struct fhpibdevice *)hs->sc_hc->hp_addr; 320 cnt = hs->sc_curcnt; 321 hs->sc_addr += cnt; 322 hs->sc_count -= cnt; 323 #ifdef DEBUG 324 if ((fhpibdebug & FDB_DMA) && fhpibdebugunit == unit) 325 printf("fhpibdone: addr %x cnt %d\n", 326 hs->sc_addr, hs->sc_count); 327 #endif 328 if (hs->sc_flags & HPIBF_READ) 329 hd->hpib_imask = IM_IDLE | IM_BYTE; 330 else { 331 cnt = hs->sc_count; 332 if (cnt) { 333 addr = hs->sc_addr; 334 hd->hpib_imask = IM_IDLE | IM_ROOM; 335 FHPIBWAIT(hd, IM_IDLE); 336 hd->hpib_stat = ST_WRITE; 337 while (--cnt) { 338 hd->hpib_data = *addr++; 339 FHPIBWAIT(hd, IM_ROOM); 340 } 341 hd->hpib_stat = ST_EOI; 342 hd->hpib_data = *addr; 343 } 344 hd->hpib_imask = IM_IDLE; 345 } 346 hs->sc_flags |= HPIBF_DONE; 347 hd->hpib_stat = ST_IENAB; 348 hd->hpib_ie = IDS_IE; 349 } 350 351 fhpibintr(unit) 352 register int unit; 353 { 354 register struct hpib_softc *hs = &hpib_softc[unit]; 355 register struct fhpibdevice *hd; 356 register struct devqueue *dq; 357 register int stat0; 358 359 hd = (struct fhpibdevice *)hs->sc_hc->hp_addr; 360 stat0 = hd->hpib_ids; 361 if ((stat0 & (IDS_IE|IDS_IR)) != (IDS_IE|IDS_IR)) { 362 #ifdef DEBUG 363 if ((fhpibdebug & FDB_FAIL) && (stat0 & IDS_IR) && 364 (hs->sc_flags & (HPIBF_IO|HPIBF_DONE)) != HPIBF_IO) 365 printf("hpib%d: fhpibintr: bad status %x\n", 366 unit, stat0); 367 fhpibbadint[0]++; 368 #endif 369 return(0); 370 } 371 if ((hs->sc_flags & (HPIBF_IO|HPIBF_DONE)) == HPIBF_IO) { 372 #ifdef DEBUG 373 fhpibbadint[1]++; 374 #endif 375 return(0); 376 } 377 #ifdef DEBUG 378 if ((fhpibdebug & FDB_DMA) && fhpibdebugunit == unit) 379 printf("fhpibintr: flags %x\n", hs->sc_flags); 380 #endif 381 dq = hs->sc_sq.dq_forw; 382 if (hs->sc_flags & HPIBF_IO) { 383 stat0 = hd->hpib_cmd; 384 hd->hpib_cmd = fhpibcmd[unit] & ~CT_8BIT; 385 hd->hpib_stat = 0; 386 hd->hpib_cmd = CT_REN | CT_8BIT; 387 stat0 = hd->hpib_intr; 388 hd->hpib_imask = 0; 389 hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ); 390 dmafree(&hs->sc_dq); 391 (dq->dq_driver->d_intr)(dq->dq_unit); 392 } else if (hs->sc_flags & HPIBF_PPOLL) { 393 stat0 = hd->hpib_intr; 394 #ifdef DEBUG 395 if ((fhpibdebug & FDB_FAIL) && 396 doppollint && (stat0 & IM_PPRESP) == 0) 397 printf("hpib%d: fhpibintr: bad intr reg %x\n", 398 unit, stat0); 399 #endif 400 hd->hpib_stat = 0; 401 hd->hpib_imask = 0; 402 #ifdef DEBUG 403 stat0 = fhpibppoll(unit); 404 if ((fhpibdebug & FDB_PPOLL) && unit == fhpibdebugunit) 405 printf("fhpibintr: got PPOLL status %x\n", stat0); 406 if ((stat0 & (0x80 >> dq->dq_slave)) == 0) { 407 /* 408 * XXX give it another shot (68040) 409 */ 410 fhpibppollfail[unit]++; 411 DELAY(fhpibppolldelay); 412 stat0 = fhpibppoll(unit); 413 if ((stat0 & (0x80 >> dq->dq_slave)) == 0 && 414 (fhpibdebug & FDB_PPOLL) && unit == fhpibdebugunit) 415 printf("fhpibintr: PPOLL: unit %d slave %d stat %x\n", 416 unit, dq->dq_slave, stat0); 417 } 418 #endif 419 hs->sc_flags &= ~HPIBF_PPOLL; 420 (dq->dq_driver->d_intr)(dq->dq_unit); 421 } 422 return(1); 423 } 424 425 fhpibppoll(unit) 426 int unit; 427 { 428 register struct fhpibdevice *hd; 429 register int ppoll; 430 431 hd = (struct fhpibdevice *)hpib_softc[unit].sc_hc->hp_addr; 432 hd->hpib_stat = 0; 433 hd->hpib_psense = 0; 434 hd->hpib_pmask = 0xFF; 435 hd->hpib_imask = IM_PPRESP | IM_PABORT; 436 DELAY(25); 437 hd->hpib_intr = IM_PABORT; 438 ppoll = hd->hpib_data; 439 if (hd->hpib_intr & IM_PABORT) 440 ppoll = 0; 441 hd->hpib_imask = 0; 442 hd->hpib_pmask = 0; 443 hd->hpib_stat = ST_IENAB; 444 return(ppoll); 445 } 446 447 fhpibwait(hd, x) 448 register struct fhpibdevice *hd; 449 int x; 450 { 451 register int timo = hpibtimeout; 452 453 while ((hd->hpib_intr & x) == 0 && --timo) 454 DELAY(1); 455 if (timo == 0) { 456 #ifdef DEBUG 457 if (fhpibdebug & FDB_FAIL) 458 printf("fhpibwait(%x, %x) timeout\n", hd, x); 459 #endif 460 return(-1); 461 } 462 return(0); 463 } 464 465 /* 466 * XXX: this will have to change if we ever allow more than one 467 * pending operation per HP-IB. 468 */ 469 void 470 fhpibppwatch(arg) 471 void *arg; 472 { 473 register int unit; 474 register struct hpib_softc *hs; 475 register struct fhpibdevice *hd; 476 register int slave; 477 478 unit = (int)arg; 479 hs = &hpib_softc[unit]; 480 if ((hs->sc_flags & HPIBF_PPOLL) == 0) 481 return; 482 hd = (struct fhpibdevice *)hs->sc_hc->hp_addr; 483 slave = (0x80 >> hs->sc_sq.dq_forw->dq_slave); 484 #ifdef DEBUG 485 if (!doppollint) { 486 if (fhpibppoll(unit) & slave) { 487 hd->hpib_stat = ST_IENAB; 488 hd->hpib_imask = IM_IDLE | IM_ROOM; 489 } else 490 timeout(fhpibppwatch, (void *)unit, 1); 491 return; 492 } 493 if ((fhpibdebug & FDB_PPOLL) && unit == fhpibdebugunit) 494 printf("fhpibppwatch: sense request on %d\n", unit); 495 #endif 496 hd->hpib_psense = ~slave; 497 hd->hpib_pmask = slave; 498 hd->hpib_stat = ST_IENAB; 499 hd->hpib_imask = IM_PPRESP | IM_PABORT; 500 hd->hpib_ie = IDS_IE; 501 } 502 #endif 503