diff options
author | Jens Arnold <amiconn@rockbox.org> | 2008-09-19 07:27:08 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2008-09-19 07:27:08 +0000 |
commit | 5b17f37e84cdba2fd9057429dc9f102c4c0cc8f5 (patch) | |
tree | 593ef1d6f5acee216d915922b9b501c7c64596fe | |
parent | eab54984840ecb9b0e55622f73260c84847f07be (diff) | |
download | rockbox-5b17f37e84cdba2fd9057429dc9f102c4c0cc8f5.tar.gz rockbox-5b17f37e84cdba2fd9057429dc9f102c4c0cc8f5.zip |
Change the way send_cmd() returns data to make it cleaner and save binsize. Also change the command composition for the same reasons.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18551 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/drivers/ata_mmc.c | 143 |
1 files changed, 60 insertions, 83 deletions
diff --git a/firmware/drivers/ata_mmc.c b/firmware/drivers/ata_mmc.c index 5acc75c680..447bd8bec6 100644 --- a/firmware/drivers/ata_mmc.c +++ b/firmware/drivers/ata_mmc.c | |||
@@ -145,7 +145,7 @@ static void read_transfer(unsigned char *buf, int len) | |||
145 | __attribute__ ((section(".icode"))); | 145 | __attribute__ ((section(".icode"))); |
146 | static unsigned char poll_byte(long timeout); | 146 | static unsigned char poll_byte(long timeout); |
147 | static unsigned char poll_busy(long timeout); | 147 | static unsigned char poll_busy(long timeout); |
148 | static int send_cmd(int cmd, unsigned long parameter, unsigned char *response); | 148 | static unsigned char send_cmd(int cmd, unsigned long parameter, void *data); |
149 | static int receive_cxd(unsigned char *buf); | 149 | static int receive_cxd(unsigned char *buf); |
150 | static int initialize_card(int card_no); | 150 | static int initialize_card(int card_no); |
151 | static int receive_block(unsigned char *inbuf, long timeout); | 151 | static int receive_block(unsigned char *inbuf, long timeout); |
@@ -318,30 +318,25 @@ static unsigned char poll_busy(long timeout) | |||
318 | return (dummy == 0xFF) ? data : 0; | 318 | return (dummy == 0xFF) ? data : 0; |
319 | } | 319 | } |
320 | 320 | ||
321 | /* Send MMC command and get response */ | 321 | /* Send MMC command and get response. Returns R1 byte directly. |
322 | static int send_cmd(int cmd, unsigned long parameter, unsigned char *response) | 322 | * Returns further R2 or R3 bytes in *data (can be NULL for other commands) */ |
323 | static unsigned char send_cmd(int cmd, unsigned long parameter, void *data) | ||
323 | { | 324 | { |
324 | unsigned char command[] = {0x40, 0x00, 0x00, 0x00, 0x00, 0x95, 0xFF}; | 325 | static struct { |
326 | unsigned char cmd; | ||
327 | unsigned long parameter; | ||
328 | const unsigned char crc7; /* fixed, valid for CMD0 only */ | ||
329 | const unsigned char trailer; | ||
330 | } __attribute__((packed)) command = {0x40, 0, 0x95, 0xFF}; | ||
325 | 331 | ||
326 | command[0] = cmd; | 332 | unsigned char ret; |
327 | |||
328 | if (parameter != 0) | ||
329 | { | ||
330 | command[1] = (parameter >> 24) & 0xFF; | ||
331 | command[2] = (parameter >> 16) & 0xFF; | ||
332 | command[3] = (parameter >> 8) & 0xFF; | ||
333 | command[4] = parameter & 0xFF; | ||
334 | } | ||
335 | |||
336 | write_transfer(command, 7); | ||
337 | 333 | ||
338 | response[0] = poll_byte(20); | 334 | command.cmd = cmd; |
335 | command.parameter = htobe32(parameter); | ||
339 | 336 | ||
340 | if (response[0] != 0x00) | 337 | write_transfer((unsigned char *)&command, sizeof(command)); |
341 | { | 338 | |
342 | write_transfer(dummy, 1); | 339 | ret = poll_byte(20); |
343 | return -1; | ||
344 | } | ||
345 | 340 | ||
346 | switch (cmd) | 341 | switch (cmd) |
347 | { | 342 | { |
@@ -349,24 +344,21 @@ static int send_cmd(int cmd, unsigned long parameter, unsigned char *response) | |||
349 | case CMD_SEND_CID: | 344 | case CMD_SEND_CID: |
350 | case CMD_READ_SINGLE_BLOCK: | 345 | case CMD_READ_SINGLE_BLOCK: |
351 | case CMD_READ_MULTIPLE_BLOCK: | 346 | case CMD_READ_MULTIPLE_BLOCK: |
352 | break; | 347 | return ret; |
353 | 348 | ||
354 | case CMD_SEND_STATUS: /* R2 response, close with dummy */ | 349 | case CMD_SEND_STATUS: /* R2 response, close with dummy */ |
355 | read_transfer(response + 1, 1); | 350 | read_transfer(data, 1); |
356 | write_transfer(dummy, 1); | ||
357 | break; | 351 | break; |
358 | 352 | ||
359 | case CMD_READ_OCR: /* R3 response, close with dummy */ | 353 | case CMD_READ_OCR: /* R3 response, close with dummy */ |
360 | read_transfer(response + 1, 4); | 354 | read_transfer(data, 4); |
361 | write_transfer(dummy, 1); | ||
362 | break; | 355 | break; |
363 | 356 | ||
364 | default: /* R1 response, close with dummy */ | 357 | default: /* R1 response, close with dummy */ |
365 | write_transfer(dummy, 1); | ||
366 | break; /* also catches block writes */ | 358 | break; /* also catches block writes */ |
367 | } | 359 | } |
368 | 360 | write_transfer(dummy, 1); | |
369 | return 0; | 361 | return ret; |
370 | } | 362 | } |
371 | 363 | ||
372 | /* Receive CID/ CSD data (16 bytes) */ | 364 | /* Receive CID/ CSD data (16 bytes) */ |
@@ -388,7 +380,6 @@ static int initialize_card(int card_no) | |||
388 | { | 380 | { |
389 | int rc, i; | 381 | int rc, i; |
390 | int blk_exp, ts_exp, taac_exp; | 382 | int blk_exp, ts_exp, taac_exp; |
391 | unsigned char response[5]; | ||
392 | tCardInfo *card = &card_info[card_no]; | 383 | tCardInfo *card = &card_info[card_no]; |
393 | 384 | ||
394 | static const char mantissa[] = { /* *10 */ | 385 | static const char mantissa[] = { /* *10 */ |
@@ -402,43 +393,40 @@ static int initialize_card(int card_no) | |||
402 | 393 | ||
403 | if (card_no == 1) | 394 | if (card_no == 1) |
404 | mmc_status = MMC_TOUCHED; | 395 | mmc_status = MMC_TOUCHED; |
396 | |||
405 | /* switch to SPI mode */ | 397 | /* switch to SPI mode */ |
406 | send_cmd(CMD_GO_IDLE_STATE, 0, response); | 398 | if (send_cmd(CMD_GO_IDLE_STATE, 0, NULL) != 0x01) |
407 | if (response[0] != 0x01) | 399 | return -1; /* error or no response */ |
408 | return -1; /* error response */ | ||
409 | 400 | ||
410 | /* initialize card */ | 401 | /* initialize card */ |
411 | for (i = 0; i < HZ; i++) /* timeout 1 sec */ | 402 | for (i = HZ;;) /* try for 1 second*/ |
412 | { | 403 | { |
413 | sleep(1); | 404 | sleep(1); |
414 | if (send_cmd(CMD_SEND_OP_COND, 0, response) == 0) | 405 | if (send_cmd(CMD_SEND_OP_COND, 0, NULL) == 0) |
415 | break; | 406 | break; |
407 | if (--i <= 0) | ||
408 | return -2; /* timeout */ | ||
416 | } | 409 | } |
417 | if (response[0] != 0x00) | 410 | |
418 | return -2; /* not ready */ | ||
419 | |||
420 | /* get OCR register */ | 411 | /* get OCR register */ |
421 | rc = send_cmd(CMD_READ_OCR, 0, response); | 412 | if (send_cmd(CMD_READ_OCR, 0, &card->ocr)) |
422 | if (rc) | 413 | return -3; |
423 | return rc * 10 - 3; | 414 | card->ocr = betoh32(card->ocr); /* no-op on big endian */ |
424 | card->ocr = (response[1] << 24) | (response[2] << 16) | 415 | |
425 | | (response[3] << 8) | response[4]; | ||
426 | |||
427 | /* check voltage */ | 416 | /* check voltage */ |
428 | if (!(card->ocr & 0x00100000)) /* 3.2 .. 3.3 V */ | 417 | if (!(card->ocr & 0x00100000)) /* 3.2 .. 3.3 V */ |
429 | return -4; | 418 | return -4; |
430 | 419 | ||
431 | /* get CSD register */ | 420 | /* get CSD register */ |
432 | rc = send_cmd(CMD_SEND_CSD, 0, response); | 421 | if (send_cmd(CMD_SEND_CSD, 0, NULL)) |
433 | if (rc) | 422 | return -5; |
434 | return rc * 10 - 5; | ||
435 | rc = receive_cxd((unsigned char*)card->csd); | 423 | rc = receive_cxd((unsigned char*)card->csd); |
436 | if (rc) | 424 | if (rc) |
437 | return rc * 10 - 6; | 425 | return rc * 10 - 5; |
438 | 426 | ||
439 | blk_exp = card_extract_bits(card->csd, 44, 4); | 427 | blk_exp = card_extract_bits(card->csd, 44, 4); |
440 | if (blk_exp < 9) /* block size < 512 bytes not supported */ | 428 | if (blk_exp < 9) /* block size < 512 bytes not supported */ |
441 | return -7; | 429 | return -6; |
442 | 430 | ||
443 | card->numblocks = (card_extract_bits(card->csd, 54, 12) + 1) | 431 | card->numblocks = (card_extract_bits(card->csd, 54, 12) + 1) |
444 | << (card_extract_bits(card->csd, 78, 3) + 2 + blk_exp - 9); | 432 | << (card_extract_bits(card->csd, 78, 3) + 2 + blk_exp - 9); |
@@ -472,17 +460,15 @@ static int initialize_card(int card_no) | |||
472 | setup_sci1(card->bitrate_register); | 460 | setup_sci1(card->bitrate_register); |
473 | 461 | ||
474 | /* always use 512 byte blocks */ | 462 | /* always use 512 byte blocks */ |
475 | rc = send_cmd(CMD_SET_BLOCKLEN, BLOCK_SIZE, response); | 463 | if (send_cmd(CMD_SET_BLOCKLEN, BLOCK_SIZE, NULL)) |
476 | if (rc) | 464 | return -7; |
477 | return rc * 10 - 8; | ||
478 | 465 | ||
479 | /* get CID register */ | 466 | /* get CID register */ |
480 | rc = send_cmd(CMD_SEND_CID, 0, response); | 467 | if (send_cmd(CMD_SEND_CID, 0, NULL)) |
481 | if (rc) | 468 | return -8; |
482 | return rc * 10 - 9; | ||
483 | rc = receive_cxd((unsigned char*)card->cid); | 469 | rc = receive_cxd((unsigned char*)card->cid); |
484 | if (rc) | 470 | if (rc) |
485 | return rc * 10 - 9; | 471 | return rc * 10 - 8; |
486 | 472 | ||
487 | card->initialized = true; | 473 | card->initialized = true; |
488 | return 0; | 474 | return 0; |
@@ -623,7 +609,6 @@ int ata_read_sectors(IF_MV2(int drive,) | |||
623 | int rc = 0; | 609 | int rc = 0; |
624 | int lastblock = 0; | 610 | int lastblock = 0; |
625 | unsigned long end_block; | 611 | unsigned long end_block; |
626 | unsigned char response; | ||
627 | tCardInfo *card; | 612 | tCardInfo *card; |
628 | #ifndef HAVE_MULTIVOLUME | 613 | #ifndef HAVE_MULTIVOLUME |
629 | int drive = current_card; | 614 | int drive = current_card; |
@@ -652,11 +637,10 @@ int ata_read_sectors(IF_MV2(int drive,) | |||
652 | 637 | ||
653 | if (incount > 1) | 638 | if (incount > 1) |
654 | { | 639 | { |
655 | rc = send_cmd(CMD_READ_MULTIPLE_BLOCK, start * BLOCK_SIZE, &response); | 640 | /* MMC4.2: make multiplication conditional */ |
656 | /* MMC4.2: make multiplication conditional */ | 641 | if (send_cmd(CMD_READ_MULTIPLE_BLOCK, start * BLOCK_SIZE, NULL)) |
657 | if (rc) | ||
658 | { | 642 | { |
659 | rc = rc * 10 - 3; | 643 | rc = -3; |
660 | goto error; | 644 | goto error; |
661 | } | 645 | } |
662 | while (incount-- > lastblock) | 646 | while (incount-- > lastblock) |
@@ -666,7 +650,7 @@ int ata_read_sectors(IF_MV2(int drive,) | |||
666 | { | 650 | { |
667 | /* If an error occurs during multiple block reading, the | 651 | /* If an error occurs during multiple block reading, the |
668 | * host still needs to send CMD_STOP_TRANSMISSION */ | 652 | * host still needs to send CMD_STOP_TRANSMISSION */ |
669 | send_cmd(CMD_STOP_TRANSMISSION, 0, &response); | 653 | send_cmd(CMD_STOP_TRANSMISSION, 0, NULL); |
670 | rc = rc * 10 - 4; | 654 | rc = rc * 10 - 4; |
671 | goto error; | 655 | goto error; |
672 | } | 656 | } |
@@ -674,20 +658,18 @@ int ata_read_sectors(IF_MV2(int drive,) | |||
674 | start++; | 658 | start++; |
675 | /* ^^ necessary for the abovementioned last block special case */ | 659 | /* ^^ necessary for the abovementioned last block special case */ |
676 | } | 660 | } |
677 | rc = send_cmd(CMD_STOP_TRANSMISSION, 0, &response); | 661 | if (send_cmd(CMD_STOP_TRANSMISSION, 0, NULL)) |
678 | if (rc) | ||
679 | { | 662 | { |
680 | rc = rc * 10 - 5; | 663 | rc = -5; |
681 | goto error; | 664 | goto error; |
682 | } | 665 | } |
683 | } | 666 | } |
684 | if (incount > 0) | 667 | if (incount > 0) |
685 | { | 668 | { |
686 | rc = send_cmd(CMD_READ_SINGLE_BLOCK, start * BLOCK_SIZE, &response); | 669 | /* MMC4.2: make multiplication conditional */ |
687 | /* MMC4.2: make multiplication conditional */ | 670 | if (send_cmd(CMD_READ_SINGLE_BLOCK, start * BLOCK_SIZE, NULL)) |
688 | if (rc) | ||
689 | { | 671 | { |
690 | rc = rc * 10 - 6; | 672 | rc = -6; |
691 | goto error; | 673 | goto error; |
692 | } | 674 | } |
693 | rc = receive_block(inbuf, card->read_timeout); | 675 | rc = receive_block(inbuf, card->read_timeout); |
@@ -713,7 +695,6 @@ int ata_write_sectors(IF_MV2(int drive,) | |||
713 | int rc = 0; | 695 | int rc = 0; |
714 | int write_cmd; | 696 | int write_cmd; |
715 | unsigned char start_token; | 697 | unsigned char start_token; |
716 | unsigned char response; | ||
717 | tCardInfo *card; | 698 | tCardInfo *card; |
718 | #ifndef HAVE_MULTIVOLUME | 699 | #ifndef HAVE_MULTIVOLUME |
719 | int drive = current_card; | 700 | int drive = current_card; |
@@ -743,11 +724,10 @@ int ata_write_sectors(IF_MV2(int drive,) | |||
743 | write_cmd = CMD_WRITE_BLOCK; | 724 | write_cmd = CMD_WRITE_BLOCK; |
744 | start_token = DT_START_BLOCK; | 725 | start_token = DT_START_BLOCK; |
745 | } | 726 | } |
746 | rc = send_cmd(write_cmd, start * BLOCK_SIZE, &response); | 727 | /* MMC4.2: make multiplication conditional */ |
747 | /* MMC4.2: make multiplication conditional */ | 728 | if (send_cmd(write_cmd, start * BLOCK_SIZE, NULL)) |
748 | if (rc) | ||
749 | { | 729 | { |
750 | rc = rc * 10 - 2; | 730 | rc = -2; |
751 | goto error; | 731 | goto error; |
752 | } | 732 | } |
753 | 733 | ||
@@ -771,8 +751,8 @@ int ata_write_sectors(IF_MV2(int drive,) | |||
771 | 751 | ||
772 | if (write_cmd == CMD_WRITE_MULTIPLE_BLOCK) | 752 | if (write_cmd == CMD_WRITE_MULTIPLE_BLOCK) |
773 | { | 753 | { |
774 | response = DT_STOP_TRAN; | 754 | static const unsigned char stop_tran = DT_STOP_TRAN; |
775 | write_transfer(&response, 1); | 755 | write_transfer(&stop_tran, 1); |
776 | poll_busy(card->write_timeout); | 756 | poll_busy(card->write_timeout); |
777 | } | 757 | } |
778 | 758 | ||
@@ -863,13 +843,10 @@ bool mmc_touched(void) | |||
863 | { | 843 | { |
864 | if (mmc_status == MMC_UNKNOWN) /* try to detect */ | 844 | if (mmc_status == MMC_UNKNOWN) /* try to detect */ |
865 | { | 845 | { |
866 | unsigned char response; | ||
867 | |||
868 | mutex_lock(&mmc_mutex); | 846 | mutex_lock(&mmc_mutex); |
869 | setup_sci1(7); /* safe value */ | 847 | setup_sci1(7); /* safe value */ |
870 | and_b(~0x02, &PADRH); /* assert CS */ | 848 | and_b(~0x02, &PADRH); /* assert CS */ |
871 | send_cmd(CMD_SEND_OP_COND, 0, &response); | 849 | if (send_cmd(CMD_SEND_OP_COND, 0, NULL) == 0xFF) |
872 | if (response == 0xFF) | ||
873 | mmc_status = MMC_UNTOUCHED; | 850 | mmc_status = MMC_UNTOUCHED; |
874 | else | 851 | else |
875 | mmc_status = MMC_TOUCHED; | 852 | mmc_status = MMC_TOUCHED; |