summaryrefslogtreecommitdiffstats
path: root/sys/dev/ieee488
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2005-02-06 15:22:23 +0000
committerphk <phk@FreeBSD.org>2005-02-06 15:22:23 +0000
commitcbedd686e72f6cc55f80b962e4199c78380b1b30 (patch)
tree99dcd1fad2091bdceddcf924c1c549f407478a56 /sys/dev/ieee488
parentbd8993edc121200fd4d77aa1cb5073109d702b0d (diff)
downloadFreeBSD-src-cbedd686e72f6cc55f80b962e4199c78380b1b30.zip
FreeBSD-src-cbedd686e72f6cc55f80b962e4199c78380b1b30.tar.gz
Further elaborate the GPIB driver. We now support a minimal subset of
the ibfoo() API.
Diffstat (limited to 'sys/dev/ieee488')
-rw-r--r--sys/dev/ieee488/ibfoo_int.h147
-rw-r--r--sys/dev/ieee488/pcii.c294
-rw-r--r--sys/dev/ieee488/ugpib.h152
-rw-r--r--sys/dev/ieee488/upd7210.c1026
-rw-r--r--sys/dev/ieee488/upd7210.h213
5 files changed, 1569 insertions, 263 deletions
diff --git a/sys/dev/ieee488/ibfoo_int.h b/sys/dev/ieee488/ibfoo_int.h
new file mode 100644
index 0000000..845bb7f
--- /dev/null
+++ b/sys/dev/ieee488/ibfoo_int.h
@@ -0,0 +1,147 @@
+/*-
+ * Copyright (c) 2005 Poul-Henning Kamp
+ * 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.
+ *
+ * This file defines the ABI between the userland gpib library and the
+ * kernel. This file should not be used anywhere else.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/ioccom.h>
+
+typedef void ibsrq_t(void);
+enum ibfoo_id {
+ __ID_INVALID = 0,
+ __ID_IBASK,
+ __ID_IBBNA,
+ __ID_IBCAC,
+ __ID_IBCLR,
+ __ID_IBCMD,
+ __ID_IBCMDA,
+ __ID_IBCONFIG,
+ __ID_IBDEV,
+ __ID_IBDIAG,
+ __ID_IBDMA,
+ __ID_IBEOS,
+ __ID_IBEOT,
+ __ID_IBEVENT,
+ __ID_IBFIND,
+ __ID_IBGTS,
+ __ID_IBIST,
+ __ID_IBLINES,
+ __ID_IBLLO,
+ __ID_IBLN,
+ __ID_IBLOC,
+ __ID_IBONL,
+ __ID_IBPAD,
+ __ID_IBPCT,
+ __ID_IBPOKE,
+ __ID_IBPPC,
+ __ID_IBRD,
+ __ID_IBRDA,
+ __ID_IBRDF,
+ __ID_IBRDKEY,
+ __ID_IBRPP,
+ __ID_IBRSC,
+ __ID_IBRSP,
+ __ID_IBRSV,
+ __ID_IBSAD,
+ __ID_IBSGNL,
+ __ID_IBSIC,
+ __ID_IBSRE,
+ __ID_IBSRQ,
+ __ID_IBSTOP,
+ __ID_IBTMO,
+ __ID_IBTRAP,
+ __ID_IBTRG,
+ __ID_IBWAIT,
+ __ID_IBWRT,
+ __ID_IBWRTA,
+ __ID_IBWRTF,
+ __ID_IBWRTKEY,
+ __ID_IBXTRC
+};
+
+#define __F_HANDLE (1 << 0)
+#define __F_SPR (1 << 1)
+#define __F_BUFFER (1 << 2)
+#define __F_RETVAL (1 << 3)
+#define __F_BDNAME (1 << 4)
+#define __F_MASK (1 << 5)
+#define __F_PADVAL (1 << 6)
+#define __F_SADVAL (1 << 7)
+#define __F_CNT (1 << 8)
+#define __F_TMO (1 << 9)
+#define __F_EOS (1 << 10)
+#define __F_PPR (1 << 11)
+#define __F_EOT (1 << 12)
+#define __F_V (1 << 13)
+#define __F_VALUE (1 << 14)
+#define __F_SAD (1 << 15)
+#define __F_BOARDID (1 << 16)
+#define __F_OPTION (1 << 17)
+#define __F_FLNAME (1 << 18)
+#define __F_FUNC (1 << 19)
+#define __F_LINES (1 << 20)
+#define __F_PAD (1 << 21)
+#define __F_MODE (1 << 22)
+#define __F_LISTENFLAG (1 << 23)
+#define __F_EVENT (1 << 24)
+
+struct ibfoo_iocarg {
+ enum ibfoo_id __ident;
+ unsigned int __field;
+ int __retval;
+ int __ibsts;
+ int __iberr;
+ int __ibcnt;
+ int handle;
+ char * spr;
+ void * buffer;
+ int * retval;
+ char * bdname;
+ int mask;
+ int padval;
+ int sadval;
+ long cnt;
+ int tmo;
+ int eos;
+ char * ppr;
+ int eot;
+ int v;
+ int value;
+ int sad;
+ int boardID;
+ int option;
+ char * flname;
+ ibsrq_t * func;
+ short * lines;
+ int pad;
+ int mode;
+ short * listenflag;
+ short * event;
+};
+
+#define GPIB_IBFOO _IOWR(4, 0, struct ibfoo_iocarg)
diff --git a/sys/dev/ieee488/pcii.c b/sys/dev/ieee488/pcii.c
index fadd96c..ab59545 100644
--- a/sys/dev/ieee488/pcii.c
+++ b/sys/dev/ieee488/pcii.c
@@ -6,22 +6,27 @@
* 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 as
- * the first lines of this file unmodified.
+ * 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 AUTHORS ``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 AUTHORS 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.
+ * 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.
+ *
+ * Driver for GPIB cards based on NEC µPD7210 and compatibles.
+ *
+ * This driver just hooks up to the hardware and leaves all the interesting
+ * stuff to upd7210.c.
*
* Supported hardware:
* PCIIA compatible cards.
@@ -29,13 +34,6 @@
* Tested and known working:
* "B&C Microsystems PC488A-0"
*
- * A whole lot of wonderful things could be written for GPIB, but for now
- * I have just written it such that it is possible to capture data in the
- * mode known as "unaddressed listen only mode". This is what many plotters
- * and printers do on GPIB. This is enough to capture some output from
- * various test instruments.
- *
- * If you are interested in working on this, send me email.
*/
#include <sys/cdefs.h>
@@ -43,53 +41,27 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/bus.h>
-#include <sys/mutex.h>
-#include <sys/uio.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
+#include <isa/isavar.h>
-/* ---> upd7210.h at some point. */
-
-struct upd7210 {
- bus_space_handle_t reg_handle[8];
- bus_space_tag_t reg_tag[8];
- u_int reg_offset[8];
-
- /* private stuff */
- struct mtx mutex;
- uint8_t rreg[8];
- uint8_t wreg[8];
-
- int busy;
- u_char *buf;
- size_t bufsize;
- u_int buf_wp;
- u_int buf_rp;
- struct cdev *cdev;
-};
-
-static void upd7210intr(void *);
-static void upd7210attach(struct upd7210 *);
-
-
-/* ----> pcii.c */
+#include <dev/ieee488/upd7210.h>
struct pcii_softc {
int foo;
struct resource *port[8];
struct resource *irq;
+ struct resource *dma;
void *intr_handler;
struct upd7210 upd7210;
};
-#define HERE() printf("pcii HERE %s:%d\n", __FILE__, __LINE__)
-
static devclass_t pcii_devclass;
static int pcii_probe(device_t dev);
@@ -190,8 +162,16 @@ pcii_attach(device_t dev)
upd7210intr, &sc->upd7210, &sc->intr_handler);
}
}
+ if (!error) {
+ rid = 0;
+ sc->dma = bus_alloc_resource_any(dev,
+ SYS_RES_DRQ, &rid, RF_ACTIVE | RF_SHAREABLE);
+ if (sc->dma == NULL)
+ sc->upd7210.dmachan = -1;
+ else
+ sc->upd7210.dmachan = rman_get_start(sc->dma);
+ }
if (error) {
-device_printf(dev, "error = %d\n", error);
for (i = 0; i < 8; i++) {
if (sc->port[i] == NULL)
break;
@@ -209,215 +189,3 @@ device_printf(dev, "error = %d\n", error);
DRIVER_MODULE(pcii, isa, pcii_driver, pcii_devclass, 0, 0);
DRIVER_MODULE(pcii, acpi, pcii_driver, pcii_devclass, 0, 0);
-
-/* ---> upd7210.c at some point */
-
-enum upd7210_wreg {
- CDOR = 0, /* Command/data out */
- IMR1 = 1, /* Interrupt mask 1 */
- IMR2 = 2, /* Interrupt mask 2 */
- SPMR = 3, /* Serial poll mode */
- ADMR = 4, /* Address mode */
- AUXMR = 5, /* Auxilliary mode */
- ADR = 6, /* Address */
- EOSR = 7, /* End-of-string */
-};
-
-enum upd7210_rreg {
- DIR = 0, /* Data in */
- ISR1 = 1, /* Interrupt status 1 */
- ISR2 = 2, /* Interrupt status 2 */
- SPSR = 3, /* Serial poll status */
- ADSR = 4, /* Address status */
- CPTR = 5, /* Command pass though */
- ADR0 = 6, /* Address 1 */
- ADR1 = 7, /* Address 2 */
-};
-
-#define AUXMR_PON 0x00
-#define AUXMR_CRST 0x02
-#define AUXMR_RFD 0x03
-#define AUXMR_SEOI 0x06
-#define AUXMR_GTS 0x10
-#define AUXMR_TCA 0x11
-#define AUXMR_TCS 0x12
-#define AUXMR_TCSE 0x1a
-#define AUXMR_DSC 0x14
-#define AUXMR_CIFC 0x16
-#define AUXMR_SIFC 0x1e
-#define AUXMR_CREN 0x17
-#define AUXMR_SREN 0x1f
-#define AUXMR_ICTR 0x20
-#define AUXMR_PPR 0x60
-#define AUXMR_RA 0x80
-#define AUXMR_RB 0xa0
-#define AUXMR_RE 0xc0
-
-
-/* upd7210 generic stuff */
-
-static u_int
-read_reg(struct upd7210 *u, enum upd7210_rreg reg)
-{
- u_int r;
-
- r = bus_space_read_1(
- u->reg_tag[reg],
- u->reg_handle[reg],
- u->reg_offset[reg]);
- u->rreg[reg] = r;
- return (r);
-}
-
-static void
-write_reg(struct upd7210 *u, enum upd7210_wreg reg, u_int val)
-{
- bus_space_write_1(
- u->reg_tag[reg],
- u->reg_handle[reg],
- u->reg_offset[reg], val);
- u->wreg[reg] = val;
-}
-
-static void
-upd7210intr(void *arg)
-{
- int i;
- u_int isr1, isr2;
- struct upd7210 *u;
-
- u = arg;
- mtx_lock(&u->mutex);
- isr1 = read_reg(u, ISR1);
- isr2 = read_reg(u, ISR2);
- if (isr1 & 1) {
- i = read_reg(u, DIR);
- 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)
- write_reg(u, IMR1, 0);
- wakeup(u->buf);
- } else {
- printf("upd7210intr [%02x %02x %02x",
- read_reg(u, DIR), isr1, isr2);
- printf(" %02x %02x %02x %02x %02x]\n",
- read_reg(u, SPSR),
- read_reg(u, ADSR),
- read_reg(u, CPTR),
- read_reg(u, ADR0),
- read_reg(u, ADR1));
- }
- mtx_unlock(&u->mutex);
-}
-
-static int
-gpib_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
-{
- struct upd7210 *u;
-
- u = dev->si_drv1;
-
- mtx_lock(&u->mutex);
- if (u->busy)
- return (EBUSY);
- u->busy = 1;
- mtx_unlock(&u->mutex);
-
- u->buf = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK);
- u->bufsize = PAGE_SIZE;
- u->buf_wp = 0;
- u->buf_rp = 0;
-
- write_reg(u, AUXMR, AUXMR_CRST);
- DELAY(10000);
- write_reg(u, AUXMR, AUXMR_ICTR | 8);
- DELAY(1000);
- write_reg(u, ADR, 0x60);
- write_reg(u, ADR, 0xe0);
- write_reg(u, ADMR, 0x70);
- write_reg(u, AUXMR, AUXMR_PON);
- write_reg(u, IMR1, 0x01);
- return (0);
-}
-
-static int
-gpib_close(struct cdev *dev, int oflags, int devtype, struct thread *td)
-{
- struct upd7210 *u;
-
- u = dev->si_drv1;
-
- mtx_lock(&u->mutex);
- u->busy = 0;
- write_reg(u, AUXMR, AUXMR_CRST);
- DELAY(10000);
- write_reg(u, IMR1, 0x00);
- write_reg(u, IMR2, 0x00);
- free(u->buf, M_DEVBUF);
- u->buf = NULL;
- mtx_unlock(&u->mutex);
- return (0);
-}
-
-static int
-gpib_read(struct cdev *dev, struct uio *uio, int ioflag)
-{
- struct upd7210 *u;
- int error;
- size_t z;
-
- u = dev->si_drv1;
- error = 0;
-
- mtx_lock(&u->mutex);
- while (u->buf_wp == u->buf_rp) {
- error = msleep(u->buf, &u->mutex, PZERO | PCATCH,
- "gpibrd", hz);
- if (error && error != EWOULDBLOCK) {
- mtx_unlock(&u->mutex);
- return (error);
- }
- }
- while (uio->uio_resid > 0 && u->buf_wp != u->buf_rp) {
- if (u->buf_wp < u->buf_rp)
- z = u->bufsize - u->buf_rp;
- else
- z = u->buf_wp - u->buf_rp;
- if (z > uio->uio_resid)
- z = uio->uio_resid;
- mtx_unlock(&u->mutex);
- error = uiomove(u->buf + u->buf_rp, z, uio);
- mtx_lock(&u->mutex);
- if (error)
- break;
- u->buf_rp += z;
- u->buf_rp &= (u->bufsize - 1);
- }
- if (u->wreg[IMR1] == 0)
- write_reg(u, IMR1, 0x01);
- mtx_unlock(&u->mutex);
- return (error);
-}
-
-
-
-struct cdevsw gpib_cdevsw = {
- .d_version = D_VERSION,
- .d_name = "gpib",
- .d_open = gpib_open,
- .d_close = gpib_close,
- .d_read = gpib_read,
-};
-
-static void
-upd7210attach(struct upd7210 *u)
-{
- int unit = 0;
-
- mtx_init(&u->mutex, "gpib", NULL, MTX_DEF);
- u->cdev = make_dev(&gpib_cdevsw, unit,
- UID_ROOT, GID_WHEEL, 0444,
- "gpib%ul", unit);
- u->cdev->si_drv1 = u;
-}
diff --git a/sys/dev/ieee488/ugpib.h b/sys/dev/ieee488/ugpib.h
new file mode 100644
index 0000000..77b7fcd
--- /dev/null
+++ b/sys/dev/ieee488/ugpib.h
@@ -0,0 +1,152 @@
+/*-
+ * Copyright (c) 2005 Poul-Henning Kamp <phk@FreeBSD.org>
+ * 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$
+ *
+ */
+
+#ifndef _DEV_IEEE488_UGPIB_H_
+#define _DEV_IEEE488_UGPIB_H_
+
+/* ibfoo() return values */
+#define EDVR 0 /* System error */
+#define ECIC 1 /* Not Active Controller */
+#define ENOL 2 /* Nobody listening */
+#define EADR 3 /* Controller not addressed */
+#define EARG 4 /* Invalid argument */
+#define ESAC 5 /* Not System Controller */
+#define EABO 6 /* I/O Aborted/Time out */
+#define ENEB 7 /* No such controller */
+#define EOIP 10 /* Async I/O in progress */
+#define ECAP 11 /* No such capability */
+#define EFSO 12 /* File system error */
+#define EBUS 14 /* Command byte xfer error */
+#define ESTB 15 /* Serial poll status byte lost */
+#define ESRQ 16 /* SRQ line stuck */
+#define ETAB 20 /* Table problem */
+
+/* ibsta bits */
+#define ERR (1<<15) /* Error */
+#define TIMO (1<<14) /* Timeout */
+#define END (1<<13) /* EOI/EOS */
+#define SRQI (1<<12) /* SRQ */
+#define RQS (1<<11) /* Device requests service */
+#define SPOLL (1<<10) /* Serial Poll */
+#define EVENT (1<<9) /* Event occured */
+#define CMPL (1<<8) /* I/O complete */
+#define LOK (1<<7) /* Lockout */
+#define REM (1<<6) /* Remote */
+#define CIC (1<<5) /* CIC */
+#define ATN (1<<4) /* ATN */
+#define TACS (1<<3) /* Talker */
+#define LACS (1<<2) /* Listener */
+#define DTAS (1<<1) /* Device trigger status */
+#define DCAS (1<<0) /* Device clear state */
+
+/* Timeouts */
+#define TNONE 0
+#define T10us 1
+#define T30us 2
+#define T100us 3
+#define T300us 4
+#define T1ms 5
+#define T3ms 6
+#define T10ms 7
+#define T30ms 8
+#define T100ms 9
+#define T300ms 10
+#define T1s 11
+#define T3s 12
+#define T10s 13
+#define T30s 14
+#define T100s 15
+#define T300s 16
+#define T1000s 17
+
+/* EOS bits */
+#define REOS (1 << 10)
+#define XEOS (1 << 11)
+#define BIN (1 << 12)
+
+/* Bus commands */
+#define LAD 0x20 /* Listen address */
+#define UNL 0x3F /* Unlisten */
+#define TAD 0x40 /* Talk address */
+#define UNT 0x5F /* Untalk */
+
+#ifndef _KERNEL
+
+extern int ibcnt, iberr;
+
+int ibask(int handle, int option, int *retval);
+int ibbna(int handle, char *bdname);
+int ibcac(int handle, int v);
+int ibclr(int handle);
+int ibcmd(int handle, void *buffer, long cnt);
+int ibcmda(int handle, void *buffer, long cnt);
+int ibconfig(int handle, int option, int value);
+int ibdev(int boardID, int pad, int sad, int tmo, int eot, int eos);
+int ibdiag(int handle, void *buffer, long cnt);
+int ibdma(int handle, int v);
+int ibeos(int handle, int eos);
+int ibeot(int handle, int v);
+int ibevent(int handle, short *event);
+int ibfind(char *bdname);
+int ibgts(int handle, int v);
+int ibist(int handle, int v);
+int iblines(int handle, short *lines);
+int ibllo(int handle);
+int ibln(int handle, int padval, int sadval, short *listenflag);
+int ibloc(int handle);
+int ibonl(int handle, int v);
+int ibpad(int handle, int v);
+int ibpct(int handle);
+int ibpoke(int handle, int option, int value);
+int ibppc(int handle, int v);
+int ibrd(int handle, void *buffer, long cnt);
+int ibrda(int handle, void *buffer, long cnt);
+int ibrdf(int handle, char *flname);
+int ibrdkey(int handle, void *buffer, int cnt);
+int ibrpp(int handle, char *ppr);
+int ibrsc(int handle, int v);
+int ibrsp(int handle, char *spr);
+int ibrsv(int handle, int v);
+int ibsad(int handle, int v);
+int ibsgnl(int handle, int v);
+int ibsic(int handle);
+int ibsre(int handle, int v);
+int ibsrq(void (*func)(void));
+int ibstop(int handle);
+int ibtmo(int handle, int tmo);
+int ibtrap(int mask, int mode);
+int ibtrg(int handle);
+int ibwait(int handle, int mask);
+int ibwrt(int handle, void *buffer, long cnt);
+int ibwrta(int handle, void *buffer, long cnt);
+int ibwrtf(int handle, char *flname);
+int ibwrtkey(int handle, void *buffer, int cnt);
+int ibxtrc(int handle, void *buffer, long cnt);
+#endif /* _KERNEL */
+#endif /* _DEV_IEEE488_UGPIB_H_ */
diff --git a/sys/dev/ieee488/upd7210.c b/sys/dev/ieee488/upd7210.c
new file mode 100644
index 0000000..4a1c8524
--- /dev/null
+++ b/sys/dev/ieee488/upd7210.c
@@ -0,0 +1,1026 @@
+/*-
+ * Copyright (c) 2005 Poul-Henning Kamp <phk@FreeBSD.org>
+ * 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.
+ *
+ * High-level driver for µPD7210 based GPIB cards.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+# define GPIB_DEBUG
+# undef GPIB_DEBUG
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/limits.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <isa/isavar.h>
+
+#include <dev/ieee488/upd7210.h>
+#include <dev/ieee488/ugpib.h>
+
+MALLOC_DEFINE(M_GPIB, "GPIB", "GPIB");
+
+/* upd7210 generic stuff */
+
+static void
+print_isr(u_int isr1, u_int isr2)
+{
+ printf("isr1=0x%b isr2=0x%b",
+ isr1, "\20\10CPT\7APT\6DET\5ENDRX\4DEC\3ERR\2DO\1DI",
+ isr2, "\20\10INT\7SRQI\6LOK\5REM\4CO\3LOKC\2REMC\1ADSC");
+}
+
+static u_int
+read_reg(struct upd7210 *u, enum upd7210_rreg reg)
+{
+ u_int r;
+
+ r = bus_space_read_1(
+ u->reg_tag[reg],
+ u->reg_handle[reg],
+ u->reg_offset[reg]);
+ u->rreg[reg] = r;
+ return (r);
+}
+
+static void
+write_reg(struct upd7210 *u, enum upd7210_wreg reg, u_int val)
+{
+ bus_space_write_1(
+ u->reg_tag[reg],
+ u->reg_handle[reg],
+ u->reg_offset[reg], val);
+ u->wreg[reg] = val;
+ if (reg == AUXMR)
+ u->wreg[8 + (val >> 5)] = val & 0x1f;
+}
+
+void
+upd7210intr(void *arg)
+{
+ u_int isr1, isr2;
+ struct upd7210 *u;
+
+ u = arg;
+ mtx_lock(&u->mutex);
+ isr1 = read_reg(u, ISR1);
+ isr2 = read_reg(u, ISR2);
+ if (u->busy == 0 || u->irq == NULL || !u->irq(u)) {
+ printf("upd7210intr [%02x %02x %02x",
+ read_reg(u, DIR), isr1, isr2);
+ printf(" %02x %02x %02x %02x %02x] ",
+ read_reg(u, SPSR),
+ read_reg(u, ADSR),
+ read_reg(u, CPTR),
+ read_reg(u, ADR0),
+ read_reg(u, ADR1));
+ print_isr(isr1, isr2);
+ printf("\n");
+ write_reg(u, IMR1, 0);
+ write_reg(u, IMR2, 0);
+ }
+ mtx_unlock(&u->mutex);
+}
+
+static int
+upd7210_take_ctrl_async(struct upd7210 *u)
+{
+ int i;
+
+ write_reg(u, AUXMR, AUXMR_TCA);
+
+ if (!(read_reg(u, ADSR) & ADSR_ATN))
+ return (0);
+ for (i = 0; i < 20; i++) {
+ DELAY(1);
+ if (!(read_reg(u, ADSR) & ADSR_ATN))
+ return (0);
+ }
+ return (1);
+}
+
+static int
+upd7210_goto_standby(struct upd7210 *u)
+{
+ int i;
+
+ write_reg(u, AUXMR, AUXMR_GTS);
+
+ if (read_reg(u, ADSR) & ADSR_ATN)
+ return (0);
+ for (i = 0; i < 20; i++) {
+ DELAY(1);
+ if (read_reg(u, ADSR) & ADSR_ATN)
+ return (0);
+ }
+ return (1);
+}
+
+static int
+deadyet(struct upd7210 *u)
+{
+ struct timeval tv;
+
+ if (!timevalisset(&u->deadline))
+ return (0);
+
+ getmicrouptime(&tv);
+ if (timevalcmp(&u->deadline, &tv, <)) {
+printf("DEADNOW\n");
+ return (1);
+ }
+
+ return (0);
+}
+
+/* Unaddressed Listen Only mode */
+
+static int
+gpib_l_irq(struct upd7210 *u)
+{
+ int i;
+
+ if (u->rreg[ISR1] & 1) {
+ i = read_reg(u, DIR);
+ 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)
+ write_reg(u, IMR1, 0);
+ wakeup(u->buf);
+ return (1);
+ }
+ return (0);
+}
+
+static int
+gpib_l_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
+{
+ struct upd7210 *u;
+
+ u = dev->si_drv1;
+
+ mtx_lock(&u->mutex);
+ if (u->busy)
+ return (EBUSY);
+ u->busy = 1;
+ u->irq = gpib_l_irq;
+ mtx_unlock(&u->mutex);
+
+ u->buf = malloc(PAGE_SIZE, M_GPIB, M_WAITOK);
+ u->bufsize = PAGE_SIZE;
+ u->buf_wp = 0;
+ u->buf_rp = 0;
+
+ write_reg(u, AUXMR, AUXMR_CRST);
+ DELAY(10000);
+ write_reg(u, AUXMR, C_ICR | 8);
+ DELAY(1000);
+ write_reg(u, ADR, 0x60);
+ write_reg(u, ADR, 0xe0);
+ write_reg(u, ADMR, 0x70);
+ write_reg(u, AUXMR, AUXMR_PON);
+ write_reg(u, IMR1, 0x01);
+ return (0);
+}
+
+static int
+gpib_l_close(struct cdev *dev, int oflags, int devtype, struct thread *td)
+{
+ struct upd7210 *u;
+
+ u = dev->si_drv1;
+
+ mtx_lock(&u->mutex);
+ u->busy = 0;
+ write_reg(u, AUXMR, AUXMR_CRST);
+ DELAY(10000);
+ write_reg(u, IMR1, 0x00);
+ write_reg(u, IMR2, 0x00);
+ free(u->buf, M_GPIB);
+ u->buf = NULL;
+ mtx_unlock(&u->mutex);
+ return (0);
+}
+
+static int
+gpib_l_read(struct cdev *dev, struct uio *uio, int ioflag)
+{
+ struct upd7210 *u;
+ int error;
+ size_t z;
+
+ u = dev->si_drv1;
+ error = 0;
+
+ mtx_lock(&u->mutex);
+ while (u->buf_wp == u->buf_rp) {
+ error = msleep(u->buf, &u->mutex, PZERO | PCATCH,
+ "gpibrd", hz);
+ if (error && error != EWOULDBLOCK) {
+ mtx_unlock(&u->mutex);
+ return (error);
+ }
+ }
+ while (uio->uio_resid > 0 && u->buf_wp != u->buf_rp) {
+ if (u->buf_wp < u->buf_rp)
+ z = u->bufsize - u->buf_rp;
+ else
+ z = u->buf_wp - u->buf_rp;
+ if (z > uio->uio_resid)
+ z = uio->uio_resid;
+ mtx_unlock(&u->mutex);
+ error = uiomove(u->buf + u->buf_rp, z, uio);
+ mtx_lock(&u->mutex);
+ if (error)
+ break;
+ u->buf_rp += z;
+ u->buf_rp &= (u->bufsize - 1);
+ }
+ if (u->wreg[IMR1] == 0)
+ write_reg(u, IMR1, 0x01);
+ mtx_unlock(&u->mutex);
+ return (error);
+}
+
+struct cdevsw gpib_l_cdevsw = {
+ .d_version = D_VERSION,
+ .d_name = "gpib_l",
+ .d_open = gpib_l_open,
+ .d_close = gpib_l_close,
+ .d_read = gpib_l_read,
+};
+
+/* ibfoo API */
+
+#include <dev/ieee488/ibfoo_int.h>
+
+struct handle {
+ LIST_ENTRY(handle) list;
+ int handle;
+ int pad;
+ int sad;
+ struct timeval timeout;
+ int eot;
+ int eos;
+};
+
+struct ibfoo {
+ struct upd7210 *upd7210;
+ LIST_HEAD(,handle) handles;
+ struct unrhdr *unrhdr;
+
+ u_char *cmdbuf;
+ u_int cmdlen;
+
+ struct handle *rdh; /* addressed for read */
+ struct handle *wrh; /* addressed for write */
+
+ u_char *dobuf;
+ u_int dolen;
+ int doeoi;
+};
+
+static struct timeval timeouts[] = {
+ [TNONE] = { 0, 0},
+ [T10us] = { 0, 10},
+ [T30us] = { 0, 30},
+ [T100us] = { 0, 100},
+ [T300us] = { 0, 300},
+ [T1ms] = { 0, 1000},
+ [T3ms] = { 0, 3000},
+ [T10ms] = { 0, 10000},
+ [T30ms] = { 0, 30000},
+ [T100ms] = { 0, 100000},
+ [T300ms] = { 0, 300000},
+ [T1s] = { 1, 0},
+ [T3s] = { 3, 0},
+ [T10s] = { 10, 0},
+ [T30s] = { 30, 0},
+ [T100s] = { 100, 0},
+ [T300s] = { 300, 0},
+ [T1000s] = { 1000, 0}
+};
+
+static u_int max_timeouts = sizeof timeouts / sizeof timeouts[0];
+
+typedef int ibhandler_t(struct upd7210 *u, struct ibfoo_iocarg *ap);
+
+static int
+gpib_ib_irq(struct upd7210 *u)
+{
+ struct ibfoo *ib;
+
+ ib = u->ibfoo;
+
+ if ((u->rreg[ISR2] & IXR2_CO) && ib->cmdlen > 0) {
+ write_reg(u, CDOR, *ib->cmdbuf);
+ ib->cmdbuf++;
+ ib->cmdlen--;
+ if (ib->cmdlen == 0) {
+ wakeup(ib);
+ write_reg(u, IMR2, 0);
+ }
+ return (1);
+ }
+ if ((u->rreg[ISR1] & IXR1_DO) && ib->dolen > 0) {
+ if (ib->dolen == 1 && ib->doeoi)
+ write_reg(u, AUXMR, AUXMR_SEOI);
+ write_reg(u, CDOR, *ib->dobuf);
+ ib->dobuf++;
+ ib->dolen--;
+ if (ib->dolen == 0) {
+ wakeup(ib);
+ write_reg(u, IMR1, 0);
+ }
+ return (1);
+ }
+ if (u->rreg[ISR1] & IXR1_ENDRX) {
+ write_reg(u, IMR1, 0);
+ wakeup(ib);
+ return (1);
+ }
+
+ return (0);
+}
+
+static void
+config_eos(struct upd7210 *u, struct handle *h)
+{
+ int i;
+
+ i = 0;
+ if (h->eos & 0x0400) {
+ write_reg(u, EOSR, h->eos & 0xff);
+ i |= AUXA_REOS;
+ }
+ if (h->eos & 0x1000)
+ i |= AUXA_BIN;
+ write_reg(u, AUXRA, C_AUXA | i);
+}
+
+/*
+ * Look up the handle, and set the deadline if the handle has a timeout.
+ */
+static int
+gethandle(struct upd7210 *u, struct ibfoo_iocarg *ap, struct handle **hp)
+{
+ struct ibfoo *ib;
+ struct handle *h;
+
+ KASSERT(ap->__field & __F_HANDLE, ("gethandle without __F_HANDLE"));
+ ib = u->ibfoo;
+ LIST_FOREACH(h, &ib->handles, list) {
+ if (h->handle == ap->handle) {
+ *hp = h;
+ if (timevalisset(&h->timeout)) {
+ getmicrouptime(&u->deadline);
+ timevaladd(&u->deadline, &h->timeout);
+ } else {
+ timevalclear(&u->deadline);
+ }
+ return (0);
+ }
+ }
+ ap->__iberr = EARG;
+ return (1);
+}
+
+static int
+do_cmd(struct upd7210 *u, u_char *cmd, int len)
+{
+ int i, i1, i2;
+ struct ibfoo *ib;
+
+ ib = u->ibfoo;
+
+ if (ib->rdh != NULL || ib->wrh != NULL) {
+ upd7210_take_ctrl_async(u);
+ ib->rdh = NULL;
+ ib->wrh = NULL;
+ }
+ mtx_lock(&u->mutex);
+ ib->cmdbuf = cmd;
+ ib->cmdlen = len;
+
+ if (!(u->rreg[ISR2] & IXR2_CO)) {
+ i1 = read_reg(u, ISR1);
+ i2 = read_reg(u, ISR2);
+#ifdef GPIB_DEBUG
+ print_isr(i1, i2);
+ printf("\n");
+#endif
+ }
+ write_reg(u, IMR2, IXR2_CO);
+ if (u->rreg[ISR2] & IXR2_CO) {
+ write_reg(u, CDOR, *ib->cmdbuf);
+ ib->cmdbuf++;
+ ib->cmdlen--;
+ }
+
+ while (1) {
+ i = msleep(ib, &u->mutex, PZERO | PCATCH, "gpib_cmd", hz/10);
+ if (i == EINTR)
+ break;
+ if (u->rreg[ISR1] & IXR1_ERR)
+ break;
+ if (!ib->cmdlen)
+ break;
+ if (deadyet(u))
+ break;
+ }
+ write_reg(u, IMR2, 0);
+ mtx_unlock(&u->mutex);
+ return (0);
+}
+
+static int
+do_odata(struct upd7210 *u, u_char *data, int len, int eos)
+{
+ int i1, i2, i;
+ struct ibfoo *ib;
+
+ ib = u->ibfoo;
+
+ mtx_lock(&u->mutex);
+ ib->dobuf = data;
+ ib->dolen = len;
+ ib->doeoi = 1;
+
+ if (!(u->rreg[ISR1] & IXR1_DO)) {
+ i1 = read_reg(u, ISR1);
+ i2 = read_reg(u, ISR2);
+#ifdef GPIB_DEBUG
+ print_isr(i1, i2);
+ printf("\n");
+#endif
+ }
+ write_reg(u, IMR1, IXR1_DO);
+ if (u->rreg[ISR1] & IXR1_DO) {
+ write_reg(u, CDOR, *ib->dobuf);
+ ib->dobuf++;
+ ib->dolen--;
+ }
+ while (1) {
+ i = msleep(ib, &u->mutex, PZERO | PCATCH, "gpib_out", hz/100);
+ if (i == EINTR)
+ break;
+ if (u->rreg[ISR1] & IXR1_ERR)
+ break;
+ if (!ib->dolen)
+ break;
+ if (deadyet(u))
+ break;
+ }
+ write_reg(u, IMR2, 0);
+ mtx_unlock(&u->mutex);
+ return (len - ib->dolen);
+}
+
+static int
+do_idata(struct upd7210 *u, u_char *data, int len, int eos)
+{
+ int i1, i2, i, j;
+
+ write_reg(u, IMR1, IXR1_ENDRX);
+ mtx_lock(&Giant);
+ isa_dmastart(ISADMA_READ, data, len, u->dmachan);
+ mtx_unlock(&Giant);
+ mtx_lock(&u->mutex);
+ write_reg(u, IMR2, IMR2_DMAI);
+ while (1) {
+ i = msleep(u->ibfoo, &u->mutex, PZERO | PCATCH,
+ "gpib_idata", hz/100);
+ if (i == EINTR)
+ break;
+ if (isa_dmatc(u->dmachan))
+ break;
+ if (i == EWOULDBLOCK) {
+ i1 = read_reg(u, ISR1);
+ i2 = read_reg(u, ISR2);
+ } else {
+ i1 = u->rreg[ISR1];
+ i2 = u->rreg[ISR2];
+ }
+ if (i1 & IXR1_ENDRX)
+ break;
+ if (deadyet(u))
+ break;
+ }
+ write_reg(u, IMR1, 0);
+ write_reg(u, IMR2, 0);
+ mtx_unlock(&u->mutex);
+ mtx_lock(&Giant);
+ j = isa_dmastatus(u->dmachan);
+ isa_dmadone(ISADMA_READ, data, len, u->dmachan);
+ mtx_unlock(&Giant);
+ if (deadyet(u)) {
+ return (-1);
+ } else {
+ return (len - j);
+ }
+}
+
+#define ibask NULL
+#define ibbna NULL
+#define ibcac NULL
+#define ibclr NULL
+#define ibcmd NULL
+#define ibcmda NULL
+#define ibconfig NULL
+
+static int
+ibdev(struct upd7210 *u, struct ibfoo_iocarg *ap)
+{
+ struct handle *h;
+ struct ibfoo *ib;
+
+ if (ap->pad < 0 ||
+ ap->pad > 30 ||
+ (ap->sad != 0 && ap->sad < 0x60) ||
+ ap->sad > 126) {
+ ap->__retval = -1;
+ ap->__iberr = EARG;
+ return (0);
+ }
+
+ ib = u->ibfoo;
+ h = malloc(sizeof *h, M_GPIB, M_ZERO | M_WAITOK);
+ h->handle = alloc_unr(ib->unrhdr);
+ LIST_INSERT_HEAD(&ib->handles, h, list);
+ h->pad = ap->pad;
+ h->sad = ap->sad;
+ h->timeout = timeouts[ap->tmo];
+ h->eot = ap->eot;
+ h->eos = ap->eos;
+ ap->__retval = h->handle;
+ return (0);
+}
+
+#define ibdiag NULL
+#define ibdma NULL
+
+static int
+ibeos(struct upd7210 *u, struct ibfoo_iocarg *ap)
+{
+ struct handle *h;
+ struct ibfoo *ib;
+
+ if (gethandle(u, ap, &h))
+ return (0);
+ ib = u->ibfoo;
+ h->eos = ap->eos;
+ if (ib->rdh == h)
+ config_eos(u, h);
+ ap->__retval = 0;
+ return (0);
+}
+
+#define ibeot NULL
+#define ibevent NULL
+#define ibfind NULL
+#define ibgts NULL
+#define ibist NULL
+#define iblines NULL
+#define ibllo NULL
+#define ibln NULL
+#define ibloc NULL
+#define ibonl NULL
+#define ibpad NULL
+#define ibpct NULL
+#define ibpoke NULL
+#define ibppc NULL
+
+static int
+ibrd(struct upd7210 *u, struct ibfoo_iocarg *ap)
+{
+ struct ibfoo *ib;
+ struct handle *h;
+ u_char buf[10], *bp;
+ int i, j, error, bl, bc;
+ u_char *dp;
+
+ ib = u->ibfoo;
+ if (gethandle(u, ap, &h))
+ return (0);
+ bl = ap->cnt;
+ if (bl > PAGE_SIZE)
+ bl = PAGE_SIZE;
+ bp = malloc(bl, M_GPIB, M_WAITOK);
+
+ if (ib->rdh != h) {
+ i = 0;
+ buf[i++] = UNT;
+ buf[i++] = UNL;
+ buf[i++] = LAD | 0;
+ buf[i++] = TAD | h->pad;
+ if (h->sad)
+ buf[i++] = h->sad;
+ i = do_cmd(u, buf, i);
+ config_eos(u, h);
+ ib->rdh = h;
+ ib->wrh = NULL;
+ upd7210_goto_standby(u);
+ }
+ ap->__ibcnt = 0;
+ dp = ap->buffer;
+ bc = ap->cnt;
+ error = 0;
+ while (bc > 0) {
+ j = imin(bc, PAGE_SIZE);
+ i = do_idata(u, bp, j, 1);
+ if (i <= 0)
+ break;
+ error = copyout(bp, dp , i);
+ if (error)
+ break;
+ ap->__ibcnt += i;
+ if (i != j)
+ break;
+ bc -= i;
+ dp += i;
+ }
+ free(bp, M_GPIB);
+ ap->__retval = 0;
+ return (error);
+}
+
+#define ibrda NULL
+#define ibrdf NULL
+#define ibrdkey NULL
+#define ibrpp NULL
+#define ibrsc NULL
+#define ibrsp NULL
+#define ibrsv NULL
+#define ibsad NULL
+#define ibsgnl NULL
+#define ibsic NULL
+#define ibsre NULL
+#define ibsrq NULL
+#define ibstop NULL
+
+static int
+ibtmo(struct upd7210 *u, struct ibfoo_iocarg *ap)
+{
+ struct handle *h;
+
+ if (gethandle(u, ap, &h))
+ return (0);
+ h->timeout = timeouts[ap->tmo];
+ return (0);
+}
+
+#define ibtrap NULL
+#define ibtrg NULL
+#define ibwait NULL
+
+static int
+ibwrt(struct upd7210 *u, struct ibfoo_iocarg *ap)
+{
+ struct ibfoo *ib;
+ struct handle *h;
+ u_char buf[10], *bp;
+ int i;
+
+ ib = u->ibfoo;
+ if (gethandle(u, ap, &h))
+ return (0);
+ bp = malloc(ap->cnt, M_GPIB, M_WAITOK);
+ i = copyin(ap->buffer, bp, ap->cnt);
+ if (i) {
+ free(bp, M_GPIB);
+ return (i);
+ }
+ if (ib->wrh != h) {
+ i = 0;
+ buf[i++] = UNT;
+ buf[i++] = UNL;
+ buf[i++] = LAD | h->pad;
+ if (h->sad)
+ buf[i++] = LAD | TAD | h->sad;
+ buf[i++] = TAD | 0;
+ i = do_cmd(u, buf, i);
+ ib->rdh = NULL;
+ ib->wrh = h;
+ upd7210_goto_standby(u);
+ }
+ i = do_odata(u, bp, ap->cnt, 1);
+ ap->__ibcnt = i;
+ ap->__retval = 0;
+ free(bp, M_GPIB);
+ return (0);
+}
+
+#define ibwrta NULL
+#define ibwrtf NULL
+#define ibwrtkey NULL
+#define ibxtrc NULL
+
+static struct ibhandler {
+ const char *name;
+ ibhandler_t *func;
+ u_int args;
+} ibhandlers[] = {
+ [__ID_IBASK] = { "ibask", ibask, __F_HANDLE | __F_OPTION | __F_RETVAL },
+ [__ID_IBBNA] = { "ibbna", ibbna, __F_HANDLE | __F_BDNAME },
+ [__ID_IBCAC] = { "ibcac", ibcac, __F_HANDLE | __F_V },
+ [__ID_IBCLR] = { "ibclr", ibclr, __F_HANDLE },
+ [__ID_IBCMDA] = { "ibcmda", ibcmda, __F_HANDLE | __F_BUFFER | __F_CNT },
+ [__ID_IBCMD] = { "ibcmd", ibcmd, __F_HANDLE | __F_BUFFER | __F_CNT },
+ [__ID_IBCONFIG] = { "ibconfig", ibconfig, __F_HANDLE | __F_OPTION | __F_VALUE },
+ [__ID_IBDEV] = { "ibdev", ibdev, __F_BOARDID | __F_PAD | __F_SAD | __F_TMO | __F_EOT | __F_EOS },
+ [__ID_IBDIAG] = { "ibdiag", ibdiag, __F_HANDLE | __F_BUFFER | __F_CNT },
+ [__ID_IBDMA] = { "ibdma", ibdma, __F_HANDLE | __F_V },
+ [__ID_IBEOS] = { "ibeos", ibeos, __F_HANDLE | __F_EOS },
+ [__ID_IBEOT] = { "ibeot", ibeot, __F_HANDLE | __F_V },
+ [__ID_IBEVENT] = { "ibevent", ibevent, __F_HANDLE | __F_EVENT },
+ [__ID_IBFIND] = { "ibfind", ibfind, __F_BDNAME },
+ [__ID_IBGTS] = { "ibgts", ibgts, __F_HANDLE | __F_V },
+ [__ID_IBIST] = { "ibist", ibist, __F_HANDLE | __F_V },
+ [__ID_IBLINES] = { "iblines", iblines, __F_HANDLE | __F_LINES },
+ [__ID_IBLLO] = { "ibllo", ibllo, __F_HANDLE },
+ [__ID_IBLN] = { "ibln", ibln, __F_HANDLE | __F_PADVAL | __F_SADVAL | __F_LISTENFLAG },
+ [__ID_IBLOC] = { "ibloc", ibloc, __F_HANDLE },
+ [__ID_IBONL] = { "ibonl", ibonl, __F_HANDLE | __F_V },
+ [__ID_IBPAD] = { "ibpad", ibpad, __F_HANDLE | __F_V },
+ [__ID_IBPCT] = { "ibpct", ibpct, __F_HANDLE },
+ [__ID_IBPOKE] = { "ibpoke", ibpoke, __F_HANDLE | __F_OPTION | __F_VALUE },
+ [__ID_IBPPC] = { "ibppc", ibppc, __F_HANDLE | __F_V },
+ [__ID_IBRDA] = { "ibrda", ibrda, __F_HANDLE | __F_BUFFER | __F_CNT },
+ [__ID_IBRDF] = { "ibrdf", ibrdf, __F_HANDLE | __F_FLNAME },
+ [__ID_IBRDKEY] = { "ibrdkey", ibrdkey, __F_HANDLE | __F_BUFFER | __F_CNT },
+ [__ID_IBRD] = { "ibrd", ibrd, __F_HANDLE | __F_BUFFER | __F_CNT },
+ [__ID_IBRPP] = { "ibrpp", ibrpp, __F_HANDLE | __F_PPR },
+ [__ID_IBRSC] = { "ibrsc", ibrsc, __F_HANDLE | __F_V },
+ [__ID_IBRSP] = { "ibrsp", ibrsp, __F_HANDLE | __F_SPR },
+ [__ID_IBRSV] = { "ibrsv", ibrsv, __F_HANDLE | __F_V },
+ [__ID_IBSAD] = { "ibsad", ibsad, __F_HANDLE | __F_V },
+ [__ID_IBSGNL] = { "ibsgnl", ibsgnl, __F_HANDLE | __F_V },
+ [__ID_IBSIC] = { "ibsic", ibsic, __F_HANDLE },
+ [__ID_IBSRE] = { "ibsre", ibsre, __F_HANDLE | __F_V },
+ [__ID_IBSRQ] = { "ibsrq", ibsrq, __F_FUNC },
+ [__ID_IBSTOP] = { "ibstop", ibstop, __F_HANDLE },
+ [__ID_IBTMO] = { "ibtmo", ibtmo, __F_HANDLE | __F_TMO },
+ [__ID_IBTRAP] = { "ibtrap", ibtrap, __F_MASK | __F_MODE },
+ [__ID_IBTRG] = { "ibtrg", ibtrg, __F_HANDLE },
+ [__ID_IBWAIT] = { "ibwait", ibwait, __F_HANDLE | __F_MASK },
+ [__ID_IBWRTA] = { "ibwrta", ibwrta, __F_HANDLE | __F_BUFFER | __F_CNT },
+ [__ID_IBWRTF] = { "ibwrtf", ibwrtf, __F_HANDLE | __F_FLNAME },
+ [__ID_IBWRTKEY] = { "ibwrtkey", ibwrtkey, __F_HANDLE | __F_BUFFER | __F_CNT },
+ [__ID_IBWRT] = { "ibwrt", ibwrt, __F_HANDLE | __F_BUFFER | __F_CNT },
+ [__ID_IBXTRC] = { "ibxtrc", ibxtrc, __F_HANDLE | __F_BUFFER | __F_CNT },
+};
+
+static u_int max_ibhandler = sizeof ibhandlers / sizeof ibhandlers[0];
+
+static int
+gpib_ib_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
+{
+ struct upd7210 *u;
+ struct ibfoo *ib;
+ int error;
+
+ u = dev->si_drv1;
+
+ mtx_lock(&u->mutex);
+ if (u->busy) {
+ mtx_unlock(&u->mutex);
+ return (EBUSY);
+ }
+ u->busy = 1;
+ mtx_unlock(&u->mutex);
+
+ mtx_lock(&Giant);
+ error = isa_dma_acquire(u->dmachan);
+ if (!error) {
+ error = isa_dma_init(u->dmachan, PAGE_SIZE, M_WAITOK);
+ if (error)
+ isa_dma_release(u->dmachan);
+ }
+ mtx_unlock(&Giant);
+ if (error) {
+ mtx_lock(&u->mutex);
+ u->busy = 0;
+ mtx_unlock(&u->mutex);
+ return (error);
+ }
+
+ ib = malloc(sizeof *ib, M_GPIB, M_WAITOK | M_ZERO);
+ LIST_INIT(&ib->handles);
+ ib->unrhdr = new_unrhdr(0, INT_MAX);
+ dev->si_drv2 = ib;
+ ib->upd7210 = u;
+ u->ibfoo = ib;
+ u->irq = gpib_ib_irq;
+
+ write_reg(u, AUXMR, AUXMR_CRST);
+ DELAY(10000);
+ DELAY(1000);
+ write_reg(u, IMR1, 0x00);
+ write_reg(u, IMR2, 0x00);
+ write_reg(u, SPMR, 0x00);
+ write_reg(u, ADR, 0x00);
+ write_reg(u, ADR, ADR_ARS | ADR_DL | ADR_DT);
+ write_reg(u, ADMR, ADMR_ADM0 | ADMR_TRM0 | ADMR_TRM1);
+ write_reg(u, EOSR, 0x00);
+ write_reg(u, AUXMR, C_ICR | 8);
+ write_reg(u, AUXMR, C_PPR | PPR_U);
+ write_reg(u, AUXMR, C_AUXA);
+ write_reg(u, AUXMR, C_AUXB + 3);
+ write_reg(u, AUXMR, C_AUXE + 0);
+ write_reg(u, AUXMR, AUXMR_PON);
+ write_reg(u, AUXMR, AUXMR_CIFC);
+ DELAY(100);
+ write_reg(u, AUXMR, AUXMR_SIFC);
+ write_reg(u, AUXMR, AUXMR_SREN);
+ return (0);
+}
+
+static int
+gpib_ib_close(struct cdev *dev, int oflags, int devtype, struct thread *td)
+{
+ struct upd7210 *u;
+ struct ibfoo *ib;
+
+ u = dev->si_drv1;
+ ib = dev->si_drv2;
+ /* XXX: assert pointer consistency */
+
+ u->ibfoo = NULL;
+ /* XXX: free handles */
+ dev->si_drv2 = NULL;
+ free(ib, M_GPIB);
+
+ mtx_lock(&Giant);
+ isa_dma_release(u->dmachan);
+ mtx_unlock(&Giant);
+ mtx_lock(&u->mutex);
+ u->busy = 0;
+ write_reg(u, IMR1, 0x00);
+ write_reg(u, IMR2, 0x00);
+ write_reg(u, AUXMR, AUXMR_CRST);
+ DELAY(10000);
+ mtx_unlock(&u->mutex);
+ return (0);
+}
+
+static int
+gpib_ib_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
+{
+ struct ibfoo_iocarg *ap;
+ struct ibhandler *ih;
+ struct upd7210 *u;
+ int error;
+
+ u = dev->si_drv1;
+
+ if (cmd != GPIB_IBFOO)
+ return (ENOIOCTL);
+
+ ap = (void *)data;
+ if (ap->__ident < 0 || ap->__ident >= max_ibhandler)
+ return (EINVAL);
+ ih = &ibhandlers[ap->__ident];
+ if (ap->__field != ih->args)
+ return (EINVAL);
+
+ if (ap->__field & __F_TMO) {
+ if (ap->tmo < 0 || ap->tmo >= max_timeouts) {
+ ap->__retval = -1;
+ ap->__iberr = EARG;
+ return (0);
+ }
+ }
+
+ if (ap->__field & __F_EOS) {
+ if (ap->eos & ~(REOS | XEOS | BIN | 0xff)) {
+ ap->__retval = -1;
+ ap->__iberr = EARG;
+ return (0);
+ }
+ if (ap->eos & (REOS | XEOS)) {
+ if ((ap->eos & (BIN | 0x80)) == 0x80) {
+ ap->__retval = -1;
+ ap->__iberr = EARG;
+ return (0);
+ }
+ } else if (ap->eos != 0) {
+ ap->__retval = -1;
+ ap->__iberr = EARG;
+ return (0);
+ }
+ }
+
+ mtx_lock(&u->mutex);
+ while(u->busy != 1) {
+ error = msleep(u->ibfoo, &u->mutex, PZERO | PCATCH,
+ "gpib_ibioctl", 0);
+ if (error) {
+ mtx_unlock(&u->mutex);
+ return (EINTR);
+ }
+ }
+ u->busy = 2;
+ mtx_unlock(&u->mutex);
+
+#ifdef GPIB_DEBUG
+ if (ih->name != NULL)
+ printf("%s(", ih->name);
+ else
+ printf("ibinvalid(");
+ printf("[0x%x]", ap->__field);
+ if (ap->__field & __F_HANDLE) printf(" handle=%d", ap->handle);
+ if (ap->__field & __F_EOS) printf(" eos=%d", ap->eos);
+ if (ap->__field & __F_EOT) printf(" eot=%d", ap->eot);
+ if (ap->__field & __F_TMO) printf(" tmo=%d", ap->tmo);
+ if (ap->__field & __F_PAD) printf(" pad=%d", ap->pad);
+ if (ap->__field & __F_SAD) printf(" sad=%d", ap->sad);
+ if (ap->__field & __F_BUFFER) printf(" buffer=%p", ap->buffer);
+ if (ap->__field & __F_CNT) printf(" cnt=%ld", ap->cnt);
+ /* XXX more ... */
+ printf(")\n");
+#endif
+
+ ap->__iberr = 0;
+ error = EOPNOTSUPP;
+ if (ih->func != NULL)
+ error = ih->func(u, ap);
+ if (error) {
+ ap->__retval = EDVR;
+ ap->__iberr = EDVR;
+ ap->__ibcnt = error;
+ } else if (ap->__iberr) {
+ ap->__retval = -1;
+ }
+#ifdef GPIB_DEBUG
+ printf("%s(...) = %d (error=%d)\n", ih->name, ap->__retval, error);
+#endif
+ mtx_lock(&u->mutex);
+ u->busy = 1;
+ wakeup(u->ibfoo);
+ mtx_unlock(&u->mutex);
+ return (error);
+}
+
+struct cdevsw gpib_ib_cdevsw = {
+ .d_version = D_VERSION,
+ .d_name = "gpib_ib",
+ .d_open = gpib_ib_open,
+ .d_ioctl = gpib_ib_ioctl,
+ .d_close = gpib_ib_close,
+};
+
+/* Housekeeping */
+
+void
+upd7210attach(struct upd7210 *u)
+{
+ int unit = 0;
+ struct cdev *dev;
+
+ mtx_init(&u->mutex, "gpib", NULL, MTX_DEF);
+ u->cdev = make_dev(&gpib_l_cdevsw, unit,
+ UID_ROOT, GID_WHEEL, 0444,
+ "gpib%ul", unit);
+ u->cdev->si_drv1 = u;
+
+ dev = make_dev(&gpib_ib_cdevsw, unit,
+ UID_ROOT, GID_WHEEL, 0444,
+ "gpib%uib", unit);
+ dev->si_drv1 = u;
+ dev_depends(u->cdev, dev);
+}
diff --git a/sys/dev/ieee488/upd7210.h b/sys/dev/ieee488/upd7210.h
new file mode 100644
index 0000000..623fb11
--- /dev/null
+++ b/sys/dev/ieee488/upd7210.h
@@ -0,0 +1,213 @@
+/*-
+ * Copyright (c) 2005 Poul-Henning Kamp <phk@FreeBSD.org>
+ * 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$
+ *
+ * Locating an actual µPD7210 data book has proven quite impossible for me.
+ * There are a fair number of newer chips which are supersets of the µPD7210
+ * but they are particular eager to comprehensively mark what the extensions
+ * are and what is in the base set. Some even give the registers and their
+ * bits new names.
+ *
+ * The following information is based on a description of the µPD7210 found
+ * in an old manual for a VME board which used the chip.
+ */
+
+/* upd7210 interface definitions */
+
+struct upd7210;
+
+struct ibfoo;
+
+void upd7210intr(void *);
+void upd7210attach(struct upd7210 *);
+
+typedef int upd7210_irq_t(struct upd7210 *);
+
+struct upd7210 {
+ bus_space_handle_t reg_handle[8];
+ bus_space_tag_t reg_tag[8];
+ u_int reg_offset[8];
+ u_int dmachan;
+
+ /* private stuff */
+ struct timeval deadline;
+ struct mtx mutex;
+ uint8_t rreg[8];
+ uint8_t wreg[8 + 8];
+
+ upd7210_irq_t *irq;
+
+ int busy;
+ u_char *buf;
+ size_t bufsize;
+ u_int buf_wp;
+ u_int buf_rp;
+ struct cdev *cdev;
+
+ struct ibfoo *ibfoo;
+};
+
+/* upd7210 hardware definitions. */
+
+/* Write registers */
+enum upd7210_wreg {
+ CDOR = 0, /* Command/Data Out Register */
+ IMR1 = 1, /* Interrupt Mask Register 1 */
+ IMR2 = 2, /* Interrupt Mask Register 2 */
+ SPMR = 3, /* Serial Poll Mode Register */
+ ADMR = 4, /* ADdress Mode Register */
+ AUXMR = 5, /* AUXilliary Mode Register */
+ ICR = 5, /* Internal Counter Register */
+ PPR = 5, /* Parallel Poll Register */
+ AUXRA = 5, /* AUXilliary Register A */
+ AUXRB = 5, /* AUXilliary Register B */
+ AUXRE = 5, /* AUXilliary Register E */
+ ADR = 6, /* ADdress Register */
+ EOSR = 7, /* End-Of-String Register */
+};
+
+/* Read registers */
+enum upd7210_rreg {
+ DIR = 0, /* Data In Register */
+ ISR1 = 1, /* Interrupt Status Register 1 */
+ ISR2 = 2, /* Interrupt Status Register 2 */
+ SPSR = 3, /* Serial Poll Status Register */
+ ADSR = 4, /* ADdress Status Register */
+ CPTR = 5, /* Command Pass Though Register */
+ ADR0 = 6, /* ADdress Register 0 */
+ ADR1 = 7, /* ADdress Register 1 */
+};
+
+/* Bits for ISR1 and IMR1 */
+#define IXR1_DI (1 << 0) /* Data In */
+#define IXR1_DO (1 << 1) /* Data Out */
+#define IXR1_ERR (1 << 2) /* Error */
+#define IXR1_DEC (1 << 3) /* Device Clear */
+#define IXR1_ENDRX (1 << 4) /* End Received */
+#define IXR1_DET (1 << 5) /* Device Execute Trigger */
+#define IXR1_APT (1 << 6) /* Address Pass-Through */
+#define IXR1_CPT (1 << 7) /* Command Pass-Through */
+
+/* Bits for ISR2 and IMR2 */
+#define IXR2_ADSC (1 << 0) /* Addressed Status Change */
+#define IXR2_REMC (1 << 1) /* Remote Change */
+#define IXR2_LOKC (1 << 2) /* Lockout Change */
+#define IXR2_CO (1 << 3) /* Command Out */
+#define ISR2_REM (1 << 4) /* Remove */
+#define IMR2_DMAI (1 << 4) /* DMA In Enable */
+#define ISR2_LOK (1 << 5) /* Lockout */
+#define IMR2_DMAO (1 << 5) /* DMA Out Enable */
+#define IXR2_SRQI (1 << 6) /* Service Request Input */
+#define ISR2_INT (1 << 7) /* Interrupt */
+
+#define SPSR_PEND (1 << 6) /* Pending */
+#define SPMR_RSV (1 << 6) /* Request SerVice */
+
+#define ADSR_MJMN (1 << 0) /* MaJor MiNor */
+#define ADSR_TA (1 << 1) /* Talker Active */
+#define ADSR_LA (1 << 2) /* Listener Active */
+#define ADSR_TPAS (1 << 3) /* Talker Primary Addr. State */
+#define ADSR_LPAS (1 << 4) /* Listener Primary Addr. State */
+#define ADSR_SPMS (1 << 5) /* Serial Poll Mode State */
+#define ADSR_ATN (1 << 6) /* Attention */
+#define ADSR_CIC (1 << 7) /* Controller In Charge */
+
+#define ADMR_ADM0 (1 << 0) /* Address Mode 0 */
+#define ADMR_ADM1 (1 << 1) /* Address Mode 1 */
+#define ADMR_TRM0 (1 << 4) /* Transmit/Receive Mode 0 */
+#define ADMR_TRM1 (1 << 5) /* Transmit/Receive Mode 1 */
+#define ADMR_LON (1 << 6) /* Listen Only */
+#define ADMR_TON (1 << 7) /* Talk Only */
+
+/* Constant part of overloaded write registers */
+#define C_ICR 0x20
+#define C_PPR 0x60
+#define C_AUXA 0x80
+#define C_AUXB 0xa0
+#define C_AUXE 0xc0
+
+#define AUXMR_PON 0x00 /* Immediate Execute pon */
+#define AUXMR_CPP 0x01 /* Clear Parallel Poll */
+#define AUXMR_CRST 0x02 /* Chip Reset */
+#define AUXMR_RFD 0x03 /* Finish Handshake */
+#define AUXMR_TRIG 0x04 /* Trigger */
+#define AUXMR_RTL 0x05 /* Return to local */
+#define AUXMR_SEOI 0x06 /* Send EOI */
+#define AUXMR_NVSA 0x07 /* Non-Valid Secondary cmd/addr */
+ /* 0x08 undefined/unknown */
+#define AUXMR_SPP 0x09 /* Set Parallel Poll */
+ /* 0x0a undefined/unknown */
+ /* 0x0b undefined/unknown */
+ /* 0x0c undefined/unknown */
+ /* 0x0d undefined/unknown */
+ /* 0x0e undefined/unknown */
+#define AUXMR_VSA 0x0f /* Valid Secondary cmd/addr */
+#define AUXMR_GTS 0x10 /* Go to Standby */
+#define AUXMR_TCA 0x11 /* Take Control Async (pulsed) */
+#define AUXMR_TCS 0x12 /* Take Control Synchronously */
+#define AUXMR_LISTEN 0x13 /* Listen */
+#define AUXMR_DSC 0x14 /* Disable System Control */
+ /* 0x15 undefined/unknown */
+#define AUXMR_SIFC 0x16 /* Set IFC */
+#define AUXMR_CREN 0x17 /* Clear REN */
+ /* 0x18 undefined/unknown */
+ /* 0x19 undefined/unknown */
+#define AUXMR_TCSE 0x1a /* Take Control Sync on End */
+#define AUXMR_LCM 0x1b /* Listen Continuously Mode */
+#define AUXMR_LUNL 0x1c /* Local Unlisten */
+#define AUXMR_EPP 0x1d /* Execute Parallel Poll */
+#define AUXMR_CIFC 0x1e /* Clear IFC */
+#define AUXMR_SREN 0x1f /* Set REN */
+
+#define PPR_U (1 << 4) /* Unconfigure */
+#define PPR_S (1 << 3) /* Status Polarity */
+
+#define AUXA_HLDA (1 << 0) /* Holdoff on All */
+#define AUXA_HLDE (1 << 1) /* Holdoff on END */
+#define AUXA_REOS (1 << 2) /* End on EOS received */
+#define AUXA_XEOS (1 << 3) /* Transmit END with EOS */
+#define AUXA_BIN (1 << 4) /* Binary */
+
+#define AUXB_CPTE (1 << 0) /* Cmd Pass Through Enable */
+#define AUXB_SPEOI (1 << 1) /* Send Serial Poll EOI */
+#define AUXB_TRI (1 << 2) /* Three-State Timing */
+#define AUXB_INV (1 << 3) /* Invert */
+#define AUXB_ISS (1 << 4) /* Individual Status Select */
+
+#define AUXE_DHDT (1 << 0) /* DAC Holdoff on DTAS */
+#define AUXE_DHDC (1 << 1) /* DAC Holdoff on DCAS */
+
+#define ADR0_DL0 (1 << 5) /* Disable Listener 0 */
+#define ADR0_DT0 (1 << 6) /* Disable Talker 0 */
+
+#define ADR_DL (1 << 5) /* Disable Listener */
+#define ADR_DT (1 << 6) /* Disable Talker */
+#define ADR_ARS (1 << 7) /* Address Register Select */
+
+#define ADR1_DL1 (1 << 5) /* Disable Listener 1 */
+#define ADR1_DT1 (1 << 6) /* Disable Talker 1 */
+#define ADR1_EOI (1 << 7) /* End or Identify */
+
OpenPOWER on IntegriCloud