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