X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=client%2Ftag%2F0.6.2%2Fanago%2Fscript_flash.c;fp=client%2Ftag%2F0.6.2%2Fanago%2Fscript_flash.c;h=5d8b449aca8b9524390e2197dc8ccaf0d7e5b06b;hb=fd3c4aad1e26f9baf71607fae8d65a3fee88c6f5;hp=0000000000000000000000000000000000000000;hpb=a124c9eabff6604ad8ccaa2816bd2248d0d4ce12;p=unagi%2Fold-svn-converted.git diff --git a/client/tag/0.6.2/anago/script_flash.c b/client/tag/0.6.2/anago/script_flash.c new file mode 100644 index 0000000..5d8b449 --- /dev/null +++ b/client/tag/0.6.2/anago/script_flash.c @@ -0,0 +1,466 @@ +#include +#include +#include +#include +#include +#include +#include +#include "type.h" +#include "header.h" +#include "memory_manage.h" +#include "reader_master.h" +#include "squirrel_wrap.h" +#include "flash_device.h" +#include "progress.h" +#include "script_common.h" +#include "script_flash.h" + +struct anago_driver{ + struct anago_flash_order{ + bool command_change; + struct{ + long address, length, count, offset; + }programming, compare; + long c000x, c2aaa, c5555; + struct memory *const memory; + struct flash_device *const device; + void (*const config)(long c000x, long c2aaa, long c5555, long unit, bool retry); + void (*const device_get)(uint8_t s[2]); + void (*const write)(long address, long length, const uint8_t *data); + void (*const read)(long address, long length, u8 *data); + void (*const erase)(long address, bool dowait); + long (*const program)(long address, long length, const u8 *data, bool dowait, bool skip); + }order_cpu, order_ppu; + void (*const flash_status)(uint8_t s[2]); + uint8_t (*const vram_connection)(void); + const enum vram_mirroring vram_mirroring; + bool compare, testrun; +}; + +static SQInteger vram_mirrorfind(HSQUIRRELVM v) +{ + struct anago_driver *d; + SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d); + if(SQ_FAILED(r)){ + return r; + } + if((d->vram_connection() == 0x05) != (d->vram_mirroring == MIRROR_VERTICAL)){ + puts("warning: vram mirroring is inconnect"); + } + return 0; +} +static SQInteger command_set(HSQUIRRELVM v, struct anago_flash_order *t) +{ + long command, address ,mask; + SQRESULT r = qr_argument_get(v, 3, &command, &address, &mask); + if(SQ_FAILED(r)){ + return r; + } + long d = command & (mask - 1); + d |= address; + switch(command){ + case 0x0000: + t->c000x = d; + break; + case 0x02aa: case 0x2aaa: + t->c2aaa = d; + break; + case 0x0555: case 0x5555: + t->c5555 = d; + break; + default: + return sq_throwerror(v, "unknown command address"); + } + t->command_change = true; + return 0; +} +static SQInteger cpu_command(HSQUIRRELVM v) +{ + struct anago_driver *d; + SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d); + if(SQ_FAILED(r)){ + return r; + } + return command_set(v, &d->order_cpu); +} +static SQInteger ppu_command(HSQUIRRELVM v) +{ + struct anago_driver *d; + SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d); + if(SQ_FAILED(r)){ + return r; + } + return command_set(v, &d->order_ppu); +} +static SQInteger write_memory(HSQUIRRELVM v, struct anago_flash_order *t) +{ + long address, data; + SQRESULT r = qr_argument_get(v, 2, &address, &data); + if(SQ_FAILED(r)){ + return r; + } + uint8_t d8 = (uint8_t) data; + t->write(address, 1, &d8); + return 0; +} +static SQInteger cpu_write(HSQUIRRELVM v) +{ + struct anago_driver *d; + SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d); + if(SQ_FAILED(r)){ + return r; + } + return write_memory(v, &d->order_cpu); +} +static SQInteger erase_set(HSQUIRRELVM v, struct anago_flash_order *t, const char *region) +{ + t->config(t->c000x, t->c2aaa, t->c5555, t->device->pagesize, t->device->retry); + t->command_change = false; + if(t->device->erase_require == true){ + t->erase(t->c2aaa, false); + printf("erasing %s memory...\n", region); + fflush(stdout); + } + return 0; +} +static SQInteger cpu_erase(HSQUIRRELVM v) +{ + struct anago_driver *d; + SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d); + if(SQ_FAILED(r)){ + return r; + } + return erase_set(v, &d->order_cpu, "program"); +} +static SQInteger ppu_erase(HSQUIRRELVM v) +{ + struct anago_driver *d; + SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d); + if(SQ_FAILED(r)){ + return r; + } + return erase_set(v, &d->order_ppu, "charcter"); +} +static SQInteger program_regist(HSQUIRRELVM v, const char *name, struct anago_flash_order *t) +{ + SQRESULT r = qr_argument_get(v, 2, &t->programming.address, &t->programming.length); + if(SQ_FAILED(r)){ + return r; + } + t->compare = t->programming; + t->compare.offset = t->memory->offset & (t->memory->size - 1); + if(t->command_change == true){ + t->config(t->c000x, t->c2aaa, t->c5555, t->device->pagesize, t->device->retry); + t->command_change = false; + } + +/* printf("programming %s ROM area 0x%06x...\n", name, t->memory->offset); + fflush(stdout);*/ + return sq_suspendvm(v); +} +static void program_execute(struct anago_flash_order *t) +{ + const long w = t->program(t->programming.address, t->programming.length, t->memory->data + t->memory->offset, false, t->device->erase_require); + t->programming.address += w; + t->programming.length -= w; + t->memory->offset += w; + t->memory->offset &= t->memory->size - 1; + t->programming.offset += w; +} + +static bool program_compare(struct anago_flash_order *t) +{ + uint8_t *comparea = Malloc(t->compare.length); + bool ret = false; + if(t->device->erase_require == true){ + memset(comparea, 0xff, t->compare.length); + int doread = memcmp(comparea, t->memory->data + t->compare.offset, t->compare.length); + if(0){ + memset(comparea, 0, t->compare.length); + doread &= memcmp(comparea, t->memory->data + t->compare.offset, t->compare.length); + } + if(doread == 0){ + Free(comparea); + return true; + } + } + + t->read(t->compare.address, t->compare.length, comparea); + if(memcmp(comparea, t->memory->data + t->compare.offset, t->compare.length) == 0){ + ret = true; + } + Free(comparea); + return ret; +} +static SQInteger cpu_program_memory(HSQUIRRELVM v) +{ + struct anago_driver *d; + SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d); + if(SQ_FAILED(r)){ + return r; + } + return program_regist(v, "program", &d->order_cpu); +} +static SQInteger ppu_program_memory(HSQUIRRELVM v) +{ + struct anago_driver *d; + SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d); + if(SQ_FAILED(r)){ + return r; + } + return program_regist(v, "charcter", &d->order_ppu); +} + +static long erase_timer_get(struct anago_flash_order *t) +{ + if( + (t->memory->transtype != TRANSTYPE_EMPTY) && + (t->device->erase_require == true) + ){ + return t->device->erase_wait; + }else{ + return 0; + } +} +static SQInteger erase_wait(HSQUIRRELVM v) +{ + struct anago_driver *d; + SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d); + if(SQ_FAILED(r)){ + return r; + } + if(0){ + long timer_wait = erase_timer_get(&d->order_cpu); + long timer_ppu = erase_timer_get(&d->order_ppu); + if(timer_wait < timer_ppu){ + timer_wait = timer_ppu; + } + wait(timer_wait); + }else{ + uint8_t s[2]; + do{ + wait(2); + d->flash_status(s); + //ËÜÍè¤Î°Õ¿Þ¤«¤é¤Ç¤Ï¤³¤³¤Î¾ò·ï¼°¤Ï && ¤Ç¤Ï¤Ê¤¯ || ¤À¤¬¡¢Àè¤Ë erase ¤¬½ª¤ï¤Ã¤¿¥Ç¥Ð¥¤¥¹¤¬Æ°¤«¤»¤ë¤Î¤Ç»Ä¤·¤Æ¤ª¤¯ + }while((s[0] != KAZZO_TASK_FLASH_IDLE) && (s[1] != KAZZO_TASK_FLASH_IDLE)); + } + return 0; +} + +static bool program_memoryarea(HSQUIRRELVM co, struct anago_flash_order *t, bool compare, const char *region, SQInteger *state, bool *console_update) +{ + if(t->programming.length == 0){ + if(t->programming.offset != 0 && compare == true){ + if(program_compare(t) == false){ + printf("%s memory compare error\n", region); + return false; + } + } + + sq_wakeupvm(co, SQFalse, SQFalse, SQTrue/*, SQTrue*/); + *state = sq_getvmstate(co); + }else{ + program_execute(t); + *console_update = true; + } + return true; +} + +static SQInteger program_main(HSQUIRRELVM v) +{ + if(sq_gettop(v) != (1 + 3)){ //roottable, userpointer, co_cpu, co_ppu + return sq_throwerror(v, "argument number error"); + } + struct anago_driver *d; + SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d); + if(SQ_FAILED(r)){ + return r; + } + HSQUIRRELVM co_cpu, co_ppu; + if(SQ_FAILED(sq_getthread(v, 3, &co_cpu))){ + return sq_throwerror(v, "thread error"); + } + if(SQ_FAILED(sq_getthread(v, 4, &co_ppu))){ + return sq_throwerror(v, "thread error"); + } + SQInteger state_cpu = sq_getvmstate(co_cpu); + SQInteger state_ppu = sq_getvmstate(co_ppu); + const long sleepms = d->compare == true ? 6 : 2; //W29C040 ¤Ç compare ¤ò¤¹¤ë¤È¡¢error ¤¬½Ð¤ë¤Î¤Ç½Ð¤Ê¤¤ÃͤËÄ´À° (¤ä¤Ã¤Ä¤±Âбþ) + + progress_init(); + while((state_cpu != SQ_VMSTATE_IDLE) || (state_ppu != SQ_VMSTATE_IDLE)){ + uint8_t s[2]; + bool console_update = false; + wait(sleepms); + d->flash_status(s); + if(state_cpu != SQ_VMSTATE_IDLE && s[0] == KAZZO_TASK_FLASH_IDLE){ + if(program_memoryarea(co_cpu, &d->order_cpu, d->compare, "program", &state_cpu, &console_update) == false){ + return 0; + } + } + if(state_ppu != SQ_VMSTATE_IDLE && s[1] == KAZZO_TASK_FLASH_IDLE){ + if(program_memoryarea(co_ppu, &d->order_ppu, d->compare, "charcter", &state_ppu, &console_update) == false){ + return 0; + } + } + if((console_update == true) && (d->testrun == false)){ + progress_draw(d->order_cpu.programming.offset, d->order_cpu.programming.count, d->order_ppu.programming.offset, d->order_ppu.programming.count); + } + } + return 0; +} + +static SQInteger program_count(HSQUIRRELVM v, struct anago_flash_order *t, const struct range *range_address, const struct range *range_length) +{ + SQRESULT r = qr_argument_get(v, 2, &t->programming.address, &t->programming.length); + if(SQ_FAILED(r)){ + return r; + } + r = range_check(v, "length", t->programming.length, range_length); + if(SQ_FAILED(r)){ + return r; + } + if((t->programming.address < range_address->start) || ((t->programming.address + t->programming.length) > range_address->end)){ + printf("address range must be 0x%06x to 0x%06x", (int) range_address->start, (int) range_address->end - 1); + return sq_throwerror(v, "script logical error");; + } + t->programming.count += t->programming.length; + return 0; +} +static SQInteger cpu_program_count(HSQUIRRELVM v) +{ + static const struct range range_address = {0x8000, 0x10000}; + static const struct range range_length = {0x0100, 0x4000}; + struct anago_driver *d; + SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d); + if(SQ_FAILED(r)){ + return r; + } + return program_count(v, &d->order_cpu, &range_address, &range_length); +} + +static SQInteger ppu_program_count(HSQUIRRELVM v) +{ + static const struct range range_address = {0x0000, 0x2000}; + static const struct range range_length = {0x0100, 0x2000}; + struct anago_driver *d; + SQRESULT r = qr_userpointer_get(v, (SQUserPointer) &d); + if(SQ_FAILED(r)){ + return r; + } + return program_count(v, &d->order_ppu, &range_address, &range_length); +} + +static bool script_execute(HSQUIRRELVM v, const char *function, struct config_flash *c, struct anago_driver *d) +{ + bool ret = true; + if(SQ_FAILED(sqstd_dofile(v, _SC("flashcore.nut"), SQFalse, SQTrue))){ + printf("flash core script error\n"); + ret = false; + }else if(SQ_FAILED(sqstd_dofile(v, _SC(c->script), SQFalse, SQTrue))){ + printf("%s open error\n", c->script); + ret = false; + }else{ + SQRESULT r = qr_call( + v, function, (SQUserPointer) d, true, + 1 + 3 * 2, c->rom.mappernum, + d->order_cpu.memory->transtype, d->order_cpu.memory->size, d->order_cpu.device->capacity, + d->order_ppu.memory->transtype, d->order_ppu.memory->size, d->order_ppu.device->capacity + ); + if(SQ_FAILED(r)){ + ret = false; + } + } + return ret; +} + +void script_flash_execute(struct config_flash *c) +{ + struct anago_driver d = { + .order_cpu = { + .command_change = true, + .programming = { + .count = 0, .offset = 0 + }, + .device = &c->flash_cpu, + .memory = &c->rom.cpu_rom, + .config = c->reader->cpu_flash_config, + .device_get = c->reader->cpu_flash_device_get, + .write = c->reader->cpu_write_6502, + .read = c->reader->cpu_read, + .erase = c->reader->cpu_flash_erase, + .program = c->reader->cpu_flash_program + }, + .order_ppu = { + .command_change = true, + .programming = { + .count = 0, .offset = 0 + }, + .device = &c->flash_ppu, + .memory = &c->rom.ppu_rom, + .config = c->reader->ppu_flash_config, + .device_get = c->reader->ppu_flash_device_get, + .write = c->reader->ppu_write, + .read = c->reader->ppu_read, + .erase = c->reader->ppu_flash_erase, + .program = c->reader->ppu_flash_program, + }, + .flash_status = c->reader->flash_status, + .vram_connection = c->reader->vram_connection, + .vram_mirroring = c->rom.mirror, + .compare = c->compare, + .testrun = c->testrun + }; + { + static const char *functionname[] = { + "cpu_erase", "ppu_erase", + "erase_wait", "program_main" + }; + HSQUIRRELVM v = qr_open(); + int i; + for(i = 0; i < sizeof(functionname)/sizeof(char *); i++){ + qr_function_register_global(v, functionname[i], script_nop); + } + qr_function_register_global(v, "cpu_write", cpu_write_check); + qr_function_register_global(v, "cpu_command", cpu_command); + qr_function_register_global(v, "cpu_program", cpu_program_count); + + qr_function_register_global(v, "ppu_program", ppu_program_count); + qr_function_register_global(v, "ppu_command", ppu_command); + qr_function_register_global(v, "vram_mirrorfind", vram_mirrorfind); + + if(script_execute(v, "testrun", c, &d) == false){ + qr_close(v); + return; + } + qr_close(v); + assert(d.order_cpu.memory->size != 0); + if(d.order_cpu.programming.count % d.order_cpu.memory->size != 0){ + printf("logical error: cpu_programsize is not connected 0x%06x/0x%06x\n", (int) d.order_cpu.programming.count, (int) d.order_cpu.memory->size); + return; + } + if(d.order_ppu.memory->size != 0){ + if(d.order_ppu.programming.count % d.order_ppu.memory->size != 0){ + printf("logical error: ppu_programsize is not connected 0x%06x/0x%06x\n", (int) d.order_ppu.programming.count, (int) d.order_ppu.memory->size); + return; + } + } + } + d.order_cpu.command_change = true; + d.order_ppu.command_change = true; + { + HSQUIRRELVM v = qr_open(); + qr_function_register_global(v, "cpu_write", cpu_write); + qr_function_register_global(v, "cpu_erase", cpu_erase); + qr_function_register_global(v, "cpu_program", cpu_program_memory); + qr_function_register_global(v, "cpu_command", cpu_command); + qr_function_register_global(v, "ppu_erase", ppu_erase); + qr_function_register_global(v, "ppu_program", ppu_program_memory); + qr_function_register_global(v, "ppu_command", ppu_command); + qr_function_register_global(v, "program_main", program_main); + qr_function_register_global(v, "erase_wait", erase_wait); + qr_function_register_global(v, "vram_mirrorfind", script_nop); + script_execute(v, "program", c, &d); + qr_close(v); + } +}