1 /*-
2 * Copyright (c) 2005 Poul-Henning Kamp <phk@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * High-level driver for µPD7210 based GPIB cards.
27 *
28 */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD: releng/7.3/sys/dev/ieee488/ibfoo.c 179044 2008-05-16 10:11:15Z kris $");
32
33 # define IBDEBUG
34 # undef IBDEBUG
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/conf.h>
39 #include <sys/malloc.h>
40 #include <sys/kernel.h>
41 #include <sys/limits.h>
42 #include <sys/module.h>
43 #include <sys/bus.h>
44 #include <sys/lock.h>
45 #include <sys/mutex.h>
46 #include <sys/uio.h>
47 #include <sys/time.h>
48 #include <machine/bus.h>
49 #include <machine/resource.h>
50 #include <isa/isavar.h>
51
52 #include <dev/ieee488/ugpib.h>
53
54 #define UPD7210_SW_DRIVER
55 #include <dev/ieee488/upd7210.h>
56
57 static MALLOC_DEFINE(M_IBFOO, "IBFOO", "IBFOO");
58
59
60 /* ibfoo API */
61
62 #include <dev/ieee488/ibfoo_int.h>
63
64 /* XXX: This is really a bitmap */
65 enum h_kind {
66 H_DEV = 1,
67 H_BOARD = 2,
68 H_EITHER = 3
69 };
70
71 struct handle {
72 LIST_ENTRY(handle) list;
73 int handle;
74 enum h_kind kind;
75 int pad;
76 int sad;
77 struct timeval timeout;
78 int eot;
79 int eos;
80 int dma;
81 };
82
83 struct ibfoo {
84 struct upd7210 *u;
85 LIST_HEAD(,handle) handles;
86 struct unrhdr *unrhdr;
87 struct callout callout;
88 struct handle *h;
89 struct ibarg *ap;
90
91 enum {
92 IDLE,
93 BUSY,
94 PIO_IDATA,
95 PIO_ODATA,
96 PIO_CMD,
97 DMA_IDATA
98 } mode;
99
100 struct timeval deadline;
101
102 struct handle *rdh; /* addressed for read */
103 struct handle *wrh; /* addressed for write */
104
105 int doeoi;
106
107 u_char *buf;
108 u_int buflen;
109 };
110
111 typedef int ibhandler_t(struct ibfoo *ib);
112
113 static struct timeval timeouts[] = {
114 [TNONE] = { 0, 0},
115 [T10us] = { 0, 10},
116 [T30us] = { 0, 30},
117 [T100us] = { 0, 100},
118 [T300us] = { 0, 300},
119 [T1ms] = { 0, 1000},
120 [T3ms] = { 0, 3000},
121 [T10ms] = { 0, 10000},
122 [T30ms] = { 0, 30000},
123 [T100ms] = { 0, 100000},
124 [T300ms] = { 0, 300000},
125 [T1s] = { 1, 0},
126 [T3s] = { 3, 0},
127 [T10s] = { 10, 0},
128 [T30s] = { 30, 0},
129 [T100s] = { 100, 0},
130 [T300s] = { 300, 0},
131 [T1000s] = { 1000, 0}
132 };
133
134 static const u_int max_timeouts = sizeof timeouts / sizeof timeouts[0];
135
136 static int ibdebug;
137
138 static int
139 ib_set_error(struct ibarg *ap, int error)
140 {
141
142 if (ap->__iberr == 0)
143 ap->__iberr = error;
144 ap->__ibsta |= ERR;
145 ap->__retval = ap->__ibsta;
146 return (0);
147 }
148
149 static int
150 ib_had_timeout(struct ibarg *ap)
151 {
152
153 ib_set_error(ap, EABO);
154 ap->__ibsta |= TIMO;
155 ap->__retval = ap->__ibsta;
156 return (0);
157 }
158
159 static int
160 ib_set_errno(struct ibarg *ap, int errno)
161 {
162
163 if (ap->__iberr == 0) {
164 ap->__iberr = EDVR;
165 ap->__ibcnt = errno;
166 }
167 ap->__ibsta |= ERR;
168 ap->__retval = ap->__ibsta;
169 return (0);
170 }
171
172 static int
173 gpib_ib_irq(struct upd7210 *u, int intr __unused)
174 {
175 struct ibfoo *ib;
176
177 ib = u->ibfoo;
178
179 mtx_assert(&u->mutex, MA_OWNED);
180 switch (ib->mode) {
181 case PIO_CMD:
182 if (!(u->rreg[ISR2] & IXR2_CO))
183 return (0);
184 if (ib->buflen == 0)
185 break;
186 upd7210_wr(u, CDOR, *ib->buf);
187 ib->buf++;
188 ib->buflen--;
189 return (1);
190 case PIO_IDATA:
191 if (!(u->rreg[ISR1] & IXR1_DI))
192 return (0);
193 *ib->buf = upd7210_rd(u, DIR);
194 ib->buf++;
195 ib->buflen--;
196 if (ib->buflen == 0 || (u->rreg[ISR1] & IXR1_ENDRX))
197 break;
198 return (1);
199 case PIO_ODATA:
200 if (!(u->rreg[ISR1] & IXR1_DO))
201 return (0);
202 if (ib->buflen == 0)
203 break;
204 if (ib->buflen == 1 && ib->doeoi)
205 upd7210_wr(u, AUXMR, AUXMR_SEOI);
206 upd7210_wr(u, CDOR, *ib->buf);
207 ib->buf++;
208 ib->buflen--;
209 return (1);
210 case DMA_IDATA:
211 if (!(u->rreg[ISR1] & IXR1_ENDRX))
212 return (0);
213 break;
214 default:
215 return (0);
216 }
217 upd7210_wr(u, IMR1, 0);
218 upd7210_wr(u, IMR2, 0);
219 ib->mode = BUSY;
220 wakeup(&ib->buflen);
221 return (1);
222 }
223
224 static void
225 gpib_ib_timeout(void *arg)
226 {
227 struct upd7210 *u;
228 struct ibfoo *ib;
229 struct timeval tv;
230
231 u = arg;
232 ib = u->ibfoo;
233 mtx_lock(&u->mutex);
234 if (ib->mode == DMA_IDATA && isa_dmatc(u->dmachan)) {
235 KASSERT(u->dmachan >= 0, ("Bogus dmachan = %d", u->dmachan));
236 upd7210_wr(u, IMR1, 0);
237 upd7210_wr(u, IMR2, 0);
238 ib->mode = BUSY;
239 wakeup(&ib->buflen);
240 }
241 if (ib->mode > BUSY) {
242 upd7210_rd(u, ISR1);
243 upd7210_rd(u, ISR2);
244 gpib_ib_irq(u, 2);
245 }
246 if (ib->mode != IDLE && timevalisset(&ib->deadline)) {
247 getmicrouptime(&tv);
248 if (timevalcmp(&ib->deadline, &tv, <)) {
249 ib_had_timeout(ib->ap);
250 upd7210_wr(u, IMR1, 0);
251 upd7210_wr(u, IMR2, 0);
252 ib->mode = BUSY;
253 wakeup(&ib->buflen);
254 }
255 }
256 if (ib->mode != IDLE)
257 callout_reset(&ib->callout, hz / 5, gpib_ib_timeout, arg);
258 mtx_unlock(&u->mutex);
259 }
260
261 static void
262 gpib_ib_wait_xfer(struct upd7210 *u, struct ibfoo *ib)
263 {
264 int i;
265
266 mtx_assert(&u->mutex, MA_OWNED);
267 while (ib->mode > BUSY) {
268 i = msleep(&ib->buflen, &u->mutex,
269 PZERO | PCATCH, "ibwxfr", 0);
270 if (i == EINTR) {
271 ib_set_errno(ib->ap, i);
272 break;
273 }
274 if (u->rreg[ISR1] & IXR1_ERR) {
275 ib_set_error(ib->ap, EABO); /* XXX ? */
276 break;
277 }
278 }
279 ib->mode = BUSY;
280 ib->buf = NULL;
281 upd7210_wr(u, IMR1, 0);
282 upd7210_wr(u, IMR2, 0);
283 }
284
285 static void
286 config_eos(struct upd7210 *u, struct handle *h)
287 {
288 int i;
289
290 i = 0;
291 if (h->eos & REOS) {
292 upd7210_wr(u, EOSR, h->eos & 0xff);
293 i |= AUXA_REOS;
294 }
295 if (h->eos & XEOS) {
296 upd7210_wr(u, EOSR, h->eos & 0xff);
297 i |= AUXA_XEOS;
298 }
299 if (h->eos & BIN)
300 i |= AUXA_BIN;
301 upd7210_wr(u, AUXRA, C_AUXA | i);
302 }
303
304 /*
305 * Look up the handle, and set the deadline if the handle has a timeout.
306 */
307 static int
308 gethandle(struct upd7210 *u, struct ibarg *ap, struct handle **hp)
309 {
310 struct ibfoo *ib;
311 struct handle *h;
312
313 KASSERT(ap->__field & __F_HANDLE, ("gethandle without __F_HANDLE"));
314 ib = u->ibfoo;
315 LIST_FOREACH(h, &ib->handles, list) {
316 if (h->handle == ap->handle) {
317 *hp = h;
318 return (0);
319 }
320 }
321 ib_set_error(ap, EARG);
322 return (1);
323 }
324
325 static int
326 pio_cmd(struct upd7210 *u, u_char *cmd, int len)
327 {
328 struct ibfoo *ib;
329
330 ib = u->ibfoo;
331
332 if (ib->rdh != NULL || ib->wrh != NULL) {
333 upd7210_take_ctrl_async(u);
334 ib->rdh = NULL;
335 ib->wrh = NULL;
336 }
337 mtx_lock(&u->mutex);
338 ib->mode = PIO_CMD;
339 ib->buf = cmd;
340 ib->buflen = len;
341 upd7210_wr(u, IMR2, IXR2_CO);
342
343 gpib_ib_irq(u, 1);
344
345 gpib_ib_wait_xfer(u, ib);
346
347 mtx_unlock(&u->mutex);
348 return (len - ib->buflen);
349 }
350
351 static int
352 pio_odata(struct upd7210 *u, u_char *data, int len)
353 {
354 struct ibfoo *ib;
355
356 ib = u->ibfoo;
357
358 if (len == 0)
359 return (0);
360 mtx_lock(&u->mutex);
361 ib->mode = PIO_ODATA;
362 ib->buf = data;
363 ib->buflen = len;
364 upd7210_wr(u, IMR1, IXR1_DO);
365
366 gpib_ib_wait_xfer(u, ib);
367
368 mtx_unlock(&u->mutex);
369 return (len - ib->buflen);
370 }
371
372 static int
373 pio_idata(struct upd7210 *u, u_char *data, int len)
374 {
375 struct ibfoo *ib;
376
377 ib = u->ibfoo;
378
379 mtx_lock(&u->mutex);
380 ib->mode = PIO_IDATA;
381 ib->buf = data;
382 ib->buflen = len;
383 upd7210_wr(u, IMR1, IXR1_DI);
384
385 gpib_ib_wait_xfer(u, ib);
386
387 mtx_unlock(&u->mutex);
388 return (len - ib->buflen);
389 }
390
391 static int
392 dma_idata(struct upd7210 *u, u_char *data, int len)
393 {
394 int j;
395 struct ibfoo *ib;
396
397 KASSERT(u->dmachan >= 0, ("Bogus dmachan %d", u->dmachan));
398 ib = u->ibfoo;
399 ib->mode = DMA_IDATA;
400 mtx_lock(&Giant);
401 isa_dmastart(ISADMA_READ, data, len, u->dmachan);
402 mtx_unlock(&Giant);
403 mtx_lock(&u->mutex);
404 upd7210_wr(u, IMR1, IXR1_ENDRX);
405 upd7210_wr(u, IMR2, IMR2_DMAI);
406 gpib_ib_wait_xfer(u, ib);
407 mtx_unlock(&u->mutex);
408 mtx_lock(&Giant);
409 j = isa_dmastatus(u->dmachan);
410 isa_dmadone(ISADMA_READ, data, len, u->dmachan);
411 mtx_unlock(&Giant);
412 return (len - j);
413 }
414
415 static int
416 ib_send_msg(struct ibfoo *ib, int msg)
417 {
418 u_char buf[10];
419 int i, j;
420
421 i = 0;
422 buf[i++] = UNT;
423 buf[i++] = UNL;
424 buf[i++] = LAD | ib->h->pad;
425 if (ib->h->sad)
426 buf[i++] = LAD | TAD | ib->h->sad;
427 buf[i++] = TAD | 0;
428 buf[i++] = msg;
429 j = pio_cmd(ib->u, buf, i);
430 if (i != j)
431 ib_set_error(ib->ap, EABO); /* XXX ? */
432 return (0);
433 }
434
435 static int
436 ibask(struct ibfoo *ib)
437 { /* XXX */
438
439 ibdebug = ib->ap->option;
440 return (0);
441 }
442
443 #define ibbna NULL
444 #define ibcac NULL
445
446 static int
447 ibclr(struct ibfoo *ib)
448 {
449
450 return (ib_send_msg(ib, SDC));
451 }
452
453 #define ibcmd NULL
454 #define ibcmda NULL
455 #define ibconfig NULL
456
457 static int
458 ibdev(struct ibfoo *ib)
459 { /* TBD */
460 struct handle *h;
461
462 h = malloc(sizeof *h, M_IBFOO, M_ZERO | M_WAITOK);
463 h->handle = alloc_unr(ib->unrhdr);
464 h->kind = H_DEV;
465 h->pad = ib->ap->pad;
466 h->sad = ib->ap->sad;
467 h->timeout = timeouts[ib->ap->tmo];
468 h->eot = ib->ap->eot;
469 h->eos = ib->ap->eos;
470 mtx_lock(&ib->u->mutex);
471 LIST_INSERT_HEAD(&ib->handles, h, list);
472 mtx_unlock(&ib->u->mutex);
473 ib->ap->__retval = h->handle;
474 return (0);
475 }
476
477 #define ibdiag NULL
478
479 static int
480 ibdma(struct ibfoo *ib)
481 {
482
483 if (ib->u->dmachan < 0 && ib->ap->v)
484 return (ib_set_error(ib->ap, EARG));
485 ib->h->dma = ib->ap->v;
486 return (0);
487 }
488
489 static int
490 ibeos(struct ibfoo *ib)
491 {
492
493 ib->ap->__iberr = ib->h->eos;
494 ib->h->eos = ib->ap->eos;
495 if (ib->rdh == ib->h)
496 config_eos(ib->u, ib->h);
497 return (0);
498 }
499
500 static int
501 ibeot(struct ibfoo *ib)
502 {
503
504 ib->h->eot = ib->ap->eot;
505 return (0);
506 }
507
508 #define ibevent NULL
509 #define ibfind NULL
510 #define ibgts NULL
511 #define ibist NULL
512 #define iblines NULL
513 #define ibllo NULL
514 #define ibln NULL
515
516 static int
517 ibloc(struct ibfoo *ib)
518 { /* XXX */
519
520 if (ib->h->kind == H_BOARD)
521 return (EOPNOTSUPP); /* XXX */
522 return (ib_send_msg(ib, GTL));
523 }
524
525 static int
526 ibonl(struct ibfoo *ib)
527 { /* XXX */
528
529 if (ib->ap->v)
530 return (EOPNOTSUPP); /* XXX */
531 mtx_lock(&ib->u->mutex);
532 LIST_REMOVE(ib->h, list);
533 mtx_unlock(&ib->u->mutex);
534 free(ib->h, M_IBFOO);
535 ib->h = NULL;
536 return (0);
537 }
538
539 static int
540 ibpad(struct ibfoo *ib)
541 {
542
543 ib->h->pad = ib->ap->pad;
544 return (0);
545 }
546
547 #define ibpct NULL
548 #define ibpoke NULL
549 #define ibppc NULL
550
551 static int
552 ibrd(struct ibfoo *ib)
553 { /* TBD */
554 u_char buf[10], *bp;
555 int i, j, error, bl, bc;
556 u_char *dp;
557
558 if (ib->h->kind == H_BOARD)
559 return (EOPNOTSUPP); /* XXX */
560 bl = ib->ap->cnt;
561 if (bl > PAGE_SIZE)
562 bl = PAGE_SIZE;
563 bp = malloc(bl, M_IBFOO, M_WAITOK);
564
565 if (ib->rdh != ib->h) {
566 i = 0;
567 buf[i++] = UNT;
568 buf[i++] = UNL;
569 buf[i++] = LAD | 0;
570 buf[i++] = TAD | ib->h->pad;
571 if (ib->h->sad)
572 buf[i++] = ib->h->sad;
573 i = pio_cmd(ib->u, buf, i);
574 config_eos(ib->u, ib->h);
575 ib->rdh = ib->h;
576 ib->wrh = NULL;
577 }
578 upd7210_goto_standby(ib->u);
579 dp = ib->ap->buffer;
580 bc = ib->ap->cnt;
581 error = 0;
582 while (bc > 0 && ib->ap->__iberr == 0) {
583 j = imin(bc, PAGE_SIZE);
584 if (ib->h->dma)
585 i = dma_idata(ib->u, bp, j);
586 else
587 i = pio_idata(ib->u, bp, j);
588 error = copyout(bp, dp , i);
589 if (error)
590 break;
591 ib->ap->__ibcnt += i;
592 if (i != j)
593 break;
594 bc -= i;
595 dp += i;
596 }
597 upd7210_take_ctrl_async(ib->u);
598 free(bp, M_IBFOO);
599 return (error);
600 }
601
602 #define ibrda NULL
603 #define ibrdf NULL
604 #define ibrdkey NULL
605 #define ibrpp NULL
606 #define ibrsc NULL
607 #define ibrsp NULL
608 #define ibrsv NULL
609
610 static int
611 ibsad(struct ibfoo *ib)
612 {
613
614 ib->h->sad = ib->ap->sad;
615 return (0);
616 }
617
618 #define ibsgnl NULL
619
620 static int
621 ibsic(struct ibfoo *ib)
622 { /* TBD */
623
624 upd7210_wr(ib->u, AUXMR, AUXMR_SIFC);
625 DELAY(100);
626 upd7210_wr(ib->u, AUXMR, AUXMR_CIFC);
627 return (0);
628 }
629
630 #define ibsre NULL
631 #define ibsrq NULL
632 #define ibstop NULL
633
634 static int
635 ibtmo(struct ibfoo *ib)
636 {
637
638 ib->h->timeout = timeouts[ib->ap->tmo];
639 return (0);
640 }
641
642 #define ibtrap NULL
643
644 static int
645 ibtrg(struct ibfoo *ib)
646 {
647
648 return (ib_send_msg(ib, GET));
649 }
650
651 #define ibwait NULL
652
653 static int
654 ibwrt(struct ibfoo *ib)
655 { /* XXX */
656 u_char buf[10], *bp;
657 int i;
658
659 if (ib->h->kind == H_BOARD)
660 return (EOPNOTSUPP);
661 bp = malloc(ib->ap->cnt, M_IBFOO, M_WAITOK);
662 /* XXX: bigger than PAGE_SIZE handling */
663 i = copyin(ib->ap->buffer, bp, ib->ap->cnt);
664 if (i) {
665 free(bp, M_IBFOO);
666 return (i);
667 }
668 if (ib->wrh != ib->h) {
669 i = 0;
670 buf[i++] = UNT;
671 buf[i++] = UNL;
672 buf[i++] = LAD | ib->h->pad;
673 if (ib->h->sad)
674 buf[i++] = LAD | TAD | ib->h->sad;
675 buf[i++] = TAD | 0;
676 i = pio_cmd(ib->u, buf, i);
677 ib->rdh = NULL;
678 ib->wrh = ib->h;
679 config_eos(ib->u, ib->h);
680 }
681 upd7210_goto_standby(ib->u);
682 ib->doeoi = ib->h->eot;
683 i = pio_odata(ib->u, bp, ib->ap->cnt);
684 upd7210_take_ctrl_async(ib->u);
685 ib->ap->__ibcnt = i;
686 free(bp, M_IBFOO);
687 return (0);
688 }
689
690 #define ibwrta NULL
691 #define ibwrtf NULL
692 #define ibwrtkey NULL
693 #define ibxtrc NULL
694
695 static struct ibhandler {
696 const char *name;
697 enum h_kind kind;
698 ibhandler_t *func;
699 u_int args;
700 } ibhandlers[] = {
701 [__ID_IBASK] = { "ibask", H_EITHER, ibask, __F_HANDLE | __F_OPTION | __F_RETVAL },
702 [__ID_IBBNA] = { "ibbna", H_DEV, ibbna, __F_HANDLE | __F_BDNAME },
703 [__ID_IBCAC] = { "ibcac", H_BOARD, ibcac, __F_HANDLE | __F_V },
704 [__ID_IBCLR] = { "ibclr", H_DEV, ibclr, __F_HANDLE },
705 [__ID_IBCMD] = { "ibcmd", H_BOARD, ibcmd, __F_HANDLE | __F_BUFFER | __F_CNT },
706 [__ID_IBCMDA] = { "ibcmda", H_BOARD, ibcmda, __F_HANDLE | __F_BUFFER | __F_CNT },
707 [__ID_IBCONFIG] = { "ibconfig", H_EITHER, ibconfig, __F_HANDLE | __F_OPTION | __F_VALUE },
708 [__ID_IBDEV] = { "ibdev", 0, ibdev, __F_BOARDID | __F_PAD | __F_SAD | __F_TMO | __F_EOT | __F_EOS },
709 [__ID_IBDIAG] = { "ibdiag", H_EITHER, ibdiag, __F_HANDLE | __F_BUFFER | __F_CNT },
710 [__ID_IBDMA] = { "ibdma", H_EITHER, ibdma, __F_HANDLE | __F_V },
711 [__ID_IBEOS] = { "ibeos", H_EITHER, ibeos, __F_HANDLE | __F_EOS },
712 [__ID_IBEOT] = { "ibeot", H_EITHER, ibeot, __F_HANDLE | __F_EOT },
713 [__ID_IBEVENT] = { "ibevent", H_BOARD, ibevent, __F_HANDLE | __F_EVENT },
714 [__ID_IBFIND] = { "ibfind", 0, ibfind, __F_BDNAME },
715 [__ID_IBGTS] = { "ibgts", H_BOARD, ibgts, __F_HANDLE | __F_V },
716 [__ID_IBIST] = { "ibist", H_BOARD, ibist, __F_HANDLE | __F_V },
717 [__ID_IBLINES] = { "iblines", H_BOARD, iblines, __F_HANDLE | __F_LINES },
718 [__ID_IBLLO] = { "ibllo", H_EITHER, ibllo, __F_HANDLE },
719 [__ID_IBLN] = { "ibln", H_BOARD, ibln, __F_HANDLE | __F_PADVAL | __F_SADVAL | __F_LISTENFLAG },
720 [__ID_IBLOC] = { "ibloc", H_EITHER, ibloc, __F_HANDLE },
721 [__ID_IBONL] = { "ibonl", H_EITHER, ibonl, __F_HANDLE | __F_V },
722 [__ID_IBPAD] = { "ibpad", H_EITHER, ibpad, __F_HANDLE | __F_PAD },
723 [__ID_IBPCT] = { "ibpct", H_DEV, ibpct, __F_HANDLE },
724 [__ID_IBPOKE] = { "ibpoke", H_EITHER, ibpoke, __F_HANDLE | __F_OPTION | __F_VALUE },
725 [__ID_IBPPC] = { "ibppc", H_EITHER, ibppc, __F_HANDLE | __F_V },
726 [__ID_IBRD] = { "ibrd", H_EITHER, ibrd, __F_HANDLE | __F_BUFFER | __F_CNT },
727 [__ID_IBRDA] = { "ibrda", H_EITHER, ibrda, __F_HANDLE | __F_BUFFER | __F_CNT },
728 [__ID_IBRDF] = { "ibrdf", H_EITHER, ibrdf, __F_HANDLE | __F_FLNAME },
729 [__ID_IBRDKEY] = { "ibrdkey", H_EITHER, ibrdkey, __F_HANDLE | __F_BUFFER | __F_CNT },
730 [__ID_IBRPP] = { "ibrpp", H_EITHER, ibrpp, __F_HANDLE | __F_PPR },
731 [__ID_IBRSC] = { "ibrsc", H_BOARD, ibrsc, __F_HANDLE | __F_V },
732 [__ID_IBRSP] = { "ibrsp", H_DEV, ibrsp, __F_HANDLE | __F_SPR },
733 [__ID_IBRSV] = { "ibrsv", H_EITHER, ibrsv, __F_HANDLE | __F_V },
734 [__ID_IBSAD] = { "ibsad", H_EITHER, ibsad, __F_HANDLE | __F_SAD },
735 [__ID_IBSGNL] = { "ibsgnl", H_EITHER, ibsgnl, __F_HANDLE | __F_V },
736 [__ID_IBSIC] = { "ibsic", H_BOARD, ibsic, __F_HANDLE },
737 [__ID_IBSRE] = { "ibsre", H_BOARD, ibsre, __F_HANDLE | __F_V },
738 [__ID_IBSRQ] = { "ibsrq", H_EITHER, ibsrq, __F_FUNC },
739 [__ID_IBSTOP] = { "ibstop", H_EITHER, ibstop, __F_HANDLE },
740 [__ID_IBTMO] = { "ibtmo", H_EITHER, ibtmo, __F_HANDLE | __F_TMO },
741 [__ID_IBTRAP] = { "ibtrap", H_EITHER, ibtrap, __F_MASK | __F_MODE },
742 [__ID_IBTRG] = { "ibtrg", H_DEV, ibtrg, __F_HANDLE },
743 [__ID_IBWAIT] = { "ibwait", H_EITHER, ibwait, __F_HANDLE | __F_MASK },
744 [__ID_IBWRT] = { "ibwrt", H_EITHER, ibwrt, __F_HANDLE | __F_BUFFER | __F_CNT },
745 [__ID_IBWRTA] = { "ibwrta", H_EITHER, ibwrta, __F_HANDLE | __F_BUFFER | __F_CNT },
746 [__ID_IBWRTF] = { "ibwrtf", H_EITHER, ibwrtf, __F_HANDLE | __F_FLNAME },
747 [__ID_IBWRTKEY] = { "ibwrtkey", H_EITHER, ibwrtkey, __F_HANDLE | __F_BUFFER | __F_CNT },
748 [__ID_IBXTRC] = { "ibxtrc", H_EITHER, ibxtrc, __F_HANDLE | __F_BUFFER | __F_CNT },
749 };
750
751 static const u_int max_ibhandler = sizeof ibhandlers / sizeof ibhandlers[0];
752
753 static void
754 ib_dump_args(struct ibhandler *ih, struct ibarg *ap)
755 {
756
757 if (ih->name != NULL)
758 printf("%s(", ih->name);
759 else
760 printf("ibinvalid(");
761 printf("[0x%x]", ap->__field);
762 if (ap->__field & __F_HANDLE) printf(" handle=%d", ap->handle);
763 if (ap->__field & __F_EOS) printf(" eos=0x%x", ap->eos);
764 if (ap->__field & __F_EOT) printf(" eot=%d", ap->eot);
765 if (ap->__field & __F_TMO) printf(" tmo=%d", ap->tmo);
766 if (ap->__field & __F_PAD) printf(" pad=0x%x", ap->pad);
767 if (ap->__field & __F_SAD) printf(" sad=0x%x", ap->sad);
768 if (ap->__field & __F_BUFFER) printf(" buffer=%p", ap->buffer);
769 if (ap->__field & __F_CNT) printf(" cnt=%ld", ap->cnt);
770 if (ap->__field & __F_V) printf(" v=%d/0x%x", ap->v, ap->v);
771 /* XXX more ... */
772 printf(")\n");
773 }
774
775 static int
776 gpib_ib_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
777 {
778 struct upd7210 *u;
779 struct ibfoo *ib;
780 int error = 0;
781
782 u = dev->si_drv1;
783
784 mtx_lock(&u->mutex);
785 if (u->busy) {
786 mtx_unlock(&u->mutex);
787 return (EBUSY);
788 }
789 u->busy = 1;
790 mtx_unlock(&u->mutex);
791
792 if (u->dmachan >= 0) {
793 mtx_lock(&Giant);
794 error = isa_dma_acquire(u->dmachan);
795 if (!error) {
796 error = isa_dma_init(u->dmachan, PAGE_SIZE, M_WAITOK);
797 if (error)
798 isa_dma_release(u->dmachan);
799 }
800 mtx_unlock(&Giant);
801 }
802
803 if (error) {
804 mtx_lock(&u->mutex);
805 u->busy = 0;
806 mtx_unlock(&u->mutex);
807 return (error);
808 }
809
810 ib = malloc(sizeof *ib, M_IBFOO, M_WAITOK | M_ZERO);
811 LIST_INIT(&ib->handles);
812 callout_init(&ib->callout, CALLOUT_MPSAFE);
813 ib->unrhdr = new_unrhdr(0, INT_MAX, NULL);
814 dev->si_drv2 = ib;
815 ib->u = u;
816 u->ibfoo = ib;
817 u->irq = gpib_ib_irq;
818
819 upd7210_wr(u, AUXMR, AUXMR_CRST);
820 DELAY(10000);
821 DELAY(1000);
822 upd7210_wr(u, IMR1, 0x00);
823 upd7210_wr(u, IMR2, 0x00);
824 upd7210_wr(u, SPMR, 0x00);
825 upd7210_wr(u, ADR, 0x00);
826 upd7210_wr(u, ADR, ADR_ARS | ADR_DL | ADR_DT);
827 upd7210_wr(u, ADMR, ADMR_ADM0 | ADMR_TRM0 | ADMR_TRM1);
828 upd7210_wr(u, EOSR, 0x00);
829 upd7210_wr(u, AUXMR, C_ICR | 8);
830 upd7210_wr(u, AUXMR, C_PPR | PPR_U);
831 upd7210_wr(u, AUXMR, C_AUXA);
832 upd7210_wr(u, AUXMR, C_AUXB + 3);
833 upd7210_wr(u, AUXMR, C_AUXE + 0);
834 upd7210_wr(u, AUXMR, AUXMR_PON);
835 upd7210_wr(u, AUXMR, AUXMR_CIFC);
836 DELAY(100);
837 upd7210_wr(u, AUXMR, AUXMR_SIFC);
838 upd7210_wr(u, AUXMR, AUXMR_SREN);
839 return (0);
840 }
841
842 static int
843 gpib_ib_close(struct cdev *dev, int oflags, int devtype, struct thread *td)
844 {
845 struct upd7210 *u;
846 struct ibfoo *ib;
847
848 u = dev->si_drv1;
849 ib = dev->si_drv2;
850 /* XXX: assert pointer consistency */
851
852 u->ibfoo = NULL;
853 /* XXX: free handles */
854 dev->si_drv2 = NULL;
855 free(ib, M_IBFOO);
856
857 if (u->dmachan >= 0) {
858 mtx_lock(&Giant);
859 isa_dma_release(u->dmachan);
860 mtx_unlock(&Giant);
861 }
862 mtx_lock(&u->mutex);
863 u->busy = 0;
864 ibdebug = 0;
865 upd7210_wr(u, IMR1, 0x00);
866 upd7210_wr(u, IMR2, 0x00);
867 upd7210_wr(u, AUXMR, AUXMR_CRST);
868 DELAY(10000);
869 mtx_unlock(&u->mutex);
870 return (0);
871 }
872
873 static int
874 gpib_ib_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
875 {
876 struct ibarg *ap;
877 struct ibhandler *ih;
878 struct handle *h;
879 struct upd7210 *u;
880 struct ibfoo *ib;
881 int error;
882 struct timeval deadline, tv;
883
884 u = dev->si_drv1;
885 ib = u->ibfoo;
886
887 /* We only support a single ioctl, everything else is a mistake */
888 if (cmd != GPIB_IBFOO)
889 return (ENOIOCTL);
890
891 /* Check the identifier and field-bitmap in the arguments. */
892 ap = (void *)data;
893 if (ap->__ident < 0 || ap->__ident >= max_ibhandler)
894 return (EINVAL);
895 ih = &ibhandlers[ap->__ident];
896 if (ap->__field != ih->args)
897 return (EINVAL);
898
899 if (ibdebug)
900 ib_dump_args(ih, ap);
901
902 if (ih->func == NULL)
903 return (EOPNOTSUPP);
904
905 ap->__iberr = 0;
906 ap->__ibsta = 0;
907 ap->__ibcnt = 0;
908 ap->retval = 0;
909
910 if (ap->__field & __F_TMO) {
911 if (ap->tmo < 0 || ap->tmo >= max_timeouts)
912 return (ib_set_error(ap, EARG));
913 }
914
915 if (ap->__field & __F_EOS) {
916 if ((ap->eos & ~(REOS | XEOS | BIN | 0xff)) ||
917 ((ap->eos & (BIN | 0x80)) == 0x80))
918 return (ib_set_error(ap, EARG));
919 }
920 if (ap->__field & __F_PAD) {
921 if (ap->pad < 0 || ap->pad > 30)
922 return (ib_set_error(ap, EARG));
923 }
924 if (ap->__field & __F_SAD) {
925 if (ap->sad != 0 && (ap->sad < 0x60 || ap->sad > 126))
926 return (ib_set_error(ap, EARG));
927 }
928
929
930 mtx_lock(&u->mutex);
931
932
933 /* Find the handle, if any */
934 h = NULL;
935 if ((ap->__field & __F_HANDLE) && gethandle(u, ap, &h)) {
936 mtx_unlock(&u->mutex);
937 return (0);
938 }
939
940 /* Check that the handle is the right kind */
941 if (h != NULL && !(h->kind & ih->kind)) {
942 mtx_unlock(&u->mutex);
943 return (ib_set_error(ap, EARG));
944 }
945
946 /* Set up handle and deadline */
947 if (h != NULL && timevalisset(&h->timeout)) {
948 getmicrouptime(&deadline);
949 timevaladd(&deadline, &h->timeout);
950 } else {
951 timevalclear(&deadline);
952 }
953
954 /* Wait for the card to be(come) available, respect deadline */
955 while(u->busy != 1) {
956 error = msleep(ib, &u->mutex,
957 PZERO | PCATCH, "gpib_ibioctl", hz / 10);
958 if (error == 0)
959 continue;
960 mtx_unlock(&u->mutex);
961 if (error == EINTR)
962 return(ib_set_error(ap, EABO));
963 if (error == EWOULDBLOCK && timevalisset(&deadline)) {
964 getmicrouptime(&tv);
965 if (timevalcmp(&deadline, &tv, <))
966 return(ib_had_timeout(ap));
967 }
968 mtx_lock(&u->mutex);
969 }
970 u->busy = 2;
971 mtx_unlock(&u->mutex);
972
973 /* Hand over deadline handling to the callout routine */
974 ib->ap = ap;
975 ib->h = h;
976 ib->mode = BUSY;
977 ib->deadline = deadline;
978 callout_reset(&ib->callout, hz / 5, gpib_ib_timeout, u);
979
980 error = ih->func(ib);
981
982 /* Release card */
983 ib->mode = IDLE;
984 ib->ap = NULL;
985 ib->h = NULL;
986 timevalclear(&deadline);
987 callout_stop(&ib->callout);
988
989 mtx_lock(&u->mutex);
990 u->busy = 1;
991 wakeup(ib);
992 mtx_unlock(&u->mutex);
993
994 if (error)
995 return(ib_set_errno(ap, error));
996 return (0);
997 }
998
999 struct cdevsw gpib_ib_cdevsw = {
1000 .d_version = D_VERSION,
1001 .d_name = "gpib_ib",
1002 .d_open = gpib_ib_open,
1003 .d_ioctl = gpib_ib_ioctl,
1004 .d_close = gpib_ib_close,
1005 };
Cache object: f08b3800e61ee73b16d028648410549e
|