cec.c revision 1.11 1 /* $NetBSD: cec.c,v 1.11 2009/05/12 09:10:15 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 *
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.11 2009/05/12 09:10:15 cegger 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(device_t, cfdata_t, void *);
91 void cecattach(device_t, device_t, 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(device_t parent, cfdata_t 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(device_t parent, device_t 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