Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions gc/ogc/stm.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,36 @@ distribution.
extern "C" {
#endif /* __cplusplus */

// There are also in conf.h anyways
enum STM_LedMode {
STM_LEDMODE_OFF,
STM_LEDMODE_DIM,
STM_LEDMODE_BRIGHT,
};

enum {
STM_MAX_LED_PATTERNS = 128,

STM_LEDFLASH_USER = (1 << 0),
STM_LEDFLASH_NOEXEC = (1 << 1),

STM_IDLEMODE_FAN_ON = (1 << 0),
};

typedef void (*stmcallback)(u32 event);

s32 __STM_Init(void);
s32 __STM_Close(void);
stmcallback STM_RegisterEventHandler(stmcallback newhandler);

s32 STM_ShutdownToStandby(void);
s32 STM_ShutdownToIdle(void);
s32 STM_SetLedMode(u32 mode);
s32 STM_ShutdownToIdleEx(u32 flags);
#define STM_ShutdownToIdle() STM_ShutdownToIdleEx(0)
s32 STM_RebootSystem(void);
stmcallback STM_RegisterEventHandler(stmcallback newhandler);

s32 STM_SetLedMode(u32 mode);
s32 STM_StartLedFlashLoop(u8 pattern_id, u8 priority, u8 flags, const u16* patterns, u32 num_patterns);
s32 STM_VIDimming(bool enable, u32 luma, u32 chroma);

#ifdef __cplusplus
}
Expand Down
166 changes: 118 additions & 48 deletions libogc/stm.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,21 @@ distribution.

#if defined(HW_RVL)

#include <stdio.h>
#include <string.h>
#include "ipc.h"
#include "system.h"
#include "asm.h"
#include "processor.h"
#include "cache.h"
#include "stm.h"

//#define DEBUG_STM
#ifdef DEBUG_STM
#include <stdio.h>
#define STM_printf(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS)
#else
#define STM_printf(...) while (0) {}
#endif

#define IOCTL_STM_EVENTHOOK 0x1000
#define IOCTL_STM_GET_IDLEMODE 0x3001
Expand All @@ -63,8 +70,6 @@ static u32 __stm_ehclear= 0;

static u32 __stm_ehbufin[0x08] ATTRIBUTE_ALIGN(32) = {0,0,0,0,0,0,0,0};
static u32 __stm_ehbufout[0x08] ATTRIBUTE_ALIGN(32) = {0,0,0,0,0,0,0,0};
static u32 __stm_immbufin[0x08] ATTRIBUTE_ALIGN(32) = {0,0,0,0,0,0,0,0};
static u32 __stm_immbufout[0x08] ATTRIBUTE_ALIGN(32) = {0,0,0,0,0,0,0,0};

static char __stm_eh_fs[] ATTRIBUTE_ALIGN(32) = "/dev/stm/eventhook";
static char __stm_imm_fs[] ATTRIBUTE_ALIGN(32) = "/dev/stm/immediate";
Expand All @@ -80,9 +85,8 @@ static vu16* const _viReg = (u16*)0xCC002000;
s32 __STM_Init(void)
{
if(__stm_initialized==1) return 1;
#ifdef DEBUG_STM
printf("STM Init\n");
#endif

STM_printf("STM init");

__stm_vdinuse = 0;
__stm_imm_fd = IOS_Open(__stm_imm_fs,0);
Expand All @@ -91,9 +95,7 @@ s32 __STM_Init(void)
__stm_eh_fd = IOS_Open(__stm_eh_fs,0);
if(__stm_eh_fd<0) return 0;

#ifdef DEBUG_STM
printf("STM FDs: %d, %d\n",__stm_imm_fd, __stm_eh_fd);
#endif
STM_printf("STM FDs: %d, %d\n",__stm_imm_fd, __stm_eh_fd);

__stm_initialized = 1;
__STM_SetEventHook();
Expand All @@ -120,6 +122,13 @@ s32 __STM_Close(void)
return ret;
}

