summaryrefslogtreecommitdiff
path: root/scsi/rz_tape.c
diff options
context:
space:
mode:
Diffstat (limited to 'scsi/rz_tape.c')
-rw-r--r--scsi/rz_tape.c560
1 files changed, 0 insertions, 560 deletions
diff --git a/scsi/rz_tape.c b/scsi/rz_tape.c
deleted file mode 100644
index 1d27722..0000000
--- a/scsi/rz_tape.c
+++ /dev/null
@@ -1,560 +0,0 @@
-/*
- * Mach Operating System
- * Copyright (c) 1991,1990 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-/*
- * File: rz_tape.c
- * Author: Alessandro Forin, Carnegie Mellon University
- * Date: 10/90
- *
- * Top layer of the SCSI driver: interface with the MI.
- * This file contains operations specific to TAPE-like devices.
- */
-
-#include <mach/std_types.h>
-#include <scsi/compat_30.h>
-
-#include <sys/ioctl.h>
-#ifdef MACH_KERNEL
-#include <device/tape_status.h>
-#else /*MACH_KERNEL*/
-#include <mips/PMAX/tape_status.h>
-#endif /*MACH_KERNEL*/
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_defs.h>
-#include <scsi/rz.h>
-
-#if (NSCSI > 0)
-
-
-void sctape_start(); /* forward */
-
-int scsi_tape_timeout = 5*60; /* secs, tk50 is slow when positioning far apart */
-
-int sctape_open(tgt, req)
- target_info_t *tgt;
- io_req_t req;
-{
- io_return_t ret;
- io_req_t ior;
- int i;
- scsi_mode_sense_data_t *mod;
-
-#ifdef MACH_KERNEL
- req->io_device->flag |= D_EXCL_OPEN;
-#endif /*MACH_KERNEL*/
-
- /* Preferably allow tapes to disconnect */
- if (BGET(scsi_might_disconnect,(unsigned char)tgt->masterno,tgt->target_id))
- BSET(scsi_should_disconnect,(unsigned char)tgt->masterno,tgt->target_id);
-
- /*
- * Dummy ior for proper sync purposes
- */
- io_req_alloc(ior,0);
- ior->io_count = 0;
-
- /*
- * Do a mode sense first, some drives might be picky
- * about changing params [even if the standard might
- * say otherwise, sigh.]
- */
- do {
- ior->io_op = IO_INTERNAL;
- ior->io_next = 0;
- ior->io_error = 0;
- ret = scsi_mode_sense(tgt, 0, 32, ior);
- } while (ret == SCSI_RET_RETRY);
-
- mod = (scsi_mode_sense_data_t *)tgt->cmd_ptr;
- if (scsi_debug) {
- int p[5];
- bcopy((char*)mod, (char*)p, sizeof(p));
- printf("[modsns(%x): x%x x%x x%x x%x x%x]", ret,
- p[0], p[1], p[2], p[3], p[4]);
- }
- if (ret == SCSI_RET_DEVICE_DOWN)
- goto out;
- if (ret == SCSI_RET_SUCCESS) {
- tgt->dev_info.tape.read_only = mod->wp;
- tgt->dev_info.tape.speed = mod->speed;
- tgt->dev_info.tape.density = mod->bdesc[0].density_code;
- } /* else they all default sensibly, using zeroes */
-
- /* Some tapes have limits on record-length */
-again:
- ior->io_op = IO_INTERNAL;
- ior->io_next = 0;
- ior->io_error = 0;
- ret = scsi_read_block_limits( tgt, ior);
- if (ret == SCSI_RET_RETRY) goto again;
- if (!ior->io_error && (ret == SCSI_RET_SUCCESS)) {
- scsi_blimits_data_t *lim;
- int maxl;
-
- lim = (scsi_blimits_data_t *) tgt->cmd_ptr;
-
- tgt->block_size = (lim->minlen_msb << 8) |
- lim->minlen_lsb;
-
- maxl = (lim->maxlen_msb << 16) |
- (lim->maxlen_sb << 8) |
- lim->maxlen_lsb;
- if (maxl == 0)
- maxl = (unsigned)-1;
- tgt->dev_info.tape.maxreclen = maxl;
- tgt->dev_info.tape.fixed_size = (maxl == tgt->block_size);
- } else {
- /* let the user worry about it */
- /* default: tgt->block_size = 1; */
- tgt->dev_info.tape.maxreclen = (unsigned)-1;
- tgt->dev_info.tape.fixed_size = FALSE;
- }
-
- /* Try hard to do a mode select */
- for (i = 0; i < 5; i++) {
- ior->io_op = IO_INTERNAL;
- ior->io_error = 0;
- ret = sctape_mode_select(tgt, 0, 0, FALSE, ior);
- if (ret == SCSI_RET_SUCCESS)
- break;
- }
- if (scsi_watchdog_period < scsi_tape_timeout)
- scsi_watchdog_period += scsi_tape_timeout;
-
-#if 0 /* this might imply rewind, which we do not want, although yes, .. */
- /* we want the tape loaded */
- ior->io_op = IO_INTERNAL;
- ior->io_next = 0;
- ior->io_error = 0;
- ret = scsi_start_unit(tgt, SCSI_CMD_SS_START, ior);
-#endif
- req->io_device->bsize = tgt->block_size;
-out:
- io_req_free(ior);
- return ret;
-}
-
-
-io_return_t sctape_close(tgt)
- target_info_t *tgt;
-{
- io_return_t ret = SCSI_RET_SUCCESS;
- io_req_t ior;
-
- /*
- * Dummy ior for proper sync purposes
- */
- io_req_alloc(ior,0);
- ior->io_op = IO_INTERNAL;
- ior->io_next = 0;
- ior->io_count = 0;
-
- if (tgt->ior) printf("TAPE: Close with pending requests ?? \n");
-
- /* write a filemark if we xtnded/truncated the tape */
- if (tgt->flags & TGT_WRITTEN_TO) {
- tgt->ior = ior;
- ior->io_error = 0;
- ret = scsi_write_filemarks(tgt, 2, ior);
- if (ret != SCSI_RET_SUCCESS)
- printf("%s%d: wfmark failed x%x\n",
- (*tgt->dev_ops->driver_name)(TRUE), tgt->target_id, ret);
- /*
- * Don't bother repositioning if we'll rewind it
- */
- if (tgt->flags & TGT_REWIND_ON_CLOSE)
- goto rew;
-retry:
- tgt->ior = ior;
- ior->io_op = IO_INTERNAL;
- ior->io_error = 0;
- ior->io_next = 0;
- ret = scsi_space(tgt, SCSI_CMD_SP_FIL, -1, ior);
- if (ret != SCSI_RET_SUCCESS) {
- if (ret == SCSI_RET_RETRY) {
- timeout(wakeup, tgt, hz);
- await(tgt);
- goto retry;
- }
- printf("%s%d: bspfile failed x%x\n",
- (*tgt->dev_ops->driver_name)(TRUE), tgt->target_id, ret);
- }
- }
-rew:
- if (tgt->flags & TGT_REWIND_ON_CLOSE) {
- /* Rewind tape */
- ior->io_error = 0;
- ior->io_op = IO_INTERNAL;
- ior->io_error = 0;
- tgt->ior = ior;
- (void) scsi_rewind(tgt, ior, FALSE);
- iowait(ior);
- if (tgt->done == SCSI_RET_RETRY) {
- timeout(wakeup, tgt, 5*hz);
- await(tgt);
- goto rew;
- }
- }
- io_req_free(ior);
-
- tgt->flags &= ~(TGT_ONLINE|TGT_WRITTEN_TO|TGT_REWIND_ON_CLOSE);
- return ret;
-}
-
-int sctape_strategy(ior)
- register io_req_t ior;
-{
- target_info_t *tgt;
- register int i = ior->io_unit;
-
- tgt = scsi_softc[rzcontroller(i)]->target[rzslave(i)];
-
- if (((ior->io_op & IO_READ) == 0) &&
- tgt->dev_info.tape.read_only) {
- ior->io_error = D_INVALID_OPERATION;
- ior->io_op |= IO_ERROR;
- ior->io_residual = ior->io_count;
- iodone(ior);
- return ior->io_error;
- }
-
- return rz_simpleq_strategy( ior, sctape_start);
-}
-
-static void
-do_residue(ior, sns, bsize)
- io_req_t ior;
- scsi_sense_data_t *sns;
- int bsize;
-{
- int residue;
-
- /* Not an error situation */
- ior->io_error = 0;
- ior->io_op &= ~IO_ERROR;
-
- if (!sns->addr_valid) {
- ior->io_residual = ior->io_count;
- return;
- }
-
- residue = sns->u.xtended.info0 << 24 |
- sns->u.xtended.info1 << 16 |
- sns->u.xtended.info2 << 8 |
- sns->u.xtended.info3;
- /* fixed ? */
- residue *= bsize;
- /*
- * NOTE: residue == requested - actual
- * We only care if > 0
- */
- if (residue < 0) residue = 0;/* sanity */
- ior->io_residual += residue;
-}
-
-void sctape_start( tgt, done)
- target_info_t *tgt;
- boolean_t done;
-{
- io_req_t head, ior = tgt->ior;
-
- if (ior == 0)
- return;
-
- if (done) {
-
- /* see if we must retry */
- if ((tgt->done == SCSI_RET_RETRY) &&
- ((ior->io_op & IO_INTERNAL) == 0)) {
- delay(1000000);/*XXX*/
- goto start;
- } else
- /* got a bus reset ? ouch, that hurts */
- if (tgt->done == (SCSI_RET_ABORTED|SCSI_RET_RETRY)) {
- /*
- * we really cannot retry because the tape position
- * is lost.
- */
- printf("Lost tape position\n");
- ior->io_error = D_IO_ERROR;
- ior->io_op |= IO_ERROR;
- } else
-
- /* check completion status */
-
- if (tgt->cur_cmd == SCSI_CMD_REQUEST_SENSE) {
- scsi_sense_data_t *sns;
-
- ior->io_op = ior->io_temporary;
- ior->io_error = D_IO_ERROR;
- ior->io_op |= IO_ERROR;
-
- sns = (scsi_sense_data_t *)tgt->cmd_ptr;
-
- if (scsi_debug)
- scsi_print_sense_data(sns);
-
- if (scsi_check_sense_data(tgt, sns)) {
- if (sns->u.xtended.ili) {
- if (ior->io_op & IO_READ) {
- do_residue(ior, sns, tgt->block_size);
- if (scsi_debug)
- printf("Tape Short Read (%d)\n",
- ior->io_residual);
- }
- } else if (sns->u.xtended.eom) {
- do_residue(ior, sns, tgt->block_size);
- if (scsi_debug)
- printf("End of Physical Tape!\n");
- } else if (sns->u.xtended.fm) {
- do_residue(ior, sns, tgt->block_size);
- if (scsi_debug)
- printf("File Mark\n");
- }
- }
- }
-
- else if (tgt->done != SCSI_RET_SUCCESS) {
-
- if (tgt->done == SCSI_RET_NEED_SENSE) {
-
- ior->io_temporary = ior->io_op;
- ior->io_op = IO_INTERNAL;
- if (scsi_debug)
- printf("[NeedSns x%x x%x]", ior->io_residual, ior->io_count);
- scsi_request_sense(tgt, ior, 0);
- return;
-
- } else if (tgt->done == SCSI_RET_RETRY) {
- /* only retry here READs and WRITEs */
- if ((ior->io_op & IO_INTERNAL) == 0) {
- ior->io_residual = 0;
- goto start;
- } else{
- ior->io_error = D_WOULD_BLOCK;
- ior->io_op |= IO_ERROR;
- }
- } else {
- ior->io_error = D_IO_ERROR;
- ior->io_op |= IO_ERROR;
- }
- }
-
- if (scsi_debug)
- printf("[Resid x%x]", ior->io_residual);
-
- /* dequeue next one */
- head = ior;
-
- simple_lock(&tgt->target_lock);
- ior = head->io_next;
- tgt->ior = ior;
- if (ior)
- ior->io_prev = head->io_prev;
- simple_unlock(&tgt->target_lock);
-
- iodone(head);
-
- if (ior == 0)
- return;
- }
- ior->io_residual = 0;
-start:
- if (ior->io_op & IO_READ) {
- tgt->flags &= ~TGT_WRITTEN_TO;
- sctape_read( tgt, ior );
- } else if ((ior->io_op & IO_INTERNAL) == 0) {
- tgt->flags |= TGT_WRITTEN_TO;
- sctape_write( tgt, ior );
- }
-}
-
-io_return_t
-sctape_get_status( dev, tgt, flavor, status, status_count)
- int dev;
- target_info_t *tgt;
- dev_flavor_t flavor;
- dev_status_t status;
- natural_t *status_count;
-{
- switch (flavor) {
- case DEV_GET_SIZE:
-
- status[DEV_GET_SIZE_DEVICE_SIZE] = 0;
- status[DEV_GET_SIZE_RECORD_SIZE] = tgt->block_size;
- *status_count = DEV_GET_SIZE_COUNT;
- break;
- case TAPE_STATUS: {
- struct tape_status *ts = (struct tape_status *) status;
-
- ts->mt_type = MT_ISSCSI;
- ts->speed = tgt->dev_info.tape.speed;
- ts->density = tgt->dev_info.tape.density;
- ts->flags = (tgt->flags & TGT_REWIND_ON_CLOSE) ?
- TAPE_FLG_REWIND : 0;
- if (tgt->dev_info.tape.read_only)
- ts->flags |= TAPE_FLG_WP;
-#ifdef MACH_KERNEL
- *status_count = TAPE_STATUS_COUNT;
-#endif
-
- break;
- }
- /* U*x compat */
- case MTIOCGET: {
- struct mtget *g = (struct mtget *) status;
-
- bzero(g, sizeof(struct mtget));
- g->mt_type = 0x7; /* Ultrix compat */
-#ifdef MACH_KERNEL
- *status_count = sizeof(struct mtget)/sizeof(int);
-#endif
- break;
- }
- default:
- return D_INVALID_OPERATION;
- }
- return D_SUCCESS;
-}
-
-io_return_t
-sctape_set_status( dev, tgt, flavor, status, status_count)
- int dev;
- target_info_t *tgt;
- dev_flavor_t flavor;
- dev_status_t status;
- natural_t status_count;
-{
- scsi_ret_t ret;
-
- switch (flavor) {
- case TAPE_STATUS: {
- struct tape_status *ts = (struct tape_status *) status;
- if (ts->flags & TAPE_FLG_REWIND)
- tgt->flags |= TGT_REWIND_ON_CLOSE;
- else
- tgt->flags &= ~TGT_REWIND_ON_CLOSE;
-
- if (ts->speed || ts->density) {
- unsigned int ospeed, odensity;
- io_req_t ior;
-
- io_req_alloc(ior,0);
- ior->io_op = IO_INTERNAL;
- ior->io_error = 0;
- ior->io_next = 0;
- ior->io_count = 0;
-
- ospeed = tgt->dev_info.tape.speed;
- odensity = tgt->dev_info.tape.density;
- tgt->dev_info.tape.speed = ts->speed;
- tgt->dev_info.tape.density = ts->density;
-
- ret = sctape_mode_select(tgt, 0, 0, (ospeed == ts->speed), ior);
- if (ret != SCSI_RET_SUCCESS) {
- tgt->dev_info.tape.speed = ospeed;
- tgt->dev_info.tape.density = odensity;
- }
-
- io_req_free(ior);
- }
-
- break;
- }
- /* U*x compat */
- case MTIOCTOP: {
- struct tape_params *mt = (struct tape_params *) status;
- io_req_t ior;
-
- if (scsi_debug)
- printf("[sctape_sstatus: %x %x %x]\n",
- flavor, mt->mt_operation, mt->mt_repeat_count);
-
- io_req_alloc(ior,0);
-retry:
- ior->io_count = 0;
- ior->io_op = IO_INTERNAL;
- ior->io_error = 0;
- ior->io_next = 0;
- tgt->ior = ior;
-
- /* compat: in U*x it is a short */
- switch ((short)(mt->mt_operation)) {
- case MTWEOF: /* write an end-of-file record */
- ret = scsi_write_filemarks(tgt, mt->mt_repeat_count, ior);
- break;
- case MTFSF: /* forward space file */
- ret = scsi_space(tgt, SCSI_CMD_SP_FIL, mt->mt_repeat_count, ior);
- break;
- case MTBSF: /* backward space file */
- ret = scsi_space(tgt, SCSI_CMD_SP_FIL, -mt->mt_repeat_count,ior);
- break;
- case MTFSR: /* forward space record */
- ret = scsi_space(tgt, SCSI_CMD_SP_BLOCKS, mt->mt_repeat_count, ior);
- break;
- case MTBSR: /* backward space record */
- ret = scsi_space(tgt, SCSI_CMD_SP_BLOCKS, -mt->mt_repeat_count, ior);
- break;
- case MTREW: /* rewind */
- case MTOFFL: /* rewind and put the drive offline */
- ret = scsi_rewind(tgt, ior, TRUE);
- iowait(ior);
- if ((short)(mt->mt_operation) == MTREW) break;
- ior->io_op = 0;
- ior->io_next = 0;
- ior->io_error = 0;
- (void) scsi_start_unit(tgt, 0, ior);
- break;
- case MTNOP: /* no operation, sets status only */
- case MTCACHE: /* enable controller cache */
- case MTNOCACHE: /* disable controller cache */
- ret = SCSI_RET_SUCCESS;
- break;
- default:
- tgt->ior = 0;
- io_req_free(ior);
- return D_INVALID_OPERATION;
- }
-
- if (ret == SCSI_RET_RETRY) {
- timeout(wakeup, ior, 5*hz);
- await(ior);
- goto retry;
- }
-
- io_req_free(ior);
- if (ret != SCSI_RET_SUCCESS)
- return D_IO_ERROR;
- break;
- }
- case MTIOCIEOT:
- case MTIOCEEOT:
- default:
- return D_INVALID_OPERATION;
- }
- return D_SUCCESS;
-}
-#endif /* NSCSI > 0 */