From efc3172fbac774eb1eab69ae2b25613eb4d90318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sat, 9 Nov 2013 23:04:54 +0100 Subject: [PATCH] ahci: Dump some TRIM device specifics. * Maximum LBA range blocks per trim are now read, but not yet taken into account. * Minor cleanup. --- .../kernel/bus_managers/ata/ATAInfoBlock.h | 24 +++++++++++++++---- .../kernel/busses/scsi/ahci/ahci_port.cpp | 14 ++++++++--- .../kernel/busses/scsi/ahci/ahci_port.h | 1 + 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/add-ons/kernel/bus_managers/ata/ATAInfoBlock.h b/src/add-ons/kernel/bus_managers/ata/ATAInfoBlock.h index 402fd20323..9dadb91676 100644 --- a/src/add-ons/kernel/bus_managers/ata/ATAInfoBlock.h +++ b/src/add-ons/kernel/bus_managers/ata/ATAInfoBlock.h @@ -124,7 +124,21 @@ typedef struct ata_device_infoblock { uint16 recommended_multiword_dma_cycle_time; uint16 min_pio_cycle_time; 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_service_command_to_busy_clear_time_ns; uint16 word_71_74_reserved[2]; @@ -136,10 +150,9 @@ typedef struct ata_device_infoblock { uint16 word_76_79_reserved[4]; - LBITFIELD15( + LBITFIELD14( word_80_bit_0_reserved : 1, - word_80_bot_1_2_obsolete : 2, - supports_ata_3 : 1, + word_80_bit_1_3_obsolete : 3, supports_ata_atapi_4 : 1, supports_ata_atapi_5 : 1, supports_ata_atapi_6 : 1, @@ -294,7 +307,8 @@ typedef struct ata_device_infoblock { uint16 word_95_99_reserved[5]; uint64 lba48_sector_count; - uint16 word_104_105_reserved[2]; + uint16 word_104_reserved; + uint16 max_data_set_management_lba_range_blocks; LBITFIELD6( logical_sectors_per_physical_sector : 4, // 2^x exponent 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 c68af4b411..7d6ca45556 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp @@ -615,11 +615,21 @@ AHCIPort::ScsiInquiry(scsi_ccb* request) fSectorCount = ataData.SectorCount(fUse48BitCommands, true); fSectorSize = ataData.SectorSize(); 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 ", sectors48 %" B_PRIu64 ", size %" B_PRIu64 "\n", ataData.dma_supported != 0, ataData.lba48_supported != 0, fUse48BitCommands, ataData.lba_sector_count, 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 @@ -803,8 +813,6 @@ 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__); - // Determine how many ranges we'll need // We assume that the SCSI unmap ranges cannot be merged together uint32 scsiRangeCount = B_BENDIAN_TO_HOST_INT16( @@ -851,7 +859,7 @@ AHCIPort::ScsiUnmap(scsi_ccb* request, scsi_unmap_parameter_list* unmapBlocks) sreq.WaitForCompletion(); 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; } else request->subsys_status = SCSI_REQ_CMP; 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 f89a62246e..c08ea54a1f 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h @@ -74,6 +74,7 @@ private: bool fResetPort; bool fError; bool fTrimSupported; + uint32 fMaxTrimRangeBlocks; volatile fis * fFIS; volatile command_list_entry * fCommandList;