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