PS2SDK
PS2 Homebrew Libraries
rpc_client.c
1 #include <errno.h>
2 #include <kernel.h>
3 #include <sifrpc.h>
4 #include <string.h>
5 #include <stdio.h>
6 #include <malloc.h>
7 #include <netman.h>
8 #include <netman_rpc.h>
9 #include <iopcontrol.h>
10 
11 #include "rpc_client.h"
12 
13 static SifRpcClientData_t NETMAN_rpc_cd;
14 extern void *_gp;
15 
16 static union {
17  s32 mode;
18  struct NetManIoctl IoctlArgs;
19  char netifName[NETMAN_NETIF_NAME_MAX_LEN];
20  struct NetManRegNetworkStack NetStack;
21  u8 buffer[128];
22 }TransmitBuffer ALIGNED(64);
23 
24 static union {
25  s32 result;
26  struct NetManRegNetworkStackResult NetStackResult;
27  struct NetManIoctlResult IoctlResult;
28  struct NetManQueryMainNetIFResult QueryMainNetIFResult;
29  u8 buffer[128];
30 }ReceiveBuffer ALIGNED(64);
31 
32 static int NetManIOSemaID, NETMAN_Tx_threadID;
33 static unsigned char NETMAN_Tx_ThreadStack[0x1000] ALIGNED(16);
34 
35 static unsigned short int IOPFrameBufferWrPtr;
36 static u8 *IOPFrameBuffer = NULL; /* On the IOP side. */
37 static struct NetManBD *IOPFrameBufferStatus = NULL;
38 static struct NetManBD *FrameBufferStatus = NULL;
39 
40 static unsigned char IsProcessingTx;
41 
42 static void deinitCleanup(void)
43 {
44  if(NetManIOSemaID > 0)
45  {
46  DeleteSema(NetManIOSemaID);
47  NetManIOSemaID = 0;
48  }
49  if(NETMAN_Tx_threadID > 0)
50  {
51  TerminateThread(NETMAN_Tx_threadID);
52  DeleteThread(NETMAN_Tx_threadID);
53  NETMAN_Tx_threadID = 0;
54  }
55  memset(&NETMAN_rpc_cd, 0, sizeof(NETMAN_rpc_cd));
56 }
57 
58 static void NETMAN_TxThread(void *arg);
59 
60 int NetManInitRPCClient(void){
61  static const char NetManID[]="NetMan";
62  int result;
63  ee_sema_t SemaData;
66  deinitCleanup();
67 
68  if(NETMAN_rpc_cd.server)
69  return 0;
70  SemaData.max_count=1;
71  SemaData.init_count=1;
72  SemaData.option=(u32)NetManID;
73  SemaData.attr=0;
74  if((NetManIOSemaID=CreateSema(&SemaData)) <= 0)
75  {
76  NetManIOSemaID = 0;
77  deinitCleanup();
78  return -1;
79  }
80 
81  thread.func=&NETMAN_TxThread;
82  thread.stack=NETMAN_Tx_ThreadStack;
83  thread.stack_size=sizeof(NETMAN_Tx_ThreadStack);
84  thread.gp_reg=&_gp;
85  thread.initial_priority=0x56; /* Should be given a higher priority than the protocol stack, so that it can dump frames in the EE and return. */
86  thread.attr=thread.option=0;
87 
88  if((NETMAN_Tx_threadID=CreateThread(&thread)) <= 0)
89  {
90  NETMAN_Tx_threadID = 0;
91  deinitCleanup();
92  return NETMAN_Tx_threadID;
93  }
94  IsProcessingTx = 0;
95  StartThread(NETMAN_Tx_threadID, NULL);
96 
97  while((sceSifBindRpc(&NETMAN_rpc_cd, NETMAN_RPC_NUMBER, 0)<0)||(NETMAN_rpc_cd.server==NULL))
98  nopdelay();
99 
100  if((result=sceSifCallRpc(&NETMAN_rpc_cd, NETMAN_IOP_RPC_FUNC_INIT, 0, NULL, 0, &ReceiveBuffer, sizeof(s32), NULL, NULL))<0 || (result=ReceiveBuffer.result) != 0)
101  deinitCleanup();
102 
103  return result;
104 }
105 
106 int NetManRPCRegisterNetworkStack(void)
107 {
108  int result;
109 
110  WaitSema(NetManIOSemaID);
111 
112  if(FrameBufferStatus == NULL) FrameBufferStatus = memalign(64, NETMAN_RPC_BLOCK_SIZE * sizeof(struct NetManBD));
113 
114  if(FrameBufferStatus != NULL)
115  {
116  memset(UNCACHED_SEG(FrameBufferStatus), 0, NETMAN_RPC_BLOCK_SIZE * sizeof(struct NetManBD));
117  TransmitBuffer.NetStack.FrameBufferStatus = FrameBufferStatus;
118  IOPFrameBufferWrPtr = 0;
119 
120  if((result=sceSifCallRpc(&NETMAN_rpc_cd, NETMAN_IOP_RPC_FUNC_REG_NETWORK_STACK, 0, &TransmitBuffer, sizeof(struct NetManRegNetworkStack), &ReceiveBuffer, sizeof(struct NetManRegNetworkStackResult), NULL, NULL))>=0)
121  {
122  if((result=ReceiveBuffer.NetStackResult.result) == 0)
123  {
124  IOPFrameBuffer = ReceiveBuffer.NetStackResult.FrameBuffer;
125  IOPFrameBufferStatus = ReceiveBuffer.NetStackResult.FrameBufferStatus;
126  }
127  }
128  }
129  else
130  {
131  result = -ENOMEM;
132  }
133 
134  SignalSema(NetManIOSemaID);
135 
136  return result;
137 }
138 
139 int NetManRPCUnregisterNetworkStack(void)
140 {
141  int result;
142 
143  WaitSema(NetManIOSemaID);
144 
145  result=sceSifCallRpc(&NETMAN_rpc_cd, NETMAN_IOP_RPC_FUNC_UNREG_NETWORK_STACK, 0, NULL, 0, NULL, 0, NULL, NULL);
146  IOPFrameBuffer = NULL;
147  IOPFrameBufferWrPtr = 0;
148 
149  free(FrameBufferStatus);
150  FrameBufferStatus = NULL;
151 
152  SignalSema(NetManIOSemaID);
153 
154  return result;
155 }
156 
157 void NetManDeinitRPCClient(void)
158 {
159  if(NETMAN_rpc_cd.server)
160  {
161  WaitSema(NetManIOSemaID);
162 
163  sceSifCallRpc(&NETMAN_rpc_cd, NETMAN_IOP_RPC_FUNC_DEINIT, 0, NULL, 0, NULL, 0, NULL, NULL);
164  deinitCleanup();
165  }
166 }
167 
168 int NetManRpcIoctl(unsigned int command, void *args, unsigned int args_len, void *output, unsigned int length)
169 {
170  int result;
171  struct NetManIoctl *IoctlArgs=&TransmitBuffer.IoctlArgs;
172 
173  WaitSema(NetManIOSemaID);
174 
175  IoctlArgs->command=command;
176  memcpy(IoctlArgs->args, args, args_len);
177  IoctlArgs->args_len=args_len;
178  IoctlArgs->output=output;
179  IoctlArgs->length=length;
180 
181  if((result=sceSifCallRpc(&NETMAN_rpc_cd, NETMAN_IOP_RPC_FUNC_IOCTL, 0, &TransmitBuffer, sizeof(struct NetManIoctl), &ReceiveBuffer, sizeof(struct NetManIoctlResult), NULL, NULL))>=0)
182  {
183  result=ReceiveBuffer.IoctlResult.result;
184  memcpy(output, ReceiveBuffer.IoctlResult.output, length);
185  }
186 
187  SignalSema(NetManIOSemaID);
188 
189  return result;
190 }
191 
192 static void NETMAN_TxThread(void *arg)
193 {
194  static SifCmdHeader_t cmd ALIGNED(64);
195  SifDmaTransfer_t dmat[2];
196  struct NetManPktCmd *npcmd;
197  int dmat_id, unaligned, unalignedCache;
198  void *payload, *payloadAligned, *payloadCacheAligned;
199  volatile struct NetManBD *bd, *bdNext;
200 
201  (void)arg;
202 
203  while(1)
204  {
205  int length, NumTx;
206  SleepThread();
207 
208  NumTx = 0;
209  while((length = NetManTxPacketNext(&payload)) > 0)
210  {
211  IsProcessingTx = 1;
212 
213  //Write back D-cache, before performing a DMA transfer.
214  unaligned = (int)((u32)payload & 15);
215  unalignedCache = (int)((u32)payload & 63);
216  payloadAligned = (void*)((u32)payload & ~15);
217  payloadCacheAligned = (void*)((u32)payload & ~63);
218  sceSifWriteBackDCache(payloadCacheAligned, (length + unalignedCache + 63) & ~63);
219 
220  do {
221  //Wait for a spot to be freed up.
222  bd = UNCACHED_SEG(&FrameBufferStatus[IOPFrameBufferWrPtr]);
223  while(bd->length != 0){}
224 
225  //Transfer to IOP RAM
226  //Determine mode of transfer.
227  bdNext = UNCACHED_SEG(&FrameBufferStatus[(IOPFrameBufferWrPtr + 1) % NETMAN_RPC_BLOCK_SIZE]);
228  if((NumTx + 1) >= NETMAN_FRAME_GROUP_SIZE || bdNext->length == 0)
229  {
230  //Prepare SIFCMD packet
231  //Record the frame length.
232  npcmd = (struct NetManPktCmd*)&cmd.opt;
233  npcmd->length = length;
234  npcmd->offset = unaligned;
235  npcmd->id = IOPFrameBufferWrPtr;
236 
237  while((dmat_id = sceSifSendCmd(NETMAN_SIFCMD_ID, &cmd, sizeof(SifCmdHeader_t),
238  (void*)payloadAligned,
239  (void*)&IOPFrameBuffer[IOPFrameBufferWrPtr * NETMAN_MAX_FRAME_SIZE],
240  (length + unaligned + 15) & ~15)) == 0){ };
241  } else {
242  //Record the frame length.
243  bd->length = length;
244  bd->offset = unaligned;
245 
246  //Normal DMA transfer
247  dmat[0].src = (void*)payloadAligned;
248  dmat[0].dest = (void*)&IOPFrameBuffer[IOPFrameBufferWrPtr * NETMAN_MAX_FRAME_SIZE];
249  dmat[0].size = (length + unaligned + 15) & ~15;
250  dmat[0].attr = 0;
251  dmat[1].src = (void*)&FrameBufferStatus[IOPFrameBufferWrPtr];
252  dmat[1].dest = (void*)&IOPFrameBufferStatus[IOPFrameBufferWrPtr];
253  dmat[1].size = sizeof(struct NetManBD);
254  dmat[1].attr = 0;
255 
256  while((dmat_id = sceSifSetDma(dmat, 2)) == 0){ };
257  }
258 
259  //Increase write pointer by one position.
260  IOPFrameBufferWrPtr = (IOPFrameBufferWrPtr + 1) % NETMAN_RPC_BLOCK_SIZE;
261 
262  if((length = NetManTxPacketAfter(&payload)) > 0)
263  { //Write back the cache of the next packet, while waiting.
264  unaligned = (int)((u32)payload & 15);
265  unalignedCache = (int)((u32)payload & 63);
266  payloadAligned = (void*)((u32)payload & ~15);
267  payloadCacheAligned = (void*)((u32)payload & ~63);
268  sceSifWriteBackDCache(payloadCacheAligned, (length + unalignedCache + 63) & ~63);
269  }
270 
271  NumTx++;
272 
273  while(sceSifDmaStat(dmat_id) >= 0){ };
274  NetManTxPacketDeQ();
275  } while(length > 0);
276 
277  IsProcessingTx = 0;
278  }
279  }
280 }
281 
282 void NetManRpcNetIFXmit(void)
283 {
284  if(!IsProcessingTx)
285  WakeupThread(NETMAN_Tx_threadID);
286 }
287 
288 int NetManSetMainIF(const char *name)
289 {
290  int result;
291 
292  if (!NETMAN_rpc_cd.server)
293  return -1;
294 
295  WaitSema(NetManIOSemaID);
296 
297  strlcpy(TransmitBuffer.netifName, name, sizeof(TransmitBuffer.netifName));
298  TransmitBuffer.netifName[NETMAN_NETIF_NAME_MAX_LEN-1] = '\0';
299  if((result=sceSifCallRpc(&NETMAN_rpc_cd, NETMAN_IOP_RPC_FUNC_SET_MAIN_NETIF, 0, &TransmitBuffer, NETMAN_NETIF_NAME_MAX_LEN, &ReceiveBuffer, sizeof(s32), NULL, NULL))>=0)
300  result=ReceiveBuffer.result;
301 
302  SignalSema(NetManIOSemaID);
303 
304  return result;
305 }
306 
307 int NetManQueryMainIF(char *name)
308 {
309  int result;
310 
311  if (!NETMAN_rpc_cd.server)
312  return -1;
313 
314  WaitSema(NetManIOSemaID);
315 
316  if((result=sceSifCallRpc(&NETMAN_rpc_cd, NETMAN_IOP_RPC_FUNC_QUERY_MAIN_NETIF, 0, NULL, 0, &ReceiveBuffer, sizeof(struct NetManQueryMainNetIFResult), NULL, NULL))>=0)
317  {
318  if((result=ReceiveBuffer.QueryMainNetIFResult.result) == 0)
319  {
320  sprintf(name, "%.*s", (int)sizeof(ReceiveBuffer.QueryMainNetIFResult.name), ReceiveBuffer.QueryMainNetIFResult.name);
321  name[NETMAN_NETIF_NAME_MAX_LEN-1] = '\0';
322  }
323  }
324 
325  SignalSema(NetManIOSemaID);
326 
327  return result;
328 }
329 
330 int NetManSetLinkMode(int mode)
331 {
332  int result;
333 
334  if (!NETMAN_rpc_cd.server)
335  return -1;
336 
337  WaitSema(NetManIOSemaID);
338 
339  TransmitBuffer.mode = mode;
340  if((result=sceSifCallRpc(&NETMAN_rpc_cd, NETMAN_IOP_RPC_FUNC_SET_LINK_MODE, 0, &TransmitBuffer, sizeof(s32), &ReceiveBuffer, sizeof(s32), NULL, NULL))>=0)
341  result=ReceiveBuffer.result;
342 
343  SignalSema(NetManIOSemaID);
344 
345  return result;
346 }
kernel.h
NetManPktCmd
Definition: netman_rpc.h:75
NetManIoctlResult
Definition: netman_rpc.h:69
NetManRegNetworkStack
Definition: netman_rpc.h:39
ENOMEM
#define ENOMEM
Definition: errno.h:43
NetManQueryMainNetIFResult
Definition: netman_rpc.h:51
thread
Definition: thcommon.h:143
iopcontrol.h
t_ee_sema
Definition: kernel.h:193
t_SifCmdHeader
Definition: sifcmd-common.h:22
netman.h
_gp
void * _gp
netman_rpc.h
HasIopRebootedSinceLastCall
static int HasIopRebootedSinceLastCall(void)
Definition: iopcontrol.h:47
stdio.h
NetManRegNetworkStackResult
Definition: netman_rpc.h:44
t_SifDmaTransfer
Definition: sifdma.h:52
NetManIoctl
Definition: netman_rpc.h:60
t_SifRpcClientData
Definition: sifrpc-common.h:134
NetManBD
Definition: netman_rpc.h:82
t_ee_thread
Definition: kernel.h:203
errno.h