@ -228,84 +228,101 @@ int diskinfo_get_mounts(const char *base_disk, struct disk_mount *mounts_out, in
/*
* Extracts advanced ATA / SATA hardware descriptor properties from
* the provided native IDENTIFY parameter blocks .
* the provided native IDENTIFY parameter blocks using native libcam functions .
*/
static void parse_advanced_ata_fields ( struct ata_params * buf , struct disk_properties * props ) {
/* Base internal storage fields configuration */
uint16_t ff = buf - > form_factor ;
uint16_t major = buf - > version_major ;
uint16_t transport = buf - > transport_major ; /* Word 222: Transport Major Revision Number */
uint16_t sata_cap = buf - > satacapabilities ; /* Word 76: SATA Capabilities descriptor */
uint16_t sec = buf - > security_status ; /* Word 128: ATA Security Feature Set state */
static void parse_advanced_ata_fields ( struct ata_params * buf , struct disk_properties * props , float current_speed ) {
/* 1. Form Factor dimensions handling (Word 168) */
uint16_t ff = buf - > form_factor ;
if ( ff = = 2 ) strlcpy ( props - > form_factor , " 3.5 inches " , sizeof ( props - > form_factor ) ) ;
else if ( ff = = 3 ) strlcpy ( props - > form_factor , " 2.5 inches " , sizeof ( props - > form_factor ) ) ;
else if ( ff = = 4 ) strlcpy ( props - > form_factor , " 1.8 inches " , sizeof ( props - > form_factor ) ) ;
else if ( ff = = 5 ) strlcpy ( props - > form_factor , " less than 1.8 " , sizeof ( props - > form_factor ) ) ;
else strlcpy ( props - > form_factor , " N/A " , sizeof ( props - > form_factor ) ) ;
/* 2. Major ATA Version standard handling (Word 80 & Word 222 Transport Framework) */
if ( major = = 0xFFFF | | major = = 0x0000 ) {
fprintf ( stderr , " [WARNING] ATA Version unreadable: Word 80 reports invalid boundary (0x%04X) \n " , major ) ;
strlcpy ( props - > ata_version , " Unknown (Invalid Word 80) " , sizeof ( props - > ata_version ) ) ;
}
/*
* Detect actual ATA / ACS revision specification standard level by
* cross - verifying backward - compatible Word 80 flags against physical Word 222 transport bits .
*/
else if ( ( major & ( 1 < < 14 ) ) | | ( ( major & ( 1 < < 11 ) ) & & ( transport & 0x1000 ) & & ( transport & 0x0040 ) ) ) {
strlcpy ( props - > ata_version , " ACS-4 " , sizeof ( props - > ata_version ) ) ;
} else if ( ( major & ( 1 < < 13 ) ) | | ( ( major & ( 1 < < 10 ) ) & & ( transport & 0x1000 ) ) ) {
strlcpy ( props - > ata_version , " ACS-3 " , sizeof ( props - > ata_version ) ) ;
} else if ( major & ( 1 < < 12 ) ) {
strlcpy ( props - > ata_version , " ACS-2 " , sizeof ( props - > ata_version ) ) ;
} else if ( ( major & ( 1 < < 11 ) ) | | ( major & ( 1 < < 8 ) ) ) {
strlcpy ( props - > ata_version , " ATA8-ACS " , sizeof ( props - > ata_version ) ) ;
} else if ( major & ( 1 < < 7 ) ) {
strlcpy ( props - > ata_version , " ATA/ATAPI-7 " , sizeof ( props - > ata_version ) ) ;
} else if ( major & ( 1 < < 6 ) ) {
strlcpy ( props - > ata_version , " ATA/ATAPI-6 " , sizeof ( props - > ata_version ) ) ;
/* 2. Major ATA Version standard handling using native ata_version() from libcam.so */
int version = ata_version ( buf - > version_major ) ;
if ( buf - > version_major = = 0xFFFF | | buf - > version_major = = 0x0000 | | version < 0 ) {
strlcpy ( props - > ata_version , " Unknown " , sizeof ( props - > ata_version ) ) ;
} else {
snprintf ( props - > ata_version , sizeof ( props - > ata_version ) , " ATA Minor/Legacy (0x%04X) " , major ) ;
switch ( version ) {
case 0 :
strlcpy ( props - > ata_version , " ATA " , sizeof ( props - > ata_version ) ) ;
break ;
case 8 :
strlcpy ( props - > ata_version , " ATA8-ACS " , sizeof ( props - > ata_version ) ) ;
break ;
default :
if ( version < = 7 ) {
snprintf ( props - > ata_version , sizeof ( props - > ata_version ) , " ATA-%d " , version ) ;
} else {
snprintf ( props - > ata_version , sizeof ( props - > ata_version ) , " ACS-%d " , version - 7 ) ;
}
break ;
}
}
/* 3. Serial ATA Capabilities layout tracing (Word 76 & Word 222 Context) */
/* 3. Serial ATA Capabilities layout tracing matching camcontrol.c atacapprint() bitmasks (Word 76 & Word 222) */
uint16_t sata_cap = buf - > satacapabilities ;
uint16_t transport = buf - > transport_major ;
if ( sata_cap = = 0xFFFF | | sata_cap = = 0x0000 ) {
strlcpy ( props - > sata_version , " Not a SATA device " , sizeof ( props - > sata_version ) ) ;
} else {
const char * ver = " SATA " ;
const char * ver = NULL ;
float cap_speed = 1.5 ;
/* Extract logical transport revision from Word 222 using explicit camcontrol bit boundaries */
if ( transport ! = 0xFFFF & & transport ! = 0x0000 & & ( transport & 0x1000 ) ) {
if ( strcmp ( props - > ata_version , " ACS-4 " ) = = 0 ) {
if ( ( transport & ( 1 < < 6 ) ) & & ( transport & 0x0100 ) ) {
ver = " SATA 3.3 " ;
if ( transport & 0x0400 ) ver = " SATA 3.5 " ;
else if ( transport & 0x0200 ) ver = " SATA 3.4 " ;
else if ( transport & 0x0100 ) ver = " SATA 3.3 " ;
else if ( transport & 0x0080 ) ver = " SATA 3.2 " ;
else if ( transport & 0x0040 ) ver = " SATA 3.1 " ;
else if ( transport & 0x0020 ) ver = " SATA 3.0 " ;
else if ( transport & 0x0010 ) ver = " SATA 2.6 " ;
else if ( transport & 0x0008 ) ver = " SATA 2.5 " ;
}
/* Fallback to physical link generation signaling limits from Word 76 if transport is unmapped */
if ( ver = = NULL ) {
/*
* Enforce strict historical standard ceilings .
* ATA - 7 and older legacy specifications historically never supported anything beyond SATA 1. x .
* This prevents modern USB bridges from injecting fake SATA 3. x strings into classic drives .
*/
if ( strcmp ( props - > ata_version , " ATA-7 " ) = = 0 | | strncmp ( props - > ata_version , " ATA- " , 4 ) = = 0 ) {
ver = " SATA 1.x " ;
cap_speed = 1.5 ; /* Enforce strict hardware capability ceiling for legacy disk lines */
} else {
if ( sata_cap & 0x0006 ) {
ver = " SATA 3.x " ;
cap_speed = 6.0 ;
} else if ( sata_cap & 0x0004 ) {
ver = " SATA 2.x " ;
cap_speed = 3.0 ;
} else {
ver = " SATA 3.2 " ;
ver = " SATA 1.x " ;
cap_speed = 1.5 ;
}
} else if ( strcmp ( props - > ata_version , " ACS-3 " ) = = 0 ) {
ver = " SATA 3.1 " ;
} else {
if ( sata_cap & 0x0006 ) ver = " SATA 3.0 " ;
else if ( sata_cap & 0x0004 ) ver = " SATA 2.6 " ;
else if ( sata_cap & 0x0002 ) ver = " SATA 1.0a " ;
}
} else {
if ( sata_cap & 0x0006 ) ver = " SATA 3.0 " ;
else if ( sata_cap & 0x0004 ) ver = " SATA 2.6 " ;
else if ( sata_cap & 0x0002 ) ver = " SATA 1.0a " ;
/* Determine maximum capable speed rate from Word 76 capabilities for modern units */
if ( sata_cap & 0x0006 ) cap_speed = 6.0 ;
else if ( sata_cap & 0x0004 ) cap_speed = 3.0 ;
}
if ( sata_cap & 0x0006 ) {
snprintf ( props - > sata_version , sizeof ( props - > sata_version ) , " %s, 6.0 Gb/s " , ver ) ;
} else if ( sata_cap & 0x0004 ) {
snprintf ( props - > sata_version , sizeof ( props - > sata_version ) , " %s, 3.0 Gb/s " , ver ) ;
} else {
snprintf ( props - > sata_version , sizeof ( props - > sata_version ) , " %s, 1.5 Gb/s " , ver ) ;
/* If CAM transport layout parsing returned empty/restricted, sync with capable speed */
if ( current_speed < = 0.0 ) {
current_speed = cap_speed ;
}
/* Generate final elegant string matches smartctl style */
snprintf ( props - > sata_version , sizeof ( props - > sata_version ) ,
" %s, %.1f Gb/s (current: %.1f Gb/s) " , ver , cap_speed , current_speed ) ;
}
/* 4. ATA Security Feature Set state validation (Word 128) */
uint16_t sec = buf - > security_status ;
if ( ! ( sec & 0x0001 ) ) {
strlcpy ( props - > security_status , " Disabled " , sizeof ( props - > security_status ) ) ;
} else if ( sec & 0x0004 ) {
@ -353,12 +370,73 @@ static void query_cam_properties(
return ;
}
/* CRITICAL: Must use O_RDWR for transport-layer commands execution path to unlock */
cam_dev = cam_open_device ( base_disk , O_RDWR ) ;
if ( cam_dev = = NULL ) return ;
/* Extract current active signaling rate mirroring camcontrol.c camxferrate() flow exactly */
float current_speed = 0.0 ;
uint32_t speed = 0 ;
union ccb * ccb_cts = NULL ;
struct ccb_pathinq cpi ;
memset ( & cpi , 0 , sizeof ( struct ccb_pathinq ) ) ;
/* Step A: Fetch base speed path inquiry matching camcontrol get_cpi() */
union ccb * ccb_cpi = cam_getccb ( cam_dev ) ;
if ( ccb_cpi ! = NULL ) {
ccb_cpi - > ccb_h . func_code = XPT_PATH_INQ ;
ccb_cpi - > ccb_h . flags = CAM_DIR_NONE ;
ccb_cpi - > ccb_h . retry_count = 1 ;
ccb_cpi - > ccb_h . timeout = 1000 ;
if ( cam_send_ccb ( cam_dev , ccb_cpi ) = = 0 & & ( ccb_cpi - > ccb_h . status & CAM_STATUS_MASK ) = = CAM_REQ_CMP ) {
bcopy ( & ccb_cpi - > cpi , & cpi , sizeof ( struct ccb_pathinq ) ) ;
}
cam_freeccb ( ccb_cpi ) ;
}
/* Initialize baseline transfer speed value from Path Inquiry */
speed = cpi . base_transfer_speed ;
/* Step B: Query exact active transfer settings from the CAM layer */
ccb_cts = cam_getccb ( cam_dev ) ;
if ( ccb_cts ! = NULL ) {
ccb_cts - > ccb_h . func_code = XPT_GET_TRAN_SETTINGS ;
ccb_cts - > ccb_h . flags = CAM_DIR_NONE ;
ccb_cts - > ccb_h . retry_count = 1 ;
ccb_cts - > ccb_h . timeout = 1000 ;
ccb_cts - > ccb_h . target_id = cam_dev - > target_id ;
ccb_cts - > ccb_h . target_lun = cam_dev - > target_lun ;
ccb_cts - > cts . type = CTS_TYPE_CURRENT_SETTINGS ; /* Force runtime active link preference layout fetch */
if ( cam_send_ccb ( cam_dev , ccb_cts ) = = 0 & & ( ccb_cts - > ccb_h . status & CAM_STATUS_MASK ) = = CAM_REQ_CMP ) {
/* Execute exact transport specific branching copied from camcontrol.c source */
if ( ccb_cts - > cts . transport = = XPORT_ATA ) {
struct ccb_trans_settings_pata * pata = & ccb_cts - > cts . xport_specific . ata ;
if ( pata - > valid & CTS_ATA_VALID_MODE ) {
speed = ata_mode2speed ( pata - > mode ) ;
}
} else if ( ccb_cts - > cts . transport = = XPORT_SATA ) {
struct ccb_trans_settings_sata * sata = & ccb_cts - > cts . xport_specific . sata ;
if ( sata - > valid & CTS_SATA_VALID_REVISION ) {
speed = ata_revision2speed ( sata - > revision ) ;
}
} else if ( ccb_cts - > cts . transport = = XPORT_SAS ) {
struct ccb_trans_settings_sas * sas = & ccb_cts - > cts . xport_specific . sas ;
if ( sas - > valid & 0x01 ) { /* CTS_SAS_VALID_SPEED */
speed = sas - > bitrate ;
}
}
}
cam_freeccb ( ccb_cts ) ;
}
/* Map finalized speed KB/s calculation to human-readable Gb/s standard format */
uint32_t mb = speed / 1000 ;
if ( mb > = 550 ) current_speed = 6.0 ;
else if ( mb > = 280 ) current_speed = 3.0 ;
else if ( mb > = 140 ) current_speed = 1.5 ;
/* Allocate CCB structure for standard IDENTIFY command execution path below */
ccb = cam_getccb ( cam_dev ) ;
if ( ccb = = NULL ) {
fprintf ( stderr , " [ERROR] %s: Failed to allocate CAM CCB structure \n " , base_disk ) ;
cam_close_device ( cam_dev ) ;
return ;
}
@ -477,7 +555,7 @@ static void query_cam_properties(
}
/* Parse advanced hardware descriptors from the verified buffer */
parse_advanced_ata_fields ( ident_buf , props ) ;
parse_advanced_ata_fields ( ident_buf , props , current_speed ) ;
/* Parse Sector Sizes (Word 106: Physical sector size / Advanced Format) */
if ( ( ident_buf - > pss & 0x4000 ) & & ( ident_buf - > pss & 0x2000 ) ) {
@ -552,7 +630,7 @@ static void query_cam_properties(
}
/* Parse advanced hardware descriptors from the direct AHCI buffer */
parse_advanced_ata_fields ( ident_buf , props ) ;
parse_advanced_ata_fields ( ident_buf , props , current_speed ) ;
/* Parse Sector Sizes (Word 106: Physical sector size / Advanced Format) */
if ( ( ident_buf - > pss & 0x4000 ) & & ( ident_buf - > pss & 0x2000 ) ) {