* Made at least scsi_cmd_rw_10 the same as the one in private/drivers/scsi_cmds.h;
ideally, we would only have one file and no copies - later. * That also changed how READ/WRITE_6 commands are translated to READ/WRITE_10 commands, but it was obviously correct before, at least I can still reproduce bug #1577 (so it has to be something else). * Spotted a few suspicious uses of transform_6_10() vs. transform_cmd_6_10(); at least the FreeBSD driver seem to work differently here, anyway (it always uses 12 byte commands for most of these). * Cleaned up the file. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22838 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -6,6 +6,8 @@ if $(TARGET_PLATFORM) != haiku {
|
|||||||
UsePublicHeaders [ FDirName drivers ] ;
|
UsePublicHeaders [ FDirName drivers ] ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UsePrivateHeaders drivers ;
|
||||||
|
|
||||||
KernelAddon usb_scsi :
|
KernelAddon usb_scsi :
|
||||||
usb_scsi.c
|
usb_scsi.c
|
||||||
tracing.c
|
tracing.c
|
||||||
|
|||||||
@@ -1,19 +1,16 @@
|
|||||||
/**
|
/*
|
||||||
*
|
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
|
||||||
* TODO: description
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
|
||||||
* 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 <[email protected]>
|
|
||||||
*
|
|
||||||
*
|
*
|
||||||
|
* Author:
|
||||||
|
* Siarzhuk Zharski <[email protected]>
|
||||||
*/
|
*/
|
||||||
/** definitions for SCSI commands, structures etc. */
|
|
||||||
|
|
||||||
#ifndef _SCSI_COMMANDS_H_
|
#ifndef _SCSI_COMMANDS_H_
|
||||||
#define _SCSI_COMMANDS_H_
|
#define _SCSI_COMMANDS_H_
|
||||||
|
|
||||||
|
/*! Definitions for SCSI commands, structures etc. */
|
||||||
|
|
||||||
|
#include <lendian_bitfield.h>
|
||||||
|
|
||||||
/* References:
|
/* References:
|
||||||
* http://www.t10.org/ftp/t10/drafts/rbc/rbc-r10a.pdf
|
* http://www.t10.org/ftp/t10/drafts/rbc/rbc-r10a.pdf
|
||||||
@@ -189,18 +186,23 @@ typedef struct{
|
|||||||
}scsi_cmd_generic_12;
|
}scsi_cmd_generic_12;
|
||||||
/* READ_6 / WRITE_6 */
|
/* READ_6 / WRITE_6 */
|
||||||
typedef scsi_cmd_generic_6 scsi_cmd_rw_6;
|
typedef scsi_cmd_generic_6 scsi_cmd_rw_6;
|
||||||
|
|
||||||
/* READ_10 / WRITE_10 */
|
/* READ_10 / WRITE_10 */
|
||||||
typedef struct{
|
typedef struct {
|
||||||
uint8 opcode;
|
uint8 opcode;
|
||||||
uint8 byte2;
|
LBITFIELD8_5(
|
||||||
#define CMD_RW_10_RELADDR 0x01
|
relative_address : 1, // relative address
|
||||||
#define CMD_RW_10_FUA 0x08
|
_res1_1 : 2,
|
||||||
#define CMD_RW_10_DPO 0x10
|
force_unit_access : 1, // force unit access (1 = safe, cacheless access)
|
||||||
uint8 addr[4];
|
disable_page_out : 1, // disable page out (1 = not worth caching)
|
||||||
uint8 reserved;
|
lun : 3
|
||||||
uint8 len[2];
|
);
|
||||||
uint8 ctrl;
|
uint32 lba; // big endian
|
||||||
}scsi_cmd_rw_10;
|
uint8 _reserved;
|
||||||
|
uint16 length; // big endian
|
||||||
|
uint8 control;
|
||||||
|
} scsi_cmd_rw_10;
|
||||||
|
|
||||||
/* MODE_SELECT_6 */
|
/* MODE_SELECT_6 */
|
||||||
typedef struct{
|
typedef struct{
|
||||||
uint8 opcode;
|
uint8 opcode;
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
/**
|
/*
|
||||||
*
|
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
|
||||||
* TODO: description
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
|
||||||
* 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 <[email protected]>
|
|
||||||
*
|
|
||||||
*
|
*
|
||||||
|
* Author:
|
||||||
|
* Siarzhuk Zharski <[email protected]>
|
||||||
*/
|
*/
|
||||||
/** SCSI commands transformations support */
|
|
||||||
|
/*! SCSI commands transformations support */
|
||||||
|
|
||||||
#include "usb_scsi.h"
|
#include "usb_scsi.h"
|
||||||
|
|
||||||
@@ -18,208 +14,228 @@
|
|||||||
#include "transform_procs.h"
|
#include "transform_procs.h"
|
||||||
#include "tracing.h"
|
#include "tracing.h"
|
||||||
#include "scsi_commands.h"
|
#include "scsi_commands.h"
|
||||||
//#include "proto_common.h"
|
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "strings.h"
|
#include "strings.h"
|
||||||
|
|
||||||
#define UFI_COMMAND_LEN 12
|
#define UFI_COMMAND_LEN 12
|
||||||
#define ATAPI_COMMAND_LEN 12
|
#define ATAPI_COMMAND_LEN 12
|
||||||
|
|
||||||
static status_t
|
|
||||||
scsi_transform(usb_device_info *udi, uint8 *cmd,
|
/*! Transforms a 6-byte command to 10-byte one if required. Transformed command
|
||||||
uint8 len, uint8 **rcmd, uint8 *rlen);
|
is returned in rcmd parameter. In case if no transformation was performed
|
||||||
static status_t rbc_transform(usb_device_info *udi, uint8 *cmd,
|
the return buffer is untouched.
|
||||||
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 cmd: SCSI command buffer to be transformed
|
||||||
\param len: length of buffer, pointed by cmd parameter
|
\param len: length of buffer, pointed by cmd parameter
|
||||||
\param rcmd: a place for buffer pointer with transformed command
|
\param rcmd: a place for buffer pointer with transformed command
|
||||||
\param rlen: a place for length of transformed command
|
\param rlen: a place for length of transformed command
|
||||||
\return: true if transformation was performed
|
\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,
|
static void
|
||||||
uint8 **rcmd, uint8 *rlen)
|
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;
|
scsi_cmd_generic_6 *from = (scsi_cmd_generic_6 *)cmd;
|
||||||
memset(*rcmd, 0, *rlen);
|
|
||||||
switch (from->opcode){
|
*rlen = 10;
|
||||||
|
memset(*rcmd, 0, 10);
|
||||||
|
|
||||||
|
switch (from->opcode) {
|
||||||
case READ_6:
|
case READ_6:
|
||||||
case WRITE_6:{
|
case WRITE_6:
|
||||||
scsi_cmd_rw_10 *to = (scsi_cmd_rw_10 *)(*rcmd);
|
{
|
||||||
to->opcode = (from->opcode == READ_6) ? READ_10 : WRITE_10;
|
scsi_cmd_rw_10 *to = (scsi_cmd_rw_10 *)(*rcmd);
|
||||||
memcpy(to->addr + 1, from->addr, 3);
|
|
||||||
to->byte2 = from->addr[0];
|
to->opcode = (from->opcode == READ_6) ? READ_10 : WRITE_10;
|
||||||
to->byte2 &= ~CMD_GEN_6_ADDR;
|
to->lba = B_HOST_TO_BENDIAN_INT32(((from->addr[0] & 0x1f) << 16)
|
||||||
to->addr[1] &= CMD_GEN_6_ADDR;
|
| (from->addr[1] << 8) | from->addr[0]);
|
||||||
to->len[1] = from->len;
|
to->lun = (from->addr[0] & CMD_LUN) >> CMD_LUN_SHIFT;
|
||||||
to->ctrl = from->ctrl;
|
to->control = from->ctrl;
|
||||||
if(0 == from->len){ /* special case! in 6-byte R/W commands */
|
if (from->len == 0) {
|
||||||
to->len[0] = 1; /* the length 0x00 assume transfering 0x100 blocks! */
|
/* special case! in 6-byte R/W commands */
|
||||||
}
|
/* the length 0x00 assume transfering 0x100 blocks! */
|
||||||
}break;
|
to->length = B_HOST_TO_BENDIAN_INT16((uint16)256);
|
||||||
|
} else
|
||||||
|
to->length = B_HOST_TO_BENDIAN_INT16((uint16)from->len);
|
||||||
|
}
|
||||||
|
|
||||||
case MODE_SENSE_6:
|
case MODE_SENSE_6:
|
||||||
case MODE_SELECT_6:{
|
case MODE_SELECT_6:
|
||||||
scsi_cmd_generic_10 *to = (scsi_cmd_generic_10 *)(*rcmd);
|
{
|
||||||
if(from->opcode == MODE_SENSE_6){
|
scsi_cmd_generic_10 *to = (scsi_cmd_generic_10 *)(*rcmd);
|
||||||
|
|
||||||
|
if (from->opcode == MODE_SENSE_6) {
|
||||||
to->opcode = MODE_SENSE_10;
|
to->opcode = MODE_SENSE_10;
|
||||||
((scsi_cmd_mode_sense_10 *)to)->byte3 =
|
((scsi_cmd_mode_sense_10 *)to)->byte3
|
||||||
((scsi_cmd_mode_sense_6 *)from)->byte3;
|
= ((scsi_cmd_mode_sense_6 *)from)->byte3;
|
||||||
}else
|
} else
|
||||||
to->opcode = MODE_SELECT_10;
|
to->opcode = MODE_SELECT_10;
|
||||||
to->byte2 = from->addr[0];
|
to->byte2 = from->addr[0];
|
||||||
to->len[1] = from->len + 4; /*TODO: hardcoded length*/
|
to->len[1] = from->len + 4; /*TODO: hardcoded length*/
|
||||||
to->ctrl = from->ctrl;
|
to->ctrl = from->ctrl;
|
||||||
}break;
|
}
|
||||||
default:{ /* no transformation needed */
|
|
||||||
transformed = false;
|
default:
|
||||||
}break;
|
/* no transformation needed */
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return transformed;
|
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
\fn:transform_cmd_6_to_10
|
|
||||||
|
/*! Transforms a 6-byte command to 10-byte depending on information provided
|
||||||
|
with udi object.
|
||||||
|
|
||||||
\param udi: usb_device_info object for wich transformation is requested
|
\param udi: usb_device_info object for wich transformation is requested
|
||||||
\param cmd: SCSI command buffer to be transformed
|
\param cmd: SCSI command buffer to be transformed
|
||||||
\param len: length of buffer, pointed by cmd parameter
|
\param len: length of buffer, pointed by cmd parameter
|
||||||
\param rcmd: a place for buffer pointer with transformed command
|
\param rcmd: a place for buffer pointer with transformed command
|
||||||
\param rlen: a place for length of transformed command
|
\param rlen: a place for length of transformed command
|
||||||
\return: true if transformation was performed
|
\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,
|
static bool
|
||||||
uint8 len, uint8 **rcmd, uint8 *rlen)
|
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;
|
scsi_cmd_generic_6 *from = (scsi_cmd_generic_6 *)cmd;
|
||||||
switch (from->opcode){
|
|
||||||
|
switch (from->opcode) {
|
||||||
case READ_6:
|
case READ_6:
|
||||||
case WRITE_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 (!HAS_FIXES(udi->properties, FIX_FORCE_RW_TO_6)) {
|
||||||
if((transformed = transform_6_to_10(cmd, len, rcmd, rlen)) == true)
|
transform_6_to_10(cmd, len, rcmd, rlen);
|
||||||
*rlen = 10;
|
return true;
|
||||||
}else
|
}
|
||||||
transformed = false;
|
break;
|
||||||
}break;
|
}
|
||||||
|
|
||||||
case MODE_SENSE_6:
|
case MODE_SENSE_6:
|
||||||
case MODE_SELECT_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 (HAS_FIXES(udi->properties, FIX_FORCE_MS_TO_10)) {
|
||||||
if((transformed = transform_6_to_10(cmd, len, rcmd, rlen)) == true)
|
transform_6_to_10(cmd, len, rcmd, rlen);
|
||||||
*rlen = 10;
|
return true;
|
||||||
}else
|
}
|
||||||
transformed = false;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return transformed;
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
\fn:transform_cmd_test_unit_ready
|
|
||||||
|
/*! Transforms a TEST_UNIT_COMAND SCSI command to START_STOP_UNIT one depending
|
||||||
|
on properties provided with udi object.
|
||||||
|
|
||||||
\param udi: usb_device_info object for wich transformation is requested
|
\param udi: usb_device_info object for wich transformation is requested
|
||||||
\param cmd: SCSI command buffer to be transformed
|
\param cmd: SCSI command buffer to be transformed
|
||||||
\param len: length of buffer, pointed by cmd parameter
|
\param len: length of buffer, pointed by cmd parameter
|
||||||
\param rcmd: a place for buffer pointer with transformed command
|
\param rcmd: a place for buffer pointer with transformed command
|
||||||
\param rlen: a place for length of transformed command
|
\param rlen: a place for length of transformed command
|
||||||
\return: true if transformation was performed
|
\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,
|
static bool
|
||||||
uint8 *cmd, uint8 len,
|
transform_cmd_test_unit_ready(usb_device_info *udi, uint8 *cmd, uint8 len,
|
||||||
uint8 **rcmd, uint8 *rlen)
|
uint8 **rcmd, uint8 *rlen)
|
||||||
{
|
{
|
||||||
bool transformed = false;
|
scsi_cmd_start_stop_unit *command = (scsi_cmd_start_stop_unit *)(*rcmd);
|
||||||
if(HAS_FIXES(udi->properties, FIX_TRANS_TEST_UNIT)){
|
|
||||||
scsi_cmd_start_stop_unit *command = (scsi_cmd_start_stop_unit *)(*rcmd);
|
if (!HAS_FIXES(udi->properties, FIX_TRANS_TEST_UNIT))
|
||||||
memset(*rcmd, 0, *rlen);
|
return false;
|
||||||
command->opcode = START_STOP_UNIT;
|
|
||||||
command->start_loej = CMD_SSU_START;
|
memset(*rcmd, 0, *rlen);
|
||||||
*rlen = 6;
|
command->opcode = START_STOP_UNIT;
|
||||||
transformed = true;
|
command->start_loej = CMD_SSU_START;
|
||||||
}
|
*rlen = 6;
|
||||||
return transformed;
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
\fn:scsi_transform
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
/*! 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 "broken" USB
|
||||||
|
devices. If no transformation was performed resulting command buffer
|
||||||
|
points to original one.
|
||||||
|
|
||||||
\param udi: usb_device_info object for wich transformation is requested
|
\param udi: usb_device_info object for wich transformation is requested
|
||||||
\param cmd: SCSI command buffer to be transformed
|
\param cmd: SCSI command buffer to be transformed
|
||||||
\param len: length of buffer, pointed by cmd parameter
|
\param len: length of buffer, pointed by cmd parameter
|
||||||
\param rcmd: a place for buffer pointer with transformed command
|
\param rcmd: a place for buffer pointer with transformed command
|
||||||
\param rlen: a place for length of transformed command
|
\param rlen: a place for length of transformed command
|
||||||
\return: B_OK if transformation was successfull, B_ERROR otherwise
|
\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
|
static status_t
|
||||||
scsi_transform(usb_device_info *udi, uint8 *cmd,
|
scsi_transform(usb_device_info *udi, uint8 *cmd, uint8 len, uint8 **rcmd,
|
||||||
uint8 len, uint8 **rcmd, uint8 *rlen)
|
uint8 *rlen)
|
||||||
{
|
{
|
||||||
status_t status = B_OK;
|
|
||||||
bool transformed = false;
|
bool transformed = false;
|
||||||
scsi_cmd_generic *command = (scsi_cmd_generic *)cmd;
|
scsi_cmd_generic *command = (scsi_cmd_generic *)cmd;
|
||||||
TRACE_SCSI_COMMAND(cmd, len);
|
TRACE_SCSI_COMMAND(cmd, len);
|
||||||
switch(command->opcode){
|
|
||||||
|
switch (command->opcode) {
|
||||||
case READ_6:
|
case READ_6:
|
||||||
case WRITE_6:
|
case WRITE_6:
|
||||||
case MODE_SENSE_6:
|
case MODE_SENSE_6:
|
||||||
case MODE_SELECT_6:
|
case MODE_SELECT_6:
|
||||||
transformed = transform_cmd_6_to_10(udi, cmd, len, rcmd, rlen);
|
transformed = transform_cmd_6_to_10(udi, cmd, len, rcmd, rlen);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TEST_UNIT_READY:
|
case TEST_UNIT_READY:
|
||||||
transformed = transform_cmd_test_unit_ready(udi, cmd, len, rcmd, rlen);
|
transformed = transform_cmd_test_unit_ready(udi, cmd, len, rcmd,
|
||||||
|
rlen);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
break;
|
break;
|
||||||
default: break;
|
|
||||||
}
|
}
|
||||||
if(!transformed){ /* transformation was not required */
|
|
||||||
|
if (!transformed) {
|
||||||
|
/* transformation was not required */
|
||||||
*rcmd = cmd;
|
*rcmd = cmd;
|
||||||
*rlen = len;
|
*rlen = len;
|
||||||
}else
|
} else
|
||||||
TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen);
|
TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen);
|
||||||
return status;
|
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
\fn:rbc_transform
|
|
||||||
|
/*! 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 "broken" USB devices.
|
||||||
|
If no transformation was performed resulting command buffer points to
|
||||||
|
original one.
|
||||||
|
|
||||||
\param udi: usb_device_info object for wich transformation is requested
|
\param udi: usb_device_info object for wich transformation is requested
|
||||||
\param cmd: SCSI command buffer to be transformed
|
\param cmd: SCSI command buffer to be transformed
|
||||||
\param len: length of buffer, pointed by cmd parameter
|
\param len: length of buffer, pointed by cmd parameter
|
||||||
\param rcmd: a place for buffer pointer with transformed command
|
\param rcmd: a place for buffer pointer with transformed command
|
||||||
\param rlen: a place for length of transformed command
|
\param rlen: a place for length of transformed command
|
||||||
\return: B_OK if transformation was successfull, B_ERROR otherwise
|
\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,
|
static status_t
|
||||||
uint8 len, uint8 **rcmd, uint8 *rlen)
|
rbc_transform(usb_device_info *udi, uint8 *cmd, uint8 len, uint8 **rcmd,
|
||||||
|
uint8 *rlen)
|
||||||
{
|
{
|
||||||
status_t status = B_OK;
|
|
||||||
bool transformed = false;
|
bool transformed = false;
|
||||||
scsi_cmd_generic *command = (scsi_cmd_generic *)cmd;
|
scsi_cmd_generic *command = (scsi_cmd_generic *)cmd;
|
||||||
TRACE_SCSI_COMMAND(cmd, len);
|
TRACE_SCSI_COMMAND(cmd, len);
|
||||||
switch(command->opcode){
|
|
||||||
|
switch (command->opcode) {
|
||||||
case TEST_UNIT_READY:
|
case TEST_UNIT_READY:
|
||||||
transformed = transform_cmd_test_unit_ready(udi, cmd, len, rcmd, rlen);
|
transformed = transform_cmd_test_unit_ready(udi, cmd, len, rcmd, rlen);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case READ_6:
|
case READ_6:
|
||||||
case WRITE_6: /* there are no such command in list of allowed - transform*/
|
case WRITE_6: /* there are no such command in list of allowed - transform*/
|
||||||
transformed = transform_cmd_6_to_10(udi, cmd, len, rcmd, rlen);
|
transformed = transform_cmd_6_to_10(udi, cmd, len, rcmd, rlen);
|
||||||
break;
|
break;
|
||||||
case FORMAT_UNIT: /* TODO: all following ones are not checked against specs !!!*/
|
|
||||||
|
/* TODO: all following ones are not checked against specs !!!*/
|
||||||
|
case FORMAT_UNIT:
|
||||||
case INQUIRY: /*TODO: check !!! */
|
case INQUIRY: /*TODO: check !!! */
|
||||||
case MODE_SELECT_6: /*TODO: check !!! */
|
case MODE_SELECT_6: /*TODO: check !!! */
|
||||||
case MODE_SENSE_6: /*TODO: check !!! */
|
case MODE_SENSE_6: /*TODO: check !!! */
|
||||||
@@ -235,222 +251,251 @@ status_t rbc_transform(usb_device_info *udi, uint8 *cmd,
|
|||||||
case SYNCHRONIZE_CACHE: /*TODO: check !!! */
|
case SYNCHRONIZE_CACHE: /*TODO: check !!! */
|
||||||
case VERIFY: /*TODO: check !!! */
|
case VERIFY: /*TODO: check !!! */
|
||||||
case WRITE_10: /*TODO: check !!! */
|
case WRITE_10: /*TODO: check !!! */
|
||||||
case WRITE_BUFFER:/*TODO Check correctnes of such translation!*/
|
case WRITE_BUFFER: /*TODO Check correctnes of such translation!*/
|
||||||
*rcmd = cmd; /* No need to copy */
|
*rcmd = cmd; /* No need to copy */
|
||||||
*rlen = len; /*TODO: check !!! */
|
*rlen = len; /*TODO: check !!! */
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
TRACE_ALWAYS("An unsupported RBC command: %08x\n", command->opcode);
|
TRACE_ALWAYS("An unsupported RBC command: %08x\n", command->opcode);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transformed)
|
||||||
|
TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! 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 "broken" USB devices.
|
||||||
|
If no transformation was performed resulting command buffer points to
|
||||||
|
the original one.
|
||||||
|
|
||||||
|
\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
|
||||||
|
*/
|
||||||
|
static status_t
|
||||||
|
ufi_transform(usb_device_info *udi, uint8 *cmd, uint8 len, uint8 **rcmd,
|
||||||
|
uint8 *rlen)
|
||||||
|
{
|
||||||
|
scsi_cmd_generic *command = (scsi_cmd_generic *)cmd;
|
||||||
|
status_t status = B_OK;
|
||||||
|
|
||||||
|
TRACE_SCSI_COMMAND(cmd, len);
|
||||||
|
memset(*rcmd, 0, UFI_COMMAND_LEN);
|
||||||
|
|
||||||
|
switch (command->opcode) {
|
||||||
|
case READ_6:
|
||||||
|
case WRITE_6:
|
||||||
|
case MODE_SENSE_6:
|
||||||
|
case MODE_SELECT_6:
|
||||||
|
// TODO: not transform_cmd_*()?
|
||||||
|
transform_6_to_10(cmd, len, rcmd, rlen);
|
||||||
|
break;
|
||||||
|
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;
|
status = B_ERROR;
|
||||||
break;
|
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.
|
|
||||||
*/
|
|
||||||
status_t ufi_transform(usb_device_info *udi,
|
|
||||||
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 !!!*/
|
*rlen = UFI_COMMAND_LEN; /* override any value set in transform funcs !!!*/
|
||||||
if(status == B_OK)
|
|
||||||
|
if (status == B_OK)
|
||||||
TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen);
|
TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
\fn:atapi_transform
|
|
||||||
|
/*! 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 the original one.
|
||||||
|
|
||||||
\param udi: usb_device_info object for wich transformation is requested
|
\param udi: usb_device_info object for wich transformation is requested
|
||||||
\param cmd: SCSI command buffer to be transformed
|
\param cmd: SCSI command buffer to be transformed
|
||||||
\param len: length of buffer, pointed by cmd parameter
|
\param len: length of buffer, pointed by cmd parameter
|
||||||
\param rcmd: a place for buffer pointer with transformed command
|
\param rcmd: a place for buffer pointer with transformed command
|
||||||
\param rlen: a place for length of transformed command
|
\param rlen: a place for length of transformed command
|
||||||
\return: B_OK if transformation was successfull, B_ERROR otherwise
|
\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,
|
static status_t
|
||||||
uint8 *cmd,
|
atapi_transform(usb_device_info *udi, uint8 *cmd, uint8 len, uint8 **rcmd,
|
||||||
uint8 len,
|
uint8 *rlen)
|
||||||
uint8 **rcmd,
|
|
||||||
uint8 *rlen)
|
|
||||||
{
|
{
|
||||||
|
scsi_cmd_generic *command = (scsi_cmd_generic *)cmd;
|
||||||
status_t status = B_OK;
|
status_t status = B_OK;
|
||||||
|
|
||||||
TRACE_SCSI_COMMAND(cmd, len);
|
TRACE_SCSI_COMMAND(cmd, len);
|
||||||
memset(*rcmd, 0, ATAPI_COMMAND_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) {
|
||||||
switch(command->opcode){
|
case READ_6:
|
||||||
case TEST_UNIT_READY:
|
case WRITE_6:
|
||||||
if(transform_cmd_test_unit_ready(udi, cmd, len, rcmd, rlen)){
|
case MODE_SENSE_6:
|
||||||
break; /* if TEST UNIT READY was transformed*/
|
case MODE_SELECT_6:
|
||||||
}
|
// TODO: not transform_cmd_*()?
|
||||||
case FORMAT_UNIT:
|
transform_6_to_10(cmd, len, rcmd, rlen))
|
||||||
case INQUIRY:
|
break;
|
||||||
case MODE_SELECT_10:
|
case TEST_UNIT_READY:
|
||||||
case MODE_SENSE_10:
|
if (transform_cmd_test_unit_ready(udi, cmd, len, rcmd, rlen))
|
||||||
case PREVENT_ALLOW_MEDIA_REMOVAL:
|
break;
|
||||||
case READ_10:
|
case FORMAT_UNIT:
|
||||||
case READ_12: /* mismatch in byte 1 */
|
case INQUIRY:
|
||||||
case READ_CAPACITY: /* mismatch. no transf len defined... */
|
case MODE_SELECT_10:
|
||||||
case READ_FORMAT_CAPACITY: /* TODO: check!!! */
|
case MODE_SENSE_10:
|
||||||
case REQUEST_SENSE:
|
case PREVENT_ALLOW_MEDIA_REMOVAL:
|
||||||
case SEEK_10:
|
case READ_10:
|
||||||
case START_STOP_UNIT:
|
case READ_12: /* mismatch in byte 1 */
|
||||||
case VERIFY: /* mismatch DPO */
|
case READ_CAPACITY: /* mismatch. no transf len defined... */
|
||||||
case WRITE_10: /* mismatch in byte 1 */
|
case READ_FORMAT_CAPACITY: /* TODO: check!!! */
|
||||||
case WRITE_12: /* mismatch in byte 1 */
|
case REQUEST_SENSE:
|
||||||
case WRITE_AND_VERIFY: /* mismatch byte 1 */
|
case SEEK_10:
|
||||||
case PAUSE_RESUME:
|
case START_STOP_UNIT:
|
||||||
case PLAY_AUDIO:
|
case VERIFY: /* mismatch DPO */
|
||||||
case PLAY_AUDIO_MSF:
|
case WRITE_10: /* mismatch in byte 1 */
|
||||||
case REWIND:
|
case WRITE_12: /* mismatch in byte 1 */
|
||||||
case PLAY_AUDIO_TRACK:
|
case WRITE_AND_VERIFY: /* mismatch byte 1 */
|
||||||
/* are in FreeBSD driver but no in 8070/8020 specs ...
|
case PAUSE_RESUME:
|
||||||
//case REZERO_UNIT:
|
case PLAY_AUDIO:
|
||||||
//case SEND_DIAGNOSTIC:
|
case PLAY_AUDIO_MSF:
|
||||||
//case POSITION_TO_ELEMENT: */
|
case REWIND:
|
||||||
case GET_CONFIGURATION:
|
case PLAY_AUDIO_TRACK:
|
||||||
case SYNCHRONIZE_CACHE:
|
/* are in FreeBSD driver but no in 8070/8020 specs ...
|
||||||
case READ_BUFFER:
|
//case REZERO_UNIT:
|
||||||
case READ_SUBCHANNEL:
|
//case SEND_DIAGNOSTIC:
|
||||||
case READ_TOC: /* some mismatch */
|
//case POSITION_TO_ELEMENT: */
|
||||||
case READ_HEADER:
|
case GET_CONFIGURATION:
|
||||||
case READ_DISK_INFO:
|
case SYNCHRONIZE_CACHE:
|
||||||
case READ_TRACK_INFO:
|
case READ_BUFFER:
|
||||||
case SEND_OPC:
|
case READ_SUBCHANNEL:
|
||||||
case READ_MASTER_CUE:
|
case READ_TOC: /* some mismatch */
|
||||||
case CLOSE_TR_SESSION:
|
case READ_HEADER:
|
||||||
case READ_BUFFER_CAP:
|
case READ_DISK_INFO:
|
||||||
case SEND_CUE_SHEET:
|
case READ_TRACK_INFO:
|
||||||
case BLANK:
|
case SEND_OPC:
|
||||||
case EXCHANGE_MEDIUM:
|
case READ_MASTER_CUE:
|
||||||
case READ_DVD_STRUCTURE:
|
case CLOSE_TR_SESSION:
|
||||||
case SET_CD_SPEED:
|
case READ_BUFFER_CAP:
|
||||||
case DVD_REPORT_KEY:
|
case SEND_CUE_SHEET:
|
||||||
|
case BLANK:
|
||||||
|
case EXCHANGE_MEDIUM:
|
||||||
|
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!!! */
|
//case 0xe5: /* READ_TRACK_INFO_PHILIPS *//* TODO: check!!! */
|
||||||
memcpy(*rcmd, cmd, len); /* TODO: check!!! */
|
memcpy(*rcmd, cmd, len); /* TODO: check!!! */
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
TRACE_ALWAYS("An unsupported (?) ATAPI command: %08x\n", command->opcode);
|
default:
|
||||||
status = B_ERROR;
|
TRACE_ALWAYS("An unsupported (?) ATAPI command: %08x\n",
|
||||||
break;
|
command->opcode);
|
||||||
}
|
status = B_ERROR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
*rlen = ATAPI_COMMAND_LEN;
|
*rlen = ATAPI_COMMAND_LEN;
|
||||||
if(status == B_OK)
|
|
||||||
|
if (status == B_OK)
|
||||||
TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen);
|
TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
\fn:qic157_transform
|
|
||||||
|
/*! 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 "broken" USB devices.
|
||||||
|
If no transformation was performed the resulting command buffer points to
|
||||||
|
the original one.
|
||||||
|
|
||||||
\param udi: usb_device_info object for wich transformation is requested
|
\param udi: usb_device_info object for wich transformation is requested
|
||||||
\param cmd: SCSI command buffer to be transformed
|
\param cmd: SCSI command buffer to be transformed
|
||||||
\param len: length of buffer, pointed by cmd parameter
|
\param len: length of buffer, pointed by cmd parameter
|
||||||
\param rcmd: a place for buffer pointer with transformed command
|
\param rcmd: a place for buffer pointer with transformed command
|
||||||
\param rlen: a place for length of transformed command
|
\param rlen: a place for length of transformed command
|
||||||
\return: B_OK if transformation was successfull, B_ERROR otherwise
|
\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,
|
static status_t
|
||||||
uint8 *cmd,
|
qic157_transform(usb_device_info *udi, uint8 *cmd, uint8 len, uint8 **rcmd,
|
||||||
uint8 len,
|
uint8 *rlen)
|
||||||
uint8 **rcmd,
|
|
||||||
uint8 *rlen)
|
|
||||||
{
|
{
|
||||||
|
scsi_cmd_generic *command = (scsi_cmd_generic *)cmd;
|
||||||
status_t status = B_OK;
|
status_t status = B_OK;
|
||||||
|
|
||||||
TRACE_SCSI_COMMAND(cmd, len);
|
TRACE_SCSI_COMMAND(cmd, len);
|
||||||
*rlen = ATAPI_COMMAND_LEN;
|
*rlen = ATAPI_COMMAND_LEN;
|
||||||
memset(*rcmd, 0, *rlen);
|
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) {
|
||||||
switch(command->opcode){
|
case READ_6:
|
||||||
case TEST_UNIT_READY:
|
case WRITE_6:
|
||||||
if(transform_cmd_test_unit_ready(udi, cmd, len, rcmd, rlen)){
|
case MODE_SENSE_6:
|
||||||
break; // if TEST UNIT READY was transformed
|
case MODE_SELECT_6:
|
||||||
}
|
// TODO: not transform_cmd_*()?
|
||||||
case ERASE: /*TODO: check !!! */
|
transform_6_to_10(cmd, len, rcmd, rlen);
|
||||||
case INQUIRY: /*TODO: check !!! */
|
break;
|
||||||
case LOAD_UNLOAD: /*TODO: check !!! */
|
case TEST_UNIT_READY:
|
||||||
case LOCATE: /*TODO: check !!! */
|
if (transform_cmd_test_unit_ready(udi, cmd, len, rcmd, rlen))
|
||||||
case LOG_SELECT: /*TODO: check !!! */
|
break; // if TEST UNIT READY was transformed
|
||||||
case LOG_SENSE: /*TODO: check !!! */
|
case ERASE: /*TODO: check !!! */
|
||||||
case MODE_SELECT_6: /*TODO: check !!! */
|
case INQUIRY: /*TODO: check !!! */
|
||||||
case MODE_SENSE_6: /*TODO: check !!! */
|
case LOAD_UNLOAD: /*TODO: check !!! */
|
||||||
case READ_6: /*TODO: check !!! */
|
case LOCATE: /*TODO: check !!! */
|
||||||
case READ_POSITION: /*TODO: check !!! */
|
case LOG_SELECT: /*TODO: check !!! */
|
||||||
case REQUEST_SENSE: /*TODO: check !!! */
|
case LOG_SENSE: /*TODO: check !!! */
|
||||||
case REWIND: /*TODO: check !!! */
|
case READ_POSITION: /*TODO: check !!! */
|
||||||
case SPACE: /*TODO: check !!! */
|
case REQUEST_SENSE: /*TODO: check !!! */
|
||||||
case WRITE_6: /*TODO: check !!! */
|
case REWIND: /*TODO: check !!! */
|
||||||
case WRITE_FILEMARK: /*TODO: check !!! */
|
case SPACE: /*TODO: check !!! */
|
||||||
*rcmd = cmd; /*TODO: check !!! */
|
case WRITE_FILEMARK: /*TODO: check !!! */
|
||||||
*rlen = len;
|
*rcmd = cmd; /*TODO: check !!! */
|
||||||
break;
|
*rlen = len;
|
||||||
default:
|
break;
|
||||||
TRACE_ALWAYS("An unsupported QIC-157 command: %08x\n", command->opcode);
|
default:
|
||||||
status = B_ERROR;
|
TRACE_ALWAYS("An unsupported QIC-157 command: %08x\n",
|
||||||
break;
|
command->opcode);
|
||||||
}
|
status = B_ERROR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if(status == B_OK)
|
|
||||||
|
if (status == B_OK)
|
||||||
TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen);
|
TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user