PS2SDK
PS2 Homebrew Libraries
rpc_server.c
1 #include <kernel.h>
2 #include <malloc.h>
3 #include <sifcmd.h>
4 #include <sifrpc.h>
5 #include <stdio.h>
6 #include <errno.h>
7 #include <string.h>
8 #include <netman.h>
9 #include <netman_rpc.h>
10 
11 #include "internal.h"
12 #include "rpc_server.h"
13 
14 static int NETMAN_RpcSvr_threadID, NETMAN_Rx_threadID, SifHandlerID;
15 static unsigned char NETMAN_RpcSvr_ThreadStack[0x1000] ALIGNED(16);
16 static unsigned char NETMAN_Rx_ThreadStack[0x1000] ALIGNED(16);
17 static unsigned char IsInitialized=0, IsProcessingRx;
18 
19 static struct NetManBD *FrameBufferStatus = NULL;
20 static struct NetManBD *RxIOPFrameBufferStatus;
21 static unsigned short int RxBufferRdPtr, RxBufferNextRdPtr;
22 extern void *_gp;
23 
24 static void NETMAN_RxThread(void *arg);
25 
26 static void ClearBufferLen(int index, void *packet, void *payload)
27 {
28  struct NetManBD *bd;
29  SifDmaTransfer_t dmat;
30 
31  bd = UNCACHED_SEG(&FrameBufferStatus[index]);
32  bd->length = 0;
33  bd->packet = packet;
34  bd->payload = payload;
35 
36  //Transfer to IOP RAM
37  dmat.src = (void*)&FrameBufferStatus[index];
38  dmat.dest = &RxIOPFrameBufferStatus[index];
39  dmat.size = sizeof(struct NetManBD);
40  dmat.attr = 0;
41  while(sceSifSetDma(&dmat, 1) == 0){ };
42 }
43 
44 static s32 HandleRxEvent(s32 channel)
45 {
46  struct NetManBD *bd;
47 
48  (void)channel;
49 
50  bd = UNCACHED_SEG(&FrameBufferStatus[RxBufferNextRdPtr]);
51  if(bd->length > 0)
52  {
53  isceSifSetDChain();
54 
55  if(!IsProcessingRx)
56  {
57  IsProcessingRx = 1;
58  iWakeupThread(NETMAN_Rx_threadID);
59  }
60  }
61 
62  ExitHandler();
63  //Must allow the other SIF handlers to check their states, as it is possible for this handler to block other handlers until FrameBufferStatus is cleared.
64  return 0;
65 }
66 
67 int NetManRPCAllocRxBuffers(void)
68 {
69  int i;
70 
71  for(i = 0; i < NETMAN_RPC_BLOCK_SIZE; i++)
72  {
73  void *packet, *payload;
74 
75  if((packet = NetManNetProtStackAllocRxPacket(NETMAN_NETIF_FRAME_SIZE, &payload)) != NULL)
76  {
77  ClearBufferLen(i, packet, payload);
78  } else {
79  printf("NETMAN: error - unable to allocate Rx FIFO buffers.\n");
80  return -ENOMEM;
81  }
82  }
83 
84  return 0;
85 }
86 
87 /* Main EE RPC thread. */
88 static void *NETMAN_EE_RPC_Handler(int fnum, void *buffer, int NumBytes)
89 {
91  void *result;
92 
93  (void)NumBytes;
94 
95  switch(fnum)
96  {
97  case NETMAN_EE_RPC_FUNC_INIT:
98  RxIOPFrameBufferStatus = *(void**)buffer;
99 
100  //Maintain 64-byte alignment to avoid non-uncached writes to the same cache line from contaminating the line.
101  if(FrameBufferStatus == NULL) FrameBufferStatus = memalign(64, sizeof(struct NetManBD) * NETMAN_RPC_BLOCK_SIZE);
102 
103  if(FrameBufferStatus != NULL)
104  {
105  memset(UNCACHED_SEG(FrameBufferStatus), 0, sizeof(struct NetManBD) * NETMAN_RPC_BLOCK_SIZE);
106  RxBufferRdPtr = 0;
107  RxBufferNextRdPtr = 0;
108  IsProcessingRx = 0;
109 
110  thread.func=&NETMAN_RxThread;
111  thread.stack=NETMAN_Rx_ThreadStack;
112  thread.stack_size=sizeof(NETMAN_Rx_ThreadStack);
113  thread.gp_reg=&_gp;
114  thread.initial_priority=0x59; /* Should be given a lower priority than the protocol stack, so that the protocol stack can process incoming frames. */
115  thread.attr=thread.option=0;
116 
117  if((NETMAN_Rx_threadID=CreateThread(&thread)) > 0)
118  {
119  StartThread(NETMAN_Rx_threadID, NULL);
120 
121  SifHandlerID = AddDmacHandler(DMAC_SIF0, &HandleRxEvent, 0);
122  EnableDmac(DMAC_SIF0);
123  ((struct NetManEEInitResult *)buffer)->result = 0;
124  ((struct NetManEEInitResult *)buffer)->FrameBufferStatus = FrameBufferStatus;
125  }
126  else{
127  ((struct NetManEEInitResult *)buffer)->result = NETMAN_Rx_threadID;
128  }
129  }else{
130  ((struct NetManEEInitResult *)buffer)->result = -ENOMEM;
131  }
132  result=buffer;
133  break;
134  case NETMAN_EE_RPC_FUNC_DEINIT:
135  if(FrameBufferStatus != NULL)
136  {
137  free(FrameBufferStatus);
138  FrameBufferStatus = NULL;
139  }
140  result=NULL;
141  break;
142  case NETMAN_EE_RPC_FUNC_HANDLE_LINK_STATUS_CHANGE:
143  NetManToggleGlobalNetIFLinkState(*(u32*)buffer);
144  result=NULL;
145  break;
146  default:
147  printf("NETMAN [EE]: Unrecognized command: 0x%x\n", fnum);
148  *(int *)buffer=EINVAL;
149  result=buffer;
150  }
151 
152  return result;
153 }
154 
155 static struct t_SifRpcDataQueue cb_queue;
156 static struct t_SifRpcServerData cb_srv;
157 
158 static void NETMAN_RPC_Thread(void *arg)
159 {
160  static unsigned char cb_rpc_buffer[64] __attribute__((__aligned__(64)));
161 
162  (void)arg;
163 
164  sceSifSetRpcQueue(&cb_queue, NETMAN_RpcSvr_threadID);
165  sceSifRegisterRpc(&cb_srv, NETMAN_RPC_NUMBER, &NETMAN_EE_RPC_Handler, cb_rpc_buffer, NULL, NULL, &cb_queue);
166  sceSifRpcLoop(&cb_queue);
167 }
168 
169 static void NETMAN_RxThread(void *arg)
170 {
171  volatile struct NetManBD *bd;
172  u32 PacketLength, PacketLengthAligned;
173  u8 run;
174 
175  (void)arg;
176 
177  while(1)
178  {
179  void *payload, *payloadNext;
180  void *packet, *packetNext;
181 
182  bd = UNCACHED_SEG(&FrameBufferStatus[RxBufferRdPtr]);
183 
184  do {
185  DI();
186  PacketLength = bd->length;
187  if (PacketLength > 0)
188  {
189  run = 1;
190  } else {
191  run = 0;
192  IsProcessingRx = 0;
193  }
194  EI();
195 
196  if(!run)
197  SleepThread();
198  } while(!run);
199 
200  payload = bd->payload;
201  packet = bd->packet;
202 
203  //Must successfully allocate a replacement buffer for the input buffer.
204  while((packetNext = NetManNetProtStackAllocRxPacket(NETMAN_NETIF_FRAME_SIZE, &payloadNext)) == NULL){};
205  RxBufferNextRdPtr = (RxBufferNextRdPtr + 1) % NETMAN_RPC_BLOCK_SIZE;
206  ClearBufferLen(RxBufferRdPtr, packetNext, payloadNext);
207 
208  //Increment read pointer by one place.
209  RxBufferRdPtr = RxBufferNextRdPtr;
210 
211  //Now process the received packet.
212  PacketLengthAligned = (PacketLength + 63) & ~63;
213  sceSifWriteBackDCache(payload, PacketLengthAligned);
214  NetManNetProtStackReallocRxPacket(packet, PacketLength);
215  NetManNetProtStackEnQRxPacket(packet);
216  }
217 }
218 
219 int NetManInitRPCServer(void)
220 {
221  int result;
222  ee_thread_t ThreadData;
223 
224  if(!IsInitialized)
225  {
226  ThreadData.func=&NETMAN_RPC_Thread;
227  ThreadData.stack=NETMAN_RpcSvr_ThreadStack;
228  ThreadData.stack_size=sizeof(NETMAN_RpcSvr_ThreadStack);
229  ThreadData.gp_reg=&_gp;
230  ThreadData.initial_priority=0x57; /* The RPC server thread should be given a higher priority than the protocol stack, so that it can issue commants to the EE and return. */
231  ThreadData.attr=ThreadData.option=0;
232 
233  if((NETMAN_RpcSvr_threadID=CreateThread(&ThreadData))>0)
234  {
235  StartThread(NETMAN_RpcSvr_threadID, NULL);
236  IsInitialized=1;
237  result=0;
238  }
239  else result=NETMAN_RpcSvr_threadID;
240  }
241  else result=0;
242 
243  return result;
244 }
245 
246 void NetManDeinitRPCServer(void)
247 {
248  if(IsInitialized)
249  {
250  sceSifRemoveRpc(&cb_srv, &cb_queue);
251  sceSifRemoveRpcQueue(&cb_queue);
252  RemoveDmacHandler(DMAC_SIF0, SifHandlerID);
253 
254  if(NETMAN_RpcSvr_threadID>0)
255  {
256  TerminateThread(NETMAN_RpcSvr_threadID);
257  DeleteThread(NETMAN_RpcSvr_threadID);
258  NETMAN_RpcSvr_threadID = 0;
259  }
260 
261  if(NETMAN_Rx_threadID>0)
262  {
263  TerminateThread(NETMAN_Rx_threadID);
264  DeleteThread(NETMAN_Rx_threadID);
265  NETMAN_Rx_threadID = 0;
266  }
267 
268  IsInitialized=0;
269  }
270 }
kernel.h
__attribute__
static int rpc_buffer[18000/4] __attribute__((__aligned__(4)))
ENOMEM
#define ENOMEM
Definition: errno.h:43
thread
Definition: thcommon.h:143
netman.h
_gp
void * _gp
netman_rpc.h
stdio.h
t_SifDmaTransfer
Definition: sifdma.h:52
t_SifRpcServerData
Definition: sifrpc-common.h:98
t_SifRpcDataQueue
Definition: sifrpc-common.h:153
NetManBD
Definition: netman_rpc.h:82
EINVAL
#define EINVAL
Definition: errno.h:63
t_ee_thread
Definition: kernel.h:203
NetManEEInitResult
Definition: netman_rpc.h:33
errno.h