ibfoo.c revision 141777
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 141777 2005-02-12 23:52:44Z phk $"); 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 = IDLE; 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 / 100, 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_irq(u, 1); 367 368 gpib_ib_wait_xfer(u, ib); 369 370 mtx_unlock(&u->mutex); 371 return (len - ib->buflen); 372} 373 374static int 375pio_idata(struct upd7210 *u, u_char *data, int len) 376{ 377 struct ibfoo *ib; 378 379 ib = u->ibfoo; 380 381 mtx_lock(&u->mutex); 382 ib->mode = PIO_IDATA; 383 ib->buf = data; 384 ib->buflen = len; 385 upd7210_wr(u, IMR1, IXR1_DI); 386 387 gpib_ib_wait_xfer(u, ib); 388 389 mtx_unlock(&u->mutex); 390 return (len - ib->buflen); 391} 392 393static int 394dma_idata(struct upd7210 *u, u_char *data, int len) 395{ 396 int j; 397 struct ibfoo *ib; 398 399 KASSERT(u->dmachan >= 0, ("Bogus dmachan %d", u->dmachan)); 400 ib = u->ibfoo; 401 ib->mode = DMA_IDATA; 402 mtx_lock(&Giant); 403 isa_dmastart(ISADMA_READ, data, len, u->dmachan); 404 mtx_unlock(&Giant); 405 mtx_lock(&u->mutex); 406 upd7210_wr(u, IMR1, IXR1_ENDRX); 407 upd7210_wr(u, IMR2, IMR2_DMAI); 408 gpib_ib_wait_xfer(u, ib); 409 mtx_unlock(&u->mutex); 410 mtx_lock(&Giant); 411 j = isa_dmastatus(u->dmachan); 412 isa_dmadone(ISADMA_READ, data, len, u->dmachan); 413 mtx_unlock(&Giant); 414 return (len - j); 415} 416 417static int 418ib_send_msg(struct ibfoo *ib, int msg) 419{ 420 u_char buf[10]; 421 int i, j; 422 423 i = 0; 424 buf[i++] = UNT; 425 buf[i++] = UNL; 426 buf[i++] = LAD | ib->h->pad; 427 if (ib->h->sad) 428 buf[i++] = LAD | TAD | ib->h->sad; 429 buf[i++] = TAD | 0; 430 buf[i++] = msg; 431 j = pio_cmd(ib->u, buf, i); 432 if (i != j) 433 ib_set_error(ib->ap, EABO); /* XXX ? */ 434 return (0); 435} 436 437static int 438ibask(struct ibfoo *ib) 439{ /* XXX */ 440 441 ibdebug = ib->ap->option; 442 return (0); 443} 444 445#define ibbna NULL 446#define ibcac NULL 447 448static int 449ibclr(struct ibfoo *ib) 450{ 451 452 return (ib_send_msg(ib, SDC)); 453} 454 455#define ibcmd NULL 456#define ibcmda NULL 457#define ibconfig NULL 458 459static int 460ibdev(struct ibfoo *ib) 461{ /* TBD */ 462 struct handle *h; 463 464 h = malloc(sizeof *h, M_IBFOO, M_ZERO | M_WAITOK); 465 h->handle = alloc_unr(ib->unrhdr); 466 h->kind = H_DEV; 467 h->pad = ib->ap->pad; 468 h->sad = ib->ap->sad; 469 h->timeout = timeouts[ib->ap->tmo]; 470 h->eot = ib->ap->eot; 471 h->eos = ib->ap->eos; 472 mtx_lock(&ib->u->mutex); 473 LIST_INSERT_HEAD(&ib->handles, h, list); 474 mtx_unlock(&ib->u->mutex); 475 ib->ap->__retval = h->handle; 476 return (0); 477} 478 479#define ibdiag NULL 480 481static int 482ibdma(struct ibfoo *ib) 483{ 484 485 if (ib->u->dmachan < 0 && ib->ap->v) 486 return (ib_set_error(ib->ap, EARG)); 487 ib->h->dma = ib->ap->v; 488 return (0); 489} 490 491static int 492ibeos(struct ibfoo *ib) 493{ 494 495 ib->ap->__iberr = ib->h->eos; 496 ib->h->eos = ib->ap->eos; 497 if (ib->rdh == ib->h) 498 config_eos(ib->u, ib->h); 499 return (0); 500} 501 502static int 503ibeot(struct ibfoo *ib) 504{ 505 506 ib->h->eot = ib->ap->eot; 507 return (0); 508} 509 510#define ibevent NULL 511#define ibfind NULL 512#define ibgts NULL 513#define ibist NULL 514#define iblines NULL 515#define ibllo NULL 516#define ibln NULL 517 518static int 519ibloc(struct ibfoo *ib) 520{ /* XXX */ 521 522 if (ib->h->kind == H_BOARD) 523 return (EOPNOTSUPP); /* XXX */ 524 return (ib_send_msg(ib, GTL)); 525} 526 527static int 528ibonl(struct ibfoo *ib) 529{ /* XXX */ 530 531 if (ib->ap->v) 532 return (EOPNOTSUPP); /* XXX */ 533 mtx_lock(&ib->u->mutex); 534 LIST_REMOVE(ib->h, list); 535 mtx_unlock(&ib->u->mutex); 536 free(ib->h, M_IBFOO); 537 ib->h = NULL; 538 return (0); 539} 540 541static int 542ibpad(struct ibfoo *ib) 543{ 544 545 ib->h->pad = ib->ap->pad; 546 return (0); 547} 548 549#define ibpct NULL 550#define ibpoke NULL 551#define ibppc NULL 552 553static int 554ibrd(struct ibfoo *ib) 555{ /* TBD */ 556 u_char buf[10], *bp; 557 int i, j, error, bl, bc; 558 u_char *dp; 559 560 if (ib->h->kind == H_BOARD) 561 return (EOPNOTSUPP); /* XXX */ 562 bl = ib->ap->cnt; 563 if (bl > PAGE_SIZE) 564 bl = PAGE_SIZE; 565 bp = malloc(bl, M_IBFOO, M_WAITOK); 566 567 if (ib->rdh != ib->h) { 568 i = 0; 569 buf[i++] = UNT; 570 buf[i++] = UNL; 571 buf[i++] = LAD | 0; 572 buf[i++] = TAD | ib->h->pad; 573 if (ib->h->sad) 574 buf[i++] = ib->h->sad; 575 i = pio_cmd(ib->u, buf, i); 576 config_eos(ib->u, ib->h); 577 ib->rdh = ib->h; 578 ib->wrh = NULL; 579 upd7210_goto_standby(ib->u); 580 } 581 dp = ib->ap->buffer; 582 bc = ib->ap->cnt; 583 error = 0; 584 while (bc > 0 && ib->ap->__iberr == 0) { 585 j = imin(bc, PAGE_SIZE); 586 if (ib->h->dma) 587 i = dma_idata(ib->u, bp, j); 588 else 589 i = pio_idata(ib->u, bp, j); 590 error = copyout(bp, dp , i); 591 if (error) 592 break; 593 ib->ap->__ibcnt += i; 594 if (i != j) 595 break; 596 bc -= i; 597 dp += i; 598 } 599 free(bp, M_IBFOO); 600 return (error); 601} 602 603#define ibrda NULL 604#define ibrdf NULL 605#define ibrdkey NULL 606#define ibrpp NULL 607#define ibrsc NULL 608#define ibrsp NULL 609#define ibrsv NULL 610 611static int 612ibsad(struct ibfoo *ib) 613{ 614 615 ib->h->sad = ib->ap->sad; 616 return (0); 617} 618 619#define ibsgnl NULL 620 621static int 622ibsic(struct ibfoo *ib) 623{ /* TBD */ 624 625 upd7210_wr(ib->u, AUXMR, AUXMR_SIFC); 626 DELAY(100); 627 upd7210_wr(ib->u, AUXMR, AUXMR_CIFC); 628 return (0); 629} 630 631#define ibsre NULL 632#define ibsrq NULL 633#define ibstop NULL 634 635static int 636ibtmo(struct ibfoo *ib) 637{ 638 639 ib->h->timeout = timeouts[ib->ap->tmo]; 640 return (0); 641} 642 643#define ibtrap NULL 644 645static int 646ibtrg(struct ibfoo *ib) 647{ 648 649 return (ib_send_msg(ib, GET)); 650} 651 652#define ibwait NULL 653 654static int 655ibwrt(struct ibfoo *ib) 656{ /* XXX */ 657 u_char buf[10], *bp; 658 int i; 659 660 if (ib->h->kind == H_BOARD) 661 return (EOPNOTSUPP); 662 bp = malloc(ib->ap->cnt, M_IBFOO, M_WAITOK); 663 /* XXX: bigger than PAGE_SIZE handling */ 664 i = copyin(ib->ap->buffer, bp, ib->ap->cnt); 665 if (i) { 666 free(bp, M_IBFOO); 667 return (i); 668 } 669 if (ib->wrh != ib->h) { 670 i = 0; 671 buf[i++] = UNT; 672 buf[i++] = UNL; 673 buf[i++] = LAD | ib->h->pad; 674 if (ib->h->sad) 675 buf[i++] = LAD | TAD | ib->h->sad; 676 buf[i++] = TAD | 0; 677 i = pio_cmd(ib->u, buf, i); 678 ib->rdh = NULL; 679 ib->wrh = ib->h; 680 upd7210_goto_standby(ib->u); 681 config_eos(ib->u, ib->h); 682 } 683 ib->doeoi = ib->h->eot; 684 i = pio_odata(ib->u, bp, ib->ap->cnt); 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, 1); 813 ib->unrhdr = new_unrhdr(0, INT_MAX); 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 / 100, 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