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