xref: /netbsd-src/sys/dev/isa/cec.c (revision c7fb772b85b2b5d4cfb282f868f454b4701534fd)
1*c7fb772bSthorpej /*	$NetBSD: cec.c,v 1.16 2021/08/07 16:19:12 thorpej Exp $	*/
29d6ae676Sgmcgarry 
39d6ae676Sgmcgarry /*-
49d6ae676Sgmcgarry  * Copyright (c) 2003 The NetBSD Foundation, Inc.
59d6ae676Sgmcgarry  * All rights reserved.
69d6ae676Sgmcgarry  *
79d6ae676Sgmcgarry  * This code is derived from software contributed to The NetBSD Foundation
89d6ae676Sgmcgarry  * by Gregory McGarry.
99d6ae676Sgmcgarry  *
109d6ae676Sgmcgarry  * Redistribution and use in source and binary forms, with or without
119d6ae676Sgmcgarry  * modification, are permitted provided that the following conditions
129d6ae676Sgmcgarry  * are met:
139d6ae676Sgmcgarry  * 1. Redistributions of source code must retain the above copyright
149d6ae676Sgmcgarry  *    notice, this list of conditions and the following disclaimer.
159d6ae676Sgmcgarry  * 2. Redistributions in binary form must reproduce the above copyright
169d6ae676Sgmcgarry  *    notice, this list of conditions and the following disclaimer in the
179d6ae676Sgmcgarry  *    documentation and/or other materials provided with the distribution.
189d6ae676Sgmcgarry  *
199d6ae676Sgmcgarry  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
209d6ae676Sgmcgarry  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
219d6ae676Sgmcgarry  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
229d6ae676Sgmcgarry  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
239d6ae676Sgmcgarry  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
249d6ae676Sgmcgarry  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
259d6ae676Sgmcgarry  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
269d6ae676Sgmcgarry  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
279d6ae676Sgmcgarry  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
289d6ae676Sgmcgarry  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
299d6ae676Sgmcgarry  * POSSIBILITY OF SUCH DAMAGE.
309d6ae676Sgmcgarry  */
319d6ae676Sgmcgarry 
329d6ae676Sgmcgarry #include <sys/cdefs.h>
33*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: cec.c,v 1.16 2021/08/07 16:19:12 thorpej Exp $");
349d6ae676Sgmcgarry 
359d6ae676Sgmcgarry #include <sys/param.h>
369d6ae676Sgmcgarry #include <sys/systm.h>
379d6ae676Sgmcgarry #include <sys/callout.h>
389d6ae676Sgmcgarry #include <sys/conf.h>
399d6ae676Sgmcgarry #include <sys/device.h>
409d6ae676Sgmcgarry #include <sys/kernel.h>
419d6ae676Sgmcgarry 
42a2a38285Sad #include <sys/bus.h>
439d6ae676Sgmcgarry 
449d6ae676Sgmcgarry #include <dev/isa/isavar.h>
459d6ae676Sgmcgarry #include <dev/isa/isadmavar.h>
469d6ae676Sgmcgarry 
479d6ae676Sgmcgarry #include <dev/gpib/gpibvar.h>
489d6ae676Sgmcgarry 
499d6ae676Sgmcgarry #include <dev/ic/nec7210reg.h>
509d6ae676Sgmcgarry 
51f3f3dfb3Stsutsui #ifndef DEBUG
529d6ae676Sgmcgarry #define DEBUG
53f3f3dfb3Stsutsui #endif
549d6ae676Sgmcgarry 
559d6ae676Sgmcgarry #ifdef DEBUG
569d6ae676Sgmcgarry int cecdebug = 0x1f;
579d6ae676Sgmcgarry #define DPRINTF(flag, str)	if (cecdebug & (flag)) printf str
589d6ae676Sgmcgarry #define DBG_FOLLOW	0x01
599d6ae676Sgmcgarry #define DBG_CONFIG	0x02
609d6ae676Sgmcgarry #define DBG_INTR	0x04
619d6ae676Sgmcgarry #define DBG_REPORTTIME	0x08
629d6ae676Sgmcgarry #define DBG_FAIL	0x10
639d6ae676Sgmcgarry #define DBG_WAIT	0x20
649d6ae676Sgmcgarry #else
659d6ae676Sgmcgarry #define DPRINTF(flag, str)	/* nothing */
669d6ae676Sgmcgarry #endif
679d6ae676Sgmcgarry 
689d6ae676Sgmcgarry #define CEC_IOSIZE	8
699d6ae676Sgmcgarry 
709d6ae676Sgmcgarry struct cec_softc {
71cbab9cadSchs 	device_t sc_dev;		/* generic device glue */
729d6ae676Sgmcgarry 
739d6ae676Sgmcgarry 	bus_space_tag_t sc_iot;
749d6ae676Sgmcgarry 	bus_space_handle_t sc_ioh;
759d6ae676Sgmcgarry 	isa_chipset_tag_t sc_ic;
769d6ae676Sgmcgarry 	int sc_drq;
779d6ae676Sgmcgarry 	void *sc_ih;
789d6ae676Sgmcgarry 
799d6ae676Sgmcgarry 	int sc_myaddr;			/* my address */
809d6ae676Sgmcgarry 	struct gpib_softc *sc_gpib;
819d6ae676Sgmcgarry 
829d6ae676Sgmcgarry 	volatile int sc_flags;
839d6ae676Sgmcgarry #define	CECF_IO		0x1
849d6ae676Sgmcgarry #define	CECF_PPOLL	0x4
859d6ae676Sgmcgarry #define	CECF_READ	0x8
869d6ae676Sgmcgarry #define	CECF_TIMO	0x10
879d6ae676Sgmcgarry #define CECF_USEDMA	0x20
889d6ae676Sgmcgarry 	int sc_ppoll_slave;		/* XXX stash our ppoll address */
8988ab7da9Sad 	callout_t sc_timeout_ch;
909d6ae676Sgmcgarry };
919d6ae676Sgmcgarry 
92ab57cc6fScegger int	cecprobe(device_t, cfdata_t, void *);
93ab57cc6fScegger void	cecattach(device_t, device_t, void *);
949d6ae676Sgmcgarry 
95cbab9cadSchs CFATTACH_DECL_NEW(cec, sizeof(struct cec_softc),
969d6ae676Sgmcgarry 	cecprobe, cecattach, NULL, NULL);
979d6ae676Sgmcgarry 
989d6ae676Sgmcgarry void	cecreset(void *);
999d6ae676Sgmcgarry int	cecpptest(void *, int);
1009d6ae676Sgmcgarry void	cecppwatch(void *, int);
1019d6ae676Sgmcgarry void	cecppclear(void *);
1029d6ae676Sgmcgarry void	cecxfer(void *, int, int, void *, int, int, int);
1039d6ae676Sgmcgarry void	cecgo(void *v);
1049d6ae676Sgmcgarry int	cecintr(void *);
1059d6ae676Sgmcgarry int	cecsendcmds(void *, void *, int);
1069d6ae676Sgmcgarry int	cecsenddata(void *, void *, int);
1079d6ae676Sgmcgarry int	cecrecvdata(void *, void *, int);
1089d6ae676Sgmcgarry int	cecgts(void *);
1099d6ae676Sgmcgarry int	cectc(void *, int);
1109d6ae676Sgmcgarry void	cecifc(void *);
1119d6ae676Sgmcgarry 
1129d6ae676Sgmcgarry static int	cecwait(struct cec_softc *, int, int);
1139d6ae676Sgmcgarry static void	cectimeout(void *v);
1149d6ae676Sgmcgarry static int	nec7210_setaddress(struct cec_softc *, int, int);
1159d6ae676Sgmcgarry static void	nec7210_init(struct cec_softc *);
1169d6ae676Sgmcgarry static void	nec7210_ifc(struct cec_softc *);
1179d6ae676Sgmcgarry 
1189d6ae676Sgmcgarry /*
1199d6ae676Sgmcgarry  * Our chipset structure.
1209d6ae676Sgmcgarry  */
1219d6ae676Sgmcgarry struct gpib_chipset_tag cec_ic = {
1229d6ae676Sgmcgarry 	cecreset,
1239d6ae676Sgmcgarry 	NULL,
1249d6ae676Sgmcgarry 	NULL,
1259d6ae676Sgmcgarry 	cecpptest,
1269d6ae676Sgmcgarry 	cecppwatch,
1279d6ae676Sgmcgarry 	cecppclear,
1289d6ae676Sgmcgarry 	cecxfer,
1299d6ae676Sgmcgarry 	cectc,
1309d6ae676Sgmcgarry 	cecgts,
1319d6ae676Sgmcgarry 	cecifc,
1329d6ae676Sgmcgarry 	cecsendcmds,
1339d6ae676Sgmcgarry 	cecsenddata,
13416cd2575Scube 	cecrecvdata,
13516cd2575Scube 	NULL,
13616cd2575Scube 	NULL
1379d6ae676Sgmcgarry };
1389d6ae676Sgmcgarry 
1399d6ae676Sgmcgarry int cecwtimeout = 0x10000;
1409d6ae676Sgmcgarry int cecdmathresh = 3;
1419d6ae676Sgmcgarry 
1429d6ae676Sgmcgarry int
cecprobe(device_t parent,cfdata_t match,void * aux)143ab57cc6fScegger cecprobe(device_t parent, cfdata_t match, void *aux)
1449d6ae676Sgmcgarry {
1459d6ae676Sgmcgarry 	struct isa_attach_args *ia = aux;
1469d6ae676Sgmcgarry 	bus_space_tag_t iot = ia->ia_iot;
1479d6ae676Sgmcgarry 	bus_space_handle_t ioh;
1489d6ae676Sgmcgarry 
1499d6ae676Sgmcgarry 	DPRINTF(DBG_CONFIG, ("cecprobe: called\n"));
1509d6ae676Sgmcgarry 
1519d6ae676Sgmcgarry 	if (ia->ia_nio < 1)
1529d6ae676Sgmcgarry 		return (0);
1539d6ae676Sgmcgarry 	if (ia->ia_nirq < 1)
1549d6ae676Sgmcgarry 		return (0);
1559d6ae676Sgmcgarry 	if (ia->ia_ndrq < 1)
1569d6ae676Sgmcgarry 		return (0);
1579d6ae676Sgmcgarry 
1589d6ae676Sgmcgarry 	if (ISA_DIRECT_CONFIG(ia))
1599d6ae676Sgmcgarry 		return (0);
1609d6ae676Sgmcgarry 
1611308c6d7Sdrochner 	if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT)
1629d6ae676Sgmcgarry 		return (0);
1639d6ae676Sgmcgarry 
1641308c6d7Sdrochner 	if (ia->ia_ndrq > 0 && ia->ia_drq[0].ir_drq == ISA_UNKNOWN_DRQ)
1659d6ae676Sgmcgarry 		ia->ia_ndrq = 0;
1669d6ae676Sgmcgarry 
1679d6ae676Sgmcgarry 	if (bus_space_map(iot, ia->ia_io[0].ir_addr, CEC_IOSIZE, 0, &ioh))
1689d6ae676Sgmcgarry 		return (0);
1699d6ae676Sgmcgarry 
1709d6ae676Sgmcgarry 	/* XXX insert probe here */
1719d6ae676Sgmcgarry 
1729d6ae676Sgmcgarry 	ia->ia_io[0].ir_size = CEC_IOSIZE;
1739d6ae676Sgmcgarry 	ia->ia_niomem = 0;
1749d6ae676Sgmcgarry 
1759d6ae676Sgmcgarry 	bus_space_unmap(iot, ioh, CEC_IOSIZE);
1769d6ae676Sgmcgarry 
1779d6ae676Sgmcgarry 	return (1);
1789d6ae676Sgmcgarry }
1799d6ae676Sgmcgarry 
1809d6ae676Sgmcgarry void
cecattach(device_t parent,device_t self,void * aux)181ab57cc6fScegger cecattach(device_t parent, device_t self, void *aux)
1829d6ae676Sgmcgarry {
183cbab9cadSchs 	struct cec_softc *sc = device_private(self);
1849d6ae676Sgmcgarry 	struct isa_attach_args *ia = aux;
1859d6ae676Sgmcgarry 	struct gpibdev_attach_args ga;
1869d6ae676Sgmcgarry 	bus_size_t maxsize;
1879d6ae676Sgmcgarry 
1889d6ae676Sgmcgarry 	printf("\n");
1899d6ae676Sgmcgarry 
1909d6ae676Sgmcgarry 	DPRINTF(DBG_CONFIG, ("cecattach: called\n"));
1919d6ae676Sgmcgarry 
192cbab9cadSchs 	sc->sc_dev = self;
1939d6ae676Sgmcgarry 	sc->sc_iot = ia->ia_iot;
1949d6ae676Sgmcgarry 	sc->sc_ic = ia->ia_ic;
1959d6ae676Sgmcgarry 
1969d6ae676Sgmcgarry 	if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr, CEC_IOSIZE,
1979d6ae676Sgmcgarry 	    0, &sc->sc_ioh) != 0) {
198cbab9cadSchs 		aprint_error_dev(sc->sc_dev, "unable to map I/O space\n");
1999d6ae676Sgmcgarry 		return;
2009d6ae676Sgmcgarry 	}
2019d6ae676Sgmcgarry 
2029d6ae676Sgmcgarry 	if (ia->ia_ndrq > 0) {
2039d6ae676Sgmcgarry 		sc->sc_flags |= CECF_USEDMA;
2049d6ae676Sgmcgarry 		sc->sc_drq = ia->ia_drq[0].ir_drq;
2059d6ae676Sgmcgarry 
2069d6ae676Sgmcgarry 		(void) isa_drq_alloc(sc->sc_ic, sc->sc_drq);
2079d6ae676Sgmcgarry 		maxsize = isa_dmamaxsize(sc->sc_ic, sc->sc_drq);
2089d6ae676Sgmcgarry 		if (isa_dmamap_create(sc->sc_ic, sc->sc_drq,
2099d6ae676Sgmcgarry 		    maxsize, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW)) {
21071fbb921Smsaitoh 			aprint_error_dev(sc->sc_dev,
21171fbb921Smsaitoh 			    "unable to create map for drq %d\n", sc->sc_drq);
2129d6ae676Sgmcgarry 			sc->sc_flags &= ~CECF_USEDMA;
2139d6ae676Sgmcgarry 		}
2149d6ae676Sgmcgarry 	}
2159d6ae676Sgmcgarry 
2169d6ae676Sgmcgarry 	sc->sc_myaddr = 15;		/* XXX */
2179d6ae676Sgmcgarry 
2189d6ae676Sgmcgarry 	cecreset(sc);
2199d6ae676Sgmcgarry 	(void) nec7210_setaddress(sc, sc->sc_myaddr, -1);
2209d6ae676Sgmcgarry 
2219d6ae676Sgmcgarry 	sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq,
2229d6ae676Sgmcgarry 	    IST_EDGE, IPL_BIO, cecintr, sc);
2239d6ae676Sgmcgarry 	if (sc->sc_ih == NULL) {
224cbab9cadSchs 		aprint_error_dev(sc->sc_dev, "couldn't establish interrupt\n");
2259d6ae676Sgmcgarry 		return;
2269d6ae676Sgmcgarry 	}
2279d6ae676Sgmcgarry 
22888ab7da9Sad 	callout_init(&sc->sc_timeout_ch, 0);
2299d6ae676Sgmcgarry 
2309d6ae676Sgmcgarry 	/* attach MI GPIB bus */
2319d6ae676Sgmcgarry 	cec_ic.cookie = (void *)sc;
2329d6ae676Sgmcgarry 	ga.ga_ic = &cec_ic;
2339d6ae676Sgmcgarry 	ga.ga_address = sc->sc_myaddr;
2349d6ae676Sgmcgarry 	sc->sc_gpib =
2352685996bSthorpej 	    (struct gpib_softc *)config_found(self, &ga, gpibdevprint,
236*c7fb772bSthorpej 	    CFARGS_NONE);
2379d6ae676Sgmcgarry }
2389d6ae676Sgmcgarry 
2399d6ae676Sgmcgarry int
cecintr(void * v)2409d6ae676Sgmcgarry cecintr(void *v)
2419d6ae676Sgmcgarry {
2429d6ae676Sgmcgarry 	struct cec_softc *sc = v;
2439d6ae676Sgmcgarry 	bus_space_tag_t iot = sc->sc_iot;
2449d6ae676Sgmcgarry 	bus_space_handle_t ioh = sc->sc_ioh;
2459d6ae676Sgmcgarry 	u_int8_t stat1, stat2;
2469d6ae676Sgmcgarry 
2479d6ae676Sgmcgarry 	stat1 = bus_space_read_1(iot, ioh, NEC7210_ISR1);
2489d6ae676Sgmcgarry 	stat2 = bus_space_read_1(iot, ioh, NEC7210_ISR2);
2499d6ae676Sgmcgarry 
2509d6ae676Sgmcgarry 	DPRINTF(DBG_INTR, ("cecintr: sc=%p stat1=0x%x stat2=0x%x\n",
2519d6ae676Sgmcgarry 	    sc, stat1, stat2));
2529d6ae676Sgmcgarry 
2539d6ae676Sgmcgarry 	if (sc->sc_flags & CECF_IO) {
2549d6ae676Sgmcgarry 
2559d6ae676Sgmcgarry 		if (sc->sc_flags & CECF_TIMO)
2569d6ae676Sgmcgarry 			callout_stop(&sc->sc_timeout_ch);
2579d6ae676Sgmcgarry 
2589d6ae676Sgmcgarry 		bus_space_write_1(iot, ioh, NEC7210_IMR1, 0);
2599d6ae676Sgmcgarry 		bus_space_write_1(iot, ioh, NEC7210_IMR2, 0);
2609d6ae676Sgmcgarry 		bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCA);
2619d6ae676Sgmcgarry 		sc->sc_flags &= ~(CECF_IO | CECF_READ | CECF_TIMO);
2629d6ae676Sgmcgarry 		if (sc->sc_flags & CECF_USEDMA)
2639d6ae676Sgmcgarry 			isa_dmadone(sc->sc_ic, sc->sc_drq);
2649d6ae676Sgmcgarry 		gpibintr(sc->sc_gpib);
2659d6ae676Sgmcgarry 
2669d6ae676Sgmcgarry 	} else if (sc->sc_flags & CECF_PPOLL) {
2679d6ae676Sgmcgarry 
2689d6ae676Sgmcgarry 		if (cecpptest(sc, sc->sc_ppoll_slave)) {
2699d6ae676Sgmcgarry 			sc->sc_flags &= ~CECF_PPOLL;
2709d6ae676Sgmcgarry 			bus_space_write_1(iot, ioh, NEC7210_IMR2, 0);
2719d6ae676Sgmcgarry 			gpibintr(sc->sc_gpib);
2729d6ae676Sgmcgarry 		}
2739d6ae676Sgmcgarry 
2749d6ae676Sgmcgarry 	}
2759d6ae676Sgmcgarry 	return (1);
2769d6ae676Sgmcgarry }
2779d6ae676Sgmcgarry 
2789d6ae676Sgmcgarry void
cecreset(void * v)2799d6ae676Sgmcgarry cecreset(void *v)
2809d6ae676Sgmcgarry {
2819d6ae676Sgmcgarry 	struct cec_softc *sc = v;
2829d6ae676Sgmcgarry 	u_int8_t cmd;
2839d6ae676Sgmcgarry 
2849d6ae676Sgmcgarry 	DPRINTF(DBG_FOLLOW, ("cecreset: sc=%p\n", sc));
2859d6ae676Sgmcgarry 
2869d6ae676Sgmcgarry 	nec7210_init(sc);
2879d6ae676Sgmcgarry 	nec7210_ifc(sc);
2889d6ae676Sgmcgarry 	/* we're now the system controller */
2899d6ae676Sgmcgarry 
2909d6ae676Sgmcgarry 	/* XXX should be pushed higher */
2919d6ae676Sgmcgarry 
2929d6ae676Sgmcgarry 	/* universal device clear */
2939d6ae676Sgmcgarry 	cmd = GPIBCMD_DCL;
2949d6ae676Sgmcgarry 	(void) cecsendcmds(sc, &cmd, 1);
2959d6ae676Sgmcgarry 	/* delay for devices to clear */
2969d6ae676Sgmcgarry 	DELAY(100000);
2979d6ae676Sgmcgarry }
2989d6ae676Sgmcgarry 
2999d6ae676Sgmcgarry int
cecsendcmds(void * v,void * ptr,int origcnt)3009d6ae676Sgmcgarry cecsendcmds(void *v, void *ptr, int origcnt)
3019d6ae676Sgmcgarry {
3029d6ae676Sgmcgarry 	struct cec_softc *sc = v;
3039d6ae676Sgmcgarry 	bus_space_tag_t iot = sc->sc_iot;
3049d6ae676Sgmcgarry 	bus_space_handle_t ioh = sc->sc_ioh;
3059d6ae676Sgmcgarry 	int cnt = origcnt;
3069d6ae676Sgmcgarry 	u_int8_t *addr = ptr;
3079d6ae676Sgmcgarry 
3089d6ae676Sgmcgarry 	DPRINTF(DBG_FOLLOW, ("cecsendcmds: sc=%p, ptr=%p cnt=%d\n",
3099d6ae676Sgmcgarry 	    sc, ptr, origcnt));
3109d6ae676Sgmcgarry 
3119d6ae676Sgmcgarry 	while (--cnt >= 0) {
3129d6ae676Sgmcgarry 		bus_space_write_1(iot, ioh, NEC7210_CDOR, *addr++);
3139d6ae676Sgmcgarry 		if (cecwait(sc, 0, ISR2_CO))
3149d6ae676Sgmcgarry 			return (origcnt - cnt - 1);
3159d6ae676Sgmcgarry 	}
3169d6ae676Sgmcgarry 	return (origcnt);
3179d6ae676Sgmcgarry }
3189d6ae676Sgmcgarry 
3199d6ae676Sgmcgarry 
3209d6ae676Sgmcgarry int
cecrecvdata(void * v,void * ptr,int origcnt)3219d6ae676Sgmcgarry cecrecvdata(void *v, void *ptr, int origcnt)
3229d6ae676Sgmcgarry {
3239d6ae676Sgmcgarry 	struct cec_softc *sc = v;
3249d6ae676Sgmcgarry 	bus_space_tag_t iot = sc->sc_iot;
3259d6ae676Sgmcgarry 	bus_space_handle_t ioh = sc->sc_ioh;
3269d6ae676Sgmcgarry 	int cnt = origcnt;
3279d6ae676Sgmcgarry 	u_int8_t *addr = ptr;
3289d6ae676Sgmcgarry 
3299d6ae676Sgmcgarry 	DPRINTF(DBG_FOLLOW, ("cecrecvdata: sc=%p, ptr=%p cnt=%d\n",
3309d6ae676Sgmcgarry 	    sc, ptr, origcnt));
3319d6ae676Sgmcgarry 
3329d6ae676Sgmcgarry 	/* XXX holdoff on end */
3339d6ae676Sgmcgarry 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, NEC7210_AUXMR, AUXCMD_RHDF);
3349d6ae676Sgmcgarry 
3359d6ae676Sgmcgarry 	if (cnt) {
3369d6ae676Sgmcgarry 		while (--cnt >= 0) {
3379d6ae676Sgmcgarry 			if (cecwait(sc, ISR1_DI, 0))
3389d6ae676Sgmcgarry 				return (origcnt - cnt - 1);
3399d6ae676Sgmcgarry 			*addr++ = bus_space_read_1(iot, ioh, NEC7210_DIR);
3409d6ae676Sgmcgarry 		}
3419d6ae676Sgmcgarry 	}
3429d6ae676Sgmcgarry 	return (origcnt);
3439d6ae676Sgmcgarry }
3449d6ae676Sgmcgarry 
3459d6ae676Sgmcgarry int
cecsenddata(void * v,void * ptr,int origcnt)3469d6ae676Sgmcgarry cecsenddata(void *v, void *ptr, int origcnt)
3479d6ae676Sgmcgarry {
3489d6ae676Sgmcgarry 	struct cec_softc *sc = v;
3499d6ae676Sgmcgarry 	bus_space_tag_t iot = sc->sc_iot;
3509d6ae676Sgmcgarry 	bus_space_handle_t ioh = sc->sc_ioh;
3519d6ae676Sgmcgarry 	int cnt = origcnt;
3529d6ae676Sgmcgarry 	u_int8_t *addr = ptr;
3539d6ae676Sgmcgarry 
3549d6ae676Sgmcgarry 	DPRINTF(DBG_FOLLOW, ("cecdsenddata: sc=%p, ptr=%p cnt=%d\n",
3559d6ae676Sgmcgarry 	    sc, ptr, origcnt));
3569d6ae676Sgmcgarry 
3579d6ae676Sgmcgarry 	if (cnt) {
3589d6ae676Sgmcgarry 		while (--cnt > 0) {
3599d6ae676Sgmcgarry 			bus_space_write_1(iot, ioh, NEC7210_CDOR, *addr++);
3609d6ae676Sgmcgarry 			if (cecwait(sc, ISR1_DO, 0))
3619d6ae676Sgmcgarry 				return (origcnt - cnt - 1);
3629d6ae676Sgmcgarry 		}
3639d6ae676Sgmcgarry 		bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_SEOI);
3649d6ae676Sgmcgarry 		bus_space_write_1(iot, ioh, NEC7210_CDOR, *addr);
3659d6ae676Sgmcgarry 		(void) cecwait(sc, ISR1_DO, 0);
3669d6ae676Sgmcgarry 	}
3679d6ae676Sgmcgarry 	return (origcnt);
3689d6ae676Sgmcgarry }
3699d6ae676Sgmcgarry 
3709d6ae676Sgmcgarry int
cectc(void * v,int sync)3719d6ae676Sgmcgarry cectc(void *v, int sync)
3729d6ae676Sgmcgarry {
3739d6ae676Sgmcgarry 	struct cec_softc *sc = v;
3749d6ae676Sgmcgarry 	bus_space_tag_t iot = sc->sc_iot;
3759d6ae676Sgmcgarry 	bus_space_handle_t ioh = sc->sc_ioh;
3769d6ae676Sgmcgarry 	u_int8_t adsr;
3779d6ae676Sgmcgarry 	int timo = cecwtimeout;
3789d6ae676Sgmcgarry 
3799d6ae676Sgmcgarry 	DPRINTF(DBG_FOLLOW, ("cectc: sc=%p, sync=%d\n", sc, sync));
3809d6ae676Sgmcgarry 
3819d6ae676Sgmcgarry 	adsr = bus_space_read_1(iot, ioh, NEC7210_ADSR);
3829d6ae676Sgmcgarry #if 0
3839d6ae676Sgmcgarry 	if ((adsr & (ADSR_CIC | ADSR_NATN)) == ADSR_CIC) {
3849d6ae676Sgmcgarry 		DPRINTF(0xff, ("cectc: already CIC\n"));
3859d6ae676Sgmcgarry 		return (0);
3869d6ae676Sgmcgarry 	}
3879d6ae676Sgmcgarry #endif
3889d6ae676Sgmcgarry 
3899d6ae676Sgmcgarry 	if (sync) {
3909d6ae676Sgmcgarry 		bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_RHDF);
3919d6ae676Sgmcgarry 		bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCS);
3929d6ae676Sgmcgarry 	} else {
3939d6ae676Sgmcgarry 		bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCA);
3949d6ae676Sgmcgarry 	}
3959d6ae676Sgmcgarry 
3969d6ae676Sgmcgarry 	/* wait until ATN is asserted */
3979d6ae676Sgmcgarry 	for (;;) {
3989d6ae676Sgmcgarry 		adsr = bus_space_read_1(iot, ioh, NEC7210_ADSR);
3999d6ae676Sgmcgarry 		if (--timo == 0) {
4009d6ae676Sgmcgarry 			DPRINTF(DBG_REPORTTIME, ("cectc: timeout\n"));
4019d6ae676Sgmcgarry 			return (1);
4029d6ae676Sgmcgarry 		}
4039d6ae676Sgmcgarry 		if ((adsr & ADSR_NATN) == 0)
4049d6ae676Sgmcgarry 			break;
4059d6ae676Sgmcgarry 		DELAY(1);
4069d6ae676Sgmcgarry 	}
4079d6ae676Sgmcgarry 
4089d6ae676Sgmcgarry 	return (0);
4099d6ae676Sgmcgarry }
4109d6ae676Sgmcgarry 
4119d6ae676Sgmcgarry int
cecgts(void * v)4129d6ae676Sgmcgarry cecgts(void *v)
4139d6ae676Sgmcgarry {
4149d6ae676Sgmcgarry 	struct cec_softc *sc = v;
4159d6ae676Sgmcgarry 	bus_space_tag_t iot = sc->sc_iot;
4169d6ae676Sgmcgarry 	bus_space_handle_t ioh = sc->sc_ioh;
4179d6ae676Sgmcgarry 	u_int8_t adsr;
4189d6ae676Sgmcgarry 	int timo = cecwtimeout;
4199d6ae676Sgmcgarry 
4209d6ae676Sgmcgarry 	DPRINTF(DBG_FOLLOW, ("cecgts: sc=%p\n", sc));
4219d6ae676Sgmcgarry 
4229d6ae676Sgmcgarry 	adsr = bus_space_read_1(iot, ioh, NEC7210_ADSR);
4239d6ae676Sgmcgarry #if 0
4249d6ae676Sgmcgarry 	if ((adsr & (ADSR_CIC | ADSR_NATN)) == ADSR_NATN) {
4259d6ae676Sgmcgarry 		DPRINTF(0xff, ("cecgts: already standby\n"));
4269d6ae676Sgmcgarry 		return (0);
4279d6ae676Sgmcgarry 	}
4289d6ae676Sgmcgarry #endif
4299d6ae676Sgmcgarry 
4309d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_GTS);
4319d6ae676Sgmcgarry 
4329d6ae676Sgmcgarry 	/* wait unit ATN is released */
4339d6ae676Sgmcgarry 	for (;;) {
4349d6ae676Sgmcgarry 		adsr = bus_space_read_1(iot, ioh, NEC7210_ADSR);
4359d6ae676Sgmcgarry 		if (--timo == 0) {
4369d6ae676Sgmcgarry 			DPRINTF(DBG_REPORTTIME, ("cecgts: timeout\n"));
4379d6ae676Sgmcgarry 			return (1);
4389d6ae676Sgmcgarry 		}
4399d6ae676Sgmcgarry 		if ((adsr & ADSR_NATN) == ADSR_NATN)
4409d6ae676Sgmcgarry 			break;
4419d6ae676Sgmcgarry 		DELAY(1);
4429d6ae676Sgmcgarry 	}
4439d6ae676Sgmcgarry 
4449d6ae676Sgmcgarry 	return (0);
4459d6ae676Sgmcgarry }
4469d6ae676Sgmcgarry 
4479d6ae676Sgmcgarry int
cecpptest(void * v,int slave)4489d6ae676Sgmcgarry cecpptest(void *v, int slave)
4499d6ae676Sgmcgarry {
4509d6ae676Sgmcgarry 	struct cec_softc *sc = v;
4519d6ae676Sgmcgarry 	bus_space_tag_t iot = sc->sc_iot;
4529d6ae676Sgmcgarry 	bus_space_handle_t ioh = sc->sc_ioh;
4539d6ae676Sgmcgarry 	int ppoll;
4549d6ae676Sgmcgarry 
4559d6ae676Sgmcgarry 	DPRINTF(DBG_FOLLOW, ("cecpptest: sc=%p slave=%d\n", sc, slave));
4569d6ae676Sgmcgarry 
4579d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_EPP);
4589d6ae676Sgmcgarry 	DELAY(25);
4599d6ae676Sgmcgarry 	ppoll = bus_space_read_1(iot, ioh, NEC7210_CPTR);
4609d6ae676Sgmcgarry 	DPRINTF(0xff, ("cecpptest: ppoll=%x\n", ppoll));
4619d6ae676Sgmcgarry 	return ((ppoll & (0x80 >> slave)) != 0);
4629d6ae676Sgmcgarry }
4639d6ae676Sgmcgarry 
4649d6ae676Sgmcgarry void
cecppwatch(void * v,int slave)4659d6ae676Sgmcgarry cecppwatch(void *v, int slave)
4669d6ae676Sgmcgarry {
4679d6ae676Sgmcgarry 	struct cec_softc *sc = v;
4689d6ae676Sgmcgarry 	bus_space_tag_t iot = sc->sc_iot;
4699d6ae676Sgmcgarry 	bus_space_handle_t ioh = sc->sc_ioh;
4709d6ae676Sgmcgarry 
4719d6ae676Sgmcgarry 	DPRINTF(DBG_FOLLOW, ("cecppwatch: sc=%p\n", sc));
4729d6ae676Sgmcgarry 
4739d6ae676Sgmcgarry 	sc->sc_flags |= CECF_PPOLL;
4749d6ae676Sgmcgarry 	sc->sc_ppoll_slave = slave;
4759d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_CO);
4769d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_EPP);
4779d6ae676Sgmcgarry }
4789d6ae676Sgmcgarry 
4799d6ae676Sgmcgarry void
cecppclear(void * v)4809d6ae676Sgmcgarry cecppclear(void *v)
4819d6ae676Sgmcgarry {
4829d6ae676Sgmcgarry 	struct cec_softc *sc = v;
4839d6ae676Sgmcgarry 
4849d6ae676Sgmcgarry 	DPRINTF(DBG_FOLLOW, ("cecppclear: sc=%p\n", sc));
4859d6ae676Sgmcgarry 
4869d6ae676Sgmcgarry 	sc->sc_flags &= ~CECF_PPOLL;
4879d6ae676Sgmcgarry 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, NEC7210_IMR2, 0);
4889d6ae676Sgmcgarry }
4899d6ae676Sgmcgarry 
4909d6ae676Sgmcgarry void
cecxfer(void * v,int slave,int sec,void * buf,int count,int dir,int timo)4919d6ae676Sgmcgarry cecxfer(void *v, int slave, int sec, void *buf, int count, int dir, int timo)
4929d6ae676Sgmcgarry {
4939d6ae676Sgmcgarry 	struct cec_softc *sc = v;
4949d6ae676Sgmcgarry 	bus_space_tag_t iot = sc->sc_iot;
4959d6ae676Sgmcgarry 	bus_space_handle_t ioh = sc->sc_ioh;
4969d6ae676Sgmcgarry 
4979d6ae676Sgmcgarry 	DPRINTF(DBG_FOLLOW,
4989d6ae676Sgmcgarry 	    ("cecxfer: slave=%d sec=%d buf=%p count=%d dir=%x timo=%d\n",
4999d6ae676Sgmcgarry 	    slave, sec, buf, count, dir, timo));
5009d6ae676Sgmcgarry 
5019d6ae676Sgmcgarry 	sc->sc_flags |= CECF_IO;
5029d6ae676Sgmcgarry 	if (dir == GPIB_READ)
5039d6ae676Sgmcgarry 		sc->sc_flags |= CECF_READ;
5049d6ae676Sgmcgarry 	if (timo) {
5059d6ae676Sgmcgarry 		sc->sc_flags |= CECF_TIMO;
5069d6ae676Sgmcgarry 		callout_reset(&sc->sc_timeout_ch, 5*hz, cectimeout, sc);
5079d6ae676Sgmcgarry 	}
5089d6ae676Sgmcgarry 
5099d6ae676Sgmcgarry 	if (sc->sc_flags & CECF_READ) {
5109d6ae676Sgmcgarry 		DPRINTF(DBG_FOLLOW, ("cecxfer: DMA read request\n"));
5119d6ae676Sgmcgarry 		if ((sc->sc_flags & CECF_USEDMA) != 0) {
5129d6ae676Sgmcgarry 			isa_dmastart(sc->sc_ic, sc->sc_drq, buf, count, NULL,
5139d6ae676Sgmcgarry 			    DMAMODE_READ | DMAMODE_DEMAND, BUS_DMA_NOWAIT);
5149d6ae676Sgmcgarry 			bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_DMAI);
5159d6ae676Sgmcgarry 			bus_space_write_1(iot, ioh, NEC7210_IMR1, IMR1_END);
5169d6ae676Sgmcgarry 			// XXX (void) cecrecv(sc, slave, sec, NULL, 0);
5179d6ae676Sgmcgarry 			(void) gpibrecv(&cec_ic, slave, sec, NULL, 0);
5189d6ae676Sgmcgarry 		} else {
5199d6ae676Sgmcgarry 			/* XXX this doesn't work */
5209d6ae676Sgmcgarry 			DPRINTF(DBG_FOLLOW, ("cecxfer: polling instead\n"));
5219d6ae676Sgmcgarry 			bus_space_write_1(iot, ioh, NEC7210_IMR1, IMR1_END);
5229d6ae676Sgmcgarry 			// XXX (void) cecrecv(sc, slave, sec, buf, count);
5239d6ae676Sgmcgarry 			(void) gpibrecv(&cec_ic, slave, sec, buf, count);
5249d6ae676Sgmcgarry 			bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_CO);
5259d6ae676Sgmcgarry 		}
5269d6ae676Sgmcgarry 	} else {
5279d6ae676Sgmcgarry 		DPRINTF(DBG_FOLLOW, ("cecxfer: DMA write request\n"));
5289d6ae676Sgmcgarry 		bus_space_write_1(iot, ioh, NEC7210_IMR2, 0);
5299d6ae676Sgmcgarry 		if (count < cecdmathresh ||
5309d6ae676Sgmcgarry 		    (sc->sc_flags & CECF_USEDMA) == 0) {
5319d6ae676Sgmcgarry 			DPRINTF(DBG_FOLLOW, ("cecxfer: polling instead\n"));
5329d6ae676Sgmcgarry 			// XXX (void) cecsend(sc, slave, sec, buf, count);
5339d6ae676Sgmcgarry 			(void) gpibsend(&cec_ic, slave, sec, buf, count);
5349d6ae676Sgmcgarry 			bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_CO);
5359d6ae676Sgmcgarry 			return;
5369d6ae676Sgmcgarry 		}
5379d6ae676Sgmcgarry 		/* we send the last byte with EOI set */
5389d6ae676Sgmcgarry 		isa_dmastart(sc->sc_ic, sc->sc_drq, buf, count-1, NULL,
5399d6ae676Sgmcgarry 		    DMAMODE_WRITE | DMAMODE_DEMAND, BUS_DMA_NOWAIT);
5409d6ae676Sgmcgarry 		bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_DMAO);
5419d6ae676Sgmcgarry 		// XXX (void) cecsend(sc, slave, sec, NULL, 0);
5429d6ae676Sgmcgarry 		(void) gpibsend(&cec_ic, slave, sec, NULL, 0);
5439d6ae676Sgmcgarry 		while (!isa_dmafinished(sc->sc_ic, sc->sc_drq))
5449d6ae676Sgmcgarry 			DELAY(1);
5459d6ae676Sgmcgarry 		(void) cecwait(sc, ISR1_DO, 0);
5469d6ae676Sgmcgarry 		bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_SEOI);
5479d6ae676Sgmcgarry 		bus_space_write_1(iot, ioh, NEC7210_CDOR, *(char *)buf+count);
5489d6ae676Sgmcgarry 		/* generate interrupt */
5499d6ae676Sgmcgarry 		bus_space_write_1(iot, ioh, NEC7210_IMR1, IMR1_DO);
5509d6ae676Sgmcgarry 	}
5519d6ae676Sgmcgarry }
5529d6ae676Sgmcgarry 
5539d6ae676Sgmcgarry void
cecifc(void * v)5549d6ae676Sgmcgarry cecifc(void *v)
5559d6ae676Sgmcgarry {
5569d6ae676Sgmcgarry 	struct cec_softc *sc = v;
5579d6ae676Sgmcgarry 
5589d6ae676Sgmcgarry 	nec7210_ifc(sc);
5599d6ae676Sgmcgarry }
5609d6ae676Sgmcgarry 
5619d6ae676Sgmcgarry static int
nec7210_setaddress(struct cec_softc * sc,int pri,int sec)5629d6ae676Sgmcgarry nec7210_setaddress(struct cec_softc *sc, int pri, int sec)
5639d6ae676Sgmcgarry {
5649d6ae676Sgmcgarry 	bus_space_tag_t iot = sc->sc_iot;
5659d6ae676Sgmcgarry 	bus_space_handle_t ioh = sc->sc_ioh;
5669d6ae676Sgmcgarry 	u_int8_t admr;
5679d6ae676Sgmcgarry 
5689d6ae676Sgmcgarry 	/* assign our primary address */
5699d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_ADDR, (pri & ADDR_MASK));
5709d6ae676Sgmcgarry 
5719d6ae676Sgmcgarry 	admr = ADMR_TRM0 | ADMR_TRM1;
5729d6ae676Sgmcgarry 
5739d6ae676Sgmcgarry 	/* assign our secondary address */
5749d6ae676Sgmcgarry 	if (sec != -1) {
5759d6ae676Sgmcgarry 		bus_space_write_1(iot, ioh, NEC7210_ADDR,
5769d6ae676Sgmcgarry 		    (ADDR_ARS | (sec & ADDR_MASK)));
5779d6ae676Sgmcgarry 		admr |= ADMR_ADM1;
5789d6ae676Sgmcgarry 	} else {
5799d6ae676Sgmcgarry 		/* disable secondary address */
5809d6ae676Sgmcgarry 		bus_space_write_1(iot, ioh, NEC7210_ADDR,
5819d6ae676Sgmcgarry 		    (ADDR_ARS | ADDR_DT | ADDR_DL));
5829d6ae676Sgmcgarry 		admr |= ADMR_ADM0;
5839d6ae676Sgmcgarry 	}
5849d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_ADMR, admr);
5859d6ae676Sgmcgarry 
5869d6ae676Sgmcgarry 	return (0);
5879d6ae676Sgmcgarry }
5889d6ae676Sgmcgarry 
5899d6ae676Sgmcgarry static void
nec7210_init(struct cec_softc * sc)5909d6ae676Sgmcgarry nec7210_init(struct cec_softc *sc)
5919d6ae676Sgmcgarry {
5929d6ae676Sgmcgarry 	bus_space_tag_t iot = sc->sc_iot;
5939d6ae676Sgmcgarry 	bus_space_handle_t ioh = sc->sc_ioh;
5949d6ae676Sgmcgarry 
5959d6ae676Sgmcgarry 	/* reset chip */
5969d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_CRST);
5979d6ae676Sgmcgarry 
5989d6ae676Sgmcgarry 	/* clear interrupts */
5999d6ae676Sgmcgarry 	bus_space_read_1(iot, ioh, NEC7210_CPTR);
6009d6ae676Sgmcgarry 	bus_space_read_1(iot, ioh, NEC7210_ISR1);
6019d6ae676Sgmcgarry 	bus_space_read_1(iot, ioh, NEC7210_ISR2);
6029d6ae676Sgmcgarry 
6039d6ae676Sgmcgarry 	/* initialise interrupts */
6049d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_IMR1, 0);
6059d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_IMR2, 0);
6069d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_SPMR, 0);
6079d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_EOSR, 0);
6089d6ae676Sgmcgarry 
6099d6ae676Sgmcgarry 	/* set internal clock to 8MHz */
6109d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, (AUXMR_ICR | 0x8));
6119d6ae676Sgmcgarry 	/* parallel poll unconfigure */
6129d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, (AUXMR_PPOLL | PPOLL_PPU));
6139d6ae676Sgmcgarry 
6149d6ae676Sgmcgarry 	/* assign our address */
6159d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_ADDR, 0);
6169d6ae676Sgmcgarry 	/* disable secondary address */
6179d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_ADDR,
6189d6ae676Sgmcgarry 	    (ADDR_ARS | ADDR_DT | ADDR_DL));
6199d6ae676Sgmcgarry 
6209d6ae676Sgmcgarry 	/* setup transceivers */
6219d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_ADMR,
6229d6ae676Sgmcgarry 	    (ADMR_ADM0 | ADMR_TRM0 | ADMR_TRM1));
6239d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_AUXMR,
6249d6ae676Sgmcgarry 	    (AUXMR_REGA | AUX_A_HSNORM));
6259d6ae676Sgmcgarry 
6269d6ae676Sgmcgarry 	/* set INT pin to active high */
6279d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXMR_REGB);
6289d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXMR_REGE);
6299d6ae676Sgmcgarry 
6309d6ae676Sgmcgarry 	/* holdoff on end condition */
6319d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, (AUXMR_REGA | AUX_A_HLDE));
6329d6ae676Sgmcgarry 
6339d6ae676Sgmcgarry 	/* reconnect to bus */
6349d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, (AUXMR_CMD | AUXCMD_IEPON));
6359d6ae676Sgmcgarry }
6369d6ae676Sgmcgarry 
6379d6ae676Sgmcgarry /*
6389d6ae676Sgmcgarry  * Place all devices on the bus into quiescient state ready for
6399d6ae676Sgmcgarry  * remote programming.
6409d6ae676Sgmcgarry  * Obviously, we're the system controller upon exit.
6419d6ae676Sgmcgarry  */
6429d6ae676Sgmcgarry void
nec7210_ifc(struct cec_softc * sc)6439d6ae676Sgmcgarry nec7210_ifc(struct cec_softc *sc)
6449d6ae676Sgmcgarry {
6459d6ae676Sgmcgarry 	bus_space_tag_t iot = sc->sc_iot;
6469d6ae676Sgmcgarry 	bus_space_handle_t ioh = sc->sc_ioh;
6479d6ae676Sgmcgarry 
6489d6ae676Sgmcgarry /*XXX*/	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCA);
6499d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_CREN);
6509d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_SIFC);
6519d6ae676Sgmcgarry 	/* wait for devices to enter quiescient state */
6529d6ae676Sgmcgarry 	DELAY(100);
6539d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_CIFC);
6549d6ae676Sgmcgarry 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_SREN);
6559d6ae676Sgmcgarry }
6569d6ae676Sgmcgarry 
6579d6ae676Sgmcgarry static int
cecwait(struct cec_softc * sc,int x1,int x2)6589d6ae676Sgmcgarry cecwait(struct cec_softc *sc, int x1, int x2)
6599d6ae676Sgmcgarry {
6609d6ae676Sgmcgarry 	int timo = cecwtimeout;
6619d6ae676Sgmcgarry 	bus_space_tag_t iot = sc->sc_iot;
6629d6ae676Sgmcgarry 	bus_space_handle_t ioh = sc->sc_ioh;
6639d6ae676Sgmcgarry 	u_int8_t stat1, stat2;
6649d6ae676Sgmcgarry 
6659d6ae676Sgmcgarry 	DPRINTF(DBG_WAIT, ("cecwait: sc=%p, x1=0x%x x2=0x%x\n", sc, x1, x2));
6669d6ae676Sgmcgarry 
6679d6ae676Sgmcgarry 	for (;;) {
6689d6ae676Sgmcgarry 		stat1 = bus_space_read_1(iot, ioh, NEC7210_ISR1);
6699d6ae676Sgmcgarry 		stat2 = bus_space_read_1(iot, ioh, NEC7210_ISR2);
6709d6ae676Sgmcgarry #if 0
6719d6ae676Sgmcgarry 		if ((stat1 & ISR1_ERR)) {
6729d6ae676Sgmcgarry 			DPRINTF(DBG_WAIT, ("cecwait: got ERR\n"));
6739d6ae676Sgmcgarry 			return (1);
6749d6ae676Sgmcgarry 		}
6759d6ae676Sgmcgarry #endif
6769d6ae676Sgmcgarry 		if (--timo == 0) {
6779d6ae676Sgmcgarry 			DPRINTF(DBG_REPORTTIME,
6789d6ae676Sgmcgarry 			    ("cecwait: timeout x1=0x%x x2=0x%x\n", x1, x2));
6799d6ae676Sgmcgarry 			return (1);
6809d6ae676Sgmcgarry 		}
6819d6ae676Sgmcgarry 		if ((stat1 & x1) || (stat2 & x2))
6829d6ae676Sgmcgarry 			break;
6839d6ae676Sgmcgarry 		DELAY(1);
6849d6ae676Sgmcgarry 	}
6859d6ae676Sgmcgarry 	return (0);
6869d6ae676Sgmcgarry }
6879d6ae676Sgmcgarry 
6889d6ae676Sgmcgarry static void
cectimeout(void * v)6899d6ae676Sgmcgarry cectimeout(void *v)
6909d6ae676Sgmcgarry {
6919d6ae676Sgmcgarry 	struct cec_softc *sc = v;
6929d6ae676Sgmcgarry 	bus_space_tag_t iot = sc->sc_iot;
6939d6ae676Sgmcgarry 	bus_space_handle_t ioh = sc->sc_ioh;
6949d6ae676Sgmcgarry 	int s;
6959d6ae676Sgmcgarry 
6969d6ae676Sgmcgarry 	DPRINTF(DBG_FOLLOW, ("cectimeout: sc=%p\n", sc));
6979d6ae676Sgmcgarry 
6989d6ae676Sgmcgarry 	s = splbio();
6999d6ae676Sgmcgarry 	if (sc->sc_flags & CECF_IO) {
7009d6ae676Sgmcgarry 		bus_space_write_1(iot, ioh, NEC7210_IMR1, 0);
7019d6ae676Sgmcgarry 		bus_space_write_2(iot, ioh, NEC7210_IMR2, 0);
7029d6ae676Sgmcgarry 		bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCA);
7039d6ae676Sgmcgarry 		sc->sc_flags &= ~(CECF_IO | CECF_READ | CECF_TIMO);
7049d6ae676Sgmcgarry 		isa_dmaabort(sc->sc_ic, sc->sc_drq);
705cbab9cadSchs 		aprint_error_dev(sc->sc_dev, "%s timeout\n",
7069d6ae676Sgmcgarry 		    sc->sc_flags & CECF_READ ? "read" : "write");
7079d6ae676Sgmcgarry 		gpibintr(sc->sc_gpib);
7089d6ae676Sgmcgarry 	}
7099d6ae676Sgmcgarry 	splx(s);
7109d6ae676Sgmcgarry }
711