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