summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander von Gluck IV <kallisti5@unixzen.com>2012-06-08 16:18:31 (GMT)
committerAlexander von Gluck IV <kallisti5@unixzen.com>2012-06-11 01:47:13 (GMT)
commitb937bd211c37af1cbd71f58ab0b1f272020f1103 (patch)
treeceddf871f475c85430ec9fd702c3a08cd0d0ff1a
parent372863638f6eb692e597c69b6677e2312a7ee600 (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.cpp32
-rw-r--r--src/add-ons/kernel/busses/scsi/ahci/ahci_port.h1
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;