|
|
1.1 ! root 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.