diff options
-rw-r--r-- | sys/dev/ieee488/ibfoo.c | 856 | ||||
-rw-r--r-- | sys/dev/ieee488/pcii.c | 1 | ||||
-rw-r--r-- | sys/dev/ieee488/upd7210.c | 830 | ||||
-rw-r--r-- | sys/dev/ieee488/upd7210.h | 33 |
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 000000000000..a2bd1c578fed --- /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 574f3513efb1..d575f6927d59 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 6fbb44f00c86..4707766e68a1 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 623fb11b9c73..f592bbdd870c 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_ */ |