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