PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
rpc_server.c
1#include <errno.h>
2#include <stdio.h>
3#include <sysclib.h>
4#include <sifcmd.h>
5#include <sifman.h>
6#include <loadcore.h>
7#include <thbase.h>
8#include <thevent.h>
9#include <thsemap.h>
10#include <intrman.h>
11#include <netman.h>
12#include <netman_rpc.h>
13
14#include "internal.h"
15#include "rpc_server.h"
16#include "rpc_client.h"
17
18/* Data used for registering the RPC server. */
19static SifRpcServerData_t rpc_sdata;
20static unsigned char rpc_buffer[80] __attribute__((__aligned__(4)));
21static SifRpcDataQueue_t rpc_qdata;
22
23static union{
24 s32 result;
25 struct NetManIoctlResult IoctlResult;
26 struct NetManQueryMainNetIFResult QueryMainNetIFResult;
27 struct NetManRegNetworkStackResult RegNetworkStackResult;
28 u8 buffer[80];
29} SifRpcTxBuffer;
30
31/* Packet transmission buffer. The EE will DMA transfer the packet to be transmitted directly into this buffer before invoking FUNC_SEND_PACKET. */
32static u8 *TxFrameBuffer = NULL;
33static struct NetManBD *FrameBufferStatus = NULL;
34static struct NetManBD *EEFrameBufferStatus = NULL;
35static unsigned short int IOPFrameBufferRdPtr;
36
37static int RpcThreadID = -1;
38static unsigned char IsInitialized=0, IsRpcStackInitialized=0;
39
40static void ClearBufferLen(int index);
41
42static void LinkStateUp(void)
43{
44 NetManRpcToggleGlobalNetIFLinkState(1);
45}
46
47static void LinkStateDown(void)
48{
49 NetManRpcToggleGlobalNetIFLinkState(0);
50}
51
52static void *AllocRxPacket(unsigned int length, void **payload)
53{
54 return NetManRpcNetProtStackAllocRxPacket(length, payload);
55}
56
57static void FreeRxPacket(void *packet)
58{
59 NetManRpcNetProtStackFreeRxPacket(packet);
60}
61
62static void EnQRxPacket(void *packet)
63{
64 NetManRpcProtStackEnQRxPacket(packet);
65}
66
67static int NextTxPacket(void **payload)
68{
69 *payload = &TxFrameBuffer[IOPFrameBufferRdPtr * NETMAN_MAX_FRAME_SIZE + FrameBufferStatus[IOPFrameBufferRdPtr].offset];
70 return FrameBufferStatus[IOPFrameBufferRdPtr].length;
71}
72
73static void DeQTxPacket(void)
74{
75 ClearBufferLen(IOPFrameBufferRdPtr);
76
77 //Increment read pointer by one place.
78 IOPFrameBufferRdPtr = (IOPFrameBufferRdPtr + 1) % NETMAN_RPC_BLOCK_SIZE;
79}
80
81static struct NetManNetProtStack RpcStack={
82 &LinkStateUp,
83 &LinkStateDown,
84 &AllocRxPacket,
85 &FreeRxPacket,
86 &EnQRxPacket,
87 &NextTxPacket,
88 &DeQTxPacket,
89 NULL,
90 NULL,
91};
92
93static void unregisterEENetworkStack(void)
94{
95 if(IsRpcStackInitialized)
96 {
97 IsRpcStackInitialized=0;
98 NetManUnregisterNetworkStack();
99
100 if(TxFrameBuffer != NULL)
101 {
102 free(TxFrameBuffer);
103 TxFrameBuffer = NULL;
104 }
105 if(FrameBufferStatus != NULL)
106 {
107 free(FrameBufferStatus);
108 FrameBufferStatus = NULL;
109 }
110
111 EEFrameBufferStatus = NULL;
112 }
113
114 sceSifRemoveCmdHandler(NETMAN_SIFCMD_ID);
115}
116
117static void ClearBufferLen(int index)
118{
119 static struct NetManBD zero = { 0 };
120 SifDmaTransfer_t dmat;
121 int dmat_id, OldState;
122
123 FrameBufferStatus[index].length = 0;
124
125 //Transfer to EE RAM
126 dmat.src = (void*)&zero;
127 dmat.dest = &EEFrameBufferStatus[index];
128 dmat.size = sizeof(zero);
129 dmat.attr = 0;
130
131 do{
132 CpuSuspendIntr(&OldState);
133 dmat_id = sceSifSetDma(&dmat, 1);
134 CpuResumeIntr(OldState);
135 }while(dmat_id == 0);
136}
137
138static void HandleRxEvent(void *packet, void *common)
139{
140 struct NetManPktCmd *bd = (struct NetManPktCmd*)&((SifCmdHeader_t*)packet)->opt;
141 u8 id = bd->id;
142 u8 offset = bd->offset;
143 u16 len = bd->length;
144
145 (void)common;
146
147 FrameBufferStatus[id].length = len;
148 FrameBufferStatus[id].offset = offset;
149
150 NetManNetIFXmit();
151}
152
153static void *NETMAN_rpc_handler(int fno, void *buffer, int size)
154{
155 static int ResultValue;
156 void *result;
157
158 (void)size;
159
160 switch(fno)
161 {
162 case NETMAN_IOP_RPC_FUNC_INIT:
163 ResultValue=NetManInitRPCClient();
164 result=&ResultValue;
165 break;
166 case NETMAN_IOP_RPC_FUNC_DEINIT:
167 unregisterEENetworkStack();
168 NetManDeinitRPCClient();
169 result=NULL;
170 break;
171 case NETMAN_IOP_RPC_FUNC_REG_NETWORK_STACK:
172 result = &SifRpcTxBuffer;
173
174 if(TxFrameBuffer == NULL) TxFrameBuffer = malloc(NETMAN_MAX_FRAME_SIZE * NETMAN_RPC_BLOCK_SIZE);
175 if(FrameBufferStatus == NULL) FrameBufferStatus = malloc(sizeof(struct NetManBD) * NETMAN_RPC_BLOCK_SIZE);
176
177 if(TxFrameBuffer != NULL && FrameBufferStatus != NULL)
178 {
179 EEFrameBufferStatus = ((struct NetManRegNetworkStack*)buffer)->FrameBufferStatus;
180 memset(FrameBufferStatus, 0, sizeof(struct NetManBD) * NETMAN_RPC_BLOCK_SIZE);
181 memset(TxFrameBuffer, 0, NETMAN_MAX_FRAME_SIZE * NETMAN_RPC_BLOCK_SIZE);
182 SifRpcTxBuffer.RegNetworkStackResult.FrameBuffer = TxFrameBuffer;
183 IOPFrameBufferRdPtr = 0;
184 ResultValue = NetManRegisterNetworkStack(&RpcStack);
185
186 if(ResultValue == 0)
187 sceSifAddCmdHandler(NETMAN_SIFCMD_ID, &HandleRxEvent, NULL);
188 }else{
189 ResultValue = -ENOMEM;
190 }
191
192 IsRpcStackInitialized=1;
193 SifRpcTxBuffer.RegNetworkStackResult.result = ResultValue;
194 SifRpcTxBuffer.RegNetworkStackResult.FrameBufferStatus = FrameBufferStatus;
195 break;
196 case NETMAN_IOP_RPC_FUNC_UNREG_NETWORK_STACK:
197 unregisterEENetworkStack();
198 result=NULL;
199 break;
200 case NETMAN_IOP_RPC_FUNC_IOCTL:
201 SifRpcTxBuffer.IoctlResult.result=NetManIoctl(((struct NetManIoctl*)buffer)->command, ((struct NetManIoctl*)buffer)->args, ((struct NetManIoctl*)buffer)->args_len, SifRpcTxBuffer.IoctlResult.output, ((struct NetManIoctl*)buffer)->length);
202 result=&SifRpcTxBuffer;
203 break;
204 case NETMAN_IOP_RPC_FUNC_SET_MAIN_NETIF:
205 SifRpcTxBuffer.result=NetManSetMainIF(buffer);
206 result=&SifRpcTxBuffer;
207 break;
208 case NETMAN_IOP_RPC_FUNC_QUERY_MAIN_NETIF:
209 SifRpcTxBuffer.QueryMainNetIFResult.result=NetManQueryMainIF(SifRpcTxBuffer.QueryMainNetIFResult.name);
210 result=&SifRpcTxBuffer;
211 break;
212 case NETMAN_IOP_RPC_FUNC_SET_LINK_MODE:
213 ResultValue=NetManSetLinkMode(*(s32*)buffer);
214 result=&ResultValue;
215 break;
216 default:
217 printf("NETMAN [IOP]: Unrecognized command: 0x%x\n", fno);
218 ResultValue=-1;
219 result=&ResultValue;
220 }
221
222 return result;
223}
224
225static void NETMAN_RPC_srv(void *args)
226{
227 (void)args;
228
229 sceSifSetRpcQueue(&rpc_qdata, RpcThreadID);
230
231 sceSifRegisterRpc(&rpc_sdata, NETMAN_RPC_NUMBER, &NETMAN_rpc_handler, rpc_buffer, NULL, NULL, &rpc_qdata);
232 sceSifRpcLoop(&rpc_qdata);
233}
234
235int NetmanInitRPCServer(void)
236{
237 iop_thread_t ThreadData;
238
239 if(!IsInitialized)
240 {
241 ThreadData.attr=TH_C;
242 ThreadData.option=0;
243 ThreadData.thread=&NETMAN_RPC_srv;
244 ThreadData.stacksize=0x600;
245 ThreadData.priority=0x27; //Should have higher priority than the IF driver thread, in order to dump frames in the IOP before returning.
246
247 StartThread(RpcThreadID=CreateThread(&ThreadData), NULL);
248 IsInitialized=1;
249 }
250
251 return 0;
252}
253
254void NetmanDeinitRPCServer(void)
255{
256 if(IsInitialized)
257 {
258 sceSifRemoveRpc(&rpc_sdata, &rpc_qdata);
259 sceSifRemoveRpcQueue(&rpc_qdata);
260
261 TerminateThread(RpcThreadID);
262 DeleteThread(RpcThreadID);
263 IsInitialized=0;
264 }
265}
#define ENOMEM
Definition errno.h:43
int CpuResumeIntr(int state)
Definition intrman.c:227
int CpuSuspendIntr(int *state)
Definition intrman.c:205