1 /* $NetBSD: gpib.c,v 1.2 2004/09/13 12:55:47 drochner 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.2 2004/09/13 12:55:47 drochner 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 __P((struct device *, struct cfdata *, void *)); 69 void gpibattach __P((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 locdesc_t *, void *); 76 static int gpibsubmatch2(struct device *, struct cfdata *, 77 const locdesc_t *, 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 = (struct gpib_softc *)self; 114 struct cfdata *cf = sc->sc_dev.dv_cfdata; 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 locdesc_t *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 locdesc_t *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