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