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