]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/dev/ieee488/ibfoo.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / dev / ieee488 / ibfoo.c
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$");
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 };