OSDN Git Service

flash driver test 中
[unagi/old-svn-converted.git] / client / trunk / flashmemory.c
1 /*
2 famicom ROM cartridge utility - unagi
3 flash memory driver
4
5 Copyright (C) 2008  sato_tiff
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
21 flashmemory.c ¤À¤±¤Î·Ù¹ð
22 ¤³¤Î¥½¡¼¥¹¥³¡¼¥É¤ò»²¹Í¡¢Å¾ÍѤ·¤Æ¥·¥§¥¢¥¦¥§¥¢¤Ê¤É¤ÇÍø±×¤òÆÀ¤Ê¤¤¤³¤È¡£
23 ȽÌÀ¤·¤¿¾ì¹ç¤Ï LGPL ¤¬Å¬ÍѤµ¤ì¡¢³ºÅö²Õ½ê¤Î¥½¡¼¥¹¤ò¸ø³«¤¹¤ëɬÍפ¬¤¢¤ë¡£
24 */
25 #include <assert.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <windows.h>
30 #include "driver_master.h"
31 #include "flashmemory.h"
32 /*
33 driver for Winbond W29C020, W49F002
34 */
35 /*
36 ----memory detail----
37 VRC6 CPU memory bank
38 cpu address|rom address    |page|task
39 $8000-$bfff|0x00000-0x03fff|0   |write 0x2aaa+0x8000
40 $c000-$dfff|0x04000-0x05fff|2   |write 0x5555+0x8000
41 $e000-$efff|0x3e000-0x3ffff|fix |boot area
42
43 MMC3 CPU memory bank
44 cpu address|rom address    |page|task
45 $8000-$9fff|0x02000-0x03fff|1   |write 0x2aaa+0x8000-0x2000
46 $a000-$bfff|0x04000-0x05fff|2   |write 0x5555+0x8000-0x4000
47 $c000-$efff|ËöÈø           |fix |boot area
48
49 generic CPU memory bank
50 cpu address|rom address    |page|task
51 $8000-$9fff|0x02000-0x03fff|1   |write 0x2aaa+0x8000-0x2000
52 $a000-$bfff|0x04000-0x05fff|2   |write 0x5555+0x8000-0x4000
53 $c000-$dfff|n * 0x2000     |n   |write area
54 $e000-$efff|ËöÈø           |fix |boot area, Ì¤»ÈÍÑ
55
56 generic PPU memory bank
57 ppu address|rom address    |page|task
58 $0000-$03ff|0x02800-0x02bff|0x0a|write 0x2aaa-0x2800
59 $0400-$07ff|0x05400-0x057ff|0x15|write 0x5555-0x5400
60 $0800-$0fff|̤»ÈÍÑ
61 $1000-$1fff|n * 0x0400     |n   |write area
62 */
63 /*
64 JEDEC flash memory command
65 http://www.sst.com/downloads/software_driver/SST49LF002A.txt
66 */
67 struct flash_task{
68         long address, data;
69 };
70 enum{
71         flash_task_end = 0x46494649
72 };
73 static const struct flash_task PRODUCTID_ENTRY[] = {
74         {0x5555, 0xaa},
75         {0x2aaa, 0x55},
76         {0x5555, 0x90},
77         {flash_task_end, 0}
78 };
79 static const struct flash_task PRODUCTID_EXIT[] = {
80         {0x5555, 0xaa},
81         {0x2aaa, 0x55},
82         {0x5555, 0xf0},
83         {flash_task_end, 0}
84 };
85 static const struct flash_task PROTECT_DISABLE[] = {
86         {0x5555, 0xaa},
87         {0x2aaa, 0x55},
88         {0x5555, 0xa0},
89         {flash_task_end, 0}
90 };
91 static const struct flash_task PROTECT_ENABLE[] = {
92         {0x5555, 0xaa},
93         {0x2aaa, 0x55},
94         {0x5555, 0x80},
95         {0x5555, 0xaa},
96         {0x2aaa, 0x55},
97         {0x5555, 0x20},
98         {flash_task_end, 0}
99 };
100 static const struct flash_task ERASE[] = {
101         {0x5555, 0xaa},
102         {0x2aaa, 0x55},
103         {0x5555, 0x80},
104         {0x5555, 0xaa},
105         {0x2aaa, 0x55},
106         {0x5555, 0x10},
107         {flash_task_end, 0}
108 };
109
110 static void task_set(const struct reader_driver *d, const struct flash_task *t, long address_2aaa, long address_5555)
111 {
112         while(t->address != flash_task_end){
113                 long cpu_address = 0;
114                 switch(t->address){
115                 case 0x2aaa:
116                         cpu_address = address_2aaa;
117                         break;
118                 case 0x5555:
119                         cpu_address = address_5555;
120                         break;
121                 default:
122                         assert(0);
123                 }
124                 d->cpu_flash_write(cpu_address, t->data);
125                 t++;
126         }
127 }
128
129 /*
130 ---- product ID check ----
131 */
132 static int productid_check(const struct reader_driver *d, const struct flash_driver *f, long address_0000, long address_2aaa, long address_5555)
133 {
134         u8 data[2];
135         task_set(d, PRODUCTID_ENTRY, address_2aaa, address_5555);
136         d->cpu_read(address_0000, 2, data);
137         task_set(d, PRODUCTID_EXIT, address_2aaa, address_5555);
138         if(f->id_manufacurer != data[0]){
139                 return NG;
140         }
141         if(f->id_device != data[1]){
142                 return NG;
143         }
144         return OK;
145 }
146
147 /*
148 ---- toggle check ----
149 databit6
150 */
151 const int CHECK_RETRY_MAX = 0x10000;
152 static int toggle_check(const struct reader_driver *d, long address)
153 {
154         u8 predata;
155         int retry = 0;
156         d->cpu_read(address, 1, &predata); //read DQ6
157         predata &= 0x40;
158         while(retry < CHECK_RETRY_MAX){
159                 u8 data;
160                 d->cpu_read(address, 1, &data); //read DQ6 again
161                 data &= 0x40;
162                 if(predata == data){
163                         return OK;
164                 }
165                 predata = data;
166                 retry++;
167         }
168         return NG;
169 }
170
171 /*
172 ---- polling check ----
173 databit7
174 */
175 static int polling_check(const struct reader_driver *d, long address, u8 truedata)
176 {
177         int retry = 0;
178         
179         truedata &= 0x80;
180         while(retry < CHECK_RETRY_MAX){
181                 u8 data;
182                 d->cpu_read(address, 1, &data);
183                 data &= 0x80;
184                 if(truedata == data){
185                         return OK;
186                 }
187                 retry++;
188         }
189         return NG;
190 }
191
192 /*
193 ---- erase ----
194 */
195 static void flash_erase(const struct reader_driver *d, long address_2aaa, long address_5555)
196 {
197         task_set(d, ERASE, address_2aaa, address_5555);
198         toggle_check(d, address_2aaa);
199         //Sleep(200); //Tec 0.2 sec
200 }
201
202 /*
203 ---- program ----
204 */
205 static int program_byte(const struct reader_driver *d, long address, const u8 *data, long length, long address_2aaa, long address_5555)
206 {
207         while(length != 0){
208                 if(*data != 0xff){
209                         task_set(d, PROTECT_DISABLE, address_2aaa, address_5555);
210                         d->cpu_flash_write(address, *data);
211                 }
212                 if(toggle_check(d, address) == NG){
213                         return NG;
214                 }
215                 address++;
216                 data++;
217                 length--;
218         }
219         return OK;
220 }
221
222 static int program_pagewrite(const struct reader_driver *d, long address, const u8 *data, long length, long address_2aaa, long address_5555)
223 {
224         task_set(d, PROTECT_DISABLE, address_2aaa, address_5555);
225         while(length != 0){
226                 d->cpu_flash_write(address, *data);
227                 address++;
228                 data++;
229                 length--;
230         }
231         Sleep(1);
232         return toggle_check(d, address);
233 }
234
235 /*
236 ---- block compare ----
237 */
238 static void compare(const struct reader_driver *d, long address, const u8 *data, long length)
239 {
240         u8 *romdata, *r;
241         romdata = malloc(length);
242         d->cpu_read(address, length, romdata);
243         r = romdata;
244         while(length != 0){
245                 if(*r != *data){
246                         printf("%06x\n", (int)address);
247                 }
248                 r++;
249                 data++;
250                 address++;
251                 length--;
252         }
253         free(romdata);
254 }
255
256 /*
257 ¸ÇÍ­¥Ç¥Ð¥¤¥¹¥É¥é¥¤¥Ð
258 */
259 static void w49f002_write(const struct reader_driver *d, long address, const u8 *data, long length, long address_2aaa, long address_5555)
260 {
261         program_byte(d, address, data, length, address_2aaa, address_5555);
262         compare(d, address, data, length);
263 }
264
265 static void w29c020_write(const struct reader_driver *d, long address, const u8 *data, long length, long address_2aaa, long address_5555)
266 {
267         {
268                 const long pagesize = 0x80;
269                 long a = address;
270                 long i = length;
271                 const u8 *dd;
272                 dd = data;
273                 while(i >= 0){
274                         int result = program_pagewrite(d, a, dd, pagesize, address_2aaa, address_5555);
275                         if(result == NG){
276                                 return;
277                         }
278                         a += pagesize;
279                         dd += pagesize;
280                         i -= pagesize;
281                 }
282         }
283         compare(d, address, data, length);
284 }
285
286 /*
287 ¥Ç¥Ð¥¤¥¹¥ê¥¹¥È
288 */
289 static const struct flash_driver DRIVER_W29C020 = {
290         name: "W29C020",
291         capacity: 0x40000,
292         id_manufacurer: 0xda,
293         id_device: 0x45,
294         productid_check: productid_check,
295         erase: flash_erase,
296         write: w29c020_write
297 };
298
299 static const struct flash_driver DRIVER_W49F002 = {
300         name: "W49F002",
301         capacity: 0x40000,
302         id_manufacurer: 0xda,
303         id_device: 0xae,
304         productid_check: productid_check,
305         erase: flash_erase,
306         write: w49f002_write
307 };
308
309 static const struct flash_driver *DRIVER_LIST[] = {
310         &DRIVER_W29C020, &DRIVER_W49F002,
311         NULL
312 };
313
314 const struct flash_driver *flash_driver_get(const char *name)
315 {
316         const struct flash_driver **d;
317         d = DRIVER_LIST;
318         while(*d != NULL){
319                 if(strcmp(name, (*d)->name) == 0){
320                         return *d;
321                 }
322                 d++;
323         }
324         return NULL;
325 }