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