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