Index: firmware/target/arm/sandisk/sansa-e200/ata-e200.c =================================================================== --- firmware/target/arm/sandisk/sansa-e200/ata-e200.c (revision 14406) +++ firmware/target/arm/sandisk/sansa-e200/ata-e200.c (working copy) @@ -80,6 +80,7 @@ #define SWITCH_FUNC 6 #define SELECT_CARD 7 #define DESELECT_CARD 7 +#define SEND_IF_COND 8 #define SEND_CSD 9 #define SEND_CID 10 #define STOP_TRANSMISSION 12 @@ -244,12 +245,12 @@ } else { - /* Response types 1, 1b, 3, 6 have the following structure: + /* Response types 1, 1b, 3, 6, 7 have the following structure: * Types 4 and 5 are not supported. * * [47] Start bit - '0' * [46] Transmission bit - '0' - * [45:40] R1, R1b, R6: Command index + * [45:40] R1, R1b, R6, R7: Command index * R3: Reserved - '111111' * [39:8] R1, R1b: Card Status * R3: OCR Register @@ -266,6 +267,8 @@ * [3] AKE_SEQ_ERROR * [2] Reserved * [1:0] Reserved for test mode + * R7: [19:16] Voltage accepted + * [15:8] echo-back of check pattern * [7:1] R1, R1b: CRC7 * R3: Reserved - '1111111' * [0] End Bit - '1' @@ -544,6 +547,7 @@ static void sd_init_device(int card_no) { /* SD Protocol registers */ + unsigned int response = 0; unsigned int i; unsigned int c_size; unsigned long c_mult; @@ -581,13 +585,25 @@ goto card_init_error; check_time[EC_POWER_UP] = USEC_TIMER; + + /* Check for SDHC - we don't worry about this returning an error because the + card doesn't respond, we expect it to with non-SDHC cards */ + ret = sd_command(SEND_IF_COND,0x1aa, &response,7); + while ((currcard->ocr & (1 << 31)) == 0) /* until card is powered up */ { ret = sd_command(APP_CMD, currcard->rca, NULL, 1); if (ret < 0) goto card_init_error; - ret = sd_command(SD_APP_OP_COND, 0x100000, &currcard->ocr, 3); + if(response == 0x1aa) + { + /* SDHC */ + ret = sd_command(SD_APP_OP_COND, (1<<30)| 0x100000, &currcard->ocr, 3); + } else { + /* SD Standard */ + ret = sd_command(SD_APP_OP_COND, 0x100000, &currcard->ocr, 3); + } if (ret < 0) goto card_init_error; @@ -639,7 +655,7 @@ BLOCK_SIZE_REG = currcard->block_size; /* If this card is > 4Gb, then we need to enable bank switching */ - if (currcard->numblocks >= BLOCKS_PER_BANK) + if( (currcard->numblocks >= BLOCKS_PER_BANK) && ((currcard->ocr & (1<<30))==0) ) { SD_STATE_REG = TRAN; BLOCK_COUNT_REG = 1; @@ -737,24 +753,36 @@ last_disk_activity = current_tick; - bank = start / BLOCKS_PER_BANK; + if((currcard->ocr & (1<<30))==0) + { + /* Don't switch bank with SDHC cards */ + bank = start / BLOCKS_PER_BANK; - if (currcard->current_bank != bank) - { - ret = sd_select_bank(bank); - if (ret < 0) - goto ata_read_error; + if (currcard->current_bank != bank) + { + ret = sd_select_bank(bank); + if (ret < 0) + goto ata_read_error; + } + + start -= bank * BLOCKS_PER_BANK; } - - start -= bank * BLOCKS_PER_BANK; - + ret = sd_wait_for_state(TRAN, EC_TRAN_READ_ENTRY); if (ret < 0) goto ata_read_error; BLOCK_COUNT_REG = incount; - ret = sd_command(READ_MULTIPLE_BLOCK, start * BLOCK_SIZE, NULL, 0x1c25); + if(currcard->ocr & (1<<30) ) + { + /* SDHC */ + ret = sd_command(READ_MULTIPLE_BLOCK, start, NULL, 0x1c25); + } + else + { + ret = sd_command(READ_MULTIPLE_BLOCK, start * BLOCK_SIZE, NULL, 0x1c25); + } if (ret < 0) goto ata_read_error; @@ -833,17 +861,20 @@ goto ata_write_error; } - bank = start / BLOCKS_PER_BANK; + if((currcard->ocr & (1<<30))==0) + { + bank = start / BLOCKS_PER_BANK; - if (currcard->current_bank != bank) - { - ret = sd_select_bank(bank); - if (ret < 0) - goto ata_write_error; + if (currcard->current_bank != bank) + { + ret = sd_select_bank(bank); + if (ret < 0) + goto ata_write_error; + } + + start -= bank * BLOCKS_PER_BANK; } - - start -= bank * BLOCKS_PER_BANK; - + check_time[EC_WRITE_TIMEOUT] = USEC_TIMER; ret = sd_wait_for_state(TRAN, EC_TRAN_WRITE_ENTRY); @@ -852,8 +883,15 @@ BLOCK_COUNT_REG = count; - ret = sd_command(WRITE_MULTIPLE_BLOCK, start * SECTOR_SIZE, - NULL, 0x1c2d); + if(currcard->ocr & (1<<30) ) + { + /* SDHC */ + ret = sd_command(WRITE_MULTIPLE_BLOCK, start, NULL, 0x1c2d); + } + else + { + ret = sd_command(WRITE_MULTIPLE_BLOCK, start * BLOCK_SIZE, NULL, 0x1c2d); + } if (ret < 0) goto ata_write_error;