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