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