nhpib.c revision 1.17 1 /* $NetBSD: nhpib.c,v 1.17 1997/05/05 21:06:41 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) dio_intr_establish(nhpibintr, sc, ipl, IPL_BIO);
181
182 ha.ha_ops = &nhpib_controller;
183 ha.ha_type = type; /* XXX */
184 ha.ha_ba = (type == HPIBA) ? HPIBA_BA :
185 (sc->sc_regs->hpib_csa & CSA_BA);
186 ha.ha_softcpp = &sc->sc_hpibbus; /* XXX */
187 (void)config_found(self, &ha, hpibdevprint);
188 }
189
190 void
191 nhpibreset(hs)
192 struct hpibbus_softc *hs;
193 {
194 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
195 struct nhpibdevice *hd = sc->sc_regs;
196
197 hd->hpib_acr = AUX_SSWRST;
198 hd->hpib_ar = hs->sc_ba;
199 hd->hpib_lim = LIS_ERR;
200 hd->hpib_mim = 0;
201 hd->hpib_acr = AUX_CDAI;
202 hd->hpib_acr = AUX_CSHDW;
203 hd->hpib_acr = AUX_SSTD1;
204 hd->hpib_acr = AUX_SVSTD1;
205 hd->hpib_acr = AUX_CPP;
206 hd->hpib_acr = AUX_CHDFA;
207 hd->hpib_acr = AUX_CHDFE;
208 hd->hpib_acr = AUX_RHDF;
209 hd->hpib_acr = AUX_CSWRST;
210 nhpibifc(hd);
211 hd->hpib_ie = IDS_IE;
212 hd->hpib_data = C_DCL_P;
213 DELAY(100000);
214 }
215
216 void
217 nhpibifc(hd)
218 struct nhpibdevice *hd;
219 {
220 hd->hpib_acr = AUX_TCA;
221 hd->hpib_acr = AUX_CSRE;
222 hd->hpib_acr = AUX_SSIC;
223 DELAY(100);
224 hd->hpib_acr = AUX_CSIC;
225 hd->hpib_acr = AUX_SSRE;
226 }
227
228 int
229 nhpibsend(hs, slave, sec, ptr, origcnt)
230 struct hpibbus_softc *hs;
231 int slave, sec, origcnt;
232 void *ptr;
233 {
234 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
235 struct nhpibdevice *hd = sc->sc_regs;
236 int cnt = origcnt;
237 char *addr = ptr;
238
239 hd->hpib_acr = AUX_TCA;
240 hd->hpib_data = C_UNL_P;
241 if (nhpibwait(hd, MIS_BO))
242 goto senderror;
243 hd->hpib_data = talker_par[hs->sc_ba];
244 hd->hpib_acr = AUX_STON;
245 if (nhpibwait(hd, MIS_BO))
246 goto senderror;
247 hd->hpib_data = listnr_par[slave];
248 if (nhpibwait(hd, MIS_BO))
249 goto senderror;
250 if (sec >= 0 || sec == -2) {
251 if (sec == -2) /* selected device clear KLUDGE */
252 hd->hpib_data = C_SDC_P;
253 else
254 hd->hpib_data = sec_par[sec];
255 if (nhpibwait(hd, MIS_BO))
256 goto senderror;
257 }
258 hd->hpib_acr = AUX_GTS;
259 if (cnt) {
260 while (--cnt > 0) {
261 hd->hpib_data = *addr++;
262 if (nhpibwait(hd, MIS_BO))
263 goto senderror;
264 }
265 hd->hpib_acr = AUX_EOI;
266 hd->hpib_data = *addr;
267 if (nhpibwait(hd, MIS_BO))
268 goto senderror;
269 hd->hpib_acr = AUX_TCA;
270 #if 0
271 /*
272 * May be causing 345 disks to hang due to interference
273 * with PPOLL mechanism.
274 */
275 hd->hpib_data = C_UNL_P;
276 (void) nhpibwait(hd, MIS_BO);
277 #endif
278 }
279 return(origcnt);
280
281 senderror:
282 nhpibifc(hd);
283 return(origcnt - cnt - 1);
284 }
285
286 int
287 nhpibrecv(hs, slave, sec, ptr, origcnt)
288 struct hpibbus_softc *hs;
289 int slave, sec, origcnt;
290 void *ptr;
291 {
292 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
293 struct nhpibdevice *hd = sc->sc_regs;
294 int cnt = origcnt;
295 char *addr = ptr;
296
297 /*
298 * Slave < 0 implies continuation of a previous receive
299 * that probably timed out.
300 */
301 if (slave >= 0) {
302 hd->hpib_acr = AUX_TCA;
303 hd->hpib_data = C_UNL_P;
304 if (nhpibwait(hd, MIS_BO))
305 goto recverror;
306 hd->hpib_data = listnr_par[hs->sc_ba];
307 hd->hpib_acr = AUX_SLON;
308 if (nhpibwait(hd, MIS_BO))
309 goto recverror;
310 hd->hpib_data = talker_par[slave];
311 if (nhpibwait(hd, MIS_BO))
312 goto recverror;
313 if (sec >= 0) {
314 hd->hpib_data = sec_par[sec];
315 if (nhpibwait(hd, MIS_BO))
316 goto recverror;
317 }
318 hd->hpib_acr = AUX_RHDF;
319 hd->hpib_acr = AUX_GTS;
320 }
321 if (cnt) {
322 while (--cnt >= 0) {
323 if (nhpibwait(hd, MIS_BI))
324 goto recvbyteserror;
325 *addr++ = hd->hpib_data;
326 }
327 hd->hpib_acr = AUX_TCA;
328 hd->hpib_data = (slave == 31) ? C_UNA_P : C_UNT_P;
329 (void) nhpibwait(hd, MIS_BO);
330 }
331 return(origcnt);
332
333 recverror:
334 nhpibifc(hd);
335 recvbyteserror:
336 return(origcnt - cnt - 1);
337 }
338
339 void
340 nhpibgo(hs, slave, sec, ptr, count, rw, timo)
341 struct hpibbus_softc *hs;
342 int slave, sec, count, rw, timo;
343 void *ptr;
344 {
345 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
346 struct nhpibdevice *hd = sc->sc_regs;
347 char *addr = ptr;
348
349 hs->sc_flags |= HPIBF_IO;
350 if (timo)
351 hs->sc_flags |= HPIBF_TIMO;
352 if (rw == B_READ)
353 hs->sc_flags |= HPIBF_READ;
354 #ifdef DEBUG
355 else if (hs->sc_flags & HPIBF_READ) {
356 printf("nhpibgo: HPIBF_READ still set\n");
357 hs->sc_flags &= ~HPIBF_READ;
358 }
359 #endif
360 hs->sc_count = count;
361 hs->sc_addr = addr;
362 if (hs->sc_flags & HPIBF_READ) {
363 hs->sc_curcnt = count;
364 dmago(hs->sc_dq->dq_chan, addr, count, DMAGO_BYTE|DMAGO_READ);
365 nhpibrecv(hs, slave, sec, 0, 0);
366 hd->hpib_mim = MIS_END;
367 } else {
368 hd->hpib_mim = 0;
369 if (count < hpibdmathresh) {
370 hs->sc_curcnt = count;
371 nhpibsend(hs, slave, sec, addr, count);
372 nhpibdone(hs);
373 return;
374 }
375 hs->sc_curcnt = --count;
376 dmago(hs->sc_dq->dq_chan, addr, count, DMAGO_BYTE);
377 nhpibsend(hs, slave, sec, 0, 0);
378 }
379 hd->hpib_ie = IDS_IE | IDS_DMA(hs->sc_dq->dq_chan);
380 }
381
382 /*
383 * This timeout can only happen if a DMA read finishes DMAing with the read
384 * still pending (more data in read transaction than the driver was prepared
385 * to accept). At the moment, variable-record tape drives are the only things
386 * capabale of doing this. We repeat the necessary code from nhpibintr() -
387 * easier and quicker than calling nhpibintr() for this special case.
388 */
389 void
390 nhpibreadtimo(arg)
391 void *arg;
392 {
393 struct hpibbus_softc *hs = arg;
394 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
395 int s = splbio();
396
397 if (hs->sc_flags & HPIBF_IO) {
398 struct nhpibdevice *hd = sc->sc_regs;
399 struct hpibqueue *hq;
400
401 hd->hpib_mim = 0;
402 hd->hpib_acr = AUX_TCA;
403 hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO);
404 dmafree(hs->sc_dq);
405
406 hq = hs->sc_queue.tqh_first;
407 (hq->hq_intr)(hq->hq_softc);
408 }
409 splx(s);
410 }
411
412 void
413 nhpibdone(hs)
414 struct hpibbus_softc *hs;
415 {
416 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
417 struct nhpibdevice *hd = sc->sc_regs;
418 int cnt;
419
420 cnt = hs->sc_curcnt;
421 hs->sc_addr += cnt;
422 hs->sc_count -= cnt;
423 hs->sc_flags |= HPIBF_DONE;
424 hd->hpib_ie = IDS_IE;
425 if (hs->sc_flags & HPIBF_READ) {
426 if ((hs->sc_flags & HPIBF_TIMO) &&
427 (hd->hpib_ids & IDS_IR) == 0)
428 timeout(nhpibreadtimo, hs, hz >> 2);
429 } else {
430 if (hs->sc_count == 1) {
431 (void) nhpibwait(hd, MIS_BO);
432 hd->hpib_acr = AUX_EOI;
433 hd->hpib_data = *hs->sc_addr;
434 hd->hpib_mim = MIS_BO;
435 }
436 #ifdef DEBUG
437 else if (hs->sc_count)
438 panic("nhpibdone");
439 #endif
440 }
441 }
442
443 int
444 nhpibintr(arg)
445 void *arg;
446 {
447 struct nhpib_softc *sc = arg;
448 struct hpibbus_softc *hs = sc->sc_hpibbus;
449 struct nhpibdevice *hd = sc->sc_regs;
450 struct hpibqueue *hq;
451 int stat0;
452 int stat1;
453
454 #ifdef lint
455 if (stat1 = unit) return(1);
456 #endif
457 if ((hd->hpib_ids & IDS_IR) == 0)
458 return(0);
459 stat0 = hd->hpib_mis;
460 stat1 = hd->hpib_lis;
461
462 hq = hs->sc_queue.tqh_first;
463
464 if (hs->sc_flags & HPIBF_IO) {
465 hd->hpib_mim = 0;
466 if ((hs->sc_flags & HPIBF_DONE) == 0) {
467 hs->sc_flags &= ~HPIBF_TIMO;
468 dmastop(hs->sc_dq->dq_chan);
469 } else if (hs->sc_flags & HPIBF_TIMO)
470 untimeout(nhpibreadtimo, hs);
471 hd->hpib_acr = AUX_TCA;
472 hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO);
473
474 dmafree(hs->sc_dq);
475 (hq->hq_intr)(hq->hq_softc);
476 } else if (hs->sc_flags & HPIBF_PPOLL) {
477 hd->hpib_mim = 0;
478 stat0 = nhpibppoll(hs);
479 if (stat0 & (0x80 >> hq->hq_slave)) {
480 hs->sc_flags &= ~HPIBF_PPOLL;
481 (hq->hq_intr)(hq->hq_softc);
482 }
483 #ifdef DEBUG
484 else
485 printf("%s: PPOLL intr bad status %x\n",
486 hs->sc_dev.dv_xname, stat0);
487 #endif
488 }
489 return(1);
490 }
491
492 int
493 nhpibppoll(hs)
494 struct hpibbus_softc *hs;
495 {
496 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
497 struct nhpibdevice *hd = sc->sc_regs;
498 int ppoll;
499
500 hd->hpib_acr = AUX_SPP;
501 DELAY(25);
502 ppoll = hd->hpib_cpt;
503 hd->hpib_acr = AUX_CPP;
504 return(ppoll);
505 }
506
507 #ifdef DEBUG
508 int nhpibreporttimo = 0;
509 #endif
510
511 int
512 nhpibwait(hd, x)
513 struct nhpibdevice *hd;
514 int x;
515 {
516 int timo = hpibtimeout;
517
518 while ((hd->hpib_mis & x) == 0 && --timo)
519 DELAY(1);
520 if (timo == 0) {
521 #ifdef DEBUG
522 if (nhpibreporttimo)
523 printf("hpib0: %s timo\n", x==MIS_BO?"OUT":"IN");
524 #endif
525 return(-1);
526 }
527 return(0);
528 }
529
530 void
531 nhpibppwatch(arg)
532 void *arg;
533 {
534 struct hpibbus_softc *hs = arg;
535 struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
536 extern int cold;
537
538 if ((hs->sc_flags & HPIBF_PPOLL) == 0)
539 return;
540 again:
541 if (nhpibppoll(hs) & (0x80 >> hs->sc_queue.tqh_first->hq_slave))
542 sc->sc_regs->hpib_mim = MIS_BO;
543 else if (cold)
544 /* timeouts not working yet */
545 goto again;
546 else
547 timeout(nhpibppwatch, hs, 1);
548 }
549