Further elaborate the GPIB driver. We now support a minimal subset of

the ibfoo() API.
This commit is contained in:
Poul-Henning Kamp 2005-02-06 15:22:23 +00:00
parent d61902a5b4
commit df05d0fb93
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=141398
6 changed files with 1570 additions and 263 deletions

View File

@ -538,6 +538,7 @@ dev/ida/ida_pci.c optional ida pci
dev/ie/if_ie.c optional ie isa nowerror
dev/ie/if_ie_isa.c optional ie isa
dev/ieee488/pcii.c optional pcii
dev/ieee488/upd7210.c optional pcii
dev/iicbus/if_ic.c optional ic
dev/iicbus/iic.c optional iic
dev/iicbus/iicbb.c optional iicbb

147
sys/dev/ieee488/ibfoo_int.h Normal file
View File

@ -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)

View File

@ -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;
}

152
sys/dev/ieee488/ugpib.h Normal file
View File

@ -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_ */

1026
sys/dev/ieee488/upd7210.c Normal file

File diff suppressed because it is too large Load Diff

213
sys/dev/ieee488/upd7210.h Normal file
View File

@ -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 */