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