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