svn commit: r204491 - stable/8/sys/dev/ieee488

Joerg Wunsch joerg at FreeBSD.org
Sun Feb 28 22:25:40 UTC 2010


Author: joerg
Date: Sun Feb 28 22:25:39 2010
New Revision: 204491
URL: http://svn.freebsd.org/changeset/base/204491

Log:
  MFC r203360
  
    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.

Added:
  stable/8/sys/dev/ieee488/tnt4882.h
     - copied unchanged from r203360, head/sys/dev/ieee488/tnt4882.h
Modified:
  stable/8/sys/dev/ieee488/ibfoo.c
  stable/8/sys/dev/ieee488/pcii.c
  stable/8/sys/dev/ieee488/tnt4882.c
  stable/8/sys/dev/ieee488/upd7210.c
  stable/8/sys/dev/ieee488/upd7210.h
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)
  stable/8/sys/netinet/   (props changed)

Modified: stable/8/sys/dev/ieee488/ibfoo.c
==============================================================================
--- stable/8/sys/dev/ieee488/ibfoo.c	Sun Feb 28 22:09:09 2010	(r204490)
+++ stable/8/sys/dev/ieee488/ibfoo.c	Sun Feb 28 22:25:39 2010	(r204491)
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2005 Poul-Henning Kamp <phk at FreeBSD.org>
+ * Copyright (c) 2010 Joerg Wunsch <joerg at 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 
 		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, str
 	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, 
 		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 *dat
 	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 *dat
 	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);
 }
@@ -832,6 +943,12 @@ gpib_ib_open(struct cdev *dev, int oflag
 	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);
@@ -864,6 +981,11 @@ gpib_ib_close(struct cdev *dev, int ofla
 	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);

Modified: stable/8/sys/dev/ieee488/pcii.c
==============================================================================
--- stable/8/sys/dev/ieee488/pcii.c	Sun Feb 28 22:09:09 2010	(r204490)
+++ stable/8/sys/dev/ieee488/pcii.c	Sun Feb 28 22:25:39 2010	(r204491)
@@ -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);

Modified: stable/8/sys/dev/ieee488/tnt4882.c
==============================================================================
--- stable/8/sys/dev/ieee488/tnt4882.c	Sun Feb 28 22:09:09 2010	(r204490)
+++ stable/8/sys/dev/ieee488/tnt4882.c	Sun Feb 28 22:25:39 2010	(r204491)
@@ -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);
 }

Copied: stable/8/sys/dev/ieee488/tnt4882.h (from r203360, head/sys/dev/ieee488/tnt4882.h)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/8/sys/dev/ieee488/tnt4882.h	Sun Feb 28 22:25:39 2010	(r204491, copy of r203360, head/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
+};
+

Modified: stable/8/sys/dev/ieee488/upd7210.c
==============================================================================
--- stable/8/sys/dev/ieee488/upd7210.c	Sun Feb 28 22:09:09 2010	(r204490)
+++ stable/8/sys/dev/ieee488/upd7210.c	Sun Feb 28 22:25:39 2010	(r204491)
@@ -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 upd72
 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;
+	int have_data = 0;
 
-	if (u->rreg[ISR1] & 1) {
+	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
 	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 oflag
 
 	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
 		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);
 }

Modified: stable/8/sys/dev/ieee488/upd7210.h
==============================================================================
--- stable/8/sys/dev/ieee488/upd7210.h	Sun Feb 28 22:09:09 2010	(r204490)
+++ stable/8/sys/dev/ieee488/upd7210.h	Sun Feb 28 22:25:39 2010	(r204491)
@@ -53,6 +53,7 @@ struct upd7210 {
 	u_int			reg_offset[8];
 	int			dmachan;
 	int			unit;
+	int			use_fifo;
 
 	/* private stuff */
 	struct mtx		mutex;


More information about the svn-src-stable mailing list