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