nhpib.c revision 1.35 1 1.35 tsutsui /* $NetBSD: nhpib.c,v 1.35 2006/07/21 10:01:39 tsutsui Exp $ */
2 1.18 thorpej
3 1.18 thorpej /*-
4 1.18 thorpej * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
5 1.18 thorpej * All rights reserved.
6 1.18 thorpej *
7 1.18 thorpej * This code is derived from software contributed to The NetBSD Foundation
8 1.18 thorpej * by Jason R. Thorpe.
9 1.18 thorpej *
10 1.18 thorpej * Redistribution and use in source and binary forms, with or without
11 1.18 thorpej * modification, are permitted provided that the following conditions
12 1.18 thorpej * are met:
13 1.18 thorpej * 1. Redistributions of source code must retain the above copyright
14 1.18 thorpej * notice, this list of conditions and the following disclaimer.
15 1.18 thorpej * 2. Redistributions in binary form must reproduce the above copyright
16 1.18 thorpej * notice, this list of conditions and the following disclaimer in the
17 1.18 thorpej * documentation and/or other materials provided with the distribution.
18 1.18 thorpej * 3. All advertising materials mentioning features or use of this software
19 1.18 thorpej * must display the following acknowledgement:
20 1.18 thorpej * This product includes software developed by the NetBSD
21 1.18 thorpej * Foundation, Inc. and its contributors.
22 1.18 thorpej * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.18 thorpej * contributors may be used to endorse or promote products derived
24 1.18 thorpej * from this software without specific prior written permission.
25 1.18 thorpej *
26 1.18 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.18 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.18 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.18 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.18 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.18 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.18 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.18 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.18 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.18 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.18 thorpej * POSSIBILITY OF SUCH DAMAGE.
37 1.18 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.29 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 * @(#)nhpib.c 8.2 (Berkeley) 1/12/94
68 1.1 cgd */
69 1.1 cgd
70 1.1 cgd /*
71 1.1 cgd * Internal/98624 HPIB driver
72 1.1 cgd */
73 1.24 gmcgarry
74 1.24 gmcgarry #include <sys/cdefs.h>
75 1.35 tsutsui __KERNEL_RCSID(0, "$NetBSD: nhpib.c,v 1.35 2006/07/21 10:01:39 tsutsui Exp $");
76 1.1 cgd
77 1.4 mycroft #include <sys/param.h>
78 1.4 mycroft #include <sys/systm.h>
79 1.22 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.27 gmcgarry #include <machine/bus.h>
85 1.14 thorpej
86 1.27 gmcgarry #include <hp300/dev/intiovar.h>
87 1.14 thorpej #include <hp300/dev/diovar.h>
88 1.14 thorpej #include <hp300/dev/diodevs.h>
89 1.14 thorpej #include <hp300/dev/dmavar.h>
90 1.4 mycroft
91 1.4 mycroft #include <hp300/dev/nhpibreg.h>
92 1.4 mycroft #include <hp300/dev/hpibvar.h>
93 1.1 cgd
94 1.6 mycroft /*
95 1.6 mycroft * ODD parity table for listen and talk addresses and secondary commands.
96 1.6 mycroft * The TI9914A doesn't produce the parity bit.
97 1.6 mycroft */
98 1.31 thorpej static const u_char listnr_par[] = {
99 1.6 mycroft 0040,0241,0242,0043,0244,0045,0046,0247,
100 1.6 mycroft 0250,0051,0052,0253,0054,0255,0256,0057,
101 1.6 mycroft 0260,0061,0062,0263,0064,0265,0266,0067,
102 1.6 mycroft 0070,0271,0272,0073,0274,0075,0076,0277,
103 1.6 mycroft };
104 1.31 thorpej static const u_char talker_par[] = {
105 1.6 mycroft 0100,0301,0302,0103,0304,0105,0106,0307,
106 1.6 mycroft 0310,0111,0112,0313,0114,0315,0316,0117,
107 1.6 mycroft 0320,0121,0122,0323,0124,0325,0326,0127,
108 1.6 mycroft 0130,0331,0332,0133,0334,0135,0136,0337,
109 1.6 mycroft };
110 1.31 thorpej static const u_char sec_par[] = {
111 1.6 mycroft 0340,0141,0142,0343,0144,0345,0346,0147,
112 1.6 mycroft 0150,0351,0352,0153,0354,0155,0156,0357,
113 1.6 mycroft 0160,0361,0362,0163,0364,0165,0166,0367,
114 1.6 mycroft 0370,0171,0172,0373,0174,0375,0376,0177
115 1.6 mycroft };
116 1.6 mycroft
117 1.31 thorpej static void nhpibifc(struct nhpibdevice *);
118 1.31 thorpej static void nhpibreadtimo(void *);
119 1.31 thorpej static int nhpibwait(struct nhpibdevice *, int);
120 1.31 thorpej
121 1.31 thorpej static void nhpibreset(struct hpibbus_softc *);
122 1.31 thorpej static int nhpibsend(struct hpibbus_softc *, int, int, void *, int);
123 1.31 thorpej static int nhpibrecv(struct hpibbus_softc *, int, int, void *, int);
124 1.31 thorpej static int nhpibppoll(struct hpibbus_softc *);
125 1.31 thorpej static void nhpibppwatch(void *);
126 1.31 thorpej static void nhpibgo(struct hpibbus_softc *, int, int, void *, int, int,
127 1.31 thorpej int);
128 1.31 thorpej static void nhpibdone(struct hpibbus_softc *);
129 1.31 thorpej static int nhpibintr(void *);
130 1.7 thorpej
131 1.7 thorpej /*
132 1.7 thorpej * Our controller ops structure.
133 1.7 thorpej */
134 1.31 thorpej static struct hpib_controller nhpib_controller = {
135 1.7 thorpej nhpibreset,
136 1.7 thorpej nhpibsend,
137 1.7 thorpej nhpibrecv,
138 1.7 thorpej nhpibppoll,
139 1.7 thorpej nhpibppwatch,
140 1.7 thorpej nhpibgo,
141 1.7 thorpej nhpibdone,
142 1.7 thorpej nhpibintr
143 1.7 thorpej };
144 1.7 thorpej
145 1.14 thorpej struct nhpib_softc {
146 1.14 thorpej struct device sc_dev; /* generic device glue */
147 1.27 gmcgarry
148 1.27 gmcgarry bus_space_tag_t sc_bst;
149 1.27 gmcgarry bus_space_handle_t sc_bsh;
150 1.27 gmcgarry
151 1.14 thorpej struct nhpibdevice *sc_regs; /* device registers */
152 1.14 thorpej struct hpibbus_softc *sc_hpibbus; /* XXX */
153 1.27 gmcgarry
154 1.27 gmcgarry int sc_myaddr;
155 1.27 gmcgarry int sc_type;
156 1.27 gmcgarry
157 1.22 thorpej struct callout sc_read_ch;
158 1.22 thorpej struct callout sc_ppwatch_ch;
159 1.14 thorpej };
160 1.14 thorpej
161 1.31 thorpej static int nhpib_dio_match(struct device *, struct cfdata *, void *);
162 1.31 thorpej static void nhpib_dio_attach(struct device *, struct device *, void *);
163 1.31 thorpej static int nhpib_intio_match(struct device *, struct cfdata *, void *);
164 1.31 thorpej static void nhpib_intio_attach(struct device *, struct device *, void *);
165 1.27 gmcgarry
166 1.31 thorpej static void nhpib_common_attach(struct nhpib_softc *, const char *);
167 1.27 gmcgarry
168 1.27 gmcgarry CFATTACH_DECL(nhpib_dio, sizeof(struct nhpib_softc),
169 1.27 gmcgarry nhpib_dio_match, nhpib_dio_attach, NULL, NULL);
170 1.27 gmcgarry
171 1.27 gmcgarry CFATTACH_DECL(nhpib_intio, sizeof(struct nhpib_softc),
172 1.27 gmcgarry nhpib_intio_match, nhpib_intio_attach, NULL, NULL);
173 1.27 gmcgarry
174 1.31 thorpej static int
175 1.31 thorpej nhpib_intio_match(struct device *parent, struct cfdata *match, void *aux)
176 1.27 gmcgarry {
177 1.27 gmcgarry struct intio_attach_args *ia = aux;
178 1.27 gmcgarry
179 1.27 gmcgarry if (strcmp("hpib", ia->ia_modname) == 0)
180 1.35 tsutsui return 1;
181 1.14 thorpej
182 1.35 tsutsui return 0;
183 1.27 gmcgarry }
184 1.14 thorpej
185 1.31 thorpej static int
186 1.31 thorpej nhpib_dio_match(struct device *parent, struct cfdata *match, void *aux)
187 1.1 cgd {
188 1.14 thorpej struct dio_attach_args *da = aux;
189 1.1 cgd
190 1.27 gmcgarry if (da->da_id == DIO_DEVICE_ID_NHPIB)
191 1.35 tsutsui return 1;
192 1.8 thorpej
193 1.35 tsutsui return 0;
194 1.8 thorpej }
195 1.8 thorpej
196 1.31 thorpej static void
197 1.31 thorpej nhpib_intio_attach(struct device *parent, struct device *self, void *aux)
198 1.27 gmcgarry {
199 1.27 gmcgarry struct nhpib_softc *sc = (struct nhpib_softc *)self;
200 1.27 gmcgarry struct intio_attach_args *ia = aux;
201 1.28 tsutsui bus_space_tag_t bst = ia->ia_bst;
202 1.27 gmcgarry const char *desc = "internal HP-IB";
203 1.27 gmcgarry
204 1.28 tsutsui if (bus_space_map(bst, ia->ia_iobase, INTIO_DEVSIZE, 0, &sc->sc_bsh)) {
205 1.27 gmcgarry printf(": can't map registers\n");
206 1.27 gmcgarry return;
207 1.27 gmcgarry }
208 1.27 gmcgarry
209 1.28 tsutsui sc->sc_bst = bst;
210 1.27 gmcgarry sc->sc_myaddr = HPIBA_BA;
211 1.27 gmcgarry sc->sc_type = HPIBA;
212 1.27 gmcgarry
213 1.27 gmcgarry nhpib_common_attach(sc, desc);
214 1.27 gmcgarry
215 1.27 gmcgarry /* establish the interrupt handler */
216 1.35 tsutsui (void)intio_intr_establish(nhpibintr, sc, ia->ia_ipl, IPL_BIO);
217 1.27 gmcgarry }
218 1.27 gmcgarry
219 1.31 thorpej static void
220 1.31 thorpej nhpib_dio_attach(struct device *parent, struct device *self, void *aux)
221 1.14 thorpej {
222 1.14 thorpej struct nhpib_softc *sc = (struct nhpib_softc *)self;
223 1.14 thorpej struct dio_attach_args *da = aux;
224 1.28 tsutsui bus_space_tag_t bst = da->da_bst;
225 1.27 gmcgarry const char *desc = DIO_DEVICE_DESC_NHPIB;
226 1.14 thorpej
227 1.28 tsutsui if (bus_space_map(bst, da->da_addr, da->da_size, 0, &sc->sc_bsh)) {
228 1.27 gmcgarry printf(": can't map registers\n");
229 1.14 thorpej return;
230 1.14 thorpej }
231 1.8 thorpej
232 1.28 tsutsui sc->sc_bst = bst;
233 1.27 gmcgarry /* read address off switches */
234 1.27 gmcgarry sc->sc_myaddr = bus_space_read_1(sc->sc_bst, sc->sc_bsh, 5);
235 1.27 gmcgarry sc->sc_type = HPIBB;
236 1.27 gmcgarry
237 1.27 gmcgarry nhpib_common_attach(sc, desc);
238 1.27 gmcgarry
239 1.27 gmcgarry /* establish the interrupt handler */
240 1.27 gmcgarry (void)dio_intr_establish(nhpibintr, sc, da->da_ipl, IPL_BIO);
241 1.27 gmcgarry }
242 1.8 thorpej
243 1.31 thorpej static void
244 1.31 thorpej nhpib_common_attach(struct nhpib_softc *sc, const char *desc)
245 1.27 gmcgarry {
246 1.30 tsutsui struct hpibdev_attach_args ha;
247 1.14 thorpej
248 1.27 gmcgarry printf(": %s\n", desc);
249 1.14 thorpej
250 1.27 gmcgarry sc->sc_regs = (struct nhpibdevice *)bus_space_vaddr(sc->sc_bst,
251 1.27 gmcgarry sc->sc_bsh);
252 1.14 thorpej
253 1.22 thorpej callout_init(&sc->sc_read_ch);
254 1.22 thorpej callout_init(&sc->sc_ppwatch_ch);
255 1.22 thorpej
256 1.14 thorpej ha.ha_ops = &nhpib_controller;
257 1.27 gmcgarry ha.ha_type = sc->sc_type; /* XXX */
258 1.27 gmcgarry ha.ha_ba = sc->sc_myaddr;
259 1.27 gmcgarry ha.ha_softcpp = &sc->sc_hpibbus; /* XXX */
260 1.27 gmcgarry (void)config_found((void *)sc, &ha, hpibdevprint);
261 1.1 cgd }
262 1.1 cgd
263 1.31 thorpej static void
264 1.31 thorpej nhpibreset(struct hpibbus_softc *hs)
265 1.1 cgd {
266 1.33 thorpej struct nhpib_softc *sc =
267 1.33 thorpej (struct nhpib_softc *)device_parent(&hs->sc_dev);
268 1.14 thorpej struct nhpibdevice *hd = sc->sc_regs;
269 1.1 cgd
270 1.1 cgd hd->hpib_acr = AUX_SSWRST;
271 1.1 cgd hd->hpib_ar = hs->sc_ba;
272 1.1 cgd hd->hpib_lim = LIS_ERR;
273 1.1 cgd hd->hpib_mim = 0;
274 1.1 cgd hd->hpib_acr = AUX_CDAI;
275 1.1 cgd hd->hpib_acr = AUX_CSHDW;
276 1.1 cgd hd->hpib_acr = AUX_SSTD1;
277 1.1 cgd hd->hpib_acr = AUX_SVSTD1;
278 1.1 cgd hd->hpib_acr = AUX_CPP;
279 1.1 cgd hd->hpib_acr = AUX_CHDFA;
280 1.1 cgd hd->hpib_acr = AUX_CHDFE;
281 1.1 cgd hd->hpib_acr = AUX_RHDF;
282 1.1 cgd hd->hpib_acr = AUX_CSWRST;
283 1.1 cgd nhpibifc(hd);
284 1.1 cgd hd->hpib_ie = IDS_IE;
285 1.6 mycroft hd->hpib_data = C_DCL_P;
286 1.1 cgd DELAY(100000);
287 1.1 cgd }
288 1.1 cgd
289 1.31 thorpej static void
290 1.31 thorpej nhpibifc(struct nhpibdevice *hd)
291 1.1 cgd {
292 1.35 tsutsui
293 1.1 cgd hd->hpib_acr = AUX_TCA;
294 1.1 cgd hd->hpib_acr = AUX_CSRE;
295 1.1 cgd hd->hpib_acr = AUX_SSIC;
296 1.1 cgd DELAY(100);
297 1.1 cgd hd->hpib_acr = AUX_CSIC;
298 1.1 cgd hd->hpib_acr = AUX_SSRE;
299 1.1 cgd }
300 1.1 cgd
301 1.31 thorpej static int
302 1.31 thorpej nhpibsend(struct hpibbus_softc *hs, int slave, int sec, void *ptr, int origcnt)
303 1.1 cgd {
304 1.33 thorpej struct nhpib_softc *sc =
305 1.33 thorpej (struct nhpib_softc *)device_parent(&hs->sc_dev);
306 1.14 thorpej struct nhpibdevice *hd = sc->sc_regs;
307 1.14 thorpej int cnt = origcnt;
308 1.7 thorpej char *addr = ptr;
309 1.1 cgd
310 1.1 cgd hd->hpib_acr = AUX_TCA;
311 1.6 mycroft hd->hpib_data = C_UNL_P;
312 1.1 cgd if (nhpibwait(hd, MIS_BO))
313 1.1 cgd goto senderror;
314 1.6 mycroft hd->hpib_data = talker_par[hs->sc_ba];
315 1.1 cgd hd->hpib_acr = AUX_STON;
316 1.1 cgd if (nhpibwait(hd, MIS_BO))
317 1.1 cgd goto senderror;
318 1.6 mycroft hd->hpib_data = listnr_par[slave];
319 1.1 cgd if (nhpibwait(hd, MIS_BO))
320 1.1 cgd goto senderror;
321 1.6 mycroft if (sec >= 0 || sec == -2) {
322 1.6 mycroft if (sec == -2) /* selected device clear KLUDGE */
323 1.6 mycroft hd->hpib_data = C_SDC_P;
324 1.6 mycroft else
325 1.6 mycroft hd->hpib_data = sec_par[sec];
326 1.1 cgd if (nhpibwait(hd, MIS_BO))
327 1.1 cgd goto senderror;
328 1.1 cgd }
329 1.1 cgd hd->hpib_acr = AUX_GTS;
330 1.1 cgd if (cnt) {
331 1.1 cgd while (--cnt > 0) {
332 1.1 cgd hd->hpib_data = *addr++;
333 1.1 cgd if (nhpibwait(hd, MIS_BO))
334 1.1 cgd goto senderror;
335 1.1 cgd }
336 1.1 cgd hd->hpib_acr = AUX_EOI;
337 1.1 cgd hd->hpib_data = *addr;
338 1.1 cgd if (nhpibwait(hd, MIS_BO))
339 1.1 cgd goto senderror;
340 1.1 cgd hd->hpib_acr = AUX_TCA;
341 1.1 cgd #if 0
342 1.1 cgd /*
343 1.1 cgd * May be causing 345 disks to hang due to interference
344 1.1 cgd * with PPOLL mechanism.
345 1.1 cgd */
346 1.6 mycroft hd->hpib_data = C_UNL_P;
347 1.1 cgd (void) nhpibwait(hd, MIS_BO);
348 1.1 cgd #endif
349 1.1 cgd }
350 1.35 tsutsui return origcnt;
351 1.6 mycroft
352 1.1 cgd senderror:
353 1.1 cgd nhpibifc(hd);
354 1.35 tsutsui return origcnt - cnt - 1;
355 1.1 cgd }
356 1.1 cgd
357 1.31 thorpej static int
358 1.31 thorpej nhpibrecv(struct hpibbus_softc *hs, int slave, int sec, void *ptr, int origcnt)
359 1.1 cgd {
360 1.33 thorpej struct nhpib_softc *sc =
361 1.33 thorpej (struct nhpib_softc *)device_parent(&hs->sc_dev);
362 1.14 thorpej struct nhpibdevice *hd = sc->sc_regs;
363 1.14 thorpej int cnt = origcnt;
364 1.7 thorpej char *addr = ptr;
365 1.1 cgd
366 1.6 mycroft /*
367 1.6 mycroft * Slave < 0 implies continuation of a previous receive
368 1.6 mycroft * that probably timed out.
369 1.6 mycroft */
370 1.6 mycroft if (slave >= 0) {
371 1.6 mycroft hd->hpib_acr = AUX_TCA;
372 1.6 mycroft hd->hpib_data = C_UNL_P;
373 1.6 mycroft if (nhpibwait(hd, MIS_BO))
374 1.6 mycroft goto recverror;
375 1.6 mycroft hd->hpib_data = listnr_par[hs->sc_ba];
376 1.6 mycroft hd->hpib_acr = AUX_SLON;
377 1.6 mycroft if (nhpibwait(hd, MIS_BO))
378 1.6 mycroft goto recverror;
379 1.6 mycroft hd->hpib_data = talker_par[slave];
380 1.1 cgd if (nhpibwait(hd, MIS_BO))
381 1.1 cgd goto recverror;
382 1.6 mycroft if (sec >= 0) {
383 1.6 mycroft hd->hpib_data = sec_par[sec];
384 1.6 mycroft if (nhpibwait(hd, MIS_BO))
385 1.6 mycroft goto recverror;
386 1.6 mycroft }
387 1.6 mycroft hd->hpib_acr = AUX_RHDF;
388 1.6 mycroft hd->hpib_acr = AUX_GTS;
389 1.1 cgd }
390 1.1 cgd if (cnt) {
391 1.1 cgd while (--cnt >= 0) {
392 1.1 cgd if (nhpibwait(hd, MIS_BI))
393 1.1 cgd goto recvbyteserror;
394 1.1 cgd *addr++ = hd->hpib_data;
395 1.1 cgd }
396 1.1 cgd hd->hpib_acr = AUX_TCA;
397 1.6 mycroft hd->hpib_data = (slave == 31) ? C_UNA_P : C_UNT_P;
398 1.1 cgd (void) nhpibwait(hd, MIS_BO);
399 1.1 cgd }
400 1.35 tsutsui return origcnt;
401 1.6 mycroft
402 1.1 cgd recverror:
403 1.1 cgd nhpibifc(hd);
404 1.1 cgd recvbyteserror:
405 1.35 tsutsui return origcnt - cnt - 1;
406 1.1 cgd }
407 1.1 cgd
408 1.31 thorpej static void
409 1.31 thorpej nhpibgo(struct hpibbus_softc *hs, int slave, int sec, void *ptr, int count,
410 1.31 thorpej int rw, int timo)
411 1.1 cgd {
412 1.33 thorpej struct nhpib_softc *sc =
413 1.33 thorpej (struct nhpib_softc *)device_parent(&hs->sc_dev);
414 1.14 thorpej struct nhpibdevice *hd = sc->sc_regs;
415 1.7 thorpej char *addr = ptr;
416 1.1 cgd
417 1.1 cgd hs->sc_flags |= HPIBF_IO;
418 1.6 mycroft if (timo)
419 1.6 mycroft hs->sc_flags |= HPIBF_TIMO;
420 1.1 cgd if (rw == B_READ)
421 1.1 cgd hs->sc_flags |= HPIBF_READ;
422 1.1 cgd #ifdef DEBUG
423 1.1 cgd else if (hs->sc_flags & HPIBF_READ) {
424 1.13 christos printf("nhpibgo: HPIBF_READ still set\n");
425 1.1 cgd hs->sc_flags &= ~HPIBF_READ;
426 1.1 cgd }
427 1.1 cgd #endif
428 1.1 cgd hs->sc_count = count;
429 1.1 cgd hs->sc_addr = addr;
430 1.1 cgd if (hs->sc_flags & HPIBF_READ) {
431 1.1 cgd hs->sc_curcnt = count;
432 1.14 thorpej dmago(hs->sc_dq->dq_chan, addr, count, DMAGO_BYTE|DMAGO_READ);
433 1.14 thorpej nhpibrecv(hs, slave, sec, 0, 0);
434 1.1 cgd hd->hpib_mim = MIS_END;
435 1.1 cgd } else {
436 1.1 cgd hd->hpib_mim = 0;
437 1.1 cgd if (count < hpibdmathresh) {
438 1.1 cgd hs->sc_curcnt = count;
439 1.14 thorpej nhpibsend(hs, slave, sec, addr, count);
440 1.14 thorpej nhpibdone(hs);
441 1.1 cgd return;
442 1.1 cgd }
443 1.1 cgd hs->sc_curcnt = --count;
444 1.14 thorpej dmago(hs->sc_dq->dq_chan, addr, count, DMAGO_BYTE);
445 1.14 thorpej nhpibsend(hs, slave, sec, 0, 0);
446 1.1 cgd }
447 1.14 thorpej hd->hpib_ie = IDS_IE | IDS_DMA(hs->sc_dq->dq_chan);
448 1.1 cgd }
449 1.1 cgd
450 1.6 mycroft /*
451 1.6 mycroft * This timeout can only happen if a DMA read finishes DMAing with the read
452 1.6 mycroft * still pending (more data in read transaction than the driver was prepared
453 1.6 mycroft * to accept). At the moment, variable-record tape drives are the only things
454 1.6 mycroft * capabale of doing this. We repeat the necessary code from nhpibintr() -
455 1.6 mycroft * easier and quicker than calling nhpibintr() for this special case.
456 1.6 mycroft */
457 1.31 thorpej static void
458 1.31 thorpej nhpibreadtimo(void *arg)
459 1.6 mycroft {
460 1.14 thorpej struct hpibbus_softc *hs = arg;
461 1.33 thorpej struct nhpib_softc *sc =
462 1.33 thorpej (struct nhpib_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 nhpibdevice *hd = sc->sc_regs;
467 1.15 scottr struct hpibqueue *hq;
468 1.6 mycroft
469 1.6 mycroft hd->hpib_mim = 0;
470 1.6 mycroft hd->hpib_acr = AUX_TCA;
471 1.6 mycroft hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO);
472 1.14 thorpej dmafree(hs->sc_dq);
473 1.14 thorpej
474 1.14 thorpej hq = hs->sc_queue.tqh_first;
475 1.14 thorpej (hq->hq_intr)(hq->hq_softc);
476 1.6 mycroft }
477 1.14 thorpej splx(s);
478 1.6 mycroft }
479 1.6 mycroft
480 1.31 thorpej static void
481 1.31 thorpej nhpibdone(struct hpibbus_softc *hs)
482 1.1 cgd {
483 1.33 thorpej struct nhpib_softc *sc =
484 1.33 thorpej (struct nhpib_softc *)device_parent(&hs->sc_dev);
485 1.14 thorpej struct nhpibdevice *hd = sc->sc_regs;
486 1.14 thorpej int cnt;
487 1.1 cgd
488 1.1 cgd cnt = hs->sc_curcnt;
489 1.1 cgd hs->sc_addr += cnt;
490 1.1 cgd hs->sc_count -= cnt;
491 1.1 cgd hs->sc_flags |= HPIBF_DONE;
492 1.1 cgd hd->hpib_ie = IDS_IE;
493 1.6 mycroft if (hs->sc_flags & HPIBF_READ) {
494 1.6 mycroft if ((hs->sc_flags & HPIBF_TIMO) &&
495 1.6 mycroft (hd->hpib_ids & IDS_IR) == 0)
496 1.23 frueauf callout_reset(&sc->sc_read_ch, hz >> 2,
497 1.22 thorpej nhpibreadtimo, hs);
498 1.6 mycroft } else {
499 1.1 cgd if (hs->sc_count == 1) {
500 1.1 cgd (void) nhpibwait(hd, MIS_BO);
501 1.1 cgd hd->hpib_acr = AUX_EOI;
502 1.1 cgd hd->hpib_data = *hs->sc_addr;
503 1.1 cgd hd->hpib_mim = MIS_BO;
504 1.1 cgd }
505 1.1 cgd #ifdef DEBUG
506 1.1 cgd else if (hs->sc_count)
507 1.1 cgd panic("nhpibdone");
508 1.1 cgd #endif
509 1.1 cgd }
510 1.1 cgd }
511 1.1 cgd
512 1.31 thorpej static int
513 1.31 thorpej nhpibintr(void *arg)
514 1.1 cgd {
515 1.14 thorpej struct nhpib_softc *sc = arg;
516 1.14 thorpej struct hpibbus_softc *hs = sc->sc_hpibbus;
517 1.14 thorpej struct nhpibdevice *hd = sc->sc_regs;
518 1.14 thorpej struct hpibqueue *hq;
519 1.14 thorpej int stat0;
520 1.14 thorpej int stat1;
521 1.1 cgd
522 1.1 cgd #ifdef lint
523 1.35 tsutsui if (stat1 = unit)
524 1.35 tsutsui return 1;
525 1.1 cgd #endif
526 1.1 cgd if ((hd->hpib_ids & IDS_IR) == 0)
527 1.35 tsutsui return 0;
528 1.1 cgd stat0 = hd->hpib_mis;
529 1.1 cgd stat1 = hd->hpib_lis;
530 1.14 thorpej
531 1.14 thorpej hq = hs->sc_queue.tqh_first;
532 1.14 thorpej
533 1.1 cgd if (hs->sc_flags & HPIBF_IO) {
534 1.1 cgd hd->hpib_mim = 0;
535 1.6 mycroft if ((hs->sc_flags & HPIBF_DONE) == 0) {
536 1.6 mycroft hs->sc_flags &= ~HPIBF_TIMO;
537 1.14 thorpej dmastop(hs->sc_dq->dq_chan);
538 1.6 mycroft } else if (hs->sc_flags & HPIBF_TIMO)
539 1.22 thorpej callout_stop(&sc->sc_read_ch);
540 1.1 cgd hd->hpib_acr = AUX_TCA;
541 1.6 mycroft hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO);
542 1.14 thorpej
543 1.14 thorpej dmafree(hs->sc_dq);
544 1.14 thorpej (hq->hq_intr)(hq->hq_softc);
545 1.1 cgd } else if (hs->sc_flags & HPIBF_PPOLL) {
546 1.1 cgd hd->hpib_mim = 0;
547 1.14 thorpej stat0 = nhpibppoll(hs);
548 1.14 thorpej if (stat0 & (0x80 >> hq->hq_slave)) {
549 1.1 cgd hs->sc_flags &= ~HPIBF_PPOLL;
550 1.14 thorpej (hq->hq_intr)(hq->hq_softc);
551 1.1 cgd }
552 1.1 cgd #ifdef DEBUG
553 1.1 cgd else
554 1.13 christos printf("%s: PPOLL intr bad status %x\n",
555 1.14 thorpej hs->sc_dev.dv_xname, stat0);
556 1.1 cgd #endif
557 1.1 cgd }
558 1.35 tsutsui return 1;
559 1.1 cgd }
560 1.1 cgd
561 1.31 thorpej static int
562 1.31 thorpej nhpibppoll(struct hpibbus_softc *hs)
563 1.1 cgd {
564 1.33 thorpej struct nhpib_softc *sc =
565 1.33 thorpej (struct nhpib_softc *)device_parent(&hs->sc_dev);
566 1.14 thorpej struct nhpibdevice *hd = sc->sc_regs;
567 1.14 thorpej int ppoll;
568 1.1 cgd
569 1.1 cgd hd->hpib_acr = AUX_SPP;
570 1.1 cgd DELAY(25);
571 1.1 cgd ppoll = hd->hpib_cpt;
572 1.1 cgd hd->hpib_acr = AUX_CPP;
573 1.35 tsutsui return ppoll;
574 1.1 cgd }
575 1.1 cgd
576 1.6 mycroft #ifdef DEBUG
577 1.6 mycroft int nhpibreporttimo = 0;
578 1.6 mycroft #endif
579 1.6 mycroft
580 1.31 thorpej static int
581 1.31 thorpej nhpibwait(struct nhpibdevice *hd, int x)
582 1.1 cgd {
583 1.15 scottr int timo = hpibtimeout;
584 1.1 cgd
585 1.1 cgd while ((hd->hpib_mis & x) == 0 && --timo)
586 1.11 thorpej DELAY(1);
587 1.6 mycroft if (timo == 0) {
588 1.6 mycroft #ifdef DEBUG
589 1.6 mycroft if (nhpibreporttimo)
590 1.13 christos printf("hpib0: %s timo\n", x==MIS_BO?"OUT":"IN");
591 1.6 mycroft #endif
592 1.35 tsutsui return -1;
593 1.6 mycroft }
594 1.35 tsutsui return 0;
595 1.1 cgd }
596 1.1 cgd
597 1.31 thorpej static void
598 1.31 thorpej nhpibppwatch(void *arg)
599 1.1 cgd {
600 1.14 thorpej struct hpibbus_softc *hs = arg;
601 1.33 thorpej struct nhpib_softc *sc =
602 1.33 thorpej (struct nhpib_softc *)device_parent(&hs->sc_dev);
603 1.1 cgd
604 1.1 cgd if ((hs->sc_flags & HPIBF_PPOLL) == 0)
605 1.1 cgd return;
606 1.4 mycroft again:
607 1.14 thorpej if (nhpibppoll(hs) & (0x80 >> hs->sc_queue.tqh_first->hq_slave))
608 1.34 tsutsui sc->sc_regs->hpib_mim = MIS_BO;
609 1.4 mycroft else if (cold)
610 1.4 mycroft /* timeouts not working yet */
611 1.4 mycroft goto again;
612 1.1 cgd else
613 1.22 thorpej callout_reset(&sc->sc_ppwatch_ch, 1, nhpibppwatch, hs);
614 1.1 cgd }
615