2015-05-12 11:15:16 +12:00
|
|
|
// Copyright 2014 Normmatt
|
|
|
|
// Licensed under GPLv2 or any later version
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
2015-05-10 00:53:09 -07:00
|
|
|
#include "protocol_ctr.h"
|
|
|
|
|
|
|
|
#include "protocol.h"
|
|
|
|
#include "delay.h"
|
|
|
|
|
|
|
|
void CTR_SetSecKey(u32 value) {
|
|
|
|
REG_CTRCARDSECCNT |= ((value & 3) << 8) | 4;
|
|
|
|
while (!(REG_CTRCARDSECCNT & 0x4000));
|
|
|
|
}
|
|
|
|
|
2015-05-10 01:22:47 -07:00
|
|
|
void CTR_SetSecSeed(const u32* seed, bool flag) {
|
2015-05-10 00:53:09 -07:00
|
|
|
REG_CTRCARDSECSEED = BSWAP32(seed[3]);
|
|
|
|
REG_CTRCARDSECSEED = BSWAP32(seed[2]);
|
|
|
|
REG_CTRCARDSECSEED = BSWAP32(seed[1]);
|
|
|
|
REG_CTRCARDSECSEED = BSWAP32(seed[0]);
|
|
|
|
REG_CTRCARDSECCNT |= 0x8000;
|
|
|
|
|
|
|
|
while (!(REG_CTRCARDSECCNT & 0x4000));
|
|
|
|
|
|
|
|
if (flag) {
|
|
|
|
(*(vu32*)0x1000400C) = 0x00000001; // Enable cart command encryption?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-10 01:22:47 -07:00
|
|
|
void CTR_SendCommand(const u32 command[4], u32 pageSize, u32 blocks, u32 latency, void* buffer)
|
2015-05-10 00:53:09 -07:00
|
|
|
{
|
|
|
|
REG_CTRCARDCMD[0] = command[3];
|
|
|
|
REG_CTRCARDCMD[1] = command[2];
|
|
|
|
REG_CTRCARDCMD[2] = command[1];
|
|
|
|
REG_CTRCARDCMD[3] = command[0];
|
|
|
|
|
|
|
|
//Make sure this never happens
|
|
|
|
if(blocks == 0) blocks = 1;
|
|
|
|
|
|
|
|
pageSize -= pageSize & 3; // align to 4 byte
|
|
|
|
u32 pageParam = CTRCARD_PAGESIZE_4K;
|
|
|
|
u32 transferLength = 4096;
|
|
|
|
// make zero read and 4 byte read a little special for timing optimization(and 512 too)
|
|
|
|
switch(pageSize) {
|
|
|
|
case 0:
|
|
|
|
transferLength = 0;
|
|
|
|
pageParam = CTRCARD_PAGESIZE_0;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
transferLength = 4;
|
|
|
|
pageParam = CTRCARD_PAGESIZE_4;
|
|
|
|
break;
|
|
|
|
case 64:
|
|
|
|
transferLength = 64;
|
|
|
|
pageParam = CTRCARD_PAGESIZE_64;
|
|
|
|
break;
|
|
|
|
case 512:
|
|
|
|
transferLength = 512;
|
|
|
|
pageParam = CTRCARD_PAGESIZE_512;
|
|
|
|
break;
|
|
|
|
case 1024:
|
|
|
|
transferLength = 1024;
|
|
|
|
pageParam = CTRCARD_PAGESIZE_1K;
|
|
|
|
break;
|
|
|
|
case 2048:
|
|
|
|
transferLength = 2048;
|
|
|
|
pageParam = CTRCARD_PAGESIZE_2K;
|
|
|
|
break;
|
|
|
|
case 4096:
|
|
|
|
transferLength = 4096;
|
|
|
|
pageParam = CTRCARD_PAGESIZE_4K;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
REG_CTRCARDBLKCNT = blocks - 1;
|
|
|
|
transferLength *= blocks;
|
|
|
|
|
|
|
|
// go
|
|
|
|
REG_CTRCARDCNT = 0x10000000;
|
|
|
|
REG_CTRCARDCNT = /*CTRKEY_PARAM | */CTRCARD_ACTIVATE | CTRCARD_nRESET | pageParam | latency;
|
|
|
|
|
|
|
|
u8 * pbuf = (u8 *)buffer;
|
|
|
|
u32 * pbuf32 = (u32 * )buffer;
|
|
|
|
bool useBuf = ( NULL != pbuf );
|
|
|
|
bool useBuf32 = (useBuf && (0 == (3 & ((u32)buffer))));
|
|
|
|
|
|
|
|
u32 count = 0;
|
|
|
|
u32 cardCtrl = REG_CTRCARDCNT;
|
|
|
|
|
|
|
|
if(useBuf32)
|
|
|
|
{
|
|
|
|
while( (cardCtrl & CTRCARD_BUSY) && count < transferLength)
|
|
|
|
{
|
|
|
|
cardCtrl = REG_CTRCARDCNT;
|
|
|
|
if( cardCtrl & CTRCARD_DATA_READY ) {
|
|
|
|
u32 data = REG_CTRCARDFIFO;
|
|
|
|
*pbuf32++ = data;
|
|
|
|
count += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(useBuf)
|
|
|
|
{
|
|
|
|
while( (cardCtrl & CTRCARD_BUSY) && count < transferLength)
|
|
|
|
{
|
|
|
|
cardCtrl = REG_CTRCARDCNT;
|
|
|
|
if( cardCtrl & CTRCARD_DATA_READY ) {
|
|
|
|
u32 data = REG_CTRCARDFIFO;
|
|
|
|
pbuf[0] = (unsigned char) (data >> 0);
|
|
|
|
pbuf[1] = (unsigned char) (data >> 8);
|
|
|
|
pbuf[2] = (unsigned char) (data >> 16);
|
|
|
|
pbuf[3] = (unsigned char) (data >> 24);
|
|
|
|
pbuf += sizeof (unsigned int);
|
|
|
|
count += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while( (cardCtrl & CTRCARD_BUSY) && count < transferLength)
|
|
|
|
{
|
|
|
|
cardCtrl = REG_CTRCARDCNT;
|
|
|
|
if( cardCtrl & CTRCARD_DATA_READY ) {
|
|
|
|
u32 data = REG_CTRCARDFIFO;
|
|
|
|
(void)data;
|
|
|
|
count += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// if read is not finished, ds will not pull ROM CS to high, we pull it high manually
|
|
|
|
if( count != transferLength ) {
|
|
|
|
// MUST wait for next data ready,
|
|
|
|
// if ds pull ROM CS to high during 4 byte data transfer, something will mess up
|
|
|
|
// so we have to wait next data ready
|
|
|
|
do { cardCtrl = REG_CTRCARDCNT; } while(!(cardCtrl & CTRCARD_DATA_READY));
|
|
|
|
// and this tiny delay is necessary
|
|
|
|
ioDelay(33);
|
|
|
|
// pull ROM CS high
|
|
|
|
REG_CTRCARDCNT = 0x10000000;
|
|
|
|
REG_CTRCARDCNT = CTRKEY_PARAM | CTRCARD_ACTIVATE | CTRCARD_nRESET;
|
|
|
|
}
|
|
|
|
// wait rom cs high
|
|
|
|
do { cardCtrl = REG_CTRCARDCNT; } while( cardCtrl & CTRCARD_BUSY );
|
|
|
|
//lastCmd[0] = command[0];lastCmd[1] = command[1];
|
2015-05-10 01:00:50 -07:00
|
|
|
}
|