Parse() functions made generic

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@105 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2007-04-03 14:47:47 +00:00
parent 3b449d4705
commit 3c1cf6c033
11 changed files with 439 additions and 488 deletions
+54 -2
View File
@@ -443,10 +443,22 @@
#define SCST_RES_3RDPTY 0x10
#define SCST_RES_LONGID 0x02
/*************************************************************
** Bits in the READ POSITION command
*************************************************************/
#define TCLP_BIT 4
#define LONG_BIT 2
#define BT_BIT 1
/*************************************************************
** Misc SCSI constants
*************************************************************/
#define SCST_SENSE_ASC_UA_RESET 0x29
#define READ_CAP_LEN 8
#define READ_CAP16_LEN 12
#define BYTCHK 0x02
#define POSITION_LEN_SHORT 20
#define POSITION_LEN_LONG 32
/*************************************************************
** Name of the entry in /proc
@@ -754,8 +766,7 @@ struct scst_dev_type
*
* MUST HAVE
*/
int (*parse) (struct scst_cmd *cmd,
const struct scst_info_cdb *cdb_info);
int (*parse) (struct scst_cmd *cmd, struct scst_info_cdb *cdb_info);
/*
* Called to execute CDB. Useful, for instance, to implement
@@ -2299,4 +2310,45 @@ static inline void scst_thr_data_put(struct scst_thr_data_hdr *data)
data->free_fn(data);
}
/**
** Generic parse() support routines
**/
/* Calculates and returns block shift for the given sector size */
int scst_calc_block_shift(int sector_size);
/* Generic parse() for SBC (disk) devices */
int scst_sbc_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb, int block_shift);
/* Generic parse() for MMC (cdrom) devices */
int scst_cdrom_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb, int block_shift);
/* Generic parse() for MO disk devices */
int scst_modisk_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb, int block_shift);
/* Generic parse() for tape devices */
int scst_tape_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb, int block_size);
/* Generic parse() functions for other devices */
int scst_null_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb);
static inline int scst_changer_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb)
{
return scst_null_parse(cmd, info_cdb);
}
static inline int scst_processor_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb)
{
return scst_null_parse(cmd, info_cdb);
}
static inline int scst_raid_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb)
{
return scst_null_parse(cmd, info_cdb);
}
#endif /* __SCST_H */
+30 -90
View File
@@ -37,23 +37,18 @@
dev_done: cdrom_done, \
}
#define CDROM_RETRIES 2
#define CDROM_SMALL_TIMEOUT (3 * HZ)
#define CDROM_REG_TIMEOUT (900 * HZ)
#define CDROM_LONG_TIMEOUT (14000 * HZ)
#define READ_CAP_LEN 8
/* Flags */
#define BYTCHK 0x02
struct cdrom_params
{
int sector_size;
int block_shift;
};
int cdrom_attach(struct scst_device *);
void cdrom_detach(struct scst_device *);
int cdrom_parse(struct scst_cmd *, const struct scst_info_cdb *);
int cdrom_parse(struct scst_cmd *, struct scst_info_cdb *);
int cdrom_done(struct scst_cmd *);
static struct scst_dev_type cdrom_devtype = CDROM_TYPE;
@@ -117,7 +112,7 @@ int cdrom_attach(struct scst_device *dev)
TRACE_DBG("%s", "Doing READ_CAPACITY");
res = scsi_execute(dev->scsi_dev, cmd, data_dir, buffer,
buffer_size, sbuff,
CDROM_REG_TIMEOUT, CDROM_RETRIES, 0);
CDROM_REG_TIMEOUT, 3, 0);
TRACE_DBG("READ_CAPACITY done: %x", res);
@@ -128,22 +123,22 @@ int cdrom_attach(struct scst_device *dev)
if (!--retries) {
PRINT_ERROR_PR("UA not clear after %d retries",
SCST_DEV_UA_RETRIES);
cdrom->sector_size = 2048;
cdrom->block_shift = 11; /* 2048 bytes */
// res = -ENODEV;
goto out_free_buf;
}
}
if (res == 0) {
cdrom->sector_size = ((buffer[4] << 24) | (buffer[5] << 16) |
int sector_size = ((buffer[4] << 24) | (buffer[5] << 16) |
(buffer[6] << 8) | (buffer[7] << 0));
if (sector_size == 0)
sector_size = 2048;
cdrom->block_shift = scst_calc_block_shift(sector_size);
TRACE_DBG("Sector size is %i scsi_level %d(SCSI_2 %d)",
cdrom->sector_size, dev->scsi_dev->scsi_level, SCSI_2);
if (!cdrom->sector_size) {
cdrom->sector_size = 2048;
}
sector_size, dev->scsi_dev->scsi_level, SCSI_2);
} else {
TRACE_BUFFER("Sense set", sbuff, SCSI_SENSE_BUFFERSIZE);
cdrom->sector_size = 2048;
cdrom->block_shift = 11; /* 2048 bytes */
// res = -ENODEV;
goto out_free_buf;
}
@@ -195,19 +190,20 @@ void cdrom_detach(struct scst_device *dev)
*
* Note: Not all states are allowed on return
********************************************************************/
int cdrom_parse(struct scst_cmd *cmd, const struct scst_info_cdb *info_cdb)
int cdrom_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
{
int res = SCST_CMD_STATE_DEFAULT;
struct cdrom_params *cdrom;
int fixed;
struct cdrom_params *cdrom = (struct cdrom_params *)cmd->dev->dh_priv;
TRACE_ENTRY();
/*
* SCST sets good defaults for cmd->data_direction and cmd->bufflen
* based on info_cdb, therefore change them only if necessary
/*
* No need for locks here, since *_detach() can not be
* called, when there are existing commands.
*/
scst_cdrom_generic_parse(cmd, info_cdb, cdrom->block_shift);
cmd->retries = 1;
if (info_cdb->flags & SCST_SMALL_TIMEOUT) {
cmd->timeout = CDROM_SMALL_TIMEOUT;
} else if (info_cdb->flags & SCST_LONG_TIMEOUT) {
@@ -215,62 +211,6 @@ int cdrom_parse(struct scst_cmd *cmd, const struct scst_info_cdb *info_cdb)
} else {
cmd->timeout = CDROM_REG_TIMEOUT;
}
TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d lun %d(%d)",
info_cdb->op_name,
info_cdb->direction,
info_cdb->flags,
info_cdb->transfer_len, cmd->lun, (cmd->cdb[1] >> 5) & 7);
cmd->cdb[1] &= 0x1f;
fixed = info_cdb->flags & SCST_TRANSFER_LEN_TYPE_FIXED;
switch (cmd->cdb[0]) {
case READ_CAPACITY:
cmd->bufflen = READ_CAP_LEN;
cmd->data_direction = SCST_DATA_READ;
break;
case GPCMD_SET_STREAMING:
cmd->bufflen = (((*(cmd->cdb + 9)) & 0xff) << 8) +
((*(cmd->cdb + 10)) & 0xff);
cmd->bufflen &= 0xffff;
break;
case GPCMD_READ_CD:
cmd->bufflen = cmd->bufflen >> 8;
break;
#if 0
case SYNCHRONIZE_CACHE:
cmd->underflow = 0;
break;
#endif
case VERIFY_6:
case VERIFY:
case VERIFY_12:
case VERIFY_16:
if ((cmd->cdb[1] & BYTCHK) == 0) {
cmd->bufflen = 0;
cmd->data_direction = SCST_DATA_NONE;
fixed = 0;
}
break;
default:
/* It's all good */
break;
}
if (fixed) {
/*
* No need for locks here, since *_detach() can not be
* called, when there are existing commands.
*/
cdrom = (struct cdrom_params *)cmd->dev->dh_priv;
cmd->bufflen = info_cdb->transfer_len * cdrom->sector_size;
}
TRACE_DBG("res %d bufflen %zd direct %d",
res, cmd->bufflen, cmd->data_direction);
TRACE_EXIT();
return res;
}
@@ -308,13 +248,9 @@ int cdrom_done(struct scst_cmd *cmd)
case READ_CAPACITY:
{
/* Always keep track of cdrom capacity */
int buffer_size;
/*
* To force the compiler not to optimize it out to keep
* cdrom->sector_size access atomic
*/
volatile int sector_size;
int buffer_size, sector_size, block_shift;
uint8_t *buffer;
buffer_size = scst_get_buf_first(cmd, &buffer);
if (unlikely(buffer_size <= 0)) {
PRINT_ERROR_PR("%s: Unable to get the buffer",
@@ -331,12 +267,16 @@ int cdrom_done(struct scst_cmd *cmd)
sector_size =
((buffer[4] << 24) | (buffer[5] << 16) |
(buffer[6] << 8) | (buffer[7] << 0));
if (!sector_size)
sector_size = 2048;
cdrom->sector_size = sector_size;
TRACE_DBG("Sector size is %i", cdrom->sector_size);
scst_put_buf(cmd, buffer);
if (sector_size == 0)
sector_size = 2048;
block_shift = scst_calc_block_shift(sector_size);
/*
* To force the compiler not to optimize it out to keep
* cdrom->block_shift access atomic
*/
barrier();
cdrom->block_shift = block_shift;
break;
}
default:
+3 -23
View File
@@ -42,7 +42,7 @@
int changer_attach(struct scst_device *);
void changer_detach(struct scst_device *);
int changer_parse(struct scst_cmd *, const struct scst_info_cdb *);
int changer_parse(struct scst_cmd *, struct scst_info_cdb *);
int changer_done(struct scst_cmd *);
static struct scst_dev_type changer_devtype = CHANGER_TYPE;
@@ -124,16 +124,11 @@ void changer_detach(struct scst_device *dev)
*
* Note: Not all states are allowed on return
********************************************************************/
int changer_parse(struct scst_cmd *cmd, const struct scst_info_cdb *info_cdb)
int changer_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
{
int res = SCST_CMD_STATE_DEFAULT;
TRACE_ENTRY();
/*
* SCST sets good defaults for cmd->data_direction and cmd->bufflen
* based on info_cdb, therefore change them only if necessary
*/
scst_changer_generic_parse(cmd, info_cdb);
cmd->retries = 1;
@@ -143,21 +138,6 @@ int changer_parse(struct scst_cmd *cmd, const struct scst_info_cdb *info_cdb)
cmd->timeout = CHANGER_TIMEOUT;
}
TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d",
info_cdb->op_name,
info_cdb->direction, info_cdb->flags, info_cdb->transfer_len);
#if 0
switch (cmd->cdb[0]) {
default:
/* It's all good */
break;
}
#endif
TRACE_DBG("res %d bufflen %zd direct %d",
res, cmd->bufflen, cmd->data_direction);
TRACE_EXIT();
return res;
}
+22 -76
View File
@@ -56,23 +56,18 @@
exec: disk_exec, \
}
#define DISK_RETRIES 5
#define DISK_SMALL_TIMEOUT (3 * HZ)
#define DISK_REG_TIMEOUT (60 * HZ)
#define DISK_LONG_TIMEOUT (3600 * HZ)
#define READ_CAP_LEN 8
/* Flags */
#define BYTCHK 0x02
struct disk_params
{
int sector_size;
int block_shift;
};
int disk_attach(struct scst_device *dev);
void disk_detach(struct scst_device *dev);
int disk_parse(struct scst_cmd *cmd, const struct scst_info_cdb *info_cmd);
int disk_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cmd);
int disk_done(struct scst_cmd *cmd);
int disk_exec(struct scst_cmd *cmd);
@@ -193,7 +188,7 @@ int disk_attach(struct scst_device *dev)
TRACE_DBG("%s", "Doing READ_CAPACITY");
res = scsi_execute(dev->scsi_dev, cmd, data_dir, buffer,
buffer_size, sbuff,
DISK_REG_TIMEOUT, DISK_RETRIES, 0);
DISK_REG_TIMEOUT, 3, 0);
TRACE_DBG("READ_CAPACITY done: %x", res);
@@ -209,12 +204,9 @@ int disk_attach(struct scst_device *dev)
}
}
if (res == 0) {
disk->sector_size = ((buffer[4] << 24) | (buffer[5] << 16) |
int sector_size = ((buffer[4] << 24) | (buffer[5] << 16) |
(buffer[6] << 8) | (buffer[7] << 0));
TRACE_DBG("Sector size is %i", disk->sector_size);
if (!disk->sector_size) {
disk->sector_size = 512;
}
disk->block_shift = scst_calc_block_shift(sector_size);
} else {
TRACE_BUFFER("Sense set", sbuff, SCSI_SENSE_BUFFERSIZE);
res = -ENODEV;
@@ -268,20 +260,19 @@ void disk_detach(struct scst_device *dev)
*
* Note: Not all states are allowed on return
********************************************************************/
int disk_parse(struct scst_cmd *cmd, const struct scst_info_cdb *info_cdb)
int disk_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
{
struct disk_params *disk = (struct disk_params *)cmd->dev->dh_priv;
int res = SCST_CMD_STATE_DEFAULT;
struct disk_params *disk;
int fixed;
TRACE_ENTRY();
/*
* SCST sets good defaults for cmd->data_direction and cmd->bufflen
* based on info_cdb, therefore change them only if necessary
/*
* No need for locks here, since *_detach() can not be
* called, when there are existing commands.
*/
cmd->retries = DISK_RETRIES;
scst_sbc_generic_parse(cmd, info_cdb, disk->block_shift);
cmd->retries = 1;
if (info_cdb->flags & SCST_SMALL_TIMEOUT) {
cmd->timeout = DISK_SMALL_TIMEOUT;
@@ -291,49 +282,6 @@ int disk_parse(struct scst_cmd *cmd, const struct scst_info_cdb *info_cdb)
cmd->timeout = DISK_REG_TIMEOUT;
}
TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d",
info_cdb->op_name,
info_cdb->direction, info_cdb->flags, info_cdb->transfer_len);
fixed = info_cdb->flags & SCST_TRANSFER_LEN_TYPE_FIXED;
switch (cmd->cdb[0]) {
case READ_CAPACITY:
cmd->bufflen = READ_CAP_LEN;
cmd->data_direction = SCST_DATA_READ;
break;
#if 0
case SYNCHRONIZE_CACHE:
cmd->underflow = 0;
break;
#endif
case VERIFY_6:
case VERIFY:
case VERIFY_12:
case VERIFY_16:
if ((cmd->cdb[1] & BYTCHK) == 0) {
cmd->bufflen = 0;
cmd->data_direction = SCST_DATA_NONE;
fixed = 0;
}
break;
default:
/* It's all good */
break;
}
if (fixed) {
/*
* No need for locks here, since *_detach() can not be
* called, when there are existing commands.
*/
disk = (struct disk_params *)cmd->dev->dh_priv;
cmd->bufflen = info_cdb->transfer_len * disk->sector_size;
}
TRACE_DBG("res %d bufflen %zd direct %d",
res, cmd->bufflen, cmd->data_direction);
TRACE_EXIT_RES(res);
return res;
}
@@ -371,13 +319,9 @@ int disk_done(struct scst_cmd *cmd)
case READ_CAPACITY:
{
/* Always keep track of disk capacity */
int buffer_size;
/*
* To force the compiler not to optimize it out to keep
* disk->sector_size access atomic
*/
volatile int sector_size;
int buffer_size, sector_size, block_shift;
uint8_t *buffer;
buffer_size = scst_get_buf_first(cmd, &buffer);
if (unlikely(buffer_size <= 0)) {
PRINT_ERROR_PR("%s: Unable to get the buffer",
@@ -394,12 +338,14 @@ int disk_done(struct scst_cmd *cmd)
sector_size =
((buffer[4] << 24) | (buffer[5] << 16) |
(buffer[6] << 8) | (buffer[7] << 0));
if (!sector_size)
sector_size = 512;
disk->sector_size = sector_size;
TRACE_DBG("Sector size is %i", disk->sector_size);
scst_put_buf(cmd, buffer);
block_shift = scst_calc_block_shift(sector_size);
/*
* To force the compiler not to optimize it out to keep
* disk->block_shift access atomic
*/
barrier();
disk->block_shift = block_shift;
break;
}
default:
+30 -88
View File
@@ -56,23 +56,20 @@
exec: modisk_exec, \
}
#define MODISK_RETRIES 2
#define MODISK_SMALL_TIMEOUT (3 * HZ)
#define MODISK_REG_TIMEOUT (900 * HZ)
#define MODISK_LONG_TIMEOUT (14000 * HZ)
#define READ_CAP_LEN 8
#define MODISK_SECTOR_SIZE 1024
/* Flags */
#define BYTCHK 0x02
#define MODISK_BLOCK_SHIFT 10
#define MODISK_SECTOR_SIZE (1 << MODISK_BLOCK_SHIFT)
struct modisk_params
{
int sector_size;
int block_shift;
};
int modisk_attach(struct scst_device *);
void modisk_detach(struct scst_device *);
int modisk_parse(struct scst_cmd *, const struct scst_info_cdb *);
int modisk_parse(struct scst_cmd *, struct scst_info_cdb *);
int modisk_done(struct scst_cmd *);
int modisk_exec(struct scst_cmd *);
@@ -171,7 +168,7 @@ int modisk_attach(struct scst_device *dev)
res = -ENOMEM;
goto out;
}
modisk->sector_size = MODISK_SECTOR_SIZE;
modisk->block_shift = MODISK_BLOCK_SHIFT;
/*
* If the device is offline, don't try to read capacity or any
@@ -205,7 +202,7 @@ int modisk_attach(struct scst_device *dev)
TRACE_DBG("%s", "Doing READ_CAPACITY");
res = scsi_execute(dev->scsi_dev, cmd, data_dir, buffer,
buffer_size, sbuff,
MODISK_REG_TIMEOUT, MODISK_RETRIES, 0);
MODISK_REG_TIMEOUT, 3, 0);
TRACE_DBG("READ_CAPACITY done: %x", res);
@@ -220,13 +217,13 @@ int modisk_attach(struct scst_device *dev)
}
}
if (res == 0) {
modisk->sector_size = ((buffer[4] << 24) | (buffer[5] << 16) |
int sector_size = ((buffer[4] << 24) | (buffer[5] << 16) |
(buffer[6] << 8) | (buffer[7] << 0));
if (sector_size == 0)
sector_size = MODISK_SECTOR_SIZE;
modisk->block_shift = scst_calc_block_shift(sector_size);
TRACE_DBG("Sector size is %i scsi_level %d(SCSI_2 %d)",
modisk->sector_size, dev->scsi_dev->scsi_level, SCSI_2);
if (!modisk->sector_size) {
modisk->sector_size = MODISK_SECTOR_SIZE;
}
sector_size, dev->scsi_dev->scsi_level, SCSI_2);
} else {
TRACE_BUFFER("Sense set", sbuff, SCSI_SENSE_BUFFERSIZE);
@@ -282,19 +279,20 @@ void modisk_detach(struct scst_device *dev)
*
* Note: Not all states are allowed on return
********************************************************************/
int modisk_parse(struct scst_cmd *cmd, const struct scst_info_cdb *info_cdb)
int modisk_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
{
int res = SCST_CMD_STATE_DEFAULT;
struct modisk_params *modisk;
int fixed;
struct modisk_params *modisk = (struct modisk_params*)cmd->dev->dh_priv;
TRACE_ENTRY();
/*
* SCST sets good defaults for cmd->data_direction and cmd->bufflen
* based on info_cdb, therefore change them only if necessary
/*
* No need for locks here, since *_detach() can not be
* called, when there are existing commands.
*/
scst_modisk_generic_parse(cmd, info_cdb, modisk->block_shift);
cmd->retries = 1;
if (info_cdb->flags & SCST_SMALL_TIMEOUT) {
cmd->timeout = MODISK_SMALL_TIMEOUT;
} else if (info_cdb->flags & SCST_LONG_TIMEOUT) {
@@ -302,62 +300,6 @@ int modisk_parse(struct scst_cmd *cmd, const struct scst_info_cdb *info_cdb)
} else {
cmd->timeout = MODISK_REG_TIMEOUT;
}
TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d lun %d(%d)",
info_cdb->op_name,
info_cdb->direction,
info_cdb->flags,
info_cdb->transfer_len, cmd->lun, (cmd->cdb[1] >> 5) & 7);
cmd->cdb[1] &= 0x1f;
fixed = info_cdb->flags & SCST_TRANSFER_LEN_TYPE_FIXED;
switch (cmd->cdb[0]) {
case READ_CAPACITY:
cmd->bufflen = READ_CAP_LEN;
cmd->data_direction = SCST_DATA_READ;
break;
case 0xB6 /* SET_STREAMING */ :
cmd->bufflen = (((*(cmd->cdb + 9)) & 0xff) << 8) +
((*(cmd->cdb + 10)) & 0xff);
cmd->bufflen &= 0xffff;
break;
case 0xBE /* READ_CD */ :
cmd->bufflen = cmd->bufflen >> 8;
break;
#if 0
case SYNCHRONIZE_CACHE:
cmd->underflow = 0;
break;
#endif
case VERIFY_6:
case VERIFY:
case VERIFY_12:
case VERIFY_16:
if ((cmd->cdb[1] & BYTCHK) == 0) {
cmd->bufflen = 0;
cmd->data_direction = SCST_DATA_NONE;
fixed = 0;
}
break;
default:
/* It's all good */
break;
}
if (fixed) {
/*
* No need for locks here, since *_detach() can not be
* called, when there are existing commands.
*/
modisk = (struct modisk_params *)cmd->dev->dh_priv;
cmd->bufflen = info_cdb->transfer_len * modisk->sector_size;
}
TRACE_DBG("res %d bufflen %zd direct %d",
res, cmd->bufflen, cmd->data_direction);
TRACE_EXIT_RES(res);
return res;
}
@@ -395,13 +337,9 @@ int modisk_done(struct scst_cmd *cmd)
case READ_CAPACITY:
{
/* Always keep track of modisk capacity */
int buffer_size;
/*
* To force the compiler not to optimize it out to keep
* modisk->sector_size access atomic
*/
volatile int sector_size;
int buffer_size, sector_size, block_shift;
uint8_t *buffer;
buffer_size = scst_get_buf_first(cmd, &buffer);
if (unlikely(buffer_size <= 0)) {
PRINT_ERROR_PR("%s: Unable to get the buffer",
@@ -418,12 +356,16 @@ int modisk_done(struct scst_cmd *cmd)
sector_size =
((buffer[4] << 24) | (buffer[5] << 16) |
(buffer[6] << 8) | (buffer[7] << 0));
scst_put_buf(cmd, buffer);
if (!sector_size)
sector_size = MODISK_SECTOR_SIZE;
modisk->sector_size = sector_size;
TRACE_DBG("Sector size is %i", modisk->sector_size);
scst_put_buf(cmd, buffer);
block_shift = scst_calc_block_shift(sector_size);
/*
* To force the compiler not to optimize it out to keep
* cdrom->block_shift access atomic
*/
barrier();
modisk->block_shift = block_shift;
break;
}
default:
+3 -24
View File
@@ -42,7 +42,7 @@
int processor_attach(struct scst_device *);
void processor_detach(struct scst_device *);
int processor_parse(struct scst_cmd *, const struct scst_info_cdb *);
int processor_parse(struct scst_cmd *, struct scst_info_cdb *);
int processor_done(struct scst_cmd *);
static struct scst_dev_type processor_devtype = PROCESSOR_TYPE;
@@ -124,16 +124,11 @@ void processor_detach(struct scst_device *dev)
*
* Note: Not all states are allowed on return
********************************************************************/
int processor_parse(struct scst_cmd *cmd, const struct scst_info_cdb *info_cdb)
int processor_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
{
int res = SCST_CMD_STATE_DEFAULT;
TRACE_ENTRY();
/*
* SCST sets good defaults for cmd->data_direction and cmd->bufflen
* based on info_cdb, therefore change them only if necessary
*/
scst_processor_generic_parse(cmd, info_cdb);
cmd->retries = 1;
@@ -142,22 +137,6 @@ int processor_parse(struct scst_cmd *cmd, const struct scst_info_cdb *info_cdb)
} else {
cmd->timeout = PROCESSOR_TIMEOUT;
}
TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d",
info_cdb->op_name,
info_cdb->direction, info_cdb->flags, info_cdb->transfer_len);
#if 0
switch (cmd->cdb[0]) {
default:
/* It's all good */
break;
}
#endif
TRACE_DBG("res %d bufflen %zd direct %d",
res, cmd->bufflen, cmd->data_direction);
TRACE_EXIT();
return res;
}
+3 -24
View File
@@ -42,7 +42,7 @@
int raid_attach(struct scst_device *);
void raid_detach(struct scst_device *);
int raid_parse(struct scst_cmd *, const struct scst_info_cdb *);
int raid_parse(struct scst_cmd *, struct scst_info_cdb *);
int raid_done(struct scst_cmd *);
static struct scst_dev_type raid_devtype = RAID_TYPE;
@@ -124,16 +124,11 @@ void raid_detach(struct scst_device *dev)
*
* Note: Not all states are allowed on return
********************************************************************/
int raid_parse(struct scst_cmd *cmd, const struct scst_info_cdb *info_cdb)
int raid_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
{
int res = SCST_CMD_STATE_DEFAULT;
TRACE_ENTRY();
/*
* SCST sets good defaults for cmd->data_direction and cmd->bufflen
* based on info_cdb, therefore change them only if necessary
*/
scst_raid_generic_parse(cmd, info_cdb);
cmd->retries = 1;
@@ -142,22 +137,6 @@ int raid_parse(struct scst_cmd *cmd, const struct scst_info_cdb *info_cdb)
} else {
cmd->timeout = RAID_TIMEOUT;
}
TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d",
info_cdb->op_name,
info_cdb->direction, info_cdb->flags, info_cdb->transfer_len);
#if 0
switch (cmd->cdb[0]) {
default:
/* It's all good */
break;
}
#endif
TRACE_DBG("res %d bufflen %zd direct %d",
res, cmd->bufflen, cmd->data_direction);
TRACE_EXIT();
return res;
}
+8 -46
View File
@@ -65,14 +65,6 @@
/* The fixed bit in READ/WRITE/VERIFY */
#define SILI_BIT 2
/* Bits in the READ POSITION command */
#define TCLP_BIT 4
#define LONG_BIT 2
#define BT_BIT 1
#define POSITION_LEN_SHORT 20
#define POSITION_LEN_LONG 32
struct tape_params
{
spinlock_t tp_lock;
@@ -85,7 +77,7 @@ struct tape_params
int tape_attach(struct scst_device *);
void tape_detach(struct scst_device *);
int tape_parse(struct scst_cmd *, const struct scst_info_cdb *);
int tape_parse(struct scst_cmd *, struct scst_info_cdb *);
int tape_done(struct scst_cmd *);
int tape_exec(struct scst_cmd *);
@@ -280,18 +272,18 @@ void tape_detach(struct scst_device *dev)
*
* Note: Not all states are allowed on return
********************************************************************/
int tape_parse(struct scst_cmd *cmd, const struct scst_info_cdb *info_cdb)
int tape_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
{
int res = SCST_CMD_STATE_DEFAULT;
struct tape_params *tape;
struct tape_params *tape = (struct tape_params*)cmd->dev->dh_priv;
TRACE_ENTRY();
/*
* SCST sets good defaults for cmd->data_direction and cmd->bufflen
* based on info_cdb, therefore change them only if necessary
/*
* No need for locks here, since *_detach() can not be called,
* when there are existing commands.
*/
scst_tape_generic_parse(cmd, info_cdb, tape->block_size);
cmd->retries = 1;
if (info_cdb->flags & SCST_SMALL_TIMEOUT) {
@@ -301,36 +293,6 @@ int tape_parse(struct scst_cmd *cmd, const struct scst_info_cdb *info_cdb)
} else {
cmd->timeout = TAPE_REG_TIMEOUT;
}
TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d",
info_cdb->op_name,
info_cdb->direction, info_cdb->flags, info_cdb->transfer_len);
if (cmd->cdb[0] == READ_POSITION) {
int tclp = cmd->cdb[1] & TCLP_BIT;
int long_bit = cmd->cdb[1] & LONG_BIT;
int bt = cmd->cdb[1] & BT_BIT;
if ((tclp == long_bit) && (!bt || !long_bit)) {
cmd->bufflen =
tclp ? POSITION_LEN_LONG : POSITION_LEN_SHORT;
cmd->data_direction = SCST_DATA_READ;
} else {
cmd->bufflen = 0;
cmd->data_direction = SCST_DATA_NONE;
}
}
if (info_cdb->flags & SCST_TRANSFER_LEN_TYPE_FIXED & cmd->cdb[1]) {
/*
* No need for locks here, since *_detach() can not be called,
* when there are existing commands.
*/
tape = (struct tape_params *)cmd->dev->dh_priv;
cmd->bufflen = info_cdb->transfer_len * tape->block_size;
}
TRACE_EXIT_RES(res);
return res;
}
+8 -115
View File
@@ -65,13 +65,8 @@ static struct scst_proc_log vdisk_proc_local_trace_tbl[] =
/* 4 byte ASCII Product Revision Level - left aligned */
#define SCST_FIO_REV " 096"
#define READ_CAP_LEN 8
#define READ_CAP16_LEN 12
#define MAX_USN_LEN 20
#define BYTCHK 0x02
#define INQ_BUF_SZ 128
#define EVPD 0x01
#define CMDDT 0x02
@@ -145,9 +140,9 @@ static int vdisk_attach(struct scst_device *dev);
static void vdisk_detach(struct scst_device *dev);
static int vdisk_attach_tgt(struct scst_tgt_dev *tgt_dev);
static void vdisk_detach_tgt(struct scst_tgt_dev *tgt_dev);
static int vdisk_parse(struct scst_cmd *, const struct scst_info_cdb *info_cdb);
static int vdisk_parse(struct scst_cmd *, struct scst_info_cdb *info_cdb);
static int vdisk_do_job(struct scst_cmd *cmd);
static int vcdrom_parse(struct scst_cmd *, const struct scst_info_cdb *info_cdb);
static int vcdrom_parse(struct scst_cmd *, struct scst_info_cdb *info_cdb);
static int vcdrom_exec(struct scst_cmd *cmd);
static void vdisk_exec_read(struct scst_cmd *cmd,
struct scst_vdisk_thr *thr, loff_t loff);
@@ -835,67 +830,13 @@ out:
* Note: Not all states are allowed on return
********************************************************************/
static int vdisk_parse(struct scst_cmd *cmd,
const struct scst_info_cdb *info_cdb)
struct scst_info_cdb *info_cdb)
{
int res = SCST_CMD_STATE_DEFAULT;
int fixed;
struct scst_vdisk_dev *virt_dev =
(struct scst_vdisk_dev *)cmd->dev->dh_priv;
TRACE_ENTRY();
/*
* SCST sets good defaults for cmd->data_direction and cmd->bufflen
* based on info_cdb, therefore change them only if necessary
*/
TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d",
info_cdb->op_name,
info_cdb->direction, info_cdb->flags, info_cdb->transfer_len);
fixed = info_cdb->flags & SCST_TRANSFER_LEN_TYPE_FIXED;
switch (cmd->cdb[0]) {
case READ_CAPACITY:
cmd->bufflen = READ_CAP_LEN;
cmd->data_direction = SCST_DATA_READ;
break;
case SERVICE_ACTION_IN:
if ((cmd->cdb[1] & 0x1f) == SAI_READ_CAPACITY_16) {
cmd->bufflen = READ_CAP16_LEN;
cmd->data_direction = SCST_DATA_READ;
}
break;
case VERIFY_6:
case VERIFY:
case VERIFY_12:
case VERIFY_16:
if ((cmd->cdb[1] & BYTCHK) == 0) {
cmd->data_len =
info_cdb->transfer_len << virt_dev->block_shift;
cmd->bufflen = 0;
cmd->data_direction = SCST_DATA_NONE;
fixed = 0;
} else
cmd->data_len = 0;
break;
default:
/* It's all good */
break;
}
if (fixed) {
/*
* No need for locks here, since *_detach() can not be
* called, when there are existing commands.
*/
cmd->bufflen = info_cdb->transfer_len << virt_dev->block_shift;
}
TRACE_DBG("res %d, bufflen %zd, data_len %zd, direct %d",
res, cmd->bufflen, cmd->data_len, cmd->data_direction);
TRACE_EXIT();
return res;
scst_sbc_generic_parse(cmd, info_cdb, virt_dev->block_shift);
return SCST_CMD_STATE_DEFAULT;
}
/********************************************************************
@@ -910,61 +851,13 @@ static int vdisk_parse(struct scst_cmd *cmd,
* Note: Not all states are allowed on return
********************************************************************/
static int vcdrom_parse(struct scst_cmd *cmd,
const struct scst_info_cdb *info_cdb)
struct scst_info_cdb *info_cdb)
{
int res = SCST_CMD_STATE_DEFAULT;
int fixed;
struct scst_vdisk_dev *virt_dev =
(struct scst_vdisk_dev *)cmd->dev->dh_priv;
TRACE_ENTRY();
/*
* SCST sets good defaults for cmd->data_direction and cmd->bufflen
* based on info_cdb, therefore change them only if necessary
*/
TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d",
info_cdb->op_name,
info_cdb->direction, info_cdb->flags, info_cdb->transfer_len);
fixed = info_cdb->flags & SCST_TRANSFER_LEN_TYPE_FIXED;
switch (cmd->cdb[0]) {
case READ_CAPACITY:
cmd->bufflen = READ_CAP_LEN;
cmd->data_direction = SCST_DATA_READ;
break;
case VERIFY_6:
case VERIFY:
case VERIFY_12:
case VERIFY_16:
if ((cmd->cdb[1] & BYTCHK) == 0) {
cmd->data_len =
info_cdb->transfer_len << virt_dev->block_shift;
cmd->bufflen = 0;
cmd->data_direction = SCST_DATA_NONE;
fixed = 0;
} else
cmd->data_len = 0;
break;
default:
/* It's all good */
break;
}
if (fixed) {
/*
* No need for locks here, since *_detach() can not be
* called, when there are existing commands.
*/
cmd->bufflen = info_cdb->transfer_len << virt_dev->block_shift;
}
TRACE_DBG("res %d, bufflen %zd, data_len %zd, direct %d",
res, cmd->bufflen, cmd->data_len, cmd->data_direction);
TRACE_EXIT_HRES(res);
return res;
scst_cdrom_generic_parse(cmd, info_cdb, virt_dev->block_shift);
return SCST_CMD_STATE_DEFAULT;
}
/********************************************************************
+8
View File
@@ -1476,6 +1476,14 @@ EXPORT_SYMBOL(scst_del_all_thr_data);
EXPORT_SYMBOL(scst_dev_del_all_thr_data);
EXPORT_SYMBOL(scst_find_thr_data);
/* Generic parse() routines */
EXPORT_SYMBOL(scst_calc_block_shift);
EXPORT_SYMBOL(scst_sbc_generic_parse);
EXPORT_SYMBOL(scst_cdrom_generic_parse);
EXPORT_SYMBOL(scst_modisk_generic_parse);
EXPORT_SYMBOL(scst_tape_generic_parse);
EXPORT_SYMBOL(scst_null_parse);
/*
* Other Commands
*/
+270
View File
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/cdrom.h>
#include <asm/unistd.h>
#include <asm/string.h>
@@ -1829,6 +1830,275 @@ out_err:
goto out;
}
int scst_calc_block_shift(int sector_size)
{
int block_shift = 0;
int t = sector_size;
if (sector_size == 0)
sector_size = 512;
while(1) {
if ((t & 1) != 0)
break;
t >>= 1;
block_shift++;
}
if (block_shift < 9) {
PRINT_ERROR_PR("Wrong sector size %d", sector_size);
block_shift = -1;
}
TRACE_EXIT_RES(block_shift);
return block_shift;
}
int scst_sbc_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb, int block_shift)
{
int res = 0;
TRACE_ENTRY();
/*
* SCST sets good defaults for cmd->data_direction and cmd->bufflen
* based on info_cdb, therefore change them only if necessary
*/
TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d",
info_cdb->op_name,
info_cdb->direction, info_cdb->flags, info_cdb->transfer_len);
switch (cmd->cdb[0]) {
case READ_CAPACITY:
cmd->bufflen = READ_CAP_LEN;
cmd->data_direction = SCST_DATA_READ;
break;
case SERVICE_ACTION_IN:
if ((cmd->cdb[1] & 0x1f) == SAI_READ_CAPACITY_16) {
cmd->bufflen = READ_CAP16_LEN;
cmd->data_direction = SCST_DATA_READ;
}
break;
case VERIFY_6:
case VERIFY:
case VERIFY_12:
case VERIFY_16:
if ((cmd->cdb[1] & BYTCHK) == 0) {
cmd->data_len =
info_cdb->transfer_len << block_shift;
cmd->bufflen = 0;
cmd->data_direction = SCST_DATA_NONE;
info_cdb->flags &= ~SCST_TRANSFER_LEN_TYPE_FIXED;
} else
cmd->data_len = 0;
break;
default:
/* It's all good */
break;
}
if (info_cdb->flags & SCST_TRANSFER_LEN_TYPE_FIXED) {
/*
* No need for locks here, since *_detach() can not be
* called, when there are existing commands.
*/
cmd->bufflen = info_cdb->transfer_len << block_shift;
}
TRACE_DBG("res %d, bufflen %zd, data_len %zd, direct %d",
res, cmd->bufflen, cmd->data_len, cmd->data_direction);
TRACE_EXIT_RES(res);
return res;
}
int scst_cdrom_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb, int block_shift)
{
int res = 0;
TRACE_ENTRY();
/*
* SCST sets good defaults for cmd->data_direction and cmd->bufflen
* based on info_cdb, therefore change them only if necessary
*/
TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d lun %d(%d)",
info_cdb->op_name,
info_cdb->direction,
info_cdb->flags,
info_cdb->transfer_len, cmd->lun, (cmd->cdb[1] >> 5) & 7);
cmd->cdb[1] &= 0x1f;
switch (cmd->cdb[0]) {
case READ_CAPACITY:
cmd->bufflen = READ_CAP_LEN;
cmd->data_direction = SCST_DATA_READ;
break;
case GPCMD_SET_STREAMING:
cmd->bufflen = (((*(cmd->cdb + 9)) & 0xff) << 8) +
((*(cmd->cdb + 10)) & 0xff);
cmd->bufflen &= 0xffff;
break;
case GPCMD_READ_CD:
cmd->bufflen = cmd->bufflen >> 8;
break;
case VERIFY_6:
case VERIFY:
case VERIFY_12:
case VERIFY_16:
if ((cmd->cdb[1] & BYTCHK) == 0) {
cmd->data_len =
info_cdb->transfer_len << block_shift;
cmd->bufflen = 0;
cmd->data_direction = SCST_DATA_NONE;
info_cdb->flags &= ~SCST_TRANSFER_LEN_TYPE_FIXED;
}
break;
default:
/* It's all good */
break;
}
if (info_cdb->flags & SCST_TRANSFER_LEN_TYPE_FIXED)
cmd->bufflen = info_cdb->transfer_len << block_shift;
TRACE_DBG("res %d bufflen %zd direct %d",
res, cmd->bufflen, cmd->data_direction);
TRACE_EXIT();
return res;
}
int scst_modisk_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb, int block_shift)
{
int res = 0;
TRACE_ENTRY();
/*
* SCST sets good defaults for cmd->data_direction and cmd->bufflen
* based on info_cdb, therefore change them only if necessary
*/
TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d lun %d(%d)",
info_cdb->op_name,
info_cdb->direction,
info_cdb->flags,
info_cdb->transfer_len, cmd->lun, (cmd->cdb[1] >> 5) & 7);
cmd->cdb[1] &= 0x1f;
switch (cmd->cdb[0]) {
case READ_CAPACITY:
cmd->bufflen = READ_CAP_LEN;
cmd->data_direction = SCST_DATA_READ;
break;
case 0xB6 /* SET_STREAMING */ :
cmd->bufflen = (((*(cmd->cdb + 9)) & 0xff) << 8) +
((*(cmd->cdb + 10)) & 0xff);
cmd->bufflen &= 0xffff;
break;
case 0xBE /* READ_CD */ :
cmd->bufflen = cmd->bufflen >> 8;
break;
case VERIFY_6:
case VERIFY:
case VERIFY_12:
case VERIFY_16:
if ((cmd->cdb[1] & BYTCHK) == 0) {
cmd->data_len =
info_cdb->transfer_len << block_shift;
cmd->bufflen = 0;
cmd->data_direction = SCST_DATA_NONE;
info_cdb->flags &= ~SCST_TRANSFER_LEN_TYPE_FIXED;
}
break;
default:
/* It's all good */
break;
}
if (info_cdb->flags & SCST_TRANSFER_LEN_TYPE_FIXED)
cmd->bufflen = info_cdb->transfer_len << block_shift;;
TRACE_DBG("res %d bufflen %zd direct %d",
res, cmd->bufflen, cmd->data_direction);
TRACE_EXIT_RES(res);
return res;
}
int scst_tape_generic_parse(struct scst_cmd *cmd,
struct scst_info_cdb *info_cdb, int block_size)
{
int res = 0;
TRACE_ENTRY();
/*
* SCST sets good defaults for cmd->data_direction and cmd->bufflen
* based on info_cdb, therefore change them only if necessary
*/
TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d",
info_cdb->op_name,
info_cdb->direction, info_cdb->flags, info_cdb->transfer_len);
if (cmd->cdb[0] == READ_POSITION) {
int tclp = cmd->cdb[1] & TCLP_BIT;
int long_bit = cmd->cdb[1] & LONG_BIT;
int bt = cmd->cdb[1] & BT_BIT;
if ((tclp == long_bit) && (!bt || !long_bit)) {
cmd->bufflen =
tclp ? POSITION_LEN_LONG : POSITION_LEN_SHORT;
cmd->data_direction = SCST_DATA_READ;
} else {
cmd->bufflen = 0;
cmd->data_direction = SCST_DATA_NONE;
}
}
if (info_cdb->flags & SCST_TRANSFER_LEN_TYPE_FIXED & cmd->cdb[1])
cmd->bufflen = info_cdb->transfer_len * block_size;
TRACE_EXIT_RES(res);
return res;
}
int scst_null_parse(struct scst_cmd *cmd, struct scst_info_cdb *info_cdb)
{
int res = 0;
TRACE_ENTRY();
/*
* SCST sets good defaults for cmd->data_direction and cmd->bufflen
* based on info_cdb, therefore change them only if necessary
*/
TRACE_DBG("op_name <%s> direct %d flags %d transfer_len %d",
info_cdb->op_name,
info_cdb->direction, info_cdb->flags, info_cdb->transfer_len);
#if 0
switch (cmd->cdb[0]) {
default:
/* It's all good */
break;
}
#endif
TRACE_DBG("res %d bufflen %zd direct %d",
res, cmd->bufflen, cmd->data_direction);
TRACE_EXIT();
return res;
}
/* Called under dev_lock and BH off */
void scst_process_reset(struct scst_device *dev,
struct scst_session *originator, struct scst_cmd *exclude_cmd,