summaryrefslogtreecommitdiffstats
path: root/sys/dev/ieee488
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2005-02-12 17:39:50 +0000
committerphk <phk@FreeBSD.org>2005-02-12 17:39:50 +0000
commitf634be7a95eeb69c8ade4746fcb55a6725acd7bb (patch)
tree1be7f508259f8e3cbb94c975484d9606fdb3b25a /sys/dev/ieee488
parentd3f751172c945cad64cc899acaf7b0b30e490471 (diff)
downloadFreeBSD-src-f634be7a95eeb69c8ade4746fcb55a6725acd7bb.zip
FreeBSD-src-f634be7a95eeb69c8ade4746fcb55a6725acd7bb.tar.gz
Split the ibfoo API into its own file.
Implement ibdma() (only affects ibrd() mode) Implement ibeot()
Diffstat (limited to 'sys/dev/ieee488')
-rw-r--r--sys/dev/ieee488/ibfoo.c856
-rw-r--r--sys/dev/ieee488/pcii.c1
-rw-r--r--sys/dev/ieee488/upd7210.c830
-rw-r--r--sys/dev/ieee488/upd7210.h33
4 files changed, 926 insertions, 794 deletions
diff --git a/sys/dev/ieee488/ibfoo.c b/sys/dev/ieee488/ibfoo.c
new file mode 100644
index 0000000..a2bd1c5
--- /dev/null
+++ b/sys/dev/ieee488/ibfoo.c
@@ -0,0 +1,856 @@
+/*-
+ * Copyright (c) 2005 Poul-Henning Kamp <phk@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * High-level driver for µPD7210 based GPIB cards.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+# define IBDEBUG
+# undef IBDEBUG
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/limits.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <isa/isavar.h>
+
+#include <dev/ieee488/ugpib.h>
+
+#define UPD7210_SW_DRIVER
+#include <dev/ieee488/upd7210.h>
+
+static MALLOC_DEFINE(M_IBFOO, "IBFOO", "IBFOO");
+
+
+/* ibfoo API */
+
+#include <dev/ieee488/ibfoo_int.h>
+
+struct handle {
+ LIST_ENTRY(handle) list;
+ int handle;
+ int pad;
+ int sad;
+ struct timeval timeout;
+ int eot;
+ int eos;
+ int dma;
+};
+
+struct ibfoo {
+ struct upd7210 *upd7210;
+ LIST_HEAD(,handle) handles;
+ struct unrhdr *unrhdr;
+
+ enum {
+ IDLE,
+ PIO_IDATA,
+ DMA_IDATA,
+ PIO_ODATA,
+ PIO_CMD
+ } mode;
+
+ struct timeval deadline;
+
+ struct handle *rdh; /* addressed for read */
+ struct handle *wrh; /* addressed for write */
+
+ int doeoi;
+
+ u_char *buf;
+ u_int buflen;
+};
+
+static struct timeval timeouts[] = {
+ [TNONE] = { 0, 0},
+ [T10us] = { 0, 10},
+ [T30us] = { 0, 30},
+ [T100us] = { 0, 100},
+ [T300us] = { 0, 300},
+ [T1ms] = { 0, 1000},
+ [T3ms] = { 0, 3000},
+ [T10ms] = { 0, 10000},
+ [T30ms] = { 0, 30000},
+ [T100ms] = { 0, 100000},
+ [T300ms] = { 0, 300000},
+ [T1s] = { 1, 0},
+ [T3s] = { 3, 0},
+ [T10s] = { 10, 0},
+ [T30s] = { 30, 0},
+ [T100s] = { 100, 0},
+ [T300s] = { 300, 0},
+ [T1000s] = { 1000, 0}
+};
+
+static const u_int max_timeouts = sizeof timeouts / sizeof timeouts[0];
+
+static int
+deadyet(struct ibfoo *ib)
+{
+ struct timeval tv;
+
+ if (!timevalisset(&ib->deadline))
+ return (0);
+
+ getmicrouptime(&tv);
+ if (timevalcmp(&ib->deadline, &tv, <)) {
+printf("DEADNOW\n");
+ return (1);
+ }
+
+ return (0);
+}
+
+typedef int ibhandler_t(struct handle *h, struct upd7210 *u, struct ibfoo_iocarg *ap);
+
+static int
+gpib_ib_irq(struct upd7210 *u, int intr __unused)
+{
+ struct ibfoo *ib;
+
+ ib = u->ibfoo;
+
+ switch (ib->mode) {
+ case PIO_CMD:
+ if (!(u->rreg[ISR2] & IXR2_CO))
+ return (0);
+ if (ib->buflen == 0)
+ break;
+ upd7210_wr(u, CDOR, *ib->buf);
+ ib->buf++;
+ ib->buflen--;
+ return (1);
+ case PIO_IDATA:
+ if (!(u->rreg[ISR1] & IXR1_DI))
+ return (0);
+ *ib->buf = upd7210_rd(u, DIR);
+ ib->buf++;
+ ib->buflen--;
+ if (ib->buflen == 0 || (u->rreg[ISR1] & IXR1_ENDRX))
+ break;
+ return (1);
+ case PIO_ODATA:
+ if (!(u->rreg[ISR1] & IXR1_DO))
+ return (0);
+ if (ib->buflen == 0)
+ break;
+ if (ib->buflen == 1 && ib->doeoi)
+ upd7210_wr(u, AUXMR, AUXMR_SEOI);
+ upd7210_wr(u, CDOR, *ib->buf);
+ ib->buf++;
+ ib->buflen--;
+ return (1);
+ case DMA_IDATA:
+ if (!(u->rreg[ISR1] & IXR1_ENDRX))
+ return (0);
+ break;
+ default:
+ return (0);
+ }
+ upd7210_wr(u, IMR1, 0);
+ upd7210_wr(u, IMR2, 0);
+ ib->mode = IDLE;
+ wakeup(ib);
+ return (1);
+}
+
+static void
+config_eos(struct upd7210 *u, struct handle *h)
+{
+ int i;
+
+ i = 0;
+ if (h->eos & REOS) {
+ upd7210_wr(u, EOSR, h->eos & 0xff);
+ i |= AUXA_REOS;
+ }
+ if (h->eos & XEOS) {
+ upd7210_wr(u, EOSR, h->eos & 0xff);
+ i |= AUXA_XEOS;
+ }
+ if (h->eos & BIN)
+ i |= AUXA_BIN;
+ upd7210_wr(u, AUXRA, C_AUXA | i);
+}
+
+/*
+ * Look up the handle, and set the deadline if the handle has a timeout.
+ */
+static int
+gethandle(struct upd7210 *u, struct ibfoo_iocarg *ap, struct handle **hp)
+{
+ struct ibfoo *ib;
+ struct handle *h;
+
+ KASSERT(ap->__field & __F_HANDLE, ("gethandle without __F_HANDLE"));
+ ib = u->ibfoo;
+ LIST_FOREACH(h, &ib->handles, list) {
+ if (h->handle == ap->handle) {
+ *hp = h;
+ if (timevalisset(&h->timeout)) {
+ getmicrouptime(&ib->deadline);
+ timevaladd(&ib->deadline, &h->timeout);
+ } else {
+ timevalclear(&ib->deadline);
+ }
+ return (0);
+ }
+ }
+ ap->__iberr = EARG;
+ return (1);
+}
+
+static int
+pio_cmd(struct upd7210 *u, u_char *cmd, int len)
+{
+ int i;
+ struct ibfoo *ib;
+
+ ib = u->ibfoo;
+
+ if (ib->rdh != NULL || ib->wrh != NULL) {
+ upd7210_take_ctrl_async(u);
+ ib->rdh = NULL;
+ ib->wrh = NULL;
+ }
+ mtx_lock(&u->mutex);
+ ib->mode = PIO_CMD;
+ ib->buf = cmd;
+ ib->buflen = len;
+ upd7210_wr(u, IMR2, IXR2_CO);
+
+ gpib_ib_irq(u, 1);
+
+ while (1) {
+ i = msleep(ib, &u->mutex, PZERO | PCATCH, "gpib_cmd", hz/10);
+ if (i == EINTR)
+ break;
+ if (u->rreg[ISR1] & IXR1_ERR)
+ break;
+ if (!ib->buflen)
+ break;
+ if (deadyet(ib))
+ break;
+ }
+ upd7210_wr(u, IMR2, 0);
+ mtx_unlock(&u->mutex);
+ return (0);
+}
+
+static int
+pio_odata(struct upd7210 *u, u_char *data, int len)
+{
+ int i;
+ struct ibfoo *ib;
+
+ ib = u->ibfoo;
+
+ if (len == 0)
+ return (0);
+ mtx_lock(&u->mutex);
+ ib->mode = PIO_ODATA;
+ ib->buf = data;
+ ib->buflen = len;
+ upd7210_wr(u, IMR1, IXR1_DO);
+
+ gpib_ib_irq(u, 1);
+
+ while (1) {
+ i = msleep(ib, &u->mutex, PZERO | PCATCH, "gpib_out", hz/100);
+ if (i == EINTR || i == 0)
+ break;
+#if 0
+ if (u->rreg[ISR1] & IXR1_ERR)
+ break;
+#endif
+ if (deadyet(ib))
+ break;
+ }
+ ib->mode = IDLE;
+ upd7210_wr(u, IMR1, 0);
+ upd7210_wr(u, IMR2, 0);
+ mtx_unlock(&u->mutex);
+ return (len - ib->buflen);
+}
+
+static int
+pio_idata(struct upd7210 *u, u_char *data, int len)
+{
+ int i;
+ struct ibfoo *ib;
+
+ ib = u->ibfoo;
+
+ mtx_lock(&u->mutex);
+ ib->mode = PIO_IDATA;
+ ib->buf = data;
+ ib->buflen = len;
+ upd7210_wr(u, IMR1, IXR1_DI);
+ while (1) {
+ i = msleep(ib, &u->mutex, PZERO | PCATCH,
+ "ib_pioidata", hz/100);
+ if (i == EINTR || i == 0)
+ break;
+ if (deadyet(u->ibfoo))
+ break;
+ }
+ ib->mode = IDLE;
+ upd7210_wr(u, IMR1, 0);
+ upd7210_wr(u, IMR2, 0);
+ mtx_unlock(&u->mutex);
+ if (deadyet(u->ibfoo)) {
+ return (-1);
+ } else {
+ return (len - ib->buflen);
+ }
+}
+
+static int
+dma_idata(struct upd7210 *u, u_char *data, int len)
+{
+ int i1, i2, i, j;
+ struct ibfoo *ib;
+
+ ib = u->ibfoo;
+ ib->mode = DMA_IDATA;
+ upd7210_wr(u, IMR1, IXR1_ENDRX);
+ mtx_lock(&Giant);
+ isa_dmastart(ISADMA_READ, data, len, u->dmachan);
+ mtx_unlock(&Giant);
+ mtx_lock(&u->mutex);
+ upd7210_wr(u, IMR2, IMR2_DMAI);
+ while (1) {
+ i = msleep(ib, &u->mutex, PZERO | PCATCH,
+ "gpib_idata", hz/100);
+ if (i == EINTR)
+ break;
+ if (isa_dmatc(u->dmachan))
+ break;
+ if (i == EWOULDBLOCK) {
+ i1 = upd7210_rd(u, ISR1);
+ i2 = upd7210_rd(u, ISR2);
+ } else {
+ i1 = u->rreg[ISR1];
+ i2 = u->rreg[ISR2];
+ }
+ if (i1 & IXR1_ENDRX)
+ break;
+ if (deadyet(ib))
+ break;
+ }
+ upd7210_wr(u, IMR1, 0);
+ upd7210_wr(u, IMR2, 0);
+ mtx_unlock(&u->mutex);
+ mtx_lock(&Giant);
+ j = isa_dmastatus(u->dmachan);
+ isa_dmadone(ISADMA_READ, data, len, u->dmachan);
+ mtx_unlock(&Giant);
+ if (deadyet(ib)) {
+ return (-1);
+ } else {
+ return (len - j);
+ }
+}
+
+#define ibask NULL
+#define ibbna NULL
+#define ibcac NULL
+#define ibclr NULL
+#define ibcmd NULL
+#define ibcmda NULL
+#define ibconfig NULL
+
+static int
+ibdev(struct handle *h, struct upd7210 *u, struct ibfoo_iocarg *ap)
+{
+ struct ibfoo *ib;
+
+ if (ap->pad < 0 ||
+ ap->pad > 30 ||
+ (ap->sad != 0 && ap->sad < 0x60) ||
+ ap->sad > 126) {
+ ap->__retval = -1;
+ ap->__iberr = EARG;
+ return (0);
+ }
+
+ ib = u->ibfoo;
+ h = malloc(sizeof *h, M_IBFOO, M_ZERO | M_WAITOK);
+ h->handle = alloc_unr(ib->unrhdr);
+ LIST_INSERT_HEAD(&ib->handles, h, list);
+ h->pad = ap->pad;
+ h->sad = ap->sad;
+ h->timeout = timeouts[ap->tmo];
+ h->eot = ap->eot;
+ h->eos = ap->eos;
+ ap->__retval = h->handle;
+ return (0);
+}
+
+#define ibdiag NULL
+
+static int
+ibdma(struct handle *h, struct upd7210 *u, struct ibfoo_iocarg *ap)
+{
+
+ h->dma = ap->v;
+ return (0);
+}
+
+static int
+ibeos(struct handle *h, struct upd7210 *u, struct ibfoo_iocarg *ap)
+{
+ struct ibfoo *ib;
+
+ ib = u->ibfoo;
+ h->eos = ap->eos;
+ if (ib->rdh == h)
+ config_eos(u, h);
+ ap->__retval = 0;
+ return (0);
+}
+
+static int
+ibeot(struct handle *h, struct upd7210 *u, struct ibfoo_iocarg *ap)
+{
+ struct ibfoo *ib;
+
+ ib = u->ibfoo;
+
+ h->eot = ap->eot;
+ return (0);
+}
+
+#define ibevent NULL
+#define ibfind NULL
+#define ibgts NULL
+#define ibist NULL
+#define iblines NULL
+#define ibllo NULL
+#define ibln NULL
+#define ibloc NULL
+#define ibonl NULL
+#define ibpad NULL
+#define ibpct NULL
+#define ibpoke NULL
+#define ibppc NULL
+
+static int
+ibrd(struct handle *h, struct upd7210 *u, struct ibfoo_iocarg *ap)
+{
+ struct ibfoo *ib;
+ u_char buf[10], *bp;
+ int i, j, error, bl, bc;
+ u_char *dp;
+
+ ib = u->ibfoo;
+ bl = ap->cnt;
+ if (bl > PAGE_SIZE)
+ bl = PAGE_SIZE;
+ bp = malloc(bl, M_IBFOO, M_WAITOK);
+
+ if (ib->rdh != h) {
+ i = 0;
+ buf[i++] = UNT;
+ buf[i++] = UNL;
+ buf[i++] = LAD | 0;
+ buf[i++] = TAD | h->pad;
+ if (h->sad)
+ buf[i++] = h->sad;
+ i = pio_cmd(u, buf, i);
+ config_eos(u, h);
+ ib->rdh = h;
+ ib->wrh = NULL;
+ upd7210_goto_standby(u);
+ }
+ ap->__ibcnt = 0;
+ dp = ap->buffer;
+ bc = ap->cnt;
+ error = 0;
+ while (bc > 0) {
+ j = imin(bc, PAGE_SIZE);
+ if (h->dma)
+ i = dma_idata(u, bp, j);
+ else
+ i = pio_idata(u, bp, j);
+ if (i <= 0)
+ break;
+ error = copyout(bp, dp , i);
+ if (error)
+ break;
+ ap->__ibcnt += i;
+ if (i != j)
+ break;
+ bc -= i;
+ dp += i;
+ }
+ free(bp, M_IBFOO);
+ ap->__retval = 0;
+ return (error);
+}
+
+#define ibrda NULL
+#define ibrdf NULL
+#define ibrdkey NULL
+#define ibrpp NULL
+#define ibrsc NULL
+#define ibrsp NULL
+#define ibrsv NULL
+#define ibsad NULL
+#define ibsgnl NULL
+#define ibsic NULL
+#define ibsre NULL
+#define ibsrq NULL
+#define ibstop NULL
+
+static int
+ibtmo(struct handle *h, struct upd7210 *u, struct ibfoo_iocarg *ap)
+{
+
+ h->timeout = timeouts[ap->tmo];
+ return (0);
+}
+
+#define ibtrap NULL
+#define ibtrg NULL
+#define ibwait NULL
+
+static int
+ibwrt(struct handle *h, struct upd7210 *u, struct ibfoo_iocarg *ap)
+{
+ struct ibfoo *ib;
+ u_char buf[10], *bp;
+ int i;
+
+ ib = u->ibfoo;
+ bp = malloc(ap->cnt, M_IBFOO, M_WAITOK);
+ i = copyin(ap->buffer, bp, ap->cnt);
+ if (i) {
+ free(bp, M_IBFOO);
+ return (i);
+ }
+ if (ib->wrh != h) {
+ i = 0;
+ buf[i++] = UNT;
+ buf[i++] = UNL;
+ buf[i++] = LAD | h->pad;
+ if (h->sad)
+ buf[i++] = LAD | TAD | h->sad;
+ buf[i++] = TAD | 0;
+ i = pio_cmd(u, buf, i);
+ ib->rdh = NULL;
+ ib->wrh = h;
+ upd7210_goto_standby(u);
+ config_eos(u, h);
+ }
+ ib->doeoi = h->eot;
+ i = pio_odata(u, bp, ap->cnt);
+ ap->__ibcnt = i;
+ ap->__retval = 0;
+ free(bp, M_IBFOO);
+ return (0);
+}
+
+#define ibwrta NULL
+#define ibwrtf NULL
+#define ibwrtkey NULL
+#define ibxtrc NULL
+
+static struct ibhandler {
+ const char *name;
+ ibhandler_t *func;
+ u_int args;
+} ibhandlers[] = {
+ [__ID_IBASK] = { "ibask", ibask, __F_HANDLE | __F_OPTION | __F_RETVAL },
+ [__ID_IBBNA] = { "ibbna", ibbna, __F_HANDLE | __F_BDNAME },
+ [__ID_IBCAC] = { "ibcac", ibcac, __F_HANDLE | __F_V },
+ [__ID_IBCLR] = { "ibclr", ibclr, __F_HANDLE },
+ [__ID_IBCMDA] = { "ibcmda", ibcmda, __F_HANDLE | __F_BUFFER | __F_CNT },
+ [__ID_IBCMD] = { "ibcmd", ibcmd, __F_HANDLE | __F_BUFFER | __F_CNT },
+ [__ID_IBCONFIG] = { "ibconfig", ibconfig, __F_HANDLE | __F_OPTION | __F_VALUE },
+ [__ID_IBDEV] = { "ibdev", ibdev, __F_BOARDID | __F_PAD | __F_SAD | __F_TMO | __F_EOT | __F_EOS },
+ [__ID_IBDIAG] = { "ibdiag", ibdiag, __F_HANDLE | __F_BUFFER | __F_CNT },
+ [__ID_IBDMA] = { "ibdma", ibdma, __F_HANDLE | __F_V },
+ [__ID_IBEOS] = { "ibeos", ibeos, __F_HANDLE | __F_EOS },
+ [__ID_IBEOT] = { "ibeot", ibeot, __F_HANDLE | __F_EOT },
+ [__ID_IBEVENT] = { "ibevent", ibevent, __F_HANDLE | __F_EVENT },
+ [__ID_IBFIND] = { "ibfind", ibfind, __F_BDNAME },
+ [__ID_IBGTS] = { "ibgts", ibgts, __F_HANDLE | __F_V },
+ [__ID_IBIST] = { "ibist", ibist, __F_HANDLE | __F_V },
+ [__ID_IBLINES] = { "iblines", iblines, __F_HANDLE | __F_LINES },
+ [__ID_IBLLO] = { "ibllo", ibllo, __F_HANDLE },
+ [__ID_IBLN] = { "ibln", ibln, __F_HANDLE | __F_PADVAL | __F_SADVAL | __F_LISTENFLAG },
+ [__ID_IBLOC] = { "ibloc", ibloc, __F_HANDLE },
+ [__ID_IBONL] = { "ibonl", ibonl, __F_HANDLE | __F_V },
+ [__ID_IBPAD] = { "ibpad", ibpad, __F_HANDLE | __F_V },
+ [__ID_IBPCT] = { "ibpct", ibpct, __F_HANDLE },
+ [__ID_IBPOKE] = { "ibpoke", ibpoke, __F_HANDLE | __F_OPTION | __F_VALUE },
+ [__ID_IBPPC] = { "ibppc", ibppc, __F_HANDLE | __F_V },
+ [__ID_IBRDA] = { "ibrda", ibrda, __F_HANDLE | __F_BUFFER | __F_CNT },
+ [__ID_IBRDF] = { "ibrdf", ibrdf, __F_HANDLE | __F_FLNAME },
+ [__ID_IBRDKEY] = { "ibrdkey", ibrdkey, __F_HANDLE | __F_BUFFER | __F_CNT },
+ [__ID_IBRD] = { "ibrd", ibrd, __F_HANDLE | __F_BUFFER | __F_CNT },
+ [__ID_IBRPP] = { "ibrpp", ibrpp, __F_HANDLE | __F_PPR },
+ [__ID_IBRSC] = { "ibrsc", ibrsc, __F_HANDLE | __F_V },
+ [__ID_IBRSP] = { "ibrsp", ibrsp, __F_HANDLE | __F_SPR },
+ [__ID_IBRSV] = { "ibrsv", ibrsv, __F_HANDLE | __F_V },
+ [__ID_IBSAD] = { "ibsad", ibsad, __F_HANDLE | __F_V },
+ [__ID_IBSGNL] = { "ibsgnl", ibsgnl, __F_HANDLE | __F_V },
+ [__ID_IBSIC] = { "ibsic", ibsic, __F_HANDLE },
+ [__ID_IBSRE] = { "ibsre", ibsre, __F_HANDLE | __F_V },
+ [__ID_IBSRQ] = { "ibsrq", ibsrq, __F_FUNC },
+ [__ID_IBSTOP] = { "ibstop", ibstop, __F_HANDLE },
+ [__ID_IBTMO] = { "ibtmo", ibtmo, __F_HANDLE | __F_TMO },
+ [__ID_IBTRAP] = { "ibtrap", ibtrap, __F_MASK | __F_MODE },
+ [__ID_IBTRG] = { "ibtrg", ibtrg, __F_HANDLE },
+ [__ID_IBWAIT] = { "ibwait", ibwait, __F_HANDLE | __F_MASK },
+ [__ID_IBWRTA] = { "ibwrta", ibwrta, __F_HANDLE | __F_BUFFER | __F_CNT },
+ [__ID_IBWRTF] = { "ibwrtf", ibwrtf, __F_HANDLE | __F_FLNAME },
+ [__ID_IBWRTKEY] = { "ibwrtkey", ibwrtkey, __F_HANDLE | __F_BUFFER | __F_CNT },
+ [__ID_IBWRT] = { "ibwrt", ibwrt, __F_HANDLE | __F_BUFFER | __F_CNT },
+ [__ID_IBXTRC] = { "ibxtrc", ibxtrc, __F_HANDLE | __F_BUFFER | __F_CNT },
+};
+
+static u_int max_ibhandler = sizeof ibhandlers / sizeof ibhandlers[0];
+
+static int
+gpib_ib_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
+{
+ struct upd7210 *u;
+ struct ibfoo *ib;
+ int error;
+
+ u = dev->si_drv1;
+
+ mtx_lock(&u->mutex);
+ if (u->busy) {
+ mtx_unlock(&u->mutex);
+ return (EBUSY);
+ }
+ u->busy = 1;
+ mtx_unlock(&u->mutex);
+
+ mtx_lock(&Giant);
+ error = isa_dma_acquire(u->dmachan);
+ if (!error) {
+ error = isa_dma_init(u->dmachan, PAGE_SIZE, M_WAITOK);
+ if (error)
+ isa_dma_release(u->dmachan);
+ }
+ mtx_unlock(&Giant);
+ if (error) {
+ mtx_lock(&u->mutex);
+ u->busy = 0;
+ mtx_unlock(&u->mutex);
+ return (error);
+ }
+
+ ib = malloc(sizeof *ib, M_IBFOO, M_WAITOK | M_ZERO);
+ LIST_INIT(&ib->handles);
+ ib->unrhdr = new_unrhdr(0, INT_MAX);
+ dev->si_drv2 = ib;
+ ib->upd7210 = u;
+ u->ibfoo = ib;
+ u->irq = gpib_ib_irq;
+
+ upd7210_wr(u, AUXMR, AUXMR_CRST);
+ DELAY(10000);
+ DELAY(1000);
+ upd7210_wr(u, IMR1, 0x00);
+ upd7210_wr(u, IMR2, 0x00);
+ upd7210_wr(u, SPMR, 0x00);
+ upd7210_wr(u, ADR, 0x00);
+ upd7210_wr(u, ADR, ADR_ARS | ADR_DL | ADR_DT);
+ upd7210_wr(u, ADMR, ADMR_ADM0 | ADMR_TRM0 | ADMR_TRM1);
+ upd7210_wr(u, EOSR, 0x00);
+ upd7210_wr(u, AUXMR, C_ICR | 8);
+ upd7210_wr(u, AUXMR, C_PPR | PPR_U);
+ upd7210_wr(u, AUXMR, C_AUXA);
+ upd7210_wr(u, AUXMR, C_AUXB + 3);
+ upd7210_wr(u, AUXMR, C_AUXE + 0);
+ upd7210_wr(u, AUXMR, AUXMR_PON);
+ upd7210_wr(u, AUXMR, AUXMR_CIFC);
+ DELAY(100);
+ upd7210_wr(u, AUXMR, AUXMR_SIFC);
+ upd7210_wr(u, AUXMR, AUXMR_SREN);
+ return (0);
+}
+
+static int
+gpib_ib_close(struct cdev *dev, int oflags, int devtype, struct thread *td)
+{
+ struct upd7210 *u;
+ struct ibfoo *ib;
+
+ u = dev->si_drv1;
+ ib = dev->si_drv2;
+ /* XXX: assert pointer consistency */
+
+ u->ibfoo = NULL;
+ /* XXX: free handles */
+ dev->si_drv2 = NULL;
+ free(ib, M_IBFOO);
+
+ mtx_lock(&Giant);
+ isa_dma_release(u->dmachan);
+ mtx_unlock(&Giant);
+ mtx_lock(&u->mutex);
+ u->busy = 0;
+ upd7210_wr(u, IMR1, 0x00);
+ upd7210_wr(u, IMR2, 0x00);
+ upd7210_wr(u, AUXMR, AUXMR_CRST);
+ DELAY(10000);
+ mtx_unlock(&u->mutex);
+ return (0);
+}
+
+static int
+gpib_ib_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
+{
+ struct ibfoo_iocarg *ap;
+ struct ibhandler *ih;
+ struct handle *h;
+ struct upd7210 *u;
+ int error;
+
+ u = dev->si_drv1;
+
+ if (cmd != GPIB_IBFOO)
+ return (ENOIOCTL);
+
+ ap = (void *)data;
+ if (ap->__ident < 0 || ap->__ident >= max_ibhandler)
+ return (EINVAL);
+ ih = &ibhandlers[ap->__ident];
+ if (ap->__field != ih->args)
+ return (EINVAL);
+
+ if (ap->__field & __F_TMO) {
+ if (ap->tmo < 0 || ap->tmo >= max_timeouts) {
+ ap->__retval = -1;
+ ap->__iberr = EARG;
+ return (0);
+ }
+ }
+
+ if (ap->__field & __F_EOS) {
+ if (ap->eos & ~(REOS | XEOS | BIN | 0xff)) {
+ ap->__retval = -1;
+ ap->__iberr = EARG;
+ return (0);
+ }
+ if (ap->eos & (REOS | XEOS)) {
+ if ((ap->eos & (BIN | 0x80)) == 0x80) {
+ ap->__retval = -1;
+ ap->__iberr = EARG;
+ return (0);
+ }
+ } else if (ap->eos != 0) {
+ ap->__retval = -1;
+ ap->__iberr = EARG;
+ return (0);
+ }
+ }
+
+ mtx_lock(&u->mutex);
+ while(u->busy != 1) {
+ error = msleep(u->ibfoo, &u->mutex, PZERO | PCATCH,
+ "gpib_ibioctl", 0);
+ if (error) {
+ mtx_unlock(&u->mutex);
+ return (EINTR);
+ }
+ }
+ u->busy = 2;
+ mtx_unlock(&u->mutex);
+
+#ifdef IBDEBUG
+ if (ih->name != NULL)
+ printf("%s(", ih->name);
+ else
+ printf("ibinvalid(");
+ printf("[0x%x]", ap->__field);
+ if (ap->__field & __F_HANDLE) printf(" handle=%d", ap->handle);
+ if (ap->__field & __F_EOS) printf(" eos=%d", ap->eos);
+ if (ap->__field & __F_EOT) printf(" eot=%d", ap->eot);
+ if (ap->__field & __F_TMO) printf(" tmo=%d", ap->tmo);
+ if (ap->__field & __F_PAD) printf(" pad=%d", ap->pad);
+ if (ap->__field & __F_SAD) printf(" sad=%d", ap->sad);
+ if (ap->__field & __F_BUFFER) printf(" buffer=%p", ap->buffer);
+ if (ap->__field & __F_CNT) printf(" cnt=%ld", ap->cnt);
+ /* XXX more ... */
+ printf(")\n");
+#endif
+
+ if (ap->__field & __F_HANDLE) {
+ if (gethandle(u, ap, &h)) {
+ error = 0; /* XXX iberr */
+ goto bail;
+ }
+ } else
+ h = NULL;
+ ap->__iberr = 0;
+ error = EOPNOTSUPP;
+ if (ih->func != NULL)
+ error = ih->func(h, u, ap);
+ if (error) {
+ ap->__retval = EDVR;
+ ap->__iberr = EDVR;
+ ap->__ibcnt = error;
+ } else if (ap->__iberr) {
+ ap->__retval = -1;
+ }
+#ifdef IBDEBUG
+ printf("%s(...) = %d (error=%d)\n", ih->name, ap->__retval, error);
+#endif
+
+bail:
+ mtx_lock(&u->mutex);
+ u->busy = 1;
+ wakeup(u->ibfoo);
+ mtx_unlock(&u->mutex);
+ return (error);
+}
+
+struct cdevsw gpib_ib_cdevsw = {
+ .d_version = D_VERSION,
+ .d_name = "gpib_ib",
+ .d_open = gpib_ib_open,
+ .d_ioctl = gpib_ib_ioctl,
+ .d_close = gpib_ib_close,
+};
diff --git a/sys/dev/ieee488/pcii.c b/sys/dev/ieee488/pcii.c
index 574f351..d575f69 100644
--- a/sys/dev/ieee488/pcii.c
+++ b/sys/dev/ieee488/pcii.c
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
#include <isa/isavar.h>
+#define UPD7210_HW_DRIVER
#include <dev/ieee488/upd7210.h>
struct pcii_softc {
diff --git a/sys/dev/ieee488/upd7210.c b/sys/dev/ieee488/upd7210.c
index 6fbb44f..4707766 100644
--- a/sys/dev/ieee488/upd7210.c
+++ b/sys/dev/ieee488/upd7210.c
@@ -49,23 +49,24 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <isa/isavar.h>
+#define UPD7210_HW_DRIVER
+#define UPD7210_SW_DRIVER
#include <dev/ieee488/upd7210.h>
-#include <dev/ieee488/ugpib.h>
static MALLOC_DEFINE(M_GPIB, "GPIB", "GPIB");
/* upd7210 generic stuff */
-static void
-print_isr(u_int isr1, u_int isr2)
+void
+upd7210_print_isr(u_int isr1, u_int isr2)
{
printf("isr1=0x%b isr2=0x%b",
isr1, "\20\10CPT\7APT\6DET\5ENDRX\4DEC\3ERR\2DO\1DI",
isr2, "\20\10INT\7SRQI\6LOK\5REM\4CO\3LOKC\2REMC\1ADSC");
}
-static u_int
-read_reg(struct upd7210 *u, enum upd7210_rreg reg)
+u_int
+upd7210_rd(struct upd7210 *u, enum upd7210_rreg reg)
{
u_int r;
@@ -77,8 +78,8 @@ read_reg(struct upd7210 *u, enum upd7210_rreg reg)
return (r);
}
-static void
-write_reg(struct upd7210 *u, enum upd7210_wreg reg, u_int val)
+void
+upd7210_wr(struct upd7210 *u, enum upd7210_wreg reg, u_int val)
{
bus_space_write_1(
u->reg_tag[reg],
@@ -97,90 +98,73 @@ upd7210intr(void *arg)
u = arg;
mtx_lock(&u->mutex);
- isr1 = read_reg(u, ISR1);
- isr2 = read_reg(u, ISR2);
- if (u->busy == 0 || u->irq == NULL || !u->irq(u)) {
+ isr1 = upd7210_rd(u, ISR1);
+ isr2 = upd7210_rd(u, ISR2);
+ if (u->busy == 0 || u->irq == NULL || !u->irq(u, 1)) {
printf("upd7210intr [%02x %02x %02x",
- read_reg(u, DIR), isr1, isr2);
+ upd7210_rd(u, DIR), isr1, isr2);
printf(" %02x %02x %02x %02x %02x] ",
- read_reg(u, SPSR),
- read_reg(u, ADSR),
- read_reg(u, CPTR),
- read_reg(u, ADR0),
- read_reg(u, ADR1));
- print_isr(isr1, isr2);
+ upd7210_rd(u, SPSR),
+ upd7210_rd(u, ADSR),
+ upd7210_rd(u, CPTR),
+ upd7210_rd(u, ADR0),
+ upd7210_rd(u, ADR1));
+ upd7210_print_isr(isr1, isr2);
printf("\n");
- write_reg(u, IMR1, 0);
- write_reg(u, IMR2, 0);
+ upd7210_wr(u, IMR1, 0);
+ upd7210_wr(u, IMR2, 0);
}
mtx_unlock(&u->mutex);
}
-static int
+int
upd7210_take_ctrl_async(struct upd7210 *u)
{
int i;
- write_reg(u, AUXMR, AUXMR_TCA);
+ upd7210_wr(u, AUXMR, AUXMR_TCA);
- if (!(read_reg(u, ADSR) & ADSR_ATN))
+ if (!(upd7210_rd(u, ADSR) & ADSR_ATN))
return (0);
for (i = 0; i < 20; i++) {
DELAY(1);
- if (!(read_reg(u, ADSR) & ADSR_ATN))
+ if (!(upd7210_rd(u, ADSR) & ADSR_ATN))
return (0);
}
return (1);
}
-static int
+int
upd7210_goto_standby(struct upd7210 *u)
{
int i;
- write_reg(u, AUXMR, AUXMR_GTS);
+ upd7210_wr(u, AUXMR, AUXMR_GTS);
- if (read_reg(u, ADSR) & ADSR_ATN)
+ if (upd7210_rd(u, ADSR) & ADSR_ATN)
return (0);
for (i = 0; i < 20; i++) {
DELAY(1);
- if (read_reg(u, ADSR) & ADSR_ATN)
+ if (upd7210_rd(u, ADSR) & ADSR_ATN)
return (0);
}
return (1);
}
-static int
-deadyet(struct upd7210 *u)
-{
- struct timeval tv;
-
- if (!timevalisset(&u->deadline))
- return (0);
-
- getmicrouptime(&tv);
- if (timevalcmp(&u->deadline, &tv, <)) {
-printf("DEADNOW\n");
- return (1);
- }
-
- return (0);
-}
-
/* Unaddressed Listen Only mode */
static int
-gpib_l_irq(struct upd7210 *u)
+gpib_l_irq(struct upd7210 *u, int intr __unused)
{
int i;
if (u->rreg[ISR1] & 1) {
- i = read_reg(u, DIR);
+ i = upd7210_rd(u, DIR);
u->buf[u->buf_wp++] = i;
u->buf_wp &= (u->bufsize - 1);
i = (u->buf_rp + u->bufsize - u->buf_wp) & (u->bufsize - 1);
if (i < 8)
- write_reg(u, IMR1, 0);
+ upd7210_wr(u, IMR1, 0);
wakeup(u->buf);
return (1);
}
@@ -206,15 +190,15 @@ gpib_l_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
u->buf_wp = 0;
u->buf_rp = 0;
- write_reg(u, AUXMR, AUXMR_CRST);
+ upd7210_wr(u, AUXMR, AUXMR_CRST);
DELAY(10000);
- write_reg(u, AUXMR, C_ICR | 8);
+ upd7210_wr(u, AUXMR, C_ICR | 8);
DELAY(1000);
- write_reg(u, ADR, 0x60);
- write_reg(u, ADR, 0xe0);
- write_reg(u, ADMR, 0x70);
- write_reg(u, AUXMR, AUXMR_PON);
- write_reg(u, IMR1, 0x01);
+ upd7210_wr(u, ADR, 0x60);
+ upd7210_wr(u, ADR, 0xe0);
+ upd7210_wr(u, ADMR, 0x70);
+ upd7210_wr(u, AUXMR, AUXMR_PON);
+ upd7210_wr(u, IMR1, 0x01);
return (0);
}
@@ -227,10 +211,10 @@ gpib_l_close(struct cdev *dev, int oflags, int devtype, struct thread *td)
mtx_lock(&u->mutex);
u->busy = 0;
- write_reg(u, AUXMR, AUXMR_CRST);
+ upd7210_wr(u, AUXMR, AUXMR_CRST);
DELAY(10000);
- write_reg(u, IMR1, 0x00);
- write_reg(u, IMR2, 0x00);
+ upd7210_wr(u, IMR1, 0x00);
+ upd7210_wr(u, IMR2, 0x00);
free(u->buf, M_GPIB);
u->buf = NULL;
mtx_unlock(&u->mutex);
@@ -272,7 +256,7 @@ gpib_l_read(struct cdev *dev, struct uio *uio, int ioflag)
u->buf_rp &= (u->bufsize - 1);
}
if (u->wreg[IMR1] == 0)
- write_reg(u, IMR1, 0x01);
+ upd7210_wr(u, IMR1, 0x01);
mtx_unlock(&u->mutex);
return (error);
}
@@ -285,736 +269,6 @@ static struct cdevsw gpib_l_cdevsw = {
.d_read = gpib_l_read,
};
-/* ibfoo API */
-
-#include <dev/ieee488/ibfoo_int.h>
-
-struct handle {
- LIST_ENTRY(handle) list;
- int handle;
- int pad;
- int sad;
- struct timeval timeout;
- int eot;
- int eos;
-};
-
-struct ibfoo {
- struct upd7210 *upd7210;
- LIST_HEAD(,handle) handles;
- struct unrhdr *unrhdr;
-
- u_char *cmdbuf;
- u_int cmdlen;
-
- struct handle *rdh; /* addressed for read */
- struct handle *wrh; /* addressed for write */
-
- u_char *dobuf;
- u_int dolen;
- int doeoi;
-};
-
-static struct timeval timeouts[] = {
- [TNONE] = { 0, 0},
- [T10us] = { 0, 10},
- [T30us] = { 0, 30},
- [T100us] = { 0, 100},
- [T300us] = { 0, 300},
- [T1ms] = { 0, 1000},
- [T3ms] = { 0, 3000},
- [T10ms] = { 0, 10000},
- [T30ms] = { 0, 30000},
- [T100ms] = { 0, 100000},
- [T300ms] = { 0, 300000},
- [T1s] = { 1, 0},
- [T3s] = { 3, 0},
- [T10s] = { 10, 0},
- [T30s] = { 30, 0},
- [T100s] = { 100, 0},
- [T300s] = { 300, 0},
- [T1000s] = { 1000, 0}
-};
-
-static u_int max_timeouts = sizeof timeouts / sizeof timeouts[0];
-
-typedef int ibhandler_t(struct upd7210 *u, struct ibfoo_iocarg *ap);
-
-static int
-gpib_ib_irq(struct upd7210 *u)
-{
- struct ibfoo *ib;
-
- ib = u->ibfoo;
-
- if ((u->rreg[ISR2] & IXR2_CO) && ib->cmdbuf != NULL) {
- if (ib->cmdlen == 0) {
- wakeup(ib);
- ib->cmdbuf = NULL;
- write_reg(u, IMR2, 0);
- return (1);
- }
- write_reg(u, CDOR, *ib->cmdbuf);
- ib->cmdbuf++;
- ib->cmdlen--;
- return (1);
- }
- if ((u->rreg[ISR1] & IXR1_DO) && ib->dobuf != NULL) {
- if (ib->dolen == 0) {
- wakeup(ib);
- ib->dobuf = NULL;
- write_reg(u, IMR1, 0);
- return (1);
- }
- if (ib->dolen == 1 && ib->doeoi)
- write_reg(u, AUXMR, AUXMR_SEOI);
- write_reg(u, CDOR, *ib->dobuf);
- ib->dobuf++;
- ib->dolen--;
- return (1);
- }
- if (u->rreg[ISR1] & IXR1_ENDRX) {
- write_reg(u, IMR1, 0);
- wakeup(ib);
- return (1);
- }
-
- return (0);
-}
-
-static void
-config_eos(struct upd7210 *u, struct handle *h)
-{
- int i;
-
- i = 0;
- if (h->eos & REOS) {
- write_reg(u, EOSR, h->eos & 0xff);
- i |= AUXA_REOS;
- }
- if (h->eos & XEOS) {
- write_reg(u, EOSR, h->eos & 0xff);
- i |= AUXA_XEOS;
- }
- if (h->eos & BIN)
- i |= AUXA_BIN;
- write_reg(u, AUXRA, C_AUXA | i);
-}
-
-/*
- * Look up the handle, and set the deadline if the handle has a timeout.
- */
-static int
-gethandle(struct upd7210 *u, struct ibfoo_iocarg *ap, struct handle **hp)
-{
- struct ibfoo *ib;
- struct handle *h;
-
- KASSERT(ap->__field & __F_HANDLE, ("gethandle without __F_HANDLE"));
- ib = u->ibfoo;
- LIST_FOREACH(h, &ib->handles, list) {
- if (h->handle == ap->handle) {
- *hp = h;
- if (timevalisset(&h->timeout)) {
- getmicrouptime(&u->deadline);
- timevaladd(&u->deadline, &h->timeout);
- } else {
- timevalclear(&u->deadline);
- }
- return (0);
- }
- }
- ap->__iberr = EARG;
- return (1);
-}
-
-static int
-do_cmd(struct upd7210 *u, u_char *cmd, int len)
-{
- int i, i1, i2;
- struct ibfoo *ib;
-
- ib = u->ibfoo;
-
- if (ib->rdh != NULL || ib->wrh != NULL) {
- upd7210_take_ctrl_async(u);
- ib->rdh = NULL;
- ib->wrh = NULL;
- }
- mtx_lock(&u->mutex);
- ib->cmdbuf = cmd;
- ib->cmdlen = len;
-
- if (!(u->rreg[ISR2] & IXR2_CO)) {
- i1 = read_reg(u, ISR1);
- i2 = read_reg(u, ISR2);
-#ifdef GPIB_DEBUG
- print_isr(i1, i2);
- printf("\n");
-#endif
- }
- write_reg(u, IMR2, IXR2_CO);
- if (u->rreg[ISR2] & IXR2_CO) {
- write_reg(u, CDOR, *ib->cmdbuf);
- ib->cmdbuf++;
- ib->cmdlen--;
- }
-
- while (1) {
- i = msleep(ib, &u->mutex, PZERO | PCATCH, "gpib_cmd", hz/10);
- if (i == EINTR)
- break;
- if (u->rreg[ISR1] & IXR1_ERR)
- break;
- if (!ib->cmdlen)
- break;
- if (deadyet(u))
- break;
- }
- write_reg(u, IMR2, 0);
- mtx_unlock(&u->mutex);
- return (0);
-}
-
-static int
-do_odata(struct upd7210 *u, u_char *data, int len, int eos)
-{
- int i1, i2, i;
- struct ibfoo *ib;
-
- ib = u->ibfoo;
-
- if (len == 0)
- return (0);
- mtx_lock(&u->mutex);
- ib->dobuf = data;
- ib->dolen = len;
- ib->doeoi = 0;
-
- if (!(u->rreg[ISR1] & IXR1_DO)) {
- i1 = read_reg(u, ISR1);
- i2 = read_reg(u, ISR2);
-#ifdef GPIB_DEBUG
- print_isr(i1, i2);
- printf("\n");
-#endif
- }
- write_reg(u, IMR1, IXR1_DO);
- if (u->rreg[ISR1] & IXR1_DO) {
- write_reg(u, CDOR, *ib->dobuf);
- ib->dobuf++;
- ib->dolen--;
- }
- while (1) {
- i = msleep(ib, &u->mutex, PZERO | PCATCH, "gpib_out", hz/100);
- if (i == EINTR)
- break;
- if (u->rreg[ISR1] & IXR1_ERR)
- break;
- if (!ib->dolen)
- break;
- if (deadyet(u))
- break;
- }
- write_reg(u, IMR2, 0);
- mtx_unlock(&u->mutex);
- return (len - ib->dolen);
-}
-
-static int
-do_idata(struct upd7210 *u, u_char *data, int len, int eos)
-{
- int i1, i2, i, j;
-
- write_reg(u, IMR1, IXR1_ENDRX);
- mtx_lock(&Giant);
- isa_dmastart(ISADMA_READ, data, len, u->dmachan);
- mtx_unlock(&Giant);
- mtx_lock(&u->mutex);
- write_reg(u, IMR2, IMR2_DMAI);
- while (1) {
- i = msleep(u->ibfoo, &u->mutex, PZERO | PCATCH,
- "gpib_idata", hz/100);
- if (i == EINTR)
- break;
- if (isa_dmatc(u->dmachan))
- break;
- if (i == EWOULDBLOCK) {
- i1 = read_reg(u, ISR1);
- i2 = read_reg(u, ISR2);
- } else {
- i1 = u->rreg[ISR1];
- i2 = u->rreg[ISR2];
- }
- if (i1 & IXR1_ENDRX)
- break;
- if (deadyet(u))
- break;
- }
- write_reg(u, IMR1, 0);
- write_reg(u, IMR2, 0);
- mtx_unlock(&u->mutex);
- mtx_lock(&Giant);
- j = isa_dmastatus(u->dmachan);
- isa_dmadone(ISADMA_READ, data, len, u->dmachan);
- mtx_unlock(&Giant);
- if (deadyet(u)) {
- return (-1);
- } else {
- return (len - j);
- }
-}
-
-#define ibask NULL
-#define ibbna NULL
-#define ibcac NULL
-#define ibclr NULL
-#define ibcmd NULL
-#define ibcmda NULL
-#define ibconfig NULL
-
-static int
-ibdev(struct upd7210 *u, struct ibfoo_iocarg *ap)
-{
- struct handle *h;
- struct ibfoo *ib;
-
- if (ap->pad < 0 ||
- ap->pad > 30 ||
- (ap->sad != 0 && ap->sad < 0x60) ||
- ap->sad > 126) {
- ap->__retval = -1;
- ap->__iberr = EARG;
- return (0);
- }
-
- ib = u->ibfoo;
- h = malloc(sizeof *h, M_GPIB, M_ZERO | M_WAITOK);
- h->handle = alloc_unr(ib->unrhdr);
- LIST_INSERT_HEAD(&ib->handles, h, list);
- h->pad = ap->pad;
- h->sad = ap->sad;
- h->timeout = timeouts[ap->tmo];
- h->eot = ap->eot;
- h->eos = ap->eos;
- ap->__retval = h->handle;
- return (0);
-}
-
-#define ibdiag NULL
-#define ibdma NULL
-
-static int
-ibeos(struct upd7210 *u, struct ibfoo_iocarg *ap)
-{
- struct handle *h;
- struct ibfoo *ib;
-
- if (gethandle(u, ap, &h))
- return (0);
- ib = u->ibfoo;
- h->eos = ap->eos;
- if (ib->rdh == h)
- config_eos(u, h);
- ap->__retval = 0;
- return (0);
-}
-
-#define ibeot NULL
-#define ibevent NULL
-#define ibfind NULL
-#define ibgts NULL
-#define ibist NULL
-#define iblines NULL
-#define ibllo NULL
-#define ibln NULL
-#define ibloc NULL
-#define ibonl NULL
-#define ibpad NULL
-#define ibpct NULL
-#define ibpoke NULL
-#define ibppc NULL
-
-static int
-ibrd(struct upd7210 *u, struct ibfoo_iocarg *ap)
-{
- struct ibfoo *ib;
- struct handle *h;
- u_char buf[10], *bp;
- int i, j, error, bl, bc;
- u_char *dp;
-
- ib = u->ibfoo;
- if (gethandle(u, ap, &h))
- return (0);
- bl = ap->cnt;
- if (bl > PAGE_SIZE)
- bl = PAGE_SIZE;
- bp = malloc(bl, M_GPIB, M_WAITOK);
-
- if (ib->rdh != h) {
- i = 0;
- buf[i++] = UNT;
- buf[i++] = UNL;
- buf[i++] = LAD | 0;
- buf[i++] = TAD | h->pad;
- if (h->sad)
- buf[i++] = h->sad;
- i = do_cmd(u, buf, i);
- config_eos(u, h);
- ib->rdh = h;
- ib->wrh = NULL;
- upd7210_goto_standby(u);
- }
- ap->__ibcnt = 0;
- dp = ap->buffer;
- bc = ap->cnt;
- error = 0;
- while (bc > 0) {
- j = imin(bc, PAGE_SIZE);
- i = do_idata(u, bp, j, 1);
- if (i <= 0)
- break;
- error = copyout(bp, dp , i);
- if (error)
- break;
- ap->__ibcnt += i;
- if (i != j)
- break;
- bc -= i;
- dp += i;
- }
- free(bp, M_GPIB);
- ap->__retval = 0;
- return (error);
-}
-
-#define ibrda NULL
-#define ibrdf NULL
-#define ibrdkey NULL
-#define ibrpp NULL
-#define ibrsc NULL
-#define ibrsp NULL
-#define ibrsv NULL
-#define ibsad NULL
-#define ibsgnl NULL
-#define ibsic NULL
-#define ibsre NULL
-#define ibsrq NULL
-#define ibstop NULL
-
-static int
-ibtmo(struct upd7210 *u, struct ibfoo_iocarg *ap)
-{
- struct handle *h;
-
- if (gethandle(u, ap, &h))
- return (0);
- h->timeout = timeouts[ap->tmo];
- return (0);
-}
-
-#define ibtrap NULL
-#define ibtrg NULL
-#define ibwait NULL
-
-static int
-ibwrt(struct upd7210 *u, struct ibfoo_iocarg *ap)
-{
- struct ibfoo *ib;
- struct handle *h;
- u_char buf[10], *bp;
- int i;
-
- ib = u->ibfoo;
- if (gethandle(u, ap, &h))
- return (0);
- bp = malloc(ap->cnt, M_GPIB, M_WAITOK);
- i = copyin(ap->buffer, bp, ap->cnt);
- if (i) {
- free(bp, M_GPIB);
- return (i);
- }
- if (ib->wrh != h) {
- i = 0;
- buf[i++] = UNT;
- buf[i++] = UNL;
- buf[i++] = LAD | h->pad;
- if (h->sad)
- buf[i++] = LAD | TAD | h->sad;
- buf[i++] = TAD | 0;
- i = do_cmd(u, buf, i);
- ib->rdh = NULL;
- ib->wrh = h;
- upd7210_goto_standby(u);
- config_eos(u, h);
- }
- i = do_odata(u, bp, ap->cnt, 1);
- ap->__ibcnt = i;
- ap->__retval = 0;
- free(bp, M_GPIB);
- return (0);
-}
-
-#define ibwrta NULL
-#define ibwrtf NULL
-#define ibwrtkey NULL
-#define ibxtrc NULL
-
-static struct ibhandler {
- const char *name;
- ibhandler_t *func;
- u_int args;
-} ibhandlers[] = {
- [__ID_IBASK] = { "ibask", ibask, __F_HANDLE | __F_OPTION | __F_RETVAL },
- [__ID_IBBNA] = { "ibbna", ibbna, __F_HANDLE | __F_BDNAME },
- [__ID_IBCAC] = { "ibcac", ibcac, __F_HANDLE | __F_V },
- [__ID_IBCLR] = { "ibclr", ibclr, __F_HANDLE },
- [__ID_IBCMDA] = { "ibcmda", ibcmda, __F_HANDLE | __F_BUFFER | __F_CNT },
- [__ID_IBCMD] = { "ibcmd", ibcmd, __F_HANDLE | __F_BUFFER | __F_CNT },
- [__ID_IBCONFIG] = { "ibconfig", ibconfig, __F_HANDLE | __F_OPTION | __F_VALUE },
- [__ID_IBDEV] = { "ibdev", ibdev, __F_BOARDID | __F_PAD | __F_SAD | __F_TMO | __F_EOT | __F_EOS },
- [__ID_IBDIAG] = { "ibdiag", ibdiag, __F_HANDLE | __F_BUFFER | __F_CNT },
- [__ID_IBDMA] = { "ibdma", ibdma, __F_HANDLE | __F_V },
- [__ID_IBEOS] = { "ibeos", ibeos, __F_HANDLE | __F_EOS },
- [__ID_IBEOT] = { "ibeot", ibeot, __F_HANDLE | __F_V },
- [__ID_IBEVENT] = { "ibevent", ibevent, __F_HANDLE | __F_EVENT },
- [__ID_IBFIND] = { "ibfind", ibfind, __F_BDNAME },
- [__ID_IBGTS] = { "ibgts", ibgts, __F_HANDLE | __F_V },
- [__ID_IBIST] = { "ibist", ibist, __F_HANDLE | __F_V },
- [__ID_IBLINES] = { "iblines", iblines, __F_HANDLE | __F_LINES },
- [__ID_IBLLO] = { "ibllo", ibllo, __F_HANDLE },
- [__ID_IBLN] = { "ibln", ibln, __F_HANDLE | __F_PADVAL | __F_SADVAL | __F_LISTENFLAG },
- [__ID_IBLOC] = { "ibloc", ibloc, __F_HANDLE },
- [__ID_IBONL] = { "ibonl", ibonl, __F_HANDLE | __F_V },
- [__ID_IBPAD] = { "ibpad", ibpad, __F_HANDLE | __F_V },
- [__ID_IBPCT] = { "ibpct", ibpct, __F_HANDLE },
- [__ID_IBPOKE] = { "ibpoke", ibpoke, __F_HANDLE | __F_OPTION | __F_VALUE },
- [__ID_IBPPC] = { "ibppc", ibppc, __F_HANDLE | __F_V },
- [__ID_IBRDA] = { "ibrda", ibrda, __F_HANDLE | __F_BUFFER | __F_CNT },
- [__ID_IBRDF] = { "ibrdf", ibrdf, __F_HANDLE | __F_FLNAME },
- [__ID_IBRDKEY] = { "ibrdkey", ibrdkey, __F_HANDLE | __F_BUFFER | __F_CNT },
- [__ID_IBRD] = { "ibrd", ibrd, __F_HANDLE | __F_BUFFER | __F_CNT },
- [__ID_IBRPP] = { "ibrpp", ibrpp, __F_HANDLE | __F_PPR },
- [__ID_IBRSC] = { "ibrsc", ibrsc, __F_HANDLE | __F_V },
- [__ID_IBRSP] = { "ibrsp", ibrsp, __F_HANDLE | __F_SPR },
- [__ID_IBRSV] = { "ibrsv", ibrsv, __F_HANDLE | __F_V },
- [__ID_IBSAD] = { "ibsad", ibsad, __F_HANDLE | __F_V },
- [__ID_IBSGNL] = { "ibsgnl", ibsgnl, __F_HANDLE | __F_V },
- [__ID_IBSIC] = { "ibsic", ibsic, __F_HANDLE },
- [__ID_IBSRE] = { "ibsre", ibsre, __F_HANDLE | __F_V },
- [__ID_IBSRQ] = { "ibsrq", ibsrq, __F_FUNC },
- [__ID_IBSTOP] = { "ibstop", ibstop, __F_HANDLE },
- [__ID_IBTMO] = { "ibtmo", ibtmo, __F_HANDLE | __F_TMO },
- [__ID_IBTRAP] = { "ibtrap", ibtrap, __F_MASK | __F_MODE },
- [__ID_IBTRG] = { "ibtrg", ibtrg, __F_HANDLE },
- [__ID_IBWAIT] = { "ibwait", ibwait, __F_HANDLE | __F_MASK },
- [__ID_IBWRTA] = { "ibwrta", ibwrta, __F_HANDLE | __F_BUFFER | __F_CNT },
- [__ID_IBWRTF] = { "ibwrtf", ibwrtf, __F_HANDLE | __F_FLNAME },
- [__ID_IBWRTKEY] = { "ibwrtkey", ibwrtkey, __F_HANDLE | __F_BUFFER | __F_CNT },
- [__ID_IBWRT] = { "ibwrt", ibwrt, __F_HANDLE | __F_BUFFER | __F_CNT },
- [__ID_IBXTRC] = { "ibxtrc", ibxtrc, __F_HANDLE | __F_BUFFER | __F_CNT },
-};
-
-static u_int max_ibhandler = sizeof ibhandlers / sizeof ibhandlers[0];
-
-static int
-gpib_ib_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
-{
- struct upd7210 *u;
- struct ibfoo *ib;
- int error;
-
- u = dev->si_drv1;
-
- mtx_lock(&u->mutex);
- if (u->busy) {
- mtx_unlock(&u->mutex);
- return (EBUSY);
- }
- u->busy = 1;
- mtx_unlock(&u->mutex);
-
- mtx_lock(&Giant);
- error = isa_dma_acquire(u->dmachan);
- if (!error) {
- error = isa_dma_init(u->dmachan, PAGE_SIZE, M_WAITOK);
- if (error)
- isa_dma_release(u->dmachan);
- }
- mtx_unlock(&Giant);
- if (error) {
- mtx_lock(&u->mutex);
- u->busy = 0;
- mtx_unlock(&u->mutex);
- return (error);
- }
-
- ib = malloc(sizeof *ib, M_GPIB, M_WAITOK | M_ZERO);
- LIST_INIT(&ib->handles);
- ib->unrhdr = new_unrhdr(0, INT_MAX);
- dev->si_drv2 = ib;
- ib->upd7210 = u;
- u->ibfoo = ib;
- u->irq = gpib_ib_irq;
-
- write_reg(u, AUXMR, AUXMR_CRST);
- DELAY(10000);
- DELAY(1000);
- write_reg(u, IMR1, 0x00);
- write_reg(u, IMR2, 0x00);
- write_reg(u, SPMR, 0x00);
- write_reg(u, ADR, 0x00);
- write_reg(u, ADR, ADR_ARS | ADR_DL | ADR_DT);
- write_reg(u, ADMR, ADMR_ADM0 | ADMR_TRM0 | ADMR_TRM1);
- write_reg(u, EOSR, 0x00);
- write_reg(u, AUXMR, C_ICR | 8);
- write_reg(u, AUXMR, C_PPR | PPR_U);
- write_reg(u, AUXMR, C_AUXA);
- write_reg(u, AUXMR, C_AUXB + 3);
- write_reg(u, AUXMR, C_AUXE + 0);
- write_reg(u, AUXMR, AUXMR_PON);
- write_reg(u, AUXMR, AUXMR_CIFC);
- DELAY(100);
- write_reg(u, AUXMR, AUXMR_SIFC);
- write_reg(u, AUXMR, AUXMR_SREN);
- return (0);
-}
-
-static int
-gpib_ib_close(struct cdev *dev, int oflags, int devtype, struct thread *td)
-{
- struct upd7210 *u;
- struct ibfoo *ib;
-
- u = dev->si_drv1;
- ib = dev->si_drv2;
- /* XXX: assert pointer consistency */
-
- u->ibfoo = NULL;
- /* XXX: free handles */
- dev->si_drv2 = NULL;
- free(ib, M_GPIB);
-
- mtx_lock(&Giant);
- isa_dma_release(u->dmachan);
- mtx_unlock(&Giant);
- mtx_lock(&u->mutex);
- u->busy = 0;
- write_reg(u, IMR1, 0x00);
- write_reg(u, IMR2, 0x00);
- write_reg(u, AUXMR, AUXMR_CRST);
- DELAY(10000);
- mtx_unlock(&u->mutex);
- return (0);
-}
-
-static int
-gpib_ib_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
-{
- struct ibfoo_iocarg *ap;
- struct ibhandler *ih;
- struct upd7210 *u;
- int error;
-
- u = dev->si_drv1;
-
- if (cmd != GPIB_IBFOO)
- return (ENOIOCTL);
-
- ap = (void *)data;
- if (ap->__ident < 0 || ap->__ident >= max_ibhandler)
- return (EINVAL);
- ih = &ibhandlers[ap->__ident];
- if (ap->__field != ih->args)
- return (EINVAL);
-
- if (ap->__field & __F_TMO) {
- if (ap->tmo < 0 || ap->tmo >= max_timeouts) {
- ap->__retval = -1;
- ap->__iberr = EARG;
- return (0);
- }
- }
-
- if (ap->__field & __F_EOS) {
- if (ap->eos & ~(REOS | XEOS | BIN | 0xff)) {
- ap->__retval = -1;
- ap->__iberr = EARG;
- return (0);
- }
- if (ap->eos & (REOS | XEOS)) {
- if ((ap->eos & (BIN | 0x80)) == 0x80) {
- ap->__retval = -1;
- ap->__iberr = EARG;
- return (0);
- }
- } else if (ap->eos != 0) {
- ap->__retval = -1;
- ap->__iberr = EARG;
- return (0);
- }
- }
-
- mtx_lock(&u->mutex);
- while(u->busy != 1) {
- error = msleep(u->ibfoo, &u->mutex, PZERO | PCATCH,
- "gpib_ibioctl", 0);
- if (error) {
- mtx_unlock(&u->mutex);
- return (EINTR);
- }
- }
- u->busy = 2;
- mtx_unlock(&u->mutex);
-
-#ifdef GPIB_DEBUG
- if (ih->name != NULL)
- printf("%s(", ih->name);
- else
- printf("ibinvalid(");
- printf("[0x%x]", ap->__field);
- if (ap->__field & __F_HANDLE) printf(" handle=%d", ap->handle);
- if (ap->__field & __F_EOS) printf(" eos=%d", ap->eos);
- if (ap->__field & __F_EOT) printf(" eot=%d", ap->eot);
- if (ap->__field & __F_TMO) printf(" tmo=%d", ap->tmo);
- if (ap->__field & __F_PAD) printf(" pad=%d", ap->pad);
- if (ap->__field & __F_SAD) printf(" sad=%d", ap->sad);
- if (ap->__field & __F_BUFFER) printf(" buffer=%p", ap->buffer);
- if (ap->__field & __F_CNT) printf(" cnt=%ld", ap->cnt);
- /* XXX more ... */
- printf(")\n");
-#endif
-
- ap->__iberr = 0;
- error = EOPNOTSUPP;
- if (ih->func != NULL)
- error = ih->func(u, ap);
- if (error) {
- ap->__retval = EDVR;
- ap->__iberr = EDVR;
- ap->__ibcnt = error;
- } else if (ap->__iberr) {
- ap->__retval = -1;
- }
-#ifdef GPIB_DEBUG
- printf("%s(...) = %d (error=%d)\n", ih->name, ap->__retval, error);
-#endif
- mtx_lock(&u->mutex);
- u->busy = 1;
- wakeup(u->ibfoo);
- mtx_unlock(&u->mutex);
- return (error);
-}
-
-static struct cdevsw gpib_ib_cdevsw = {
- .d_version = D_VERSION,
- .d_name = "gpib_ib",
- .d_open = gpib_ib_open,
- .d_ioctl = gpib_ib_ioctl,
- .d_close = gpib_ib_close,
-};
-
/* Housekeeping */
void
diff --git a/sys/dev/ieee488/upd7210.h b/sys/dev/ieee488/upd7210.h
index 623fb11..f592bbd 100644
--- a/sys/dev/ieee488/upd7210.h
+++ b/sys/dev/ieee488/upd7210.h
@@ -35,16 +35,16 @@
* in an old manual for a VME board which used the chip.
*/
-/* upd7210 interface definitions */
+#ifndef _DEV_IEEE488_UPD7210_H_
+#define _DEV_IEEE488_UPD7210_H_
+#ifdef _KERNEL
struct upd7210;
-
struct ibfoo;
-void upd7210intr(void *);
-void upd7210attach(struct upd7210 *);
+/* upd7210 interface definitions for HW drivers */
-typedef int upd7210_irq_t(struct upd7210 *);
+typedef int upd7210_irq_t(struct upd7210 *, int);
struct upd7210 {
bus_space_handle_t reg_handle[8];
@@ -53,7 +53,6 @@ struct upd7210 {
u_int dmachan;
/* private stuff */
- struct timeval deadline;
struct mtx mutex;
uint8_t rreg[8];
uint8_t wreg[8 + 8];
@@ -70,6 +69,13 @@ struct upd7210 {
struct ibfoo *ibfoo;
};
+#ifdef UPD7210_HW_DRIVER
+void upd7210intr(void *);
+void upd7210attach(struct upd7210 *);
+#endif
+
+#ifdef UPD7210_SW_DRIVER
+
/* upd7210 hardware definitions. */
/* Write registers */
@@ -211,3 +217,18 @@ enum upd7210_rreg {
#define ADR1_DT1 (1 << 6) /* Disable Talker 1 */
#define ADR1_EOI (1 << 7) /* End or Identify */
+/* Stuff from software drivers */
+extern struct cdevsw gpib_l_cdevsw;
+extern struct cdevsw gpib_ib_cdevsw;
+
+/* Stuff from upd7210.c */
+void upd7210_print_isr(u_int isr1, u_int isr2);
+u_int upd7210_rd(struct upd7210 *u, enum upd7210_rreg reg);
+void upd7210_wr(struct upd7210 *u, enum upd7210_wreg reg, u_int val);
+int upd7210_take_ctrl_async(struct upd7210 *u);
+int upd7210_goto_standby(struct upd7210 *u);
+
+#endif /* UPD7210_SW_DRIVER */
+
+#endif /* _KERNEL */
+#endif /* _DEV_IEEE488_UPD7210_H_ */
OpenPOWER on IntegriCloud