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