2 famicom ROM cartridge utility - unagi
5 Copyright (C) 2008 sato_tiff
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.
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.
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
21 flashmemory.c ¤À¤±¤Î·Ù¹ð
22 ¤³¤Î¥½¡¼¥¹¥³¡¼¥É¤ò»²¹Í¡¢Å¾ÍѤ·¤Æ¥·¥§¥¢¥¦¥§¥¢¤Ê¤É¤ÇÍø±×¤òÆÀ¤Ê¤¤¤³¤È¡£
23 ȽÌÀ¤·¤¿¾ì¹ç¤Ï LGPL ¤¬Å¬ÍѤµ¤ì¡¢³ºÅö²Õ½ê¤Î¥½¡¼¥¹¤ò¸ø³«¤¹¤ëɬÍפ¬¤¢¤ë¡£
32 #include "flashmemory.h"
34 driver for Winbond W29C020, W49F002
37 JEDEC flash memory command
38 http://www.sst.com/downloads/software_driver/SST49LF002A.txt
45 ADDRESS_2AAA = 0x2aaa,
46 ADDRESS_5555 = 0x5555,
49 static const struct flash_task PRODUCTID_ENTRY[] = {
53 {FLASH_COMMAND_END, 0}
55 static const struct flash_task PRODUCTID_EXIT[] = {
59 {FLASH_COMMAND_END, 0}
61 static const struct flash_task PROTECT_DISABLE[] = {
65 {FLASH_COMMAND_END, 0}
67 static const struct flash_task PROTECT_ENABLE[] = {
74 {FLASH_COMMAND_END, 0}
76 static const struct flash_task ERASE[] = {
83 {FLASH_COMMAND_END, 0}
86 static const struct flash_task PP[] = {
93 {FLASH_COMMAND_END, 0}
96 static void command_set(const struct flash_order *d, const struct flash_task *t)
98 while(t->address != FLASH_COMMAND_END){
99 long logical_address = 0;
101 case ADDRESS_0000: //bank ¤Ë¤è¤Ã¤Æ¤ÏÀßÄê¤Ç¤¤Ê¤¤¤«¤â?
102 logical_address = d->command_0000;
105 logical_address = d->command_2aaa;
108 logical_address = d->command_5555;
111 assert(0); //unknown task address
113 d->flash_write(logical_address, t->data);
119 ---- product ID check ----
121 static int productid_check(const struct flash_order *d, const struct flash_driver *f)
124 command_set(d, PRODUCTID_ENTRY);
125 d->read(d->command_0000, 3, data);
126 command_set(d, PRODUCTID_EXIT);
127 if(f->id_manufacurer != data[0]){
130 if(f->id_device != data[1]){
137 ---- toggle check ----
140 const int CHECK_RETRY_MAX = 0x10000;
141 static int toggle_check(const struct flash_order *d, long address)
145 d->read(address, 1, &predata); //read DQ6
147 while(retry < CHECK_RETRY_MAX){
149 d->read(address, 1, &data); //read DQ6 again
161 ---- polling check ----
164 static int polling_check(const struct flash_order *d, long address, u8 truedata)
169 while(retry < CHECK_RETRY_MAX){
171 d->read(address, 1, &data);
173 if(truedata == data){
181 static void bootblock_lockout(const struct flash_order *d)
185 d->read(0x8000 ,3, dummy);
186 printf("%02x %02x %02x \n", dummy[0], dummy[1], dummy[2]);
187 d->read(0xfff2 ,1, dummy);
188 command_set(d, PRODUCTID_EXIT);
193 static void flash_erase(const struct flash_order *d)
195 if(0) bootblock_lockout(d);
196 command_set(d, ERASE);
197 toggle_check(d, d->command_2aaa);
198 Sleep(200); //Tec 0.2 sec
204 static int program_byte(const struct flash_order *d, long address, const u8 *data, long length)
209 d->read(address, 1, &dummy);
211 printf("%s %06x\n", __FUNCTION__, (int) address);
213 command_set(d, PROTECT_DISABLE);
214 d->flash_write(address, *data);
215 if(toggle_check(d, address) == NG){
217 printf("%s NG\n", __FUNCTION__);
231 static int program_pagewrite(const struct flash_order *d, long address, const u8 *data, long length)
233 const long toggle_address = address ;
234 command_set(d, PROTECT_DISABLE);
236 d->flash_write(address, *data);
242 int ret = toggle_check(d, toggle_address);
246 polling_check(d, address - 1, *data);
249 //command_set(d, PROTECT_ENABLE);
255 ---- block compare ----
257 static void compare(const struct flash_order *d, long address, const u8 *data, long length)
261 romdata = malloc(length);
262 d->read(address, length, romdata);
267 if((count & 7) == 7){
271 printf("%06x%c", (int)address, safix);
284 static void w49f002_init(const struct flash_order *d)
287 byte program mode ¤Ç¤Ï 1->0 ¤Ë¤¹¤ë¤À¤±¡£ 0->1 ¤Ï erase ¤Î¤ß¡£
288 ¤è¤Ã¤Æ½é´ü²½»þ¤Ë¤Ï erase ¤ò¼Â¹Ô¤¹¤ë
293 static void w49f002_write(const struct flash_order *d, long address, long length, const struct memory *m)
301 compare = malloc(length);
303 if(program_byte(d, address, data, length) == NG){
306 d->read(address, length, compare);
307 writemiss = memcmp(compare, data, length);
309 printf("%s retry error\n", __FUNCTION__);
313 }while(writemiss != 0);
318 static void w29c020_init(const struct flash_order *d)
321 page write mode ¤Ç¤Ï¤È¤¯¤Ë¤Ê¤·
325 static void w29c020_write(const struct flash_order *d, long address, long length, const struct memory *m)
335 cmp = malloc(d->pagesize);
337 int result = program_pagewrite(d, a, dd, d->pagesize);
339 printf("%s: write error\n", __FUNCTION__);
343 d->read(a, d->pagesize, cmp);
344 if(memcmp(cmp, dd, d->pagesize) == 0){
358 printf("write ok. retry %d\n", retry);
359 compare(d, address, m->data, length);
363 static void w29c040_write(const struct flash_order *d, long address, long length, const struct memory *m)
368 cmp = malloc(d->pagesize);
372 long offset = m->offset;
378 d->read(a, d->pagesize, cmp);
379 if(memcmp(cmp, dd, d->pagesize) != 0){
381 printf("write %s 0x%06x\n", m->name, (int) offset);
382 int result = program_pagewrite(d, a, dd, d->pagesize);
384 printf("%s: write error\n", __FUNCTION__);
391 offset += d->pagesize;
394 printf("%s 0x%06x, ngblock %d\n", m->name, (int) offset, ngblock);
395 if(retry >= 3 && ngblock >= 16){
405 }while(ngblock != 0);
408 // compare(d, address, data, length);
415 static const struct flash_driver DRIVER_W29C020 = {
419 .id_manufacurer = 0xda,
421 .productid_check = productid_check,
423 .erase = flash_erase,
425 .init = w29c020_init,
426 .write = w29c020_write
429 static const struct flash_driver DRIVER_W29C040 = {
433 .id_manufacurer = 0xda,
435 .productid_check = productid_check,
437 .erase = flash_erase,
439 .init = w29c020_init,
440 .write = w29c040_write
443 static const struct flash_driver DRIVER_W49F002 = {
447 .id_manufacurer = 0xda,
449 .productid_check = productid_check,
451 .erase = flash_erase,
453 .init = w49f002_init,
454 .write = w49f002_write
457 static const struct flash_driver *DRIVER_LIST[] = {
458 &DRIVER_W29C020, &DRIVER_W29C040, &DRIVER_W49F002,
462 const struct flash_driver *flash_driver_get(const char *name)
464 const struct flash_driver **d;
467 if(strcmp(name, (*d)->name) == 0){