2 * Copyright (c) 2005 Poul-Henning Kamp <phk@FreeBSD.org>
3 * Copyright (c) 2010 Joerg Wunsch <joerg@FreeBSD.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * High-level driver for µPD7210 based GPIB cards.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
37 #include <sys/param.h>
38 #include <sys/systm.h>
40 #include <sys/malloc.h>
41 #include <sys/kernel.h>
42 #include <sys/limits.h>
43 #include <sys/module.h>
47 #include <sys/mutex.h>
50 #include <machine/bus.h>
51 #include <machine/resource.h>
52 #include <isa/isavar.h>
54 #include <dev/ieee488/ugpib.h>
56 #define UPD7210_SW_DRIVER
57 #include <dev/ieee488/upd7210.h>
58 #include <dev/ieee488/tnt4882.h>
60 static MALLOC_DEFINE(M_IBFOO, "IBFOO", "IBFOO");
65 #include <dev/ieee488/ibfoo_int.h>
67 /* XXX: This is really a bitmap */
75 LIST_ENTRY(handle) list;
80 struct timeval timeout;
88 LIST_HEAD(,handle) handles;
89 struct unrhdr *unrhdr;
90 struct callout callout;
106 struct timeval deadline;
108 struct handle *rdh; /* addressed for read */
109 struct handle *wrh; /* addressed for write */
117 typedef int ibhandler_t(struct ibfoo *ib);
119 static struct timeval timeouts[] = {
123 [T100us] = { 0, 100},
124 [T300us] = { 0, 300},
127 [T10ms] = { 0, 10000},
128 [T30ms] = { 0, 30000},
129 [T100ms] = { 0, 100000},
130 [T300ms] = { 0, 300000},
137 [T1000s] = { 1000, 0}
140 static const u_int max_timeouts = sizeof timeouts / sizeof timeouts[0];
145 ib_set_error(struct ibarg *ap, int error)
148 if (ap->__iberr == 0)
151 ap->__retval = ap->__ibsta;
156 ib_had_timeout(struct ibarg *ap)
159 ib_set_error(ap, EABO);
161 ap->__retval = ap->__ibsta;
166 ib_set_errno(struct ibarg *ap, int errno)
169 if (ap->__iberr == 0) {
174 ap->__retval = ap->__ibsta;
179 gpib_ib_irq(struct upd7210 *u, int isr_3)
185 mtx_assert(&u->mutex, MA_OWNED);
188 if (!(u->rreg[ISR2] & IXR2_CO))
192 upd7210_wr(u, CDOR, *ib->buf);
197 if (!(u->rreg[ISR1] & IXR1_DI))
199 *ib->buf = upd7210_rd(u, DIR);
202 if (ib->buflen == 0 || (u->rreg[ISR1] & IXR1_ENDRX))
206 if (!(u->rreg[ISR1] & IXR1_DO))
210 if (ib->buflen == 1 && ib->doeoi)
211 upd7210_wr(u, AUXMR, AUXMR_SEOI);
212 upd7210_wr(u, CDOR, *ib->buf);
217 if (!(u->rreg[ISR1] & IXR1_ENDRX))
223 while (ib->buflen != 0 && (isr_3 & 0x04 /* NEF */) != 0) {
224 *ib->buf = bus_read_1(u->reg_res[0], fifob);
227 isr_3 = bus_read_1(u->reg_res[0], isr3);
229 if ((isr_3 & 0x01) != 0 /* xfr done */ ||
230 (u->rreg[ISR1] & IXR1_ENDRX) != 0 ||
235 bus_write_1(u->reg_res[0], cmdr, 0x04); /* GO */
236 upd7210_wr(u, AUXMR, AUXMR_RFD);
245 while (ib->buflen != 0 && (isr_3 & 0x08 /* NFF */) != 0) {
246 bus_write_1(u->reg_res[0], fifob, *ib->buf);
249 isr_3 = bus_read_1(u->reg_res[0], isr3);
253 bus_write_1(u->reg_res[0], cmdr, 0x04); /* GO */
255 /* no more NFF interrupts wanted */
256 bus_write_1(u->reg_res[0], imr3, 0x11); /* STOP IE, DONE IE */
261 upd7210_wr(u, IMR1, 0);
262 upd7210_wr(u, IMR2, 0);
264 bus_write_1(u->reg_res[0], imr3, 0x00);
265 bus_write_1(u->reg_res[0], cmdr, 0x22); /* soft RESET */
273 gpib_ib_timeout(void *arg)
283 if (ib->mode == DMA_IDATA && isa_dmatc(u->dmachan)) {
284 KASSERT(u->dmachan >= 0, ("Bogus dmachan = %d", u->dmachan));
285 upd7210_wr(u, IMR1, 0);
286 upd7210_wr(u, IMR2, 0);
290 if (ib->mode > BUSY) {
294 isr_3 = bus_read_1(u->reg_res[0], isr3);
297 gpib_ib_irq(u, isr_3);
299 if (ib->mode != IDLE && timevalisset(&ib->deadline)) {
301 if (timevalcmp(&ib->deadline, &tv, <)) {
302 ib_had_timeout(ib->ap);
303 upd7210_wr(u, IMR1, 0);
304 upd7210_wr(u, IMR2, 0);
306 bus_write_1(u->reg_res[0], imr3, 0x00);
307 bus_write_1(u->reg_res[0], cmdr, 0x22); /* soft RESET */
313 if (ib->mode != IDLE)
314 callout_reset(&ib->callout, hz / 5, gpib_ib_timeout, arg);
315 mtx_unlock(&u->mutex);
319 gpib_ib_wait_xfer(struct upd7210 *u, struct ibfoo *ib)
323 mtx_assert(&u->mutex, MA_OWNED);
324 while (ib->mode > BUSY) {
325 i = msleep(&ib->buflen, &u->mutex,
326 PZERO | PCATCH, "ibwxfr", 0);
328 ib_set_errno(ib->ap, i);
331 if (u->rreg[ISR1] & IXR1_ERR) {
332 ib_set_error(ib->ap, EABO); /* XXX ? */
338 upd7210_wr(u, IMR1, 0);
339 upd7210_wr(u, IMR2, 0);
341 bus_write_1(u->reg_res[0], imr3, 0x00);
345 config_eos(struct upd7210 *u, struct handle *h)
351 upd7210_wr(u, EOSR, h->eos & 0xff);
355 upd7210_wr(u, EOSR, h->eos & 0xff);
360 upd7210_wr(u, AUXRA, C_AUXA | i);
364 * Look up the handle, and set the deadline if the handle has a timeout.
367 gethandle(struct upd7210 *u, struct ibarg *ap, struct handle **hp)
372 KASSERT(ap->__field & __F_HANDLE, ("gethandle without __F_HANDLE"));
374 LIST_FOREACH(h, &ib->handles, list) {
375 if (h->handle == ap->handle) {
380 ib_set_error(ap, EARG);
385 pio_cmd(struct upd7210 *u, u_char *cmd, int len)
391 if (ib->rdh != NULL || ib->wrh != NULL) {
392 upd7210_take_ctrl_async(u);
400 /* TNT5004 or TNT4882 in FIFO mode */
402 upd7210_wr(u, AUXMR, 0x51); /* holdoff immediately */
403 bus_write_1(u->reg_res[0], cmdr, 0x10); /* reset FIFO */
404 bus_write_1(u->reg_res[0], cfg, 0x80); /* CMD, xfer OUT, 8-bit FIFO */
405 bus_write_1(u->reg_res[0], imr3, 0x19); /* STOP IE, NFF IE, DONE IE */
406 bus_write_1(u->reg_res[0], cnt0, -len);
407 bus_write_1(u->reg_res[0], cnt1, (-len) >> 8);
408 bus_write_1(u->reg_res[0], cnt2, (-len) >> 16);
409 bus_write_1(u->reg_res[0], cnt3, (-len) >> 24);
410 bus_write_1(u->reg_res[0], cmdr, 0x04); /* GO */
413 upd7210_wr(u, IMR2, IXR2_CO);
417 gpib_ib_wait_xfer(u, ib);
420 bus_write_1(u->reg_res[0], cmdr, 0x08); /* STOP */
422 mtx_unlock(&u->mutex);
423 return (len - ib->buflen);
427 pio_odata(struct upd7210 *u, u_char *data, int len)
439 /* TNT5004 or TNT4882 in FIFO mode */
440 ib->mode = FIFO_ODATA;
441 bus_write_1(u->reg_res[0], cmdr, 0x10); /* reset FIFO */
443 bus_write_1(u->reg_res[0], cfg, 0x08); /* CCEN */
445 bus_write_1(u->reg_res[0], cfg, 0x00); /* xfer OUT, 8-bit FIFO */
446 bus_write_1(u->reg_res[0], imr3, 0x19); /* STOP IE, NFF IE, DONE IE */
447 bus_write_1(u->reg_res[0], cnt0, -len);
448 bus_write_1(u->reg_res[0], cnt1, (-len) >> 8);
449 bus_write_1(u->reg_res[0], cnt2, (-len) >> 16);
450 bus_write_1(u->reg_res[0], cnt3, (-len) >> 24);
451 bus_write_1(u->reg_res[0], cmdr, 0x04); /* GO */
453 ib->mode = PIO_ODATA;
454 upd7210_wr(u, IMR1, IXR1_DO);
457 gpib_ib_wait_xfer(u, ib);
460 bus_write_1(u->reg_res[0], cmdr, 0x08); /* STOP */
462 mtx_unlock(&u->mutex);
463 return (len - ib->buflen);
467 pio_idata(struct upd7210 *u, u_char *data, int len)
477 /* TNT5004 or TNT4882 in FIFO mode */
478 ib->mode = FIFO_IDATA;
479 bus_write_1(u->reg_res[0], cmdr, 0x10); /* reset FIFO */
480 bus_write_1(u->reg_res[0], cfg, 0x20); /* xfer IN, 8-bit FIFO */
481 bus_write_1(u->reg_res[0], cnt0, -len);
482 bus_write_1(u->reg_res[0], cnt1, (-len) >> 8);
483 bus_write_1(u->reg_res[0], cnt2, (-len) >> 16);
484 bus_write_1(u->reg_res[0], cnt3, (-len) >> 24);
485 bus_write_1(u->reg_res[0], cmdr, 0x04); /* GO */
486 upd7210_wr(u, AUXMR, AUXMR_RFD);
487 bus_write_1(u->reg_res[0], imr3, 0x15); /* STOP IE, NEF IE, DONE IE */
489 ib->mode = PIO_IDATA;
490 upd7210_wr(u, IMR1, IXR1_DI);
493 gpib_ib_wait_xfer(u, ib);
496 bus_write_1(u->reg_res[0], cmdr, 0x08); /* STOP */
498 mtx_unlock(&u->mutex);
499 return (len - ib->buflen);
503 dma_idata(struct upd7210 *u, u_char *data, int len)
508 KASSERT(u->dmachan >= 0, ("Bogus dmachan %d", u->dmachan));
510 ib->mode = DMA_IDATA;
512 isa_dmastart(ISADMA_READ, data, len, u->dmachan);
515 upd7210_wr(u, IMR1, IXR1_ENDRX);
516 upd7210_wr(u, IMR2, IMR2_DMAI);
517 gpib_ib_wait_xfer(u, ib);
518 mtx_unlock(&u->mutex);
520 j = isa_dmastatus(u->dmachan);
521 isa_dmadone(ISADMA_READ, data, len, u->dmachan);
527 ib_send_msg(struct ibfoo *ib, int msg)
535 buf[i++] = LAD | ib->h->pad;
537 buf[i++] = LAD | TAD | ib->h->sad;
540 j = pio_cmd(ib->u, buf, i);
542 ib_set_error(ib->ap, EABO); /* XXX ? */
547 ibask(struct ibfoo *ib)
550 ibdebug = ib->ap->option;
558 ibclr(struct ibfoo *ib)
561 return (ib_send_msg(ib, SDC));
566 #define ibconfig NULL
569 ibdev(struct ibfoo *ib)
573 h = malloc(sizeof *h, M_IBFOO, M_ZERO | M_WAITOK);
574 h->handle = alloc_unr(ib->unrhdr);
576 h->pad = ib->ap->pad;
577 h->sad = ib->ap->sad;
578 h->timeout = timeouts[ib->ap->tmo];
579 h->eot = ib->ap->eot;
580 h->eos = ib->ap->eos;
581 mtx_lock(&ib->u->mutex);
582 LIST_INSERT_HEAD(&ib->handles, h, list);
583 mtx_unlock(&ib->u->mutex);
584 ib->ap->__retval = h->handle;
591 ibdma(struct ibfoo *ib)
594 if (ib->u->dmachan < 0 && ib->ap->v)
595 return (ib_set_error(ib->ap, EARG));
596 ib->h->dma = ib->ap->v;
601 ibeos(struct ibfoo *ib)
604 ib->ap->__iberr = ib->h->eos;
605 ib->h->eos = ib->ap->eos;
606 if (ib->rdh == ib->h)
607 config_eos(ib->u, ib->h);
612 ibeot(struct ibfoo *ib)
615 ib->h->eot = ib->ap->eot;
628 ibloc(struct ibfoo *ib)
631 if (ib->h->kind == H_BOARD)
632 return (EOPNOTSUPP); /* XXX */
633 return (ib_send_msg(ib, GTL));
637 ibonl(struct ibfoo *ib)
641 return (EOPNOTSUPP); /* XXX */
642 mtx_lock(&ib->u->mutex);
643 LIST_REMOVE(ib->h, list);
644 mtx_unlock(&ib->u->mutex);
645 free(ib->h, M_IBFOO);
651 ibpad(struct ibfoo *ib)
654 ib->h->pad = ib->ap->pad;
663 ibrd(struct ibfoo *ib)
666 int i, j, error, bl, bc;
669 if (ib->h->kind == H_BOARD)
670 return (EOPNOTSUPP); /* XXX */
674 bp = malloc(bl, M_IBFOO, M_WAITOK);
676 if (ib->rdh != ib->h) {
681 buf[i++] = TAD | ib->h->pad;
683 buf[i++] = ib->h->sad;
684 i = pio_cmd(ib->u, buf, i);
685 config_eos(ib->u, ib->h);
689 upd7210_goto_standby(ib->u);
693 while (bc > 0 && ib->ap->__iberr == 0) {
694 j = imin(bc, PAGE_SIZE);
696 i = dma_idata(ib->u, bp, j);
698 i = pio_idata(ib->u, bp, j);
699 error = copyout(bp, dp , i);
702 ib->ap->__ibcnt += i;
708 upd7210_take_ctrl_async(ib->u);
722 ibsad(struct ibfoo *ib)
725 ib->h->sad = ib->ap->sad;
732 ibsic(struct ibfoo *ib)
735 upd7210_wr(ib->u, AUXMR, AUXMR_SIFC);
737 upd7210_wr(ib->u, AUXMR, AUXMR_CIFC);
746 ibtmo(struct ibfoo *ib)
749 ib->h->timeout = timeouts[ib->ap->tmo];
756 ibtrg(struct ibfoo *ib)
759 return (ib_send_msg(ib, GET));
765 ibwrt(struct ibfoo *ib)
770 if (ib->h->kind == H_BOARD)
772 bp = malloc(ib->ap->cnt, M_IBFOO, M_WAITOK);
773 /* XXX: bigger than PAGE_SIZE handling */
774 i = copyin(ib->ap->buffer, bp, ib->ap->cnt);
779 if (ib->wrh != ib->h) {
783 buf[i++] = LAD | ib->h->pad;
785 buf[i++] = LAD | TAD | ib->h->sad;
787 i = pio_cmd(ib->u, buf, i);
790 config_eos(ib->u, ib->h);
792 upd7210_goto_standby(ib->u);
793 ib->doeoi = ib->h->eot;
794 i = pio_odata(ib->u, bp, ib->ap->cnt);
795 upd7210_take_ctrl_async(ib->u);
803 #define ibwrtkey NULL
806 static struct ibhandler {
812 [__ID_IBASK] = { "ibask", H_EITHER, ibask, __F_HANDLE | __F_OPTION | __F_RETVAL },
813 [__ID_IBBNA] = { "ibbna", H_DEV, ibbna, __F_HANDLE | __F_BDNAME },
814 [__ID_IBCAC] = { "ibcac", H_BOARD, ibcac, __F_HANDLE | __F_V },
815 [__ID_IBCLR] = { "ibclr", H_DEV, ibclr, __F_HANDLE },
816 [__ID_IBCMD] = { "ibcmd", H_BOARD, ibcmd, __F_HANDLE | __F_BUFFER | __F_CNT },
817 [__ID_IBCMDA] = { "ibcmda", H_BOARD, ibcmda, __F_HANDLE | __F_BUFFER | __F_CNT },
818 [__ID_IBCONFIG] = { "ibconfig", H_EITHER, ibconfig, __F_HANDLE | __F_OPTION | __F_VALUE },
819 [__ID_IBDEV] = { "ibdev", 0, ibdev, __F_BOARDID | __F_PAD | __F_SAD | __F_TMO | __F_EOT | __F_EOS },
820 [__ID_IBDIAG] = { "ibdiag", H_EITHER, ibdiag, __F_HANDLE | __F_BUFFER | __F_CNT },
821 [__ID_IBDMA] = { "ibdma", H_EITHER, ibdma, __F_HANDLE | __F_V },
822 [__ID_IBEOS] = { "ibeos", H_EITHER, ibeos, __F_HANDLE | __F_EOS },
823 [__ID_IBEOT] = { "ibeot", H_EITHER, ibeot, __F_HANDLE | __F_EOT },
824 [__ID_IBEVENT] = { "ibevent", H_BOARD, ibevent, __F_HANDLE | __F_EVENT },
825 [__ID_IBFIND] = { "ibfind", 0, ibfind, __F_BDNAME },
826 [__ID_IBGTS] = { "ibgts", H_BOARD, ibgts, __F_HANDLE | __F_V },
827 [__ID_IBIST] = { "ibist", H_BOARD, ibist, __F_HANDLE | __F_V },
828 [__ID_IBLINES] = { "iblines", H_BOARD, iblines, __F_HANDLE | __F_LINES },
829 [__ID_IBLLO] = { "ibllo", H_EITHER, ibllo, __F_HANDLE },
830 [__ID_IBLN] = { "ibln", H_BOARD, ibln, __F_HANDLE | __F_PADVAL | __F_SADVAL | __F_LISTENFLAG },
831 [__ID_IBLOC] = { "ibloc", H_EITHER, ibloc, __F_HANDLE },
832 [__ID_IBONL] = { "ibonl", H_EITHER, ibonl, __F_HANDLE | __F_V },
833 [__ID_IBPAD] = { "ibpad", H_EITHER, ibpad, __F_HANDLE | __F_PAD },
834 [__ID_IBPCT] = { "ibpct", H_DEV, ibpct, __F_HANDLE },
835 [__ID_IBPOKE] = { "ibpoke", H_EITHER, ibpoke, __F_HANDLE | __F_OPTION | __F_VALUE },
836 [__ID_IBPPC] = { "ibppc", H_EITHER, ibppc, __F_HANDLE | __F_V },
837 [__ID_IBRD] = { "ibrd", H_EITHER, ibrd, __F_HANDLE | __F_BUFFER | __F_CNT },
838 [__ID_IBRDA] = { "ibrda", H_EITHER, ibrda, __F_HANDLE | __F_BUFFER | __F_CNT },
839 [__ID_IBRDF] = { "ibrdf", H_EITHER, ibrdf, __F_HANDLE | __F_FLNAME },
840 [__ID_IBRDKEY] = { "ibrdkey", H_EITHER, ibrdkey, __F_HANDLE | __F_BUFFER | __F_CNT },
841 [__ID_IBRPP] = { "ibrpp", H_EITHER, ibrpp, __F_HANDLE | __F_PPR },
842 [__ID_IBRSC] = { "ibrsc", H_BOARD, ibrsc, __F_HANDLE | __F_V },
843 [__ID_IBRSP] = { "ibrsp", H_DEV, ibrsp, __F_HANDLE | __F_SPR },
844 [__ID_IBRSV] = { "ibrsv", H_EITHER, ibrsv, __F_HANDLE | __F_V },
845 [__ID_IBSAD] = { "ibsad", H_EITHER, ibsad, __F_HANDLE | __F_SAD },
846 [__ID_IBSGNL] = { "ibsgnl", H_EITHER, ibsgnl, __F_HANDLE | __F_V },
847 [__ID_IBSIC] = { "ibsic", H_BOARD, ibsic, __F_HANDLE },
848 [__ID_IBSRE] = { "ibsre", H_BOARD, ibsre, __F_HANDLE | __F_V },
849 [__ID_IBSRQ] = { "ibsrq", H_EITHER, ibsrq, __F_FUNC },
850 [__ID_IBSTOP] = { "ibstop", H_EITHER, ibstop, __F_HANDLE },
851 [__ID_IBTMO] = { "ibtmo", H_EITHER, ibtmo, __F_HANDLE | __F_TMO },
852 [__ID_IBTRAP] = { "ibtrap", H_EITHER, ibtrap, __F_MASK | __F_MODE },
853 [__ID_IBTRG] = { "ibtrg", H_DEV, ibtrg, __F_HANDLE },
854 [__ID_IBWAIT] = { "ibwait", H_EITHER, ibwait, __F_HANDLE | __F_MASK },
855 [__ID_IBWRT] = { "ibwrt", H_EITHER, ibwrt, __F_HANDLE | __F_BUFFER | __F_CNT },
856 [__ID_IBWRTA] = { "ibwrta", H_EITHER, ibwrta, __F_HANDLE | __F_BUFFER | __F_CNT },
857 [__ID_IBWRTF] = { "ibwrtf", H_EITHER, ibwrtf, __F_HANDLE | __F_FLNAME },
858 [__ID_IBWRTKEY] = { "ibwrtkey", H_EITHER, ibwrtkey, __F_HANDLE | __F_BUFFER | __F_CNT },
859 [__ID_IBXTRC] = { "ibxtrc", H_EITHER, ibxtrc, __F_HANDLE | __F_BUFFER | __F_CNT },
862 static const u_int max_ibhandler = sizeof ibhandlers / sizeof ibhandlers[0];
865 ib_dump_args(struct ibhandler *ih, struct ibarg *ap)
868 if (ih->name != NULL)
869 printf("%s(", ih->name);
871 printf("ibinvalid(");
872 printf("[0x%x]", ap->__field);
873 if (ap->__field & __F_HANDLE) printf(" handle=%d", ap->handle);
874 if (ap->__field & __F_EOS) printf(" eos=0x%x", ap->eos);
875 if (ap->__field & __F_EOT) printf(" eot=%d", ap->eot);
876 if (ap->__field & __F_TMO) printf(" tmo=%d", ap->tmo);
877 if (ap->__field & __F_PAD) printf(" pad=0x%x", ap->pad);
878 if (ap->__field & __F_SAD) printf(" sad=0x%x", ap->sad);
879 if (ap->__field & __F_BUFFER) printf(" buffer=%p", ap->buffer);
880 if (ap->__field & __F_CNT) printf(" cnt=%ld", ap->cnt);
881 if (ap->__field & __F_V) printf(" v=%d/0x%x", ap->v, ap->v);
887 gpib_ib_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
897 mtx_unlock(&u->mutex);
901 mtx_unlock(&u->mutex);
903 if (u->dmachan >= 0) {
905 error = isa_dma_acquire(u->dmachan);
907 error = isa_dma_init(u->dmachan, PAGE_SIZE, M_WAITOK);
909 isa_dma_release(u->dmachan);
917 mtx_unlock(&u->mutex);
921 ib = malloc(sizeof *ib, M_IBFOO, M_WAITOK | M_ZERO);
922 LIST_INIT(&ib->handles);
923 callout_init(&ib->callout, CALLOUT_MPSAFE);
924 ib->unrhdr = new_unrhdr(0, INT_MAX, NULL);
928 u->irq = gpib_ib_irq;
930 upd7210_wr(u, AUXMR, AUXMR_CRST);
933 upd7210_wr(u, IMR1, 0x00);
934 upd7210_wr(u, IMR2, 0x00);
935 upd7210_wr(u, SPMR, 0x00);
936 upd7210_wr(u, ADR, 0x00);
937 upd7210_wr(u, ADR, ADR_ARS | ADR_DL | ADR_DT);
938 upd7210_wr(u, ADMR, ADMR_ADM0 | ADMR_TRM0 | ADMR_TRM1);
939 upd7210_wr(u, EOSR, 0x00);
940 upd7210_wr(u, AUXMR, C_ICR | 8);
941 upd7210_wr(u, AUXMR, C_PPR | PPR_U);
942 upd7210_wr(u, AUXMR, C_AUXA);
943 upd7210_wr(u, AUXMR, C_AUXB + 3);
944 upd7210_wr(u, AUXMR, C_AUXE + 0);
945 upd7210_wr(u, AUXMR, AUXMR_PON);
947 bus_write_1(u->reg_res[0], imr3, 0x00);
948 bus_write_1(u->reg_res[0], cmdr, 0x22); /* soft reset */
949 bus_write_1(u->reg_res[0], cmdr, 0x03); /* set system
952 upd7210_wr(u, AUXMR, AUXMR_CIFC);
954 upd7210_wr(u, AUXMR, AUXMR_SIFC);
955 upd7210_wr(u, AUXMR, AUXMR_SREN);
960 gpib_ib_close(struct cdev *dev, int oflags, int devtype, struct thread *td)
967 /* XXX: assert pointer consistency */
970 /* XXX: free handles */
974 if (u->dmachan >= 0) {
976 isa_dma_release(u->dmachan);
982 upd7210_wr(u, IMR1, 0x00);
983 upd7210_wr(u, IMR2, 0x00);
985 bus_write_1(u->reg_res[0], imr3, 0x00);
986 bus_write_1(u->reg_res[0], cmdr, 0x02); /* clear system
989 upd7210_wr(u, AUXMR, AUXMR_CRST);
991 mtx_unlock(&u->mutex);
996 gpib_ib_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
999 struct ibhandler *ih;
1004 struct timeval deadline, tv;
1009 /* We only support a single ioctl, everything else is a mistake */
1010 if (cmd != GPIB_IBFOO)
1013 /* Check the identifier and field-bitmap in the arguments. */
1015 if (ap->__ident < 0 || ap->__ident >= max_ibhandler)
1017 ih = &ibhandlers[ap->__ident];
1018 if (ap->__field != ih->args)
1022 ib_dump_args(ih, ap);
1024 if (ih->func == NULL)
1025 return (EOPNOTSUPP);
1032 if (ap->__field & __F_TMO) {
1033 if (ap->tmo < 0 || ap->tmo >= max_timeouts)
1034 return (ib_set_error(ap, EARG));
1037 if (ap->__field & __F_EOS) {
1038 if ((ap->eos & ~(REOS | XEOS | BIN | 0xff)) ||
1039 ((ap->eos & (BIN | 0x80)) == 0x80))
1040 return (ib_set_error(ap, EARG));
1042 if (ap->__field & __F_PAD) {
1043 if (ap->pad < 0 || ap->pad > 30)
1044 return (ib_set_error(ap, EARG));
1046 if (ap->__field & __F_SAD) {
1047 if (ap->sad != 0 && (ap->sad < 0x60 || ap->sad > 126))
1048 return (ib_set_error(ap, EARG));
1052 mtx_lock(&u->mutex);
1055 /* Find the handle, if any */
1057 if ((ap->__field & __F_HANDLE) && gethandle(u, ap, &h)) {
1058 mtx_unlock(&u->mutex);
1062 /* Check that the handle is the right kind */
1063 if (h != NULL && !(h->kind & ih->kind)) {
1064 mtx_unlock(&u->mutex);
1065 return (ib_set_error(ap, EARG));
1068 /* Set up handle and deadline */
1069 if (h != NULL && timevalisset(&h->timeout)) {
1070 getmicrouptime(&deadline);
1071 timevaladd(&deadline, &h->timeout);
1073 timevalclear(&deadline);
1076 /* Wait for the card to be(come) available, respect deadline */
1077 while(u->busy != 1) {
1078 error = msleep(ib, &u->mutex,
1079 PZERO | PCATCH, "gpib_ibioctl", hz / 10);
1082 mtx_unlock(&u->mutex);
1084 return(ib_set_error(ap, EABO));
1085 if (error == EWOULDBLOCK && timevalisset(&deadline)) {
1086 getmicrouptime(&tv);
1087 if (timevalcmp(&deadline, &tv, <))
1088 return(ib_had_timeout(ap));
1090 mtx_lock(&u->mutex);
1093 mtx_unlock(&u->mutex);
1095 /* Hand over deadline handling to the callout routine */
1099 ib->deadline = deadline;
1100 callout_reset(&ib->callout, hz / 5, gpib_ib_timeout, u);
1102 error = ih->func(ib);
1108 timevalclear(&deadline);
1109 callout_stop(&ib->callout);
1111 mtx_lock(&u->mutex);
1114 mtx_unlock(&u->mutex);
1117 return(ib_set_errno(ap, error));
1121 struct cdevsw gpib_ib_cdevsw = {
1122 .d_version = D_VERSION,
1123 .d_name = "gpib_ib",
1124 .d_open = gpib_ib_open,
1125 .d_ioctl = gpib_ib_ioctl,
1126 .d_close = gpib_ib_close,