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