summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/drivers/ata_mmc.c134
1 files changed, 104 insertions, 30 deletions
diff --git a/firmware/drivers/ata_mmc.c b/firmware/drivers/ata_mmc.c
index d55baf3eea..e17eceff80 100644
--- a/firmware/drivers/ata_mmc.c
+++ b/firmware/drivers/ata_mmc.c
@@ -42,16 +42,14 @@
42#define CMD_GO_IDLE_STATE 0x40 /* R1 */ 42#define CMD_GO_IDLE_STATE 0x40 /* R1 */
43#define CMD_SEND_OP_COND 0x41 /* R1 */ 43#define CMD_SEND_OP_COND 0x41 /* R1 */
44#define CMD_SEND_CSD 0x49 /* R1 */ 44#define CMD_SEND_CSD 0x49 /* R1 */
45#define CMD_SEND_CID 0x4A /* R1 */ 45#define CMD_SEND_CID 0x4a /* R1 */
46#define CMD_STOP_TRANSMISSION 0x4C /* R1 */ 46#define CMD_STOP_TRANSMISSION 0x4c /* R1 */
47#define CMD_SEND_STATUS 0x4D /* R2 */ 47#define CMD_SEND_STATUS 0x4d /* R2 */
48#define CMD_SET_BLOCKLEN 0x50 /* R1 */
49#define CMD_READ_SINGLE_BLOCK 0x51 /* R1 */ 48#define CMD_READ_SINGLE_BLOCK 0x51 /* R1 */
50#define CMD_READ_MULTIPLE_BLOCK 0x52 /* R1 */ 49#define CMD_READ_MULTIPLE_BLOCK 0x52 /* R1 */
51#define CMD_SET_BLOCK_COUNT 0x57 /* R1 */
52#define CMD_WRITE_BLOCK 0x58 /* R1b */ 50#define CMD_WRITE_BLOCK 0x58 /* R1b */
53#define CMD_WRITE_MULTIPLE_BLOCK 0x59 /* R1b */ 51#define CMD_WRITE_MULTIPLE_BLOCK 0x59 /* R1b */
54#define CMD_READ_OCR 0x7A /* R3 */ 52#define CMD_READ_OCR 0x7a /* R3 */
55 53
56/* Response formats: 54/* Response formats:
57 R1 = single byte, msb=0, various error flags 55 R1 = single byte, msb=0, various error flags
@@ -77,6 +75,12 @@
77#define R2_ERASE_SKIP 0x02 75#define R2_ERASE_SKIP 0x02
78#define R2_CARD_LOCKED 0x01 76#define R2_CARD_LOCKED 0x01
79 77
78/* Data start tokens */
79
80#define DT_START_BLOCK 0xfe
81#define DT_START_WRITE_MULTIPLE 0xfc
82#define DT_STOP_TRAN 0xfd
83
80// DEBUG 84// DEBUG
81#include "../../apps/screens.h" 85#include "../../apps/screens.h"
82 86
@@ -89,7 +93,7 @@ long last_disk_activity = -1;
89 93
90/* private variables */ 94/* private variables */
91 95
92static struct mutex ata_mtx; 96static struct mutex mmc_mutex;
93 97
94static char mmc_stack[DEFAULT_STACK_SIZE]; 98static char mmc_stack[DEFAULT_STACK_SIZE];
95static const char mmc_thread_name[] = "mmc"; 99static const char mmc_thread_name[] = "mmc";
@@ -129,8 +133,11 @@ static void write_transfer(const unsigned char *buf, int len)
129static void read_transfer(unsigned char *buf, int len) 133static void read_transfer(unsigned char *buf, int len)
130 __attribute__ ((section(".icode"))); 134 __attribute__ ((section(".icode")));
131static unsigned char poll_byte(int timeout); 135static unsigned char poll_byte(int timeout);
136static unsigned char poll_busy(int timeout);
132static int send_cmd(int cmd, unsigned long parameter, unsigned char *response); 137static int send_cmd(int cmd, unsigned long parameter, unsigned char *response);
133static int receive_data(unsigned char *buf, int len, int timeout); 138static int receive_data(unsigned char *buf, int len, int timeout);
139static int send_data(char start_token, const unsigned char *buf, int len,
140 int timeout);
134static int initialize_card(int card_no); 141static int initialize_card(int card_no);
135 142
136/* implementation */ 143/* implementation */
@@ -264,7 +271,7 @@ static unsigned char poll_busy(int timeout)
264 271
265static int send_cmd(int cmd, unsigned long parameter, unsigned char *response) 272static int send_cmd(int cmd, unsigned long parameter, unsigned char *response)
266{ 273{
267 unsigned char command[] = {0x40, 0x00, 0x00, 0x00, 0x00, 0x95 }; 274 unsigned char command[] = {0x40, 0x00, 0x00, 0x00, 0x00, 0x95, 0xFF};
268 275
269 command[0] = cmd; 276 command[0] = cmd;
270 277
@@ -276,7 +283,7 @@ static int send_cmd(int cmd, unsigned long parameter, unsigned char *response)
276 command[4] = parameter & 0xFF; 283 command[4] = parameter & 0xFF;
277 } 284 }
278 285
279 write_transfer(command, 6); 286 write_transfer(command, 7);
280 287
281 response[0] = poll_byte(20); 288 response[0] = poll_byte(20);
282 289
@@ -291,7 +298,7 @@ static int send_cmd(int cmd, unsigned long parameter, unsigned char *response)
291 case CMD_SEND_CSD: /* R1 response, leave open */ 298 case CMD_SEND_CSD: /* R1 response, leave open */
292 case CMD_SEND_CID: 299 case CMD_SEND_CID:
293 case CMD_READ_SINGLE_BLOCK: 300 case CMD_READ_SINGLE_BLOCK:
294 // case READ_MULTIPLE_BLOCK: 301 case CMD_READ_MULTIPLE_BLOCK:
295 break; 302 break;
296 303
297 case CMD_SEND_STATUS: /* R2 response, close with dummy */ 304 case CMD_SEND_STATUS: /* R2 response, close with dummy */
@@ -316,7 +323,7 @@ static int receive_data(unsigned char *buf, int len, int timeout)
316{ 323{
317 unsigned char crc[2]; /* unused */ 324 unsigned char crc[2]; /* unused */
318 325
319 if (poll_byte(timeout) != 0xFE) 326 if (poll_byte(timeout) != DT_START_BLOCK)
320 { 327 {
321 write_transfer(dummy, 1); 328 write_transfer(dummy, 1);
322 return -1; /* not start of data */ 329 return -1; /* not start of data */
@@ -329,12 +336,12 @@ static int receive_data(unsigned char *buf, int len, int timeout)
329 return 0; 336 return 0;
330} 337}
331 338
332static int send_data(const unsigned char *buf, int len, int timeout) 339static int send_data(char start_token, const unsigned char *buf, int len,
340 int timeout)
333{ 341{
334 static const unsigned char start_data = 0xFE;
335 int ret = 0; 342 int ret = 0;
336 343
337 write_transfer(&start_data, 1); 344 write_transfer(&start_token, 1);
338 write_transfer(buf, len); 345 write_transfer(buf, len);
339 write_transfer(dummy, 2); /* crc - dontcare */ 346 write_transfer(dummy, 2); /* crc - dontcare */
340 347
@@ -441,6 +448,7 @@ static int initialize_card(int card_no)
441 return 0; 448 return 0;
442} 449}
443 450
451#if 0 /* old implementation */
444int ata_read_sectors(unsigned long start, 452int ata_read_sectors(unsigned long start,
445 int incount, 453 int incount,
446 void* inbuf) 454 void* inbuf)
@@ -453,7 +461,7 @@ int ata_read_sectors(unsigned long start,
453 461
454 addr = start * SECTOR_SIZE; 462 addr = start * SECTOR_SIZE;
455 463
456 mutex_lock(&ata_mtx); 464 mutex_lock(&mmc_mutex);
457 ret = select_card(current_card); 465 ret = select_card(current_card);
458 466
459 for (i = 0; (i < incount) && (ret == 0); i++) 467 for (i = 0; (i < incount) && (ret == 0); i++)
@@ -467,11 +475,56 @@ int ata_read_sectors(unsigned long start,
467 } 475 }
468 476
469 deselect_card(); 477 deselect_card();
470 mutex_unlock(&ata_mtx); 478 mutex_unlock(&mmc_mutex);
471 479
472 return ret; 480 return ret;
473} 481}
482#endif
483
484int ata_read_sectors(unsigned long start,
485 int incount,
486 void* inbuf)
487{
488 int ret = 0;
489 int i;
490 unsigned long addr;
491 unsigned char response;
492 tCardInfo *card = &card_info[current_card];
493
494 if (incount <= 0)
495 return ret;
496
497 addr = start * SECTOR_SIZE;
498
499 mutex_lock(&mmc_mutex);
500 ret = select_card(current_card);
501
502 if (ret == 0)
503 {
504 if (incount == 1)
505 {
506 ret = send_cmd(CMD_READ_SINGLE_BLOCK, addr, &response);
507 if (ret == 0)
508 ret = receive_data(inbuf, SECTOR_SIZE, card->read_timeout);
509 }
510 else
511 {
512 ret = send_cmd(CMD_READ_MULTIPLE_BLOCK, addr, &response);
513 for (i = 0; (i < incount) && (ret == 0); i++)
514 {
515 ret = receive_data(inbuf, SECTOR_SIZE, card->read_timeout);
516 inbuf += SECTOR_SIZE;
517 }
518 if (ret == 0)
519 ret = send_cmd(CMD_STOP_TRANSMISSION, 0, &response);
520 }
521 }
522
523 deselect_card();
524 mutex_unlock(&mmc_mutex);
474 525
526 return ret;
527}
475 528
476int ata_write_sectors(unsigned long start, 529int ata_write_sectors(unsigned long start,
477 int count, 530 int count,
@@ -486,24 +539,44 @@ int ata_write_sectors(unsigned long start,
486 if (start == 0) 539 if (start == 0)
487 panicf("Writing on sector 0\n"); 540 panicf("Writing on sector 0\n");
488 541
489 addr = start * SECTOR_SIZE; 542 if (count <= 0)
543 return ret;
490 544
491 mutex_lock(&ata_mtx); 545 addr = start * SECTOR_SIZE;
546
547 mutex_lock(&mmc_mutex);
492 ret = select_card(current_card); 548 ret = select_card(current_card);
493 549
494 for (i = 0; (i < count) && (ret == 0); i++) 550 if (ret == 0)
495 { 551 {
496 if ((ret = send_cmd(CMD_WRITE_BLOCK, addr, &response))) 552 if (count == 1)
497 break; 553 {
498 ret = send_data(buf, SECTOR_SIZE, card->write_timeout); 554 ret = send_cmd(CMD_WRITE_BLOCK, addr, &response);
499 555 if (ret == 0)
500 addr += SECTOR_SIZE; 556 ret = send_data(DT_START_BLOCK, buf, SECTOR_SIZE,
501 buf += SECTOR_SIZE; 557 card->write_timeout);
558 }
559 else
560 {
561 ret = send_cmd(CMD_WRITE_MULTIPLE_BLOCK, addr, &response);
562 for (i = 0; (i < count) && (ret == 0); i++)
563 {
564 ret = send_data(DT_START_WRITE_MULTIPLE, buf, SECTOR_SIZE,
565 card->write_timeout);
566 buf += SECTOR_SIZE;
567 }
568 if (ret == 0)
569 {
570 response = DT_STOP_TRAN;
571 write_transfer(&response, 1);
572 poll_busy(card->write_timeout);
573 }
574 }
502 } 575 }
503 576
504 deselect_card(); 577 deselect_card();
505 mutex_unlock(&ata_mtx); 578 mutex_unlock(&mmc_mutex);
506 579
507 return ret; 580 return ret;
508} 581}
509 582
@@ -523,8 +596,9 @@ void ata_spindown(int seconds)
523} 596}
524 597
525bool ata_disk_is_active(void) 598bool ata_disk_is_active(void)
526{ 599{
527 return false; /* FIXME: dirty, but makes idle poweroff work */ 600 /* this is correct unless early return from write gets implemented */
601 return mmc_mutex.locked;
528} 602}
529 603
530int ata_standby(int time) 604int ata_standby(int time)
@@ -596,7 +670,7 @@ int ata_init(void)
596{ 670{
597 int rc = 0; 671 int rc = 0;
598 672
599 mutex_init(&ata_mtx); 673 mutex_init(&mmc_mutex);
600 674
601 led(false); 675 led(false);
602 676