diff options
-rw-r--r-- | firmware/export/config/ipod6g.h | 3 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c | 178 |
2 files changed, 1 insertions, 180 deletions
diff --git a/firmware/export/config/ipod6g.h b/firmware/export/config/ipod6g.h index 84a13d8830..c8920c767c 100644 --- a/firmware/export/config/ipod6g.h +++ b/firmware/export/config/ipod6g.h | |||
@@ -194,9 +194,6 @@ | |||
194 | /* Define this if you can read an absolute wheel position */ | 194 | /* Define this if you can read an absolute wheel position */ |
195 | #define HAVE_WHEEL_POSITION | 195 | #define HAVE_WHEEL_POSITION |
196 | 196 | ||
197 | #define ATA_HAVE_BBT | ||
198 | #define ATA_BBT_PAGES 4096 | ||
199 | |||
200 | #define SECTOR_SIZE 4096 | 197 | #define SECTOR_SIZE 4096 |
201 | 198 | ||
202 | #define STORAGE_NEEDS_ALIGN | 199 | #define STORAGE_NEEDS_ALIGN |
diff --git a/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c index 48197cb085..98efa33c84 100644 --- a/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c +++ b/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c | |||
@@ -69,42 +69,6 @@ static int dma_mode = 0; | |||
69 | static char aligned_buffer[SECTOR_SIZE] STORAGE_ALIGN_ATTR; | 69 | static char aligned_buffer[SECTOR_SIZE] STORAGE_ALIGN_ATTR; |
70 | 70 | ||
71 | static int ata_reset(void); | 71 | static int ata_reset(void); |
72 | static void ata_power_down(void); | ||
73 | |||
74 | #ifdef ATA_HAVE_BBT | ||
75 | char ata_bbt_buf[ATA_BBT_PAGES * 64] STORAGE_ALIGN_ATTR; | ||
76 | uint16_t (*ata_bbt)[0x20]; | ||
77 | uint64_t ata_virtual_sectors; | ||
78 | uint32_t ata_last_offset; | ||
79 | uint64_t ata_last_phys; | ||
80 | |||
81 | int ata_rw_sectors_internal(uint64_t sector, uint32_t count, | ||
82 | void* buffer, bool write); | ||
83 | |||
84 | int ata_bbt_read_sectors(uint32_t sector, uint32_t count, void* buffer) | ||
85 | { | ||
86 | if (ata_last_phys != sector - 1 && ata_last_phys > sector - 64) ata_reset(); | ||
87 | int rc = ata_rw_sectors_internal(sector, count, buffer, false); | ||
88 | if (rc) rc = ata_rw_sectors_internal(sector, count, buffer, false); | ||
89 | if (rc) | ||
90 | { | ||
91 | ata_reset(); | ||
92 | rc = ata_rw_sectors_internal(sector, count, buffer, false); | ||
93 | } | ||
94 | if (rc) | ||
95 | { | ||
96 | ata_power_down(); | ||
97 | sleep(HZ * 10); | ||
98 | rc = ata_rw_sectors_internal(sector, count, buffer, false); | ||
99 | } | ||
100 | ata_last_phys = sector + count - 1; | ||
101 | ata_last_offset = 0; | ||
102 | if (IS_ERR(rc)) | ||
103 | panicf("ATA: Error %08X while reading BBT (sector %d, count %d)", | ||
104 | (unsigned int)rc, (unsigned int)sector, (unsigned int)count); | ||
105 | return rc; | ||
106 | } | ||
107 | #endif | ||
108 | 72 | ||
109 | 73 | ||
110 | static uint16_t ata_read_cbr(uint32_t volatile* reg) | 74 | static uint16_t ata_read_cbr(uint32_t volatile* reg) |
@@ -687,11 +651,7 @@ static int ata_power_up(void) | |||
687 | dma_mode = param; | 651 | dma_mode = param; |
688 | PASS_RC(ata_set_feature(0x03, param), 3, 4); | 652 | PASS_RC(ata_set_feature(0x03, param), 3, 4); |
689 | if (ata_identify_data[82] & BIT(5)) | 653 | if (ata_identify_data[82] & BIT(5)) |
690 | #ifdef ATA_HAVE_BBT | ||
691 | PASS_RC(ata_set_feature(ata_bbt ? 0x82 : 0x02, 0), 3, 5); | ||
692 | #else | ||
693 | PASS_RC(ata_set_feature(0x02, 0), 3, 5); | 654 | PASS_RC(ata_set_feature(0x02, 0), 3, 5); |
694 | #endif | ||
695 | if (ata_identify_data[82] & BIT(6)) PASS_RC(ata_set_feature(0xaa, 0), 3, 6); | 655 | if (ata_identify_data[82] & BIT(6)) PASS_RC(ata_set_feature(0xaa, 0), 3, 6); |
696 | ATA_PIO_TIME = piotime; | 656 | ATA_PIO_TIME = piotime; |
697 | ATA_MDMA_TIME = mdmatime; | 657 | ATA_MDMA_TIME = mdmatime; |
@@ -850,59 +810,6 @@ static int ata_rw_chunk(uint64_t sector, uint32_t cnt, void* buffer, bool write) | |||
850 | return rc; | 810 | return rc; |
851 | } | 811 | } |
852 | 812 | ||
853 | #ifdef ATA_HAVE_BBT | ||
854 | int ata_bbt_translate(uint64_t sector, uint32_t count, uint64_t* phys, uint32_t* physcount) | ||
855 | { | ||
856 | if (sector + count > ata_virtual_sectors) RET_ERR(0); | ||
857 | if (!ata_bbt) | ||
858 | { | ||
859 | *phys = sector; | ||
860 | *physcount = count; | ||
861 | return 0; | ||
862 | } | ||
863 | if (!count) | ||
864 | { | ||
865 | *phys = 0; | ||
866 | *physcount = 0; | ||
867 | return 0; | ||
868 | } | ||
869 | uint32_t offset; | ||
870 | uint32_t l0idx = sector >> 15; | ||
871 | uint32_t l0offs = sector & 0x7fff; | ||
872 | *physcount = MIN(count, 0x8000 - l0offs); | ||
873 | uint32_t l0data = ata_bbt[0][l0idx << 1]; | ||
874 | uint32_t base = ata_bbt[0][(l0idx << 1) | 1] << 12; | ||
875 | if (l0data < 0x8000) offset = l0data + base; | ||
876 | else | ||
877 | { | ||
878 | uint32_t l1idx = (sector >> 10) & 0x1f; | ||
879 | uint32_t l1offs = sector & 0x3ff; | ||
880 | *physcount = MIN(count, 0x400 - l1offs); | ||
881 | uint32_t l1data = ata_bbt[l0data & 0x7fff][l1idx]; | ||
882 | if (l1data < 0x8000) offset = l1data + base; | ||
883 | else | ||
884 | { | ||
885 | uint32_t l2idx = (sector >> 5) & 0x1f; | ||
886 | uint32_t l2offs = sector & 0x1f; | ||
887 | *physcount = MIN(count, 0x20 - l2offs); | ||
888 | uint32_t l2data = ata_bbt[l1data & 0x7fff][l2idx]; | ||
889 | if (l2data < 0x8000) offset = l2data + base; | ||
890 | else | ||
891 | { | ||
892 | uint32_t l3idx = sector & 0x1f; | ||
893 | uint32_t l3data = ata_bbt[l2data & 0x7fff][l3idx]; | ||
894 | for (*physcount = 1; *physcount < count && l3idx + *physcount < 0x20; (*physcount)++) | ||
895 | if (ata_bbt[l2data & 0x7fff][l3idx + *physcount] != l3data) | ||
896 | break; | ||
897 | offset = l3data + base; | ||
898 | } | ||
899 | } | ||
900 | } | ||
901 | *phys = sector + offset; | ||
902 | return 0; | ||
903 | } | ||
904 | #endif | ||
905 | |||
906 | static int ata_rw_sectors(uint64_t sector, uint32_t count, void* buffer, bool write) | 813 | static int ata_rw_sectors(uint64_t sector, uint32_t count, void* buffer, bool write) |
907 | { | 814 | { |
908 | if (STORAGE_OVERLAP((uint32_t)buffer)) | 815 | if (STORAGE_OVERLAP((uint32_t)buffer)) |
@@ -925,30 +832,6 @@ static int ata_rw_sectors(uint64_t sector, uint32_t count, void* buffer, bool wr | |||
925 | return 0; | 832 | return 0; |
926 | } | 833 | } |
927 | 834 | ||
928 | #ifdef ATA_HAVE_BBT | ||
929 | if (sector + count > ata_virtual_sectors) RET_ERR(0); | ||
930 | if (ata_bbt) | ||
931 | while (count) | ||
932 | { | ||
933 | uint64_t phys; | ||
934 | uint32_t cnt; | ||
935 | PASS_RC(ata_bbt_translate(sector, count, &phys, &cnt), 0, 0); | ||
936 | uint32_t offset = phys - sector; | ||
937 | if (offset != ata_last_offset && phys - ata_last_phys < 64) ata_reset(); | ||
938 | ata_last_offset = offset; | ||
939 | ata_last_phys = phys + cnt; | ||
940 | PASS_RC(ata_rw_sectors_internal(phys, cnt, buffer, write), 0, 0); | ||
941 | buffer += cnt * SECTOR_SIZE; | ||
942 | sector += cnt; | ||
943 | count -= cnt; | ||
944 | } | ||
945 | else PASS_RC(ata_rw_sectors_internal(sector, count, buffer, write), 0, 0); | ||
946 | return 0; | ||
947 | } | ||
948 | |||
949 | int ata_rw_sectors_internal(uint64_t sector, uint32_t count, void* buffer, bool write) | ||
950 | { | ||
951 | #endif | ||
952 | if (!ata_powered) ata_power_up(); | 835 | if (!ata_powered) ata_power_up(); |
953 | if (sector + count > ata_total_sectors) RET_ERR(0); | 836 | if (sector + count > ata_total_sectors) RET_ERR(0); |
954 | ata_set_active(); | 837 | ata_set_active(); |
@@ -1105,11 +988,7 @@ void ata_spin(void) | |||
1105 | void ata_get_info(IF_MD(int drive,) struct storage_info *info) | 988 | void ata_get_info(IF_MD(int drive,) struct storage_info *info) |
1106 | { | 989 | { |
1107 | (*info).sector_size = SECTOR_SIZE; | 990 | (*info).sector_size = SECTOR_SIZE; |
1108 | #ifdef ATA_HAVE_BBT | ||
1109 | (*info).num_sectors = ata_virtual_sectors; | ||
1110 | #else | ||
1111 | (*info).num_sectors = ata_total_sectors; | 991 | (*info).num_sectors = ata_total_sectors; |
1112 | #endif | ||
1113 | (*info).vendor = "Apple"; | 992 | (*info).vendor = "Apple"; |
1114 | (*info).product = "iPod Classic"; | 993 | (*info).product = "iPod Classic"; |
1115 | (*info).revision = "1.0"; | 994 | (*info).revision = "1.0"; |
@@ -1120,58 +999,6 @@ long ata_last_disk_activity(void) | |||
1120 | return ata_last_activity_value; | 999 | return ata_last_activity_value; |
1121 | } | 1000 | } |
1122 | 1001 | ||
1123 | #ifdef ATA_HAVE_BBT | ||
1124 | void ata_bbt_disable(void) | ||
1125 | { | ||
1126 | mutex_lock(&ata_mutex); | ||
1127 | ata_bbt = NULL; | ||
1128 | ata_virtual_sectors = ata_total_sectors; | ||
1129 | mutex_unlock(&ata_mutex); | ||
1130 | } | ||
1131 | |||
1132 | int ata_bbt_reload(void) | ||
1133 | { | ||
1134 | mutex_lock(&ata_mutex); | ||
1135 | ata_bbt_disable(); | ||
1136 | PASS_RC(ata_power_up(), 1, 0); | ||
1137 | uint32_t* buf = (uint32_t*)(ata_bbt_buf + sizeof(ata_bbt_buf) - SECTOR_SIZE); | ||
1138 | if (buf) | ||
1139 | { | ||
1140 | if (IS_ERR(ata_bbt_read_sectors(0, 1, buf))) | ||
1141 | ata_virtual_sectors = ata_total_sectors; | ||
1142 | else if (!memcmp(buf, "emBIbbth", 8)) | ||
1143 | { | ||
1144 | if (!ceata) | ||
1145 | if (ata_identify_data[82] & BIT(5)) PASS_RC(ata_set_feature(0x02, 0), 1, 1); | ||
1146 | ata_virtual_sectors = (((uint64_t)buf[0x1fd]) << 32) | buf[0x1fc]; | ||
1147 | uint32_t count = buf[0x1ff]; | ||
1148 | if (count > ATA_BBT_PAGES / 64) | ||
1149 | panicf("ATA: BBT too big! (space: %d, size: %d)", | ||
1150 | ATA_BBT_PAGES, (unsigned int)(count * 64)); | ||
1151 | uint32_t i; | ||
1152 | uint32_t cnt; | ||
1153 | ata_bbt = (typeof(ata_bbt))ata_bbt_buf; | ||
1154 | for (i = 0; i < count; i += cnt) | ||
1155 | { | ||
1156 | uint32_t phys = buf[0x200 + i]; | ||
1157 | for (cnt = 1; cnt < count; cnt++) | ||
1158 | if (buf[0x200 + i + cnt] != phys + cnt) | ||
1159 | break; | ||
1160 | if (IS_ERR(ata_bbt_read_sectors(phys, cnt, ata_bbt[i << 6]))) | ||
1161 | { | ||
1162 | ata_virtual_sectors = ata_total_sectors; | ||
1163 | break; | ||
1164 | } | ||
1165 | } | ||
1166 | } | ||
1167 | else ata_virtual_sectors = ata_total_sectors; | ||
1168 | } | ||
1169 | else ata_virtual_sectors = ata_total_sectors; | ||
1170 | mutex_unlock(&ata_mutex); | ||
1171 | return 0; | ||
1172 | } | ||
1173 | #endif | ||
1174 | |||
1175 | int ata_init(void) | 1002 | int ata_init(void) |
1176 | { | 1003 | { |
1177 | mutex_init(&ata_mutex); | 1004 | mutex_init(&ata_mutex); |
@@ -1181,15 +1008,12 @@ int ata_init(void) | |||
1181 | ceata = PDAT(11) & BIT(1); | 1008 | ceata = PDAT(11) & BIT(1); |
1182 | ata_powered = false; | 1009 | ata_powered = false; |
1183 | ata_total_sectors = 0; | 1010 | ata_total_sectors = 0; |
1184 | #ifdef ATA_HAVE_BBT | 1011 | |
1185 | PASS_RC(ata_bbt_reload(), 0, 0); | ||
1186 | #else | ||
1187 | /* get ata_identify_data */ | 1012 | /* get ata_identify_data */ |
1188 | mutex_lock(&ata_mutex); | 1013 | mutex_lock(&ata_mutex); |
1189 | int rc = ata_power_up(); | 1014 | int rc = ata_power_up(); |
1190 | mutex_unlock(&ata_mutex); | 1015 | mutex_unlock(&ata_mutex); |
1191 | if (IS_ERR(rc)) return rc; | 1016 | if (IS_ERR(rc)) return rc; |
1192 | #endif | ||
1193 | 1017 | ||
1194 | create_thread(ata_thread, ata_stack, | 1018 | create_thread(ata_thread, ata_stack, |
1195 | sizeof(ata_stack), 0, "ATA idle monitor" | 1019 | sizeof(ata_stack), 0, "ATA idle monitor" |