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
38 cpu address|rom address |page|task
39 $8000-$bfff|0x00000-0x03fff|0 |write (0x2aaa & 0x3fff) + 0x8000
40 $c000-$dfff|0x04000-0x05fff|2 |write (0x5555 & 0x1fff) + 0xc000
41 $e000-$efff|0x3e000-0x3ffff|fix |boot area
44 cpu address|rom address |page|task
45 $8000-$9fff|0x02000-0x03fff|1 |write (0x2aaa & 0x1fff) + 0x8000
46 $a000-$bfff|0x04000-0x05fff|2 |write (0x5555 & 0x1fff) + 0xa000
47 $c000-$efff|ËöÈø |fix |boot area
49 generic CPU memory bank
50 cpu address|rom address |page|task
51 $8000-$9fff|0x02000-0x03fff|1 |write (0x2aaa & 0x1fff) + 0x8000
52 $a000-$bfff|0x04000-0x05fff|2 |write (0x5555 & 0x1fff) + 0xa000
53 $c000-$dfff|n * 0x2000 |n |write area
54 $e000-$efff|ËöÈø |fix |boot area, ̤»ÈÍÑ
56 generic PPU memory bank
57 ppu address|rom address |page|task
58 $0000-$03ff|0x02800-0x02bff|0x0a|write (0x2aaa & 0x03ff) + 0
59 $0400-$07ff|0x05400-0x057ff|0x15|write (0x5555 & 0x03ff) + 0x400
61 $1000-$1fff|n * 0x0400 |n |write area
64 JEDEC flash memory command
65 http://www.sst.com/downloads/software_driver/SST49LF002A.txt
71 flash_task_end = 0x46494649
73 static const struct flash_task PRODUCTID_ENTRY[] = {
79 static const struct flash_task PRODUCTID_EXIT[] = {
85 static const struct flash_task PROTECT_DISABLE[] = {
91 static const struct flash_task PROTECT_ENABLE[] = {
100 //boot lock lockout enable ¤ò¤¤¤ì¤Ê¤¤¤È¥Ð¥ó¥¯ÀÚ¤êÂؤ¨¤ò¤¹¤ë¤È
101 //ÀèƬ¤Î0x100byte¤°¤é¤¤¤¬½ñ¤´¹¤¨¤é¤ì¤ë?
102 static const struct flash_task BOOTBLOCK_FIRST[] = {
112 static const struct flash_task ERASE[] = {
122 static void task_set(const struct flash_order *d, const struct flash_task *t)
124 while(t->address != flash_task_end){
125 long logical_address = 0;
128 logical_address = d->task_0000;
131 logical_address = d->task_2aaa;
134 logical_address = d->task_5555;
139 d->flash_write(logical_address, t->data);
145 ---- product ID check ----
147 static int productid_check(const struct flash_order *d, const struct flash_driver *f)
150 task_set(d, PRODUCTID_ENTRY);
151 d->read(d->task_0000, 3, data);
152 task_set(d, PRODUCTID_EXIT);
153 if(f->id_manufacurer != data[0]){
156 if(f->id_device != data[1]){
163 ---- toggle check ----
166 const int CHECK_RETRY_MAX = 0x10000;
167 static int toggle_check(const struct flash_order *d, long address)
171 d->read(address, 1, &predata); //read DQ6
173 while(retry < CHECK_RETRY_MAX){
175 d->read(address, 1, &data); //read DQ6 again
187 ---- polling check ----
190 static int polling_check(const struct flash_order *d, long address, u8 truedata)
195 while(retry < CHECK_RETRY_MAX){
197 d->read(address, 1, &data);
199 if(truedata == data){
210 static void flash_erase(const struct flash_order *d)
213 toggle_check(d, d->task_2aaa);
214 //Sleep(200); //Tec 0.2 sec
220 static int program_byte(const struct flash_order *d, long address, const u8 *data, long length)
224 task_set(d, PROTECT_DISABLE);
225 d->flash_write(address, *data);
226 if(toggle_check(d, address) == NG){
228 printf("%s NG\n", __FUNCTION__);
234 d->read(address, 1, &putdata);
235 if(putdata != *data){
236 printf("%s %06x retry\n", __FUNCTION__, (int) address);
241 if((DEBUG == 1) && (address & 0x1f) == 0){
242 printf("%s %06x\n", __FUNCTION__, (int) address);
252 static int program_pagewrite(const struct flash_order *d, long address, const u8 *data, long length)
254 const long toggle_address = address;
255 task_set(d, PROTECT_DISABLE);
257 d->flash_write(address, *data);
263 int ret = toggle_check(d, toggle_address);
267 polling_check(d, address - 1, *data);
270 //task_set(d, PROTECT_ENABLE);
276 ---- block compare ----
278 static void compare(const struct flash_order *d, long address, const u8 *data, long length)
282 romdata = malloc(length);
283 d->read(address, length, romdata);
288 if((count & 7) == 7){
292 printf("%06x%c", (int)address, safix);
305 static void w49f002_write(const struct flash_order *d)
307 program_byte(d, d->address, d->data, d->length);
308 compare(d, d->address, d->data, d->length);
311 static void w29c020_write(const struct flash_order *d)
313 const long pagesize = 0x80;
322 cmp = malloc(pagesize);
324 int result = program_pagewrite(d, a, dd, pagesize);
326 printf("%s: write error\n", __FUNCTION__);
330 d->read(a, pagesize, cmp);
331 if(memcmp(cmp, dd, pagesize) == 0){
342 printf("write ok. retry %d\n", retry);
343 compare(d, d->address, d->data, d->length);
344 task_set(d, BOOTBLOCK_FIRST);
351 static const struct flash_driver DRIVER_W29C020 = {
354 id_manufacurer: 0xda,
356 productid_check: productid_check,
361 static const struct flash_driver DRIVER_W49F002 = {
364 id_manufacurer: 0xda,
366 productid_check: productid_check,
371 static const struct flash_driver *DRIVER_LIST[] = {
372 &DRIVER_W29C020, &DRIVER_W49F002,
376 const struct flash_driver *flash_driver_get(const char *name)
378 const struct flash_driver **d;
381 if(strcmp(name, (*d)->name) == 0){