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
ib_set_error(struct ibarg * ap,int error)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
ib_had_timeout(struct ibarg * ap)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
ib_set_errno(struct ibarg * ap,int errno)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
gpib_ib_irq(struct upd7210 * u,int isr_3)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
gpib_ib_timeout(void * arg)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
gpib_ib_wait_xfer(struct upd7210 * u,struct ibfoo * ib)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
config_eos(struct upd7210 * u,struct handle * h)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
gethandle(struct upd7210 * u,struct ibarg * ap,struct handle ** hp)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
pio_cmd(struct upd7210 * u,u_char * cmd,int len)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
pio_odata(struct upd7210 * u,u_char * data,int len)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
pio_idata(struct upd7210 * u,u_char * data,int len)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
dma_idata(struct upd7210 * u,u_char * data,int len)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 isa_dmastart(ISADMA_READ, data, len, u->dmachan);
520 mtx_lock(&u->mutex);
521 upd7210_wr(u, IMR1, IXR1_ENDRX);
522 upd7210_wr(u, IMR2, IMR2_DMAI);
523 gpib_ib_wait_xfer(u, ib);
524 mtx_unlock(&u->mutex);
525 j = isa_dmastatus(u->dmachan);
526 isa_dmadone(ISADMA_READ, data, len, u->dmachan);
527 return (len - j);
528 }
529
530 static int
ib_send_msg(struct ibfoo * ib,int msg)531 ib_send_msg(struct ibfoo *ib, int msg)
532 {
533 u_char buf[10];
534 int i, j;
535
536 i = 0;
537 buf[i++] = UNT;
538 buf[i++] = UNL;
539 buf[i++] = LAD | ib->h->pad;
540 if (ib->h->sad)
541 buf[i++] = LAD | TAD | ib->h->sad;
542 buf[i++] = TAD | 0;
543 buf[i++] = msg;
544 j = pio_cmd(ib->u, buf, i);
545 if (i != j)
546 ib_set_error(ib->ap, EABO); /* XXX ? */
547 return (0);
548 }
549
550 static int
ibask(struct ibfoo * ib)551 ibask(struct ibfoo *ib)
552 { /* XXX */
553
554 ibdebug = ib->ap->option;
555 return (0);
556 }
557
558 #define ibbna NULL
559 #define ibcac NULL
560
561 static int
ibclr(struct ibfoo * ib)562 ibclr(struct ibfoo *ib)
563 {
564
565 return (ib_send_msg(ib, SDC));
566 }
567
568 #define ibcmd NULL
569 #define ibcmda NULL
570 #define ibconfig NULL
571
572 static int
ibdev(struct ibfoo * ib)573 ibdev(struct ibfoo *ib)
574 { /* TBD */
575 struct handle *h;
576
577 h = malloc(sizeof *h, M_IBFOO, M_ZERO | M_WAITOK);
578 h->handle = alloc_unr(ib->unrhdr);
579 h->kind = H_DEV;
580 h->pad = ib->ap->pad;
581 h->sad = ib->ap->sad;
582 h->timeout = timeouts[ib->ap->tmo];
583 h->eot = ib->ap->eot;
584 h->eos = ib->ap->eos;
585 mtx_lock(&ib->u->mutex);
586 LIST_INSERT_HEAD(&ib->handles, h, list);
587 mtx_unlock(&ib->u->mutex);
588 ib->ap->__retval = h->handle;
589 return (0);
590 }
591
592 #define ibdiag NULL
593
594 static int
ibdma(struct ibfoo * ib)595 ibdma(struct ibfoo *ib)
596 {
597
598 if (ib->u->dmachan < 0 && ib->ap->v)
599 return (ib_set_error(ib->ap, EARG));
600 ib->h->dma = ib->ap->v;
601 return (0);
602 }
603
604 static int
ibeos(struct ibfoo * ib)605 ibeos(struct ibfoo *ib)
606 {
607
608 ib->ap->__iberr = ib->h->eos;
609 ib->h->eos = ib->ap->eos;
610 if (ib->rdh == ib->h)
611 config_eos(ib->u, ib->h);
612 return (0);
613 }
614
615 static int
ibeot(struct ibfoo * ib)616 ibeot(struct ibfoo *ib)
617 {
618
619 ib->h->eot = ib->ap->eot;
620 return (0);
621 }
622
623 #define ibevent NULL
624 #define ibfind NULL
625 #define ibgts NULL
626 #define ibist NULL
627 #define iblines NULL
628 #define ibllo NULL
629 #define ibln NULL
630
631 static int
ibloc(struct ibfoo * ib)632 ibloc(struct ibfoo *ib)
633 { /* XXX */
634
635 if (ib->h->kind == H_BOARD)
636 return (EOPNOTSUPP); /* XXX */
637 return (ib_send_msg(ib, GTL));
638 }
639
640 static int
ibonl(struct ibfoo * ib)641 ibonl(struct ibfoo *ib)
642 { /* XXX */
643
644 if (ib->ap->v)
645 return (EOPNOTSUPP); /* XXX */
646 mtx_lock(&ib->u->mutex);
647 LIST_REMOVE(ib->h, list);
648 mtx_unlock(&ib->u->mutex);
649 free(ib->h, M_IBFOO);
650 ib->h = NULL;
651 return (0);
652 }
653
654 static int
ibpad(struct ibfoo * ib)655 ibpad(struct ibfoo *ib)
656 {
657
658 ib->h->pad = ib->ap->pad;
659 return (0);
660 }
661
662 #define ibpct NULL
663 #define ibpoke NULL
664 #define ibppc NULL
665
666 static int
ibrd(struct ibfoo * ib)667 ibrd(struct ibfoo *ib)
668 { /* TBD */
669 u_char buf[10], *bp;
670 int i, j, error, bl, bc;
671 u_char *dp;
672
673 if (ib->h->kind == H_BOARD)
674 return (EOPNOTSUPP); /* XXX */
675 bl = ib->ap->cnt;
676 if (bl > PAGE_SIZE)
677 bl = PAGE_SIZE;
678 bp = malloc(bl, M_IBFOO, M_WAITOK);
679
680 if (ib->rdh != ib->h) {
681 i = 0;
682 buf[i++] = UNT;
683 buf[i++] = UNL;
684 buf[i++] = LAD | 0;
685 buf[i++] = TAD | ib->h->pad;
686 if (ib->h->sad)
687 buf[i++] = ib->h->sad;
688 i = pio_cmd(ib->u, buf, i);
689 config_eos(ib->u, ib->h);
690 ib->rdh = ib->h;
691 ib->wrh = NULL;
692 }
693 upd7210_goto_standby(ib->u);
694 dp = ib->ap->buffer;
695 bc = ib->ap->cnt;
696 error = 0;
697 while (bc > 0 && ib->ap->__iberr == 0) {
698 j = imin(bc, PAGE_SIZE);
699 if (ib->h->dma)
700 i = dma_idata(ib->u, bp, j);
701 else
702 i = pio_idata(ib->u, bp, j);
703 error = copyout(bp, dp , i);
704 if (error)
705 break;
706 ib->ap->__ibcnt += i;
707 if (i != j)
708 break;
709 bc -= i;
710 dp += i;
711 }
712 upd7210_take_ctrl_async(ib->u);
713 free(bp, M_IBFOO);
714 return (error);
715 }
716
717 #define ibrda NULL
718 #define ibrdf NULL
719 #define ibrdkey NULL
720 #define ibrpp NULL
721 #define ibrsc NULL
722 #define ibrsp NULL
723 #define ibrsv NULL
724
725 static int
ibsad(struct ibfoo * ib)726 ibsad(struct ibfoo *ib)
727 {
728
729 ib->h->sad = ib->ap->sad;
730 return (0);
731 }
732
733 #define ibsgnl NULL
734
735 static int
ibsic(struct ibfoo * ib)736 ibsic(struct ibfoo *ib)
737 { /* TBD */
738
739 upd7210_wr(ib->u, AUXMR, AUXMR_SIFC);
740 DELAY(100);
741 upd7210_wr(ib->u, AUXMR, AUXMR_CIFC);
742 return (0);
743 }
744
745 #define ibsre NULL
746 #define ibsrq NULL
747 #define ibstop NULL
748
749 static int
ibtmo(struct ibfoo * ib)750 ibtmo(struct ibfoo *ib)
751 {
752
753 ib->h->timeout = timeouts[ib->ap->tmo];
754 return (0);
755 }
756
757 #define ibtrap NULL
758
759 static int
ibtrg(struct ibfoo * ib)760 ibtrg(struct ibfoo *ib)
761 {
762
763 return (ib_send_msg(ib, GET));
764 }
765
766 #define ibwait NULL
767
768 static int
ibwrt(struct ibfoo * ib)769 ibwrt(struct ibfoo *ib)
770 { /* XXX */
771 u_char buf[10], *bp;
772 int i;
773
774 if (ib->h->kind == H_BOARD)
775 return (EOPNOTSUPP);
776 bp = malloc(ib->ap->cnt, M_IBFOO, M_WAITOK);
777 /* XXX: bigger than PAGE_SIZE handling */
778 i = copyin(ib->ap->buffer, bp, ib->ap->cnt);
779 if (i) {
780 free(bp, M_IBFOO);
781 return (i);
782 }
783 if (ib->wrh != ib->h) {
784 i = 0;
785 buf[i++] = UNT;
786 buf[i++] = UNL;
787 buf[i++] = LAD | ib->h->pad;
788 if (ib->h->sad)
789 buf[i++] = LAD | TAD | ib->h->sad;
790 buf[i++] = TAD | 0;
791 i = pio_cmd(ib->u, buf, i);
792 ib->rdh = NULL;
793 ib->wrh = ib->h;
794 config_eos(ib->u, ib->h);
795 }
796 upd7210_goto_standby(ib->u);
797 ib->doeoi = ib->h->eot;
798 i = pio_odata(ib->u, bp, ib->ap->cnt);
799 upd7210_take_ctrl_async(ib->u);
800 ib->ap->__ibcnt = i;
801 free(bp, M_IBFOO);
802 return (0);
803 }
804
805 #define ibwrta NULL
806 #define ibwrtf NULL
807 #define ibwrtkey NULL
808 #define ibxtrc NULL
809
810 static struct ibhandler {
811 const char *name;
812 enum h_kind kind;
813 ibhandler_t *func;
814 u_int args;
815 } ibhandlers[] = {
816 [__ID_IBASK] = { "ibask", H_EITHER, ibask, __F_HANDLE | __F_OPTION | __F_RETVAL },
817 [__ID_IBBNA] = { "ibbna", H_DEV, ibbna, __F_HANDLE | __F_BDNAME },
818 [__ID_IBCAC] = { "ibcac", H_BOARD, ibcac, __F_HANDLE | __F_V },
819 [__ID_IBCLR] = { "ibclr", H_DEV, ibclr, __F_HANDLE },
820 [__ID_IBCMD] = { "ibcmd", H_BOARD, ibcmd, __F_HANDLE | __F_BUFFER | __F_CNT },
821 [__ID_IBCMDA] = { "ibcmda", H_BOARD, ibcmda, __F_HANDLE | __F_BUFFER | __F_CNT },
822 [__ID_IBCONFIG] = { "ibconfig", H_EITHER, ibconfig, __F_HANDLE | __F_OPTION | __F_VALUE },
823 [__ID_IBDEV] = { "ibdev", 0, ibdev, __F_BOARDID | __F_PAD | __F_SAD | __F_TMO | __F_EOT | __F_EOS },
824 [__ID_IBDIAG] = { "ibdiag", H_EITHER, ibdiag, __F_HANDLE | __F_BUFFER | __F_CNT },
825 [__ID_IBDMA] = { "ibdma", H_EITHER, ibdma, __F_HANDLE | __F_V },
826 [__ID_IBEOS] = { "ibeos", H_EITHER, ibeos, __F_HANDLE | __F_EOS },
827 [__ID_IBEOT] = { "ibeot", H_EITHER, ibeot, __F_HANDLE | __F_EOT },
828 [__ID_IBEVENT] = { "ibevent", H_BOARD, ibevent, __F_HANDLE | __F_EVENT },
829 [__ID_IBFIND] = { "ibfind", 0, ibfind, __F_BDNAME },
830 [__ID_IBGTS] = { "ibgts", H_BOARD, ibgts, __F_HANDLE | __F_V },
831 [__ID_IBIST] = { "ibist", H_BOARD, ibist, __F_HANDLE | __F_V },
832 [__ID_IBLINES] = { "iblines", H_BOARD, iblines, __F_HANDLE | __F_LINES },
833 [__ID_IBLLO] = { "ibllo", H_EITHER, ibllo, __F_HANDLE },
834 [__ID_IBLN] = { "ibln", H_BOARD, ibln, __F_HANDLE | __F_PADVAL | __F_SADVAL | __F_LISTENFLAG },
835 [__ID_IBLOC] = { "ibloc", H_EITHER, ibloc, __F_HANDLE },
836 [__ID_IBONL] = { "ibonl", H_EITHER, ibonl, __F_HANDLE | __F_V },
837 [__ID_IBPAD] = { "ibpad", H_EITHER, ibpad, __F_HANDLE | __F_PAD },
838 [__ID_IBPCT] = { "ibpct", H_DEV, ibpct, __F_HANDLE },
839 [__ID_IBPOKE] = { "ibpoke", H_EITHER, ibpoke, __F_HANDLE | __F_OPTION | __F_VALUE },
840 [__ID_IBPPC] = { "ibppc", H_EITHER, ibppc, __F_HANDLE | __F_V },
841 [__ID_IBRD] = { "ibrd", H_EITHER, ibrd, __F_HANDLE | __F_BUFFER | __F_CNT },
842 [__ID_IBRDA] = { "ibrda", H_EITHER, ibrda, __F_HANDLE | __F_BUFFER | __F_CNT },
843 [__ID_IBRDF] = { "ibrdf", H_EITHER, ibrdf, __F_HANDLE | __F_FLNAME },
844 [__ID_IBRDKEY] = { "ibrdkey", H_EITHER, ibrdkey, __F_HANDLE | __F_BUFFER | __F_CNT },
845 [__ID_IBRPP] = { "ibrpp", H_EITHER, ibrpp, __F_HANDLE | __F_PPR },
846 [__ID_IBRSC] = { "ibrsc", H_BOARD, ibrsc, __F_HANDLE | __F_V },
847 [__ID_IBRSP] = { "ibrsp", H_DEV, ibrsp, __F_HANDLE | __F_SPR },
848 [__ID_IBRSV] = { "ibrsv", H_EITHER, ibrsv, __F_HANDLE | __F_V },
849 [__ID_IBSAD] = { "ibsad", H_EITHER, ibsad, __F_HANDLE | __F_SAD },
850 [__ID_IBSGNL] = { "ibsgnl", H_EITHER, ibsgnl, __F_HANDLE | __F_V },
851 [__ID_IBSIC] = { "ibsic", H_BOARD, ibsic, __F_HANDLE },
852 [__ID_IBSRE] = { "ibsre", H_BOARD, ibsre, __F_HANDLE | __F_V },
853 [__ID_IBSRQ] = { "ibsrq", H_EITHER, ibsrq, __F_FUNC },
854 [__ID_IBSTOP] = { "ibstop", H_EITHER, ibstop, __F_HANDLE },
855 [__ID_IBTMO] = { "ibtmo", H_EITHER, ibtmo, __F_HANDLE | __F_TMO },
856 [__ID_IBTRAP] = { "ibtrap", H_EITHER, ibtrap, __F_MASK | __F_MODE },
857 [__ID_IBTRG] = { "ibtrg", H_DEV, ibtrg, __F_HANDLE },
858 [__ID_IBWAIT] = { "ibwait", H_EITHER, ibwait, __F_HANDLE | __F_MASK },
859 [__ID_IBWRT] = { "ibwrt", H_EITHER, ibwrt, __F_HANDLE | __F_BUFFER | __F_CNT },
860 [__ID_IBWRTA] = { "ibwrta", H_EITHER, ibwrta, __F_HANDLE | __F_BUFFER | __F_CNT },
861 [__ID_IBWRTF] = { "ibwrtf", H_EITHER, ibwrtf, __F_HANDLE | __F_FLNAME },
862 [__ID_IBWRTKEY] = { "ibwrtkey", H_EITHER, ibwrtkey, __F_HANDLE | __F_BUFFER | __F_CNT },
863 [__ID_IBXTRC] = { "ibxtrc", H_EITHER, ibxtrc, __F_HANDLE | __F_BUFFER | __F_CNT },
864 };
865
866 static const u_int max_ibhandler = sizeof ibhandlers / sizeof ibhandlers[0];
867
868 static void
ib_dump_args(struct ibhandler * ih,struct ibarg * ap)869 ib_dump_args(struct ibhandler *ih, struct ibarg *ap)
870 {
871
872 if (ih->name != NULL)
873 printf("%s(", ih->name);
874 else
875 printf("ibinvalid(");
876 printf("[0x%x]", ap->__field);
877 if (ap->__field & __F_HANDLE) printf(" handle=%d", ap->handle);
878 if (ap->__field & __F_EOS) printf(" eos=0x%x", ap->eos);
879 if (ap->__field & __F_EOT) printf(" eot=%d", ap->eot);
880 if (ap->__field & __F_TMO) printf(" tmo=%d", ap->tmo);
881 if (ap->__field & __F_PAD) printf(" pad=0x%x", ap->pad);
882 if (ap->__field & __F_SAD) printf(" sad=0x%x", ap->sad);
883 if (ap->__field & __F_BUFFER) printf(" buffer=%p", ap->buffer);
884 if (ap->__field & __F_CNT) printf(" cnt=%ld", ap->cnt);
885 if (ap->__field & __F_V) printf(" v=%d/0x%x", ap->v, ap->v);
886 /* XXX more ... */
887 printf(")\n");
888 }
889
890 static int
gpib_ib_open(struct cdev * dev,int oflags,int devtype,struct thread * td)891 gpib_ib_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
892 {
893 struct upd7210 *u;
894 struct ibfoo *ib;
895 int error = 0;
896
897 u = dev->si_drv1;
898
899 mtx_lock(&u->mutex);
900 if (u->busy) {
901 mtx_unlock(&u->mutex);
902 return (EBUSY);
903 }
904 u->busy = 1;
905 mtx_unlock(&u->mutex);
906
907 if (u->dmachan >= 0) {
908 error = isa_dma_acquire(u->dmachan);
909 if (!error) {
910 error = isa_dma_init(u->dmachan, PAGE_SIZE, M_WAITOK);
911 if (error)
912 isa_dma_release(u->dmachan);
913 }
914 }
915
916 if (error) {
917 mtx_lock(&u->mutex);
918 u->busy = 0;
919 mtx_unlock(&u->mutex);
920 return (error);
921 }
922
923 ib = malloc(sizeof *ib, M_IBFOO, M_WAITOK | M_ZERO);
924 LIST_INIT(&ib->handles);
925 callout_init(&ib->callout, CALLOUT_MPSAFE);
926 ib->unrhdr = new_unrhdr(0, INT_MAX, NULL);
927 dev->si_drv2 = ib;
928 ib->u = u;
929 u->ibfoo = ib;
930 u->irq = gpib_ib_irq;
931
932 upd7210_wr(u, AUXMR, AUXMR_CRST);
933 DELAY(10000);
934 DELAY(1000);
935 upd7210_wr(u, IMR1, 0x00);
936 upd7210_wr(u, IMR2, 0x00);
937 upd7210_wr(u, SPMR, 0x00);
938 upd7210_wr(u, ADR, 0x00);
939 upd7210_wr(u, ADR, ADR_ARS | ADR_DL | ADR_DT);
940 upd7210_wr(u, ADMR, ADMR_ADM0 | ADMR_TRM0 | ADMR_TRM1);
941 upd7210_wr(u, EOSR, 0x00);
942 upd7210_wr(u, AUXMR, C_ICR | 8);
943 upd7210_wr(u, AUXMR, C_PPR | PPR_U);
944 upd7210_wr(u, AUXMR, C_AUXA);
945 upd7210_wr(u, AUXMR, C_AUXB + 3);
946 upd7210_wr(u, AUXMR, C_AUXE + 0);
947 upd7210_wr(u, AUXMR, AUXMR_PON);
948 if (u->use_fifo) {
949 bus_write_1(u->reg_res[0], imr3, 0x00);
950 bus_write_1(u->reg_res[0], cmdr, 0x22); /* soft reset */
951 bus_write_1(u->reg_res[0], cmdr, 0x03); /* set system
952 * controller bit */
953 }
954 upd7210_wr(u, AUXMR, AUXMR_CIFC);
955 DELAY(100);
956 upd7210_wr(u, AUXMR, AUXMR_SIFC);
957 upd7210_wr(u, AUXMR, AUXMR_SREN);
958 return (0);
959 }
960
961 static int
gpib_ib_close(struct cdev * dev,int oflags,int devtype,struct thread * td)962 gpib_ib_close(struct cdev *dev, int oflags, int devtype, struct thread *td)
963 {
964 struct upd7210 *u;
965 struct ibfoo *ib;
966
967 u = dev->si_drv1;
968 ib = dev->si_drv2;
969 /* XXX: assert pointer consistency */
970
971 u->ibfoo = NULL;
972 /* XXX: free handles */
973 dev->si_drv2 = NULL;
974 free(ib, M_IBFOO);
975
976 if (u->dmachan >= 0) {
977 isa_dma_release(u->dmachan);
978 }
979 mtx_lock(&u->mutex);
980 u->busy = 0;
981 ibdebug = 0;
982 upd7210_wr(u, IMR1, 0x00);
983 upd7210_wr(u, IMR2, 0x00);
984 if (u->use_fifo) {
985 bus_write_1(u->reg_res[0], imr3, 0x00);
986 bus_write_1(u->reg_res[0], cmdr, 0x02); /* clear system
987 * controller bit */
988 }
989 upd7210_wr(u, AUXMR, AUXMR_CRST);
990 DELAY(10000);
991 mtx_unlock(&u->mutex);
992 return (0);
993 }
994
995 static int
gpib_ib_ioctl(struct cdev * dev,u_long cmd,caddr_t data,int fflag,struct thread * td)996 gpib_ib_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
997 {
998 struct ibarg *ap;
999 struct ibhandler *ih;
1000 struct handle *h;
1001 struct upd7210 *u;
1002 struct ibfoo *ib;
1003 int error;
1004 struct timeval deadline, tv;
1005
1006 u = dev->si_drv1;
1007 ib = u->ibfoo;
1008
1009 /* We only support a single ioctl, everything else is a mistake */
1010 if (cmd != GPIB_IBFOO)
1011 return (ENOIOCTL);
1012
1013 /* Check the identifier and field-bitmap in the arguments. */
1014 ap = (void *)data;
1015 if (ap->__ident < 0 || ap->__ident >= max_ibhandler)
1016 return (EINVAL);
1017 ih = &ibhandlers[ap->__ident];
1018 if (ap->__field != ih->args)
1019 return (EINVAL);
1020
1021 if (ibdebug)
1022 ib_dump_args(ih, ap);
1023
1024 if (ih->func == NULL)
1025 return (EOPNOTSUPP);
1026
1027 ap->__iberr = 0;
1028 ap->__ibsta = 0;
1029 ap->__ibcnt = 0;
1030 ap->__retval = 0;
1031
1032 if (ap->__field & __F_TMO) {
1033 if (ap->tmo < 0 || ap->tmo >= max_timeouts)
1034 return (ib_set_error(ap, EARG));
1035 }
1036
1037 if (ap->__field & __F_EOS) {
1038 if ((ap->eos & ~(REOS | XEOS | BIN | 0xff)) ||
1039 ((ap->eos & (BIN | 0x80)) == 0x80))
1040 return (ib_set_error(ap, EARG));
1041 }
1042 if (ap->__field & __F_PAD) {
1043 if (ap->pad < 0 || ap->pad > 30)
1044 return (ib_set_error(ap, EARG));
1045 }
1046 if (ap->__field & __F_SAD) {
1047 if (ap->sad != 0 && (ap->sad < 0x60 || ap->sad > 126))
1048 return (ib_set_error(ap, EARG));
1049 }
1050
1051
1052 mtx_lock(&u->mutex);
1053
1054
1055 /* Find the handle, if any */
1056 h = NULL;
1057 if ((ap->__field & __F_HANDLE) && gethandle(u, ap, &h)) {
1058 mtx_unlock(&u->mutex);
1059 return (0);
1060 }
1061
1062 /* Check that the handle is the right kind */
1063 if (h != NULL && !(h->kind & ih->kind)) {
1064 mtx_unlock(&u->mutex);
1065 return (ib_set_error(ap, EARG));
1066 }
1067
1068 /* Set up handle and deadline */
1069 if (h != NULL && timevalisset(&h->timeout)) {
1070 getmicrouptime(&deadline);
1071 timevaladd(&deadline, &h->timeout);
1072 } else {
1073 timevalclear(&deadline);
1074 }
1075
1076 /* Wait for the card to be(come) available, respect deadline */
1077 while(u->busy != 1) {
1078 error = msleep(ib, &u->mutex,
1079 PZERO | PCATCH, "gpib_ibioctl", hz / 10);
1080 if (error == 0)
1081 continue;
1082 mtx_unlock(&u->mutex);
1083 if (error == EINTR)
1084 return(ib_set_error(ap, EABO));
1085 if (error == EWOULDBLOCK && timevalisset(&deadline)) {
1086 getmicrouptime(&tv);
1087 if (timevalcmp(&deadline, &tv, <))
1088 return(ib_had_timeout(ap));
1089 }
1090 mtx_lock(&u->mutex);
1091 }
1092 u->busy = 2;
1093 mtx_unlock(&u->mutex);
1094
1095 /* Hand over deadline handling to the callout routine */
1096 ib->ap = ap;
1097 ib->h = h;
1098 ib->mode = BUSY;
1099 ib->deadline = deadline;
1100 callout_reset(&ib->callout, hz / 5, gpib_ib_timeout, u);
1101
1102 error = ih->func(ib);
1103
1104 /* Release card */
1105 ib->mode = IDLE;
1106 ib->ap = NULL;
1107 ib->h = NULL;
1108 timevalclear(&deadline);
1109 callout_stop(&ib->callout);
1110
1111 mtx_lock(&u->mutex);
1112 u->busy = 1;
1113 wakeup(ib);
1114 mtx_unlock(&u->mutex);
1115
1116 if (error)
1117 return(ib_set_errno(ap, error));
1118 return (0);
1119 }
1120
1121 struct cdevsw gpib_ib_cdevsw = {
1122 .d_version = D_VERSION,
1123 .d_name = "gpib_ib",
1124 .d_open = gpib_ib_open,
1125 .d_ioctl = gpib_ib_ioctl,
1126 .d_close = gpib_ib_close,
1127 };
1128