1 /* $NetBSD: gpib.c,v 1.18 2009/09/12 18:38:00 tsutsui Exp $ */
4 * Copyright (c) 2003 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: gpib.c,v 1.18 2009/09/12 18:38:00 tsutsui Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
38 #include <sys/device.h>
39 #include <sys/ioctl.h>
40 #include <sys/malloc.h>
43 #include <dev/gpib/gpibvar.h>
45 #include <dev/gpib/gpibio.h> /* XXX */
55 #define DBG_FOLLOW 0x01
58 #define DPRINTF(mask, str) if (gpibdebug & (mask)) printf str
60 #define DPRINTF(mask, str) /* nothing */
63 int gpibmatch(device_t
, cfdata_t
, void *);
64 void gpibattach(device_t
, device_t
, void *);
66 CFATTACH_DECL(gpib
, sizeof(struct gpib_softc
),
67 gpibmatch
, gpibattach
, NULL
, NULL
);
69 static int gpibsubmatch1(device_t
, cfdata_t
,
71 static int gpibsubmatch2(device_t
, cfdata_t
,
73 static int gpibprint(void *, const char *);
75 dev_type_open(gpibopen
);
76 dev_type_close(gpibclose
);
77 dev_type_read(gpibread
);
78 dev_type_write(gpibwrite
);
79 dev_type_ioctl(gpibioctl
);
80 dev_type_poll(gpibpoll
);
82 const struct cdevsw gpib_cdevsw
= {
83 gpibopen
, gpibclose
, gpibread
, gpibwrite
, gpibioctl
,
84 nostop
, notty
, gpibpoll
, nommap
, nokqfilter
, D_OTHER
87 extern struct cfdriver gpib_cd
;
89 #define GPIBUNIT(dev) (minor(dev) & 0x0f)
91 int gpibtimeout
= 100000; /* # of status tests before we give up */
94 gpibmatch(device_t parent
, cfdata_t match
, void *aux
)
101 gpibattach(device_t parent
, device_t self
, void *aux
)
103 struct gpib_softc
*sc
= device_private(self
);
104 cfdata_t cf
= device_cfdata(&sc
->sc_dev
);
105 struct gpibdev_attach_args
*gda
= aux
;
106 struct gpib_attach_args ga
;
109 sc
->sc_ic
= gda
->ga_ic
;
112 * If the configuration file specified a host address, then
113 * use it in favour of registers/switches or the default (30).
115 if (cf
->cf_loc
[GPIBDEVCF_ADDRESS
] != GPIBDEVCF_ADDRESS_DEFAULT
)
116 sc
->sc_myaddr
= cf
->cf_loc
[GPIBDEVCF_ADDRESS
];
117 else if (gda
->ga_address
!= GPIBDEVCF_ADDRESS_DEFAULT
)
118 sc
->sc_myaddr
= gda
->ga_address
;
122 printf(": host address %d\n", sc
->sc_myaddr
);
124 /* record our softc pointer */
127 /* Initialize the slave request queue */
128 TAILQ_INIT(&sc
->sc_queue
);
130 /* attach addressed devices */
131 for (address
=0; address
<GPIB_NDEVS
; address
++) {
132 ga
.ga_ic
= sc
->sc_ic
;
133 ga
.ga_address
= address
;
134 (void) config_search_ia(gpibsubmatch1
, &sc
->sc_dev
, "gpib", &ga
);
137 /* attach the wild-carded devices - probably protocol busses */
138 ga
.ga_ic
= sc
->sc_ic
;
139 (void) config_search_ia(gpibsubmatch2
, &sc
->sc_dev
, "gpib", &ga
);
143 gpibsubmatch1(device_t parent
, cfdata_t cf
, const int *ldesc
, void *aux
)
145 struct gpib_softc
*sc
= (struct gpib_softc
*)parent
;
146 struct gpib_attach_args
*ga
= aux
;
148 if (cf
->cf_loc
[GPIBCF_ADDRESS
] != ga
->ga_address
)
151 if (cf
->cf_loc
[GPIBCF_ADDRESS
] == sc
->sc_myaddr
)
154 if (config_match(parent
, cf
, ga
) > 0) {
155 if (gpib_alloc(sc
, ga
->ga_address
))
157 config_attach(parent
, cf
, ga
, gpibprint
);
164 gpibsubmatch2(device_t parent
, cfdata_t cf
, const int *ldesc
, void *aux
)
166 struct gpib_attach_args
*ga
= aux
;
168 if (cf
->cf_loc
[GPIBCF_ADDRESS
] != GPIBCF_ADDRESS_DEFAULT
)
171 ga
->ga_address
= GPIBCF_ADDRESS_DEFAULT
;
172 if (config_match(parent
, cf
, ga
) > 0) {
173 config_attach(parent
, cf
, ga
, gpibdevprint
);
180 gpibprint(void *aux
, const char *pnp
)
182 struct gpib_attach_args
*ga
= aux
;
184 if (ga
->ga_address
!= GPIBCF_ADDRESS_DEFAULT
)
185 printf(" address %d", ga
->ga_address
);
190 gpibdevprint(void *aux
, const char *pnp
)
194 printf("gpib at %s", pnp
);
199 * Called by hardware driver, pass to device driver.
204 struct gpib_softc
*sc
= v
;
207 DPRINTF(DBG_INTR
, ("gpibintr: sc=%p\n", sc
));
209 hdl
= TAILQ_FIRST(&sc
->sc_queue
);
210 (hdl
->hq_callback
)(hdl
->hq_softc
, GPIBCBF_INTR
);
215 * Create a callback handle.
218 _gpibregister(struct gpib_softc
*sc
, int slave
, gpib_callback_t callback
, void *arg
, gpib_handle_t
*hdl
)
221 *hdl
= malloc(sizeof(struct gpibqueue
), M_DEVBUF
, M_NOWAIT
);
223 DPRINTF(DBG_FAIL
, ("_gpibregister: can't allocate queue\n"));
227 (*hdl
)->hq_slave
= slave
;
228 (*hdl
)->hq_callback
= callback
;
229 (*hdl
)->hq_softc
= arg
;
235 * Request exclusive access to the GPIB bus.
238 _gpibrequest(struct gpib_softc
*sc
, gpib_handle_t hdl
)
241 DPRINTF(DBG_FOLLOW
, ("_gpibrequest: sc=%p hdl=%p\n", sc
, hdl
));
243 TAILQ_INSERT_TAIL(&sc
->sc_queue
, hdl
, hq_list
);
244 if (TAILQ_FIRST(&sc
->sc_queue
) == hdl
)
251 * Release exclusive access to the GPIB bus.
254 _gpibrelease(struct gpib_softc
*sc
, gpib_handle_t hdl
)
257 DPRINTF(DBG_FOLLOW
, ("_gpibrelease: sc=%p hdl=%p\n", sc
, hdl
));
259 TAILQ_REMOVE(&sc
->sc_queue
, hdl
, hq_list
);
260 if ((hdl
= TAILQ_FIRST(&sc
->sc_queue
)) != NULL
)
261 (*hdl
->hq_callback
)(hdl
->hq_softc
, GPIBCBF_START
);
269 _gpibawait(struct gpib_softc
*sc
)
273 DPRINTF(DBG_FOLLOW
, ("_gpibawait: sc=%p\n", sc
));
275 slave
= TAILQ_FIRST(&sc
->sc_queue
)->hq_slave
;
276 (*sc
->sc_ic
->ppwatch
)(sc
->sc_ic
->cookie
, slave
);
280 * Synchronous (spin) wait.
283 _gpibswait(struct gpib_softc
*sc
, int slave
)
285 int timo
= gpibtimeout
;
286 int (*pptest
)(void *, int);
288 DPRINTF(DBG_FOLLOW
, ("_gpibswait: sc=%p\n", sc
));
290 pptest
= sc
->sc_ic
->pptest
;
291 while ((*pptest
)(sc
->sc_ic
->cookie
, slave
) == 0) {
293 aprint_error_dev(&sc
->sc_dev
, "swait timeout\n");
301 * Resource accounting: check if the address has already been
302 * claimed and allocated.
305 gpib_isalloc(struct gpib_softc
*sc
, u_int8_t address
)
308 DPRINTF(DBG_FOLLOW
, ("gpib_isalloc: sc=%p address=%d\n", sc
, address
));
311 if (address
>= GPIB_NDEVS
)
312 panic("gpib_isalloc: device address out of range");
315 return ((sc
->sc_rmap
& (1 << address
)) != 0);
319 * Resource accounting: allocate the address.
322 gpib_alloc(struct gpib_softc
*sc
, u_int8_t address
)
325 DPRINTF(DBG_FOLLOW
, ("gpib_alloc: sc=%p address=%d\n", sc
, address
));
328 if (address
>= GPIB_NDEVS
)
329 panic("gpib_alloc: device address out of range");
332 if (!gpib_isalloc(sc
, address
)) {
333 sc
->sc_rmap
|= (1 << address
);
340 * Resource accounting: deallocate the address.
343 gpib_dealloc(struct gpib_softc
*sc
, u_int8_t address
)
346 DPRINTF(DBG_FOLLOW
, ("gpib_free: sc=%p address=%d\n", sc
, address
));
349 if (address
>= GPIB_NDEVS
)
350 panic("gpib_free: device address out of range");
352 if (!gpib_isalloc(sc
, address
))
353 panic("gpib_free: not allocated");
356 sc
->sc_rmap
&= ~(1 << address
);
360 _gpibsend(struct gpib_softc
*sc
, int slave
, int sec
, void *ptr
, int origcnt
)
368 ("_gpibsend: sc=%p slave %d sec=%d ptr=%p cnt=%d\n",
369 sc
, slave
, sec
, ptr
, origcnt
));
372 * For compatibility, call the hardware driver directly.
374 if (sc
->sc_ic
->send
!= NULL
) {
375 rv
= (*sc
->sc_ic
->send
)(sc
->sc_ic
->cookie
,
376 slave
, sec
, ptr
, origcnt
);
380 if ((*sc
->sc_ic
->tc
)(sc
->sc_ic
->cookie
, 0))
382 cmds
[i
++] = GPIBCMD_UNL
;
383 cmds
[i
++] = GPIBCMD_TAG
| sc
->sc_myaddr
;
384 cmds
[i
++] = GPIBCMD_LAG
| slave
;
385 if (sec
>= 0 || sec
== -2) {
386 if (sec
== -2) /* selected device clear KLUDGE */
387 cmds
[i
++] = GPIBCMD_SDC
;
389 cmds
[i
++] = GPIBCMD_SCG
| sec
;
391 if ((*sc
->sc_ic
->sendcmds
)(sc
->sc_ic
->cookie
, cmds
, i
) != i
)
393 if ((*sc
->sc_ic
->gts
)(sc
->sc_ic
->cookie
))
396 cnt
= (*sc
->sc_ic
->senddata
)(sc
->sc_ic
->cookie
, ptr
, origcnt
);
399 if ((*sc
->sc_ic
->tc
)(sc
->sc_ic
->cookie
, 0))
405 (*sc
->sc_ic
->ifc
)(sc
->sc_ic
->cookie
);
407 ("%s: _gpibsend failed: slave %d, sec %x, sent %d of %d bytes\n",
408 device_xname(&sc
->sc_dev
), slave
, sec
, cnt
, origcnt
));
413 _gpibrecv(struct gpib_softc
*sc
, int slave
, int sec
, void *ptr
, int origcnt
)
421 ("_gpibrecv: sc=%p slave=%d sec=%d buf=%p cnt=%d\n",
422 sc
, slave
, sec
, ptr
, origcnt
));
425 * For compatibility, call the hardware driver directly.
427 if (sc
->sc_ic
->recv
!= NULL
) {
428 rv
= (*sc
->sc_ic
->recv
)(sc
->sc_ic
->cookie
,
429 slave
, sec
, ptr
, origcnt
);
434 * slave < 0 implies continuation of a previous receive
435 * that probably timed out.
438 if ((*sc
->sc_ic
->tc
)(sc
->sc_ic
->cookie
, 0))
440 cmds
[i
++] = GPIBCMD_UNL
;
441 cmds
[i
++] = GPIBCMD_LAG
| sc
->sc_myaddr
;
442 cmds
[i
++] = GPIBCMD_TAG
| slave
;
444 cmds
[i
++] = GPIBCMD_SCG
| sec
;
445 if ((*sc
->sc_ic
->sendcmds
)(sc
->sc_ic
->cookie
, cmds
, i
) != i
)
447 if ((*sc
->sc_ic
->gts
)(sc
->sc_ic
->cookie
))
451 cnt
= (*sc
->sc_ic
->recvdata
)(sc
->sc_ic
->cookie
, ptr
, origcnt
);
454 if ((sc
->sc_ic
->tc
)(sc
->sc_ic
->cookie
, 0))
456 cmds
[0] = (slave
== GPIB_BROADCAST_ADDR
) ?
457 GPIBCMD_UNA
: GPIBCMD_UNT
;
458 if ((*sc
->sc_ic
->sendcmds
)(sc
->sc_ic
->cookie
, cmds
, 1) != 1)
464 (*sc
->sc_ic
->ifc
)(sc
->sc_ic
->cookie
);
466 ("_gpibrecv: failed, sc=%p slave %d, sec %x, got %d of %d bytes\n",
467 sc
, slave
, sec
, cnt
, origcnt
));
472 * /dev/gpib? interface
476 gpibopen(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
478 struct gpib_softc
*sc
;
480 sc
= device_lookup_private(&gpib_cd
, GPIBUNIT(dev
));
484 DPRINTF(DBG_FOLLOW
, ("gpibopen: sc=%p\n", sc
));
486 if (sc
->sc_flags
& GPIBF_ACTIVE
)
488 sc
->sc_flags
|= GPIBF_ACTIVE
;
494 gpibclose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
496 struct gpib_softc
*sc
;
498 sc
= device_lookup_private(&gpib_cd
, GPIBUNIT(dev
));
502 DPRINTF(DBG_FOLLOW
, ("gpibclose: sc=%p\n", sc
));
504 sc
->sc_flags
&= ~GPIBF_ACTIVE
;
510 gpibread(dev_t dev
, struct uio
*uio
, int flags
)
512 struct gpib_softc
*sc
;
514 sc
= device_lookup_private(&gpib_cd
, GPIBUNIT(dev
));
518 DPRINTF(DBG_FOLLOW
, ("gpibread: sc=%p\n", sc
));
524 gpibwrite(dev_t dev
, struct uio
*uio
, int flags
)
526 struct gpib_softc
*sc
;
528 sc
= device_lookup_private(&gpib_cd
, GPIBUNIT(dev
));
532 DPRINTF(DBG_FOLLOW
, ("gpibwrite: sc=%p\n", sc
));
538 gpibioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
540 struct gpib_softc
*sc
;
542 sc
= device_lookup_private(&gpib_cd
, GPIBUNIT(dev
));
546 DPRINTF(DBG_FOLLOW
, ("gpibioctl(%lu, '%c',%lu): sc=%p\n",
547 IOCPARM_LEN(cmd
), (char)IOCGROUP(cmd
), cmd
& 0xff, sc
));
551 (*(int *)data
) = 0xa5a5a5a5;
559 gpibpoll(dev_t dev
, int events
, struct lwp
*l
)
561 struct gpib_softc
*sc
;
563 sc
= device_lookup_private(&gpib_cd
, GPIBUNIT(dev
));
567 DPRINTF(DBG_FOLLOW
, ("gpibpoll: sc=%p\n", sc
));