1 // Copyright (c) 2012- PPSSPP Project.
2 
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0 or later versions.
6 
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 // GNU General Public License 2.0 for more details.
11 
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
14 
15 // Official git repository and contact information can be found at
16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17 
18 #pragma once
19 
20 #include <map>
21 
22 class PointerWrap;
23 
24 enum PSPInterrupt {
25 	PSP_GPIO_INTR      =  4,
26 	PSP_ATA_INTR       =  5,
27 	PSP_UMD_INTR       =  6,
28 	PSP_MSCM0_INTR     =  7,
29 	PSP_WLAN_INTR      =  8,
30 	PSP_AUDIO_INTR     = 10,
31 	PSP_I2C_INTR       = 12,
32 	PSP_SIRS_INTR      = 14,
33 	PSP_SYSTIMER0_INTR = 15,
34 	PSP_SYSTIMER1_INTR = 16,
35 	PSP_SYSTIMER2_INTR = 17,
36 	PSP_SYSTIMER3_INTR = 18,
37 	PSP_THREAD0_INTR   = 19,
38 	PSP_NAND_INTR      = 20,
39 	PSP_DMACPLUS_INTR  = 21,
40 	PSP_DMA0_INTR      = 22,
41 	PSP_DMA1_INTR      = 23,
42 	PSP_MEMLMD_INTR    = 24,
43 	PSP_GE_INTR        = 25,
44 	PSP_VBLANK_INTR    = 30,
45 	PSP_MECODEC_INTR   = 31,
46 	PSP_HPREMOTE_INTR  = 36,
47 	PSP_MSCM1_INTR     = 60,
48 	PSP_MSCM2_INTR     = 61,
49 	PSP_THREAD1_INTR   = 65,
50 	PSP_INTERRUPT_INTR = 66,
51 	PSP_NUMBER_INTERRUPTS = 67
52 };
53 
54 
55 // These are invented for PPSSPP:
56 enum PSPGeSubInterrupts {
57   PSP_GE_SUBINTR_SIGNAL = 0,
58   PSP_GE_SUBINTR_FINISH = 1,
59 };
60 
61 enum PSPInterruptTriggerType {
62 	// Trigger immediately, for CoreTiming events.
63 	PSP_INTR_IMMEDIATE = 0x0,
64 	// Trigger after the HLE syscall finishes.
65 	PSP_INTR_HLE = 0x1,
66 	// Only trigger (as above) if interrupts are not suspended.
67 	PSP_INTR_ONLY_IF_ENABLED = 0x2,
68 	// Always reschedule, even if there's no handler registered.
69 	// TODO: Maybe this should just always do this?  Not sure.
70 	PSP_INTR_ALWAYS_RESCHED = 0x4,
71 };
72 
73 enum PSPSubInterruptTriggerType {
74 	// Trigger all sub intr
75 	PSP_INTR_SUB_ALL    = -2,
76 	// Trigger code at the interrupt handler level
77 	PSP_INTR_SUB_NONE   = -1,
78 	// Trigger specific sub interrupt
79 	PSP_INTR_SUB_NUMBER = 0,
80 };
81 
82 struct PendingInterrupt {
PendingInterruptPendingInterrupt83 	PendingInterrupt(int intr_, int subintr_)
84 		: intr(intr_), subintr(subintr_) {}
85 
86 	void DoState(PointerWrap &p);
87 
88 	int intr;
89 	int subintr;
90 };
91 
92 struct SubIntrHandler
93 {
94 	bool enabled;
95 	int intrNumber;
96 	int subIntrNumber;
97 	u32 handlerAddress;
98 	u32 handlerArg;
99 };
100 
101 class IntrHandler
102 {
103 public:
IntrHandler(int intrNumber_)104 	IntrHandler(int intrNumber_)
105 		: intrNumber(intrNumber_)
106 	{
107 	}
~IntrHandler()108 	virtual ~IntrHandler() {}
109 
110 	virtual bool run(PendingInterrupt& pend);
111 	virtual void copyArgsToCPU(PendingInterrupt& pend);
112 	virtual void handleResult(PendingInterrupt& pend);
113 	void queueUp(int subintr);
114 
115 	SubIntrHandler* add(int subIntrNum);
116 	void remove(int subIntrNum);
117 	bool has(int subIntrNum) const;
118 	void enable(int subIntrNum);
119 	void disable(int subIntrNum);
120 	SubIntrHandler *get(int subIntrNum);
121 	void clear();
122 
123 
124 	void DoState(PointerWrap &p);
125 
126 private:
127 	int intrNumber;
128 	std::map<int, SubIntrHandler> subIntrHandlers;
129 };
130 
131 void __DisableInterrupts();
132 void __EnableInterrupts();
133 bool __InterruptsEnabled();
134 bool __IsInInterrupt();
135 void __InterruptsInit();
136 void __InterruptsDoState(PointerWrap &p);
137 void __InterruptsDoStateLate(PointerWrap &p);
138 void __InterruptsShutdown();
139 void __TriggerInterrupt(int type, PSPInterrupt intno, int subInterrupts = -1);
140 bool __RunOnePendingInterrupt();
141 void __KernelReturnFromInterrupt();
142 
143 void __RegisterIntrHandler(u32 intrNumber, IntrHandler* handler);
144 SubIntrHandler *__RegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handler, u32 handlerArg, u32 &error);
145 int __ReleaseSubIntrHandler(int intrNumber, int subIntrNumber);
146 
147 u32 sceKernelRegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handler, u32 handlerArg);
148 u32 sceKernelReleaseSubIntrHandler(u32 intrNumber, u32 subIntrNumber);
149 u32 sceKernelEnableSubIntr(u32 intrNumber, u32 subIntrNumber);
150 
151 void Register_Kernel_Library();
152 void Register_InterruptManager();
153 
154 void Register_SysclibForKernel();
155