summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2008-09-19 07:27:08 +0000
committerJens Arnold <amiconn@rockbox.org>2008-09-19 07:27:08 +0000
commit5b17f37e84cdba2fd9057429dc9f102c4c0cc8f5 (patch)
tree593ef1d6f5acee216d915922b9b501c7c64596fe
parenteab54984840ecb9b0e55622f73260c84847f07be (diff)
downloadrockbox-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.c143
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")));
146static unsigned char poll_byte(long timeout); 146static unsigned char poll_byte(long timeout);
147static unsigned char poll_busy(long timeout); 147static unsigned char poll_busy(long timeout);
148static int send_cmd(int cmd, unsigned long parameter, unsigned char *response); 148static unsigned char send_cmd(int cmd, unsigned long parameter, void *data);
149static int receive_cxd(unsigned char *buf); 149static int receive_cxd(unsigned char *buf);
150static int initialize_card(int card_no); 150static int initialize_card(int card_no);
151static int receive_block(unsigned char *inbuf, long timeout); 151static 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.
322static 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) */
323static 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;