fhpib.c revision 1.35 1 1.35 he /* $NetBSD: fhpib.c,v 1.35 2007/07/12 20:39:01 he Exp $ */
2 1.19 thorpej
3 1.19 thorpej /*-
4 1.19 thorpej * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
5 1.19 thorpej * All rights reserved.
6 1.19 thorpej *
7 1.19 thorpej * This code is derived from software contributed to The NetBSD Foundation
8 1.19 thorpej * by Jason R. Thorpe.
9 1.19 thorpej *
10 1.19 thorpej * Redistribution and use in source and binary forms, with or without
11 1.19 thorpej * modification, are permitted provided that the following conditions
12 1.19 thorpej * are met:
13 1.19 thorpej * 1. Redistributions of source code must retain the above copyright
14 1.19 thorpej * notice, this list of conditions and the following disclaimer.
15 1.19 thorpej * 2. Redistributions in binary form must reproduce the above copyright
16 1.19 thorpej * notice, this list of conditions and the following disclaimer in the
17 1.19 thorpej * documentation and/or other materials provided with the distribution.
18 1.19 thorpej * 3. All advertising materials mentioning features or use of this software
19 1.19 thorpej * must display the following acknowledgement:
20 1.19 thorpej * This product includes software developed by the NetBSD
21 1.19 thorpej * Foundation, Inc. and its contributors.
22 1.19 thorpej * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.19 thorpej * contributors may be used to endorse or promote products derived
24 1.19 thorpej * from this software without specific prior written permission.
25 1.19 thorpej *
26 1.19 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.19 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.19 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.19 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.19 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.19 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.19 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.19 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.19 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.19 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.19 thorpej * POSSIBILITY OF SUCH DAMAGE.
37 1.19 thorpej */
38 1.5 cgd
39 1.1 cgd /*
40 1.4 mycroft * Copyright (c) 1982, 1990, 1993
41 1.4 mycroft * The Regents of the University of California. All rights reserved.
42 1.1 cgd *
43 1.1 cgd * Redistribution and use in source and binary forms, with or without
44 1.1 cgd * modification, are permitted provided that the following conditions
45 1.1 cgd * are met:
46 1.1 cgd * 1. Redistributions of source code must retain the above copyright
47 1.1 cgd * notice, this list of conditions and the following disclaimer.
48 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
49 1.1 cgd * notice, this list of conditions and the following disclaimer in the
50 1.1 cgd * documentation and/or other materials provided with the distribution.
51 1.27 agc * 3. Neither the name of the University nor the names of its contributors
52 1.1 cgd * may be used to endorse or promote products derived from this software
53 1.1 cgd * without specific prior written permission.
54 1.1 cgd *
55 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
56 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
57 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
58 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
59 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
60 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
61 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
62 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
63 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
64 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65 1.1 cgd * SUCH DAMAGE.
66 1.1 cgd *
67 1.5 cgd * @(#)fhpib.c 8.2 (Berkeley) 1/12/94
68 1.1 cgd */
69 1.1 cgd
70 1.1 cgd /*
71 1.1 cgd * 98625A/B HPIB driver
72 1.1 cgd */
73 1.22 gmcgarry
74 1.22 gmcgarry #include <sys/cdefs.h>
75 1.35 he __KERNEL_RCSID(0, "$NetBSD: fhpib.c,v 1.35 2007/07/12 20:39:01 he Exp $");
76 1.1 cgd
77 1.4 mycroft #include <sys/param.h>
78 1.4 mycroft #include <sys/systm.h>
79 1.21 thorpej #include <sys/callout.h>
80 1.6 mycroft #include <sys/kernel.h>
81 1.4 mycroft #include <sys/buf.h>
82 1.14 thorpej #include <sys/device.h>
83 1.14 thorpej
84 1.14 thorpej #include <machine/autoconf.h>
85 1.17 thorpej #include <machine/intr.h>
86 1.14 thorpej
87 1.14 thorpej #include <hp300/dev/diovar.h>
88 1.14 thorpej #include <hp300/dev/diodevs.h>
89 1.14 thorpej
90 1.14 thorpej #include <hp300/dev/dmavar.h>
91 1.4 mycroft
92 1.4 mycroft #include <hp300/dev/fhpibreg.h>
93 1.4 mycroft #include <hp300/dev/hpibvar.h>
94 1.1 cgd
95 1.1 cgd /*
96 1.1 cgd * Inline version of fhpibwait to be used in places where
97 1.1 cgd * we don't worry about getting hung.
98 1.1 cgd */
99 1.11 thorpej #define FHPIBWAIT(hd, m) while (((hd)->hpib_intr & (m)) == 0) DELAY(1)
100 1.1 cgd
101 1.1 cgd #ifdef DEBUG
102 1.1 cgd int fhpibdebugunit = -1;
103 1.1 cgd int fhpibdebug = 0;
104 1.1 cgd #define FDB_FAIL 0x01
105 1.1 cgd #define FDB_DMA 0x02
106 1.1 cgd #define FDB_WAIT 0x04
107 1.1 cgd #define FDB_PPOLL 0x08
108 1.1 cgd
109 1.1 cgd int dopriodma = 0; /* use high priority DMA */
110 1.25 wiz int doworddma = 1; /* non-zero if we should attempt word DMA */
111 1.1 cgd int doppollint = 1; /* use ppoll interrupts instead of watchdog */
112 1.4 mycroft int fhpibppolldelay = 50;
113 1.1 cgd #endif
114 1.1 cgd
115 1.29 thorpej static void fhpibifc(struct fhpibdevice *);
116 1.29 thorpej static void fhpibdmadone(void *);
117 1.29 thorpej static int fhpibwait(struct fhpibdevice *, int);
118 1.29 thorpej
119 1.29 thorpej static void fhpibreset(struct hpibbus_softc *);
120 1.29 thorpej static int fhpibsend(struct hpibbus_softc *, int, int, void *, int);
121 1.29 thorpej static int fhpibrecv(struct hpibbus_softc *, int, int, void *, int);
122 1.29 thorpej static int fhpibppoll(struct hpibbus_softc *);
123 1.29 thorpej static void fhpibppwatch(void *);
124 1.29 thorpej static void fhpibgo(struct hpibbus_softc *, int, int, void *, int, int,
125 1.29 thorpej int);
126 1.29 thorpej static void fhpibdone(struct hpibbus_softc *);
127 1.29 thorpej static int fhpibintr(void *);
128 1.7 thorpej
129 1.7 thorpej /*
130 1.7 thorpej * Our controller ops structure.
131 1.7 thorpej */
132 1.29 thorpej static struct hpib_controller fhpib_controller = {
133 1.7 thorpej fhpibreset,
134 1.7 thorpej fhpibsend,
135 1.7 thorpej fhpibrecv,
136 1.7 thorpej fhpibppoll,
137 1.7 thorpej fhpibppwatch,
138 1.7 thorpej fhpibgo,
139 1.7 thorpej fhpibdone,
140 1.7 thorpej fhpibintr
141 1.7 thorpej };
142 1.7 thorpej
143 1.14 thorpej struct fhpib_softc {
144 1.14 thorpej struct device sc_dev; /* generic device glue */
145 1.14 thorpej struct fhpibdevice *sc_regs; /* device registers */
146 1.14 thorpej int sc_cmd;
147 1.14 thorpej struct hpibbus_softc *sc_hpibbus; /* XXX */
148 1.21 thorpej struct callout sc_dmadone_ch;
149 1.21 thorpej struct callout sc_ppwatch_ch;
150 1.14 thorpej };
151 1.14 thorpej
152 1.29 thorpej static int fhpibmatch(struct device *, struct cfdata *, void *);
153 1.29 thorpej static void fhpibattach(struct device *, struct device *, void *);
154 1.14 thorpej
155 1.24 thorpej CFATTACH_DECL(fhpib, sizeof(struct fhpib_softc),
156 1.24 thorpej fhpibmatch, fhpibattach, NULL, NULL);
157 1.14 thorpej
158 1.29 thorpej static int
159 1.29 thorpej fhpibmatch(struct device *parent, struct cfdata *match, void *aux)
160 1.1 cgd {
161 1.14 thorpej struct dio_attach_args *da = aux;
162 1.7 thorpej
163 1.14 thorpej if (da->da_id == DIO_DEVICE_ID_FHPIB)
164 1.33 tsutsui return 1;
165 1.7 thorpej
166 1.33 tsutsui return 0;
167 1.8 thorpej }
168 1.8 thorpej
169 1.29 thorpej static void
170 1.29 thorpej fhpibattach(struct device *parent, struct device *self, void *aux)
171 1.14 thorpej {
172 1.14 thorpej struct fhpib_softc *sc = (struct fhpib_softc *)self;
173 1.14 thorpej struct dio_attach_args *da = aux;
174 1.14 thorpej struct hpibdev_attach_args ha;
175 1.34 tsutsui bus_space_handle_t bsh;
176 1.14 thorpej
177 1.34 tsutsui if (bus_space_map(da->da_bst, da->da_addr, da->da_size, 0, &bsh)) {
178 1.14 thorpej printf("\n%s: can't map registers\n", self->dv_xname);
179 1.14 thorpej return;
180 1.14 thorpej }
181 1.34 tsutsui sc->sc_regs = bus_space_vaddr(da->da_bst, bsh);
182 1.14 thorpej
183 1.26 gmcgarry printf(": %s\n", DIO_DEVICE_DESC_FHPIB);
184 1.8 thorpej
185 1.14 thorpej /* Establish the interrupt handler. */
186 1.33 tsutsui (void)dio_intr_establish(fhpibintr, sc, da->da_ipl, IPL_BIO);
187 1.14 thorpej
188 1.35 he callout_init(&sc->sc_dmadone_ch, 0);
189 1.35 he callout_init(&sc->sc_ppwatch_ch, 0);
190 1.21 thorpej
191 1.14 thorpej ha.ha_ops = &fhpib_controller;
192 1.14 thorpej ha.ha_type = HPIBC; /* XXX */
193 1.14 thorpej ha.ha_ba = HPIBC_BA;
194 1.14 thorpej ha.ha_softcpp = &sc->sc_hpibbus; /* XXX */
195 1.14 thorpej (void)config_found(self, &ha, hpibdevprint);
196 1.1 cgd }
197 1.1 cgd
198 1.29 thorpej static void
199 1.29 thorpej fhpibreset(struct hpibbus_softc *hs)
200 1.1 cgd {
201 1.31 thorpej struct fhpib_softc *sc =
202 1.31 thorpej (struct fhpib_softc *)device_parent(&hs->sc_dev);
203 1.14 thorpej struct fhpibdevice *hd = sc->sc_regs;
204 1.1 cgd
205 1.1 cgd hd->hpib_cid = 0xFF;
206 1.1 cgd DELAY(100);
207 1.1 cgd hd->hpib_cmd = CT_8BIT;
208 1.1 cgd hd->hpib_ar = AR_ARONC;
209 1.1 cgd fhpibifc(hd);
210 1.1 cgd hd->hpib_ie = IDS_IE;
211 1.1 cgd hd->hpib_data = C_DCL;
212 1.1 cgd DELAY(100000);
213 1.1 cgd /*
214 1.25 wiz * See if we can do word DMA.
215 1.1 cgd * If so, we should be able to write and read back the appropos bit.
216 1.1 cgd */
217 1.1 cgd hd->hpib_ie |= IDS_WDMA;
218 1.1 cgd if (hd->hpib_ie & IDS_WDMA) {
219 1.1 cgd hd->hpib_ie &= ~IDS_WDMA;
220 1.1 cgd hs->sc_flags |= HPIBF_DMA16;
221 1.1 cgd #ifdef DEBUG
222 1.1 cgd if (fhpibdebug & FDB_DMA)
223 1.25 wiz printf("fhpibtype: %s has word DMA\n",
224 1.14 thorpej sc->sc_dev.dv_xname);
225 1.1 cgd #endif
226 1.1 cgd }
227 1.1 cgd }
228 1.1 cgd
229 1.29 thorpej static void
230 1.29 thorpej fhpibifc(struct fhpibdevice *hd)
231 1.1 cgd {
232 1.33 tsutsui
233 1.1 cgd hd->hpib_cmd |= CT_IFC;
234 1.1 cgd hd->hpib_cmd |= CT_INITFIFO;
235 1.1 cgd DELAY(100);
236 1.1 cgd hd->hpib_cmd &= ~CT_IFC;
237 1.1 cgd hd->hpib_cmd |= CT_REN;
238 1.1 cgd hd->hpib_stat = ST_ATN;
239 1.1 cgd }
240 1.1 cgd
241 1.29 thorpej static int
242 1.29 thorpej fhpibsend(struct hpibbus_softc *hs, int slave, int sec, void *ptr, int origcnt)
243 1.1 cgd {
244 1.31 thorpej struct fhpib_softc *sc =
245 1.31 thorpej (struct fhpib_softc *)device_parent(&hs->sc_dev);
246 1.14 thorpej struct fhpibdevice *hd = sc->sc_regs;
247 1.15 scottr int cnt = origcnt;
248 1.15 scottr int timo;
249 1.7 thorpej char *addr = ptr;
250 1.1 cgd
251 1.1 cgd hd->hpib_stat = 0;
252 1.1 cgd hd->hpib_imask = IM_IDLE | IM_ROOM;
253 1.1 cgd if (fhpibwait(hd, IM_IDLE) < 0)
254 1.1 cgd goto senderr;
255 1.1 cgd hd->hpib_stat = ST_ATN;
256 1.1 cgd hd->hpib_data = C_UNL;
257 1.1 cgd hd->hpib_data = C_TAG + hs->sc_ba;
258 1.1 cgd hd->hpib_data = C_LAG + slave;
259 1.6 mycroft if (sec < 0) {
260 1.6 mycroft if (sec == -2) /* selected device clear KLUDGE */
261 1.6 mycroft hd->hpib_data = C_SDC;
262 1.6 mycroft } else
263 1.1 cgd hd->hpib_data = C_SCG + sec;
264 1.1 cgd if (fhpibwait(hd, IM_IDLE) < 0)
265 1.1 cgd goto senderr;
266 1.1 cgd if (cnt) {
267 1.1 cgd hd->hpib_stat = ST_WRITE;
268 1.1 cgd while (--cnt) {
269 1.1 cgd hd->hpib_data = *addr++;
270 1.1 cgd timo = hpibtimeout;
271 1.1 cgd while ((hd->hpib_intr & IM_ROOM) == 0) {
272 1.1 cgd if (--timo <= 0)
273 1.1 cgd goto senderr;
274 1.11 thorpej DELAY(1);
275 1.1 cgd }
276 1.1 cgd }
277 1.1 cgd hd->hpib_stat = ST_EOI;
278 1.1 cgd hd->hpib_data = *addr;
279 1.1 cgd FHPIBWAIT(hd, IM_ROOM);
280 1.1 cgd hd->hpib_stat = ST_ATN;
281 1.1 cgd /* XXX: HP-UX claims bug with CS80 transparent messages */
282 1.1 cgd if (sec == 0x12)
283 1.1 cgd DELAY(150);
284 1.1 cgd hd->hpib_data = C_UNL;
285 1.1 cgd (void) fhpibwait(hd, IM_IDLE);
286 1.1 cgd }
287 1.1 cgd hd->hpib_imask = 0;
288 1.33 tsutsui return origcnt;
289 1.6 mycroft
290 1.1 cgd senderr:
291 1.1 cgd hd->hpib_imask = 0;
292 1.1 cgd fhpibifc(hd);
293 1.1 cgd #ifdef DEBUG
294 1.1 cgd if (fhpibdebug & FDB_FAIL) {
295 1.13 christos printf("%s: fhpibsend failed: slave %d, sec %x, ",
296 1.14 thorpej sc->sc_dev.dv_xname, slave, sec);
297 1.13 christos printf("sent %d of %d bytes\n", origcnt-cnt-1, origcnt);
298 1.1 cgd }
299 1.1 cgd #endif
300 1.33 tsutsui return origcnt - cnt - 1;
301 1.1 cgd }
302 1.1 cgd
303 1.29 thorpej static int
304 1.29 thorpej fhpibrecv(struct hpibbus_softc *hs, int slave, int sec, void *ptr, int origcnt)
305 1.1 cgd {
306 1.31 thorpej struct fhpib_softc *sc =
307 1.31 thorpej (struct fhpib_softc *)device_parent(&hs->sc_dev);
308 1.14 thorpej struct fhpibdevice *hd = sc->sc_regs;
309 1.15 scottr int cnt = origcnt;
310 1.15 scottr int timo;
311 1.7 thorpej char *addr = ptr;
312 1.1 cgd
313 1.6 mycroft /*
314 1.6 mycroft * Slave < 0 implies continuation of a previous receive
315 1.6 mycroft * that probably timed out.
316 1.6 mycroft */
317 1.6 mycroft if (slave >= 0) {
318 1.6 mycroft hd->hpib_stat = 0;
319 1.6 mycroft hd->hpib_imask = IM_IDLE | IM_ROOM | IM_BYTE;
320 1.6 mycroft if (fhpibwait(hd, IM_IDLE) < 0)
321 1.6 mycroft goto recverror;
322 1.6 mycroft hd->hpib_stat = ST_ATN;
323 1.6 mycroft hd->hpib_data = C_UNL;
324 1.6 mycroft hd->hpib_data = C_LAG + hs->sc_ba;
325 1.6 mycroft hd->hpib_data = C_TAG + slave;
326 1.6 mycroft if (sec != -1)
327 1.6 mycroft hd->hpib_data = C_SCG + sec;
328 1.6 mycroft if (fhpibwait(hd, IM_IDLE) < 0)
329 1.6 mycroft goto recverror;
330 1.6 mycroft hd->hpib_stat = ST_READ0;
331 1.6 mycroft hd->hpib_data = 0;
332 1.6 mycroft }
333 1.1 cgd if (cnt) {
334 1.1 cgd while (--cnt >= 0) {
335 1.1 cgd timo = hpibtimeout;
336 1.1 cgd while ((hd->hpib_intr & IM_BYTE) == 0) {
337 1.1 cgd if (--timo == 0)
338 1.1 cgd goto recvbyteserror;
339 1.11 thorpej DELAY(1);
340 1.1 cgd }
341 1.1 cgd *addr++ = hd->hpib_data;
342 1.1 cgd }
343 1.1 cgd FHPIBWAIT(hd, IM_ROOM);
344 1.1 cgd hd->hpib_stat = ST_ATN;
345 1.1 cgd hd->hpib_data = (slave == 31) ? C_UNA : C_UNT;
346 1.1 cgd (void) fhpibwait(hd, IM_IDLE);
347 1.1 cgd }
348 1.1 cgd hd->hpib_imask = 0;
349 1.33 tsutsui return origcnt;
350 1.1 cgd
351 1.1 cgd recverror:
352 1.1 cgd fhpibifc(hd);
353 1.1 cgd recvbyteserror:
354 1.1 cgd hd->hpib_imask = 0;
355 1.1 cgd #ifdef DEBUG
356 1.1 cgd if (fhpibdebug & FDB_FAIL) {
357 1.13 christos printf("%s: fhpibrecv failed: slave %d, sec %x, ",
358 1.14 thorpej sc->sc_dev.dv_xname, slave, sec);
359 1.13 christos printf("got %d of %d bytes\n", origcnt-cnt-1, origcnt);
360 1.1 cgd }
361 1.1 cgd #endif
362 1.33 tsutsui return origcnt - cnt - 1;
363 1.1 cgd }
364 1.1 cgd
365 1.29 thorpej static void
366 1.29 thorpej fhpibgo(struct hpibbus_softc *hs, int slave, int sec, void *ptr, int count,
367 1.29 thorpej int rw, int timo)
368 1.1 cgd {
369 1.31 thorpej struct fhpib_softc *sc =
370 1.31 thorpej (struct fhpib_softc *)device_parent(&hs->sc_dev);
371 1.15 scottr struct fhpibdevice *hd = sc->sc_regs;
372 1.15 scottr int i;
373 1.7 thorpej char *addr = ptr;
374 1.1 cgd int flags = 0;
375 1.1 cgd
376 1.1 cgd hs->sc_flags |= HPIBF_IO;
377 1.6 mycroft if (timo)
378 1.6 mycroft hs->sc_flags |= HPIBF_TIMO;
379 1.1 cgd if (rw == B_READ)
380 1.1 cgd hs->sc_flags |= HPIBF_READ;
381 1.1 cgd #ifdef DEBUG
382 1.1 cgd else if (hs->sc_flags & HPIBF_READ) {
383 1.13 christos printf("fhpibgo: HPIBF_READ still set\n");
384 1.1 cgd hs->sc_flags &= ~HPIBF_READ;
385 1.1 cgd }
386 1.1 cgd #endif
387 1.1 cgd hs->sc_count = count;
388 1.1 cgd hs->sc_addr = addr;
389 1.1 cgd #ifdef DEBUG
390 1.14 thorpej /* fhpibtransfer[unit]++; XXX */
391 1.1 cgd #endif
392 1.1 cgd if ((hs->sc_flags & HPIBF_DMA16) &&
393 1.1 cgd ((int)addr & 1) == 0 && count && (count & 1) == 0
394 1.1 cgd #ifdef DEBUG
395 1.1 cgd && doworddma
396 1.1 cgd #endif
397 1.1 cgd ) {
398 1.1 cgd #ifdef DEBUG
399 1.14 thorpej /* fhpibworddma[unit]++; XXX */
400 1.1 cgd #endif
401 1.1 cgd flags |= DMAGO_WORD;
402 1.1 cgd hd->hpib_latch = 0;
403 1.1 cgd }
404 1.1 cgd #ifdef DEBUG
405 1.1 cgd if (dopriodma)
406 1.1 cgd flags |= DMAGO_PRI;
407 1.1 cgd #endif
408 1.1 cgd if (hs->sc_flags & HPIBF_READ) {
409 1.14 thorpej sc->sc_cmd = CT_REN | CT_8BIT;
410 1.1 cgd hs->sc_curcnt = count;
411 1.14 thorpej dmago(hs->sc_dq->dq_chan, addr, count, flags|DMAGO_READ);
412 1.14 thorpej if (fhpibrecv(hs, slave, sec, 0, 0) < 0) {
413 1.1 cgd #ifdef DEBUG
414 1.13 christos printf("fhpibgo: recv failed, retrying...\n");
415 1.1 cgd #endif
416 1.14 thorpej (void) fhpibrecv(hs, slave, sec, 0, 0);
417 1.1 cgd }
418 1.1 cgd i = hd->hpib_cmd;
419 1.14 thorpej hd->hpib_cmd = sc->sc_cmd;
420 1.14 thorpej hd->hpib_ie = IDS_DMA(hs->sc_dq->dq_chan) |
421 1.1 cgd ((flags & DMAGO_WORD) ? IDS_WDMA : 0);
422 1.1 cgd return;
423 1.1 cgd }
424 1.14 thorpej sc->sc_cmd = CT_REN | CT_8BIT | CT_FIFOSEL;
425 1.1 cgd if (count < hpibdmathresh) {
426 1.1 cgd #ifdef DEBUG
427 1.14 thorpej /* fhpibnondma[unit]++; XXX */
428 1.1 cgd if (flags & DMAGO_WORD)
429 1.14 thorpej /* fhpibworddma[unit]--; XXX */ ;
430 1.1 cgd #endif
431 1.1 cgd hs->sc_curcnt = count;
432 1.14 thorpej (void) fhpibsend(hs, slave, sec, addr, count);
433 1.14 thorpej fhpibdone(hs);
434 1.1 cgd return;
435 1.1 cgd }
436 1.1 cgd count -= (flags & DMAGO_WORD) ? 2 : 1;
437 1.1 cgd hs->sc_curcnt = count;
438 1.14 thorpej dmago(hs->sc_dq->dq_chan, addr, count, flags);
439 1.14 thorpej if (fhpibsend(hs, slave, sec, 0, 0) < 0) {
440 1.1 cgd #ifdef DEBUG
441 1.13 christos printf("fhpibgo: send failed, retrying...\n");
442 1.1 cgd #endif
443 1.14 thorpej (void) fhpibsend(hs, slave, sec, 0, 0);
444 1.1 cgd }
445 1.1 cgd i = hd->hpib_cmd;
446 1.14 thorpej hd->hpib_cmd = sc->sc_cmd;
447 1.14 thorpej hd->hpib_ie = IDS_DMA(hs->sc_dq->dq_chan) | IDS_WRITE |
448 1.1 cgd ((flags & DMAGO_WORD) ? IDS_WDMA : 0);
449 1.1 cgd }
450 1.1 cgd
451 1.6 mycroft /*
452 1.6 mycroft * A DMA read can finish but the device can still be waiting (MAG-tape
453 1.6 mycroft * with more data than we're waiting for). This timeout routine
454 1.6 mycroft * takes care of that. Somehow, the thing gets hosed. For now, since
455 1.6 mycroft * this should be a very rare occurence, we RESET it.
456 1.6 mycroft */
457 1.29 thorpej static void
458 1.29 thorpej fhpibdmadone(void *arg)
459 1.6 mycroft {
460 1.15 scottr struct hpibbus_softc *hs = arg;
461 1.31 thorpej struct fhpib_softc *sc =
462 1.31 thorpej (struct fhpib_softc *)device_parent(&hs->sc_dev);
463 1.6 mycroft int s = splbio();
464 1.6 mycroft
465 1.6 mycroft if (hs->sc_flags & HPIBF_IO) {
466 1.15 scottr struct fhpibdevice *hd = sc->sc_regs;
467 1.15 scottr struct hpibqueue *hq;
468 1.6 mycroft
469 1.6 mycroft hd->hpib_imask = 0;
470 1.6 mycroft hd->hpib_cid = 0xFF;
471 1.6 mycroft DELAY(100);
472 1.6 mycroft hd->hpib_cmd = CT_8BIT;
473 1.6 mycroft hd->hpib_ar = AR_ARONC;
474 1.6 mycroft fhpibifc(hd);
475 1.6 mycroft hd->hpib_ie = IDS_IE;
476 1.6 mycroft hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO);
477 1.14 thorpej dmafree(hs->sc_dq);
478 1.14 thorpej
479 1.14 thorpej hq = hs->sc_queue.tqh_first;
480 1.14 thorpej (hq->hq_intr)(hq->hq_softc);
481 1.6 mycroft }
482 1.14 thorpej splx(s);
483 1.6 mycroft }
484 1.6 mycroft
485 1.29 thorpej static void
486 1.29 thorpej fhpibdone(struct hpibbus_softc *hs)
487 1.1 cgd {
488 1.31 thorpej struct fhpib_softc *sc =
489 1.31 thorpej (struct fhpib_softc *)device_parent(&hs->sc_dev);
490 1.15 scottr struct fhpibdevice *hd = sc->sc_regs;
491 1.15 scottr char *addr;
492 1.15 scottr int cnt;
493 1.1 cgd
494 1.1 cgd cnt = hs->sc_curcnt;
495 1.1 cgd hs->sc_addr += cnt;
496 1.1 cgd hs->sc_count -= cnt;
497 1.1 cgd #ifdef DEBUG
498 1.32 thorpej if ((fhpibdebug & FDB_DMA) &&
499 1.32 thorpej fhpibdebugunit == device_unit(&sc->sc_dev))
500 1.16 scottr printf("fhpibdone: addr %p cnt %d\n",
501 1.1 cgd hs->sc_addr, hs->sc_count);
502 1.1 cgd #endif
503 1.6 mycroft if (hs->sc_flags & HPIBF_READ) {
504 1.1 cgd hd->hpib_imask = IM_IDLE | IM_BYTE;
505 1.6 mycroft if (hs->sc_flags & HPIBF_TIMO)
506 1.21 thorpej callout_reset(&sc->sc_dmadone_ch, hz >> 2,
507 1.21 thorpej fhpibdmadone, hs);
508 1.6 mycroft } else {
509 1.1 cgd cnt = hs->sc_count;
510 1.1 cgd if (cnt) {
511 1.1 cgd addr = hs->sc_addr;
512 1.1 cgd hd->hpib_imask = IM_IDLE | IM_ROOM;
513 1.1 cgd FHPIBWAIT(hd, IM_IDLE);
514 1.1 cgd hd->hpib_stat = ST_WRITE;
515 1.1 cgd while (--cnt) {
516 1.1 cgd hd->hpib_data = *addr++;
517 1.1 cgd FHPIBWAIT(hd, IM_ROOM);
518 1.1 cgd }
519 1.1 cgd hd->hpib_stat = ST_EOI;
520 1.1 cgd hd->hpib_data = *addr;
521 1.1 cgd }
522 1.1 cgd hd->hpib_imask = IM_IDLE;
523 1.1 cgd }
524 1.1 cgd hs->sc_flags |= HPIBF_DONE;
525 1.1 cgd hd->hpib_stat = ST_IENAB;
526 1.1 cgd hd->hpib_ie = IDS_IE;
527 1.1 cgd }
528 1.1 cgd
529 1.29 thorpej static int
530 1.29 thorpej fhpibintr(void *arg)
531 1.1 cgd {
532 1.14 thorpej struct fhpib_softc *sc = arg;
533 1.15 scottr struct hpibbus_softc *hs = sc->sc_hpibbus;
534 1.15 scottr struct fhpibdevice *hd = sc->sc_regs;
535 1.15 scottr struct hpibqueue *hq;
536 1.15 scottr int stat0;
537 1.1 cgd
538 1.1 cgd stat0 = hd->hpib_ids;
539 1.1 cgd if ((stat0 & (IDS_IE|IDS_IR)) != (IDS_IE|IDS_IR)) {
540 1.1 cgd #ifdef DEBUG
541 1.1 cgd if ((fhpibdebug & FDB_FAIL) && (stat0 & IDS_IR) &&
542 1.1 cgd (hs->sc_flags & (HPIBF_IO|HPIBF_DONE)) != HPIBF_IO)
543 1.13 christos printf("%s: fhpibintr: bad status %x\n",
544 1.14 thorpej sc->sc_dev.dv_xname, stat0);
545 1.14 thorpej /* fhpibbadint[0]++; XXX */
546 1.1 cgd #endif
547 1.33 tsutsui return 0;
548 1.1 cgd }
549 1.1 cgd if ((hs->sc_flags & (HPIBF_IO|HPIBF_DONE)) == HPIBF_IO) {
550 1.1 cgd #ifdef DEBUG
551 1.14 thorpej /* fhpibbadint[1]++; XXX */
552 1.1 cgd #endif
553 1.33 tsutsui return 0;
554 1.1 cgd }
555 1.1 cgd #ifdef DEBUG
556 1.32 thorpej if ((fhpibdebug & FDB_DMA) &&
557 1.32 thorpej fhpibdebugunit == device_unit(&sc->sc_dev))
558 1.13 christos printf("fhpibintr: flags %x\n", hs->sc_flags);
559 1.1 cgd #endif
560 1.14 thorpej hq = hs->sc_queue.tqh_first;
561 1.1 cgd if (hs->sc_flags & HPIBF_IO) {
562 1.6 mycroft if (hs->sc_flags & HPIBF_TIMO)
563 1.21 thorpej callout_stop(&sc->sc_dmadone_ch);
564 1.1 cgd stat0 = hd->hpib_cmd;
565 1.14 thorpej hd->hpib_cmd = sc->sc_cmd & ~CT_8BIT;
566 1.1 cgd hd->hpib_stat = 0;
567 1.1 cgd hd->hpib_cmd = CT_REN | CT_8BIT;
568 1.1 cgd stat0 = hd->hpib_intr;
569 1.1 cgd hd->hpib_imask = 0;
570 1.6 mycroft hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO);
571 1.14 thorpej dmafree(hs->sc_dq);
572 1.14 thorpej (hq->hq_intr)(hq->hq_softc);
573 1.1 cgd } else if (hs->sc_flags & HPIBF_PPOLL) {
574 1.1 cgd stat0 = hd->hpib_intr;
575 1.1 cgd #ifdef DEBUG
576 1.1 cgd if ((fhpibdebug & FDB_FAIL) &&
577 1.1 cgd doppollint && (stat0 & IM_PPRESP) == 0)
578 1.13 christos printf("%s: fhpibintr: bad intr reg %x\n",
579 1.14 thorpej sc->sc_dev.dv_xname, stat0);
580 1.1 cgd #endif
581 1.1 cgd hd->hpib_stat = 0;
582 1.1 cgd hd->hpib_imask = 0;
583 1.1 cgd #ifdef DEBUG
584 1.14 thorpej stat0 = fhpibppoll(hs);
585 1.16 scottr if ((fhpibdebug & FDB_PPOLL) &&
586 1.32 thorpej fhpibdebugunit == device_unit(&sc->sc_dev))
587 1.13 christos printf("fhpibintr: got PPOLL status %x\n", stat0);
588 1.14 thorpej if ((stat0 & (0x80 >> hq->hq_slave)) == 0) {
589 1.4 mycroft /*
590 1.4 mycroft * XXX give it another shot (68040)
591 1.4 mycroft */
592 1.14 thorpej /* fhpibppollfail[unit]++; XXX */
593 1.4 mycroft DELAY(fhpibppolldelay);
594 1.14 thorpej stat0 = fhpibppoll(hs);
595 1.14 thorpej if ((stat0 & (0x80 >> hq->hq_slave)) == 0 &&
596 1.16 scottr (fhpibdebug & FDB_PPOLL) &&
597 1.32 thorpej fhpibdebugunit == device_unit(&sc->sc_dev))
598 1.13 christos printf("fhpibintr: PPOLL: unit %d slave %d stat %x\n",
599 1.32 thorpej device_unit(&sc->sc_dev), hq->hq_slave,
600 1.32 thorpej stat0);
601 1.1 cgd }
602 1.1 cgd #endif
603 1.1 cgd hs->sc_flags &= ~HPIBF_PPOLL;
604 1.14 thorpej (hq->hq_intr)(hq->hq_softc);
605 1.1 cgd }
606 1.33 tsutsui return 1;
607 1.1 cgd }
608 1.1 cgd
609 1.29 thorpej static int
610 1.29 thorpej fhpibppoll(struct hpibbus_softc *hs)
611 1.1 cgd {
612 1.31 thorpej struct fhpib_softc *sc =
613 1.31 thorpej (struct fhpib_softc *)device_parent(&hs->sc_dev);
614 1.15 scottr struct fhpibdevice *hd = sc->sc_regs;
615 1.15 scottr int ppoll;
616 1.1 cgd
617 1.1 cgd hd->hpib_stat = 0;
618 1.1 cgd hd->hpib_psense = 0;
619 1.1 cgd hd->hpib_pmask = 0xFF;
620 1.1 cgd hd->hpib_imask = IM_PPRESP | IM_PABORT;
621 1.1 cgd DELAY(25);
622 1.1 cgd hd->hpib_intr = IM_PABORT;
623 1.1 cgd ppoll = hd->hpib_data;
624 1.1 cgd if (hd->hpib_intr & IM_PABORT)
625 1.1 cgd ppoll = 0;
626 1.1 cgd hd->hpib_imask = 0;
627 1.1 cgd hd->hpib_pmask = 0;
628 1.1 cgd hd->hpib_stat = ST_IENAB;
629 1.33 tsutsui return ppoll;
630 1.1 cgd }
631 1.1 cgd
632 1.29 thorpej static int
633 1.29 thorpej fhpibwait(struct fhpibdevice *hd, int x)
634 1.1 cgd {
635 1.15 scottr int timo = hpibtimeout;
636 1.1 cgd
637 1.1 cgd while ((hd->hpib_intr & x) == 0 && --timo)
638 1.11 thorpej DELAY(1);
639 1.1 cgd if (timo == 0) {
640 1.1 cgd #ifdef DEBUG
641 1.1 cgd if (fhpibdebug & FDB_FAIL)
642 1.16 scottr printf("fhpibwait(%p, %x) timeout\n", hd, x);
643 1.1 cgd #endif
644 1.33 tsutsui return -1;
645 1.1 cgd }
646 1.33 tsutsui return 0;
647 1.1 cgd }
648 1.1 cgd
649 1.1 cgd /*
650 1.4 mycroft * XXX: this will have to change if we ever allow more than one
651 1.1 cgd * pending operation per HP-IB.
652 1.1 cgd */
653 1.29 thorpej static void
654 1.29 thorpej fhpibppwatch(void *arg)
655 1.1 cgd {
656 1.15 scottr struct hpibbus_softc *hs = arg;
657 1.31 thorpej struct fhpib_softc *sc =
658 1.31 thorpej (struct fhpib_softc *)device_parent(&hs->sc_dev);
659 1.15 scottr struct fhpibdevice *hd = sc->sc_regs;
660 1.15 scottr int slave;
661 1.1 cgd
662 1.1 cgd if ((hs->sc_flags & HPIBF_PPOLL) == 0)
663 1.1 cgd return;
664 1.14 thorpej slave = (0x80 >> hs->sc_queue.tqh_first->hq_slave);
665 1.1 cgd #ifdef DEBUG
666 1.1 cgd if (!doppollint) {
667 1.14 thorpej if (fhpibppoll(hs) & slave) {
668 1.1 cgd hd->hpib_stat = ST_IENAB;
669 1.1 cgd hd->hpib_imask = IM_IDLE | IM_ROOM;
670 1.1 cgd } else
671 1.21 thorpej callout_reset(&sc->sc_ppwatch_ch, 1, fhpibppwatch, sc);
672 1.1 cgd return;
673 1.1 cgd }
674 1.32 thorpej if ((fhpibdebug & FDB_PPOLL) &&
675 1.32 thorpej device_unit(&sc->sc_dev) == fhpibdebugunit)
676 1.14 thorpej printf("fhpibppwatch: sense request on %s\n",
677 1.14 thorpej sc->sc_dev.dv_xname);
678 1.1 cgd #endif
679 1.1 cgd hd->hpib_psense = ~slave;
680 1.1 cgd hd->hpib_pmask = slave;
681 1.1 cgd hd->hpib_stat = ST_IENAB;
682 1.1 cgd hd->hpib_imask = IM_PPRESP | IM_PABORT;
683 1.1 cgd hd->hpib_ie = IDS_IE;
684 1.1 cgd }
685