s32 __STM_SendCommand(s32 ioctl, const void *inbuf, u32 inlen, void *outbuf, u32 outlen) {
if (__stm_initialized == 0)
return STM_ENOTINIT;

return IOS_Ioctl(__stm_imm_fd, ioctl, (void *)inbuf, inlen, outbuf, outlen);
}

s32 __STM_SetEventHook(void)
{
s32 ret;
Expand Down Expand Up @@ -147,7 +156,7 @@ s32 __STM_ReleaseEventHook(void)

__stm_ehclear = 1;

ret = IOS_Ioctl(__stm_imm_fd,IOCTL_STM_RELEASE_EH,__stm_immbufin,0x20,__stm_immbufout,0x20);
ret = __STM_SendCommand(IOCTL_STM_RELEASE_EH,NULL,0,NULL,0);
if(ret>=0) __stm_ehregistered = 0;

return ret;
Expand All @@ -161,10 +170,8 @@ static s32 __STMEventHandler(s32 result,void *usrdata)
return result;
}

#ifdef DEBUG_STM
printf("STM Event: %08x\n",__stm_ehbufout[0]);
#endif

STM_printf("STM Event: %08x\n",__stm_ehbufout[0]);

if(__stm_ehclear) { //release
return 0;
}
Expand All @@ -186,71 +193,77 @@ stmcallback STM_RegisterEventHandler(stmcallback newhandler)
return old;
}

__attribute__((noreturn))
static void WaitForImpendingDoom(void) {
u32 level;
_CPU_ISR_Disable(level);
ICFlashInvalidate();
ppchalt();
}

s32 STM_ShutdownToStandby(void)
{
int res;

_viReg[1] = 0;
if(__stm_initialized==0) {
#ifdef DEBUG_STM
printf("STM notinited\n");
#endif
STM_printf("STM notinited\n");
return STM_ENOTINIT;
}
__stm_immbufin[0] = 0;
res= IOS_Ioctl(__stm_imm_fd,IOCTL_STM_SHUTDOWN,__stm_immbufin,0x20,__stm_immbufout,0x20);
u32 config = 0;
res = __STM_SendCommand(IOCTL_STM_SHUTDOWN, &config, sizeof(u32), NULL, 0);
if(res<0) {
#ifdef DEBUG_STM
printf("STM STBY failed: %d\n",res);
#endif
STM_printf("STM STBY failed: %d\n",res);
}

WaitForImpendingDoom();
return res;
}

s32 STM_ShutdownToIdle(void)
s32 STM_ShutdownToIdleEx(u32 flags)
{
int res;
u32 config;

_viReg[1] = 0;
if(__stm_initialized==0) {
#ifdef DEBUG_STM
printf("STM notinited\n");
#endif
STM_printf("STM notinited\n");
return STM_ENOTINIT;
}
switch(SYS_GetHollywoodRevision()) {
case 0:
case 1:
case 2:
__stm_immbufin[0] = 0xFCA08280;
config = 0xFCA08280;
break;
default:
__stm_immbufin[0] = 0xFCE082C0;
config = 0xFCE082C0;
break;
}
res= IOS_Ioctl(__stm_imm_fd,IOCTL_STM_IDLE,__stm_immbufin,0x20,__stm_immbufout,0x20);

if (flags & STM_IDLEMODE_FAN_ON) {
config &= ~(1 << 30);
}

res = __STM_SendCommand(IOCTL_STM_IDLE, &config, sizeof(u32), NULL, 0);
if(res<0) {
#ifdef DEBUG_STM
printf("STM IDLE failed: %d\n",res);
#endif
STM_printf("STM IDLE failed: %d\n",res);
}

WaitForImpendingDoom();
return res;
}

