|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1990 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution is only permitted until one year after the first shipment ! 6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and ! 7: * binary forms are permitted provided that: (1) source distributions retain ! 8: * this entire copyright notice and comment, and (2) distributions including ! 9: * binaries display the following acknowledgement: This product includes ! 10: * software developed by the University of California, Berkeley and its ! 11: * contributors'' in the documentation or other materials provided with the ! 12: * distribution and in all advertising materials mentioning features or use ! 13: * of this software. Neither the name of the University nor the names of ! 14: * its contributors may be used to endorse or promote products derived from ! 15: * this software without specific prior written permission. ! 16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 19: * ! 20: * @(#)fhpib.c 7.1 (Berkeley) 5/8/90 ! 21: */ ! 22: ! 23: /* ! 24: * 98625A/B HPIB driver ! 25: */ ! 26: #include "hpib.h" ! 27: #if NHPIB > 0 ! 28: ! 29: #include "param.h" ! 30: #include "systm.h" ! 31: #include "buf.h" ! 32: #include "device.h" ! 33: #include "fhpibreg.h" ! 34: #include "hpibvar.h" ! 35: #include "dmavar.h" ! 36: ! 37: /* ! 38: * Inline version of fhpibwait to be used in places where ! 39: * we don't worry about getting hung. ! 40: */ ! 41: #define FHPIBWAIT(hd, m) while (((hd)->hpib_intr & (m)) == 0) ! 42: ! 43: #ifdef DEBUG ! 44: int fhpibdebugunit = -1; ! 45: int fhpibdebug = 0; ! 46: #define FDB_FAIL 0x01 ! 47: #define FDB_DMA 0x02 ! 48: #define FDB_WAIT 0x04 ! 49: #define FDB_PPOLL 0x08 ! 50: ! 51: int dopriodma = 0; /* use high priority DMA */ ! 52: int doworddma = 1; /* non-zero if we should attempt word dma */ ! 53: int dolworddma = 1; /* use longword dma (scsi) */ ! 54: int doppollint = 1; /* use ppoll interrupts instead of watchdog */ ! 55: ! 56: long fhpibbadint[2] = { 0 }; ! 57: long fhpibtransfer[NHPIB] = { 0 }; ! 58: long fhpibnondma[NHPIB] = { 0 }; ! 59: long fhpibworddma[NHPIB] = { 0 }; ! 60: long fhpibremain[NHPIB] = { 0 }; ! 61: long fhpibloops[NHPIB] = { 0 }; ! 62: ! 63: #endif ! 64: ! 65: int fhpibcmd[NHPIB]; ! 66: int dmathresh = 3; /* char count beyond which we will attempt dma */ ! 67: ! 68: extern int hpibtimeout; ! 69: ! 70: fhpibtype(hc) ! 71: register struct hp_ctlr *hc; ! 72: { ! 73: register struct hpib_softc *hs = &hpib_softc[hc->hp_unit]; ! 74: register struct fhpibdevice *hd = (struct fhpibdevice *)hc->hp_addr; ! 75: ! 76: if (hd->hpib_cid != HPIBC) ! 77: return(0); ! 78: hs->sc_type = HPIBC; ! 79: hs->sc_ba = HPIBC_BA; ! 80: hc->hp_ipl = HPIB_IPL(hd->hpib_ids); ! 81: return(1); ! 82: } ! 83: ! 84: fhpibreset(unit) ! 85: { ! 86: register struct hpib_softc *hs = &hpib_softc[unit]; ! 87: register struct fhpibdevice *hd; ! 88: ! 89: hd = (struct fhpibdevice *)hs->sc_hc->hp_addr; ! 90: hd->hpib_cid = 0xFF; ! 91: DELAY(100); ! 92: hd->hpib_cmd = CT_8BIT; ! 93: hd->hpib_ar = AR_ARONC; ! 94: fhpibifc(hd); ! 95: hd->hpib_ie = IDS_IE; ! 96: hd->hpib_data = C_DCL; ! 97: DELAY(100000); ! 98: /* ! 99: * See if we can do word dma. ! 100: * If so, we should be able to write and read back the appropos bit. ! 101: */ ! 102: hd->hpib_ie |= IDS_WDMA; ! 103: if (hd->hpib_ie & IDS_WDMA) { ! 104: hd->hpib_ie &= ~IDS_WDMA; ! 105: hs->sc_flags |= HPIBF_DMA16; ! 106: #ifdef DEBUG ! 107: if (fhpibdebug & FDB_DMA) ! 108: printf("fhpibtype: unit %d has word dma\n", unit); ! 109: ! 110: #endif ! 111: } ! 112: } ! 113: ! 114: fhpibifc(hd) ! 115: register struct fhpibdevice *hd; ! 116: { ! 117: hd->hpib_cmd |= CT_IFC; ! 118: hd->hpib_cmd |= CT_INITFIFO; ! 119: DELAY(100); ! 120: hd->hpib_cmd &= ~CT_IFC; ! 121: hd->hpib_cmd |= CT_REN; ! 122: hd->hpib_stat = ST_ATN; ! 123: } ! 124: ! 125: fhpibsend(unit, slave, sec, addr, cnt) ! 126: register char *addr; ! 127: register int cnt; ! 128: { ! 129: register struct hpib_softc *hs = &hpib_softc[unit]; ! 130: register struct fhpibdevice *hd; ! 131: register int timo; ! 132: int origcnt = cnt; ! 133: int err = 0; ! 134: ! 135: hd = (struct fhpibdevice *)hs->sc_hc->hp_addr; ! 136: hd->hpib_stat = 0; ! 137: hd->hpib_imask = IM_IDLE | IM_ROOM; ! 138: if (fhpibwait(hd, IM_IDLE) < 0) ! 139: err++; ! 140: hd->hpib_stat = ST_ATN; ! 141: hd->hpib_data = C_UNL; ! 142: hd->hpib_data = C_TAG + hs->sc_ba; ! 143: hd->hpib_data = C_LAG + slave; ! 144: if (sec != -1) ! 145: hd->hpib_data = C_SCG + sec; ! 146: if (fhpibwait(hd, IM_IDLE) < 0) ! 147: err++; ! 148: hd->hpib_stat = ST_WRITE; ! 149: if (cnt && !err) { ! 150: while (--cnt) { ! 151: hd->hpib_data = *addr++; ! 152: timo = hpibtimeout; ! 153: while ((hd->hpib_intr & IM_ROOM) == 0) ! 154: if (--timo == 0) { ! 155: err++; ! 156: goto out; ! 157: } ! 158: } ! 159: hd->hpib_stat = ST_EOI; ! 160: hd->hpib_data = *addr; ! 161: FHPIBWAIT(hd, IM_ROOM); ! 162: hd->hpib_stat = ST_ATN; ! 163: /* XXX: HP-UX claims bug with CS80 transparent messages */ ! 164: if (sec == 0x12) ! 165: DELAY(150); ! 166: hd->hpib_data = C_UNL; ! 167: if (fhpibwait(hd, IM_IDLE) < 0) ! 168: err++; ! 169: } ! 170: out: ! 171: if (err) { ! 172: cnt++; ! 173: fhpibifc(hd); ! 174: #ifdef DEBUG ! 175: if (fhpibdebug & FDB_FAIL) { ! 176: printf("hpib%d: fhpibsend failed: slave %d, sec %x, ", ! 177: unit, slave, sec); ! 178: printf("sent %d of %d bytes\n", origcnt-cnt, origcnt); ! 179: } ! 180: #endif ! 181: } ! 182: hd->hpib_imask = 0; ! 183: return(origcnt - cnt); ! 184: } ! 185: ! 186: fhpibrecv(unit, slave, sec, addr, cnt) ! 187: register char *addr; ! 188: register int cnt; ! 189: { ! 190: register struct hpib_softc *hs = &hpib_softc[unit]; ! 191: register struct fhpibdevice *hd; ! 192: register int timo; ! 193: int origcnt = cnt; ! 194: int err = 0; ! 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: err++; ! 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: err++; ! 209: hd->hpib_stat = ST_READ0; ! 210: hd->hpib_data = 0; ! 211: if (cnt && !err) { ! 212: do { ! 213: timo = hpibtimeout; ! 214: while ((hd->hpib_intr & IM_BYTE) == 0) ! 215: if (--timo == 0) { ! 216: err++; ! 217: goto out; ! 218: } ! 219: *addr++ = hd->hpib_data; ! 220: } while (--cnt); ! 221: out: ! 222: FHPIBWAIT(hd, IM_ROOM); ! 223: hd->hpib_stat = ST_ATN; ! 224: hd->hpib_data = (slave == 31) ? C_UNA : C_UNT; ! 225: if (fhpibwait(hd, IM_IDLE) < 0) ! 226: err++; ! 227: } ! 228: if (err) { ! 229: if (!cnt) ! 230: cnt++; ! 231: fhpibifc(hd); ! 232: #ifdef DEBUG ! 233: if (fhpibdebug & FDB_FAIL) { ! 234: printf("hpib%d: fhpibrecv failed: slave %d, sec %x, ", ! 235: unit, slave, sec); ! 236: printf("got %d of %d bytes\n", origcnt-cnt, origcnt); ! 237: } ! 238: #endif ! 239: } ! 240: hd->hpib_imask = 0; ! 241: return(origcnt - cnt); ! 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 < dmathresh) { ! 305: #ifdef DEBUG ! 306: fhpibnondma[unit]++; ! 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: #ifdef DEBUG ! 353: fhpibremain[unit]++; ! 354: while ((hd->hpib_intr & IM_IDLE) == 0) ! 355: fhpibloops[unit]++; ! 356: #else ! 357: FHPIBWAIT(hd, IM_IDLE); ! 358: #endif ! 359: hd->hpib_stat = ST_WRITE; ! 360: while (--cnt) { ! 361: hd->hpib_data = *addr++; ! 362: FHPIBWAIT(hd, IM_ROOM); ! 363: } ! 364: hd->hpib_stat = ST_EOI; ! 365: hd->hpib_data = *addr; ! 366: } ! 367: hd->hpib_imask = IM_IDLE; ! 368: } ! 369: hs->sc_flags |= HPIBF_DONE; ! 370: hd->hpib_stat = ST_IENAB; ! 371: hd->hpib_ie = IDS_IE; ! 372: } ! 373: ! 374: fhpibintr(unit) ! 375: register int unit; ! 376: { ! 377: register struct hpib_softc *hs = &hpib_softc[unit]; ! 378: register struct fhpibdevice *hd; ! 379: register struct devqueue *dq; ! 380: register int stat0; ! 381: ! 382: hd = (struct fhpibdevice *)hs->sc_hc->hp_addr; ! 383: stat0 = hd->hpib_ids; ! 384: if ((stat0 & (IDS_IE|IDS_IR)) != (IDS_IE|IDS_IR)) { ! 385: #ifdef DEBUG ! 386: if ((fhpibdebug & FDB_FAIL) && (stat0 & IDS_IR) && ! 387: (hs->sc_flags & (HPIBF_IO|HPIBF_DONE)) != HPIBF_IO) ! 388: printf("hpib%d: fhpibintr: bad status %x\n", ! 389: unit, stat0); ! 390: fhpibbadint[0]++; ! 391: #endif ! 392: return(0); ! 393: } ! 394: if ((hs->sc_flags & (HPIBF_IO|HPIBF_DONE)) == HPIBF_IO) { ! 395: #ifdef DEBUG ! 396: fhpibbadint[1]++; ! 397: #endif ! 398: return(0); ! 399: } ! 400: #ifdef DEBUG ! 401: if ((fhpibdebug & FDB_DMA) && fhpibdebugunit == unit) ! 402: printf("fhpibintr: flags %x\n", hs->sc_flags); ! 403: #endif ! 404: dq = hs->sc_sq.dq_forw; ! 405: if (hs->sc_flags & HPIBF_IO) { ! 406: stat0 = hd->hpib_cmd; ! 407: hd->hpib_cmd = fhpibcmd[unit] & ~CT_8BIT; ! 408: hd->hpib_stat = 0; ! 409: hd->hpib_cmd = CT_REN | CT_8BIT; ! 410: stat0 = hd->hpib_intr; ! 411: hd->hpib_imask = 0; ! 412: hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ); ! 413: dmafree(&hs->sc_dq); ! 414: (dq->dq_driver->d_intr)(dq->dq_unit); ! 415: } else if (hs->sc_flags & HPIBF_PPOLL) { ! 416: stat0 = hd->hpib_intr; ! 417: #ifdef DEBUG ! 418: if ((fhpibdebug & FDB_FAIL) && ! 419: doppollint && (stat0 & IM_PPRESP) == 0) ! 420: printf("hpib%d: fhpibintr: bad intr reg %x\n", ! 421: unit, stat0); ! 422: #endif ! 423: hd->hpib_stat = 0; ! 424: hd->hpib_imask = 0; ! 425: #ifdef DEBUG ! 426: stat0 = fhpibppoll(unit); ! 427: if ((fhpibdebug & FDB_PPOLL) && unit == fhpibdebugunit) ! 428: printf("fhpibintr: got PPOLL status %x\n", stat0); ! 429: if ((stat0 & (0x80 >> dq->dq_slave)) == 0) { ! 430: printf("fhpibintr: PPOLL: unit %d slave %d stat %x\n", ! 431: unit, dq->dq_slave, stat0); ! 432: return(1); ! 433: } ! 434: #endif ! 435: hs->sc_flags &= ~HPIBF_PPOLL; ! 436: (dq->dq_driver->d_intr)(dq->dq_unit); ! 437: } ! 438: return(1); ! 439: } ! 440: ! 441: fhpibppoll(unit) ! 442: { ! 443: register struct fhpibdevice *hd; ! 444: register int ppoll; ! 445: ! 446: hd = (struct fhpibdevice *)hpib_softc[unit].sc_hc->hp_addr; ! 447: hd->hpib_stat = 0; ! 448: hd->hpib_psense = 0; ! 449: hd->hpib_pmask = 0xFF; ! 450: hd->hpib_imask = IM_PPRESP | IM_PABORT; ! 451: DELAY(25); ! 452: hd->hpib_intr = IM_PABORT; ! 453: ppoll = hd->hpib_data; ! 454: if (hd->hpib_intr & IM_PABORT) ! 455: ppoll = 0; ! 456: hd->hpib_imask = 0; ! 457: hd->hpib_pmask = 0; ! 458: hd->hpib_stat = ST_IENAB; ! 459: return(ppoll); ! 460: } ! 461: ! 462: fhpibwait(hd, x) ! 463: register struct fhpibdevice *hd; ! 464: { ! 465: register int timo = hpibtimeout; ! 466: ! 467: while ((hd->hpib_intr & x) == 0 && --timo) ! 468: ; ! 469: if (timo == 0) { ! 470: #ifdef DEBUG ! 471: if (fhpibdebug & FDB_FAIL) ! 472: printf("fhpibwait(%x, %x) timeout\n", hd, x); ! 473: #endif ! 474: return(-1); ! 475: } ! 476: return(0); ! 477: } ! 478: ! 479: /* ! 480: * XXX: this will have to change if we every allow more than one ! 481: * pending operation per HP-IB. ! 482: */ ! 483: fhpibppwatch(unit) ! 484: { ! 485: register struct hpib_softc *hs = &hpib_softc[unit]; ! 486: register struct fhpibdevice *hd; ! 487: register int slave; ! 488: ! 489: if ((hs->sc_flags & HPIBF_PPOLL) == 0) ! 490: return; ! 491: hd = (struct fhpibdevice *)hs->sc_hc->hp_addr; ! 492: slave = (0x80 >> hs->sc_sq.dq_forw->dq_slave); ! 493: #ifdef DEBUG ! 494: if (!doppollint) { ! 495: if (fhpibppoll(unit) & slave) { ! 496: hd->hpib_stat = ST_IENAB; ! 497: hd->hpib_imask = IM_IDLE | IM_ROOM; ! 498: } else ! 499: timeout(fhpibppwatch, unit, 1); ! 500: return; ! 501: } ! 502: if ((fhpibdebug & FDB_PPOLL) && unit == fhpibdebugunit) ! 503: printf("fhpibppwatch: sense request on %d\n", unit); ! 504: #endif ! 505: hd->hpib_psense = ~slave; ! 506: hd->hpib_pmask = slave; ! 507: hd->hpib_stat = ST_IENAB; ! 508: hd->hpib_imask = IM_PPRESP | IM_PABORT; ! 509: hd->hpib_ie = IDS_IE; ! 510: } ! 511: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.