1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - NWM - libraries
3   File:     nwm_cmd.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-17#$
14   $Rev: 8556 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 
18 #include <twl.h>
19 
20 #include "nwm_common_private.h"
21 #include "nwm_arm9_private.h"
22 
23 static u32 *NwmGetCommandBuffer4Arm7(void);
24 
25 /*---------------------------------------------------------------------------*
26   Name:         NWMi_SetCallbackTable
27 
28   Description:  Registers the callback function for each asynchronous function.
29 
30   Arguments:    id:              Asynchronous function's API ID.
31                 callback:        The callback function to be registered.
32 
33   Returns:      None.
34  *---------------------------------------------------------------------------*/
NWMi_SetCallbackTable(NWMApiid id,NWMCallbackFunc callback)35 void NWMi_SetCallbackTable(NWMApiid id, NWMCallbackFunc callback)
36 {
37     NWMArm9Buf *sys = NWMi_GetSystemWork();
38 
39     SDK_NULL_ASSERT(sys);
40 
41     sys->callbackTable[id] = callback;
42 }
43 
44 
45 /*---------------------------------------------------------------------------*
46   Name:         NWMi_SetReceiveCallbackTable
47 
48   Description:  Registers a callback function for receiving data frames.
49 
50   Arguments:    id:              Asynchronous function's API ID.
51                 callback:        The callback function to be registered.
52 
53   Returns:      None.
54  *---------------------------------------------------------------------------*/
NWMi_SetReceiveCallbackTable(NWMFramePort port,NWMCallbackFunc callback)55 void NWMi_SetReceiveCallbackTable(NWMFramePort port, NWMCallbackFunc callback)
56 {
57     NWMArm9Buf *sys = NWMi_GetSystemWork();
58 
59     SDK_NULL_ASSERT(sys);
60 
61     sys->recvCallbackTable[port] = callback;
62 }
63 
64 /*---------------------------------------------------------------------------*
65   Name:         NWMi_SendCommand
66 
67   Description:  Transmits a request to the ARM7 via the FIFO.
68                 For commands accompanied by some number of u32-type parameters, specify the parameters by enumerating them.
69 
70 
71   Arguments:    id:              API ID that corresponds to the request.
72                 paramNum:        Number of virtual arguments.
73                 ...:         Virtual argument.
74 
75   Returns:      int: Returns the result of the process as an NWM_RETCODE_* value.
76  *---------------------------------------------------------------------------*/
NWMi_SendCommand(NWMApiid id,u16 paramNum,...)77 NWMRetCode NWMi_SendCommand(NWMApiid id, u16 paramNum, ...)
78 {
79     va_list vlist;
80     s32     i;
81     int     result;
82     u32    *tmpAddr;
83     NWMArm9Buf *sys = NWMi_GetSystemWork();
84 
85     // Reserves a buffer for command sending
86     tmpAddr = NwmGetCommandBuffer4Arm7();
87     if (tmpAddr == NULL)
88     {
89         NWM_WARNING("Failed to get command buffer.\n");
90         return NWM_RETCODE_FIFO_ERROR;
91     }
92 
93     // API ID
94     *(u16 *)tmpAddr = (u16)id;
95 
96     // Adds the specified number of arguments
97     va_start(vlist, paramNum);
98     for (i = 0; i < paramNum; i++)
99     {
100         tmpAddr[i + 1] = va_arg(vlist, u32);
101     }
102     va_end(vlist);
103 
104     DC_StoreRange(tmpAddr, NWM_APIFIFO_BUF_SIZE);
105 
106     // Notification with FIFO
107     result = PXI_SendWordByFifo(PXI_FIFO_TAG_WMW, (u32)tmpAddr, FALSE);
108 
109     (void)OS_SendMessage(&sys->apibufQ.q, tmpAddr, OS_MESSAGE_BLOCK);
110 
111     if (result < 0)
112     {
113         NWM_WARNING("Failed to send command through FIFO.\n");
114         return NWM_RETCODE_FIFO_ERROR;
115     }
116 
117     return NWM_RETCODE_OPERATING;
118 }
119 
120 /*---------------------------------------------------------------------------*
121   Name:         NWMi_SendCommandDirect
122 
123   Description:  Transmits a request to the ARM7 via the FIFO.
124                 Directly specifies the command sent to the ARM7.
125 
126   Arguments:    data:            Command sent to the ARM7.
127                 length:          Size of the command sent to the ARM7.
128 
129   Returns:      int: Returns the result of the process as an NWM_RETCODE_* value.
130  *---------------------------------------------------------------------------*/
NWMi_SendCommandDirect(void * data,u32 length)131 NWMRetCode NWMi_SendCommandDirect(void *data, u32 length)
132 {
133     int     result;
134     u32    *tmpAddr;
135     NWMArm9Buf *sys = NWMi_GetSystemWork();
136 
137     SDK_ASSERT(length <= NWM_APIFIFO_BUF_SIZE);
138 
139     // Reserves a buffer for command sending
140     tmpAddr = NwmGetCommandBuffer4Arm7();
141     if (tmpAddr == NULL)
142     {
143         NWM_WARNING("Failed to get command buffer.\n");
144         return NWM_RETCODE_FIFO_ERROR;
145     }
146 
147     // Copies to a buffer specifically for commands sent to the ARM7.
148     MI_CpuCopy8(data, tmpAddr, length);
149 
150     DC_StoreRange(tmpAddr, length);
151 
152     // Notification with FIFO
153     result = PXI_SendWordByFifo(PXI_FIFO_TAG_WMW, (u32)tmpAddr, FALSE);
154 
155     (void)OS_SendMessage(&sys->apibufQ.q, tmpAddr, OS_MESSAGE_BLOCK);
156 
157     if (result < 0)
158     {
159         NWM_WARNING("Failed to send command through FIFO.\n");
160         return NWM_RETCODE_FIFO_ERROR;
161     }
162 
163     return NWM_RETCODE_OPERATING;
164 }
165 
166 /*---------------------------------------------------------------------------*
167   Name:         NwmGetCommandBuffer4Arm7
168 
169   Description:  Reserves from the pool a buffer for commands directed to ARM7.
170 
171   Arguments:    None.
172 
173   Returns:      If it can be reserved, it's that value; otherwise: NULL
174  *---------------------------------------------------------------------------*/
NwmGetCommandBuffer4Arm7(void)175 u32 *NwmGetCommandBuffer4Arm7(void)
176 {
177     u32    *tmpAddr = NULL;
178     NWMArm9Buf *sys = NWMi_GetSystemWork();
179 
180     do {
181         if (FALSE == OS_ReceiveMessage(&sys->apibufQ.q, (OSMessage *)&tmpAddr, OS_MESSAGE_NOBLOCK))
182         {
183             return NULL;
184         }
185 
186         // invalidate entire apibuf
187         DC_InvalidateRange(sys->apibuf, NWM_APIBUF_NUM * NWM_APIFIFO_BUF_SIZE);
188 
189         // Check if the ring buffer is available (queue is not full)
190         DC_InvalidateRange(tmpAddr, sizeof(u16));
191 
192         if ((*((u16 *)tmpAddr) & NWM_API_REQUEST_ACCEPTED) == 0)
193         {
194             // return pending buffer to tail of queue
195             (void)OS_SendMessage(&sys->apibufQ.q, tmpAddr, OS_MESSAGE_BLOCK);
196             tmpAddr = NULL;
197             continue;
198         }
199     } while(tmpAddr == NULL);
200 
201     return tmpAddr;
202 }
203