Initial work on SIBios

This commit is contained in:
Phillip Stephens 2022-10-07 22:53:41 -07:00
parent 784b2857bd
commit b841756b36
8 changed files with 460 additions and 13 deletions

View File

@ -10,8 +10,6 @@
"editor.tabSize": 2,
"files.associations": {
"source_location": "cpp",
"dtk.h": "c",
"dvd.h": "c"
},
"files.autoSave": "onFocusChange",
"files.insertFinalNewline": true,

View File

@ -149,7 +149,8 @@ $(PAD_FILES): MWCC_VERSION := 1.2.5
$(PAD_FILES): CFLAGS := $(CFLAGS_BASE)
$(DTK_FILES): MWCC_VERSION := 1.2.5
$(DTK_FILES): CFLAGS := $(CFLAGS_BASE)
$(SI_FILES): MWCC_VERSION := 1.2.5
$(SI_FILES): CFLAGS := $(CFLAGS_BASE)
#-------------------------------------------------------------------------------
# Recipes
#-------------------------------------------------------------------------------

View File

@ -1781,9 +1781,6 @@ lbl_803BFE10:
/* 803BFE24 003BCD84 7C 03 00 00 */ cmpw r3, r0
/* 803BFE28 003BCD88 4D 82 00 20 */ beqlr
/* 803BFE2C 003BCD8C 48 00 00 08 */ b lbl_803BFE34
.global sub_803bfe30
sub_803bfe30:
/* 803BFE30 003BCD90 4E 80 00 20 */ blr
lbl_803BFE34:
/* 803BFE34 003BCD94 38 60 00 40 */ li r3, 0x40
@ -1804,9 +1801,6 @@ lbl_803BFE50:
/* 803BFE68 003BCDC8 7C 03 00 00 */ cmpw r3, r0
/* 803BFE6C 003BCDCC 4D 82 00 20 */ beqlr
/* 803BFE70 003BCDD0 48 00 00 08 */ b lbl_803BFE78
.global sub_803bfe74
sub_803bfe74:
/* 803BFE74 003BCDD4 4E 80 00 20 */ blr
lbl_803BFE78:
/* 803BFE78 003BCDD8 54 A3 00 14 */ rlwinm r3, r5, 0, 0, 0xa

View File

@ -136,7 +136,9 @@ void OSFatal(GXColor fg, GXColor bg, const char* msg);
#include <dolphin/os/OSCache.h>
#include <dolphin/os/OSContext.h>
#include <dolphin/os/OSError.h>
#include <dolphin/os/OSException.h>
#include <dolphin/os/OSFont.h>
#include <dolphin/os/OSInterrupt.h>
#include <dolphin/os/OSReset.h>
#include <dolphin/os/OSSerial.h>
#include <dolphin/os/OSThread.h>

View File

@ -0,0 +1,18 @@
#ifndef __OSEXCEPTION_H__
#define __OSEXCEPTION_H__
#include <dolphin/os/OSContext.h>
#include <dolphin/types.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef u8 __OSException;
typedef void (*__OSExceptionHandler)(__OSException exception, OSContext* context);
#ifdef __cplusplus
}
#endif
#endif // __OSEXCEPTION_H__

View File

