Home | History | Annotate | Line # | Download | only in isa
      1 /*	$NetBSD: cec.c,v 1.16 2021/08/07 16:19:12 thorpej Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2003 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Gregory McGarry.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __KERNEL_RCSID(0, "$NetBSD: cec.c,v 1.16 2021/08/07 16:19:12 thorpej Exp $");
     34 
     35 #include <sys/param.h>
     36 #include <sys/systm.h>
     37 #include <sys/callout.h>
     38 #include <sys/conf.h>
     39 #include <sys/device.h>
     40 #include <sys/kernel.h>
     41 
     42 #include <sys/bus.h>
     43 
     44 #include <dev/isa/isavar.h>
     45 #include <dev/isa/isadmavar.h>
     46 
     47 #include <dev/gpib/gpibvar.h>
     48 
     49 #include <dev/ic/nec7210reg.h>
     50 
     51 #ifndef DEBUG
     52 #define DEBUG
     53 #endif
     54 
     55 #ifdef DEBUG
     56 int cecdebug = 0x1f;
     57 #define DPRINTF(flag, str)	if (cecdebug & (flag)) printf str
     58 #define DBG_FOLLOW	0x01
     59 #define DBG_CONFIG	0x02
     60 #define DBG_INTR	0x04
     61 #define DBG_REPORTTIME	0x08
     62 #define DBG_FAIL	0x10
     63 #define DBG_WAIT	0x20
     64 #else
     65 #define DPRINTF(flag, str)	/* nothing */
     66 #endif
     67 
     68 #define CEC_IOSIZE	8
     69 
     70 struct cec_softc {
     71 	device_t sc_dev;		/* generic device glue */
     72 
     73 	bus_space_tag_t sc_iot;
     74 	bus_space_handle_t sc_ioh;
     75 	isa_chipset_tag_t sc_ic;
     76 	int sc_drq;
     77 	void *sc_ih;
     78 
     79 	int sc_myaddr;			/* my address */
     80 	struct gpib_softc *sc_gpib;
     81 
     82 	volatile int sc_flags;
     83 #define	CECF_IO		0x1
     84 #define	CECF_PPOLL	0x4
     85 #define	CECF_READ	0x8
     86 #define	CECF_TIMO	0x10
     87 #define CECF_USEDMA	0x20
     88 	int sc_ppoll_slave;		/* XXX stash our ppoll address */
     89 	callout_t sc_timeout_ch;
     90 };
     91 
     92 int	cecprobe(device_t, cfdata_t, void *);
     93 void	cecattach(device_t, device_t, void *);
     94 
     95 CFATTACH_DECL_NEW(cec, sizeof(struct cec_softc),
     96 	cecprobe, cecattach, NULL, NULL);
     97 
     98 void	cecreset(void *);
     99 int	cecpptest(void *, int);
    100 void	cecppwatch(void *, int);
    101 void	cecppclear(void *);
    102 void	cecxfer(void *, int, int, void *, int, int, int);
    103 void	cecgo(void *v);
    104 int	cecintr(void *);
    105 int	cecsendcmds(void *, void *, int);
    106 int	cecsenddata(void *, void *, int);
    107 int	cecrecvdata(void *, void *, int);
    108 int	cecgts(void *);
    109 int	cectc(void *, int);
    110 void	cecifc(void *);
    111 
    112 static int	cecwait(struct cec_softc *, int, int);
    113 static void	cectimeout(void *v);
    114 static int	nec7210_setaddress(struct cec_softc *, int, int);
    115 static void	nec7210_init(struct cec_softc *);
    116 static void	nec7210_ifc(struct cec_softc *);
    117 
    118 /*
    119  * Our chipset structure.
    120  */
    121 struct gpib_chipset_tag cec_ic = {
    122 	cecreset,
    123 	NULL,
    124 	NULL,
    125 	cecpptest,
    126 	cecppwatch,
    127 	cecppclear,
    128 	cecxfer,
    129 	cectc,
    130 	cecgts,
    131 	cecifc,
    132 	cecsendcmds,
    133 	cecsenddata,
    134 	cecrecvdata,
    135 	NULL,
    136 	NULL
    137 };
    138 
    139 int cecwtimeout = 0x10000;
    140 int cecdmathresh = 3;
    141 
    142 int
    143 cecprobe(device_t parent, cfdata_t match, void *aux)
    144 {
    145 	struct isa_attach_args *ia = aux;
    146 	bus_space_tag_t iot = ia->ia_iot;
    147 	bus_space_handle_t ioh;
    148 
    149 	DPRINTF(DBG_CONFIG, ("cecprobe: called\n"));
    150 
    151 	if (ia->ia_nio < 1)
    152 		return (0);
    153 	if (ia->ia_nirq < 1)
    154 		return (0);
    155 	if (ia->ia_ndrq < 1)
    156 		return (0);
    157 
    158 	if (ISA_DIRECT_CONFIG(ia))
    159 		return (0);
    160 
    161 	if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT)
    162 		return (0);
    163 
    164 	if (ia->ia_ndrq > 0 && ia->ia_drq[0].ir_drq == ISA_UNKNOWN_DRQ)
    165 		ia->ia_ndrq = 0;
    166 
    167 	if (bus_space_map(iot, ia->ia_io[0].ir_addr, CEC_IOSIZE, 0, &ioh))
    168 		return (0);
    169 
    170 	/* XXX insert probe here */
    171 
    172 	ia->ia_io[0].ir_size = CEC_IOSIZE;
    173 	ia->ia_niomem = 0;
    174 
    175 	bus_space_unmap(iot, ioh, CEC_IOSIZE);
    176 
    177 	return (1);
    178 }
    179 
    180 void
    181 cecattach(device_t parent, device_t self, void *aux)
    182 {
    183 	struct cec_softc *sc = device_private(self);
    184 	struct isa_attach_args *ia = aux;
    185 	struct gpibdev_attach_args ga;
    186 	bus_size_t maxsize;
    187 
    188 	printf("\n");
    189 
    190 	DPRINTF(DBG_CONFIG, ("cecattach: called\n"));
    191 
    192 	sc->sc_dev = self;
    193 	sc->sc_iot = ia->ia_iot;
    194 	sc->sc_ic = ia->ia_ic;
    195 
    196 	if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr, CEC_IOSIZE,
    197 	    0, &sc->sc_ioh) != 0) {
    198 		aprint_error_dev(sc->sc_dev, "unable to map I/O space\n");
    199 		return;
    200 	}
    201 
    202 	if (ia->ia_ndrq > 0) {
    203 		sc->sc_flags |= CECF_USEDMA;
    204 		sc->sc_drq = ia->ia_drq[0].ir_drq;
    205 
    206 		(void) isa_drq_alloc(sc->sc_ic, sc->sc_drq);
    207 		maxsize = isa_dmamaxsize(sc->sc_ic, sc->sc_drq);
    208 		if (isa_dmamap_create(sc->sc_ic, sc->sc_drq,
    209 		    maxsize, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW)) {
    210 			aprint_error_dev(sc->sc_dev,
    211 			    "unable to create map for drq %d\n", sc->sc_drq);
    212 			sc->sc_flags &= ~CECF_USEDMA;
    213 		}
    214 	}
    215 
    216 	sc->sc_myaddr = 15;		/* XXX */
    217 
    218 	cecreset(sc);
    219 	(void) nec7210_setaddress(sc, sc->sc_myaddr, -1);
    220 
    221 	sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq,
    222 	    IST_EDGE, IPL_BIO, cecintr, sc);
    223 	if (sc->sc_ih == NULL) {
    224 		aprint_error_dev(sc->sc_dev, "couldn't establish interrupt\n");
    225 		return;
    226 	}
    227 
    228 	callout_init(&sc->sc_timeout_ch, 0);
    229 
    230 	/* attach MI GPIB bus */
    231 	cec_ic.cookie = (void *)sc;
    232 	ga.ga_ic = &cec_ic;
    233 	ga.ga_address = sc->sc_myaddr;
    234 	sc->sc_gpib =
    235 	    (struct gpib_softc *)config_found(self, &ga, gpibdevprint,
    236 	    CFARGS_NONE);
    237 }
    238 
    239 int
    240 cecintr(void *v)
    241 {
    242 	struct cec_softc *sc = v;
    243 	bus_space_tag_t iot = sc->sc_iot;
    244 	bus_space_handle_t ioh = sc->sc_ioh;
    245 	u_int8_t stat1, stat2;
    246 
    247 	stat1 = bus_space_read_1(iot, ioh, NEC7210_ISR1);
    248 	stat2 = bus_space_read_1(iot, ioh, NEC7210_ISR2);
    249 
    250 	DPRINTF(DBG_INTR, ("cecintr: sc=%p stat1=0x%x stat2=0x%x\n",
    251 	    sc, stat1, stat2));
    252 
    253 	if (sc->sc_flags & CECF_IO) {
    254 
    255 		if (sc->sc_flags & CECF_TIMO)
    256 			callout_stop(&sc->sc_timeout_ch);
    257 
    258 		bus_space_write_1(iot, ioh, NEC7210_IMR1, 0);
    259 		bus_space_write_1(iot, ioh, NEC7210_IMR2, 0);
    260 		bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCA);
    261 		sc->sc_flags &= ~(CECF_IO | CECF_READ | CECF_TIMO);
    262 		if (sc->sc_flags & CECF_USEDMA)
    263 			isa_dmadone(sc->sc_ic, sc->sc_drq);
    264 		gpibintr(sc->sc_gpib);
    265 
    266 	} else if (sc->sc_flags & CECF_PPOLL) {
    267 
    268 		if (cecpptest(sc, sc->sc_ppoll_slave)) {
    269 			sc->sc_flags &= ~CECF_PPOLL;
    270 			bus_space_write_1(iot, ioh, NEC7210_IMR2, 0);
    271 			gpibintr(sc->sc_gpib);
    272 		}
    273 
    274 	}
    275 	return (1);
    276 }
    277 
    278 void
    279 cecreset(void *v)
    280 {
    281 	struct cec_softc *sc = v;
    282 	u_int8_t cmd;
    283 
    284 	DPRINTF(DBG_FOLLOW, ("cecreset: sc=%p\n", sc));
    285 
    286 	nec7210_init(sc);
    287 	nec7210_ifc(sc);
    288 	/* we're now the system controller */
    289 
    290 	/* XXX should be pushed higher */
    291 
    292 	/* universal device clear */
    293 	cmd = GPIBCMD_DCL;
    294 	(void) cecsendcmds(sc, &cmd, 1);
    295 	/* delay for devices to clear */
    296 	DELAY(100000);
    297 }
    298 
    299 int
    300 cecsendcmds(void *v, void *ptr, int origcnt)
    301 {
    302 	struct cec_softc *sc = v;
    303 	bus_space_tag_t iot = sc->sc_iot;
    304 	bus_space_handle_t ioh = sc->sc_ioh;
    305 	int cnt = origcnt;
    306 	u_int8_t *addr = ptr;
    307 
    308 	DPRINTF(DBG_FOLLOW, ("cecsendcmds: sc=%p, ptr=%p cnt=%d\n",
    309 	    sc, ptr, origcnt));
    310 
    311 	while (--cnt >= 0) {
    312 		bus_space_write_1(iot, ioh, NEC7210_CDOR, *addr++);
    313 		if (cecwait(sc, 0, ISR2_CO))
    314 			return (origcnt - cnt - 1);
    315 	}
    316 	return (origcnt);
    317 }
    318 
    319 
    320 int
    321 cecrecvdata(void *v, void *ptr, int origcnt)
    322 {
    323 	struct cec_softc *sc = v;
    324 	bus_space_tag_t iot = sc->sc_iot;
    325 	bus_space_handle_t ioh = sc->sc_ioh;
    326 	int cnt = origcnt;
    327 	u_int8_t *addr = ptr;
    328 
    329 	DPRINTF(DBG_FOLLOW, ("cecrecvdata: sc=%p, ptr=%p cnt=%d\n",
    330 	    sc, ptr, origcnt));
    331 
    332 	/* XXX holdoff on end */
    333 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, NEC7210_AUXMR, AUXCMD_RHDF);
    334 
    335 	if (cnt) {
    336 		while (--cnt >= 0) {
    337 			if (cecwait(sc, ISR1_DI, 0))
    338 				return (origcnt - cnt - 1);
    339 			*addr++ = bus_space_read_1(iot, ioh, NEC7210_DIR);
    340 		}
    341 	}
    342 	return (origcnt);
    343 }
    344 
    345 int
    346 cecsenddata(void *v, void *ptr, int origcnt)
    347 {
    348 	struct cec_softc *sc = v;
    349 	bus_space_tag_t iot = sc->sc_iot;
    350 	bus_space_handle_t ioh = sc->sc_ioh;
    351 	int cnt = origcnt;
    352 	u_int8_t *addr = ptr;
    353 
    354 	DPRINTF(DBG_FOLLOW, ("cecdsenddata: sc=%p, ptr=%p cnt=%d\n",
    355 	    sc, ptr, origcnt));
    356 
    357 	if (cnt) {
    358 		while (--cnt > 0) {
    359 			bus_space_write_1(iot, ioh, NEC7210_CDOR, *addr++);
    360 			if (cecwait(sc, ISR1_DO, 0))
    361 				return (origcnt - cnt - 1);
    362 		}
    363 		bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_SEOI);
    364 		bus_space_write_1(iot, ioh, NEC7210_CDOR, *addr);
    365 		(void) cecwait(sc, ISR1_DO, 0);
    366 	}
    367 	return (origcnt);
    368 }
    369 
    370 int
    371 cectc(void *v, int sync)
    372 {
    373 	struct cec_softc *sc = v;
    374 	bus_space_tag_t iot = sc->sc_iot;
    375 	bus_space_handle_t ioh = sc->sc_ioh;
    376 	u_int8_t adsr;
    377 	int timo = cecwtimeout;
    378 
    379 	DPRINTF(DBG_FOLLOW, ("cectc: sc=%p, sync=%d\n", sc, sync));
    380 
    381 	adsr = bus_space_read_1(iot, ioh, NEC7210_ADSR);
    382 #if 0
    383 	if ((adsr & (ADSR_CIC | ADSR_NATN)) == ADSR_CIC) {
    384 		DPRINTF(0xff, ("cectc: already CIC\n"));
    385 		return (0);
    386 	}
    387 #endif
    388 
    389 	if (sync) {
    390 		bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_RHDF);
    391 		bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCS);
    392 	} else {
    393 		bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCA);
    394 	}
    395 
    396 	/* wait until ATN is asserted */
    397 	for (;;) {
    398 		adsr = bus_space_read_1(iot, ioh, NEC7210_ADSR);
    399 		if (--timo == 0) {
    400 			DPRINTF(DBG_REPORTTIME, ("cectc: timeout\n"));
    401 			return (1);
    402 		}
    403 		if ((adsr & ADSR_NATN) == 0)
    404 			break;
    405 		DELAY(1);
    406 	}
    407 
    408 	return (0);
    409 }
    410 
    411 int
    412 cecgts(void *v)
    413 {
    414 	struct cec_softc *sc = v;
    415 	bus_space_tag_t iot = sc->sc_iot;
    416 	bus_space_handle_t ioh = sc->sc_ioh;
    417 	u_int8_t adsr;
    418 	int timo = cecwtimeout;
    419 
    420 	DPRINTF(DBG_FOLLOW, ("cecgts: sc=%p\n", sc));
    421 
    422 	adsr = bus_space_read_1(iot, ioh, NEC7210_ADSR);
    423 #if 0
    424 	if ((adsr & (ADSR_CIC | ADSR_NATN)) == ADSR_NATN) {
    425 		DPRINTF(0xff, ("cecgts: already standby\n"));
    426 		return (0);
    427 	}
    428 #endif
    429 
    430 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_GTS);
    431 
    432 	/* wait unit ATN is released */
    433 	for (;;) {
    434 		adsr = bus_space_read_1(iot, ioh, NEC7210_ADSR);
    435 		if (--timo == 0) {
    436 			DPRINTF(DBG_REPORTTIME, ("cecgts: timeout\n"));
    437 			return (1);
    438 		}
    439 		if ((adsr & ADSR_NATN) == ADSR_NATN)
    440 			break;
    441 		DELAY(1);
    442 	}
    443 
    444 	return (0);
    445 }
    446 
    447 int
    448 cecpptest(void *v, int slave)
    449 {
    450 	struct cec_softc *sc = v;
    451 	bus_space_tag_t iot = sc->sc_iot;
    452 	bus_space_handle_t ioh = sc->sc_ioh;
    453 	int ppoll;
    454 
    455 	DPRINTF(DBG_FOLLOW, ("cecpptest: sc=%p slave=%d\n", sc, slave));
    456 
    457 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_EPP);
    458 	DELAY(25);
    459 	ppoll = bus_space_read_1(iot, ioh, NEC7210_CPTR);
    460 	DPRINTF(0xff, ("cecpptest: ppoll=%x\n", ppoll));
    461 	return ((ppoll & (0x80 >> slave)) != 0);
    462 }
    463 
    464 void
    465 cecppwatch(void *v, int slave)
    466 {
    467 	struct cec_softc *sc = v;
    468 	bus_space_tag_t iot = sc->sc_iot;
    469 	bus_space_handle_t ioh = sc->sc_ioh;
    470 
    471 	DPRINTF(DBG_FOLLOW, ("cecppwatch: sc=%p\n", sc));
    472 
    473 	sc->sc_flags |= CECF_PPOLL;
    474 	sc->sc_ppoll_slave = slave;
    475 	bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_CO);
    476 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_EPP);
    477 }
    478 
    479 void
    480 cecppclear(void *v)
    481 {
    482 	struct cec_softc *sc = v;
    483 
    484 	DPRINTF(DBG_FOLLOW, ("cecppclear: sc=%p\n", sc));
    485 
    486 	sc->sc_flags &= ~CECF_PPOLL;
    487 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, NEC7210_IMR2, 0);
    488 }
    489 
    490 void
    491 cecxfer(void *v, int slave, int sec, void *buf, int count, int dir, int timo)
    492 {
    493 	struct cec_softc *sc = v;
    494 	bus_space_tag_t iot = sc->sc_iot;
    495 	bus_space_handle_t ioh = sc->sc_ioh;
    496 
    497 	DPRINTF(DBG_FOLLOW,
    498 	    ("cecxfer: slave=%d sec=%d buf=%p count=%d dir=%x timo=%d\n",
    499 	    slave, sec, buf, count, dir, timo));
    500 
    501 	sc->sc_flags |= CECF_IO;
    502 	if (dir == GPIB_READ)
    503 		sc->sc_flags |= CECF_READ;
    504 	if (timo) {
    505 		sc->sc_flags |= CECF_TIMO;
    506 		callout_reset(&sc->sc_timeout_ch, 5*hz, cectimeout, sc);
    507 	}
    508 
    509 	if (sc->sc_flags & CECF_READ) {
    510 		DPRINTF(DBG_FOLLOW, ("cecxfer: DMA read request\n"));
    511 		if ((sc->sc_flags & CECF_USEDMA) != 0) {
    512 			isa_dmastart(sc->sc_ic, sc->sc_drq, buf, count, NULL,
    513 			    DMAMODE_READ | DMAMODE_DEMAND, BUS_DMA_NOWAIT);
    514 			bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_DMAI);
    515 			bus_space_write_1(iot, ioh, NEC7210_IMR1, IMR1_END);
    516 			// XXX (void) cecrecv(sc, slave, sec, NULL, 0);
    517 			(void) gpibrecv(&cec_ic, slave, sec, NULL, 0);
    518 		} else {
    519 			/* XXX this doesn't work */
    520 			DPRINTF(DBG_FOLLOW, ("cecxfer: polling instead\n"));
    521 			bus_space_write_1(iot, ioh, NEC7210_IMR1, IMR1_END);
    522 			// XXX (void) cecrecv(sc, slave, sec, buf, count);
    523 			(void) gpibrecv(&cec_ic, slave, sec, buf, count);
    524 			bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_CO);
    525 		}
    526 	} else {
    527 		DPRINTF(DBG_FOLLOW, ("cecxfer: DMA write request\n"));
    528 		bus_space_write_1(iot, ioh, NEC7210_IMR2, 0);
    529 		if (count < cecdmathresh ||
    530 		    (sc->sc_flags & CECF_USEDMA) == 0) {
    531 			DPRINTF(DBG_FOLLOW, ("cecxfer: polling instead\n"));
    532 			// XXX (void) cecsend(sc, slave, sec, buf, count);
    533 			(void) gpibsend(&cec_ic, slave, sec, buf, count);
    534 			bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_CO);
    535 			return;
    536 		}
    537 		/* we send the last byte with EOI set */
    538 		isa_dmastart(sc->sc_ic, sc->sc_drq, buf, count-1, NULL,
    539 		    DMAMODE_WRITE | DMAMODE_DEMAND, BUS_DMA_NOWAIT);
    540 		bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_DMAO);
    541 		// XXX (void) cecsend(sc, slave, sec, NULL, 0);
    542 		(void) gpibsend(&cec_ic, slave, sec, NULL, 0);
    543 		while (!isa_dmafinished(sc->sc_ic, sc->sc_drq))
    544 			DELAY(1);
    545 		(void) cecwait(sc, ISR1_DO, 0);
    546 		bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_SEOI);
    547 		bus_space_write_1(iot, ioh, NEC7210_CDOR, *(char *)buf+count);
    548 		/* generate interrupt */
    549 		bus_space_write_1(iot, ioh, NEC7210_IMR1, IMR1_DO);
    550 	}
    551 }
    552 
    553 void
    554 cecifc(void *v)
    555 {
    556 	struct cec_softc *sc = v;
    557 
    558 	nec7210_ifc(sc);
    559 }
    560 
    561 static int
    562 nec7210_setaddress(struct cec_softc *sc, int pri, int sec)
    563 {
    564 	bus_space_tag_t iot = sc->sc_iot;
    565 	bus_space_handle_t ioh = sc->sc_ioh;
    566 	u_int8_t admr;
    567 
    568 	/* assign our primary address */
    569 	bus_space_write_1(iot, ioh, NEC7210_ADDR, (pri & ADDR_MASK));
    570 
    571 	admr = ADMR_TRM0 | ADMR_TRM1;
    572 
    573 	/* assign our secondary address */
    574 	if (sec != -1) {
    575 		bus_space_write_1(iot, ioh, NEC7210_ADDR,
    576 		    (ADDR_ARS | (sec & ADDR_MASK)));
    577 		admr |= ADMR_ADM1;
    578 	} else {
    579 		/* disable secondary address */
    580 		bus_space_write_1(iot, ioh, NEC7210_ADDR,
    581 		    (ADDR_ARS | ADDR_DT | ADDR_DL));
    582 		admr |= ADMR_ADM0;
    583 	}
    584 	bus_space_write_1(iot, ioh, NEC7210_ADMR, admr);
    585 
    586 	return (0);
    587 }
    588 
    589 static void
    590 nec7210_init(struct cec_softc *sc)
    591 {
    592 	bus_space_tag_t iot = sc->sc_iot;
    593 	bus_space_handle_t ioh = sc->sc_ioh;
    594 
    595 	/* reset chip */
    596 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_CRST);
    597 
    598 	/* clear interrupts */
    599 	bus_space_read_1(iot, ioh, NEC7210_CPTR);
    600 	bus_space_read_1(iot, ioh, NEC7210_ISR1);
    601 	bus_space_read_1(iot, ioh, NEC7210_ISR2);
    602 
    603 	/* initialise interrupts */
    604 	bus_space_write_1(iot, ioh, NEC7210_IMR1, 0);
    605 	bus_space_write_1(iot, ioh, NEC7210_IMR2, 0);
    606 	bus_space_write_1(iot, ioh, NEC7210_SPMR, 0);
    607 	bus_space_write_1(iot, ioh, NEC7210_EOSR, 0);
    608 
    609 	/* set internal clock to 8MHz */
    610 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, (AUXMR_ICR | 0x8));
    611 	/* parallel poll unconfigure */
    612 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, (AUXMR_PPOLL | PPOLL_PPU));
    613 
    614 	/* assign our address */
    615 	bus_space_write_1(iot, ioh, NEC7210_ADDR, 0);
    616 	/* disable secondary address */
    617 	bus_space_write_1(iot, ioh, NEC7210_ADDR,
    618 	    (ADDR_ARS | ADDR_DT | ADDR_DL));
    619 
    620 	/* setup transceivers */
    621 	bus_space_write_1(iot, ioh, NEC7210_ADMR,
    622 	    (ADMR_ADM0 | ADMR_TRM0 | ADMR_TRM1));
    623 	bus_space_write_1(iot, ioh, NEC7210_AUXMR,
    624 	    (AUXMR_REGA | AUX_A_HSNORM));
    625 
    626 	/* set INT pin to active high */
    627 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXMR_REGB);
    628 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXMR_REGE);
    629 
    630 	/* holdoff on end condition */
    631 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, (AUXMR_REGA | AUX_A_HLDE));
    632 
    633 	/* reconnect to bus */
    634 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, (AUXMR_CMD | AUXCMD_IEPON));
    635 }
    636 
    637 /*
    638  * Place all devices on the bus into quiescient state ready for
    639  * remote programming.
    640  * Obviously, we're the system controller upon exit.
    641  */
    642 void
    643 nec7210_ifc(struct cec_softc *sc)
    644 {
    645 	bus_space_tag_t iot = sc->sc_iot;
    646 	bus_space_handle_t ioh = sc->sc_ioh;
    647 
    648 /*XXX*/	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCA);
    649 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_CREN);
    650 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_SIFC);
    651 	/* wait for devices to enter quiescient state */
    652 	DELAY(100);
    653 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_CIFC);
    654 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_SREN);
    655 }
    656 
    657 static int
    658 cecwait(struct cec_softc *sc, int x1, int x2)
    659 {
    660 	int timo = cecwtimeout;
    661 	bus_space_tag_t iot = sc->sc_iot;
    662 	bus_space_handle_t ioh = sc->sc_ioh;
    663 	u_int8_t stat1, stat2;
    664 
    665 	DPRINTF(DBG_WAIT, ("cecwait: sc=%p, x1=0x%x x2=0x%x\n", sc, x1, x2));
    666 
    667 	for (;;) {
    668 		stat1 = bus_space_read_1(iot, ioh, NEC7210_ISR1);
    669 		stat2 = bus_space_read_1(iot, ioh, NEC7210_ISR2);
    670 #if 0
    671 		if ((stat1 & ISR1_ERR)) {
    672 			DPRINTF(DBG_WAIT, ("cecwait: got ERR\n"));
    673 			return (1);
    674 		}
    675 #endif
    676 		if (--timo == 0) {
    677 			DPRINTF(DBG_REPORTTIME,
    678 			    ("cecwait: timeout x1=0x%x x2=0x%x\n", x1, x2));
    679 			return (1);
    680 		}
    681 		if ((stat1 & x1) || (stat2 & x2))
    682 			break;
    683 		DELAY(1);
    684 	}
    685 	return (0);
    686 }
    687 
    688 static void
    689 cectimeout(void *v)
    690 {
    691 	struct cec_softc *sc = v;
    692 	bus_space_tag_t iot = sc->sc_iot;
    693 	bus_space_handle_t ioh = sc->sc_ioh;
    694 	int s;
    695 
    696 	DPRINTF(DBG_FOLLOW, ("cectimeout: sc=%p\n", sc));
    697 
    698 	s = splbio();
    699 	if (sc->sc_flags & CECF_IO) {
    700 		bus_space_write_1(iot, ioh, NEC7210_IMR1, 0);
    701 		bus_space_write_2(iot, ioh, NEC7210_IMR2, 0);
    702 		bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCA);
    703 		sc->sc_flags &= ~(CECF_IO | CECF_READ | CECF_TIMO);
    704 		isa_dmaabort(sc->sc_ic, sc->sc_drq);
    705 		aprint_error_dev(sc->sc_dev, "%s timeout\n",
    706 		    sc->sc_flags & CECF_READ ? "read" : "write");
    707 		gpibintr(sc->sc_gpib);
    708 	}
    709 	splx(s);
    710 }
    711