mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-12-02 21:32:58 +00:00
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
This commit is contained in:
parent
fac3c43153
commit
ac0797c3d1
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=203360
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
77
sys/dev/ieee488/tnt4882.h
Normal file
77
sys/dev/ieee488/tnt4882.h
Normal file
@ -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
|
||||
};
|
||||
|
@ -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;
|
||||
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, 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);
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ struct upd7210 {
|
||||
u_int reg_offset[8];
|
||||
int dmachan;
|
||||
int unit;
|
||||
int use_fifo;
|
||||
|
||||
/* private stuff */
|
||||
struct mtx mutex;
|
||||
|
Loading…
Reference in New Issue
Block a user