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