#ifndef ATA_INFOBLOCK_H
#define ATA_INFOBLOCK_H
#include <lendian_bitfield.h>
#define ATA_WORD_0_ATA_DEVICE 0
#define ATA_WORD_0_ATAPI_DEVICE 2
#define ATA_WORD_0_CFA_MAGIC 0x848a
typedef struct ata_device_infoblock {
union {
struct {
B_LBITFIELD16_8(
word_0_bit_0_reserved : 1,
word_0_bit_1_retired : 1,
response_incomplete : 1,
word_0_bit_3_5_retired : 3,
word_0_bit_6_obsolete : 1,
removable_media_device : 1,
word_0_bit_8_14_retired : 7,
ata_device : 1
);
} ata;
struct {
B_LBITFIELD16_8(
packet_length : 2,
response_incomplete : 1,
word_0_bit_3_4_reserved : 2,
data_request_delay : 2,
removable_media_device : 1,
command_packet_set : 5,
word_0_bit_13_reserved : 1,
atapi_device : 2
);
} atapi;
uint16 raw;
} word_0;
uint16 word_1_obsolete;
uint16 specific_configuration;
uint16 word_3_obsolete;
uint16 word_4_5_retired[2];
uint16 word_6_obsolete;
uint16 word_7_8_reserved_compact_flash_assoc[2];
uint16 word_9_retired;
char serial_number[20];
uint16 word_20_21_retired[2];
uint16 word_22_obsolete;
char firmware_revision[8];
char model_number[40];
B_LBITFIELD16_2(
max_sectors_per_interrupt : 8,
word_47_bit_8_15_80h : 8
);
uint16 word_48_reserved;
B_LBITFIELD16_9(
word_49_bit_0_7_retired : 8,
dma_supported : 1,
lba_supported : 1,
io_ready_disable : 1,
io_ready_supported : 1,
word_19_bit_12_obsolete : 1,
standby_timer_standard : 1,
atapi_command_queuing_supported : 1,
atapi_interleaved_dma_supported : 1
);
B_LBITFIELD16_5(
standby_timer_value_min : 1,
word_50_bit_1_obsolete : 1,
word_50_bit_2_13_reserved : 12,
word_50_bit_14_one : 1,
word_50_bit_15_zero : 1
);
uint16 word_51_52_obsolete[2];
B_LBITFIELD16_4(
word_53_bit_0_obsolete : 1,
word_64_70_valid : 1,
word_88_valid : 1,
word_53_bit_3_15 : 13
);
uint16 word_54_58_obsolete[5];
B_LBITFIELD16_3(
current_sectors_per_interrupt : 8,
multiple_sector_setting_valid : 1,
word_59_bit_9_15_reserved : 7
);
uint32 lba_sector_count;
uint16 word_62_obsolete;
B_LBITFIELD16_8(
multiword_dma_0_supported : 1,
multiword_dma_1_supported : 1,
multiword_dma_2_supported : 1,
word_63_bit_3_7_resereved : 5,
multiword_dma_0_selected : 1,
multiword_dma_1_selected : 1,
multiword_dma_2_selected : 1,
word_63_bit_11_15_reserved : 5
);
B_LBITFIELD16_2(
pio_modes_supported : 8,
word_64_bit_8_15_reserved : 8
);
uint16 min_multiword_dma_cycle_time;
uint16 recommended_multiword_dma_cycle_time;
uint16 min_pio_cycle_time;
uint16 min_pio_cycle_time_io_ready;
B_LBITFIELD16_12(
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];
B_LBITFIELD16_2(
max_queue_depth_minus_one : 5,
word_75_bit_5_15_reserved : 11
);
uint16 word_76_79_reserved[4];
B_LBITFIELD16_14(
word_80_bit_0_reserved : 1,
word_80_bit_1_3_obsolete : 3,
supports_ata_atapi_4 : 1,
supports_ata_atapi_5 : 1,
supports_ata_atapi_6 : 1,
supports_ata_atapi_7 : 1,
supports_ata_atapi_8 : 1,
supports_ata_atapi_9 : 1,
supports_ata_atapi_10 : 1,
supports_ata_atapi_11 : 1,
supports_ata_atapi_12 : 1,
supports_ata_atapi_13 : 1,
supports_ata_atapi_14 : 1,
word_80_bit_15_reserved : 1
);
uint16 minor_version;
B_LBITFIELD16_16(
smart_supported : 1,
security_mode_supported : 1,
removable_media_supported : 1,
mandatory_power_management_supported : 1,
packet_supported : 1,
write_cache_supported : 1,
look_ahead_supported : 1,
release_interrupt_supported : 1,
service_interrupt_supported : 1,
device_reset_supported : 1,
host_protected_area_supported : 1,
word_82_bit_11_obsolete : 1,
write_buffer_command_supported : 1,
read_buffer_command_supported : 1,
nop_supported : 1,
word_82_bit_15_obsolete : 1
);
B_LBITFIELD16_16(
download_microcode_supported : 1,
read_write_dma_queued_supported : 1,
compact_flash_assoc_supported : 1,
advanced_power_management_supported : 1,
removable_media_status_supported : 1,
power_up_in_standby_supported : 1,
set_features_required_for_spinup : 1,
word_83_bit_7_reserved : 1,
set_max_security_extension_supported : 1,
automatic_acoustic_management_supported : 1,
lba48_supported : 1,
device_configuration_overlay_supported : 1,
mandatory_flush_cache_supported : 1,
flush_cache_ext_supported : 1,
word_83_bit_14_one : 1,
word_83_bit_15_zero : 1
);
B_LBITFIELD16_9(
smart_error_logging_supported : 1,
smart_self_test_supported : 1,
media_serial_number_supported : 1,
media_card_pass_through_supported : 1,
word_84_bit_4_reserved : 1,
general_purpose_logging_supported : 1,
word_84_bit_6_13_reserved : 8,
word_84_bit_14_one : 1,
word_84_bit_15_zero : 1
);
B_LBITFIELD16_16(
smart_enabled : 1,
security_mode_enabled : 1,
removable_media_enabled : 1,
mandatory_power_management_enabled : 1,
packet_enabled : 1,
write_cache_enabled : 1,
look_ahead_enabled : 1,
release_interrupt_enabled : 1,
service_interrupt_enabled : 1,
device_reset_enabled : 1,
host_protected_area_enabled : 1,
word_85_bit_11_obsolete : 1,
write_buffer_command_enabled : 1,
read_buffer_command_enabled : 1,
nop_enabled : 1,
word_85_bit_15_obsolete : 1
);
B_LBITFIELD16_15(
download_microcode_supported_2 : 1,
read_write_dma_queued_supported_2 : 1,
compact_flash_assoc_enabled : 1,
advanced_power_management_enabled : 1,
removable_media_status_enabled : 1,
power_up_in_standby_enabled : 1,
set_features_required_for_spinup_2 : 1,
word_86_bit_7_reserved : 1,
set_max_security_extension_enabled : 1,
automatic_acoustic_management_enabled : 1,
lba48_supported_2 : 1,
device_configuration_overlay_supported_2: 1,
mandatory_flush_cache_supported_2 : 1,
flush_cache_ext_supported_2 : 1,
word_86_bit_14_15_reserved : 2
);
B_LBITFIELD16_9(
smart_error_logging_supported_2 : 1,
smart_self_test_supported_2 : 1,
media_serial_number_valid : 1,
media_card_pass_through_enabled : 1,
word_87_bit_4_reserved : 1,
general_purpose_logging_supported_2 : 1,
word_87_bit_6_13_reserved : 8,
word_87_bit_14_one : 1,
word_87_bit_15_zero : 1
);
B_LBITFIELD16_16(
ultra_dma_0_supported : 1,
ultra_dma_1_supported : 1,
ultra_dma_2_supported : 1,
ultra_dma_3_supported : 1,
ultra_dma_4_supported : 1,
ultra_dma_5_supported : 1,
ultra_dma_6_supported : 1,
word_88_bit_7_reserved : 1,
ultra_dma_0_selected : 1,
ultra_dma_1_selected : 1,
ultra_dma_2_selected : 1,
ultra_dma_3_selected : 1,
ultra_dma_4_selected : 1,
ultra_dma_5_selected : 1,
ultra_dma_6_selected : 1,
word_88_bit_15_reserved : 1
);
uint16 security_erase_unit_duration;
uint16 enhanced_security_erase_duration;
uint16 current_advanced_power_management_value;
uint16 master_password_revision_code;
B_LBITFIELD16_5(
device_0_hardware_reset_result : 8,
device_1_hardware_reset_result : 5,
cable_id_detected : 1,
word_93_bit_14_one : 1,
word_93_bit_15_zero : 1
);
B_LBITFIELD16_2(
current_acoustic_management_value : 8,
recommended_acoustic_management_value : 8
);
uint16 word_95_99_reserved[5];
uint64 lba48_sector_count;
uint16 word_104_reserved;
uint16 max_data_set_management_lba_range_blocks;
B_LBITFIELD16_6(
logical_sectors_per_physical_sector : 4,
word_106_bit_4_11_reserved : 8,
logical_sector_not_512_bytes : 1,
multiple_logical_per_physical_sectors : 1,
word_106_bit_14_one : 1,
word_106_bit_15_zero : 1
);
uint16 word_107_116_reserved[10];
uint32 logical_sector_size;
uint16 word_119_126_reserved[8];
B_LBITFIELD16_2(
removable_media_status_supported_2 : 2,
word_127_bit_2_15_reserved : 14
);
B_LBITFIELD16_9(
security_supported : 1,
security_enabled : 1,
security_locked : 1,
security_frozen : 1,
security_count_expired : 1,
ehnaced_security_erase_supported : 1,
word_128_bit_6_7_reserved : 2,
security_level : 1,
word_128_bit_9_15 : 7
);
uint16 word_129_159_vendor_specific[31];
B_LBITFIELD16_5(
cfa_max_current_milli_ampers : 12,
cfa_power_mode_1_disabled : 1,
cfa_power_mode_1_required : 1,
word_160_bit_14_reserved : 1,
word_160_supported : 1
);
uint16 word_161_167_reserved_compact_flash_assoc[7];
B_LBITFIELD16_2(
device_nominal_form_factor : 4,
word_168_bits_4_15_reserved : 12
);
B_LBITFIELD16_2(
data_set_management_support : 1,
word_169_bits_1_15_reserved : 15
);
uint16 additional_product_identifier[4];
uint16 word_174_175_reserved[2];
uint16 current_media_serial_number[30];
uint16 word_206_208_reserved[3];
B_LBITFIELD16_3(
logical_sector_offset : 14,
word_209_bit_14_one : 1,
word_209_bit_15_zero : 1
);
uint16 word_210_254_reserved[45];
B_LBITFIELD16_2(
signature : 8,
checksum : 8
);
uint64 SectorCount(bool& use48Bits, bool force)
{
if (lba48_supported && lba48_sector_count >= lba_sector_count) {
use48Bits = true;
return lba48_sector_count;
}
use48Bits = force ? lba48_supported : false;
return lba_sector_count;
}
uint32 PhysicalSectorSize()
{
uint32 blockSize = 512;
if (word_106_bit_14_one && !word_106_bit_15_zero) {
if (logical_sector_not_512_bytes)
blockSize = logical_sector_size * 2;
if (multiple_logical_per_physical_sectors)
return blockSize << logical_sectors_per_physical_sector;
}
return blockSize;
}
uint32 SectorSize()
{
if (word_106_bit_14_one && !word_106_bit_15_zero) {
if (logical_sector_not_512_bytes)
return logical_sector_size * 2;
}
return 512;
}
uint32 BlockOffset()
{
if (word_209_bit_14_one && !word_209_bit_15_zero) {
return logical_sector_offset;
}
return 0;
}
} _PACKED ata_device_infoblock;
#endif