diff options
Diffstat (limited to 'firmware/target/arm/s5l8702/ipod6g')
-rw-r--r-- | firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c index c629fd583a..53ec45ec6d 100644 --- a/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c +++ b/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c | |||
@@ -50,6 +50,9 @@ | |||
50 | /** static, private data **/ | 50 | /** static, private data **/ |
51 | static uint8_t ceata_taskfile[16] STORAGE_ALIGN_ATTR; | 51 | static uint8_t ceata_taskfile[16] STORAGE_ALIGN_ATTR; |
52 | static uint16_t ata_identify_data[0x100] STORAGE_ALIGN_ATTR; | 52 | static uint16_t ata_identify_data[0x100] STORAGE_ALIGN_ATTR; |
53 | #ifdef HAVE_ATA_SMART | ||
54 | static uint16_t ata_smart_data[0x100] STORAGE_ALIGN_ATTR; | ||
55 | #endif | ||
53 | static bool ceata; | 56 | static bool ceata; |
54 | static bool ata_swap; | 57 | static bool ata_swap; |
55 | static bool ata_lba48; | 58 | static bool ata_lba48; |
@@ -1211,6 +1214,62 @@ int ata_init(void) | |||
1211 | return 0; | 1214 | return 0; |
1212 | } | 1215 | } |
1213 | 1216 | ||
1217 | #ifdef HAVE_ATA_SMART | ||
1218 | static int ata_smart(uint16_t* buf) | ||
1219 | { | ||
1220 | mutex_lock(&ata_mutex); | ||
1221 | ata_power_up(); | ||
1222 | |||
1223 | if (ceata) | ||
1224 | { | ||
1225 | memset(ceata_taskfile, 0, 16); | ||
1226 | ceata_taskfile[0xc] = 0x4f; | ||
1227 | ceata_taskfile[0xd] = 0xc2; | ||
1228 | ceata_taskfile[0xe] = 0x40; /* Device/Head Register, bit6: 0->CHS, 1->LBA */ | ||
1229 | ceata_taskfile[0xf] = 0xb0; | ||
1230 | PASS_RC(ceata_wait_idle(), 3, 0); | ||
1231 | if (((uint8_t*)ata_identify_data)[54] != 'A') /* Model != aAmsung */ | ||
1232 | { | ||
1233 | ceata_taskfile[0x9] = 0xd8; /* SMART enable operations */ | ||
1234 | PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 3, 1); | ||
1235 | PASS_RC(ceata_check_error(), 3, 2); | ||
1236 | } | ||
1237 | ceata_taskfile[0x9] = 0xd0; /* SMART read data */ | ||
1238 | PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 3, 3); | ||
1239 | PASS_RC(ceata_rw_multiple_block(false, buf, 1, CEATA_COMMAND_TIMEOUT * HZ / 1000000), 3, 4); | ||
1240 | } | ||
1241 | else | ||
1242 | { | ||
1243 | int i; | ||
1244 | uint32_t old = ATA_CFG; | ||
1245 | ATA_CFG |= BIT(6); /* 16bit big-endian */ | ||
1246 | PASS_RC(ata_wait_for_not_bsy(10000000), 3, 5); | ||
1247 | ata_write_cbr(&ATA_PIO_DAD, 0); | ||
1248 | ata_write_cbr(&ATA_PIO_FED, 0xd0); | ||
1249 | ata_write_cbr(&ATA_PIO_SCR, 0); | ||
1250 | ata_write_cbr(&ATA_PIO_LLR, 0); | ||
1251 | ata_write_cbr(&ATA_PIO_LMR, 0x4f); | ||
1252 | ata_write_cbr(&ATA_PIO_LHR, 0xc2); | ||
1253 | ata_write_cbr(&ATA_PIO_DVR, BIT(6)); | ||
1254 | ata_write_cbr(&ATA_PIO_CSD, 0xb0); | ||
1255 | PASS_RC(ata_wait_for_start_of_transfer(10000000), 3, 6); | ||
1256 | for (i = 0; i < 0x100; i++) buf[i] = ata_read_cbr(&ATA_PIO_DTR); | ||
1257 | ATA_CFG = old; | ||
1258 | } | ||
1259 | |||
1260 | ata_set_active(); | ||
1261 | mutex_unlock(&ata_mutex); | ||
1262 | |||
1263 | return 0; | ||
1264 | } | ||
1265 | |||
1266 | void* ata_read_smart(void) | ||
1267 | { | ||
1268 | ata_smart(ata_smart_data); | ||
1269 | return ata_smart_data; | ||
1270 | } | ||
1271 | #endif /* HAVE_ATA_SMART */ | ||
1272 | |||
1214 | #ifdef CONFIG_STORAGE_MULTI | 1273 | #ifdef CONFIG_STORAGE_MULTI |
1215 | static int ata_num_drives(int first_drive) | 1274 | static int ata_num_drives(int first_drive) |
1216 | { | 1275 | { |