@ -0,0 +1,116 @@
#ifndef __OSINTERRUPT_H__
#define __OSINTERRUPT_H__
#include <dolphin/os/OSContext.h>
#include <dolphin/types.h>
#ifdef __cplusplus
extern "C" {
#endif
#define __OS_INTERRUPT_MEM_0 0
#define __OS_INTERRUPT_MEM_1 1
#define __OS_INTERRUPT_MEM_2 2
#define __OS_INTERRUPT_MEM_3 3
#define __OS_INTERRUPT_MEM_ADDRESS 4
#define __OS_INTERRUPT_DSP_AI 5
#define __OS_INTERRUPT_DSP_ARAM 6
#define __OS_INTERRUPT_DSP_DSP 7
#define __OS_INTERRUPT_AI_AI 8
#define __OS_INTERRUPT_EXI_0_EXI 9
#define __OS_INTERRUPT_EXI_0_TC 10
#define __OS_INTERRUPT_EXI_0_EXT 11
#define __OS_INTERRUPT_EXI_1_EXI 12
#define __OS_INTERRUPT_EXI_1_TC 13
#define __OS_INTERRUPT_EXI_1_EXT 14
#define __OS_INTERRUPT_EXI_2_EXI 15
#define __OS_INTERRUPT_EXI_2_TC 16
#define __OS_INTERRUPT_PI_CP 17
#define __OS_INTERRUPT_PI_PE_TOKEN 18
#define __OS_INTERRUPT_PI_PE_FINISH 19
#define __OS_INTERRUPT_PI_SI 20
#define __OS_INTERRUPT_PI_DI 21
#define __OS_INTERRUPT_PI_RSW 22
#define __OS_INTERRUPT_PI_ERROR 23
#define __OS_INTERRUPT_PI_VI 24
#define __OS_INTERRUPT_PI_DEBUG 25
#define __OS_INTERRUPT_PI_HSP 26
#define __OS_INTERRUPT_MAX 32
#define OS_INTERRUPTMASK(interrupt) (0x80000000u >> (interrupt))
#define OS_INTERRUPTMASK_MEM_0 OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_0)
#define OS_INTERRUPTMASK_MEM_1 OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_1)
#define OS_INTERRUPTMASK_MEM_2 OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_2)
#define OS_INTERRUPTMASK_MEM_3 OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_3)
#define OS_INTERRUPTMASK_MEM_ADDRESS OS_INTERRUPTMASK(__OS_INTERRUPT_MEM_ADDRESS)
#define OS_INTERRUPTMASK_MEM \
(OS_INTERRUPTMASK_MEM_0 | OS_INTERRUPTMASK_MEM_1 | OS_INTERRUPTMASK_MEM_2 | \
OS_INTERRUPTMASK_MEM_3 | OS_INTERRUPTMASK_MEM_ADDRESS)
#define OS_INTERRUPTMASK_DSP_AI OS_INTERRUPTMASK(__OS_INTERRUPT_DSP_AI)
#define OS_INTERRUPTMASK_DSP_ARAM OS_INTERRUPTMASK(__OS_INTERRUPT_DSP_ARAM)
#define OS_INTERRUPTMASK_DSP_DSP OS_INTERRUPTMASK(__OS_INTERRUPT_DSP_DSP)
#define OS_INTERRUPTMASK_DSP \
(OS_INTERRUPTMASK_DSP_AI | OS_INTERRUPTMASK_DSP_ARAM | OS_INTERRUPTMASK_DSP_DSP)
#define OS_INTERRUPTMASK_AI_AI OS_INTERRUPTMASK(__OS_INTERRUPT_AI_AI)
#define OS_INTERRUPTMASK_AI (OS_INTERRUPTMASK_AI_AI)
#define OS_INTERRUPTMASK_EXI_0_EXI OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_0_EXI)
#define OS_INTERRUPTMASK_EXI_0_TC OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_0_TC)
#define OS_INTERRUPTMASK_EXI_0_EXT OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_0_EXT)
#define OS_INTERRUPTMASK_EXI_0 \
(OS_INTERRUPTMASK_EXI_0_EXI | OS_INTERRUPTMASK_EXI_0_TC | OS_INTERRUPTMASK_EXI_0_EXT)
#define OS_INTERRUPTMASK_EXI_1_EXI OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_1_EXI)
#define OS_INTERRUPTMASK_EXI_1_TC OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_1_TC)
#define OS_INTERRUPTMASK_EXI_1_EXT OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_1_EXT)
#define OS_INTERRUPTMASK_EXI_1 \
(OS_INTERRUPTMASK_EXI_1_EXI | OS_INTERRUPTMASK_EXI_1_TC | OS_INTERRUPTMASK_EXI_1_EXT)
#define OS_INTERRUPTMASK_EXI_2_EXI OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_2_EXI)
#define OS_INTERRUPTMASK_EXI_2_TC OS_INTERRUPTMASK(__OS_INTERRUPT_EXI_2_TC)
#define OS_INTERRUPTMASK_EXI_2 (OS_INTERRUPTMASK_EXI_2_EXI | OS_INTERRUPTMASK_EXI_2_TC)
#define OS_INTERRUPTMASK_EXI \
(OS_INTERRUPTMASK_EXI_0_EXI | OS_INTERRUPTMASK_EXI_0_TC | OS_INTERRUPTMASK_EXI_0_EXT | \
OS_INTERRUPTMASK_EXI_1_EXI | OS_INTERRUPTMASK_EXI_1_TC | OS_INTERRUPTMASK_EXI_1_EXT | \
OS_INTERRUPTMASK_EXI_2_EXI | OS_INTERRUPTMASK_EXI_2_TC)
#define OS_INTERRUPTMASK_PI_PE_TOKEN OS_INTERRUPTMASK(__OS_INTERRUPT_PI_PE_TOKEN)
#define OS_INTERRUPTMASK_PI_PE_FINISH OS_INTERRUPTMASK(__OS_INTERRUPT_PI_PE_FINISH)
#define OS_INTERRUPTMASK_PI_PE (OS_INTERRUPTMASK_PI_PE_TOKEN | OS_INTERRUPTMASK_PI_PE_FINISH)
#define OS_INTERRUPTMASK_PI_CP OS_INTERRUPTMASK(__OS_INTERRUPT_PI_CP)
#define OS_INTERRUPTMASK_PI_SI OS_INTERRUPTMASK(__OS_INTERRUPT_PI_SI)
#define OS_INTERRUPTMASK_PI_DI OS_INTERRUPTMASK(__OS_INTERRUPT_PI_DI)
#define OS_INTERRUPTMASK_PI_RSW OS_INTERRUPTMASK(__OS_INTERRUPT_PI_RSW)
#define OS_INTERRUPTMASK_PI_ERROR OS_INTERRUPTMASK(__OS_INTERRUPT_PI_ERROR)
#define OS_INTERRUPTMASK_PI_VI OS_INTERRUPTMASK(__OS_INTERRUPT_PI_VI)
#define OS_INTERRUPTMASK_PI_DEBUG OS_INTERRUPTMASK(__OS_INTERRUPT_PI_DEBUG)
#define OS_INTERRUPTMASK_PI_HSP OS_INTERRUPTMASK(__OS_INTERRUPT_PI_HSP)
#define OS_INTERRUPTMASK_PI \
(OS_INTERRUPTMASK_PI_CP | OS_INTERRUPTMASK_PI_SI | OS_INTERRUPTMASK_PI_DI | \
OS_INTERRUPTMASK_PI_RSW | OS_INTERRUPTMASK_PI_ERROR | OS_INTERRUPTMASK_PI_VI | \
OS_INTERRUPTMASK_PI_PE_TOKEN | OS_INTERRUPTMASK_PI_PE_FINISH | OS_INTERRUPTMASK_PI_DEBUG | \
OS_INTERRUPTMASK_PI_HSP)
typedef s16 __OSInterrupt;
typedef void (*__OSInterruptHandler)(__OSInterrupt interrupt, OSContext* context);
typedef u32 OSInterruptMask;
extern volatile __OSInterrupt __OSLastInterrupt;
extern volatile u32 __OSLastInterruptSrr0;
extern volatile OSTime __OSLastInterruptTime;
__OSInterruptHandler __OSSetInterruptHandler(__OSInterrupt interrupt, __OSInterruptHandler handler);
__OSInterruptHandler __OSGetInterruptHandler(__OSInterrupt interrupt);
void __OSDispatchInterrupt(__OSException exception, OSContext* context);
OSInterruptMask OSGetInterruptMask(void);
OSInterruptMask OSSetInterruptMask(OSInterruptMask mask);
OSInterruptMask __OSMaskInterrupts(OSInterruptMask mask);
OSInterruptMask __OSUnmaskInterrupts(OSInterruptMask mask);
#ifdef __cplusplus
}
#endif
#endif // __OSINTERRUPT_H__

