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