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