diff options
Diffstat (limited to 'firmware/target/arm/pp')
-rw-r--r-- | firmware/target/arm/pp/ata-sd-pp.c | 274 | ||||
-rw-r--r-- | firmware/target/arm/pp/ata-target.h | 4 |
2 files changed, 94 insertions, 184 deletions
diff --git a/firmware/target/arm/pp/ata-sd-pp.c b/firmware/target/arm/pp/ata-sd-pp.c index edb806ab96..fb0a9e150e 100644 --- a/firmware/target/arm/pp/ata-sd-pp.c +++ b/firmware/target/arm/pp/ata-sd-pp.c | |||
@@ -24,16 +24,10 @@ | |||
24 | #ifdef HAVE_HOTSWAP | 24 | #ifdef HAVE_HOTSWAP |
25 | #include "sd-pp-target.h" | 25 | #include "sd-pp-target.h" |
26 | #endif | 26 | #endif |
27 | #include "ata_idle_notify.h" | ||
28 | #include "system.h" | 27 | #include "system.h" |
29 | #include <string.h> | 28 | #include <string.h> |
30 | #include "thread.h" | ||
31 | #include "led.h" | 29 | #include "led.h" |
32 | #include "disk.h" | ||
33 | #include "cpu.h" | 30 | #include "cpu.h" |
34 | #include "panic.h" | ||
35 | #include "usb.h" | ||
36 | #include "sd.h" | ||
37 | #include "storage.h" | 31 | #include "storage.h" |
38 | #include "fs_defines.h" | 32 | #include "fs_defines.h" |
39 | 33 | ||
@@ -151,12 +145,6 @@ | |||
151 | /* for compatibility */ | 145 | /* for compatibility */ |
152 | static long last_disk_activity = -1; | 146 | static long last_disk_activity = -1; |
153 | 147 | ||
154 | /** static, private data **/ | ||
155 | static bool initialized = false; | ||
156 | static unsigned int sd_thread_id = 0; | ||
157 | |||
158 | #define Q_CLOSE 1 | ||
159 | |||
160 | static long next_yield = 0; | 148 | static long next_yield = 0; |
161 | #define MIN_YIELD_PERIOD 1000 | 149 | #define MIN_YIELD_PERIOD 1000 |
162 | 150 | ||
@@ -177,30 +165,28 @@ static struct sd_card_status sd_status[NUM_DRIVES] = | |||
177 | #endif | 165 | #endif |
178 | }; | 166 | }; |
179 | 167 | ||
180 | /* Shoot for around 75% usage */ | 168 | static struct mutex sd_mtx SHAREDBSS_ATTR; |
181 | static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)]; | ||
182 | static const char sd_thread_name[] = "ata/sd"; | ||
183 | static struct mutex sd_mtx SHAREDBSS_ATTR; | ||
184 | static struct event_queue sd_queue SHAREDBSS_ATTR; | ||
185 | 169 | ||
186 | #ifdef HAVE_HOTSWAP | 170 | #ifdef HAVE_HOTSWAP |
187 | static int sd_first_drive = 0; | 171 | static int sd_first_drive = 0; |
188 | #endif | 172 | #endif |
189 | 173 | ||
190 | /* Posted when card plugged status has changed */ | ||
191 | #define SD_HOTSWAP 1 | ||
192 | /* Actions taken by sd_thread when card status has changed */ | ||
193 | enum sd_thread_actions | ||
194 | { | ||
195 | SDA_NONE = 0x0, | ||
196 | SDA_UNMOUNTED = 0x1, | ||
197 | SDA_MOUNTED = 0x2 | ||
198 | }; | ||
199 | |||
200 | /* Private Functions */ | 174 | /* Private Functions */ |
201 | 175 | ||
202 | static unsigned int check_time[NUM_EC]; | 176 | static unsigned int check_time[NUM_EC]; |
203 | 177 | ||
178 | static inline void enable_controller(bool on) | ||
179 | { | ||
180 | if(on) | ||
181 | { | ||
182 | DEV_EN |= DEV_ATA; /* Enable controller */ | ||
183 | } | ||
184 | else | ||
185 | { | ||
186 | DEV_EN &= ~DEV_ATA; /* Disable controller */ | ||
187 | } | ||
188 | } | ||
189 | |||
204 | static inline bool sd_check_timeout(long timeout, int id) | 190 | static inline bool sd_check_timeout(long timeout, int id) |
205 | { | 191 | { |
206 | return !TIME_AFTER(USEC_TIMER, check_time[id] + timeout); | 192 | return !TIME_AFTER(USEC_TIMER, check_time[id] + timeout); |
@@ -876,7 +862,7 @@ int sd_read_sectors(IF_MD(int drive,) unsigned long start, int incount, | |||
876 | /* TODO: Add DMA support. */ | 862 | /* TODO: Add DMA support. */ |
877 | 863 | ||
878 | mutex_lock(&sd_mtx); | 864 | mutex_lock(&sd_mtx); |
879 | sd_enable(true); | 865 | enable_controller(true); |
880 | led(true); | 866 | led(true); |
881 | 867 | ||
882 | sd_read_retry: | 868 | sd_read_retry: |
@@ -964,7 +950,7 @@ sd_read_retry: | |||
964 | while (1) | 950 | while (1) |
965 | { | 951 | { |
966 | led(false); | 952 | led(false); |
967 | sd_enable(false); | 953 | enable_controller(false); |
968 | mutex_unlock(&sd_mtx); | 954 | mutex_unlock(&sd_mtx); |
969 | 955 | ||
970 | return ret; | 956 | return ret; |
@@ -994,7 +980,7 @@ int sd_write_sectors(IF_MD(int drive,) unsigned long start, int count, | |||
994 | unsigned int bank; | 980 | unsigned int bank; |
995 | 981 | ||
996 | mutex_lock(&sd_mtx); | 982 | mutex_lock(&sd_mtx); |
997 | sd_enable(true); | 983 | enable_controller(true); |
998 | led(true); | 984 | led(true); |
999 | 985 | ||
1000 | sd_write_retry: | 986 | sd_write_retry: |
@@ -1092,7 +1078,7 @@ sd_write_retry: | |||
1092 | while (1) | 1078 | while (1) |
1093 | { | 1079 | { |
1094 | led(false); | 1080 | led(false); |
1095 | sd_enable(false); | 1081 | enable_controller(false); |
1096 | mutex_unlock(&sd_mtx); | 1082 | mutex_unlock(&sd_mtx); |
1097 | 1083 | ||
1098 | return ret; | 1084 | return ret; |
@@ -1108,182 +1094,79 @@ sd_write_error: | |||
1108 | } | 1094 | } |
1109 | } | 1095 | } |
1110 | 1096 | ||
1111 | #ifndef SD_DRIVER_CLOSE | ||
1112 | static void sd_thread(void) NORETURN_ATTR; | ||
1113 | #endif | ||
1114 | static void sd_thread(void) | ||
1115 | { | ||
1116 | struct queue_event ev; | ||
1117 | bool idle_notified = false; | ||
1118 | |||
1119 | while (1) | ||
1120 | { | ||
1121 | queue_wait_w_tmo(&sd_queue, &ev, HZ); | ||
1122 | |||
1123 | switch ( ev.id ) | ||
1124 | { | ||
1125 | #ifdef HAVE_HOTSWAP | ||
1126 | case SYS_HOTSWAP_INSERTED: | ||
1127 | case SYS_HOTSWAP_EXTRACTED:; | ||
1128 | int success = 1; | ||
1129 | |||
1130 | disk_unmount(sd_first_drive+1); /* release "by force" */ | ||
1131 | |||
1132 | mutex_lock(&sd_mtx); /* lock-out card activity */ | ||
1133 | |||
1134 | /* Force card init for new card, re-init for re-inserted one or | ||
1135 | * clear if the last attempt to init failed with an error. */ | ||
1136 | card_info[1].initialized = 0; | ||
1137 | sd_status[1].retry = 0; | ||
1138 | |||
1139 | /* Access is now safe */ | ||
1140 | mutex_unlock(&sd_mtx); | ||
1141 | |||
1142 | if (ev.id == SYS_HOTSWAP_INSERTED) | ||
1143 | success = disk_mount(sd_first_drive+1); /* 0 if fail */ | ||
1144 | |||
1145 | if (success) | ||
1146 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
1147 | break; | ||
1148 | #endif /* HAVE_HOTSWAP */ | ||
1149 | case SYS_TIMEOUT: | ||
1150 | if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ))) | ||
1151 | { | ||
1152 | idle_notified = false; | ||
1153 | } | ||
1154 | else | ||
1155 | { | ||
1156 | /* never let a timer wrap confuse us */ | ||
1157 | next_yield = USEC_TIMER; | ||
1158 | |||
1159 | if (!idle_notified) | ||
1160 | { | ||
1161 | call_storage_idle_notifys(false); | ||
1162 | idle_notified = true; | ||
1163 | } | ||
1164 | } | ||
1165 | break; | ||
1166 | case SYS_USB_CONNECTED: | ||
1167 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
1168 | /* Wait until the USB cable is extracted again */ | ||
1169 | usb_wait_for_disconnect(&sd_queue); | ||
1170 | break; | ||
1171 | |||
1172 | #ifdef SD_DRIVER_CLOSE | ||
1173 | case Q_CLOSE: | ||
1174 | return; | ||
1175 | #endif | ||
1176 | } | ||
1177 | } | ||
1178 | } | ||
1179 | |||
1180 | #ifdef SD_DRIVER_CLOSE | ||
1181 | void sd_close(void) | ||
1182 | { | ||
1183 | unsigned int thread_id = sd_thread_id; | ||
1184 | |||
1185 | if (thread_id == 0) | ||
1186 | return; | ||
1187 | |||
1188 | sd_thread_id = 0; | ||
1189 | |||
1190 | queue_post(&sd_queue, Q_CLOSE, 0); | ||
1191 | thread_wait(thread_id); | ||
1192 | } | ||
1193 | #endif /* SD_DRIVER_CLOSE */ | ||
1194 | |||
1195 | void sd_enable(bool on) | 1097 | void sd_enable(bool on) |
1196 | { | 1098 | { |
1197 | if(on) | 1099 | mutex_lock(&sd_mtx); |
1198 | { | 1100 | enable_controller(on); |
1199 | DEV_EN |= DEV_ATA; /* Enable controller */ | 1101 | mutex_unlock(&sd_mtx); |
1200 | } | ||
1201 | else | ||
1202 | { | ||
1203 | DEV_EN &= ~DEV_ATA; /* Disable controller */ | ||
1204 | } | ||
1205 | } | 1102 | } |
1206 | 1103 | ||
1207 | |||
1208 | int sd_init(void) | 1104 | int sd_init(void) |
1209 | { | 1105 | { |
1210 | int ret = 0; | 1106 | int ret = 0; |
1211 | 1107 | ||
1212 | if (!initialized) | 1108 | mutex_init(&sd_mtx); |
1213 | mutex_init(&sd_mtx); | ||
1214 | |||
1215 | mutex_lock(&sd_mtx); | ||
1216 | 1109 | ||
1217 | led(false); | 1110 | led(false); |
1218 | 1111 | ||
1219 | if (!initialized) | 1112 | /* init controller */ |
1220 | { | ||
1221 | initialized = true; | ||
1222 | |||
1223 | /* init controller */ | ||
1224 | #if defined(PHILIPS_SA9200) | 1113 | #if defined(PHILIPS_SA9200) |
1225 | GPIOA_ENABLE = 0x00; | 1114 | GPIOA_ENABLE = 0x00; |
1226 | GPIO_SET_BITWISE(GPIOD_ENABLE, 0x01); | 1115 | GPIO_SET_BITWISE(GPIOD_ENABLE, 0x01); |
1227 | #else | 1116 | #else |
1228 | outl(inl(0x70000088) & ~(0x4), 0x70000088); | 1117 | outl(inl(0x70000088) & ~(0x4), 0x70000088); |
1229 | outl(inl(0x7000008c) & ~(0x4), 0x7000008c); | 1118 | outl(inl(0x7000008c) & ~(0x4), 0x7000008c); |
1230 | GPO32_ENABLE |= 0x4; | 1119 | GPO32_ENABLE |= 0x4; |
1231 | 1120 | ||
1232 | GPIO_SET_BITWISE(GPIOG_ENABLE, (0x3 << 5)); | 1121 | GPIO_SET_BITWISE(GPIOG_ENABLE, (0x3 << 5)); |
1233 | GPIO_SET_BITWISE(GPIOG_OUTPUT_EN, (0x3 << 5)); | 1122 | GPIO_SET_BITWISE(GPIOG_OUTPUT_EN, (0x3 << 5)); |
1234 | GPIO_SET_BITWISE(GPIOG_OUTPUT_VAL, (0x3 << 5)); | 1123 | GPIO_SET_BITWISE(GPIOG_OUTPUT_VAL, (0x3 << 5)); |
1235 | #endif | 1124 | #endif |
1236 | 1125 | ||
1237 | #ifdef HAVE_HOTSWAP | 1126 | #ifdef HAVE_HOTSWAP |
1238 | /* enable card detection port - mask interrupt first */ | 1127 | /* enable card detection port - mask interrupt first */ |
1239 | #ifdef SANSA_E200 | 1128 | #ifdef SANSA_E200 |
1240 | GPIO_CLEAR_BITWISE(GPIOA_INT_EN, 0x80); | 1129 | GPIO_CLEAR_BITWISE(GPIOA_INT_EN, 0x80); |
1241 | 1130 | ||
1242 | GPIO_CLEAR_BITWISE(GPIOA_OUTPUT_EN, 0x80); | 1131 | GPIO_CLEAR_BITWISE(GPIOA_OUTPUT_EN, 0x80); |
1243 | GPIO_SET_BITWISE(GPIOA_ENABLE, 0x80); | 1132 | GPIO_SET_BITWISE(GPIOA_ENABLE, 0x80); |
1244 | #elif defined SANSA_C200 | 1133 | #elif defined SANSA_C200 |
1245 | GPIO_CLEAR_BITWISE(GPIOL_INT_EN, 0x08); | 1134 | GPIO_CLEAR_BITWISE(GPIOL_INT_EN, 0x08); |
1246 | 1135 | ||
1247 | GPIO_CLEAR_BITWISE(GPIOL_OUTPUT_EN, 0x08); | 1136 | GPIO_CLEAR_BITWISE(GPIOL_OUTPUT_EN, 0x08); |
1248 | GPIO_SET_BITWISE(GPIOL_ENABLE, 0x08); | 1137 | GPIO_SET_BITWISE(GPIOL_ENABLE, 0x08); |
1249 | #endif | 1138 | #endif |
1250 | #endif | 1139 | #endif |
1251 | sd_select_device(0); | 1140 | sd_select_device(0); |
1252 | |||
1253 | if (currcard->initialized < 0) | ||
1254 | ret = currcard->initialized; | ||
1255 | 1141 | ||
1256 | queue_init(&sd_queue, true); | 1142 | if (currcard->initialized < 0) |
1257 | sd_thread_id = create_thread(sd_thread, sd_stack, sizeof(sd_stack), | 1143 | ret = currcard->initialized; |
1258 | 0, sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) | ||
1259 | IF_COP(, CPU)); | ||
1260 | 1144 | ||
1261 | /* enable interupt for the mSD card */ | 1145 | /* enable interupt for the mSD card */ |
1262 | sleep(HZ/10); | 1146 | sleep(HZ/10); |
1263 | #ifdef HAVE_HOTSWAP | 1147 | #ifdef HAVE_HOTSWAP |
1264 | #ifdef SANSA_E200 | 1148 | #ifdef SANSA_E200 |
1265 | CPU_INT_EN = HI_MASK; | 1149 | CPU_INT_EN = HI_MASK; |
1266 | CPU_HI_INT_EN = GPIO0_MASK; | 1150 | CPU_HI_INT_EN = GPIO0_MASK; |
1267 | 1151 | ||
1268 | GPIOA_INT_LEV = (0x80 << 8) | (~GPIOA_INPUT_VAL & 0x80); | 1152 | GPIOA_INT_LEV = (0x80 << 8) | (~GPIOA_INPUT_VAL & 0x80); |
1269 | 1153 | ||
1270 | GPIOA_INT_CLR = 0x80; | 1154 | GPIOA_INT_CLR = 0x80; |
1271 | 1155 | ||
1272 | /* enable the card detect interrupt */ | 1156 | /* enable the card detect interrupt */ |
1273 | GPIO_SET_BITWISE(GPIOA_INT_EN, 0x80); | 1157 | GPIO_SET_BITWISE(GPIOA_INT_EN, 0x80); |
1274 | #elif defined SANSA_C200 | 1158 | #elif defined SANSA_C200 |
1275 | CPU_INT_EN = HI_MASK; | 1159 | CPU_INT_EN = HI_MASK; |
1276 | CPU_HI_INT_EN = GPIO2_MASK; | 1160 | CPU_HI_INT_EN = GPIO2_MASK; |
1277 | 1161 | ||
1278 | GPIOL_INT_LEV = (0x08 << 8) | (~GPIOL_INPUT_VAL & 0x08); | 1162 | GPIOL_INT_LEV = (0x08 << 8) | (~GPIOL_INPUT_VAL & 0x08); |
1279 | 1163 | ||
1280 | GPIOL_INT_CLR = 0x08; | 1164 | GPIOL_INT_CLR = 0x08; |
1281 | 1165 | ||
1282 | /* enable the card detect interrupt */ | 1166 | /* enable the card detect interrupt */ |
1283 | GPIO_SET_BITWISE(GPIOL_INT_EN, 0x08); | 1167 | GPIO_SET_BITWISE(GPIOL_INT_EN, 0x08); |
1284 | #endif | ||
1285 | #endif | 1168 | #endif |
1286 | } | 1169 | #endif /* HAVE_HOTSWAP */ |
1287 | 1170 | ||
1288 | mutex_unlock(&sd_mtx); | 1171 | mutex_unlock(&sd_mtx); |
1289 | 1172 | ||
@@ -1294,19 +1177,17 @@ tCardInfo *card_get_info_target(int card_no) | |||
1294 | { | 1177 | { |
1295 | return &card_info[card_no]; | 1178 | return &card_info[card_no]; |
1296 | } | 1179 | } |
1180 | |||
1297 | #ifdef HAVE_HOTSWAP | 1181 | #ifdef HAVE_HOTSWAP |
1298 | static int sd1_oneshot_callback(struct timeout *tmo) | 1182 | static int sd1_oneshot_callback(struct timeout *tmo) |
1299 | { | 1183 | { |
1300 | (void)tmo; | ||
1301 | |||
1302 | /* This is called only if the state was stable for 300ms - check state | 1184 | /* This is called only if the state was stable for 300ms - check state |
1303 | * and post appropriate event. */ | 1185 | * and post appropriate event. */ |
1304 | if (card_detect_target()) | 1186 | queue_broadcast(card_detect_target() ? SYS_HOTSWAP_INSERTED : |
1305 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | 1187 | SYS_HOTSWAP_EXTRACTED, |
1306 | else | 1188 | sd_first_drive+1); |
1307 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | ||
1308 | |||
1309 | return 0; | 1189 | return 0; |
1190 | (void)tmo; | ||
1310 | } | 1191 | } |
1311 | 1192 | ||
1312 | /* called on insertion/removal interrupt */ | 1193 | /* called on insertion/removal interrupt */ |
@@ -1377,3 +1258,36 @@ int sd_num_drives(int first_drive) | |||
1377 | #endif | 1258 | #endif |
1378 | } | 1259 | } |
1379 | #endif | 1260 | #endif |
1261 | |||
1262 | int sd_event(long id, intptr_t data) | ||
1263 | { | ||
1264 | int rc = 0; | ||
1265 | |||
1266 | switch (id) | ||
1267 | { | ||
1268 | #ifdef HAVE_HOTSWAP | ||
1269 | case SYS_HOTSWAP_INSERTED: | ||
1270 | case SYS_HOTSWAP_EXTRACTED: | ||
1271 | mutex_lock(&sd_mtx); /* lock-out card activity */ | ||
1272 | |||
1273 | /* Force card init for new card, re-init for re-inserted one or | ||
1274 | * clear if the last attempt to init failed with an error. */ | ||
1275 | card_info[data].initialized = 0; | ||
1276 | sd_status[data].retry = 0; | ||
1277 | |||
1278 | /* Access is now safe */ | ||
1279 | mutex_unlock(&sd_mtx); | ||
1280 | break; | ||
1281 | #endif /* HAVE_HOTSWAP */ | ||
1282 | |||
1283 | case Q_STORAGE_TICK: | ||
1284 | /* never let a timer wrap confuse us */ | ||
1285 | next_yield = USEC_TIMER; | ||
1286 | default: | ||
1287 | rc = storage_event_default_handler(id, data, last_disk_activity, | ||
1288 | STORAGE_SD); | ||
1289 | break; | ||
1290 | } | ||
1291 | |||
1292 | return rc; | ||
1293 | } | ||
diff --git a/firmware/target/arm/pp/ata-target.h b/firmware/target/arm/pp/ata-target.h index b888f85b88..a11aeda36d 100644 --- a/firmware/target/arm/pp/ata-target.h +++ b/firmware/target/arm/pp/ata-target.h | |||
@@ -24,10 +24,6 @@ | |||
24 | 24 | ||
25 | #include "config.h" | 25 | #include "config.h" |
26 | 26 | ||
27 | #ifdef HAVE_BOOTLOADER_USB_MODE | ||
28 | #define ATA_DRIVER_CLOSE | ||
29 | #endif | ||
30 | |||
31 | /* primary channel */ | 27 | /* primary channel */ |
32 | #define ATA_DATA (*((volatile unsigned short*)(IDE_BASE + 0x1e0))) | 28 | #define ATA_DATA (*((volatile unsigned short*)(IDE_BASE + 0x1e0))) |
33 | #define ATA_ERROR (*((volatile unsigned char*)(IDE_BASE + 0x1e4))) | 29 | #define ATA_ERROR (*((volatile unsigned char*)(IDE_BASE + 0x1e4))) |