diff options
-rw-r--r-- | firmware/export/mmc.h | 50 | ||||
-rw-r--r-- | firmware/target/arm/imx233/sdmmc-imx233.c | 368 |
2 files changed, 228 insertions, 190 deletions
diff --git a/firmware/export/mmc.h b/firmware/export/mmc.h index 4c7e9c0926..8d20f81236 100644 --- a/firmware/export/mmc.h +++ b/firmware/export/mmc.h | |||
@@ -55,5 +55,55 @@ long mmc_last_disk_activity(void); | |||
55 | int mmc_num_drives(int first_drive); | 55 | int mmc_num_drives(int first_drive); |
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | /* MMC States */ | ||
59 | #define MMC_IDLE 0 | ||
60 | #define MMC_READY 1 | ||
61 | #define MMC_IDENT 2 | ||
62 | #define MMC_STBY 3 | ||
63 | #define MMC_TRAN 4 | ||
64 | #define MMC_DATA 5 | ||
65 | #define MMC_RCV 6 | ||
66 | #define MMC_PRG 7 | ||
67 | #define MMC_DIS 8 | ||
68 | #define MMC_BTST 9 | ||
69 | |||
70 | /* MMC Commands */ | ||
71 | #define MMC_GO_IDLE_STATE 0 | ||
72 | #define MMC_SEND_OP_COND 1 | ||
73 | #define MMC_ALL_SEND_CID 2 | ||
74 | #define MMC_SET_RELATIVE_ADDR 3 | ||
75 | #define MMC_SET_DSR 4 | ||
76 | #define MMC_SWITCH 6 | ||
77 | #define MMC_SELECT_CARD 7 /* with card's rca */ | ||
78 | #define MMC_DESELECT_CARD 7 /* with rca = 0 */ | ||
79 | #define MMC_SEND_EXT_CSD 8 | ||
80 | #define MMC_SEND_CSD 9 | ||
81 | #define MMC_SEND_CID 10 | ||
82 | #define MMC_READ_DAT_UNTIL_STOP 11 | ||
83 | #define MMC_STOP_TRANSMISSION 12 | ||
84 | #define MMC_SEND_STATUS 13 | ||
85 | #define MMC_BUSTEST_R 14 | ||
86 | #define MMC_GO_INACTIVE_STATE 15 | ||
87 | #define MMC_SET_BLOCKLEN 16 | ||
88 | #define MMC_READ_SINGLE_BLOCK 17 | ||
89 | #define MMC_READ_MULTIPLE_BLOCK 18 | ||
90 | #define MMC_BUSTEST_W 19 | ||
91 | #define MMC_WRITE_DAT_UNTIL_STOP 20 | ||
92 | #define MMC_SET_BLOCK_COUNT 23 | ||
93 | #define MMC_WRITE_BLOCK 24 | ||
94 | #define MMC_WRITE_MULTIPLE_BLOCK 25 | ||
95 | #define MMC_PROGRAM_CID 26 | ||
96 | #define MMC_PROGRAM_CSD 27 | ||
97 | #define MMC_SET_WRITE_PROT 28 | ||
98 | #define MMC_CLR_WRITE_PROT 29 | ||
99 | #define MMC_SEND_WRITE_PROT 30 | ||
100 | #define MMC_ERASE_GROUP_START 35 | ||
101 | #define MMC_ERASE_GROUP_END 36 | ||
102 | #define MMC_ERASE 38 | ||
103 | #define MMC_FAST_IO 39 | ||
104 | #define MMC_GO_IRQ_STATE 40 | ||
105 | #define MMC_LOCK_UNLOCK 42 | ||
106 | #define MMC_APP_CMD 55 | ||
107 | #define MMC_GEN_CMD 56 | ||
58 | 108 | ||
59 | #endif | 109 | #endif |
diff --git a/firmware/target/arm/imx233/sdmmc-imx233.c b/firmware/target/arm/imx233/sdmmc-imx233.c index c52734f471..5309f844f2 100644 --- a/firmware/target/arm/imx233/sdmmc-imx233.c +++ b/firmware/target/arm/imx233/sdmmc-imx233.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include "config.h" | 21 | #include "config.h" |
22 | #include "system.h" | 22 | #include "system.h" |
23 | #include "sd.h" | 23 | #include "sd.h" |
24 | #include "mmc.h" | ||
24 | #include "sdmmc.h" | 25 | #include "sdmmc.h" |
25 | #include "ssp-imx233.h" | 26 | #include "ssp-imx233.h" |
26 | #include "pinctrl-imx233.h" | 27 | #include "pinctrl-imx233.h" |
@@ -32,6 +33,24 @@ | |||
32 | #include "debug.h" | 33 | #include "debug.h" |
33 | #include "string.h" | 34 | #include "string.h" |
34 | 35 | ||
36 | /** NOTE For convenience, this drivers relies on the many similar commands | ||
37 | * between SD and MMC. The following assumptions are made: | ||
38 | * - SD_SEND_STATUS = MMC_SEND_STATUS | ||
39 | * - SD_SELECT_CARD = MMC_SELECT_CARD | ||
40 | * - SD_TRAN = MMC_TRAN | ||
41 | * - MMC_WRITE_MULTIPLE_BLOCK = SD_WRITE_MULTIPLE_BLOCK | ||
42 | * - MMC_READ_MULTIPLE_BLOCK = SD_READ_MULTIPLE_BLOCK | ||
43 | * - SD_STOP_TRANSMISSION = MMC_STOP_TRANSMISSION | ||
44 | * - SD_DESELECT_CARD = MMC_DESELECT_CARD | ||
45 | */ | ||
46 | #if SD_SEND_STATUS != MMC_SEND_STATUS || SD_SELECT_CARD != MMC_SELECT_CARD || \ | ||
47 | SD_TRAN != MMC_TRAN || MMC_WRITE_MULTIPLE_BLOCK != SD_WRITE_MULTIPLE_BLOCK || \ | ||
48 | MMC_READ_MULTIPLE_BLOCK != SD_READ_MULTIPLE_BLOCK || \ | ||
49 | SD_STOP_TRANSMISSION != MMC_STOP_TRANSMISSION || \ | ||
50 | SD_DESELECT_CARD != MMC_DESELECT_CARD | ||
51 | #error SD/MMC mismatch | ||
52 | #endif | ||
53 | |||
35 | struct sdmmc_config_t | 54 | struct sdmmc_config_t |
36 | { | 55 | { |
37 | const char *name; /* name(for debug) */ | 56 | const char *name; /* name(for debug) */ |
@@ -115,11 +134,18 @@ struct sdmmc_config_t sdmmc_config[] = | |||
115 | #define SDMMC_SSP(drive) SDMMC_CONF(drive).ssp | 134 | #define SDMMC_SSP(drive) SDMMC_CONF(drive).ssp |
116 | #define SDMMC_MODE(drive) SDMMC_CONF(drive).mode | 135 | #define SDMMC_MODE(drive) SDMMC_CONF(drive).mode |
117 | 136 | ||
137 | /** WARNING | ||
138 | * to be consistent with all our SD drivers, the .rca field of sdmmc_card_info | ||
139 | * in reality holds (rca << 16) because all command arguments actually require | ||
140 | * the RCA is the 16-bit msb. Be careful that this is not the actuall RCA ! */ | ||
141 | |||
118 | /* common */ | 142 | /* common */ |
119 | static unsigned window_start[SDMMC_NUM_DRIVES]; | 143 | static unsigned window_start[SDMMC_NUM_DRIVES]; |
120 | static unsigned window_end[SDMMC_NUM_DRIVES]; | 144 | static unsigned window_end[SDMMC_NUM_DRIVES]; |
121 | static uint8_t aligned_buffer[SDMMC_NUM_DRIVES][512] CACHEALIGN_ATTR; | 145 | static uint8_t aligned_buffer[SDMMC_NUM_DRIVES][512] CACHEALIGN_ATTR; |
122 | static tCardInfo sdmmc_card_info[SDMMC_NUM_DRIVES]; | 146 | static tCardInfo sdmmc_card_info[SDMMC_NUM_DRIVES]; |
147 | static struct mutex mutex[SDMMC_NUM_DRIVES]; | ||
148 | static int disk_last_activity[SDMMC_NUM_DRIVES]; | ||
123 | 149 | ||
124 | #define SDMMC_INFO(drive) sdmmc_card_info[drive] | 150 | #define SDMMC_INFO(drive) sdmmc_card_info[drive] |
125 | #define SDMMC_RCA(drive) SDMMC_INFO(drive).rca | 151 | #define SDMMC_RCA(drive) SDMMC_INFO(drive).rca |
@@ -127,19 +153,16 @@ static tCardInfo sdmmc_card_info[SDMMC_NUM_DRIVES]; | |||
127 | /* sd only */ | 153 | /* sd only */ |
128 | #if CONFIG_STORAGE & STORAGE_SD | 154 | #if CONFIG_STORAGE & STORAGE_SD |
129 | static long sd_stack[(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)]; | 155 | static long sd_stack[(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)]; |
130 | static struct mutex sd_mutex; | ||
131 | static const char sd_thread_name[] = "sd"; | 156 | static const char sd_thread_name[] = "sd"; |
132 | static struct event_queue sd_queue; | 157 | static struct event_queue sd_queue; |
133 | static int sd_first_drive; | 158 | static int sd_first_drive; |
134 | static unsigned _sd_num_drives; | 159 | static unsigned _sd_num_drives; |
135 | static int _sd_last_disk_activity; | ||
136 | static int sd_map[SDMMC_NUM_DRIVES]; /* sd->sdmmc map */ | 160 | static int sd_map[SDMMC_NUM_DRIVES]; /* sd->sdmmc map */ |
137 | #endif | 161 | #endif |
138 | /* mmc only */ | 162 | /* mmc only */ |
139 | #if CONFIG_STORAGE & STORAGE_MMC | 163 | #if CONFIG_STORAGE & STORAGE_MMC |
140 | static int mmc_first_drive; | 164 | static int mmc_first_drive; |
141 | static unsigned _mmc_num_drives; | 165 | static unsigned _mmc_num_drives; |
142 | static int _mmc_last_disk_activity; | ||
143 | static int mmc_map[SDMMC_NUM_DRIVES]; /* mmc->sdmmc map */ | 166 | static int mmc_map[SDMMC_NUM_DRIVES]; /* mmc->sdmmc map */ |
144 | #endif | 167 | #endif |
145 | 168 | ||
@@ -193,13 +216,13 @@ static void sdmmc_power(int drive, bool on) | |||
193 | #define MCI_NO_RESP 0 | 216 | #define MCI_NO_RESP 0 |
194 | #define MCI_RESP (1<<0) | 217 | #define MCI_RESP (1<<0) |
195 | #define MCI_LONG_RESP (1<<1) | 218 | #define MCI_LONG_RESP (1<<1) |
196 | #define MCI_ACMD (1<<2) | 219 | #define MCI_ACMD (1<<2) /* sd only */ |
197 | #define MCI_NOCRC (1<<3) | 220 | #define MCI_NOCRC (1<<3) |
198 | #define MCI_BUSY (1<<4) | 221 | #define MCI_BUSY (1<<4) |
199 | 222 | ||
200 | static bool send_sd_cmd(int drive, uint8_t cmd, uint32_t arg, uint32_t flags, uint32_t *resp) | 223 | static bool send_cmd(int drive, uint8_t cmd, uint32_t arg, uint32_t flags, uint32_t *resp) |
201 | { | 224 | { |
202 | if((flags & MCI_ACMD) && !send_sd_cmd(drive, SD_APP_CMD, SDMMC_RCA(drive), MCI_RESP, resp)) | 225 | if((flags & MCI_ACMD) && !send_cmd(drive, SD_APP_CMD, SDMMC_RCA(drive), MCI_RESP, resp)) |
203 | return false; | 226 | return false; |
204 | 227 | ||
205 | enum imx233_ssp_resp_t resp_type = (flags & MCI_LONG_RESP) ? SSP_LONG_RESP : | 228 | enum imx233_ssp_resp_t resp_type = (flags & MCI_LONG_RESP) ? SSP_LONG_RESP : |
@@ -219,7 +242,7 @@ static bool send_sd_cmd(int drive, uint8_t cmd, uint32_t arg, uint32_t flags, ui | |||
219 | return ret == SSP_SUCCESS; | 242 | return ret == SSP_SUCCESS; |
220 | } | 243 | } |
221 | 244 | ||
222 | static int wait_for_sd_tran_state(int drive) | 245 | static int wait_for_state(int drive, unsigned state) |
223 | { | 246 | { |
224 | unsigned long response; | 247 | unsigned long response; |
225 | unsigned int timeout = current_tick + 5*HZ; | 248 | unsigned int timeout = current_tick + 5*HZ; |
@@ -227,26 +250,27 @@ static int wait_for_sd_tran_state(int drive) | |||
227 | 250 | ||
228 | while (1) | 251 | while (1) |
229 | { | 252 | { |
230 | while(!send_sd_cmd(drive, SD_SEND_STATUS, SDMMC_RCA(drive), MCI_RESP, &response) && cmd_retry > 0) | 253 | /* NOTE: rely on SD_SEND_STATUS=MMC_SEND_STATUS */ |
254 | while(!send_cmd(drive, SD_SEND_STATUS, SDMMC_RCA(drive), MCI_RESP, &response) && cmd_retry > 0) | ||
231 | cmd_retry--; | 255 | cmd_retry--; |
232 | 256 | ||
233 | if(cmd_retry <= 0) | 257 | if(cmd_retry <= 0) |
234 | return -1; | 258 | return -1; |
235 | 259 | ||
236 | if(((response >> 9) & 0xf) == SD_TRAN) | 260 | if(((response >> 9) & 0xf) == state) |
237 | return 0; | 261 | return 0; |
238 | 262 | ||
239 | if(TIME_AFTER(current_tick, timeout)) | 263 | if(TIME_AFTER(current_tick, timeout)) |
240 | return -10 * ((response >> 9) & 0xf); | 264 | return -10 * ((response >> 9) & 0xf); |
241 | 265 | ||
242 | _sd_last_disk_activity = current_tick; | 266 | disk_last_activity[drive] = current_tick; |
243 | } | 267 | } |
244 | 268 | ||
245 | return 0; | 269 | return 0; |
246 | } | 270 | } |
247 | 271 | ||
248 | #if CONFIG_STORAGE & STORAGE_SD | 272 | #if CONFIG_STORAGE & STORAGE_SD |
249 | static int sdmmc_init_sd_card(int drive) | 273 | static int init_sd_card(int drive) |
250 | { | 274 | { |
251 | int ssp = SDMMC_SSP(drive); | 275 | int ssp = SDMMC_SSP(drive); |
252 | sdmmc_power(drive, false); | 276 | sdmmc_power(drive, false); |
@@ -267,11 +291,11 @@ static int sdmmc_init_sd_card(int drive) | |||
267 | uint32_t resp; | 291 | uint32_t resp; |
268 | long init_timeout; | 292 | long init_timeout; |
269 | /* go to idle state */ | 293 | /* go to idle state */ |
270 | if(!send_sd_cmd(drive, SD_GO_IDLE_STATE, 0, MCI_NO_RESP, NULL)) | 294 | if(!send_cmd(drive, SD_GO_IDLE_STATE, 0, MCI_NO_RESP, NULL)) |
271 | return -1; | 295 | return -1; |
272 | /* CMD8 Check for v2 sd card. Must be sent before using ACMD41 | 296 | /* CMD8 Check for v2 sd card. Must be sent before using ACMD41 |
273 | Non v2 cards will not respond to this command */ | 297 | Non v2 cards will not respond to this command */ |
274 | if(send_sd_cmd(drive, SD_SEND_IF_COND, 0x1AA, MCI_RESP, &resp)) | 298 | if(send_cmd(drive, SD_SEND_IF_COND, 0x1AA, MCI_RESP, &resp)) |
275 | if((resp & 0xFFF) == 0x1AA) | 299 | if((resp & 0xFFF) == 0x1AA) |
276 | sd_v2 = true; | 300 | sd_v2 = true; |
277 | /* timeout for initialization is 1sec, from SD Specification 2.00 */ | 301 | /* timeout for initialization is 1sec, from SD Specification 2.00 */ |
@@ -283,42 +307,42 @@ static int sdmmc_init_sd_card(int drive) | |||
283 | return -2; | 307 | return -2; |
284 | 308 | ||
285 | /* ACMD41 For v2 cards set HCS bit[30] & send host voltage range to all */ | 309 | /* ACMD41 For v2 cards set HCS bit[30] & send host voltage range to all */ |
286 | if(!send_sd_cmd(drive, SD_APP_OP_COND, (0x00FF8000 | (sd_v2 ? 1<<30 : 0)), | 310 | if(!send_cmd(drive, SD_APP_OP_COND, (0x00FF8000 | (sd_v2 ? 1<<30 : 0)), |
287 | MCI_ACMD|MCI_NOCRC|MCI_RESP, &SDMMC_INFO(drive).ocr)) | 311 | MCI_ACMD|MCI_NOCRC|MCI_RESP, &SDMMC_INFO(drive).ocr)) |
288 | return -100; | 312 | return -100; |
289 | } while(!(SDMMC_INFO(drive).ocr & (1<<31))); | 313 | } while(!(SDMMC_INFO(drive).ocr & (1<<31))); |
290 | 314 | ||
291 | /* CMD2 send CID */ | 315 | /* CMD2 send CID */ |
292 | if(!send_sd_cmd(drive, SD_ALL_SEND_CID, 0, MCI_RESP|MCI_LONG_RESP, SDMMC_INFO(drive).cid)) | 316 | if(!send_cmd(drive, SD_ALL_SEND_CID, 0, MCI_RESP|MCI_LONG_RESP, SDMMC_INFO(drive).cid)) |
293 | return -3; | 317 | return -3; |
294 | 318 | ||
295 | /* CMD3 send RCA */ | 319 | /* CMD3 send RCA */ |
296 | if(!send_sd_cmd(drive, SD_SEND_RELATIVE_ADDR, 0, MCI_RESP, &SDMMC_INFO(drive).rca)) | 320 | if(!send_cmd(drive, SD_SEND_RELATIVE_ADDR, 0, MCI_RESP, &SDMMC_INFO(drive).rca)) |
297 | return -4; | 321 | return -4; |
298 | 322 | ||
299 | /* Try to switch V2 cards to HS timings, non HS seem to ignore this */ | 323 | /* Try to switch V2 cards to HS timings, non HS seem to ignore this */ |
300 | if(sd_v2) | 324 | if(sd_v2) |
301 | { | 325 | { |
302 | /* CMD7 w/rca: Select card to put it in TRAN state */ | 326 | /* CMD7 w/rca: Select card to put it in TRAN state */ |
303 | if(!send_sd_cmd(drive, SD_SELECT_CARD, SDMMC_RCA(drive), MCI_RESP, NULL)) | 327 | if(!send_cmd(drive, SD_SELECT_CARD, SDMMC_RCA(drive), MCI_RESP, NULL)) |
304 | return -5; | 328 | return -5; |
305 | 329 | ||
306 | if(wait_for_sd_tran_state(drive)) | 330 | if(wait_for_state(drive, SD_TRAN)) |
307 | return -6; | 331 | return -6; |
308 | 332 | ||
309 | /* CMD6 */ | 333 | /* CMD6 */ |
310 | if(!send_sd_cmd(drive, SD_SWITCH_FUNC, 0x80fffff1, MCI_NO_RESP, NULL)) | 334 | if(!send_cmd(drive, SD_SWITCH_FUNC, 0x80fffff1, MCI_NO_RESP, NULL)) |
311 | return -7; | 335 | return -7; |
312 | sleep(HZ/10); | 336 | sleep(HZ/10); |
313 | 337 | ||
314 | /* go back to STBY state so we can read csd */ | 338 | /* go back to STBY state so we can read csd */ |
315 | /* CMD7 w/rca=0: Deselect card to put it in STBY state */ | 339 | /* CMD7 w/rca=0: Deselect card to put it in STBY state */ |
316 | if(!send_sd_cmd(drive, SD_DESELECT_CARD, 0, MCI_NO_RESP, NULL)) | 340 | if(!send_cmd(drive, SD_DESELECT_CARD, 0, MCI_NO_RESP, NULL)) |
317 | return -8; | 341 | return -8; |
318 | } | 342 | } |
319 | 343 | ||
320 | /* CMD9 send CSD */ | 344 | /* CMD9 send CSD */ |
321 | if(!send_sd_cmd(drive, SD_SEND_CSD, SDMMC_RCA(drive), MCI_RESP|MCI_LONG_RESP, | 345 | if(!send_cmd(drive, SD_SEND_CSD, SDMMC_RCA(drive), MCI_RESP|MCI_LONG_RESP, |
322 | SDMMC_INFO(drive).csd)) | 346 | SDMMC_INFO(drive).csd)) |
323 | return -9; | 347 | return -9; |
324 | 348 | ||
@@ -331,16 +355,16 @@ static int sdmmc_init_sd_card(int drive) | |||
331 | imx233_ssp_set_timings(ssp, 4, 0, 0xffff); | 355 | imx233_ssp_set_timings(ssp, 4, 0, 0xffff); |
332 | 356 | ||
333 | /* CMD7 w/rca: Select card to put it in TRAN state */ | 357 | /* CMD7 w/rca: Select card to put it in TRAN state */ |
334 | if(!send_sd_cmd(drive, SD_SELECT_CARD, SDMMC_RCA(drive), MCI_RESP, &resp)) | 358 | if(!send_cmd(drive, SD_SELECT_CARD, SDMMC_RCA(drive), MCI_RESP, &resp)) |
335 | return -12; | 359 | return -12; |
336 | if(wait_for_sd_tran_state(drive) < 0) | 360 | if(wait_for_state(drive, SD_TRAN)) |
337 | return -13; | 361 | return -13; |
338 | 362 | ||
339 | /* ACMD6: set bus width to 4-bit */ | 363 | /* ACMD6: set bus width to 4-bit */ |
340 | if(!send_sd_cmd(drive, SD_SET_BUS_WIDTH, 2, MCI_RESP|MCI_ACMD, &resp)) | 364 | if(!send_cmd(drive, SD_SET_BUS_WIDTH, 2, MCI_RESP|MCI_ACMD, &resp)) |
341 | return -15; | 365 | return -15; |
342 | /* ACMD42: disconnect the pull-up resistor on CD/DAT3 */ | 366 | /* ACMD42: disconnect the pull-up resistor on CD/DAT3 */ |
343 | if(!send_sd_cmd(drive, SD_SET_CLR_CARD_DETECT, 0, MCI_RESP|MCI_ACMD, &resp)) | 367 | if(!send_cmd(drive, SD_SET_CLR_CARD_DETECT, 0, MCI_RESP|MCI_ACMD, &resp)) |
344 | return -17; | 368 | return -17; |
345 | 369 | ||
346 | /* Switch to 4-bit */ | 370 | /* Switch to 4-bit */ |
@@ -350,115 +374,15 @@ static int sdmmc_init_sd_card(int drive) | |||
350 | 374 | ||
351 | return 0; | 375 | return 0; |
352 | } | 376 | } |
353 | |||
354 | static int transfer_sd_sectors(int drive, unsigned long start, int count, void *buf, bool read) | ||
355 | { | ||
356 | int ret = 0; | ||
357 | uint32_t resp; | ||
358 | |||
359 | _sd_last_disk_activity = current_tick; | ||
360 | |||
361 | mutex_lock(&sd_mutex); | ||
362 | |||
363 | if(SDMMC_INFO(drive).initialized <= 0) | ||
364 | { | ||
365 | ret = sdmmc_init_sd_card(drive); | ||
366 | if(SDMMC_INFO(drive).initialized <= 0) | ||
367 | goto Lend; | ||
368 | } | ||
369 | |||
370 | /* check window */ | ||
371 | start += window_start[drive]; | ||
372 | if((start + count) > window_end[drive]) | ||
373 | { | ||
374 | ret = -201; | ||
375 | goto Lend; | ||
376 | } | ||
377 | |||
378 | if(!send_sd_cmd(drive, SD_SELECT_CARD, SDMMC_RCA(drive), MCI_NO_RESP, NULL)) | ||
379 | { | ||
380 | ret = -20; | ||
381 | goto Lend; | ||
382 | } | ||
383 | ret = wait_for_sd_tran_state(drive); | ||
384 | if(ret < 0) | ||
385 | goto Ldeselect; | ||
386 | while(count != 0) | ||
387 | { | ||
388 | /* FIXME implement this_count > 1 by using a sub-buffer of [sub] that is | ||
389 | * cache-aligned and then moving the data when possible. This way we could | ||
390 | * transfer much greater amount of data at once */ | ||
391 | int this_count = 1; | ||
392 | /* Set bank_start to the correct unit (blocks or bytes) */ | ||
393 | int bank_start = start; | ||
394 | if(!(SDMMC_INFO(drive).ocr & (1<<30))) /* not SDHC */ | ||
395 | bank_start *= SD_BLOCK_SIZE; | ||
396 | if(!read) | ||
397 | memcpy(aligned_buffer[drive], buf, 512); | ||
398 | ret = imx233_ssp_sd_mmc_transfer(SDMMC_SSP(drive), | ||
399 | read ? SD_READ_MULTIPLE_BLOCK : SD_WRITE_MULTIPLE_BLOCK, | ||
400 | bank_start, SSP_SHORT_RESP, aligned_buffer[drive], this_count, false, read, &resp); | ||
401 | if(ret != SSP_SUCCESS) | ||
402 | break; | ||
403 | if(!send_sd_cmd(drive, SD_STOP_TRANSMISSION, 0, MCI_RESP|MCI_BUSY, &resp)) | ||
404 | { | ||
405 | ret = -15; | ||
406 | break; | ||
407 | } | ||
408 | if(read) | ||
409 | memcpy(buf, aligned_buffer[drive], 512); | ||
410 | count -= this_count; | ||
411 | start += this_count; | ||
412 | buf += this_count * 512; | ||
413 | } | ||
414 | |||
415 | Ldeselect: | ||
416 | /* CMD7 w/rca =0 : deselects card & puts it in STBY state */ | ||
417 | if(!send_sd_cmd(drive, SD_DESELECT_CARD, 0, MCI_NO_RESP, NULL)) | ||
418 | ret = -23; | ||
419 | Lend: | ||
420 | mutex_unlock(&sd_mutex); | ||
421 | return ret; | ||
422 | } | ||
423 | #endif | 377 | #endif |
424 | 378 | ||
425 | #if CONFIG_STORAGE & STORAGE_MMC | 379 | #if CONFIG_STORAGE & STORAGE_MMC |
426 | static int transfer_mmc_sectors(int drive, unsigned long start, int count, void *buf, bool read) | 380 | static int init_mmc_drive(int drive) |
427 | { | ||
428 | /* check window */ | ||
429 | start += window_start[drive]; | ||
430 | if((start + count) > window_end[drive]) | ||
431 | return -201; | ||
432 | int ret = 0; | ||
433 | uint32_t resp; | ||
434 | |||
435 | _mmc_last_disk_activity = current_tick; | ||
436 | |||
437 | do | ||
438 | { | ||
439 | /* FIXME implement this_count > 1 by using a sub-buffer of [sub] that is | ||
440 | * cache-aligned and then moving the data when possible. This way we could | ||
441 | * transfer much greater amount of data at once */ | ||
442 | int this_count = 1; | ||
443 | if(!read) | ||
444 | memcpy(aligned_buffer[drive], buf, 512); | ||
445 | ret = imx233_ssp_sd_mmc_transfer(SDMMC_SSP(drive), read ? 17 : 24, start, | ||
446 | SSP_SHORT_RESP, aligned_buffer[drive], this_count, false, read, &resp); | ||
447 | if(read) | ||
448 | memcpy(buf, aligned_buffer[drive], 512); | ||
449 | count -= this_count; | ||
450 | start += this_count; | ||
451 | buf += this_count * 512; | ||
452 | }while(count != 0 && ret == SSP_SUCCESS); | ||
453 | |||
454 | return ret; | ||
455 | } | ||
456 | |||
457 | static int sdmmc_init_mmc_drive(int drive) | ||
458 | { | 381 | { |
459 | int ssp = SDMMC_SSP(drive); | 382 | int ssp = SDMMC_SSP(drive); |
460 | // we can choose the RCA of mmc cards: pick drive | 383 | /* we can choose the RCA of mmc cards: pick drive. Following our convention, |
461 | SDMMC_RCA(drive) = drive; | 384 | * .rca is actually RCA << 16 */ |
385 | SDMMC_RCA(drive) = drive << 16; | ||
462 | 386 | ||
463 | sdmmc_power(drive, false); | 387 | sdmmc_power(drive, false); |
464 | sdmmc_power(drive, true); | 388 | sdmmc_power(drive, true); |
@@ -472,52 +396,44 @@ static int sdmmc_init_mmc_drive(int drive) | |||
472 | imx233_ssp_set_bus_width(ssp, 1); | 396 | imx233_ssp_set_bus_width(ssp, 1); |
473 | imx233_ssp_set_block_size(ssp, 9); | 397 | imx233_ssp_set_block_size(ssp, 9); |
474 | /* go to idle state */ | 398 | /* go to idle state */ |
475 | int ret = imx233_ssp_sd_mmc_transfer(ssp, 0, 0, SSP_NO_RESP, NULL, 0, false, false, NULL); | 399 | if(!send_cmd(drive, MMC_GO_IDLE_STATE, 0, MCI_NO_RESP, NULL)) |
476 | if(ret != 0) | ||
477 | return -1; | 400 | return -1; |
478 | /* send op cond until the card respond with busy bit set; it must complete within 1sec */ | 401 | /* send op cond until the card respond with busy bit set; it must complete within 1sec */ |
479 | unsigned timeout = current_tick + HZ; | 402 | unsigned timeout = current_tick + HZ; |
403 | bool ret = false; | ||
480 | do | 404 | do |
481 | { | 405 | { |
482 | uint32_t ocr; | 406 | uint32_t ocr; |
483 | ret = imx233_ssp_sd_mmc_transfer(ssp, 1, 0x40ff8000, SSP_SHORT_RESP, NULL, 0, false, false, &ocr); | 407 | ret = send_cmd(drive, MMC_SEND_OP_COND, 0x40ff8000, MCI_RESP, &ocr); |
484 | if(ret == 0 && ocr & (1 << 31)) | 408 | if(ret && ocr & (1 << 31)) |
485 | break; | 409 | break; |
486 | }while(!TIME_AFTER(current_tick, timeout)); | 410 | }while(!TIME_AFTER(current_tick, timeout)); |
487 | 411 | ||
488 | if(ret != 0) | 412 | if(!ret) |
489 | return -2; | 413 | return -2; |
490 | /* get CID */ | 414 | /* get CID */ |
491 | uint32_t cid[4]; | 415 | uint32_t cid[4]; |
492 | ret = imx233_ssp_sd_mmc_transfer(ssp, 2, 0, SSP_LONG_RESP, NULL, 0, false, false, cid); | 416 | if(!send_cmd(drive, MMC_ALL_SEND_CID, 0, MCI_LONG_RESP, cid)) |
493 | if(ret != 0) | ||
494 | return -3; | 417 | return -3; |
495 | /* Set RCA */ | 418 | /* Set RCA */ |
496 | uint32_t status; | 419 | uint32_t status; |
497 | ret = imx233_ssp_sd_mmc_transfer(ssp, 3, SDMMC_RCA(drive) << 16, SSP_SHORT_RESP, NULL, 0, false, false, &status); | 420 | if(!send_cmd(drive, MMC_SET_RELATIVE_ADDR, SDMMC_RCA(drive), MCI_RESP, &status)) |
498 | if(ret != 0) | ||
499 | return -4; | 421 | return -4; |
500 | /* Select card */ | 422 | /* Select card */ |
501 | ret = imx233_ssp_sd_mmc_transfer(ssp, 7, SDMMC_RCA(drive) << 16, SSP_SHORT_RESP, NULL, 0, false, false, &status); | 423 | if(!send_cmd(drive, MMC_SELECT_CARD, SDMMC_RCA(drive), MCI_RESP, &status)) |
502 | if(ret != 0) | ||
503 | return -5; | 424 | return -5; |
504 | /* Check TRAN state */ | 425 | /* Check TRAN state */ |
505 | ret = imx233_ssp_sd_mmc_transfer(ssp, 13, SDMMC_RCA(drive) << 16, SSP_SHORT_RESP, NULL, 0, false, false, &status); | 426 | if(wait_for_state(drive, MMC_TRAN)) |
506 | if(ret != 0) | ||
507 | return -6; | 427 | return -6; |
508 | if(((status >> 9) & 0xf) != 4) | ||
509 | return -7; | ||
510 | /* Switch to 8-bit bus */ | 428 | /* Switch to 8-bit bus */ |
511 | ret = imx233_ssp_sd_mmc_transfer(ssp, 6, 0x3b70200, SSP_SHORT_RESP, NULL, 0, true, false, &status); | 429 | if(!send_cmd(drive, MMC_SWITCH, 0x3b70200, MCI_RESP|MCI_BUSY, &status)) |
512 | if(ret != 0) | ||
513 | return -8; | 430 | return -8; |
514 | /* switch error ? */ | 431 | /* switch error ? */ |
515 | if(status & 0x80) | 432 | if(status & 0x80) |
516 | return -9; | 433 | return -9; |
517 | imx233_ssp_set_bus_width(ssp, 8); | 434 | imx233_ssp_set_bus_width(ssp, 8); |
518 | /* Switch to high speed mode */ | 435 | /* Switch to high speed mode */ |
519 | ret = imx233_ssp_sd_mmc_transfer(ssp, 6, 0x3b90100, SSP_SHORT_RESP, NULL, 0, true, false, &status); | 436 | if(!send_cmd(drive, MMC_SWITCH, 0x3b90100, MCI_RESP|MCI_BUSY, &status)) |
520 | if(ret != 0) | ||
521 | return -10; | 437 | return -10; |
522 | /* switch error ?*/ | 438 | /* switch error ?*/ |
523 | if(status & 0x80) | 439 | if(status & 0x80) |
@@ -529,76 +445,139 @@ static int sdmmc_init_mmc_drive(int drive) | |||
529 | /* read extended CSD */ | 445 | /* read extended CSD */ |
530 | { | 446 | { |
531 | uint8_t ext_csd[512]; | 447 | uint8_t ext_csd[512]; |
532 | ret = imx233_ssp_sd_mmc_transfer(ssp, 8, 0, SSP_SHORT_RESP, aligned_buffer[drive], 1, true, true, &status); | 448 | if(imx233_ssp_sd_mmc_transfer(ssp, 8, 0, SSP_SHORT_RESP, aligned_buffer[drive], 1, true, true, &status)) |
533 | if(ret != 0) | ||
534 | return -12; | 449 | return -12; |
535 | memcpy(ext_csd, aligned_buffer[drive], 512); | 450 | memcpy(ext_csd, aligned_buffer[drive], 512); |
536 | uint32_t *sec_count = (void *)&ext_csd[212]; | 451 | uint32_t *sec_count = (void *)&ext_csd[212]; |
537 | window_start[drive] = 0; | 452 | window_start[drive] = 0; |
538 | window_end[drive] = *sec_count; | 453 | window_end[drive] = *sec_count; |
539 | } | 454 | } |
455 | /* deselect card */ | ||
456 | if(!send_cmd(drive, MMC_DESELECT_CARD, 0, MCI_NO_RESP, NULL)) | ||
457 | return -13; | ||
540 | 458 | ||
541 | return 0; | 459 | return 0; |
542 | } | 460 | } |
543 | #endif | 461 | #endif |
544 | 462 | ||
545 | static int sdmmc_read_sectors(int drive, unsigned long start, int count, void* buf) | 463 | static int transfer_sectors(int drive, unsigned long start, int count, void *buf, bool read) |
546 | { | 464 | { |
547 | switch(SDMMC_MODE(drive)) | 465 | int ret = 0; |
548 | { | 466 | uint32_t resp; |
467 | |||
468 | /* update disk activity */ | ||
469 | disk_last_activity[drive] = current_tick; | ||
470 | |||
471 | /* lock per-drive mutex */ | ||
472 | mutex_lock(&mutex[drive]); | ||
473 | |||
474 | /* for SD cards, init if necessary */ | ||
549 | #if CONFIG_STORAGE & STORAGE_SD | 475 | #if CONFIG_STORAGE & STORAGE_SD |
550 | case SD_MODE: return transfer_sd_sectors(drive, start, count, buf, true); | 476 | if(SDMMC_MODE(drive) == SD_MODE && SDMMC_INFO(drive).initialized <= 0) |
551 | #endif | 477 | { |
552 | #if CONFIG_STORAGE & STORAGE_MMC | 478 | ret = init_sd_card(drive); |
553 | case MMC_MODE: return transfer_mmc_sectors(drive, start, count, buf, true); | 479 | if(SDMMC_INFO(drive).initialized <= 0) |
480 | goto Lend; | ||
481 | } | ||
554 | #endif | 482 | #endif |
555 | default: return -1; | 483 | |
484 | /* check window */ | ||
485 | start += window_start[drive]; | ||
486 | if((start + count) > window_end[drive]) | ||
487 | { | ||
488 | ret = -201; | ||
489 | goto Lend; | ||
556 | } | 490 | } |
557 | } | ||
558 | 491 | ||
559 | static int sdmmc_write_sectors(int drive, unsigned long start, int count, const void* buf) | 492 | /* select card. |
560 | { | 493 | * NOTE: rely on SD_SELECT_CARD=MMC_SELECT_CARD */ |
561 | switch(SDMMC_MODE(drive)) | 494 | if(!send_cmd(drive, SD_SELECT_CARD, SDMMC_RCA(drive), MCI_NO_RESP, NULL)) |
562 | { | 495 | { |
563 | #if CONFIG_STORAGE & STORAGE_SD | 496 | ret = -20; |
564 | case SD_MODE: return transfer_sd_sectors(drive, start, count, (void *)buf, false); | 497 | goto Lend; |
565 | #endif | ||
566 | #if CONFIG_STORAGE & STORAGE_MMC | ||
567 | case MMC_MODE: return transfer_mmc_sectors(drive, start, count, (void *)buf, false); | ||
568 | #endif | ||
569 | default: return -1; | ||
570 | } | 498 | } |
499 | /* wait for TRAN state */ | ||
500 | /* NOTE: rely on SD_TRAN=MMC_TRAN */ | ||
501 | ret = wait_for_state(drive, SD_TRAN); | ||
502 | if(ret < 0) | ||
503 | goto Ldeselect; | ||
504 | while(count != 0) | ||
505 | { | ||
506 | /* FIXME implement this_count > 1 by using a sub-buffer of [sub] that is | ||
507 | * cache-aligned and then moving the data when possible. This way we could | ||
508 | * transfer much greater amount of data at once */ | ||
509 | int this_count = 1; | ||
510 | /* Set bank_start to the correct unit (blocks or bytes). | ||
511 | * MMC drives use block addressing, SD cards bytes or blocks */ | ||
512 | int bank_start = start; | ||
513 | if(SDMMC_MODE(drive) == SD_MODE && !(SDMMC_INFO(drive).ocr & (1<<30))) /* not SDHC */ | ||
514 | bank_start *= SD_BLOCK_SIZE; | ||
515 | /* on write transfers, copy data to the aligned buffer */ | ||
516 | if(!read) | ||
517 | memcpy(aligned_buffer[drive], buf, 512); | ||
518 | /* issue read/write | ||
519 | * NOTE: rely on SD_{READ,WRITE}_MULTIPLE_BLOCK=MMC_{READ,WRITE}_MULTIPLE_BLOCK */ | ||
520 | ret = imx233_ssp_sd_mmc_transfer(SDMMC_SSP(drive), | ||
521 | read ? SD_READ_MULTIPLE_BLOCK : SD_WRITE_MULTIPLE_BLOCK, | ||
522 | bank_start, SSP_SHORT_RESP, aligned_buffer[drive], this_count, false, read, &resp); | ||
523 | if(ret != SSP_SUCCESS) | ||
524 | break; | ||
525 | /* stop transmission | ||
526 | * NOTE: rely on SD_STOP_TRANSMISSION=MMC_STOP_TRANSMISSION */ | ||
527 | if(!send_cmd(drive, SD_STOP_TRANSMISSION, 0, MCI_RESP|MCI_BUSY, &resp)) | ||
528 | { | ||
529 | ret = -15; | ||
530 | break; | ||
531 | } | ||
532 | /* on read transfers, copy the data back to the user buffer */ | ||
533 | if(read) | ||
534 | memcpy(buf, aligned_buffer[drive], 512); | ||
535 | count -= this_count; | ||
536 | start += this_count; | ||
537 | buf += this_count * 512; | ||
538 | } | ||
539 | /* deselect card */ | ||
540 | Ldeselect: | ||
541 | /* CMD7 w/rca =0 : deselects card & puts it in STBY state | ||
542 | * NOTE: rely on SD_DESELECT_CARD=MMC_DESELECT_CARD */ | ||
543 | if(!send_cmd(drive, SD_DESELECT_CARD, 0, MCI_NO_RESP, NULL)) | ||
544 | ret = -23; | ||
545 | Lend: | ||
546 | /* release per-drive mutex */ | ||
547 | mutex_unlock(&mutex[drive]); | ||
548 | return ret; | ||
571 | } | 549 | } |
572 | 550 | ||
573 | static int sdmmc_init_drive(int drive) | 551 | static int init_drive(int drive) |
574 | { | 552 | { |
575 | int ret; | 553 | int ret; |
576 | switch(SDMMC_MODE(drive)) | 554 | switch(SDMMC_MODE(drive)) |
577 | { | 555 | { |
578 | #if CONFIG_STORAGE & STORAGE_SD | 556 | #if CONFIG_STORAGE & STORAGE_SD |
579 | case SD_MODE: ret = sdmmc_init_sd_card(drive); break; | 557 | case SD_MODE: ret = init_sd_card(drive); break; |
580 | #endif | 558 | #endif |
581 | #if CONFIG_STORAGE & STORAGE_MMC | 559 | #if CONFIG_STORAGE & STORAGE_MMC |
582 | case MMC_MODE: ret = sdmmc_init_mmc_drive(drive); break; | 560 | case MMC_MODE: ret = init_mmc_drive(drive); break; |
583 | #endif | 561 | #endif |
584 | default: ret = 0; | 562 | default: ret = 0; |
585 | } | 563 | } |
586 | if(ret < 0) | 564 | if(ret < 0) |
565 | panicf("die %d", ret); | ||
566 | if(ret < 0) | ||
587 | return ret; | 567 | return ret; |
588 | 568 | ||
589 | /* compute window */ | 569 | /* compute window */ |
590 | if((SDMMC_FLAGS(drive) & WINDOW) && imx233_partitions_is_window_enabled()) | 570 | if((SDMMC_FLAGS(drive) & WINDOW) && imx233_partitions_is_window_enabled()) |
591 | { | 571 | { |
592 | uint8_t mbr[512]; | 572 | uint8_t mbr[512]; |
593 | int ret = sdmmc_read_sectors(IF_MD2(drive,) 0, 1, mbr); | 573 | int ret = transfer_sectors(drive, 0, 1, mbr, true); |
594 | if(ret) | 574 | if(ret) |
595 | panicf("Cannot read MBR: %d", ret); | 575 | panicf("Cannot read MBR: %d", ret); |
596 | ret = imx233_partitions_compute_window(mbr, &window_start[drive], | 576 | ret = imx233_partitions_compute_window(mbr, &window_start[drive], |
597 | &window_end[drive]); | 577 | &window_end[drive]); |
598 | if(ret) | 578 | if(ret) |
599 | panicf("cannot compute partitions window: %d", ret); | 579 | panicf("cannot compute partitions window: %d", ret); |
600 | if(SDMMC_MODE(drive) == SD_MODE) | 580 | SDMMC_INFO(drive).numblocks = window_end[drive] - window_start[drive]; |
601 | SDMMC_INFO(drive).numblocks = window_end[drive] - window_start[drive]; | ||
602 | } | 581 | } |
603 | 582 | ||
604 | return 0; | 583 | return 0; |
@@ -624,9 +603,6 @@ static void sd_thread(void) | |||
624 | * would cause a reverse-order attempt with | 603 | * would cause a reverse-order attempt with |
625 | * another thread */ | 604 | * another thread */ |
626 | fat_lock(); | 605 | fat_lock(); |
627 | /* lock-out card activity - direct calls | ||
628 | * into driver that bypass the fat cache */ | ||
629 | mutex_lock(&sd_mutex); | ||
630 | 606 | ||
631 | /* We now have exclusive control of fat cache and sd. | 607 | /* We now have exclusive control of fat cache and sd. |
632 | * Release "by force", ensure file | 608 | * Release "by force", ensure file |
@@ -634,9 +610,13 @@ static void sd_thread(void) | |||
634 | * ones are invalid if mounting. */ | 610 | * ones are invalid if mounting. */ |
635 | for(unsigned sd_drive = 0; sd_drive < _sd_num_drives; sd_drive++) | 611 | for(unsigned sd_drive = 0; sd_drive < _sd_num_drives; sd_drive++) |
636 | { | 612 | { |
613 | int drive = sd_map[sd_drive]; | ||
637 | /* Skip non-removable drivers */ | 614 | /* Skip non-removable drivers */ |
638 | if(!sd_removable(sd_drive)) | 615 | if(!sd_removable(sd_drive)) |
639 | continue; | 616 | continue; |
617 | /* lock-out card activity - direct calls | ||
618 | * into driver that bypass the fat cache */ | ||
619 | mutex_lock(&mutex[drive]); | ||
640 | disk_unmount(sd_first_drive + sd_drive); | 620 | disk_unmount(sd_first_drive + sd_drive); |
641 | /* Force card init for new card, re-init for re-inserted one or | 621 | /* Force card init for new card, re-init for re-inserted one or |
642 | * clear if the last attempt to init failed with an error. */ | 622 | * clear if the last attempt to init failed with an error. */ |
@@ -644,7 +624,7 @@ static void sd_thread(void) | |||
644 | 624 | ||
645 | if(ev.id == SYS_HOTSWAP_INSERTED) | 625 | if(ev.id == SYS_HOTSWAP_INSERTED) |
646 | { | 626 | { |
647 | microsd_init = sdmmc_init_drive(sd_map[sd_drive]); | 627 | microsd_init = init_drive(drive); |
648 | if(microsd_init < 0) /* initialisation failed */ | 628 | if(microsd_init < 0) /* initialisation failed */ |
649 | panicf("%s init failed : %d", SDMMC_CONF(sd_map[sd_drive]).name, microsd_init); | 629 | panicf("%s init failed : %d", SDMMC_CONF(sd_map[sd_drive]).name, microsd_init); |
650 | 630 | ||
@@ -656,14 +636,15 @@ static void sd_thread(void) | |||
656 | */ | 636 | */ |
657 | if(microsd_init) | 637 | if(microsd_init) |
658 | queue_broadcast(SYS_FS_CHANGED, 0); | 638 | queue_broadcast(SYS_FS_CHANGED, 0); |
639 | /* unlock card */ | ||
640 | mutex_unlock(&mutex[drive]); | ||
659 | } | 641 | } |
660 | /* Access is now safe */ | 642 | /* Access is now safe */ |
661 | mutex_unlock(&sd_mutex); | ||
662 | fat_unlock(); | 643 | fat_unlock(); |
663 | break; | 644 | break; |
664 | } | 645 | } |
665 | case SYS_TIMEOUT: | 646 | case SYS_TIMEOUT: |
666 | if(!TIME_BEFORE(current_tick, _sd_last_disk_activity + 3 * HZ)) | 647 | if(!TIME_BEFORE(current_tick, sd_last_disk_activity() + 3 * HZ)) |
667 | sd_enable(false); | 648 | sd_enable(false); |
668 | break; | 649 | break; |
669 | case SYS_USB_CONNECTED: | 650 | case SYS_USB_CONNECTED: |
@@ -675,15 +656,16 @@ static void sd_thread(void) | |||
675 | } | 656 | } |
676 | } | 657 | } |
677 | 658 | ||
678 | int sdmmc_init(void) | 659 | static int sdmmc_init(void) |
679 | { | 660 | { |
680 | static int is_initialized = false; | 661 | static int is_initialized = false; |
681 | if(is_initialized) | 662 | if(is_initialized) |
682 | return 0; | 663 | return 0; |
683 | is_initialized = true; | 664 | is_initialized = true; |
665 | for(unsigned drive = 0; drive < SDMMC_NUM_DRIVES; drive++) | ||
666 | mutex_init(&mutex[drive]); | ||
684 | 667 | ||
685 | #if CONFIG_STORAGE & STORAGE_SD | 668 | #if CONFIG_STORAGE & STORAGE_SD |
686 | mutex_init(&sd_mutex); | ||
687 | queue_init(&sd_queue, true); | 669 | queue_init(&sd_queue, true); |
688 | create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0, | 670 | create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0, |
689 | sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU)); | 671 | sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU)); |
@@ -748,7 +730,10 @@ bool sd_removable(IF_MV_NONVOID(int sd_drive)) | |||
748 | 730 | ||
749 | long sd_last_disk_activity(void) | 731 | long sd_last_disk_activity(void) |
750 | { | 732 | { |
751 | return _sd_last_disk_activity; | 733 | long last = 0; |
734 | for(unsigned i = 0; i < _sd_num_drives; i++) | ||
735 | last = MAX(last, disk_last_activity[sd_map[i]]); | ||
736 | return last; | ||
752 | } | 737 | } |
753 | 738 | ||
754 | void sd_enable(bool on) | 739 | void sd_enable(bool on) |
@@ -758,12 +743,12 @@ void sd_enable(bool on) | |||
758 | 743 | ||
759 | int sd_read_sectors(IF_MD2(int sd_drive,) unsigned long start, int count, void *buf) | 744 | int sd_read_sectors(IF_MD2(int sd_drive,) unsigned long start, int count, void *buf) |
760 | { | 745 | { |
761 | return sdmmc_read_sectors(sd_map[sd_drive], start, count, buf); | 746 | return transfer_sectors(sd_map[sd_drive], start, count, buf, true); |
762 | } | 747 | } |
763 | 748 | ||
764 | int sd_write_sectors(IF_MD2(int sd_drive,) unsigned long start, int count, const void* buf) | 749 | int sd_write_sectors(IF_MD2(int sd_drive,) unsigned long start, int count, const void* buf) |
765 | { | 750 | { |
766 | return sdmmc_write_sectors(sd_map[sd_drive], start, count, buf); | 751 | return transfer_sectors(sd_map[sd_drive], start, count, (void *)buf, false); |
767 | } | 752 | } |
768 | #endif | 753 | #endif |
769 | 754 | ||
@@ -778,7 +763,7 @@ int mmc_init(void) | |||
778 | if(SDMMC_MODE(drive) == MMC_MODE) | 763 | if(SDMMC_MODE(drive) == MMC_MODE) |
779 | { | 764 | { |
780 | mmc_map[_mmc_num_drives++] = drive; | 765 | mmc_map[_mmc_num_drives++] = drive; |
781 | sdmmc_init_drive(drive); | 766 | init_drive(drive); |
782 | } | 767 | } |
783 | return 0; | 768 | return 0; |
784 | } | 769 | } |
@@ -811,7 +796,10 @@ bool mmc_removable(IF_MV_NONVOID(int mmc_drive)) | |||
811 | 796 | ||
812 | long mmc_last_disk_activity(void) | 797 | long mmc_last_disk_activity(void) |
813 | { | 798 | { |
814 | return _mmc_last_disk_activity; | 799 | long last = 0; |
800 | for(unsigned i = 0; i < _mmc_num_drives; i++) | ||
801 | last = MAX(last, disk_last_activity[mmc_map[i]]); | ||
802 | return last; | ||
815 | } | 803 | } |
816 | 804 | ||
817 | void mmc_enable(bool on) | 805 | void mmc_enable(bool on) |
@@ -863,12 +851,12 @@ int mmc_spinup_time(void) | |||
863 | 851 | ||
864 | int mmc_read_sectors(IF_MD2(int mmc_drive,) unsigned long start, int count, void *buf) | 852 | int mmc_read_sectors(IF_MD2(int mmc_drive,) unsigned long start, int count, void *buf) |
865 | { | 853 | { |
866 | return sdmmc_read_sectors(mmc_map[mmc_drive], start, count, buf); | 854 | return transfer_sectors(mmc_map[mmc_drive], start, count, buf, true); |
867 | } | 855 | } |
868 | 856 | ||
869 | int mmc_write_sectors(IF_MD2(int mmc_drive,) unsigned long start, int count, const void* buf) | 857 | int mmc_write_sectors(IF_MD2(int mmc_drive,) unsigned long start, int count, const void* buf) |
870 | { | 858 | { |
871 | return sdmmc_write_sectors(mmc_map[mmc_drive], start, count, buf); | 859 | return transfer_sectors(mmc_map[mmc_drive], start, count, (void *)buf, false); |
872 | } | 860 | } |
873 | 861 | ||
874 | #endif | 862 | #endif |