summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjoerg <joerg@FreeBSD.org>2010-02-01 21:21:10 +0000
committerjoerg <joerg@FreeBSD.org>2010-02-01 21:21:10 +0000
commitd67164f24c90020e7faa21f9a119342ba4c94eda (patch)
treed2b8cccc7e23ea72cbede5a0e58fb2d699312d6a
parent8d6ed99eb05f2c34a558f53113a6c747f941be1a (diff)
downloadFreeBSD-src-d67164f24c90020e7faa21f9a119342ba4c94eda.zip
FreeBSD-src-d67164f24c90020e7faa21f9a119342ba4c94eda.tar.gz
GPIB overhaul, part #2: make the tnt4882 driver work with the newer
TNT5004 IC. This involved a major rewrite of a number of things, as this chip no longer supports the NAT7210 legacy mode but requires the host to use the (more modern) FIFO mode. In theory, this also ought to work on the older TNT4882C chip. I'll probably add this as optional support (perhaps by a device.hints flag) later on. By now, FIFO mode is *only* activates iff a TNT5004 chip has been detected (where the old code didn't work at all), while everything else is supposed to use the old code. MFC after: 2 weeks
-rw-r--r--sys/dev/ieee488/ibfoo.c144
-rw-r--r--sys/dev/ieee488/pcii.c5
-rw-r--r--sys/dev/ieee488/tnt4882.c71
-rw-r--r--sys/dev/ieee488/tnt4882.h77
-rw-r--r--sys/dev/ieee488/upd7210.c87
-rw-r--r--sys/dev/ieee488/upd7210.h1
6 files changed, 304 insertions, 81 deletions
diff --git a/sys/dev/ieee488/ibfoo.c b/sys/dev/ieee488/ibfoo.c
index 7458d8b..7ae9160 100644
--- a/sys/dev/ieee488/ibfoo.c
+++ b/sys/dev/ieee488/ibfoo.c
@@ -1,5 +1,6 @@
/*-
* 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
@@ -40,6 +41,7 @@ __FBSDID("$FreeBSD$");
#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>
@@ -53,6 +55,7 @@ __FBSDID("$FreeBSD$");
#define UPD7210_SW_DRIVER
#include <dev/ieee488/upd7210.h>
+#include <dev/ieee488/tnt4882.h>
static MALLOC_DEFINE(M_IBFOO, "IBFOO", "IBFOO");
@@ -94,7 +97,10 @@ struct ibfoo {
PIO_IDATA,
PIO_ODATA,
PIO_CMD,
- DMA_IDATA
+ DMA_IDATA,
+ FIFO_IDATA,
+ FIFO_ODATA,
+ FIFO_CMD
} mode;
struct timeval deadline;
@@ -170,7 +176,7 @@ ib_set_errno(struct ibarg *ap, int errno)
}
static int
-gpib_ib_irq(struct upd7210 *u, int intr __unused)
+gpib_ib_irq(struct upd7210 *u, int isr_3)
{
struct ibfoo *ib;
@@ -211,11 +217,53 @@ gpib_ib_irq(struct upd7210 *u, int intr __unused)
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);
@@ -227,6 +275,7 @@ gpib_ib_timeout(void *arg)
struct upd7210 *u;
struct ibfoo *ib;
struct timeval tv;
+ u_int isr_3;
u = arg;
ib = u->ibfoo;
@@ -241,7 +290,11 @@ gpib_ib_timeout(void *arg)
if (ib->mode > BUSY) {
upd7210_rd(u, ISR1);
upd7210_rd(u, ISR2);
- gpib_ib_irq(u, 2);
+ 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);
@@ -249,6 +302,10 @@ gpib_ib_timeout(void *arg)
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);
}
@@ -280,6 +337,8 @@ gpib_ib_wait_xfer(struct upd7210 *u, struct ibfoo *ib)
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
@@ -335,15 +394,31 @@ pio_cmd(struct upd7210 *u, u_char *cmd, int len)
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);
+ 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);
}
@@ -358,13 +433,32 @@ pio_odata(struct upd7210 *u, u_char *data, int len)
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);
+ 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);
}
@@ -377,13 +471,30 @@ pio_idata(struct upd7210 *u, u_char *data, int len)
ib = u->ibfoo;
mtx_lock(&u->mutex);
- ib->mode = PIO_IDATA;
ib->buf = data;
ib->buflen = len;
- upd7210_wr(u, IMR1, IXR1_DI);
+ 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);
}
@@ -826,6 +937,12 @@ gpib_ib_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
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);
@@ -856,6 +973,11 @@ gpib_ib_close(struct cdev *dev, int oflags, int devtype, struct thread *td)
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);
diff --git a/sys/dev/ieee488/pcii.c b/sys/dev/ieee488/pcii.c
index 7e92432..3c5699e 100644
--- a/sys/dev/ieee488/pcii.c
+++ b/sys/dev/ieee488/pcii.c
@@ -238,6 +238,7 @@ pcii_attach(device_t dev)
sc->upd7210.reg_offset[rid] = 0;
}
sc->upd7210.irq_clear_res = sc->res[10];
+ sc->upd7210.use_fifo = 0;
if (sc->res[1] == NULL)
sc->upd7210.dmachan = -1;
@@ -245,7 +246,9 @@ pcii_attach(device_t dev)
sc->upd7210.dmachan = rman_get_start(sc->res[1]);
upd7210attach(&sc->upd7210);
- return (error);
+ device_printf(dev, "attached gpib%d\n", sc->upd7210.unit);
+
+ return (0);
}
DRIVER_MODULE(pcii, isa, pcii_driver, pcii_devclass, 0, 0);
diff --git a/sys/dev/ieee488/tnt4882.c b/sys/dev/ieee488/tnt4882.c
index a4222a6..4b69d0d 100644
--- a/sys/dev/ieee488/tnt4882.c
+++ b/sys/dev/ieee488/tnt4882.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2005 Poul-Henning Kamp
+ * Copyright (c) 2010 Joerg Wunsch
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -46,6 +47,7 @@
#define UPD7210_HW_DRIVER 1
#include <dev/ieee488/upd7210.h>
+#include <dev/ieee488/tnt4882.h>
struct tnt_softc {
int foo;
@@ -62,55 +64,6 @@ static struct resource_spec tnt_res_spec[] = {
{ -1, 0 }
};
-enum tnt4882reg {
- dir = 0x00,
- cdor = 0x00,
- isr1 = 0x02,
- imr1 = 0x02,
- isr2 = 0x04,
- imr2 = 0x04,
- accwr = 0x05,
- spsr = 0x06,
- spmr = 0x06,
- intr = 0x07,
- adsr = 0x08,
- admr = 0x08,
- cnt2 = 0x09,
- cptr = 0x0a,
- auxmr = 0x0a,
- tauxcr = 0x0a, /* 9914 mode register */
- cnt3 = 0x0b,
- adr0 = 0x0c,
- adr = 0x0c,
- hssel = 0x0d,
- adr1 = 0x0e,
- eosr = 0x0e,
- sts1 = 0x10,
- cfg = 0x10,
- dsr = 0x11,
- sh_cnt = 0x11,
- imr3 = 0x12,
- hier = 0x13,
- cnt0 = 0x14,
- misc = 0x15,
- cnt1 = 0x16,
- csr = 0x17,
- keyreg = 0x17,
- fifob = 0x18,
- fifoa = 0x19,
- isr3 = 0x1a,
- ccr = 0x1a,
- sasr = 0x1b,
- dcr = 0x1b,
- sts2 = 0x1c,
- cmdr = 0x1c,
- isr0 = 0x1d,
- imr0 = 0x1d,
- timer = 0x1e,
- bsr = 0x1f,
- bcr = 0x1f
-};
-
struct tst {
enum {RD, WT, xDELAY, END}
action;
@@ -276,6 +229,7 @@ tnt_attach(device_t dev)
{
struct tnt_softc *sc;
int error, i;
+ uint8_t version;
sc = device_get_softc(dev);
@@ -286,7 +240,7 @@ tnt_attach(device_t dev)
error = bus_setup_intr(dev, sc->res[2], INTR_TYPE_MISC | INTR_MPSAFE,
NULL, upd7210intr, &sc->upd7210, &sc->intr_handler);
- /* Necessary magic for MITE */
+ /* IO Device Window Base Size Register (IODWBSR) */
bus_write_4(sc->res[0], 0xc0, rman_get_start(sc->res[1]) | 0x80);
tst_exec(sc, tst_reset, "Reset");
@@ -298,6 +252,18 @@ tnt_attach(device_t dev)
tst_exec(sc, tst_count0_1, "COUNT0:1");
tst_exec(sc, tst_reset, "Reset");
+ version = bus_read_1(sc->res[1], csr);
+ version = (version >> 4) & 0x0f;
+ device_printf(dev, "Chip version 0x%02x (TNT%s)\n",
+ version,
+ version >= 4? "5004 or above": "4882");
+ if (version >= 4) {
+ device_printf(dev, "Forcing FIFO mode\n");
+ sc->upd7210.use_fifo = 1;
+ } else {
+ sc->upd7210.use_fifo = 0;
+ }
+
/* pass 7210 interrupts through */
bus_write_1(sc->res[1], imr3, 0x02);
@@ -313,6 +279,11 @@ tnt_attach(device_t dev)
sc->upd7210.irq_clear_res = NULL;
upd7210attach(&sc->upd7210);
+ device_printf(dev, "attached gpib%d\n", sc->upd7210.unit);
+
+ if (sc->upd7210.use_fifo)
+ bus_write_1(sc->res[0], hssel, 0x01); /* one-chip mode */
+
return (0);
}
diff --git a/sys/dev/ieee488/tnt4882.h b/sys/dev/ieee488/tnt4882.h
new file mode 100644
index 0000000..221cfd9
--- /dev/null
+++ b/sys/dev/ieee488/tnt4882.h
@@ -0,0 +1,77 @@
+/*-
+ * Copyright (c) 2010 Joerg Wunsch
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+enum tnt4882reg {
+ dir = 0x00,
+ cdor = 0x00,
+ isr1 = 0x02,
+ imr1 = 0x02,
+ isr2 = 0x04,
+ imr2 = 0x04,
+ accwr = 0x05,
+ spsr = 0x06,
+ spmr = 0x06,
+ intr = 0x07,
+ adsr = 0x08,
+ admr = 0x08,
+ cnt2 = 0x09,
+ cptr = 0x0a,
+ auxmr = 0x0a,
+ tauxcr = 0x0a, /* 9914 mode register */
+ cnt3 = 0x0b,
+ adr0 = 0x0c,
+ adr = 0x0c,
+ hssel = 0x0d,
+ adr1 = 0x0e,
+ eosr = 0x0e,
+ sts1 = 0x10,
+ cfg = 0x10,
+ dsr = 0x11,
+ sh_cnt = 0x11,
+ imr3 = 0x12,
+ hier = 0x13,
+ cnt0 = 0x14,
+ misc = 0x15,
+ cnt1 = 0x16,
+ csr = 0x17,
+ keyreg = 0x17,
+ fifob = 0x18,
+ fifoa = 0x19,
+ isr3 = 0x1a,
+ ccr = 0x1a,
+ sasr = 0x1b,
+ dcr = 0x1b,
+ sts2 = 0x1c,
+ cmdr = 0x1c,
+ isr0 = 0x1d,
+ imr0 = 0x1d,
+ timer = 0x1e,
+ bsr = 0x1f,
+ bcr = 0x1f
+};
+
diff --git a/sys/dev/ieee488/upd7210.c b/sys/dev/ieee488/upd7210.c
index b245a65..ed6c64e 100644
--- a/sys/dev/ieee488/upd7210.c
+++ b/sys/dev/ieee488/upd7210.c
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
#define UPD7210_HW_DRIVER
#define UPD7210_SW_DRIVER
#include <dev/ieee488/upd7210.h>
+#include <dev/ieee488/tnt4882.h>
static MALLOC_DEFINE(M_GPIB, "GPIB", "GPIB");
@@ -90,15 +91,20 @@ upd7210_wr(struct upd7210 *u, enum upd7210_wreg reg, u_int val)
void
upd7210intr(void *arg)
{
- u_int isr1, isr2;
+ u_int isr_1, isr_2, isr_3;
struct upd7210 *u;
u = arg;
mtx_lock(&u->mutex);
- isr1 = upd7210_rd(u, ISR1);
- isr2 = upd7210_rd(u, ISR2);
- if (isr1 != 0 || isr2 != 0) {
- if (u->busy == 0 || u->irq == NULL || !u->irq(u, 1)) {
+ isr_1 = upd7210_rd(u, ISR1);
+ isr_2 = upd7210_rd(u, ISR2);
+ if (u->use_fifo) {
+ isr_3 = bus_read_1(u->reg_res[0], isr3);
+ } else {
+ isr_3 = 0;
+ }
+ if (isr_1 != 0 || isr_2 != 0 || isr_3 != 0) {
+ if (u->busy == 0 || u->irq == NULL || !u->irq(u, isr_3)) {
#if 0
printf("upd7210intr [%02x %02x %02x",
upd7210_rd(u, DIR), isr1, isr2);
@@ -168,17 +174,38 @@ upd7210_goto_standby(struct upd7210 *u)
/* Unaddressed Listen Only mode */
static int
-gpib_l_irq(struct upd7210 *u, int intr __unused)
+gpib_l_irq(struct upd7210 *u, int isr_3)
{
int i;
-
- if (u->rreg[ISR1] & 1) {
+ int have_data = 0;
+
+ if (u->use_fifo) {
+ /* TNT5004 or TNT4882 in FIFO mode */
+ if (isr_3 & 0x04) {
+ /* FIFO not empty */
+ i = bus_read_1(u->reg_res[0], fifob);
+ have_data = 1;
+ bus_write_1(u->reg_res[0], cnt0, -1);
+ bus_write_1(u->reg_res[0], cnt1, (-1) >> 8);
+ bus_write_1(u->reg_res[0], cnt2, (-1) >> 16);
+ bus_write_1(u->reg_res[0], cnt3, (-1) >> 24);
+ bus_write_1(u->reg_res[0], cmdr, 0x04); /* GO */
+ }
+ } else if (u->rreg[ISR1] & 1) {
i = upd7210_rd(u, DIR);
+ have_data = 1;
+ }
+
+ if (have_data) {
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)
- upd7210_wr(u, IMR1, 0);
+ if (i < 8) {
+ if (u->use_fifo)
+ bus_write_1(u->reg_res[0], imr3, 0x00);
+ else
+ upd7210_wr(u, IMR1, 0);
+ }
wakeup(u->buf);
return (1);
}
@@ -206,15 +233,28 @@ gpib_l_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
u->buf_wp = 0;
u->buf_rp = 0;
- upd7210_wr(u, AUXMR, AUXMR_CRST);
+ upd7210_wr(u, AUXMR, AUXMR_CRST); /* chip reset */
DELAY(10000);
- upd7210_wr(u, AUXMR, C_ICR | 8);
+ upd7210_wr(u, AUXMR, C_ICR | 8); /* 8 MHz clock */
DELAY(1000);
- 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);
+ upd7210_wr(u, ADR, 0x60); /* ADR0: disable listener and talker 0 */
+ upd7210_wr(u, ADR, 0xe0); /* ADR1: disable listener and talker 1 */
+ upd7210_wr(u, ADMR, 0x70); /* listen-only (lon) */
+ upd7210_wr(u, AUXMR, AUXMR_PON); /* immediate execute power-on (pon) */
+ if (u->use_fifo) {
+ /* TNT5004 or TNT4882 in FIFO mode */
+ 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, -1);
+ bus_write_1(u->reg_res[0], cnt1, (-1) >> 8);
+ bus_write_1(u->reg_res[0], cnt2, (-1) >> 16);
+ bus_write_1(u->reg_res[0], cnt3, (-1) >> 24);
+ bus_write_1(u->reg_res[0], cmdr, 0x04); /* GO */
+ bus_write_1(u->reg_res[0], imr3, 0x04); /* NEF IE */
+ } else {
+ /* µPD7210/NAT7210, or TNT4882 in non-FIFO mode */
+ upd7210_wr(u, IMR1, 0x01); /* data in interrupt enable */
+ }
return (0);
}
@@ -227,6 +267,11 @@ gpib_l_close(struct cdev *dev, int oflags, int devtype, struct thread *td)
mtx_lock(&u->mutex);
u->busy = 0;
+ if (u->use_fifo) {
+ /* TNT5004 or TNT4882 in FIFO mode */
+ bus_write_1(u->reg_res[0], cmdr, 0x22); /* soft RESET */
+ bus_write_1(u->reg_res[0], imr3, 0x00);
+ }
upd7210_wr(u, AUXMR, AUXMR_CRST);
DELAY(10000);
upd7210_wr(u, IMR1, 0x00);
@@ -271,8 +316,12 @@ gpib_l_read(struct cdev *dev, struct uio *uio, int ioflag)
u->buf_rp += z;
u->buf_rp &= (u->bufsize - 1);
}
- if (u->wreg[IMR1] == 0)
- upd7210_wr(u, IMR1, 0x01);
+ if (u->use_fifo) {
+ bus_write_1(u->reg_res[0], imr3, 0x04); /* NFF IE */
+ } else {
+ if (u->wreg[IMR1] == 0)
+ upd7210_wr(u, IMR1, 0x01);
+ }
mtx_unlock(&u->mutex);
return (error);
}
diff --git a/sys/dev/ieee488/upd7210.h b/sys/dev/ieee488/upd7210.h
index 9d619b7..88235dd 100644
--- a/sys/dev/ieee488/upd7210.h
+++ b/sys/dev/ieee488/upd7210.h
@@ -53,6 +53,7 @@ struct upd7210 {
u_int reg_offset[8];
int dmachan;
int unit;
+ int use_fifo;
/* private stuff */
struct mtx mutex;
OpenPOWER on IntegriCloud