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