@@ -30,14 +30,21 @@ distribution.
3030
3131#if defined(HW_RVL )
3232
33- #include <stdio .h>
33+ #include <string .h>
3434#include "ipc.h"
3535#include "system.h"
3636#include "asm.h"
3737#include "processor.h"
38+ #include "cache.h"
3839#include "stm.h"
3940
4041//#define DEBUG_STM
42+ #ifdef DEBUG_STM
43+ #include <stdio.h>
44+ #define STM_printf (fmt , ...) fprintf(stderr, fmt, ##__VA_ARGS)
45+ #else
46+ #define STM_printf (...) while (0) {}
47+ #endif
4148
4249#define IOCTL_STM_EVENTHOOK 0x1000
4350#define IOCTL_STM_GET_IDLEMODE 0x3001
@@ -63,8 +70,6 @@ static u32 __stm_ehclear= 0;
6370
6471static u32 __stm_ehbufin [0x08 ] ATTRIBUTE_ALIGN (32 ) = {0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 };
6572static u32 __stm_ehbufout [0x08 ] ATTRIBUTE_ALIGN (32 ) = {0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 };
66- static u32 __stm_immbufin [0x08 ] ATTRIBUTE_ALIGN (32 ) = {0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 };
67- static u32 __stm_immbufout [0x08 ] ATTRIBUTE_ALIGN (32 ) = {0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 };
6873
6974static char __stm_eh_fs [] ATTRIBUTE_ALIGN (32 ) = "/dev/stm/eventhook" ;
7075static char __stm_imm_fs [] ATTRIBUTE_ALIGN (32 ) = "/dev/stm/immediate" ;
@@ -80,9 +85,8 @@ static vu16* const _viReg = (u16*)0xCC002000;
8085s32 __STM_Init (void )
8186{
8287 if (__stm_initialized == 1 ) return 1 ;
83- #ifdef DEBUG_STM
84- printf ("STM Init\n" );
85- #endif
88+
89+ STM_printf ("STM init" );
8690
8791 __stm_vdinuse = 0 ;
8892 __stm_imm_fd = IOS_Open (__stm_imm_fs ,0 );
@@ -91,9 +95,7 @@ s32 __STM_Init(void)
9195 __stm_eh_fd = IOS_Open (__stm_eh_fs ,0 );
9296 if (__stm_eh_fd < 0 ) return 0 ;
9397
94- #ifdef DEBUG_STM
95- printf ("STM FDs: %d, %d\n" ,__stm_imm_fd , __stm_eh_fd );
96- #endif
98+ STM_printf ("STM FDs: %d, %d\n" ,__stm_imm_fd , __stm_eh_fd );
9799
98100 __stm_initialized = 1 ;
99101 __STM_SetEventHook ();
@@ -120,6 +122,13 @@ s32 __STM_Close(void)
120122 return ret ;
121123}
122124
125+ s32 __STM_SendCommand (s32 ioctl , const void * inbuf , u32 inlen , void * outbuf , u32 outlen ) {
126+ if (__stm_initialized == 0 )
127+ return STM_ENOTINIT ;
128+
129+ return IOS_Ioctl (__stm_imm_fd , ioctl , (void * )inbuf , inlen , outbuf , outlen );
130+ }
131+
123132s32 __STM_SetEventHook (void )
124133{
125134 s32 ret ;
@@ -147,7 +156,7 @@ s32 __STM_ReleaseEventHook(void)
147156
148157 __stm_ehclear = 1 ;
149158
150- ret = IOS_Ioctl ( __stm_imm_fd , IOCTL_STM_RELEASE_EH ,__stm_immbufin , 0x20 , __stm_immbufout , 0x20 );
159+ ret = __STM_SendCommand ( IOCTL_STM_RELEASE_EH ,NULL , 0 , NULL , 0 );
151160 if (ret >=0 ) __stm_ehregistered = 0 ;
152161
153162 return ret ;
@@ -161,10 +170,8 @@ static s32 __STMEventHandler(s32 result,void *usrdata)
161170 return result ;
162171 }
163172
164- #ifdef DEBUG_STM
165- printf ("STM Event: %08x\n" ,__stm_ehbufout [0 ]);
166- #endif
167-
173+ STM_printf ("STM Event: %08x\n" ,__stm_ehbufout [0 ]);
174+
168175 if (__stm_ehclear ) { //release
169176 return 0 ;
170177 }
@@ -186,71 +193,73 @@ stmcallback STM_RegisterEventHandler(stmcallback newhandler)
186193 return old ;
187194}
188195
196+ __attribute__((noreturn ))
197+ static void WaitForImpendingDoom (void ) {
198+ u32 level ;
199+ _CPU_ISR_Disable (level );
200+ ICFlashInvalidate ();
201+ ppchalt ();
202+ }
203+
189204s32 STM_ShutdownToStandby (void )
190205{
191206 int res ;
192207
193208 _viReg [1 ] = 0 ;
194209 if (__stm_initialized == 0 ) {
195- #ifdef DEBUG_STM
196- printf ("STM notinited\n" );
197- #endif
210+ STM_printf ("STM notinited\n" );
198211 return STM_ENOTINIT ;
199212 }
200- __stm_immbufin [ 0 ] = 0 ;
201- res = IOS_Ioctl ( __stm_imm_fd , IOCTL_STM_SHUTDOWN ,__stm_immbufin , 0x20 , __stm_immbufout , 0x20 );
213+ u32 config = 0 ;
214+ res = __STM_SendCommand ( IOCTL_STM_SHUTDOWN , & config , sizeof ( u32 ), NULL , 0 );
202215 if (res < 0 ) {
203- #ifdef DEBUG_STM
204- printf ("STM STBY failed: %d\n" ,res );
205- #endif
216+ STM_printf ("STM STBY failed: %d\n" ,res );
206217 }
218+
219+ WaitForImpendingDoom ();
207220 return res ;
208221}
209222
223+ // idea: rename this to STM_ShutdownToIdleEx and give it some bitflags
210224s32 STM_ShutdownToIdle (void )
211225{
212226 int res ;
227+ u32 config ;
213228
214229 _viReg [1 ] = 0 ;
215230 if (__stm_initialized == 0 ) {
216- #ifdef DEBUG_STM
217- printf ("STM notinited\n" );
218- #endif
231+ STM_printf ("STM notinited\n" );
219232 return STM_ENOTINIT ;
220233 }
221234 switch (SYS_GetHollywoodRevision ()) {
222235 case 0 :
223236 case 1 :
224237 case 2 :
225- __stm_immbufin [ 0 ] = 0xFCA08280 ;
238+ config = 0xFCA08280 ;
226239 break ;
227240 default :
228- __stm_immbufin [0 ] = 0xFCE082C0 ;
241+ config = 0xFCE082C0 ;
242+ break ;
229243 }
230- res = IOS_Ioctl ( __stm_imm_fd , IOCTL_STM_IDLE ,__stm_immbufin , 0x20 , __stm_immbufout , 0x20 );
244+ res = __STM_SendCommand ( IOCTL_STM_IDLE , & config , sizeof ( u32 ), NULL , 0 );
231245 if (res < 0 ) {
232- #ifdef DEBUG_STM
233- printf ("STM IDLE failed: %d\n" ,res );
234- #endif
246+ STM_printf ("STM IDLE failed: %d\n" ,res );
235247 }
248+
249+ WaitForImpendingDoom ();
236250 return res ;
237251}
238252
239253s32 STM_SetLedMode (u32 mode )
240254{
241255 int res ;
242256 if (__stm_initialized == 0 ) {
243- #ifdef DEBUG_STM
244- printf ("STM notinited\n" );
245- #endif
257+ STM_printf ("STM notinited\n" );
246258 return STM_ENOTINIT ;
247259 }
248- __stm_immbufin [0 ] = mode ;
249- res = IOS_Ioctl (__stm_imm_fd ,IOCTL_STM_LEDMODE ,__stm_immbufin ,0x20 ,__stm_immbufout ,0x20 );
260+ res = __STM_SendCommand (IOCTL_STM_LEDMODE , & mode , sizeof (u32 ), NULL , 0 );
250261 if (res < 0 ) {
251- #ifdef DEBUG_STM
252- printf ("STM LEDMODE failed: %d\n" ,res );
253- #endif
262+ STM_printf ("STM LEDMODE failed: %d\n" ,res );
254263 }
255264 return res ;
256265}
@@ -261,21 +270,78 @@ s32 STM_RebootSystem(void)
261270
262271 _viReg [1 ] = 0 ;
263272 if (__stm_initialized == 0 ) {
264- #ifdef DEBUG_STM
265- printf ("STM notinited\n" );
266- #endif
273+ STM_printf ("STM notinited\n" );
267274 return STM_ENOTINIT ;
268275 }
269- __stm_immbufin [0 ] = 0 ;
270- res = IOS_Ioctl (__stm_imm_fd ,IOCTL_STM_HOTRESET ,__stm_immbufin ,0x20 ,__stm_immbufout ,0x20 );
276+ res = __STM_SendCommand (IOCTL_STM_HOTRESET , NULL , 0 , NULL , 0 );
271277 if (res < 0 ) {
272- #ifdef DEBUG_STM
273- printf ("STM HRST failed: %d\n" ,res );
274- #endif
278+ STM_printf ("STM HRST failed: %d\n" ,res );
275279 }
280+
281+ WaitForImpendingDoom ();
276282 return res ;
277283}
278284
285+ struct STM_LedFlashConfig
286+ {
287+ u32 : 8 ;
288+ u32 flags : 8 ;
289+ u32 priority : 8 ;
290+ u32 pattern_id : 8 ;
291+
292+ u16 patterns [STM_MAX_LED_PATTERNS ];
293+ };
294+
295+ // capitalization of LED is debatable. libogc currently has STM_SetLedMode, meanwhile this function is internally called ISTM_StartLEDFlashLoop
296+ s32 STM_StartLedFlashLoop (u8 pattern_id , u8 priority , u8 flags , const u16 * patterns , u32 num_patterns )
297+ {
298+ s32 ret ;
299+ struct STM_LedFlashConfig config = {};
300+ if ((flags & STM_LEDFLASH_USER ) && patterns != NULL ) {
301+ if (num_patterns > STM_MAX_LED_PATTERNS )
302+ num_patterns = STM_MAX_LED_PATTERNS ;
303+
304+ memcpy (config .patterns , patterns , sizeof (u16 [num_patterns ]));
305+ } else {
306+ num_patterns = 0 ;
307+ flags &= ~STM_LEDFLASH_USER ;
308+ }
279309
310+ config .pattern_id = pattern_id ;
311+ config .priority = priority ;
312+ config .flags = flags ;
313+
314+ ret = __STM_SendCommand (IOCTL_STM_LEDFLASH , & config , offsetof(struct STM_LedFlashConfig , patterns [num_patterns ]), NULL , 0 );
315+ if (ret < 0 ) {
316+ STM_printf ("STM LEDFLASH failed: %d\n" , ret );
317+ }
318+
319+ return ret ;
320+ }
321+
322+ // This is where __stm_vdinuse would come into play
323+ // https://github.com/koopthekoopa/wii-ipl/blob/main/libs/RVL_SDK/src/os/OSStateTM.c#L176
324+ // I guess it's to prevent the function from being called 0ms after it was called the first time. Not sure why.
325+ s32 STM_VIDimming (bool enable , u32 luma , u32 chroma )
326+ {
327+ s32 ret ;
328+ u32 inbuf [8 ];
329+ u32 outbuf [8 ];
330+
331+ inbuf [0 ] = (enable << 7 ) | (luma & 0x7 ) << 3 | (chroma & 0x7 );
332+ inbuf [1 ] = 0 ;
333+ inbuf [2 ] = 0 ;
334+
335+ inbuf [4 ] = 0 ; // keep nothing
336+ inbuf [5 ] = ~0 ; // keep everything
337+ inbuf [6 ] = ~0 ; // <official software> uses 0xFFFF0000 here, but, what is the register even for....
338+
339+ ret = __STM_SendCommand (IOCTL_STM_VIDIMMING , inbuf , sizeof inbuf , outbuf , sizeof outbuf );
340+ if (ret < 0 ) {
341+ STM_printf ("STM VIDIM failed: %d\n" , ret );
342+ }
343+
344+ return ret ;
345+ }
280346
281347#endif /* defined(HW_RVL) */
0 commit comments