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