Annotation of Gnu-Mach/scsi/rz_tape.c, revision 1.1.1.1

1.1       root        1: /* 
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1991,1990 Carnegie Mellon University
                      4:  * All Rights Reserved.
                      5:  * 
                      6:  * Permission to use, copy, modify and distribute this software and its
                      7:  * documentation is hereby granted, provided that both the copyright
                      8:  * notice and this permission notice appear in all copies of the
                      9:  * software, derivative works or modified versions, and any portions
                     10:  * thereof, and that both notices appear in supporting documentation.
                     11:  * 
                     12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     15:  * 
                     16:  * Carnegie Mellon requests users of this software to return to
                     17:  * 
                     18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
                     22:  * 
                     23:  * any improvements or extensions that they make and grant Carnegie Mellon
                     24:  * the rights to redistribute these changes.
                     25:  */
                     26: /*
                     27:  *     File: rz_tape.c
                     28:  *     Author: Alessandro Forin, Carnegie Mellon University
                     29:  *     Date:   10/90
                     30:  *
                     31:  *     Top layer of the SCSI driver: interface with the MI.
                     32:  *     This file contains operations specific to TAPE-like devices.
                     33:  */
                     34: 
                     35: #include <mach/std_types.h>
                     36: #include <scsi/compat_30.h>
                     37: 
                     38: #include <sys/ioctl.h>
                     39: #ifdef MACH_KERNEL
                     40: #include <device/tape_status.h>
                     41: #else  /*MACH_KERNEL*/
                     42: #include <mips/PMAX/tape_status.h>
                     43: #endif /*MACH_KERNEL*/
                     44: 
                     45: #include <scsi/scsi.h>
                     46: #include <scsi/scsi_defs.h>
                     47: #include <scsi/rz.h>
                     48: 
                     49: #if  (NSCSI > 0)
                     50: 
                     51: 
                     52: void sctape_start(); /* forward */
                     53: 
                     54: int scsi_tape_timeout = 5*60;  /* secs, tk50 is slow when positioning far apart */
                     55: 
                     56: int sctape_open(tgt, req)
                     57:        target_info_t   *tgt;
                     58:        io_req_t        req;
                     59: {
                     60:        io_return_t     ret;
                     61:        io_req_t        ior;
                     62:        int             i;
                     63:        scsi_mode_sense_data_t *mod;
                     64: 
                     65: #ifdef MACH_KERNEL
                     66:        req->io_device->flag |= D_EXCL_OPEN;
                     67: #endif /*MACH_KERNEL*/
                     68: 
                     69:        /* Preferably allow tapes to disconnect */
                     70:        if (BGET(scsi_might_disconnect,(unsigned char)tgt->masterno,tgt->target_id))
                     71:                BSET(scsi_should_disconnect,(unsigned char)tgt->masterno,tgt->target_id);
                     72: 
                     73:        /*
                     74:         * Dummy ior for proper sync purposes
                     75:         */
                     76:        io_req_alloc(ior,0);
                     77:        ior->io_count = 0;
                     78: 
                     79:        /*
                     80:         * Do a mode sense first, some drives might be picky
                     81:         * about changing params [even if the standard might
                     82:         * say otherwise, sigh.]
                     83:         */
                     84:        do {
                     85:                ior->io_op = IO_INTERNAL;
                     86:                ior->io_next = 0;
                     87:                ior->io_error = 0;
                     88:                ret = scsi_mode_sense(tgt, 0, 32, ior);
                     89:        } while (ret == SCSI_RET_RETRY);
                     90: 
                     91:        mod = (scsi_mode_sense_data_t *)tgt->cmd_ptr;
                     92:        if (scsi_debug) {
                     93:                int     p[5];
                     94:                bcopy((char*)mod, (char*)p, sizeof(p));
                     95:                printf("[modsns(%x): x%x x%x x%x x%x x%x]", ret,
                     96:                        p[0], p[1], p[2], p[3], p[4]);
                     97:        }
                     98:        if (ret == SCSI_RET_DEVICE_DOWN)
                     99:                goto out;
                    100:        if (ret == SCSI_RET_SUCCESS) {
                    101:                tgt->dev_info.tape.read_only = mod->wp;
                    102:                tgt->dev_info.tape.speed = mod->speed;
                    103:                tgt->dev_info.tape.density = mod->bdesc[0].density_code;
                    104:        } /* else they all default sensibly, using zeroes */
                    105: 
                    106:        /* Some tapes have limits on record-length */
                    107: again:
                    108:        ior->io_op = IO_INTERNAL;
                    109:        ior->io_next = 0;
                    110:        ior->io_error = 0;
                    111:        ret = scsi_read_block_limits( tgt, ior);
                    112:        if (ret == SCSI_RET_RETRY) goto again;
                    113:        if (!ior->io_error && (ret == SCSI_RET_SUCCESS)) {
                    114:                scsi_blimits_data_t     *lim;
                    115:                int                     maxl;
                    116: 
                    117:                lim = (scsi_blimits_data_t *) tgt->cmd_ptr;
                    118: 
                    119:                tgt->block_size = (lim->minlen_msb << 8) |
                    120:                                   lim->minlen_lsb;
                    121: 
                    122:                maxl =  (lim->maxlen_msb << 16) |
                    123:                        (lim->maxlen_sb  <<  8) |
                    124:                         lim->maxlen_lsb;
                    125:                if (maxl == 0)
                    126:                        maxl = (unsigned)-1;
                    127:                tgt->dev_info.tape.maxreclen = maxl;
                    128:                tgt->dev_info.tape.fixed_size = (maxl == tgt->block_size);
                    129:        } else {
                    130:                /* let the user worry about it */
                    131:                /* default: tgt->block_size = 1; */
                    132:                tgt->dev_info.tape.maxreclen = (unsigned)-1;
                    133:                tgt->dev_info.tape.fixed_size = FALSE;
                    134:        }
                    135: 
                    136:        /* Try hard to do a mode select */
                    137:        for (i = 0; i < 5; i++) {
                    138:                ior->io_op = IO_INTERNAL;
                    139:                ior->io_error = 0;
                    140:                ret = sctape_mode_select(tgt, 0, 0, FALSE, ior);
                    141:                if (ret == SCSI_RET_SUCCESS)
                    142:                        break;
                    143:        }
                    144:        if (scsi_watchdog_period < scsi_tape_timeout)
                    145:                scsi_watchdog_period += scsi_tape_timeout;
                    146: 
                    147: #if 0  /* this might imply rewind, which we do not want, although yes, .. */
                    148:        /* we want the tape loaded */
                    149:        ior->io_op = IO_INTERNAL;
                    150:        ior->io_next = 0;
                    151:        ior->io_error = 0;
                    152:        ret = scsi_start_unit(tgt, SCSI_CMD_SS_START, ior);
                    153: #endif
                    154:        req->io_device->bsize = tgt->block_size;
                    155: out:
                    156:        io_req_free(ior);
                    157:        return ret;
                    158: }
                    159: 
                    160: 
                    161: io_return_t sctape_close(tgt)
                    162:        target_info_t   *tgt;
                    163: {
                    164:        io_return_t     ret = SCSI_RET_SUCCESS;
                    165:        io_req_t        ior;
                    166: 
                    167:        /*
                    168:         * Dummy ior for proper sync purposes
                    169:         */
                    170:        io_req_alloc(ior,0);
                    171:        ior->io_op = IO_INTERNAL;
                    172:        ior->io_next = 0;
                    173:        ior->io_count = 0;
                    174: 
                    175:        if (tgt->ior) printf("TAPE: Close with pending requests ?? \n");
                    176: 
                    177:        /* write a filemark if we xtnded/truncated the tape */
                    178:        if (tgt->flags & TGT_WRITTEN_TO) {
                    179:                tgt->ior = ior;
                    180:                ior->io_error = 0;
                    181:                ret = scsi_write_filemarks(tgt, 2, ior);
                    182:                if (ret != SCSI_RET_SUCCESS)
                    183:                         printf("%s%d: wfmark failed x%x\n",
                    184:                         (*tgt->dev_ops->driver_name)(TRUE), tgt->target_id, ret);
                    185:                /*
                    186:                 * Don't bother repositioning if we'll rewind it
                    187:                 */
                    188:                if (tgt->flags & TGT_REWIND_ON_CLOSE)
                    189:                        goto rew;
                    190: retry:
                    191:                tgt->ior = ior;
                    192:                ior->io_op = IO_INTERNAL;
                    193:                ior->io_error = 0;
                    194:                ior->io_next = 0;
                    195:                ret = scsi_space(tgt, SCSI_CMD_SP_FIL, -1, ior);
                    196:                if (ret != SCSI_RET_SUCCESS) {
                    197:                        if (ret == SCSI_RET_RETRY) {
                    198:                                timeout(wakeup, tgt, hz);
                    199:                                await(tgt);
                    200:                                goto retry;
                    201:                        }
                    202:                        printf("%s%d: bspfile failed x%x\n",
                    203:                         (*tgt->dev_ops->driver_name)(TRUE), tgt->target_id, ret);
                    204:                }
                    205:        }
                    206: rew:
                    207:        if (tgt->flags & TGT_REWIND_ON_CLOSE) {
                    208:                /* Rewind tape */
                    209:                ior->io_error = 0;
                    210:                ior->io_op = IO_INTERNAL;
                    211:                ior->io_error = 0;
                    212:                tgt->ior = ior;
                    213:                (void) scsi_rewind(tgt, ior, FALSE);
                    214:                iowait(ior);
                    215:                if (tgt->done == SCSI_RET_RETRY) {
                    216:                        timeout(wakeup, tgt, 5*hz);
                    217:                        await(tgt);
                    218:                        goto rew;
                    219:                }
                    220:        }
                    221:                io_req_free(ior);
                    222: 
                    223:        tgt->flags &= ~(TGT_ONLINE|TGT_WRITTEN_TO|TGT_REWIND_ON_CLOSE);
                    224:        return ret;
                    225: }
                    226: 
                    227: int sctape_strategy(ior)
                    228:        register io_req_t       ior;
                    229: {
                    230:        target_info_t  *tgt;
                    231:        register int    i = ior->io_unit;
                    232: 
                    233:        tgt = scsi_softc[rzcontroller(i)]->target[rzslave(i)];
                    234: 
                    235:        if (((ior->io_op & IO_READ) == 0) &&
                    236:            tgt->dev_info.tape.read_only) {
                    237:                ior->io_error = D_INVALID_OPERATION;
                    238:                ior->io_op |= IO_ERROR;
                    239:                ior->io_residual = ior->io_count;
                    240:                iodone(ior);
                    241:                return ior->io_error;
                    242:        }
                    243: 
                    244:        return rz_simpleq_strategy( ior, sctape_start);
                    245: }
                    246: 
                    247: static void
                    248: do_residue(ior, sns, bsize)
                    249:        io_req_t          ior;
                    250:        scsi_sense_data_t *sns;
                    251:        int               bsize;
                    252: {
                    253:        int residue;
                    254: 
                    255:        /* Not an error situation */
                    256:        ior->io_error = 0;
                    257:        ior->io_op &= ~IO_ERROR;
                    258: 
                    259:        if (!sns->addr_valid) {
                    260:                ior->io_residual = ior->io_count;
                    261:                return;
                    262:        }
                    263: 
                    264:        residue = sns->u.xtended.info0 << 24 |
                    265:                  sns->u.xtended.info1 << 16 |
                    266:                  sns->u.xtended.info2 <<  8 |
                    267:                  sns->u.xtended.info3;
                    268:        /* fixed ? */
                    269:        residue *= bsize;
                    270:        /*
                    271:         * NOTE: residue == requested - actual
                    272:         * We only care if > 0
                    273:         */
                    274:        if (residue < 0) residue = 0;/* sanity */
                    275:        ior->io_residual += residue;
                    276: }
                    277: 
                    278: void sctape_start( tgt, done)
                    279:        target_info_t   *tgt;
                    280:        boolean_t       done;
                    281: {
                    282:        io_req_t                head, ior = tgt->ior;
                    283: 
                    284:        if (ior == 0)
                    285:                return;
                    286: 
                    287:        if (done) {
                    288: 
                    289:                /* see if we must retry */
                    290:                if ((tgt->done == SCSI_RET_RETRY) &&
                    291:                    ((ior->io_op & IO_INTERNAL) == 0)) {
                    292:                        delay(1000000);/*XXX*/
                    293:                        goto start;
                    294:                } else
                    295:                /* got a bus reset ? ouch, that hurts */
                    296:                if (tgt->done == (SCSI_RET_ABORTED|SCSI_RET_RETRY)) {
                    297:                        /*
                    298:                         * we really cannot retry because the tape position
                    299:                         * is lost.
                    300:                         */
                    301:                        printf("Lost tape position\n");
                    302:                        ior->io_error = D_IO_ERROR;
                    303:                        ior->io_op |= IO_ERROR;
                    304:                } else
                    305: 
                    306:                /* check completion status */
                    307: 
                    308:                if (tgt->cur_cmd == SCSI_CMD_REQUEST_SENSE) {
                    309:                        scsi_sense_data_t *sns;
                    310: 
                    311:                        ior->io_op = ior->io_temporary;
                    312:                        ior->io_error = D_IO_ERROR;
                    313:                        ior->io_op |= IO_ERROR;
                    314: 
                    315:                        sns = (scsi_sense_data_t *)tgt->cmd_ptr;
                    316: 
                    317:                        if (scsi_debug)
                    318:                                scsi_print_sense_data(sns);
                    319: 
                    320:                        if (scsi_check_sense_data(tgt, sns)) {
                    321:                            if (sns->u.xtended.ili) {
                    322:                                if (ior->io_op & IO_READ) {
                    323:                                    do_residue(ior, sns, tgt->block_size);
                    324:                                    if (scsi_debug)
                    325:                                        printf("Tape Short Read (%d)\n",
                    326:                                                ior->io_residual);
                    327:                                }
                    328:                            } else if (sns->u.xtended.eom) {
                    329:                                do_residue(ior, sns, tgt->block_size);
                    330:                                if (scsi_debug)
                    331:                                        printf("End of Physical Tape!\n");
                    332:                            } else if (sns->u.xtended.fm) {
                    333:                                do_residue(ior, sns, tgt->block_size);
                    334:                                if (scsi_debug)
                    335:                                        printf("File Mark\n");
                    336:                            }
                    337:                        }
                    338:                }
                    339: 
                    340:                else if (tgt->done != SCSI_RET_SUCCESS) {
                    341: 
                    342:                    if (tgt->done == SCSI_RET_NEED_SENSE) {
                    343: 
                    344:                        ior->io_temporary = ior->io_op;
                    345:                        ior->io_op = IO_INTERNAL;
                    346:                        if (scsi_debug)
                    347:                                printf("[NeedSns x%x x%x]", ior->io_residual, ior->io_count);
                    348:                        scsi_request_sense(tgt, ior, 0);
                    349:                        return;
                    350: 
                    351:                    } else if (tgt->done == SCSI_RET_RETRY) {
                    352:                        /* only retry here READs and WRITEs */
                    353:                        if ((ior->io_op & IO_INTERNAL) == 0) {
                    354:                                ior->io_residual = 0;
                    355:                                goto start;
                    356:                        } else{
                    357:                                ior->io_error = D_WOULD_BLOCK;
                    358:                                ior->io_op |= IO_ERROR;
                    359:                        }
                    360:                    } else {
                    361:                        ior->io_error = D_IO_ERROR;
                    362:                        ior->io_op |= IO_ERROR;
                    363:                    }
                    364:                }
                    365: 
                    366:                if (scsi_debug)
                    367:                        printf("[Resid x%x]", ior->io_residual);
                    368: 
                    369:                /* dequeue next one */
                    370:                head = ior;
                    371: 
                    372:                simple_lock(&tgt->target_lock);
                    373:                ior = head->io_next;
                    374:                tgt->ior = ior;
                    375:                if (ior)
                    376:                        ior->io_prev = head->io_prev;
                    377:                simple_unlock(&tgt->target_lock);
                    378: 
                    379:                iodone(head);
                    380: 
                    381:                if (ior == 0)
                    382:                        return;
                    383:        }
                    384:        ior->io_residual = 0;
                    385: start:
                    386:        if (ior->io_op & IO_READ) {
                    387:                tgt->flags &= ~TGT_WRITTEN_TO;
                    388:                sctape_read( tgt, ior );
                    389:        } else if ((ior->io_op & IO_INTERNAL) == 0) {
                    390:                tgt->flags |= TGT_WRITTEN_TO;
                    391:                sctape_write( tgt, ior );
                    392:        }
                    393: }
                    394: 
                    395: io_return_t
                    396: sctape_get_status( dev, tgt, flavor, status, status_count)
                    397:        int             dev;
                    398:        target_info_t   *tgt;
                    399:        dev_flavor_t    flavor;
                    400:        dev_status_t    status;
                    401:        natural_t       *status_count;
                    402: {
                    403:        switch (flavor) {
                    404:        case DEV_GET_SIZE:
                    405:                
                    406:                status[DEV_GET_SIZE_DEVICE_SIZE] = 0;
                    407:                status[DEV_GET_SIZE_RECORD_SIZE] = tgt->block_size;
                    408:                *status_count = DEV_GET_SIZE_COUNT;
                    409:                break;
                    410:        case TAPE_STATUS: {
                    411:                struct tape_status *ts = (struct tape_status *) status;
                    412: 
                    413:                ts->mt_type             = MT_ISSCSI;
                    414:                ts->speed               = tgt->dev_info.tape.speed;
                    415:                ts->density             = tgt->dev_info.tape.density;
                    416:                ts->flags               = (tgt->flags & TGT_REWIND_ON_CLOSE) ?
                    417:                                                TAPE_FLG_REWIND : 0;
                    418:                if (tgt->dev_info.tape.read_only)
                    419:                        ts->flags |= TAPE_FLG_WP;
                    420: #ifdef MACH_KERNEL
                    421:                *status_count = TAPE_STATUS_COUNT;
                    422: #endif
                    423: 
                    424:                break;
                    425:            }
                    426:        /* U*x compat */
                    427:        case MTIOCGET: {
                    428:                struct mtget *g = (struct mtget *) status;
                    429: 
                    430:                bzero(g, sizeof(struct mtget));
                    431:                g->mt_type = 0x7;       /* Ultrix compat */
                    432: #ifdef MACH_KERNEL
                    433:                *status_count = sizeof(struct mtget)/sizeof(int);
                    434: #endif
                    435:                break;
                    436:            }
                    437:        default:
                    438:                return D_INVALID_OPERATION;
                    439:        }
                    440:        return D_SUCCESS;
                    441: }
                    442: 
                    443: io_return_t
                    444: sctape_set_status( dev, tgt, flavor, status, status_count)
                    445:        int             dev;
                    446:        target_info_t   *tgt;
                    447:        dev_flavor_t    flavor;
                    448:        dev_status_t    status;
                    449:        natural_t       status_count;
                    450: {
                    451:        scsi_ret_t              ret;
                    452: 
                    453:        switch (flavor) {
                    454:        case TAPE_STATUS: {
                    455:                struct tape_status *ts = (struct tape_status *) status;
                    456:                if (ts->flags & TAPE_FLG_REWIND)
                    457:                        tgt->flags |= TGT_REWIND_ON_CLOSE;
                    458:                else
                    459:                        tgt->flags &= ~TGT_REWIND_ON_CLOSE;
                    460: 
                    461:                if (ts->speed || ts->density) {
                    462:                        unsigned int ospeed, odensity;
                    463:                        io_req_t        ior;
                    464: 
                    465:                        io_req_alloc(ior,0);
                    466:                        ior->io_op = IO_INTERNAL;
                    467:                        ior->io_error = 0;
                    468:                        ior->io_next = 0;
                    469:                        ior->io_count = 0;
                    470: 
                    471:                        ospeed = tgt->dev_info.tape.speed;
                    472:                        odensity = tgt->dev_info.tape.density;
                    473:                        tgt->dev_info.tape.speed = ts->speed;
                    474:                        tgt->dev_info.tape.density = ts->density;
                    475: 
                    476:                        ret = sctape_mode_select(tgt, 0, 0, (ospeed == ts->speed), ior);
                    477:                        if (ret != SCSI_RET_SUCCESS) {
                    478:                                tgt->dev_info.tape.speed = ospeed;
                    479:                                tgt->dev_info.tape.density = odensity;
                    480:                        }
                    481: 
                    482:                        io_req_free(ior);
                    483:                }
                    484: 
                    485:                break;
                    486:            }
                    487:        /* U*x compat */
                    488:        case MTIOCTOP: {
                    489:                struct tape_params *mt = (struct tape_params *) status;
                    490:                io_req_t        ior;
                    491: 
                    492:                if (scsi_debug)
                    493:                        printf("[sctape_sstatus: %x %x %x]\n",
                    494:                                flavor, mt->mt_operation, mt->mt_repeat_count);
                    495: 
                    496:                io_req_alloc(ior,0);
                    497: retry:
                    498:                ior->io_count = 0;
                    499:                ior->io_op = IO_INTERNAL;
                    500:                ior->io_error = 0;
                    501:                ior->io_next = 0;
                    502:                tgt->ior = ior;
                    503: 
                    504:                /* compat: in U*x it is a short */
                    505:                switch ((short)(mt->mt_operation)) {
                    506:                case MTWEOF:    /* write an end-of-file record */
                    507:                        ret = scsi_write_filemarks(tgt, mt->mt_repeat_count, ior);
                    508:                        break;
                    509:                case MTFSF:     /* forward space file */
                    510:                        ret = scsi_space(tgt, SCSI_CMD_SP_FIL, mt->mt_repeat_count, ior);
                    511:                        break;
                    512:                case MTBSF:     /* backward space file */
                    513:                        ret = scsi_space(tgt, SCSI_CMD_SP_FIL, -mt->mt_repeat_count,ior);
                    514:                        break;
                    515:                case MTFSR:     /* forward space record */
                    516:                        ret = scsi_space(tgt, SCSI_CMD_SP_BLOCKS, mt->mt_repeat_count, ior);
                    517:                        break;
                    518:                case MTBSR:     /* backward space record */
                    519:                        ret = scsi_space(tgt, SCSI_CMD_SP_BLOCKS, -mt->mt_repeat_count, ior);
                    520:                        break;
                    521:                case MTREW:     /* rewind */
                    522:                case MTOFFL:    /* rewind and put the drive offline */
                    523:                        ret = scsi_rewind(tgt, ior, TRUE);
                    524:                        iowait(ior);
                    525:                        if ((short)(mt->mt_operation) == MTREW) break;
                    526:                        ior->io_op = 0;
                    527:                        ior->io_next = 0;
                    528:                        ior->io_error = 0;
                    529:                        (void) scsi_start_unit(tgt, 0, ior);
                    530:                        break;
                    531:                case MTNOP:     /* no operation, sets status only */
                    532:                case MTCACHE:   /* enable controller cache */
                    533:                case MTNOCACHE: /* disable controller cache */
                    534:                        ret = SCSI_RET_SUCCESS;
                    535:                        break;
                    536:                default:
                    537:                        tgt->ior = 0;
                    538:                        io_req_free(ior);
                    539:                        return D_INVALID_OPERATION;
                    540:                }
                    541: 
                    542:                if (ret == SCSI_RET_RETRY) {
                    543:                        timeout(wakeup, ior, 5*hz);
                    544:                        await(ior);
                    545:                        goto retry;
                    546:                }
                    547: 
                    548:                io_req_free(ior);
                    549:                if (ret != SCSI_RET_SUCCESS)
                    550:                        return D_IO_ERROR;
                    551:                break;
                    552:        }
                    553:        case MTIOCIEOT:
                    554:        case MTIOCEEOT:
                    555:        default:
                    556:                return D_INVALID_OPERATION;
                    557:        }
                    558:        return D_SUCCESS;
                    559: }
                    560: #endif  /* NSCSI > 0 */

unix.superglobalmegacorp.com

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