mirror of
https://github.com/BernardoGiordano/Checkpoint
synced 2024-11-15 06:07:06 +00:00
fix #18; formatting
This commit is contained in:
parent
cde48b0e43
commit
c2c2fe92a5
1 changed files with 102 additions and 89 deletions
191
source/spi.cpp
191
source/spi.cpp
|
@ -20,7 +20,8 @@
|
|||
|
||||
u8* fill_buf = NULL;
|
||||
|
||||
Result SPIWriteRead(CardType type, void* cmd, u32 cmdSize, void* answer, u32 answerSize, void* data, u32 dataSize) {
|
||||
Result SPIWriteRead(CardType type, void* cmd, u32 cmdSize, void* answer, u32 answerSize, void* data, u32 dataSize)
|
||||
{
|
||||
u8 transferOp = pxiDevMakeTransferOption(BAUDRATE_4MHZ, BUSMODE_1BIT), transferOp2 = pxiDevMakeTransferOption(BAUDRATE_1MHZ, BUSMODE_1BIT);
|
||||
u64 waitOp = pxiDevMakeWaitOperation(WAIT_NONE, DEASSERT_NONE, 0LL);
|
||||
u64 headerFooterVal = 0;
|
||||
|
@ -36,85 +37,94 @@ Result SPIWriteRead(CardType type, void* cmd, u32 cmdSize, void* answer, u32 ans
|
|||
return PXIDEV_SPIMultiWriteRead(&headerBuffer, &cmdBuffer, &answerBuffer, &dataBuffer, &nullBuffer, &footerBuffer);
|
||||
}
|
||||
|
||||
Result SPIWaitWriteEnd(CardType type) {
|
||||
Result SPIWaitWriteEnd(CardType type)
|
||||
{
|
||||
u8 cmd = SPI_CMD_RDSR, statusReg = 0;
|
||||
Result res = 0;
|
||||
|
||||
do{
|
||||
int cnt = 0;
|
||||
do {
|
||||
cnt++;
|
||||
res = SPIWriteRead(type, &cmd, 1, &statusReg, 1, 0, 0);
|
||||
if(res) return res;
|
||||
} while(statusReg & SPI_FLG_WIP);
|
||||
if (res) return res;
|
||||
} while(statusReg & SPI_FLG_WIP && cnt < 1000);
|
||||
|
||||
return 0;
|
||||
return cnt >= 1000 ? 1 : 0;
|
||||
}
|
||||
|
||||
Result SPIEnableWriting(CardType type) {
|
||||
Result SPIEnableWriting(CardType type)
|
||||
{
|
||||
u8 cmd = SPI_CMD_WREN, statusReg = 0;
|
||||
Result res = SPIWriteRead(type, &cmd, 1, NULL, 0, 0, 0);
|
||||
|
||||
if(res || type == EEPROM_512B) return res; // Weird, but works (otherwise we're getting an infinite loop for that chip type).
|
||||
if (res || type == EEPROM_512B) return res; // Weird, but works (otherwise we're getting an infinite loop for that chip type).
|
||||
cmd = SPI_CMD_RDSR;
|
||||
|
||||
do{
|
||||
do {
|
||||
res = SPIWriteRead(type, &cmd, 1, &statusReg, 1, 0, 0);
|
||||
if(res) return res;
|
||||
if (res) return res;
|
||||
} while(statusReg & ~SPI_FLG_WEL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result SPIReadJEDECIDAndStatusReg(CardType type, u32* id, u8* statusReg) {
|
||||
Result SPIReadJEDECIDAndStatusReg(CardType type, u32* id, u8* statusReg)
|
||||
{
|
||||
u8 cmd = SPI_FLASH_CMD_RDID;
|
||||
u8 reg = 0;
|
||||
u8 idbuf[3] = { 0 };
|
||||
u32 id_ = 0;
|
||||
Result res = SPIWaitWriteEnd(type);
|
||||
if(res) return res;
|
||||
if (res) return res;
|
||||
|
||||
if((res = SPIWriteRead(type, &cmd, 1, idbuf, 3, 0, 0))) return res;
|
||||
if ((res = SPIWriteRead(type, &cmd, 1, idbuf, 3, 0, 0))) return res;
|
||||
|
||||
id_ = (idbuf[0] << 16) | (idbuf[1] << 8) | idbuf[2];
|
||||
cmd = SPI_CMD_RDSR;
|
||||
|
||||
if((res = SPIWriteRead(type, &cmd, 1, ®, 1, 0, 0))) return res;
|
||||
if ((res = SPIWriteRead(type, &cmd, 1, ®, 1, 0, 0))) return res;
|
||||
|
||||
if(id) *id = id_;
|
||||
if(statusReg) *statusReg = reg;
|
||||
if (id) *id = id_;
|
||||
if (statusReg) *statusReg = reg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 SPIGetPageSize(CardType type) {
|
||||
u32 SPIGetPageSize(CardType type)
|
||||
{
|
||||
u32 EEPROMSizes[] = { 16, 32, 128, 256 };
|
||||
if(type == NO_CHIP || type > CHIP_LAST) return 0;
|
||||
else if(type < FLASH_256KB_1) return EEPROMSizes[(int) type];
|
||||
if (type == NO_CHIP || type > CHIP_LAST) return 0;
|
||||
else if (type < FLASH_256KB_1) return EEPROMSizes[(int) type];
|
||||
else return 256;
|
||||
}
|
||||
|
||||
u32 SPIGetCapacity(CardType type) {
|
||||
u32 SPIGetCapacity(CardType type)
|
||||
{
|
||||
u32 sz[] = { 9, 13, 16, 17, 18, 18, 19, 19, 20, 23, 19, 19 };
|
||||
|
||||
if(type == NO_CHIP || type > CHIP_LAST) return 0;
|
||||
if (type == NO_CHIP || type > CHIP_LAST) return 0;
|
||||
else return 1 << sz[(int) type];
|
||||
}
|
||||
|
||||
Result SPIWriteSaveData(CardType type, u32 offset, void* data, u32 size) {
|
||||
Result SPIWriteSaveData(CardType type, u32 offset, void* data, u32 size)
|
||||
{
|
||||
u8 cmd[4] = { 0 };
|
||||
u32 cmdSize = 4;
|
||||
|
||||
u32 end = offset + size;
|
||||
u32 pos = offset;
|
||||
if(size == 0) return 0;
|
||||
if (size == 0) return 0;
|
||||
u32 pageSize = SPIGetPageSize(type);
|
||||
if(pageSize == 0) return 0xC8E13404;
|
||||
if (pageSize == 0) return 0xC8E13404;
|
||||
|
||||
Result res = SPIWaitWriteEnd(type);
|
||||
if(res) return res;
|
||||
if (res) return res;
|
||||
|
||||
size = (size <= SPIGetCapacity(type) - offset) ? size : SPIGetCapacity(type) - offset;
|
||||
|
||||
while(pos < end) {
|
||||
switch(type) {
|
||||
while(pos < end)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case EEPROM_512B:
|
||||
cmdSize = 2;
|
||||
cmd[0] = (pos >= 0x100) ? SPI_512B_EEPROM_CMD_WRHI : SPI_512B_EEPROM_CMD_WRLO;
|
||||
|
@ -135,15 +145,6 @@ Result SPIWriteSaveData(CardType type, u32 offset, void* data, u32 size) {
|
|||
cmd[3] = (u8) pos;
|
||||
break;
|
||||
case FLASH_256KB_1:
|
||||
/*
|
||||
This is what is done in the official implementation, but I think it's wrong
|
||||
cmdSize = 4;
|
||||
cmd[0] = SPI_CMD_PP;
|
||||
cmd[1] = (u8)(pos >> 16);
|
||||
cmd[2] = (u8)(pos >> 8);
|
||||
cmd[3] = (u8) pos;
|
||||
break;
|
||||
*/
|
||||
case FLASH_256KB_2:
|
||||
case FLASH_512KB_1:
|
||||
case FLASH_512KB_2:
|
||||
|
@ -167,9 +168,9 @@ Result SPIWriteSaveData(CardType type, u32 offset, void* data, u32 size) {
|
|||
|
||||
u32 dataSize = (remaining < nb) ? remaining : nb;
|
||||
|
||||
if( (res = SPIEnableWriting(type)) ) return res;
|
||||
if( (res = SPIWriteRead(type, cmd, cmdSize, NULL, 0, (void*) ((u8*) data - offset + pos), dataSize)) ) return res;
|
||||
if( (res = SPIWaitWriteEnd(type)) ) return res;
|
||||
if ( (res = SPIEnableWriting(type)) ) return res;
|
||||
if ( (res = SPIWriteRead(type, cmd, cmdSize, NULL, 0, (void*) ((u8*) data - offset + pos), dataSize)) ) return res;
|
||||
if ( (res = SPIWaitWriteEnd(type)) ) return res;
|
||||
|
||||
pos = ((pos / pageSize) + 1) * pageSize; // truncate
|
||||
}
|
||||
|
@ -177,50 +178,54 @@ Result SPIWriteSaveData(CardType type, u32 offset, void* data, u32 size) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
Result _SPIReadSaveData_512B_impl(u32 pos, void* data, u32 size) {
|
||||
Result _SPIReadSaveData_512B_impl(u32 pos, void* data, u32 size)
|
||||
{
|
||||
u8 cmd[4];
|
||||
u32 cmdSize = 2;
|
||||
|
||||
u32 end = pos + size;
|
||||
|
||||
u32 read = 0;
|
||||
if(pos < 0x100) {
|
||||
if (pos < 0x100)
|
||||
{
|
||||
u32 len = 0x100 - pos;
|
||||
cmd[0] = SPI_512B_EEPROM_CMD_RDLO;
|
||||
cmd[1] = (u8) pos;
|
||||
|
||||
Result res = SPIWriteRead(EEPROM_512B, cmd, cmdSize, data, len, NULL, 0);
|
||||
if(res) return res;
|
||||
if (res) return res;
|
||||
|
||||
read += len;
|
||||
}
|
||||
|
||||
if(end >= 0x100) {
|
||||
if (end >= 0x100)
|
||||
{
|
||||
u32 len = end - 0x100;
|
||||
|
||||
cmd[0] = SPI_512B_EEPROM_CMD_RDHI;
|
||||
cmd[1] = (u8)(pos + read);
|
||||
|
||||
Result res = SPIWriteRead(EEPROM_512B, cmd, cmdSize, (void*)((u8*)data + read), len, NULL, 0);
|
||||
|
||||
if(res) return res;
|
||||
if (res) return res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result SPIReadSaveData(CardType type, u32 offset, void* data, u32 size) {
|
||||
Result SPIReadSaveData(CardType type, u32 offset, void* data, u32 size)
|
||||
{
|
||||
u8 cmd[4] = { SPI_CMD_READ };
|
||||
u32 cmdSize = 4;
|
||||
if(size == 0) return 0;
|
||||
if(type == NO_CHIP) return 0xC8E13404;
|
||||
if (size == 0) return 0;
|
||||
if (type == NO_CHIP) return 0xC8E13404;
|
||||
|
||||
Result res = SPIWaitWriteEnd(type);
|
||||
if(res) return res;
|
||||
if (res) return res;
|
||||
|
||||
size = (size <= SPIGetCapacity(type) - offset) ? size : SPIGetCapacity(type) - offset;
|
||||
u32 pos = offset;
|
||||
switch(type) {
|
||||
switch(type)
|
||||
{
|
||||
case EEPROM_512B:
|
||||
return _SPIReadSaveData_512B_impl(offset, data, size);
|
||||
break;
|
||||
|
@ -256,24 +261,28 @@ Result SPIReadSaveData(CardType type, u32 offset, void* data, u32 size) {
|
|||
return SPIWriteRead(type, cmd, cmdSize, data, size, NULL, 0);
|
||||
}
|
||||
|
||||
Result SPIEraseSector(CardType type, u32 offset) {
|
||||
Result SPIEraseSector(CardType type, u32 offset)
|
||||
{
|
||||
u8 cmd[4] = { SPI_FLASH_CMD_SE, (u8)(offset >> 16), (u8)(offset >> 8), (u8) offset };
|
||||
if(type == NO_CHIP || type == FLASH_8MB) return 0xC8E13404;
|
||||
if (type == NO_CHIP || type == FLASH_8MB) return 0xC8E13404;
|
||||
|
||||
if(type < FLASH_256KB_1 && fill_buf == NULL) {
|
||||
fill_buf = new u8[0x10000];
|
||||
memset(fill_buf, 0xff, 0x10000);
|
||||
if (type < FLASH_256KB_1 && fill_buf == NULL)
|
||||
{
|
||||
fill_buf = new u8[0x10000];
|
||||
memset(fill_buf, 0xff, 0x10000);
|
||||
}
|
||||
|
||||
Result res = SPIWaitWriteEnd(type);
|
||||
|
||||
if(type >= FLASH_256KB_1) {
|
||||
if( (res = SPIEnableWriting(type)) ) return res;
|
||||
if( (res = SPIWriteRead(type, cmd, 4, NULL, 0, NULL, 0)) ) return res;
|
||||
if( (res = SPIWaitWriteEnd(type)) ) return res;
|
||||
if(type >= FLASH_256KB_1)
|
||||
{
|
||||
if ( (res = SPIEnableWriting(type)) ) return res;
|
||||
if ( (res = SPIWriteRead(type, cmd, 4, NULL, 0, NULL, 0)) ) return res;
|
||||
if ( (res = SPIWaitWriteEnd(type)) ) return res;
|
||||
}
|
||||
// Simulate the same behavior on EEPROM chips.
|
||||
else {
|
||||
else
|
||||
{
|
||||
u32 sz = SPIGetCapacity(type);
|
||||
Result res = SPIWriteSaveData(type, 0, fill_buf, (sz < 0x10000) ? sz : 0x10000);
|
||||
return res;
|
||||
|
@ -281,7 +290,6 @@ Result SPIEraseSector(CardType type, u32 offset) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// The following routine use code from savegame-manager:
|
||||
|
||||
/*
|
||||
|
@ -310,8 +318,8 @@ Result SPIEraseSector(CardType type, u32 offset) {
|
|||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
Result _SPIIsDataMirrored(CardType type, int size, bool* mirrored) {
|
||||
Result _SPIIsDataMirrored(CardType type, int size, bool* mirrored)
|
||||
{
|
||||
u32 offset0 = (size-1); // n KB
|
||||
u32 offset1 = (2*size-1); // 2n KB
|
||||
|
||||
|
@ -322,18 +330,19 @@ Result _SPIIsDataMirrored(CardType type, int size, bool* mirrored) {
|
|||
|
||||
Result res;
|
||||
|
||||
if( (res = SPIReadSaveData(type, offset0, &buf1, 1)) ) return res;
|
||||
if( (res = SPIReadSaveData(type, offset1, &buf2, 1)) ) return res;
|
||||
if ( (res = SPIReadSaveData(type, offset0, &buf1, 1)) ) return res;
|
||||
if ( (res = SPIReadSaveData(type, offset1, &buf2, 1)) ) return res;
|
||||
buf3=~buf1;
|
||||
if( (res = SPIWriteSaveData(type, offset0, &buf3, 1)) ) return res;
|
||||
if( (res = SPIReadSaveData(type, offset1, &buf4, 1)) ) return res;
|
||||
if( (res = SPIWriteSaveData(type, offset0, &buf1, 1)) ) return res;
|
||||
if ( (res = SPIWriteSaveData(type, offset0, &buf3, 1)) ) return res;
|
||||
if ( (res = SPIReadSaveData(type, offset1, &buf4, 1)) ) return res;
|
||||
if ( (res = SPIWriteSaveData(type, offset0, &buf1, 1)) ) return res;
|
||||
|
||||
*mirrored = buf2 != buf4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result SPIGetCardType(CardType* type, int infrared) {
|
||||
Result SPIGetCardType(CardType* type, int infrared)
|
||||
{
|
||||
u8 sr = 0;
|
||||
u32 jedec = 0;
|
||||
u32 tries = 0;
|
||||
|
@ -342,9 +351,10 @@ Result SPIGetCardType(CardType* type, int infrared) {
|
|||
u32 jedecOrderedList[] = {0x204012, 0x621600, 0x204013, 0x621100, 0x204014, 0x202017};
|
||||
|
||||
u32 maxTries = (infrared == -1) ? 2 : 1; // note: infrared = -1 fails 1/3 of the time
|
||||
while(tries < maxTries){
|
||||
while (tries < maxTries)
|
||||
{
|
||||
res = SPIReadJEDECIDAndStatusReg(t, &jedec, &sr); // dummy
|
||||
if(res) return res;
|
||||
if (res) return res;
|
||||
|
||||
if ((sr & 0xfd) == 0x00 && (jedec != 0x00ffffff)) { break; }
|
||||
if ((sr & 0xfd) == 0xF0 && (jedec == 0x00ffffff)) { t = EEPROM_512B; break; }
|
||||
|
@ -352,40 +362,43 @@ Result SPIGetCardType(CardType* type, int infrared) {
|
|||
|
||||
++tries;
|
||||
t = FLASH_INFRARED_DUMMY;
|
||||
}
|
||||
}
|
||||
|
||||
if(t == EEPROM_512B) { *type = t; return 0; }
|
||||
else if(t == EEPROM_STD_DUMMY) {
|
||||
if (t == EEPROM_512B) { *type = t; return 0; }
|
||||
else if (t == EEPROM_STD_DUMMY)
|
||||
{
|
||||
bool mirrored = false;
|
||||
|
||||
if( (res = _SPIIsDataMirrored(t, 8192, &mirrored)) ) return res;
|
||||
if(mirrored) t = EEPROM_8KB;
|
||||
else{
|
||||
if( (res = _SPIIsDataMirrored(t, 65536, &mirrored)) ) return res;
|
||||
if(mirrored) t = EEPROM_64KB;
|
||||
if ( (res = _SPIIsDataMirrored(t, 8192, &mirrored)) ) return res;
|
||||
if (mirrored) t = EEPROM_8KB;
|
||||
else
|
||||
{
|
||||
if ( (res = _SPIIsDataMirrored(t, 65536, &mirrored)) ) return res;
|
||||
if (mirrored) t = EEPROM_64KB;
|
||||
else t = EEPROM_128KB;
|
||||
}
|
||||
|
||||
*type = t;
|
||||
return 0;
|
||||
}
|
||||
|
||||
else if(t == FLASH_INFRARED_DUMMY) {
|
||||
if(infrared == 0) *type = NO_CHIP; // did anything go wrong?
|
||||
else if (t == FLASH_INFRARED_DUMMY)
|
||||
{
|
||||
if (infrared == 0) *type = NO_CHIP; // did anything go wrong?
|
||||
|
||||
if(jedec == jedecOrderedList[0] || jedec == jedecOrderedList[1]) *type = FLASH_256KB_INFRARED;
|
||||
if (jedec == jedecOrderedList[0] || jedec == jedecOrderedList[1]) *type = FLASH_256KB_INFRARED;
|
||||
else *type = FLASH_512KB_INFRARED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
else {
|
||||
if(infrared == 1) *type = NO_CHIP; // did anything go wrong?
|
||||
if(jedec == 0x204017) { *type = FLASH_8MB; return 0; } // 8MB. savegame-manager: which one? (more work is required to unlock this save chip!)
|
||||
else
|
||||
{
|
||||
if (infrared == 1) *type = NO_CHIP; // did anything go wrong?
|
||||
if (jedec == 0x204017) { *type = FLASH_8MB; return 0; } // 8MB. savegame-manager: which one? (more work is required to unlock this save chip!)
|
||||
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 6; ++i) {
|
||||
for (i = 0; i < 6; ++i)
|
||||
{
|
||||
if(jedec == jedecOrderedList[i]) { *type = (CardType)((int) FLASH_256KB_1 + i); return 0; }
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue