PS2SDK
PS2 Homebrew Libraries
getkernel.c
Go to the documentation of this file.
1 /*
2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Licenced under Academic Free License version 2.0
7 # Review ps2sdk README & LICENSE files for further details.
8 */
9 
15 #include <kernel.h>
16 
17 #ifdef F_GetSyscallHandler
18 static u32 *g_pSyscallTable = NULL;
19 
21 static void InitSyscallTable(void)
22 {
23  u32 oldintr, oldop;
24  u32 *pAddr;
25 
26  oldintr = DIntr();
27  oldop = ee_set_opmode(0);
28  pAddr = (u32 *)0x800002f0;
29  g_pSyscallTable = (u32 *)((pAddr[0] << 16) | (pAddr[2] & 0xFFFF));
30  ee_set_opmode(oldop);
31  if (oldintr) {
32  EIntr();
33  }
34 }
35 
40 void *GetSyscallHandler(int syscall_no)
41 {
42  u32 oldintr, oldop;
43  u32 addr = 0;
44 
45  if (g_pSyscallTable == NULL) {
46  InitSyscallTable();
47  }
48 
49  if (g_pSyscallTable != NULL) {
50  oldintr = DIntr();
51  oldop = ee_set_opmode(0);
52  addr = g_pSyscallTable[syscall_no];
53  ee_set_opmode(oldop);
54  if (oldintr) {
55  EIntr();
56  }
57  }
58 
59  return (void *)addr;
60 }
61 #endif
62 
63 #ifdef F_GetSyscall
64 
68 void *GetSyscall(int syscall_no) { return (GetSyscallHandler(syscall_no)); }
69 #endif
70 
71 #ifdef F_GetExceptionHandler
72 
73 extern void *GetSyscallHandler(int syscall_no);
74 
79 void *GetExceptionHandler(int ex_cause_no)
80 {
81  u32 oldintr, oldop;
82  u32 addr, table_addr;
83  u16 lo16, hi16;
84 
85  if ((ex_cause_no < 1) || (ex_cause_no > 15)) {
86  return (NULL);
87  }
88 
89  // get address of the syscall "SetVTLBRefillHandler"
90  addr = (u32)GetSyscallHandler(13);
91 
92  // suspend interrupts and enter "kernel" operating mode.
93  oldintr = DIntr();
94  oldop = ee_set_opmode(0);
95 
96  // harvest the address of the exception handler table.
97  lo16 = ((vu32 *)addr)[0x20 / 4];
98  hi16 = ((vu32 *)addr)[0x14 / 4];
99  table_addr = ((u32)(hi16 << 16) | lo16);
100 
101  addr = ((u32 *)table_addr)[ex_cause_no];
102 
103  // return to the old operating mode and resume interrupts.
104  ee_set_opmode(oldop);
105  if (oldintr) {
106  EIntr();
107  }
108 
109  return ((void *)addr);
110 }
111 #endif
112 
113 #ifdef F_GetInterruptHandler
114 
115 extern void *GetSyscallHandler(int syscall_no);
116 
121 void *GetInterruptHandler(int intr_cause_no)
122 {
123  u32 oldintr, oldop;
124  u32 addr;
125  u16 lo16, hi16;
126 
127  // make sure intr_cause_no is between 0 and 7
128  if ((intr_cause_no < 0) || (intr_cause_no > 7)) {
129  return (NULL);
130  }
131 
132  // get address of the syscall "SetVInterruptHandler"
133  addr = (u32)GetSyscallHandler(15);
134 
135  // suspend interrupts and enter "kernel" operating mode.
136  oldintr = DIntr();
137  oldop = ee_set_opmode(0);
138 
139  // harvest the address of the corresponding exception handler table.
140  hi16 = ((vu32 *)addr)[0x10 / 4];
141  lo16 = ((vu32 *)addr)[0x1C / 4];
142 
143  addr = ((u32 *)((u32)(hi16 << 16) | lo16))[intr_cause_no];
144 
145  // return to the old operating mode and resume interrupts.
146  ee_set_opmode(oldop);
147  if (oldintr) {
148  EIntr();
149  }
150 
151  return (void *)addr;
152 }
153 #endif
kernel.h