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 ¤¬Å¬ÍѤµ¤ì¡¢³ºÅö²Õ½ê¤Î¥½¡¼¥¹¤ò¸ø³«¤¹¤ëɬÍפ¬¤¢¤ë¡£
30 #include "driver_master.h"
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+0x8000
40 $c000-$dfff|0x04000-0x05fff|2 |write 0x5555+0x8000
41 $e000-$efff|0x3e000-0x3ffff|fix |boot area
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
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, ̤»ÈÍÑ
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
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 static const struct flash_task ERASE[] = {
110 static void task_set(const struct reader_driver *d, const struct flash_task *t, long address_2aaa, long address_5555)
112 while(t->address != flash_task_end){
113 long cpu_address = 0;
116 cpu_address = address_2aaa;
119 cpu_address = address_5555;
124 d->cpu_flash_write(cpu_address, t->data);
130 ---- product ID check ----
132 static int productid_check(const struct reader_driver *d, const struct flash_driver *f, long address_0000, long address_2aaa, long address_5555)
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]){
141 if(f->id_device != data[1]){
148 ---- toggle check ----
151 const int CHECK_RETRY_MAX = 0x10000;
152 static int toggle_check(const struct reader_driver *d, long address)
156 d->cpu_read(address, 1, &predata); //read DQ6
158 while(retry < CHECK_RETRY_MAX){
160 d->cpu_read(address, 1, &data); //read DQ6 again
172 ---- polling check ----
175 static int polling_check(const struct reader_driver *d, long address, u8 truedata)
180 while(retry < CHECK_RETRY_MAX){
182 d->cpu_read(address, 1, &data);
184 if(truedata == data){
195 static void flash_erase(const struct reader_driver *d, long address_2aaa, long address_5555)
197 task_set(d, ERASE, address_2aaa, address_5555);
198 toggle_check(d, address_2aaa);
199 //Sleep(200); //Tec 0.2 sec
205 static int program_byte(const struct reader_driver *d, long address, const u8 *data, long length, long address_2aaa, long address_5555)
209 task_set(d, PROTECT_DISABLE, address_2aaa, address_5555);
210 d->cpu_flash_write(address, *data);
212 if(toggle_check(d, address) == NG){
222 static int program_pagewrite(const struct reader_driver *d, long address, const u8 *data, long length, long address_2aaa, long address_5555)
224 task_set(d, PROTECT_DISABLE, address_2aaa, address_5555);
226 d->cpu_flash_write(address, *data);
232 return toggle_check(d, address);
236 ---- block compare ----
238 static void compare(const struct reader_driver *d, long address, const u8 *data, long length)
241 romdata = malloc(length);
242 d->cpu_read(address, length, romdata);
246 printf("%06x\n", (int)address);
259 static void w49f002_write(const struct reader_driver *d, long address, const u8 *data, long length, long address_2aaa, long address_5555)
261 program_byte(d, address, data, length, address_2aaa, address_5555);
262 compare(d, address, data, length);
265 static void w29c020_write(const struct reader_driver *d, long address, const u8 *data, long length, long address_2aaa, long address_5555)
268 const long pagesize = 0x80;
274 int result = program_pagewrite(d, a, dd, pagesize, address_2aaa, address_5555);
283 compare(d, address, data, length);
289 static const struct flash_driver DRIVER_W29C020 = {
292 id_manufacurer: 0xda,
294 productid_check: productid_check,
299 static const struct flash_driver DRIVER_W49F002 = {
302 id_manufacurer: 0xda,
304 productid_check: productid_check,
309 static const struct flash_driver *DRIVER_LIST[] = {
310 &DRIVER_W29C020, &DRIVER_W49F002,
314 const struct flash_driver *flash_driver_get(const char *name)
316 const struct flash_driver **d;
319 if(strcmp(name, (*d)->name) == 0){