mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-17 20:56:24 +00:00
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:
+54
-2
@@ -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 */
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user