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