usb 2.0 support through ios 58, and other usb improvements/corrections. patch by...
[libogc.git] / libogc / ios.c
blob47f63cd929f08880159ec883016e6397852ccf67
1 /*-------------------------------------------------------------
3 ios.c -- IOS control
5 Copyright (C) 2008
6 Michael Wiedenbauer (shagkur)
7 Dave Murphy (WinterMute)
8 Hector Martin (marcan)
10 This software is provided 'as-is', without any express or implied
11 warranty. In no event will the authors be held liable for any
12 damages arising from the use of this software.
14 Permission is granted to anyone to use this software for any
15 purpose, including commercial applications, and to alter it and
16 redistribute it freely, subject to the following restrictions:
18 1. The origin of this software must not be misrepresented; you
19 must not claim that you wrote the original software. If you use
20 this software in a product, an acknowledgment in the product
21 documentation would be appreciated but is not required.
23 2. Altered source versions must be plainly marked as such, and
24 must not be misrepresented as being the original software.
26 3. This notice may not be removed or altered from any source
27 distribution.
29 -------------------------------------------------------------*/
31 #if defined(HW_RVL)
33 #include <stdio.h>
34 #include "asm.h"
35 #include "processor.h"
36 #include "cache.h"
37 #include "ipc.h"
38 #include "stm.h"
39 #include "es.h"
40 #include "ios.h"
41 #include "irq.h"
43 #define IOS_HEAP_SIZE 0x1000
44 #define MAX_IPC_RETRIES 200
46 //#define DEBUG_IOS
48 #define IOS_MAX_VERSION 61
49 #define IOS_MIN_VERSION 3
51 static s32 __ios_hid = -1;
52 extern void udelay(int us);
54 s32 __IOS_InitHeap(void)
56 if(__ios_hid <0 ) {
57 __ios_hid = iosCreateHeap(IOS_HEAP_SIZE);
58 if(__ios_hid < 0) return __ios_hid;
60 return 0;
63 // These two functions deal with the "internal" IOS subsystems that are used by default by libogc
64 // Other stuff should be inited by the user and deinited by the exit callbacks. The user is also responsible
65 // for deiniting other stuff before an IOS reload and reiniting them after.
66 s32 __IOS_InitializeSubsystems(void)
68 s32 res;
69 s32 ret = 0;
70 #ifdef DEBUG_IOS
71 printf("IOS Subsystem Init\n");
72 #endif
73 res = __ES_Init();
74 if(res < 0) {
75 ret = res;
76 #ifdef DEBUG_IOS
77 printf("ES Init failed: %d\n",ret);
78 #endif
80 res = __STM_Init();
81 if(res < 0) {
82 ret = res;
83 #ifdef DEBUG_IOS
84 printf("STM Init failed: %d\n",ret);
85 #endif
87 #ifdef DEBUG_IOS
88 printf("IOS Subsystem Init Done: %d\n",ret);
89 #endif
90 return ret;
93 s32 __IOS_ShutdownSubsystems(void)
95 s32 res;
96 s32 ret = 0;
97 #ifdef DEBUG_IOS
98 printf("IOS Subsystem Close\n");
99 #endif
100 res = __STM_Close();
101 if(res < 0) ret = res;
102 res = __ES_Close();
103 if(res < 0) ret = res;
104 #ifdef DEBUG_IOS
105 printf("IOS Subsystem Close Done: %d\n",ret);
106 #endif
107 return ret;
110 s32 IOS_GetPreferredVersion()
112 int ver = IOS_EBADVERSION;
113 s32 res;
114 u32 count;
115 u64 *titles;
116 u32 i;
117 u32 a,b;
119 res = __IOS_InitHeap();
120 if(res<0) return res;
122 res = ES_GetNumTitles(&count);
123 if(res < 0) {
124 #ifdef DEBUG_IOS
125 printf(" GetNumTitles failed: %d\n",res);
126 #endif
127 return res;
129 #ifdef DEBUG_IOS
130 printf(" %d titles on card:\n",count);
131 #endif
132 titles = iosAlloc(__ios_hid, sizeof(u64)*count);
133 if(!titles) {
134 printf(" iosAlloc titles failed\n");
135 return -1;
137 res = ES_GetTitles(titles, count);
138 if(res < 0) {
139 #ifdef DEBUG_IOS
140 printf(" GetTitles failed: %d\n",res);
141 #endif
142 iosFree(__ios_hid, titles);
143 return res;
146 for(i=0; i<count; i++) {
147 a = titles[i]>>32;
148 b = titles[i]&0xFFFFFFFF;
149 if(a != 1) continue;
150 if(b < IOS_MIN_VERSION) continue;
151 if(b > IOS_MAX_VERSION) continue;
152 if(((s32)b) > ((s32)ver)) ver = b;
154 #ifdef DEBUG_IOS
155 printf(" Preferred verson: %d\n",ver);
156 #endif
157 iosFree(__ios_hid, titles);
158 return ver;
161 s32 IOS_GetVersion()
163 u32 vercode;
164 u16 version;
165 DCInvalidateRange((void*)0x80003140,8);
166 vercode = *((u32*)0x80003140);
167 version = vercode >> 16;
168 if(version == 0) return IOS_EBADVERSION;
169 if(version > 0xff) return IOS_EBADVERSION;
170 return version;
173 s32 IOS_GetRevision()
175 u32 vercode;
176 u16 rev;
177 DCInvalidateRange((void*)0x80003140,8);
178 vercode = *((u32*)0x80003140);
179 rev = vercode & 0xFFFF;
180 if(vercode == 0 || rev == 0) return IOS_EBADVERSION;
181 return rev;
184 s32 IOS_GetRevisionMajor()
186 s32 rev;
187 rev = IOS_GetRevision();
188 if(rev < 0) return rev;
189 return (rev>>8)&0xFF;
192 s32 IOS_GetRevisionMinor()
194 s32 rev;
195 rev = IOS_GetRevision();
196 if(rev < 0) return rev;
197 return rev&0xFF;
200 s32 __IOS_LaunchNewIOS(int version)
202 u32 numviews;
203 s32 res;
204 u64 titleID = 0x100000000LL;
205 raw_irq_handler_t irq_handler;
206 u32 counter;
208 STACK_ALIGN(tikview,views,4,32);
209 #ifdef DEBUG_IOS
210 s32 oldversion;
211 #endif
212 s32 newversion;
214 if(version < 3 || version > 0xFF) {
215 return IOS_EBADVERSION;
218 #ifdef DEBUG_IOS
219 oldversion = IOS_GetVersion();
220 if(oldversion>0) printf("Current IOS Version: IOS%d\n",oldversion);
221 #endif
223 titleID |= version;
224 #ifdef DEBUG_IOS
225 printf("Launching IOS TitleID: %016llx\n",titleID);
226 #endif
228 res = ES_GetNumTicketViews(titleID, &numviews);
229 if(res < 0) {
230 #ifdef DEBUG_IOS
231 printf(" GetNumTicketViews failed: %d\n",res);
232 #endif
233 return res;
235 if(numviews > 4) {
236 printf(" GetNumTicketViews too many views: %u\n",numviews);
237 return IOS_ETOOMANYVIEWS;
239 res = ES_GetTicketViews(titleID, views, numviews);
240 if(res < 0) {
241 #ifdef DEBUG_IOS
242 printf(" GetTicketViews failed: %d\n",res);
243 #endif
244 return res;
247 write32(0x80003140, 0);
249 res = ES_LaunchTitleBackground(titleID, &views[0]);
250 if(res < 0) {
251 #ifdef DEBUG_IOS
252 printf(" LaunchTitleBackground failed: %d\n",res);
253 #endif
254 return res;
257 __ES_Reset();
259 // Mask IPC IRQ while we're busy reloading
260 __MaskIrq(IRQ_PI_ACR);
261 irq_handler = IRQ_Free(IRQ_PI_ACR);
263 #ifdef DEBUG_IOS
264 printf("Waiting for IOS ...\n");
265 #endif
266 while ((read32(0x80003140) >> 16) == 0)
267 udelay(1000);
269 #ifdef DEBUG_IOS
270 u32 v = read32(0x80003140);
271 printf("IOS loaded: IOS%d v%d.%d\n", v >> 16, (v >> 8) & 0xff, v & 0xff);
272 #endif
274 #ifdef DEBUG_IOS
275 printf("Waiting for IPC ...\n");
276 #endif
277 for (counter = 0; !(read32(0x0d000004) & 2); counter++) {
278 udelay(1000);
280 if (counter >= MAX_IPC_RETRIES)
281 break;
284 #ifdef DEBUG_IOS
285 printf("IPC started (%u)\n", counter);
286 #endif
288 IRQ_Request(IRQ_PI_ACR, irq_handler, NULL);
289 __UnmaskIrq(IRQ_PI_ACR);
291 __IPC_Reinitialize();
293 newversion = IOS_GetVersion();
295 if(newversion != version) {
296 #ifdef DEBUG_IOS
297 printf(" Version mismatch!\n");
298 #endif
299 return IOS_EMISMATCH;
302 return version;
305 s32 __attribute__((weak)) __IOS_LoadStartupIOS()
307 #if 0
308 int version;
309 int res;
311 res = __ES_Init();
312 if(res < 0) return res;
313 version = IOS_GetPreferredVersion();
314 if(version < 0) {
315 #ifdef DEBUG_IOS
316 printf("GetPreferredVersion failed: %d\n",version);
317 #endif
318 __ES_Close();
319 return version;
321 #ifdef DEBUG_IOS
322 printf("Loading startup IOS: %d\n",version);
323 #endif
324 res = __IOS_LaunchNewIOS(version);
325 if(res < 0) return res;
326 #endif
328 return 0;
331 s32 IOS_ReloadIOS(int version)
333 int ret = 0;
334 int res;
336 #ifdef DEBUG_IOS
337 printf("Reloading to IOS%d\n",version);
338 #endif
340 res = __IOS_ShutdownSubsystems();
341 if(res < 0) {
342 #ifdef DEBUG_IOS
343 printf("__IOS_ShutdownSubsystems failed: %d\n", res);
344 #endif
345 ret = res;
348 res = __ES_Init();
349 if(res < 0) {
350 #ifdef DEBUG_IOS
351 printf("__ES_Init failed: %d\n", res);
352 #endif
353 ret = res;
354 } else {
355 res = __IOS_LaunchNewIOS(version);
356 if(res < 0) {
357 #ifdef DEBUG_IOS
358 printf("__IOS_LaunchNewIOS failed: %d\n", res);
359 #endif
360 ret = res;
361 __ES_Close();
365 res = __IOS_InitializeSubsystems();
366 if(res < 0) {
367 #ifdef DEBUG_IOS
368 printf("__IOS_InitializeSubsystems failed: %d\n", res);
369 #endif
370 ret = res;
373 return ret;
376 #endif /* defined(HW_RVL) */