1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
#include <dolphin/dolphin.h>
#include <dolphin/si.h>
#include "__os.h"
static void __SISteeringHandler(s32 chan, u32 error, OSContext* context) {
SISteeringControl* sc;
void (*proc)(s32);
SISteeringCallback callback;
OSContext exceptionContext;
sc = &__SISteering[chan];
if (!__SIResetSteering) {
if (error & 8) {
sc->ret = -1;
} else if (error & 7) {
sc->ret = -3;
} else {
sc->ret = 0;
}
if (sc->proc != 0) {
proc = sc->proc;
sc->proc = NULL;
proc(chan);
}
if (sc->callback != 0) {
OSClearContext(&exceptionContext);
OSSetCurrentContext(&exceptionContext);
callback = sc->callback;
sc->callback = NULL;
callback(chan, sc->ret);
OSClearContext(&exceptionContext);
OSSetCurrentContext(context);
}
}
}
void __SISteeringSyncCallback(s32 chan) {
SISteeringControl* sc;
sc = &__SISteering[chan];
OSWakeupThread(&sc->threadQueue);
}
s32 __SISteeringSync(s32 chan) {
SISteeringControl* sc;
s32 ret;
BOOL enabled;
sc = &__SISteering[chan];
enabled = OSDisableInterrupts();
while (sc->callback != 0) {
OSSleepThread(&sc->threadQueue);
}
ret = sc->ret;
OSRestoreInterrupts(enabled);
return ret;
}
static void TypeAndStatusCallback(s32 chan, u32 type) {
SISteeringControl* sc;
void (*proc)(s32);
SISteeringCallback callback;
OSContext exceptionContext;
OSContext* context;
sc = &__SISteering[chan];
if (!__SIResetSteering) {
ASSERTLINE(127, !(type & SI_ERROR_BUSY));
if ((u32)((type & 0xFFFF0000) + 0xF8000000) == 0) {
if (SITransfer(chan, sc, sc->outputBytes, sc->input, sc->inputBytes, __SISteeringHandler, 0)) {
return;
}
sc->ret = -2;
} else {
sc->ret = -1;
}
if (sc->proc != 0) {
proc = sc->proc;
sc->proc = NULL;
proc(chan);
}
if (sc->callback != 0) {
context = OSGetCurrentContext();
OSClearContext(&exceptionContext);
OSSetCurrentContext(&exceptionContext);
callback = sc->callback;
sc->callback = NULL;
callback(chan, sc->ret);
OSClearContext(&exceptionContext);
OSSetCurrentContext(context);
__OSReschedule();
}
}
}
s32 __SISteeringTransfer(s32 chan, u32 outputBytes, u32 inputBytes, void (*proc)(s32)) {
BOOL enabled;
SISteeringControl* sc;
sc = &__SISteering[chan];
enabled = OSDisableInterrupts();
sc->proc = proc;
sc->outputBytes = outputBytes;
sc->inputBytes = inputBytes;
SIGetTypeAsync(chan, &TypeAndStatusCallback);
OSRestoreInterrupts(enabled);
return 0;
}
|