diff --git a/src/emulator.h b/src/emulator.h index ee01869..e2fe6a6 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -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; diff --git a/src/hardwareRegisters.c b/src/hardwareRegisters.c index a3f88ce..333fd06 100644 --- a/src/hardwareRegisters.c +++ b/src/hardwareRegisters.c @@ -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; } diff --git a/src/hardwareRegistersAccessors.c.h b/src/hardwareRegistersAccessors.c.h index 13cb989..41ccb54 100644 --- a/src/hardwareRegistersAccessors.c.h +++ b/src/hardwareRegistersAccessors.c.h @@ -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++){ diff --git a/src/sdCard.c b/src/sdCard.c index 5a91446..dc868c8 100644 --- a/src/sdCard.c +++ b/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 diff --git a/src/specs/sdCardCommandSpec.h b/src/specs/sdCardCommandSpec.h index 66bfb33..b1ff112 100644 --- a/src/specs/sdCardCommandSpec.h +++ b/src/specs/sdCardCommandSpec.h @@ -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 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