ahci: Dump some TRIM device specifics.
* Maximum LBA range blocks per trim are now read, but not yet taken into account. * Minor cleanup.
This commit is contained in:
@@ -124,7 +124,21 @@ typedef struct ata_device_infoblock {
|
|||||||
uint16 recommended_multiword_dma_cycle_time;
|
uint16 recommended_multiword_dma_cycle_time;
|
||||||
uint16 min_pio_cycle_time;
|
uint16 min_pio_cycle_time;
|
||||||
uint16 min_pio_cycle_time_io_ready;
|
uint16 min_pio_cycle_time_io_ready;
|
||||||
uint16 word_69_70_reserved[2];
|
LBITFIELD12(
|
||||||
|
word_69_bit_0_4_reserved : 5,
|
||||||
|
supports_read_zero_after_trim : 1,
|
||||||
|
supports_ata28_commands : 1,
|
||||||
|
word_69_bit_7_reserved : 1,
|
||||||
|
supports_download_microcode_dma : 1,
|
||||||
|
supports_set_max_password_unlock_dma : 1,
|
||||||
|
supports_write_buffer_dma : 1,
|
||||||
|
supports_read_buffer_dma : 1,
|
||||||
|
supports_device_configuration_identify_dma : 1,
|
||||||
|
supports_long_physical_sector_error_reporting : 1,
|
||||||
|
supports_deterministic_read_after_trim : 1,
|
||||||
|
supports_cfast_specification : 1
|
||||||
|
);
|
||||||
|
uint16 word_70_reserved;
|
||||||
uint16 atapi_packet_received_to_bus_release_time_ns;
|
uint16 atapi_packet_received_to_bus_release_time_ns;
|
||||||
uint16 atapi_service_command_to_busy_clear_time_ns;
|
uint16 atapi_service_command_to_busy_clear_time_ns;
|
||||||
uint16 word_71_74_reserved[2];
|
uint16 word_71_74_reserved[2];
|
||||||
@@ -136,10 +150,9 @@ typedef struct ata_device_infoblock {
|
|||||||
|
|
||||||
uint16 word_76_79_reserved[4];
|
uint16 word_76_79_reserved[4];
|
||||||
|
|
||||||
LBITFIELD15(
|
LBITFIELD14(
|
||||||
word_80_bit_0_reserved : 1,
|
word_80_bit_0_reserved : 1,
|
||||||
word_80_bot_1_2_obsolete : 2,
|
word_80_bit_1_3_obsolete : 3,
|
||||||
supports_ata_3 : 1,
|
|
||||||
supports_ata_atapi_4 : 1,
|
supports_ata_atapi_4 : 1,
|
||||||
supports_ata_atapi_5 : 1,
|
supports_ata_atapi_5 : 1,
|
||||||
supports_ata_atapi_6 : 1,
|
supports_ata_atapi_6 : 1,
|
||||||
@@ -294,7 +307,8 @@ typedef struct ata_device_infoblock {
|
|||||||
|
|
||||||
uint16 word_95_99_reserved[5];
|
uint16 word_95_99_reserved[5];
|
||||||
uint64 lba48_sector_count;
|
uint64 lba48_sector_count;
|
||||||
uint16 word_104_105_reserved[2];
|
uint16 word_104_reserved;
|
||||||
|
uint16 max_data_set_management_lba_range_blocks;
|
||||||
|
|
||||||
LBITFIELD6(
|
LBITFIELD6(
|
||||||
logical_sectors_per_physical_sector : 4, // 2^x exponent
|
logical_sectors_per_physical_sector : 4, // 2^x exponent
|
||||||
|
|||||||
@@ -615,11 +615,21 @@ AHCIPort::ScsiInquiry(scsi_ccb* request)
|
|||||||
fSectorCount = ataData.SectorCount(fUse48BitCommands, true);
|
fSectorCount = ataData.SectorCount(fUse48BitCommands, true);
|
||||||
fSectorSize = ataData.SectorSize();
|
fSectorSize = ataData.SectorSize();
|
||||||
fTrimSupported = ataData.data_set_management_support;
|
fTrimSupported = ataData.data_set_management_support;
|
||||||
|
fMaxTrimRangeBlocks = B_LENDIAN_TO_HOST_INT16(
|
||||||
|
ataData.max_data_set_management_lba_range_blocks);
|
||||||
TRACE("lba %d, lba48 %d, fUse48BitCommands %d, sectors %" B_PRIu32
|
TRACE("lba %d, lba48 %d, fUse48BitCommands %d, sectors %" B_PRIu32
|
||||||
", sectors48 %" B_PRIu64 ", size %" B_PRIu64 "\n",
|
", sectors48 %" B_PRIu64 ", size %" B_PRIu64 "\n",
|
||||||
ataData.dma_supported != 0, ataData.lba48_supported != 0,
|
ataData.dma_supported != 0, ataData.lba48_supported != 0,
|
||||||
fUse48BitCommands, ataData.lba_sector_count,
|
fUse48BitCommands, ataData.lba_sector_count,
|
||||||
ataData.lba48_sector_count, fSectorCount * fSectorSize);
|
ataData.lba48_sector_count, fSectorCount * fSectorSize);
|
||||||
|
if (fTrimSupported) {
|
||||||
|
bool deterministic = ataData.supports_deterministic_read_after_trim;
|
||||||
|
TRACE("trim supported, %" B_PRIu32 " ranges blocks, reads are "
|
||||||
|
"%sdeterministic%s.\n", fMaxTrimRangeBlocks,
|
||||||
|
deterministic ? "" : "non-", deterministic
|
||||||
|
? (ataData.supports_read_zero_after_trim
|
||||||
|
? ", zero" : ", random") : "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@@ -803,8 +813,6 @@ AHCIPort::ScsiReadWrite(scsi_ccb* request, uint64 lba, size_t sectorCount,
|
|||||||
void
|
void
|
||||||
AHCIPort::ScsiUnmap(scsi_ccb* request, scsi_unmap_parameter_list* unmapBlocks)
|
AHCIPort::ScsiUnmap(scsi_ccb* request, scsi_unmap_parameter_list* unmapBlocks)
|
||||||
{
|
{
|
||||||
TRACE("%s unimplemented: TRIM call\n", __func__);
|
|
||||||
|
|
||||||
// Determine how many ranges we'll need
|
// Determine how many ranges we'll need
|
||||||
// We assume that the SCSI unmap ranges cannot be merged together
|
// We assume that the SCSI unmap ranges cannot be merged together
|
||||||
uint32 scsiRangeCount = B_BENDIAN_TO_HOST_INT16(
|
uint32 scsiRangeCount = B_BENDIAN_TO_HOST_INT16(
|
||||||
@@ -851,7 +859,7 @@ AHCIPort::ScsiUnmap(scsi_ccb* request, scsi_unmap_parameter_list* unmapBlocks)
|
|||||||
sreq.WaitForCompletion();
|
sreq.WaitForCompletion();
|
||||||
|
|
||||||
if ((sreq.CompletionStatus() & ATA_ERR) != 0) {
|
if ((sreq.CompletionStatus() & ATA_ERR) != 0) {
|
||||||
TRACE("trim failed (%" B_PRIu32 " ranges)!", lbaRangeCount);
|
TRACE("trim failed (%" B_PRIu32 " ranges)!\n", lbaRangeCount);
|
||||||
request->subsys_status = SCSI_REQ_CMP_ERR;
|
request->subsys_status = SCSI_REQ_CMP_ERR;
|
||||||
} else
|
} else
|
||||||
request->subsys_status = SCSI_REQ_CMP;
|
request->subsys_status = SCSI_REQ_CMP;
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ private:
|
|||||||
bool fResetPort;
|
bool fResetPort;
|
||||||
bool fError;
|
bool fError;
|
||||||
bool fTrimSupported;
|
bool fTrimSupported;
|
||||||
|
uint32 fMaxTrimRangeBlocks;
|
||||||
|
|
||||||
volatile fis * fFIS;
|
volatile fis * fFIS;
|
||||||
volatile command_list_entry * fCommandList;
|
volatile command_list_entry * fCommandList;
|
||||||
|
|||||||
Reference in New Issue
Block a user