xref: /trueos/sys/dev/ieee488/ibfoo.c (revision 94d2b7f64912987093f1a98573737a32e4e5d8d1)
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