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 ¤¬Å¬ÍѤµ¤ì¡¢³ºÅö²Õ½ê¤Î¥½¡¼¥¹¤ò¸ø³«¤¹¤ëɬÍפ¬¤¢¤ë¡£
31 #include "flashmemory.h"
33 driver for Winbond W29C020, W49F002
36 JEDEC flash memory command
37 http://www.sst.com/downloads/software_driver/SST49LF002A.txt
44 ADDRESS_2AAA = 0x2aaa,
45 ADDRESS_5555 = 0x5555,
48 static const struct flash_task PRODUCTID_ENTRY[] = {
52 {FLASH_COMMAND_END, 0}
54 static const struct flash_task PRODUCTID_EXIT[] = {
58 {FLASH_COMMAND_END, 0}
60 static const struct flash_task PROTECT_DISABLE[] = {
64 {FLASH_COMMAND_END, 0}
66 static const struct flash_task PROTECT_ENABLE[] = {
73 {FLASH_COMMAND_END, 0}
75 static const struct flash_task ERASE[] = {
82 {FLASH_COMMAND_END, 0}
85 static const struct flash_task PP[] = {
92 {FLASH_COMMAND_END, 0}
95 static void command_set(const struct flash_order *d, const struct flash_task *t)
97 while(t->address != FLASH_COMMAND_END){
98 long logical_address = 0;
100 case ADDRESS_0000: //bank ¤Ë¤è¤Ã¤Æ¤ÏÀßÄê¤Ç¤¤Ê¤¤¤«¤â?
101 logical_address = d->command_0000;
104 logical_address = d->command_2aaa;
107 logical_address = d->command_5555;
110 assert(0); //unknown task address
112 d->flash_write(logical_address, t->data);
118 ---- product ID check ----
120 static int productid_check(const struct flash_order *d, const struct flash_driver *f)
123 command_set(d, PRODUCTID_ENTRY);
124 d->read(d->command_0000, 3, data);
125 command_set(d, PRODUCTID_EXIT);
126 if(f->id_manufacurer != data[0]){
129 if(f->id_device != data[1]){
136 ---- toggle check ----
139 const int CHECK_RETRY_MAX = 0x10000;
140 static int toggle_check(const struct flash_order *d, long address)
144 d->read(address, 1, &predata); //read DQ6
146 while(retry < CHECK_RETRY_MAX){
148 d->read(address, 1, &data); //read DQ6 again
160 ---- polling check ----
163 static int polling_check(const struct flash_order *d, long address, u8 truedata)
168 while(retry < CHECK_RETRY_MAX){
170 d->read(address, 1, &data);
172 if(truedata == data){
180 static void bootblock_lockout(const struct flash_order *d)
184 d->read(0x8000 ,3, dummy);
185 printf("%02x %02x %02x \n", dummy[0], dummy[1], dummy[2]);
186 d->read(0xfff2 ,1, dummy);
187 command_set(d, PRODUCTID_EXIT);
192 static void flash_erase(const struct flash_order *d)
194 if(0) bootblock_lockout(d);
195 command_set(d, ERASE);
196 toggle_check(d, d->command_2aaa);
197 Sleep(200); //Tec 0.2 sec
203 static int program_byte(const struct flash_order *d, long address, const u8 *data, long length)
207 command_set(d, PROTECT_DISABLE);
208 d->flash_write(address, *data);
209 if(toggle_check(d, address) == NG){
211 printf("%s NG\n", __FUNCTION__);
217 if((DEBUG == 1) && (address & 0x1f) == 0){
218 printf("%s %06x\n", __FUNCTION__, (int) address);
228 static int program_pagewrite(const struct flash_order *d, long address, const u8 *data, long length)
230 const long toggle_address = address;
231 command_set(d, PROTECT_DISABLE);
233 d->flash_write(address, *data);
239 int ret = toggle_check(d, toggle_address);
243 polling_check(d, address - 1, *data);
246 //command_set(d, PROTECT_ENABLE);
252 ---- block compare ----
254 static void compare(const struct flash_order *d, long address, const u8 *data, long length)
258 romdata = malloc(length);
259 d->read(address, length, romdata);
264 if((count & 7) == 7){
268 printf("%06x%c", (int)address, safix);
281 static void w49f002_init(const struct flash_order *d)
284 byte program mode ¤Ç¤Ï 1->0 ¤Ë¤¹¤ë¤À¤±¡£ 0->1 ¤Ï erase ¤Î¤ß¡£
285 ¤è¤Ã¤Æ½é´ü²½»þ¤Ë¤Ï erase ¤ò¼Â¹Ô¤¹¤ë
290 static void w49f002_write(const struct flash_order *d, long address, long length, const u8 *data)
292 program_byte(d, address, data, length);
293 compare(d, address, data, length);
296 static void w29c020_init(const struct flash_order *d)
299 page write mode ¤Ç¤Ï¤È¤¯¤Ë¤Ê¤·
303 static void w29c020_write(const struct flash_order *d, long address, long length, const u8 *data)
305 const long pagesize = 0x80;
314 cmp = malloc(pagesize);
316 int result = program_pagewrite(d, a, dd, pagesize);
318 printf("%s: write error\n", __FUNCTION__);
322 d->read(a, pagesize, cmp);
323 if(memcmp(cmp, dd, pagesize) == 0){
337 printf("write ok. retry %d\n", retry);
338 compare(d, address, data, length);
342 static void w29c040_write(const struct flash_order *d, long address, long length, const u8 *data)
344 const long pagesize = 0x100;
347 cmp = malloc(pagesize);
356 d->read(a, pagesize, cmp);
357 if(memcmp(cmp, dd, pagesize) != 0){
359 printf("write %x\n", (int) a);
360 int result = program_pagewrite(d, a, dd, pagesize);
362 printf("%s: write error\n", __FUNCTION__);
371 printf("ngblock %d\n", ngblock);
373 }while(ngblock != 0);
376 compare(d, address, data, length);
383 static const struct flash_driver DRIVER_W29C020 = {
386 .id_manufacurer = 0xda,
388 .productid_check = productid_check,
390 .erase = flash_erase,
392 .init = w29c020_init,
393 .write = w29c020_write
396 static const struct flash_driver DRIVER_W29C040 = {
399 .id_manufacurer = 0xda,
401 .productid_check = productid_check,
403 .erase = flash_erase,
405 .init = w29c020_init,
406 .write = w29c040_write
409 static const struct flash_driver DRIVER_W49F002 = {
412 .id_manufacurer = 0xda,
414 .productid_check = productid_check,
416 .erase = flash_erase,
418 .init = w49f002_init,
419 .write = w49f002_write
422 static const struct flash_driver *DRIVER_LIST[] = {
423 &DRIVER_W29C020, &DRIVER_W29C040, &DRIVER_W49F002,
427 const struct flash_driver *flash_driver_get(const char *name)
429 const struct flash_driver **d;
432 if(strcmp(name, (*d)->name) == 0){