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