Exemple #1
0
static int ssc_read_block_limit(int host_no, struct scsi_cmd *cmd)
{
	uint8_t buf[READ_BLK_LIMITS_SZ];
	uint8_t block_length = ssc_get_block_length(cmd->dev);

	memset(buf, 0, sizeof(buf));

	buf[0] = GRANULARITY;
	if (block_length) {
		/* Fixed block size */
		put_unaligned_be24(block_length, buf + 1);
		put_unaligned_be16(block_length, buf + 4);
	} else {
		/* Variable block size */
		put_unaligned_be24(MAX_BLK_SIZE, buf + 1);
		put_unaligned_be16(MIN_BLK_SIZE, buf + 4);
	}

	memcpy(scsi_get_in_buffer(cmd), buf, READ_BLK_LIMITS_SZ);
	eprintf("In ssc_read_block_limit \n");
	return SAM_STAT_GOOD;
}
Exemple #2
0
static void tape_rdwr_request(struct scsi_cmd *cmd)
{
	struct ssc_info *ssc = dtype_priv(cmd->dev);
	struct blk_header_info *h = &ssc->c_blk;
	int ret, code;
	uint32_t length, i, transfer_length, residue;
	int result = SAM_STAT_GOOD;
	uint8_t *buf;
	int32_t count;
	int8_t fixed;
	int8_t sti;
	uint32_t block_length = ssc_get_block_length(cmd->dev);

	ret = 0;
	length = 0;
	i = 0;
	transfer_length = 0;
	residue = 0;
	code = 0;
	ssc = dtype_priv(cmd->dev);

	switch (cmd->scb[0]) {
	case REZERO_UNIT:
		dprintf("**** Rewind ****\n");
		if (resp_rewind(cmd->dev)) {
			sense_data_build(cmd,
				MEDIUM_ERROR, ASC_SEQUENTIAL_POSITION_ERR);
			result = SAM_STAT_CHECK_CONDITION;
		}
		break;

	case WRITE_FILEMARKS:
		ret = get_unaligned_be24(&cmd->scb[2]);
		dprintf("*** Write %d filemark%s ***\n", ret,
			((ret > 1) || (ret < 0)) ? "s" : "");

		for (i = 0; i < ret; i++)
			append_blk(cmd, scsi_get_out_buffer(cmd), 0,
					0, BLK_FILEMARK);

		fsync(cmd->dev->fd);
		break;

	case READ_6:
		fixed = cmd->scb[1] & 1;
		sti = cmd->scb[1] & 2;

		if (fixed && sti) {
			sense_data_build(cmd, ILLEGAL_REQUEST,
						ASC_INVALID_FIELD_IN_CDB);
			result = SAM_STAT_CHECK_CONDITION;
			break;
		}

		length = scsi_get_in_length(cmd);
		count = get_unaligned_be24(&cmd->scb[2]);
		buf = scsi_get_in_buffer(cmd);

		dprintf("*** READ_6: length %d, count %d, fixed block %s,"
			" %" PRIu64 " %d\n", length, count,
			(fixed) ? "Yes" : "No", h->curr, sti);
		if (fixed)
			result = resp_fixed_read(cmd, buf, length, &ret);
		else
			result = resp_var_read(cmd, buf, length, &ret);

		eprintf("Executed READ_6, Read %d bytes, %" PRIu64 "\n",
			ret, h->curr);
		break;

	case WRITE_6:
		fixed = cmd->scb[1] & 1;

		buf = scsi_get_out_buffer(cmd);
		count = get_unaligned_be24(&cmd->scb[2]);
		length = scsi_get_out_length(cmd);

		if (!fixed) {
			block_length = length;
			count = 1;
		}

		for (i = 0, ret = 0; i < count; i++) {
			if (append_blk(cmd, buf, block_length,
				       block_length, BLK_UNCOMPRESS_DATA)) {
				sense_data_build(cmd, MEDIUM_ERROR,
						ASC_WRITE_ERROR);
				result = SAM_STAT_CHECK_CONDITION;
				break;
			}
			buf += block_length;
			ret += block_length;
		}

		dprintf("*** WRITE_6 count: %d, length: %d, ret: %d, fixed: %s,"
			" ssc->blk_sz: %d\n",
			count, length, ret, (fixed) ? "Yes" : "No",
			block_length);

		/* Check for end of media */
		if (current_size(cmd) > ssc->mam.max_capacity) {
			sense_data_build(cmd, NO_SENSE|SENSE_EOM,
						NO_ADDITIONAL_SENSE);
			result = SAM_STAT_CHECK_CONDITION;
			break;
		}

		if (ret != length) {
			sense_data_build(cmd, MEDIUM_ERROR, ASC_WRITE_ERROR);
			result = SAM_STAT_CHECK_CONDITION;
		}
		break;

	case SPACE:
		code = cmd->scb[1] & 0xf;
		count = be24_to_2comp(&cmd->scb[2]);

		if (code == 0) {	/* Logical Blocks */
			result = space_blocks(cmd, count);
			break;
		} else if (code == 1) { /* Filemarks */
			result = space_filemark(cmd, count);
			break;
		} else if (code == 3) { /* End of data */
			while (h->blk_type != BLK_EOD)
				if (skip_next_header(cmd->dev)) {
					sense_data_build(cmd, MEDIUM_ERROR,
						ASC_MEDIUM_FORMAT_CORRUPT);
					result = SAM_STAT_CHECK_CONDITION;
					break;
				}
		} else { /* Unsupported */
			sense_data_build(cmd, ILLEGAL_REQUEST,
						ASC_INVALID_FIELD_IN_CDB);
			result = SAM_STAT_CHECK_CONDITION;
		}
		break;

	case READ_POSITION:
	{
		int service_action = cmd->scb[1] & 0x1f;
		uint8_t *data = scsi_get_in_buffer(cmd);
		int len = scsi_get_in_length(cmd);

		dprintf("Size of in_buffer = %d\n", len);
		dprintf("Sizeof(buf): %zd\n", sizeof(buf));
		dprintf("service action: 0x%02x\n", service_action);

		if (service_action == 0) {	/* Short form - block ID */
			memset(data, 0, 20);
			data[0] = 20;
		} else if (service_action == 1) { /* Short form - vendor uniq */
			memset(data, 0, 20);
			data[0] = 20;
		} else if (service_action == 6) { /* Long form */
			memset(data, 0, 32);
			data[0] = 32;
		} else {
			sense_data_build(cmd, ILLEGAL_REQUEST,
						ASC_INVALID_FIELD_IN_CDB);
			result = SAM_STAT_CHECK_CONDITION;
		}
		break;
	}
	default:
		eprintf("Unknown op code - should never see this\n");
		sense_data_build(cmd, ILLEGAL_REQUEST, ASC_INVALID_OP_CODE);
		result = SAM_STAT_CHECK_CONDITION;
		break;
	}

	dprintf("io done %p %x %d %u\n", cmd, cmd->scb[0], ret, length);

	scsi_set_result(cmd, result);

	if (result != SAM_STAT_GOOD)
		eprintf("io error %p %x %d %d %" PRIu64 ", %m\n",
			cmd, cmd->scb[0], ret, length, cmd->offset);
}
Exemple #3
0
static int resp_fixed_read(struct scsi_cmd *cmd, uint8_t *buf, uint32_t length,
			   int *transferred)
{
	struct ssc_info *ssc = dtype_priv(cmd->dev);
	struct blk_header_info *h = &ssc->c_blk;
	int i, ret, result = SAM_STAT_GOOD;
	int count;
	ssize_t residue;
	int fd;
	uint32_t block_length = ssc_get_block_length(cmd->dev);

	count = get_unaligned_be24(&cmd->scb[2]);
	fd = cmd->dev->fd;
	ret = 0;

	for (i = 0; i < count; i++) {
		if (h->blk_type == BLK_FILEMARK) {
			uint8_t info[4];

			eprintf("Oops - found filemark\n");
			put_unaligned_be32(count - i, info);
			ssc_sense_data_build(cmd, NO_SENSE | SENSE_FILEMARK,
					     ASC_MARK, info, sizeof(info));
			skip_next_header(cmd->dev);
			result = SAM_STAT_CHECK_CONDITION;
			goto out;
		}

		if (block_length != h->blk_sz) {
			eprintf("block size mismatch %d vs %d\n",
				block_length, h->blk_sz);
			sense_data_build(cmd, MEDIUM_ERROR,
						ASC_MEDIUM_FORMAT_CORRUPT);
			result = SAM_STAT_CHECK_CONDITION;
			goto out;
		}

		residue = pread64(fd, buf, block_length,
				  h->curr + SSC_BLK_HDR_SIZE);
		if (block_length != residue) {
			eprintf("Could only read %d bytes, not %d\n",
					(int)residue, block_length);
			sense_data_build(cmd, MEDIUM_ERROR, ASC_READ_ERROR);
			result = SAM_STAT_CHECK_CONDITION;
			goto out;
		}
		ret += block_length;
		buf += block_length;

		if (skip_next_header(cmd->dev)) {
			eprintf("Could not read next header\n");
			sense_data_build(cmd, MEDIUM_ERROR,
						ASC_MEDIUM_FORMAT_CORRUPT);
			result = SAM_STAT_CHECK_CONDITION;
			goto out;
		}
	}

	*transferred = ret;
out:
	return result;
}