ppsspp/Core/HLE/sceKernelInterrupt.h
Unknown W. Brackets 87ee0bc650 Return error codes in register/release subintr.
This checks for duplicate registrations and other thigns that could've
been causing wrong behavior.
2014-06-21 21:27:58 -07:00

153 lines
4.0 KiB
C++

// Copyright (c) 2012- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#pragma once
#include <map>
class PointerWrap;
enum PSPInterrupt {
PSP_GPIO_INTR = 4,
PSP_ATA_INTR = 5,
PSP_UMD_INTR = 6,
PSP_MSCM0_INTR = 7,
PSP_WLAN_INTR = 8,
PSP_AUDIO_INTR = 10,
PSP_I2C_INTR = 12,
PSP_SIRS_INTR = 14,
PSP_SYSTIMER0_INTR = 15,
PSP_SYSTIMER1_INTR = 16,
PSP_SYSTIMER2_INTR = 17,
PSP_SYSTIMER3_INTR = 18,
PSP_THREAD0_INTR = 19,
PSP_NAND_INTR = 20,
PSP_DMACPLUS_INTR = 21,
PSP_DMA0_INTR = 22,
PSP_DMA1_INTR = 23,
PSP_MEMLMD_INTR = 24,
PSP_GE_INTR = 25,
PSP_VBLANK_INTR = 30,
PSP_MECODEC_INTR = 31,
PSP_HPREMOTE_INTR = 36,
PSP_MSCM1_INTR = 60,
PSP_MSCM2_INTR = 61,
PSP_THREAD1_INTR = 65,
PSP_INTERRUPT_INTR = 66,
PSP_NUMBER_INTERRUPTS = 67
};
// These are invented for PPSSPP:
enum PSPGeSubInterrupts {
PSP_GE_SUBINTR_SIGNAL = 0,
PSP_GE_SUBINTR_FINISH = 1,
};
enum PSPInterruptTriggerType {
// Trigger immediately, for CoreTiming events.
PSP_INTR_IMMEDIATE = 0x0,
// Trigger after the HLE syscall finishes.
PSP_INTR_HLE = 0x1,
// Only trigger (as above) if interrupts are not suspended.
PSP_INTR_ONLY_IF_ENABLED = 0x2,
// Always reschedule, even if there's no handler registered.
// TODO: Maybe this should just always do this? Not sure.
PSP_INTR_ALWAYS_RESCHED = 0x4,
};
enum PSPSubInterruptTriggerType {
// Trigger all sub intr
PSP_INTR_SUB_ALL = -2,
// Trigger code at the interrupt handler level
PSP_INTR_SUB_NONE = -1,
// Trigger specific sub interrupt
PSP_INTR_SUB_NUMBER = 0,
};
struct PendingInterrupt {
PendingInterrupt(int intr_, int subintr_)
: intr(intr_), subintr(subintr_) {}
void DoState(PointerWrap &p);
int intr;
int subintr;
};
struct SubIntrHandler
{
bool enabled;
int intrNumber;
int subIntrNumber;
u32 handlerAddress;
u32 handlerArg;
};
class IntrHandler
{
public:
IntrHandler(int intrNumber_)
: intrNumber(intrNumber_)
{
}
virtual ~IntrHandler() {}
virtual bool run(PendingInterrupt& pend);
virtual void copyArgsToCPU(PendingInterrupt& pend);
virtual void handleResult(PendingInterrupt& pend);
void queueUp(int subintr);
SubIntrHandler* add(int subIntrNum);
void remove(int subIntrNum);
bool has(int subIntrNum) const;
void enable(int subIntrNum);
void disable(int subIntrNum);
SubIntrHandler *get(int subIntrNum);
void clear();
void DoState(PointerWrap &p);
private:
int intrNumber;
std::map<int, SubIntrHandler> subIntrHandlers;
};
bool __InterruptsEnabled();
bool __IsInInterrupt();
void __InterruptsInit();
void __InterruptsDoState(PointerWrap &p);
void __InterruptsDoStateLate(PointerWrap &p);
void __InterruptsShutdown();
void __TriggerInterrupt(int type, PSPInterrupt intno, int subInterrupts = -1);
bool __RunOnePendingInterrupt();
void __KernelReturnFromInterrupt();
void __RegisterIntrHandler(u32 intrNumber, IntrHandler* handler);
SubIntrHandler *__RegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handler, u32 handlerArg, u32 &error);
int __ReleaseSubIntrHandler(int intrNumber, int subIntrNumber);
u32 sceKernelRegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handler, u32 handlerArg);
u32 sceKernelReleaseSubIntrHandler(u32 intrNumber, u32 subIntrNumber);
u32 sceKernelEnableSubIntr(u32 intrNumber, u32 subIntrNumber);
void Register_Kernel_Library();
void Register_InterruptManager();
void Register_SysclibForKernel();