upd7210.c revision 141398
1141398Sphk/*-
2141398Sphk * Copyright (c) 2005 Poul-Henning Kamp <phk@FreeBSD.org>
3141398Sphk * All rights reserved.
4141398Sphk *
5141398Sphk * Redistribution and use in source and binary forms, with or without
6141398Sphk * modification, are permitted provided that the following conditions
7141398Sphk * are met:
8141398Sphk * 1. Redistributions of source code must retain the above copyright
9141398Sphk *    notice, this list of conditions and the following disclaimer.
10141398Sphk * 2. Redistributions in binary form must reproduce the above copyright
11141398Sphk *    notice, this list of conditions and the following disclaimer in the
12141398Sphk *    documentation and/or other materials provided with the distribution.
13141398Sphk *
14141398Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15141398Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16141398Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17141398Sphk * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18141398Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19141398Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20141398Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21141398Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22141398Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23141398Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24141398Sphk * SUCH DAMAGE.
25141398Sphk *
26141398Sphk * High-level driver for �PD7210 based GPIB cards.
27141398Sphk *
28141398Sphk */
29141398Sphk
30141398Sphk#include <sys/cdefs.h>
31141398Sphk__FBSDID("$FreeBSD: head/sys/dev/ieee488/upd7210.c 141398 2005-02-06 15:22:23Z phk $");
32141398Sphk
33141398Sphk#  define	GPIB_DEBUG
34141398Sphk#  undef	GPIB_DEBUG
35141398Sphk
36141398Sphk#include <sys/param.h>
37141398Sphk#include <sys/systm.h>
38141398Sphk#include <sys/conf.h>
39141398Sphk#include <sys/malloc.h>
40141398Sphk#include <sys/kernel.h>
41141398Sphk#include <sys/limits.h>
42141398Sphk#include <sys/module.h>
43141398Sphk#include <sys/bus.h>
44141398Sphk#include <sys/lock.h>
45141398Sphk#include <sys/mutex.h>
46141398Sphk#include <sys/uio.h>
47141398Sphk#include <sys/time.h>
48141398Sphk#include <machine/bus.h>
49141398Sphk#include <machine/resource.h>
50141398Sphk#include <isa/isavar.h>
51141398Sphk
52141398Sphk#include <dev/ieee488/upd7210.h>
53141398Sphk#include <dev/ieee488/ugpib.h>
54141398Sphk
55141398SphkMALLOC_DEFINE(M_GPIB, "GPIB", "GPIB");
56141398Sphk
57141398Sphk/* upd7210 generic stuff */
58141398Sphk
59141398Sphkstatic void
60141398Sphkprint_isr(u_int isr1, u_int isr2)
61141398Sphk{
62141398Sphk	printf("isr1=0x%b isr2=0x%b",
63141398Sphk	    isr1, "\20\10CPT\7APT\6DET\5ENDRX\4DEC\3ERR\2DO\1DI",
64141398Sphk	    isr2, "\20\10INT\7SRQI\6LOK\5REM\4CO\3LOKC\2REMC\1ADSC");
65141398Sphk}
66141398Sphk
67141398Sphkstatic u_int
68141398Sphkread_reg(struct upd7210 *u, enum upd7210_rreg reg)
69141398Sphk{
70141398Sphk	u_int r;
71141398Sphk
72141398Sphk	r = bus_space_read_1(
73141398Sphk	    u->reg_tag[reg],
74141398Sphk	    u->reg_handle[reg],
75141398Sphk	    u->reg_offset[reg]);
76141398Sphk	u->rreg[reg] = r;
77141398Sphk	return (r);
78141398Sphk}
79141398Sphk
80141398Sphkstatic void
81141398Sphkwrite_reg(struct upd7210 *u, enum upd7210_wreg reg, u_int val)
82141398Sphk{
83141398Sphk	bus_space_write_1(
84141398Sphk	    u->reg_tag[reg],
85141398Sphk	    u->reg_handle[reg],
86141398Sphk	    u->reg_offset[reg], val);
87141398Sphk	u->wreg[reg] = val;
88141398Sphk	if (reg == AUXMR)
89141398Sphk		u->wreg[8 + (val >> 5)] = val & 0x1f;
90141398Sphk}
91141398Sphk
92141398Sphkvoid
93141398Sphkupd7210intr(void *arg)
94141398Sphk{
95141398Sphk	u_int isr1, isr2;
96141398Sphk	struct upd7210 *u;
97141398Sphk
98141398Sphk	u = arg;
99141398Sphk	mtx_lock(&u->mutex);
100141398Sphk	isr1 = read_reg(u, ISR1);
101141398Sphk	isr2 = read_reg(u, ISR2);
102141398Sphk	if (u->busy == 0 || u->irq == NULL || !u->irq(u)) {
103141398Sphk		printf("upd7210intr [%02x %02x %02x",
104141398Sphk		    read_reg(u, DIR), isr1, isr2);
105141398Sphk		printf(" %02x %02x %02x %02x %02x] ",
106141398Sphk		    read_reg(u, SPSR),
107141398Sphk		    read_reg(u, ADSR),
108141398Sphk		    read_reg(u, CPTR),
109141398Sphk		    read_reg(u, ADR0),
110141398Sphk		    read_reg(u, ADR1));
111141398Sphk		print_isr(isr1, isr2);
112141398Sphk		printf("\n");
113141398Sphk		write_reg(u, IMR1, 0);
114141398Sphk		write_reg(u, IMR2, 0);
115141398Sphk	}
116141398Sphk	mtx_unlock(&u->mutex);
117141398Sphk}
118141398Sphk
119141398Sphkstatic int
120141398Sphkupd7210_take_ctrl_async(struct upd7210 *u)
121141398Sphk{
122141398Sphk	int i;
123141398Sphk
124141398Sphk	write_reg(u, AUXMR, AUXMR_TCA);
125141398Sphk
126141398Sphk	if (!(read_reg(u, ADSR) & ADSR_ATN))
127141398Sphk		return (0);
128141398Sphk	for (i = 0; i < 20; i++) {
129141398Sphk		DELAY(1);
130141398Sphk		if (!(read_reg(u, ADSR) & ADSR_ATN))
131141398Sphk			return (0);
132141398Sphk	}
133141398Sphk	return (1);
134141398Sphk}
135141398Sphk
136141398Sphkstatic int
137141398Sphkupd7210_goto_standby(struct upd7210 *u)
138141398Sphk{
139141398Sphk	int i;
140141398Sphk
141141398Sphk	write_reg(u, AUXMR, AUXMR_GTS);
142141398Sphk
143141398Sphk	if (read_reg(u, ADSR) & ADSR_ATN)
144141398Sphk		return (0);
145141398Sphk	for (i = 0; i < 20; i++) {
146141398Sphk		DELAY(1);
147141398Sphk		if (read_reg(u, ADSR) & ADSR_ATN)
148141398Sphk			return (0);
149141398Sphk	}
150141398Sphk	return (1);
151141398Sphk}
152141398Sphk
153141398Sphkstatic int
154141398Sphkdeadyet(struct upd7210 *u)
155141398Sphk{
156141398Sphk	struct timeval tv;
157141398Sphk
158141398Sphk	if (!timevalisset(&u->deadline))
159141398Sphk		return (0);
160141398Sphk
161141398Sphk	getmicrouptime(&tv);
162141398Sphk	if (timevalcmp(&u->deadline, &tv, <)) {
163141398Sphkprintf("DEADNOW\n");
164141398Sphk		return (1);
165141398Sphk	}
166141398Sphk
167141398Sphk	return (0);
168141398Sphk}
169141398Sphk
170141398Sphk/* Unaddressed Listen Only mode */
171141398Sphk
172141398Sphkstatic int
173141398Sphkgpib_l_irq(struct upd7210 *u)
174141398Sphk{
175141398Sphk	int i;
176141398Sphk
177141398Sphk	if (u->rreg[ISR1] & 1) {
178141398Sphk		i = read_reg(u, DIR);
179141398Sphk		u->buf[u->buf_wp++] = i;
180141398Sphk		u->buf_wp &= (u->bufsize - 1);
181141398Sphk		i = (u->buf_rp + u->bufsize - u->buf_wp) & (u->bufsize - 1);
182141398Sphk		if (i < 8)
183141398Sphk			write_reg(u, IMR1, 0);
184141398Sphk		wakeup(u->buf);
185141398Sphk		return (1);
186141398Sphk	}
187141398Sphk	return (0);
188141398Sphk}
189141398Sphk
190141398Sphkstatic int
191141398Sphkgpib_l_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
192141398Sphk{
193141398Sphk	struct upd7210 *u;
194141398Sphk
195141398Sphk	u = dev->si_drv1;
196141398Sphk
197141398Sphk	mtx_lock(&u->mutex);
198141398Sphk	if (u->busy)
199141398Sphk		return (EBUSY);
200141398Sphk	u->busy = 1;
201141398Sphk	u->irq = gpib_l_irq;
202141398Sphk	mtx_unlock(&u->mutex);
203141398Sphk
204141398Sphk	u->buf = malloc(PAGE_SIZE, M_GPIB, M_WAITOK);
205141398Sphk	u->bufsize = PAGE_SIZE;
206141398Sphk	u->buf_wp = 0;
207141398Sphk	u->buf_rp = 0;
208141398Sphk
209141398Sphk	write_reg(u, AUXMR, AUXMR_CRST);
210141398Sphk	DELAY(10000);
211141398Sphk	write_reg(u, AUXMR, C_ICR | 8);
212141398Sphk	DELAY(1000);
213141398Sphk	write_reg(u, ADR, 0x60);
214141398Sphk	write_reg(u, ADR, 0xe0);
215141398Sphk	write_reg(u, ADMR, 0x70);
216141398Sphk	write_reg(u, AUXMR, AUXMR_PON);
217141398Sphk	write_reg(u, IMR1, 0x01);
218141398Sphk	return (0);
219141398Sphk}
220141398Sphk
221141398Sphkstatic int
222141398Sphkgpib_l_close(struct cdev *dev, int oflags, int devtype, struct thread *td)
223141398Sphk{
224141398Sphk	struct upd7210 *u;
225141398Sphk
226141398Sphk	u = dev->si_drv1;
227141398Sphk
228141398Sphk	mtx_lock(&u->mutex);
229141398Sphk	u->busy = 0;
230141398Sphk	write_reg(u, AUXMR, AUXMR_CRST);
231141398Sphk	DELAY(10000);
232141398Sphk	write_reg(u, IMR1, 0x00);
233141398Sphk	write_reg(u, IMR2, 0x00);
234141398Sphk	free(u->buf, M_GPIB);
235141398Sphk	u->buf = NULL;
236141398Sphk	mtx_unlock(&u->mutex);
237141398Sphk	return (0);
238141398Sphk}
239141398Sphk
240141398Sphkstatic int
241141398Sphkgpib_l_read(struct cdev *dev, struct uio *uio, int ioflag)
242141398Sphk{
243141398Sphk	struct upd7210 *u;
244141398Sphk	int error;
245141398Sphk	size_t z;
246141398Sphk
247141398Sphk	u = dev->si_drv1;
248141398Sphk	error = 0;
249141398Sphk
250141398Sphk	mtx_lock(&u->mutex);
251141398Sphk	while (u->buf_wp == u->buf_rp) {
252141398Sphk		error = msleep(u->buf, &u->mutex, PZERO | PCATCH,
253141398Sphk		    "gpibrd", hz);
254141398Sphk		if (error && error != EWOULDBLOCK) {
255141398Sphk			mtx_unlock(&u->mutex);
256141398Sphk			return (error);
257141398Sphk		}
258141398Sphk	}
259141398Sphk	while (uio->uio_resid > 0 && u->buf_wp != u->buf_rp) {
260141398Sphk		if (u->buf_wp < u->buf_rp)
261141398Sphk			z = u->bufsize - u->buf_rp;
262141398Sphk		else
263141398Sphk			z = u->buf_wp - u->buf_rp;
264141398Sphk		if (z > uio->uio_resid)
265141398Sphk			z = uio->uio_resid;
266141398Sphk		mtx_unlock(&u->mutex);
267141398Sphk		error = uiomove(u->buf + u->buf_rp, z, uio);
268141398Sphk		mtx_lock(&u->mutex);
269141398Sphk		if (error)
270141398Sphk			break;
271141398Sphk		u->buf_rp += z;
272141398Sphk		u->buf_rp &= (u->bufsize - 1);
273141398Sphk	}
274141398Sphk	if (u->wreg[IMR1] == 0)
275141398Sphk		write_reg(u, IMR1, 0x01);
276141398Sphk	mtx_unlock(&u->mutex);
277141398Sphk	return (error);
278141398Sphk}
279141398Sphk
280141398Sphkstruct cdevsw gpib_l_cdevsw = {
281141398Sphk	.d_version =	D_VERSION,
282141398Sphk	.d_name =	"gpib_l",
283141398Sphk	.d_open	=	gpib_l_open,
284141398Sphk	.d_close =	gpib_l_close,
285141398Sphk	.d_read =	gpib_l_read,
286141398Sphk};
287141398Sphk
288141398Sphk/* ibfoo API */
289141398Sphk
290141398Sphk#include <dev/ieee488/ibfoo_int.h>
291141398Sphk
292141398Sphkstruct handle {
293141398Sphk	LIST_ENTRY(handle)	list;
294141398Sphk	int			handle;
295141398Sphk	int			pad;
296141398Sphk	int			sad;
297141398Sphk	struct timeval		timeout;
298141398Sphk	int			eot;
299141398Sphk	int			eos;
300141398Sphk};
301141398Sphk
302141398Sphkstruct ibfoo {
303141398Sphk	struct upd7210		*upd7210;
304141398Sphk	LIST_HEAD(,handle)	handles;
305141398Sphk	struct unrhdr		*unrhdr;
306141398Sphk
307141398Sphk	u_char			*cmdbuf;
308141398Sphk	u_int			cmdlen;
309141398Sphk
310141398Sphk	struct handle		*rdh;		/* addressed for read */
311141398Sphk	struct handle		*wrh;		/* addressed for write */
312141398Sphk
313141398Sphk	u_char			*dobuf;
314141398Sphk	u_int			dolen;
315141398Sphk	int			doeoi;
316141398Sphk};
317141398Sphk
318141398Sphkstatic struct timeval timeouts[] = {
319141398Sphk	[TNONE] =	{    0,      0},
320141398Sphk	[T10us] =	{    0,     10},
321141398Sphk	[T30us] =	{    0,     30},
322141398Sphk	[T100us] =	{    0,    100},
323141398Sphk	[T300us] =	{    0,    300},
324141398Sphk	[T1ms] =	{    0,   1000},
325141398Sphk	[T3ms] =	{    0,   3000},
326141398Sphk	[T10ms] =	{    0,  10000},
327141398Sphk	[T30ms] =	{    0,  30000},
328141398Sphk	[T100ms] =	{    0, 100000},
329141398Sphk	[T300ms] =	{    0, 300000},
330141398Sphk	[T1s] =		{    1,      0},
331141398Sphk	[T3s] =		{    3,      0},
332141398Sphk	[T10s] =	{   10,      0},
333141398Sphk	[T30s] =	{   30,      0},
334141398Sphk	[T100s] =	{  100,      0},
335141398Sphk	[T300s] =	{  300,      0},
336141398Sphk	[T1000s] =	{ 1000,      0}
337141398Sphk};
338141398Sphk
339141398Sphkstatic u_int max_timeouts = sizeof timeouts / sizeof timeouts[0];
340141398Sphk
341141398Sphktypedef int ibhandler_t(struct upd7210 *u, struct ibfoo_iocarg *ap);
342141398Sphk
343141398Sphkstatic int
344141398Sphkgpib_ib_irq(struct upd7210 *u)
345141398Sphk{
346141398Sphk	struct ibfoo *ib;
347141398Sphk
348141398Sphk	ib = u->ibfoo;
349141398Sphk
350141398Sphk	if ((u->rreg[ISR2] & IXR2_CO) && ib->cmdlen > 0) {
351141398Sphk		write_reg(u, CDOR, *ib->cmdbuf);
352141398Sphk		ib->cmdbuf++;
353141398Sphk		ib->cmdlen--;
354141398Sphk		if (ib->cmdlen == 0) {
355141398Sphk			wakeup(ib);
356141398Sphk			write_reg(u, IMR2, 0);
357141398Sphk		}
358141398Sphk		return (1);
359141398Sphk	}
360141398Sphk	if ((u->rreg[ISR1] & IXR1_DO) && ib->dolen > 0) {
361141398Sphk		if (ib->dolen == 1 && ib->doeoi)
362141398Sphk			write_reg(u, AUXMR, AUXMR_SEOI);
363141398Sphk		write_reg(u, CDOR, *ib->dobuf);
364141398Sphk		ib->dobuf++;
365141398Sphk		ib->dolen--;
366141398Sphk		if (ib->dolen == 0) {
367141398Sphk			wakeup(ib);
368141398Sphk			write_reg(u, IMR1, 0);
369141398Sphk		}
370141398Sphk		return (1);
371141398Sphk	}
372141398Sphk	if (u->rreg[ISR1] & IXR1_ENDRX) {
373141398Sphk		write_reg(u, IMR1, 0);
374141398Sphk		wakeup(ib);
375141398Sphk		return (1);
376141398Sphk	}
377141398Sphk
378141398Sphk	return (0);
379141398Sphk}
380141398Sphk
381141398Sphkstatic void
382141398Sphkconfig_eos(struct upd7210 *u, struct handle *h)
383141398Sphk{
384141398Sphk	int i;
385141398Sphk
386141398Sphk	i = 0;
387141398Sphk	if (h->eos & 0x0400) {
388141398Sphk		write_reg(u, EOSR, h->eos & 0xff);
389141398Sphk		i |= AUXA_REOS;
390141398Sphk	}
391141398Sphk	if (h->eos & 0x1000)
392141398Sphk		i |= AUXA_BIN;
393141398Sphk	write_reg(u, AUXRA, C_AUXA | i);
394141398Sphk}
395141398Sphk
396141398Sphk/*
397141398Sphk * Look up the handle, and set the deadline if the handle has a timeout.
398141398Sphk */
399141398Sphkstatic int
400141398Sphkgethandle(struct upd7210 *u, struct ibfoo_iocarg *ap, struct handle **hp)
401141398Sphk{
402141398Sphk	struct ibfoo *ib;
403141398Sphk	struct handle *h;
404141398Sphk
405141398Sphk	KASSERT(ap->__field & __F_HANDLE, ("gethandle without __F_HANDLE"));
406141398Sphk	ib = u->ibfoo;
407141398Sphk	LIST_FOREACH(h, &ib->handles, list) {
408141398Sphk		if (h->handle == ap->handle) {
409141398Sphk			*hp = h;
410141398Sphk			if (timevalisset(&h->timeout)) {
411141398Sphk				getmicrouptime(&u->deadline);
412141398Sphk				timevaladd(&u->deadline, &h->timeout);
413141398Sphk			} else {
414141398Sphk				timevalclear(&u->deadline);
415141398Sphk			}
416141398Sphk			return (0);
417141398Sphk		}
418141398Sphk	}
419141398Sphk	ap->__iberr = EARG;
420141398Sphk	return (1);
421141398Sphk}
422141398Sphk
423141398Sphkstatic int
424141398Sphkdo_cmd(struct upd7210 *u, u_char *cmd, int len)
425141398Sphk{
426141398Sphk	int i, i1, i2;
427141398Sphk	struct ibfoo *ib;
428141398Sphk
429141398Sphk	ib = u->ibfoo;
430141398Sphk
431141398Sphk	if (ib->rdh != NULL || ib->wrh != NULL) {
432141398Sphk		upd7210_take_ctrl_async(u);
433141398Sphk		ib->rdh = NULL;
434141398Sphk		ib->wrh = NULL;
435141398Sphk	}
436141398Sphk	mtx_lock(&u->mutex);
437141398Sphk	ib->cmdbuf = cmd;
438141398Sphk	ib->cmdlen = len;
439141398Sphk
440141398Sphk	if (!(u->rreg[ISR2] & IXR2_CO)) {
441141398Sphk		i1 = read_reg(u, ISR1);
442141398Sphk		i2 = read_reg(u, ISR2);
443141398Sphk#ifdef GPIB_DEBUG
444141398Sphk		print_isr(i1, i2);
445141398Sphk		printf("\n");
446141398Sphk#endif
447141398Sphk	}
448141398Sphk	write_reg(u, IMR2, IXR2_CO);
449141398Sphk	if (u->rreg[ISR2] & IXR2_CO) {
450141398Sphk		write_reg(u, CDOR, *ib->cmdbuf);
451141398Sphk		ib->cmdbuf++;
452141398Sphk		ib->cmdlen--;
453141398Sphk	}
454141398Sphk
455141398Sphk	while (1) {
456141398Sphk		i = msleep(ib, &u->mutex, PZERO | PCATCH, "gpib_cmd", hz/10);
457141398Sphk		if (i == EINTR)
458141398Sphk			break;
459141398Sphk		if (u->rreg[ISR1] & IXR1_ERR)
460141398Sphk			break;
461141398Sphk		if (!ib->cmdlen)
462141398Sphk			break;
463141398Sphk		if (deadyet(u))
464141398Sphk			break;
465141398Sphk	}
466141398Sphk	write_reg(u, IMR2, 0);
467141398Sphk	mtx_unlock(&u->mutex);
468141398Sphk	return (0);
469141398Sphk}
470141398Sphk
471141398Sphkstatic int
472141398Sphkdo_odata(struct upd7210 *u, u_char *data, int len, int eos)
473141398Sphk{
474141398Sphk	int i1, i2, i;
475141398Sphk	struct ibfoo *ib;
476141398Sphk
477141398Sphk	ib = u->ibfoo;
478141398Sphk
479141398Sphk	mtx_lock(&u->mutex);
480141398Sphk	ib->dobuf = data;
481141398Sphk	ib->dolen = len;
482141398Sphk	ib->doeoi = 1;
483141398Sphk
484141398Sphk	if (!(u->rreg[ISR1] & IXR1_DO)) {
485141398Sphk		i1 = read_reg(u, ISR1);
486141398Sphk		i2 = read_reg(u, ISR2);
487141398Sphk#ifdef GPIB_DEBUG
488141398Sphk		print_isr(i1, i2);
489141398Sphk		printf("\n");
490141398Sphk#endif
491141398Sphk	}
492141398Sphk	write_reg(u, IMR1, IXR1_DO);
493141398Sphk	if (u->rreg[ISR1] & IXR1_DO) {
494141398Sphk		write_reg(u, CDOR, *ib->dobuf);
495141398Sphk		ib->dobuf++;
496141398Sphk		ib->dolen--;
497141398Sphk	}
498141398Sphk	while (1) {
499141398Sphk		i = msleep(ib, &u->mutex, PZERO | PCATCH, "gpib_out", hz/100);
500141398Sphk		if (i == EINTR)
501141398Sphk			break;
502141398Sphk		if (u->rreg[ISR1] & IXR1_ERR)
503141398Sphk			break;
504141398Sphk		if (!ib->dolen)
505141398Sphk			break;
506141398Sphk		if (deadyet(u))
507141398Sphk			break;
508141398Sphk	}
509141398Sphk	write_reg(u, IMR2, 0);
510141398Sphk	mtx_unlock(&u->mutex);
511141398Sphk	return (len - ib->dolen);
512141398Sphk}
513141398Sphk
514141398Sphkstatic int
515141398Sphkdo_idata(struct upd7210 *u, u_char *data, int len, int eos)
516141398Sphk{
517141398Sphk	int i1, i2, i, j;
518141398Sphk
519141398Sphk	write_reg(u, IMR1, IXR1_ENDRX);
520141398Sphk	mtx_lock(&Giant);
521141398Sphk	isa_dmastart(ISADMA_READ, data, len, u->dmachan);
522141398Sphk	mtx_unlock(&Giant);
523141398Sphk	mtx_lock(&u->mutex);
524141398Sphk	write_reg(u, IMR2, IMR2_DMAI);
525141398Sphk	while (1) {
526141398Sphk		i = msleep(u->ibfoo, &u->mutex, PZERO | PCATCH,
527141398Sphk		    "gpib_idata", hz/100);
528141398Sphk		if (i == EINTR)
529141398Sphk			break;
530141398Sphk		if (isa_dmatc(u->dmachan))
531141398Sphk			break;
532141398Sphk		if (i == EWOULDBLOCK) {
533141398Sphk			i1 = read_reg(u, ISR1);
534141398Sphk			i2 = read_reg(u, ISR2);
535141398Sphk		} else {
536141398Sphk			i1 = u->rreg[ISR1];
537141398Sphk			i2 = u->rreg[ISR2];
538141398Sphk		}
539141398Sphk		if (i1 & IXR1_ENDRX)
540141398Sphk			break;
541141398Sphk		if (deadyet(u))
542141398Sphk			break;
543141398Sphk	}
544141398Sphk	write_reg(u, IMR1, 0);
545141398Sphk	write_reg(u, IMR2, 0);
546141398Sphk	mtx_unlock(&u->mutex);
547141398Sphk	mtx_lock(&Giant);
548141398Sphk	j = isa_dmastatus(u->dmachan);
549141398Sphk	isa_dmadone(ISADMA_READ, data, len, u->dmachan);
550141398Sphk	mtx_unlock(&Giant);
551141398Sphk	if (deadyet(u)) {
552141398Sphk		return (-1);
553141398Sphk	} else {
554141398Sphk		return (len - j);
555141398Sphk	}
556141398Sphk}
557141398Sphk
558141398Sphk#define ibask NULL
559141398Sphk#define ibbna NULL
560141398Sphk#define ibcac NULL
561141398Sphk#define ibclr NULL
562141398Sphk#define ibcmd NULL
563141398Sphk#define ibcmda NULL
564141398Sphk#define ibconfig NULL
565141398Sphk
566141398Sphkstatic int
567141398Sphkibdev(struct upd7210 *u, struct ibfoo_iocarg *ap)
568141398Sphk{
569141398Sphk	struct handle *h;
570141398Sphk	struct ibfoo *ib;
571141398Sphk
572141398Sphk	if (ap->pad < 0 ||
573141398Sphk	    ap->pad > 30 ||
574141398Sphk	    (ap->sad != 0 && ap->sad < 0x60) ||
575141398Sphk	    ap->sad > 126) {
576141398Sphk		ap->__retval = -1;
577141398Sphk		ap->__iberr = EARG;
578141398Sphk		return (0);
579141398Sphk	}
580141398Sphk
581141398Sphk	ib = u->ibfoo;
582141398Sphk	h = malloc(sizeof *h, M_GPIB, M_ZERO | M_WAITOK);
583141398Sphk	h->handle = alloc_unr(ib->unrhdr);
584141398Sphk	LIST_INSERT_HEAD(&ib->handles, h, list);
585141398Sphk	h->pad = ap->pad;
586141398Sphk	h->sad = ap->sad;
587141398Sphk	h->timeout = timeouts[ap->tmo];
588141398Sphk	h->eot = ap->eot;
589141398Sphk	h->eos = ap->eos;
590141398Sphk	ap->__retval = h->handle;
591141398Sphk	return (0);
592141398Sphk}
593141398Sphk
594141398Sphk#define ibdiag NULL
595141398Sphk#define ibdma NULL
596141398Sphk
597141398Sphkstatic int
598141398Sphkibeos(struct upd7210 *u, struct ibfoo_iocarg *ap)
599141398Sphk{
600141398Sphk	struct handle *h;
601141398Sphk	struct ibfoo *ib;
602141398Sphk
603141398Sphk	if (gethandle(u, ap, &h))
604141398Sphk		return (0);
605141398Sphk	ib = u->ibfoo;
606141398Sphk	h->eos = ap->eos;
607141398Sphk	if (ib->rdh == h)
608141398Sphk		config_eos(u, h);
609141398Sphk	ap->__retval = 0;
610141398Sphk	return (0);
611141398Sphk}
612141398Sphk
613141398Sphk#define ibeot NULL
614141398Sphk#define ibevent NULL
615141398Sphk#define ibfind NULL
616141398Sphk#define ibgts NULL
617141398Sphk#define ibist NULL
618141398Sphk#define iblines NULL
619141398Sphk#define ibllo NULL
620141398Sphk#define ibln NULL
621141398Sphk#define ibloc NULL
622141398Sphk#define ibonl NULL
623141398Sphk#define ibpad NULL
624141398Sphk#define ibpct NULL
625141398Sphk#define ibpoke NULL
626141398Sphk#define ibppc NULL
627141398Sphk
628141398Sphkstatic int
629141398Sphkibrd(struct upd7210 *u, struct ibfoo_iocarg *ap)
630141398Sphk{
631141398Sphk	struct ibfoo *ib;
632141398Sphk	struct handle *h;
633141398Sphk	u_char buf[10], *bp;
634141398Sphk	int i, j, error, bl, bc;
635141398Sphk	u_char *dp;
636141398Sphk
637141398Sphk	ib = u->ibfoo;
638141398Sphk	if (gethandle(u, ap, &h))
639141398Sphk		return (0);
640141398Sphk	bl = ap->cnt;
641141398Sphk	if (bl > PAGE_SIZE)
642141398Sphk		bl = PAGE_SIZE;
643141398Sphk	bp = malloc(bl, M_GPIB, M_WAITOK);
644141398Sphk
645141398Sphk	if (ib->rdh != h) {
646141398Sphk		i = 0;
647141398Sphk		buf[i++] = UNT;
648141398Sphk		buf[i++] = UNL;
649141398Sphk		buf[i++] = LAD | 0;
650141398Sphk		buf[i++] = TAD | h->pad;
651141398Sphk		if (h->sad)
652141398Sphk			buf[i++] = h->sad;
653141398Sphk		i = do_cmd(u, buf, i);
654141398Sphk		config_eos(u, h);
655141398Sphk		ib->rdh = h;
656141398Sphk		ib->wrh = NULL;
657141398Sphk		upd7210_goto_standby(u);
658141398Sphk	}
659141398Sphk	ap->__ibcnt = 0;
660141398Sphk	dp = ap->buffer;
661141398Sphk	bc = ap->cnt;
662141398Sphk	error = 0;
663141398Sphk	while (bc > 0) {
664141398Sphk		j = imin(bc, PAGE_SIZE);
665141398Sphk		i = do_idata(u, bp, j, 1);
666141398Sphk		if (i <= 0)
667141398Sphk			break;
668141398Sphk		error = copyout(bp, dp , i);
669141398Sphk		if (error)
670141398Sphk			break;
671141398Sphk		ap->__ibcnt += i;
672141398Sphk		if (i != j)
673141398Sphk			break;
674141398Sphk		bc -= i;
675141398Sphk		dp += i;
676141398Sphk	}
677141398Sphk	free(bp, M_GPIB);
678141398Sphk	ap->__retval = 0;
679141398Sphk	return (error);
680141398Sphk}
681141398Sphk
682141398Sphk#define ibrda NULL
683141398Sphk#define ibrdf NULL
684141398Sphk#define ibrdkey NULL
685141398Sphk#define ibrpp NULL
686141398Sphk#define ibrsc NULL
687141398Sphk#define ibrsp NULL
688141398Sphk#define ibrsv NULL
689141398Sphk#define ibsad NULL
690141398Sphk#define ibsgnl NULL
691141398Sphk#define ibsic NULL
692141398Sphk#define ibsre NULL
693141398Sphk#define ibsrq NULL
694141398Sphk#define ibstop NULL
695141398Sphk
696141398Sphkstatic int
697141398Sphkibtmo(struct upd7210 *u, struct ibfoo_iocarg *ap)
698141398Sphk{
699141398Sphk	struct handle *h;
700141398Sphk
701141398Sphk	if (gethandle(u, ap, &h))
702141398Sphk		return (0);
703141398Sphk	h->timeout = timeouts[ap->tmo];
704141398Sphk	return (0);
705141398Sphk}
706141398Sphk
707141398Sphk#define ibtrap NULL
708141398Sphk#define ibtrg NULL
709141398Sphk#define ibwait NULL
710141398Sphk
711141398Sphkstatic int
712141398Sphkibwrt(struct upd7210 *u, struct ibfoo_iocarg *ap)
713141398Sphk{
714141398Sphk	struct ibfoo *ib;
715141398Sphk	struct handle *h;
716141398Sphk	u_char buf[10], *bp;
717141398Sphk	int i;
718141398Sphk
719141398Sphk	ib = u->ibfoo;
720141398Sphk	if (gethandle(u, ap, &h))
721141398Sphk		return (0);
722141398Sphk	bp = malloc(ap->cnt, M_GPIB, M_WAITOK);
723141398Sphk	i = copyin(ap->buffer, bp, ap->cnt);
724141398Sphk	if (i) {
725141398Sphk		free(bp, M_GPIB);
726141398Sphk		return (i);
727141398Sphk	}
728141398Sphk	if (ib->wrh != h) {
729141398Sphk		i = 0;
730141398Sphk		buf[i++] = UNT;
731141398Sphk		buf[i++] = UNL;
732141398Sphk		buf[i++] = LAD | h->pad;
733141398Sphk		if (h->sad)
734141398Sphk			buf[i++] = LAD | TAD | h->sad;
735141398Sphk		buf[i++] = TAD | 0;
736141398Sphk		i = do_cmd(u, buf, i);
737141398Sphk		ib->rdh = NULL;
738141398Sphk		ib->wrh = h;
739141398Sphk		upd7210_goto_standby(u);
740141398Sphk	}
741141398Sphk	i = do_odata(u, bp, ap->cnt, 1);
742141398Sphk	ap->__ibcnt = i;
743141398Sphk	ap->__retval = 0;
744141398Sphk	free(bp, M_GPIB);
745141398Sphk	return (0);
746141398Sphk}
747141398Sphk
748141398Sphk#define ibwrta NULL
749141398Sphk#define ibwrtf NULL
750141398Sphk#define ibwrtkey NULL
751141398Sphk#define ibxtrc NULL
752141398Sphk
753141398Sphkstatic struct ibhandler {
754141398Sphk	const char 	*name;
755141398Sphk	ibhandler_t	*func;
756141398Sphk	u_int		args;
757141398Sphk} ibhandlers[] = {
758141398Sphk	[__ID_IBASK] =		{ "ibask",	ibask,		__F_HANDLE | __F_OPTION | __F_RETVAL },
759141398Sphk	[__ID_IBBNA] =		{ "ibbna",	ibbna,		__F_HANDLE | __F_BDNAME },
760141398Sphk	[__ID_IBCAC] =		{ "ibcac",	ibcac,		__F_HANDLE | __F_V },
761141398Sphk	[__ID_IBCLR] =		{ "ibclr",	ibclr,		__F_HANDLE },
762141398Sphk	[__ID_IBCMDA] =		{ "ibcmda",	ibcmda,		__F_HANDLE | __F_BUFFER | __F_CNT },
763141398Sphk	[__ID_IBCMD] =		{ "ibcmd",	ibcmd,		__F_HANDLE | __F_BUFFER | __F_CNT },
764141398Sphk	[__ID_IBCONFIG] =	{ "ibconfig",	ibconfig,	__F_HANDLE | __F_OPTION | __F_VALUE },
765141398Sphk	[__ID_IBDEV] =		{ "ibdev",	ibdev,		__F_BOARDID | __F_PAD | __F_SAD | __F_TMO | __F_EOT | __F_EOS },
766141398Sphk	[__ID_IBDIAG] =		{ "ibdiag",	ibdiag,		__F_HANDLE | __F_BUFFER | __F_CNT },
767141398Sphk	[__ID_IBDMA] =		{ "ibdma",	ibdma,		__F_HANDLE | __F_V },
768141398Sphk	[__ID_IBEOS] =		{ "ibeos",	ibeos,		__F_HANDLE | __F_EOS },
769141398Sphk	[__ID_IBEOT] =		{ "ibeot",	ibeot,		__F_HANDLE | __F_V },
770141398Sphk	[__ID_IBEVENT] =	{ "ibevent",	ibevent,	__F_HANDLE | __F_EVENT },
771141398Sphk	[__ID_IBFIND] =		{ "ibfind",	ibfind,		__F_BDNAME },
772141398Sphk	[__ID_IBGTS] =		{ "ibgts",	ibgts,		__F_HANDLE | __F_V },
773141398Sphk	[__ID_IBIST] =		{ "ibist",	ibist,		__F_HANDLE | __F_V },
774141398Sphk	[__ID_IBLINES] =	{ "iblines",	iblines,	__F_HANDLE | __F_LINES },
775141398Sphk	[__ID_IBLLO] =		{ "ibllo",	ibllo,		__F_HANDLE },
776141398Sphk	[__ID_IBLN] =		{ "ibln",	ibln,		__F_HANDLE | __F_PADVAL | __F_SADVAL | __F_LISTENFLAG },
777141398Sphk	[__ID_IBLOC] =		{ "ibloc",	ibloc,		__F_HANDLE },
778141398Sphk	[__ID_IBONL] =		{ "ibonl",	ibonl,		__F_HANDLE | __F_V },
779141398Sphk	[__ID_IBPAD] =		{ "ibpad",	ibpad,		__F_HANDLE | __F_V },
780141398Sphk	[__ID_IBPCT] =		{ "ibpct",	ibpct,		__F_HANDLE },
781141398Sphk	[__ID_IBPOKE] =		{ "ibpoke",	ibpoke,		__F_HANDLE | __F_OPTION | __F_VALUE },
782141398Sphk	[__ID_IBPPC] =		{ "ibppc",	ibppc,		__F_HANDLE | __F_V },
783141398Sphk	[__ID_IBRDA] =		{ "ibrda",	ibrda,		__F_HANDLE | __F_BUFFER | __F_CNT },
784141398Sphk	[__ID_IBRDF] =		{ "ibrdf",	ibrdf,		__F_HANDLE | __F_FLNAME },
785141398Sphk	[__ID_IBRDKEY] =	{ "ibrdkey",	ibrdkey,	__F_HANDLE | __F_BUFFER | __F_CNT },
786141398Sphk	[__ID_IBRD] =		{ "ibrd",	ibrd,		__F_HANDLE | __F_BUFFER | __F_CNT },
787141398Sphk	[__ID_IBRPP] =		{ "ibrpp",	ibrpp,		__F_HANDLE | __F_PPR },
788141398Sphk	[__ID_IBRSC] =		{ "ibrsc",	ibrsc,		__F_HANDLE | __F_V },
789141398Sphk	[__ID_IBRSP] =		{ "ibrsp",	ibrsp,		__F_HANDLE | __F_SPR },
790141398Sphk	[__ID_IBRSV] =		{ "ibrsv",	ibrsv,		__F_HANDLE | __F_V },
791141398Sphk	[__ID_IBSAD] =		{ "ibsad",	ibsad,		__F_HANDLE | __F_V },
792141398Sphk	[__ID_IBSGNL] =		{ "ibsgnl",	ibsgnl,		__F_HANDLE | __F_V },
793141398Sphk	[__ID_IBSIC] =		{ "ibsic",	ibsic,		__F_HANDLE },
794141398Sphk	[__ID_IBSRE] =		{ "ibsre",	ibsre,		__F_HANDLE | __F_V },
795141398Sphk	[__ID_IBSRQ] =		{ "ibsrq",	ibsrq,		__F_FUNC },
796141398Sphk	[__ID_IBSTOP] =		{ "ibstop",	ibstop,		__F_HANDLE },
797141398Sphk	[__ID_IBTMO] =		{ "ibtmo",	ibtmo,		__F_HANDLE | __F_TMO },
798141398Sphk	[__ID_IBTRAP] =		{ "ibtrap",	ibtrap,		__F_MASK | __F_MODE },
799141398Sphk	[__ID_IBTRG] =		{ "ibtrg",	ibtrg,		__F_HANDLE },
800141398Sphk	[__ID_IBWAIT] =		{ "ibwait",	ibwait,		__F_HANDLE | __F_MASK },
801141398Sphk	[__ID_IBWRTA] =		{ "ibwrta",	ibwrta,		__F_HANDLE | __F_BUFFER | __F_CNT },
802141398Sphk	[__ID_IBWRTF] =		{ "ibwrtf",	ibwrtf,		__F_HANDLE | __F_FLNAME },
803141398Sphk	[__ID_IBWRTKEY] =	{ "ibwrtkey",	ibwrtkey,	__F_HANDLE | __F_BUFFER | __F_CNT },
804141398Sphk	[__ID_IBWRT] =		{ "ibwrt",	ibwrt,		__F_HANDLE | __F_BUFFER | __F_CNT },
805141398Sphk	[__ID_IBXTRC] =		{ "ibxtrc",	ibxtrc,		__F_HANDLE | __F_BUFFER | __F_CNT },
806141398Sphk};
807141398Sphk
808141398Sphkstatic u_int max_ibhandler = sizeof ibhandlers / sizeof ibhandlers[0];
809141398Sphk
810141398Sphkstatic int
811141398Sphkgpib_ib_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
812141398Sphk{
813141398Sphk	struct upd7210 *u;
814141398Sphk	struct ibfoo *ib;
815141398Sphk	int error;
816141398Sphk
817141398Sphk	u = dev->si_drv1;
818141398Sphk
819141398Sphk	mtx_lock(&u->mutex);
820141398Sphk	if (u->busy) {
821141398Sphk		mtx_unlock(&u->mutex);
822141398Sphk		return (EBUSY);
823141398Sphk	}
824141398Sphk	u->busy = 1;
825141398Sphk	mtx_unlock(&u->mutex);
826141398Sphk
827141398Sphk	mtx_lock(&Giant);
828141398Sphk	error = isa_dma_acquire(u->dmachan);
829141398Sphk	if (!error) {
830141398Sphk		error = isa_dma_init(u->dmachan, PAGE_SIZE, M_WAITOK);
831141398Sphk		if (error)
832141398Sphk			isa_dma_release(u->dmachan);
833141398Sphk	}
834141398Sphk	mtx_unlock(&Giant);
835141398Sphk	if (error) {
836141398Sphk		mtx_lock(&u->mutex);
837141398Sphk		u->busy = 0;
838141398Sphk		mtx_unlock(&u->mutex);
839141398Sphk		return (error);
840141398Sphk	}
841141398Sphk
842141398Sphk	ib = malloc(sizeof *ib, M_GPIB, M_WAITOK | M_ZERO);
843141398Sphk	LIST_INIT(&ib->handles);
844141398Sphk	ib->unrhdr = new_unrhdr(0, INT_MAX);
845141398Sphk	dev->si_drv2 = ib;
846141398Sphk	ib->upd7210 = u;
847141398Sphk	u->ibfoo = ib;
848141398Sphk	u->irq = gpib_ib_irq;
849141398Sphk
850141398Sphk	write_reg(u, AUXMR, AUXMR_CRST);
851141398Sphk	DELAY(10000);
852141398Sphk	DELAY(1000);
853141398Sphk	write_reg(u, IMR1, 0x00);
854141398Sphk	write_reg(u, IMR2, 0x00);
855141398Sphk	write_reg(u, SPMR, 0x00);
856141398Sphk	write_reg(u, ADR, 0x00);
857141398Sphk	write_reg(u, ADR, ADR_ARS | ADR_DL | ADR_DT);
858141398Sphk	write_reg(u, ADMR, ADMR_ADM0 | ADMR_TRM0 | ADMR_TRM1);
859141398Sphk	write_reg(u, EOSR, 0x00);
860141398Sphk	write_reg(u, AUXMR, C_ICR | 8);
861141398Sphk	write_reg(u, AUXMR, C_PPR | PPR_U);
862141398Sphk	write_reg(u, AUXMR, C_AUXA);
863141398Sphk	write_reg(u, AUXMR, C_AUXB + 3);
864141398Sphk	write_reg(u, AUXMR, C_AUXE + 0);
865141398Sphk	write_reg(u, AUXMR, AUXMR_PON);
866141398Sphk	write_reg(u, AUXMR, AUXMR_CIFC);
867141398Sphk	DELAY(100);
868141398Sphk	write_reg(u, AUXMR, AUXMR_SIFC);
869141398Sphk	write_reg(u, AUXMR, AUXMR_SREN);
870141398Sphk	return (0);
871141398Sphk}
872141398Sphk
873141398Sphkstatic int
874141398Sphkgpib_ib_close(struct cdev *dev, int oflags, int devtype, struct thread *td)
875141398Sphk{
876141398Sphk	struct upd7210 *u;
877141398Sphk	struct ibfoo *ib;
878141398Sphk
879141398Sphk	u = dev->si_drv1;
880141398Sphk	ib = dev->si_drv2;
881141398Sphk	/* XXX: assert pointer consistency */
882141398Sphk
883141398Sphk	u->ibfoo = NULL;
884141398Sphk	/* XXX: free handles */
885141398Sphk	dev->si_drv2 = NULL;
886141398Sphk	free(ib, M_GPIB);
887141398Sphk
888141398Sphk	mtx_lock(&Giant);
889141398Sphk	isa_dma_release(u->dmachan);
890141398Sphk	mtx_unlock(&Giant);
891141398Sphk	mtx_lock(&u->mutex);
892141398Sphk	u->busy = 0;
893141398Sphk	write_reg(u, IMR1, 0x00);
894141398Sphk	write_reg(u, IMR2, 0x00);
895141398Sphk	write_reg(u, AUXMR, AUXMR_CRST);
896141398Sphk	DELAY(10000);
897141398Sphk	mtx_unlock(&u->mutex);
898141398Sphk	return (0);
899141398Sphk}
900141398Sphk
901141398Sphkstatic int
902141398Sphkgpib_ib_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
903141398Sphk{
904141398Sphk	struct ibfoo_iocarg *ap;
905141398Sphk	struct ibhandler *ih;
906141398Sphk	struct upd7210 *u;
907141398Sphk	int error;
908141398Sphk
909141398Sphk	u = dev->si_drv1;
910141398Sphk
911141398Sphk	if (cmd != GPIB_IBFOO)
912141398Sphk		return (ENOIOCTL);
913141398Sphk
914141398Sphk	ap = (void *)data;
915141398Sphk	if (ap->__ident < 0 || ap->__ident >= max_ibhandler)
916141398Sphk		return (EINVAL);
917141398Sphk	ih = &ibhandlers[ap->__ident];
918141398Sphk	if (ap->__field != ih->args)
919141398Sphk		return (EINVAL);
920141398Sphk
921141398Sphk	if (ap->__field & __F_TMO) {
922141398Sphk		if (ap->tmo < 0 || ap->tmo >= max_timeouts) {
923141398Sphk			ap->__retval = -1;
924141398Sphk			ap->__iberr = EARG;
925141398Sphk			return (0);
926141398Sphk		}
927141398Sphk	}
928141398Sphk
929141398Sphk	if (ap->__field & __F_EOS) {
930141398Sphk		if (ap->eos & ~(REOS | XEOS | BIN | 0xff)) {
931141398Sphk			ap->__retval = -1;
932141398Sphk			ap->__iberr = EARG;
933141398Sphk			return (0);
934141398Sphk		}
935141398Sphk		if (ap->eos & (REOS | XEOS)) {
936141398Sphk			if ((ap->eos & (BIN | 0x80)) == 0x80) {
937141398Sphk				ap->__retval = -1;
938141398Sphk				ap->__iberr = EARG;
939141398Sphk				return (0);
940141398Sphk			}
941141398Sphk		} else if (ap->eos != 0) {
942141398Sphk			ap->__retval = -1;
943141398Sphk			ap->__iberr = EARG;
944141398Sphk			return (0);
945141398Sphk		}
946141398Sphk	}
947141398Sphk
948141398Sphk	mtx_lock(&u->mutex);
949141398Sphk	while(u->busy != 1) {
950141398Sphk		error = msleep(u->ibfoo, &u->mutex, PZERO | PCATCH,
951141398Sphk		    "gpib_ibioctl", 0);
952141398Sphk		if (error) {
953141398Sphk			mtx_unlock(&u->mutex);
954141398Sphk			return (EINTR);
955141398Sphk		}
956141398Sphk	}
957141398Sphk	u->busy = 2;
958141398Sphk	mtx_unlock(&u->mutex);
959141398Sphk
960141398Sphk#ifdef GPIB_DEBUG
961141398Sphk	if (ih->name != NULL)
962141398Sphk		printf("%s(", ih->name);
963141398Sphk	else
964141398Sphk		printf("ibinvalid(");
965141398Sphk	printf("[0x%x]", ap->__field);
966141398Sphk	if (ap->__field & __F_HANDLE)	printf(" handle=%d", ap->handle);
967141398Sphk	if (ap->__field & __F_EOS)	printf(" eos=%d", ap->eos);
968141398Sphk	if (ap->__field & __F_EOT)	printf(" eot=%d", ap->eot);
969141398Sphk	if (ap->__field & __F_TMO)	printf(" tmo=%d", ap->tmo);
970141398Sphk	if (ap->__field & __F_PAD)	printf(" pad=%d", ap->pad);
971141398Sphk	if (ap->__field & __F_SAD)	printf(" sad=%d", ap->sad);
972141398Sphk	if (ap->__field & __F_BUFFER)	printf(" buffer=%p", ap->buffer);
973141398Sphk	if (ap->__field & __F_CNT)	printf(" cnt=%ld", ap->cnt);
974141398Sphk	/* XXX more ... */
975141398Sphk	printf(")\n");
976141398Sphk#endif
977141398Sphk
978141398Sphk	ap->__iberr = 0;
979141398Sphk	error = EOPNOTSUPP;
980141398Sphk	if (ih->func != NULL)
981141398Sphk		error = ih->func(u, ap);
982141398Sphk	if (error) {
983141398Sphk		ap->__retval = EDVR;
984141398Sphk		ap->__iberr = EDVR;
985141398Sphk		ap->__ibcnt = error;
986141398Sphk	} else if (ap->__iberr) {
987141398Sphk		ap->__retval = -1;
988141398Sphk	}
989141398Sphk#ifdef GPIB_DEBUG
990141398Sphk	printf("%s(...) = %d (error=%d)\n", ih->name, ap->__retval, error);
991141398Sphk#endif
992141398Sphk	mtx_lock(&u->mutex);
993141398Sphk	u->busy = 1;
994141398Sphk	wakeup(u->ibfoo);
995141398Sphk	mtx_unlock(&u->mutex);
996141398Sphk	return (error);
997141398Sphk}
998141398Sphk
999141398Sphkstruct cdevsw gpib_ib_cdevsw = {
1000141398Sphk	.d_version =	D_VERSION,
1001141398Sphk	.d_name =	"gpib_ib",
1002141398Sphk	.d_open	=	gpib_ib_open,
1003141398Sphk	.d_ioctl =	gpib_ib_ioctl,
1004141398Sphk	.d_close =	gpib_ib_close,
1005141398Sphk};
1006141398Sphk
1007141398Sphk/* Housekeeping */
1008141398Sphk
1009141398Sphkvoid
1010141398Sphkupd7210attach(struct upd7210 *u)
1011141398Sphk{
1012141398Sphk	int unit = 0;
1013141398Sphk	struct cdev *dev;
1014141398Sphk
1015141398Sphk	mtx_init(&u->mutex, "gpib", NULL, MTX_DEF);
1016141398Sphk	u->cdev = make_dev(&gpib_l_cdevsw, unit,
1017141398Sphk	    UID_ROOT, GID_WHEEL, 0444,
1018141398Sphk	    "gpib%ul", unit);
1019141398Sphk	u->cdev->si_drv1 = u;
1020141398Sphk
1021141398Sphk	dev = make_dev(&gpib_ib_cdevsw, unit,
1022141398Sphk	    UID_ROOT, GID_WHEEL, 0444,
1023141398Sphk	    "gpib%uib", unit);
1024141398Sphk	dev->si_drv1 = u;
1025141398Sphk	dev_depends(u->cdev, dev);
1026141398Sphk}
1027