Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 1 Feb 2010 21:21:10 +0000 (UTC)
From:      Joerg Wunsch <joerg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r203360 - head/sys/dev/ieee488
Message-ID:  <201002012121.o11LLAag075889@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: joerg
Date: Mon Feb  1 21:21:10 2010
New Revision: 203360
URL: http://svn.freebsd.org/changeset/base/203360

Log:
  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

Added:
  head/sys/dev/ieee488/tnt4882.h   (contents, props changed)
Modified:
  head/sys/dev/ieee488/ibfoo.c
  head/sys/dev/ieee488/pcii.c
  head/sys/dev/ieee488/tnt4882.c
  head/sys/dev/ieee488/upd7210.c
  head/sys/dev/ieee488/upd7210.h

Modified: head/sys/dev/ieee488/ibfoo.c
==============================================================================
--- head/sys/dev/ieee488/ibfoo.c	Mon Feb  1 21:01:20 2010	(r203359)
+++ head/sys/dev/ieee488/ibfoo.c	Mon Feb  1 21:21:10 2010	(r203360)
@@ -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 
 		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);
 }
@@ -826,6 +937,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);
@@ -856,6 +973,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: head/sys/dev/ieee488/pcii.c
==============================================================================
--- head/sys/dev/ieee488/pcii.c	Mon Feb  1 21:01:20 2010	(r203359)
+++ head/sys/dev/ieee488/pcii.c	Mon Feb  1 21:21:10 2010	(r203360)
@@ -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: head/sys/dev/ieee488/tnt4882.c
==============================================================================
--- head/sys/dev/ieee488/tnt4882.c	Mon Feb  1 21:01:20 2010	(r203359)
+++ head/sys/dev/ieee488/tnt4882.c	Mon Feb  1 21:21:10 2010	(r203360)
@@ -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);
 }

Added: head/sys/dev/ieee488/tnt4882.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/ieee488/tnt4882.h	Mon Feb  1 21:21:10 2010	(r203360)
@@ -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: head/sys/dev/ieee488/upd7210.c
==============================================================================
--- head/sys/dev/ieee488/upd7210.c	Mon Feb  1 21:01:20 2010	(r203359)
+++ head/sys/dev/ieee488/upd7210.c	Mon Feb  1 21:21:10 2010	(r203360)
@@ -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: head/sys/dev/ieee488/upd7210.h
==============================================================================
--- head/sys/dev/ieee488/upd7210.h	Mon Feb  1 21:01:20 2010	(r203359)
+++ head/sys/dev/ieee488/upd7210.h	Mon Feb  1 21:21:10 2010	(r203360)
@@ -53,6 +53,7 @@ struct upd7210 {
 	u_int			reg_offset[8];
 	int			dmachan;
 	int			unit;
+	int			use_fifo;
 
 	/* private stuff */
 	struct mtx		mutex;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201002012121.o11LLAag075889>