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