Annotation of sys/arch/hp300/dev/ct.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: ct.c,v 1.18 2007/06/06 17:15:11 deraadt Exp $ */
! 2: /* $NetBSD: ct.c,v 1.21 1997/04/02 22:37:23 scottr Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1996, 1997 Jason R. Thorpe. All rights reserved.
! 6: * Copyright (c) 1982, 1990, 1993
! 7: * The Regents of the University of California. All rights reserved.
! 8: *
! 9: * Redistribution and use in source and binary forms, with or without
! 10: * modification, are permitted provided that the following conditions
! 11: * are met:
! 12: * 1. Redistributions of source code must retain the above copyright
! 13: * notice, this list of conditions and the following disclaimer.
! 14: * 2. Redistributions in binary form must reproduce the above copyright
! 15: * notice, this list of conditions and the following disclaimer in the
! 16: * documentation and/or other materials provided with the distribution.
! 17: * 3. 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 8.2 (Berkeley) 1/12/94
! 34: */
! 35:
! 36: /*
! 37: * CS80 cartridge tape driver (9144, 88140, 9145)
! 38: *
! 39: * Reminder:
! 40: * C_CC bit (character count option) when used in the CS/80 command
! 41: * 'set options' will cause the tape not to stream.
! 42: *
! 43: * TODO:
! 44: * make filesystem compatible
! 45: * make block mode work according to mtio(4) spec. (if possible)
! 46: * merge with cs80 disk driver
! 47: * finish support of 9145
! 48: */
! 49:
! 50: #include <sys/param.h>
! 51: #include <sys/systm.h>
! 52: #include <sys/buf.h>
! 53: #include <sys/conf.h>
! 54: #include <sys/device.h>
! 55: #include <sys/ioctl.h>
! 56: #include <sys/mtio.h>
! 57: #include <sys/proc.h>
! 58:
! 59: #include <hp300/dev/hpibvar.h>
! 60:
! 61: #include <hp300/dev/ctreg.h>
! 62:
! 63: /* number of eof marks to remember */
! 64: #define EOFS 128
! 65:
! 66: struct ct_softc {
! 67: struct device sc_dev;
! 68: int sc_slave; /* HP-IB slave ID */
! 69: int sc_punit; /* physical unit */
! 70: struct ct_iocmd sc_ioc;
! 71: struct ct_rscmd sc_rsc;
! 72: struct ct_stat sc_stat;
! 73: struct ct_ssmcmd sc_ssmc;
! 74: struct ct_srcmd sc_src;
! 75: struct ct_soptcmd sc_soptc;
! 76: struct ct_ulcmd sc_ul;
! 77: struct ct_wfmcmd sc_wfm;
! 78: struct ct_clearcmd sc_clear;
! 79: struct buf sc_tab;
! 80: struct buf *sc_bp;
! 81: struct buf sc_bufstore; /* XXX */
! 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: struct hpibqueue sc_hq; /* entry on hpib job queue */
! 89: int sc_eofp;
! 90: int sc_eofs[EOFS];
! 91: };
! 92:
! 93: /* flags */
! 94: #define CTF_OPEN 0x01
! 95: #define CTF_ALIVE 0x02
! 96: #define CTF_WRT 0x04
! 97: #define CTF_CMD 0x08
! 98: #define CTF_IO 0x10
! 99: #define CTF_BEOF 0x20
! 100: #define CTF_AEOF 0x40
! 101: #define CTF_EOT 0x80
! 102: #define CTF_STATWAIT 0x100
! 103: #define CTF_CANSTREAM 0x200
! 104: #define CTF_WRTTN 0x400
! 105:
! 106: int ctmatch(struct device *, void *, void *);
! 107: void ctattach(struct device *, struct device *, void *);
! 108:
! 109: struct cfattach ct_ca = {
! 110: sizeof(struct ct_softc), ctmatch, ctattach
! 111: };
! 112:
! 113: struct cfdriver ct_cd = {
! 114: NULL, "ct", DV_TAPE
! 115: };
! 116:
! 117: int ctident(struct device *, struct ct_softc *,
! 118: struct hpibbus_attach_args *);
! 119:
! 120: void ctreset(struct ct_softc *);
! 121: void ctaddeof(struct ct_softc *);
! 122: void ctustart(struct ct_softc *);
! 123: void cteof(struct ct_softc *, struct buf *);
! 124: void ctdone(struct ct_softc *, struct buf *);
! 125:
! 126: void ctstart(void *);
! 127: void ctgo(void *);
! 128: void ctintr(void *);
! 129:
! 130: void ctcommand(dev_t, int, int);
! 131:
! 132: cdev_decl(ct);
! 133: bdev_decl(ct);
! 134:
! 135: const struct ctinfo {
! 136: short hwid;
! 137: short punit;
! 138: char *desc;
! 139: } ctinfo[] = {
! 140: { CT7946ID, 1, "7946A" },
! 141: { CT7912PID, 1, "7912P" },
! 142: { CT7914PID, 1, "7914P" },
! 143: { CT9144ID, 0, "9144" },
! 144: { CT9145ID, 0, "9145" },
! 145: };
! 146: int nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]);
! 147:
! 148: #define CT_NOREW 4
! 149: #define CT_STREAM 8
! 150: #define UNIT(x) (minor(x) & 3)
! 151: #define ctpunit(x) ((x) & 7)
! 152:
! 153: #ifdef DEBUG
! 154: int ctdebug = 0;
! 155: #define CDB_FILES 0x01
! 156: #define CT_BSF 0x02
! 157: #endif
! 158:
! 159: int
! 160: ctmatch(parent, match, aux)
! 161: struct device *parent;
! 162: void *match, *aux;
! 163: {
! 164: struct hpibbus_attach_args *ha = aux;
! 165:
! 166: return (ctident(parent, NULL, ha));
! 167: }
! 168:
! 169: void
! 170: ctattach(parent, self, aux)
! 171: struct device *parent, *self;
! 172: void *aux;
! 173: {
! 174: struct ct_softc *sc = (struct ct_softc *)self;
! 175: struct hpibbus_attach_args *ha = aux;
! 176:
! 177: if (ctident(parent, sc, ha) == 0) {
! 178: /* can't happen */
! 179: printf("\n%s: didn't respond to describe command!\n",
! 180: sc->sc_dev.dv_xname);
! 181: return;
! 182: }
! 183:
! 184: sc->sc_slave = ha->ha_slave;
! 185: sc->sc_punit = ha->ha_punit;
! 186:
! 187: sc->sc_tab.b_actb = &sc->sc_tab.b_actf;
! 188:
! 189: /* Initialize hpib job queue entry. */
! 190: sc->sc_hq.hq_softc = sc;
! 191: sc->sc_hq.hq_slave = sc->sc_slave;
! 192: sc->sc_hq.hq_start = ctstart;
! 193: sc->sc_hq.hq_go = ctgo;
! 194: sc->sc_hq.hq_intr = ctintr;
! 195:
! 196: ctreset(sc);
! 197: sc->sc_flags |= CTF_ALIVE;
! 198: }
! 199:
! 200: int
! 201: ctident(parent, sc, ha)
! 202: struct device *parent;
! 203: struct ct_softc *sc;
! 204: struct hpibbus_attach_args *ha;
! 205: {
! 206: struct cs80_describe desc;
! 207: u_char stat, cmd[3];
! 208: char name[7];
! 209: int i, id, n, type, canstream;
! 210:
! 211: type = canstream = 0;
! 212:
! 213: /* Verify that we have a CS80 device. */
! 214: if ((ha->ha_id & 0x200) == 0)
! 215: return (0);
! 216:
! 217: /* Is it one of the tapes we support? */
! 218: for (id = 0; id < nctinfo; id++)
! 219: if (ha->ha_id == ctinfo[id].hwid &&
! 220: ha->ha_punit == ctinfo[id].punit)
! 221: break;
! 222: if (id == nctinfo)
! 223: return (0);
! 224:
! 225: /*
! 226: * So far, so good. Get drive parameters. Note command
! 227: * is always issued to unit 0.
! 228: */
! 229: bzero(&desc, sizeof(desc));
! 230: stat = 0;
! 231: cmd[0] = C_SUNIT(0);
! 232: cmd[1] = C_SVOL(0);
! 233: cmd[2] = C_DESC;
! 234: hpibsend(parent->dv_unit, ha->ha_slave, C_CMD, cmd, sizeof(cmd));
! 235: hpibrecv(parent->dv_unit, ha->ha_slave, C_EXEC, &desc, sizeof(desc));
! 236: hpibrecv(parent->dv_unit, ha->ha_slave, C_QSTAT, &stat, sizeof(stat));
! 237:
! 238: if (desc.d_name == 0 && stat != 0)
! 239: return (0);
! 240:
! 241: bzero(name, sizeof(name));
! 242: n = desc.d_name;
! 243: for (i = 5; i >= 0; i--) {
! 244: name[i] = (n & 0xf) + '0';
! 245: n >>= 4;
! 246: }
! 247:
! 248: switch (ha->ha_id) {
! 249: case CT7946ID:
! 250: if (bcmp(name, "079450", 6) == 0)
! 251: return (0); /* not really a 7946 */
! 252: /* FALLTHROUGH */
! 253: case CT9144ID:
! 254: case CT9145ID:
! 255: type = CT9144;
! 256: canstream = 1;
! 257: break;
! 258:
! 259: case CT7912PID:
! 260: case CT7914PID:
! 261: type = CT88140;
! 262: break;
! 263: }
! 264:
! 265: if (sc != NULL) {
! 266: sc->sc_type = type;
! 267: sc->sc_flags = canstream ? CTF_CANSTREAM : 0;
! 268: printf(": %s %stape\n", ctinfo[id].desc,
! 269: canstream ? "streaming " : "");
! 270: }
! 271:
! 272: return (1);
! 273: }
! 274:
! 275: void
! 276: ctreset(sc)
! 277: struct ct_softc *sc;
! 278: {
! 279: int ctlr, slave;
! 280: u_char stat;
! 281:
! 282: ctlr = sc->sc_dev.dv_parent->dv_unit;
! 283: slave = sc->sc_slave;
! 284:
! 285: sc->sc_clear.unit = C_SUNIT(sc->sc_punit);
! 286: sc->sc_clear.cmd = C_CLEAR;
! 287: hpibsend(ctlr, slave, C_TCMD, &sc->sc_clear, sizeof(sc->sc_clear));
! 288: hpibswait(ctlr, slave);
! 289: hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
! 290:
! 291: sc->sc_src.unit = C_SUNIT(CTCTLR);
! 292: sc->sc_src.nop = C_NOP;
! 293: sc->sc_src.cmd = C_SREL;
! 294: sc->sc_src.param = C_REL;
! 295: hpibsend(ctlr, slave, C_CMD, &sc->sc_src, sizeof(sc->sc_src));
! 296: hpibswait(ctlr, slave);
! 297: hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
! 298:
! 299: sc->sc_ssmc.unit = C_SUNIT(sc->sc_punit);
! 300: sc->sc_ssmc.cmd = C_SSM;
! 301: sc->sc_ssmc.refm = REF_MASK;
! 302: sc->sc_ssmc.fefm = FEF_MASK;
! 303: sc->sc_ssmc.aefm = AEF_MASK;
! 304: sc->sc_ssmc.iefm = IEF_MASK;
! 305: hpibsend(ctlr, slave, C_CMD, &sc->sc_ssmc, sizeof(sc->sc_ssmc));
! 306: hpibswait(ctlr, slave);
! 307: hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
! 308:
! 309: sc->sc_soptc.unit = C_SUNIT(sc->sc_punit);
! 310: sc->sc_soptc.nop = C_NOP;
! 311: sc->sc_soptc.cmd = C_SOPT;
! 312: sc->sc_soptc.opt = C_SPAR;
! 313: hpibsend(ctlr, slave, C_CMD, &sc->sc_soptc, sizeof(sc->sc_soptc));
! 314: hpibswait(ctlr, slave);
! 315: hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
! 316: }
! 317:
! 318: /*ARGSUSED*/
! 319: int
! 320: ctopen(dev, flag, type, p)
! 321: dev_t dev;
! 322: int flag, type;
! 323: struct proc *p;
! 324: {
! 325: struct ct_softc *sc;
! 326: u_char stat;
! 327: int cc, ctlr, slave;
! 328:
! 329: if (UNIT(dev) >= ct_cd.cd_ndevs ||
! 330: (sc = ct_cd.cd_devs[UNIT(dev)]) == NULL ||
! 331: (sc->sc_flags & CTF_ALIVE) == 0)
! 332: return (ENXIO);
! 333:
! 334: if (sc->sc_flags & CTF_OPEN)
! 335: return (EBUSY);
! 336:
! 337: ctlr = sc->sc_dev.dv_parent->dv_unit;
! 338: slave = sc->sc_slave;
! 339:
! 340: sc->sc_soptc.unit = C_SUNIT(sc->sc_punit);
! 341: sc->sc_soptc.nop = C_NOP;
! 342: sc->sc_soptc.cmd = C_SOPT;
! 343: if ((dev & CT_STREAM) && (sc->sc_flags & CTF_CANSTREAM))
! 344: sc->sc_soptc.opt = C_SPAR | C_IMRPT;
! 345: else
! 346: sc->sc_soptc.opt = C_SPAR;
! 347:
! 348: /*
! 349: * Check the return of hpibsend() and hpibswait().
! 350: * Drive could be loading/unloading a tape. If not checked,
! 351: * driver hangs.
! 352: */
! 353: cc = hpibsend(ctlr, slave, C_CMD, &sc->sc_soptc, sizeof(sc->sc_soptc));
! 354: if (cc != sizeof(sc->sc_soptc))
! 355: return (EBUSY);
! 356:
! 357: hpibswait(ctlr, slave);
! 358: cc = hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
! 359: if (cc != sizeof(stat))
! 360: return(EBUSY);
! 361:
! 362: sc->sc_flags |= CTF_OPEN;
! 363: return(0);
! 364: }
! 365:
! 366: /*ARGSUSED*/
! 367: int
! 368: ctclose(dev, flag, fmt, p)
! 369: dev_t dev;
! 370: int flag, fmt;
! 371: struct proc *p;
! 372: {
! 373: struct ct_softc *sc = ct_cd.cd_devs[UNIT(dev)];
! 374:
! 375: if ((sc->sc_flags & (CTF_WRT|CTF_WRTTN)) == (CTF_WRT|CTF_WRTTN) &&
! 376: (sc->sc_flags & CTF_EOT) == 0 ) { /* XXX return error if EOT ?? */
! 377: ctcommand(dev, MTWEOF, 2);
! 378: ctcommand(dev, MTBSR, 1);
! 379: if (sc->sc_eofp == EOFS - 1)
! 380: sc->sc_eofs[EOFS - 1]--;
! 381: else
! 382: sc->sc_eofp--;
! 383: #ifdef DEBUG
! 384: if(ctdebug & CT_BSF)
! 385: printf("%s: ctclose backup eofs prt %d blk %d\n",
! 386: sc->sc_dev.dv_xname, sc->sc_eofp,
! 387: sc->sc_eofs[sc->sc_eofp]);
! 388: #endif
! 389: }
! 390: if ((minor(dev) & CT_NOREW) == 0)
! 391: ctcommand(dev, MTREW, 1);
! 392: sc->sc_flags &= ~(CTF_OPEN | CTF_WRT | CTF_WRTTN);
! 393: #ifdef DEBUG
! 394: if (ctdebug & CDB_FILES)
! 395: printf("ctclose: flags %x\n", sc->sc_flags);
! 396: #endif
! 397: return(0); /* XXX */
! 398: }
! 399:
! 400: void
! 401: ctcommand(dev, cmd, cnt)
! 402: dev_t dev;
! 403: int cmd;
! 404: int cnt;
! 405: {
! 406: struct ct_softc *sc = ct_cd.cd_devs[UNIT(dev)];
! 407: struct buf *bp = &sc->sc_bufstore;
! 408: struct buf *nbp = 0;
! 409:
! 410: if (cmd == MTBSF && sc->sc_eofp == EOFS - 1) {
! 411: cnt = sc->sc_eofs[EOFS - 1] - cnt;
! 412: ctcommand(dev, MTREW, 1);
! 413: ctcommand(dev, MTFSF, cnt);
! 414: cnt = 2;
! 415: cmd = MTBSR;
! 416: }
! 417:
! 418: if (cmd == MTBSF && sc->sc_eofp - cnt < 0) {
! 419: cnt = 1;
! 420: cmd = MTREW;
! 421: }
! 422:
! 423: sc->sc_flags |= CTF_CMD;
! 424: sc->sc_bp = bp;
! 425: sc->sc_cmd = cmd;
! 426: bp->b_dev = dev;
! 427: if (cmd == MTFSF) {
! 428: nbp = (struct buf *)geteblk(MAXBSIZE);
! 429: bp->b_data = nbp->b_data;
! 430: bp->b_bcount = MAXBSIZE;
! 431: }
! 432:
! 433: while (cnt-- > 0) {
! 434: bp->b_flags = B_BUSY;
! 435: if (cmd == MTBSF) {
! 436: sc->sc_blkno = sc->sc_eofs[sc->sc_eofp];
! 437: sc->sc_eofp--;
! 438: #ifdef DEBUG
! 439: if (ctdebug & CT_BSF)
! 440: printf("%s: backup eof pos %d blk %d\n",
! 441: sc->sc_dev.dv_xname, sc->sc_eofp,
! 442: sc->sc_eofs[sc->sc_eofp]);
! 443: #endif
! 444: }
! 445: ctstrategy(bp);
! 446: biowait(bp);
! 447: }
! 448: bp->b_flags = 0;
! 449: sc->sc_flags &= ~CTF_CMD;
! 450: if (nbp)
! 451: brelse(nbp);
! 452: }
! 453:
! 454: void
! 455: ctstrategy(bp)
! 456: struct buf *bp;
! 457: {
! 458: struct buf *dp;
! 459: int s, unit;
! 460: struct ct_softc *sc;
! 461:
! 462: unit = UNIT(bp->b_dev);
! 463: sc = ct_cd.cd_devs[unit];
! 464:
! 465: dp = &sc->sc_tab;
! 466: bp->b_actf = NULL;
! 467: s = splbio();
! 468: bp->b_actb = dp->b_actb;
! 469: *(dp->b_actb) = bp;
! 470: dp->b_actb = &bp->b_actf;
! 471: if (dp->b_active == 0) {
! 472: dp->b_active = 1;
! 473: ctustart(sc);
! 474: }
! 475: splx(s);
! 476: }
! 477:
! 478: void
! 479: ctustart(sc)
! 480: struct ct_softc *sc;
! 481: {
! 482: struct buf *bp;
! 483:
! 484: bp = sc->sc_tab.b_actf;
! 485: sc->sc_addr = bp->b_data;
! 486: sc->sc_resid = bp->b_bcount;
! 487: if (hpibreq(sc->sc_dev.dv_parent, &sc->sc_hq))
! 488: ctstart(sc);
! 489: }
! 490:
! 491: void
! 492: ctstart(arg)
! 493: void *arg;
! 494: {
! 495: struct ct_softc *sc = arg;
! 496: struct buf *bp;
! 497: int i, ctlr, slave;
! 498:
! 499: ctlr = sc->sc_dev.dv_parent->dv_unit;
! 500: slave = sc->sc_slave;
! 501:
! 502: bp = sc->sc_tab.b_actf;
! 503: if ((sc->sc_flags & CTF_CMD) && sc->sc_bp == bp) {
! 504: switch(sc->sc_cmd) {
! 505: case MTFSF:
! 506: bp->b_flags |= B_READ;
! 507: goto mustio;
! 508:
! 509: case MTBSF:
! 510: goto gotaddr;
! 511:
! 512: case MTOFFL:
! 513: sc->sc_blkno = 0;
! 514: sc->sc_ul.unit = C_SUNIT(sc->sc_punit);
! 515: sc->sc_ul.cmd = C_UNLOAD;
! 516: hpibsend(ctlr, slave, C_CMD, &sc->sc_ul,
! 517: sizeof(sc->sc_ul));
! 518: break;
! 519:
! 520: case MTWEOF:
! 521: sc->sc_blkno++;
! 522: sc->sc_flags |= CTF_WRT;
! 523: sc->sc_wfm.unit = C_SUNIT(sc->sc_punit);
! 524: sc->sc_wfm.cmd = C_WFM;
! 525: hpibsend(ctlr, slave, C_CMD, &sc->sc_wfm,
! 526: sizeof(sc->sc_wfm));
! 527: ctaddeof(sc);
! 528: break;
! 529:
! 530: case MTBSR:
! 531: sc->sc_blkno--;
! 532: goto gotaddr;
! 533:
! 534: case MTFSR:
! 535: sc->sc_blkno++;
! 536: goto gotaddr;
! 537:
! 538: case MTREW:
! 539: sc->sc_blkno = 0;
! 540: #ifdef DEBUG
! 541: if(ctdebug & CT_BSF)
! 542: printf("%s: clearing eofs\n",
! 543: sc->sc_dev.dv_xname);
! 544: #endif
! 545: for (i=0; i<EOFS; i++)
! 546: sc->sc_eofs[i] = 0;
! 547: sc->sc_eofp = 0;
! 548:
! 549: gotaddr:
! 550: sc->sc_ioc.saddr = C_SADDR;
! 551: sc->sc_ioc.addr0 = 0;
! 552: sc->sc_ioc.addr = sc->sc_blkno;
! 553: sc->sc_ioc.unit = C_SUNIT(sc->sc_punit);
! 554: sc->sc_ioc.nop2 = C_NOP;
! 555: sc->sc_ioc.slen = C_SLEN;
! 556: sc->sc_ioc.len = 0;
! 557: sc->sc_ioc.nop3 = C_NOP;
! 558: sc->sc_ioc.cmd = C_READ;
! 559: hpibsend(ctlr, slave, C_CMD, &sc->sc_ioc,
! 560: sizeof(sc->sc_ioc));
! 561: break;
! 562: }
! 563: } else {
! 564: mustio:
! 565: if ((bp->b_flags & B_READ) &&
! 566: sc->sc_flags & (CTF_BEOF|CTF_EOT)) {
! 567: #ifdef DEBUG
! 568: if (ctdebug & CDB_FILES)
! 569: printf("ctstart: before flags %x\n",
! 570: sc->sc_flags);
! 571: #endif
! 572: if (sc->sc_flags & CTF_BEOF) {
! 573: sc->sc_flags &= ~CTF_BEOF;
! 574: sc->sc_flags |= CTF_AEOF;
! 575: #ifdef DEBUG
! 576: if (ctdebug & CDB_FILES)
! 577: printf("ctstart: after flags %x\n",
! 578: sc->sc_flags);
! 579: #endif
! 580: }
! 581: bp->b_resid = bp->b_bcount;
! 582: ctdone(sc, bp);
! 583: return;
! 584: }
! 585: sc->sc_flags |= CTF_IO;
! 586: sc->sc_ioc.unit = C_SUNIT(sc->sc_punit);
! 587: sc->sc_ioc.saddr = C_SADDR;
! 588: sc->sc_ioc.addr0 = 0;
! 589: sc->sc_ioc.addr = sc->sc_blkno;
! 590: sc->sc_ioc.nop2 = C_NOP;
! 591: sc->sc_ioc.slen = C_SLEN;
! 592: sc->sc_ioc.len = sc->sc_resid;
! 593: sc->sc_ioc.nop3 = C_NOP;
! 594: if (bp->b_flags & B_READ)
! 595: sc->sc_ioc.cmd = C_READ;
! 596: else {
! 597: sc->sc_ioc.cmd = C_WRITE;
! 598: sc->sc_flags |= (CTF_WRT | CTF_WRTTN);
! 599: }
! 600: hpibsend(ctlr, slave, C_CMD, &sc->sc_ioc, sizeof(sc->sc_ioc));
! 601: }
! 602: hpibawait(ctlr);
! 603: }
! 604:
! 605: void
! 606: ctgo(arg)
! 607: void *arg;
! 608: {
! 609: struct ct_softc *sc = arg;
! 610: struct buf *bp;
! 611: int rw;
! 612:
! 613: bp = sc->sc_tab.b_actf;
! 614: rw = bp->b_flags & B_READ;
! 615: hpibgo(sc->sc_dev.dv_parent->dv_unit, sc->sc_slave, C_EXEC,
! 616: sc->sc_addr, sc->sc_resid, rw, rw != 0);
! 617: }
! 618:
! 619: /*
! 620: * Hideous grue to handle EOF/EOT (mostly for reads)
! 621: */
! 622: void
! 623: cteof(sc, bp)
! 624: struct ct_softc *sc;
! 625: struct buf *bp;
! 626: {
! 627: long blks;
! 628:
! 629: /*
! 630: * EOT on a write is an error.
! 631: */
! 632: if ((bp->b_flags & B_READ) == 0) {
! 633: bp->b_resid = bp->b_bcount;
! 634: bp->b_flags |= B_ERROR;
! 635: bp->b_error = ENOSPC;
! 636: sc->sc_flags |= CTF_EOT;
! 637: return;
! 638: }
! 639: /*
! 640: * Use returned block position to determine how many blocks
! 641: * we really read and update b_resid.
! 642: */
! 643: blks = sc->sc_stat.c_blk - sc->sc_blkno - 1;
! 644: #ifdef DEBUG
! 645: if (ctdebug & CDB_FILES)
! 646: printf("cteof: bc %ld oblk %d nblk %ld read %ld, resid %ld\n",
! 647: bp->b_bcount, sc->sc_blkno, sc->sc_stat.c_blk,
! 648: blks, bp->b_bcount - CTKTOB(blks));
! 649: #endif
! 650: if (blks == -1) { /* 9145 on EOF does not change sc_stat.c_blk */
! 651: blks = 0;
! 652: sc->sc_blkno++;
! 653: }
! 654: else {
! 655: sc->sc_blkno = sc->sc_stat.c_blk;
! 656: }
! 657: bp->b_resid = bp->b_bcount - CTKTOB(blks);
! 658: /*
! 659: * If we are at physical EOV or were after an EOF,
! 660: * we are now at logical EOT.
! 661: */
! 662: if ((sc->sc_stat.c_aef & AEF_EOV) ||
! 663: (sc->sc_flags & CTF_AEOF)) {
! 664: sc->sc_flags |= CTF_EOT;
! 665: sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF);
! 666: }
! 667: /*
! 668: * If we were before an EOF or we have just completed a FSF,
! 669: * we are now after EOF.
! 670: */
! 671: else if ((sc->sc_flags & CTF_BEOF) ||
! 672: ((sc->sc_flags & CTF_CMD) && sc->sc_cmd == MTFSF)) {
! 673: sc->sc_flags |= CTF_AEOF;
! 674: sc->sc_flags &= ~CTF_BEOF;
! 675: }
! 676: /*
! 677: * Otherwise if we read something we are now before EOF
! 678: * (and no longer after EOF).
! 679: */
! 680: else if (blks) {
! 681: sc->sc_flags |= CTF_BEOF;
! 682: sc->sc_flags &= ~CTF_AEOF;
! 683: }
! 684: /*
! 685: * Finally, if we didn't read anything we just passed an EOF
! 686: */
! 687: else
! 688: sc->sc_flags |= CTF_AEOF;
! 689: #ifdef DEBUG
! 690: if (ctdebug & CDB_FILES)
! 691: printf("cteof: leaving flags %x\n", sc->sc_flags);
! 692: #endif
! 693: }
! 694:
! 695: /* ARGSUSED */
! 696: void
! 697: ctintr(arg)
! 698: void *arg;
! 699: {
! 700: struct ct_softc *sc = arg;
! 701: struct buf *bp;
! 702: u_char stat;
! 703: int ctlr, slave, unit;
! 704:
! 705: ctlr = sc->sc_dev.dv_parent->dv_unit;
! 706: slave = sc->sc_slave;
! 707: unit = sc->sc_dev.dv_unit;
! 708:
! 709: bp = sc->sc_tab.b_actf;
! 710: if (bp == NULL) {
! 711: printf("%s: bp == NULL\n", sc->sc_dev.dv_xname);
! 712: return;
! 713: }
! 714: if (sc->sc_flags & CTF_IO) {
! 715: sc->sc_flags &= ~CTF_IO;
! 716: if (hpibustart(ctlr))
! 717: ctgo(sc);
! 718: return;
! 719: }
! 720: if ((sc->sc_flags & CTF_STATWAIT) == 0) {
! 721: if (hpibpptest(ctlr, slave) == 0) {
! 722: sc->sc_flags |= CTF_STATWAIT;
! 723: hpibawait(ctlr);
! 724: return;
! 725: }
! 726: } else
! 727: sc->sc_flags &= ~CTF_STATWAIT;
! 728: hpibrecv(ctlr, slave, C_QSTAT, &stat, 1);
! 729: #ifdef DEBUG
! 730: if (ctdebug & CDB_FILES)
! 731: printf("ctintr: before flags %x\n", sc->sc_flags);
! 732: #endif
! 733: if (stat) {
! 734: sc->sc_rsc.unit = C_SUNIT(sc->sc_punit);
! 735: sc->sc_rsc.cmd = C_STATUS;
! 736: hpibsend(ctlr, slave, C_CMD, &sc->sc_rsc, sizeof(sc->sc_rsc));
! 737: hpibrecv(ctlr, slave, C_EXEC, &sc->sc_stat,
! 738: sizeof(sc->sc_stat));
! 739: hpibrecv(ctlr, slave, C_QSTAT, &stat, 1);
! 740: #ifdef DEBUG
! 741: if (ctdebug & CDB_FILES)
! 742: printf("ctintr: return stat 0x%x, A%x F%x blk %ld\n",
! 743: stat, sc->sc_stat.c_aef,
! 744: sc->sc_stat.c_fef, sc->sc_stat.c_blk);
! 745: #endif
! 746: if (stat == 0) {
! 747: if (sc->sc_stat.c_aef & (AEF_EOF | AEF_EOV)) {
! 748: cteof(sc, bp);
! 749: ctaddeof(sc);
! 750: goto done;
! 751: }
! 752: if (sc->sc_stat.c_fef & FEF_PF) {
! 753: ctreset(sc);
! 754: ctstart(sc);
! 755: return;
! 756: }
! 757: if (sc->sc_stat.c_fef & FEF_REXMT) {
! 758: ctstart(sc);
! 759: return;
! 760: }
! 761: if (sc->sc_stat.c_aef & 0x5800) {
! 762: if (sc->sc_stat.c_aef & 0x4000)
! 763: printf("%s: uninitialized media\n",
! 764: sc->sc_dev.dv_xname);
! 765: if (sc->sc_stat.c_aef & 0x1000)
! 766: printf("%s: not ready\n",
! 767: sc->sc_dev.dv_xname);
! 768: if (sc->sc_stat.c_aef & 0x0800)
! 769: printf("%s: write protect\n",
! 770: sc->sc_dev.dv_xname);
! 771: } else {
! 772: printf("%s err: v%d u%d ru%d bn%ld, ",
! 773: sc->sc_dev.dv_xname,
! 774: (sc->sc_stat.c_vu>>4)&0xF,
! 775: sc->sc_stat.c_vu&0xF,
! 776: sc->sc_stat.c_pend,
! 777: sc->sc_stat.c_blk);
! 778: printf("R0x%x F0x%x A0x%x I0x%x\n",
! 779: sc->sc_stat.c_ref,
! 780: sc->sc_stat.c_fef,
! 781: sc->sc_stat.c_aef,
! 782: sc->sc_stat.c_ief);
! 783: }
! 784: } else
! 785: printf("%s: request status failed\n",
! 786: sc->sc_dev.dv_xname);
! 787: bp->b_flags |= B_ERROR;
! 788: bp->b_error = EIO;
! 789: goto done;
! 790: } else
! 791: bp->b_resid = 0;
! 792: if (sc->sc_flags & CTF_CMD) {
! 793: switch (sc->sc_cmd) {
! 794: case MTFSF:
! 795: sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF);
! 796: sc->sc_blkno += CTBTOK(sc->sc_resid);
! 797: ctstart(sc);
! 798: return;
! 799: case MTBSF:
! 800: sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF|CTF_EOT);
! 801: break;
! 802: case MTBSR:
! 803: sc->sc_flags &= ~CTF_BEOF;
! 804: if (sc->sc_flags & CTF_EOT) {
! 805: sc->sc_flags |= CTF_AEOF;
! 806: sc->sc_flags &= ~CTF_EOT;
! 807: } else if (sc->sc_flags & CTF_AEOF) {
! 808: sc->sc_flags |= CTF_BEOF;
! 809: sc->sc_flags &= ~CTF_AEOF;
! 810: }
! 811: break;
! 812: case MTWEOF:
! 813: sc->sc_flags &= ~CTF_BEOF;
! 814: if (sc->sc_flags & (CTF_AEOF|CTF_EOT)) {
! 815: sc->sc_flags |= CTF_EOT;
! 816: sc->sc_flags &= ~CTF_AEOF;
! 817: } else
! 818: sc->sc_flags |= CTF_AEOF;
! 819: break;
! 820: case MTREW:
! 821: case MTOFFL:
! 822: sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF|CTF_EOT);
! 823: break;
! 824: }
! 825: } else {
! 826: sc->sc_flags &= ~CTF_AEOF;
! 827: sc->sc_blkno += CTBTOK(sc->sc_resid);
! 828: }
! 829: done:
! 830: #ifdef DEBUG
! 831: if (ctdebug & CDB_FILES)
! 832: printf("ctintr: after flags %x\n", sc->sc_flags);
! 833: #endif
! 834: ctdone(sc, bp);
! 835: }
! 836:
! 837: void
! 838: ctdone(sc, bp)
! 839: struct ct_softc *sc;
! 840: struct buf *bp;
! 841: {
! 842: struct buf *dp;
! 843: int s;
! 844:
! 845: if ((dp = bp->b_actf) != NULL)
! 846: dp->b_actb = bp->b_actb;
! 847: else
! 848: sc->sc_tab.b_actb = bp->b_actb;
! 849: *bp->b_actb = dp;
! 850: s = splbio();
! 851: biodone(bp);
! 852: splx(s);
! 853: hpibfree(sc->sc_dev.dv_parent, &sc->sc_hq);
! 854: if (sc->sc_tab.b_actf == NULL) {
! 855: sc->sc_tab.b_active = 0;
! 856: return;
! 857: }
! 858: ctustart(sc);
! 859: }
! 860:
! 861: int
! 862: ctread(dev, uio, flags)
! 863: dev_t dev;
! 864: struct uio *uio;
! 865: int flags;
! 866: {
! 867: return (physio(ctstrategy, NULL, dev, B_READ, minphys, uio));
! 868: }
! 869:
! 870: int
! 871: ctwrite(dev, uio, flags)
! 872: dev_t dev;
! 873: struct uio *uio;
! 874: int flags;
! 875: {
! 876: /* XXX: check for hardware write-protect? */
! 877: return (physio(ctstrategy, NULL, dev, B_WRITE, minphys, uio));
! 878: }
! 879:
! 880: /*ARGSUSED*/
! 881: int
! 882: ctioctl(dev, cmd, data, flag, p)
! 883: dev_t dev;
! 884: u_long cmd;
! 885: int flag;
! 886: caddr_t data;
! 887: struct proc *p;
! 888: {
! 889: struct mtop *op;
! 890: int cnt;
! 891:
! 892: switch (cmd) {
! 893:
! 894: case MTIOCTOP:
! 895: op = (struct mtop *)data;
! 896: switch(op->mt_op) {
! 897:
! 898: case MTWEOF:
! 899: case MTFSF:
! 900: case MTBSR:
! 901: case MTBSF:
! 902: case MTFSR:
! 903: cnt = op->mt_count;
! 904: break;
! 905:
! 906: case MTREW:
! 907: case MTOFFL:
! 908: cnt = 1;
! 909: break;
! 910:
! 911: default:
! 912: return(EINVAL);
! 913: }
! 914: ctcommand(dev, op->mt_op, cnt);
! 915: break;
! 916:
! 917: case MTIOCGET:
! 918: break;
! 919:
! 920: default:
! 921: return(EINVAL);
! 922: }
! 923: return(0);
! 924: }
! 925:
! 926: /* ARGSUSED */
! 927: int
! 928: ctdump(dev, blkno, va, size)
! 929: dev_t dev;
! 930: daddr64_t blkno;
! 931: caddr_t va;
! 932: size_t size;
! 933: {
! 934:
! 935: return (ENODEV);
! 936: }
! 937:
! 938: void
! 939: ctaddeof(sc)
! 940: struct ct_softc *sc;
! 941: {
! 942:
! 943: if (sc->sc_eofp == EOFS - 1)
! 944: sc->sc_eofs[EOFS - 1]++;
! 945: else {
! 946: sc->sc_eofp++;
! 947: if (sc->sc_eofp == EOFS - 1)
! 948: sc->sc_eofs[EOFS - 1] = EOFS;
! 949: else
! 950: /* save blkno */
! 951: sc->sc_eofs[sc->sc_eofp] = sc->sc_blkno - 1;
! 952: }
! 953: #ifdef DEBUG
! 954: if (ctdebug & CT_BSF)
! 955: printf("%s: add eof pos %d blk %d\n",
! 956: sc->sc_dev.dv_xname, sc->sc_eofp,
! 957: sc->sc_eofs[sc->sc_eofp]);
! 958: #endif
! 959: }
CVSweb