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