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