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