Home | History | Annotate | Line # | Download | only in isa
cec.c revision 1.7
      1 /*	$NetBSD: cec.c,v 1.7 2007/10/19 12:00:15 ad 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.7 2007/10/19 12:00:15 ad 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 		printf("%s: unable to map I/O space\n", sc->sc_dev.dv_xname);
    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 			printf("%s: unable to create map for drq %d\n",
    215 			    sc->sc_dev.dv_xname, 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 		printf("%s: couldn't establish interrupt\n",
    229 		    sc->sc_dev.dv_xname);
    230 		return;
    231 	}
    232 
    233 	callout_init(&sc->sc_timeout_ch, 0);
    234 
    235 	/* attach MI GPIB bus */
    236 	cec_ic.cookie = (void *)sc;
    237 	ga.ga_ic = &cec_ic;
    238 	ga.ga_address = sc->sc_myaddr;
    239 	sc->sc_gpib =
    240 	    (struct gpib_softc *)config_found(self, &ga, gpibdevprint);
    241 }
    242 
    243 int
    244 cecintr(void *v)
    245 {
    246 	struct cec_softc *sc = v;
    247 	bus_space_tag_t iot = sc->sc_iot;
    248 	bus_space_handle_t ioh = sc->sc_ioh;
    249 	u_int8_t stat1, stat2;
    250 
    251 	stat1 = bus_space_read_1(iot, ioh, NEC7210_ISR1);
    252 	stat2 = bus_space_read_1(iot, ioh, NEC7210_ISR2);
    253 
    254 	DPRINTF(DBG_INTR, ("cecintr: sc=%p stat1=0x%x stat2=0x%x\n",
    255 	    sc, stat1, stat2));
    256 
    257 	if (sc->sc_flags & CECF_IO) {
    258 
    259 		if (sc->sc_flags & CECF_TIMO)
    260 			callout_stop(&sc->sc_timeout_ch);
    261 
    262 		bus_space_write_1(iot, ioh, NEC7210_IMR1, 0);
    263 		bus_space_write_1(iot, ioh, NEC7210_IMR2, 0);
    264 		bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCA);
    265 		sc->sc_flags &= ~(CECF_IO | CECF_READ | CECF_TIMO);
    266 		if (sc->sc_flags & CECF_USEDMA)
    267 			isa_dmadone(sc->sc_ic, sc->sc_drq);
    268 		gpibintr(sc->sc_gpib);
    269 
    270 	} else if (sc->sc_flags & CECF_PPOLL) {
    271 
    272 		if (cecpptest(sc, sc->sc_ppoll_slave)) {
    273 			sc->sc_flags &= ~CECF_PPOLL;
    274 			bus_space_write_1(iot, ioh, NEC7210_IMR2, 0);
    275 			gpibintr(sc->sc_gpib);
    276 		}
    277 
    278 	}
    279 	return (1);
    280 }
    281 
    282 void
    283 cecreset(void *v)
    284 {
    285 	struct cec_softc *sc = v;
    286 	u_int8_t cmd;
    287 
    288 	DPRINTF(DBG_FOLLOW, ("cecreset: sc=%p\n", sc));
    289 
    290 	nec7210_init(sc);
    291 	nec7210_ifc(sc);
    292 	/* we're now the system controller */
    293 
    294 	/* XXX should be pushed higher */
    295 
    296 	/* universal device clear */
    297 	cmd = GPIBCMD_DCL;
    298 	(void) cecsendcmds(sc, &cmd, 1);
    299 	/* delay for devices to clear */
    300 	DELAY(100000);
    301 }
    302 
    303 int
    304 cecsendcmds(void *v, void *ptr, int origcnt)
    305 {
    306 	struct cec_softc *sc = v;
    307 	bus_space_tag_t iot = sc->sc_iot;
    308 	bus_space_handle_t ioh = sc->sc_ioh;
    309 	int cnt = origcnt;
    310 	u_int8_t *addr = ptr;
    311 
    312 	DPRINTF(DBG_FOLLOW, ("cecsendcmds: sc=%p, ptr=%p cnt=%d\n",
    313 	    sc, ptr, origcnt));
    314 
    315 	while (--cnt >= 0) {
    316 		bus_space_write_1(iot, ioh, NEC7210_CDOR, *addr++);
    317 		if (cecwait(sc, 0, ISR2_CO))
    318 			return (origcnt - cnt - 1);
    319 	}
    320 	return (origcnt);
    321 }
    322 
    323 
    324 int
    325 cecrecvdata(void *v, void *ptr, int origcnt)
    326 {
    327 	struct cec_softc *sc = v;
    328 	bus_space_tag_t iot = sc->sc_iot;
    329 	bus_space_handle_t ioh = sc->sc_ioh;
    330 	int cnt = origcnt;
    331 	u_int8_t *addr = ptr;
    332 
    333 	DPRINTF(DBG_FOLLOW, ("cecrecvdata: sc=%p, ptr=%p cnt=%d\n",
    334 	    sc, ptr, origcnt));
    335 
    336 	/* XXX holdoff on end */
    337 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, NEC7210_AUXMR, AUXCMD_RHDF);
    338 
    339 	if (cnt) {
    340 		while (--cnt >= 0) {
    341 			if (cecwait(sc, ISR1_DI, 0))
    342 				return (origcnt - cnt - 1);
    343 			*addr++ = bus_space_read_1(iot, ioh, NEC7210_DIR);
    344 		}
    345 	}
    346 	return (origcnt);
    347 }
    348 
    349 int
    350 cecsenddata(void *v, void *ptr, int origcnt)
    351 {
    352 	struct cec_softc *sc = v;
    353 	bus_space_tag_t iot = sc->sc_iot;
    354 	bus_space_handle_t ioh = sc->sc_ioh;
    355 	int cnt = origcnt;
    356 	u_int8_t *addr = ptr;
    357 
    358 	DPRINTF(DBG_FOLLOW, ("cecdsenddata: sc=%p, ptr=%p cnt=%d\n",
    359 	    sc, ptr, origcnt));
    360 
    361 	if (cnt) {
    362 		while (--cnt > 0) {
    363 			bus_space_write_1(iot, ioh, NEC7210_CDOR, *addr++);
    364 			if (cecwait(sc, ISR1_DO, 0))
    365 				return (origcnt - cnt - 1);
    366 		}
    367 		bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_SEOI);
    368 		bus_space_write_1(iot, ioh, NEC7210_CDOR, *addr);
    369 		(void) cecwait(sc, ISR1_DO, 0);
    370 	}
    371 	return (origcnt);
    372 }
    373 
    374 int
    375 cectc(void *v, int sync)
    376 {
    377 	struct cec_softc *sc = v;
    378 	bus_space_tag_t iot = sc->sc_iot;
    379 	bus_space_handle_t ioh = sc->sc_ioh;
    380 	u_int8_t adsr;
    381 	int timo = cecwtimeout;
    382 
    383 	DPRINTF(DBG_FOLLOW, ("cectc: sc=%p, sync=%d\n", sc, sync));
    384 
    385 	adsr = bus_space_read_1(iot, ioh, NEC7210_ADSR);
    386 #if 0
    387 	if ((adsr & (ADSR_CIC | ADSR_NATN)) == ADSR_CIC) {
    388 		DPRINTF(0xff, ("cectc: already CIC\n"));
    389 		return (0);
    390 	}
    391 #endif
    392 
    393 	if (sync) {
    394 		bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_RHDF);
    395 		bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCS);
    396 	} else {
    397 		bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCA);
    398 	}
    399 
    400 	/* wait until ATN is asserted */
    401 	for (;;) {
    402 		adsr = bus_space_read_1(iot, ioh, NEC7210_ADSR);
    403 		if (--timo == 0) {
    404 			DPRINTF(DBG_REPORTTIME, ("cectc: timeout\n"));
    405 			return (1);
    406 		}
    407 		if ((adsr & ADSR_NATN) == 0)
    408 			break;
    409 		DELAY(1);
    410 	}
    411 
    412 	return (0);
    413 }
    414 
    415 int
    416 cecgts(void *v)
    417 {
    418 	struct cec_softc *sc = v;
    419 	bus_space_tag_t iot = sc->sc_iot;
    420 	bus_space_handle_t ioh = sc->sc_ioh;
    421 	u_int8_t adsr;
    422 	int timo = cecwtimeout;
    423 
    424 	DPRINTF(DBG_FOLLOW, ("cecgts: sc=%p\n", sc));
    425 
    426 	adsr = bus_space_read_1(iot, ioh, NEC7210_ADSR);
    427 #if 0
    428 	if ((adsr & (ADSR_CIC | ADSR_NATN)) == ADSR_NATN) {
    429 		DPRINTF(0xff, ("cecgts: already standby\n"));
    430 		return (0);
    431 	}
    432 #endif
    433 
    434 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_GTS);
    435 
    436 	/* wait unit ATN is released */
    437 	for (;;) {
    438 		adsr = bus_space_read_1(iot, ioh, NEC7210_ADSR);
    439 		if (--timo == 0) {
    440 			DPRINTF(DBG_REPORTTIME, ("cecgts: timeout\n"));
    441 			return (1);
    442 		}
    443 		if ((adsr & ADSR_NATN) == ADSR_NATN)
    444 			break;
    445 		DELAY(1);
    446 	}
    447 
    448 	return (0);
    449 }
    450 
    451 int
    452 cecpptest(void *v, int slave)
    453 {
    454 	struct cec_softc *sc = v;
    455 	bus_space_tag_t iot = sc->sc_iot;
    456 	bus_space_handle_t ioh = sc->sc_ioh;
    457 	int ppoll;
    458 
    459 	DPRINTF(DBG_FOLLOW, ("cecpptest: sc=%p slave=%d\n", sc, slave));
    460 
    461 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_EPP);
    462 	DELAY(25);
    463 	ppoll = bus_space_read_1(iot, ioh, NEC7210_CPTR);
    464 	DPRINTF(0xff, ("cecpptest: ppoll=%x\n", ppoll));
    465 	return ((ppoll & (0x80 >> slave)) != 0);
    466 }
    467 
    468 void
    469 cecppwatch(void *v, int slave)
    470 {
    471 	struct cec_softc *sc = v;
    472 	bus_space_tag_t iot = sc->sc_iot;
    473 	bus_space_handle_t ioh = sc->sc_ioh;
    474 
    475 	DPRINTF(DBG_FOLLOW, ("cecppwatch: sc=%p\n", sc));
    476 
    477 	sc->sc_flags |= CECF_PPOLL;
    478 	sc->sc_ppoll_slave = slave;
    479 	bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_CO);
    480 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_EPP);
    481 }
    482 
    483 void
    484 cecppclear(void *v)
    485 {
    486 	struct cec_softc *sc = v;
    487 
    488 	DPRINTF(DBG_FOLLOW, ("cecppclear: sc=%p\n", sc));
    489 
    490 	sc->sc_flags &= ~CECF_PPOLL;
    491 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, NEC7210_IMR2, 0);
    492 }
    493 
    494 void
    495 cecxfer(void *v, int slave, int sec, void *buf, int count, int dir, int timo)
    496 {
    497 	struct cec_softc *sc = v;
    498 	bus_space_tag_t iot = sc->sc_iot;
    499 	bus_space_handle_t ioh = sc->sc_ioh;
    500 
    501 	DPRINTF(DBG_FOLLOW,
    502 	    ("cecxfer: slave=%d sec=%d buf=%p count=%d dir=%x timo=%d\n",
    503 	    slave, sec, buf, count, dir, timo));
    504 
    505 	sc->sc_flags |= CECF_IO;
    506 	if (dir == GPIB_READ)
    507 		sc->sc_flags |= CECF_READ;
    508 	if (timo) {
    509 		sc->sc_flags |= CECF_TIMO;
    510 		callout_reset(&sc->sc_timeout_ch, 5*hz, cectimeout, sc);
    511 	}
    512 
    513 	if (sc->sc_flags & CECF_READ) {
    514 		DPRINTF(DBG_FOLLOW, ("cecxfer: DMA read request\n"));
    515 		if ((sc->sc_flags & CECF_USEDMA) != 0) {
    516 			isa_dmastart(sc->sc_ic, sc->sc_drq, buf, count, NULL,
    517 			    DMAMODE_READ | DMAMODE_DEMAND, BUS_DMA_NOWAIT);
    518 			bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_DMAI);
    519 			bus_space_write_1(iot, ioh, NEC7210_IMR1, IMR1_END);
    520 			// XXX (void) cecrecv(sc, slave, sec, NULL, 0);
    521 			(void) gpibrecv(&cec_ic, slave, sec, NULL, 0);
    522 		} else {
    523 			/* XXX this doesn't work */
    524 			DPRINTF(DBG_FOLLOW, ("cecxfer: polling instead\n"));
    525 			bus_space_write_1(iot, ioh, NEC7210_IMR1, IMR1_END);
    526 			// XXX (void) cecrecv(sc, slave, sec, buf, count);
    527 			(void) gpibrecv(&cec_ic, slave, sec, buf, count);
    528 			bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_CO);
    529 		}
    530 	} else {
    531 		DPRINTF(DBG_FOLLOW, ("cecxfer: DMA write request\n"));
    532 		bus_space_write_1(iot, ioh, NEC7210_IMR2, 0);
    533 		if (count < cecdmathresh ||
    534 		    (sc->sc_flags & CECF_USEDMA) == 0) {
    535 			DPRINTF(DBG_FOLLOW, ("cecxfer: polling instead\n"));
    536 			// XXX (void) cecsend(sc, slave, sec, buf, count);
    537 			(void) gpibsend(&cec_ic, slave, sec, buf, count);
    538 			bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_CO);
    539 			return;
    540 		}
    541 		/* we send the last byte with EOI set */
    542 		isa_dmastart(sc->sc_ic, sc->sc_drq, buf, count-1, NULL,
    543 		    DMAMODE_WRITE | DMAMODE_DEMAND, BUS_DMA_NOWAIT);
    544 		bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_DMAO);
    545 		// XXX (void) cecsend(sc, slave, sec, NULL, 0);
    546 		(void) gpibsend(&cec_ic, slave, sec, NULL, 0);
    547 		while (!isa_dmafinished(sc->sc_ic, sc->sc_drq))
    548 			DELAY(1);
    549 		(void) cecwait(sc, ISR1_DO, 0);
    550 		bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_SEOI);
    551 		bus_space_write_1(iot, ioh, NEC7210_CDOR, *(char *)buf+count);
    552 		/* generate interrupt */
    553 		bus_space_write_1(iot, ioh, NEC7210_IMR1, IMR1_DO);
    554 	}
    555 }
    556 
    557 void
    558 cecifc(void *v)
    559 {
    560 	struct cec_softc *sc = v;
    561 
    562 	nec7210_ifc(sc);
    563 }
    564 
    565 static int
    566 nec7210_setaddress(struct cec_softc *sc, int pri, int sec)
    567 {
    568 	bus_space_tag_t iot = sc->sc_iot;
    569 	bus_space_handle_t ioh = sc->sc_ioh;
    570 	u_int8_t admr;
    571 
    572 	/* assign our primary address */
    573 	bus_space_write_1(iot, ioh, NEC7210_ADDR, (pri & ADDR_MASK));
    574 
    575 	admr = ADMR_TRM0 | ADMR_TRM1;
    576 
    577 	/* assign our secondary address */
    578 	if (sec != -1) {
    579 		bus_space_write_1(iot, ioh, NEC7210_ADDR,
    580 		    (ADDR_ARS | (sec & ADDR_MASK)));
    581 		admr |= ADMR_ADM1;
    582 	} else {
    583 		/* disable secondary address */
    584 		bus_space_write_1(iot, ioh, NEC7210_ADDR,
    585 		    (ADDR_ARS | ADDR_DT | ADDR_DL));
    586 		admr |= ADMR_ADM0;
    587 	}
    588 	bus_space_write_1(iot, ioh, NEC7210_ADMR, admr);
    589 
    590 	return (0);
    591 }
    592 
    593 static void
    594 nec7210_init(struct cec_softc *sc)
    595 {
    596 	bus_space_tag_t iot = sc->sc_iot;
    597 	bus_space_handle_t ioh = sc->sc_ioh;
    598 
    599 	/* reset chip */
    600 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_CRST);
    601 
    602 	/* clear interrupts */
    603 	bus_space_read_1(iot, ioh, NEC7210_CPTR);
    604 	bus_space_read_1(iot, ioh, NEC7210_ISR1);
    605 	bus_space_read_1(iot, ioh, NEC7210_ISR2);
    606 
    607 	/* initialise interrupts */
    608 	bus_space_write_1(iot, ioh, NEC7210_IMR1, 0);
    609 	bus_space_write_1(iot, ioh, NEC7210_IMR2, 0);
    610 	bus_space_write_1(iot, ioh, NEC7210_SPMR, 0);
    611 	bus_space_write_1(iot, ioh, NEC7210_EOSR, 0);
    612 
    613 	/* set internal clock to 8MHz */
    614 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, (AUXMR_ICR | 0x8));
    615 	/* parallel poll unconfigure */
    616 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, (AUXMR_PPOLL | PPOLL_PPU));
    617 
    618 	/* assign our address */
    619 	bus_space_write_1(iot, ioh, NEC7210_ADDR, 0);
    620 	/* disable secondary address */
    621 	bus_space_write_1(iot, ioh, NEC7210_ADDR,
    622 	    (ADDR_ARS | ADDR_DT | ADDR_DL));
    623 
    624 	/* setup transceivers */
    625 	bus_space_write_1(iot, ioh, NEC7210_ADMR,
    626 	    (ADMR_ADM0 | ADMR_TRM0 | ADMR_TRM1));
    627 	bus_space_write_1(iot, ioh, NEC7210_AUXMR,
    628 	    (AUXMR_REGA | AUX_A_HSNORM));
    629 
    630 	/* set INT pin to active high */
    631 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXMR_REGB);
    632 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXMR_REGE);
    633 
    634 	/* holdoff on end condition */
    635 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, (AUXMR_REGA | AUX_A_HLDE));
    636 
    637 	/* reconnect to bus */
    638 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, (AUXMR_CMD | AUXCMD_IEPON));
    639 }
    640 
    641 /*
    642  * Place all devices on the bus into quiescient state ready for
    643  * remote programming.
    644  * Obviously, we're the system controller upon exit.
    645  */
    646 void
    647 nec7210_ifc(struct cec_softc *sc)
    648 {
    649 	bus_space_tag_t iot = sc->sc_iot;
    650 	bus_space_handle_t ioh = sc->sc_ioh;
    651 
    652 /*XXX*/	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCA);
    653 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_CREN);
    654 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_SIFC);
    655 	/* wait for devices to enter quiescient state */
    656 	DELAY(100);
    657 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_CIFC);
    658 	bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_SREN);
    659 }
    660 
    661 static int
    662 cecwait(struct cec_softc *sc, int x1, int x2)
    663 {
    664 	int timo = cecwtimeout;
    665 	bus_space_tag_t iot = sc->sc_iot;
    666 	bus_space_handle_t ioh = sc->sc_ioh;
    667 	u_int8_t stat1, stat2;
    668 
    669 	DPRINTF(DBG_WAIT, ("cecwait: sc=%p, x1=0x%x x2=0x%x\n", sc, x1, x2));
    670 
    671 	for (;;) {
    672 		stat1 = bus_space_read_1(iot, ioh, NEC7210_ISR1);
    673 		stat2 = bus_space_read_1(iot, ioh, NEC7210_ISR2);
    674 #if 0
    675 		if ((stat1 & ISR1_ERR)) {
    676 			DPRINTF(DBG_WAIT, ("cecwait: got ERR\n"));
    677 			return (1);
    678 		}
    679 #endif
    680 		if (--timo == 0) {
    681 			DPRINTF(DBG_REPORTTIME,
    682 			    ("cecwait: timeout x1=0x%x x2=0x%x\n", x1, x2));
    683 			return (1);
    684 		}
    685 		if ((stat1 & x1) || (stat2 & x2))
    686 			break;
    687 		DELAY(1);
    688 	}
    689 	return (0);
    690 }
    691 
    692 static void
    693 cectimeout(void *v)
    694 {
    695 	struct cec_softc *sc = v;
    696 	bus_space_tag_t iot = sc->sc_iot;
    697 	bus_space_handle_t ioh = sc->sc_ioh;
    698 	int s;
    699 
    700 	DPRINTF(DBG_FOLLOW, ("cectimeout: sc=%p\n", sc));
    701 
    702 	s = splbio();
    703 	if (sc->sc_flags & CECF_IO) {
    704 		bus_space_write_1(iot, ioh, NEC7210_IMR1, 0);
    705 		bus_space_write_2(iot, ioh, NEC7210_IMR2, 0);
    706 		bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCA);
    707 		sc->sc_flags &= ~(CECF_IO | CECF_READ | CECF_TIMO);
    708 		isa_dmaabort(sc->sc_ic, sc->sc_drq);
    709 		printf("%s: %s timeout\n", sc->sc_dev.dv_xname,
    710 		    sc->sc_flags & CECF_READ ? "read" : "write");
    711 		gpibintr(sc->sc_gpib);
    712 	}
    713 	splx(s);
    714 }
    715