diff options
author | Jens Arnold <amiconn@rockbox.org> | 2004-10-03 23:32:09 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2004-10-03 23:32:09 +0000 |
commit | dc6caf9ce817102ee2fca8cc9eb1258c64cbeeed (patch) | |
tree | b188fbf1984938d42925c28bc1ff0780d2f10d11 | |
parent | 4f8d3482c68467670afb3b3b955b7d8b4d665363 (diff) | |
download | rockbox-dc6caf9ce817102ee2fca8cc9eb1258c64cbeeed.tar.gz rockbox-dc6caf9ce817102ee2fca8cc9eb1258c64cbeeed.zip |
Implemented multiple block reading and writing. Significant speedup.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5153 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/drivers/ata_mmc.c | 134 |
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 | ||
92 | static struct mutex ata_mtx; | 96 | static struct mutex mmc_mutex; |
93 | 97 | ||
94 | static char mmc_stack[DEFAULT_STACK_SIZE]; | 98 | static char mmc_stack[DEFAULT_STACK_SIZE]; |
95 | static const char mmc_thread_name[] = "mmc"; | 99 | static const char mmc_thread_name[] = "mmc"; |
@@ -129,8 +133,11 @@ static void write_transfer(const unsigned char *buf, int len) | |||
129 | static void read_transfer(unsigned char *buf, int len) | 133 | static void read_transfer(unsigned char *buf, int len) |
130 | __attribute__ ((section(".icode"))); | 134 | __attribute__ ((section(".icode"))); |
131 | static unsigned char poll_byte(int timeout); | 135 | static unsigned char poll_byte(int timeout); |
136 | static unsigned char poll_busy(int timeout); | ||
132 | static int send_cmd(int cmd, unsigned long parameter, unsigned char *response); | 137 | static int send_cmd(int cmd, unsigned long parameter, unsigned char *response); |
133 | static int receive_data(unsigned char *buf, int len, int timeout); | 138 | static int receive_data(unsigned char *buf, int len, int timeout); |
139 | static int send_data(char start_token, const unsigned char *buf, int len, | ||
140 | int timeout); | ||
134 | static int initialize_card(int card_no); | 141 | static 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 | ||
265 | static int send_cmd(int cmd, unsigned long parameter, unsigned char *response) | 272 | static 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 | ||
332 | static int send_data(const unsigned char *buf, int len, int timeout) | 339 | static 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 */ | ||
444 | int ata_read_sectors(unsigned long start, | 452 | int 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 | |||
484 | int 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 | ||
476 | int ata_write_sectors(unsigned long start, | 529 | int 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 | ||
525 | bool ata_disk_is_active(void) | 598 | bool 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 | ||
530 | int ata_standby(int time) | 604 | int 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 | ||