1 /* $NetBSD: ct.c,v 1.21 1997/04/02 22:37:23 scottr Exp $ */ 2 3 /* 4 * Copyright (c) 1996, 1997 Jason R. Thorpe. All rights reserved. 5 * Copyright (c) 1982, 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)ct.c 8.2 (Berkeley) 1/12/94 37 */ 38 39 /* 40 * CS80 cartridge tape driver (9144, 88140, 9145) 41 * 42 * Reminder: 43 * C_CC bit (character count option) when used in the CS/80 command 44 * 'set options' will cause the tape not to stream. 45 * 46 * TODO: 47 * make filesystem compatible 48 * make block mode work according to mtio(4) spec. (if possible) 49 * merge with cs80 disk driver 50 * finish support of 9145 51 */ 52 53 #include <sys/param.h> 54 #include <sys/systm.h> 55 #include <sys/buf.h> 56 #include <sys/conf.h> 57 #include <sys/device.h> 58 #include <sys/ioctl.h> 59 #include <sys/mtio.h> 60 #include <sys/proc.h> 61 #include <sys/tprintf.h> 62 63 #include <hp300/dev/hpibvar.h> 64 65 #include <hp300/dev/ctreg.h> 66 67 /* number of eof marks to remember */ 68 #define EOFS 128 69 70 struct ct_softc { 71 struct device sc_dev; 72 int sc_slave; /* HP-IB slave ID */ 73 int sc_punit; /* physical unit */ 74 struct ct_iocmd sc_ioc; 75 struct ct_rscmd sc_rsc; 76 struct ct_stat sc_stat; 77 struct ct_ssmcmd sc_ssmc; 78 struct ct_srcmd sc_src; 79 struct ct_soptcmd sc_soptc; 80 struct ct_ulcmd sc_ul; 81 struct ct_wfmcmd sc_wfm; 82 struct ct_clearcmd sc_clear; 83 struct buf sc_tab; 84 struct buf *sc_bp; 85 struct buf sc_bufstore; /* XXX */ 86 int sc_blkno; 87 int sc_cmd; 88 int sc_resid; 89 char *sc_addr; 90 int sc_flags; 91 short sc_type; 92 tpr_t sc_tpr; 93 struct hpibqueue sc_hq; /* entry on hpib job queue */ 94 int sc_eofp; 95 int sc_eofs[EOFS]; 96 }; 97 98 /* flags */ 99 #define CTF_OPEN 0x01 100 #define CTF_ALIVE 0x02 101 #define CTF_WRT 0x04 102 #define CTF_CMD 0x08 103 #define CTF_IO 0x10 104 #define CTF_BEOF 0x20 105 #define CTF_AEOF 0x40 106 #define CTF_EOT 0x80 107 #define CTF_STATWAIT 0x100 108 #define CTF_CANSTREAM 0x200 109 #define CTF_WRTTN 0x400 110 111 int ctmatch __P((struct device *, struct cfdata *, void *)); 112 void ctattach __P((struct device *, struct device *, void *)); 113 114 struct cfattach ct_ca = { 115 sizeof(struct ct_softc), ctmatch, ctattach 116 }; 117 118 struct cfdriver ct_cd = { 119 NULL, "ct", DV_TAPE 120 }; 121 122 int ctident __P((struct device *, struct ct_softc *, 123 struct hpibbus_attach_args *)); 124 125 void ctreset __P((struct ct_softc *)); 126 void ctaddeof __P((struct ct_softc *)); 127 void ctustart __P((struct ct_softc *)); 128 void cteof __P((struct ct_softc *, struct buf *)); 129 void ctdone __P((struct ct_softc *, struct buf *)); 130 131 void ctstart __P((void *)); 132 void ctgo __P((void *)); 133 void ctintr __P((void *)); 134 135 void ctcommand __P((dev_t, int, int)); 136 137 cdev_decl(ct); 138 bdev_decl(ct); 139 140 struct ctinfo { 141 short hwid; 142 short punit; 143 char *desc; 144 } ctinfo[] = { 145 { CT7946ID, 1, "7946A" }, 146 { CT7912PID, 1, "7912P" }, 147 { CT7914PID, 1, "7914P" }, 148 { CT9144ID, 0, "9144" }, 149 { CT9145ID, 0, "9145" }, 150 }; 151 int nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]); 152 153 #define CT_NOREW 4 154 #define CT_STREAM 8 155 #define UNIT(x) (minor(x) & 3) 156 #define ctpunit(x) ((x) & 7) 157 158 #ifdef DEBUG 159 int ctdebug = 0; 160 #define CDB_FILES 0x01 161 #define CT_BSF 0x02 162 #endif 163 164 int 165 ctmatch(parent, match, aux) 166 struct device *parent; 167 struct cfdata *match; 168 void *aux; 169 { 170 struct hpibbus_attach_args *ha = aux; 171 172 return (ctident(parent, NULL, ha)); 173 } 174 175 void 176 ctattach(parent, self, aux) 177 struct device *parent, *self; 178 void *aux; 179 { 180 struct ct_softc *sc = (struct ct_softc *)self; 181 struct hpibbus_attach_args *ha = aux; 182 183 if (ctident(parent, sc, ha) == 0) { 184 printf("\n%s: didn't respond to describe command!\n", 185 sc->sc_dev.dv_xname); 186 return; 187 } 188 189 sc->sc_slave = ha->ha_slave; 190 sc->sc_punit = ha->ha_punit; 191 192 sc->sc_tab.b_actb = &sc->sc_tab.b_actf; 193 194 /* Initialize hpib job queue entry. */ 195 sc->sc_hq.hq_softc = sc; 196 sc->sc_hq.hq_slave = sc->sc_slave; 197 sc->sc_hq.hq_start = ctstart; 198 sc->sc_hq.hq_go = ctgo; 199 sc->sc_hq.hq_intr = ctintr; 200 201 ctreset(sc); 202 sc->sc_flags |= CTF_ALIVE; 203 } 204 205 int 206 ctident(parent, sc, ha) 207 struct device *parent; 208 struct ct_softc *sc; 209 struct hpibbus_attach_args *ha; 210 { 211 struct ct_describe desc; 212 u_char stat, cmd[3]; 213 char name[7]; 214 int i, id, n, type, canstream; 215 216 type = canstream = 0; 217 218 /* Verify that we have a CS80 device. */ 219 if ((ha->ha_id & 0x200) == 0) 220 return (0); 221 222 /* Is it one of the tapes we support? */ 223 for (id = 0; id < nctinfo; id++) 224 if (ha->ha_id == ctinfo[id].hwid) 225 break; 226 if (id == nctinfo) 227 return (0); 228 229 ha->ha_punit = ctinfo[id].punit; 230 231 /* 232 * So far, so good. Get drive parameters. Note command 233 * is always issued to unit 0. 234 */ 235 cmd[0] = C_SUNIT(0); 236 cmd[1] = C_SVOL(0); 237 cmd[2] = C_DESC; 238 hpibsend(parent->dv_unit, ha->ha_slave, C_CMD, cmd, sizeof(cmd)); 239 hpibrecv(parent->dv_unit, ha->ha_slave, C_EXEC, &desc, 37); 240 hpibrecv(parent->dv_unit, ha->ha_slave, C_QSTAT, &stat, sizeof(stat)); 241 242 bzero(name, sizeof(name)); 243 if (stat == 0) { 244 n = desc.d_name; 245 for (i = 5; i >= 0; i--) { 246 name[i] = (n & 0xf) + '0'; 247 n >>= 4; 248 } 249 } 250 251 switch (ha->ha_id) { 252 case CT7946ID: 253 if (bcmp(name, "079450", 6) == 0) 254 return (0); /* not really a 7946 */ 255 /* fall into... */ 256 case CT9144ID: 257 case CT9145ID: 258 type = CT9144; 259 canstream = 1; 260 break; 261 262 case CT7912PID: 263 case CT7914PID: 264 type = CT88140; 265 break; 266 } 267 268 if (sc != NULL) { 269 sc->sc_type = type; 270 sc->sc_flags = canstream ? CTF_CANSTREAM : 0; 271 printf(": %s %stape\n", ctinfo[id].desc, 272 canstream ? "streaming " : ""); 273 } 274 275 return (1); 276 } 277 278 void 279 ctreset(sc) 280 struct ct_softc *sc; 281 { 282 int ctlr, slave; 283 u_char stat; 284 285 ctlr = sc->sc_dev.dv_parent->dv_unit; 286 slave = sc->sc_slave; 287 288 sc->sc_clear.unit = C_SUNIT(sc->sc_punit); 289 sc->sc_clear.cmd = C_CLEAR; 290 hpibsend(ctlr, slave, C_TCMD, &sc->sc_clear, sizeof(sc->sc_clear)); 291 hpibswait(ctlr, slave); 292 hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat)); 293 294 sc->sc_src.unit = C_SUNIT(CTCTLR); 295 sc->sc_src.nop = C_NOP; 296 sc->sc_src.cmd = C_SREL; 297 sc->sc_src.param = C_REL; 298 hpibsend(ctlr, slave, C_CMD, &sc->sc_src, sizeof(sc->sc_src)); 299 hpibswait(ctlr, slave); 300 hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat)); 301 302 sc->sc_ssmc.unit = C_SUNIT(sc->sc_punit); 303 sc->sc_ssmc.cmd = C_SSM; 304 sc->sc_ssmc.refm = REF_MASK; 305 sc->sc_ssmc.fefm = FEF_MASK; 306 sc->sc_ssmc.aefm = AEF_MASK; 307 sc->sc_ssmc.iefm = IEF_MASK; 308 hpibsend(ctlr, slave, C_CMD, &sc->sc_ssmc, sizeof(sc->sc_ssmc)); 309 hpibswait(ctlr, slave); 310 hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat)); 311 312 sc->sc_soptc.unit = C_SUNIT(sc->sc_punit); 313 sc->sc_soptc.nop = C_NOP; 314 sc->sc_soptc.cmd = C_SOPT; 315 sc->sc_soptc.opt = C_SPAR; 316 hpibsend(ctlr, slave, C_CMD, &sc->sc_soptc, sizeof(sc->sc_soptc)); 317 hpibswait(ctlr, slave); 318 hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat)); 319 } 320 321 /*ARGSUSED*/ 322 int 323 ctopen(dev, flag, type, p) 324 dev_t dev; 325 int flag, type; 326 struct proc *p; 327 { 328 struct ct_softc *sc; 329 u_char stat; 330 int cc, ctlr, slave; 331 332 if (UNIT(dev) >= ct_cd.cd_ndevs || 333 (sc = ct_cd.cd_devs[UNIT(dev)]) == NULL || 334 (sc->sc_flags & CTF_ALIVE) == 0) 335 return (ENXIO); 336 337 if (sc->sc_flags & CTF_OPEN) 338 return (EBUSY); 339 340 ctlr = sc->sc_dev.dv_parent->dv_unit; 341 slave = sc->sc_slave; 342 343 sc->sc_soptc.unit = C_SUNIT(sc->sc_punit); 344 sc->sc_soptc.nop = C_NOP; 345 sc->sc_soptc.cmd = C_SOPT; 346 if ((dev & CT_STREAM) && (sc->sc_flags & CTF_CANSTREAM)) 347 sc->sc_soptc.opt = C_SPAR | C_IMRPT; 348 else 349 sc->sc_soptc.opt = C_SPAR; 350 351 /* 352 * Check the return of hpibsend() and hpibswait(). 353 * Drive could be loading/unloading a tape. If not checked, 354 * driver hangs. 355 */ 356 cc = hpibsend(ctlr, slave, C_CMD, &sc->sc_soptc, sizeof(sc->sc_soptc)); 357 if (cc != sizeof(sc->sc_soptc)) 358 return (EBUSY); 359 360 hpibswait(ctlr, slave); 361 cc = hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat)); 362 if (cc != sizeof(stat)) 363 return(EBUSY); 364 365 sc->sc_tpr = tprintf_open(p); 366 sc->sc_flags |= CTF_OPEN; 367 return(0); 368 } 369 370 /*ARGSUSED*/ 371 int 372 ctclose(dev, flag, fmt, p) 373 dev_t dev; 374 int flag, fmt; 375 struct proc *p; 376 { 377 struct ct_softc *sc = ct_cd.cd_devs[UNIT(dev)]; 378 379 if ((sc->sc_flags & (CTF_WRT|CTF_WRTTN)) == (CTF_WRT|CTF_WRTTN) && 380 (sc->sc_flags & CTF_EOT) == 0 ) { /* XXX return error if EOT ?? */ 381 ctcommand(dev, MTWEOF, 2); 382 ctcommand(dev, MTBSR, 1); 383 if (sc->sc_eofp == EOFS - 1) 384 sc->sc_eofs[EOFS - 1]--; 385 else 386 sc->sc_eofp--; 387 #ifdef DEBUG 388 if(ctdebug & CT_BSF) 389 printf("%s: ctclose backup eofs prt %d blk %d\n", 390 sc->sc_dev.dv_xname, sc->sc_eofp, 391 sc->sc_eofs[sc->sc_eofp]); 392 #endif 393 } 394 if ((minor(dev) & CT_NOREW) == 0) 395 ctcommand(dev, MTREW, 1); 396 sc->sc_flags &= ~(CTF_OPEN | CTF_WRT | CTF_WRTTN); 397 tprintf_close(sc->sc_tpr); 398 #ifdef DEBUG 399 if (ctdebug & CDB_FILES) 400 printf("ctclose: flags %x\n", sc->sc_flags); 401 #endif 402 return(0); /* XXX */ 403 } 404 405 void 406 ctcommand(dev, cmd, cnt) 407 dev_t dev; 408 int cmd; 409 int cnt; 410 { 411 struct ct_softc *sc = ct_cd.cd_devs[UNIT(dev)]; 412 struct buf *bp = &sc->sc_bufstore; 413 struct buf *nbp = 0; 414 415 if (cmd == MTBSF && sc->sc_eofp == EOFS - 1) { 416 cnt = sc->sc_eofs[EOFS - 1] - cnt; 417 ctcommand(dev, MTREW, 1); 418 ctcommand(dev, MTFSF, cnt); 419 cnt = 2; 420 cmd = MTBSR; 421 } 422 423 if (cmd == MTBSF && sc->sc_eofp - cnt < 0) { 424 cnt = 1; 425 cmd = MTREW; 426 } 427 428 sc->sc_flags |= CTF_CMD; 429 sc->sc_bp = bp; 430 sc->sc_cmd = cmd; 431 bp->b_dev = dev; 432 if (cmd == MTFSF) { 433 nbp = (struct buf *)geteblk(MAXBSIZE); 434 bp->b_un.b_addr = nbp->b_un.b_addr; 435 bp->b_bcount = MAXBSIZE; 436 } 437 438 while (cnt-- > 0) { 439 bp->b_flags = B_BUSY; 440 if (cmd == MTBSF) { 441 sc->sc_blkno = sc->sc_eofs[sc->sc_eofp]; 442 sc->sc_eofp--; 443 #ifdef DEBUG 444 if (ctdebug & CT_BSF) 445 printf("%s: backup eof pos %d blk %d\n", 446 sc->sc_dev.dv_xname, sc->sc_eofp, 447 sc->sc_eofs[sc->sc_eofp]); 448 #endif 449 } 450 ctstrategy(bp); 451 iowait(bp); 452 } 453 bp->b_flags = 0; 454 sc->sc_flags &= ~CTF_CMD; 455 if (nbp) 456 brelse(nbp); 457 } 458 459 void 460 ctstrategy(bp) 461 struct buf *bp; 462 { 463 struct buf *dp; 464 int s, unit; 465 struct ct_softc *sc; 466 467 unit = UNIT(bp->b_dev); 468 sc = ct_cd.cd_devs[unit]; 469 470 dp = &sc->sc_tab; 471 bp->b_actf = NULL; 472 s = splbio(); 473 bp->b_actb = dp->b_actb; 474 *(dp->b_actb) = bp; 475 dp->b_actb = &bp->b_actf; 476 if (dp->b_active == 0) { 477 dp->b_active = 1; 478 ctustart(sc); 479 } 480 splx(s); 481 } 482 483 void 484 ctustart(sc) 485 struct ct_softc *sc; 486 { 487 struct buf *bp; 488 489 bp = sc->sc_tab.b_actf; 490 sc->sc_addr = bp->b_un.b_addr; 491 sc->sc_resid = bp->b_bcount; 492 if (hpibreq(sc->sc_dev.dv_parent, &sc->sc_hq)) 493 ctstart(sc); 494 } 495 496 void 497 ctstart(arg) 498 void *arg; 499 { 500 struct ct_softc *sc = arg; 501 struct buf *bp; 502 int i, ctlr, slave; 503 504 ctlr = sc->sc_dev.dv_parent->dv_unit; 505 slave = sc->sc_slave; 506 507 bp = sc->sc_tab.b_actf; 508 if ((sc->sc_flags & CTF_CMD) && sc->sc_bp == bp) { 509 switch(sc->sc_cmd) { 510 case MTFSF: 511 bp->b_flags |= B_READ; 512 goto mustio; 513 514 case MTBSF: 515 goto gotaddr; 516 517 case MTOFFL: 518 sc->sc_blkno = 0; 519 sc->sc_ul.unit = C_SUNIT(sc->sc_punit); 520 sc->sc_ul.cmd = C_UNLOAD; 521 hpibsend(ctlr, slave, C_CMD, &sc->sc_ul, 522 sizeof(sc->sc_ul)); 523 break; 524 525 case MTWEOF: 526 sc->sc_blkno++; 527 sc->sc_flags |= CTF_WRT; 528 sc->sc_wfm.unit = C_SUNIT(sc->sc_punit); 529 sc->sc_wfm.cmd = C_WFM; 530 hpibsend(ctlr, slave, C_CMD, &sc->sc_wfm, 531 sizeof(sc->sc_wfm)); 532 ctaddeof(sc); 533 break; 534 535 case MTBSR: 536 sc->sc_blkno--; 537 goto gotaddr; 538 539 case MTFSR: 540 sc->sc_blkno++; 541 goto gotaddr; 542 543 case MTREW: 544 sc->sc_blkno = 0; 545 #ifdef DEBUG 546 if(ctdebug & CT_BSF) 547 printf("%s: clearing eofs\n", 548 sc->sc_dev.dv_xname); 549 #endif 550 for (i=0; i<EOFS; i++) 551 sc->sc_eofs[i] = 0; 552 sc->sc_eofp = 0; 553 554 gotaddr: 555 sc->sc_ioc.saddr = C_SADDR; 556 sc->sc_ioc.addr0 = 0; 557 sc->sc_ioc.addr = sc->sc_blkno; 558 sc->sc_ioc.unit = C_SUNIT(sc->sc_punit); 559 sc->sc_ioc.nop2 = C_NOP; 560 sc->sc_ioc.slen = C_SLEN; 561 sc->sc_ioc.len = 0; 562 sc->sc_ioc.nop3 = C_NOP; 563 sc->sc_ioc.cmd = C_READ; 564 hpibsend(ctlr, slave, C_CMD, &sc->sc_ioc, 565 sizeof(sc->sc_ioc)); 566 break; 567 } 568 } else { 569 mustio: 570 if ((bp->b_flags & B_READ) && 571 sc->sc_flags & (CTF_BEOF|CTF_EOT)) { 572 #ifdef DEBUG 573 if (ctdebug & CDB_FILES) 574 printf("ctstart: before flags %x\n", 575 sc->sc_flags); 576 #endif 577 if (sc->sc_flags & CTF_BEOF) { 578 sc->sc_flags &= ~CTF_BEOF; 579 sc->sc_flags |= CTF_AEOF; 580 #ifdef DEBUG 581 if (ctdebug & CDB_FILES) 582 printf("ctstart: after flags %x\n", 583 sc->sc_flags); 584 #endif 585 } 586 bp->b_resid = bp->b_bcount; 587 ctdone(sc, bp); 588 return; 589 } 590 sc->sc_flags |= CTF_IO; 591 sc->sc_ioc.unit = C_SUNIT(sc->sc_punit); 592 sc->sc_ioc.saddr = C_SADDR; 593 sc->sc_ioc.addr0 = 0; 594 sc->sc_ioc.addr = sc->sc_blkno; 595 sc->sc_ioc.nop2 = C_NOP; 596 sc->sc_ioc.slen = C_SLEN; 597 sc->sc_ioc.len = sc->sc_resid; 598 sc->sc_ioc.nop3 = C_NOP; 599 if (bp->b_flags & B_READ) 600 sc->sc_ioc.cmd = C_READ; 601 else { 602 sc->sc_ioc.cmd = C_WRITE; 603 sc->sc_flags |= (CTF_WRT | CTF_WRTTN); 604 } 605 hpibsend(ctlr, slave, C_CMD, &sc->sc_ioc, sizeof(sc->sc_ioc)); 606 } 607 hpibawait(ctlr); 608 } 609 610 void 611 ctgo(arg) 612 void *arg; 613 { 614 struct ct_softc *sc = arg; 615 struct buf *bp; 616 int rw; 617 618 bp = sc->sc_tab.b_actf; 619 rw = bp->b_flags & B_READ; 620 hpibgo(sc->sc_dev.dv_parent->dv_unit, sc->sc_slave, C_EXEC, 621 sc->sc_addr, sc->sc_resid, rw, rw != 0); 622 } 623 624 /* 625 * Hideous grue to handle EOF/EOT (mostly for reads) 626 */ 627 void 628 cteof(sc, bp) 629 struct ct_softc *sc; 630 struct buf *bp; 631 { 632 long blks; 633 634 /* 635 * EOT on a write is an error. 636 */ 637 if ((bp->b_flags & B_READ) == 0) { 638 bp->b_resid = bp->b_bcount; 639 bp->b_flags |= B_ERROR; 640 bp->b_error = ENOSPC; 641 sc->sc_flags |= CTF_EOT; 642 return; 643 } 644 /* 645 * Use returned block position to determine how many blocks 646 * we really read and update b_resid. 647 */ 648 blks = sc->sc_stat.c_blk - sc->sc_blkno - 1; 649 #ifdef DEBUG 650 if (ctdebug & CDB_FILES) 651 printf("cteof: bc %ld oblk %d nblk %ld read %ld, resid %ld\n", 652 bp->b_bcount, sc->sc_blkno, sc->sc_stat.c_blk, 653 blks, bp->b_bcount - CTKTOB(blks)); 654 #endif 655 if (blks == -1) { /* 9145 on EOF does not change sc_stat.c_blk */ 656 blks = 0; 657 sc->sc_blkno++; 658 } 659 else { 660 sc->sc_blkno = sc->sc_stat.c_blk; 661 } 662 bp->b_resid = bp->b_bcount - CTKTOB(blks); 663 /* 664 * If we are at physical EOV or were after an EOF, 665 * we are now at logical EOT. 666 */ 667 if ((sc->sc_stat.c_aef & AEF_EOV) || 668 (sc->sc_flags & CTF_AEOF)) { 669 sc->sc_flags |= CTF_EOT; 670 sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF); 671 } 672 /* 673 * If we were before an EOF or we have just completed a FSF, 674 * we are now after EOF. 675 */ 676 else if ((sc->sc_flags & CTF_BEOF) || 677 ((sc->sc_flags & CTF_CMD) && sc->sc_cmd == MTFSF)) { 678 sc->sc_flags |= CTF_AEOF; 679 sc->sc_flags &= ~CTF_BEOF; 680 } 681 /* 682 * Otherwise if we read something we are now before EOF 683 * (and no longer after EOF). 684 */ 685 else if (blks) { 686 sc->sc_flags |= CTF_BEOF; 687 sc->sc_flags &= ~CTF_AEOF; 688 } 689 /* 690 * Finally, if we didn't read anything we just passed an EOF 691 */ 692 else 693 sc->sc_flags |= CTF_AEOF; 694 #ifdef DEBUG 695 if (ctdebug & CDB_FILES) 696 printf("cteof: leaving flags %x\n", sc->sc_flags); 697 #endif 698 } 699 700 /* ARGSUSED */ 701 void 702 ctintr(arg) 703 void *arg; 704 { 705 struct ct_softc *sc = arg; 706 struct buf *bp; 707 u_char stat; 708 int ctlr, slave, unit; 709 710 ctlr = sc->sc_dev.dv_parent->dv_unit; 711 slave = sc->sc_slave; 712 unit = sc->sc_dev.dv_unit; 713 714 bp = sc->sc_tab.b_actf; 715 if (bp == NULL) { 716 printf("%s: bp == NULL\n", sc->sc_dev.dv_xname); 717 return; 718 } 719 if (sc->sc_flags & CTF_IO) { 720 sc->sc_flags &= ~CTF_IO; 721 if (hpibustart(ctlr)) 722 ctgo(sc); 723 return; 724 } 725 if ((sc->sc_flags & CTF_STATWAIT) == 0) { 726 if (hpibpptest(ctlr, slave) == 0) { 727 sc->sc_flags |= CTF_STATWAIT; 728 hpibawait(ctlr); 729 return; 730 } 731 } else 732 sc->sc_flags &= ~CTF_STATWAIT; 733 hpibrecv(ctlr, slave, C_QSTAT, &stat, 1); 734 #ifdef DEBUG 735 if (ctdebug & CDB_FILES) 736 printf("ctintr: before flags %x\n", sc->sc_flags); 737 #endif 738 if (stat) { 739 sc->sc_rsc.unit = C_SUNIT(sc->sc_punit); 740 sc->sc_rsc.cmd = C_STATUS; 741 hpibsend(ctlr, slave, C_CMD, &sc->sc_rsc, sizeof(sc->sc_rsc)); 742 hpibrecv(ctlr, slave, C_EXEC, &sc->sc_stat, 743 sizeof(sc->sc_stat)); 744 hpibrecv(ctlr, slave, C_QSTAT, &stat, 1); 745 #ifdef DEBUG 746 if (ctdebug & CDB_FILES) 747 printf("ctintr: return stat 0x%x, A%x F%x blk %ld\n", 748 stat, sc->sc_stat.c_aef, 749 sc->sc_stat.c_fef, sc->sc_stat.c_blk); 750 #endif 751 if (stat == 0) { 752 if (sc->sc_stat.c_aef & (AEF_EOF | AEF_EOV)) { 753 cteof(sc, bp); 754 ctaddeof(sc); 755 goto done; 756 } 757 if (sc->sc_stat.c_fef & FEF_PF) { 758 ctreset(sc); 759 ctstart(sc); 760 return; 761 } 762 if (sc->sc_stat.c_fef & FEF_REXMT) { 763 ctstart(sc); 764 return; 765 } 766 if (sc->sc_stat.c_aef & 0x5800) { 767 if (sc->sc_stat.c_aef & 0x4000) 768 tprintf(sc->sc_tpr, 769 "%s: uninitialized media\n", 770 sc->sc_dev.dv_xname); 771 if (sc->sc_stat.c_aef & 0x1000) 772 tprintf(sc->sc_tpr, 773 "%s: not ready\n", 774 sc->sc_dev.dv_xname); 775 if (sc->sc_stat.c_aef & 0x0800) 776 tprintf(sc->sc_tpr, 777 "%s: write protect\n", 778 sc->sc_dev.dv_xname); 779 } else { 780 printf("%s err: v%d u%d ru%d bn%ld, ", 781 sc->sc_dev.dv_xname, 782 (sc->sc_stat.c_vu>>4)&0xF, 783 sc->sc_stat.c_vu&0xF, 784 sc->sc_stat.c_pend, 785 sc->sc_stat.c_blk); 786 printf("R0x%x F0x%x A0x%x I0x%x\n", 787 sc->sc_stat.c_ref, 788 sc->sc_stat.c_fef, 789 sc->sc_stat.c_aef, 790 sc->sc_stat.c_ief); 791 } 792 } else 793 printf("%s: request status failed\n", 794 sc->sc_dev.dv_xname); 795 bp->b_flags |= B_ERROR; 796 bp->b_error = EIO; 797 goto done; 798 } else 799 bp->b_resid = 0; 800 if (sc->sc_flags & CTF_CMD) { 801 switch (sc->sc_cmd) { 802 case MTFSF: 803 sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF); 804 sc->sc_blkno += CTBTOK(sc->sc_resid); 805 ctstart(sc); 806 return; 807 case MTBSF: 808 sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF|CTF_EOT); 809 break; 810 case MTBSR: 811 sc->sc_flags &= ~CTF_BEOF; 812 if (sc->sc_flags & CTF_EOT) { 813 sc->sc_flags |= CTF_AEOF; 814 sc->sc_flags &= ~CTF_EOT; 815 } else if (sc->sc_flags & CTF_AEOF) { 816 sc->sc_flags |= CTF_BEOF; 817 sc->sc_flags &= ~CTF_AEOF; 818 } 819 break; 820 case MTWEOF: 821 sc->sc_flags &= ~CTF_BEOF; 822 if (sc->sc_flags & (CTF_AEOF|CTF_EOT)) { 823 sc->sc_flags |= CTF_EOT; 824 sc->sc_flags &= ~CTF_AEOF; 825 } else 826 sc->sc_flags |= CTF_AEOF; 827 break; 828 case MTREW: 829 case MTOFFL: 830 sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF|CTF_EOT); 831 break; 832 } 833 } else { 834 sc->sc_flags &= ~CTF_AEOF; 835 sc->sc_blkno += CTBTOK(sc->sc_resid); 836 } 837 done: 838 #ifdef DEBUG 839 if (ctdebug & CDB_FILES) 840 printf("ctintr: after flags %x\n", sc->sc_flags); 841 #endif 842 ctdone(sc, bp); 843 } 844 845 void 846 ctdone(sc, bp) 847 struct ct_softc *sc; 848 struct buf *bp; 849 { 850 struct buf *dp; 851 852 if ((dp = bp->b_actf) != NULL) 853 dp->b_actb = bp->b_actb; 854 else 855 sc->sc_tab.b_actb = bp->b_actb; 856 *bp->b_actb = dp; 857 biodone(bp); 858 hpibfree(sc->sc_dev.dv_parent, &sc->sc_hq); 859 if (sc->sc_tab.b_actf == NULL) { 860 sc->sc_tab.b_active = 0; 861 return; 862 } 863 ctustart(sc); 864 } 865 866 int 867 ctread(dev, uio, flags) 868 dev_t dev; 869 struct uio *uio; 870 int flags; 871 { 872 return (physio(ctstrategy, NULL, dev, B_READ, minphys, uio)); 873 } 874 875 int 876 ctwrite(dev, uio, flags) 877 dev_t dev; 878 struct uio *uio; 879 int flags; 880 { 881 /* XXX: check for hardware write-protect? */ 882 return (physio(ctstrategy, NULL, dev, B_WRITE, minphys, uio)); 883 } 884 885 /*ARGSUSED*/ 886 int 887 ctioctl(dev, cmd, data, flag, p) 888 dev_t dev; 889 u_long cmd; 890 int flag; 891 caddr_t data; 892 struct proc *p; 893 { 894 struct mtop *op; 895 int cnt; 896 897 switch (cmd) { 898 899 case MTIOCTOP: 900 op = (struct mtop *)data; 901 switch(op->mt_op) { 902 903 case MTWEOF: 904 case MTFSF: 905 case MTBSR: 906 case MTBSF: 907 case MTFSR: 908 cnt = op->mt_count; 909 break; 910 911 case MTREW: 912 case MTOFFL: 913 cnt = 1; 914 break; 915 916 default: 917 return(EINVAL); 918 } 919 ctcommand(dev, op->mt_op, cnt); 920 break; 921 922 case MTIOCGET: 923 break; 924 925 default: 926 return(EINVAL); 927 } 928 return(0); 929 } 930 931 /* ARGSUSED */ 932 int 933 ctdump(dev, blkno, va, size) 934 dev_t dev; 935 daddr_t blkno; 936 caddr_t va; 937 size_t size; 938 { 939 940 return (ENODEV); 941 } 942 943 void 944 ctaddeof(sc) 945 struct ct_softc *sc; 946 { 947 948 if (sc->sc_eofp == EOFS - 1) 949 sc->sc_eofs[EOFS - 1]++; 950 else { 951 sc->sc_eofp++; 952 if (sc->sc_eofp == EOFS - 1) 953 sc->sc_eofs[EOFS - 1] = EOFS; 954 else 955 /* save blkno */ 956 sc->sc_eofs[sc->sc_eofp] = sc->sc_blkno - 1; 957 } 958 #ifdef DEBUG 959 if (ctdebug & CT_BSF) 960 printf("%s: add eof pos %d blk %d\n", 961 sc->sc_dev.dv_xname, sc->sc_eofp, 962 sc->sc_eofs[sc->sc_eofp]); 963 #endif 964 } 965