nhpib.c revision 1.11 1 /* $NetBSD: nhpib.c,v 1.11 1996/05/18 23:57:01 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((void *));
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 hc->hp_ipl = HPIBA_IPL;
110 return (1);
111 } else if (hd->hpib_cid == HPIBB) {
112 hs->sc_type = HPIBB;
113 hc->hp_ipl = HPIB_IPL(hd->hpib_ids);
114 return (1);
115 }
116
117 return(0);
118 }
119
120 void
121 nhpibattach(hc)
122 register struct hp_ctlr *hc;
123 {
124 struct hpib_softc *hs = &hpib_softc[hc->hp_unit];
125 register struct nhpibdevice *hd = (struct nhpibdevice *)hc->hp_addr;
126
127 switch (hs->sc_type) {
128 case HPIBA:
129 hs->sc_ba = HPIBA_BA;
130 hs->sc_descrip = "Internal HP-IB";
131 break;
132
133 case HPIBB:
134 hs->sc_ba = hd->hpib_csa & CSA_BA;
135 hs->sc_descrip = "98624 HP-IB";
136 break;
137
138 default:
139 panic("nhpibattach: unknown type 0x%x", hs->sc_type);
140 /* NOTREACHED */
141 }
142
143 hs->sc_controller = &nhpib_controller;
144 }
145
146 void
147 nhpibreset(unit)
148 int unit;
149 {
150 register struct hpib_softc *hs = &hpib_softc[unit];
151 register struct nhpibdevice *hd;
152
153 hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
154 hd->hpib_acr = AUX_SSWRST;
155 hd->hpib_ar = hs->sc_ba;
156 hd->hpib_lim = LIS_ERR;
157 hd->hpib_mim = 0;
158 hd->hpib_acr = AUX_CDAI;
159 hd->hpib_acr = AUX_CSHDW;
160 hd->hpib_acr = AUX_SSTD1;
161 hd->hpib_acr = AUX_SVSTD1;
162 hd->hpib_acr = AUX_CPP;
163 hd->hpib_acr = AUX_CHDFA;
164 hd->hpib_acr = AUX_CHDFE;
165 hd->hpib_acr = AUX_RHDF;
166 hd->hpib_acr = AUX_CSWRST;
167 nhpibifc(hd);
168 hd->hpib_ie = IDS_IE;
169 hd->hpib_data = C_DCL_P;
170 DELAY(100000);
171 }
172
173 nhpibifc(hd)
174 register struct nhpibdevice *hd;
175 {
176 hd->hpib_acr = AUX_TCA;
177 hd->hpib_acr = AUX_CSRE;
178 hd->hpib_acr = AUX_SSIC;
179 DELAY(100);
180 hd->hpib_acr = AUX_CSIC;
181 hd->hpib_acr = AUX_SSRE;
182 }
183
184 int
185 nhpibsend(unit, slave, sec, ptr, origcnt)
186 int unit, slave, sec, origcnt;
187 void *ptr;
188 {
189 register struct hpib_softc *hs = &hpib_softc[unit];
190 register struct nhpibdevice *hd;
191 register int cnt = origcnt;
192 char *addr = ptr;
193
194 hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
195 hd->hpib_acr = AUX_TCA;
196 hd->hpib_data = C_UNL_P;
197 if (nhpibwait(hd, MIS_BO))
198 goto senderror;
199 hd->hpib_data = talker_par[hs->sc_ba];
200 hd->hpib_acr = AUX_STON;
201 if (nhpibwait(hd, MIS_BO))
202 goto senderror;
203 hd->hpib_data = listnr_par[slave];
204 if (nhpibwait(hd, MIS_BO))
205 goto senderror;
206 if (sec >= 0 || sec == -2) {
207 if (sec == -2) /* selected device clear KLUDGE */
208 hd->hpib_data = C_SDC_P;
209 else
210 hd->hpib_data = sec_par[sec];
211 if (nhpibwait(hd, MIS_BO))
212 goto senderror;
213 }
214 hd->hpib_acr = AUX_GTS;
215 if (cnt) {
216 while (--cnt > 0) {
217 hd->hpib_data = *addr++;
218 if (nhpibwait(hd, MIS_BO))
219 goto senderror;
220 }
221 hd->hpib_acr = AUX_EOI;
222 hd->hpib_data = *addr;
223 if (nhpibwait(hd, MIS_BO))
224 goto senderror;
225 hd->hpib_acr = AUX_TCA;
226 #if 0
227 /*
228 * May be causing 345 disks to hang due to interference
229 * with PPOLL mechanism.
230 */
231 hd->hpib_data = C_UNL_P;
232 (void) nhpibwait(hd, MIS_BO);
233 #endif
234 }
235 return(origcnt);
236
237 senderror:
238 nhpibifc(hd);
239 return(origcnt - cnt - 1);
240 }
241
242 int
243 nhpibrecv(unit, slave, sec, ptr, origcnt)
244 int unit, slave, sec, origcnt;
245 void *ptr;
246 {
247 register struct hpib_softc *hs = &hpib_softc[unit];
248 register struct nhpibdevice *hd;
249 register int cnt = origcnt;
250 char *addr = ptr;
251
252 hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
253 /*
254 * Slave < 0 implies continuation of a previous receive
255 * that probably timed out.
256 */
257 if (slave >= 0) {
258 hd->hpib_acr = AUX_TCA;
259 hd->hpib_data = C_UNL_P;
260 if (nhpibwait(hd, MIS_BO))
261 goto recverror;
262 hd->hpib_data = listnr_par[hs->sc_ba];
263 hd->hpib_acr = AUX_SLON;
264 if (nhpibwait(hd, MIS_BO))
265 goto recverror;
266 hd->hpib_data = talker_par[slave];
267 if (nhpibwait(hd, MIS_BO))
268 goto recverror;
269 if (sec >= 0) {
270 hd->hpib_data = sec_par[sec];
271 if (nhpibwait(hd, MIS_BO))
272 goto recverror;
273 }
274 hd->hpib_acr = AUX_RHDF;
275 hd->hpib_acr = AUX_GTS;
276 }
277 if (cnt) {
278 while (--cnt >= 0) {
279 if (nhpibwait(hd, MIS_BI))
280 goto recvbyteserror;
281 *addr++ = hd->hpib_data;
282 }
283 hd->hpib_acr = AUX_TCA;
284 hd->hpib_data = (slave == 31) ? C_UNA_P : C_UNT_P;
285 (void) nhpibwait(hd, MIS_BO);
286 }
287 return(origcnt);
288
289 recverror:
290 nhpibifc(hd);
291 recvbyteserror:
292 return(origcnt - cnt - 1);
293 }
294
295 void
296 nhpibgo(unit, slave, sec, ptr, count, rw, timo)
297 int unit, slave, sec, count, rw, timo;
298 void *ptr;
299 {
300 register struct hpib_softc *hs = &hpib_softc[unit];
301 register struct nhpibdevice *hd;
302 char *addr = ptr;
303
304 hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
305 hs->sc_flags |= HPIBF_IO;
306 if (timo)
307 hs->sc_flags |= HPIBF_TIMO;
308 if (rw == B_READ)
309 hs->sc_flags |= HPIBF_READ;
310 #ifdef DEBUG
311 else if (hs->sc_flags & HPIBF_READ) {
312 printf("nhpibgo: HPIBF_READ still set\n");
313 hs->sc_flags &= ~HPIBF_READ;
314 }
315 #endif
316 hs->sc_count = count;
317 hs->sc_addr = addr;
318 if (hs->sc_flags & HPIBF_READ) {
319 hs->sc_curcnt = count;
320 dmago(hs->sc_dq.dq_ctlr, addr, count, DMAGO_BYTE|DMAGO_READ);
321 nhpibrecv(unit, slave, sec, 0, 0);
322 hd->hpib_mim = MIS_END;
323 } else {
324 hd->hpib_mim = 0;
325 if (count < hpibdmathresh) {
326 hs->sc_curcnt = count;
327 nhpibsend(unit, slave, sec, addr, count);
328 nhpibdone(unit);
329 return;
330 }
331 hs->sc_curcnt = --count;
332 dmago(hs->sc_dq.dq_ctlr, addr, count, DMAGO_BYTE);
333 nhpibsend(unit, slave, sec, 0, 0);
334 }
335 hd->hpib_ie = IDS_IE | IDS_DMA(hs->sc_dq.dq_ctlr);
336 }
337
338 /*
339 * This timeout can only happen if a DMA read finishes DMAing with the read
340 * still pending (more data in read transaction than the driver was prepared
341 * to accept). At the moment, variable-record tape drives are the only things
342 * capabale of doing this. We repeat the necessary code from nhpibintr() -
343 * easier and quicker than calling nhpibintr() for this special case.
344 */
345 void
346 nhpibreadtimo(arg)
347 void *arg;
348 {
349 int unit;
350 register struct hpib_softc *hs;
351 int s = splbio();
352
353 unit = (int)arg;
354 hs = &hpib_softc[unit];
355 if (hs->sc_flags & HPIBF_IO) {
356 register struct nhpibdevice *hd;
357 register struct devqueue *dq;
358
359 hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
360 hd->hpib_mim = 0;
361 hd->hpib_acr = AUX_TCA;
362 hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO);
363 dmafree(&hs->sc_dq);
364 dq = hs->sc_sq.dq_forw;
365 (dq->dq_driver->d_intr)(dq->dq_softc);
366 }
367 (void) splx(s);
368 }
369
370 void
371 nhpibdone(unit)
372 register int unit;
373 {
374 register struct hpib_softc *hs = &hpib_softc[unit];
375 register struct nhpibdevice *hd;
376 register int cnt;
377
378 hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
379 cnt = hs->sc_curcnt;
380 hs->sc_addr += cnt;
381 hs->sc_count -= cnt;
382 hs->sc_flags |= HPIBF_DONE;
383 hd->hpib_ie = IDS_IE;
384 if (hs->sc_flags & HPIBF_READ) {
385 if ((hs->sc_flags & HPIBF_TIMO) &&
386 (hd->hpib_ids & IDS_IR) == 0)
387 timeout(nhpibreadtimo, (void *)unit, hz >> 2);
388 } else {
389 if (hs->sc_count == 1) {
390 (void) nhpibwait(hd, MIS_BO);
391 hd->hpib_acr = AUX_EOI;
392 hd->hpib_data = *hs->sc_addr;
393 hd->hpib_mim = MIS_BO;
394 }
395 #ifdef DEBUG
396 else if (hs->sc_count)
397 panic("nhpibdone");
398 #endif
399 }
400 }
401
402 int
403 nhpibintr(arg)
404 void *arg;
405 {
406 register struct hpib_softc *hs = arg;
407 register struct nhpibdevice *hd;
408 register struct devqueue *dq;
409 register int stat0;
410 int stat1, unit = hs->sc_hc->hp_unit;
411
412 #ifdef lint
413 if (stat1 = unit) return(1);
414 #endif
415 hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
416 if ((hd->hpib_ids & IDS_IR) == 0)
417 return(0);
418 stat0 = hd->hpib_mis;
419 stat1 = hd->hpib_lis;
420 dq = hs->sc_sq.dq_forw;
421 if (hs->sc_flags & HPIBF_IO) {
422 hd->hpib_mim = 0;
423 if ((hs->sc_flags & HPIBF_DONE) == 0) {
424 hs->sc_flags &= ~HPIBF_TIMO;
425 dmastop(hs->sc_dq.dq_ctlr);
426 } else if (hs->sc_flags & HPIBF_TIMO)
427 untimeout(nhpibreadtimo, (void *)unit);
428 hd->hpib_acr = AUX_TCA;
429 hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO);
430 dmafree(&hs->sc_dq);
431 (dq->dq_driver->d_intr)(dq->dq_softc);
432 } else if (hs->sc_flags & HPIBF_PPOLL) {
433 hd->hpib_mim = 0;
434 stat0 = nhpibppoll(unit);
435 if (stat0 & (0x80 >> dq->dq_slave)) {
436 hs->sc_flags &= ~HPIBF_PPOLL;
437 (dq->dq_driver->d_intr)(dq->dq_softc);
438 }
439 #ifdef DEBUG
440 else
441 printf("%s: PPOLL intr bad status %x\n",
442 hs->sc_hc->hp_xname, stat0);
443 #endif
444 }
445 return(1);
446 }
447
448 int
449 nhpibppoll(unit)
450 int unit;
451 {
452 register struct nhpibdevice *hd;
453 register int ppoll;
454
455 hd = (struct nhpibdevice *)hpib_softc[unit].sc_hc->hp_addr;
456 hd->hpib_acr = AUX_SPP;
457 DELAY(25);
458 ppoll = hd->hpib_cpt;
459 hd->hpib_acr = AUX_CPP;
460 return(ppoll);
461 }
462
463 #ifdef DEBUG
464 int nhpibreporttimo = 0;
465 #endif
466
467 int
468 nhpibwait(hd, x)
469 register struct nhpibdevice *hd;
470 int x;
471 {
472 register int timo = hpibtimeout;
473
474 while ((hd->hpib_mis & x) == 0 && --timo)
475 DELAY(1);
476 if (timo == 0) {
477 #ifdef DEBUG
478 if (nhpibreporttimo)
479 printf("hpib0: %s timo\n", x==MIS_BO?"OUT":"IN");
480 #endif
481 return(-1);
482 }
483 return(0);
484 }
485
486 void
487 nhpibppwatch(arg)
488 void *arg;
489 {
490 register struct hpib_softc *hs;
491 register int unit;
492 extern int cold;
493
494 unit = (int)arg;
495 hs = &hpib_softc[unit];
496 if ((hs->sc_flags & HPIBF_PPOLL) == 0)
497 return;
498 again:
499 if (nhpibppoll(unit) & (0x80 >> hs->sc_sq.dq_forw->dq_slave))
500 ((struct nhpibdevice *)hs->sc_hc->hp_addr)->hpib_mim = MIS_BO;
501 else if (cold)
502 /* timeouts not working yet */
503 goto again;
504 else
505 timeout(nhpibppwatch, (void *)unit, 1);
506 }
507 #endif /* NHPIB > 0 */
508