Esempio n. 1
0
/*
 *
 * Process the SCSI command
 *
 * Called with:
 *	cdev          -> Char dev file handle,
 *	cdb           -> SCSI Command buffer pointer,
 *	struct vtl_ds -> general purpose data structure... Need better name
 *
 * Return:
 *	SAM status returned in struct vtl_ds.sam_stat
 */
static void processCommand(int cdev, uint8_t *cdb, struct vtl_ds *dbuf_p,
			useconds_t pollInterval)
{
	int err = 0;
	struct scsi_cmd _cmd;
	struct scsi_cmd *cmd;
	cmd = &_cmd;

	cmd->scb = cdb;
	cmd->scb_len = 16;	/* fixme */
	cmd->dbuf_p = dbuf_p;
	cmd->lu = &lunit;
	cmd->pollInterval = pollInterval;
	cmd->cdev = cdev;

	MHVTL_DBG_PRT_CDB(1, cmd);

	switch (cdb[0]) {
	case REPORT_LUNS:
	case REQUEST_SENSE:
	case MODE_SELECT:
	case INQUIRY:
		dbuf_p->sam_stat = SAM_STAT_GOOD;
		break;
	default:
		if (cmd->lu->online == 0) {
			sam_not_ready(E_OFFLINE, &dbuf_p->sam_stat);
			return;
		}
		if (check_reset(&dbuf_p->sam_stat))
			return;
	}

	/* Skip main op code processing if pre-cmd returns non-zero */
	if (cmd->lu->scsi_ops->ops[cdb[0]].pre_cmd_perform)
		err = cmd->lu->scsi_ops->ops[cdb[0]].pre_cmd_perform(cmd, NULL);

	if (!err)
		dbuf_p->sam_stat = cmd->lu->scsi_ops->ops[cdb[0]].cmd_perform(cmd);

	/* Post op code processing regardless */
	if (cmd->lu->scsi_ops->ops[cdb[0]].post_cmd_perform)
		cmd->lu->scsi_ops->ops[cdb[0]].post_cmd_perform(cmd, NULL);

	return;
}
Esempio n. 2
0
/*
 *
 * Process the SCSI command
 *
 * Called with:
 *	cdev          -> Char dev file handle,
 *	cdb           -> SCSI Command buffer pointer,
 *	struct vtl_ds -> general purpose data structure... Need better name
 *
 * Return:
 *	SAM status returned in struct vtl_ds.sam_stat
 */
static void processCommand(int cdev, uint8_t *cdb, struct vtl_ds *dbuf_p,
			useconds_t pollInterval)
{
	struct scsi_cmd _cmd;
	struct scsi_cmd *cmd;
	cmd = &_cmd;

	cmd->scb = cdb;
	cmd->scb_len = 16;	/* fixme */
	cmd->dbuf_p = dbuf_p;
	cmd->lu = &lunit;
	cmd->pollInterval = pollInterval;

	MHVTL_DBG_PRT_CDB(1, cmd);

	switch (cdb[0]) {
	case REPORT_LUNS:
	case REQUEST_SENSE:
	case MODE_SELECT:
	case INQUIRY:
		dbuf_p->sam_stat = SAM_STAT_GOOD;
		break;
	default:
		if (cmd->lu->online == 0) {
			mkSenseBuf(NOT_READY, E_OFFLINE, &dbuf_p->sam_stat);
			return;
		}
		if (check_reset(&dbuf_p->sam_stat))
			return;
	}

	if (cmd->lu->scsi_ops->ops[cdb[0]].pre_cmd_perform)
		cmd->lu->scsi_ops->ops[cdb[0]].pre_cmd_perform(cmd, NULL);

	dbuf_p->sam_stat = cmd->lu->scsi_ops->ops[cdb[0]].cmd_perform(cmd);
	return;
}
Esempio n. 3
0
/*
 * 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;
}