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:: 2009-06-09#$
14   $Rev: 10718 $
15   $Author: okajima_manabu $
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     // child_aid range check
103     SDK_ASSERT(child_aid != 0 && child_aid <= MB_MAX_CHILD);
104 
105     if (req_buf == NULL)
106     {
107         return;
108     }
109 
110     MI_CpuClear8(req_buf->data_buf[child_aid - 1],
111                  MB_COMM_CALC_REQ_DATA_BUF_SIZE(req_data_piece.bufSize));
112     req_buf->data_bmp[child_aid - 1] = 0;
113 }
114 
115 
116 /*---------------------------------------------------------------------------*
117   Name:         MBi_MakeParentSendBuffer
118 
119   Description:  Builds the actual data to send, using a parent's send header information.
120 
121   Arguments:    hdr: Pointer to the parent send header
122                 sendbuf: Pointer to the buffer that creates the send data
123 
124   Returns:      Pointer to send buffer.
125  *---------------------------------------------------------------------------*/
MBi_MakeParentSendBuffer(const MBCommParentBlockHeader * hdr,u8 * sendbuf)126 u8     *MBi_MakeParentSendBuffer(const MBCommParentBlockHeader * hdr, u8 *sendbuf)
127 {
128     u8     *ptr = sendbuf;
129 
130     *ptr++ = hdr->type;
131 
132     switch (hdr->type)
133     {
134     case MB_COMM_TYPE_PARENT_SENDSTART:        //  1
135         break;
136     case MB_COMM_TYPE_PARENT_KICKREQ: //  2
137         break;
138     case MB_COMM_TYPE_PARENT_DL_FILEINFO:      //  3
139         break;
140     case MB_COMM_TYPE_PARENT_DATA:    //  4
141         *ptr++ = (u8)(0x00ff & hdr->fid);       // Lo
142         *ptr++ = (u8)((0xff00 & hdr->fid) >> 8);        // Hi
143         *ptr++ = (u8)(0x00ff & hdr->seqno);     // Lo
144         *ptr++ = (u8)((0xff00 & hdr->seqno) >> 8);      // Hi
145         break;
146     case MB_COMM_TYPE_PARENT_BOOTREQ: //  5
147         break;
148     case MB_COMM_TYPE_PARENT_MEMBER_FULL:      //  6
149         break;
150     default:
151         return NULL;
152     }
153 
154     return ptr;
155 }
156 
157 
158 /*---------------------------------------------------------------------------*
159   Name:         MBi_SetRecvBufferFromChild
160 
161   Description:  Get the header portion from a packet received from the child, and return a pointer to the data portion.
162 
163 
164   Arguments:    hdr: Pointer to a variable for getting the header
165                 recvbuf: Pointer to the receive buffer
166 
167   Returns:      Pointer to the data portion.
168  *---------------------------------------------------------------------------*/
MBi_SetRecvBufferFromChild(const u8 * recvbuf,MBCommChildBlockHeader * hdr,u16 child_id)169 u8     *MBi_SetRecvBufferFromChild(const u8 *recvbuf, MBCommChildBlockHeader * hdr, u16 child_id)
170 {
171     u8     *ptr = (u8 *)recvbuf;
172 
173     SDK_ASSERT(child_id != 0 && child_id <= MB_MAX_CHILD);
174 
175     hdr->type = *ptr++;
176 
177     switch (hdr->type)
178     {
179     case MB_COMM_TYPE_CHILD_FILEREQ:
180         // Restore fragmented data
181         if (IsGetAllRequestData(child_id))
182         {
183             return (u8 *)req_buf->data_buf[child_id - 1];
184         }
185 
186         hdr->req_data.piece = *ptr++;
187         if (hdr->req_data.piece > req_data_piece.num)
188         {
189             return NULL;               // Error
190         }
191         MI_CpuCopy8(ptr, hdr->req_data.data, (u32)req_data_piece.size);
192         ptr = MBi_ReceiveRequestDataPiece(hdr, child_id);
193         break;
194     case MB_COMM_TYPE_CHILD_ACCEPT_FILEINFO:
195         hdr->data.req = (u16)(0x00ff & (*ptr++));
196         hdr->data.req |= (((u16)(*ptr++) << 8) & 0xff00);
197         break;
198     case MB_COMM_TYPE_CHILD_CONTINUE:
199         hdr->data.req = (u16)(0x00ff & (*ptr++));
200         hdr->data.req |= (((u16)(*ptr++) << 8) & 0xff00);
201         MI_CpuCopy8(ptr, hdr->data.reserved, (u32)req_data_piece.size);
202         ptr += req_data_piece.size;
203         break;
204     default:
205         return NULL;
206     }
207 
208     return ptr;
209 }
210 
211 
212 /*---------------------------------------------------------------------------*
213   Name:         MBi_ReceiveRequestDataPiece
214 
215   Description:  Builds data in its entirety from the divided request data that was received from the child.
216 
217   Arguments:    hdr: Pointer to a variable for getting the header
218                 recvbuf: Pointer to the receive buffer
219 
220   Returns:      Pointer to the data when the divided request data is all complete.
221                 NULL when not it is not complete.
222  *---------------------------------------------------------------------------*/
MBi_ReceiveRequestDataPiece(const MBCommChildBlockHeader * hdr,u16 child)223 static u8 *MBi_ReceiveRequestDataPiece(const MBCommChildBlockHeader * hdr, u16 child)
224 {
225     u8      piece;
226     u8     *ptr;
227 
228     SDK_ASSERT(child != 0 && child <= MB_MAX_CHILD);
229 
230     if (req_buf == NULL)
231     {
232         return NULL;
233     }
234 
235     piece = hdr->req_data.piece;
236 
237     if (piece > req_data_piece.num)
238     {
239         return NULL;
240     }
241 
242     ptr = ((u8 *)req_buf->data_buf[child - 1]) + (piece * req_data_piece.size);
243 
244     MI_CpuCopy8(&hdr->req_data.data[0], ptr, (u32)req_data_piece.size);
245 
246     req_buf->data_bmp[child - 1] |= (1 << piece);
247 
248     MB_DEBUG_OUTPUT(" %02x %02x %02x %02x %02x %02x\n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4],
249                     ptr[5]);
250 
251     if (IsGetAllRequestData(child))
252     {
253         return (u8 *)req_buf->data_buf[child - 1];
254     }
255 
256     return NULL;
257 }
258 
259 
260 /*---------------------------------------------------------------------------*
261   Name:
262 
263   Description:  Builds data in its entirety from the divided request data that was received from the child.
264 
265   Arguments:    hdr: Pointer to a variable for getting the header
266                 recvbuf: Pointer to the receive buffer
267 
268   Returns:      TRUE if the divided request data is all complete.
269                 FALSE if it is not complete.
270  *---------------------------------------------------------------------------*/
IsGetAllRequestData(u16 child)271 static BOOL IsGetAllRequestData(u16 child)
272 {
273     u16     i;
274 
275     SDK_ASSERT(child != 0 && child <= MB_MAX_CHILD);
276 
277     /* Determine whether Pieces were collected */
278     for (i = 0; i < req_data_piece.num; i++)
279     {
280         if ((req_buf->data_bmp[child - 1] & (1 << i)) == 0)
281         {
282             return FALSE;
283         }
284     }
285 
286     return TRUE;
287 }
288 
289 
290 
291 /*---------------------------------------------------------------------------*
292   Name:         MBi_MakeChildSendBuffer
293 
294   Description:  Builds the actual data to send, using a child's send header information.
295 
296   Arguments:    hdr: Pointer to the child send header
297                 sendbuf: Pointer to the buffer that creates the send data
298 
299   Returns:      Pointer to send buffer.
300  *---------------------------------------------------------------------------*/
MBi_MakeChildSendBuffer(const MBCommChildBlockHeader * hdr,u8 * sendbuf)301 u8     *MBi_MakeChildSendBuffer(const MBCommChildBlockHeader * hdr, u8 *sendbuf)
302 {
303     u8     *pbuf = sendbuf;
304 
305     *pbuf++ = hdr->type;
306     switch (hdr->type)
307     {
308     case MB_COMM_TYPE_CHILD_FILEREQ:
309         *pbuf++ = hdr->req_data.piece;
310         if (hdr->req_data.piece > req_data_piece.num)
311         {
312             return NULL;               // Error
313         }
314 
315         MI_CpuCopy8((void *)(hdr->req_data.data), (void *)pbuf, (u32)req_data_piece.size);
316         pbuf += req_data_piece.size;
317         break;
318     case MB_COMM_TYPE_CHILD_ACCEPT_FILEINFO:
319         break;
320     case MB_COMM_TYPE_CHILD_CONTINUE:
321         *pbuf++ = (u8)(0x00ff & hdr->data.req); // Lo
322         *pbuf++ = (u8)((0xff00 & hdr->data.req) >> 8);  // Hi
323         MI_CpuCopy8((void *)(hdr->data.reserved), (void *)pbuf, (u32)req_data_piece.size);
324         pbuf += req_data_piece.size;
325         break;
326     case MB_COMM_TYPE_CHILD_STOPREQ:
327         break;
328     case MB_COMM_TYPE_CHILD_BOOTREQ_ACCEPTED:
329         break;
330     default:
331         return NULL;
332     }
333 
334     return pbuf;
335 }
336 
337 
338 /*---------------------------------------------------------------------------*
339   Name:         MBi_SendRequestDataPiece
340 
341   Description:  Divides request data to send from a child.
342 
343   Arguments:    pData: Pointer that gets divided data
344                 pReq: Request data to divide
345 
346   Returns:      Index value of the divided data that was obtained.
347  *---------------------------------------------------------------------------*/
MBi_SendRequestDataPiece(u8 * pData,const MBCommRequestData * pReq)348 u8 MBi_SendRequestDataPiece(u8 *pData, const MBCommRequestData *pReq)
349 {
350     const u8 *ptr = (u8 *)pReq;
351 
352     /* Decide upon the send piece */
353     req_data_piece_idx = (u8)((req_data_piece_idx + 1) % req_data_piece.num);
354     MB_DEBUG_OUTPUT("req_data piece : %d\n", req_data_piece_idx);
355 
356     // Copy data to the send buffer
357     MI_CpuCopy8((void *)&ptr[req_data_piece_idx * req_data_piece.size],
358                 pData, (u32)req_data_piece.size);
359 
360     MB_DEBUG_OUTPUT(" %02x %02x %02x %02x %02x %02x\n", pData[0], pData[1], pData[2], pData[3],
361                     pData[4], pData[5]);
362 
363     return req_data_piece_idx;
364 }
365 
366 
367 
368 /*---------------------------------------------------------------------------*
369   Name:         MBi_SetRecvBufferFromParent
370 
371   Description:  Get the header portion from a packet received from the parent, and return a pointer to the data portion.
372 
373 
374   Arguments:    hdr: Pointer to a variable for getting the header
375                 recvbuf: Pointer to the receive buffer
376 
377   Returns:      Pointer to the data portion.
378  *---------------------------------------------------------------------------*/
MBi_SetRecvBufferFromParent(MBCommParentBlockHeader * hdr,const u8 * recvbuf)379 u8     *MBi_SetRecvBufferFromParent(MBCommParentBlockHeader * hdr, const u8 *recvbuf)
380 {
381 
382     hdr->type = *recvbuf++;
383 
384     switch (hdr->type)
385     {
386     case MB_COMM_TYPE_PARENT_SENDSTART:
387         break;
388     case MB_COMM_TYPE_PARENT_KICKREQ:
389         break;
390     case MB_COMM_TYPE_PARENT_DL_FILEINFO:
391         break;
392     case MB_COMM_TYPE_PARENT_DATA:
393         hdr->fid = (u16)(*recvbuf++);  // Lo
394         hdr->fid |= ((u16)(*recvbuf++) << 8);   // Hi
395         hdr->seqno = (u16)(*recvbuf++); // Lo
396         hdr->seqno |= ((u16)(*recvbuf++) << 8); // Hi
397         break;
398     case MB_COMM_TYPE_PARENT_BOOTREQ:
399         break;
400     case MB_COMM_TYPE_PARENT_MEMBER_FULL:
401         break;
402     default:
403         return NULL;
404     }
405     return (u8 *)recvbuf;
406 }
407