Example #1
0
static int skip_to_next_header(uint8_t *sam_stat)
{
	MHVTL_DBG(1, "skip_to_next_header");
	if (raw_pos.hdr.blk_type == B_EOD) {
		sam_blank_check(E_END_OF_DATA, sam_stat);
		MHVTL_DBG(1, "End of data detected while forward SPACEing!!");
		return -1;
	}

	if (raw_pos.next_blk != lseek64(datafile, raw_pos.next_blk, SEEK_SET)) {
		sam_medium_error(E_SEQUENTIAL_POSITION_ERR, sam_stat);
		MHVTL_DBG(1, "Unable to seek to next block header");
		return -1;
	}
	if (read_header(&raw_pos, sam_stat)) {
		sam_medium_error(E_SEQUENTIAL_POSITION_ERR, sam_stat);
		MHVTL_DBG(1, "Unable to read next block header");
		return -1;
	}
	/* Position to start of header (rewind over header) */
	if (raw_pos.curr_blk != position_to_curr_header(sam_stat)) {
		sam_medium_error(E_SEQUENTIAL_POSITION_ERR, sam_stat);
		MHVTL_DBG(1, "Error position in datafile. Offset: %" PRId64,
				raw_pos.curr_blk);
		return -1;
	}
	return 0;
}
Example #2
0
int position_to_block(uint32_t blk_number, uint8_t *sam_stat)
{
	if (!tape_loaded(sam_stat))
		return -1;

	MHVTL_DBG(2, "Position to block %d", blk_number);

	if (mam.MediumType == MEDIA_TYPE_WORM)
		OK_to_write = 0;

	if (blk_number > eod_blk_number) {
		sam_blank_check(E_END_OF_DATA, sam_stat);
		MHVTL_DBG(1, "End of data detected while positioning");
		return position_to_eod(sam_stat);
	}

	/* Treat a position to block zero specially, as it has different
	   semantics than other blocks when the tape is WORM.
	*/

	if (blk_number == 0)
		return rewind_tape(sam_stat);
	else
		return read_header(blk_number, sam_stat);
}
Example #3
0
uint8_t ssc_write_attributes(struct scsi_cmd *cmd)
{
	int sz;
	struct priv_lu_ssc *lu_priv;
	uint8_t *sam_stat;

	lu_priv = cmd->lu->lu_private;
	sam_stat = &cmd->dbuf_p->sam_stat;

	MHVTL_DBG(1, "Write Attributes (%ld) **", (long)cmd->dbuf_p->serialNo);

	switch (lu_priv->tapeLoaded) {
	case TAPE_UNLOADED:
		mkSenseBuf(NOT_READY, E_MEDIUM_NOT_PRESENT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
		break;
	case TAPE_LOADED:
		cmd->dbuf_p->sz = get_unaligned_be32(&cmd->scb[10]);
		sz = retrieve_CDB_data(cmd->cdev, cmd->dbuf_p);
		MHVTL_DBG(1, "  --> Expected to read %d bytes"
				", read %d", cmd->dbuf_p->sz, sz);
		if (resp_write_attribute(cmd) > 0)
			rewriteMAM(sam_stat);
		break;
	default:
		mkSenseBuf(NOT_READY, E_MEDIUM_FMT_CORRUPT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
		break;
	}
	return SAM_STAT_GOOD;
}
Example #4
0
uint8_t ssc_report_density_support(struct scsi_cmd *cmd)
{
	struct priv_lu_ssc *lu_priv;
	uint8_t *sam_stat;
	uint8_t media;

	lu_priv = cmd->lu->lu_private;
	sam_stat = &cmd->dbuf_p->sam_stat;

	media = cmd->scb[1] & 0x01;
	cmd->dbuf_p->sz = 0;

	MHVTL_DBG(1, "Report %s Density Support (%ld) **",
					(media) ? "mounted Media" : "Drive",
					(long)cmd->dbuf_p->serialNo);

	if (cmd->scb[1] & 0x02) { /* Don't support Medium Type (yet) */
		MHVTL_DBG(1, "Medium Type - not currently supported");
		mkSenseBuf(ILLEGAL_REQUEST, E_INVALID_FIELD_IN_CDB, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
	}

	if (media == 1 && lu_priv->tapeLoaded != TAPE_LOADED) {
		MHVTL_DBG(1, "Media has to be mounted to return media density");
		mkSenseBuf(NOT_READY, E_MEDIUM_NOT_PRESENT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
	}

	cmd->dbuf_p->sz = get_unaligned_be16(&cmd->scb[7]);
	cmd->dbuf_p->sz = resp_report_density(lu_priv, media, cmd->dbuf_p);
	return SAM_STAT_GOOD;
}
Example #5
0
uint8_t ssc_allow_overwrite(struct scsi_cmd *cmd)
{
	uint8_t *cdb = cmd->scb;
	uint8_t allow_overwrite = cdb[2] & 0x0f;
	uint8_t partition = cdb[3];
	uint8_t *sam_stat = &cmd->dbuf_p->sam_stat;
	uint8_t ret_stat = SAM_STAT_GOOD;
	uint64_t allow_overwrite_block;
	struct priv_lu_ssc *lu_ssc;

	lu_ssc = cmd->lu->lu_private;

	if (allow_overwrite > 2) /* Truncate bad values 3 to 15 -> '3' */
		allow_overwrite = 3;

	MHVTL_DBG(1, "ALLOW OVERWRITE (%ld) : %s **",
			(long)cmd->dbuf_p->serialNo,
			allow_overwrite_desc[allow_overwrite].desc);

	lu_ssc->allow_overwrite = FALSE;

	switch (allow_overwrite) {
	case 0:
		break;
	case 1:  /* current position */
		if (partition) { /* Paritions not supported at this stage */
			MHVTL_LOG("Partitions not implemented at this time");
			mkSenseBuf(ILLEGAL_REQUEST,
					E_INVALID_FIELD_IN_CDB,
					sam_stat);
			return SAM_STAT_CHECK_CONDITION;
		}
		allow_overwrite_block = get_unaligned_be64(&cdb[4]);
		MHVTL_DBG(1, "Allow overwrite block: %lld",
					(long long)allow_overwrite_block);
		if (allow_overwrite_block == current_tape_block()) {
			lu_ssc->allow_overwrite_block = allow_overwrite_block;
			lu_ssc->allow_overwrite = TRUE;
		} else {
			/* Set allow_overwrite position to an invalid number */
			lu_ssc->allow_overwrite_block = 0;
			lu_ssc->allow_overwrite_block--;
			mkSenseBuf(ILLEGAL_REQUEST,
					E_SEQUENTIAL_POSITIONING_ERROR,
					sam_stat);
			ret_stat = SAM_STAT_CHECK_CONDITION;
		}
		break;
	case 2:
		lu_ssc->allow_overwrite = 2;
		break;
	default:
		mkSenseBuf(ILLEGAL_REQUEST, E_INVALID_FIELD_IN_CDB, sam_stat);
		ret_stat = SAM_STAT_CHECK_CONDITION;
		break;
	}

	return ret_stat;
}
Example #6
0
/*
 * Rewind to beginning of data file and the position to first data header.
 *
 * Return 0 -> Not loaded.
 *        1 -> Load OK
 *        2 -> format corrupt.
 */
int rewind_tape(uint8_t *sam_stat)
{
	MHVTL_DBG(1, "rewind_tape");
	if (rawRewind(sam_stat)) {
		sam_medium_error(E_MEDIUM_FMT_CORRUPT, sam_stat);
		return 2;
	}

	if (raw_pos.hdr.blk_type != B_BOT) {
		sam_medium_error(E_MEDIUM_FMT_CORRUPT, sam_stat);
		return 2;
	}

	if (skip_to_next_header(sam_stat))
		return 2;

	switch (MediumType) {
	case MEDIA_TYPE_CLEAN:
		OK_to_write = 0;
		break;
	case MEDIA_TYPE_WORM:
		/* Special condition...
		* If we
		* - rewind,
		* - write filemark
		* - EOD
		* We set this as writable media as the tape is blank.
		*/
		if (raw_pos.hdr.blk_type != B_EOD)
			OK_to_write = 0;

		/* Check that this header is a filemark and the next header
		 *  is End of Data. If it is, we are OK to write
		 */
		if (raw_pos.hdr.blk_type == B_FILEMARK) {
			skip_to_next_header(sam_stat);
			if (raw_pos.hdr.blk_type == B_EOD)
				OK_to_write = 1;
		}
		/* Now we have to go thru thru the rewind again.. */
		if (rawRewind(sam_stat)) {
			sam_medium_error(E_MEDIUM_FMT_CORRUPT,
								sam_stat);
			return 2;
		}

		/* No need to do all previous error checking... */
		skip_to_next_header(sam_stat);
		break;
	case MEDIA_TYPE_DATA:
		OK_to_write = 1;	/* Reset flag to OK. */
		break;
	}

	MHVTL_DBG(1, "Media is %s",
				(OK_to_write) ? "writable" : "not writable");

	return 1;
}
Example #7
0
/*
 * Initialise structure data for mode pages.
 * - Allocate memory for each mode page & init to 0
 * - Set up size of mode page
 * - Set initial values of mode pages
 *
 * Return void  - Nothing
 */
static void init_ult_mode_pages(struct lu_phy_attr *lu, struct mode *m)
{
	struct mode *mp;

	MHVTL_DBG(3, "+++ Trace mode pages at %p +++", sm);

	mp = alloc_mode_page(m, 0x24, 0, 6);
	MHVTL_DBG(3, "smp: %p", mp);
}
Example #8
0
int
position_blocks_forw(uint32_t count, uint8_t *sam_stat)
{
	uint32_t residual;
	uint32_t blk_target;
	unsigned int i;

	if (!tape_loaded(sam_stat)) {
		return -1;
	}

	if (mam.MediumType == MEDIA_TYPE_WORM)
		OK_to_write = 0;

	blk_target = raw_pos.hdr.blk_number + count;

	/* Find the first filemark forward from our current position, if any. */

	for (i = 0; i < meta.filemark_count; i++) {
		MHVTL_DBG(3, "filemark at %ld", (unsigned long)filemarks[i]);
		if (filemarks[i] >= raw_pos.hdr.blk_number) {
			break;
		}
	}

	/* If there is one, see if it is between our current position and our
	   desired destination.
	*/

	if (i < meta.filemark_count) {
		if (filemarks[i] >= blk_target) {
			return position_to_block(blk_target, sam_stat);
		}

		residual = blk_target - raw_pos.hdr.blk_number + 1;
		if (read_header(filemarks[i] + 1, sam_stat)) {
			return -1;
		}
		MHVTL_DBG(1, "Filemark encountered: block %d", filemarks[i]);
		mkSenseBuf(NO_SENSE | SD_FILEMARK, E_MARK, sam_stat);
		put_unaligned_be32(residual, &sense[3]);
		return -1;
	}

	if (blk_target > eod_blk_number) {
		residual = blk_target - eod_blk_number;
		if (read_header(eod_blk_number, sam_stat)) {
			return -1;
		}
		MHVTL_DBG(1, "EOD encountered");
		mkSenseBuf(BLANK_CHECK, E_END_OF_DATA, sam_stat);
		put_unaligned_be32(residual, &sense[3]);
		return -1;
	}

	return position_to_block(blk_target, sam_stat);
}
Example #9
0
uint8_t ssc_write_6(struct scsi_cmd *cmd)
{
	uint8_t *cdb = cmd->scb;
	struct vtl_ds *dbuf_p;
	struct priv_lu_ssc *lu_ssc;
	int count;
	int sz;
	int k;
	int retval = 0;

	lu_ssc = cmd->lu->lu_private;
	dbuf_p = cmd->dbuf_p;

	current_state = MHVTL_STATE_WRITING;

	if (cdb[1] & FIXED) {	/* If Fixed block writes */
		count = get_unaligned_be24(&cdb[2]);
		sz = get_unaligned_be24(&modeBlockDescriptor[5]);
		MHVTL_DBG(last_cmd == WRITE_6 ? 2 : 1,
				"WRITE_6: %d blks of %d bytes (%ld) **",
						count,
						sz,
						(long)dbuf_p->serialNo);
	} else {		 /* else - Variable Block writes */
		count = 1;
		sz = get_unaligned_be24(&cdb[2]);
		MHVTL_DBG(last_cmd == WRITE_6 ? 2 : 1,
				"WRITE_6: %d bytes (%ld) **",
						sz,
						(long)dbuf_p->serialNo);
	}

	/* FIXME: Should handle this instead of 'check & warn' */
	if ((sz * count) > lu_ssc->bufsize)
		MHVTL_DBG(1,
			"Fatal: bufsize %d, requested write of %d bytes",
							lu_ssc->bufsize, sz);

	/* Retrieve data from kernel */
	dbuf_p->sz = sz * count;
	retrieve_CDB_data(cmd->cdev, dbuf_p);

	if (!lu_ssc->pm->check_restrictions(cmd))
		return SAM_STAT_CHECK_CONDITION;

	if (OK_to_write) {
		for (k = 0; k < count; k++) {
			retval = writeBlock(cmd, sz);
			dbuf_p->data += retval;

			/* If sam_stat != SAM_STAT_GOOD, return */
			if (cmd->dbuf_p->sam_stat)
				return cmd->dbuf_p->sam_stat;
		}
	}
	return SAM_STAT_GOOD;
}
Example #10
0
static int
check_for_overwrite(uint8_t *sam_stat)
{
	uint32_t blk_number;
	uint64_t data_offset;
	unsigned int i;

	if (raw_pos.hdr.blk_type == B_EOD) {
		return 0;
	}

	MHVTL_DBG(2, "At block %ld", (unsigned long)raw_pos.hdr.blk_number);

	/* We aren't at EOD so we are performing a rewrite.  Truncate
	   the data and index files back to the current length.
	*/

	blk_number = raw_pos.hdr.blk_number;
	data_offset = raw_pos.data_offset;

	if (ftruncate(indxfile, blk_number * sizeof(raw_pos))) {
		mkSenseBuf(MEDIUM_ERROR, E_WRITE_ERROR, sam_stat);
		MHVTL_ERR("Index file ftruncate failure, pos: "
			"%" PRId64 ": %s",
			(uint64_t)blk_number * sizeof(raw_pos),
			strerror(errno));
		return -1;
	}
	if (ftruncate(datafile, data_offset)) {
		mkSenseBuf(MEDIUM_ERROR, E_WRITE_ERROR, sam_stat);
		MHVTL_ERR("Data file ftruncate failure, pos: "
			"%" PRId64 ": %s", data_offset,
			strerror(errno));
		return -1;
	}

	/* Update the filemark map removing any filemarks which will be
	   overwritten.  Rewrite the filemark map so that the on-disk image
	   of the map is consistent with the new sizes of the other two files.
	*/

	for (i = 0; i < meta.filemark_count; i++) {
		MHVTL_DBG(2, "filemarks[%d] %d", i, filemarks[i]);
		if (filemarks[i] >= blk_number) {
			MHVTL_DBG(2, "Setting filemark_count from %d to %d",
					meta.filemark_count, i);
			meta.filemark_count = i;
			return rewrite_meta_file();
		}
	}

	return 0;
}
Example #11
0
uint8_t ssc_spin(struct scsi_cmd *cmd)
{
	MHVTL_DBG(1, "Security Protocol In (%ld) **",
					(long)cmd->dbuf_p->serialNo);

	return resp_spin(cmd);
}
Example #12
0
/*
 * Transport Geometry Parameters mode page
 * SMC-3 7.3.4
 */
int add_mode_transport_geometry(struct lu_phy_attr *lu)
{
	struct list_head *mode_pg;
	struct mode *mp;
	uint8_t pcode;
	uint8_t subpcode;
	uint8_t size;

	mode_pg = &lu->mode_pg;
	pcode = MODE_TRANSPORT_GEOMETRY;
	subpcode = 0;
	size = 4;

	MHVTL_DBG(3, "Adding mode page %s (%02x/%02x)",
				mode_transport_geometry, pcode, subpcode);

	mp = alloc_mode_page(mode_pg, pcode, subpcode, size);
	if (!mp)
		return -ENOMEM;

	mp->pcodePointer[0] = pcode;
	mp->pcodePointer[1] = size
				 - sizeof(mp->pcodePointer[0])
				 - sizeof(mp->pcodePointer[1]);

	/* And copy pcode/size into bitmap structure */
	mp->pcodePointerBitMap[0] = mp->pcodePointer[0];
	mp->pcodePointerBitMap[1] = mp->pcodePointer[1];

	mp->description = mode_transport_geometry;

	return 0;
}
Example #13
0
int add_mode_power_condition(struct lu_phy_attr *lu)
{
	struct list_head *mode_pg;
	struct mode *mp;
	uint8_t pcode;
	uint8_t subpcode;
	uint8_t size;

	mode_pg = &lu->mode_pg;
	pcode = MODE_POWER_CONDITION;
	subpcode = 0;
	size = 0x26;

	MHVTL_DBG(3, "Adding mode page %s (%02x/%02x)",
				mode_power_condition, pcode, subpcode);

	mp = alloc_mode_page(mode_pg, pcode, subpcode, size);
	if (!mp)
		return -ENOMEM;

	mp->pcodePointer[0] = pcode;
	mp->pcodePointer[1] = size
				 - sizeof(mp->pcodePointer[0])
				 - sizeof(mp->pcodePointer[1]);

	/* And copy pcode/size into bitmap structure */
	mp->pcodePointerBitMap[0] = mp->pcodePointer[0];
	mp->pcodePointerBitMap[1] = mp->pcodePointer[1];

	mp->description = mode_power_condition;

	return 0;
}
Example #14
0
uint8_t ssc_erase(struct scsi_cmd *cmd)
{
	struct priv_lu_ssc *lu_priv;
	uint8_t *sam_stat;

	lu_priv = cmd->lu->lu_private;
	sam_stat = &cmd->dbuf_p->sam_stat;

	MHVTL_DBG(1, "Erasing (%ld) **", (long)cmd->dbuf_p->serialNo);

	current_state = MHVTL_STATE_ERASE;

	if (!lu_priv->pm->check_restrictions(cmd))
		return SAM_STAT_CHECK_CONDITION;

	if (c_pos->blk_number != 0) {
		MHVTL_LOG("Not at BOT.. Can't erase unless at BOT");
		mkSenseBuf(NOT_READY, E_INVALID_FIELD_IN_CDB, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
	}

	if (OK_to_write)
		format_tape(sam_stat);
	else {
		MHVTL_LOG("Attempt to erase Write-protected media");
		mkSenseBuf(NOT_READY, E_MEDIUM_OVERWRITE_ATTEMPTED, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
	}
	return SAM_STAT_GOOD;
}
Example #15
0
uint8_t ssc_read_media_sn(struct scsi_cmd *cmd)
{
	struct priv_lu_ssc *lu_priv;
	uint8_t *sam_stat;

	lu_priv = cmd->lu->lu_private;
	sam_stat = &cmd->dbuf_p->sam_stat;

	MHVTL_DBG(1, "Read Medium Serial No. (%ld) **",
						(long)cmd->dbuf_p->serialNo);
	switch (lu_priv->tapeLoaded) {
	case TAPE_LOADED:
		cmd->dbuf_p->sz = resp_read_media_serial(lu_priv->mediaSerialNo,
							cmd->dbuf_p->data,
							sam_stat);
		break;
	case TAPE_UNLOADED:
		mkSenseBuf(NOT_READY, E_MEDIUM_NOT_PRESENT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
		break;
	default:
		mkSenseBuf(NOT_READY, E_MEDIUM_FMT_CORRUPT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
		break;
	}
	return *sam_stat;
}
Example #16
0
uint8_t ssc_read_position(struct scsi_cmd *cmd)
{
	struct priv_lu_ssc *lu_priv;
	uint8_t *sam_stat;
	int service_action;

	lu_priv = cmd->lu->lu_private;
	sam_stat = &cmd->dbuf_p->sam_stat;

	MHVTL_DBG(1, "Read Position (%ld) **", (long)cmd->dbuf_p->serialNo);

	service_action = cmd->scb[1] & 0x1f;
	/* service_action == 0 or 1 -> Returns 20 bytes of data (short) */

	*sam_stat = SAM_STAT_GOOD;

	switch (lu_priv->tapeLoaded) {
	case TAPE_LOADED:
		if ((service_action == 0) || (service_action == 1))
			cmd->dbuf_p->sz = resp_read_position(c_pos->blk_number,
							cmd->dbuf_p->data,
							sam_stat);
		break;
	case TAPE_UNLOADED:
		mkSenseBuf(NOT_READY, E_MEDIUM_NOT_PRESENT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
		break;
	default:
		mkSenseBuf(NOT_READY, E_MEDIUM_FMT_CORRUPT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
		break;
	}
	return *sam_stat;
}
Example #17
0
uint8_t ssc_read_block_limits(struct scsi_cmd *cmd)
{
	struct priv_lu_ssc *lu_priv;
	uint8_t *sam_stat;

	lu_priv = cmd->lu->lu_private;
	sam_stat = &cmd->dbuf_p->sam_stat;

	MHVTL_DBG(1, "Read block limits (%ld) **",
						(long)cmd->dbuf_p->serialNo);

	switch (lu_priv->tapeLoaded) {
	case TAPE_LOADED:
	case TAPE_UNLOADED:
		cmd->dbuf_p->sz = resp_read_block_limits(cmd->dbuf_p,
							lu_priv->bufsize);
		break;
	default:
		mkSenseBuf(NOT_READY, E_MEDIUM_FMT_CORRUPT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
		break;
	}

	return SAM_STAT_GOOD;
}
Example #18
0
uint8_t ssc_rewind(struct scsi_cmd *cmd)
{
	struct priv_lu_ssc *lu_priv;
	uint8_t *sam_stat;
	int retval;

	lu_priv = cmd->lu->lu_private;
	sam_stat = &cmd->dbuf_p->sam_stat;

	MHVTL_DBG(1, "Rewinding (%ld) **", (long)cmd->dbuf_p->serialNo);

	current_state = MHVTL_STATE_REWIND;

	switch (lu_priv->tapeLoaded) {
	case TAPE_UNLOADED:
		mkSenseBuf(NOT_READY, E_MEDIUM_NOT_PRESENT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
		break;
	case TAPE_LOADED:
		retval = rewind_tape(sam_stat);
		if (retval < 0) {
			mkSenseBuf(NOT_READY, E_MEDIUM_FMT_CORRUPT, sam_stat);
			return SAM_STAT_CHECK_CONDITION;
		}
		break;
	default:
		mkSenseBuf(NOT_READY, E_MEDIUM_FMT_CORRUPT, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
		break;
	}

	return SAM_STAT_GOOD;
}
Example #19
0
void init_ait3_ssc(struct lu_phy_attr *lu)
{
	MHVTL_DBG(3, "+++ Trace mode pages at %p +++", &lu->mode_pg);

	ssc_pm.name = name_ait_3;
	ssc_pm.lu = lu;
	personality_module_register(&ssc_pm);

	/* Drive capabilities need to be defined before mode pages */
	ssc_pm.drive_supports_append_only_mode = FALSE;
	ssc_pm.drive_supports_early_warning = TRUE;
	ssc_pm.drive_supports_prog_early_warning = FALSE;

	init_ait_inquiry(lu);
	init_ait_mode_pages(lu);

	add_log_write_err_counter(lu);
	add_log_read_err_counter(lu);
	add_log_sequential_access(lu);
	add_log_temperature_page(lu);
	add_log_tape_alert(lu);
	add_log_tape_usage(lu);
	add_log_tape_capacity(lu);
	add_log_data_compression(lu);
	ssc_pm.native_drive_density = &density_ait3;
	add_density_support(&lu->den_list, &density_ait1, 0);
	add_density_support(&lu->den_list, &density_ait2, 1);
	add_density_support(&lu->den_list, &density_ait3, 1);
	add_drive_media_list(lu, LOAD_RO, "AIT1");
	add_drive_media_list(lu, LOAD_RO, "AIT1 Clean");
	add_drive_media_list(lu, LOAD_RW, "AIT2");
	add_drive_media_list(lu, LOAD_RO, "AIT2 Clean");
	add_drive_media_list(lu, LOAD_RW, "AIT3");
	add_drive_media_list(lu, LOAD_RO, "AIT3 Clean");
}
Example #20
0
int position_blocks(int32_t count, uint8_t *sam_stat)
{
	MHVTL_DBG(1, "position_blocks");
	if (!tape_loaded(sam_stat))
		return -1;

	if (MediumType == MEDIA_TYPE_WORM)
		OK_to_write = 0;

	if (count < 0) {
		for (; count < 0; count++) {
			if (skip_to_prev_header(sam_stat))
				return -1;
			if (raw_pos.hdr.blk_type == B_FILEMARK) {
				sam_no_sense(SD_FILEMARK, E_MARK, sam_stat);
				return -1;
			}
		}
	} else {
		for (; count > 0; count--) {
			if (skip_to_next_header(sam_stat))
				return -1;
			if (raw_pos.hdr.blk_type == B_FILEMARK) {
				sam_no_sense(SD_FILEMARK, E_MARK, sam_stat);
				return -1;
			}
		}
	}
	return 0;
}
Example #21
0
int position_to_block(uint32_t blk_no, uint8_t *sam_stat)
{
	MHVTL_DBG(1, "position_to_block");
	if (!tape_loaded(sam_stat))
		return -1;

	if (MediumType == MEDIA_TYPE_WORM)
		OK_to_write = 0;

	if (blk_no < raw_pos.hdr.blk_number &&
				raw_pos.hdr.blk_number - blk_no > blk_no) {
		if (rewind_tape(sam_stat))
			return -1;
	}
	while (raw_pos.hdr.blk_number != blk_no) {
		if (raw_pos.hdr.blk_number > blk_no) {
			if (skip_to_prev_header(sam_stat) == -1)
				return -1;
		} else {
			if (skip_to_next_header(sam_stat) == -1)
				return -1;
		}
	}
	return 0;
}
Example #22
0
static void update_stk_l_vpd_80(struct lu_phy_attr *lu)
{
	struct vpd **lu_vpd = lu->lu_vpd;
	struct smc_priv *smc_p = lu->lu_private;
	uint8_t *d;
	int pg;

	smc_p = lu->lu_private;

	/* Unit Serial Number */
	pg = PCODE_OFFSET(0x80);
	if (lu_vpd[pg])		/* Free any earlier allocation */
		dealloc_vpd(lu_vpd[pg]);
	lu_vpd[pg] = alloc_vpd(0x12);
	if (lu_vpd[pg]) {
		d = lu_vpd[pg]->data;
		d[0] = lu->ptype;
		d[1] = 0x80;	/* Page code */
		d[3] = 0x0b;	/* Page length */
		/* d[4 - 15] Serial number of device */
		snprintf((char *)&d[4], 10, "%-10s", lu->lu_serial_no);
		/* Unique Logical Library Identifier */
	} else {
		MHVTL_DBG(1, "Could not malloc(0x12) bytes, line %d", __LINE__);
	}
}
Example #23
0
/*
 * READ/WRITE Error Recovery
 * SSC3-8.3.5
 */
int add_mode_page_rw_err_recovery(struct lu_phy_attr *lu)
{
	struct list_head *mode_pg;
	struct mode *mp;
	uint8_t pcode;
	uint8_t subpcode;
	uint8_t size;

	pcode = MODE_RW_ERROR_RECOVER;
	subpcode = 0;
	size = 12;

	mode_pg = &lu->mode_pg;

	MHVTL_DBG(3, "Adding mode page %s (%02x/%02x)",
				mode_rw_error_recover, pcode, subpcode);

	mp = alloc_mode_page(mode_pg, pcode, subpcode, size);
	if (!mp)
		return -ENOMEM;

	mp->pcodePointer[0] = pcode;
	mp->pcodePointer[1] = size
				 - sizeof(mp->pcodePointer[0])
				 - sizeof(mp->pcodePointer[1]);

	/* And copy pcode/size into bitmap structure */
	mp->pcodePointerBitMap[0] = mp->pcodePointer[0];
	mp->pcodePointerBitMap[1] = mp->pcodePointer[1];

	mp->description = mode_rw_error_recover;

	return 0;
}
Example #24
0
int rewind_tape(uint8_t *sam_stat)
{
	if (!tape_loaded(sam_stat))
		return -1;

	if (read_header(0, sam_stat))
		return -1;

	switch (mam.MediumType) {
	case MEDIA_TYPE_CLEAN:
		OK_to_write = 0;
		break;
	case MEDIA_TYPE_WORM:
		/* Check if this header is a filemark and the next header
		 *  is End of Data. If it is, we are OK to write
		 */

		if (raw_pos.hdr.blk_type == B_EOD ||
		    (raw_pos.hdr.blk_type == B_FILEMARK && eod_blk_number == 1))
			OK_to_write = 1;
		else
			OK_to_write = 0;
		break;
	case MEDIA_TYPE_DATA:
		OK_to_write = 1;	/* Reset flag to OK. */
		break;
	}

	MHVTL_DBG(1, "Media is%s writable", (OK_to_write) ? "" : " not");

	return 1;
}
Example #25
0
static int read_header(uint32_t blk_number, uint8_t *sam_stat)
{
	loff_t nread;

	if (blk_number > eod_blk_number) {
		MHVTL_ERR("Attempt to seek [%d] beyond EOD [%d]",
				blk_number, eod_blk_number);
	} else if (blk_number == eod_blk_number)
		mkEODHeader(eod_blk_number, eod_data_offset);
	else {
		nread = pread(indxfile, &raw_pos, sizeof(raw_pos),
			blk_number * sizeof(raw_pos));
		if (nread < 0) {
			MHVTL_ERR("Medium format corrupt");
			sam_medium_error(E_MEDIUM_FMT_CORRUPT, sam_stat);
			return -1;
		} else if (nread != sizeof(raw_pos)) {
			MHVTL_ERR("Failed to read next header");
			sam_medium_error(E_END_OF_DATA, sam_stat);
			return -1;
		}
	}

	MHVTL_DBG(3, "Reading header %d at offset %ld, type: %s, size: %d",
			raw_pos.hdr.blk_number,
			(unsigned long)raw_pos.data_offset,
			mhvtl_block_type_desc(raw_pos.hdr.blk_type),
			raw_pos.hdr.blk_size);
	return 0;
}
Example #26
0
void init_t10kA_ssc(struct lu_phy_attr *lu)
{
	MHVTL_DBG(3, "+++ Trace mode pages at %p +++", &lu->mode_pg);

	ssc_pm.name = pm_name_t10kA;
	ssc_pm.lu = lu;
	personality_module_register(&ssc_pm);

	/* Drive capabilities need to be defined before mode pages */
	ssc_pm.drive_supports_append_only_mode = FALSE;
	ssc_pm.drive_supports_early_warning = TRUE;
	ssc_pm.drive_supports_prog_early_warning = FALSE;

	init_t10k_mode_pages(lu);

	add_log_write_err_counter(lu);
	add_log_read_err_counter(lu);
	add_log_sequential_access(lu);
	add_log_temperature_page(lu);
	add_log_tape_alert(lu);
	add_log_tape_usage(lu);
	add_log_tape_capacity(lu);
	add_log_data_compression(lu);
	ssc_pm.native_drive_density = &density_t10kA;
	register_ops(lu, SECURITY_PROTOCOL_IN, ssc_spin);
	register_ops(lu, SECURITY_PROTOCOL_OUT, ssc_spout);
	register_ops(lu, LOAD_DISPLAY, ssc_load_display);
	init_t10k_inquiry(lu);
	add_density_support(&lu->den_list, &density_t10kA, 1);
	add_drive_media_list(lu, LOAD_RW, "T10KA");
	add_drive_media_list(lu, LOAD_RO, "T10KA Clean");
}
Example #27
0
static int skip_prev_filemark(uint8_t *sam_stat)
{
	MHVTL_DBG(1, "skip_prev_filemark");

	if (raw_pos.hdr.blk_type == B_FILEMARK)
		raw_pos.hdr.blk_type = B_NOOP;
	while (raw_pos.hdr.blk_type != B_FILEMARK) {
		if (raw_pos.hdr.blk_type == B_BOT) {
			sam_no_sense(NO_SENSE, E_BOM, sam_stat);
			MHVTL_DBG(2, "Found Beginning of tape");
			return -1;
		}
		if (skip_to_prev_header(sam_stat))
			return -1;
	}
	return 0;
}
Example #28
0
void unload_tape(uint8_t *sam_stat)
{
	MHVTL_DBG(1, "unload_tape");
	if (datafile >= 0) {
		close(datafile);
		datafile = -1;
	}
}
Example #29
0
uint8_t ssc_allow_prevent_removal(struct scsi_cmd *cmd)
{
	/* FIXME: Currently does nothing... */
	MHVTL_DBG(1, "%s MEDIA removal (%ld) **",
					(cmd->scb[4]) ? "Prevent" : "Allow",
					(long)cmd->dbuf_p->serialNo);
	return SAM_STAT_GOOD;
}
Example #30
0
uint8_t ssc_load_display(struct scsi_cmd *cmd)
{
	unsigned char *d;
	char str1[9];
	char str2[9];

	MHVTL_DBG(1, "LOAD DISPLAY (%ld) - T10000 specific **",
					(long)cmd->dbuf_p->serialNo);

	cmd->dbuf_p->sz = cmd->scb[4];
	retrieve_CDB_data(cmd->cdev, cmd->dbuf_p);
	d = cmd->dbuf_p->data;
	memcpy(str1, &d[1], 8);
	str1[8] = 0;
	memcpy(str2, &d[9], 8);
	str2[8] = 0;

	MHVTL_DBG(3, "Raw data: %02x  "
			"%02x %02x %02x %02x %02x %02x %02x %02x  "
			"%02x %02x %02x %02x %02x %02x %02x %02x",
			d[0], d[1], d[2], d[3], d[4],
			d[5], d[6], d[7], d[8],
			d[9], d[10], d[11], d[12],
			d[13], d[14], d[15], d[16]);

	switch (d[0] >> 5) { /* Bits 5, 6 & 7 are overlay */
	case 0:
		MHVTL_DBG(1, "Display \'%s\' until next"
				" command that initiates tape motion",
	/* Low/High bit */	(d[0] & 2) ? str2 : str1);
		break;
	case 1:
		MHVTL_DBG(1, "Maintain \'%s\' until the"
				" cartridge is unloaded",
	/* Low/High bit */	(d[0] & 2) ? str2 : str1);
		break;
	case 2:
		MHVTL_DBG(1, "Maintain \'%s\' until the drive"
				" is next loaded", str1);
		break;
	case 3:
		MHVTL_DBG(1, "Physically access tape drive with"
				"out changing the msg");
		break;
	case 7:
		MHVTL_DBG(1, "Display \'%s\' until the tape"
				" drive is unloaded then \'%s\'",
					str1, str2);
		break;
	}
	MHVTL_DBG(2, "Load display: msg1: %s msg2: %s",
					str1, str2);

	cmd->dbuf_p->sz = 0;
	return SAM_STAT_GOOD;
}