Home | History | Annotate | Line # | Download | only in gpib
gpib.c revision 1.1
      1 /*	$NetBSD: gpib.c,v 1.1 2003/06/02 03:45:42 gmcgarry Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2003 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Gregory McGarry.
      9  *
     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.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *	This product includes software developed by the NetBSD
     21  *	Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 #include <sys/cdefs.h>
     40 __KERNEL_RCSID(0, "$NetBSD: gpib.c,v 1.1 2003/06/02 03:45:42 gmcgarry Exp $");
     41 
     42 #include <sys/param.h>
     43 #include <sys/systm.h>
     44 #include <sys/conf.h>
     45 #include <sys/device.h>
     46 #include <sys/ioctl.h>
     47 #include <sys/malloc.h>
     48 #include <sys/proc.h>
     49 
     50 #include <dev/gpib/gpibvar.h>
     51 
     52 #include <dev/gpib/gpibio.h>		/* XXX */
     53 
     54 #include "locators.h"
     55 
     56 #define DEBUG
     57 
     58 #ifdef DEBUG
     59 int gpibdebug = 0xff;
     60 #define DBG_FOLLOW	0x01
     61 #define DBG_INTR	0x02
     62 #define DBG_FAIL	0x04
     63 #define DPRINTF(mask, str)	if (gpibdebug & (mask)) printf str
     64 #else
     65 #define DPRINTF(mask, str)	/* nothing */
     66 #endif
     67 
     68 int	gpibmatch __P((struct device *, struct cfdata *, void *));
     69 void	gpibattach __P((struct device *, struct device *, void *));
     70 
     71 CFATTACH_DECL(gpib, sizeof(struct gpib_softc),
     72 	gpibmatch, gpibattach, NULL, NULL);
     73 
     74 static int	gpibsubmatch1(struct device *, struct cfdata *, void *);
     75 static int	gpibsubmatch2(struct device *, struct cfdata *, void *);
     76 static int	gpibprint(void *, const char *);
     77 
     78 dev_type_open(gpibopen);
     79 dev_type_close(gpibclose);
     80 dev_type_read(gpibread);
     81 dev_type_write(gpibwrite);
     82 dev_type_ioctl(gpibioctl);
     83 dev_type_poll(gpibpoll);
     84 
     85 const struct cdevsw gpib_cdevsw = {
     86 	gpibopen, gpibclose, gpibread, gpibwrite, gpibioctl,
     87 	nostop, notty, gpibpoll, nommap, nokqfilter,
     88 };
     89 
     90 extern struct cfdriver gpib_cd;
     91 
     92 #define GPIBUNIT(dev)		(minor(dev) & 0x0f)
     93 
     94 int gpibtimeout = 100000;	/* # of status tests before we give up */
     95 
     96 int
     97 gpibmatch(parent, match, aux)
     98 	struct device *parent;
     99 	struct cfdata *match;
    100 	void *aux;
    101 {
    102 
    103 	return (1);
    104 }
    105 
    106 void
    107 gpibattach(parent, self, aux)
    108 	struct device *parent, *self;
    109 	void *aux;
    110 {
    111 	struct gpib_softc *sc = (struct gpib_softc *)self;
    112 	struct cfdata *cf = sc->sc_dev.dv_cfdata;
    113 	struct gpibdev_attach_args *gda = aux;
    114 	struct gpib_attach_args ga;
    115 	int address;
    116 
    117 	sc->sc_ic = gda->ga_ic;
    118 
    119 	/*
    120 	 * If the configuration file specified a host address, then
    121 	 * use it in favour of registers/switches or the default (30).
    122 	 */
    123 	if (cf->cf_loc[GPIBDEVCF_ADDRESS] != GPIBDEVCF_ADDRESS_DEFAULT)
    124 		sc->sc_myaddr = cf->cf_loc[GPIBDEVCF_ADDRESS];
    125 	else if (gda->ga_address != GPIBDEVCF_ADDRESS_DEFAULT)
    126 		sc->sc_myaddr = gda->ga_address;
    127 	else
    128 		sc->sc_myaddr = 30;
    129 
    130 	printf(": host address %d\n", sc->sc_myaddr);
    131 
    132 	/* record our softc pointer */
    133 	sc->sc_ic->bus = sc;
    134 
    135 	/* Initialize the slave request queue */
    136 	TAILQ_INIT(&sc->sc_queue);
    137 
    138 	/* attach addressed devices */
    139 	for (address=0; address<GPIB_NDEVS; address++) {
    140 		ga.ga_ic = sc->sc_ic;
    141 		ga.ga_address = address;
    142 		(void) config_search(gpibsubmatch1, &sc->sc_dev, &ga);
    143 	}
    144 
    145 	/* attach the wild-carded devices - probably protocol busses */
    146 	ga.ga_ic = sc->sc_ic;
    147 	(void) config_search(gpibsubmatch2,  &sc->sc_dev, &ga);
    148 }
    149 
    150 int
    151 gpibsubmatch1(parent, cf, aux)
    152 	struct device *parent;
    153 	struct cfdata *cf;
    154 	void *aux;
    155 {
    156 	struct gpib_softc *sc = (struct gpib_softc *)parent;
    157 	struct gpib_attach_args *ga = aux;
    158 
    159 	if (cf->cf_loc[GPIBCF_ADDRESS] != ga->ga_address)
    160 		return (0);
    161 
    162 	if (cf->cf_loc[GPIBCF_ADDRESS] == sc->sc_myaddr)
    163 		return (0);
    164 
    165 	if (config_match(parent, cf, ga) > 0) {
    166 		if (gpib_alloc(sc, ga->ga_address))
    167 			return (0);
    168 		config_attach(parent, cf, ga, gpibprint);
    169 		return (0);
    170 	}
    171 	return (0);
    172 }
    173 
    174 int
    175 gpibsubmatch2(parent, cf, aux)
    176 	struct device *parent;
    177 	struct cfdata *cf;
    178 	void *aux;
    179 {
    180 	struct gpib_attach_args *ga = aux;
    181 
    182 	if (cf->cf_loc[GPIBCF_ADDRESS] != GPIBCF_ADDRESS_DEFAULT)
    183 		return (0);
    184 
    185 	ga->ga_address = GPIBCF_ADDRESS_DEFAULT;
    186 	if (config_match(parent, cf, ga) > 0) {
    187 		config_attach(parent, cf, ga, gpibdevprint);
    188 		return (0);
    189 	}
    190 	return (0);
    191 }
    192 
    193 int
    194 gpibprint(aux, pnp)
    195 	void *aux;
    196 	const char *pnp;
    197 {
    198 	struct gpib_attach_args *ga = aux;
    199 
    200 	if (ga->ga_address != GPIBCF_ADDRESS_DEFAULT)
    201 		printf(" address %d", ga->ga_address);
    202 	return (UNCONF);
    203 }
    204 
    205 int
    206 gpibdevprint(aux, pnp)
    207 	void *aux;
    208 	const char *pnp;
    209 {
    210 
    211 	if (pnp != NULL)
    212 		printf("gpib at %s", pnp);
    213 	return (UNCONF);
    214 }
    215 
    216 /*
    217  * Called by hardware driver, pass to device driver.
    218  */
    219 int
    220 gpibintr(v)
    221 	void *v;
    222 {
    223 	struct gpib_softc *sc = v;
    224 	gpib_handle_t hdl;
    225 
    226 	DPRINTF(DBG_INTR, ("gpibintr: sc=%p\n", sc));
    227 
    228 	hdl = TAILQ_FIRST(&sc->sc_queue);
    229 	(hdl->hq_callback)(hdl->hq_softc, GPIBCBF_INTR);
    230 	return (0);
    231 }
    232 
    233 /*
    234  * Create a callback handle.
    235  */
    236 int
    237 _gpibregister(sc, slave, callback, arg, hdl)
    238 	struct gpib_softc *sc;
    239 	int slave;
    240 	gpib_callback_t callback;
    241 	void *arg;
    242 	gpib_handle_t *hdl;
    243 {
    244 
    245 	MALLOC(*hdl, gpib_handle_t, sizeof(struct gpibqueue),
    246 	    M_DEVBUF, M_NOWAIT);
    247 	if (*hdl == NULL) {
    248 		DPRINTF(DBG_FAIL, ("_gpibregister: can't allocate queue\n"));
    249 		return (1);
    250 	}
    251 
    252 	(*hdl)->hq_slave = slave;
    253 	(*hdl)->hq_callback = callback;
    254 	(*hdl)->hq_softc = arg;
    255 
    256 	return (0);
    257 }
    258 
    259 /*
    260  * Request exclusive access to the GPIB bus.
    261  */
    262 int
    263 _gpibrequest(sc, hdl)
    264 	struct gpib_softc *sc;
    265 	gpib_handle_t hdl;
    266 {
    267 
    268 	DPRINTF(DBG_FOLLOW, ("_gpibrequest: sc=%p hdl=%p\n", sc, hdl));
    269 
    270 	TAILQ_INSERT_TAIL(&sc->sc_queue, hdl, hq_list);
    271 	if (TAILQ_FIRST(&sc->sc_queue) == hdl)
    272 		return (1);
    273 
    274 	return (0);
    275 }
    276 
    277 /*
    278  * Release exclusive access to the GPIB bus.
    279  */
    280 void
    281 _gpibrelease(sc, hdl)
    282 	struct gpib_softc *sc;
    283 	gpib_handle_t hdl;
    284 {
    285 
    286 	DPRINTF(DBG_FOLLOW, ("_gpibrelease: sc=%p hdl=%p\n", sc, hdl));
    287 
    288 	TAILQ_REMOVE(&sc->sc_queue, hdl, hq_list);
    289 	if ((hdl = TAILQ_FIRST(&sc->sc_queue)) != NULL)
    290 		(*hdl->hq_callback)(hdl->hq_softc, GPIBCBF_START);
    291 }
    292 
    293 
    294 /*
    295  * Asynchronous wait.
    296  */
    297 void
    298 _gpibawait(sc)
    299 	struct gpib_softc *sc;
    300 {
    301 	int slave;
    302 
    303 	DPRINTF(DBG_FOLLOW, ("_gpibawait: sc=%p\n", sc));
    304 
    305 	slave = TAILQ_FIRST(&sc->sc_queue)->hq_slave;
    306 	(*sc->sc_ic->ppwatch)(sc->sc_ic->cookie, slave);
    307 }
    308 
    309 /*
    310  * Synchronous (spin) wait.
    311  */
    312 int
    313 _gpibswait(sc, slave)
    314 	struct gpib_softc *sc;
    315 	int slave;
    316 {
    317 	int timo = gpibtimeout;
    318 	int (*pptest)(void *, int);
    319 
    320 	DPRINTF(DBG_FOLLOW, ("_gpibswait: sc=%p\n", sc));
    321 
    322 	pptest = sc->sc_ic->pptest;
    323 	while ((*pptest)(sc->sc_ic->cookie, slave) == 0) {
    324 		if (--timo == 0) {
    325 			printf("%s: swait timeout\n", sc->sc_dev.dv_xname);
    326 			return(-1);
    327 		}
    328 	}
    329 	return (0);
    330 }
    331 
    332 /*
    333  * Resource accounting: check if the address has already been
    334  * claimed and allocated.
    335  */
    336 int
    337 gpib_isalloc(sc, address)
    338 	struct gpib_softc *sc;
    339 	u_int8_t address;
    340 {
    341 
    342 	DPRINTF(DBG_FOLLOW, ("gpib_isalloc: sc=%p address=%d\n", sc, address));
    343 
    344 #ifdef DIAGNOSTIC
    345 	if (address >= GPIB_NDEVS)
    346 		panic("gpib_isalloc: device address out of range");
    347 #endif
    348 
    349 	return ((sc->sc_rmap & (1 << address)) != 0);
    350 }
    351 
    352 /*
    353  * Resource accounting: allocate the address.
    354  */
    355 int
    356 gpib_alloc(sc, address)
    357 	struct gpib_softc *sc;
    358 	u_int8_t address;
    359 {
    360 
    361 	DPRINTF(DBG_FOLLOW, ("gpib_alloc: sc=%p address=%d\n", sc, address));
    362 
    363 #ifdef DIAGNOSTIC
    364 	if (address >= GPIB_NDEVS)
    365 		panic("gpib_alloc: device address out of range");
    366 #endif
    367 
    368 	if (!gpib_isalloc(sc, address)) {
    369 		sc->sc_rmap |= (1 << address);
    370 		return (0);
    371 	}
    372 	return (1);
    373 }
    374 
    375 /*
    376  * Resource accounting: deallocate the address.
    377  */
    378 void
    379 gpib_dealloc(sc, address)
    380 	struct gpib_softc *sc;
    381 	u_int8_t address;
    382 {
    383 
    384 	DPRINTF(DBG_FOLLOW, ("gpib_free: sc=%p address=%d\n", sc, address));
    385 
    386 #ifdef DIAGNOSTIC
    387 	if (address >= GPIB_NDEVS)
    388 		panic("gpib_free: device address out of range");
    389 
    390 	if (!gpib_isalloc(sc, address))
    391 		panic("gpib_free: not allocated");
    392 #endif
    393 
    394 	sc->sc_rmap &= ~(1 << address);
    395 }
    396 
    397 int
    398 _gpibsend(sc, slave, sec, ptr, origcnt)
    399 	struct gpib_softc *sc;
    400 	int slave;
    401 	int sec;
    402 	void *ptr;
    403 	int origcnt;
    404 {
    405 	int rv;
    406 	int cnt = 0;
    407 	u_int8_t cmds[4];
    408 	int i = 0;
    409 
    410 	DPRINTF(DBG_FOLLOW,
    411 	    ("_gpibsend: sc=%p slave %d sec=%d ptr=%p cnt=%d\n",
    412 	    sc, slave, sec, ptr, origcnt));
    413 
    414 	/*
    415 	 * For compatibility, call the hardware driver directly.
    416 	 */
    417 	if (sc->sc_ic->send != NULL) {
    418 		rv = (*sc->sc_ic->send)(sc->sc_ic->cookie,
    419 			slave, sec, ptr, origcnt);
    420 		return (rv);
    421 	}
    422 
    423 	if ((*sc->sc_ic->tc)(sc->sc_ic->cookie, 0))
    424 		goto senderror;
    425 	cmds[i++] = GPIBCMD_UNL;
    426 	cmds[i++] = GPIBCMD_TAG | sc->sc_myaddr;
    427 	cmds[i++] = GPIBCMD_LAG | slave;
    428 	if (sec >= 0 || sec == -2) {
    429 		if (sec == -2)		/* selected device clear KLUDGE */
    430 			cmds[i++] = GPIBCMD_SDC;
    431 		else
    432 			cmds[i++] = GPIBCMD_SCG | sec;
    433 	}
    434 	if ((*sc->sc_ic->sendcmds)(sc->sc_ic->cookie, cmds, i) != i)
    435 		goto senderror;
    436 	if ((*sc->sc_ic->gts)(sc->sc_ic->cookie))
    437 		goto senderror;
    438 	if (origcnt) {
    439 		cnt = (*sc->sc_ic->senddata)(sc->sc_ic->cookie, ptr, origcnt);
    440 		if (cnt != origcnt)
    441 			goto senderror;
    442 		if ((*sc->sc_ic->tc)(sc->sc_ic->cookie, 0))
    443 			goto senderror;
    444 	}
    445 	return (origcnt);
    446 
    447 senderror:
    448 	(*sc->sc_ic->ifc)(sc->sc_ic->cookie);
    449 	DPRINTF(DBG_FAIL,
    450 	    ("%s: _gpibsend failed: slave %d, sec %x, sent %d of %d bytes\n",
    451 	    sc->sc_dev.dv_xname, slave, sec, cnt, origcnt));
    452 	return (cnt);
    453 }
    454 
    455 int
    456 _gpibrecv(sc, slave, sec, ptr, origcnt)
    457 	struct gpib_softc *sc;
    458 	int slave;
    459 	int sec;
    460 	void *ptr;
    461 	int origcnt;
    462 {
    463 	int rv;
    464 	u_int8_t cmds[4];
    465 	int cnt = 0;
    466 	int i = 0;
    467 
    468 	DPRINTF(DBG_FOLLOW,
    469 	    ("_gpibrecv: sc=%p slave=%d sec=%d buf=%p cnt=%d\n",
    470 	    sc, slave, sec, ptr, origcnt));
    471 
    472 	/*
    473 	 * For compatibility, call the hardware driver directly.
    474 	 */
    475 	if (sc->sc_ic->recv != NULL) {
    476 		rv = (*sc->sc_ic->recv)(sc->sc_ic->cookie,
    477 			slave, sec, ptr, origcnt);
    478 		return (rv);
    479 	}
    480 
    481 	/*
    482 	 * slave < 0 implies continuation of a previous receive
    483 	 * that probably timed out.
    484 	 */
    485 	if (slave >= 0) {
    486 		if ((*sc->sc_ic->tc)(sc->sc_ic->cookie, 0))
    487 			goto recverror;
    488 		cmds[i++] = GPIBCMD_UNL;
    489 		cmds[i++] = GPIBCMD_LAG | sc->sc_myaddr;
    490 		cmds[i++] = GPIBCMD_TAG | slave;
    491 		if (sec >= 0)
    492 			cmds[i++] = GPIBCMD_SCG | sec;
    493 		if ((*sc->sc_ic->sendcmds)(sc->sc_ic->cookie, cmds, i) != i)
    494 			goto recverror;
    495 		if ((*sc->sc_ic->gts)(sc->sc_ic->cookie))
    496 			goto recverror;
    497 	}
    498 	if (origcnt) {
    499 		cnt = (*sc->sc_ic->recvdata)(sc->sc_ic->cookie, ptr, origcnt);
    500 		if (cnt != origcnt)
    501 			goto recverror;
    502 		if ((sc->sc_ic->tc)(sc->sc_ic->cookie, 0))
    503 			goto recverror;
    504 		cmds[0] = (slave == GPIB_BROADCAST_ADDR) ?
    505 		    GPIBCMD_UNA : GPIBCMD_UNT;
    506 		if ((*sc->sc_ic->sendcmds)(sc->sc_ic->cookie, cmds, 1) != 1)
    507 			goto recverror;
    508 	}
    509 	return (origcnt);
    510 
    511 recverror:
    512 	(*sc->sc_ic->ifc)(sc->sc_ic->cookie);
    513 	DPRINTF(DBG_FAIL,
    514 	    ("_gpibrecv: failed, sc=%p slave %d, sec %x, got %d of %d bytes\n",
    515 	    sc, slave, sec, cnt, origcnt));
    516 	return (cnt);
    517 }
    518 
    519 /*
    520  * /dev/gpib? interface
    521  */
    522 
    523 int
    524 gpibopen(dev, flags, mode, p)
    525 	dev_t dev;
    526 	int flags, mode;
    527 	struct proc *p;
    528 {
    529 	struct gpib_softc *sc;
    530 
    531 	sc = device_lookup(&gpib_cd, GPIBUNIT(dev));
    532 	if (sc == NULL)
    533 		return (ENXIO);
    534 
    535 	DPRINTF(DBG_FOLLOW, ("gpibopen: sc=%p\n", sc));
    536 
    537 	if (sc->sc_flags & GPIBF_ACTIVE)
    538 		return (EBUSY);
    539 	sc->sc_flags |= GPIBF_ACTIVE;
    540 
    541 	return (0);
    542 }
    543 
    544 int
    545 gpibclose(dev, flag, mode, p)
    546 	dev_t dev;
    547 	int flag, mode;
    548 	struct proc *p;
    549 {
    550 	struct gpib_softc *sc;
    551 
    552 	sc = device_lookup(&gpib_cd, GPIBUNIT(dev));
    553 	if (sc == NULL)
    554 		return (ENXIO);
    555 
    556 	DPRINTF(DBG_FOLLOW, ("gpibclose: sc=%p\n", sc));
    557 
    558 	sc->sc_flags &= ~GPIBF_ACTIVE;
    559 
    560 	return (0);
    561 }
    562 
    563 int
    564 gpibread(dev, uio, flags)
    565 	dev_t dev;
    566 	struct uio *uio;
    567 	int flags;
    568 {
    569 	struct gpib_softc *sc;
    570 
    571 	sc = device_lookup(&gpib_cd, GPIBUNIT(dev));
    572 	if (sc == NULL)
    573 		return (ENXIO);
    574 
    575 	DPRINTF(DBG_FOLLOW, ("gpibread: sc=%p\n", sc));
    576 
    577 	return (EOPNOTSUPP);
    578 }
    579 
    580 int
    581 gpibwrite(dev, uio, flags)
    582 	dev_t dev;
    583 	struct uio *uio;
    584 	int flags;
    585 {
    586 	struct gpib_softc *sc;
    587 
    588 	sc = device_lookup(&gpib_cd, GPIBUNIT(dev));
    589 	if (sc == NULL)
    590 		return (ENXIO);
    591 
    592 	DPRINTF(DBG_FOLLOW, ("gpibwrite: sc=%p\n", sc));
    593 
    594 	return (EOPNOTSUPP);
    595 }
    596 
    597 int
    598 gpibioctl(dev, cmd, data, flag, p)
    599 	dev_t dev;
    600 	u_long cmd;
    601 	caddr_t data;
    602 	int flag;
    603 	struct proc *p;
    604 {
    605 	struct gpib_softc *sc;
    606 
    607 	sc = device_lookup(&gpib_cd, GPIBUNIT(dev));
    608 	if (sc == NULL)
    609 		return (ENXIO);
    610 
    611 	DPRINTF(DBG_FOLLOW, ("gpibioctl(%lu, '%c',%lu): sc=%p\n",
    612 	    IOCPARM_LEN(cmd), (char)IOCGROUP(cmd), cmd & 0xff, sc));
    613 
    614 	switch (cmd) {
    615 	case GPIB_INFO:
    616 		(*(int *)data) = 0xa5a5a5a5;
    617 		break;
    618 	}
    619 
    620 	return (EINVAL);
    621 }
    622 
    623 int
    624 gpibpoll(dev, events, p)
    625 	dev_t dev;
    626 	int events;
    627 	struct proc *p;
    628 {
    629 	struct gpib_softc *sc;
    630 
    631 	sc = device_lookup(&gpib_cd, GPIBUNIT(dev));
    632 	if (sc == NULL)
    633 		return (ENXIO);
    634 
    635 	DPRINTF(DBG_FOLLOW, ("gpibpoll: sc=%p\n", sc));
    636 
    637 	return (0);
    638 }
    639