ibfoo.c revision 178250
1/*- 2 * Copyright (c) 2005 Poul-Henning Kamp <phk@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * High-level driver for �PD7210 based GPIB cards. 27 * 28 */ 29 30#include <sys/cdefs.h> 31__FBSDID("$FreeBSD: head/sys/dev/ieee488/ibfoo.c 178250 2008-04-16 16:47:14Z kris $"); 32 33# define IBDEBUG 34# undef IBDEBUG 35 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/conf.h> 39#include <sys/malloc.h> 40#include <sys/kernel.h> 41#include <sys/limits.h> 42#include <sys/module.h> 43#include <sys/bus.h> 44#include <sys/lock.h> 45#include <sys/mutex.h> 46#include <sys/uio.h> 47#include <sys/time.h> 48#include <machine/bus.h> 49#include <machine/resource.h> 50#include <isa/isavar.h> 51 52#include <dev/ieee488/ugpib.h> 53 54#define UPD7210_SW_DRIVER 55#include <dev/ieee488/upd7210.h> 56 57static MALLOC_DEFINE(M_IBFOO, "IBFOO", "IBFOO"); 58 59 60/* ibfoo API */ 61 62#include <dev/ieee488/ibfoo_int.h> 63 64/* XXX: This is really a bitmap */ 65enum h_kind { 66 H_DEV = 1, 67 H_BOARD = 2, 68 H_EITHER = 3 69}; 70 71struct handle { 72 LIST_ENTRY(handle) list; 73 int handle; 74 enum h_kind kind; 75 int pad; 76 int sad; 77 struct timeval timeout; 78 int eot; 79 int eos; 80 int dma; 81}; 82 83struct ibfoo { 84 struct upd7210 *u; 85 LIST_HEAD(,handle) handles; 86 struct unrhdr *unrhdr; 87 struct callout callout; 88 struct handle *h; 89 struct ibarg *ap; 90 91 enum { 92 IDLE, 93 BUSY, 94 PIO_IDATA, 95 PIO_ODATA, 96 PIO_CMD, 97 DMA_IDATA 98 } mode; 99 100 struct timeval deadline; 101 102 struct handle *rdh; /* addressed for read */ 103 struct handle *wrh; /* addressed for write */ 104 105 int doeoi; 106 107 u_char *buf; 108 u_int buflen; 109}; 110 111typedef int ibhandler_t(struct ibfoo *ib); 112 113static struct timeval timeouts[] = { 114 [TNONE] = { 0, 0}, 115 [T10us] = { 0, 10}, 116 [T30us] = { 0, 30}, 117 [T100us] = { 0, 100}, 118 [T300us] = { 0, 300}, 119 [T1ms] = { 0, 1000}, 120 [T3ms] = { 0, 3000}, 121 [T10ms] = { 0, 10000}, 122 [T30ms] = { 0, 30000}, 123 [T100ms] = { 0, 100000}, 124 [T300ms] = { 0, 300000}, 125 [T1s] = { 1, 0}, 126 [T3s] = { 3, 0}, 127 [T10s] = { 10, 0}, 128 [T30s] = { 30, 0}, 129 [T100s] = { 100, 0}, 130 [T300s] = { 300, 0}, 131 [T1000s] = { 1000, 0} 132}; 133 134static const u_int max_timeouts = sizeof timeouts / sizeof timeouts[0]; 135 136static int ibdebug; 137 138static int 139ib_set_error(struct ibarg *ap, int error) 140{ 141 142 if (ap->__iberr == 0) 143 ap->__iberr = error; 144 ap->__ibsta |= ERR; 145 ap->__retval = ap->__ibsta; 146 return (0); 147} 148 149static int 150ib_had_timeout(struct ibarg *ap) 151{ 152 153 ib_set_error(ap, EABO); 154 ap->__ibsta |= TIMO; 155 ap->__retval = ap->__ibsta; 156 return (0); 157} 158 159static int 160ib_set_errno(struct ibarg *ap, int errno) 161{ 162 163 if (ap->__iberr == 0) { 164 ap->__iberr = EDVR; 165 ap->__ibcnt = errno; 166 } 167 ap->__ibsta |= ERR; 168 ap->__retval = ap->__ibsta; 169 return (0); 170} 171 172static int 173gpib_ib_irq(struct upd7210 *u, int intr __unused) 174{ 175 struct ibfoo *ib; 176 177 ib = u->ibfoo; 178 179 mtx_assert(&u->mutex, MA_OWNED); 180 switch (ib->mode) { 181 case PIO_CMD: 182 if (!(u->rreg[ISR2] & IXR2_CO)) 183 return (0); 184 if (ib->buflen == 0) 185 break; 186 upd7210_wr(u, CDOR, *ib->buf); 187 ib->buf++; 188 ib->buflen--; 189 return (1); 190 case PIO_IDATA: 191 if (!(u->rreg[ISR1] & IXR1_DI)) 192 return (0); 193 *ib->buf = upd7210_rd(u, DIR); 194 ib->buf++; 195 ib->buflen--; 196 if (ib->buflen == 0 || (u->rreg[ISR1] & IXR1_ENDRX)) 197 break; 198 return (1); 199 case PIO_ODATA: 200 if (!(u->rreg[ISR1] & IXR1_DO)) 201 return (0); 202 if (ib->buflen == 0) 203 break; 204 if (ib->buflen == 1 && ib->doeoi) 205 upd7210_wr(u, AUXMR, AUXMR_SEOI); 206 upd7210_wr(u, CDOR, *ib->buf); 207 ib->buf++; 208 ib->buflen--; 209 return (1); 210 case DMA_IDATA: 211 if (!(u->rreg[ISR1] & IXR1_ENDRX)) 212 return (0); 213 break; 214 default: 215 return (0); 216 } 217 upd7210_wr(u, IMR1, 0); 218 upd7210_wr(u, IMR2, 0); 219 ib->mode = BUSY; 220 wakeup(&ib->buflen); 221 return (1); 222} 223 224static void 225gpib_ib_timeout(void *arg) 226{ 227 struct upd7210 *u; 228 struct ibfoo *ib; 229 struct timeval tv; 230 231 u = arg; 232 ib = u->ibfoo; 233 mtx_lock(&u->mutex); 234 if (ib->mode == DMA_IDATA && isa_dmatc(u->dmachan)) { 235 KASSERT(u->dmachan >= 0, ("Bogus dmachan = %d", u->dmachan)); 236 upd7210_wr(u, IMR1, 0); 237 upd7210_wr(u, IMR2, 0); 238 ib->mode = BUSY; 239 wakeup(&ib->buflen); 240 } 241 if (ib->mode > BUSY) { 242 upd7210_rd(u, ISR1); 243 upd7210_rd(u, ISR2); 244 gpib_ib_irq(u, 2); 245 } 246 if (ib->mode != IDLE && timevalisset(&ib->deadline)) { 247 getmicrouptime(&tv); 248 if (timevalcmp(&ib->deadline, &tv, <)) { 249 ib_had_timeout(ib->ap); 250 upd7210_wr(u, IMR1, 0); 251 upd7210_wr(u, IMR2, 0); 252 ib->mode = BUSY; 253 wakeup(&ib->buflen); 254 } 255 } 256 if (ib->mode != IDLE) 257 callout_reset(&ib->callout, hz / 5, gpib_ib_timeout, arg); 258 mtx_unlock(&u->mutex); 259} 260 261static void 262gpib_ib_wait_xfer(struct upd7210 *u, struct ibfoo *ib) 263{ 264 int i; 265 266 mtx_assert(&u->mutex, MA_OWNED); 267 while (ib->mode > BUSY) { 268 i = msleep(&ib->buflen, &u->mutex, 269 PZERO | PCATCH, "ibwxfr", 0); 270 if (i == EINTR) { 271 ib_set_errno(ib->ap, i); 272 break; 273 } 274 if (u->rreg[ISR1] & IXR1_ERR) { 275 ib_set_error(ib->ap, EABO); /* XXX ? */ 276 break; 277 } 278 } 279 ib->mode = BUSY; 280 ib->buf = NULL; 281 upd7210_wr(u, IMR1, 0); 282 upd7210_wr(u, IMR2, 0); 283} 284 285static void 286config_eos(struct upd7210 *u, struct handle *h) 287{ 288 int i; 289 290 i = 0; 291 if (h->eos & REOS) { 292 upd7210_wr(u, EOSR, h->eos & 0xff); 293 i |= AUXA_REOS; 294 } 295 if (h->eos & XEOS) { 296 upd7210_wr(u, EOSR, h->eos & 0xff); 297 i |= AUXA_XEOS; 298 } 299 if (h->eos & BIN) 300 i |= AUXA_BIN; 301 upd7210_wr(u, AUXRA, C_AUXA | i); 302} 303 304/* 305 * Look up the handle, and set the deadline if the handle has a timeout. 306 */ 307static int 308gethandle(struct upd7210 *u, struct ibarg *ap, struct handle **hp) 309{ 310 struct ibfoo *ib; 311 struct handle *h; 312 313 KASSERT(ap->__field & __F_HANDLE, ("gethandle without __F_HANDLE")); 314 ib = u->ibfoo; 315 LIST_FOREACH(h, &ib->handles, list) { 316 if (h->handle == ap->handle) { 317 *hp = h; 318 return (0); 319 } 320 } 321 ib_set_error(ap, EARG); 322 return (1); 323} 324 325static int 326pio_cmd(struct upd7210 *u, u_char *cmd, int len) 327{ 328 struct ibfoo *ib; 329 330 ib = u->ibfoo; 331 332 if (ib->rdh != NULL || ib->wrh != NULL) { 333 upd7210_take_ctrl_async(u); 334 ib->rdh = NULL; 335 ib->wrh = NULL; 336 } 337 mtx_lock(&u->mutex); 338 ib->mode = PIO_CMD; 339 ib->buf = cmd; 340 ib->buflen = len; 341 upd7210_wr(u, IMR2, IXR2_CO); 342 343 gpib_ib_irq(u, 1); 344 345 gpib_ib_wait_xfer(u, ib); 346 347 mtx_unlock(&u->mutex); 348 return (len - ib->buflen); 349} 350 351static int 352pio_odata(struct upd7210 *u, u_char *data, int len) 353{ 354 struct ibfoo *ib; 355 356 ib = u->ibfoo; 357 358 if (len == 0) 359 return (0); 360 mtx_lock(&u->mutex); 361 ib->mode = PIO_ODATA; 362 ib->buf = data; 363 ib->buflen = len; 364 upd7210_wr(u, IMR1, IXR1_DO); 365 366 gpib_ib_wait_xfer(u, ib); 367 368 mtx_unlock(&u->mutex); 369 return (len - ib->buflen); 370} 371 372static int 373pio_idata(struct upd7210 *u, u_char *data, int len) 374{ 375 struct ibfoo *ib; 376 377 ib = u->ibfoo; 378 379 mtx_lock(&u->mutex); 380 ib->mode = PIO_IDATA; 381 ib->buf = data; 382 ib->buflen = len; 383 upd7210_wr(u, IMR1, IXR1_DI); 384 385 gpib_ib_wait_xfer(u, ib); 386 387 mtx_unlock(&u->mutex); 388 return (len - ib->buflen); 389} 390 391static int 392dma_idata(struct upd7210 *u, u_char *data, int len) 393{ 394 int j; 395 struct ibfoo *ib; 396 397 KASSERT(u->dmachan >= 0, ("Bogus dmachan %d", u->dmachan)); 398 ib = u->ibfoo; 399 ib->mode = DMA_IDATA; 400 mtx_lock(&Giant); 401 isa_dmastart(ISADMA_READ, data, len, u->dmachan); 402 mtx_unlock(&Giant); 403 mtx_lock(&u->mutex); 404 upd7210_wr(u, IMR1, IXR1_ENDRX); 405 upd7210_wr(u, IMR2, IMR2_DMAI); 406 gpib_ib_wait_xfer(u, ib); 407 mtx_unlock(&u->mutex); 408 mtx_lock(&Giant); 409 j = isa_dmastatus(u->dmachan); 410 isa_dmadone(ISADMA_READ, data, len, u->dmachan); 411 mtx_unlock(&Giant); 412 return (len - j); 413} 414 415static int 416ib_send_msg(struct ibfoo *ib, int msg) 417{ 418 u_char buf[10]; 419 int i, j; 420 421 i = 0; 422 buf[i++] = UNT; 423 buf[i++] = UNL; 424 buf[i++] = LAD | ib->h->pad; 425 if (ib->h->sad) 426 buf[i++] = LAD | TAD | ib->h->sad; 427 buf[i++] = TAD | 0; 428 buf[i++] = msg; 429 j = pio_cmd(ib->u, buf, i); 430 if (i != j) 431 ib_set_error(ib->ap, EABO); /* XXX ? */ 432 return (0); 433} 434 435static int 436ibask(struct ibfoo *ib) 437{ /* XXX */ 438 439 ibdebug = ib->ap->option; 440 return (0); 441} 442 443#define ibbna NULL 444#define ibcac NULL 445 446static int 447ibclr(struct ibfoo *ib) 448{ 449 450 return (ib_send_msg(ib, SDC)); 451} 452 453#define ibcmd NULL 454#define ibcmda NULL 455#define ibconfig NULL 456 457static int 458ibdev(struct ibfoo *ib) 459{ /* TBD */ 460 struct handle *h; 461 462 h = malloc(sizeof *h, M_IBFOO, M_ZERO | M_WAITOK); 463 h->handle = alloc_unr(ib->unrhdr); 464 h->kind = H_DEV; 465 h->pad = ib->ap->pad; 466 h->sad = ib->ap->sad; 467 h->timeout = timeouts[ib->ap->tmo]; 468 h->eot = ib->ap->eot; 469 h->eos = ib->ap->eos; 470 mtx_lock(&ib->u->mutex); 471 LIST_INSERT_HEAD(&ib->handles, h, list); 472 mtx_unlock(&ib->u->mutex); 473 ib->ap->__retval = h->handle; 474 return (0); 475} 476 477#define ibdiag NULL 478 479static int 480ibdma(struct ibfoo *ib) 481{ 482 483 if (ib->u->dmachan < 0 && ib->ap->v) 484 return (ib_set_error(ib->ap, EARG)); 485 ib->h->dma = ib->ap->v; 486 return (0); 487} 488 489static int 490ibeos(struct ibfoo *ib) 491{ 492 493 ib->ap->__iberr = ib->h->eos; 494 ib->h->eos = ib->ap->eos; 495 if (ib->rdh == ib->h) 496 config_eos(ib->u, ib->h); 497 return (0); 498} 499 500static int 501ibeot(struct ibfoo *ib) 502{ 503 504 ib->h->eot = ib->ap->eot; 505 return (0); 506} 507 508#define ibevent NULL 509#define ibfind NULL 510#define ibgts NULL 511#define ibist NULL 512#define iblines NULL 513#define ibllo NULL 514#define ibln NULL 515 516static int 517ibloc(struct ibfoo *ib) 518{ /* XXX */ 519 520 if (ib->h->kind == H_BOARD) 521 return (EOPNOTSUPP); /* XXX */ 522 return (ib_send_msg(ib, GTL)); 523} 524 525static int 526ibonl(struct ibfoo *ib) 527{ /* XXX */ 528 529 if (ib->ap->v) 530 return (EOPNOTSUPP); /* XXX */ 531 mtx_lock(&ib->u->mutex); 532 LIST_REMOVE(ib->h, list); 533 mtx_unlock(&ib->u->mutex); 534 free(ib->h, M_IBFOO); 535 ib->h = NULL; 536 return (0); 537} 538 539static int 540ibpad(struct ibfoo *ib) 541{ 542 543 ib->h->pad = ib->ap->pad; 544 return (0); 545} 546 547#define ibpct NULL 548#define ibpoke NULL 549#define ibppc NULL 550 551static int 552ibrd(struct ibfoo *ib) 553{ /* TBD */ 554 u_char buf[10], *bp; 555 int i, j, error, bl, bc; 556 u_char *dp; 557 558 if (ib->h->kind == H_BOARD) 559 return (EOPNOTSUPP); /* XXX */ 560 bl = ib->ap->cnt; 561 if (bl > PAGE_SIZE) 562 bl = PAGE_SIZE; 563 bp = malloc(bl, M_IBFOO, M_WAITOK); 564 565 if (ib->rdh != ib->h) { 566 i = 0; 567 buf[i++] = UNT; 568 buf[i++] = UNL; 569 buf[i++] = LAD | 0; 570 buf[i++] = TAD | ib->h->pad; 571 if (ib->h->sad) 572 buf[i++] = ib->h->sad; 573 i = pio_cmd(ib->u, buf, i); 574 config_eos(ib->u, ib->h); 575 ib->rdh = ib->h; 576 ib->wrh = NULL; 577 } 578 upd7210_goto_standby(ib->u); 579 dp = ib->ap->buffer; 580 bc = ib->ap->cnt; 581 error = 0; 582 while (bc > 0 && ib->ap->__iberr == 0) { 583 j = imin(bc, PAGE_SIZE); 584 if (ib->h->dma) 585 i = dma_idata(ib->u, bp, j); 586 else 587 i = pio_idata(ib->u, bp, j); 588 error = copyout(bp, dp , i); 589 if (error) 590 break; 591 ib->ap->__ibcnt += i; 592 if (i != j) 593 break; 594 bc -= i; 595 dp += i; 596 } 597 upd7210_take_ctrl_async(ib->u); 598 free(bp, M_IBFOO); 599 return (error); 600} 601 602#define ibrda NULL 603#define ibrdf NULL 604#define ibrdkey NULL 605#define ibrpp NULL 606#define ibrsc NULL 607#define ibrsp NULL 608#define ibrsv NULL 609 610static int 611ibsad(struct ibfoo *ib) 612{ 613 614 ib->h->sad = ib->ap->sad; 615 return (0); 616} 617 618#define ibsgnl NULL 619 620static int 621ibsic(struct ibfoo *ib) 622{ /* TBD */ 623 624 upd7210_wr(ib->u, AUXMR, AUXMR_SIFC); 625 DELAY(100); 626 upd7210_wr(ib->u, AUXMR, AUXMR_CIFC); 627 return (0); 628} 629 630#define ibsre NULL 631#define ibsrq NULL 632#define ibstop NULL 633 634static int 635ibtmo(struct ibfoo *ib) 636{ 637 638 ib->h->timeout = timeouts[ib->ap->tmo]; 639 return (0); 640} 641 642#define ibtrap NULL 643 644static int 645ibtrg(struct ibfoo *ib) 646{ 647 648 return (ib_send_msg(ib, GET)); 649} 650 651#define ibwait NULL 652 653static int 654ibwrt(struct ibfoo *ib) 655{ /* XXX */ 656 u_char buf[10], *bp; 657 int i; 658 659 if (ib->h->kind == H_BOARD) 660 return (EOPNOTSUPP); 661 bp = malloc(ib->ap->cnt, M_IBFOO, M_WAITOK); 662 /* XXX: bigger than PAGE_SIZE handling */ 663 i = copyin(ib->ap->buffer, bp, ib->ap->cnt); 664 if (i) { 665 free(bp, M_IBFOO); 666 return (i); 667 } 668 if (ib->wrh != ib->h) { 669 i = 0; 670 buf[i++] = UNT; 671 buf[i++] = UNL; 672 buf[i++] = LAD | ib->h->pad; 673 if (ib->h->sad) 674 buf[i++] = LAD | TAD | ib->h->sad; 675 buf[i++] = TAD | 0; 676 i = pio_cmd(ib->u, buf, i); 677 ib->rdh = NULL; 678 ib->wrh = ib->h; 679 config_eos(ib->u, ib->h); 680 } 681 upd7210_goto_standby(ib->u); 682 ib->doeoi = ib->h->eot; 683 i = pio_odata(ib->u, bp, ib->ap->cnt); 684 upd7210_take_ctrl_async(ib->u); 685 ib->ap->__ibcnt = i; 686 free(bp, M_IBFOO); 687 return (0); 688} 689 690#define ibwrta NULL 691#define ibwrtf NULL 692#define ibwrtkey NULL 693#define ibxtrc NULL 694 695static struct ibhandler { 696 const char *name; 697 enum h_kind kind; 698 ibhandler_t *func; 699 u_int args; 700} ibhandlers[] = { 701 [__ID_IBASK] = { "ibask", H_EITHER, ibask, __F_HANDLE | __F_OPTION | __F_RETVAL }, 702 [__ID_IBBNA] = { "ibbna", H_DEV, ibbna, __F_HANDLE | __F_BDNAME }, 703 [__ID_IBCAC] = { "ibcac", H_BOARD, ibcac, __F_HANDLE | __F_V }, 704 [__ID_IBCLR] = { "ibclr", H_DEV, ibclr, __F_HANDLE }, 705 [__ID_IBCMD] = { "ibcmd", H_BOARD, ibcmd, __F_HANDLE | __F_BUFFER | __F_CNT }, 706 [__ID_IBCMDA] = { "ibcmda", H_BOARD, ibcmda, __F_HANDLE | __F_BUFFER | __F_CNT }, 707 [__ID_IBCONFIG] = { "ibconfig", H_EITHER, ibconfig, __F_HANDLE | __F_OPTION | __F_VALUE }, 708 [__ID_IBDEV] = { "ibdev", 0, ibdev, __F_BOARDID | __F_PAD | __F_SAD | __F_TMO | __F_EOT | __F_EOS }, 709 [__ID_IBDIAG] = { "ibdiag", H_EITHER, ibdiag, __F_HANDLE | __F_BUFFER | __F_CNT }, 710 [__ID_IBDMA] = { "ibdma", H_EITHER, ibdma, __F_HANDLE | __F_V }, 711 [__ID_IBEOS] = { "ibeos", H_EITHER, ibeos, __F_HANDLE | __F_EOS }, 712 [__ID_IBEOT] = { "ibeot", H_EITHER, ibeot, __F_HANDLE | __F_EOT }, 713 [__ID_IBEVENT] = { "ibevent", H_BOARD, ibevent, __F_HANDLE | __F_EVENT }, 714 [__ID_IBFIND] = { "ibfind", 0, ibfind, __F_BDNAME }, 715 [__ID_IBGTS] = { "ibgts", H_BOARD, ibgts, __F_HANDLE | __F_V }, 716 [__ID_IBIST] = { "ibist", H_BOARD, ibist, __F_HANDLE | __F_V }, 717 [__ID_IBLINES] = { "iblines", H_BOARD, iblines, __F_HANDLE | __F_LINES }, 718 [__ID_IBLLO] = { "ibllo", H_EITHER, ibllo, __F_HANDLE }, 719 [__ID_IBLN] = { "ibln", H_BOARD, ibln, __F_HANDLE | __F_PADVAL | __F_SADVAL | __F_LISTENFLAG }, 720 [__ID_IBLOC] = { "ibloc", H_EITHER, ibloc, __F_HANDLE }, 721 [__ID_IBONL] = { "ibonl", H_EITHER, ibonl, __F_HANDLE | __F_V }, 722 [__ID_IBPAD] = { "ibpad", H_EITHER, ibpad, __F_HANDLE | __F_PAD }, 723 [__ID_IBPCT] = { "ibpct", H_DEV, ibpct, __F_HANDLE }, 724 [__ID_IBPOKE] = { "ibpoke", H_EITHER, ibpoke, __F_HANDLE | __F_OPTION | __F_VALUE }, 725 [__ID_IBPPC] = { "ibppc", H_EITHER, ibppc, __F_HANDLE | __F_V }, 726 [__ID_IBRD] = { "ibrd", H_EITHER, ibrd, __F_HANDLE | __F_BUFFER | __F_CNT }, 727 [__ID_IBRDA] = { "ibrda", H_EITHER, ibrda, __F_HANDLE | __F_BUFFER | __F_CNT }, 728 [__ID_IBRDF] = { "ibrdf", H_EITHER, ibrdf, __F_HANDLE | __F_FLNAME }, 729 [__ID_IBRDKEY] = { "ibrdkey", H_EITHER, ibrdkey, __F_HANDLE | __F_BUFFER | __F_CNT }, 730 [__ID_IBRPP] = { "ibrpp", H_EITHER, ibrpp, __F_HANDLE | __F_PPR }, 731 [__ID_IBRSC] = { "ibrsc", H_BOARD, ibrsc, __F_HANDLE | __F_V }, 732 [__ID_IBRSP] = { "ibrsp", H_DEV, ibrsp, __F_HANDLE | __F_SPR }, 733 [__ID_IBRSV] = { "ibrsv", H_EITHER, ibrsv, __F_HANDLE | __F_V }, 734 [__ID_IBSAD] = { "ibsad", H_EITHER, ibsad, __F_HANDLE | __F_SAD }, 735 [__ID_IBSGNL] = { "ibsgnl", H_EITHER, ibsgnl, __F_HANDLE | __F_V }, 736 [__ID_IBSIC] = { "ibsic", H_BOARD, ibsic, __F_HANDLE }, 737 [__ID_IBSRE] = { "ibsre", H_BOARD, ibsre, __F_HANDLE | __F_V }, 738 [__ID_IBSRQ] = { "ibsrq", H_EITHER, ibsrq, __F_FUNC }, 739 [__ID_IBSTOP] = { "ibstop", H_EITHER, ibstop, __F_HANDLE }, 740 [__ID_IBTMO] = { "ibtmo", H_EITHER, ibtmo, __F_HANDLE | __F_TMO }, 741 [__ID_IBTRAP] = { "ibtrap", H_EITHER, ibtrap, __F_MASK | __F_MODE }, 742 [__ID_IBTRG] = { "ibtrg", H_DEV, ibtrg, __F_HANDLE }, 743 [__ID_IBWAIT] = { "ibwait", H_EITHER, ibwait, __F_HANDLE | __F_MASK }, 744 [__ID_IBWRT] = { "ibwrt", H_EITHER, ibwrt, __F_HANDLE | __F_BUFFER | __F_CNT }, 745 [__ID_IBWRTA] = { "ibwrta", H_EITHER, ibwrta, __F_HANDLE | __F_BUFFER | __F_CNT }, 746 [__ID_IBWRTF] = { "ibwrtf", H_EITHER, ibwrtf, __F_HANDLE | __F_FLNAME }, 747 [__ID_IBWRTKEY] = { "ibwrtkey", H_EITHER, ibwrtkey, __F_HANDLE | __F_BUFFER | __F_CNT }, 748 [__ID_IBXTRC] = { "ibxtrc", H_EITHER, ibxtrc, __F_HANDLE | __F_BUFFER | __F_CNT }, 749}; 750 751static const u_int max_ibhandler = sizeof ibhandlers / sizeof ibhandlers[0]; 752 753static void 754ib_dump_args(struct ibhandler *ih, struct ibarg *ap) 755{ 756 757 if (ih->name != NULL) 758 printf("%s(", ih->name); 759 else 760 printf("ibinvalid("); 761 printf("[0x%x]", ap->__field); 762 if (ap->__field & __F_HANDLE) printf(" handle=%d", ap->handle); 763 if (ap->__field & __F_EOS) printf(" eos=0x%x", ap->eos); 764 if (ap->__field & __F_EOT) printf(" eot=%d", ap->eot); 765 if (ap->__field & __F_TMO) printf(" tmo=%d", ap->tmo); 766 if (ap->__field & __F_PAD) printf(" pad=0x%x", ap->pad); 767 if (ap->__field & __F_SAD) printf(" sad=0x%x", ap->sad); 768 if (ap->__field & __F_BUFFER) printf(" buffer=%p", ap->buffer); 769 if (ap->__field & __F_CNT) printf(" cnt=%ld", ap->cnt); 770 if (ap->__field & __F_V) printf(" v=%d/0x%x", ap->v, ap->v); 771 /* XXX more ... */ 772 printf(")\n"); 773} 774 775static int 776gpib_ib_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 777{ 778 struct upd7210 *u; 779 struct ibfoo *ib; 780 int error = 0; 781 782 u = dev->si_drv1; 783 784 mtx_lock(&u->mutex); 785 if (u->busy) { 786 mtx_unlock(&u->mutex); 787 return (EBUSY); 788 } 789 u->busy = 1; 790 mtx_unlock(&u->mutex); 791 792 if (u->dmachan >= 0) { 793 mtx_lock(&Giant); 794 error = isa_dma_acquire(u->dmachan); 795 if (!error) { 796 error = isa_dma_init(u->dmachan, PAGE_SIZE, M_WAITOK); 797 if (error) 798 isa_dma_release(u->dmachan); 799 } 800 mtx_unlock(&Giant); 801 } 802 803 if (error) { 804 mtx_lock(&u->mutex); 805 u->busy = 0; 806 mtx_unlock(&u->mutex); 807 return (error); 808 } 809 810 ib = malloc(sizeof *ib, M_IBFOO, M_WAITOK | M_ZERO); 811 LIST_INIT(&ib->handles); 812 callout_init(&ib->callout, CALLOUT_MPSAFE); 813 ib->unrhdr = new_unrhdr(0, INT_MAX, NULL); 814 dev->si_drv2 = ib; 815 ib->u = u; 816 u->ibfoo = ib; 817 u->irq = gpib_ib_irq; 818 819 upd7210_wr(u, AUXMR, AUXMR_CRST); 820 DELAY(10000); 821 DELAY(1000); 822 upd7210_wr(u, IMR1, 0x00); 823 upd7210_wr(u, IMR2, 0x00); 824 upd7210_wr(u, SPMR, 0x00); 825 upd7210_wr(u, ADR, 0x00); 826 upd7210_wr(u, ADR, ADR_ARS | ADR_DL | ADR_DT); 827 upd7210_wr(u, ADMR, ADMR_ADM0 | ADMR_TRM0 | ADMR_TRM1); 828 upd7210_wr(u, EOSR, 0x00); 829 upd7210_wr(u, AUXMR, C_ICR | 8); 830 upd7210_wr(u, AUXMR, C_PPR | PPR_U); 831 upd7210_wr(u, AUXMR, C_AUXA); 832 upd7210_wr(u, AUXMR, C_AUXB + 3); 833 upd7210_wr(u, AUXMR, C_AUXE + 0); 834 upd7210_wr(u, AUXMR, AUXMR_PON); 835 upd7210_wr(u, AUXMR, AUXMR_CIFC); 836 DELAY(100); 837 upd7210_wr(u, AUXMR, AUXMR_SIFC); 838 upd7210_wr(u, AUXMR, AUXMR_SREN); 839 return (0); 840} 841 842static int 843gpib_ib_close(struct cdev *dev, int oflags, int devtype, struct thread *td) 844{ 845 struct upd7210 *u; 846 struct ibfoo *ib; 847 848 u = dev->si_drv1; 849 ib = dev->si_drv2; 850 /* XXX: assert pointer consistency */ 851 852 u->ibfoo = NULL; 853 /* XXX: free handles */ 854 dev->si_drv2 = NULL; 855 free(ib, M_IBFOO); 856 857 if (u->dmachan >= 0) { 858 mtx_lock(&Giant); 859 isa_dma_release(u->dmachan); 860 mtx_unlock(&Giant); 861 } 862 mtx_lock(&u->mutex); 863 u->busy = 0; 864 ibdebug = 0; 865 upd7210_wr(u, IMR1, 0x00); 866 upd7210_wr(u, IMR2, 0x00); 867 upd7210_wr(u, AUXMR, AUXMR_CRST); 868 DELAY(10000); 869 mtx_unlock(&u->mutex); 870 return (0); 871} 872 873static int 874gpib_ib_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td) 875{ 876 struct ibarg *ap; 877 struct ibhandler *ih; 878 struct handle *h; 879 struct upd7210 *u; 880 struct ibfoo *ib; 881 int error; 882 struct timeval deadline, tv; 883 884 u = dev->si_drv1; 885 ib = u->ibfoo; 886 887 /* We only support a single ioctl, everything else is a mistake */ 888 if (cmd != GPIB_IBFOO) 889 return (ENOIOCTL); 890 891 /* Check the identifier and field-bitmap in the arguments. */ 892 ap = (void *)data; 893 if (ap->__ident < 0 || ap->__ident >= max_ibhandler) 894 return (EINVAL); 895 ih = &ibhandlers[ap->__ident]; 896 if (ap->__field != ih->args) 897 return (EINVAL); 898 899 if (ibdebug) 900 ib_dump_args(ih, ap); 901 902 if (ih->func == NULL) 903 return (EOPNOTSUPP); 904 905 ap->__iberr = 0; 906 ap->__ibsta = 0; 907 ap->__ibcnt = 0; 908 ap->retval = 0; 909 910 if (ap->__field & __F_TMO) { 911 if (ap->tmo < 0 || ap->tmo >= max_timeouts) 912 return (ib_set_error(ap, EARG)); 913 } 914 915 if (ap->__field & __F_EOS) { 916 if ((ap->eos & ~(REOS | XEOS | BIN | 0xff)) || 917 ((ap->eos & (BIN | 0x80)) == 0x80)) 918 return (ib_set_error(ap, EARG)); 919 } 920 if (ap->__field & __F_PAD) { 921 if (ap->pad < 0 || ap->pad > 30) 922 return (ib_set_error(ap, EARG)); 923 } 924 if (ap->__field & __F_SAD) { 925 if (ap->sad != 0 && (ap->sad < 0x60 || ap->sad > 126)) 926 return (ib_set_error(ap, EARG)); 927 } 928 929 930 mtx_lock(&u->mutex); 931 932 933 /* Find the handle, if any */ 934 h = NULL; 935 if ((ap->__field & __F_HANDLE) && gethandle(u, ap, &h)) { 936 mtx_unlock(&u->mutex); 937 return (0); 938 } 939 940 /* Check that the handle is the right kind */ 941 if (h != NULL && !(h->kind & ih->kind)) { 942 mtx_unlock(&u->mutex); 943 return (ib_set_error(ap, EARG)); 944 } 945 946 /* Set up handle and deadline */ 947 if (h != NULL && timevalisset(&h->timeout)) { 948 getmicrouptime(&deadline); 949 timevaladd(&deadline, &h->timeout); 950 } else { 951 timevalclear(&deadline); 952 } 953 954 /* Wait for the card to be(come) available, respect deadline */ 955 while(u->busy != 1) { 956 error = msleep(ib, &u->mutex, 957 PZERO | PCATCH, "gpib_ibioctl", hz / 10); 958 if (error == 0) 959 continue; 960 mtx_unlock(&u->mutex); 961 if (error == EINTR) 962 return(ib_set_error(ap, EABO)); 963 if (error == EWOULDBLOCK && timevalisset(&deadline)) { 964 getmicrouptime(&tv); 965 if (timevalcmp(&deadline, &tv, <)) 966 return(ib_had_timeout(ap)); 967 } 968 mtx_lock(&u->mutex); 969 } 970 u->busy = 2; 971 mtx_unlock(&u->mutex); 972 973 /* Hand over deadline handling to the callout routine */ 974 ib->ap = ap; 975 ib->h = h; 976 ib->mode = BUSY; 977 ib->deadline = deadline; 978 callout_reset(&ib->callout, hz / 5, gpib_ib_timeout, u); 979 980 error = ih->func(ib); 981 982 /* Release card */ 983 ib->mode = IDLE; 984 ib->ap = NULL; 985 ib->h = NULL; 986 timevalclear(&deadline); 987 callout_stop(&ib->callout); 988 989 mtx_lock(&u->mutex); 990 u->busy = 1; 991 wakeup(ib); 992 mtx_unlock(&u->mutex); 993 994 if (error) 995 return(ib_set_errno(ap, error)); 996 return (0); 997} 998 999struct cdevsw gpib_ib_cdevsw = { 1000 .d_version = D_VERSION, 1001 .d_name = "gpib_ib", 1002 .d_open = gpib_ib_open, 1003 .d_ioctl = gpib_ib_ioctl, 1004 .d_close = gpib_ib_close, 1005}; 1006