From f058886908e994cc5a6c141e212c3bd62e923023 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Tue, 2 Nov 2010 20:56:20 +0000 Subject: [PATCH] * added definitions for SCSI_OP_VERIFY_* op commands * added support READ_12/16 and WRITE_12/16 in ata and scsi_periph, this enables read/write on block offsets greater than 2TB git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39278 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/drivers/scsi_cmds.h | 5 ++- .../kernel/bus_managers/ata/ATADevice.cpp | 34 +++++++++++++++++++ src/add-ons/kernel/generic/scsi_periph/io.cpp | 28 +++++++++++++-- 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/headers/private/drivers/scsi_cmds.h b/headers/private/drivers/scsi_cmds.h index 078f960ef6..f5e8927c47 100644 --- a/headers/private/drivers/scsi_cmds.h +++ b/headers/private/drivers/scsi_cmds.h @@ -166,6 +166,7 @@ #define SCSI_OP_READ_6 0x08 #define SCSI_OP_WRITE_6 0x0a #define SCSI_OP_INQUIRY 0x12 +#define SCSI_OP_VERIFY_6 0x13 #define SCSI_OP_MODE_SELECT_6 0x15 #define SCSI_OP_RESERVE 0x16 #define SCSI_OP_RELEASE 0x17 @@ -178,7 +179,7 @@ #define SCSI_OP_READ_10 0x28 #define SCSI_OP_WRITE_10 0x2a #define SCSI_OP_POSITION_TO_ELEMENT 0x2b -#define SCSI_OP_VERIFY 0x2f +#define SCSI_OP_VERIFY_10 0x2f #define SCSI_OP_SYNCHRONIZE_CACHE 0x35 #define SCSI_OP_WRITE_BUFFER 0x3b #define SCSI_OP_READ_BUFFER 0x3c @@ -193,11 +194,13 @@ #define SCSI_OP_MODE_SENSE_10 0x5A #define SCSI_OP_READ_16 0x88 #define SCSI_OP_WRITE_16 0x8a +#define SCSI_OP_VERIFY_16 0x8f #define SCSI_OP_SERVICE_ACTION_IN 0x9e #define SCSI_OP_SERVICE_ACTION_OUT 0x9f #define SCSI_OP_MOVE_MEDIUM 0xa5 #define SCSI_OP_READ_12 0xa8 #define SCSI_OP_WRITE_12 0xaa +#define SCSI_OP_VERIFY_12 0xaf #define SCSI_OP_READ_ELEMENT_STATUS 0xb8 #define SCSI_OP_SCAN 0xba #define SCSI_OP_READ_CD 0xbe diff --git a/src/add-ons/kernel/bus_managers/ata/ATADevice.cpp b/src/add-ons/kernel/bus_managers/ata/ATADevice.cpp index 5457dc5376..4852ca6ea7 100644 --- a/src/add-ons/kernel/bus_managers/ata/ATADevice.cpp +++ b/src/add-ons/kernel/bus_managers/ata/ATADevice.cpp @@ -311,6 +311,40 @@ ATADevice::ExecuteIO(ATARequest *request) return B_OK; } } + + case SCSI_OP_READ_12: + case SCSI_OP_WRITE_12: + { + scsi_cmd_rw_12 *command = (scsi_cmd_rw_12 *)ccb->cdb; + uint32 address = B_BENDIAN_TO_HOST_INT32(command->lba); + uint32 sectorCount = B_BENDIAN_TO_HOST_INT32(command->length); + + request->SetIsWrite(command->opcode == SCSI_OP_WRITE_12); + if (sectorCount > 0) + return ExecuteReadWrite(request, address, sectorCount); + else { + // we cannot transfer zero blocks (apart from LBA48) + request->SetStatus(SCSI_REQ_CMP); + return B_OK; + } + } + + case SCSI_OP_READ_16: + case SCSI_OP_WRITE_16: + { + scsi_cmd_rw_16 *command = (scsi_cmd_rw_16 *)ccb->cdb; + uint64 address = B_BENDIAN_TO_HOST_INT64(command->lba); + uint32 sectorCount = B_BENDIAN_TO_HOST_INT32(command->length); + + request->SetIsWrite(command->opcode == SCSI_OP_WRITE_16); + if (sectorCount > 0) + return ExecuteReadWrite(request, address, sectorCount); + else { + // we cannot transfer zero blocks (apart from LBA48) + request->SetStatus(SCSI_REQ_CMP); + return B_OK; + } + } } TRACE("command not implemented\n"); diff --git a/src/add-ons/kernel/generic/scsi_periph/io.cpp b/src/add-ons/kernel/generic/scsi_periph/io.cpp index 846e95855c..6779622dfb 100644 --- a/src/add-ons/kernel/generic/scsi_periph/io.cpp +++ b/src/add-ons/kernel/generic/scsi_periph/io.cpp @@ -119,7 +119,7 @@ read_write(scsi_periph_device_info *device, scsi_ccb *request, do { size_t numBytes; - bool isReadWrite10; + bool isReadWrite10 = false; request->flags = isWrite ? SCSI_DIR_OUT : SCSI_DIR_IN; @@ -177,7 +177,7 @@ read_write(scsi_periph_device_info *device, scsi_ccb *request, cmd->length = numBlocks; request->cdb_length = sizeof(*cmd); - } else { + } else if (offset + numBlocks < 0x100000000LL && numBlocks <= 0x10000) { scsi_cmd_rw_10 *cmd = (scsi_cmd_rw_10 *)request->cdb; isReadWrite10 = true; @@ -190,6 +190,30 @@ read_write(scsi_periph_device_info *device, scsi_ccb *request, cmd->lba = B_HOST_TO_BENDIAN_INT32(pos); cmd->length = B_HOST_TO_BENDIAN_INT16(numBlocks); + request->cdb_length = sizeof(*cmd); + } else if (offset + numBlocks < 0x100000000LL && numBlocks <= 0x10000000) { + scsi_cmd_rw_12 *cmd = (scsi_cmd_rw_12 *)request->cdb; + + memset(cmd, 0, sizeof(*cmd)); + cmd->opcode = isWrite ? SCSI_OP_WRITE_12 : SCSI_OP_READ_12; + cmd->relative_address = 0; + cmd->force_unit_access = 0; + cmd->disable_page_out = 0; + cmd->lba = B_HOST_TO_BENDIAN_INT32(pos); + cmd->length = B_HOST_TO_BENDIAN_INT32(numBlocks); + + request->cdb_length = sizeof(*cmd); + } else { + scsi_cmd_rw_16 *cmd = (scsi_cmd_rw_16 *)request->cdb; + + memset(cmd, 0, sizeof(*cmd)); + cmd->opcode = isWrite ? SCSI_OP_WRITE_16 : SCSI_OP_READ_16; + cmd->force_unit_access_non_volatile = 0; + cmd->force_unit_access = 0; + cmd->disable_page_out = 0; + cmd->lba = B_HOST_TO_BENDIAN_INT64(offset); + cmd->length = B_HOST_TO_BENDIAN_INT32(numBlocks); + request->cdb_length = sizeof(*cmd); }