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