Sync usage with man page.
[netbsd-mini2440.git] / sys / dev / gpib / gpib.c
blobd93fbd7033697473904a0c348e3046725c751df7
1 /* $NetBSD: gpib.c,v 1.18 2009/09/12 18:38:00 tsutsui Exp $ */
3 /*-
4 * Copyright (c) 2003 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Gregory McGarry.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
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>
37 #include <sys/conf.h>
38 #include <sys/device.h>
39 #include <sys/ioctl.h>
40 #include <sys/malloc.h>
41 #include <sys/proc.h>
43 #include <dev/gpib/gpibvar.h>
45 #include <dev/gpib/gpibio.h> /* XXX */
47 #include "locators.h"
49 #ifndef DEBUG
50 #define DEBUG
51 #endif
53 #ifdef DEBUG
54 int gpibdebug = 0xff;
55 #define DBG_FOLLOW 0x01
56 #define DBG_INTR 0x02
57 #define DBG_FAIL 0x04
58 #define DPRINTF(mask, str) if (gpibdebug & (mask)) printf str
59 #else
60 #define DPRINTF(mask, str) /* nothing */
61 #endif
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,
70 const int *, void *);
71 static int gpibsubmatch2(device_t, cfdata_t,
72 const int *, void *);
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 */
93 int
94 gpibmatch(device_t parent, cfdata_t match, void *aux)
97 return (1);
100 void
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;
107 int address;
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;
119 else
120 sc->sc_myaddr = 30;
122 printf(": host address %d\n", sc->sc_myaddr);
124 /* record our softc pointer */
125 sc->sc_ic->bus = sc;
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)
149 return (0);
151 if (cf->cf_loc[GPIBCF_ADDRESS] == sc->sc_myaddr)
152 return (0);
154 if (config_match(parent, cf, ga) > 0) {
155 if (gpib_alloc(sc, ga->ga_address))
156 return (0);
157 config_attach(parent, cf, ga, gpibprint);
158 return (0);
160 return (0);
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)
169 return (0);
171 ga->ga_address = GPIBCF_ADDRESS_DEFAULT;
172 if (config_match(parent, cf, ga) > 0) {
173 config_attach(parent, cf, ga, gpibdevprint);
174 return (0);
176 return (0);
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);
186 return (UNCONF);
190 gpibdevprint(void *aux, const char *pnp)
193 if (pnp != NULL)
194 printf("gpib at %s", pnp);
195 return (UNCONF);
199 * Called by hardware driver, pass to device driver.
202 gpibintr(void *v)
204 struct gpib_softc *sc = v;
205 gpib_handle_t hdl;
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);
211 return (0);
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);
222 if (*hdl == NULL) {
223 DPRINTF(DBG_FAIL, ("_gpibregister: can't allocate queue\n"));
224 return (1);
227 (*hdl)->hq_slave = slave;
228 (*hdl)->hq_callback = callback;
229 (*hdl)->hq_softc = arg;
231 return (0);
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)
245 return (1);
247 return (0);
251 * Release exclusive access to the GPIB bus.
253 void
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);
266 * Asynchronous wait.
268 void
269 _gpibawait(struct gpib_softc *sc)
271 int slave;
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) {
292 if (--timo == 0) {
293 aprint_error_dev(&sc->sc_dev, "swait timeout\n");
294 return(-1);
297 return (0);
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));
310 #ifdef DIAGNOSTIC
311 if (address >= GPIB_NDEVS)
312 panic("gpib_isalloc: device address out of range");
313 #endif
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));
327 #ifdef DIAGNOSTIC
328 if (address >= GPIB_NDEVS)
329 panic("gpib_alloc: device address out of range");
330 #endif
332 if (!gpib_isalloc(sc, address)) {
333 sc->sc_rmap |= (1 << address);
334 return (0);
336 return (1);
340 * Resource accounting: deallocate the address.
342 void
343 gpib_dealloc(struct gpib_softc *sc, u_int8_t address)
346 DPRINTF(DBG_FOLLOW, ("gpib_free: sc=%p address=%d\n", sc, address));
348 #ifdef DIAGNOSTIC
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");
354 #endif
356 sc->sc_rmap &= ~(1 << address);
360 _gpibsend(struct gpib_softc *sc, int slave, int sec, void *ptr, int origcnt)
362 int rv;
363 int cnt = 0;
364 u_int8_t cmds[4];
365 int i = 0;
367 DPRINTF(DBG_FOLLOW,
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);
377 return (rv);
380 if ((*sc->sc_ic->tc)(sc->sc_ic->cookie, 0))
381 goto senderror;
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;
388 else
389 cmds[i++] = GPIBCMD_SCG | sec;
391 if ((*sc->sc_ic->sendcmds)(sc->sc_ic->cookie, cmds, i) != i)
392 goto senderror;
393 if ((*sc->sc_ic->gts)(sc->sc_ic->cookie))
394 goto senderror;
395 if (origcnt) {
396 cnt = (*sc->sc_ic->senddata)(sc->sc_ic->cookie, ptr, origcnt);
397 if (cnt != origcnt)
398 goto senderror;
399 if ((*sc->sc_ic->tc)(sc->sc_ic->cookie, 0))
400 goto senderror;
402 return (origcnt);
404 senderror:
405 (*sc->sc_ic->ifc)(sc->sc_ic->cookie);
406 DPRINTF(DBG_FAIL,
407 ("%s: _gpibsend failed: slave %d, sec %x, sent %d of %d bytes\n",
408 device_xname(&sc->sc_dev), slave, sec, cnt, origcnt));
409 return (cnt);
413 _gpibrecv(struct gpib_softc *sc, int slave, int sec, void *ptr, int origcnt)
415 int rv;
416 u_int8_t cmds[4];
417 int cnt = 0;
418 int i = 0;
420 DPRINTF(DBG_FOLLOW,
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);
430 return (rv);
434 * slave < 0 implies continuation of a previous receive
435 * that probably timed out.
437 if (slave >= 0) {
438 if ((*sc->sc_ic->tc)(sc->sc_ic->cookie, 0))
439 goto recverror;
440 cmds[i++] = GPIBCMD_UNL;
441 cmds[i++] = GPIBCMD_LAG | sc->sc_myaddr;
442 cmds[i++] = GPIBCMD_TAG | slave;
443 if (sec >= 0)
444 cmds[i++] = GPIBCMD_SCG | sec;
445 if ((*sc->sc_ic->sendcmds)(sc->sc_ic->cookie, cmds, i) != i)
446 goto recverror;
447 if ((*sc->sc_ic->gts)(sc->sc_ic->cookie))
448 goto recverror;
450 if (origcnt) {
451 cnt = (*sc->sc_ic->recvdata)(sc->sc_ic->cookie, ptr, origcnt);
452 if (cnt != origcnt)
453 goto recverror;
454 if ((sc->sc_ic->tc)(sc->sc_ic->cookie, 0))
455 goto recverror;
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)
459 goto recverror;
461 return (origcnt);
463 recverror:
464 (*sc->sc_ic->ifc)(sc->sc_ic->cookie);
465 DPRINTF(DBG_FAIL,
466 ("_gpibrecv: failed, sc=%p slave %d, sec %x, got %d of %d bytes\n",
467 sc, slave, sec, cnt, origcnt));
468 return (cnt);
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));
481 if (sc == NULL)
482 return (ENXIO);
484 DPRINTF(DBG_FOLLOW, ("gpibopen: sc=%p\n", sc));
486 if (sc->sc_flags & GPIBF_ACTIVE)
487 return (EBUSY);
488 sc->sc_flags |= GPIBF_ACTIVE;
490 return (0);
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));
499 if (sc == NULL)
500 return (ENXIO);
502 DPRINTF(DBG_FOLLOW, ("gpibclose: sc=%p\n", sc));
504 sc->sc_flags &= ~GPIBF_ACTIVE;
506 return (0);
510 gpibread(dev_t dev, struct uio *uio, int flags)
512 struct gpib_softc *sc;
514 sc = device_lookup_private(&gpib_cd, GPIBUNIT(dev));
515 if (sc == NULL)
516 return (ENXIO);
518 DPRINTF(DBG_FOLLOW, ("gpibread: sc=%p\n", sc));
520 return (EOPNOTSUPP);
524 gpibwrite(dev_t dev, struct uio *uio, int flags)
526 struct gpib_softc *sc;
528 sc = device_lookup_private(&gpib_cd, GPIBUNIT(dev));
529 if (sc == NULL)
530 return (ENXIO);
532 DPRINTF(DBG_FOLLOW, ("gpibwrite: sc=%p\n", sc));
534 return (EOPNOTSUPP);
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));
543 if (sc == NULL)
544 return (ENXIO);
546 DPRINTF(DBG_FOLLOW, ("gpibioctl(%lu, '%c',%lu): sc=%p\n",
547 IOCPARM_LEN(cmd), (char)IOCGROUP(cmd), cmd & 0xff, sc));
549 switch (cmd) {
550 case GPIB_INFO:
551 (*(int *)data) = 0xa5a5a5a5;
552 break;
555 return (EINVAL);
559 gpibpoll(dev_t dev, int events, struct lwp *l)
561 struct gpib_softc *sc;
563 sc = device_lookup_private(&gpib_cd, GPIBUNIT(dev));
564 if (sc == NULL)
565 return (ENXIO);
567 DPRINTF(DBG_FOLLOW, ("gpibpoll: sc=%p\n", sc));
569 return (0);