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