Annotation of researchv9/sys/sundev/st.c, revision 1.1

1.1     ! root        1: /*     @(#)st.c 1.1 86/02/03 SMI       */
        !             2: 
        !             3: /*
        !             4:  * Copyright (c) 1985 by Sun Microsystems, Inc.
        !             5:  */
        !             6: 
        !             7: #include "st.h"
        !             8: #if NST > 0
        !             9: 
        !            10: /*
        !            11:  * Driver for Sysgen SC400 and Emulex MT02 SCSI tape controller.
        !            12:  */
        !            13: 
        !            14: #include "../h/param.h"
        !            15: #include "../h/systm.h"
        !            16: #include "../h/buf.h"
        !            17: #include "../h/dir.h"
        !            18: #include "../h/conf.h"
        !            19: #include "../h/user.h"
        !            20: #include "../h/file.h"
        !            21: #include "../h/map.h"
        !            22: #include "../h/vm.h"
        !            23: #include "../h/mtio.h"
        !            24: #include "../h/cmap.h"
        !            25: 
        !            26: #include "../sun/dklabel.h"
        !            27: #include "../sun/dkio.h"
        !            28: #include "../machine/psl.h"
        !            29: #include "../machine/mmu.h"
        !            30: #include "../machine/cpu.h"
        !            31: #include "../sundev/mbvar.h"
        !            32: #include "../sundev/screg.h"
        !            33: #include "../sundev/sireg.h"
        !            34: #include "../sundev/scsi.h"
        !            35: #include "../sundev/streg.h"
        !            36: 
        !            37: #define        INF             1000000000
        !            38: /*
        !            39:  * Max # of buffers outstanding per unit.
        !            40:  */
        !            41: #define        MAXSTBUF        3
        !            42: 
        !            43: /*
        !            44:  * Bits in minor device.
        !            45:  */
        !            46: #define        STUNIT(dev)     (minor(dev) & 03)
        !            47: #define        T_NOREWIND      04
        !            48: #define QIC_24         8
        !            49: 
        !            50: extern struct scsi_unit stunits[];
        !            51: extern struct scsi_unit_subr scsi_unit_subr[];
        !            52: extern struct scsi_tape stape[];
        !            53: extern int nstape;
        !            54: 
        !            55: /*
        !            56:  * Return a pointer to this unit's unit structure.
        !            57:  */
        !            58: stunitptr(md)
        !            59:        register struct mb_device *md;
        !            60: {
        !            61:        return ((int)&stunits[md->md_unit]);
        !            62: }
        !            63: 
        !            64: /*
        !            65:  * Attach device (boot time).
        !            66:  */
        !            67: stattach(md)
        !            68:        register struct mb_device *md;
        !            69: {
        !            70:        register struct scsi_unit *un;
        !            71:        register struct scsi_tape *dsi;
        !            72: 
        !            73:        un = &stunits[md->md_unit];
        !            74:        dsi = &stape[md->md_unit];
        !            75:        un->un_md = md;
        !            76:        un->un_mc = md->md_mc;
        !            77:        un->un_unit = md->md_unit;
        !            78:        un->un_target = TARGET(md->md_slave);
        !            79:        un->un_lun = LUN(md->md_slave);
        !            80:        un->un_ss = &scsi_unit_subr[TYPE(md->md_flags)];
        !            81:        dsi->un_ctype = ST_TYPE_INVALID;
        !            82:        dsi->un_openf = CLOSED;
        !            83: }
        !            84: 
        !            85: stinit(dev)
        !            86:        dev_t dev;
        !            87: {
        !            88:        register int unit;
        !            89:        register struct scsi_tape *dsi;
        !            90: 
        !            91:        unit = STUNIT(dev);
        !            92:        dsi = &stape[unit];
        !            93: 
        !            94:        dsi->un_ctype = 1;
        !            95:        dsi->un_openf = OPENING;
        !            96:        stcmd(dev, SC_TEST_UNIT_READY, 0);
        !            97:        if (stcmd(dev, SC_REQUEST_SENSE, 0) == 0 || dsi->un_openf != OPEN) {
        !            98:                dsi->un_openf = OPENING;
        !            99:                if (stcmd(dev, SC_REQUEST_SENSE, 0) == 0 ||
        !           100:                    dsi->un_openf != OPEN) {
        !           101:                        if (stcmd(dev, SC_REQUEST_SENSE, 0) == 0 ||
        !           102:                            dsi->un_openf != OPEN) {
        !           103:                                if (dsi->un_openf == OPEN_FAILED) {
        !           104:                                        uprintf("st%d: no cartridge loaded\n",
        !           105:                                            unit);
        !           106:                                } else {
        !           107:                                        uprintf("st%d: tape not online \n", 
        !           108:                                            unit);
        !           109:                                }
        !           110:                                dsi->un_openf = CLOSED;
        !           111:                                dsi->un_ctype = ST_TYPE_INVALID;
        !           112:                                return (0);
        !           113:                        }
        !           114:                }
        !           115:        }
        !           116:        dsi->un_openf = CLOSED;
        !           117:        return (1);
        !           118: }
        !           119: 
        !           120: sctopen(dev, flag)
        !           121:        dev_t dev;
        !           122:        int flag;
        !           123: {
        !           124:        register struct scsi_unit *un;
        !           125:        register int unit, s;
        !           126:        register struct scsi_tape *dsi;
        !           127:        register int i;
        !           128: 
        !           129:        unit = STUNIT(dev);
        !           130:        if (unit > nstape) {
        !           131:                u.u_error = ENXIO;
        !           132:                return;
        !           133:        }
        !           134:        un = &stunits[unit];
        !           135:        dsi = &stape[unit];
        !           136:        if (un->un_mc == 0) {   /* never attached */
        !           137:                u.u_error = ENXIO;
        !           138:                return;
        !           139:        }
        !           140: 
        !           141:        /* determine type of tape controller */
        !           142:        if (dsi->un_ctype == ST_TYPE_INVALID) {
        !           143:                if (stinit(dev) == 0) {
        !           144:                        u.u_error = EIO;
        !           145:                        return;
        !           146:                }
        !           147:        }
        !           148: 
        !           149:        s = spl6();
        !           150:        if (dsi->un_openf != CLOSED) {  /* already open */
        !           151:                (void) splx(s);
        !           152:                u.u_error = EBUSY;
        !           153:                return;
        !           154:        }
        !           155:        dsi->un_openf = OPEN;
        !           156:        (void) splx(s);
        !           157:        dsi->un_read_only = 0;
        !           158: 
        !           159:        /* must be qic 24 format */
        !           160:        if (!(minor(dev) & QIC_24)) {
        !           161:                dsi->un_openf = CLOSED;
        !           162:                u.u_error = EIO;
        !           163:                return;
        !           164:        }
        !           165:        if ((flag & FWRITE) && dsi->un_read_only) {
        !           166:                uprintf("st%d: cartridge is write protected \n", unit);
        !           167:                dsi->un_openf = CLOSED;
        !           168:                u.u_error = EIO;
        !           169:                return;
        !           170:        }
        !           171:        dsi->un_lastiow = 0;
        !           172:        dsi->un_lastior = 0;
        !           173:        dsi->un_next_block = 0;
        !           174:        dsi->un_last_block = INF;
        !           175:        /* if we reset these here they will never be preserved for "mt status"
        !           176:        dsi->un_retry_ct = 0;
        !           177:        dsi->un_underruns = 0;
        !           178:        */
        !           179:        u.u_error = 0;
        !           180:        return;
        !           181: }
        !           182: 
        !           183: /*ARGSUSED*/
        !           184: sctclose(dev, flag)
        !           185:        register dev_t dev;
        !           186:        int flag;
        !           187: {
        !           188:        register struct scsi_unit *un;
        !           189:        register struct scsi_tape *dsi;
        !           190: 
        !           191:        un = &stunits[STUNIT(dev)];
        !           192:        dsi = &stape[STUNIT(dev)];
        !           193:        dsi->un_openf = CLOSING;
        !           194:        if (dsi->un_lastiow) {
        !           195:                if (stcmd(dev, SC_WRITE_FILE_MARK, 0) == 0) {
        !           196:                        printf("st%d: stclose failed to write file mark\n",
        !           197:                                un - stunits);
        !           198:                }
        !           199:        }
        !           200:        if ((minor(dev) & T_NOREWIND) == 0) {
        !           201:                (void) stcmd(dev, SC_REWIND, -1);
        !           202:        } 
        !           203:        dsi->un_openf = CLOSED;
        !           204: }
        !           205: 
        !           206: stcmd(dev, cmd, count)
        !           207:        dev_t dev;
        !           208:        int cmd, count;
        !           209: {
        !           210:        register struct buf *bp;
        !           211:        register int s, error;
        !           212:        register struct scsi_unit *un;
        !           213: 
        !           214:        un = &stunits[STUNIT(dev)];
        !           215:        bp = &un->un_sbuf;
        !           216:        s = splx(pritospl(un->un_mc->mc_intpri));
        !           217:        while (bp->b_flags & B_BUSY) {
        !           218:                /*
        !           219:                 * special test because B_BUSY never gets cleared in
        !           220:                 * the non-waiting rewind case.
        !           221:                 */
        !           222:                if (bp->b_bcount == -1 && (bp->b_flags & B_DONE)) {
        !           223:                        break;
        !           224:                }
        !           225:                bp->b_flags |= B_WANTED;
        !           226:                sleep((caddr_t) bp, PRIBIO);
        !           227:        }
        !           228:        bp->b_flags = B_BUSY | B_READ;
        !           229:        (void) splx(s);
        !           230:        bp->b_dev = dev;
        !           231:        bp->b_bcount = count;
        !           232:        un->un_scmd = cmd;
        !           233:        ststrategy(bp);
        !           234:        /*
        !           235:         * In case of rewind on close, don't wait.
        !           236:         */
        !           237:        if (cmd == SC_REWIND && count == -1) {
        !           238:                return (1);
        !           239:        }
        !           240:        s = splx(pritospl(un->un_mc->mc_intpri));
        !           241:        while ((bp->b_flags & B_DONE) == 0) {
        !           242:                sleep((caddr_t) bp, PRIBIO);
        !           243:        }
        !           244:        (void) splx(s);
        !           245:        error = geterror(bp);
        !           246:        if (bp->b_flags & B_WANTED) {
        !           247:                wakeup((caddr_t) bp);
        !           248:        }
        !           249:        bp->b_flags &= B_ERROR;         /* clears B_BUSY */
        !           250:        return (error == 0);
        !           251: }
        !           252: 
        !           253: ststrategy(bp)
        !           254:        register struct buf *bp;
        !           255: {
        !           256:        register struct scsi_unit *un;
        !           257:        register int unit, s;
        !           258:        register struct buf *ap;
        !           259:        register struct scsi_tape *dsi;
        !           260: 
        !           261:        unit = STUNIT(bp->b_dev);
        !           262:        if (unit > nstape) {
        !           263:                printf("st%d: ststrategy: invalid unit %x\n", unit, unit);
        !           264:                bp->b_flags |= B_ERROR;
        !           265:                iodone(bp);
        !           266:                return;
        !           267:        }
        !           268:        un = &stunits[unit];
        !           269:        dsi = &stape[unit];
        !           270:        if (dsi->un_openf != OPEN && bp != &un->un_sbuf) {
        !           271:                bp->b_flags |= B_ERROR;
        !           272:                iodone(bp);
        !           273:                return;
        !           274:        }
        !           275:        s = splx(pritospl(un->un_mc->mc_intpri));
        !           276:        while (dsi->un_bufcnt >= MAXSTBUF) {
        !           277:                sleep((caddr_t) &dsi->un_bufcnt, PRIBIO);
        !           278:        }
        !           279:        dsi->un_bufcnt++;
        !           280: 
        !           281:        /*
        !           282:         * Put the block at the end of the queue.
        !           283:         * Should probably have a pointer to the end of
        !           284:         * the queue, but the queue can't get too long,
        !           285:         * so the added code complexity probably isn't
        !           286:         * worth it.
        !           287:         */
        !           288:        ap = &un->un_utab;
        !           289:        while (ap->b_actf != NULL) {
        !           290:                ap = ap->b_actf;
        !           291:        }
        !           292:        ap->b_actf = bp;
        !           293:        bp->b_actf = NULL;
        !           294:        if (un->un_utab.b_active == 0) {
        !           295:                (*un->un_c->c_ss->scs_ustart)(un);
        !           296:                bp = &un->un_mc->mc_tab;
        !           297:                if (bp->b_actf && bp->b_active == 0) {
        !           298:                        (*un->un_c->c_ss->scs_start)(un);
        !           299:                }
        !           300:        }
        !           301:        (void) splx(s);
        !           302: }
        !           303: 
        !           304: /*
        !           305:  * Start the operation.
        !           306:  */
        !           307: /*ARGSUSED*/
        !           308: ststart(bp, un)
        !           309:        register struct buf *bp;
        !           310:        register struct scsi_unit *un;
        !           311: {
        !           312:        register int bno;
        !           313:        register struct scsi_tape *dsi;
        !           314: 
        !           315:        dsi = &stape[STUNIT(bp->b_dev)];
        !           316:        /*
        !           317:         * Default is that last command was NOT a read/write command;
        !           318:         * if we issue a read/write command we will notice this in stintr().
        !           319:         */
        !           320:        dsi->un_lastiow = 0;
        !           321:        dsi->un_lastior = 0;
        !           322:        if (bp == &un->un_sbuf) {
        !           323:                un->un_cmd = un->un_scmd;
        !           324:                un->un_count = bp->b_bcount;
        !           325:        } else if (bp == &un->un_rbuf) {
        !           326:                if (bp->b_flags & B_READ) {
        !           327:                        if (dsi->un_eof) {
        !           328:                                bp->b_resid = bp->b_bcount;
        !           329:                                iodone(bp);
        !           330:                                if (dsi->un_bufcnt-- >= MAXSTBUF) {
        !           331:                                        wakeup((caddr_t) &dsi->un_bufcnt);
        !           332:                                }
        !           333:                                return (0);
        !           334:                        }
        !           335:                        un->un_cmd = SC_READ;
        !           336:                } else {
        !           337:                        un->un_cmd = SC_WRITE;
        !           338:                }
        !           339:                un->un_count = howmany(bp->b_bcount, DEV_BSIZE);
        !           340:                un->un_flags |= SC_UNF_DVMA;
        !           341:        } else {
        !           342:                bno = bp->b_blkno;
        !           343:                if (bno > dsi->un_last_block && bp->b_flags & B_READ) {
        !           344:                        /* 
        !           345:                         * Can't read past EOF.
        !           346:                         */
        !           347:                        bp->b_flags |= B_ERROR;
        !           348:                        bp->b_error = EIO;
        !           349:                        iodone(bp);
        !           350:                        if (dsi->un_bufcnt-- >= MAXSTBUF) {
        !           351:                                wakeup((caddr_t) &dsi->un_bufcnt);
        !           352:                        }
        !           353:                        return (0);
        !           354:                }
        !           355:                if (bno == dsi->un_last_block && bp->b_flags & B_READ) {
        !           356:                        /*
        !           357:                         * Reading at EOF returns 0 bytes.
        !           358:                         */
        !           359:                        bp->b_resid = bp->b_bcount;
        !           360:                        iodone(bp);
        !           361:                        if (dsi->un_bufcnt-- >= MAXSTBUF) {
        !           362:                                wakeup((caddr_t) &dsi->un_bufcnt);
        !           363:                        }
        !           364:                        return (0);
        !           365:                }
        !           366:                if ((bp->b_flags & B_READ) == 0) {
        !           367:                        /*
        !           368:                         * Writing sets EOF.
        !           369:                         */
        !           370:                        dsi->un_last_block = bno + 1;
        !           371:                }
        !           372:                if (bno != dsi->un_next_block) {
        !           373:                        /*
        !           374:                         * Not the next record.
        !           375:                         * In theory we could space forward, or even rewind
        !           376:                         * and space forward, and maybe someday we will.
        !           377:                         * For now, no one really needs this capability.
        !           378:                         */
        !           379:                        bp->b_flags |= B_ERROR;
        !           380:                        bp->b_error = ENXIO;
        !           381:                        iodone(bp);
        !           382:                        if (dsi->un_bufcnt-- >= MAXSTBUF) {
        !           383:                                wakeup((caddr_t) &dsi->un_bufcnt);
        !           384:                        }
        !           385:                        return (0);
        !           386:                }
        !           387:                /*
        !           388:                 * Position OK, we can do the read or write.
        !           389:                 */
        !           390:                if (bp->b_flags & B_READ) {
        !           391:                        un->un_cmd = SC_READ;
        !           392:                } else {
        !           393:                        un->un_cmd = SC_WRITE;
        !           394:                }
        !           395:                un->un_count = howmany(bp->b_bcount, DEV_BSIZE);
        !           396:                un->un_flags |= SC_UNF_DVMA;
        !           397:        }
        !           398:        bp->b_resid = 0;
        !           399:        return (1);
        !           400: }
        !           401: 
        !           402: /*
        !           403:  * Make a command description block.
        !           404:  */
        !           405: stmkcdb(c, un)
        !           406:        register struct scsi_ctlr *c;
        !           407:        register struct scsi_unit *un;
        !           408: {
        !           409:        register struct scsi_cdb *cdb;
        !           410:        register struct scsi_tape *dsi;
        !           411:        int density = 0;
        !           412: 
        !           413:        cdb = &c->c_cdb;
        !           414:        bzero((caddr_t)cdb, sizeof (*cdb));
        !           415:        cdb->cmd = un->un_cmd;
        !           416:        cdb->lun = un->un_lun;
        !           417:        un->un_dma_addr = un->un_dma_count = 0;
        !           418:        dsi = &stape[un->un_unit];
        !           419: 
        !           420:        switch (un->un_cmd) {
        !           421: 
        !           422:        case SC_WRITE_FILE_MARK:
        !           423:        case SC_LOAD:
        !           424:                cdb->count = 1;
        !           425:                break;
        !           426: 
        !           427:        case SC_TEST_UNIT_READY:
        !           428:                break;
        !           429:                
        !           430:        case SC_REWIND:
        !           431:                break;
        !           432: 
        !           433:        case SC_ERASE_CARTRIDGE:
        !           434:                cdb->t_code = 1;
        !           435:                break;
        !           436: 
        !           437:        case SC_REQUEST_SENSE:
        !           438:                un->un_dma_addr = (int)c->c_sense - (int)DVMA;
        !           439:                un->un_dma_count = cdb->count = sizeof (struct st_archive_sense);               
        !           440:                break;
        !           441: 
        !           442:        case SC_READ:
        !           443:        case SC_WRITE:
        !           444:                cdb->t_code = 1;
        !           445:                cdb->high_count = un->un_count >> 16;
        !           446:                cdb->mid_count = (un->un_count >> 8) & 0xFF;
        !           447:                cdb->low_count = un->un_count & 0xFF;
        !           448:                un->un_dma_addr = un->un_baddr;
        !           449:                un->un_dma_count = un->un_count * DEV_BSIZE;
        !           450:                break;
        !           451: 
        !           452:        case SC_SPACE_FILE:
        !           453:                if (un->un_count == 0)
        !           454:                        cdb->t_code = 3;        /* space to end */
        !           455:                else
        !           456:                        cdb->t_code = 1;        /* space files, not records */
        !           457:                /* fall through ... */
        !           458: 
        !           459:        case SC_SPACE_REC:
        !           460:                cdb->cmd = SC_SPACE;
        !           461:                cdb->high_count = un->un_count >> 16;
        !           462:                cdb->mid_count = (un->un_count >> 8) & 0xFF;
        !           463:                cdb->low_count = un->un_count & 0xFF;
        !           464:                un->un_dma_addr = un->un_dma_count = 0;
        !           465:                break;
        !           466: 
        !           467:        default:
        !           468:                printf("st%d: stmkcdb: invalid command %x\n", un - stunits,
        !           469:                        un->un_cmd);
        !           470:                break;  
        !           471:        }
        !           472: }
        !           473: 
        !           474: stintr(c, resid, error)
        !           475:        register struct scsi_ctlr *c;
        !           476:        register int resid, error;
        !           477: {
        !           478:        register struct scsi_unit *un;
        !           479:        register struct buf *bp;
        !           480:        register struct scsi_tape *dsi;
        !           481:        struct st_archive_sense *ars;
        !           482: 
        !           483:        un = c->c_un;
        !           484:        bp = un->un_mc->mc_tab.b_actf->b_actf;
        !           485:        dsi = &stape[STUNIT(bp->b_dev)];
        !           486:        ars = (struct st_archive_sense *)c->c_sense;
        !           487: 
        !           488:        /* 
        !           489:         * We determine which tape controller we have by the number of
        !           490:         * sense bytes we get back.
        !           491:         */
        !           492:        if (dsi->un_openf == OPENING && un->un_cmd == SC_REQUEST_SENSE) {
        !           493:                if (resid || ST_NO_CART(dsi, c->c_sense)) {
        !           494:                        dsi->un_openf = OPEN_FAILED;
        !           495:                } else {
        !           496:                        dsi->un_openf = OPEN;
        !           497:                        if (ST_WRITE_PROT(dsi, c->c_sense))
        !           498:                                dsi->un_read_only = 1;
        !           499:                }
        !           500:        }
        !           501: 
        !           502:        if (c->c_scb.busy)
        !           503:                bp->b_flags |= B_ERROR;
        !           504:        else if (error || c->c_scb.chk || resid > 0) {
        !           505:                if (c->c_scb.chk && ST_RESET(dsi, c->c_sense)) {
        !           506:                        /*
        !           507:                         * Power on or reset occurred
        !           508:                         */
        !           509:                        dsi->un_reset_occurred = 1;
        !           510:                        bp->b_flags |= B_ERROR;
        !           511:                } else if (c->c_scb.chk && ST_NO_CART(dsi, c->c_sense)) {
        !           512:                        printf("st%d: no cartridge loaded \n", 
        !           513:                            un - stunits);
        !           514:                        bp->b_flags |= B_ERROR;
        !           515:                } else if (c->c_scb.chk && ST_FILE_MARK(dsi, c->c_sense)) {
        !           516:                        /*
        !           517:                         * File mark detected.
        !           518:                         */
        !           519:                        dsi->un_eof = 1;
        !           520:                        switch (un->un_cmd) {
        !           521:                        case SC_READ:
        !           522:                                dsi->un_next_block += un->un_count -
        !           523:                                        resid / DEV_BSIZE;
        !           524:                                dsi->un_last_block = dsi->un_next_block;
        !           525:                                break;
        !           526:                        case SC_SPACE_REC:
        !           527:                                dsi->un_last_block = dsi->un_next_block +=
        !           528:                                        un->un_count;   /* a little high */
        !           529:                                break;
        !           530:                        default:
        !           531:                                printf("st%d: scsi tape hit eof on cmd %x\n",
        !           532:                                        un - stunits, un->un_cmd);
        !           533:                                break;
        !           534:                        }
        !           535:                        bp->b_resid = resid;
        !           536:                } else if ((un->un_cmd == SC_WRITE || 
        !           537:                    un->un_cmd == SC_WRITE_FILE_MARK) &&
        !           538:                    c->c_scb.chk && ST_WRITE_PROT(dsi, c->c_sense)) {
        !           539:                        /*
        !           540:                         * Write protected tape.
        !           541:                         */
        !           542:                        printf("st%d: tape is write protected \n, ",
        !           543:                                un - stunits);
        !           544:                        dsi->un_read_only = 1;
        !           545:                        bp->b_flags |= B_ERROR;
        !           546:                } else if (c->c_scb.chk && ST_EOT(dsi, c->c_sense)) {
        !           547:                        /*
        !           548:                         * End of tape.
        !           549:                         */
        !           550:                        bp->b_resid = bp->b_bcount;
        !           551:                        if (un->un_cmd == SC_WRITE) {
        !           552:                                /*
        !           553:                                 * Setting this flag makes stclose()
        !           554:                                 * write a file mark before closing.
        !           555:                                 * Until a file mark is written, the 
        !           556:                                 * tape will return invalid command
        !           557:                                 * indications and not respond to 
        !           558:                                 * rewinds.
        !           559:                                 */
        !           560:                                dsi->un_lastiow = 1;
        !           561:                        }
        !           562:                } else if (c->c_scb.chk && ST_ILLEGAL(dsi, c->c_sense)) {
        !           563:                        printf("st%d: illegal command 0x%x\n", un-stunits, un->un_cmd);
        !           564:                        bp->b_flags |= B_ERROR;
        !           565:                } else if (ST_CORRECTABLE(dsi, c->c_sense))
        !           566:                        goto success;
        !           567:                else if (ST_EOD(dsi, c->c_sense))
        !           568:                        bp->b_flags |= B_ERROR;
        !           569:                else {
        !           570:                        /*
        !           571:                         * Some other error which we can't handle.
        !           572:                         */
        !           573:                        if ((c->c_scb.chk && dsi->un_openf == OPEN))
        !           574:                                st_pr_sense(c, dsi);
        !           575:                        bp->b_flags |= B_ERROR;
        !           576:                }
        !           577:        } else {
        !           578: success:
        !           579:                switch (un->un_cmd) {
        !           580: 
        !           581:                case SC_REWIND:
        !           582:                case SC_ERASE_CARTRIDGE:
        !           583:                case SC_MODE_SELECT:
        !           584:                case SC_LOAD:
        !           585:                        dsi->un_next_block = 0;
        !           586:                        dsi->un_eof = 0;
        !           587:                        break;
        !           588: 
        !           589:                case SC_WRITE:
        !           590:                        dsi->un_lastiow = 1;
        !           591:                        dsi->un_next_block += un->un_count;
        !           592:                        break;
        !           593: 
        !           594:                case SC_READ:
        !           595:                        dsi->un_lastior = 1;
        !           596:                        dsi->un_next_block += un->un_count;
        !           597:                        break;
        !           598: 
        !           599:                case SC_SPACE_FILE:
        !           600:                        dsi->un_next_block = 0;
        !           601:                        dsi->un_last_block = INF;
        !           602:                        dsi->un_eof = 0;
        !           603:                        break;
        !           604: 
        !           605:                case SC_SPACE_REC:
        !           606:                        dsi->un_next_block += un->un_count;
        !           607:                        break;
        !           608: 
        !           609:                case SC_REQUEST_SENSE:
        !           610:                        dsi->un_status = ((char *)ars)[2];
        !           611: /*
        !           612:                        if (ars->ext_sense.add_len >= AR_ES_ADD_LEN) {
        !           613:                                dsi->un_retry_ct += 
        !           614:                                    (ars->retries_msb << 8) +
        !           615:                                    ars->retries_lsb;
        !           616:                        }
        !           617: */
        !           618:                        break;
        !           619: 
        !           620:                case SC_TEST_UNIT_READY:
        !           621:                        break;
        !           622: 
        !           623:                case SC_WRITE_FILE_MARK:
        !           624:                        dsi->un_next_block = 0;
        !           625:                        dsi->un_last_block = 0; /* i.e. no reads allowed */
        !           626:                        break;
        !           627: 
        !           628:                default:
        !           629:                        printf("st%d: stintr: invalid command %x\n",
        !           630:                            un - stunits, un->un_cmd);
        !           631:                        break;
        !           632:                }
        !           633:        }
        !           634:        if (bp == &un->un_sbuf && 
        !           635:            ((un->un_flags & SC_UNF_DVMA) == 0)) {
        !           636:                (*c->c_ss->scs_done)(un->un_mc);
        !           637:        } else {
        !           638:                mbdone(un->un_mc);
        !           639:                un->un_flags &= ~SC_UNF_DVMA;
        !           640:        }
        !           641:        if (dsi->un_bufcnt-- >= MAXSTBUF) {
        !           642:                wakeup((caddr_t) &dsi->un_bufcnt);
        !           643:        }
        !           644: }
        !           645: 
        !           646: st_pr_sense(c, dsi)
        !           647:        register struct scsi_ctlr *c;
        !           648:        register struct scsi_tape *dsi;
        !           649: {
        !           650:        register struct scsi_unit *un;
        !           651:        register u_char *cp;
        !           652:        register int i;
        !           653: 
        !           654:        un = c->c_un;
        !           655:        cp = (u_char *)c->c_sense;
        !           656:        printf("st%d: stintr: sense ", un - stunits);
        !           657:        for (i=0; i < sizeof (struct st_archive_sense); i++)
        !           658:                printf("%x ", *cp++);
        !           659:        printf("\n");
        !           660: }
        !           661: 
        !           662: sctread(dev)
        !           663:        register dev_t dev;
        !           664: {
        !           665:        register struct scsi_unit *un;
        !           666:        register int unit, r, resid;
        !           667:        register struct scsi_tape *dsi;
        !           668: 
        !           669:        unit = STUNIT(dev);
        !           670:        if (unit > nstape) {
        !           671:                u.u_error = ENXIO;
        !           672:                return;
        !           673:        }
        !           674:        un = &stunits[unit];
        !           675:        dsi = &stape[unit];
        !           676:        if (u.u_count % DEV_BSIZE) {
        !           677:                u.u_error = ENXIO;
        !           678:                return; /* drive can't do it */
        !           679:        }
        !           680:        resid = u.u_count;
        !           681:        dsi->un_next_block = u.u_offset / DEV_BSIZE;
        !           682:        dsi->un_last_block = INF;
        !           683:        physio(ststrategy, &un->un_rbuf, dev, B_READ, minphys);
        !           684:        if (dsi->un_eof && u.u_count == resid) {
        !           685:                dsi->un_eof = 0;        /* the user is really getting it */
        !           686:        }
        !           687: }
        !           688: 
        !           689: sctwrite(dev)
        !           690:        register dev_t dev;
        !           691: {
        !           692:        register struct scsi_unit *un;
        !           693:        register int unit;
        !           694:        register struct scsi_tape *dsi;
        !           695: 
        !           696:        unit = STUNIT(dev);
        !           697:        if (unit > nstape) {
        !           698:                u.u_error = ENXIO;
        !           699:                return;
        !           700:        }
        !           701:        un = &stunits[unit];
        !           702:        dsi = &stape[unit];
        !           703:        dsi->un_next_block = u.u_offset / DEV_BSIZE;
        !           704:        dsi->un_last_block = INF;
        !           705:        physio(ststrategy, &un->un_rbuf, dev, B_WRITE, minphys);
        !           706: }
        !           707: 
        !           708: /*ARGSUSED*/
        !           709: sctioctl(dev, cmd, data, flag)
        !           710:        register dev_t dev;
        !           711:        register int cmd;
        !           712:        register caddr_t data;
        !           713:        int flag;
        !           714: {
        !           715:        register int fcount;
        !           716:        struct mtop mtop;
        !           717:        struct mtget mtget;
        !           718:        register int unit;
        !           719:        register struct scsi_tape *dsi;
        !           720:        static int ops[] = {
        !           721:                SC_WRITE_FILE_MARK,     /* write tape mark */
        !           722:                SC_SPACE_FILE,          /* forward space file */
        !           723:                SC_SPACE_FILE,          /* backspace file */
        !           724:                SC_SPACE_REC,           /* forward space record */
        !           725:                SC_SPACE_REC,           /* backspace record */
        !           726:                SC_REWIND,              /* rewind tape */
        !           727:                SC_REWIND,              /* unload - we just rewind */
        !           728:                SC_REQUEST_SENSE,       /* get status */
        !           729:                SC_REWIND,              /* retension - rewind + vu_57 */
        !           730:                SC_ERASE_CARTRIDGE,     /* erase entire tape */
        !           731:        };
        !           732: 
        !           733:        unit = STUNIT(dev);
        !           734:        if (unit > nstape) {
        !           735:                u.u_error = ENXIO;
        !           736:                return;
        !           737:        }
        !           738:        dsi = &stape[unit];
        !           739:        switch (cmd) {
        !           740:        case MTIOCTOP:  /* tape operation */
        !           741:                if (copyin((caddr_t)data, (caddr_t)&mtop, sizeof(mtop))) {
        !           742:                        u.u_error = EFAULT;
        !           743:                        return;
        !           744:                }
        !           745:                switch (mtop.mt_op) {
        !           746:                case MTWEOF:
        !           747:                case MTERASE:
        !           748:                        if (dsi->un_read_only) {
        !           749:                                u.u_error = ENXIO;
        !           750:                                return;
        !           751:                        }
        !           752:                }
        !           753: 
        !           754:                switch (mtop.mt_op) {
        !           755:                case MTBSF:
        !           756:                case MTBSR:
        !           757:                        fcount = -mtop.mt_count;
        !           758:                        break;
        !           759:                case MTRETEN:
        !           760:                        dsi->un_reten_rewind = 1;
        !           761:                        /* FALL THRU */
        !           762:                case MTFSF:
        !           763:                        fcount = mtop.mt_count;
        !           764:                        if (fcount == -1)
        !           765:                                fcount = 0;
        !           766:                case MTWEOF:
        !           767:                case MTREW:
        !           768:                case MTOFFL:
        !           769:                case MTNOP:
        !           770:                case MTERASE:
        !           771:                        fcount = mtop.mt_count;
        !           772:                        break;
        !           773:                default:
        !           774:                        u.u_error = ENXIO;
        !           775:                        return;
        !           776:                }
        !           777:                /*
        !           778:                 * If eof_flag then we hit eof but didn't tell the user yet.
        !           779:                 */
        !           780:                if (ops[mtop.mt_op] == SC_SPACE_FILE && dsi->un_eof) {
        !           781:                        dsi->un_eof = 0;
        !           782:                        if (mtop.mt_op == MTFSF)
        !           783:                                fcount--;
        !           784:                }
        !           785:                if (stcmd(dev, ops[mtop.mt_op], fcount) == 0)
        !           786:                        u.u_error = EIO;
        !           787:                return;
        !           788: 
        !           789:        case MTIOCGET:
        !           790:                if (stcmd(dev, SC_REQUEST_SENSE, 0) == 0) {
        !           791:                        u.u_error = EIO;
        !           792:                        return;
        !           793:                }
        !           794:                mtget.mt_type = MT_ISSC;
        !           795:                mtget.mt_erreg = dsi->un_status;
        !           796:                mtget.mt_fileno = dsi->un_retry_ct;
        !           797:                mtget.mt_blkno = dsi->un_underruns;
        !           798:                dsi->un_retry_ct = dsi->un_underruns = 0;
        !           799:                if (copyout((caddr_t)&mtget, data, sizeof(mtget)))
        !           800:                        u.u_error = EFAULT;
        !           801:                return;
        !           802: 
        !           803:        default:
        !           804:                u.u_error = ENXIO;
        !           805:                return;
        !           806:        }
        !           807: }
        !           808: #endif NST > 0

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.