1 /* $NetBSD: ct.c,v 1.25 2014/03/16 05:20:27 dholland Exp $ */ 2 3 /*- 4 * Copyright (c) 1996-2003 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1988 University of Utah. 34 * Copyright (c) 1982, 1990, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * This code is derived from software contributed to Berkeley by 38 * the Systems Programming Group of the University of Utah Computer 39 * Science Department. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 3. Neither the name of the University nor the names of its contributors 50 * may be used to endorse or promote products derived from this software 51 * without specific prior written permission. 52 * 53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 * SUCH DAMAGE. 64 * 65 * from: Utah $Hdr: rd.c 1.44 92/12/26$ 66 * 67 * @(#)rd.c 8.2 (Berkeley) 5/19/94 68 */ 69 70 /* 71 * CS/80 cartridge tape driver (HP9144, HP88140, HP9145) 72 * 73 * Reminder: 74 * C_CC bit (character count option) when used in the CS/80 command 75 * 'set options' will cause the tape not to stream. 76 * 77 * TODO: 78 * make filesystem compatible 79 * make block mode work according to mtio(4) spec. (if possible) 80 * merge with CS/80 disk driver 81 * finish support of HP9145 82 */ 83 84 #include <sys/cdefs.h> 85 __KERNEL_RCSID(0, "$NetBSD: ct.c,v 1.25 2014/03/16 05:20:27 dholland Exp $"); 86 87 #include <sys/param.h> 88 #include <sys/systm.h> 89 #include <sys/buf.h> 90 #include <sys/bufq.h> 91 #include <sys/conf.h> 92 #include <sys/device.h> 93 #include <sys/ioctl.h> 94 #include <sys/mtio.h> 95 #include <sys/proc.h> 96 #include <sys/tprintf.h> 97 98 #include <dev/gpib/ctreg.h> /* XXX must be before cs80busvar.h ATM */ 99 100 #include <dev/gpib/gpibvar.h> 101 #include <dev/gpib/cs80busvar.h> 102 103 /* number of eof marks to remember */ 104 #define EOFS 128 105 106 #ifdef DEBUG 107 int ctdebug = 0xff; 108 #define CDB_FILES 0x01 109 #define CDB_BSF 0x02 110 #define CDB_IDENT 0x04 111 #define CDB_FAIL 0x08 112 #define CDB_FOLLOW 0x10 113 #define DPRINTF(mask, str) if (ctdebug & (mask)) printf str 114 #else 115 #define DPRINTF(mask, str) /* nothing */ 116 #endif 117 118 struct ct_softc { 119 device_t sc_dev; 120 121 gpib_chipset_tag_t sc_ic; 122 gpib_handle_t sc_hdl; 123 124 int sc_slave; /* GPIB slave ID */ 125 int sc_punit; /* physical unit */ 126 struct ct_iocmd sc_ioc; 127 struct ct_rscmd sc_rsc; 128 struct cs80_stat sc_stat; 129 struct bufq_state *sc_tab; 130 int sc_active; 131 struct buf *sc_bp; 132 struct buf sc_bufstore; /* XXX */ 133 int sc_blkno; 134 int sc_cmd; 135 int sc_resid; 136 char *sc_addr; 137 int sc_flags; 138 #define CTF_OPEN 0x01 139 #define CTF_ALIVE 0x02 140 #define CTF_WRT 0x04 141 #define CTF_CMD 0x08 142 #define CTF_IO 0x10 143 #define CTF_BEOF 0x20 144 #define CTF_AEOF 0x40 145 #define CTF_EOT 0x80 146 #define CTF_STATWAIT 0x100 147 #define CTF_CANSTREAM 0x200 148 #define CTF_WRTTN 0x400 149 short sc_type; 150 tpr_t sc_tpr; 151 int sc_eofp; 152 int sc_eofs[EOFS]; 153 }; 154 155 int ctmatch(device_t, cfdata_t, void *); 156 void ctattach(device_t, device_t, void *); 157 158 CFATTACH_DECL_NEW(ct, sizeof(struct ct_softc), 159 ctmatch, ctattach, NULL, NULL); 160 161 int ctident(device_t, struct ct_softc *, 162 struct cs80bus_attach_args *); 163 164 int ctlookup(int, int, int); 165 void ctaddeof(struct ct_softc *); 166 void ctustart(struct ct_softc *); 167 void cteof(struct ct_softc *, struct buf *); 168 void ctdone(struct ct_softc *, struct buf *); 169 170 void ctcallback(void *, int); 171 void ctstart(struct ct_softc *); 172 void ctintr(struct ct_softc *); 173 174 void ctcommand(dev_t, int, int); 175 176 dev_type_open(ctopen); 177 dev_type_close(ctclose); 178 dev_type_read(ctread); 179 dev_type_write(ctwrite); 180 dev_type_ioctl(ctioctl); 181 dev_type_strategy(ctstrategy); 182 183 const struct bdevsw ct_bdevsw = { 184 .d_open = ctopen, 185 .d_close = ctclose, 186 .d_strategy = ctstrategy, 187 .d_ioctl = ctioctl, 188 .d_dump = nodump, 189 .d_psize = nosize, 190 .d_flag = D_TAPE 191 }; 192 193 const struct cdevsw ct_cdevsw = { 194 .d_open = ctopen, 195 .d_close = ctclose, 196 .d_read = ctread, 197 .d_write = ctwrite, 198 .d_ioctl = ctioctl, 199 .d_stop = nostop, 200 .d_tty = notty, 201 .d_poll = nopoll, 202 .d_mmap = nommap, 203 .d_kqfilter = nokqfilter, 204 .d_flag = D_TAPE 205 }; 206 207 extern struct cfdriver ct_cd; 208 209 struct ctinfo { 210 short hwid; 211 short punit; 212 const char *desc; 213 } ctinfo[] = { 214 { CT7946ID, 1, "7946A" }, 215 { CT7912PID, 1, "7912P" }, 216 { CT7914PID, 1, "7914P" }, 217 { CT9144ID, 0, "9144" }, 218 { CT9145ID, 0, "9145" }, 219 { CT35401ID, 0, "35401A"}, 220 }; 221 int nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]); 222 223 #define CT_NOREW 4 224 #define CT_STREAM 8 225 #define CTUNIT(x) (minor(x) & 0x03) 226 227 int 228 ctlookup(int id, int slave, int punit) 229 { 230 int i; 231 232 for (i = 0; i < nctinfo; i++) 233 if (ctinfo[i].hwid == id) 234 break; 235 if (i == nctinfo) 236 return (-1); 237 return (i); 238 } 239 240 int 241 ctmatch(device_t parent, cfdata_t match, void *aux) 242 { 243 struct cs80bus_attach_args *ca = aux; 244 int i; 245 246 if ((i = ctlookup(ca->ca_id, ca->ca_slave, ca->ca_punit)) < 0) 247 return (0); 248 ca->ca_punit = ctinfo[i].punit; 249 return (1); 250 } 251 252 void 253 ctattach(device_t parent, device_t self, void *aux) 254 { 255 struct ct_softc *sc = device_private(self); 256 struct cs80bus_attach_args *ca = aux; 257 struct cs80_description csd; 258 char name[7]; 259 int type, i, n, canstream = 0; 260 261 sc->sc_ic = ca->ca_ic; 262 sc->sc_slave = ca->ca_slave; 263 sc->sc_punit = ca->ca_punit; 264 265 if ((type = ctlookup(ca->ca_id, ca->ca_slave, ca->ca_punit)) < 0) 266 return; 267 268 if (cs80reset(parent, sc->sc_slave, sc->sc_punit)) { 269 aprint_normal("\n"); 270 aprint_error_dev(sc->sc_dev, "can't reset device\n"); 271 return; 272 } 273 274 if (cs80describe(parent, sc->sc_slave, sc->sc_punit, &csd)) { 275 aprint_normal("\n"); 276 aprint_error_dev(sc->sc_dev, "didn't respond to describe command\n"); 277 return; 278 } 279 memset(name, 0, sizeof(name)); 280 for (i=0, n=0; i<3; i++) { 281 name[n++] = (csd.d_name[i] >> 4) + '0'; 282 name[n++] = (csd.d_name[i] & 0x0f) + '0'; 283 } 284 285 #ifdef DEBUG 286 if (ctdebug & CDB_IDENT) { 287 printf("\n%s: name: ('%s')\n", 288 device_xname(sc->sc_dev),name); 289 printf(" iuw %x, maxxfr %d, ctype %d\n", 290 csd.d_iuw, csd.d_cmaxxfr, csd.d_ctype); 291 printf(" utype %d, bps %d, blkbuf %d, burst %d, blktime %d\n", 292 csd.d_utype, csd.d_sectsize, 293 csd.d_blkbuf, csd.d_burstsize, csd.d_blocktime); 294 printf(" avxfr %d, ort %d, atp %d, maxint %d, fv %x, rv %x\n", 295 csd.d_uavexfr, csd.d_retry, csd.d_access, 296 csd.d_maxint, csd.d_fvbyte, csd.d_rvbyte); 297 printf(" maxcyl/head/sect %d/%d/%d, maxvsect %d, inter %d\n", 298 csd.d_maxcylhead >> 8 , csd.d_maxcylhead & 0xff, 299 csd.d_maxsect, csd.d_maxvsectl, csd.d_interleave); 300 printf("%s", device_xname(sc->sc_dev)); 301 } 302 #endif 303 304 switch (ca->ca_id) { 305 case CT7946ID: 306 if (memcmp(name, "079450", 6) == 0) 307 return; /* not really a 7946 */ 308 /* fall into... */ 309 case CT9144ID: 310 case CT9145ID: 311 case CT35401ID: 312 sc->sc_type = CT9144; 313 canstream = 1; 314 break; 315 316 case CT7912PID: 317 case CT7914PID: 318 sc->sc_type = CT88140; 319 break; 320 default: 321 sc->sc_type = type; 322 break; 323 } 324 325 sc->sc_type = type; 326 sc->sc_flags = canstream ? CTF_CANSTREAM : 0; 327 printf(": %s %stape\n", ctinfo[type].desc, 328 canstream ? "streaming " : ""); 329 330 bufq_alloc(&sc->sc_tab, "fcfs", 0); 331 332 if (gpibregister(sc->sc_ic, sc->sc_slave, ctcallback, sc, 333 &sc->sc_hdl)) { 334 aprint_error_dev(sc->sc_dev, "can't register callback\n"); 335 return; 336 } 337 338 sc->sc_flags |= CTF_ALIVE; 339 } 340 341 /*ARGSUSED*/ 342 int 343 ctopen(dev_t dev, int flag, int type, struct lwp *l) 344 { 345 struct ct_softc *sc; 346 u_int8_t opt; 347 348 sc = device_lookup_private(&ct_cd, CTUNIT(dev)); 349 if (sc == NULL || (sc->sc_flags & CTF_ALIVE) == 0) 350 return (ENXIO); 351 352 if (sc->sc_flags & CTF_OPEN) 353 return (EBUSY); 354 355 if ((dev & CT_STREAM) && (sc->sc_flags & CTF_CANSTREAM)) 356 opt = C_SPAR | C_IMRPT; 357 else 358 opt = C_SPAR; 359 360 if (cs80setoptions(device_parent(sc->sc_dev), sc->sc_slave, 361 sc->sc_punit, opt)) 362 return (EBUSY); 363 364 sc->sc_tpr = tprintf_open(l->l_proc); 365 sc->sc_flags |= CTF_OPEN; 366 367 return (0); 368 } 369 370 /*ARGSUSED*/ 371 int 372 ctclose(dev_t dev, int flag, int fmt, struct lwp *l) 373 { 374 struct ct_softc *sc; 375 376 sc = device_lookup_private(&ct_cd, CTUNIT(dev)); 377 if (sc == NULL) 378 return (ENXIO); 379 380 if ((sc->sc_flags & (CTF_WRT|CTF_WRTTN)) == (CTF_WRT|CTF_WRTTN) && 381 (sc->sc_flags & CTF_EOT) == 0 ) { /* XXX return error if EOT ?? */ 382 ctcommand(dev, MTWEOF, 2); 383 ctcommand(dev, MTBSR, 1); 384 if (sc->sc_eofp == EOFS - 1) 385 sc->sc_eofs[EOFS - 1]--; 386 else 387 sc->sc_eofp--; 388 DPRINTF(CDB_BSF, ("%s: ctclose backup eofs prt %d blk %d\n", 389 device_xname(sc->sc_dev), sc->sc_eofp, 390 sc->sc_eofs[sc->sc_eofp])); 391 } 392 393 if ((minor(dev) & CT_NOREW) == 0) 394 ctcommand(dev, MTREW, 1); 395 sc->sc_flags &= ~(CTF_OPEN | CTF_WRT | CTF_WRTTN); 396 tprintf_close(sc->sc_tpr); 397 DPRINTF(CDB_FILES, ("ctclose: flags %x\n", sc->sc_flags)); 398 399 return (0); /* XXX */ 400 } 401 402 void 403 ctcommand(dev_t dev, int cmd, int cnt) 404 { 405 struct ct_softc *sc; 406 struct buf *bp; 407 struct buf *nbp = 0; 408 409 sc = device_lookup_private(&ct_cd, CTUNIT(dev)); 410 bp = &sc->sc_bufstore; 411 412 DPRINTF(CDB_FOLLOW, ("ctcommand: called\n")); 413 414 if (cmd == MTBSF && sc->sc_eofp == EOFS - 1) { 415 cnt = sc->sc_eofs[EOFS - 1] - cnt; 416 ctcommand(dev, MTREW, 1); 417 ctcommand(dev, MTFSF, cnt); 418 cnt = 2; 419 cmd = MTBSR; 420 } 421 422 if (cmd == MTBSF && sc->sc_eofp - cnt < 0) { 423 cnt = 1; 424 cmd = MTREW; 425 } 426 427 sc->sc_flags |= CTF_CMD; 428 sc->sc_bp = bp; 429 sc->sc_cmd = cmd; 430 bp->b_dev = dev; 431 bp->b_objlock = &buffer_lock; 432 if (cmd == MTFSF) { 433 nbp = (struct buf *)geteblk(MAXBSIZE); 434 bp->b_data = nbp->b_data; 435 bp->b_bcount = MAXBSIZE; 436 } 437 438 while (cnt-- > 0) { 439 bp->b_flags = 0; 440 bp->b_cflags = BC_BUSY; 441 bp->b_oflags = 0; 442 if (cmd == MTBSF) { 443 sc->sc_blkno = sc->sc_eofs[sc->sc_eofp]; 444 sc->sc_eofp--; 445 DPRINTF(CDB_BSF, ("%s: backup eof pos %d blk %d\n", 446 device_xname(sc->sc_dev), sc->sc_eofp, 447 sc->sc_eofs[sc->sc_eofp])); 448 } 449 ctstrategy(bp); 450 biowait(bp); 451 } 452 bp->b_flags = 0; 453 sc->sc_flags &= ~CTF_CMD; 454 if (nbp) 455 brelse(nbp, 0); 456 } 457 458 void 459 ctstrategy(struct buf *bp) 460 { 461 struct ct_softc *sc; 462 int s; 463 464 DPRINTF(CDB_FOLLOW, ("cdstrategy(%p): dev %" PRIx64 ", bn %" PRIx64 465 ", bcount %x, %c\n", 466 bp, bp->b_dev, bp->b_blkno, bp->b_bcount, 467 (bp->b_flags & B_READ) ? 'R' : 'W')); 468 469 sc = device_lookup_private(&ct_cd, CTUNIT(bp->b_dev)); 470 471 s = splbio(); 472 bufq_put(sc->sc_tab, bp); 473 if (sc->sc_active == 0) { 474 sc->sc_active = 1; 475 ctustart(sc); 476 } 477 splx(s); 478 } 479 480 void 481 ctustart(struct ct_softc *sc) 482 { 483 struct buf *bp; 484 485 bp = bufq_peek(sc->sc_tab); 486 sc->sc_addr = bp->b_data; 487 sc->sc_resid = bp->b_bcount; 488 if (gpibrequest(sc->sc_ic, sc->sc_hdl)) 489 ctstart(sc); 490 } 491 492 void 493 ctstart(struct ct_softc *sc) 494 { 495 struct buf *bp; 496 struct ct_ulcmd ul; 497 struct ct_wfmcmd wfm; 498 int i, slave, punit; 499 500 slave = sc->sc_slave; 501 punit = sc->sc_punit; 502 503 bp = bufq_peek(sc->sc_tab); 504 if ((sc->sc_flags & CTF_CMD) && sc->sc_bp == bp) { 505 switch(sc->sc_cmd) { 506 case MTFSF: 507 bp->b_flags |= B_READ; 508 goto mustio; 509 510 case MTBSF: 511 goto gotaddr; 512 513 case MTOFFL: 514 sc->sc_blkno = 0; 515 ul.unit = CS80CMD_SUNIT(punit); 516 ul.cmd = CS80CMD_UNLOAD; 517 (void) cs80send(device_parent(sc->sc_dev), slave, 518 punit, CS80CMD_SCMD, &ul, sizeof(ul)); 519 break; 520 521 case MTWEOF: 522 sc->sc_blkno++; 523 sc->sc_flags |= CTF_WRT; 524 wfm.unit = CS80CMD_SUNIT(sc->sc_punit); 525 wfm.cmd = CS80CMD_WFM; 526 (void) cs80send(device_parent(sc->sc_dev), slave, 527 punit, CS80CMD_SCMD, &wfm, sizeof(wfm)); 528 ctaddeof(sc); 529 break; 530 531 case MTBSR: 532 sc->sc_blkno--; 533 goto gotaddr; 534 535 case MTFSR: 536 sc->sc_blkno++; 537 goto gotaddr; 538 539 case MTREW: 540 sc->sc_blkno = 0; 541 DPRINTF(CDB_BSF, ("%s: clearing eofs\n", 542 device_xname(sc->sc_dev))); 543 for (i=0; i<EOFS; i++) 544 sc->sc_eofs[i] = 0; 545 sc->sc_eofp = 0; 546 547 gotaddr: 548 sc->sc_ioc.unit = CS80CMD_SUNIT(sc->sc_punit); 549 sc->sc_ioc.saddr = CS80CMD_SADDR; 550 sc->sc_ioc.addr0 = 0; 551 sc->sc_ioc.addr = htobe32(sc->sc_blkno); 552 sc->sc_ioc.nop2 = CS80CMD_NOP; 553 sc->sc_ioc.slen = CS80CMD_SLEN; 554 sc->sc_ioc.len = htobe32(0); 555 sc->sc_ioc.nop3 = CS80CMD_NOP; 556 sc->sc_ioc.cmd = CS80CMD_READ; 557 (void) cs80send(device_parent(sc->sc_dev), slave, 558 punit, CS80CMD_SCMD, &sc->sc_ioc, 559 sizeof(sc->sc_ioc)); 560 break; 561 } 562 } else { 563 mustio: 564 if ((bp->b_flags & B_READ) && 565 sc->sc_flags & (CTF_BEOF|CTF_EOT)) { 566 DPRINTF(CDB_FILES, ("ctstart: before %x\n", 567 sc->sc_flags)); 568 if (sc->sc_flags & CTF_BEOF) { 569 sc->sc_flags &= ~CTF_BEOF; 570 sc->sc_flags |= CTF_AEOF; 571 DPRINTF(CDB_FILES, ("ctstart: after %x\n", 572 sc->sc_flags)); 573 } 574 bp->b_resid = bp->b_bcount; 575 ctdone(sc, bp); 576 return; 577 } 578 sc->sc_flags |= CTF_IO; 579 sc->sc_ioc.unit = CS80CMD_SUNIT(sc->sc_punit); 580 sc->sc_ioc.saddr = CS80CMD_SADDR; 581 sc->sc_ioc.addr0 = 0; 582 sc->sc_ioc.addr = htobe32(sc->sc_blkno); 583 sc->sc_ioc.nop2 = CS80CMD_NOP; 584 sc->sc_ioc.slen = CS80CMD_SLEN; 585 sc->sc_ioc.len = htobe32(sc->sc_resid); 586 sc->sc_ioc.nop3 = CS80CMD_NOP; 587 if (bp->b_flags & B_READ) 588 sc->sc_ioc.cmd = CS80CMD_READ; 589 else { 590 sc->sc_ioc.cmd = CS80CMD_WRITE; 591 sc->sc_flags |= (CTF_WRT | CTF_WRTTN); 592 } 593 (void) cs80send(device_parent(sc->sc_dev), slave, punit, 594 CS80CMD_SCMD, &sc->sc_ioc, sizeof(sc->sc_ioc)); 595 } 596 gpibawait(sc->sc_ic); 597 } 598 599 /* 600 * Hideous grue to handle EOF/EOT (mostly for reads) 601 */ 602 void 603 cteof(struct ct_softc *sc, struct buf *bp) 604 { 605 long blks; 606 607 /* 608 * EOT on a write is an error. 609 */ 610 if ((bp->b_flags & B_READ) == 0) { 611 bp->b_resid = bp->b_bcount; 612 bp->b_error = ENOSPC; 613 sc->sc_flags |= CTF_EOT; 614 return; 615 } 616 /* 617 * Use returned block position to determine how many blocks 618 * we really read and update b_resid. 619 */ 620 blks = sc->sc_stat.c_blk - sc->sc_blkno - 1; 621 DPRINTF(CDB_FILES, ("cteof: bc %d oblk %d nblk %d read %ld, resid %ld\n", 622 bp->b_bcount, sc->sc_blkno, sc->sc_stat.c_blk, 623 blks, bp->b_bcount - CTKTOB(blks))); 624 if (blks == -1) { /* 9145 on EOF does not change sc_stat.c_blk */ 625 blks = 0; 626 sc->sc_blkno++; 627 } 628 else { 629 sc->sc_blkno = sc->sc_stat.c_blk; 630 } 631 bp->b_resid = bp->b_bcount - CTKTOB(blks); 632 /* 633 * If we are at physical EOV or were after an EOF, 634 * we are now at logical EOT. 635 */ 636 if ((sc->sc_stat.c_aef & AEF_EOV) || 637 (sc->sc_flags & CTF_AEOF)) { 638 sc->sc_flags |= CTF_EOT; 639 sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF); 640 } 641 /* 642 * If we were before an EOF or we have just completed a FSF, 643 * we are now after EOF. 644 */ 645 else if ((sc->sc_flags & CTF_BEOF) || 646 ((sc->sc_flags & CTF_CMD) && sc->sc_cmd == MTFSF)) { 647 sc->sc_flags |= CTF_AEOF; 648 sc->sc_flags &= ~CTF_BEOF; 649 } 650 /* 651 * Otherwise if we read something we are now before EOF 652 * (and no longer after EOF). 653 */ 654 else if (blks) { 655 sc->sc_flags |= CTF_BEOF; 656 sc->sc_flags &= ~CTF_AEOF; 657 } 658 /* 659 * Finally, if we didn't read anything we just passed an EOF 660 */ 661 else 662 sc->sc_flags |= CTF_AEOF; 663 DPRINTF(CDB_FILES, ("cteof: leaving flags %x\n", sc->sc_flags)); 664 } 665 666 667 void 668 ctcallback(void *v, int action) 669 { 670 struct ct_softc *sc = v; 671 672 DPRINTF(CDB_FOLLOW, ("ctcallback: v=%p, action=%d\n", v, action)); 673 674 switch (action) { 675 case GPIBCBF_START: 676 ctstart(sc); 677 break; 678 case GPIBCBF_INTR: 679 ctintr(sc); 680 break; 681 #ifdef DEBUG 682 default: 683 DPRINTF(CDB_FAIL, ("ctcallback: unknown action %d\n", action)); 684 break; 685 #endif 686 } 687 } 688 689 void 690 ctintr(struct ct_softc *sc) 691 { 692 struct buf *bp; 693 u_int8_t stat; 694 int slave, punit; 695 int dir; 696 697 slave = sc->sc_slave; 698 punit = sc->sc_punit; 699 700 bp = bufq_peek(sc->sc_tab); 701 if (bp == NULL) { 702 aprint_error_dev(sc->sc_dev, "bp == NULL\n"); 703 return; 704 } 705 if (sc->sc_flags & CTF_IO) { 706 sc->sc_flags &= ~CTF_IO; 707 dir = (bp->b_flags & B_READ ? GPIB_READ : GPIB_WRITE); 708 gpibxfer(sc->sc_ic, slave, CS80CMD_EXEC, sc->sc_addr, 709 sc->sc_resid, dir, dir == GPIB_READ); 710 return; 711 } 712 if ((sc->sc_flags & CTF_STATWAIT) == 0) { 713 if (gpibpptest(sc->sc_ic, slave) == 0) { 714 sc->sc_flags |= CTF_STATWAIT; 715 gpibawait(sc->sc_ic); 716 return; 717 } 718 } else 719 sc->sc_flags &= ~CTF_STATWAIT; 720 (void) gpibrecv(sc->sc_ic, slave, CS80CMD_QSTAT, &stat, 1); 721 DPRINTF(CDB_FILES, ("ctintr: before flags %x\n", sc->sc_flags)); 722 if (stat) { 723 sc->sc_rsc.unit = CS80CMD_SUNIT(punit); 724 sc->sc_rsc.cmd = CS80CMD_STATUS; 725 (void) gpibsend(sc->sc_ic, slave, CS80CMD_SCMD, &sc->sc_rsc, 726 sizeof(sc->sc_rsc)); 727 (void) gpibrecv(sc->sc_ic, slave, CS80CMD_EXEC, &sc->sc_stat, 728 sizeof(sc->sc_stat)); 729 (void) gpibrecv(sc->sc_ic, slave, CS80CMD_QSTAT, &stat, 1); 730 DPRINTF(CDB_FILES, ("ctintr: return stat 0x%x, A%x F%x blk %d\n", 731 stat, sc->sc_stat.c_aef, 732 sc->sc_stat.c_fef, sc->sc_stat.c_blk)); 733 if (stat == 0) { 734 if (sc->sc_stat.c_aef & (AEF_EOF | AEF_EOV)) { 735 cteof(sc, bp); 736 ctaddeof(sc); 737 goto done; 738 } 739 if (sc->sc_stat.c_fef & FEF_PF) { 740 cs80reset(sc, slave, punit); 741 ctstart(sc); 742 return; 743 } 744 if (sc->sc_stat.c_fef & FEF_REXMT) { 745 ctstart(sc); 746 return; 747 } 748 if (sc->sc_stat.c_aef & 0x5800) { 749 if (sc->sc_stat.c_aef & 0x4000) 750 tprintf(sc->sc_tpr, 751 "%s: uninitialized media\n", 752 device_xname(sc->sc_dev)); 753 if (sc->sc_stat.c_aef & 0x1000) 754 tprintf(sc->sc_tpr, 755 "%s: not ready\n", 756 device_xname(sc->sc_dev)); 757 if (sc->sc_stat.c_aef & 0x0800) 758 tprintf(sc->sc_tpr, 759 "%s: write protect\n", 760 device_xname(sc->sc_dev)); 761 } else { 762 printf("%s err: v%d u%d ru%d bn%d, ", 763 device_xname(sc->sc_dev), 764 (sc->sc_stat.c_vu>>4)&0xF, 765 sc->sc_stat.c_vu&0xF, 766 sc->sc_stat.c_pend, 767 sc->sc_stat.c_blk); 768 printf("R0x%x F0x%x A0x%x I0x%x\n", 769 sc->sc_stat.c_ref, 770 sc->sc_stat.c_fef, 771 sc->sc_stat.c_aef, 772 sc->sc_stat.c_ief); 773 } 774 } else 775 aprint_error_dev(sc->sc_dev, "request status failed\n"); 776 bp->b_error = EIO; 777 goto done; 778 } else 779 bp->b_resid = 0; 780 if (sc->sc_flags & CTF_CMD) { 781 switch (sc->sc_cmd) { 782 case MTFSF: 783 sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF); 784 sc->sc_blkno += CTBTOK(sc->sc_resid); 785 ctstart(sc); 786 return; 787 case MTBSF: 788 sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF|CTF_EOT); 789 break; 790 case MTBSR: 791 sc->sc_flags &= ~CTF_BEOF; 792 if (sc->sc_flags & CTF_EOT) { 793 sc->sc_flags |= CTF_AEOF; 794 sc->sc_flags &= ~CTF_EOT; 795 } else if (sc->sc_flags & CTF_AEOF) { 796 sc->sc_flags |= CTF_BEOF; 797 sc->sc_flags &= ~CTF_AEOF; 798 } 799 break; 800 case MTWEOF: 801 sc->sc_flags &= ~CTF_BEOF; 802 if (sc->sc_flags & (CTF_AEOF|CTF_EOT)) { 803 sc->sc_flags |= CTF_EOT; 804 sc->sc_flags &= ~CTF_AEOF; 805 } else 806 sc->sc_flags |= CTF_AEOF; 807 break; 808 case MTREW: 809 case MTOFFL: 810 sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF|CTF_EOT); 811 break; 812 } 813 } else { 814 sc->sc_flags &= ~CTF_AEOF; 815 sc->sc_blkno += CTBTOK(sc->sc_resid); 816 } 817 done: 818 DPRINTF(CDB_FILES, ("ctintr: after flags %x\n", sc->sc_flags)); 819 ctdone(sc, bp); 820 } 821 822 void 823 ctdone(struct ct_softc *sc, struct buf *bp) 824 { 825 826 (void)bufq_get(sc->sc_tab); 827 biodone(bp); 828 gpibrelease(sc->sc_ic, sc->sc_hdl); 829 if (bufq_peek(sc->sc_tab) == NULL) { 830 sc->sc_active = 0; 831 return; 832 } 833 ctustart(sc); 834 } 835 836 int 837 ctread(dev_t dev, struct uio *uio, int flags) 838 { 839 return (physio(ctstrategy, NULL, dev, B_READ, minphys, uio)); 840 } 841 842 int 843 ctwrite(dev_t dev, struct uio *uio, int flags) 844 { 845 /* XXX: check for hardware write-protect? */ 846 return (physio(ctstrategy, NULL, dev, B_WRITE, minphys, uio)); 847 } 848 849 /*ARGSUSED*/ 850 int 851 ctioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 852 { 853 struct mtop *op; 854 int cnt; 855 856 switch (cmd) { 857 858 case MTIOCTOP: 859 op = (struct mtop *)data; 860 switch(op->mt_op) { 861 862 case MTWEOF: 863 case MTFSF: 864 case MTBSR: 865 case MTBSF: 866 case MTFSR: 867 cnt = op->mt_count; 868 break; 869 870 case MTREW: 871 case MTOFFL: 872 cnt = 1; 873 break; 874 875 default: 876 return (EINVAL); 877 } 878 ctcommand(dev, op->mt_op, cnt); 879 break; 880 881 case MTIOCGET: 882 break; 883 884 default: 885 return (EINVAL); 886 } 887 return (0); 888 } 889 890 void 891 ctaddeof(struct ct_softc *sc) 892 { 893 894 if (sc->sc_eofp == EOFS - 1) 895 sc->sc_eofs[EOFS - 1]++; 896 else { 897 sc->sc_eofp++; 898 if (sc->sc_eofp == EOFS - 1) 899 sc->sc_eofs[EOFS - 1] = EOFS; 900 else 901 /* save blkno */ 902 sc->sc_eofs[sc->sc_eofp] = sc->sc_blkno - 1; 903 } 904 DPRINTF(CDB_BSF, ("%s: add eof pos %d blk %d\n", 905 device_xname(sc->sc_dev), sc->sc_eofp, 906 sc->sc_eofs[sc->sc_eofp])); 907 } 908