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