A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd

ata: Rework how flushing, sleeping, and power off interacts

* FLUSH_EXT is used if featureflag is set and we are using LBA48
(unconditionally used for CE-ATA on ipod6g)
* FLUSH is used if featureflag is set (ATA6+) or if device claims to be ATA5+

* Rename ata_disk_can_power_off() to ata_disk_can_sleep() as that is
what it actually tests for. Only use it to gate issuing the
STANDBY IMMEDIATE command.
* Restore behavior of ata_disk_is_active() to return 1 if drive is
"spinning" or powered up.
* Allow poweroff if drive claims PM support OR we are able to issue
FLUSH/FLUSH_EXT commands.

* Added ata_flush() to explicitly trigger a flush operation, and hook it
up to storage_flush() in the device shutdown path. (Flushes were
only previously used in the storage device power management path)

* After issuing all settings, re-issue IDENTIFY_DEVICE to make sure
it reflects everything we've enabled.

* Update manual section on Flash/SSD mods.

Change-Id: I6770a54ef3a87f4c47120bcb96c944a6652f1bf4

+110 -66
+2
apps/debug_menu.c
··· 1481 1481 i = identify_info[83] & (1<<9); 1482 1482 simplelist_addline( 1483 1483 "Noise mgmt: %s", i ? "enabled" : "unsupported"); 1484 + simplelist_addline( 1485 + "Flush cache: %s", identify_info[83] & (1<<13) ? "extended" : identify_info[83] & (1<<12) ? "standard" : identify_info[80] >= (1<<5) ? "ATA-5" : "unsupported"); 1484 1486 i = identify_info[82] & (1<<6); 1485 1487 simplelist_addline( 1486 1488 "Read-ahead: %s", i ? "enabled" : "unsupported");
+37 -15
firmware/drivers/ata.c
··· 103 103 #ifdef HAVE_LBA48 104 104 static bool lba48 = false; /* set for 48 bit addressing */ 105 105 #endif 106 + static bool canflush = true; 106 107 107 108 static long last_disk_activity = -1; 108 109 #ifdef HAVE_ATA_POWER_OFF ··· 139 140 static inline void keep_ata_active(void) 140 141 { 141 142 last_disk_activity = current_tick; 142 - } 143 - 144 - static inline void schedule_ata_sleep(long from_now) 145 - { 146 - last_disk_activity = current_tick - sleep_timeout + from_now; 147 143 } 148 144 149 145 static inline bool ata_sleep_timed_out(void) ··· 223 219 static int ata_perform_sleep(void) 224 220 { 225 221 /* If device doesn't support PM features, don't try to sleep. */ 226 - if (!ata_disk_can_poweroff()) 222 + if (!ata_disk_can_sleep()) 227 223 return 0; // XXX or return a failure? 228 224 229 225 logf("ata SLEEP %ld", current_tick); ··· 257 253 { 258 254 uint8_t cmd; 259 255 260 - if (identify_info[83] & (1 << 13)) { 261 - cmd = CMD_FLUSH_CACHE_EXT; 256 + if (!canflush) { 257 + return 0; 258 + } else if (lba48 && identify_info[83] & (1 << 13)) { 259 + cmd = CMD_FLUSH_CACHE_EXT; /* Flag, optional, ATA-6 and up, for use with LBA48 devices */ 262 260 } else if (identify_info[83] & (1 << 12)) { 263 - cmd = CMD_FLUSH_CACHE; 261 + cmd = CMD_FLUSH_CACHE; /* Flag, mandatory, ATA-6 and up */ 262 + } else if (identify_info[80] >= (1 << 5)) { /* Use >= instead of '&' because bits lower than the latest standard we support don't have to be set */ 263 + cmd = CMD_FLUSH_CACHE; /* No flag, mandatory, ATA-5 (Optional for ATA-4) */ 264 264 } else { 265 265 /* If neither (mandatory!) command is supported 266 266 then don't issue it. */ 267 + canflush = 0; 267 268 return 0; 268 269 } 269 270 ··· 286 287 return 0; 287 288 } 288 289 290 + int ata_flush(void) 291 + { 292 + if (ata_state >= ATA_SPINUP) { 293 + mutex_lock(&ata_mtx); 294 + ata_perform_flush_cache(); 295 + mutex_unlock(&ata_mtx); 296 + } 297 + return 0; 298 + } 299 + 289 300 static ICODE_ATTR int wait_for_start_of_transfer(void) 290 301 { 291 302 if (!wait_for_bsy()) ··· 844 855 845 856 bool ata_disk_is_active(void) 846 857 { 847 - return ata_disk_can_poweroff() ? (ata_state >= ATA_SPINUP) : 0; 858 + return (ata_state >= ATA_SPINUP); 848 859 } 849 860 850 861 void ata_sleepnow(void) ··· 856 867 if (!ata_perform_flush_cache() && !ata_perform_sleep()) { 857 868 ata_state = ATA_SLEEPING; 858 869 #ifdef HAVE_ATA_POWER_OFF 859 - if (ata_disk_can_poweroff()) 870 + if (ata_disk_can_sleep() || canflush) { 860 871 power_off_tick = current_tick + ATA_POWER_OFF_TIMEOUT; 872 + } 861 873 #endif 862 874 } 863 875 } ··· 967 979 if (set_multiple_mode(multisectors)) 968 980 return -3; 969 981 982 + if (identify()) 983 + return -2; 984 + 970 985 if (freeze_lock()) 971 986 return -4; 972 987 ··· 1017 1032 if (set_multiple_mode(multisectors)) 1018 1033 return -3; 1019 1034 1035 + if (identify()) 1036 + return -2; 1037 + 1020 1038 if (freeze_lock()) 1021 1039 return -4; 1022 1040 ··· 1255 1273 } 1256 1274 1257 1275 rc = identify(); 1258 - 1259 1276 if (rc) { 1260 1277 rc = -40 + rc; 1261 1278 goto error; ··· 1280 1297 #endif /* HAVE_LBA48 */ 1281 1298 1282 1299 rc = freeze_lock(); 1283 - 1284 1300 if (rc) { 1285 1301 rc = -50 + rc; 1286 1302 goto error; 1287 1303 } 1288 1304 1289 - rc = set_features(); // rror codes are between -1 and -49 1305 + rc = set_features(); // error codes are between -1 and -49 1290 1306 if (rc) { 1291 1307 rc = -60 + rc; 1292 1308 goto error; ··· 1324 1340 rc = set_multiple_mode(multisectors); 1325 1341 if (rc) 1326 1342 rc = -100 + rc; 1343 + 1344 + rc = identify(); 1345 + if (rc) { 1346 + rc = -40 + rc; 1347 + goto error; 1348 + } 1327 1349 1328 1350 error: 1329 1351 mutex_unlock(&ata_mtx); ··· 1440 1462 ata_sleepnow(); 1441 1463 } 1442 1464 else if (id == Q_STORAGE_SLEEP) { 1443 - schedule_ata_sleep(HZ/5); 1465 + last_disk_activity = current_tick - sleep_timeout + HZ / 5; 1444 1466 } 1445 1467 #ifndef USB_NONE 1446 1468 else if (id == SYS_USB_CONNECTED) {
+4 -2
firmware/export/ata.h
··· 208 208 ); 209 209 } 210 210 211 - /* Returns 1 if the drive can be powered off safely */ 212 - static inline int ata_disk_can_poweroff(void) 211 + /* Returns 1 if the drive supports power management commands */ 212 + static inline int ata_disk_can_sleep(void) 213 213 { 214 214 unsigned short *identify_info = ata_get_identify(); 215 215 /* Only devices that claim to support PM can be safely powered off. 216 216 This notably excludes the various SD adapters! */ 217 217 return (identify_info[82] & (1<<3) && identify_info[85] & (1<<3)); 218 218 } 219 + 220 + int ata_flush(void); 219 221 220 222 #ifdef HAVE_ATA_DMA 221 223 /* Returns current DMA mode */
+1 -1
firmware/export/storage.h
··· 174 174 #define storage_disk_is_active() ata_disk_is_active() 175 175 #define storage_soft_reset() ata_soft_reset() 176 176 #ifdef HAVE_STORAGE_FLUSH 177 - #define storage_flush() (void)0 177 + #define storage_flush() ata_flush() 178 178 #endif 179 179 #define storage_last_disk_activity() ata_last_disk_activity() 180 180 #define storage_spinup_time() ata_spinup_time()
+1 -1
firmware/storage.c
··· 555 555 int rc=0; 556 556 557 557 #if (CONFIG_STORAGE & STORAGE_ATA) 558 - //if ((rc=ata_flush())) return rc; 558 + if ((rc=ata_flush())) return rc; 559 559 #endif 560 560 561 561 #if (CONFIG_STORAGE & STORAGE_MMC)
+60 -43
firmware/target/arm/s5l8702/ipod6g/storage_ata-6g.c
··· 83 83 static long ata_last_activity_value = -1; 84 84 static long ata_sleep_timeout = 7 * HZ; 85 85 static bool ata_powered; 86 + static bool canflush = true; 86 87 static struct semaphore mmc_wakeup; 87 88 static struct semaphore mmc_comp_wakeup; 88 89 static int spinup_time = 0; ··· 578 579 579 580 bool ata_disk_is_active(void) 580 581 { 581 - return ata_disk_can_poweroff() ? ata_powered : 0; 582 + return ata_powered; 582 583 } 583 584 584 585 static int ata_set_feature(uint32_t feature, uint32_t param) ··· 745 746 ata_dma = param ? true : false; 746 747 dma_mode = param; 747 748 PASS_RC(ata_set_feature(0x03, param), 3, 4); /* Transfer mode */ 749 + 750 + /* SET_FEATURE only supported on PATA, not CE-ATA */ 748 751 if (ata_identify_data[82] & BIT(5)) 749 752 PASS_RC(ata_set_feature(0x02, 0), 3, 5); /* Enable volatile write cache */ 750 753 if (ata_identify_data[82] & BIT(6)) ··· 753 756 PASS_RC(ata_set_feature(0x05, 0x80), 3, 7); /* Enable lowest power mode w/o standby */ 754 757 if (ata_identify_data[83] & BIT(9)) 755 758 PASS_RC(ata_set_feature(0x42, 0x80), 3, 8); /* Enable lowest noise mode */ 759 + 760 + PASS_RC(ata_identify(ata_identify_data), 3, 9); /* Finally, re-read identify info */ 756 761 } 762 + 757 763 spinup_time = current_tick - spinup_start; 758 764 759 765 ata_total_sectors = (ata_identify_data[61] << 16) | ata_identify_data[60]; ··· 778 784 { 779 785 if (!ata_powered) 780 786 return; 781 - if (ceata) 782 - { 783 - memset(ceata_taskfile, 0, 16); 784 - ceata_taskfile[0xf] = CMD_STANDBY_IMMEDIATE; 785 - ceata_wait_idle(); 786 - ceata_write_multiple_register(0, ceata_taskfile, 16); 787 - ceata_wait_idle(); 788 - sleep(HZ); 789 - PWRCON(0) |= (1 << 9); 790 - } 791 - else 792 - { 793 - ata_wait_for_rdy(1000000); 794 - ata_write_cbr(&ATA_PIO_DVR, 0); 795 - ata_write_cbr(&ATA_PIO_CSD, CMD_STANDBY_IMMEDIATE); 796 - ata_wait_for_rdy(1000000); 797 - sleep(HZ / 30); 798 - ATA_CONTROL = 0; 799 - while (!(ATA_CONTROL & BIT(1))) 800 - yield(); 801 - PWRCON(0) |= (1 << 5); 802 - } 803 787 PCON(7) = 0; 804 788 PCON(8) = 0; 805 789 PCON(9) = 0; ··· 1080 1064 { 1081 1065 uint8_t cmd; 1082 1066 1083 - if (ata_identify_data[83] & BIT(13)) { 1084 - cmd = CMD_FLUSH_CACHE_EXT; 1085 - } else if (ata_identify_data[83] & BIT(12)) { 1086 - cmd = CMD_FLUSH_CACHE; 1087 - } else { 1088 - /* If neither (mandatory!) command is supported 1089 - then don't issue it. */ 1090 - return; 1091 - } 1092 - 1093 - if (ceata) 1094 - { 1067 + if (ceata) { 1095 1068 memset(ceata_taskfile, 0, 16); 1096 - ceata_taskfile[0xf] = cmd; 1069 + ceata_taskfile[0xf] = CMD_FLUSH_CACHE_EXT; /* CE-ATA only supports EXT */ 1097 1070 ceata_wait_idle(); 1098 1071 ceata_write_multiple_register(0, ceata_taskfile, 16); 1099 1072 ceata_wait_idle(); 1100 - } 1101 - else 1102 - { 1073 + } else { 1074 + if (!canflush) { 1075 + return; 1076 + } else if (ata_lba48 && ata_identify_data[83] & BIT(13)) { 1077 + cmd = CMD_FLUSH_CACHE_EXT; /* Flag, optional, ATA-6 and up, for use with LBA48 devices. Mandatory for CE-ATA */ 1078 + } else if (ata_identify_data[83] & BIT(12)) { 1079 + cmd = CMD_FLUSH_CACHE; /* Flag, mandatory, ATA-6 and up */ 1080 + } else if (ata_identify_data[80] >= BIT(5)) { /* Use >= instead of '&' because bits lower than the latest standard we support don't have to be set */ 1081 + cmd = CMD_FLUSH_CACHE; /* No flag, mandatory, ATA-5 (Optional for ATA-4) */ 1082 + } else { 1083 + /* If neither command is supported then don't issue it. */ 1084 + canflush = 0; 1085 + return; 1086 + } 1087 + 1103 1088 ata_wait_for_rdy(1000000); 1104 1089 ata_write_cbr(&ATA_PIO_DVR, 0); 1105 1090 ata_write_cbr(&ATA_PIO_CSD, cmd); ··· 1107 1092 } 1108 1093 } 1109 1094 1095 + int ata_flush(void) 1096 + { 1097 + if (ata_powered) { 1098 + mutex_lock(&ata_mutex); 1099 + ata_flush_cache(); 1100 + mutex_unlock(&ata_mutex); 1101 + } 1102 + return 0; 1103 + } 1104 + 1110 1105 void ata_sleepnow(void) 1111 1106 { 1112 1107 mutex_lock(&ata_mutex); 1113 1108 1114 - if (ata_disk_can_poweroff()) 1115 - ata_power_down(); 1116 - else 1117 - ata_flush_cache(); 1109 + ata_flush_cache(); 1110 + 1111 + if (ata_disk_can_sleep()) { 1112 + if (ceata) { 1113 + memset(ceata_taskfile, 0, 16); 1114 + ceata_taskfile[0xf] = CMD_STANDBY_IMMEDIATE; 1115 + ceata_wait_idle(); 1116 + ceata_write_multiple_register(0, ceata_taskfile, 16); 1117 + ceata_wait_idle(); 1118 + sleep(HZ); 1119 + PWRCON(0) |= (1 << 9); 1120 + } else { 1121 + ata_wait_for_rdy(1000000); 1122 + ata_write_cbr(&ATA_PIO_DVR, 0); 1123 + ata_write_cbr(&ATA_PIO_CSD, CMD_STANDBY_IMMEDIATE); 1124 + ata_wait_for_rdy(1000000); 1125 + sleep(HZ / 30); 1126 + ATA_CONTROL = 0; 1127 + while (!(ATA_CONTROL & BIT(1))) 1128 + yield(); 1129 + PWRCON(0) |= (1 << 5); 1130 + } 1131 + } 1132 + 1133 + if (ata_disk_can_sleep() || canflush) 1134 + ata_power_down(); // XXX add a powerdown delay similar to main ATA driver? 1118 1135 1119 1136 mutex_unlock(&ata_mutex); 1120 1137 }
+5 -4
manual/getting_started/installation.tex
··· 305 305 robust, but tend to be expensive and not available in larger sizes. 306 306 \item[SATA.] These are fast, reliable, and available in high capacities, but are typically optimized for high performance 307 307 at the expense of power consumption.. However, as they implement the full ATA command set, we are able 308 - to aggressively power them down when not being actively used. 308 + to minimize their power consumption and power them down when not being actively used. 309 309 \item[Single Secure Digital (SD).] While these adapters come in different form factors from multiple vendors, 310 310 they are all based on the same basic design. The ATA command set is incompletely emulated, notably lacking 311 - support for the \emph{mandatory} ATA power management commands that Rockbox uses to flush caches and safely 311 + support for \emph{mandatory} ATA power management commands that Rockbox uses to safely 312 312 transition the device in and out of low power states. Additionally, SD cards vary widely in quality 313 - and power consumption with the resultant effects on data longevity and battery life. Finally, these SD adapters do not support 2TiB or larger SDUC cards. 313 + and power consumption with the resultant effects on data longevity and battery life. Finally, these SD adapters 314 + do not support 2TiB or larger SDUC cards. 314 315 \item[Dual/Quad SD.] These are similar to the above, only allowing use of mulitiple SD cards to 315 - increase the overall storage capacity. While typically described as JBOD\footnote{Just a Bunch Of Disks}, this is not accurate as each card is not individually accessable. Instead, the adapter claims to be to be a single logical drive of the combined capacity of the individual cards in a RAID0-like manner. Consquently, if any one card fails, all data on all other cards is most likely permenantly lost. Given the quality and power management concerns mentioned earlier, this means use of multiple SD cards in one of these adapters is the least reliable/robust and the most power hungry of the various SSD mods. Finally, in another violation of the ATA specification, these ATA-SD adapters fail to properly support LBA48 addressing, meaning that no matter which combination of cards is used, they simply will not work if their combined capacity exceeds 2TiB. 316 + increase the overall storage capacity. While typically described as JBOD\footnote{Just a Bunch Of Disks}, this is not accurate as each card is not individually accessable. Instead, the adapter claims to be to be a single logical drive of the combined capacity of the individual cards in a RAID0-like manner. Consquently, if any one card fails, all data on all other cards may be rendered inacessible. Given the quality concerns mentioned earlier, this means use of multiple SD cards in one of these adapters is the least reliable/robust of the various SSD mods. Finally, in another violation of the ATA specification, these ATA-SD adapters fail to properly support LBA48 addressing, meaning that no matter what combination of cards is used, if their combined capacity exceeds 2TiB, the extra capacity will not be usable, and the device may even present as having (considerably) less space. 316 317 \end{description} 317 318 318 319 \note{All of these flash/SSD mods take up less physical space in the device enclosure than the original hard drive, so care must be taken to ensure they are securely mounted and resistant to the vibration and impacts that typically occur in portable devices. Ribbon cables are particularly vulnerable.}