xref: /netbsd-src/sys/dev/isa/cec.c (revision 8ac07aec990b9d2e483062509d0a9fa5b4f57cf2)
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