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