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