diff options
| author | Alexander von Gluck IV <kallisti5@unixzen.com> | 2012-06-08 16:18:31 (GMT) |
|---|---|---|
| committer | Alexander von Gluck IV <kallisti5@unixzen.com> | 2012-06-11 01:47:13 (GMT) |
| commit | b937bd211c37af1cbd71f58ab0b1f272020f1103 (patch) | |
| tree | ceddf871f475c85430ec9fd702c3a08cd0d0ff1a | |
| parent | 372863638f6eb692e597c69b6677e2312a7ee600 (diff) | |
ahci: Initial TRIM workhrev44238
* 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.
| -rw-r--r-- | src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp | 32 | ||||
| -rw-r--r-- | src/add-ons/kernel/busses/scsi/ahci/ahci_port.h | 1 |
2 files changed, 30 insertions, 3 deletions
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; |
