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