📄 fhpib.c
字号:
/* * Copyright (c) 1982, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)fhpib.c 8.2 (Berkeley) 1/12/94 *//* * 98625A/B HPIB driver */#include "hpib.h"#if NHPIB > 0#include <sys/param.h>#include <sys/systm.h>#include <sys/buf.h>#include <hp/dev/device.h>#include <hp300/dev/fhpibreg.h>#include <hp300/dev/hpibvar.h>#include <hp300/dev/dmavar.h>/* * Inline version of fhpibwait to be used in places where * we don't worry about getting hung. */#define FHPIBWAIT(hd, m) while (((hd)->hpib_intr & (m)) == 0) DELAY(1)#ifdef DEBUGint fhpibdebugunit = -1;int fhpibdebug = 0;#define FDB_FAIL 0x01#define FDB_DMA 0x02#define FDB_WAIT 0x04#define FDB_PPOLL 0x08int dopriodma = 0; /* use high priority DMA */int doworddma = 1; /* non-zero if we should attempt word dma */int doppollint = 1; /* use ppoll interrupts instead of watchdog */int fhpibppolldelay = 50;long fhpibbadint[2] = { 0 };long fhpibtransfer[NHPIB] = { 0 };long fhpibnondma[NHPIB] = { 0 };long fhpibworddma[NHPIB] = { 0 };long fhpibppollfail[NHPIB] = { 0 };#endifint fhpibcmd[NHPIB];fhpibtype(hc) register struct hp_ctlr *hc;{ register struct hpib_softc *hs = &hpib_softc[hc->hp_unit]; register struct fhpibdevice *hd = (struct fhpibdevice *)hc->hp_addr; if (hd->hpib_cid != HPIBC) return(0); hs->sc_type = HPIBC; hs->sc_ba = HPIBC_BA; hc->hp_ipl = HPIB_IPL(hd->hpib_ids); return(1);}fhpibreset(unit) int unit;{ register struct hpib_softc *hs = &hpib_softc[unit]; register struct fhpibdevice *hd; hd = (struct fhpibdevice *)hs->sc_hc->hp_addr; hd->hpib_cid = 0xFF; DELAY(100); hd->hpib_cmd = CT_8BIT; hd->hpib_ar = AR_ARONC; fhpibifc(hd); hd->hpib_ie = IDS_IE; hd->hpib_data = C_DCL; DELAY(100000); /* * See if we can do word dma. * If so, we should be able to write and read back the appropos bit. */ hd->hpib_ie |= IDS_WDMA; if (hd->hpib_ie & IDS_WDMA) { hd->hpib_ie &= ~IDS_WDMA; hs->sc_flags |= HPIBF_DMA16;#ifdef DEBUG if (fhpibdebug & FDB_DMA) printf("fhpibtype: unit %d has word dma\n", unit);#endif }}fhpibifc(hd) register struct fhpibdevice *hd;{ hd->hpib_cmd |= CT_IFC; hd->hpib_cmd |= CT_INITFIFO; DELAY(100); hd->hpib_cmd &= ~CT_IFC; hd->hpib_cmd |= CT_REN; hd->hpib_stat = ST_ATN;}fhpibsend(unit, slave, sec, addr, origcnt) int unit, slave, sec, origcnt; register char *addr;{ register struct hpib_softc *hs = &hpib_softc[unit]; register struct fhpibdevice *hd; register int cnt = origcnt; register int timo; hd = (struct fhpibdevice *)hs->sc_hc->hp_addr; hd->hpib_stat = 0; hd->hpib_imask = IM_IDLE | IM_ROOM; if (fhpibwait(hd, IM_IDLE) < 0) goto senderr; hd->hpib_stat = ST_ATN; hd->hpib_data = C_UNL; hd->hpib_data = C_TAG + hs->sc_ba; hd->hpib_data = C_LAG + slave; if (sec != -1) hd->hpib_data = C_SCG + sec; if (fhpibwait(hd, IM_IDLE) < 0) goto senderr; if (cnt) { hd->hpib_stat = ST_WRITE; while (--cnt) { hd->hpib_data = *addr++; timo = hpibtimeout; while ((hd->hpib_intr & IM_ROOM) == 0) { if (--timo <= 0) goto senderr; DELAY(1); } } hd->hpib_stat = ST_EOI; hd->hpib_data = *addr; FHPIBWAIT(hd, IM_ROOM); hd->hpib_stat = ST_ATN; /* XXX: HP-UX claims bug with CS80 transparent messages */ if (sec == 0x12) DELAY(150); hd->hpib_data = C_UNL; (void) fhpibwait(hd, IM_IDLE); } hd->hpib_imask = 0; return (origcnt);senderr: hd->hpib_imask = 0; fhpibifc(hd);#ifdef DEBUG if (fhpibdebug & FDB_FAIL) { printf("hpib%d: fhpibsend failed: slave %d, sec %x, ", unit, slave, sec); printf("sent %d of %d bytes\n", origcnt-cnt-1, origcnt); }#endif return(origcnt - cnt - 1);}fhpibrecv(unit, slave, sec, addr, origcnt) int unit, slave, sec, origcnt; register char *addr;{ register struct hpib_softc *hs = &hpib_softc[unit]; register struct fhpibdevice *hd; register int cnt = origcnt; register int timo; hd = (struct fhpibdevice *)hs->sc_hc->hp_addr; hd->hpib_stat = 0; hd->hpib_imask = IM_IDLE | IM_ROOM | IM_BYTE; if (fhpibwait(hd, IM_IDLE) < 0) goto recverror; hd->hpib_stat = ST_ATN; hd->hpib_data = C_UNL; hd->hpib_data = C_LAG + hs->sc_ba; hd->hpib_data = C_TAG + slave; if (sec != -1) hd->hpib_data = C_SCG + sec; if (fhpibwait(hd, IM_IDLE) < 0) goto recverror; hd->hpib_stat = ST_READ0; hd->hpib_data = 0; if (cnt) { while (--cnt >= 0) { timo = hpibtimeout; while ((hd->hpib_intr & IM_BYTE) == 0) { if (--timo == 0) goto recvbyteserror; DELAY(1); } *addr++ = hd->hpib_data; } FHPIBWAIT(hd, IM_ROOM); hd->hpib_stat = ST_ATN; hd->hpib_data = (slave == 31) ? C_UNA : C_UNT; (void) fhpibwait(hd, IM_IDLE); } hd->hpib_imask = 0; return (origcnt);recverror: fhpibifc(hd);recvbyteserror: hd->hpib_imask = 0;#ifdef DEBUG if (fhpibdebug & FDB_FAIL) { printf("hpib%d: fhpibrecv failed: slave %d, sec %x, ", unit, slave, sec); printf("got %d of %d bytes\n", origcnt-cnt-1, origcnt); }#endif return(origcnt - cnt - 1);}fhpibgo(unit, slave, sec, addr, count, rw) register int unit; int slave, sec, count, rw; char *addr;{ register struct hpib_softc *hs = &hpib_softc[unit]; register struct fhpibdevice *hd; register int i; int flags = 0;#ifdef lint i = unit; if (i) return;#endif hd = (struct fhpibdevice *)hs->sc_hc->hp_addr; hs->sc_flags |= HPIBF_IO; if (rw == B_READ) hs->sc_flags |= HPIBF_READ;#ifdef DEBUG else if (hs->sc_flags & HPIBF_READ) { printf("fhpibgo: HPIBF_READ still set\n"); hs->sc_flags &= ~HPIBF_READ; }#endif hs->sc_count = count; hs->sc_addr = addr;#ifdef DEBUG fhpibtransfer[unit]++;#endif if ((hs->sc_flags & HPIBF_DMA16) && ((int)addr & 1) == 0 && count && (count & 1) == 0#ifdef DEBUG && doworddma#endif ) {#ifdef DEBUG fhpibworddma[unit]++;#endif flags |= DMAGO_WORD; hd->hpib_latch = 0; }#ifdef DEBUG if (dopriodma) flags |= DMAGO_PRI;#endif if (hs->sc_flags & HPIBF_READ) { fhpibcmd[unit] = CT_REN | CT_8BIT; hs->sc_curcnt = count; dmago(hs->sc_dq.dq_ctlr, addr, count, flags|DMAGO_READ); if (fhpibrecv(unit, slave, sec, 0, 0) < 0) {#ifdef DEBUG printf("fhpibgo: recv failed, retrying...\n");#endif (void) fhpibrecv(unit, slave, sec, 0, 0); } i = hd->hpib_cmd; hd->hpib_cmd = fhpibcmd[unit]; hd->hpib_ie = IDS_DMA(hs->sc_dq.dq_ctlr) | ((flags & DMAGO_WORD) ? IDS_WDMA : 0); return; } fhpibcmd[unit] = CT_REN | CT_8BIT | CT_FIFOSEL; if (count < hpibdmathresh) {#ifdef DEBUG fhpibnondma[unit]++; if (flags & DMAGO_WORD) fhpibworddma[unit]--;#endif hs->sc_curcnt = count; (void) fhpibsend(unit, slave, sec, addr, count); fhpibdone(unit); return; } count -= (flags & DMAGO_WORD) ? 2 : 1; hs->sc_curcnt = count; dmago(hs->sc_dq.dq_ctlr, addr, count, flags); if (fhpibsend(unit, slave, sec, 0, 0) < 0) {#ifdef DEBUG printf("fhpibgo: send failed, retrying...\n");#endif (void) fhpibsend(unit, slave, sec, 0, 0); } i = hd->hpib_cmd; hd->hpib_cmd = fhpibcmd[unit]; hd->hpib_ie = IDS_DMA(hs->sc_dq.dq_ctlr) | IDS_WRITE | ((flags & DMAGO_WORD) ? IDS_WDMA : 0);}fhpibdone(unit) int unit;{ register struct hpib_softc *hs = &hpib_softc[unit]; register struct fhpibdevice *hd; register char *addr; register int cnt; hd = (struct fhpibdevice *)hs->sc_hc->hp_addr; cnt = hs->sc_curcnt; hs->sc_addr += cnt; hs->sc_count -= cnt;#ifdef DEBUG if ((fhpibdebug & FDB_DMA) && fhpibdebugunit == unit) printf("fhpibdone: addr %x cnt %d\n", hs->sc_addr, hs->sc_count);#endif if (hs->sc_flags & HPIBF_READ) hd->hpib_imask = IM_IDLE | IM_BYTE; else { cnt = hs->sc_count; if (cnt) { addr = hs->sc_addr; hd->hpib_imask = IM_IDLE | IM_ROOM; FHPIBWAIT(hd, IM_IDLE); hd->hpib_stat = ST_WRITE; while (--cnt) { hd->hpib_data = *addr++; FHPIBWAIT(hd, IM_ROOM); } hd->hpib_stat = ST_EOI; hd->hpib_data = *addr; } hd->hpib_imask = IM_IDLE; } hs->sc_flags |= HPIBF_DONE; hd->hpib_stat = ST_IENAB; hd->hpib_ie = IDS_IE;}fhpibintr(unit) register int unit;{ register struct hpib_softc *hs = &hpib_softc[unit]; register struct fhpibdevice *hd; register struct devqueue *dq; register int stat0; hd = (struct fhpibdevice *)hs->sc_hc->hp_addr; stat0 = hd->hpib_ids; if ((stat0 & (IDS_IE|IDS_IR)) != (IDS_IE|IDS_IR)) {#ifdef DEBUG if ((fhpibdebug & FDB_FAIL) && (stat0 & IDS_IR) && (hs->sc_flags & (HPIBF_IO|HPIBF_DONE)) != HPIBF_IO) printf("hpib%d: fhpibintr: bad status %x\n", unit, stat0); fhpibbadint[0]++;#endif return(0); } if ((hs->sc_flags & (HPIBF_IO|HPIBF_DONE)) == HPIBF_IO) {#ifdef DEBUG fhpibbadint[1]++;#endif return(0); }#ifdef DEBUG if ((fhpibdebug & FDB_DMA) && fhpibdebugunit == unit) printf("fhpibintr: flags %x\n", hs->sc_flags);#endif dq = hs->sc_sq.dq_forw; if (hs->sc_flags & HPIBF_IO) { stat0 = hd->hpib_cmd; hd->hpib_cmd = fhpibcmd[unit] & ~CT_8BIT; hd->hpib_stat = 0; hd->hpib_cmd = CT_REN | CT_8BIT; stat0 = hd->hpib_intr; hd->hpib_imask = 0; hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ); dmafree(&hs->sc_dq); (dq->dq_driver->d_intr)(dq->dq_unit); } else if (hs->sc_flags & HPIBF_PPOLL) { stat0 = hd->hpib_intr;#ifdef DEBUG if ((fhpibdebug & FDB_FAIL) && doppollint && (stat0 & IM_PPRESP) == 0) printf("hpib%d: fhpibintr: bad intr reg %x\n", unit, stat0);#endif hd->hpib_stat = 0; hd->hpib_imask = 0;#ifdef DEBUG stat0 = fhpibppoll(unit); if ((fhpibdebug & FDB_PPOLL) && unit == fhpibdebugunit) printf("fhpibintr: got PPOLL status %x\n", stat0); if ((stat0 & (0x80 >> dq->dq_slave)) == 0) { /* * XXX give it another shot (68040) */ fhpibppollfail[unit]++; DELAY(fhpibppolldelay); stat0 = fhpibppoll(unit); if ((stat0 & (0x80 >> dq->dq_slave)) == 0 && (fhpibdebug & FDB_PPOLL) && unit == fhpibdebugunit) printf("fhpibintr: PPOLL: unit %d slave %d stat %x\n", unit, dq->dq_slave, stat0); }#endif hs->sc_flags &= ~HPIBF_PPOLL; (dq->dq_driver->d_intr)(dq->dq_unit); } return(1);}fhpibppoll(unit) int unit;{ register struct fhpibdevice *hd; register int ppoll; hd = (struct fhpibdevice *)hpib_softc[unit].sc_hc->hp_addr; hd->hpib_stat = 0; hd->hpib_psense = 0; hd->hpib_pmask = 0xFF; hd->hpib_imask = IM_PPRESP | IM_PABORT; DELAY(25); hd->hpib_intr = IM_PABORT; ppoll = hd->hpib_data; if (hd->hpib_intr & IM_PABORT) ppoll = 0; hd->hpib_imask = 0; hd->hpib_pmask = 0; hd->hpib_stat = ST_IENAB; return(ppoll);}fhpibwait(hd, x) register struct fhpibdevice *hd; int x;{ register int timo = hpibtimeout; while ((hd->hpib_intr & x) == 0 && --timo) DELAY(1); if (timo == 0) {#ifdef DEBUG if (fhpibdebug & FDB_FAIL) printf("fhpibwait(%x, %x) timeout\n", hd, x);#endif return(-1); } return(0);}/* * XXX: this will have to change if we ever allow more than one * pending operation per HP-IB. */voidfhpibppwatch(arg) void *arg;{ register int unit; register struct hpib_softc *hs; register struct fhpibdevice *hd; register int slave; unit = (int)arg; hs = &hpib_softc[unit]; if ((hs->sc_flags & HPIBF_PPOLL) == 0) return; hd = (struct fhpibdevice *)hs->sc_hc->hp_addr; slave = (0x80 >> hs->sc_sq.dq_forw->dq_slave);#ifdef DEBUG if (!doppollint) { if (fhpibppoll(unit) & slave) { hd->hpib_stat = ST_IENAB; hd->hpib_imask = IM_IDLE | IM_ROOM; } else timeout(fhpibppwatch, (void *)unit, 1); return; } if ((fhpibdebug & FDB_PPOLL) && unit == fhpibdebugunit) printf("fhpibppwatch: sense request on %d\n", unit);#endif hd->hpib_psense = ~slave; hd->hpib_pmask = slave; hd->hpib_stat = ST_IENAB; hd->hpib_imask = IM_PPRESP | IM_PABORT; hd->hpib_ie = IDS_IE;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -