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