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