OSDN Git Service

54099137a2918818d23e5dd1450951babd69276b
[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-2009 ±·³«È¯¶¨Æ±Áȹç
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 "type.h"
31 #include "header.h"
32 #include "flashmemory.h"
33 /*
34 JEDEC flash memory command
35 http://www.sst.com/downloads/software_driver/SST49LF002A.txt
36 */
37 struct flash_task{
38         long address, data;
39 };
40 enum{
41         ADDRESS_0000 = 0,
42         ADDRESS_2AAA = 0x2aaa,
43         ADDRESS_5555 = 0x5555,
44         FLASH_COMMAND_END
45 };
46 static const struct flash_task PRODUCTID_ENTRY[] = {
47         {ADDRESS_5555, 0xaa},
48         {ADDRESS_2AAA, 0x55},
49         {ADDRESS_5555, 0x90},
50         {FLASH_COMMAND_END, 0}
51 };
52 static const struct flash_task PRODUCTID_EXIT[] = {
53         {ADDRESS_5555, 0xaa},
54         {ADDRESS_2AAA, 0x55},
55         {ADDRESS_5555, 0xf0},
56         {FLASH_COMMAND_END, 0}
57 };
58 static const struct flash_task PROTECT_DISABLE[] = {
59         {ADDRESS_5555, 0xaa},
60         {ADDRESS_2AAA, 0x55},
61         {ADDRESS_5555, 0xa0},
62         {FLASH_COMMAND_END, 0}
63 };
64 static const struct flash_task PROTECT_ENABLE[] = {
65         {ADDRESS_5555, 0xaa},
66         {ADDRESS_2AAA, 0x55},
67         {ADDRESS_5555, 0x80},
68         {ADDRESS_5555, 0xaa},
69         {ADDRESS_2AAA, 0x55},
70         {ADDRESS_5555, 0x20},
71         {FLASH_COMMAND_END, 0}
72 };
73 static const struct flash_task ERASE_CHIP[] = {
74         {ADDRESS_5555, 0xaa},
75         {ADDRESS_2AAA, 0x55},
76         {ADDRESS_5555, 0x80},
77         {ADDRESS_5555, 0xaa},
78         {ADDRESS_2AAA, 0x55},
79         {ADDRESS_5555, 0x10},
80         {FLASH_COMMAND_END, 0}
81 };
82
83 static const struct flash_task ERASE_SECTOR[] = {
84         {ADDRESS_5555, 0xaa},
85         {ADDRESS_2AAA, 0x55},
86         {ADDRESS_5555, 0x80},
87         {ADDRESS_5555, 0xaa},
88         {ADDRESS_2AAA, 0x55},
89         //¤³¤Î¤¢¤È sectoraddress ¤Ë 0x30 ¤ò write
90         {FLASH_COMMAND_END, 0}
91 };
92
93 static const struct flash_task PP[] = {
94         {ADDRESS_5555, 0xaa},
95         {ADDRESS_2AAA, 0x55},
96         {ADDRESS_5555, 0x80},
97         {ADDRESS_5555, 0xaa},
98         {ADDRESS_2AAA, 0x55},
99         {ADDRESS_5555, 0x60},
100         {FLASH_COMMAND_END, 0}
101 };
102
103 static void command_set(const struct flash_order *d, const struct flash_task *t)
104 {
105         while(t->address != FLASH_COMMAND_END){
106                 long logical_address = 0;
107                 switch(t->address){
108                 case ADDRESS_0000: //bank ¤Ë¤è¤Ã¤Æ¤ÏÀßÄê¤Ç¤­¤Ê¤¤¤«¤â?
109                         logical_address = d->command_0000;
110                         break;
111                 case ADDRESS_2AAA:
112                         logical_address = d->command_2aaa;
113                         break;
114                 case ADDRESS_5555:
115                         logical_address = d->command_5555;
116                         break;
117                 default:
118                         assert(0); //unknown task address
119                 }
120                 d->flash_write(logical_address, t->data);
121                 t++;
122         }
123 }
124
125 /*
126 ---- product ID check ----
127 */
128 #define dprintf if(DEBUG==1) printf
129 static int productid_check(const struct flash_order *d, const struct flash_driver *f)
130 {
131         u8 data[3];
132         command_set(d, PRODUCTID_ENTRY);
133         d->read(d->command_0000, 3, data);
134         command_set(d, PRODUCTID_EXIT);
135         if(f->id_manufacurer != data[0]){
136                 return NG;
137         }
138         if(f->id_device != data[1]){
139                 return NG;
140         }
141         return OK;
142 }
143
144 static int productid_sram(const struct flash_order *d, const struct flash_driver *f)
145 {
146         return OK;
147 }
148 /*
149 ---- toggle check ----
150 databit6
151 */
152 const int CHECK_RETRY_MAX = 0x10000;
153 static int toggle_check_d6(const struct flash_order *d, long address)
154 {
155         u8 predata;
156         int retry = 0;
157         d->read(address, 1, &predata); //read DQ6
158         predata &= 0x40;
159         while(retry < CHECK_RETRY_MAX){
160                 u8 data;
161                 d->read(address, 1, &data); //read DQ6 again
162                 data &= 0x40;
163                 if(predata == data){
164                         return OK;
165                 }
166                 predata = data;
167                 retry++;
168         }
169         return NG;
170 }
171
172 static int toggle_check_d2d5d6(const struct flash_order *d, long address)
173 {
174         u8 predata;
175         int retry = 0;
176         d->read(address, 1, &predata);
177         predata &= 0x40;
178         do{
179                 u8 data;
180                 d->read(address, 1, &data);
181                 //DQ6 toggle check
182                 if(predata == (data & 0x40)){
183                         return OK;
184                 }
185                 //DQ5 == 0 ¤Ê¤é¤ä¤ê¤Ê¤ª¤·
186                 if(data & 0x20){
187                         //recheck toggle bit, read twice
188                         u8 t[2];
189                         d->read(address, 1, &t[0]);
190                         d->read(address, 1, &t[1]);
191                         if((t[0] & 0x40) == (t[1] & 0x40)){
192                                 return OK;
193                         }
194                         //Program/Erase operation not complete, write reset command.
195                         return NG;
196                 }
197                 if((retry & 0x0f) == 0){
198                         dprintf("toggle out %06x \n", (int) address);
199                 }
200                 retry++;
201         }while(retry < CHECK_RETRY_MAX);
202         return NG;
203 }
204
205 /*
206 ---- polling check ----
207 databit7
208 */
209 static int polling_check_d7(const struct flash_order *d, long address, u8 truedata)
210 {
211         int retry = 0;
212         
213         truedata &= 0x80;
214         while(retry < CHECK_RETRY_MAX){
215                 u8 data;
216                 d->read(address, 1, &data);
217                 data &= 0x80;
218                 if(truedata == data){
219                         return OK;
220                 }
221                 retry++;
222         }
223         return NG;
224 }
225
226 static int polling_check_d5d7(const struct flash_order *d, long address, u8 truedata)
227 {
228         int retry = 0;
229         
230         truedata &= 0x80;
231         do{
232                 u8 data;
233                 d->read(address, 1, &data);
234                 if(truedata == (data & 0x80)){
235                         return OK;
236                 }
237                 if(data & 0x20){
238                         d->read(address, 1, &data);
239                         if(truedata == (data & 0x80)){
240                                 return OK;
241                         }
242                         dprintf("%s error", __FUNCTION__);
243                         return NG;
244                 }
245                 retry++;
246         }while(retry < CHECK_RETRY_MAX);
247         return NG;
248 }
249 /*
250 ---- erase ----
251 */
252 static void flash_erase_chip_2aaa(const struct flash_order *d)
253 {
254         command_set(d, ERASE_CHIP);
255         toggle_check_d6(d, d->command_2aaa);
256         Sleep(d->erase_wait);
257 }
258
259 static void flash_erase_chip_02aa(const struct flash_order *d)
260 {
261         u8 data;
262         d->read(d->command_2aaa, 1, &data);
263         command_set(d, ERASE_CHIP);
264         if(0){
265                 toggle_check_d2d5d6(d, d->command_2aaa);
266                 
267         }else{
268                 polling_check_d5d7(d, d->command_2aaa, data);
269         }
270         Sleep(d->erase_wait);
271 }
272
273 #if DEBUG==1
274 static void sram_erase(const struct flash_order *d)
275 {
276         //bank ÀÚ¤êÂؤ¨¤¬È¼¤¦¤Î¤Ç¼ÂÁõ¤Ç¤­¤Ê¤¤
277 }
278 #endif
279
280 /*
281 ---- program ----
282 */
283 static int program_byte(const struct flash_order *d, long address, const u8 *data, long length)
284 {
285         while(length != 0){
286                 if(*data != 0xff){
287                         fflush(stdout);
288                         command_set(d, PROTECT_DISABLE);
289                         d->flash_write(address, *data);
290                         if(toggle_check_d6(d, address) == NG){
291                                 dprintf("%s NG\n", __FUNCTION__);
292                                 return NG;
293                         }
294                         /*if(polling_check_d7(d, address, *data) == NG){
295                                 dprintf("%s NG\n", __FUNCTION__);
296                                 return NG;
297                         }*/
298                 }
299                 address++;
300                 data++;
301                 length--;
302         }
303         return OK;
304 }
305
306 static int program_pagewrite(const struct flash_order *d, long address, const u8 *data, long length)
307 {
308         const long toggle_address = address ;
309         command_set(d, PROTECT_DISABLE);
310         while(length != 0){
311                 d->flash_write(address, *data);
312                 address++;
313                 data++;
314                 length--;
315         }
316         int ret = toggle_check_d6(d, toggle_address);
317         if(0){
318                 data--;
319                 polling_check_d7(d, address - 1, *data);
320         }
321
322         return ret;
323 }
324
325 /*
326 ¸ÇÍ­¥Ç¥Ð¥¤¥¹¥É¥é¥¤¥Ð
327 */
328 static void w49f002_init(const struct flash_order *d)
329 {
330 /*
331 byte program mode ¤Ç¤Ï 1->0 ¤Ë¤¹¤ë¤À¤±¡£ 0->1 ¤Ï erase ¤Î¤ß¡£
332 ¤è¤Ã¤Æ½é´ü²½»þ¤Ë¤Ï erase ¤ò¼Â¹Ô¤¹¤ë
333 */
334         flash_erase_chip_2aaa(d);
335 }
336
337 static void w49f002_write(const struct flash_order *d, long address, long length, const struct memory *m)
338 {
339         program_byte(d, address, m->data, length);
340 //      dprintf("write %s 0x%06x done\n", m->name, (int) m->offset);
341 }
342
343 static void am29f040_init(const struct flash_order *d)
344 {
345         flash_erase_chip_02aa(d);
346 }
347
348 static void am29f040_write(const struct flash_order *d, long address, long length, const struct memory *m)
349 {
350         const u8 *data;
351         data = m->data;
352         while(length != 0){
353                 if(*data != 0xff){
354                         command_set(d, PROTECT_DISABLE);
355                         d->flash_write(address, *data);
356                         if(toggle_check_d2d5d6(d, address) == NG){
357                                 dprintf("%s NG\n", __FUNCTION__);
358                                 return;
359                         }
360                 }
361                 address++;
362                 data++;
363                 length--;
364         }
365 }
366
367 static void init_nop(const struct flash_order *d)
368 {
369 /*
370 page write mode ¤Ç¤Ï¤È¤¯¤Ë¤Ê¤·
371 */
372 }
373
374 static void w29c040_write(const struct flash_order *d, long address, long length, const struct memory *m)
375 {
376         u8 *cmp;
377         int ngblock = 0;
378         int retry = 0;
379         assert(d->pagesize != 0);
380         cmp = malloc(d->pagesize);
381         do{
382                 long a = address;
383                 long i = length;
384                 long offset = m->offset;
385                 const u8 *dd;
386
387                 dd = m->data;
388                 ngblock = 0;
389                 while(i != 0){
390                         d->read(a, d->pagesize, cmp);
391                         if(memcmp(cmp, dd, d->pagesize) != 0){
392                                 ngblock++;
393                                 //dprintf("write %s 0x%06x\n", m->name, (int) offset);
394                                 int result = program_pagewrite(d, a, dd, d->pagesize);
395                                 if(result == NG){
396                                         printf("%s: write error\n", __FUNCTION__);
397                                         free(cmp);
398                                         return;
399                                 }
400                         }
401                         a += d->pagesize;
402                         dd += d->pagesize;
403                         offset += d->pagesize;
404                         i -= d->pagesize;
405                 }
406                 dprintf("%s 0x%06x, ngblock %d\n", m->name, (int) m->offset, ngblock);
407                 /* mmc5 test
408                 if(retry >= 3 && ngblock >= 16){
409                         dprintf("skip\n");
410                         break;
411                 }*/
412                 if(retry > 80){
413                         dprintf("skip\n");
414                         break;
415                 }
416                 retry++;
417                 fflush(stdout);
418         }while(ngblock != 0);
419
420         free(cmp);
421 }
422
423 static void sram_write(const struct flash_order *d, long address, long length, const struct memory *m)
424 {
425         const u8 *data;
426         data = m->data;
427         while(length != 0){
428                 d->flash_write(address, *data);
429                 address++;
430                 data++;
431                 length--;
432         }
433 }
434
435 static void dummy_write(const struct flash_order *d, long address, long length, const struct memory *m)
436 {
437 }
438
439 /*
440 ¥Ç¥Ð¥¤¥¹¥ê¥¹¥È
441 */
442 //0x80 °Ê¹ß¤ÏËÜÅö¤Î¥Ç¥Ð¥¤¥¹½ÅÊ£¤·¤Ê¤¤¤È»×¤¦. Ã¯¤« JEDEC ¤Î¤È¤³¤ò¤·¤é¤Ù¤Æ.
443 static const struct flash_driver DRIVER_SRAM256K = {
444         .name = "SRAM256K",
445         .capacity = 0x8000,
446         .pagesize = 0,
447         .erase_wait = 0,
448         .command_mask = 0,
449         .id_manufacurer = FLASH_ID_DEVICE_SRAM,
450         .id_device = FLASH_ID_DEVICE_SRAM,
451         .productid_check = productid_sram,
452 #if DEBUG==1
453         .erase = sram_erase,
454 #endif
455         .init = init_nop,
456         .write = sram_write
457 };
458
459 static const struct flash_driver DRIVER_DUMMY = {
460         .name = "dummy",
461         .capacity = 0x40000,
462         .pagesize = 0,
463         .erase_wait = 0,
464         .command_mask = 0,
465         .id_manufacurer = FLASH_ID_DEVICE_DUMMY,
466         .id_device = FLASH_ID_DEVICE_DUMMY,
467         .productid_check = productid_sram,
468 #if DEBUG==1
469         .erase = init_nop,
470 #endif
471         .init = init_nop,
472         .write = dummy_write
473 };
474
475 static const struct flash_driver DRIVER_W29C020 = {
476         .name = "W29C020",
477         .capacity = 0x40000,
478         .pagesize = 0x80,
479         .erase_wait = 50,
480         .command_mask = 0x7fff,
481         .id_manufacurer = 0xda,
482         .id_device = 0x45,
483         .productid_check = productid_check,
484 #if DEBUG==1
485         .erase = flash_erase_chip_2aaa,
486 #endif
487         .init = init_nop,
488         .write = w29c040_write
489 };
490
491 static const struct flash_driver DRIVER_W29C040 = {
492         .name = "W29C040",
493         .capacity = 0x80000,
494         .pagesize = 0x100,
495         .erase_wait = 50,
496         .command_mask = 0x7fff,
497         .id_manufacurer = 0xda,
498         .id_device = 0x46,
499         .productid_check = productid_check,
500 #if DEBUG==1
501         .erase = flash_erase_chip_2aaa,
502 #endif
503         .init = init_nop,
504         .write = w29c040_write
505 };
506
507 static const struct flash_driver DRIVER_W49F002 = {
508         .name = "W49F002",
509         .capacity = 0x40000,
510         .pagesize = 0,
511         .erase_wait = 1000, //typ 0.1, max 0.2 sec
512         .command_mask = 0x7fff,
513         .id_manufacurer = 0xda,
514         .id_device = 0xae,
515         .productid_check = productid_check,
516 #if DEBUG==1
517         .erase = flash_erase_chip_2aaa,
518 #endif
519         .init = w49f002_init,
520         .write = w49f002_write
521 };
522
523 /*
524 MANUFATUTER ID 0x7f1c
525 EN29F002T DEVICE ID 0x7f92
526 EN29F002B DEVICE ID 0x7f97
527
528 command address ¤¬ 0x00555, 0x00aaa ¤Ë¤Ê¤Ã¤Æ¤ë
529 */
530 static const struct flash_driver DRIVER_EN29F002T = {
531         .name = "EN29F002T",
532         .capacity = 0x40000,
533         .pagesize = 0,
534         .erase_wait = 3000, //typ 2, max 5 sec
535         .command_mask = 0x07ff,
536         .id_manufacurer = 0x1c,
537         .id_device = 0x92,
538         .productid_check = productid_check,
539 #if DEBUG==1
540         .erase = flash_erase_chip_02aa,
541 #endif
542         .init = am29f040_init,
543         .write = am29f040_write
544 };
545
546 static const struct flash_driver DRIVER_AM29F040B = {
547         .name = "AM29F040B",
548         .capacity = 0x80000,
549         .pagesize = 0,
550         .erase_wait = 8000, //typ 8, max 64 sec
551         .command_mask = 0x07ff,
552         .id_manufacurer = 0x01,
553         .id_device = 0xa4,
554         .productid_check = productid_check,
555 #if DEBUG==1
556         .erase = flash_erase_chip_02aa,
557 #endif
558         .init = am29f040_init,
559         .write = am29f040_write
560 };
561
562 static const struct flash_driver *DRIVER_LIST[] = {
563         &DRIVER_W29C020, &DRIVER_W29C040, 
564         &DRIVER_W49F002, &DRIVER_EN29F002T, &DRIVER_AM29F040B,
565         &DRIVER_SRAM256K, 
566         &DRIVER_DUMMY,
567         NULL
568 };
569
570 const struct flash_driver *flash_driver_get(const char *name)
571 {
572         const struct flash_driver **d;
573         d = DRIVER_LIST;
574         while(*d != NULL){
575                 if(strcmp(name, (*d)->name) == 0){
576                         return *d;
577                 }
578                 d++;
579         }
580         return NULL;
581 }