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