ibfoo.c revision 141768
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 141768 2005-02-12 21:07:09Z 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 64struct handle { 65 LIST_ENTRY(handle) list; 66 int handle; 67 int pad; 68 int sad; 69 struct timeval timeout; 70 int eot; 71 int eos; 72 int dma; 73}; 74 75struct ibfoo { 76 struct upd7210 *u; 77 LIST_HEAD(,handle) handles; 78 struct unrhdr *unrhdr; 79 struct callout callout; 80 struct handle *h; 81 struct ibarg *ap; 82 83 enum { 84 IDLE, 85 BUSY, 86 PIO_IDATA, 87 PIO_ODATA, 88 PIO_CMD, 89 DMA_IDATA 90 } mode; 91 92 struct timeval deadline; 93 94 struct handle *rdh; /* addressed for read */ 95 struct handle *wrh; /* addressed for write */ 96 97 int doeoi; 98 99 u_char *buf; 100 u_int buflen; 101}; 102 103typedef int ibhandler_t(struct ibfoo *ib); 104 105static struct timeval timeouts[] = { 106 [TNONE] = { 0, 0}, 107 [T10us] = { 0, 10}, 108 [T30us] = { 0, 30}, 109 [T100us] = { 0, 100}, 110 [T300us] = { 0, 300}, 111 [T1ms] = { 0, 1000}, 112 [T3ms] = { 0, 3000}, 113 [T10ms] = { 0, 10000}, 114 [T30ms] = { 0, 30000}, 115 [T100ms] = { 0, 100000}, 116 [T300ms] = { 0, 300000}, 117 [T1s] = { 1, 0}, 118 [T3s] = { 3, 0}, 119 [T10s] = { 10, 0}, 120 [T30s] = { 30, 0}, 121 [T100s] = { 100, 0}, 122 [T300s] = { 300, 0}, 123 [T1000s] = { 1000, 0} 124}; 125 126static const u_int max_timeouts = sizeof timeouts / sizeof timeouts[0]; 127 128static int ibdebug; 129 130static int 131ib_set_error(struct ibarg *ap, int error) 132{ 133 134 if (ap->__iberr == 0) 135 ap->__iberr = error; 136 ap->__ibsta |= ERR; 137 ap->__retval = ap->__ibsta; 138 return (0); 139} 140 141static int 142ib_had_timeout(struct ibarg *ap) 143{ 144 145 ib_set_error(ap, EABO); 146 ap->__ibsta |= TIMO; 147 ap->__retval = ap->__ibsta; 148 return (0); 149} 150 151static int 152ib_set_errno(struct ibarg *ap, int errno) 153{ 154 155 if (ap->__iberr == 0) { 156 ap->__iberr = EDVR; 157 ap->__ibcnt = errno; 158 } 159 ap->__ibsta |= ERR; 160 ap->__retval = ap->__ibsta; 161 return (0); 162} 163 164static int 165gpib_ib_irq(struct upd7210 *u, int intr __unused) 166{ 167 struct ibfoo *ib; 168 169 ib = u->ibfoo; 170 171 mtx_assert(&u->mutex, MA_OWNED); 172 switch (ib->mode) { 173 case PIO_CMD: 174 if (!(u->rreg[ISR2] & IXR2_CO)) 175 return (0); 176 if (ib->buflen == 0) 177 break; 178 upd7210_wr(u, CDOR, *ib->buf); 179 ib->buf++; 180 ib->buflen--; 181 return (1); 182 case PIO_IDATA: 183 if (!(u->rreg[ISR1] & IXR1_DI)) 184 return (0); 185 *ib->buf = upd7210_rd(u, DIR); 186 ib->buf++; 187 ib->buflen--; 188 if (ib->buflen == 0 || (u->rreg[ISR1] & IXR1_ENDRX)) 189 break; 190 return (1); 191 case PIO_ODATA: 192 if (!(u->rreg[ISR1] & IXR1_DO)) 193 return (0); 194 if (ib->buflen == 0) 195 break; 196 if (ib->buflen == 1 && ib->doeoi) 197 upd7210_wr(u, AUXMR, AUXMR_SEOI); 198 upd7210_wr(u, CDOR, *ib->buf); 199 ib->buf++; 200 ib->buflen--; 201 return (1); 202 case DMA_IDATA: 203 if (!(u->rreg[ISR1] & IXR1_ENDRX)) 204 return (0); 205 break; 206 default: 207 return (0); 208 } 209 upd7210_wr(u, IMR1, 0); 210 upd7210_wr(u, IMR2, 0); 211 ib->mode = BUSY; 212 wakeup(&ib->buflen); 213 return (1); 214} 215 216static void 217gpib_ib_timeout(void *arg) 218{ 219 struct upd7210 *u; 220 struct ibfoo *ib; 221 struct timeval tv; 222 223 u = arg; 224 ib = u->ibfoo; 225 mtx_lock(&u->mutex); 226 if (ib->mode == DMA_IDATA && isa_dmatc(u->dmachan)) { 227 upd7210_wr(u, IMR1, 0); 228 upd7210_wr(u, IMR2, 0); 229 ib->mode = IDLE; 230 wakeup(&ib->buflen); 231 } 232 if (ib->mode > BUSY) { 233 upd7210_rd(u, ISR1); 234 upd7210_rd(u, ISR2); 235 gpib_ib_irq(u, 2); 236 } 237 if (ib->mode != IDLE && timevalisset(&ib->deadline)) { 238 getmicrouptime(&tv); 239 if (timevalcmp(&ib->deadline, &tv, <)) { 240 ib_had_timeout(ib->ap); 241 upd7210_wr(u, IMR1, 0); 242 upd7210_wr(u, IMR2, 0); 243 ib->mode = BUSY; 244 wakeup(&ib->buflen); 245 } 246 } 247 if (ib->mode != IDLE) 248 callout_reset(&ib->callout, hz / 100, gpib_ib_timeout, arg); 249 mtx_unlock(&u->mutex); 250} 251 252static void 253gpib_ib_wait_xfer(struct upd7210 *u, struct ibfoo *ib) 254{ 255 int i; 256 257 mtx_assert(&u->mutex, MA_OWNED); 258 while (ib->mode > BUSY) { 259 i = msleep(&ib->buflen, &u->mutex, 260 PZERO | PCATCH, "ibwxfr", 0); 261 if (i == EINTR) { 262 ib_set_errno(ib->ap, i); 263 break; 264 } 265 if (u->rreg[ISR1] & IXR1_ERR) { 266 ib_set_error(ib->ap, EABO); /* XXX ? */ 267 break; 268 } 269 } 270 ib->mode = BUSY; 271 ib->buf = NULL; 272 upd7210_wr(u, IMR1, 0); 273 upd7210_wr(u, IMR2, 0); 274} 275 276static void 277config_eos(struct upd7210 *u, struct handle *h) 278{ 279 int i; 280 281 i = 0; 282 if (h->eos & REOS) { 283 upd7210_wr(u, EOSR, h->eos & 0xff); 284 i |= AUXA_REOS; 285 } 286 if (h->eos & XEOS) { 287 upd7210_wr(u, EOSR, h->eos & 0xff); 288 i |= AUXA_XEOS; 289 } 290 if (h->eos & BIN) 291 i |= AUXA_BIN; 292 upd7210_wr(u, AUXRA, C_AUXA | i); 293} 294 295/* 296 * Look up the handle, and set the deadline if the handle has a timeout. 297 */ 298static int 299gethandle(struct upd7210 *u, struct ibarg *ap, struct handle **hp) 300{ 301 struct ibfoo *ib; 302 struct handle *h; 303 304 KASSERT(ap->__field & __F_HANDLE, ("gethandle without __F_HANDLE")); 305 ib = u->ibfoo; 306 LIST_FOREACH(h, &ib->handles, list) { 307 if (h->handle == ap->handle) { 308 *hp = h; 309 return (0); 310 } 311 } 312 ib_set_error(ap, EARG); 313 return (1); 314} 315 316static int 317pio_cmd(struct upd7210 *u, u_char *cmd, int len) 318{ 319 struct ibfoo *ib; 320 321 ib = u->ibfoo; 322 323 if (ib->rdh != NULL || ib->wrh != NULL) { 324 upd7210_take_ctrl_async(u); 325 ib->rdh = NULL; 326 ib->wrh = NULL; 327 } 328 mtx_lock(&u->mutex); 329 ib->mode = PIO_CMD; 330 ib->buf = cmd; 331 ib->buflen = len; 332 upd7210_wr(u, IMR2, IXR2_CO); 333 334 gpib_ib_irq(u, 1); 335 336 gpib_ib_wait_xfer(u, ib); 337 338 mtx_unlock(&u->mutex); 339 return (len - ib->buflen); 340} 341 342static int 343pio_odata(struct upd7210 *u, u_char *data, int len) 344{ 345 struct ibfoo *ib; 346 347 ib = u->ibfoo; 348 349 if (len == 0) 350 return (0); 351 mtx_lock(&u->mutex); 352 ib->mode = PIO_ODATA; 353 ib->buf = data; 354 ib->buflen = len; 355 upd7210_wr(u, IMR1, IXR1_DO); 356 357 gpib_ib_irq(u, 1); 358 359 gpib_ib_wait_xfer(u, ib); 360 361 mtx_unlock(&u->mutex); 362 return (len - ib->buflen); 363} 364 365static int 366pio_idata(struct upd7210 *u, u_char *data, int len) 367{ 368 struct ibfoo *ib; 369 370 ib = u->ibfoo; 371 372 mtx_lock(&u->mutex); 373 ib->mode = PIO_IDATA; 374 ib->buf = data; 375 ib->buflen = len; 376 upd7210_wr(u, IMR1, IXR1_DI); 377 378 gpib_ib_wait_xfer(u, ib); 379 380 mtx_unlock(&u->mutex); 381 return (len - ib->buflen); 382} 383 384static int 385dma_idata(struct upd7210 *u, u_char *data, int len) 386{ 387 int j; 388 struct ibfoo *ib; 389 390 ib = u->ibfoo; 391 ib->mode = DMA_IDATA; 392 mtx_lock(&Giant); 393 isa_dmastart(ISADMA_READ, data, len, u->dmachan); 394 mtx_unlock(&Giant); 395 mtx_lock(&u->mutex); 396 upd7210_wr(u, IMR1, IXR1_ENDRX); 397 upd7210_wr(u, IMR2, IMR2_DMAI); 398 gpib_ib_wait_xfer(u, ib); 399 mtx_unlock(&u->mutex); 400 mtx_lock(&Giant); 401 j = isa_dmastatus(u->dmachan); 402 isa_dmadone(ISADMA_READ, data, len, u->dmachan); 403 mtx_unlock(&Giant); 404 return (len - j); 405} 406 407#define ibask NULL 408#define ibbna NULL 409#define ibcac NULL 410#define ibclr NULL 411#define ibcmd NULL 412#define ibcmda NULL 413#define ibconfig NULL 414 415static int 416ibdev(struct ibfoo *ib) 417{ 418 struct handle *h; 419 420 h = malloc(sizeof *h, M_IBFOO, M_ZERO | M_WAITOK); 421 h->handle = alloc_unr(ib->unrhdr); 422 h->pad = ib->ap->pad; 423 h->sad = ib->ap->sad; 424 h->timeout = timeouts[ib->ap->tmo]; 425 h->eot = ib->ap->eot; 426 h->eos = ib->ap->eos; 427 mtx_lock(&ib->u->mutex); 428 LIST_INSERT_HEAD(&ib->handles, h, list); 429 mtx_unlock(&ib->u->mutex); 430 ib->ap->__retval = h->handle; 431 return (0); 432} 433 434#define ibdiag NULL 435 436static int 437ibdma(struct ibfoo *ib) 438{ 439 440 ib->h->dma = ib->ap->v; 441 return (0); 442} 443 444static int 445ibeos(struct ibfoo *ib) 446{ 447 448 ib->h->eos = ib->ap->eos; 449 if (ib->rdh == ib->h) 450 config_eos(ib->u, ib->h); 451 return (0); 452} 453 454static int 455ibeot(struct ibfoo *ib) 456{ 457 458 ib->h->eot = ib->ap->eot; 459 return (0); 460} 461 462#define ibevent NULL 463#define ibfind NULL 464#define ibgts NULL 465#define ibist NULL 466#define iblines NULL 467#define ibllo NULL 468#define ibln NULL 469#define ibloc NULL 470#define ibonl NULL 471#define ibpad NULL 472#define ibpct NULL 473#define ibpoke NULL 474#define ibppc NULL 475 476static int 477ibrd(struct ibfoo *ib) 478{ 479 u_char buf[10], *bp; 480 int i, j, error, bl, bc; 481 u_char *dp; 482 483 bl = ib->ap->cnt; 484 if (bl > PAGE_SIZE) 485 bl = PAGE_SIZE; 486 bp = malloc(bl, M_IBFOO, M_WAITOK); 487 488 if (ib->rdh != ib->h) { 489 i = 0; 490 buf[i++] = UNT; 491 buf[i++] = UNL; 492 buf[i++] = LAD | 0; 493 buf[i++] = TAD | ib->h->pad; 494 if (ib->h->sad) 495 buf[i++] = ib->h->sad; 496 i = pio_cmd(ib->u, buf, i); 497 config_eos(ib->u, ib->h); 498 ib->rdh = ib->h; 499 ib->wrh = NULL; 500 upd7210_goto_standby(ib->u); 501 } 502 dp = ib->ap->buffer; 503 bc = ib->ap->cnt; 504 error = 0; 505 while (bc > 0 && ib->ap->__iberr == 0) { 506 j = imin(bc, PAGE_SIZE); 507 if (ib->h->dma) 508 i = dma_idata(ib->u, bp, j); 509 else 510 i = pio_idata(ib->u, bp, j); 511 if (i <= 0) 512 break; 513 error = copyout(bp, dp , i); 514 if (error) 515 break; 516 ib->ap->__ibcnt += i; 517 if (i != j) 518 break; 519 bc -= i; 520 dp += i; 521 } 522 free(bp, M_IBFOO); 523 return (error); 524} 525 526#define ibrda NULL 527#define ibrdf NULL 528#define ibrdkey NULL 529#define ibrpp NULL 530#define ibrsc NULL 531#define ibrsp NULL 532#define ibrsv NULL 533#define ibsad NULL 534#define ibsgnl NULL 535#define ibsic NULL 536#define ibsre NULL 537#define ibsrq NULL 538#define ibstop NULL 539 540static int 541ibtmo(struct ibfoo *ib) 542{ 543 544 ib->h->timeout = timeouts[ib->ap->tmo]; 545 return (0); 546} 547 548#define ibtrap NULL 549#define ibtrg NULL 550#define ibwait NULL 551 552static int 553ibwrt(struct ibfoo *ib) 554{ 555 u_char buf[10], *bp; 556 int i; 557 558 bp = malloc(ib->ap->cnt, M_IBFOO, M_WAITOK); 559 /* XXX: bigger than PAGE_SIZE handling */ 560 i = copyin(ib->ap->buffer, bp, ib->ap->cnt); 561 if (i) { 562 free(bp, M_IBFOO); 563 return (i); 564 } 565 if (ib->wrh != ib->h) { 566 i = 0; 567 buf[i++] = UNT; 568 buf[i++] = UNL; 569 buf[i++] = LAD | ib->h->pad; 570 if (ib->h->sad) 571 buf[i++] = LAD | TAD | ib->h->sad; 572 buf[i++] = TAD | 0; 573 i = pio_cmd(ib->u, buf, i); 574 ib->rdh = NULL; 575 ib->wrh = ib->h; 576 upd7210_goto_standby(ib->u); 577 config_eos(ib->u, ib->h); 578 } 579 ib->doeoi = ib->h->eot; 580 i = pio_odata(ib->u, bp, ib->ap->cnt); 581 ib->ap->__ibcnt = i; 582 free(bp, M_IBFOO); 583 return (0); 584} 585 586#define ibwrta NULL 587#define ibwrtf NULL 588#define ibwrtkey NULL 589#define ibxtrc NULL 590 591static struct ibhandler { 592 const char *name; 593 ibhandler_t *func; 594 u_int args; 595} ibhandlers[] = { 596 [__ID_IBASK] = { "ibask", ibask, __F_HANDLE | __F_OPTION | __F_RETVAL }, 597 [__ID_IBBNA] = { "ibbna", ibbna, __F_HANDLE | __F_BDNAME }, 598 [__ID_IBCAC] = { "ibcac", ibcac, __F_HANDLE | __F_V }, 599 [__ID_IBCLR] = { "ibclr", ibclr, __F_HANDLE }, 600 [__ID_IBCMDA] = { "ibcmda", ibcmda, __F_HANDLE | __F_BUFFER | __F_CNT }, 601 [__ID_IBCMD] = { "ibcmd", ibcmd, __F_HANDLE | __F_BUFFER | __F_CNT }, 602 [__ID_IBCONFIG] = { "ibconfig", ibconfig, __F_HANDLE | __F_OPTION | __F_VALUE }, 603 [__ID_IBDEV] = { "ibdev", ibdev, __F_BOARDID | __F_PAD | __F_SAD | __F_TMO | __F_EOT | __F_EOS }, 604 [__ID_IBDIAG] = { "ibdiag", ibdiag, __F_HANDLE | __F_BUFFER | __F_CNT }, 605 [__ID_IBDMA] = { "ibdma", ibdma, __F_HANDLE | __F_V }, 606 [__ID_IBEOS] = { "ibeos", ibeos, __F_HANDLE | __F_EOS }, 607 [__ID_IBEOT] = { "ibeot", ibeot, __F_HANDLE | __F_EOT }, 608 [__ID_IBEVENT] = { "ibevent", ibevent, __F_HANDLE | __F_EVENT }, 609 [__ID_IBFIND] = { "ibfind", ibfind, __F_BDNAME }, 610 [__ID_IBGTS] = { "ibgts", ibgts, __F_HANDLE | __F_V }, 611 [__ID_IBIST] = { "ibist", ibist, __F_HANDLE | __F_V }, 612 [__ID_IBLINES] = { "iblines", iblines, __F_HANDLE | __F_LINES }, 613 [__ID_IBLLO] = { "ibllo", ibllo, __F_HANDLE }, 614 [__ID_IBLN] = { "ibln", ibln, __F_HANDLE | __F_PADVAL | __F_SADVAL | __F_LISTENFLAG }, 615 [__ID_IBLOC] = { "ibloc", ibloc, __F_HANDLE }, 616 [__ID_IBONL] = { "ibonl", ibonl, __F_HANDLE | __F_V }, 617 [__ID_IBPAD] = { "ibpad", ibpad, __F_HANDLE | __F_V }, 618 [__ID_IBPCT] = { "ibpct", ibpct, __F_HANDLE }, 619 [__ID_IBPOKE] = { "ibpoke", ibpoke, __F_HANDLE | __F_OPTION | __F_VALUE }, 620 [__ID_IBPPC] = { "ibppc", ibppc, __F_HANDLE | __F_V }, 621 [__ID_IBRDA] = { "ibrda", ibrda, __F_HANDLE | __F_BUFFER | __F_CNT }, 622 [__ID_IBRDF] = { "ibrdf", ibrdf, __F_HANDLE | __F_FLNAME }, 623 [__ID_IBRDKEY] = { "ibrdkey", ibrdkey, __F_HANDLE | __F_BUFFER | __F_CNT }, 624 [__ID_IBRD] = { "ibrd", ibrd, __F_HANDLE | __F_BUFFER | __F_CNT }, 625 [__ID_IBRPP] = { "ibrpp", ibrpp, __F_HANDLE | __F_PPR }, 626 [__ID_IBRSC] = { "ibrsc", ibrsc, __F_HANDLE | __F_V }, 627 [__ID_IBRSP] = { "ibrsp", ibrsp, __F_HANDLE | __F_SPR }, 628 [__ID_IBRSV] = { "ibrsv", ibrsv, __F_HANDLE | __F_V }, 629 [__ID_IBSAD] = { "ibsad", ibsad, __F_HANDLE | __F_V }, 630 [__ID_IBSGNL] = { "ibsgnl", ibsgnl, __F_HANDLE | __F_V }, 631 [__ID_IBSIC] = { "ibsic", ibsic, __F_HANDLE }, 632 [__ID_IBSRE] = { "ibsre", ibsre, __F_HANDLE | __F_V }, 633 [__ID_IBSRQ] = { "ibsrq", ibsrq, __F_FUNC }, 634 [__ID_IBSTOP] = { "ibstop", ibstop, __F_HANDLE }, 635 [__ID_IBTMO] = { "ibtmo", ibtmo, __F_HANDLE | __F_TMO }, 636 [__ID_IBTRAP] = { "ibtrap", ibtrap, __F_MASK | __F_MODE }, 637 [__ID_IBTRG] = { "ibtrg", ibtrg, __F_HANDLE }, 638 [__ID_IBWAIT] = { "ibwait", ibwait, __F_HANDLE | __F_MASK }, 639 [__ID_IBWRTA] = { "ibwrta", ibwrta, __F_HANDLE | __F_BUFFER | __F_CNT }, 640 [__ID_IBWRTF] = { "ibwrtf", ibwrtf, __F_HANDLE | __F_FLNAME }, 641 [__ID_IBWRTKEY] = { "ibwrtkey", ibwrtkey, __F_HANDLE | __F_BUFFER | __F_CNT }, 642 [__ID_IBWRT] = { "ibwrt", ibwrt, __F_HANDLE | __F_BUFFER | __F_CNT }, 643 [__ID_IBXTRC] = { "ibxtrc", ibxtrc, __F_HANDLE | __F_BUFFER | __F_CNT }, 644}; 645 646static const u_int max_ibhandler = sizeof ibhandlers / sizeof ibhandlers[0]; 647 648static void 649ib_dump_args(struct ibhandler *ih, struct ibarg *ap) 650{ 651 652 if (ih->name != NULL) 653 printf("%s(", ih->name); 654 else 655 printf("ibinvalid("); 656 printf("[0x%x]", ap->__field); 657 if (ap->__field & __F_HANDLE) printf(" handle=%d", ap->handle); 658 if (ap->__field & __F_EOS) printf(" eos=%d", ap->eos); 659 if (ap->__field & __F_EOT) printf(" eot=%d", ap->eot); 660 if (ap->__field & __F_TMO) printf(" tmo=%d", ap->tmo); 661 if (ap->__field & __F_PAD) printf(" pad=%d", ap->pad); 662 if (ap->__field & __F_SAD) printf(" sad=%d", ap->sad); 663 if (ap->__field & __F_BUFFER) printf(" buffer=%p", ap->buffer); 664 if (ap->__field & __F_CNT) printf(" cnt=%ld", ap->cnt); 665 /* XXX more ... */ 666 printf(")\n"); 667} 668 669static int 670gpib_ib_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 671{ 672 struct upd7210 *u; 673 struct ibfoo *ib; 674 int error; 675 676 u = dev->si_drv1; 677 678 mtx_lock(&u->mutex); 679 if (u->busy) { 680 mtx_unlock(&u->mutex); 681 return (EBUSY); 682 } 683 u->busy = 1; 684 mtx_unlock(&u->mutex); 685 686 mtx_lock(&Giant); 687 error = isa_dma_acquire(u->dmachan); 688 if (!error) { 689 error = isa_dma_init(u->dmachan, PAGE_SIZE, M_WAITOK); 690 if (error) 691 isa_dma_release(u->dmachan); 692 } 693 mtx_unlock(&Giant); 694 if (error) { 695 mtx_lock(&u->mutex); 696 u->busy = 0; 697 mtx_unlock(&u->mutex); 698 return (error); 699 } 700 701 ib = malloc(sizeof *ib, M_IBFOO, M_WAITOK | M_ZERO); 702 LIST_INIT(&ib->handles); 703 callout_init(&ib->callout, 1); 704 ib->unrhdr = new_unrhdr(0, INT_MAX); 705 dev->si_drv2 = ib; 706 ib->u = u; 707 u->ibfoo = ib; 708 u->irq = gpib_ib_irq; 709 710 upd7210_wr(u, AUXMR, AUXMR_CRST); 711 DELAY(10000); 712 DELAY(1000); 713 upd7210_wr(u, IMR1, 0x00); 714 upd7210_wr(u, IMR2, 0x00); 715 upd7210_wr(u, SPMR, 0x00); 716 upd7210_wr(u, ADR, 0x00); 717 upd7210_wr(u, ADR, ADR_ARS | ADR_DL | ADR_DT); 718 upd7210_wr(u, ADMR, ADMR_ADM0 | ADMR_TRM0 | ADMR_TRM1); 719 upd7210_wr(u, EOSR, 0x00); 720 upd7210_wr(u, AUXMR, C_ICR | 8); 721 upd7210_wr(u, AUXMR, C_PPR | PPR_U); 722 upd7210_wr(u, AUXMR, C_AUXA); 723 upd7210_wr(u, AUXMR, C_AUXB + 3); 724 upd7210_wr(u, AUXMR, C_AUXE + 0); 725 upd7210_wr(u, AUXMR, AUXMR_PON); 726 upd7210_wr(u, AUXMR, AUXMR_CIFC); 727 DELAY(100); 728 upd7210_wr(u, AUXMR, AUXMR_SIFC); 729 upd7210_wr(u, AUXMR, AUXMR_SREN); 730 return (0); 731} 732 733static int 734gpib_ib_close(struct cdev *dev, int oflags, int devtype, struct thread *td) 735{ 736 struct upd7210 *u; 737 struct ibfoo *ib; 738 739 u = dev->si_drv1; 740 ib = dev->si_drv2; 741 /* XXX: assert pointer consistency */ 742 743 u->ibfoo = NULL; 744 /* XXX: free handles */ 745 dev->si_drv2 = NULL; 746 free(ib, M_IBFOO); 747 748 mtx_lock(&Giant); 749 isa_dma_release(u->dmachan); 750 mtx_unlock(&Giant); 751 mtx_lock(&u->mutex); 752 u->busy = 0; 753 upd7210_wr(u, IMR1, 0x00); 754 upd7210_wr(u, IMR2, 0x00); 755 upd7210_wr(u, AUXMR, AUXMR_CRST); 756 DELAY(10000); 757 mtx_unlock(&u->mutex); 758 return (0); 759} 760 761static int 762gpib_ib_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td) 763{ 764 struct ibarg *ap; 765 struct ibhandler *ih; 766 struct handle *h; 767 struct upd7210 *u; 768 struct ibfoo *ib; 769 int error; 770 struct timeval deadline, tv; 771 772 u = dev->si_drv1; 773 ib = u->ibfoo; 774 775 /* We only support a single ioctl, everything else is a mistake */ 776 if (cmd != GPIB_IBFOO) 777 return (ENOIOCTL); 778 779 /* Check the identifier and field-bitmap in the arguments. */ 780 ap = (void *)data; 781 if (ap->__ident < 0 || ap->__ident >= max_ibhandler) 782 return (EINVAL); 783 ih = &ibhandlers[ap->__ident]; 784 if (ap->__field != ih->args) 785 return (EINVAL); 786 787 if (ibdebug) 788 ib_dump_args(ih, ap); 789 790 if (ih->func == NULL) 791 return (EOPNOTSUPP); 792 793 ap->__iberr = 0; 794 ap->__ibsta = 0; 795 ap->__ibcnt = 0; 796 ap->retval = 0; 797 798 if (ap->__field & __F_TMO) { 799 if (ap->tmo < 0 || ap->tmo >= max_timeouts) 800 return (ib_set_error(ap, EARG)); 801 } 802 803 if (ap->__field & __F_EOS) { 804 if ((ap->eos & ~(REOS | XEOS | BIN | 0xff)) || 805 ((ap->eos & (BIN | 0x80)) == 0x80)) 806 return (ib_set_error(ap, EARG)); 807 } 808 if (ap->__field & __F_PAD) { 809 if (ap->pad < 0 || ap->pad > 30) 810 return (ib_set_error(ap, EARG)); 811 } 812 if (ap->__field & __F_SAD) { 813 if (ap->sad != 0 && (ap->sad < 0x60 || ap->sad > 126)) 814 return (ib_set_error(ap, EARG)); 815 } 816 817 818 mtx_lock(&u->mutex); 819 820 821 /* Find the handle, if any */ 822 h = NULL; 823 if ((ap->__field & __F_HANDLE) && gethandle(u, ap, &h)) { 824 mtx_unlock(&u->mutex); 825 return (0); 826 } 827 828 /* Set up handle and deadline */ 829 if (h != NULL && timevalisset(&h->timeout)) { 830 getmicrouptime(&deadline); 831 timevaladd(&deadline, &h->timeout); 832 } else { 833 timevalclear(&deadline); 834 } 835 836 /* Wait for the card to be(come) available, respect deadline */ 837 while(u->busy != 1) { 838 error = msleep(ib, &u->mutex, 839 PZERO | PCATCH, "gpib_ibioctl", hz / 10); 840 if (error == 0) 841 continue; 842 mtx_unlock(&u->mutex); 843 if (error == EINTR) 844 return(ib_set_error(ap, EABO)); 845 if (error == EWOULDBLOCK && timevalisset(&deadline)) { 846 getmicrouptime(&tv); 847 if (timevalcmp(&deadline, &tv, <)) 848 return(ib_had_timeout(ap)); 849 } 850 mtx_lock(&u->mutex); 851 } 852 u->busy = 2; 853 mtx_unlock(&u->mutex); 854 855 /* Hand over deadline handling to the callout routine */ 856 ib->ap = ap; 857 ib->h = h; 858 ib->mode = BUSY; 859 ib->deadline = deadline; 860 callout_reset(&ib->callout, hz / 100, gpib_ib_timeout, u); 861 862 error = ih->func(ib); 863 864 /* Release card */ 865 ib->mode = IDLE; 866 ib->ap = NULL; 867 ib->h = NULL; 868 timevalclear(&deadline); 869 callout_stop(&ib->callout); 870 871 mtx_lock(&u->mutex); 872 u->busy = 1; 873 wakeup(ib); 874 mtx_unlock(&u->mutex); 875 876 if (error) 877 return(ib_set_errno(ap, error)); 878 return (0); 879} 880 881struct cdevsw gpib_ib_cdevsw = { 882 .d_version = D_VERSION, 883 .d_name = "gpib_ib", 884 .d_open = gpib_ib_open, 885 .d_ioctl = gpib_ib_ioctl, 886 .d_close = gpib_ib_close, 887}; 888