gpib.c revision 1.11.4.1 1 /* $NetBSD: gpib.c,v 1.11.4.1 2008/05/16 02:23:57 yamt 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.11.4.1 2008/05/16 02:23:57 yamt 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, flags, mode, l)
522 dev_t dev;
523 int flags, mode;
524 struct lwp *l;
525 {
526 struct gpib_softc *sc;
527
528 sc = device_lookup(&gpib_cd, GPIBUNIT(dev));
529 if (sc == NULL)
530 return (ENXIO);
531
532 DPRINTF(DBG_FOLLOW, ("gpibopen: sc=%p\n", sc));
533
534 if (sc->sc_flags & GPIBF_ACTIVE)
535 return (EBUSY);
536 sc->sc_flags |= GPIBF_ACTIVE;
537
538 return (0);
539 }
540
541 int
542 gpibclose(dev, flag, mode, l)
543 dev_t dev;
544 int flag, mode;
545 struct lwp *l;
546 {
547 struct gpib_softc *sc;
548
549 sc = device_lookup(&gpib_cd, GPIBUNIT(dev));
550 if (sc == NULL)
551 return (ENXIO);
552
553 DPRINTF(DBG_FOLLOW, ("gpibclose: sc=%p\n", sc));
554
555 sc->sc_flags &= ~GPIBF_ACTIVE;
556
557 return (0);
558 }
559
560 int
561 gpibread(dev, uio, flags)
562 dev_t dev;
563 struct uio *uio;
564 int flags;
565 {
566 struct gpib_softc *sc;
567
568 sc = device_lookup(&gpib_cd, GPIBUNIT(dev));
569 if (sc == NULL)
570 return (ENXIO);
571
572 DPRINTF(DBG_FOLLOW, ("gpibread: sc=%p\n", sc));
573
574 return (EOPNOTSUPP);
575 }
576
577 int
578 gpibwrite(dev, uio, flags)
579 dev_t dev;
580 struct uio *uio;
581 int flags;
582 {
583 struct gpib_softc *sc;
584
585 sc = device_lookup(&gpib_cd, GPIBUNIT(dev));
586 if (sc == NULL)
587 return (ENXIO);
588
589 DPRINTF(DBG_FOLLOW, ("gpibwrite: sc=%p\n", sc));
590
591 return (EOPNOTSUPP);
592 }
593
594 int
595 gpibioctl(dev, cmd, data, flag, l)
596 dev_t dev;
597 u_long cmd;
598 void *data;
599 int flag;
600 struct lwp *l;
601 {
602 struct gpib_softc *sc;
603
604 sc = device_lookup(&gpib_cd, GPIBUNIT(dev));
605 if (sc == NULL)
606 return (ENXIO);
607
608 DPRINTF(DBG_FOLLOW, ("gpibioctl(%lu, '%c',%lu): sc=%p\n",
609 IOCPARM_LEN(cmd), (char)IOCGROUP(cmd), cmd & 0xff, sc));
610
611 switch (cmd) {
612 case GPIB_INFO:
613 (*(int *)data) = 0xa5a5a5a5;
614 break;
615 }
616
617 return (EINVAL);
618 }
619
620 int
621 gpibpoll(dev, events, l)
622 dev_t dev;
623 int events;
624 struct lwp *l;
625 {
626 struct gpib_softc *sc;
627
628 sc = device_lookup(&gpib_cd, GPIBUNIT(dev));
629 if (sc == NULL)
630 return (ENXIO);
631
632 DPRINTF(DBG_FOLLOW, ("gpibpoll: sc=%p\n", sc));
633
634 return (0);
635 }
636