hrev44238 adds 2 changesets to branch 'master' old head: 163cd4bf53064ff57a1feadc14f04d7c09fc8efc new head: b937bd211c37af1cbd71f58ab0b1f272020f1103 ---------------------------------------------------------------------------- 3728636: scsi: Add write same SCSI operation * Will be used for TRIM b937bd2: ahci: Initial TRIM work * Since ahci devices are emulated as scsi, we use the SAS style TRIM call (unmap in scsi write same) * This prevents the need for special, one off trim calls. * We don't perform the TRIM just yet, just laying the goundwork for the request. [ Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> ] ---------------------------------------------------------------------------- 3 files changed, 53 insertions(+), 3 deletions(-) headers/private/drivers/scsi_cmds.h | 23 ++++++++++++ src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp | 32 +++++++++++++++-- src/add-ons/kernel/busses/scsi/ahci/ahci_port.h | 1 + ############################################################################ Commit: 372863638f6eb692e597c69b6677e2312a7ee600 URL: http://cgit.haiku-os.org/haiku/commit/?id=3728636 Author: Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> Date: Fri Jun 8 15:48:21 2012 UTC scsi: Add write same SCSI operation * Will be used for TRIM ---------------------------------------------------------------------------- diff --git a/headers/private/drivers/scsi_cmds.h b/headers/private/drivers/scsi_cmds.h index 2baabdd..1e1a47c 100644 --- a/headers/private/drivers/scsi_cmds.h +++ b/headers/private/drivers/scsi_cmds.h @@ -196,6 +196,7 @@ #define SCSI_OP_READ_16 0x88 #define SCSI_OP_WRITE_16 0x8a #define SCSI_OP_VERIFY_16 0x8f +#define SCSI_OP_WRITE_SAME_16 0x93 #define SCSI_OP_SERVICE_ACTION_IN 0x9e #define SCSI_OP_SERVICE_ACTION_OUT 0x9f #define SCSI_OP_MOVE_MEDIUM 0xa5 @@ -435,6 +436,28 @@ typedef struct scsi_cmd_rw_16 { } _PACKED scsi_cmd_rw_16; +// WRITE SAME (16) + +typedef struct scsi_cmd_wsame_16 { + uint8 opcode; + LBITFIELD8_6( + _res1_0 : 1, + lb_data : 1, + pb_data : 1, + unmap : 1, + _res1_4 : 1, + write_protect : 3 + ); + uint64 lba; + uint32 length; + LBITFIELD8_2( + group_number : 5, + _res14_5 : 3 + ); + uint8 control; +} _PACKED scsi_cmd_wsame_16; + + // REQUEST SENSE typedef struct scsi_cmd_request_sense { ############################################################################ Revision: hrev44238 Commit: b937bd211c37af1cbd71f58ab0b1f272020f1103 URL: http://cgit.haiku-os.org/haiku/commit/?id=b937bd2 Author: Alexander von Gluck IV <kallisti5@xxxxxxxxxxx> Date: Fri Jun 8 16:18:31 2012 UTC ahci: Initial TRIM work * Since ahci devices are emulated as scsi, we use the SAS style TRIM call (unmap in scsi write same) * This prevents the need for special, one off trim calls. * We don't perform the TRIM just yet, just laying the goundwork for the request. ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp index 74b042b..9b6da85 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp @@ -50,7 +50,8 @@ AHCIPort::AHCIPort(AHCIController *controller, int index) fIsATAPI(false), fTestUnitReadyActive(false), fResetPort(false), - fError(false) + fError(false), + fTrim(false) { B_INITIALIZE_SPINLOCK(&fSpinlock); fRequestSem = create_sem(1, "ahci request"); @@ -613,6 +614,7 @@ AHCIPort::ScsiInquiry(scsi_ccb *request) fUse48BitCommands = lba && lba48; fSectorSize = 512; fSectorCount = !(lba || sectors) ? 0 : lba48 ? sectors48 : sectors; + fTrim = ataData.data_set_management_support; TRACE("lba %d, lba48 %d, fUse48BitCommands %d, sectors %lu, " "sectors48 %llu, size %llu\n", lba, lba48, fUse48BitCommands, sectors, sectors48, @@ -641,8 +643,7 @@ AHCIPort::ScsiInquiry(scsi_ccb *request) TRACE("model number: %s\n", modelNumber); TRACE("serial number: %s\n", serialNumber); TRACE("firmware rev.: %s\n", firmwareRev); - TRACE("trim support: %s\n", - ataData.data_set_management_support ? "yes" : "no"); + TRACE("trim support: %s\n", fTrim ? "yes" : "no"); if (sg_memcpy(request->sg_list, request->sg_count, &scsiData, sizeof(scsiData)) < B_OK) { @@ -960,6 +961,31 @@ AHCIPort::ScsiExecuteRequest(scsi_ccb *request) } break; } + case SCSI_OP_WRITE_SAME_16: + { + scsi_cmd_wsame_16 *cmd = (scsi_cmd_wsame_16 *)request->cdb; + + // SCSI unmap is used for trim, otherwise we don't support it + if (!cmd->unmap) { + TRACE("%s port %d: unsupported request opcode 0x%02x\n", + __func__, fIndex, request->cdb[0]); + request->subsys_status = SCSI_REQ_ABORTED; + gSCSI->finished(request, 1); + break; + } + + if (!fTrim) { + // Drive doesn't support trim (or atapi) + // Just say it was successful and quit + request->subsys_status = SCSI_REQ_CMP; + } else { + TRACE("%s unimplemented: TRIM call\n", __func__); + // TODO: Make Serial ATA (sata_request?) trim call here. + request->subsys_status = SCSI_REQ_ABORTED; + } + gSCSI->finished(request, 1); + break; + } default: TRACE("AHCIPort::ScsiExecuteRequest port %d unsupported request " "opcode 0x%02x\n", fIndex, request->cdb[0]); diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h index 9781458..42b8e6b 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h @@ -70,6 +70,7 @@ private: bool fTestUnitReadyActive; bool fResetPort; bool fError; + bool fTrim; volatile fis * fFIS; volatile command_list_entry * fCommandList;