ibfoo.c revision 199104
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 199104 2009-11-09 20:29:10Z rdivacky $"); 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 isa_dmastart(ISADMA_READ, data, len, u->dmachan); 401 mtx_lock(&u->mutex); 402 upd7210_wr(u, IMR1, IXR1_ENDRX); 403 upd7210_wr(u, IMR2, IMR2_DMAI); 404 gpib_ib_wait_xfer(u, ib); 405 mtx_unlock(&u->mutex); 406 j = isa_dmastatus(u->dmachan); 407 isa_dmadone(ISADMA_READ, data, len, u->dmachan); 408 return (len - j); 409} 410 411static int 412ib_send_msg(struct ibfoo *ib, int msg) 413{ 414 u_char buf[10]; 415 int i, j; 416 417 i = 0; 418 buf[i++] = UNT; 419 buf[i++] = UNL; 420 buf[i++] = LAD | ib->h->pad; 421 if (ib->h->sad) 422 buf[i++] = LAD | TAD | ib->h->sad; 423 buf[i++] = TAD | 0; 424 buf[i++] = msg; 425 j = pio_cmd(ib->u, buf, i); 426 if (i != j) 427 ib_set_error(ib->ap, EABO); /* XXX ? */ 428 return (0); 429} 430 431static int 432ibask(struct ibfoo *ib) 433{ /* XXX */ 434 435 ibdebug = ib->ap->option; 436 return (0); 437} 438 439#define ibbna NULL 440#define ibcac NULL 441 442static int 443ibclr(struct ibfoo *ib) 444{ 445 446 return (ib_send_msg(ib, SDC)); 447} 448 449#define ibcmd NULL 450#define ibcmda NULL 451#define ibconfig NULL 452 453static int 454ibdev(struct ibfoo *ib) 455{ /* TBD */ 456 struct handle *h; 457 458 h = malloc(sizeof *h, M_IBFOO, M_ZERO | M_WAITOK); 459 h->handle = alloc_unr(ib->unrhdr); 460 h->kind = H_DEV; 461 h->pad = ib->ap->pad; 462 h->sad = ib->ap->sad; 463 h->timeout = timeouts[ib->ap->tmo]; 464 h->eot = ib->ap->eot; 465 h->eos = ib->ap->eos; 466 mtx_lock(&ib->u->mutex); 467 LIST_INSERT_HEAD(&ib->handles, h, list); 468 mtx_unlock(&ib->u->mutex); 469 ib->ap->__retval = h->handle; 470 return (0); 471} 472 473#define ibdiag NULL 474 475static int 476ibdma(struct ibfoo *ib) 477{ 478 479 if (ib->u->dmachan < 0 && ib->ap->v) 480 return (ib_set_error(ib->ap, EARG)); 481 ib->h->dma = ib->ap->v; 482 return (0); 483} 484 485static int 486ibeos(struct ibfoo *ib) 487{ 488 489 ib->ap->__iberr = ib->h->eos; 490 ib->h->eos = ib->ap->eos; 491 if (ib->rdh == ib->h) 492 config_eos(ib->u, ib->h); 493 return (0); 494} 495 496static int 497ibeot(struct ibfoo *ib) 498{ 499 500 ib->h->eot = ib->ap->eot; 501 return (0); 502} 503 504#define ibevent NULL 505#define ibfind NULL 506#define ibgts NULL 507#define ibist NULL 508#define iblines NULL 509#define ibllo NULL 510#define ibln NULL 511 512static int 513ibloc(struct ibfoo *ib) 514{ /* XXX */ 515 516 if (ib->h->kind == H_BOARD) 517 return (EOPNOTSUPP); /* XXX */ 518 return (ib_send_msg(ib, GTL)); 519} 520 521static int 522ibonl(struct ibfoo *ib) 523{ /* XXX */ 524 525 if (ib->ap->v) 526 return (EOPNOTSUPP); /* XXX */ 527 mtx_lock(&ib->u->mutex); 528 LIST_REMOVE(ib->h, list); 529 mtx_unlock(&ib->u->mutex); 530 free(ib->h, M_IBFOO); 531 ib->h = NULL; 532 return (0); 533} 534 535static int 536ibpad(struct ibfoo *ib) 537{ 538 539 ib->h->pad = ib->ap->pad; 540 return (0); 541} 542 543#define ibpct NULL 544#define ibpoke NULL 545#define ibppc NULL 546 547static int 548ibrd(struct ibfoo *ib) 549{ /* TBD */ 550 u_char buf[10], *bp; 551 int i, j, error, bl, bc; 552 u_char *dp; 553 554 if (ib->h->kind == H_BOARD) 555 return (EOPNOTSUPP); /* XXX */ 556 bl = ib->ap->cnt; 557 if (bl > PAGE_SIZE) 558 bl = PAGE_SIZE; 559 bp = malloc(bl, M_IBFOO, M_WAITOK); 560 561 if (ib->rdh != ib->h) { 562 i = 0; 563 buf[i++] = UNT; 564 buf[i++] = UNL; 565 buf[i++] = LAD | 0; 566 buf[i++] = TAD | ib->h->pad; 567 if (ib->h->sad) 568 buf[i++] = ib->h->sad; 569 i = pio_cmd(ib->u, buf, i); 570 config_eos(ib->u, ib->h); 571 ib->rdh = ib->h; 572 ib->wrh = NULL; 573 } 574 upd7210_goto_standby(ib->u); 575 dp = ib->ap->buffer; 576 bc = ib->ap->cnt; 577 error = 0; 578 while (bc > 0 && ib->ap->__iberr == 0) { 579 j = imin(bc, PAGE_SIZE); 580 if (ib->h->dma) 581 i = dma_idata(ib->u, bp, j); 582 else 583 i = pio_idata(ib->u, bp, j); 584 error = copyout(bp, dp , i); 585 if (error) 586 break; 587 ib->ap->__ibcnt += i; 588 if (i != j) 589 break; 590 bc -= i; 591 dp += i; 592 } 593 upd7210_take_ctrl_async(ib->u); 594 free(bp, M_IBFOO); 595 return (error); 596} 597 598#define ibrda NULL 599#define ibrdf NULL 600#define ibrdkey NULL 601#define ibrpp NULL 602#define ibrsc NULL 603#define ibrsp NULL 604#define ibrsv NULL 605 606static int 607ibsad(struct ibfoo *ib) 608{ 609 610 ib->h->sad = ib->ap->sad; 611 return (0); 612} 613 614#define ibsgnl NULL 615 616static int 617ibsic(struct ibfoo *ib) 618{ /* TBD */ 619 620 upd7210_wr(ib->u, AUXMR, AUXMR_SIFC); 621 DELAY(100); 622 upd7210_wr(ib->u, AUXMR, AUXMR_CIFC); 623 return (0); 624} 625 626#define ibsre NULL 627#define ibsrq NULL 628#define ibstop NULL 629 630static int 631ibtmo(struct ibfoo *ib) 632{ 633 634 ib->h->timeout = timeouts[ib->ap->tmo]; 635 return (0); 636} 637 638#define ibtrap NULL 639 640static int 641ibtrg(struct ibfoo *ib) 642{ 643 644 return (ib_send_msg(ib, GET)); 645} 646 647#define ibwait NULL 648 649static int 650ibwrt(struct ibfoo *ib) 651{ /* XXX */ 652 u_char buf[10], *bp; 653 int i; 654 655 if (ib->h->kind == H_BOARD) 656 return (EOPNOTSUPP); 657 bp = malloc(ib->ap->cnt, M_IBFOO, M_WAITOK); 658 /* XXX: bigger than PAGE_SIZE handling */ 659 i = copyin(ib->ap->buffer, bp, ib->ap->cnt); 660 if (i) { 661 free(bp, M_IBFOO); 662 return (i); 663 } 664 if (ib->wrh != ib->h) { 665 i = 0; 666 buf[i++] = UNT; 667 buf[i++] = UNL; 668 buf[i++] = LAD | ib->h->pad; 669 if (ib->h->sad) 670 buf[i++] = LAD | TAD | ib->h->sad; 671 buf[i++] = TAD | 0; 672 i = pio_cmd(ib->u, buf, i); 673 ib->rdh = NULL; 674 ib->wrh = ib->h; 675 config_eos(ib->u, ib->h); 676 } 677 upd7210_goto_standby(ib->u); 678 ib->doeoi = ib->h->eot; 679 i = pio_odata(ib->u, bp, ib->ap->cnt); 680 upd7210_take_ctrl_async(ib->u); 681 ib->ap->__ibcnt = i; 682 free(bp, M_IBFOO); 683 return (0); 684} 685 686#define ibwrta NULL 687#define ibwrtf NULL 688#define ibwrtkey NULL 689#define ibxtrc NULL 690 691static struct ibhandler { 692 const char *name; 693 enum h_kind kind; 694 ibhandler_t *func; 695 u_int args; 696} ibhandlers[] = { 697 [__ID_IBASK] = { "ibask", H_EITHER, ibask, __F_HANDLE | __F_OPTION | __F_RETVAL }, 698 [__ID_IBBNA] = { "ibbna", H_DEV, ibbna, __F_HANDLE | __F_BDNAME }, 699 [__ID_IBCAC] = { "ibcac", H_BOARD, ibcac, __F_HANDLE | __F_V }, 700 [__ID_IBCLR] = { "ibclr", H_DEV, ibclr, __F_HANDLE }, 701 [__ID_IBCMD] = { "ibcmd", H_BOARD, ibcmd, __F_HANDLE | __F_BUFFER | __F_CNT }, 702 [__ID_IBCMDA] = { "ibcmda", H_BOARD, ibcmda, __F_HANDLE | __F_BUFFER | __F_CNT }, 703 [__ID_IBCONFIG] = { "ibconfig", H_EITHER, ibconfig, __F_HANDLE | __F_OPTION | __F_VALUE }, 704 [__ID_IBDEV] = { "ibdev", 0, ibdev, __F_BOARDID | __F_PAD | __F_SAD | __F_TMO | __F_EOT | __F_EOS }, 705 [__ID_IBDIAG] = { "ibdiag", H_EITHER, ibdiag, __F_HANDLE | __F_BUFFER | __F_CNT }, 706 [__ID_IBDMA] = { "ibdma", H_EITHER, ibdma, __F_HANDLE | __F_V }, 707 [__ID_IBEOS] = { "ibeos", H_EITHER, ibeos, __F_HANDLE | __F_EOS }, 708 [__ID_IBEOT] = { "ibeot", H_EITHER, ibeot, __F_HANDLE | __F_EOT }, 709 [__ID_IBEVENT] = { "ibevent", H_BOARD, ibevent, __F_HANDLE | __F_EVENT }, 710 [__ID_IBFIND] = { "ibfind", 0, ibfind, __F_BDNAME }, 711 [__ID_IBGTS] = { "ibgts", H_BOARD, ibgts, __F_HANDLE | __F_V }, 712 [__ID_IBIST] = { "ibist", H_BOARD, ibist, __F_HANDLE | __F_V }, 713 [__ID_IBLINES] = { "iblines", H_BOARD, iblines, __F_HANDLE | __F_LINES }, 714 [__ID_IBLLO] = { "ibllo", H_EITHER, ibllo, __F_HANDLE }, 715 [__ID_IBLN] = { "ibln", H_BOARD, ibln, __F_HANDLE | __F_PADVAL | __F_SADVAL | __F_LISTENFLAG }, 716 [__ID_IBLOC] = { "ibloc", H_EITHER, ibloc, __F_HANDLE }, 717 [__ID_IBONL] = { "ibonl", H_EITHER, ibonl, __F_HANDLE | __F_V }, 718 [__ID_IBPAD] = { "ibpad", H_EITHER, ibpad, __F_HANDLE | __F_PAD }, 719 [__ID_IBPCT] = { "ibpct", H_DEV, ibpct, __F_HANDLE }, 720 [__ID_IBPOKE] = { "ibpoke", H_EITHER, ibpoke, __F_HANDLE | __F_OPTION | __F_VALUE }, 721 [__ID_IBPPC] = { "ibppc", H_EITHER, ibppc, __F_HANDLE | __F_V }, 722 [__ID_IBRD] = { "ibrd", H_EITHER, ibrd, __F_HANDLE | __F_BUFFER | __F_CNT }, 723 [__ID_IBRDA] = { "ibrda", H_EITHER, ibrda, __F_HANDLE | __F_BUFFER | __F_CNT }, 724 [__ID_IBRDF] = { "ibrdf", H_EITHER, ibrdf, __F_HANDLE | __F_FLNAME }, 725 [__ID_IBRDKEY] = { "ibrdkey", H_EITHER, ibrdkey, __F_HANDLE | __F_BUFFER | __F_CNT }, 726 [__ID_IBRPP] = { "ibrpp", H_EITHER, ibrpp, __F_HANDLE | __F_PPR }, 727 [__ID_IBRSC] = { "ibrsc", H_BOARD, ibrsc, __F_HANDLE | __F_V }, 728 [__ID_IBRSP] = { "ibrsp", H_DEV, ibrsp, __F_HANDLE | __F_SPR }, 729 [__ID_IBRSV] = { "ibrsv", H_EITHER, ibrsv, __F_HANDLE | __F_V }, 730 [__ID_IBSAD] = { "ibsad", H_EITHER, ibsad, __F_HANDLE | __F_SAD }, 731 [__ID_IBSGNL] = { "ibsgnl", H_EITHER, ibsgnl, __F_HANDLE | __F_V }, 732 [__ID_IBSIC] = { "ibsic", H_BOARD, ibsic, __F_HANDLE }, 733 [__ID_IBSRE] = { "ibsre", H_BOARD, ibsre, __F_HANDLE | __F_V }, 734 [__ID_IBSRQ] = { "ibsrq", H_EITHER, ibsrq, __F_FUNC }, 735 [__ID_IBSTOP] = { "ibstop", H_EITHER, ibstop, __F_HANDLE }, 736 [__ID_IBTMO] = { "ibtmo", H_EITHER, ibtmo, __F_HANDLE | __F_TMO }, 737 [__ID_IBTRAP] = { "ibtrap", H_EITHER, ibtrap, __F_MASK | __F_MODE }, 738 [__ID_IBTRG] = { "ibtrg", H_DEV, ibtrg, __F_HANDLE }, 739 [__ID_IBWAIT] = { "ibwait", H_EITHER, ibwait, __F_HANDLE | __F_MASK }, 740 [__ID_IBWRT] = { "ibwrt", H_EITHER, ibwrt, __F_HANDLE | __F_BUFFER | __F_CNT }, 741 [__ID_IBWRTA] = { "ibwrta", H_EITHER, ibwrta, __F_HANDLE | __F_BUFFER | __F_CNT }, 742 [__ID_IBWRTF] = { "ibwrtf", H_EITHER, ibwrtf, __F_HANDLE | __F_FLNAME }, 743 [__ID_IBWRTKEY] = { "ibwrtkey", H_EITHER, ibwrtkey, __F_HANDLE | __F_BUFFER | __F_CNT }, 744 [__ID_IBXTRC] = { "ibxtrc", H_EITHER, ibxtrc, __F_HANDLE | __F_BUFFER | __F_CNT }, 745}; 746 747static const u_int max_ibhandler = sizeof ibhandlers / sizeof ibhandlers[0]; 748 749static void 750ib_dump_args(struct ibhandler *ih, struct ibarg *ap) 751{ 752 753 if (ih->name != NULL) 754 printf("%s(", ih->name); 755 else 756 printf("ibinvalid("); 757 printf("[0x%x]", ap->__field); 758 if (ap->__field & __F_HANDLE) printf(" handle=%d", ap->handle); 759 if (ap->__field & __F_EOS) printf(" eos=0x%x", ap->eos); 760 if (ap->__field & __F_EOT) printf(" eot=%d", ap->eot); 761 if (ap->__field & __F_TMO) printf(" tmo=%d", ap->tmo); 762 if (ap->__field & __F_PAD) printf(" pad=0x%x", ap->pad); 763 if (ap->__field & __F_SAD) printf(" sad=0x%x", ap->sad); 764 if (ap->__field & __F_BUFFER) printf(" buffer=%p", ap->buffer); 765 if (ap->__field & __F_CNT) printf(" cnt=%ld", ap->cnt); 766 if (ap->__field & __F_V) printf(" v=%d/0x%x", ap->v, ap->v); 767 /* XXX more ... */ 768 printf(")\n"); 769} 770 771static int 772gpib_ib_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 773{ 774 struct upd7210 *u; 775 struct ibfoo *ib; 776 int error = 0; 777 778 u = dev->si_drv1; 779 780 mtx_lock(&u->mutex); 781 if (u->busy) { 782 mtx_unlock(&u->mutex); 783 return (EBUSY); 784 } 785 u->busy = 1; 786 mtx_unlock(&u->mutex); 787 788 if (u->dmachan >= 0) { 789 error = isa_dma_acquire(u->dmachan); 790 if (!error) { 791 error = isa_dma_init(u->dmachan, PAGE_SIZE, M_WAITOK); 792 if (error) 793 isa_dma_release(u->dmachan); 794 } 795 } 796 797 if (error) { 798 mtx_lock(&u->mutex); 799 u->busy = 0; 800 mtx_unlock(&u->mutex); 801 return (error); 802 } 803 804 ib = malloc(sizeof *ib, M_IBFOO, M_WAITOK | M_ZERO); 805 LIST_INIT(&ib->handles); 806 callout_init(&ib->callout, CALLOUT_MPSAFE); 807 ib->unrhdr = new_unrhdr(0, INT_MAX, NULL); 808 dev->si_drv2 = ib; 809 ib->u = u; 810 u->ibfoo = ib; 811 u->irq = gpib_ib_irq; 812 813 upd7210_wr(u, AUXMR, AUXMR_CRST); 814 DELAY(10000); 815 DELAY(1000); 816 upd7210_wr(u, IMR1, 0x00); 817 upd7210_wr(u, IMR2, 0x00); 818 upd7210_wr(u, SPMR, 0x00); 819 upd7210_wr(u, ADR, 0x00); 820 upd7210_wr(u, ADR, ADR_ARS | ADR_DL | ADR_DT); 821 upd7210_wr(u, ADMR, ADMR_ADM0 | ADMR_TRM0 | ADMR_TRM1); 822 upd7210_wr(u, EOSR, 0x00); 823 upd7210_wr(u, AUXMR, C_ICR | 8); 824 upd7210_wr(u, AUXMR, C_PPR | PPR_U); 825 upd7210_wr(u, AUXMR, C_AUXA); 826 upd7210_wr(u, AUXMR, C_AUXB + 3); 827 upd7210_wr(u, AUXMR, C_AUXE + 0); 828 upd7210_wr(u, AUXMR, AUXMR_PON); 829 upd7210_wr(u, AUXMR, AUXMR_CIFC); 830 DELAY(100); 831 upd7210_wr(u, AUXMR, AUXMR_SIFC); 832 upd7210_wr(u, AUXMR, AUXMR_SREN); 833 return (0); 834} 835 836static int 837gpib_ib_close(struct cdev *dev, int oflags, int devtype, struct thread *td) 838{ 839 struct upd7210 *u; 840 struct ibfoo *ib; 841 842 u = dev->si_drv1; 843 ib = dev->si_drv2; 844 /* XXX: assert pointer consistency */ 845 846 u->ibfoo = NULL; 847 /* XXX: free handles */ 848 dev->si_drv2 = NULL; 849 free(ib, M_IBFOO); 850 851 if (u->dmachan >= 0) { 852 isa_dma_release(u->dmachan); 853 } 854 mtx_lock(&u->mutex); 855 u->busy = 0; 856 ibdebug = 0; 857 upd7210_wr(u, IMR1, 0x00); 858 upd7210_wr(u, IMR2, 0x00); 859 upd7210_wr(u, AUXMR, AUXMR_CRST); 860 DELAY(10000); 861 mtx_unlock(&u->mutex); 862 return (0); 863} 864 865static int 866gpib_ib_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td) 867{ 868 struct ibarg *ap; 869 struct ibhandler *ih; 870 struct handle *h; 871 struct upd7210 *u; 872 struct ibfoo *ib; 873 int error; 874 struct timeval deadline, tv; 875 876 u = dev->si_drv1; 877 ib = u->ibfoo; 878 879 /* We only support a single ioctl, everything else is a mistake */ 880 if (cmd != GPIB_IBFOO) 881 return (ENOIOCTL); 882 883 /* Check the identifier and field-bitmap in the arguments. */ 884 ap = (void *)data; 885 if (ap->__ident < 0 || ap->__ident >= max_ibhandler) 886 return (EINVAL); 887 ih = &ibhandlers[ap->__ident]; 888 if (ap->__field != ih->args) 889 return (EINVAL); 890 891 if (ibdebug) 892 ib_dump_args(ih, ap); 893 894 if (ih->func == NULL) 895 return (EOPNOTSUPP); 896 897 ap->__iberr = 0; 898 ap->__ibsta = 0; 899 ap->__ibcnt = 0; 900 ap->retval = 0; 901 902 if (ap->__field & __F_TMO) { 903 if (ap->tmo < 0 || ap->tmo >= max_timeouts) 904 return (ib_set_error(ap, EARG)); 905 } 906 907 if (ap->__field & __F_EOS) { 908 if ((ap->eos & ~(REOS | XEOS | BIN | 0xff)) || 909 ((ap->eos & (BIN | 0x80)) == 0x80)) 910 return (ib_set_error(ap, EARG)); 911 } 912 if (ap->__field & __F_PAD) { 913 if (ap->pad < 0 || ap->pad > 30) 914 return (ib_set_error(ap, EARG)); 915 } 916 if (ap->__field & __F_SAD) { 917 if (ap->sad != 0 && (ap->sad < 0x60 || ap->sad > 126)) 918 return (ib_set_error(ap, EARG)); 919 } 920 921 922 mtx_lock(&u->mutex); 923 924 925 /* Find the handle, if any */ 926 h = NULL; 927 if ((ap->__field & __F_HANDLE) && gethandle(u, ap, &h)) { 928 mtx_unlock(&u->mutex); 929 return (0); 930 } 931 932 /* Check that the handle is the right kind */ 933 if (h != NULL && !(h->kind & ih->kind)) { 934 mtx_unlock(&u->mutex); 935 return (ib_set_error(ap, EARG)); 936 } 937 938 /* Set up handle and deadline */ 939 if (h != NULL && timevalisset(&h->timeout)) { 940 getmicrouptime(&deadline); 941 timevaladd(&deadline, &h->timeout); 942 } else { 943 timevalclear(&deadline); 944 } 945 946 /* Wait for the card to be(come) available, respect deadline */ 947 while(u->busy != 1) { 948 error = msleep(ib, &u->mutex, 949 PZERO | PCATCH, "gpib_ibioctl", hz / 10); 950 if (error == 0) 951 continue; 952 mtx_unlock(&u->mutex); 953 if (error == EINTR) 954 return(ib_set_error(ap, EABO)); 955 if (error == EWOULDBLOCK && timevalisset(&deadline)) { 956 getmicrouptime(&tv); 957 if (timevalcmp(&deadline, &tv, <)) 958 return(ib_had_timeout(ap)); 959 } 960 mtx_lock(&u->mutex); 961 } 962 u->busy = 2; 963 mtx_unlock(&u->mutex); 964 965 /* Hand over deadline handling to the callout routine */ 966 ib->ap = ap; 967 ib->h = h; 968 ib->mode = BUSY; 969 ib->deadline = deadline; 970 callout_reset(&ib->callout, hz / 5, gpib_ib_timeout, u); 971 972 error = ih->func(ib); 973 974 /* Release card */ 975 ib->mode = IDLE; 976 ib->ap = NULL; 977 ib->h = NULL; 978 timevalclear(&deadline); 979 callout_stop(&ib->callout); 980 981 mtx_lock(&u->mutex); 982 u->busy = 1; 983 wakeup(ib); 984 mtx_unlock(&u->mutex); 985 986 if (error) 987 return(ib_set_errno(ap, error)); 988 return (0); 989} 990 991struct cdevsw gpib_ib_cdevsw = { 992 .d_version = D_VERSION, 993 .d_name = "gpib_ib", 994 .d_open = gpib_ib_open, 995 .d_ioctl = gpib_ib_ioctl, 996 .d_close = gpib_ib_close, 997}; 998