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