mirror of
https://github.com/libretro/Mu.git
synced 2026-09-25 08:06:04 +00:00
More SD card stuff
This commit is contained in:
@@ -91,9 +91,11 @@ typedef struct{
|
||||
uint8_t response;
|
||||
uint64_t responseState;//this can contain many different types of data depending on the response type
|
||||
uint8_t responseWaitBitsRemaining;//not in savestates yet!!
|
||||
bool commandIsAcmd;//not in savestates yet!!
|
||||
bool allowInvalidCrc;
|
||||
bool chipSelect;
|
||||
bool receivingCommand;//not in savstates yet!!
|
||||
bool receivingCommand;//not in savestates yet!!
|
||||
bool inIdleState;//not in savestates yet!!
|
||||
buffer_t flashChip;
|
||||
}sd_card_t;
|
||||
|
||||
|
||||
@@ -103,10 +103,10 @@ int32_t interruptAcknowledge(int32_t intLevel){
|
||||
int32_t vector;
|
||||
|
||||
//If an interrupt occurs before the IVR has been programmed, interrupt vector 15 is returned to the CPU as an uninitialized interrupt.
|
||||
if(!vectorOffset)
|
||||
vector = 15;//EXCEPTION_UNINITIALIZED_INTERRUPT
|
||||
else
|
||||
if(vectorOffset)
|
||||
vector = vectorOffset | intLevel;
|
||||
else
|
||||
vector = 15;//EXCEPTION_UNINITIALIZED_INTERRUPT
|
||||
|
||||
//only active interrupts should wake the CPU if the PLL is off
|
||||
pllWakeCpuIfOff();
|
||||
@@ -419,7 +419,7 @@ uint16_t getHwRegister16(uint32_t address){
|
||||
uint16_t fifoVal = spi1RxFifoRead();
|
||||
//check if SPI1 interrupts changed
|
||||
setSpiIntCs(registerArrayRead16(SPIINTCS));
|
||||
debugLog("SPIRXD read, FIFO value:0x%04X, SPIINTCS:0x%04X\n", fifoVal, registerArrayRead16(SPIINTCS));
|
||||
//debugLog("SPIRXD read, FIFO value:0x%04X, SPIINTCS:0x%04X\n", fifoVal, registerArrayRead16(SPIINTCS));
|
||||
return fifoVal;
|
||||
}
|
||||
|
||||
|
||||
@@ -377,7 +377,7 @@ static void setSpiCont1(uint16_t value){
|
||||
uint16_t startBit = 1 << (bitCount - 1);
|
||||
uint8_t bits;
|
||||
|
||||
debugLog("SPI1 transfer, bitCount:%d, PC:0x%08X\n", bitCount, flx68000GetPc());
|
||||
//debugLog("SPI1 transfer, bitCount:%d, PC:0x%08X\n", bitCount, flx68000GetPc());
|
||||
|
||||
//The most significant bit is output when the CPU loads the transmitted data, 13.2.3 SPI 1 Phase and Polarity Configurations MC68VZ328UM.pdf
|
||||
for(bits = 0; bits < bitCount; bits++){
|
||||
|
||||
66
src/sdCard.c
66
src/sdCard.c
@@ -34,14 +34,18 @@ static const uint8_t sdCardCrc7Table[256] = {
|
||||
};
|
||||
static const uint64_t sdCardCsd[2] = {0x0000000000000000, 0x0000000000000000};
|
||||
static const uint64_t sdCardCid[2] = {0x0000000000000000, 0x0000000000000000};
|
||||
static const uint32_t sdCardOcr = 0x00000000;
|
||||
|
||||
|
||||
static void sdCardCmdStart(void){
|
||||
static uint32_t sdCardGetOcr(){
|
||||
return !palmSdCard.inIdleState << 31/*power up status*/ | 0 << 30/*card capacity status*/ | 0x01FF8000/*supported voltages*/;
|
||||
}
|
||||
|
||||
static void sdCardCmdStart(bool isAcmd){
|
||||
palmSdCard.command = UINT64_C(0x0000000000000000);
|
||||
palmSdCard.commandBitsRemaining = 48;
|
||||
palmSdCard.responseState = 0;
|
||||
palmSdCard.response = SD_CARD_RESPONSE_NOTHING;
|
||||
palmSdCard.commandIsAcmd = isAcmd;
|
||||
palmSdCard.receivingCommand = true;
|
||||
}
|
||||
|
||||
@@ -75,7 +79,7 @@ static void sdCardDoResponseR1(uint8_t r1){
|
||||
static void sdCardDoResponseR3(uint8_t r1){
|
||||
palmSdCard.response = SD_CARD_RESPONSE_SHIFT_OUT;
|
||||
palmSdCard.responseState = (uint64_t)r1 << 56;
|
||||
palmSdCard.responseState |= (uint64_t)sdCardOcr << 24;
|
||||
palmSdCard.responseState |= (uint64_t)sdCardGetOcr() << 24;
|
||||
palmSdCard.responseState |= UINT64_C(1) << 23;//add shift termination bit
|
||||
}
|
||||
|
||||
@@ -85,9 +89,11 @@ void sdCardReset(void){
|
||||
palmSdCard.responseState = 0;
|
||||
palmSdCard.response = SD_CARD_RESPONSE_NOTHING;
|
||||
palmSdCard.responseWaitBitsRemaining = 0;
|
||||
palmSdCard.commandIsAcmd = false;
|
||||
palmSdCard.allowInvalidCrc = false;
|
||||
palmSdCard.chipSelect = false;
|
||||
palmSdCard.receivingCommand = false;
|
||||
palmSdCard.inIdleState = true;
|
||||
}
|
||||
|
||||
void sdCardSetChipSelect(bool value){
|
||||
@@ -96,7 +102,7 @@ void sdCardSetChipSelect(bool value){
|
||||
|
||||
//commands start when chip select goes from high to low
|
||||
if(value == false)
|
||||
sdCardCmdStart();
|
||||
sdCardCmdStart(palmSdCard.commandIsAcmd);
|
||||
|
||||
palmSdCard.chipSelect = value;
|
||||
}
|
||||
@@ -158,7 +164,7 @@ bool sdCardExchangeBit(bool bit){
|
||||
palmSdCard.commandBitsRemaining--;
|
||||
}
|
||||
else{
|
||||
sdCardCmdStart();
|
||||
sdCardCmdStart(palmSdCard.commandIsAcmd);
|
||||
}
|
||||
|
||||
//process command if all bits are present
|
||||
@@ -167,27 +173,57 @@ bool sdCardExchangeBit(bool bit){
|
||||
uint32_t argument = palmSdCard.command >> 8 & 0xFFFFFFFF;
|
||||
uint8_t crc = palmSdCard.command >> 1 & 0x7F;
|
||||
|
||||
debugLog("SD command:cmd:%d, arg:0x%08X, CRC:0x%02X\n", command, argument, crc);
|
||||
debugLog("SD command: isAcmd:%d, cmd:%d, arg:0x%08X, CRC:0x%02X\n", palmSdCard.commandIsAcmd, command, argument, crc);
|
||||
|
||||
if(palmSdCard.allowInvalidCrc || sdCardCmdIsCrcValid(command, argument, crc)){
|
||||
//respond with command value
|
||||
//debugLog("SD valid CRC\n");
|
||||
|
||||
switch(command){
|
||||
case GO_IDLE_STATE:
|
||||
palmSdCard.allowInvalidCrc = true;
|
||||
sdCardDoResponseR1(0x01);//"idle state" bit set should be set
|
||||
break;
|
||||
if(!palmSdCard.commandIsAcmd){
|
||||
//normal command
|
||||
switch(command){
|
||||
case GO_IDLE_STATE:
|
||||
palmSdCard.inIdleState = true;
|
||||
palmSdCard.allowInvalidCrc = true;
|
||||
sdCardDoResponseR1(palmSdCard.inIdleState);
|
||||
break;
|
||||
|
||||
default:
|
||||
debugLog("SD unknown command:cmd:%d, arg:0x%08X, CRC:0x%02X\n", command, argument, crc);
|
||||
break;
|
||||
case SEND_OP_COND:
|
||||
palmSdCard.inIdleState = false;
|
||||
sdCardDoResponseR1(palmSdCard.inIdleState);
|
||||
break;
|
||||
|
||||
case READ_OCR:
|
||||
sdCardDoResponseR3(palmSdCard.inIdleState);
|
||||
break;
|
||||
|
||||
case APP_CMD:
|
||||
sdCardCmdStart(true);
|
||||
sdCardDoResponseR1(palmSdCard.inIdleState);
|
||||
break;
|
||||
|
||||
default:
|
||||
debugLog("SD unknown command: cmd:%d, arg:0x%08X, CRC:0x%02X\n", command, argument, crc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else{
|
||||
//ACMD command
|
||||
switch(command){
|
||||
|
||||
default:
|
||||
debugLog("SD unknown ACMD command: cmd:%d, arg:0x%08X, CRC:0x%02X\n", command, argument, crc);
|
||||
break;
|
||||
}
|
||||
|
||||
//ACMD finished, go back to normal command format
|
||||
palmSdCard.commandIsAcmd = false;
|
||||
}
|
||||
}
|
||||
else{
|
||||
//send back R1 response with CRC error set
|
||||
debugLog("SD invalid CRC\n");
|
||||
sdCardDoResponseR1(0x08);//"command CRC error" bit set
|
||||
sdCardDoResponseR1(0x08 | palmSdCard.inIdleState);//"command CRC error" bit set
|
||||
}
|
||||
|
||||
//needs to be at least 8 for MMC
|
||||
|
||||
@@ -7,14 +7,21 @@
|
||||
|
||||
#define GO_IDLE_STATE 0/*software reset*/
|
||||
#define SEND_OP_COND 1/*initiate initialization process*/
|
||||
#define SEND_IF_COND 8/*only for SDC V2, checks voltage range.*/
|
||||
#define SEND_CSD 9/*read CSD register*/
|
||||
#define SEND_CID 10/*read CID register*/
|
||||
#define STOP_TRANSMISSION 12/*stop to read data*/
|
||||
#define SET_BLOCKLEN 16/*change R/W block size*/
|
||||
#define READ_SINGLE_BLOCK 17/*read a block*/
|
||||
#define READ_MULTIPLE_BLOCK 18/*read multiple blocks*/
|
||||
#define SET_BLOCK_COUNT 23/*only for MMC, defines number of blocks to transfer with next multi-block read/write command*/
|
||||
#define WRITE_SINGLE_BLOCK 24/*write a block*/
|
||||
#define WRITE_MULTIPLE_BLOCK 25/*write multiple blocks*/
|
||||
#define APP_CMD 55/*next command is ACMD<n> command*/
|
||||
#define READ_OCR 58/*read OCR(operation condtion register)*/
|
||||
|
||||
/*Application Commands*/
|
||||
#define APP_SEND_OP_COND 41/*only for SDC, same as SEND_OP_COND*/
|
||||
#define SET_WR_BLOCK_ERASE_COUNT 23/*only for SDC, defines number of blocks to pre-erase with next multi-block write command*/
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user