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