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:
@@ -50,7 +50,8 @@ AHCIPort::AHCIPort(AHCIController *controller, int index)
|
|||||||
fIsATAPI(false),
|
fIsATAPI(false),
|
||||||
fTestUnitReadyActive(false),
|
fTestUnitReadyActive(false),
|
||||||
fResetPort(false),
|
fResetPort(false),
|
||||||
fError(false)
|
fError(false),
|
||||||
|
fTrim(false)
|
||||||
{
|
{
|
||||||
B_INITIALIZE_SPINLOCK(&fSpinlock);
|
B_INITIALIZE_SPINLOCK(&fSpinlock);
|
||||||
fRequestSem = create_sem(1, "ahci request");
|
fRequestSem = create_sem(1, "ahci request");
|
||||||
@@ -613,6 +614,7 @@ AHCIPort::ScsiInquiry(scsi_ccb *request)
|
|||||||
fUse48BitCommands = lba && lba48;
|
fUse48BitCommands = lba && lba48;
|
||||||
fSectorSize = 512;
|
fSectorSize = 512;
|
||||||
fSectorCount = !(lba || sectors) ? 0 : lba48 ? sectors48 : sectors;
|
fSectorCount = !(lba || sectors) ? 0 : lba48 ? sectors48 : sectors;
|
||||||
|
fTrim = ataData.data_set_management_support;
|
||||||
TRACE("lba %d, lba48 %d, fUse48BitCommands %d, sectors %lu, "
|
TRACE("lba %d, lba48 %d, fUse48BitCommands %d, sectors %lu, "
|
||||||
"sectors48 %llu, size %llu\n",
|
"sectors48 %llu, size %llu\n",
|
||||||
lba, lba48, fUse48BitCommands, sectors, sectors48,
|
lba, lba48, fUse48BitCommands, sectors, sectors48,
|
||||||
@@ -641,8 +643,7 @@ AHCIPort::ScsiInquiry(scsi_ccb *request)
|
|||||||
TRACE("model number: %s\n", modelNumber);
|
TRACE("model number: %s\n", modelNumber);
|
||||||
TRACE("serial number: %s\n", serialNumber);
|
TRACE("serial number: %s\n", serialNumber);
|
||||||
TRACE("firmware rev.: %s\n", firmwareRev);
|
TRACE("firmware rev.: %s\n", firmwareRev);
|
||||||
TRACE("trim support: %s\n",
|
TRACE("trim support: %s\n", fTrim ? "yes" : "no");
|
||||||
ataData.data_set_management_support ? "yes" : "no");
|
|
||||||
|
|
||||||
if (sg_memcpy(request->sg_list, request->sg_count, &scsiData,
|
if (sg_memcpy(request->sg_list, request->sg_count, &scsiData,
|
||||||
sizeof(scsiData)) < B_OK) {
|
sizeof(scsiData)) < B_OK) {
|
||||||
@@ -960,6 +961,31 @@ AHCIPort::ScsiExecuteRequest(scsi_ccb *request)
|
|||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
TRACE("AHCIPort::ScsiExecuteRequest port %d unsupported request "
|
TRACE("AHCIPort::ScsiExecuteRequest port %d unsupported request "
|
||||||
"opcode 0x%02x\n", fIndex, request->cdb[0]);
|
"opcode 0x%02x\n", fIndex, request->cdb[0]);
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ private:
|
|||||||
bool fTestUnitReadyActive;
|
bool fTestUnitReadyActive;
|
||||||
bool fResetPort;
|
bool fResetPort;
|
||||||
bool fError;
|
bool fError;
|
||||||
|
bool fTrim;
|
||||||
|
|
||||||
volatile fis * fFIS;
|
volatile fis * fFIS;
|
||||||
volatile command_list_entry * fCommandList;
|
volatile command_list_entry * fCommandList;
|
||||||
|
|||||||
Reference in New Issue
Block a user