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