Driver for GPIB controllers boards based on the uPD7210 GPIB controller,
including boards made by Captial Equipment Corp.
This commit is contained in:
parent
59720b5acd
commit
9d6ae676dd
|
@ -0,0 +1,712 @@
|
|||
/* $NetBSD: cec.c,v 1.1 2003/06/02 03:57:15 gmcgarry Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Gregory McGarry.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: cec.c,v 1.1 2003/06/02 03:57:15 gmcgarry Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/callout.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/isa/isavar.h>
|
||||
#include <dev/isa/isadmavar.h>
|
||||
|
||||
#include <dev/gpib/gpibvar.h>
|
||||
|
||||
#include <dev/ic/nec7210reg.h>
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
int cecdebug = 0x1f;
|
||||
#define DPRINTF(flag, str) if (cecdebug & (flag)) printf str
|
||||
#define DBG_FOLLOW 0x01
|
||||
#define DBG_CONFIG 0x02
|
||||
#define DBG_INTR 0x04
|
||||
#define DBG_REPORTTIME 0x08
|
||||
#define DBG_FAIL 0x10
|
||||
#define DBG_WAIT 0x20
|
||||
#else
|
||||
#define DPRINTF(flag, str) /* nothing */
|
||||
#endif
|
||||
|
||||
#define CEC_IOSIZE 8
|
||||
|
||||
struct cec_softc {
|
||||
struct device sc_dev; /* generic device glue */
|
||||
|
||||
bus_space_tag_t sc_iot;
|
||||
bus_space_handle_t sc_ioh;
|
||||
isa_chipset_tag_t sc_ic;
|
||||
int sc_drq;
|
||||
void *sc_ih;
|
||||
|
||||
int sc_myaddr; /* my address */
|
||||
struct gpib_softc *sc_gpib;
|
||||
|
||||
volatile int sc_flags;
|
||||
#define CECF_IO 0x1
|
||||
#define CECF_PPOLL 0x4
|
||||
#define CECF_READ 0x8
|
||||
#define CECF_TIMO 0x10
|
||||
#define CECF_USEDMA 0x20
|
||||
int sc_ppoll_slave; /* XXX stash our ppoll address */
|
||||
struct callout sc_timeout_ch;
|
||||
};
|
||||
|
||||
int cecprobe(struct device *, struct cfdata *, void *);
|
||||
void cecattach(struct device *, struct device *, void *);
|
||||
|
||||
CFATTACH_DECL(cec, sizeof(struct cec_softc),
|
||||
cecprobe, cecattach, NULL, NULL);
|
||||
|
||||
void cecreset(void *);
|
||||
int cecpptest(void *, int);
|
||||
void cecppwatch(void *, int);
|
||||
void cecppclear(void *);
|
||||
void cecxfer(void *, int, int, void *, int, int, int);
|
||||
void cecgo(void *v);
|
||||
int cecintr(void *);
|
||||
int cecsendcmds(void *, void *, int);
|
||||
int cecsenddata(void *, void *, int);
|
||||
int cecrecvdata(void *, void *, int);
|
||||
int cecgts(void *);
|
||||
int cectc(void *, int);
|
||||
void cecifc(void *);
|
||||
|
||||
static int cecwait(struct cec_softc *, int, int);
|
||||
static void cectimeout(void *v);
|
||||
static int nec7210_setaddress(struct cec_softc *, int, int);
|
||||
static void nec7210_init(struct cec_softc *);
|
||||
static void nec7210_ifc(struct cec_softc *);
|
||||
|
||||
/*
|
||||
* Our chipset structure.
|
||||
*/
|
||||
struct gpib_chipset_tag cec_ic = {
|
||||
cecreset,
|
||||
NULL,
|
||||
NULL,
|
||||
cecpptest,
|
||||
cecppwatch,
|
||||
cecppclear,
|
||||
cecxfer,
|
||||
cectc,
|
||||
cecgts,
|
||||
cecifc,
|
||||
cecsendcmds,
|
||||
cecsenddata,
|
||||
cecrecvdata
|
||||
};
|
||||
|
||||
int cecwtimeout = 0x10000;
|
||||
int cecdmathresh = 3;
|
||||
|
||||
int
|
||||
cecprobe(struct device *parent, struct cfdata *match, void *aux)
|
||||
{
|
||||
struct isa_attach_args *ia = aux;
|
||||
bus_space_tag_t iot = ia->ia_iot;
|
||||
bus_space_handle_t ioh;
|
||||
|
||||
DPRINTF(DBG_CONFIG, ("cecprobe: called\n"));
|
||||
|
||||
if (ia->ia_nio < 1)
|
||||
return (0);
|
||||
if (ia->ia_nirq < 1)
|
||||
return (0);
|
||||
if (ia->ia_ndrq < 1)
|
||||
return (0);
|
||||
|
||||
if (ISA_DIRECT_CONFIG(ia))
|
||||
return (0);
|
||||
|
||||
if (ia->ia_io[0].ir_addr == ISACF_PORT_DEFAULT)
|
||||
return (0);
|
||||
|
||||
if (ia->ia_ndrq > 0 && ia->ia_drq[0].ir_drq == ISACF_DRQ_DEFAULT)
|
||||
ia->ia_ndrq = 0;
|
||||
|
||||
if (bus_space_map(iot, ia->ia_io[0].ir_addr, CEC_IOSIZE, 0, &ioh))
|
||||
return (0);
|
||||
|
||||
/* XXX insert probe here */
|
||||
|
||||
ia->ia_io[0].ir_size = CEC_IOSIZE;
|
||||
ia->ia_niomem = 0;
|
||||
|
||||
bus_space_unmap(iot, ioh, CEC_IOSIZE);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
cecattach(struct device *parent, struct device *self, void *aux)
|
||||
{
|
||||
struct cec_softc *sc = (struct cec_softc *)self;
|
||||
struct isa_attach_args *ia = aux;
|
||||
struct gpibdev_attach_args ga;
|
||||
bus_size_t maxsize;
|
||||
|
||||
printf("\n");
|
||||
|
||||
DPRINTF(DBG_CONFIG, ("cecattach: called\n"));
|
||||
|
||||
sc->sc_iot = ia->ia_iot;
|
||||
sc->sc_ic = ia->ia_ic;
|
||||
|
||||
if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr, CEC_IOSIZE,
|
||||
0, &sc->sc_ioh) != 0) {
|
||||
printf("%s: unable to map I/O space\n", sc->sc_dev.dv_xname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ia->ia_ndrq > 0) {
|
||||
sc->sc_flags |= CECF_USEDMA;
|
||||
sc->sc_drq = ia->ia_drq[0].ir_drq;
|
||||
|
||||
(void) isa_drq_alloc(sc->sc_ic, sc->sc_drq);
|
||||
maxsize = isa_dmamaxsize(sc->sc_ic, sc->sc_drq);
|
||||
if (isa_dmamap_create(sc->sc_ic, sc->sc_drq,
|
||||
maxsize, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW)) {
|
||||
printf("%s: unable to create map for drq %d\n",
|
||||
sc->sc_dev.dv_xname, sc->sc_drq);
|
||||
sc->sc_flags &= ~CECF_USEDMA;
|
||||
}
|
||||
}
|
||||
|
||||
sc->sc_myaddr = 15; /* XXX */
|
||||
|
||||
cecreset(sc);
|
||||
(void) nec7210_setaddress(sc, sc->sc_myaddr, -1);
|
||||
|
||||
sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq,
|
||||
IST_EDGE, IPL_BIO, cecintr, sc);
|
||||
if (sc->sc_ih == NULL) {
|
||||
printf("%s: couldn't establish interrupt\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
return;
|
||||
}
|
||||
|
||||
callout_init(&sc->sc_timeout_ch);
|
||||
|
||||
/* attach MI GPIB bus */
|
||||
cec_ic.cookie = (void *)sc;
|
||||
ga.ga_ic = &cec_ic;
|
||||
ga.ga_address = sc->sc_myaddr;
|
||||
sc->sc_gpib =
|
||||
(struct gpib_softc *)config_found(self, &ga, gpibdevprint);
|
||||
}
|
||||
|
||||
int
|
||||
cecintr(void *v)
|
||||
{
|
||||
struct cec_softc *sc = v;
|
||||
bus_space_tag_t iot = sc->sc_iot;
|
||||
bus_space_handle_t ioh = sc->sc_ioh;
|
||||
u_int8_t stat1, stat2;
|
||||
|
||||
stat1 = bus_space_read_1(iot, ioh, NEC7210_ISR1);
|
||||
stat2 = bus_space_read_1(iot, ioh, NEC7210_ISR2);
|
||||
|
||||
DPRINTF(DBG_INTR, ("cecintr: sc=%p stat1=0x%x stat2=0x%x\n",
|
||||
sc, stat1, stat2));
|
||||
|
||||
if (sc->sc_flags & CECF_IO) {
|
||||
|
||||
if (sc->sc_flags & CECF_TIMO)
|
||||
callout_stop(&sc->sc_timeout_ch);
|
||||
|
||||
bus_space_write_1(iot, ioh, NEC7210_IMR1, 0);
|
||||
bus_space_write_1(iot, ioh, NEC7210_IMR2, 0);
|
||||
bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCA);
|
||||
sc->sc_flags &= ~(CECF_IO | CECF_READ | CECF_TIMO);
|
||||
if (sc->sc_flags & CECF_USEDMA)
|
||||
isa_dmadone(sc->sc_ic, sc->sc_drq);
|
||||
gpibintr(sc->sc_gpib);
|
||||
|
||||
} else if (sc->sc_flags & CECF_PPOLL) {
|
||||
|
||||
if (cecpptest(sc, sc->sc_ppoll_slave)) {
|
||||
sc->sc_flags &= ~CECF_PPOLL;
|
||||
bus_space_write_1(iot, ioh, NEC7210_IMR2, 0);
|
||||
gpibintr(sc->sc_gpib);
|
||||
}
|
||||
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
cecreset(void *v)
|
||||
{
|
||||
struct cec_softc *sc = v;
|
||||
u_int8_t cmd;
|
||||
|
||||
DPRINTF(DBG_FOLLOW, ("cecreset: sc=%p\n", sc));
|
||||
|
||||
nec7210_init(sc);
|
||||
nec7210_ifc(sc);
|
||||
/* we're now the system controller */
|
||||
|
||||
/* XXX should be pushed higher */
|
||||
|
||||
/* universal device clear */
|
||||
cmd = GPIBCMD_DCL;
|
||||
(void) cecsendcmds(sc, &cmd, 1);
|
||||
/* delay for devices to clear */
|
||||
DELAY(100000);
|
||||
}
|
||||
|
||||
int
|
||||
cecsendcmds(void *v, void *ptr, int origcnt)
|
||||
{
|
||||
struct cec_softc *sc = v;
|
||||
bus_space_tag_t iot = sc->sc_iot;
|
||||
bus_space_handle_t ioh = sc->sc_ioh;
|
||||
int cnt = origcnt;
|
||||
u_int8_t *addr = ptr;
|
||||
|
||||
DPRINTF(DBG_FOLLOW, ("cecsendcmds: sc=%p, ptr=%p cnt=%d\n",
|
||||
sc, ptr, origcnt));
|
||||
|
||||
while (--cnt >= 0) {
|
||||
bus_space_write_1(iot, ioh, NEC7210_CDOR, *addr++);
|
||||
if (cecwait(sc, 0, ISR2_CO))
|
||||
return (origcnt - cnt - 1);
|
||||
}
|
||||
return (origcnt);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cecrecvdata(void *v, void *ptr, int origcnt)
|
||||
{
|
||||
struct cec_softc *sc = v;
|
||||
bus_space_tag_t iot = sc->sc_iot;
|
||||
bus_space_handle_t ioh = sc->sc_ioh;
|
||||
int cnt = origcnt;
|
||||
u_int8_t *addr = ptr;
|
||||
|
||||
DPRINTF(DBG_FOLLOW, ("cecrecvdata: sc=%p, ptr=%p cnt=%d\n",
|
||||
sc, ptr, origcnt));
|
||||
|
||||
/* XXX holdoff on end */
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh, NEC7210_AUXMR, AUXCMD_RHDF);
|
||||
|
||||
if (cnt) {
|
||||
while (--cnt >= 0) {
|
||||
if (cecwait(sc, ISR1_DI, 0))
|
||||
return (origcnt - cnt - 1);
|
||||
*addr++ = bus_space_read_1(iot, ioh, NEC7210_DIR);
|
||||
}
|
||||
}
|
||||
return (origcnt);
|
||||
}
|
||||
|
||||
int
|
||||
cecsenddata(void *v, void *ptr, int origcnt)
|
||||
{
|
||||
struct cec_softc *sc = v;
|
||||
bus_space_tag_t iot = sc->sc_iot;
|
||||
bus_space_handle_t ioh = sc->sc_ioh;
|
||||
int cnt = origcnt;
|
||||
u_int8_t *addr = ptr;
|
||||
|
||||
DPRINTF(DBG_FOLLOW, ("cecdsenddata: sc=%p, ptr=%p cnt=%d\n",
|
||||
sc, ptr, origcnt));
|
||||
|
||||
if (cnt) {
|
||||
while (--cnt > 0) {
|
||||
bus_space_write_1(iot, ioh, NEC7210_CDOR, *addr++);
|
||||
if (cecwait(sc, ISR1_DO, 0))
|
||||
return (origcnt - cnt - 1);
|
||||
}
|
||||
bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_SEOI);
|
||||
bus_space_write_1(iot, ioh, NEC7210_CDOR, *addr);
|
||||
(void) cecwait(sc, ISR1_DO, 0);
|
||||
}
|
||||
return (origcnt);
|
||||
}
|
||||
|
||||
int
|
||||
cectc(void *v, int sync)
|
||||
{
|
||||
struct cec_softc *sc = v;
|
||||
bus_space_tag_t iot = sc->sc_iot;
|
||||
bus_space_handle_t ioh = sc->sc_ioh;
|
||||
u_int8_t adsr;
|
||||
int timo = cecwtimeout;
|
||||
|
||||
DPRINTF(DBG_FOLLOW, ("cectc: sc=%p, sync=%d\n", sc, sync));
|
||||
|
||||
adsr = bus_space_read_1(iot, ioh, NEC7210_ADSR);
|
||||
#if 0
|
||||
if ((adsr & (ADSR_CIC | ADSR_NATN)) == ADSR_CIC) {
|
||||
DPRINTF(0xff, ("cectc: already CIC\n"));
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sync) {
|
||||
bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_RHDF);
|
||||
bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCS);
|
||||
} else {
|
||||
bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCA);
|
||||
}
|
||||
|
||||
/* wait until ATN is asserted */
|
||||
for (;;) {
|
||||
adsr = bus_space_read_1(iot, ioh, NEC7210_ADSR);
|
||||
if (--timo == 0) {
|
||||
DPRINTF(DBG_REPORTTIME, ("cectc: timeout\n"));
|
||||
return (1);
|
||||
}
|
||||
if ((adsr & ADSR_NATN) == 0)
|
||||
break;
|
||||
DELAY(1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
cecgts(void *v)
|
||||
{
|
||||
struct cec_softc *sc = v;
|
||||
bus_space_tag_t iot = sc->sc_iot;
|
||||
bus_space_handle_t ioh = sc->sc_ioh;
|
||||
u_int8_t adsr;
|
||||
int timo = cecwtimeout;
|
||||
|
||||
DPRINTF(DBG_FOLLOW, ("cecgts: sc=%p\n", sc));
|
||||
|
||||
adsr = bus_space_read_1(iot, ioh, NEC7210_ADSR);
|
||||
#if 0
|
||||
if ((adsr & (ADSR_CIC | ADSR_NATN)) == ADSR_NATN) {
|
||||
DPRINTF(0xff, ("cecgts: already standby\n"));
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_GTS);
|
||||
|
||||
/* wait unit ATN is released */
|
||||
for (;;) {
|
||||
adsr = bus_space_read_1(iot, ioh, NEC7210_ADSR);
|
||||
if (--timo == 0) {
|
||||
DPRINTF(DBG_REPORTTIME, ("cecgts: timeout\n"));
|
||||
return (1);
|
||||
}
|
||||
if ((adsr & ADSR_NATN) == ADSR_NATN)
|
||||
break;
|
||||
DELAY(1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
cecpptest(void *v, int slave)
|
||||
{
|
||||
struct cec_softc *sc = v;
|
||||
bus_space_tag_t iot = sc->sc_iot;
|
||||
bus_space_handle_t ioh = sc->sc_ioh;
|
||||
int ppoll;
|
||||
|
||||
DPRINTF(DBG_FOLLOW, ("cecpptest: sc=%p slave=%d\n", sc, slave));
|
||||
|
||||
bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_EPP);
|
||||
DELAY(25);
|
||||
ppoll = bus_space_read_1(iot, ioh, NEC7210_CPTR);
|
||||
DPRINTF(0xff, ("cecpptest: ppoll=%x\n", ppoll));
|
||||
return ((ppoll & (0x80 >> slave)) != 0);
|
||||
}
|
||||
|
||||
void
|
||||
cecppwatch(void *v, int slave)
|
||||
{
|
||||
struct cec_softc *sc = v;
|
||||
bus_space_tag_t iot = sc->sc_iot;
|
||||
bus_space_handle_t ioh = sc->sc_ioh;
|
||||
|
||||
DPRINTF(DBG_FOLLOW, ("cecppwatch: sc=%p\n", sc));
|
||||
|
||||
sc->sc_flags |= CECF_PPOLL;
|
||||
sc->sc_ppoll_slave = slave;
|
||||
bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_CO);
|
||||
bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_EPP);
|
||||
}
|
||||
|
||||
void
|
||||
cecppclear(void *v)
|
||||
{
|
||||
struct cec_softc *sc = v;
|
||||
|
||||
DPRINTF(DBG_FOLLOW, ("cecppclear: sc=%p\n", sc));
|
||||
|
||||
sc->sc_flags &= ~CECF_PPOLL;
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh, NEC7210_IMR2, 0);
|
||||
}
|
||||
|
||||
void
|
||||
cecxfer(void *v, int slave, int sec, void *buf, int count, int dir, int timo)
|
||||
{
|
||||
struct cec_softc *sc = v;
|
||||
bus_space_tag_t iot = sc->sc_iot;
|
||||
bus_space_handle_t ioh = sc->sc_ioh;
|
||||
|
||||
DPRINTF(DBG_FOLLOW,
|
||||
("cecxfer: slave=%d sec=%d buf=%p count=%d dir=%x timo=%d\n",
|
||||
slave, sec, buf, count, dir, timo));
|
||||
|
||||
sc->sc_flags |= CECF_IO;
|
||||
if (dir == GPIB_READ)
|
||||
sc->sc_flags |= CECF_READ;
|
||||
if (timo) {
|
||||
sc->sc_flags |= CECF_TIMO;
|
||||
callout_reset(&sc->sc_timeout_ch, 5*hz, cectimeout, sc);
|
||||
}
|
||||
|
||||
if (sc->sc_flags & CECF_READ) {
|
||||
DPRINTF(DBG_FOLLOW, ("cecxfer: DMA read request\n"));
|
||||
if ((sc->sc_flags & CECF_USEDMA) != 0) {
|
||||
isa_dmastart(sc->sc_ic, sc->sc_drq, buf, count, NULL,
|
||||
DMAMODE_READ | DMAMODE_DEMAND, BUS_DMA_NOWAIT);
|
||||
bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_DMAI);
|
||||
bus_space_write_1(iot, ioh, NEC7210_IMR1, IMR1_END);
|
||||
// XXX (void) cecrecv(sc, slave, sec, NULL, 0);
|
||||
(void) gpibrecv(&cec_ic, slave, sec, NULL, 0);
|
||||
} else {
|
||||
/* XXX this doesn't work */
|
||||
DPRINTF(DBG_FOLLOW, ("cecxfer: polling instead\n"));
|
||||
bus_space_write_1(iot, ioh, NEC7210_IMR1, IMR1_END);
|
||||
// XXX (void) cecrecv(sc, slave, sec, buf, count);
|
||||
(void) gpibrecv(&cec_ic, slave, sec, buf, count);
|
||||
bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_CO);
|
||||
}
|
||||
} else {
|
||||
DPRINTF(DBG_FOLLOW, ("cecxfer: DMA write request\n"));
|
||||
bus_space_write_1(iot, ioh, NEC7210_IMR2, 0);
|
||||
if (count < cecdmathresh ||
|
||||
(sc->sc_flags & CECF_USEDMA) == 0) {
|
||||
DPRINTF(DBG_FOLLOW, ("cecxfer: polling instead\n"));
|
||||
// XXX (void) cecsend(sc, slave, sec, buf, count);
|
||||
(void) gpibsend(&cec_ic, slave, sec, buf, count);
|
||||
bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_CO);
|
||||
return;
|
||||
}
|
||||
/* we send the last byte with EOI set */
|
||||
isa_dmastart(sc->sc_ic, sc->sc_drq, buf, count-1, NULL,
|
||||
DMAMODE_WRITE | DMAMODE_DEMAND, BUS_DMA_NOWAIT);
|
||||
bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_DMAO);
|
||||
// XXX (void) cecsend(sc, slave, sec, NULL, 0);
|
||||
(void) gpibsend(&cec_ic, slave, sec, NULL, 0);
|
||||
while (!isa_dmafinished(sc->sc_ic, sc->sc_drq))
|
||||
DELAY(1);
|
||||
(void) cecwait(sc, ISR1_DO, 0);
|
||||
bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_SEOI);
|
||||
bus_space_write_1(iot, ioh, NEC7210_CDOR, *(char *)buf+count);
|
||||
/* generate interrupt */
|
||||
bus_space_write_1(iot, ioh, NEC7210_IMR1, IMR1_DO);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cecifc(void *v)
|
||||
{
|
||||
struct cec_softc *sc = v;
|
||||
|
||||
nec7210_ifc(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
nec7210_setaddress(struct cec_softc *sc, int pri, int sec)
|
||||
{
|
||||
bus_space_tag_t iot = sc->sc_iot;
|
||||
bus_space_handle_t ioh = sc->sc_ioh;
|
||||
u_int8_t admr;
|
||||
|
||||
/* assign our primary address */
|
||||
bus_space_write_1(iot, ioh, NEC7210_ADDR, (pri & ADDR_MASK));
|
||||
|
||||
admr = ADMR_TRM0 | ADMR_TRM1;
|
||||
|
||||
/* assign our secondary address */
|
||||
if (sec != -1) {
|
||||
bus_space_write_1(iot, ioh, NEC7210_ADDR,
|
||||
(ADDR_ARS | (sec & ADDR_MASK)));
|
||||
admr |= ADMR_ADM1;
|
||||
} else {
|
||||
/* disable secondary address */
|
||||
bus_space_write_1(iot, ioh, NEC7210_ADDR,
|
||||
(ADDR_ARS | ADDR_DT | ADDR_DL));
|
||||
admr |= ADMR_ADM0;
|
||||
}
|
||||
bus_space_write_1(iot, ioh, NEC7210_ADMR, admr);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
nec7210_init(struct cec_softc *sc)
|
||||
{
|
||||
bus_space_tag_t iot = sc->sc_iot;
|
||||
bus_space_handle_t ioh = sc->sc_ioh;
|
||||
|
||||
/* reset chip */
|
||||
bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_CRST);
|
||||
|
||||
/* clear interrupts */
|
||||
bus_space_read_1(iot, ioh, NEC7210_CPTR);
|
||||
bus_space_read_1(iot, ioh, NEC7210_ISR1);
|
||||
bus_space_read_1(iot, ioh, NEC7210_ISR2);
|
||||
|
||||
/* initialise interrupts */
|
||||
bus_space_write_1(iot, ioh, NEC7210_IMR1, 0);
|
||||
bus_space_write_1(iot, ioh, NEC7210_IMR2, 0);
|
||||
bus_space_write_1(iot, ioh, NEC7210_SPMR, 0);
|
||||
bus_space_write_1(iot, ioh, NEC7210_EOSR, 0);
|
||||
|
||||
/* set internal clock to 8MHz */
|
||||
bus_space_write_1(iot, ioh, NEC7210_AUXMR, (AUXMR_ICR | 0x8));
|
||||
/* parallel poll unconfigure */
|
||||
bus_space_write_1(iot, ioh, NEC7210_AUXMR, (AUXMR_PPOLL | PPOLL_PPU));
|
||||
|
||||
/* assign our address */
|
||||
bus_space_write_1(iot, ioh, NEC7210_ADDR, 0);
|
||||
/* disable secondary address */
|
||||
bus_space_write_1(iot, ioh, NEC7210_ADDR,
|
||||
(ADDR_ARS | ADDR_DT | ADDR_DL));
|
||||
|
||||
/* setup transceivers */
|
||||
bus_space_write_1(iot, ioh, NEC7210_ADMR,
|
||||
(ADMR_ADM0 | ADMR_TRM0 | ADMR_TRM1));
|
||||
bus_space_write_1(iot, ioh, NEC7210_AUXMR,
|
||||
(AUXMR_REGA | AUX_A_HSNORM));
|
||||
|
||||
/* set INT pin to active high */
|
||||
bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXMR_REGB);
|
||||
bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXMR_REGE);
|
||||
|
||||
/* holdoff on end condition */
|
||||
bus_space_write_1(iot, ioh, NEC7210_AUXMR, (AUXMR_REGA | AUX_A_HLDE));
|
||||
|
||||
/* reconnect to bus */
|
||||
bus_space_write_1(iot, ioh, NEC7210_AUXMR, (AUXMR_CMD | AUXCMD_IEPON));
|
||||
}
|
||||
|
||||
/*
|
||||
* Place all devices on the bus into quiescient state ready for
|
||||
* remote programming.
|
||||
* Obviously, we're the system controller upon exit.
|
||||
*/
|
||||
void
|
||||
nec7210_ifc(struct cec_softc *sc)
|
||||
{
|
||||
bus_space_tag_t iot = sc->sc_iot;
|
||||
bus_space_handle_t ioh = sc->sc_ioh;
|
||||
|
||||
/*XXX*/ bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCA);
|
||||
bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_CREN);
|
||||
bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_SIFC);
|
||||
/* wait for devices to enter quiescient state */
|
||||
DELAY(100);
|
||||
bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_CIFC);
|
||||
bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_SREN);
|
||||
}
|
||||
|
||||
static int
|
||||
cecwait(struct cec_softc *sc, int x1, int x2)
|
||||
{
|
||||
int timo = cecwtimeout;
|
||||
bus_space_tag_t iot = sc->sc_iot;
|
||||
bus_space_handle_t ioh = sc->sc_ioh;
|
||||
u_int8_t stat1, stat2;
|
||||
|
||||
DPRINTF(DBG_WAIT, ("cecwait: sc=%p, x1=0x%x x2=0x%x\n", sc, x1, x2));
|
||||
|
||||
for (;;) {
|
||||
stat1 = bus_space_read_1(iot, ioh, NEC7210_ISR1);
|
||||
stat2 = bus_space_read_1(iot, ioh, NEC7210_ISR2);
|
||||
#if 0
|
||||
if ((stat1 & ISR1_ERR)) {
|
||||
DPRINTF(DBG_WAIT, ("cecwait: got ERR\n"));
|
||||
return (1);
|
||||
}
|
||||
#endif
|
||||
if (--timo == 0) {
|
||||
DPRINTF(DBG_REPORTTIME,
|
||||
("cecwait: timeout x1=0x%x x2=0x%x\n", x1, x2));
|
||||
return (1);
|
||||
}
|
||||
if ((stat1 & x1) || (stat2 & x2))
|
||||
break;
|
||||
DELAY(1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
cectimeout(void *v)
|
||||
{
|
||||
struct cec_softc *sc = v;
|
||||
bus_space_tag_t iot = sc->sc_iot;
|
||||
bus_space_handle_t ioh = sc->sc_ioh;
|
||||
int s;
|
||||
|
||||
DPRINTF(DBG_FOLLOW, ("cectimeout: sc=%p\n", sc));
|
||||
|
||||
s = splbio();
|
||||
if (sc->sc_flags & CECF_IO) {
|
||||
bus_space_write_1(iot, ioh, NEC7210_IMR1, 0);
|
||||
bus_space_write_2(iot, ioh, NEC7210_IMR2, 0);
|
||||
bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCA);
|
||||
sc->sc_flags &= ~(CECF_IO | CECF_READ | CECF_TIMO);
|
||||
isa_dmaabort(sc->sc_ic, sc->sc_drq);
|
||||
printf("%s: %s timeout\n", sc->sc_dev.dv_xname,
|
||||
sc->sc_flags & CECF_READ ? "read" : "write");
|
||||
gpibintr(sc->sc_gpib);
|
||||
}
|
||||
splx(s);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: files.isa,v 1.128 2003/03/03 22:07:21 mycroft Exp $
|
||||
# $NetBSD: files.isa,v 1.129 2003/06/02 03:57:16 gmcgarry Exp $
|
||||
#
|
||||
# Config file and device description for machine-independent ISA code.
|
||||
# Included by ports that need it. Requires that the SCSI files be
|
||||
|
@ -154,6 +154,14 @@ device wt: tape, isadma
|
|||
attach wt at isa
|
||||
file dev/isa/wt.c wt needs-flag
|
||||
|
||||
#
|
||||
# GPIB controllers
|
||||
#
|
||||
|
||||
device cec: gpibdev
|
||||
attach cec at isa
|
||||
file dev/isa/cec.c cec
|
||||
|
||||
#
|
||||
# ISA networking drivers
|
||||
#
|
||||
|
|
Loading…
Reference in New Issue