diff options
Diffstat (limited to 'sys/dev/ieee488/ibfoo.c')
-rw-r--r-- | sys/dev/ieee488/ibfoo.c | 1127 |
1 files changed, 0 insertions, 1127 deletions
diff --git a/sys/dev/ieee488/ibfoo.c b/sys/dev/ieee488/ibfoo.c deleted file mode 100644 index 2fe72dc..0000000 --- a/sys/dev/ieee488/ibfoo.c +++ /dev/null @@ -1,1127 +0,0 @@ -/*- - * Copyright (c) 2005 Poul-Henning Kamp <phk@FreeBSD.org> - * Copyright (c) 2010 Joerg Wunsch <joerg@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/rman.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> -#include <dev/ieee488/tnt4882.h> - -static MALLOC_DEFINE(M_IBFOO, "IBFOO", "IBFOO"); - - -/* ibfoo API */ - -#include <dev/ieee488/ibfoo_int.h> - -/* XXX: This is really a bitmap */ -enum h_kind { - H_DEV = 1, - H_BOARD = 2, - H_EITHER = 3 -}; - -struct handle { - LIST_ENTRY(handle) list; - int handle; - enum h_kind kind; - int pad; - int sad; - struct timeval timeout; - int eot; - int eos; - int dma; -}; - -struct ibfoo { - struct upd7210 *u; - LIST_HEAD(,handle) handles; - struct unrhdr *unrhdr; - struct callout callout; - struct handle *h; - struct ibarg *ap; - - enum { - IDLE, - BUSY, - PIO_IDATA, - PIO_ODATA, - PIO_CMD, - DMA_IDATA, - FIFO_IDATA, - FIFO_ODATA, - FIFO_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; -}; - -typedef int ibhandler_t(struct ibfoo *ib); - -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 ibdebug; - -static int -ib_set_error(struct ibarg *ap, int error) -{ - - if (ap->__iberr == 0) - ap->__iberr = error; - ap->__ibsta |= ERR; - ap->__retval = ap->__ibsta; - return (0); -} - -static int -ib_had_timeout(struct ibarg *ap) -{ - - ib_set_error(ap, EABO); - ap->__ibsta |= TIMO; - ap->__retval = ap->__ibsta; - return (0); -} - -static int -ib_set_errno(struct ibarg *ap, int errno) -{ - - if (ap->__iberr == 0) { - ap->__iberr = EDVR; - ap->__ibcnt = errno; - } - ap->__ibsta |= ERR; - ap->__retval = ap->__ibsta; - return (0); -} - -static int -gpib_ib_irq(struct upd7210 *u, int isr_3) -{ - struct ibfoo *ib; - - ib = u->ibfoo; - - mtx_assert(&u->mutex, MA_OWNED); - 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; - case FIFO_IDATA: - if (!(isr_3 & 0x15)) - return (0); - while (ib->buflen != 0 && (isr_3 & 0x04 /* NEF */) != 0) { - *ib->buf = bus_read_1(u->reg_res[0], fifob); - ib->buf++; - ib->buflen--; - isr_3 = bus_read_1(u->reg_res[0], isr3); - } - if ((isr_3 & 0x01) != 0 /* xfr done */ || - (u->rreg[ISR1] & IXR1_ENDRX) != 0 || - ib->buflen == 0) - break; - if (isr_3 & 0x10) - /* xfr stopped */ - bus_write_1(u->reg_res[0], cmdr, 0x04); /* GO */ - upd7210_wr(u, AUXMR, AUXMR_RFD); - return (1); - case FIFO_CMD: - case FIFO_ODATA: - if (!(isr_3 & 0x19)) - return (0); - if (ib->buflen == 0) - /* xfr DONE */ - break; - while (ib->buflen != 0 && (isr_3 & 0x08 /* NFF */) != 0) { - bus_write_1(u->reg_res[0], fifob, *ib->buf); - ib->buf++; - ib->buflen--; - isr_3 = bus_read_1(u->reg_res[0], isr3); - } - if (isr_3 & 0x10) - /* xfr stopped */ - bus_write_1(u->reg_res[0], cmdr, 0x04); /* GO */ - if (ib->buflen == 0) - /* no more NFF interrupts wanted */ - bus_write_1(u->reg_res[0], imr3, 0x11); /* STOP IE, DONE IE */ - return (1); - default: - return (0); - } - upd7210_wr(u, IMR1, 0); - upd7210_wr(u, IMR2, 0); - if (u->use_fifo) { - bus_write_1(u->reg_res[0], imr3, 0x00); - bus_write_1(u->reg_res[0], cmdr, 0x22); /* soft RESET */ - } - ib->mode = BUSY; - wakeup(&ib->buflen); - return (1); -} - -static void -gpib_ib_timeout(void *arg) -{ - struct upd7210 *u; - struct ibfoo *ib; - struct timeval tv; - u_int isr_3; - - u = arg; - ib = u->ibfoo; - mtx_lock(&u->mutex); - if (ib->mode == DMA_IDATA && isa_dmatc(u->dmachan)) { - KASSERT(u->dmachan >= 0, ("Bogus dmachan = %d", u->dmachan)); - upd7210_wr(u, IMR1, 0); - upd7210_wr(u, IMR2, 0); - ib->mode = BUSY; - wakeup(&ib->buflen); - } - if (ib->mode > BUSY) { - upd7210_rd(u, ISR1); - upd7210_rd(u, ISR2); - if (u->use_fifo) - isr_3 = bus_read_1(u->reg_res[0], isr3); - else - isr_3 = 0; - gpib_ib_irq(u, isr_3); - } - if (ib->mode != IDLE && timevalisset(&ib->deadline)) { - getmicrouptime(&tv); - if (timevalcmp(&ib->deadline, &tv, <)) { - ib_had_timeout(ib->ap); - upd7210_wr(u, IMR1, 0); - upd7210_wr(u, IMR2, 0); - if (u->use_fifo) { - bus_write_1(u->reg_res[0], imr3, 0x00); - bus_write_1(u->reg_res[0], cmdr, 0x22); /* soft RESET */ - } - ib->mode = BUSY; - wakeup(&ib->buflen); - } - } - if (ib->mode != IDLE) - callout_reset(&ib->callout, hz / 5, gpib_ib_timeout, arg); - mtx_unlock(&u->mutex); -} - -static void -gpib_ib_wait_xfer(struct upd7210 *u, struct ibfoo *ib) -{ - int i; - - mtx_assert(&u->mutex, MA_OWNED); - while (ib->mode > BUSY) { - i = msleep(&ib->buflen, &u->mutex, - PZERO | PCATCH, "ibwxfr", 0); - if (i == EINTR) { - ib_set_errno(ib->ap, i); - break; - } - if (u->rreg[ISR1] & IXR1_ERR) { - ib_set_error(ib->ap, EABO); /* XXX ? */ - break; - } - } - if ((u->rreg[ISR1] & IXR1_ENDRX) != 0) { - ib->ap->__retval |= END; - ib->ap->__ibsta |= END; - } - if ((u->rreg[ISR2] & IXR2_SRQI) != 0) { - ib->ap->__retval |= SRQI; - ib->ap->__ibsta |= SRQI; - } - ib->mode = BUSY; - ib->buf = NULL; - upd7210_wr(u, IMR1, 0); - upd7210_wr(u, IMR2, 0); - if (u->use_fifo) - bus_write_1(u->reg_res[0], imr3, 0x00); -} - -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 ibarg *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; - return (0); - } - } - ib_set_error(ap, EARG); - return (1); -} - -static int -pio_cmd(struct upd7210 *u, u_char *cmd, int len) -{ - 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->buf = cmd; - ib->buflen = len; - if (u->use_fifo) { - /* TNT5004 or TNT4882 in FIFO mode */ - ib->mode = FIFO_CMD; - upd7210_wr(u, AUXMR, 0x51); /* holdoff immediately */ - bus_write_1(u->reg_res[0], cmdr, 0x10); /* reset FIFO */ - bus_write_1(u->reg_res[0], cfg, 0x80); /* CMD, xfer OUT, 8-bit FIFO */ - bus_write_1(u->reg_res[0], imr3, 0x19); /* STOP IE, NFF IE, DONE IE */ - bus_write_1(u->reg_res[0], cnt0, -len); - bus_write_1(u->reg_res[0], cnt1, (-len) >> 8); - bus_write_1(u->reg_res[0], cnt2, (-len) >> 16); - bus_write_1(u->reg_res[0], cnt3, (-len) >> 24); - bus_write_1(u->reg_res[0], cmdr, 0x04); /* GO */ - } else { - ib->mode = PIO_CMD; - upd7210_wr(u, IMR2, IXR2_CO); - gpib_ib_irq(u, 0); - } - - gpib_ib_wait_xfer(u, ib); - - if (u->use_fifo) - bus_write_1(u->reg_res[0], cmdr, 0x08); /* STOP */ - - mtx_unlock(&u->mutex); - return (len - ib->buflen); -} - -static int -pio_odata(struct upd7210 *u, u_char *data, int len) -{ - struct ibfoo *ib; - - ib = u->ibfoo; - - if (len == 0) - return (0); - mtx_lock(&u->mutex); - ib->buf = data; - ib->buflen = len; - if (u->use_fifo) { - /* TNT5004 or TNT4882 in FIFO mode */ - ib->mode = FIFO_ODATA; - bus_write_1(u->reg_res[0], cmdr, 0x10); /* reset FIFO */ - if (ib->doeoi) - bus_write_1(u->reg_res[0], cfg, 0x08); /* CCEN */ - else - bus_write_1(u->reg_res[0], cfg, 0x00); /* xfer OUT, 8-bit FIFO */ - bus_write_1(u->reg_res[0], imr3, 0x19); /* STOP IE, NFF IE, DONE IE */ - bus_write_1(u->reg_res[0], cnt0, -len); - bus_write_1(u->reg_res[0], cnt1, (-len) >> 8); - bus_write_1(u->reg_res[0], cnt2, (-len) >> 16); - bus_write_1(u->reg_res[0], cnt3, (-len) >> 24); - bus_write_1(u->reg_res[0], cmdr, 0x04); /* GO */ - } else { - ib->mode = PIO_ODATA; - upd7210_wr(u, IMR1, IXR1_DO); - } - - gpib_ib_wait_xfer(u, ib); - - if (u->use_fifo) - bus_write_1(u->reg_res[0], cmdr, 0x08); /* STOP */ - - mtx_unlock(&u->mutex); - return (len - ib->buflen); -} - -static int -pio_idata(struct upd7210 *u, u_char *data, int len) -{ - struct ibfoo *ib; - - ib = u->ibfoo; - - mtx_lock(&u->mutex); - ib->buf = data; - ib->buflen = len; - if (u->use_fifo) { - /* TNT5004 or TNT4882 in FIFO mode */ - ib->mode = FIFO_IDATA; - bus_write_1(u->reg_res[0], cmdr, 0x10); /* reset FIFO */ - bus_write_1(u->reg_res[0], cfg, 0x20); /* xfer IN, 8-bit FIFO */ - bus_write_1(u->reg_res[0], cnt0, -len); - bus_write_1(u->reg_res[0], cnt1, (-len) >> 8); - bus_write_1(u->reg_res[0], cnt2, (-len) >> 16); - bus_write_1(u->reg_res[0], cnt3, (-len) >> 24); - bus_write_1(u->reg_res[0], cmdr, 0x04); /* GO */ - upd7210_wr(u, AUXMR, AUXMR_RFD); - bus_write_1(u->reg_res[0], imr3, 0x15); /* STOP IE, NEF IE, DONE IE */ - } else { - ib->mode = PIO_IDATA; - upd7210_wr(u, IMR1, IXR1_DI); - } - - gpib_ib_wait_xfer(u, ib); - - if (u->use_fifo) - bus_write_1(u->reg_res[0], cmdr, 0x08); /* STOP */ - - mtx_unlock(&u->mutex); - return (len - ib->buflen); -} - -static int -dma_idata(struct upd7210 *u, u_char *data, int len) -{ - int j; - struct ibfoo *ib; - - KASSERT(u->dmachan >= 0, ("Bogus dmachan %d", u->dmachan)); - ib = u->ibfoo; - ib->mode = DMA_IDATA; - isa_dmastart(ISADMA_READ, data, len, u->dmachan); - mtx_lock(&u->mutex); - upd7210_wr(u, IMR1, IXR1_ENDRX); - upd7210_wr(u, IMR2, IMR2_DMAI); - gpib_ib_wait_xfer(u, ib); - mtx_unlock(&u->mutex); - j = isa_dmastatus(u->dmachan); - isa_dmadone(ISADMA_READ, data, len, u->dmachan); - return (len - j); -} - -static int -ib_send_msg(struct ibfoo *ib, int msg) -{ - u_char buf[10]; - int i, j; - - i = 0; - buf[i++] = UNT; - buf[i++] = UNL; - buf[i++] = LAD | ib->h->pad; - if (ib->h->sad) - buf[i++] = LAD | TAD | ib->h->sad; - buf[i++] = TAD | 0; - buf[i++] = msg; - j = pio_cmd(ib->u, buf, i); - if (i != j) - ib_set_error(ib->ap, EABO); /* XXX ? */ - return (0); -} - -static int -ibask(struct ibfoo *ib) -{ /* XXX */ - - ibdebug = ib->ap->option; - return (0); -} - -#define ibbna NULL -#define ibcac NULL - -static int -ibclr(struct ibfoo *ib) -{ - - return (ib_send_msg(ib, SDC)); -} - -#define ibcmd NULL -#define ibcmda NULL -#define ibconfig NULL - -static int -ibdev(struct ibfoo *ib) -{ /* TBD */ - struct handle *h; - - h = malloc(sizeof *h, M_IBFOO, M_ZERO | M_WAITOK); - h->handle = alloc_unr(ib->unrhdr); - h->kind = H_DEV; - h->pad = ib->ap->pad; - h->sad = ib->ap->sad; - h->timeout = timeouts[ib->ap->tmo]; - h->eot = ib->ap->eot; - h->eos = ib->ap->eos; - mtx_lock(&ib->u->mutex); - LIST_INSERT_HEAD(&ib->handles, h, list); - mtx_unlock(&ib->u->mutex); - ib->ap->__retval = h->handle; - return (0); -} - -#define ibdiag NULL - -static int -ibdma(struct ibfoo *ib) -{ - - if (ib->u->dmachan < 0 && ib->ap->v) - return (ib_set_error(ib->ap, EARG)); - ib->h->dma = ib->ap->v; - return (0); -} - -static int -ibeos(struct ibfoo *ib) -{ - - ib->ap->__iberr = ib->h->eos; - ib->h->eos = ib->ap->eos; - if (ib->rdh == ib->h) - config_eos(ib->u, ib->h); - return (0); -} - -static int -ibeot(struct ibfoo *ib) -{ - - ib->h->eot = ib->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 - -static int -ibloc(struct ibfoo *ib) -{ /* XXX */ - - if (ib->h->kind == H_BOARD) - return (EOPNOTSUPP); /* XXX */ - return (ib_send_msg(ib, GTL)); -} - -static int -ibonl(struct ibfoo *ib) -{ /* XXX */ - - if (ib->ap->v) - return (EOPNOTSUPP); /* XXX */ - mtx_lock(&ib->u->mutex); - LIST_REMOVE(ib->h, list); - mtx_unlock(&ib->u->mutex); - free(ib->h, M_IBFOO); - ib->h = NULL; - return (0); -} - -static int -ibpad(struct ibfoo *ib) -{ - - ib->h->pad = ib->ap->pad; - return (0); -} - -#define ibpct NULL -#define ibpoke NULL -#define ibppc NULL - -static int -ibrd(struct ibfoo *ib) -{ /* TBD */ - u_char buf[10], *bp; - int i, j, error, bl, bc; - u_char *dp; - - if (ib->h->kind == H_BOARD) - return (EOPNOTSUPP); /* XXX */ - bl = ib->ap->cnt; - if (bl > PAGE_SIZE) - bl = PAGE_SIZE; - bp = malloc(bl, M_IBFOO, M_WAITOK); - - if (ib->rdh != ib->h) { - i = 0; - buf[i++] = UNT; - buf[i++] = UNL; - buf[i++] = LAD | 0; - buf[i++] = TAD | ib->h->pad; - if (ib->h->sad) - buf[i++] = ib->h->sad; - i = pio_cmd(ib->u, buf, i); - config_eos(ib->u, ib->h); - ib->rdh = ib->h; - ib->wrh = NULL; - } - upd7210_goto_standby(ib->u); - dp = ib->ap->buffer; - bc = ib->ap->cnt; - error = 0; - while (bc > 0 && ib->ap->__iberr == 0) { - j = imin(bc, PAGE_SIZE); - if (ib->h->dma) - i = dma_idata(ib->u, bp, j); - else - i = pio_idata(ib->u, bp, j); - error = copyout(bp, dp , i); - if (error) - break; - ib->ap->__ibcnt += i; - if (i != j) - break; - bc -= i; - dp += i; - } - upd7210_take_ctrl_async(ib->u); - free(bp, M_IBFOO); - return (error); -} - -#define ibrda NULL -#define ibrdf NULL -#define ibrdkey NULL -#define ibrpp NULL -#define ibrsc NULL -#define ibrsp NULL -#define ibrsv NULL - -static int -ibsad(struct ibfoo *ib) -{ - - ib->h->sad = ib->ap->sad; - return (0); -} - -#define ibsgnl NULL - -static int -ibsic(struct ibfoo *ib) -{ /* TBD */ - - upd7210_wr(ib->u, AUXMR, AUXMR_SIFC); - DELAY(100); - upd7210_wr(ib->u, AUXMR, AUXMR_CIFC); - return (0); -} - -#define ibsre NULL -#define ibsrq NULL -#define ibstop NULL - -static int -ibtmo(struct ibfoo *ib) -{ - - ib->h->timeout = timeouts[ib->ap->tmo]; - return (0); -} - -#define ibtrap NULL - -static int -ibtrg(struct ibfoo *ib) -{ - - return (ib_send_msg(ib, GET)); -} - -#define ibwait NULL - -static int -ibwrt(struct ibfoo *ib) -{ /* XXX */ - u_char buf[10], *bp; - int i; - - if (ib->h->kind == H_BOARD) - return (EOPNOTSUPP); - bp = malloc(ib->ap->cnt, M_IBFOO, M_WAITOK); - /* XXX: bigger than PAGE_SIZE handling */ - i = copyin(ib->ap->buffer, bp, ib->ap->cnt); - if (i) { - free(bp, M_IBFOO); - return (i); - } - if (ib->wrh != ib->h) { - i = 0; - buf[i++] = UNT; - buf[i++] = UNL; - buf[i++] = LAD | ib->h->pad; - if (ib->h->sad) - buf[i++] = LAD | TAD | ib->h->sad; - buf[i++] = TAD | 0; - i = pio_cmd(ib->u, buf, i); - ib->rdh = NULL; - ib->wrh = ib->h; - config_eos(ib->u, ib->h); - } - upd7210_goto_standby(ib->u); - ib->doeoi = ib->h->eot; - i = pio_odata(ib->u, bp, ib->ap->cnt); - upd7210_take_ctrl_async(ib->u); - ib->ap->__ibcnt = i; - free(bp, M_IBFOO); - return (0); -} - -#define ibwrta NULL -#define ibwrtf NULL -#define ibwrtkey NULL -#define ibxtrc NULL - -static struct ibhandler { - const char *name; - enum h_kind kind; - ibhandler_t *func; - u_int args; -} ibhandlers[] = { - [__ID_IBASK] = { "ibask", H_EITHER, ibask, __F_HANDLE | __F_OPTION | __F_RETVAL }, - [__ID_IBBNA] = { "ibbna", H_DEV, ibbna, __F_HANDLE | __F_BDNAME }, - [__ID_IBCAC] = { "ibcac", H_BOARD, ibcac, __F_HANDLE | __F_V }, - [__ID_IBCLR] = { "ibclr", H_DEV, ibclr, __F_HANDLE }, - [__ID_IBCMD] = { "ibcmd", H_BOARD, ibcmd, __F_HANDLE | __F_BUFFER | __F_CNT }, - [__ID_IBCMDA] = { "ibcmda", H_BOARD, ibcmda, __F_HANDLE | __F_BUFFER | __F_CNT }, - [__ID_IBCONFIG] = { "ibconfig", H_EITHER, ibconfig, __F_HANDLE | __F_OPTION | __F_VALUE }, - [__ID_IBDEV] = { "ibdev", 0, ibdev, __F_BOARDID | __F_PAD | __F_SAD | __F_TMO | __F_EOT | __F_EOS }, - [__ID_IBDIAG] = { "ibdiag", H_EITHER, ibdiag, __F_HANDLE | __F_BUFFER | __F_CNT }, - [__ID_IBDMA] = { "ibdma", H_EITHER, ibdma, __F_HANDLE | __F_V }, - [__ID_IBEOS] = { "ibeos", H_EITHER, ibeos, __F_HANDLE | __F_EOS }, - [__ID_IBEOT] = { "ibeot", H_EITHER, ibeot, __F_HANDLE | __F_EOT }, - [__ID_IBEVENT] = { "ibevent", H_BOARD, ibevent, __F_HANDLE | __F_EVENT }, - [__ID_IBFIND] = { "ibfind", 0, ibfind, __F_BDNAME }, - [__ID_IBGTS] = { "ibgts", H_BOARD, ibgts, __F_HANDLE | __F_V }, - [__ID_IBIST] = { "ibist", H_BOARD, ibist, __F_HANDLE | __F_V }, - [__ID_IBLINES] = { "iblines", H_BOARD, iblines, __F_HANDLE | __F_LINES }, - [__ID_IBLLO] = { "ibllo", H_EITHER, ibllo, __F_HANDLE }, - [__ID_IBLN] = { "ibln", H_BOARD, ibln, __F_HANDLE | __F_PADVAL | __F_SADVAL | __F_LISTENFLAG }, - [__ID_IBLOC] = { "ibloc", H_EITHER, ibloc, __F_HANDLE }, - [__ID_IBONL] = { "ibonl", H_EITHER, ibonl, __F_HANDLE | __F_V }, - [__ID_IBPAD] = { "ibpad", H_EITHER, ibpad, __F_HANDLE | __F_PAD }, - [__ID_IBPCT] = { "ibpct", H_DEV, ibpct, __F_HANDLE }, - [__ID_IBPOKE] = { "ibpoke", H_EITHER, ibpoke, __F_HANDLE | __F_OPTION | __F_VALUE }, - [__ID_IBPPC] = { "ibppc", H_EITHER, ibppc, __F_HANDLE | __F_V }, - [__ID_IBRD] = { "ibrd", H_EITHER, ibrd, __F_HANDLE | __F_BUFFER | __F_CNT }, - [__ID_IBRDA] = { "ibrda", H_EITHER, ibrda, __F_HANDLE | __F_BUFFER | __F_CNT }, - [__ID_IBRDF] = { "ibrdf", H_EITHER, ibrdf, __F_HANDLE | __F_FLNAME }, - [__ID_IBRDKEY] = { "ibrdkey", H_EITHER, ibrdkey, __F_HANDLE | __F_BUFFER | __F_CNT }, - [__ID_IBRPP] = { "ibrpp", H_EITHER, ibrpp, __F_HANDLE | __F_PPR }, - [__ID_IBRSC] = { "ibrsc", H_BOARD, ibrsc, __F_HANDLE | __F_V }, - [__ID_IBRSP] = { "ibrsp", H_DEV, ibrsp, __F_HANDLE | __F_SPR }, - [__ID_IBRSV] = { "ibrsv", H_EITHER, ibrsv, __F_HANDLE | __F_V }, - [__ID_IBSAD] = { "ibsad", H_EITHER, ibsad, __F_HANDLE | __F_SAD }, - [__ID_IBSGNL] = { "ibsgnl", H_EITHER, ibsgnl, __F_HANDLE | __F_V }, - [__ID_IBSIC] = { "ibsic", H_BOARD, ibsic, __F_HANDLE }, - [__ID_IBSRE] = { "ibsre", H_BOARD, ibsre, __F_HANDLE | __F_V }, - [__ID_IBSRQ] = { "ibsrq", H_EITHER, ibsrq, __F_FUNC }, - [__ID_IBSTOP] = { "ibstop", H_EITHER, ibstop, __F_HANDLE }, - [__ID_IBTMO] = { "ibtmo", H_EITHER, ibtmo, __F_HANDLE | __F_TMO }, - [__ID_IBTRAP] = { "ibtrap", H_EITHER, ibtrap, __F_MASK | __F_MODE }, - [__ID_IBTRG] = { "ibtrg", H_DEV, ibtrg, __F_HANDLE }, - [__ID_IBWAIT] = { "ibwait", H_EITHER, ibwait, __F_HANDLE | __F_MASK }, - [__ID_IBWRT] = { "ibwrt", H_EITHER, ibwrt, __F_HANDLE | __F_BUFFER | __F_CNT }, - [__ID_IBWRTA] = { "ibwrta", H_EITHER, ibwrta, __F_HANDLE | __F_BUFFER | __F_CNT }, - [__ID_IBWRTF] = { "ibwrtf", H_EITHER, ibwrtf, __F_HANDLE | __F_FLNAME }, - [__ID_IBWRTKEY] = { "ibwrtkey", H_EITHER, ibwrtkey, __F_HANDLE | __F_BUFFER | __F_CNT }, - [__ID_IBXTRC] = { "ibxtrc", H_EITHER, ibxtrc, __F_HANDLE | __F_BUFFER | __F_CNT }, -}; - -static const u_int max_ibhandler = sizeof ibhandlers / sizeof ibhandlers[0]; - -static void -ib_dump_args(struct ibhandler *ih, struct ibarg *ap) -{ - - 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=0x%x", 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=0x%x", ap->pad); - if (ap->__field & __F_SAD) printf(" sad=0x%x", ap->sad); - if (ap->__field & __F_BUFFER) printf(" buffer=%p", ap->buffer); - if (ap->__field & __F_CNT) printf(" cnt=%ld", ap->cnt); - if (ap->__field & __F_V) printf(" v=%d/0x%x", ap->v, ap->v); - /* XXX more ... */ - printf(")\n"); -} - -static int -gpib_ib_open(struct cdev *dev, int oflags, int devtype, struct thread *td) -{ - struct upd7210 *u; - struct ibfoo *ib; - int error = 0; - - u = dev->si_drv1; - - mtx_lock(&u->mutex); - if (u->busy) { - mtx_unlock(&u->mutex); - return (EBUSY); - } - u->busy = 1; - mtx_unlock(&u->mutex); - - if (u->dmachan >= 0) { - 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); - } - } - - 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); - callout_init(&ib->callout, CALLOUT_MPSAFE); - ib->unrhdr = new_unrhdr(0, INT_MAX, NULL); - dev->si_drv2 = ib; - ib->u = 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); - if (u->use_fifo) { - bus_write_1(u->reg_res[0], imr3, 0x00); - bus_write_1(u->reg_res[0], cmdr, 0x22); /* soft reset */ - bus_write_1(u->reg_res[0], cmdr, 0x03); /* set system - * controller bit */ - } - 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); - - if (u->dmachan >= 0) { - isa_dma_release(u->dmachan); - } - mtx_lock(&u->mutex); - u->busy = 0; - ibdebug = 0; - upd7210_wr(u, IMR1, 0x00); - upd7210_wr(u, IMR2, 0x00); - if (u->use_fifo) { - bus_write_1(u->reg_res[0], imr3, 0x00); - bus_write_1(u->reg_res[0], cmdr, 0x02); /* clear system - * controller bit */ - } - 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 ibarg *ap; - struct ibhandler *ih; - struct handle *h; - struct upd7210 *u; - struct ibfoo *ib; - int error; - struct timeval deadline, tv; - - u = dev->si_drv1; - ib = u->ibfoo; - - /* We only support a single ioctl, everything else is a mistake */ - if (cmd != GPIB_IBFOO) - return (ENOIOCTL); - - /* Check the identifier and field-bitmap in the arguments. */ - 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 (ibdebug) - ib_dump_args(ih, ap); - - if (ih->func == NULL) - return (EOPNOTSUPP); - - ap->__iberr = 0; - ap->__ibsta = 0; - ap->__ibcnt = 0; - ap->__retval = 0; - - if (ap->__field & __F_TMO) { - if (ap->tmo < 0 || ap->tmo >= max_timeouts) - return (ib_set_error(ap, EARG)); - } - - if (ap->__field & __F_EOS) { - if ((ap->eos & ~(REOS | XEOS | BIN | 0xff)) || - ((ap->eos & (BIN | 0x80)) == 0x80)) - return (ib_set_error(ap, EARG)); - } - if (ap->__field & __F_PAD) { - if (ap->pad < 0 || ap->pad > 30) - return (ib_set_error(ap, EARG)); - } - if (ap->__field & __F_SAD) { - if (ap->sad != 0 && (ap->sad < 0x60 || ap->sad > 126)) - return (ib_set_error(ap, EARG)); - } - - - mtx_lock(&u->mutex); - - - /* Find the handle, if any */ - h = NULL; - if ((ap->__field & __F_HANDLE) && gethandle(u, ap, &h)) { - mtx_unlock(&u->mutex); - return (0); - } - - /* Check that the handle is the right kind */ - if (h != NULL && !(h->kind & ih->kind)) { - mtx_unlock(&u->mutex); - return (ib_set_error(ap, EARG)); - } - - /* Set up handle and deadline */ - if (h != NULL && timevalisset(&h->timeout)) { - getmicrouptime(&deadline); - timevaladd(&deadline, &h->timeout); - } else { - timevalclear(&deadline); - } - - /* Wait for the card to be(come) available, respect deadline */ - while(u->busy != 1) { - error = msleep(ib, &u->mutex, - PZERO | PCATCH, "gpib_ibioctl", hz / 10); - if (error == 0) - continue; - mtx_unlock(&u->mutex); - if (error == EINTR) - return(ib_set_error(ap, EABO)); - if (error == EWOULDBLOCK && timevalisset(&deadline)) { - getmicrouptime(&tv); - if (timevalcmp(&deadline, &tv, <)) - return(ib_had_timeout(ap)); - } - mtx_lock(&u->mutex); - } - u->busy = 2; - mtx_unlock(&u->mutex); - - /* Hand over deadline handling to the callout routine */ - ib->ap = ap; - ib->h = h; - ib->mode = BUSY; - ib->deadline = deadline; - callout_reset(&ib->callout, hz / 5, gpib_ib_timeout, u); - - error = ih->func(ib); - - /* Release card */ - ib->mode = IDLE; - ib->ap = NULL; - ib->h = NULL; - timevalclear(&deadline); - callout_stop(&ib->callout); - - mtx_lock(&u->mutex); - u->busy = 1; - wakeup(ib); - mtx_unlock(&u->mutex); - - if (error) - return(ib_set_errno(ap, error)); - return (0); -} - -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, -}; |