示例#1
0
文件: ssc.c 项目: aroundrobin/mhvtl
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;
}
示例#2
0
static int check_for_overwrite(uint8_t *sam_stat)
{
	MHVTL_DBG(1, "check_for_overwrite");
#if NOTDEF
	uint32_t blk_number;
	uint64_t data_offset;
	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))) {
		sam_medium_error(E_WRITE_ERROR, sam_stat);
		MHVTL_LOG("Index file ftruncate failure, pos: "
				"%" PRId64 ": %s",
				(uint64_t)blk_number * sizeof(raw_pos),
		strerror(errno));
		return -1;
	}
	if (ftruncate(datafile, data_offset)) {
		sam_medium_error(E_WRITE_ERROR, sam_stat);
		MHVTL_LOG("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();
		}
	}
#endif
	return 0;
}
示例#3
0
static void init_ait_inquiry(struct lu_phy_attr *lu)
{
	int pg;
	uint8_t worm = 1;	/* Supports WORM */
	uint8_t local_TapeAlert[8] =
			{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

	/* Sequential Access device capabilities - Ref: 8.4.2 */
	pg = PCODE_OFFSET(0xb0);
	lu->lu_vpd[pg] = alloc_vpd(VPD_B0_SZ);
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_b0(lu, &worm);

	/* Manufacture-assigned serial number - Ref: 8.4.3 */
	pg = PCODE_OFFSET(0xb1);
	lu->lu_vpd[pg] = alloc_vpd(VPD_B1_SZ);
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_b1(lu, lu->lu_serial_no);

	/* TapeAlert supported flags - Ref: 8.4.4 */
	pg = PCODE_OFFSET(0xb2);
	lu->lu_vpd[pg] = alloc_vpd(VPD_B2_SZ);
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_b2(lu, &local_TapeAlert);

	/* VPD page 0xC0 */
	pg = PCODE_OFFSET(0xc0);
	lu->lu_vpd[pg] = alloc_vpd(VPD_C0_SZ);
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_c0(lu, "10-03-2008 19:38:00");

	/* VPD page 0xC1 */
	pg = PCODE_OFFSET(0xc1);
	lu->lu_vpd[pg] = alloc_vpd(strlen("Security"));
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_c1(lu, "Security");
}
示例#4
0
文件: ssc.c 项目: aroundrobin/mhvtl
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;
}
示例#5
0
/* DLT7000 & DLT8000 */
static void init_dlt_inquiry(struct lu_phy_attr *lu)
{
	int pg;
	char b[32];
	int x, y, z;

	lu->inquiry[2] =
		((struct priv_lu_ssc *)lu->lu_private)->pm->drive_ANSI_VERSION;

	lu->inquiry[36] = get_product_family(lu);

	sprintf(b, "%s", MHVTL_VERSION);
	sscanf(b, "%d.%d.%d", &x, &y, &z);
	if (x) {
		lu->inquiry[37] = x;
		lu->inquiry[38] = y;
	} else {
		lu->inquiry[37] = y;
		lu->inquiry[38] = z;
	}

	/* VPD page 0xC0 */
	pg = PCODE_OFFSET(0xc0);
	lu->lu_vpd[pg] = alloc_vpd(44);
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_dlt_c0(lu);

	/* VPD page 0xC1 */
	pg = PCODE_OFFSET(0xc1);
	lu->lu_vpd[pg] = alloc_vpd(44);
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_dlt_c1(lu, lu->lu_serial_no);
}
示例#6
0
static void update_hp_vpd_cx(struct lu_phy_attr *lu, uint8_t pg, char *comp,
				char *vers, char *date, char *variant)
{
	struct vpd *vpd_p;
	char *data;

	vpd_p = lu->lu_vpd[PCODE_OFFSET(pg)];
	if (!vpd_p) {
		MHVTL_LOG("Arrhhh... vpd pg %d not defined...", pg);
	}
	data = (char *)vpd_p->data;

	data[3] = 0x5c;
	snprintf(&data[4], 24, "%-24s", comp);
	snprintf(&data[30], 18, "%-18s", vers);
	snprintf(&data[49], 24, "%-24s", date);
	snprintf(&data[73], 22, "%-22s", variant);
}
示例#7
0
static void init_t10k_inquiry(struct lu_phy_attr *lu)
{
	int pg;
	uint8_t worm = 1;	/* Supports WORM */

	lu->inquiry[3] = 0x42;
	lu->inquiry[4] = INQUIRY_LEN - 5;	/* Additional Length */
	lu->inquiry[54] = 0x04;	/* Key Management */
	lu->inquiry[55] = 0x12;	/* Support Encryption & Compression */

	/* Sequential Access device capabilities - Ref: 8.4.2 */
	pg = PCODE_OFFSET(0xb0);
	lu->lu_vpd[pg] = alloc_vpd(VPD_B0_SZ);
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_b0(lu, &worm);
}
示例#8
0
文件: vtlcart.c 项目: fishky/mhvtl
int load_tape(const char *pcl, uint8_t *sam_stat)
{
	char pcl_data[1024], pcl_indx[1024], pcl_meta[1024];
	struct stat data_stat, indx_stat, meta_stat;
	uint64_t exp_size;
	size_t	io_size;
	loff_t nread;
	int rc = 0;
	int null_media_type;
	char touch_file[128];

	uint8_t error_check;

	snprintf(touch_file, 127, "%s/bypass_error_check", MHVTL_HOME_PATH);
	error_check = (stat(touch_file, &data_stat) == -1) ? FALSE : TRUE;

	if (error_check) {
		MHVTL_LOG("WARNING - touch file %s found - bypassing sanity checks on open", touch_file);
	}

/* KFRDEBUG - sam_stat needs updates in lots of places here. */

	/* If some other PCL is already open, return. */
	if (datafile >= 0)
		return 1;

	/* Open all three files and stat them to get their current sizes. */

	if (strlen(home_directory))
		snprintf(currentPCL, ARRAY_SIZE(currentPCL), "%s/%s",
						home_directory, pcl);
	else
		snprintf(currentPCL, ARRAY_SIZE(currentPCL), "%s/%s",
						MHVTL_HOME_PATH, pcl);

	snprintf(pcl_data, ARRAY_SIZE(pcl_data), "%s/data", currentPCL);
	snprintf(pcl_indx, ARRAY_SIZE(pcl_indx), "%s/indx", currentPCL);
	snprintf(pcl_meta, ARRAY_SIZE(pcl_meta), "%s/meta", currentPCL);

	MHVTL_DBG(2, "Opening media: %s", pcl);

	if (stat(pcl_data, &data_stat) == -1) {
		MHVTL_DBG(2, "Couldn't find %s, trying previous default: %s/%s",
				pcl_data, MHVTL_HOME_PATH, pcl);
		snprintf(currentPCL, ARRAY_SIZE(currentPCL), "%s/%s",
						MHVTL_HOME_PATH, pcl);
		snprintf(pcl_data, ARRAY_SIZE(pcl_data), "%s/data", currentPCL);
		snprintf(pcl_indx, ARRAY_SIZE(pcl_indx), "%s/indx", currentPCL);
		snprintf(pcl_meta, ARRAY_SIZE(pcl_meta), "%s/meta", currentPCL);
	}

	datafile = open(pcl_data, O_RDWR|O_LARGEFILE);
	if (datafile == -1) {
		MHVTL_ERR("open of pcl %s file %s failed, %s", pcl,
			pcl_data, strerror(errno));
		rc = 3;
		goto failed;
	}
	indxfile = open(pcl_indx, O_RDWR|O_LARGEFILE);
	if (indxfile == -1) {
		MHVTL_ERR("open of pcl %s file %s failed, %s", pcl,
			pcl_indx, strerror(errno));
		rc = 3;
		goto failed;
	}
	metafile = open(pcl_meta, O_RDWR|O_LARGEFILE);
	if (metafile == -1) {
		MHVTL_ERR("open of pcl %s file %s failed, %s", pcl,
			pcl_meta, strerror(errno));
		rc = 3;
		goto failed;
	}

	if (fstat(datafile, &data_stat) < 0) {
		MHVTL_ERR("stat of pcl %s file %s failed: %s", pcl,
			pcl_data, strerror(errno));
		rc = 3;
		goto failed;
	}

	if (fstat(indxfile, &indx_stat) < 0) {
		MHVTL_ERR("stat of pcl %s file %s failed: %s", pcl,
			pcl_indx, strerror(errno));
		rc = 3;
		goto failed;
	}

	if (fstat(metafile, &meta_stat) < 0) {
		MHVTL_ERR("stat of pcl %s file %s failed: %s", pcl,
			pcl_meta, strerror(errno));
		rc = 3;
		goto failed;
	}

	/* Verify that the metafile size is at least reasonable. */

	exp_size = sizeof(mam) + sizeof(meta);
	if ((uint32_t)meta_stat.st_size < exp_size) {
		MHVTL_ERR("sizeof(mam) + sizeof(meta) - "
			"pcl %s file %s is not the correct length, "
			"expected at least %" PRId64 ", actual %" PRId64,
			pcl, pcl_meta, exp_size, meta_stat.st_size);
		if (error_check) {
			rc = 2;
			goto failed;
		}
	}

	/* Read in the MAM and sanity-check it. */
	nread = read(metafile, &mam, sizeof(mam));
	if (nread < 0) {
		MHVTL_ERR("Error reading pcl %s MAM from metafile: %s",
			pcl, strerror(errno));
		if (error_check) {
			rc = 2;
			goto failed;
		}
	} else if (nread != sizeof(mam)) {
		MHVTL_ERR("Error reading pcl %s MAM from metafile: "
			"unexpected read length", pcl);
		if (error_check) {
			rc = 2;
			goto failed;
		}
	}

	null_media_type = mam.MediumType == MEDIA_TYPE_NULL ? 1 : 0;

	if (mam.tape_fmt_version != TAPE_FMT_VERSION) {
		MHVTL_ERR("pcl %s MAM contains incorrect media format", pcl);
		sam_medium_error(E_MEDIUM_FMT_CORRUPT, sam_stat);
		if (error_check) {
			rc = 2;
			goto failed;
		}
	}

	/* Read in the meta_header structure and sanity-check it. */

	nread = read(metafile, &meta, sizeof(meta));
	if (nread < 0) {
		MHVTL_ERR("Error reading pcl %s meta_header from "
			"metafile: %s", pcl, strerror(errno));
		rc = 2;
		goto failed;
	} else if (nread != sizeof(meta)) {
		MHVTL_ERR("Error reading pcl %s meta header from "
			"metafile: unexpected read length", pcl);
		rc = 2;
		goto failed;
	}

	/* Now recompute the correct size of the meta file. */

	exp_size = sizeof(mam) + sizeof(meta) +
		(meta.filemark_count * sizeof(*filemarks));

	if ((uint32_t)meta_stat.st_size != exp_size) {
		MHVTL_ERR("sizeof(mam) + sizeof(meta) + sizeof(*filemarks) - "
			"pcl %s file %s is not the correct length, "
			"expected %" PRId64 ", actual %" PRId64, pcl,
			pcl_meta, exp_size, meta_stat.st_size);
		if (error_check) {
			rc = 2;
			goto failed;
		}
	}

	/* See if we have allocated enough space for the actual number of
	   filemarks on the tape.  If not, realloc now.
	*/

	if (check_filemarks_alloc(meta.filemark_count)) {
		if (error_check) {
			rc = 3;
			goto failed;
		}
	}

	/* Now read in the filemark map. */

	io_size = meta.filemark_count * sizeof(*filemarks);
	if (io_size) {
		nread = read(metafile, filemarks, io_size);
		if (nread < 0) {
			MHVTL_ERR("Error reading pcl %s filemark map from "
				"metafile: %s", pcl, strerror(errno));
			rc = 2;
			goto failed;
		} else if ((size_t)nread != io_size) {
			MHVTL_ERR("Error reading pcl %s filemark map from "
				"metafile: unexpected read length", pcl);
			if (error_check) {
				rc = 2;
				goto failed;
			}
		}
	}

	/* Use the size of the indx file to work out where the virtual
	   B_EOD block resides.
	*/

	if ((indx_stat.st_size % sizeof(struct raw_header)) != 0) {
		MHVTL_ERR("pcl %s indx file has improper length, indicating "
			"possible file corruption", pcl);
		rc = 2;
		goto failed;
	}
	eod_blk_number = indx_stat.st_size / sizeof(struct raw_header);

	/* Make sure that the filemark map is consistent with the size of the
	   indx file.
	*/
	if (meta.filemark_count && eod_blk_number &&
		filemarks[meta.filemark_count - 1] >= eod_blk_number) {
		MHVTL_ERR("pcl %s indx file has improper length as compared "
			"to the meta file, indicating possible file corruption",
			pcl);
		MHVTL_ERR("Filemark count: %d eod_blk_number: %d",
				meta.filemark_count, eod_blk_number);
		rc = 2;
		goto failed;
	}

	/* Read in the last raw_header struct from the indx file and use that
	   to validate the correct size of the data file.
	*/

	if (eod_blk_number == 0)
		eod_data_offset = 0;
	else {
		if (read_header(eod_blk_number - 1, sam_stat)) {
			rc = 3;
			goto failed;
		}
		eod_data_offset = raw_pos.data_offset +
			raw_pos.hdr.disk_blk_size;
	}

	if (null_media_type) {
		MHVTL_LOG("Loaded NULL media type");	/* Skip check */
	} else if ((uint64_t)data_stat.st_size != eod_data_offset) {
		MHVTL_ERR("st_size != eod_data_offset - "
			"pcl %s file %s is not the correct length, "
			"expected %" PRId64 ", actual %" PRId64, pcl,
			pcl_data, eod_data_offset, data_stat.st_size);
		if (error_check) {
			rc = 2;
			goto failed;
		}
	}

	/* Give a hint to the kernel that data, once written, tends not to be
	   accessed again immediately.
	*/

	posix_fadvise(indxfile, 0, 0, POSIX_FADV_DONTNEED);
	posix_fadvise(datafile, 0, 0, POSIX_FADV_DONTNEED);

	/* Now initialize raw_pos by reading in the first header, if any. */

	if (read_header(0, sam_stat)) {
		rc = 3;
		goto failed;
	}

	return 0;

failed:
	if (datafile >= 0) {
		close(datafile);
		datafile = -1;
	}
	if (indxfile >= 0) {
		close(indxfile);
		indxfile = -1;
	}
	if (metafile >= 0) {
		close(metafile);
		metafile = -1;
	}
	return rc;
}
示例#9
0
文件: vtlcart.c 项目: fishky/mhvtl
int create_tape(const char *pcl, const struct MAM *mamp, uint8_t *sam_stat)
{
	struct stat data_stat;
	char newMedia[1024];
	char newMedia_data[1024];
	char newMedia_indx[1024];
	char newMedia_meta[1024];
	struct passwd *pw;
	int rc = 0;

	/* Attempt to create the new PCL.  This will fail if the PCL's directory
	   or any of the PCL's three files already exist, leaving any existing
	   files as they were.
	*/

	pw = getpwnam(USR);	/* Find UID for user 'vtl' */
	if (!pw) {
		MHVTL_ERR("Failed to get UID for user '%s': %s", USR,
			strerror(errno));
		return 1;
	}

	snprintf(newMedia, ARRAY_SIZE(newMedia), "%s/%s", home_directory, pcl);

	snprintf(newMedia_data, ARRAY_SIZE(newMedia_data), "%s/data", newMedia);
	snprintf(newMedia_indx, ARRAY_SIZE(newMedia_indx), "%s/indx", newMedia);
	snprintf(newMedia_meta, ARRAY_SIZE(newMedia_meta), "%s/meta", newMedia);

	/* Check if data file already exists, nothing to create */
	if (stat(newMedia_data, &data_stat) != -1)
		return 0;

	umask(0007);
	rc = mkdir(newMedia, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_ISGID);
	if (rc) {
		/* No need to fail just because the parent dir exists */
		if (errno != EEXIST) {
			MHVTL_ERR("Failed to create directory %s: %s",
					newMedia, strerror(errno));
			return 2;
		}
	}

	/* Don't really care if chown() fails or not..
	 * But lets try anyway
	 */
	chown(newMedia, pw->pw_uid, pw->pw_gid);

	datafile = creat(newMedia_data, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
	if (datafile == -1) {
		MHVTL_ERR("Failed to create file %s: %s", newMedia_data,
			strerror(errno));
		return 2;
	}
	indxfile = creat(newMedia_indx, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
	if (indxfile == -1) {
		MHVTL_ERR("Failed to create file %s: %s", newMedia_indx,
			strerror(errno));
		unlink(newMedia_data);
		rc = 2;
		goto cleanup;
	}
	metafile = creat(newMedia_meta, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
	if (metafile == -1) {
		MHVTL_ERR("Failed to create file %s: %s", newMedia_meta,
			strerror(errno));
		unlink(newMedia_data);
		unlink(newMedia_indx);
		rc = 2;
		goto cleanup;
	}
	chown(newMedia_data, pw->pw_uid, pw->pw_gid);
	chown(newMedia_indx, pw->pw_uid, pw->pw_gid);
	chown(newMedia_meta, pw->pw_uid, pw->pw_gid);

	MHVTL_LOG("%s files created", newMedia);

	/* Write the meta file consisting of the MAM and the meta_header
	   structure with the filemark count initialized to zero.
	*/
	mam = *mamp;

	memset(&meta, 0, sizeof(meta));
	meta.filemark_count = 0;

	if (write(metafile, &mam, sizeof(mam)) != sizeof(mam) ||
		    write(metafile, &meta, sizeof(meta)) != sizeof(meta)) {
		MHVTL_ERR("Failed to initialize file %s: %s", newMedia_meta,
			strerror(errno));
		unlink(newMedia_data);
		unlink(newMedia_indx);
		unlink(newMedia_meta);
		rc = 1;
	}

cleanup:
	if (datafile >= 0) {
		close(datafile);
		datafile = -1;
	}
	if (indxfile >= 0) {
		close(indxfile);
		indxfile = -1;
	}
	if (metafile >= 0) {
		close(metafile);
		metafile = -1;
	}

	return rc;
}
示例#10
0
static void init_ult_inquiry(struct lu_phy_attr *lu)
{
	int pg;
	uint8_t worm = 1;	/* Supports WORM */
	uint8_t local_TapeAlert[8] =
			{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

	pg = PCODE_OFFSET(0x86);
	lu->lu_vpd[pg] = alloc_vpd(VPD_86_SZ);
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}

	/* Sequential Access device capabilities - Ref: 8.4.2 */
	pg = PCODE_OFFSET(0xb0);
	lu->lu_vpd[pg] = alloc_vpd(VPD_B0_SZ);
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_b0(lu, &worm);

	/* Manufacture-assigned serial number - Ref: 8.4.3 */
	pg = PCODE_OFFSET(0xb1);
	lu->lu_vpd[pg] = alloc_vpd(VPD_B1_SZ);
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_b1(lu, lu->lu_serial_no);

	/* TapeAlert supported flags - Ref: 8.4.4 */
	pg = PCODE_OFFSET(0xb2);
	lu->lu_vpd[pg] = alloc_vpd(VPD_B2_SZ);
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_b2(lu, &local_TapeAlert);

	/* VPD page 0xC0 - Firmware revision page */
	pg = PCODE_OFFSET(0xc0);
	lu->lu_vpd[pg] = alloc_vpd(0x60);
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_hp_vpd_cx(lu, pg, "Firmware", MHVTL_VERSION,
						"2012/04/18 19:38", "6");

	/* VPD page 0xC1 - Hardware */
	pg = PCODE_OFFSET(0xc1);
	lu->lu_vpd[pg] = alloc_vpd(0x60);
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_hp_vpd_cx(lu, pg, "Hardware", MHVTL_VERSION,
						"2012/04/18 06:53", "5");

	/* VPD page 0xC2 - PCA */
	pg = PCODE_OFFSET(0xc2);
	lu->lu_vpd[pg] = alloc_vpd(0x60);
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_hp_vpd_cx(lu, pg, "PCA", MHVTL_VERSION,
						"1996/11/29 10:00", "4");

	/* VPD page 0xC3 - Mechanism */
	pg = PCODE_OFFSET(0xc3);
	lu->lu_vpd[pg] = alloc_vpd(0x60);
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_hp_vpd_cx(lu, pg, "Mechanism", MHVTL_VERSION,
						"1992/08/11 10:00", "3");

	/* VPD page 0xC4 - Head Assembly */
	pg = PCODE_OFFSET(0xc4);
	lu->lu_vpd[pg] = alloc_vpd(0x60);
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_hp_vpd_cx(lu, pg, "Head Assy", MHVTL_VERSION,
						"1966/07/28 10:00", "2");

	/* VPD page 0xC5 - ACI */
	pg = PCODE_OFFSET(0xc5);
	lu->lu_vpd[pg] = alloc_vpd(0x60);
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_hp_vpd_cx(lu, pg, "ACI", MHVTL_VERSION,
						"1960/03/10 10:00", "1");
}
示例#11
0
/* SuperDLT range */
static void init_sdlt_inquiry(struct lu_phy_attr *lu)
{
	int pg;
	uint8_t worm;
	uint8_t ta[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
	char b[32];
	int x, y, z;

	worm = ((struct priv_lu_ssc *)lu->lu_private)->pm->drive_supports_WORM;
	lu->inquiry[2] =
		((struct priv_lu_ssc *)lu->lu_private)->pm->drive_ANSI_VERSION;


	lu->inquiry[36] = get_product_family(lu);

	sprintf(b, "%s", MHVTL_VERSION);
	sscanf(b, "%d.%d.%d", &x, &y, &z);
	if (x) {
		lu->inquiry[37] = x;
		lu->inquiry[38] = y;
	} else {
		lu->inquiry[37] = y;
		lu->inquiry[38] = z;
	}

	/* Sequential Access device capabilities - Ref: 8.4.2 */
	pg = PCODE_OFFSET(0xb0);
	lu->lu_vpd[pg] = alloc_vpd(VPD_B0_SZ);
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_b0(lu, &worm);

	/* Manufacture-assigned serial number - Ref: 8.4.3 */
	pg = PCODE_OFFSET(0xb1);
	lu->lu_vpd[pg] = alloc_vpd(VPD_B1_SZ);
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_b1(lu, lu->lu_serial_no);

	/* TapeAlert supported flags - Ref: 8.4.4 */
	pg = PCODE_OFFSET(0xb2);
	lu->lu_vpd[pg] = alloc_vpd(VPD_B2_SZ);
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_b2(lu, &ta);

	/* VPD page 0xC0 */
	pg = PCODE_OFFSET(0xc0);
	lu->lu_vpd[pg] = alloc_vpd(44);
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_dlt_c0(lu);

	/* VPD page 0xC1 */
	pg = PCODE_OFFSET(0xc1);
	lu->lu_vpd[pg] = alloc_vpd(44);
	if (!lu->lu_vpd[pg]) {
		MHVTL_LOG("Failed to malloc(): Line %d", __LINE__);
		exit(-ENOMEM);
	}
	update_vpd_dlt_c1(lu, lu->lu_serial_no);
}
示例#12
0
文件: ssc.c 项目: aroundrobin/mhvtl
/*
 * Process the MODE_SELECT command
 */
uint8_t ssc_mode_select(struct scsi_cmd *cmd)
{
	uint8_t *sam_stat = &cmd->dbuf_p->sam_stat;
	uint8_t *buf = cmd->dbuf_p->data;
	int block_descriptor_sz;
	int page_len;
	uint8_t *bdb = NULL;
	int i;
	int long_lba = 0;
	int count;
	int save_page;

	save_page = cmd->scb[1] & 0x01;

	switch (cmd->scb[0]) {
	case MODE_SELECT:
		cmd->dbuf_p->sz = cmd->scb[4];
		break;
	case MODE_SELECT_10:
		cmd->dbuf_p->sz = get_unaligned_be16(&cmd->scb[7]);
		break;
	default:
		cmd->dbuf_p->sz = 0;
	}

	count = retrieve_CDB_data(cmd->cdev, cmd->dbuf_p);

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

	if (!(cmd->scb[1] & 0x10)) { /* Page Format: 1 - SPC, 0 - vendor uniq */
		mkSenseBuf(ILLEGAL_REQUEST, E_INVALID_FIELD_IN_CDB, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
	}

	switch (cmd->scb[0]) {
	case MODE_SELECT:
		block_descriptor_sz = buf[3];
		if (block_descriptor_sz)
			bdb = &buf[4];
		i = 4 + block_descriptor_sz;
		break;
	case MODE_SELECT_10:
		block_descriptor_sz = get_unaligned_be16(&buf[6]);
		long_lba = buf[4] & 1;
		if (block_descriptor_sz)
			bdb = &buf[8];
		i = 8 + block_descriptor_sz;
		break;
	default:
		mkSenseBuf(ILLEGAL_REQUEST, E_INVALID_OP_CODE, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
	}

	if (bdb) {
		if (long_lba) {
			mkSenseBuf(ILLEGAL_REQUEST, E_INVALID_FIELD_IN_CDB,
							sam_stat);
			MHVTL_DBG(1, "Warning can not "
				"handle long descriptor block (long_lba bit)");
			return SAM_STAT_CHECK_CONDITION;
		}
		memcpy(modeBlockDescriptor, bdb, block_descriptor_sz);
	}

	/* Ignore mode pages if 'save page' bit not set */
	if (!save_page) {
		MHVTL_DBG(1, "Save page bit not set. Ignoring page data");
		return SAM_STAT_GOOD;
	}

#ifdef MHVTL_DEBUG
	if (debug)
		hex_dump(buf, cmd->dbuf_p->sz);
#endif

	MHVTL_DBG(3, "count: %d, i: %d", count, i);
	if (i == 4) {
	MHVTL_DBG(3, "Offset 0: %02x %02x %02x %02x",
			buf[0], buf[1], buf[2], buf[3]);
	} else {
	MHVTL_DBG(3, "Offset 0: %02x %02x %02x %02x  %02x %02x %02x %02x",
			buf[0], buf[1], buf[2], buf[3],
			buf[4], buf[5], buf[6], buf[7]);
	}

	count -= i;
	while (i < count) {
		MHVTL_DBG(3, " %02d: %02x %02x %02x %02x  %02x %02x %02x %02x",
			i,
			buf[i+0], buf[i+1], buf[i+2], buf[i+3],
			buf[i+4], buf[i+5], buf[i+6], buf[i+7]);
		MHVTL_DBG(3, " %02d: %02x %02x %02x %02x  %02x %02x %02x %02x",
			i+8,
			buf[i+8], buf[i+9], buf[i+10], buf[i+11],
			buf[i+12], buf[i+13], buf[i+14], buf[i+15]);
		MHVTL_DBG(3, " %02d: %02x %02x %02x %02x  %02x %02x %02x %02x",
			i+16,
			buf[i+16], buf[i+17], buf[i+18], buf[i+19],
			buf[i+20], buf[i+21], buf[i+22], buf[i+23]);
		MHVTL_DBG(3, " %02d: %02x %02x %02x %02x  %02x %02x %02x %02x",
			i+24,
			buf[i+24], buf[i+25], buf[i+26], buf[i+27],
			buf[i+28], buf[i+29], buf[i+30], buf[i+31]);
		/* Default page len is, override if sub-pages */
		page_len = buf[i + 1];
		switch (buf[i]) {
		case MODE_DATA_COMPRESSION:
			set_mode_compression(cmd, &buf[i]);
			break;

		case MODE_DEVICE_CONFIGURATION:
			/* If this is '01' it's a subpage value
			 *     i.e. DEVICE CONFIGURATION EXTENSION
			 * If it's 0x0e, it indicates a page length
			 * for MODE DEVICE CONFIGURATION
			 */
			if (buf[i + 1] == 0x01) {
				if (set_device_configuration_extension(cmd,
								&buf[i]))
					return SAM_STAT_CHECK_CONDITION;
				/* Subpage 1 - override default page length */
				page_len = get_unaligned_be16(&buf[i + 2]);
			} else
				set_device_configuration(cmd, &buf[i]);
			break;

		default:
			MHVTL_DBG_PRT_CDB(1, cmd);
			MHVTL_DBG(1, "Mode page 0x%02x not handled", buf[i]);
			break;
		}
		if (page_len == 0) { /* Something wrong with data structure */
			page_len = cmd->dbuf_p->sz;
			MHVTL_LOG("Problem with mode select data structure");
		}
		i += page_len;	/* Next mode page */
	}

	return SAM_STAT_GOOD;
}
示例#13
0
文件: ssc.c 项目: aroundrobin/mhvtl
static uint8_t set_device_configuration_extension(struct scsi_cmd *cmd, uint8_t *p)
{
	uint8_t *sam_stat = &cmd->dbuf_p->sam_stat;
	struct lu_phy_attr *lu = cmd->lu;
	struct priv_lu_ssc *lu_priv = cmd->lu->lu_private;
	struct ssc_personality_template *pm;
	struct mode *mp;
	int page_code_len;
	int write_mode;
	int pews;	/* Programable Early Warning Size */

	pm = lu_priv->pm;

	mp = lookup_pcode(&lu->mode_pg, MODE_DEVICE_CONFIGURATION, 1);

	/* Code error
	 * Any device supporting this should have this mode page defined */
	if (!mp) {
		mkSenseBuf(HARDWARE_ERROR, E_INTERNAL_TARGET_FAILURE, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
	}

	page_code_len = get_unaligned_be16(&p[2]);

	if (page_code_len != 0x1c) {
		MHVTL_LOG("Unexpected page code length.. Unexpected results");
		mkSenseBuf(ILLEGAL_REQUEST, E_INVALID_FIELD_IN_PARMS, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
	}

	write_mode = (p[5] & 0xf0) >> 4;
	if (write_mode > 1) {
		mkSenseBuf(ILLEGAL_REQUEST, E_INVALID_FIELD_IN_PARMS, sam_stat);
		return SAM_STAT_CHECK_CONDITION;
	}
	MHVTL_DBG(2, "%s mode", write_mode ? "Append-only" : "Write-anywhere");

	pews = get_unaligned_be16(&p[6]);
	if (pm->drive_supports_prog_early_warning) {
		MHVTL_DBG(2, "Set Programable Early Warning Size: %d", pews);
		lu_priv->prog_early_warning_sz = pews;
		update_prog_early_warning(lu);
	} else {
		MHVTL_DBG(2, "Programable Early Warning Size not supported"
				" by this device");
	}

	MHVTL_DBG(2, "Volume containing encrypted logical blocks "
			"requires encryption: %d",
			p[8] & 0x01);

	if (pm->drive_supports_append_only_mode) {
		/* Can't reset append-only mode via mode page ssc4 8.3.8 */
		if (lu_priv->append_only_mode && write_mode == 0) {
			MHVTL_LOG("Can't reset append only mode via mode page");
			mkSenseBuf(ILLEGAL_REQUEST, E_INVALID_FIELD_IN_PARMS,
							sam_stat);
			return SAM_STAT_CHECK_CONDITION;
		}
		if (write_mode) {
			lu_priv->append_only_mode = write_mode;
			lu_priv->allow_overwrite = FALSE;
		}
	}

	/* Now update our copy of this mode page */
	mp->pcodePointer[5] &= 0x0f;
	mp->pcodePointer[5] |= write_mode << 4;

	return SAM_STAT_GOOD;
}
示例#14
0
int load_tape(const char *pcl, uint8_t *sam_stat)
{
	loff_t nread;
	uint32_t version = 0;

	MHVTL_DBG(1, "load_tape");
/* KFRDEBUG - sam_stat needs updates in lots of places here. */
#if NOTDEF
	if (datafile == -1)
		/* return 1; */	/* don't return 1 here */
		return 0;
#endif

	sprintf(currentMedia, "%s/%s", MHVTL_HOME_PATH, pcl);
	/* MHVTL_DBG(2, "Opening file/media %s", currentMedia); */
	MHVTL_LOG("Opening file/media %s", currentMedia);
	datafile = open(currentMedia, O_RDWR|O_LARGEFILE);
	if (datafile == -1) {
		MHVTL_DBG(1, "%s: open file/media failed, %s", currentMedia,
			strerror(errno));
		return 3;	/* Unsuccessful load */
	}

	/* Now read in header information from just opened datafile */
	nread = read(datafile, &raw_pos, sizeof(raw_pos));
	if (nread < 0) {
		MHVTL_LOG("%s: %s",
			 "Error reading header in datafile, load failed",
			strerror(errno));
		close(datafile);
		datafile = -1;
		return 4;	/* Unsuccessful load */
	} else if (nread < sizeof(raw_pos)) {	/* Did not read anything... */
		MHVTL_LOG("%s: %s",
				 "Error: Not a tape format, load failed",
				strerror(errno));
		close(datafile);
		datafile = -1;
		return 5;
	}
	if (raw_pos.hdr.blk_type != B_BOT) {
		MHVTL_LOG("Header type: %d not valid, load failed",
							raw_pos.hdr.blk_type);
		close(datafile);
		datafile = -1;
		return 6;
	}
	/* FIXME: Need better validation checking here !! */
	 if (raw_pos.next_blk != (sizeof(raw_pos) + sizeof(mam))) {
		MHVTL_LOG("MAM size incorrect, load failed"
			" - Expected size: %d, size found: %" PRId64,
			(int)(sizeof(raw_pos) + sizeof(mam)),
				raw_pos.next_blk);
		close(datafile);
		datafile = -1;
		return 7;	/* Unsuccessful load */
	}
	nread = read(datafile, &mam, sizeof(mam));
	if (nread < 0) {
		MHVTL_LOG("Can not read MAM from mounted media, %s",
							strerror(errno));
		close(datafile);
		datafile = -1;
		return 8;	/* Unsuccessful load */
	}
	if (nread != sizeof(mam)) {
		MHVTL_LOG("Can not read MAM from mounted media, "
				"insufficient data");
		close(datafile);
		datafile = -1;
		return 9;	/* Unsuccessful load */
	}

	version = mam.tape_fmt_version;
	if (version != TAPE_FMT_VERSION) {
		MHVTL_LOG("Incorrect media format %lu", version);
		sam_medium_error(E_MEDIUM_FMT_CORRUPT, sam_stat);
		close(datafile);
		datafile = -1;
		return 10;
	}

	MediumType = mam.MediumType;
	c_pos = &raw_pos.hdr;
	return 0;
}