1 /* $NetBSD: gpib.c,v 1.19 2009/09/12 18:41:05 tsutsui 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.19 2009/09/12 18:41:05 tsutsui 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 #ifndef DEBUG 50 #define DEBUG 51 #endif 52 53 #ifdef DEBUG 54 int gpibdebug = 0xff; 55 #define DBG_FOLLOW 0x01 56 #define DBG_INTR 0x02 57 #define DBG_FAIL 0x04 58 #define DPRINTF(mask, str) if (gpibdebug & (mask)) printf str 59 #else 60 #define DPRINTF(mask, str) /* nothing */ 61 #endif 62 63 int gpibmatch(device_t, cfdata_t, void *); 64 void gpibattach(device_t, device_t, void *); 65 66 CFATTACH_DECL(gpib, sizeof(struct gpib_softc), 67 gpibmatch, gpibattach, NULL, NULL); 68 69 static int gpibsubmatch1(device_t, cfdata_t, 70 const int *, void *); 71 static int gpibsubmatch2(device_t, cfdata_t, 72 const int *, void *); 73 static int gpibprint(void *, const char *); 74 75 dev_type_open(gpibopen); 76 dev_type_close(gpibclose); 77 dev_type_read(gpibread); 78 dev_type_write(gpibwrite); 79 dev_type_ioctl(gpibioctl); 80 dev_type_poll(gpibpoll); 81 82 const struct cdevsw gpib_cdevsw = { 83 gpibopen, gpibclose, gpibread, gpibwrite, gpibioctl, 84 nostop, notty, gpibpoll, nommap, nokqfilter, D_OTHER 85 }; 86 87 extern struct cfdriver gpib_cd; 88 89 #define GPIBUNIT(dev) (minor(dev) & 0x0f) 90 91 int gpibtimeout = 100000; /* # of status tests before we give up */ 92 93 int 94 gpibmatch(device_t parent, cfdata_t match, void *aux) 95 { 96 97 return (1); 98 } 99 100 void 101 gpibattach(device_t parent, device_t self, void *aux) 102 { 103 struct gpib_softc *sc = device_private(self); 104 cfdata_t 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(device_t parent, cfdata_t 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(device_t parent, cfdata_t 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(struct gpib_softc *sc, int slave, gpib_callback_t callback, void *arg, gpib_handle_t *hdl) 219 { 220 221 *hdl = malloc(sizeof(struct gpibqueue), M_DEVBUF, M_NOWAIT); 222 if (*hdl == NULL) { 223 DPRINTF(DBG_FAIL, ("_gpibregister: can't allocate queue\n")); 224 return (1); 225 } 226 227 (*hdl)->hq_slave = slave; 228 (*hdl)->hq_callback = callback; 229 (*hdl)->hq_softc = arg; 230 231 return (0); 232 } 233 234 /* 235 * Request exclusive access to the GPIB bus. 236 */ 237 int 238 _gpibrequest(struct gpib_softc *sc, gpib_handle_t hdl) 239 { 240 241 DPRINTF(DBG_FOLLOW, ("_gpibrequest: sc=%p hdl=%p\n", sc, hdl)); 242 243 TAILQ_INSERT_TAIL(&sc->sc_queue, hdl, hq_list); 244 if (TAILQ_FIRST(&sc->sc_queue) == hdl) 245 return (1); 246 247 return (0); 248 } 249 250 /* 251 * Release exclusive access to the GPIB bus. 252 */ 253 void 254 _gpibrelease(struct gpib_softc *sc, gpib_handle_t hdl) 255 { 256 257 DPRINTF(DBG_FOLLOW, ("_gpibrelease: sc=%p hdl=%p\n", sc, hdl)); 258 259 TAILQ_REMOVE(&sc->sc_queue, hdl, hq_list); 260 if ((hdl = TAILQ_FIRST(&sc->sc_queue)) != NULL) 261 (*hdl->hq_callback)(hdl->hq_softc, GPIBCBF_START); 262 } 263 264 265 /* 266 * Asynchronous wait. 267 */ 268 void 269 _gpibawait(struct gpib_softc *sc) 270 { 271 int slave; 272 273 DPRINTF(DBG_FOLLOW, ("_gpibawait: sc=%p\n", sc)); 274 275 slave = TAILQ_FIRST(&sc->sc_queue)->hq_slave; 276 (*sc->sc_ic->ppwatch)(sc->sc_ic->cookie, slave); 277 } 278 279 /* 280 * Synchronous (spin) wait. 281 */ 282 int 283 _gpibswait(struct gpib_softc *sc, int slave) 284 { 285 int timo = gpibtimeout; 286 int (*pptest)(void *, int); 287 288 DPRINTF(DBG_FOLLOW, ("_gpibswait: sc=%p\n", sc)); 289 290 pptest = sc->sc_ic->pptest; 291 while ((*pptest)(sc->sc_ic->cookie, slave) == 0) { 292 if (--timo == 0) { 293 aprint_error_dev(&sc->sc_dev, "swait timeout\n"); 294 return(-1); 295 } 296 } 297 return (0); 298 } 299 300 /* 301 * Resource accounting: check if the address has already been 302 * claimed and allocated. 303 */ 304 int 305 gpib_isalloc(struct gpib_softc *sc, u_int8_t address) 306 { 307 308 DPRINTF(DBG_FOLLOW, ("gpib_isalloc: sc=%p address=%d\n", sc, address)); 309 310 #ifdef DIAGNOSTIC 311 if (address >= GPIB_NDEVS) 312 panic("gpib_isalloc: device address out of range"); 313 #endif 314 315 return ((sc->sc_rmap & (1 << address)) != 0); 316 } 317 318 /* 319 * Resource accounting: allocate the address. 320 */ 321 int 322 gpib_alloc(struct gpib_softc *sc, u_int8_t address) 323 { 324 325 DPRINTF(DBG_FOLLOW, ("gpib_alloc: sc=%p address=%d\n", sc, address)); 326 327 #ifdef DIAGNOSTIC 328 if (address >= GPIB_NDEVS) 329 panic("gpib_alloc: device address out of range"); 330 #endif 331 332 if (!gpib_isalloc(sc, address)) { 333 sc->sc_rmap |= (1 << address); 334 return (0); 335 } 336 return (1); 337 } 338 339 /* 340 * Resource accounting: deallocate the address. 341 */ 342 void 343 gpib_dealloc(struct gpib_softc *sc, u_int8_t address) 344 { 345 346 DPRINTF(DBG_FOLLOW, ("gpib_free: sc=%p address=%d\n", sc, address)); 347 348 #ifdef DIAGNOSTIC 349 if (address >= GPIB_NDEVS) 350 panic("gpib_free: device address out of range"); 351 352 if (!gpib_isalloc(sc, address)) 353 panic("gpib_free: not allocated"); 354 #endif 355 356 sc->sc_rmap &= ~(1 << address); 357 } 358 359 int 360 _gpibsend(struct gpib_softc *sc, int slave, int sec, void *ptr, int origcnt) 361 { 362 int rv; 363 int cnt = 0; 364 u_int8_t cmds[4]; 365 int i = 0; 366 367 DPRINTF(DBG_FOLLOW, 368 ("_gpibsend: sc=%p slave %d sec=%d ptr=%p cnt=%d\n", 369 sc, slave, sec, ptr, origcnt)); 370 371 /* 372 * For compatibility, call the hardware driver directly. 373 */ 374 if (sc->sc_ic->send != NULL) { 375 rv = (*sc->sc_ic->send)(sc->sc_ic->cookie, 376 slave, sec, ptr, origcnt); 377 return (rv); 378 } 379 380 if ((*sc->sc_ic->tc)(sc->sc_ic->cookie, 0)) 381 goto senderror; 382 cmds[i++] = GPIBCMD_UNL; 383 cmds[i++] = GPIBCMD_TAG | sc->sc_myaddr; 384 cmds[i++] = GPIBCMD_LAG | slave; 385 if (sec >= 0 || sec == -2) { 386 if (sec == -2) /* selected device clear KLUDGE */ 387 cmds[i++] = GPIBCMD_SDC; 388 else 389 cmds[i++] = GPIBCMD_SCG | sec; 390 } 391 if ((*sc->sc_ic->sendcmds)(sc->sc_ic->cookie, cmds, i) != i) 392 goto senderror; 393 if ((*sc->sc_ic->gts)(sc->sc_ic->cookie)) 394 goto senderror; 395 if (origcnt) { 396 cnt = (*sc->sc_ic->senddata)(sc->sc_ic->cookie, ptr, origcnt); 397 if (cnt != origcnt) 398 goto senderror; 399 if ((*sc->sc_ic->tc)(sc->sc_ic->cookie, 0)) 400 goto senderror; 401 } 402 return (origcnt); 403 404 senderror: 405 (*sc->sc_ic->ifc)(sc->sc_ic->cookie); 406 DPRINTF(DBG_FAIL, 407 ("%s: _gpibsend failed: slave %d, sec %x, sent %d of %d bytes\n", 408 device_xname(&sc->sc_dev), slave, sec, cnt, origcnt)); 409 return (cnt); 410 } 411 412 int 413 _gpibrecv(struct gpib_softc *sc, int slave, int sec, void *ptr, int origcnt) 414 { 415 int rv; 416 u_int8_t cmds[4]; 417 int cnt = 0; 418 int i = 0; 419 420 DPRINTF(DBG_FOLLOW, 421 ("_gpibrecv: sc=%p slave=%d sec=%d buf=%p cnt=%d\n", 422 sc, slave, sec, ptr, origcnt)); 423 424 /* 425 * For compatibility, call the hardware driver directly. 426 */ 427 if (sc->sc_ic->recv != NULL) { 428 rv = (*sc->sc_ic->recv)(sc->sc_ic->cookie, 429 slave, sec, ptr, origcnt); 430 return (rv); 431 } 432 433 /* 434 * slave < 0 implies continuation of a previous receive 435 * that probably timed out. 436 */ 437 if (slave >= 0) { 438 if ((*sc->sc_ic->tc)(sc->sc_ic->cookie, 0)) 439 goto recverror; 440 cmds[i++] = GPIBCMD_UNL; 441 cmds[i++] = GPIBCMD_LAG | sc->sc_myaddr; 442 cmds[i++] = GPIBCMD_TAG | slave; 443 if (sec >= 0) 444 cmds[i++] = GPIBCMD_SCG | sec; 445 if ((*sc->sc_ic->sendcmds)(sc->sc_ic->cookie, cmds, i) != i) 446 goto recverror; 447 if ((*sc->sc_ic->gts)(sc->sc_ic->cookie)) 448 goto recverror; 449 } 450 if (origcnt) { 451 cnt = (*sc->sc_ic->recvdata)(sc->sc_ic->cookie, ptr, origcnt); 452 if (cnt != origcnt) 453 goto recverror; 454 if ((sc->sc_ic->tc)(sc->sc_ic->cookie, 0)) 455 goto recverror; 456 cmds[0] = (slave == GPIB_BROADCAST_ADDR) ? 457 GPIBCMD_UNA : GPIBCMD_UNT; 458 if ((*sc->sc_ic->sendcmds)(sc->sc_ic->cookie, cmds, 1) != 1) 459 goto recverror; 460 } 461 return (origcnt); 462 463 recverror: 464 (*sc->sc_ic->ifc)(sc->sc_ic->cookie); 465 DPRINTF(DBG_FAIL, 466 ("_gpibrecv: failed, sc=%p slave %d, sec %x, got %d of %d bytes\n", 467 sc, slave, sec, cnt, origcnt)); 468 return (cnt); 469 } 470 471 /* 472 * /dev/gpib? interface 473 */ 474 475 int 476 gpibopen(dev_t dev, int flags, int mode, struct lwp *l) 477 { 478 struct gpib_softc *sc; 479 480 sc = device_lookup_private(&gpib_cd, GPIBUNIT(dev)); 481 if (sc == NULL) 482 return (ENXIO); 483 484 DPRINTF(DBG_FOLLOW, ("gpibopen: sc=%p\n", sc)); 485 486 if (sc->sc_flags & GPIBF_ACTIVE) 487 return (EBUSY); 488 sc->sc_flags |= GPIBF_ACTIVE; 489 490 return (0); 491 } 492 493 int 494 gpibclose(dev_t dev, int flag, int mode, struct lwp *l) 495 { 496 struct gpib_softc *sc; 497 498 sc = device_lookup_private(&gpib_cd, GPIBUNIT(dev)); 499 if (sc == NULL) 500 return (ENXIO); 501 502 DPRINTF(DBG_FOLLOW, ("gpibclose: sc=%p\n", sc)); 503 504 sc->sc_flags &= ~GPIBF_ACTIVE; 505 506 return (0); 507 } 508 509 int 510 gpibread(dev_t dev, struct uio *uio, int flags) 511 { 512 struct gpib_softc *sc; 513 514 sc = device_lookup_private(&gpib_cd, GPIBUNIT(dev)); 515 if (sc == NULL) 516 return (ENXIO); 517 518 DPRINTF(DBG_FOLLOW, ("gpibread: sc=%p\n", sc)); 519 520 return (EOPNOTSUPP); 521 } 522 523 int 524 gpibwrite(dev_t dev, struct uio *uio, int flags) 525 { 526 struct gpib_softc *sc; 527 528 sc = device_lookup_private(&gpib_cd, GPIBUNIT(dev)); 529 if (sc == NULL) 530 return (ENXIO); 531 532 DPRINTF(DBG_FOLLOW, ("gpibwrite: sc=%p\n", sc)); 533 534 return (EOPNOTSUPP); 535 } 536 537 int 538 gpibioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 539 { 540 struct gpib_softc *sc; 541 542 sc = device_lookup_private(&gpib_cd, GPIBUNIT(dev)); 543 if (sc == NULL) 544 return (ENXIO); 545 546 DPRINTF(DBG_FOLLOW, ("gpibioctl(%lu, '%c',%lu): sc=%p\n", 547 IOCPARM_LEN(cmd), (char)IOCGROUP(cmd), cmd & 0xff, sc)); 548 549 switch (cmd) { 550 case GPIB_INFO: 551 (*(int *)data) = 0xa5a5a5a5; 552 break; 553 } 554 555 return (EINVAL); 556 } 557 558 int 559 gpibpoll(dev_t dev, int events, struct lwp *l) 560 { 561 struct gpib_softc *sc; 562 563 sc = device_lookup_private(&gpib_cd, GPIBUNIT(dev)); 564 if (sc == NULL) 565 return (ENXIO); 566 567 DPRINTF(DBG_FOLLOW, ("gpibpoll: sc=%p\n", sc)); 568 569 return (0); 570 } 571