- fixed warnings, produced by Haiku version of gcc;

- space-based indentations replaced with tab-based ones;
 - a bit of cleanup;


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18785 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
imker 2006-09-08 19:45:43 +00:00
parent 65482713f4
commit 57c4d430a5
2 changed files with 407 additions and 396 deletions

View File

@ -1,359 +1,364 @@
/*
* Copyright (c) 2003-2005 by Siarzhuk Zharski <imker@gmx.li>
* Distributed under the terms of the BSD License.
/**
*
* TODO: description
*
* This file is a part of USB SCSI CAM for Haiku OS.
* May be used under terms of the MIT License
*
* Author(s):
* Siarzhuk Zharski <imker@gmx.li>
*
*
*/
/** SCSI commands transformations support */
#include "usb_scsi.h"
#include "usb_scsi.h"
#include "device_info.h"
#include "transform_procs.h"
#include "tracing.h"
#include "transform_procs.h"
#include "tracing.h"
#include "scsi_commands.h"
//#include "proto_common.h"
#include "settings.h"
#include "settings.h"
#include "strings.h"
#define UFI_COMMAND_LEN 12
#define ATAPI_COMMAND_LEN 12
#define UFI_COMMAND_LEN 12
#define ATAPI_COMMAND_LEN 12
static status_t
scsi_transform(usb_device_info *udi, uint8 *cmd,
uint8 len, uint8 **rcmd, uint8 *rlen);
static status_t rbc_transform(usb_device_info *udi, uint8 *cmd,
uint8 len, uint8 **rcmd, uint8 *rlen);
static status_t ufi_transform(usb_device_info *udi, uint8 *cmd,
uint8 len, uint8 **rcmd, uint8 *rlen);
static status_t atapi_transform(usb_device_info *udi, uint8 *cmd,
uint8 len, uint8 **rcmd, uint8 *rlen);
static status_t qic157_transform(usb_device_info *udi, uint8 *cmd,
uint8 len, uint8 **rcmd, uint8 *rlen);
/**
\fn:transform_6_to_10
\param cmd: SCSI command buffer to be transformed
\param len: length of buffer, pointed by cmd parameter
\param rcmd: a place for buffer pointer with transformed command
\param rlen: a place for length of transformed command
\return: true if transformation was performed
transforms a 6-byte command to 10-byte one if required.Transformed command is
returned in rcmd parameter. In case if no transformation was performed the return
buffer is untouched.
\fn:transform_6_to_10
\param cmd: SCSI command buffer to be transformed
\param len: length of buffer, pointed by cmd parameter
\param rcmd: a place for buffer pointer with transformed command
\param rlen: a place for length of transformed command
\return: true if transformation was performed
transforms a 6-byte command to 10-byte one if required.Transformed command is
returned in rcmd parameter. In case if no transformation was performed the return
buffer is untouched.
*/
static bool transform_6_to_10(uint8 *cmd,
uint8 len,
uint8 **rcmd,
uint8 *rlen)
static bool transform_6_to_10(uint8 *cmd, uint8 len,
uint8 **rcmd, uint8 *rlen)
{
bool transformed = true;
scsi_cmd_generic_6 *from = (scsi_cmd_generic_6 *)cmd;
memset(*rcmd, 0, *rlen);
switch (from->opcode){
case READ_6:
case WRITE_6:{
scsi_cmd_rw_10 *to = (scsi_cmd_rw_10 *)(*rcmd);
to->opcode = (from->opcode == READ_6) ? READ_10 : WRITE_10;
memcpy(to->addr + 1, from->addr, 3);
to->byte2 = from->addr[0];
to->byte2 &= ~CMD_GEN_6_ADDR;
to->addr[1] &= CMD_GEN_6_ADDR;
to->len[1] = from->len;
to->ctrl = from->ctrl;
if(0 == from->len){ /* special case! in 6-byte R/W commands */
to->len[0] = 1; /* the length 0x00 assume transfering 0x100 blocks! */
}
}break;
case MODE_SENSE_6:
case MODE_SELECT_6:{
scsi_cmd_generic_10 *to = (scsi_cmd_generic_10 *)(*rcmd);
if(from->opcode == MODE_SENSE_6){
to->opcode = MODE_SENSE_10;
((scsi_cmd_mode_sense_10 *)to)->byte3 =
((scsi_cmd_mode_sense_6 *)from)->byte3;
}else
to->opcode = MODE_SELECT_10;
to->byte2 = from->addr[0];
to->len[1] = from->len + 4; /*TODO: hardcoded length*/
to->ctrl = from->ctrl;
}break;
default:{ /* no transformation needed */
transformed = false;
}break;
}
return transformed;
bool transformed = true;
scsi_cmd_generic_6 *from = (scsi_cmd_generic_6 *)cmd;
memset(*rcmd, 0, *rlen);
switch (from->opcode){
case READ_6:
case WRITE_6:{
scsi_cmd_rw_10 *to = (scsi_cmd_rw_10 *)(*rcmd);
to->opcode = (from->opcode == READ_6) ? READ_10 : WRITE_10;
memcpy(to->addr + 1, from->addr, 3);
to->byte2 = from->addr[0];
to->byte2 &= ~CMD_GEN_6_ADDR;
to->addr[1] &= CMD_GEN_6_ADDR;
to->len[1] = from->len;
to->ctrl = from->ctrl;
if(0 == from->len){ /* special case! in 6-byte R/W commands */
to->len[0] = 1; /* the length 0x00 assume transfering 0x100 blocks! */
}
}break;
case MODE_SENSE_6:
case MODE_SELECT_6:{
scsi_cmd_generic_10 *to = (scsi_cmd_generic_10 *)(*rcmd);
if(from->opcode == MODE_SENSE_6){
to->opcode = MODE_SENSE_10;
((scsi_cmd_mode_sense_10 *)to)->byte3 =
((scsi_cmd_mode_sense_6 *)from)->byte3;
}else
to->opcode = MODE_SELECT_10;
to->byte2 = from->addr[0];
to->len[1] = from->len + 4; /*TODO: hardcoded length*/
to->ctrl = from->ctrl;
}break;
default:{ /* no transformation needed */
transformed = false;
}break;
}
return transformed;
}
/**
\fn:transform_cmd_6_to_10
\param udi: usb_device_info object for wich transformation is requested
\param cmd: SCSI command buffer to be transformed
\param len: length of buffer, pointed by cmd parameter
\param rcmd: a place for buffer pointer with transformed command
\param rlen: a place for length of transformed command
\return: true if transformation was performed
transforms a 6-byte command to 10-byte depending on information provided with
udi object.
\fn:transform_cmd_6_to_10
\param udi: usb_device_info object for wich transformation is requested
\param cmd: SCSI command buffer to be transformed
\param len: length of buffer, pointed by cmd parameter
\param rcmd: a place for buffer pointer with transformed command
\param rlen: a place for length of transformed command
\return: true if transformation was performed
transforms a 6-byte command to 10-byte depending on information provided with
udi object.
*/
static bool transform_cmd_6_to_10(usb_device_info *udi,
uint8 *cmd,
uint8 len,
uint8 **rcmd,
uint8 *rlen)
static bool transform_cmd_6_to_10(usb_device_info *udi, uint8 *cmd,
uint8 len, uint8 **rcmd, uint8 *rlen)
{
bool transformed = true;
scsi_cmd_generic_6 *from = (scsi_cmd_generic_6 *)cmd;
switch (from->opcode){
case READ_6:
case WRITE_6:{
// if(!(HAS_FEATURES(udi->descr.properties, PROP_FORCE_TO_6))){
if(!HAS_FIXES(udi->properties, FIX_FORCE_RW_TO_6)){
if((transformed = transform_6_to_10(cmd, len, rcmd, rlen)) == true)
*rlen = 10;
}else
transformed = false;
}break;
case MODE_SENSE_6:
case MODE_SELECT_6:{
// if(HAS_FEATURES(udi->descr.properties, PROP_USE_MODESENSE_10)){
if(HAS_FIXES(udi->properties, FIX_FORCE_MS_TO_10)){
if((transformed = transform_6_to_10(cmd, len, rcmd, rlen)) == true)
*rlen = 10;
}else
transformed = false;
}
}
return transformed;
bool transformed = true;
scsi_cmd_generic_6 *from = (scsi_cmd_generic_6 *)cmd;
switch (from->opcode){
case READ_6:
case WRITE_6:{
// if(!(HAS_FEATURES(udi->descr.properties, PROP_FORCE_TO_6))){
if(!HAS_FIXES(udi->properties, FIX_FORCE_RW_TO_6)){
if((transformed = transform_6_to_10(cmd, len, rcmd, rlen)) == true)
*rlen = 10;
}else
transformed = false;
}break;
case MODE_SENSE_6:
case MODE_SELECT_6:{
// if(HAS_FEATURES(udi->descr.properties, PROP_USE_MODESENSE_10)){
if(HAS_FIXES(udi->properties, FIX_FORCE_MS_TO_10)){
if((transformed = transform_6_to_10(cmd, len, rcmd, rlen)) == true)
*rlen = 10;
}else
transformed = false;
}
}
return transformed;
}
/**
\fn:transform_cmd_test_unit_ready
\param udi: usb_device_info object for wich transformation is requested
\param cmd: SCSI command buffer to be transformed
\param len: length of buffer, pointed by cmd parameter
\param rcmd: a place for buffer pointer with transformed command
\param rlen: a place for length of transformed command
\return: true if transformation was performed
transforms a TEST_UNIT_COMAND SCSI command to START_STOP_UNIT one depending
on properties provided with udi object.
\fn:transform_cmd_test_unit_ready
\param udi: usb_device_info object for wich transformation is requested
\param cmd: SCSI command buffer to be transformed
\param len: length of buffer, pointed by cmd parameter
\param rcmd: a place for buffer pointer with transformed command
\param rlen: a place for length of transformed command
\return: true if transformation was performed
transforms a TEST_UNIT_COMAND SCSI command to START_STOP_UNIT one depending
on properties provided with udi object.
*/
static bool transform_cmd_test_unit_ready(usb_device_info *udi,
uint8 *cmd,
uint8 len,
uint8 **rcmd,
uint8 *rlen)
uint8 *cmd, uint8 len,
uint8 **rcmd, uint8 *rlen)
{
bool transformed = false;
if(HAS_FIXES(udi->properties, FIX_TRANS_TEST_UNIT)){
scsi_cmd_start_stop_unit *command = (scsi_cmd_start_stop_unit *)(*rcmd);
memset(*rcmd, 0, *rlen);
command->opcode = START_STOP_UNIT;
command->start_loej = CMD_SSU_START;
*rlen = 6;
transformed = true;
}
return transformed;
bool transformed = false;
if(HAS_FIXES(udi->properties, FIX_TRANS_TEST_UNIT)){
scsi_cmd_start_stop_unit *command = (scsi_cmd_start_stop_unit *)(*rcmd);
memset(*rcmd, 0, *rlen);
command->opcode = START_STOP_UNIT;
command->start_loej = CMD_SSU_START;
*rlen = 6;
transformed = true;
}
return transformed;
}
/**
\fn:scsi_transform
\param udi: usb_device_info object for wich transformation is requested
\param cmd: SCSI command buffer to be transformed
\param len: length of buffer, pointed by cmd parameter
\param rcmd: a place for buffer pointer with transformed command
\param rlen: a place for length of transformed command
\return: B_OK if transformation was successfull, B_ERROR otherwise
this is the "transformation procedure" for transparent SCSI (0x06) USB subclass.It
performs all SCSI commands transformations required by this protocol. Additionally
it tries to make some workarounds for "brocken" USB devices. If no transformation
was performed resulting command buffer points to original one.
\fn:scsi_transform
\param udi: usb_device_info object for wich transformation is requested
\param cmd: SCSI command buffer to be transformed
\param len: length of buffer, pointed by cmd parameter
\param rcmd: a place for buffer pointer with transformed command
\param rlen: a place for length of transformed command
\return: B_OK if transformation was successfull, B_ERROR otherwise
this is the "transformation procedure" for transparent SCSI (0x06) USB subclass.It
performs all SCSI commands transformations required by this protocol. Additionally
it tries to make some workarounds for "brocken" USB devices. If no transformation
was performed resulting command buffer points to original one.
*/
status_t
scsi_transform(usb_device_info *udi,
uint8 *cmd,
uint8 len,
uint8 **rcmd,
uint8 *rlen)
scsi_transform(usb_device_info *udi, uint8 *cmd,
uint8 len, uint8 **rcmd, uint8 *rlen)
{
status_t status = B_OK;
bool transformed = false;
scsi_cmd_generic *command = (scsi_cmd_generic *)cmd;
TRACE_SCSI_COMMAND(cmd, len);
switch(command->opcode){
case READ_6:
case WRITE_6:
case MODE_SENSE_6:
case MODE_SELECT_6:
transformed = transform_cmd_6_to_10(udi, cmd, len, rcmd, rlen);
break;
case TEST_UNIT_READY:
transformed = transform_cmd_test_unit_ready(udi, cmd, len, rcmd, rlen);
break;
default: break;
}
if(!transformed){ /* transformation was not required */
*rcmd = cmd;
*rlen = len;
}else
TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen);
return status;
status_t status = B_OK;
bool transformed = false;
scsi_cmd_generic *command = (scsi_cmd_generic *)cmd;
TRACE_SCSI_COMMAND(cmd, len);
switch(command->opcode){
case READ_6:
case WRITE_6:
case MODE_SENSE_6:
case MODE_SELECT_6:
transformed = transform_cmd_6_to_10(udi, cmd, len, rcmd, rlen);
break;
case TEST_UNIT_READY:
transformed = transform_cmd_test_unit_ready(udi, cmd, len, rcmd, rlen);
break;
default: break;
}
if(!transformed){ /* transformation was not required */
*rcmd = cmd;
*rlen = len;
}else
TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen);
return status;
}
/**
\fn:rbc_transform
\param udi: usb_device_info object for wich transformation is requested
\param cmd: SCSI command buffer to be transformed
\param len: length of buffer, pointed by cmd parameter
\param rcmd: a place for buffer pointer with transformed command
\param rlen: a place for length of transformed command
\return: B_OK if transformation was successfull, B_ERROR otherwise
this is the "transformation procedure" for RBC USB subclass (0x01).It
performs all SCSI commands transformations required by this protocol. Additionally
it tries to make some workarounds for "brocken" USB devices. If no transformation
was performed resulting command buffer points to original one.
\fn:rbc_transform
\param udi: usb_device_info object for wich transformation is requested
\param cmd: SCSI command buffer to be transformed
\param len: length of buffer, pointed by cmd parameter
\param rcmd: a place for buffer pointer with transformed command
\param rlen: a place for length of transformed command
\return: B_OK if transformation was successfull, B_ERROR otherwise
this is the "transformation procedure" for RBC USB subclass (0x01).It
performs all SCSI commands transformations required by this protocol. Additionally
it tries to make some workarounds for "brocken" USB devices. If no transformation
was performed resulting command buffer points to original one.
*/
status_t rbc_transform(usb_device_info *udi,
uint8 *cmd,
uint8 len,
uint8 **rcmd,
uint8 *rlen)
status_t rbc_transform(usb_device_info *udi, uint8 *cmd,
uint8 len, uint8 **rcmd, uint8 *rlen)
{
status_t status = B_OK;
bool transformed = false;
scsi_cmd_generic *command = (scsi_cmd_generic *)cmd;
TRACE_SCSI_COMMAND(cmd, len);
switch(command->opcode){
case TEST_UNIT_READY:
transformed = transform_cmd_test_unit_ready(udi, cmd, len, rcmd, rlen);
break;
case READ_6:
case WRITE_6: /* there are no such command in list of allowed - transform*/
transformed = transform_cmd_6_to_10(udi, cmd, len, rcmd, rlen);
break;
case FORMAT_UNIT: /* TODO: all following ones are not checked against specs !!!*/
case INQUIRY: /*TODO: check !!! */
case MODE_SELECT_6: /*TODO: check !!! */
case MODE_SENSE_6: /*TODO: check !!! */
case PERSISTENT_RESERVE_IN: /*TODO: check !!! */
case PERSISTENT_RESERVE_OUT: /*TODO: check !!! */
case PREVENT_ALLOW_MEDIA_REMOVAL: /*TODO: check !!! */
case READ_10: /*TODO: check !!! */
case READ_CAPACITY: /*TODO: check !!! */
case RELEASE_6: /*TODO: check !!! */
case REQUEST_SENSE: /*TODO: check !!! */
case RESERVE_6: /*TODO: check !!! */
case START_STOP_UNIT: /*TODO: check !!! */
case SYNCHRONIZE_CACHE: /*TODO: check !!! */
case VERIFY: /*TODO: check !!! */
case WRITE_10: /*TODO: check !!! */
case WRITE_BUFFER:/*TODO Check correctnes of such translation!*/
*rcmd = cmd; /* No need to copy */
*rlen = len; /*TODO: check !!! */
default:
TRACE_ALWAYS("An unsupported RBC command: %08x\n", command->opcode);
status = B_ERROR;
break;
}
if(transformed)
TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen);
return status;
status_t status = B_OK;
bool transformed = false;
scsi_cmd_generic *command = (scsi_cmd_generic *)cmd;
TRACE_SCSI_COMMAND(cmd, len);
switch(command->opcode){
case TEST_UNIT_READY:
transformed = transform_cmd_test_unit_ready(udi, cmd, len, rcmd, rlen);
break;
case READ_6:
case WRITE_6: /* there are no such command in list of allowed - transform*/
transformed = transform_cmd_6_to_10(udi, cmd, len, rcmd, rlen);
break;
case FORMAT_UNIT: /* TODO: all following ones are not checked against specs !!!*/
case INQUIRY: /*TODO: check !!! */
case MODE_SELECT_6: /*TODO: check !!! */
case MODE_SENSE_6: /*TODO: check !!! */
case PERSISTENT_RESERVE_IN: /*TODO: check !!! */
case PERSISTENT_RESERVE_OUT: /*TODO: check !!! */
case PREVENT_ALLOW_MEDIA_REMOVAL: /*TODO: check !!! */
case READ_10: /*TODO: check !!! */
case READ_CAPACITY: /*TODO: check !!! */
case RELEASE_6: /*TODO: check !!! */
case REQUEST_SENSE: /*TODO: check !!! */
case RESERVE_6: /*TODO: check !!! */
case START_STOP_UNIT: /*TODO: check !!! */
case SYNCHRONIZE_CACHE: /*TODO: check !!! */
case VERIFY: /*TODO: check !!! */
case WRITE_10: /*TODO: check !!! */
case WRITE_BUFFER:/*TODO Check correctnes of such translation!*/
*rcmd = cmd; /* No need to copy */
*rlen = len; /*TODO: check !!! */
default:
TRACE_ALWAYS("An unsupported RBC command: %08x\n", command->opcode);
status = B_ERROR;
break;
}
if(transformed)
TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen);
return status;
}
/**
\fn:ufi_transform
\param udi: usb_device_info object for wich transformation is requested
\param cmd: SCSI command buffer to be transformed
\param len: length of buffer, pointed by cmd parameter
\param rcmd: a place for buffer pointer with transformed command
\param rlen: a place for length of transformed command
\return: B_OK if transformation was successfull, B_ERROR otherwise
this is the "transformation procedure" for UFI USB subclass (0x04).It
performs all SCSI commands transformations required by this protocol. Additionally
it tries to make some workarounds for "brocken" USB devices. If no transformation
was performed resulting command buffer points to original one.
\fn:ufi_transform
\param udi: usb_device_info object for wich transformation is requested
\param cmd: SCSI command buffer to be transformed
\param len: length of buffer, pointed by cmd parameter
\param rcmd: a place for buffer pointer with transformed command
\param rlen: a place for length of transformed command
\return: B_OK if transformation was successfull, B_ERROR otherwise
this is the "transformation procedure" for UFI USB subclass (0x04).It
performs all SCSI commands transformations required by this protocol. Additionally
it tries to make some workarounds for "brocken" USB devices. If no transformation
was performed resulting command buffer points to original one.
*/
status_t ufi_transform(usb_device_info *udi,
uint8 *cmd,
uint8 len,
uint8 **rcmd,
uint8 *rlen)
uint8 *cmd,
uint8 len,
uint8 **rcmd,
uint8 *rlen)
{
status_t status = B_OK;
TRACE_SCSI_COMMAND(cmd, len);
memset(*rcmd, 0, UFI_COMMAND_LEN);
if(!transform_6_to_10(cmd, len, rcmd, rlen)){ /* was not transformed ?*/
scsi_cmd_generic *command = (scsi_cmd_generic *)cmd;
switch(command->opcode){
case TEST_UNIT_READY:
if(transform_cmd_test_unit_ready(udi, cmd, len, rcmd, rlen)){
break; /* if TEST UNIT READY was transformed*/
}
case FORMAT_UNIT: /* TODO: mismatch */
case INQUIRY:
case START_STOP_UNIT:
case MODE_SELECT_10:
case MODE_SENSE_10:
case PREVENT_ALLOW_MEDIA_REMOVAL:
case READ_10:
case READ_12:
case READ_CAPACITY:
case READ_FORMAT_CAPACITY: /* TODO: not in the SCSI-2 specs */
case REQUEST_SENSE:
case REZERO_UNIT:
case SEEK_10:
case SEND_DIAGNOSTICS: /* TODO: parameter list len mismatch */
case VERIFY:
case WRITE_10:
case WRITE_12: /* TODO: EBP. mismatch */
case WRITE_AND_VERIFY:
memcpy(*rcmd, cmd, len); /*TODO what about control? ignored in UFI?*/
break;
default:
TRACE_ALWAYS("An unsupported UFI command: %08x\n", command->opcode);
status = B_ERROR;
break;
}
}
*rlen = UFI_COMMAND_LEN; /* override any value set in transform funcs !!!*/
if(status == B_OK)
TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen);
return status;
status_t status = B_OK;
TRACE_SCSI_COMMAND(cmd, len);
memset(*rcmd, 0, UFI_COMMAND_LEN);
if(!transform_6_to_10(cmd, len, rcmd, rlen)){ /* was not transformed ?*/
scsi_cmd_generic *command = (scsi_cmd_generic *)cmd;
switch(command->opcode){
case TEST_UNIT_READY:
if(transform_cmd_test_unit_ready(udi, cmd, len, rcmd, rlen)){
break; /* if TEST UNIT READY was transformed*/
}
case FORMAT_UNIT: /* TODO: mismatch */
case INQUIRY:
case START_STOP_UNIT:
case MODE_SELECT_10:
case MODE_SENSE_10:
case PREVENT_ALLOW_MEDIA_REMOVAL:
case READ_10:
case READ_12:
case READ_CAPACITY:
case READ_FORMAT_CAPACITY: /* TODO: not in the SCSI-2 specs */
case REQUEST_SENSE:
case REZERO_UNIT:
case SEEK_10:
case SEND_DIAGNOSTICS: /* TODO: parameter list len mismatch */
case VERIFY:
case WRITE_10:
case WRITE_12: /* TODO: EBP. mismatch */
case WRITE_AND_VERIFY:
memcpy(*rcmd, cmd, len); /*TODO what about control? ignored in UFI?*/
break;
default:
TRACE_ALWAYS("An unsupported UFI command: %08x\n", command->opcode);
status = B_ERROR;
break;
}
}
*rlen = UFI_COMMAND_LEN; /* override any value set in transform funcs !!!*/
if(status == B_OK)
TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen);
return status;
}
/**
\fn:atapi_transform
\param udi: usb_device_info object for wich transformation is requested
\param cmd: SCSI command buffer to be transformed
\param len: length of buffer, pointed by cmd parameter
\param rcmd: a place for buffer pointer with transformed command
\param rlen: a place for length of transformed command
\return: B_OK if transformation was successfull, B_ERROR otherwise
this is the "transformation procedure" for SFF8020I and SFF8070I
USB subclassses (0x02 and 0x05). It performs all SCSI commands transformations
required by this protocol. Additionally it tries to make some workarounds for
"broken" USB devices. If no transformation was performed resulting command
buffer points to original one.
\fn:atapi_transform
\param udi: usb_device_info object for wich transformation is requested
\param cmd: SCSI command buffer to be transformed
\param len: length of buffer, pointed by cmd parameter
\param rcmd: a place for buffer pointer with transformed command
\param rlen: a place for length of transformed command
\return: B_OK if transformation was successfull, B_ERROR otherwise
this is the "transformation procedure" for SFF8020I and SFF8070I
USB subclassses (0x02 and 0x05). It performs all SCSI commands transformations
required by this protocol. Additionally it tries to make some workarounds for
"broken" USB devices. If no transformation was performed resulting command
buffer points to original one.
*/
status_t atapi_transform(usb_device_info *udi,
uint8 *cmd,
uint8 len,
uint8 **rcmd,
uint8 *rlen)
uint8 *cmd,
uint8 len,
uint8 **rcmd,
uint8 *rlen)
{
status_t status = B_OK;
TRACE_SCSI_COMMAND(cmd, len);
memset(*rcmd, 0, ATAPI_COMMAND_LEN);
if(!transform_6_to_10(cmd, len, rcmd, rlen)){ /* was not transformed ?*/
scsi_cmd_generic *command = (scsi_cmd_generic *)cmd;
switch(command->opcode){
case TEST_UNIT_READY:
if(transform_cmd_test_unit_ready(udi, cmd, len, rcmd, rlen)){
break; /* if TEST UNIT READY was transformed*/
}
case FORMAT_UNIT:
case INQUIRY:
case MODE_SELECT_10:
case MODE_SENSE_10:
case PREVENT_ALLOW_MEDIA_REMOVAL:
case READ_10:
case READ_12: /* mismatch in byte 1 */
case READ_CAPACITY: /* mismatch. no transf len defined... */
case READ_FORMAT_CAPACITY: /* TODO: check!!! */
case REQUEST_SENSE:
case SEEK_10:
case START_STOP_UNIT:
case VERIFY: /* mismatch DPO */
case WRITE_10: /* mismatch in byte 1 */
case WRITE_12: /* mismatch in byte 1 */
case WRITE_AND_VERIFY: /* mismatch byte 1 */
case PAUSE_RESUME:
case PLAY_AUDIO:
case PLAY_AUDIO_MSF:
case REWIND:
case PLAY_AUDIO_TRACK:
/* are in FreeBSD driver but no in 8070/8020 specs ...
status_t status = B_OK;
TRACE_SCSI_COMMAND(cmd, len);
memset(*rcmd, 0, ATAPI_COMMAND_LEN);
if(!transform_6_to_10(cmd, len, rcmd, rlen)){ /* was not transformed ?*/
scsi_cmd_generic *command = (scsi_cmd_generic *)cmd;
switch(command->opcode){
case TEST_UNIT_READY:
if(transform_cmd_test_unit_ready(udi, cmd, len, rcmd, rlen)){
break; /* if TEST UNIT READY was transformed*/
}
case FORMAT_UNIT:
case INQUIRY:
case MODE_SELECT_10:
case MODE_SENSE_10:
case PREVENT_ALLOW_MEDIA_REMOVAL:
case READ_10:
case READ_12: /* mismatch in byte 1 */
case READ_CAPACITY: /* mismatch. no transf len defined... */
case READ_FORMAT_CAPACITY: /* TODO: check!!! */
case REQUEST_SENSE:
case SEEK_10:
case START_STOP_UNIT:
case VERIFY: /* mismatch DPO */
case WRITE_10: /* mismatch in byte 1 */
case WRITE_12: /* mismatch in byte 1 */
case WRITE_AND_VERIFY: /* mismatch byte 1 */
case PAUSE_RESUME:
case PLAY_AUDIO:
case PLAY_AUDIO_MSF:
case REWIND:
case PLAY_AUDIO_TRACK:
/* are in FreeBSD driver but no in 8070/8020 specs ...
//case REZERO_UNIT:
//case SEND_DIAGNOSTIC:
//case POSITION_TO_ELEMENT: */
@ -375,102 +380,102 @@ status_t atapi_transform(usb_device_info *udi,
case READ_DVD_STRUCTURE:
case SET_CD_SPEED:
case DVD_REPORT_KEY:
case DVD_SEND_KEY:
case DVD_SEND_KEY:
// case 0xe5: /* READ_TRACK_INFO_PHILIPS *//* TODO: check!!! */
memcpy(*rcmd, cmd, len); /* TODO: check!!! */
break;
default:
TRACE_ALWAYS("An unsupported (?) ATAPI command: %08x\n", command->opcode);
status = B_ERROR;
break;
}
}
*rlen = ATAPI_COMMAND_LEN;
if(status == B_OK)
TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen);
return status;
memcpy(*rcmd, cmd, len); /* TODO: check!!! */
break;
default:
TRACE_ALWAYS("An unsupported (?) ATAPI command: %08x\n", command->opcode);
status = B_ERROR;
break;
}
}
*rlen = ATAPI_COMMAND_LEN;
if(status == B_OK)
TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen);
return status;
}
/**
\fn:qic157_transform
\param udi: usb_device_info object for wich transformation is requested
\param cmd: SCSI command buffer to be transformed
\param len: length of buffer, pointed by cmd parameter
\param rcmd: a place for buffer pointer with transformed command
\param rlen: a place for length of transformed command
\return: B_OK if transformation was successfull, B_ERROR otherwise
this is the "transformation procedure" for QIC157 USB subclass (0x03).It
performs all SCSI commands transformations required by this protocol. Additionally
it tries to make some workarounds for "brocken" USB devices. If no transformation
was performed resulting command buffer points to original one.
\fn:qic157_transform
\param udi: usb_device_info object for wich transformation is requested
\param cmd: SCSI command buffer to be transformed
\param len: length of buffer, pointed by cmd parameter
\param rcmd: a place for buffer pointer with transformed command
\param rlen: a place for length of transformed command
\return: B_OK if transformation was successfull, B_ERROR otherwise
this is the "transformation procedure" for QIC157 USB subclass (0x03).It
performs all SCSI commands transformations required by this protocol. Additionally
it tries to make some workarounds for "brocken" USB devices. If no transformation
was performed resulting command buffer points to original one.
*/
status_t qic157_transform(usb_device_info *udi,
uint8 *cmd,
uint8 len,
uint8 **rcmd,
uint8 *rlen)
uint8 *cmd,
uint8 len,
uint8 **rcmd,
uint8 *rlen)
{
status_t status = B_OK;
TRACE_SCSI_COMMAND(cmd, len);
*rlen = ATAPI_COMMAND_LEN;
memset(*rcmd, 0, *rlen);
if(!transform_6_to_10(cmd, len, rcmd, rlen)){ // was not transformed ?
scsi_cmd_generic *command = (scsi_cmd_generic *)cmd;
switch(command->opcode){
case TEST_UNIT_READY:
if(transform_cmd_test_unit_ready(udi, cmd, len, rcmd, rlen)){
break; // if TEST UNIT READY was transformed
}
case ERASE: /*TODO: check !!! */
case INQUIRY: /*TODO: check !!! */
case LOAD_UNLOAD: /*TODO: check !!! */
case LOCATE: /*TODO: check !!! */
case LOG_SELECT: /*TODO: check !!! */
case LOG_SENSE: /*TODO: check !!! */
case MODE_SELECT_6: /*TODO: check !!! */
case MODE_SENSE_6: /*TODO: check !!! */
case READ_6: /*TODO: check !!! */
case READ_POSITION: /*TODO: check !!! */
case REQUEST_SENSE: /*TODO: check !!! */
case REWIND: /*TODO: check !!! */
case SPACE: /*TODO: check !!! */
case WRITE_6: /*TODO: check !!! */
case WRITE_FILEMARK: /*TODO: check !!! */
*rcmd = cmd; /*TODO: check !!! */
*rlen = len;
break;
default:
TRACE_ALWAYS("An unsupported QIC-157 command: %08x\n", command->opcode);
status = B_ERROR;
break;
}
}
if(status == B_OK)
TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen);
return status;
status_t status = B_OK;
TRACE_SCSI_COMMAND(cmd, len);
*rlen = ATAPI_COMMAND_LEN;
memset(*rcmd, 0, *rlen);
if(!transform_6_to_10(cmd, len, rcmd, rlen)){ // was not transformed ?
scsi_cmd_generic *command = (scsi_cmd_generic *)cmd;
switch(command->opcode){
case TEST_UNIT_READY:
if(transform_cmd_test_unit_ready(udi, cmd, len, rcmd, rlen)){
break; // if TEST UNIT READY was transformed
}
case ERASE: /*TODO: check !!! */
case INQUIRY: /*TODO: check !!! */
case LOAD_UNLOAD: /*TODO: check !!! */
case LOCATE: /*TODO: check !!! */
case LOG_SELECT: /*TODO: check !!! */
case LOG_SENSE: /*TODO: check !!! */
case MODE_SELECT_6: /*TODO: check !!! */
case MODE_SENSE_6: /*TODO: check !!! */
case READ_6: /*TODO: check !!! */
case READ_POSITION: /*TODO: check !!! */
case REQUEST_SENSE: /*TODO: check !!! */
case REWIND: /*TODO: check !!! */
case SPACE: /*TODO: check !!! */
case WRITE_6: /*TODO: check !!! */
case WRITE_FILEMARK: /*TODO: check !!! */
*rcmd = cmd; /*TODO: check !!! */
*rlen = len;
break;
default:
TRACE_ALWAYS("An unsupported QIC-157 command: %08x\n", command->opcode);
status = B_ERROR;
break;
}
}
if(status == B_OK)
TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen);
return status;
}
transform_module_info scsi_transform_m = {
{0, 0, 0}, /* this is not a real kernel module - just interface */
scsi_transform,
{0, 0, 0}, /* this is not a real kernel module - just interface */
scsi_transform,
};
transform_module_info rbc_transform_m = {
{0, 0, 0}, /* this is not a real kernel module - just interface */
rbc_transform,
{0, 0, 0}, /* this is not a real kernel module - just interface */
rbc_transform,
};
transform_module_info ufi_transform_m = {
{0, 0, 0}, /* this is not a real kernel module - just interface */
ufi_transform,
{0, 0, 0}, /* this is not a real kernel module - just interface */
ufi_transform,
};
transform_module_info atapi_transform_m = {
{0, 0, 0}, /* this is not a real kernel module - just interface */
atapi_transform,
{0, 0, 0}, /* this is not a real kernel module - just interface */
atapi_transform,
};
transform_module_info qic157_transform_m = {
{0, 0, 0}, /* this is not a real kernel module - just interface */
qic157_transform,
{0, 0, 0}, /* this is not a real kernel module - just interface */
qic157_transform,
};

View File

@ -1,13 +1,19 @@
/*
* Copyright (c) 2003-2005 by Siarzhuk Zharski <imker@gmx.li>
* Distributed under the terms of the BSD License.
/**
*
* TODO: description
*
* This file is a part of USB SCSI CAM for Haiku OS.
* May be used under terms of the MIT License
*
* Author(s):
* Siarzhuk Zharski <imker@gmx.li>
*
*
*/
/** decalration of SCSI commands transformation procedures */
#ifndef _TRANSFORM_PROCS_H_
#define _TRANSFORM_PROCS_H_
#define _TRANSFORM_PROCS_H_
#ifndef _PROTO_MODULE_H_
#include "proto_module.h"