TwlIPL/build/libraries_sysmenu/hotsw/ARM9/src/hotsw_ctrl.c
(no author) 5e8ea60aa9 (更新:Akabane Jumpei)
ARM9のカードデータ読み関数を修正 その2

git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlIPL/trunk@1401 b08762b0-b915-fc4b-9d8c-17b2551a87ff
2008-05-19 09:39:20 +00:00

474 lines
14 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*---------------------------------------------------------------------------*
Project: TwlIPL
File: hotsw_ctrl.c
Copyright 2007 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
$Date:: $
$Rev$
$Author$
*---------------------------------------------------------------------------*/
#include <twl.h>
#include <sysmenu.h>
#include <firm/os/common/system.h>
#include <../ARM7/include/hotswTypes.h>
// define -------------------------------------------------------------------
#define HOTSW_READ_MSG_NUM 1
#define HOTSW_CARD_GAME_MODE_CALLBACK 1
#define HOTSW_CARD_INSERT_CALLBACK 2
#define HOTSW_CARD_PULLOUT_CALLBACK 3
#define HOTSW_CALLBACK_FUNCTION_NUM 3
// Function prototype -------------------------------------------------------
static void InterruptCallbackPxi(PXIFifoTag tag, u32 data, BOOL err);
static CardDataReadState ReadPageGame(u32 start_addr, void* buf, u32 size);
// Static Values ------------------------------------------------------------
static HotSwMessageForArm9 s_HotswMsg;
static OSMessage s_HotswMsgBuffer[HOTSW_READ_MSG_NUM];
static OSMessageQueue s_HotswQueue;
static BOOL s_ReadBusy;
static OSIrqFunction s_HotswFuncTable[HOTSW_CALLBACK_FUNCTION_NUM];
static u16 s_CardLockID;
// ===========================================================================
// Function Describe
// ===========================================================================
/*---------------------------------------------------------------------------*
Name: HOTSW_Init
Description: Šˆ<C5A0>ð}”²<E2809D>ˆ<CB86>Ì<E2809A>‰Šú‰»
*---------------------------------------------------------------------------*/
#ifdef USE_WRAM_LOAD
void HOTSW_Init()
{
s32 tempLockID;
// ƒJ<C692>[ƒhƒAƒNƒZƒX—p̃<C38C>ƒbƒNID̎擾
while((tempLockID = OS_GetLockID()) == OS_LOCK_ID_ERROR){
// do nothing
}
s_CardLockID = (u16)tempLockID;
// ƒ<>ƒbƒZ<C692>[ƒWƒLƒ…<C692>[Ì<E2809A>‰Šú‰»
OS_InitMessageQueue( &s_HotswQueue, &s_HotswMsgBuffer[0], HOTSW_READ_MSG_NUM );
// Busyƒtƒ‰ƒOð—ŽÆµÄ¨­
s_ReadBusy = FALSE;
// PXI<58>‰Šú‰»
PXI_Init();
PXI_SetFifoRecvCallback(PXI_FIFO_TAG_HOTSW, InterruptCallbackPxi);
while(!PXI_IsCallbackReady(PXI_FIFO_TAG_HOTSW, PXI_PROC_ARM7))
{
// do nothing
}
}
#endif
/*---------------------------------------------------------------------------*
Name: HOTSW_EnableHotSWAsync
Description: PXIÊ<E28099>MÅARM7ÉŠˆ<C5A0>ü}”²—LŒø<C592>^³ŒøðÊm
*---------------------------------------------------------------------------*/
void HOTSW_EnableHotSWAsync( BOOL enable )
{
HotSwPxiMessageForArm7 msg;
MI_CpuClear8( &msg, sizeof(HotSwPxiMessageForArm7));
enable = enable ? 1 : 0;
// Œ»<C592>ÝÌlÆ“¯È牽๸ƒŠƒ^<5E>[ƒ“
if( SYSMi_GetWork()->flags.hotsw.isEnableHotSW == enable ) {
return;
}
msg.msg.value = enable;
msg.msg.ctrl = TRUE;
OS_TPrintf("%s %d\n", __FUNCTION__, __LINE__);
while (PXI_SendWordByFifo(PXI_FIFO_TAG_HOTSW, msg.data, FALSE) != PXI_FIFO_SUCCESS)
{
// do nothing
}
}
/*---------------------------------------------------------------------------*
Name: HOTSW_FinalizeHotSW
Description: PXIÊ<E28099>MÅARM7ÉŠˆ<C5A0>ü}”²Finalize<7A>ˆ<CB86>ðÊm
*---------------------------------------------------------------------------*/
void HOTSW_FinalizeHotSWAsync( HotSwApliType apliType )
{
HotSwPxiMessageForArm7 msg;
MI_CpuClear8( &msg, sizeof(HotSwPxiMessageForArm7));
msg.msg.finalize = TRUE;
msg.msg.bootType = (u8)apliType;
OS_TPrintf("%s %d\n", __FUNCTION__, __LINE__);
while (PXI_SendWordByFifo(PXI_FIFO_TAG_HOTSW, msg.data, FALSE) != PXI_FIFO_SUCCESS)
{
// do nothing
}
}
/*---------------------------------------------------------------------------*
Name: HOTSW_isFinalized
Description: <20>I—¹<E28094>ˆ<CB86>ªŠ®—¹µ½©ð•Ô·
*---------------------------------------------------------------------------*/
BOOL HOTSW_isFinalized(void)
{
return SYSMi_GetWork()->flags.hotsw.isFinalized;
}
/*---------------------------------------------------------------------------*
Name: HOTSW_isEnableHotSW
Description: Šˆ<C5A0>ü}”²‚Ì‹–‰Â/—}<7D>§Ì<E2809A>óÔð•Ô·
*---------------------------------------------------------------------------*/
BOOL HOTSW_isEnableHotSW(void)
{
return SYSMi_GetWork()->flags.hotsw.isEnableHotSW;
}
/*---------------------------------------------------------------------------*
Name: HOTSW_isCardLoadCompleted
Description: ƒJ<C692>[ƒhƒAƒvƒŠÌƒ<C38C><C692>[ƒhªŠ®—¹µÄ¢é©ð•Ô·
*---------------------------------------------------------------------------*/
BOOL HOTSW_isCardLoadCompleted(void)
{
return SYSMi_GetWork()->flags.hotsw.isCardLoadCompleted;
}
/*---------------------------------------------------------------------------*
Name: HOTSW_ReadCardDataAsync
Description: ƒJ<C692>[ƒhƒf<C692>[ƒ^ð“ÇÝ<E2809A>o·ŠÖ<C5A0><EFBFBD>B(”ñ“¯Šú”Å)
<09>¦ŽÀ<C5BD>ÛÉ“ÇñÅéÌÍARM7¤
<20>¦ {ŠÖ<C5A0>ðŒÄÑ<E2809A>oµÄ<E2809A>ACARD_READ_SUCCESSª•ÔÁÄ«Äà<E2809A>Aƒf<C692>[ƒ^ª<E2809A>³µ­
ƒŠ<C692>[ƒhūĢéÆÍ©¬èܹñ<E2809A>B
*---------------------------------------------------------------------------*/
#ifdef USE_WRAM_LOAD
CardDataReadState HOTSW_ReadCardDataAsync(void* src, void* dest, u32 size)
{
HotSwPxiMessageForArm7 msg;
MI_CpuClear8( &msg, sizeof(HotSwPxiMessageForArm7));
if( !HOTSW_isGameMode() ){
return CARD_READ_MODE_ERROR;
}
if( s_ReadBusy ){
return CARD_READ_BUSY;
}
s_ReadBusy = TRUE;
SYSMi_GetWork()->cardReadParam.src = (u32)src;
SYSMi_GetWork()->cardReadParam.dest = (u32)dest;
SYSMi_GetWork()->cardReadParam.size = size;
DC_FlushRange( &SYSMi_GetWork()->cardReadParam, sizeof(CardReadParam) );
DC_FlushRange( dest, size );
msg.msg.read = TRUE;
while (PXI_SendWordByFifo(PXI_FIFO_TAG_HOTSW, msg.data, FALSE) != PXI_FIFO_SUCCESS)
{
// do nothing
}
return CARD_READ_SUCCESS;
}
#endif
/*---------------------------------------------------------------------------*
Name: HOTSW_ReadCardData
Description: ƒJ<C692>[ƒhƒf<C692>[ƒ^ð“ÇÝ<E2809A>o·ŠÖ<C5A0><EFBFBD>B(“¯Šú”Å)
<09>¦ŽÀ<C5BD>ÛÉ“ÇñÅéÌÍARM7¤
*---------------------------------------------------------------------------*/
#ifdef USE_WRAM_LOAD
CardDataReadState HOTSW_ReadCardData(void* src, void* dest, u32 size)
{
HotSwMessageForArm9 *msg;
CardDataReadState retval;
retval = HOTSW_ReadCardDataAsync( src, dest, size);
if(retval != CARD_READ_SUCCESS){
return retval;
}
OS_ReceiveMessage( &s_HotswQueue, (OSMessage *)&msg, OS_MESSAGE_BLOCK );
return (CardDataReadState)msg->result;
}
#endif
/*---------------------------------------------------------------------------*
Name: HOTSW_isGameMode
Description: ƒJ<C692>[ƒhªƒQ<C692>[ƒ€ƒ<C692>[ƒhÉÈÁ½©Ç¤©ð•Ô·
*---------------------------------------------------------------------------*/
#ifdef USE_WRAM_LOAD
BOOL HOTSW_isGameMode(void)
{
return SYSMi_GetWork()->flags.hotsw.isCardGameMode ? TRUE : FALSE;
}
#endif
/*---------------------------------------------------------------------------*
Name: InterruptCallbackPxi
Description: PXIŠ„è<E2809A>žÝƒnƒ“ƒhƒ‰
*---------------------------------------------------------------------------*/
static void InterruptCallbackPxi(PXIFifoTag tag, u32 data, BOOL err)
{
#pragma unused(tag)
#pragma unused(err)
HotSwPxiMessageForArm9 d;
MI_CpuClear8( &d, sizeof(HotSwPxiMessageForArm9) );
d.data = data;
if(d.msg.mode){
if(s_HotswFuncTable[HOTSW_CARD_GAME_MODE_CALLBACK] != NULL){
s_HotswFuncTable[HOTSW_CARD_GAME_MODE_CALLBACK]();
}
}
if(d.msg.insert){
if(s_HotswFuncTable[HOTSW_CARD_INSERT_CALLBACK] != NULL){
s_HotswFuncTable[HOTSW_CARD_INSERT_CALLBACK]();
}
}
if(d.msg.pullout){
if(s_HotswFuncTable[HOTSW_CARD_PULLOUT_CALLBACK] != NULL){
s_HotswFuncTable[HOTSW_CARD_PULLOUT_CALLBACK]();
}
}
if(d.msg.read){
s_ReadBusy = FALSE;
s_HotswMsg.isReadComplete = (d.msg.read) ? TRUE : FALSE;
s_HotswMsg.result = (CardDataReadState)d.msg.result;
OS_TPrintf("%s %d Rcev Error Code[Arm9]:%x\n", __FUNCTION__, __LINE__, s_HotswMsg.result);
// ƒ<>ƒbƒZ<C692>[ƒW<E28098>M
OS_SendMessage( &s_HotswQueue, (OSMessage *)&s_HotswMsg, OS_MESSAGE_NOBLOCK);
}
}
/*---------------------------------------------------------------------------*
Name: SetGameModeCallBackFunction
Description: ƒJ<C692>[ƒhªGameƒ<C692>[ƒhÉÈÁ½ŽžÌƒR<C692>ƒoƒbƒNŠÖ<C5A0>ð<E2809A>Ýè
<20>¦ HOTSW_InitªŒÄÑ<E2809A>o³êéOÉ<E2809A>ÝèµÄ­¾³¢
*---------------------------------------------------------------------------*/
#ifdef USE_WRAM_LOAD
void HOTSW_SetGameModeCallBackFunction(OSIrqFunction function)
{
s_HotswFuncTable[HOTSW_CARD_GAME_MODE_CALLBACK] = function;
}
#endif
/*---------------------------------------------------------------------------*
Name: SetCardInsertCallBackFunction
Description: ƒJ<C692>[ƒhªŽh³Á½ŽžÌƒR<C692>ƒoƒbƒNŠÖ<C5A0>ð<E2809A>Ýè
<20>¦ HOTSW_InitªŒÄÑ<E2809A>o³êéOÉ<E2809A>ÝèµÄ­¾³¢
*---------------------------------------------------------------------------*/
#ifdef USE_WRAM_LOAD
void HOTSW_SetCardInsertCallBackFunction(OSIrqFunction function)
{
s_HotswFuncTable[HOTSW_CARD_INSERT_CALLBACK] = function;
}
#endif
/*---------------------------------------------------------------------------*
Name: SetCardPullOutCallBackFunction
Description: ƒJ<C692>[ƒhª”²¯½ŽžÌƒR<C692>ƒoƒbƒNŠÖ<C5A0>ð<E2809A>Ýè
<20>¦ HOTSW_InitªŒÄÑ<E2809A>o³êéOÉ<E2809A>ÝèµÄ­¾³¢
*---------------------------------------------------------------------------*/
#ifdef USE_WRAM_LOAD
void HOTSW_SetCardPullOutCallBackFunction(OSIrqFunction function)
{
s_HotswFuncTable[HOTSW_CARD_PULLOUT_CALLBACK] = function;
}
#endif
/*---------------------------------------------------------------------------*
Name: HOTSW_ReadCardDataOnGameMode
Description: Gameƒ<C692>[ƒh̃f<C692>[ƒ^“ÇÝŠÖ<C5A0>
*---------------------------------------------------------------------------*/
CardDataReadState HOTSW_ReadCardDataOnGameMode(const void* src, void* dest, u32 size)
{
CardDataReadState retval = CARD_READ_SUCCESS;
static u8 page_buffer[512];
u32 offset = (u32)src;
u32 page_offset = (u32)(offset & -512);
u32 buffer_offset = (u32)(offset % 512);
u32 valid_length = 512 - buffer_offset;
u32 remain_length;
// ŠJŽnƒAƒhƒŒƒXªƒy<C692>[ƒWÌ“r
if ( offset % 512 )
{
retval = ReadPageGame(page_offset, page_buffer, 512);
if (retval != HOTSW_SUCCESS)
{
return retval;
}
MI_CpuCopy8(page_buffer + buffer_offset, dest, (size < valid_length ? size : valid_length));
dest = (u8*)dest + valid_length;
offset += valid_length;
size -= valid_length;
if ( size < 0)
{
return retval;
}
}
remain_length = (u32)(size % 512);
retval = ReadPageGame(offset, dest, (u32)(size - remain_length));
// ƒPƒcªƒy<C692>[ƒW“r
if( remain_length ){
dest = (u8*)dest + (size - remain_length);
offset += size - remain_length;
retval = ReadPageGame(offset, page_buffer, 512);
if (retval != HOTSW_SUCCESS)
{
return retval;
}
MI_CpuCopy8(page_buffer, dest, remain_length);
}
return retval;
}
/*---------------------------------------------------------------------------*
Name: ReadPageGame
Description: Gameƒ<C692>[ƒhÌPage“ÇÝŠÖ<C5A0>
*---------------------------------------------------------------------------*/
static CardDataReadState ReadPageGame(u32 start_addr, void* buf, u32 size)
{
u32 loop, counter=0;
u64 i, page;
GCDCmd64 cndLE, cndBE;
page = (u32)(start_addr / PAGE_SIZE);
loop = (u32)(size / PAGE_SIZE);
loop = (size % PAGE_SIZE) ? loop + 1 : loop;
// ƒJ<C692>[ƒh̃<C38C>ƒbƒN
CARD_LockRom(s_CardLockID);
for(i=0; i<loop; i++){
if(!HOTSW_isGameMode()){
return CARD_READ_MODE_ERROR;
}
#ifndef USE_CPU_COPY
// NewDMA“]Ì<E2809A>€”õ
HOTSW_NDmaCopy_Card( HOTSW_NDMA_NO, (u32 *)HOTSW_MCD1, (u32 *)buf + (u32)(PAGE_WORD_SIZE*i), PAGE_SIZE );
#endif
// ƒRƒ}ƒ“ƒh<C692>ì<EFBFBD>¬
cndLE.dw = HSWOP_G_OP_RD_PAGE;
cndLE.dw |= (page + i) << HSWOP_G_RD_PAGE_ADDR_SHIFT;
// ƒrƒbƒOƒGƒ“ƒfƒBƒAƒ“ɼ·
cndBE.b[7] = cndLE.b[0];
cndBE.b[6] = cndLE.b[1];
cndBE.b[5] = cndLE.b[2];
cndBE.b[4] = cndLE.b[3];
cndBE.b[3] = cndLE.b[4];
cndBE.b[2] = cndLE.b[5];
cndBE.b[1] = cndLE.b[6];
cndBE.b[0] = cndLE.b[7];
//---- confirm CARD free
while( reg_HOTSW_MCCNT1 & REG_MI_MCCNT1_START_MASK ){}
// MCCMD ƒŒƒWƒXƒ^<5E>Ýè
reg_HOTSW_MCCMD0 = *(u32*)cndBE.b;
reg_HOTSW_MCCMD1 = *(u32*)&cndBE.b[4];
// MCCNT0 ƒŒƒWƒXƒ^<5E>Ýè
reg_HOTSW_MCCNT0 = (u16)((reg_HOTSW_MCCNT0 & HOTSW_E2PROM_CTRL_MASK) | REG_MI_MCCNT0_E_MASK );
// MCCNT1 ƒŒƒWƒXƒ^<5E>Ýè
reg_HOTSW_MCCNT1 = SYSMi_GetWork()->gameCommondParam | START_MASK | HOTSW_PAGE_1;
#ifndef USE_CPU_COPY
// ƒ<>ƒbƒZ<C692>[ƒWŽó<C5BD>M
OS_ReceiveMessage(&HotSwThreadData.hotswDmaQueue, (OSMessage *)&s_Msg, OS_MESSAGE_BLOCK);
#else
while(reg_HOTSW_MCCNT1 & START_FLG_MASK){
while(!(reg_HOTSW_MCCNT1 & READY_FLG_MASK)){}
*((u32 *)buf + counter++) = reg_HOTSW_MCD1;
}
#endif
}
// 100ns Wait
OS_SpinWait( OS_NSEC_TO_CPUCYC(100) );
// ƒJ<C692>[ƒh̃<C38C>ƒbƒNŠJ•ú(<28>¦ƒ<C2A6>ƒbƒNIDÍŠJ•ú¹¸ÉŽ<C389>¿±¯é)
CARD_UnlockRom(s_CardLockID);
return CARD_READ_SUCCESS;
}