1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - MB - libraries
3 File: mb_block.c
4
5 Copyright 2007-2008 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2008-09-18#$
14 $Rev: 8573 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17
18 #include <nitro.h>
19 #include "mb_common.h"
20 #include "mb_block.h"
21 #include "mb_private.h"
22
23
24 //============================================================================
25 // Function Prototype Declarations
26 //============================================================================
27 static u8 *MBi_ReceiveRequestDataPiece(const MBCommChildBlockHeader * hdr, u16 child);
28 static BOOL IsGetAllRequestData(u16 child);
29
30
31 //============================================================================
32 // Variable Declarations
33 //============================================================================
34
35 // The size and number of a divided request's fragments.
36 static struct
37 {
38 int size;
39 int num;
40 int bufSize;
41 }
42 req_data_piece;
43
44 // For child
45 // Divided request send index.
46 static u8 req_data_piece_idx = 0;
47
48 // For parent
49 // Receive buffer for a divided request
50 static MbRequestPieceBuf *req_buf;
51
52
53 //============================================================================
54 // function definitions
55 //============================================================================
56
57 /*---------------------------------------------------------------------------*
58 Name: MBi_SetChildMPMaxSize
59
60 Description: Sets the transmission data size for a child and calculates the divided request size.
61
62
63 Arguments: childMaxSize: Child transmission size.
64
65 Returns: None.
66 *---------------------------------------------------------------------------*/
MBi_SetChildMPMaxSize(u16 childMaxSize)67 void MBi_SetChildMPMaxSize(u16 childMaxSize)
68 {
69 req_data_piece.size = MB_COMM_CALC_REQ_DATA_PIECE_SIZE(childMaxSize);
70 req_data_piece.num = MB_COMM_CALC_REQ_DATA_PIECE_NUM(childMaxSize);
71 req_data_piece.bufSize = MB_COMM_CALC_REQ_DATA_BUF_SIZE(childMaxSize);
72 }
73
74
75 /*---------------------------------------------------------------------------*
76 Name: MBi_SetParentPieceBuffer
77
78 Description: Sets the receive buffer for a parent's divided request.
79
80 Arguments: buf: Pointer to the receive buffer.
81
82 Returns: None.
83 *---------------------------------------------------------------------------*/
MBi_SetParentPieceBuffer(MbRequestPieceBuf * buf)84 void MBi_SetParentPieceBuffer(MbRequestPieceBuf * buf)
85 {
86 req_buf = buf;
87 MI_CpuClear8(req_buf, sizeof(MbRequestPieceBuf));
88 }
89
90
91 /*---------------------------------------------------------------------------*
92 Name: MBi_ClearParentPieceBuffer
93
94 Description: Clears the buffer for receiving divided requests.
95
96 Arguments: child_aid: Child AID of the buffer to clear.
97
98 Returns: None.
99 *---------------------------------------------------------------------------*/
MBi_ClearParentPieceBuffer(u16 child_aid)100 void MBi_ClearParentPieceBuffer(u16 child_aid)
101 {
102 if (req_buf == NULL)
103 {
104 return;
105 }
106
107 MI_CpuClear8(req_buf->data_buf[child_aid - 1],
108 MB_COMM_CALC_REQ_DATA_BUF_SIZE(req_data_piece.bufSize));
109 req_buf->data_bmp[child_aid - 1] = 0;
110 }
111
112
113 /*---------------------------------------------------------------------------*
114 Name: MBi_MakeParentSendBuffer
115
116 Description: Builds the actual data to send, using a parent's send header information.
117
118 Arguments: hdr: Pointer to the parent send header.
119 sendbuf: Pointer to the buffer that creates the send data.
120
121 Returns: pointer to send buffer
122 *---------------------------------------------------------------------------*/
MBi_MakeParentSendBuffer(const MBCommParentBlockHeader * hdr,u8 * sendbuf)123 u8 *MBi_MakeParentSendBuffer(const MBCommParentBlockHeader * hdr, u8 *sendbuf)
124 {
125 u8 *ptr = sendbuf;
126
127 *ptr++ = hdr->type;
128
129 switch (hdr->type)
130 {
131 case MB_COMM_TYPE_PARENT_SENDSTART: // 1
132 break;
133 case MB_COMM_TYPE_PARENT_KICKREQ: // 2
134 break;
135 case MB_COMM_TYPE_PARENT_DL_FILEINFO: // 3
136 break;
137 case MB_COMM_TYPE_PARENT_DATA: // 4
138 *ptr++ = (u8)(0x00ff & hdr->fid); // Lo
139 *ptr++ = (u8)((0xff00 & hdr->fid) >> 8); // Hi
140 *ptr++ = (u8)(0x00ff & hdr->seqno); // Lo
141 *ptr++ = (u8)((0xff00 & hdr->seqno) >> 8); // Hi
142 break;
143 case MB_COMM_TYPE_PARENT_BOOTREQ: // 5
144 break;
145 case MB_COMM_TYPE_PARENT_MEMBER_FULL: // 6
146 break;
147 default:
148 return NULL;
149 }
150
151 return ptr;
152 }
153
154
155 /*---------------------------------------------------------------------------*
156 Name: MBi_SetRecvBufferFromChild
157
158 Description: Get the header portion from a packet received from the child, and return a pointer to the data portion.
159
160
161 Arguments: hdr: Pointer to a variable for getting the header.
162 recvbuf: Pointer to the receive buffer.
163
164 Returns: Pointer to the data portion.
165 *---------------------------------------------------------------------------*/
MBi_SetRecvBufferFromChild(const u8 * recvbuf,MBCommChildBlockHeader * hdr,u16 child_id)166 u8 *MBi_SetRecvBufferFromChild(const u8 *recvbuf, MBCommChildBlockHeader * hdr, u16 child_id)
167 {
168 u8 *ptr = (u8 *)recvbuf;
169
170 hdr->type = *ptr++;
171
172 switch (hdr->type)
173 {
174 case MB_COMM_TYPE_CHILD_FILEREQ:
175 // Restore fragmented data.
176 if (IsGetAllRequestData(child_id))
177 {
178 return (u8 *)req_buf->data_buf[child_id - 1];
179 }
180
181 hdr->req_data.piece = *ptr++;
182 if (hdr->req_data.piece > req_data_piece.num)
183 {
184 return NULL; // Error
185 }
186 MI_CpuCopy8(ptr, hdr->req_data.data, (u32)req_data_piece.size);
187 ptr = MBi_ReceiveRequestDataPiece(hdr, child_id);
188 break;
189 case MB_COMM_TYPE_CHILD_ACCEPT_FILEINFO:
190 hdr->data.req = (u16)(0x00ff & (*ptr++));
191 hdr->data.req |= (((u16)(*ptr++) << 8) & 0xff00);
192 break;
193 case MB_COMM_TYPE_CHILD_CONTINUE:
194 hdr->data.req = (u16)(0x00ff & (*ptr++));
195 hdr->data.req |= (((u16)(*ptr++) << 8) & 0xff00);
196 MI_CpuCopy8(ptr, hdr->data.reserved, (u32)req_data_piece.size);
197 ptr += req_data_piece.size;
198 break;
199 default:
200 return NULL;
201 }
202
203 return ptr;
204 }
205
206
207 /*---------------------------------------------------------------------------*
208 Name: MBi_ReceiveRequestDataPiece
209
210 Description: Builds data in its entirety from the divided request data that was received from the child.
211
212 Arguments: hdr: Pointer to a variable for getting the header.
213 recvbuf: Pointer to the receive buffer.
214
215 Returns: Pointer to the data when the divided request data is all complete.
216 NULL when not it is not complete.
217 *---------------------------------------------------------------------------*/
MBi_ReceiveRequestDataPiece(const MBCommChildBlockHeader * hdr,u16 child)218 static u8 *MBi_ReceiveRequestDataPiece(const MBCommChildBlockHeader * hdr, u16 child)
219 {
220 u8 piece;
221 u8 *ptr;
222
223 if (req_buf == NULL)
224 {
225 return NULL;
226 }
227
228 piece = hdr->req_data.piece;
229
230 if (piece > req_data_piece.num)
231 {
232 return NULL;
233 }
234
235 ptr = ((u8 *)req_buf->data_buf[child - 1]) + (piece * req_data_piece.size);
236
237 MI_CpuCopy8(&hdr->req_data.data[0], ptr, (u32)req_data_piece.size);
238
239 req_buf->data_bmp[child - 1] |= (1 << piece);
240
241 MB_DEBUG_OUTPUT(" %02x %02x %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4],
242 ptr[5]);
243
244 if (IsGetAllRequestData(child))
245 {
246 return (u8 *)req_buf->data_buf[child - 1];
247 }
248
249 return NULL;
250 }
251
252
253 /*---------------------------------------------------------------------------*
254 Name:
255
256 Description: Builds data in its entirety from the divided request data that was received from the child.
257
258 Arguments: hdr: Pointer to a variable for getting the header.
259 recvbuf: Pointer to the receive buffer.
260
261 Returns: TRUE if the divided request data is all complete.
262 FALSE if it is not complete.
263 *---------------------------------------------------------------------------*/
IsGetAllRequestData(u16 child)264 static BOOL IsGetAllRequestData(u16 child)
265 {
266 u16 i;
267
268 /* Determine whether Pieces were collected. */
269 for (i = 0; i < req_data_piece.num; i++)
270 {
271 if ((req_buf->data_bmp[child - 1] & (1 << i)) == 0)
272 {
273 return FALSE;
274 }
275 }
276
277 return TRUE;
278 }
279
280
281
282 /*---------------------------------------------------------------------------*
283 Name: MBi_MakeChildSendBuffer
284
285 Description: Builds the actual data to send, using a child's send header information.
286
287 Arguments: hdr: Pointer to the child send header.
288 sendbuf: Pointer to the buffer that creates the send data.
289
290 Returns: pointer to send buffer
291 *---------------------------------------------------------------------------*/
MBi_MakeChildSendBuffer(const MBCommChildBlockHeader * hdr,u8 * sendbuf)292 u8 *MBi_MakeChildSendBuffer(const MBCommChildBlockHeader * hdr, u8 *sendbuf)
293 {
294 u8 *pbuf = sendbuf;
295
296 *pbuf++ = hdr->type;
297 switch (hdr->type)
298 {
299 case MB_COMM_TYPE_CHILD_FILEREQ:
300 *pbuf++ = hdr->req_data.piece;
301 if (hdr->req_data.piece > req_data_piece.num)
302 {
303 return NULL; // Error
304 }
305
306 MI_CpuCopy8((void *)(hdr->req_data.data), (void *)pbuf, (u32)req_data_piece.size);
307 pbuf += req_data_piece.size;
308 break;
309 case MB_COMM_TYPE_CHILD_ACCEPT_FILEINFO:
310 break;
311 case MB_COMM_TYPE_CHILD_CONTINUE:
312 *pbuf++ = (u8)(0x00ff & hdr->data.req); // Lo
313 *pbuf++ = (u8)((0xff00 & hdr->data.req) >> 8); // Hi
314 MI_CpuCopy8((void *)(hdr->data.reserved), (void *)pbuf, (u32)req_data_piece.size);
315 pbuf += req_data_piece.size;
316 break;
317 case MB_COMM_TYPE_CHILD_STOPREQ:
318 break;
319 case MB_COMM_TYPE_CHILD_BOOTREQ_ACCEPTED:
320 break;
321 default:
322 return NULL;
323 }
324
325 return pbuf;
326 }
327
328
329 /*---------------------------------------------------------------------------*
330 Name: MBi_SendRequestDataPiece
331
332 Description: Divide request data to send from a child.
333
334 Arguments: pData: Pointer that gets divided data.
335 pReq: Request data to divide.
336
337 Returns: Index value of the divided data that was obtained.
338 *---------------------------------------------------------------------------*/
MBi_SendRequestDataPiece(u8 * pData,const MBCommRequestData * pReq)339 u8 MBi_SendRequestDataPiece(u8 *pData, const MBCommRequestData *pReq)
340 {
341 const u8 *ptr = (u8 *)pReq;
342
343 /* Decide upon the send piece. */
344 req_data_piece_idx = (u8)((req_data_piece_idx + 1) % req_data_piece.num);
345 MB_DEBUG_OUTPUT("req_data piece : %d\n", req_data_piece_idx);
346
347 // Copy data to the send buffer.
348 MI_CpuCopy8((void *)&ptr[req_data_piece_idx * req_data_piece.size],
349 pData, (u32)req_data_piece.size);
350
351 MB_DEBUG_OUTPUT(" %02x %02x %02x %02x %02x %02x\n", pData[0], pData[1], pData[2], pData[3],
352 pData[4], pData[5]);
353
354 return req_data_piece_idx;
355 }
356
357
358
359 /*---------------------------------------------------------------------------*
360 Name: MBi_SetRecvBufferFromParent
361
362 Description: Get the header portion from a packet received from the parent, and return a pointer to the data portion.
363
364
365 Arguments: hdr: Pointer to a variable for getting the header.
366 recvbuf: Pointer to the receive buffer.
367
368 Returns: Pointer to the data portion.
369 *---------------------------------------------------------------------------*/
MBi_SetRecvBufferFromParent(MBCommParentBlockHeader * hdr,const u8 * recvbuf)370 u8 *MBi_SetRecvBufferFromParent(MBCommParentBlockHeader * hdr, const u8 *recvbuf)
371 {
372
373 hdr->type = *recvbuf++;
374
375 switch (hdr->type)
376 {
377 case MB_COMM_TYPE_PARENT_SENDSTART:
378 break;
379 case MB_COMM_TYPE_PARENT_KICKREQ:
380 break;
381 case MB_COMM_TYPE_PARENT_DL_FILEINFO:
382 break;
383 case MB_COMM_TYPE_PARENT_DATA:
384 hdr->fid = (u16)(*recvbuf++); // Lo
385 hdr->fid |= ((u16)(*recvbuf++) << 8); // Hi
386 hdr->seqno = (u16)(*recvbuf++); // Lo
387 hdr->seqno |= ((u16)(*recvbuf++) << 8); // Hi
388 break;
389 case MB_COMM_TYPE_PARENT_BOOTREQ:
390 break;
391 case MB_COMM_TYPE_PARENT_MEMBER_FULL:
392 break;
393 default:
394 return NULL;
395 }
396 return (u8 *)recvbuf;
397 }
398