s32 STM_SetLedMode(u32 mode)
{
int res;
if(__stm_initialized==0) {
#ifdef DEBUG_STM
printf("STM notinited\n");
#endif
STM_printf("STM notinited\n");
return STM_ENOTINIT;
}
__stm_immbufin[0] = mode;
res= IOS_Ioctl(__stm_imm_fd,IOCTL_STM_LEDMODE,__stm_immbufin,0x20,__stm_immbufout,0x20);
res= __STM_SendCommand(IOCTL_STM_LEDMODE, &mode, sizeof(u32), NULL, 0);
if(res<0) {
#ifdef DEBUG_STM
printf("STM LEDMODE failed: %d\n",res);
#endif
STM_printf("STM LEDMODE failed: %d\n",res);
}
return res;
}
Expand All @@ -261,21 +274,78 @@ s32 STM_RebootSystem(void)

_viReg[1] = 0;
if(__stm_initialized==0) {
#ifdef DEBUG_STM
printf("STM notinited\n");
#endif
STM_printf("STM notinited\n");
return STM_ENOTINIT;
}
__stm_immbufin[0] = 0;
res= IOS_Ioctl(__stm_imm_fd,IOCTL_STM_HOTRESET,__stm_immbufin,0x20,__stm_immbufout,0x20);
res= __STM_SendCommand(IOCTL_STM_HOTRESET, NULL, 0, NULL, 0);
if(res<0) {
#ifdef DEBUG_STM
printf("STM HRST failed: %d\n",res);
#endif
STM_printf("STM HRST failed: %d\n",res);
}

WaitForImpendingDoom();
return res;
}

struct STM_LedFlashConfig
{
u32 : 8;
u32 flags : 8;
u32 priority : 8;
u32 pattern_id : 8;

u16 patterns[STM_MAX_LED_PATTERNS];
};

// capitalization of LED is debatable. libogc currently has STM_SetLedMode, meanwhile this function is internally called ISTM_StartLEDFlashLoop
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure the comments here and above STM_VIDimming are needed.
this one can be removed i think, but STM_VIDimming isn't saying anything to me.
i dont know what __stm_vdinuse is, or what that comment about 0ms is about, so maybe also remove it?
the function just fades the screen to black right?

s32 STM_StartLedFlashLoop(u8 pattern_id, u8 priority, u8 flags, const u16* patterns, u32 num_patterns)
{
s32 ret;
struct STM_LedFlashConfig config = {};
if ((flags & STM_LEDFLASH_USER) && patterns != NULL) {
if (num_patterns > STM_MAX_LED_PATTERNS)
num_patterns = STM_MAX_LED_PATTERNS;

memcpy(config.patterns, patterns, sizeof(u16[num_patterns]));
} else {
num_patterns = 0;
flags &= ~STM_LEDFLASH_USER;
}

config.pattern_id = pattern_id;
config.priority = priority;
config.flags = flags;

ret = __STM_SendCommand(IOCTL_STM_LEDFLASH, &config, offsetof(struct STM_LedFlashConfig, patterns[num_patterns]), NULL, 0);
if (ret < 0) {
STM_printf("STM LEDFLASH failed: %d\n", ret);
}

return ret;
}

// This is where __stm_vdinuse would come into play
// https://github.com/koopthekoopa/wii-ipl/blob/main/libs/RVL_SDK/src/os/OSStateTM.c#L176
// I guess it's to prevent the function from being called 0ms after it was called the first time. Not sure why.
s32 STM_VIDimming(bool enable, u32 luma, u32 chroma)
{
s32 ret;
u32 inbuf[8];
u32 outbuf[8];

inbuf[0] = (enable << 7) | (luma & 0x7) << 3 | (chroma & 0x7);
inbuf[1] = 0;
inbuf[2] = 0;

inbuf[4] = 0; // keep nothing
inbuf[5] = ~0; // keep everything
inbuf[6] = ~0; // <official software> uses 0xFFFF0000 here, but, what is the register even for....

ret = __STM_SendCommand(IOCTL_STM_VIDIMMING, inbuf, sizeof inbuf, outbuf, sizeof outbuf);
if (ret < 0) {
STM_printf("STM VIDIM failed: %d\n", ret);
}

return ret;
}

#endif /* defined(HW_RVL) */