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