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