nhpib.c revision 1.7 1 /* $NetBSD: nhpib.c,v 1.7 1995/11/19 17:57:19 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1982, 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)nhpib.c 8.2 (Berkeley) 1/12/94
36 */
37
38 /*
39 * Internal/98624 HPIB driver
40 */
41 #include "hpib.h"
42 #if NHPIB > 0
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
47 #include <sys/buf.h>
48
49 #include <hp300/dev/device.h>
50 #include <hp300/dev/nhpibreg.h>
51 #include <hp300/dev/hpibvar.h>
52 #include <hp300/dev/dmavar.h>
53
54 /*
55 * ODD parity table for listen and talk addresses and secondary commands.
56 * The TI9914A doesn't produce the parity bit.
57 */
58 static u_char listnr_par[] = {
59 0040,0241,0242,0043,0244,0045,0046,0247,
60 0250,0051,0052,0253,0054,0255,0256,0057,
61 0260,0061,0062,0263,0064,0265,0266,0067,
62 0070,0271,0272,0073,0274,0075,0076,0277,
63 };
64 static u_char talker_par[] = {
65 0100,0301,0302,0103,0304,0105,0106,0307,
66 0310,0111,0112,0313,0114,0315,0316,0117,
67 0320,0121,0122,0323,0124,0325,0326,0127,
68 0130,0331,0332,0133,0334,0135,0136,0337,
69 };
70 static u_char sec_par[] = {
71 0340,0141,0142,0343,0144,0345,0346,0147,
72 0150,0351,0352,0153,0354,0155,0156,0357,
73 0160,0361,0362,0163,0364,0165,0166,0367,
74 0370,0171,0172,0373,0174,0375,0376,0177
75 };
76
77 void nhpibreset __P((int));
78 int nhpibsend __P((int, int, int, void *, int));
79 int nhpibrecv __P((int, int, int, void *, int));
80 int nhpibppoll __P((int));
81 void nhpibppwatch __P((void *));
82 void nhpibgo __P((int, int, int, void *, int, int, int));
83 void nhpibdone __P((int));
84 int nhpibintr __P((int));
85
86 /*
87 * Our controller ops structure.
88 */
89 struct hpib_controller nhpib_controller = {
90 nhpibreset,
91 nhpibsend,
92 nhpibrecv,
93 nhpibppoll,
94 nhpibppwatch,
95 nhpibgo,
96 nhpibdone,
97 nhpibintr
98 };
99
100 int
101 nhpibtype(hc)
102 register struct hp_ctlr *hc;
103 {
104 register struct hpib_softc *hs = &hpib_softc[hc->hp_unit];
105 register struct nhpibdevice *hd = (struct nhpibdevice *)hc->hp_addr;
106
107 if (hc->hp_addr == internalhpib) {
108 hs->sc_type = HPIBA;
109 hs->sc_ba = HPIBA_BA;
110 hc->hp_ipl = HPIBA_IPL;
111 hs->sc_descrip = "Internal HP-IB";
112 }
113 else if (hd->hpib_cid == HPIBB) {
114 hs->sc_type = HPIBB;
115 hs->sc_ba = hd->hpib_csa & CSA_BA;
116 hc->hp_ipl = HPIB_IPL(hd->hpib_ids);
117 hs->sc_descrip = "98624 HP-IB";
118 }
119 else
120 return(0);
121
122 hs->sc_controller = &nhpib_controller;
123 return(1);
124 }
125
126 void
127 nhpibreset(unit)
128 int unit;
129 {
130 register struct hpib_softc *hs = &hpib_softc[unit];
131 register struct nhpibdevice *hd;
132
133 hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
134 hd->hpib_acr = AUX_SSWRST;
135 hd->hpib_ar = hs->sc_ba;
136 hd->hpib_lim = LIS_ERR;
137 hd->hpib_mim = 0;
138 hd->hpib_acr = AUX_CDAI;
139 hd->hpib_acr = AUX_CSHDW;
140 hd->hpib_acr = AUX_SSTD1;
141 hd->hpib_acr = AUX_SVSTD1;
142 hd->hpib_acr = AUX_CPP;
143 hd->hpib_acr = AUX_CHDFA;
144 hd->hpib_acr = AUX_CHDFE;
145 hd->hpib_acr = AUX_RHDF;
146 hd->hpib_acr = AUX_CSWRST;
147 nhpibifc(hd);
148 hd->hpib_ie = IDS_IE;
149 hd->hpib_data = C_DCL_P;
150 DELAY(100000);
151 }
152
153 nhpibifc(hd)
154 register struct nhpibdevice *hd;
155 {
156 hd->hpib_acr = AUX_TCA;
157 hd->hpib_acr = AUX_CSRE;
158 hd->hpib_acr = AUX_SSIC;
159 DELAY(100);
160 hd->hpib_acr = AUX_CSIC;
161 hd->hpib_acr = AUX_SSRE;
162 }
163
164 int
165 nhpibsend(unit, slave, sec, ptr, origcnt)
166 int unit, slave, sec, origcnt;
167 void *ptr;
168 {
169 register struct hpib_softc *hs = &hpib_softc[unit];
170 register struct nhpibdevice *hd;
171 register int cnt = origcnt;
172 char *addr = ptr;
173
174 hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
175 hd->hpib_acr = AUX_TCA;
176 hd->hpib_data = C_UNL_P;
177 if (nhpibwait(hd, MIS_BO))
178 goto senderror;
179 hd->hpib_data = talker_par[hs->sc_ba];
180 hd->hpib_acr = AUX_STON;
181 if (nhpibwait(hd, MIS_BO))
182 goto senderror;
183 hd->hpib_data = listnr_par[slave];
184 if (nhpibwait(hd, MIS_BO))
185 goto senderror;
186 if (sec >= 0 || sec == -2) {
187 if (sec == -2) /* selected device clear KLUDGE */
188 hd->hpib_data = C_SDC_P;
189 else
190 hd->hpib_data = sec_par[sec];
191 if (nhpibwait(hd, MIS_BO))
192 goto senderror;
193 }
194 hd->hpib_acr = AUX_GTS;
195 if (cnt) {
196 while (--cnt > 0) {
197 hd->hpib_data = *addr++;
198 if (nhpibwait(hd, MIS_BO))
199 goto senderror;
200 }
201 hd->hpib_acr = AUX_EOI;
202 hd->hpib_data = *addr;
203 if (nhpibwait(hd, MIS_BO))
204 goto senderror;
205 hd->hpib_acr = AUX_TCA;
206 #if 0
207 /*
208 * May be causing 345 disks to hang due to interference
209 * with PPOLL mechanism.
210 */
211 hd->hpib_data = C_UNL_P;
212 (void) nhpibwait(hd, MIS_BO);
213 #endif
214 }
215 return(origcnt);
216
217 senderror:
218 nhpibifc(hd);
219 return(origcnt - cnt - 1);
220 }
221
222 int
223 nhpibrecv(unit, slave, sec, ptr, origcnt)
224 int unit, slave, sec, origcnt;
225 void *ptr;
226 {
227 register struct hpib_softc *hs = &hpib_softc[unit];
228 register struct nhpibdevice *hd;
229 register int cnt = origcnt;
230 char *addr = ptr;
231
232 hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
233 /*
234 * Slave < 0 implies continuation of a previous receive
235 * that probably timed out.
236 */
237 if (slave >= 0) {
238 hd->hpib_acr = AUX_TCA;
239 hd->hpib_data = C_UNL_P;
240 if (nhpibwait(hd, MIS_BO))
241 goto recverror;
242 hd->hpib_data = listnr_par[hs->sc_ba];
243 hd->hpib_acr = AUX_SLON;
244 if (nhpibwait(hd, MIS_BO))
245 goto recverror;
246 hd->hpib_data = talker_par[slave];
247 if (nhpibwait(hd, MIS_BO))
248 goto recverror;
249 if (sec >= 0) {
250 hd->hpib_data = sec_par[sec];
251 if (nhpibwait(hd, MIS_BO))
252 goto recverror;
253 }
254 hd->hpib_acr = AUX_RHDF;
255 hd->hpib_acr = AUX_GTS;
256 }
257 if (cnt) {
258 while (--cnt >= 0) {
259 if (nhpibwait(hd, MIS_BI))
260 goto recvbyteserror;
261 *addr++ = hd->hpib_data;
262 }
263 hd->hpib_acr = AUX_TCA;
264 hd->hpib_data = (slave == 31) ? C_UNA_P : C_UNT_P;
265 (void) nhpibwait(hd, MIS_BO);
266 }
267 return(origcnt);
268
269 recverror:
270 nhpibifc(hd);
271 recvbyteserror:
272 return(origcnt - cnt - 1);
273 }
274
275 void
276 nhpibgo(unit, slave, sec, ptr, count, rw, timo)
277 int unit, slave, sec, count, rw, timo;
278 void *ptr;
279 {
280 register struct hpib_softc *hs = &hpib_softc[unit];
281 register struct nhpibdevice *hd;
282 char *addr = ptr;
283
284 hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
285 hs->sc_flags |= HPIBF_IO;
286 if (timo)
287 hs->sc_flags |= HPIBF_TIMO;
288 if (rw == B_READ)
289 hs->sc_flags |= HPIBF_READ;
290 #ifdef DEBUG
291 else if (hs->sc_flags & HPIBF_READ) {
292 printf("nhpibgo: HPIBF_READ still set\n");
293 hs->sc_flags &= ~HPIBF_READ;
294 }
295 #endif
296 hs->sc_count = count;
297 hs->sc_addr = addr;
298 if (hs->sc_flags & HPIBF_READ) {
299 hs->sc_curcnt = count;
300 dmago(hs->sc_dq.dq_ctlr, addr, count, DMAGO_BYTE|DMAGO_READ);
301 nhpibrecv(unit, slave, sec, 0, 0);
302 hd->hpib_mim = MIS_END;
303 } else {
304 hd->hpib_mim = 0;
305 if (count < hpibdmathresh) {
306 hs->sc_curcnt = count;
307 nhpibsend(unit, slave, sec, addr, count);
308 nhpibdone(unit);
309 return;
310 }
311 hs->sc_curcnt = --count;
312 dmago(hs->sc_dq.dq_ctlr, addr, count, DMAGO_BYTE);
313 nhpibsend(unit, slave, sec, 0, 0);
314 }
315 hd->hpib_ie = IDS_IE | IDS_DMA(hs->sc_dq.dq_ctlr);
316 }
317
318 /*
319 * This timeout can only happen if a DMA read finishes DMAing with the read
320 * still pending (more data in read transaction than the driver was prepared
321 * to accept). At the moment, variable-record tape drives are the only things
322 * capabale of doing this. We repeat the necessary code from nhpibintr() -
323 * easier and quicker than calling nhpibintr() for this special case.
324 */
325 void
326 nhpibreadtimo(arg)
327 void *arg;
328 {
329 int unit;
330 register struct hpib_softc *hs;
331 int s = splbio();
332
333 unit = (int)arg;
334 hs = &hpib_softc[unit];
335 if (hs->sc_flags & HPIBF_IO) {
336 register struct nhpibdevice *hd;
337 register struct devqueue *dq;
338
339 hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
340 hd->hpib_mim = 0;
341 hd->hpib_acr = AUX_TCA;
342 hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO);
343 dmafree(&hs->sc_dq);
344 dq = hs->sc_sq.dq_forw;
345 (dq->dq_driver->d_intr)(dq->dq_unit);
346 }
347 (void) splx(s);
348 }
349
350 void
351 nhpibdone(unit)
352 register int unit;
353 {
354 register struct hpib_softc *hs = &hpib_softc[unit];
355 register struct nhpibdevice *hd;
356 register int cnt;
357
358 hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
359 cnt = hs->sc_curcnt;
360 hs->sc_addr += cnt;
361 hs->sc_count -= cnt;
362 hs->sc_flags |= HPIBF_DONE;
363 hd->hpib_ie = IDS_IE;
364 if (hs->sc_flags & HPIBF_READ) {
365 if ((hs->sc_flags & HPIBF_TIMO) &&
366 (hd->hpib_ids & IDS_IR) == 0)
367 timeout(nhpibreadtimo, (void *)unit, hz >> 2);
368 } else {
369 if (hs->sc_count == 1) {
370 (void) nhpibwait(hd, MIS_BO);
371 hd->hpib_acr = AUX_EOI;
372 hd->hpib_data = *hs->sc_addr;
373 hd->hpib_mim = MIS_BO;
374 }
375 #ifdef DEBUG
376 else if (hs->sc_count)
377 panic("nhpibdone");
378 #endif
379 }
380 }
381
382 int
383 nhpibintr(unit)
384 register int unit;
385 {
386 register struct hpib_softc *hs = &hpib_softc[unit];
387 register struct nhpibdevice *hd;
388 register struct devqueue *dq;
389 register int stat0;
390 int stat1;
391
392 #ifdef lint
393 if (stat1 = unit) return(1);
394 #endif
395 hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
396 if ((hd->hpib_ids & IDS_IR) == 0)
397 return(0);
398 stat0 = hd->hpib_mis;
399 stat1 = hd->hpib_lis;
400 dq = hs->sc_sq.dq_forw;
401 if (hs->sc_flags & HPIBF_IO) {
402 hd->hpib_mim = 0;
403 if ((hs->sc_flags & HPIBF_DONE) == 0) {
404 hs->sc_flags &= ~HPIBF_TIMO;
405 dmastop(hs->sc_dq.dq_ctlr);
406 } else if (hs->sc_flags & HPIBF_TIMO)
407 untimeout(nhpibreadtimo, (void *)unit);
408 hd->hpib_acr = AUX_TCA;
409 hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO);
410 dmafree(&hs->sc_dq);
411 (dq->dq_driver->d_intr)(dq->dq_unit);
412 } else if (hs->sc_flags & HPIBF_PPOLL) {
413 hd->hpib_mim = 0;
414 stat0 = nhpibppoll(unit);
415 if (stat0 & (0x80 >> dq->dq_slave)) {
416 hs->sc_flags &= ~HPIBF_PPOLL;
417 (dq->dq_driver->d_intr)(dq->dq_unit);
418 }
419 #ifdef DEBUG
420 else
421 printf("hpib%d: PPOLL intr bad status %x\n",
422 unit, stat0);
423 #endif
424 }
425 return(1);
426 }
427
428 int
429 nhpibppoll(unit)
430 int unit;
431 {
432 register struct nhpibdevice *hd;
433 register int ppoll;
434
435 hd = (struct nhpibdevice *)hpib_softc[unit].sc_hc->hp_addr;
436 hd->hpib_acr = AUX_SPP;
437 DELAY(25);
438 ppoll = hd->hpib_cpt;
439 hd->hpib_acr = AUX_CPP;
440 return(ppoll);
441 }
442
443 #ifdef DEBUG
444 int nhpibreporttimo = 0;
445 #endif
446
447 int
448 nhpibwait(hd, x)
449 register struct nhpibdevice *hd;
450 int x;
451 {
452 register int timo = hpibtimeout;
453
454 while ((hd->hpib_mis & x) == 0 && --timo)
455 DELAY(1);
456 if (timo == 0) {
457 #ifdef DEBUG
458 if (nhpibreporttimo)
459 printf("hpib0: %s timo\n", x==MIS_BO?"OUT":"IN");
460 #endif
461 return(-1);
462 }
463 return(0);
464 }
465
466 void
467 nhpibppwatch(arg)
468 void *arg;
469 {
470 register struct hpib_softc *hs;
471 register int unit;
472 extern int cold;
473
474 unit = (int)arg;
475 hs = &hpib_softc[unit];
476 if ((hs->sc_flags & HPIBF_PPOLL) == 0)
477 return;
478 again:
479 if (nhpibppoll(unit) & (0x80 >> hs->sc_sq.dq_forw->dq_slave))
480 ((struct nhpibdevice *)hs->sc_hc->hp_addr)->hpib_mim = MIS_BO;
481 else if (cold)
482 /* timeouts not working yet */
483 goto again;
484 else
485 timeout(nhpibppwatch, (void *)unit, 1);
486 }
487 #endif /* NHPIB > 0 */
488