1 /*---------------------------------------------------------------------------*
2   Project:      Sample demo program for NAND library
3   File:         async.c
4   Programmer:   HIRATSU Daisuke
5 
6   Copyright (C) 2006 Nintendo.  All rights reserved.
7 
8   These coded instructions, statements, and computer programs contain
9   proprietary information of Nintendo of America Inc. and/or Nintendo
10   Company Ltd., and are protected by Federal copyright law.  They may
11   not be disclosed to third parties or copied or duplicated in any form,
12   in whole or in part, without the prior written consent of Nintendo.
13 
14   $Log: async.c,v $
15   Revision 1.4  06/05/2006 13:07:26  hiratsu
16   Removed NANDFinalize().
17 
18   Revision 1.3  05/09/2006 09:09:51  hiratsu
19   Added new tutorial code.
20 
21   Revision 1.2  05/04/2006 04:49:33  hiratsu
22   Redesigned.  Implemented chain of callback.
23 
24   Revision 1.1  05/03/2006 09:08:54  hiratsu
25   Initial check-in.  This is a sample code to use async NAND APIs.
26 
27  *---------------------------------------------------------------------------*/
28 
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <revolution.h>
33 #include <revolution/nand.h>
34 
35 #include "util.h"
36 
37 #define PATH "/tmp/nanddemo.dat"
38 #define PERM (NAND_PERM_OWNER_READ | NAND_PERM_OWNER_WRITE)    // Owner can read/write
39 #define ATTR 0x00                                              // No attributes.
40 #define DATA_SIZE 1024*1024
41 
42 static NANDCommandBlock s_block;
43 static NANDFileInfo s_info;
44 static u8 s_data[DATA_SIZE] ATTRIBUTE_ALIGN(32);
45 static volatile BOOL s_finished_flag = FALSE;
46 
47 struct UserDataType
48 {
49     BOOL finished_flag;
50     s32  resultCode;
51 };
52 
53 static void callback(s32 result, NANDCommandBlock *block);
54 
55 static void sample1(void);
56 static void create (void);
57 static void openCallback  (s32 result, NANDCommandBlock *block);
58 static void writeCallback (s32 result, NANDCommandBlock *block);
59 static void closeCallback (s32 result, NANDCommandBlock *block);
60 static void deleteCallback(s32 result, NANDCommandBlock *block);
61 static void finishCallback(s32 result, NANDCommandBlock *block);
62 
63 static void sample2(void);
64 
65 
main(void)66 int main(void)
67 {
68     if(NANDInit()!=NAND_RESULT_OK)
69     {
70         OSHalt("NANDInit() failed.");
71     }
72 
73     sample1();
74 
75     sample2();
76 
77     OSHalt("Finished with success");
78     return EXIT_SUCCESS;     // Never reach here.
79 }
80 
81 
callback(s32 result,NANDCommandBlock * block)82 static void callback(s32 result, NANDCommandBlock *block)
83 {
84     ((struct UserDataType*)NANDGetUserData(block))->finished_flag = TRUE;
85     ((struct UserDataType*)NANDGetUserData(block))->resultCode = result;
86 }
87 
88 
sample1(void)89 static void sample1(void)
90 {
91     memset(s_data, 'A', DATA_SIZE);
92     create();
93     while(!s_finished_flag)
94       ;
95     OSReport("sample1() finished.\n");
96 }
97 
98 
create(void)99 static void create(void)
100 {
101     s32 ret = NANDCreateAsync(PATH, PERM, ATTR, openCallback, &s_block);
102     if(ret != NAND_RESULT_OK)
103     {
104         printErrMsg(ret);
105         OSHalt("NANDCreateAsync() failed.\n");
106     }
107 }
108 
109 
openCallback(s32 result,NANDCommandBlock *)110 static void openCallback(s32 result, NANDCommandBlock*)
111 {
112     if(result==NAND_RESULT_OK)
113     {
114         s32 ret = NANDOpenAsync(PATH, &s_info, NAND_ACCESS_WRITE | NAND_ACCESS_READ, writeCallback, &s_block);
115         if(ret != NAND_RESULT_OK)
116         {
117             printErrMsg(ret);
118             OSHalt("NANDOpenAsync() failed.");
119         }
120     }
121     else
122     {
123         OSHalt("NANDCreateAsync() failed.");
124     }
125 }
126 
127 
writeCallback(s32 result,NANDCommandBlock *)128 static void writeCallback(s32 result, NANDCommandBlock*)
129 {
130     if(result==NAND_RESULT_OK)
131     {    s32 ret =NANDWriteAsync(&s_info, s_data, DATA_SIZE, closeCallback, &s_block);
132         if(ret != NAND_RESULT_OK)
133         {
134             printErrMsg(ret);
135             OSHalt("NANDWriteAsync() failed.");
136         }
137     }
138     else
139     {
140         OSHalt("NANDOpenAsync() failed.");
141     }
142 
143 }
144 
closeCallback(s32 result,NANDCommandBlock *)145 static void closeCallback(s32 result, NANDCommandBlock*)
146 {
147     if(result==DATA_SIZE)
148     {
149         s32 ret = NANDCloseAsync(&s_info, deleteCallback, &s_block);
150         if(ret != NAND_RESULT_OK)
151         {
152             printErrMsg(ret);
153             OSHalt("NANDCloseAsync() failed.");
154         }
155     }
156     else
157     {
158         OSHalt("NANDWriteAsync() failed.");
159     }
160 }
161 
162 
deleteCallback(s32 result,NANDCommandBlock *)163 static void deleteCallback(s32 result, NANDCommandBlock*)
164 {
165     if(result==NAND_RESULT_OK)
166     {
167         s32 ret = NANDDeleteAsync(PATH, finishCallback, &s_block);
168         if(ret != NAND_RESULT_OK)
169         {
170             printErrMsg(ret);
171             OSHalt("NANDDeleteAsync() failed.");
172         }
173     }
174     else
175     {
176         OSHalt("NANDCloseAsync() failed.");
177     }
178 }
179 
180 
finishCallback(s32 result,NANDCommandBlock *)181 static void finishCallback(s32 result, NANDCommandBlock*)
182 {
183     if(result==NAND_RESULT_OK)
184     {
185         s_finished_flag = TRUE;
186     }
187     else
188     {
189         OSHalt("NANDDeleteAsync() failed.");
190     }
191 }
192 
193 
194 #define ASYNC_CALLS 8
195 
sample2(void)196 static void sample2(void)
197 {
198     volatile struct UserDataType userData[ASYNC_CALLS];
199     NANDCommandBlock block[ASYNC_CALLS];
200     int i = 0;
201 
202     // Start async calls.
203     for(i = 0; i<ASYNC_CALLS; ++i)
204     {
205         s32 result = NAND_RESULT_FATAL_ERROR;
206         char path[NAND_MAX_PATH];
207         userData[i].finished_flag = FALSE;
208         userData[i].resultCode = NAND_RESULT_FATAL_ERROR;
209         NANDSetUserData(&block[i], (void*)&userData[i]);
210         sprintf(path, "/tmp/async%d.tmp", i);
211         result = NANDCreateAsync(path, PERM, ATTR, callback, &block[i]);
212         if(result != NAND_RESULT_OK)
213         {
214             userData[i].finished_flag = TRUE;
215             userData[i].resultCode = result;
216         }
217     }
218 
219     // Wait async calls to be finished.
220     while(1)
221     {
222         BOOL finished_all_flag = TRUE;
223         for(i=0; i<ASYNC_CALLS; ++i)
224         {
225             finished_all_flag = finished_all_flag & userData[i].finished_flag;
226         }
227         if(finished_all_flag)
228         {
229             break;
230         }
231     }
232 
233     // Report results
234     for(i = 0; i<ASYNC_CALLS; ++i)
235     {
236         if(userData[i].resultCode == NAND_RESULT_OK)
237         {
238             OSReport("Async call [%d]...success\n", i);
239         }
240         else
241         {
242             OSReport("Async call [%d]...failed : result code (%d)\n", i, userData[i].resultCode);
243             OSHalt("sample2() failed.");
244         }
245     }
246 
247     OSReport("sample2() finished.\n");
248 }
249