ahci: Pushed TRIM support a tiny bit further.

* Now doesn't do anything on SCSI_OP_UNMAP, instead of doing nothing on
  SCSI_OP_WRITE_SAME_16.
This commit is contained in:
Axel Dörfler 2013-08-15 01:40:12 +02:00
parent 99086aa323
commit 33945c5c89
2 changed files with 37 additions and 16 deletions

View File

@ -51,7 +51,7 @@ AHCIPort::AHCIPort(AHCIController *controller, int index)
fTestUnitReadyActive(false),
fResetPort(false),
fError(false),
fTrim(false)
fTrimSupported(false)
{
B_INITIALIZE_SPINLOCK(&fSpinlock);
fRequestSem = create_sem(1, "ahci request");
@ -604,7 +604,7 @@ AHCIPort::ScsiInquiry(scsi_ccb *request)
if (!fIsATAPI) {
fSectorCount = ataData.SectorCount(fUse48BitCommands, true);
fSectorSize = ataData.SectorSize();
fTrim = ataData.data_set_management_support;
fTrimSupported = ataData.data_set_management_support;
TRACE("lba %d, lba48 %d, fUse48BitCommands %d, sectors %" B_PRIu32
", sectors48 %" B_PRIu64 ", size %" B_PRIu64 "\n",
ataData.dma_supported != 0, ataData.lba48_supported != 0,
@ -634,7 +634,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", fTrim ? "yes" : "no");
TRACE("trim support: %s\n", fTrimSupported ? "yes" : "no");
// There's not enough space to fit all of the data in. ATA has 40 bytes for
// the model number, 20 for the serial number and another 8 for the
@ -786,6 +786,23 @@ AHCIPort::ScsiReadWrite(scsi_ccb *request, uint64 lba, size_t sectorCount,
}
void
AHCIPort::ScsiUnmap(scsi_ccb* request, scsi_unmap_parameter_list* unmapBlocks)
{
TRACE("%s unimplemented: TRIM call\n", __func__);
sata_request* sreq = new(std::nothrow) sata_request(request);
if (sreq == NULL) {
TRACE("out of memory when allocating unmap request\n");
request->subsys_status = SCSI_REQ_ABORTED;
gSCSI->finished(request, 1);
return;
}
delete sreq;
}
void
AHCIPort::ExecuteSataRequest(sata_request *request, bool isWrite)
{
@ -1018,12 +1035,11 @@ AHCIPort::ScsiExecuteRequest(scsi_ccb *request)
}
break;
}
case SCSI_OP_WRITE_SAME_16:
case SCSI_OP_UNMAP:
{
const scsi_cmd_wsame_16 *cmd = (const scsi_cmd_wsame_16 *)request->cdb;
const scsi_cmd_unmap* cmd = (const scsi_cmd_unmap*)request->cdb;
// SCSI unmap is used for trim, otherwise we don't support it
if (!cmd->unmap) {
if (!fTrimSupported) {
TRACE("%s port %d: unsupported request opcode 0x%02x\n",
__func__, fIndex, request->cdb[0]);
request->subsys_status = SCSI_REQ_ABORTED;
@ -1031,16 +1047,19 @@ AHCIPort::ScsiExecuteRequest(scsi_ccb *request)
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.
scsi_unmap_parameter_list* unmapBlocks
= (scsi_unmap_parameter_list*)request->data;
if (unmapBlocks == NULL
|| B_BENDIAN_TO_HOST_INT16(cmd->length) != request->data_length
|| B_BENDIAN_TO_HOST_INT16(unmapBlocks->data_length)
!= request->data_length - 1) {
TRACE("%s port %d: invalid unmap parameter data length\n",
__func__, fIndex);
request->subsys_status = SCSI_REQ_ABORTED;
gSCSI->finished(request, 1);
} else {
ScsiUnmap(request, unmapBlocks);
}
gSCSI->finished(request, 1);
break;
}
default:

View File

@ -36,6 +36,8 @@ private:
void ScsiReadCapacity16(scsi_ccb *request);
void ScsiReadWrite(scsi_ccb *request, uint64 lba, size_t sectorCount, bool isWrite);
void ScsiSynchronizeCache(scsi_ccb *request);
void ScsiUnmap(scsi_ccb* request,
struct scsi_unmap_parameter_list* unmapBlocks);
void ExecuteSataRequest(sata_request *request, bool isWrite = false);
@ -71,7 +73,7 @@ private:
bool fTestUnitReadyActive;
bool fResetPort;
bool fError;
bool fTrim;
bool fTrimSupported;
volatile fis * fFIS;
volatile command_list_entry * fCommandList;