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.
This commit is contained in:
Alexander von Gluck IV
2012-06-10 18:47:13 -07:00
parent 372863638f
commit b937bd211c
2 changed files with 30 additions and 3 deletions
@@ -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]);
@@ -70,6 +70,7 @@ private:
bool fTestUnitReadyActive;
bool fResetPort;
bool fError;
bool fTrim;
volatile fis * fFIS;
volatile command_list_entry * fCommandList;