View File

@ -9,12 +9,41 @@ extern "C" {
typedef void (*SICallback)(s32 chan, u32 sr, OSContext* context);
typedef void (*SITypeAndStatusCallback)(s32 chan, u32 type);
BOOL SIGetResponse(s32 chan, void* data);
void SISetCommand(s32 chan, u32 cmd);
typedef struct SIPacket {
s32 chan;
void* output;
u32 outputBytes;
void* input;
u32 inputBytes;
SICallback callback;
OSTime fire;
} SIPacket;
void SIInit(void);
u32 SIGetStatus(s32 chan);
BOOL SIBusy(void);
BOOL SIIsChanBusy(s32 chan);
BOOL SITransfer(s32 chan, void* output, u32 outputBytes, void* input, u32 inputBytes,
SICallback callback, OSTime delay);
void SIEnablePolling(s32 bits);
void SIDisablePolling(s32 bits);
u32 SISync(void);
void SISetCommand(s32 chan, u32 command);
u32 SIGetCommand(s32 chan);
void SITransferCommands(void);
u32 SISetXY(u32 x, u32 y);
u32 SIEnablePolling(u32 poll);
u32 SIDisablePolling(u32 poll);
BOOL SIGetResponse(s32 chan, void* data);
BOOL SIRegisterPollingHandler(__OSInterruptHandler handler);
BOOL SIUnregisterPollingHandler(__OSInterruptHandler handler);
u32 SIGetType(s32 chan);
u32 SIGetTypeAsync(s32 chan, SITypeAndStatusCallback callback);
u32 SIDecodeType(u32 type);
#ifdef __cplusplus
}

