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