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