289
src/Dolphin/si/SIBios.c Normal file
View File

@ -0,0 +1,289 @@
#include <dolphin/os.h>
#include <dolphin/sipriv.h>
vu32 __SIRegs[64] : 0xCC006400;
extern OSTime __OSGetSystemTime();
const char* __SIVersion = "<< Dolphin SDK - SI\trelease build: Sep 5 2002 05:33:08 (0x2301) >>";
typedef struct SIControl {
s32 chan;
u32 poll;
u32 inputBytes;
void* input;
SICallback callback;
} SIControl;
static SIControl Si = {
-1,
};
static SIPacket Packet[SI_MAX_CHAN];
static OSAlarm Alarm[SI_MAX_CHAN];
static u32 Type[SI_MAX_CHAN] = {
SI_ERROR_NO_RESPONSE,
SI_ERROR_NO_RESPONSE,
SI_ERROR_NO_RESPONSE,
SI_ERROR_NO_RESPONSE,
};
static OSTime TypeTime[SI_MAX_CHAN];
static OSTime XferTime[SI_MAX_CHAN];
static SITypeAndStatusCallback TypeCallback[SI_MAX_CHAN][4];
static __OSInterruptHandler RDSTHandler[4];
u32 __PADFixBits;
static BOOL __SITransfer(s32 chan, void* output, u32 outputBytes, void* input, u32 inputBytes,
SICallback callback);
static BOOL InputBufferValid[SI_MAX_CHAN];
static u32 InputBuffer[SI_MAX_CHAN][2];
static vu32 InputBufferVcount[SI_MAX_CHAN];
static BOOL SIGetResponseRaw(s32 chan);
static void GetTypeCallback(s32 chan, u32 error, OSContext* context);
BOOL SIBusy() { return Si.chan != -1 ? TRUE : FALSE; }
BOOL SIIsChanBusy(s32 chan) { return (Packet[chan].chan != -1 || Si.chan == chan); }
static void SIClearTCInterrupt() {
u32 reg;
reg = __SIRegs[13];
reg |= 0x80000000;
reg &= ~0x00000001;
__SIRegs[13] = reg;
}
static u32 CompleteTransfer() {
u32 sr;
u32 i;
u32 rLen;
u8* input;
sr = __SIRegs[14];
SIClearTCInterrupt();
if (Si.chan != -1) {
XferTime[Si.chan] = __OSGetSystemTime();
input = Si.input;
rLen = Si.inputBytes / 4;
for (i = 0; i < rLen; i++) {
*(u32*)input = __SIRegs[32 + i];
input += 4;
}
rLen = Si.inputBytes & 3;
if (rLen) {
u32 temp = __SIRegs[32 + i];
for (i = 0; i < rLen; i++) {
*input++ = (u8)((temp >> ((3 - i) * 8)) & 0xff);
}
}
if (__SIRegs[13] & 0x20000000) {
sr >>= 8 * (3 - Si.chan);
sr &= 0xf;
if ((sr & SI_ERROR_NO_RESPONSE) && !(Type[Si.chan] & SI_ERROR_BUSY)) {
Type[Si.chan] = SI_ERROR_NO_RESPONSE;
}
if (sr == 0) {
sr = SI_ERROR_COLLISION;
}
} else {
TypeTime[Si.chan] = __OSGetSystemTime();
sr = 0;
}
Si.chan = -1;
}
return sr;
}
static void SITransferNext(s32 chan) {
int i;
SIPacket* packet;
for (i = 0; i < SI_MAX_CHAN; ++i) {
++chan;
chan %= SI_MAX_CHAN;
packet = &Packet[chan];
if (packet->chan != -1 && packet->fire <= __OSGetSystemTime()) {
if (__SITransfer(packet->chan, packet->output, packet->outputBytes, packet->input,
packet->inputBytes, packet->callback)) {
OSCancelAlarm(&Alarm[chan]);
packet->chan = -1;
}
break;
}
}
}
static void SIInterruptHandler(__OSInterrupt interrupt, OSContext* context) {
u32 reg;
reg = __SIRegs[13];
if ((reg & 0xc0000000) == 0xc0000000) {
s32 chan;
u32 sr;
SICallback callback;
chan = Si.chan;
sr = CompleteTransfer();
callback = Si.callback;
Si.callback = 0;
SITransferNext(chan);
if (callback) {
callback(chan, sr, context);
}
sr = __SIRegs[14];
sr &= 0xf000000 >> (8 * chan);
__SIRegs[14] = sr;
if (Type[chan] == SI_ERROR_BUSY && !SIIsChanBusy(chan)) {
static u32 cmdTypeAndStatus = 0 << 24;
SITransfer(chan, &cmdTypeAndStatus, 1, &Type[chan], 3, GetTypeCallback,
OSMicrosecondsToTicks(65));
}
}
if ((reg & 0x18000000) == 0x18000000) {
int i;
u32 vcount;
u32 x;
vcount = VIGetCurrentLine() + 1;
x = (Si.poll & 0x03ff0000) >> 16;
for (i = 0; i < SI_MAX_CHAN; ++i) {
if (SIGetResponseRaw(i)) {
InputBufferVcount[i] = vcount;
}
}
for (i = 0; i < SI_MAX_CHAN; ++i) {
if (!(Si.poll & (SI_CHAN0_BIT >> (31 - 7 + i)))) {
continue;
}
if (InputBufferVcount[i] == 0 || InputBufferVcount[i] + (x / 2) < vcount) {
return;
}
}
for (i = 0; i < SI_MAX_CHAN; ++i) {
InputBufferVcount[i] = 0;
}
for (i = 0; i < 4; ++i) {
if (RDSTHandler[i]) {
RDSTHandler[i](interrupt, context);
}
}
}
}
static BOOL SIEnablePollingInterrupt(BOOL enable) {
BOOL enabled;
BOOL rc;
u32 reg;
int i;
enabled = OSDisableInterrupts();
reg = __SIRegs[13];
rc = (reg & 0x08000000) ? TRUE : FALSE;
if (enable) {
reg |= 0x08000000;
for (i = 0; i < SI_MAX_CHAN; ++i) {
InputBufferVcount[i] = 0;
}
} else {
reg &= ~0x08000000;
}
reg &= ~0x80000001;
__SIRegs[13] = reg;
OSRestoreInterrupts(enabled);
return rc;
}
BOOL SIRegisterPollingHandler(__OSInterruptHandler handler) {
BOOL enabled;
int i;
enabled = OSDisableInterrupts();
for (i = 0; i < 4; ++i) {
if (RDSTHandler[i] == handler) {
OSRestoreInterrupts(enabled);
return TRUE;
}
}
for (i = 0; i < 4; ++i) {
if (RDSTHandler[i] == 0) {
RDSTHandler[i] = handler;
SIEnablePollingInterrupt(TRUE);
OSRestoreInterrupts(enabled);
return TRUE;
}
}
OSRestoreInterrupts(enabled);
return FALSE;
}
BOOL SIUnregisterPollingHandler(__OSInterruptHandler handler) {
BOOL enabled;
int i;
enabled = OSDisableInterrupts();
for (i = 0; i < 4; ++i) {
if (RDSTHandler[i] == handler) {
RDSTHandler[i] = 0;
for (i = 0; i < 4; ++i) {
if (RDSTHandler[i]) {
break;
}
}
if (i == 4) {
SIEnablePollingInterrupt(FALSE);
}
OSRestoreInterrupts(enabled);
return TRUE;
break;
}
}
OSRestoreInterrupts(enabled);
return FALSE;
}
void SIInit(void) {
OSRegisterVersion(__SIVersion);
Packet[0].chan = Packet[1].chan = Packet[2].chan = Packet[3].chan = -1;
Si.poll = 0;
SISetSamplingRate(0);
while (__SIRegs[13] & 1)
;
__SIRegs[13] = 0x80000000;
__OSSetInterruptHandler(__OS_INTERRUPT_PI_SI, SIInterruptHandler);
__OSUnmaskInterrupts(OS_INTERRUPTMASK_PI_SI);
SIGetType(0);
SIGetType(1);
SIGetType(2);
SIGetType(3);
}