📄 hw_eeprom.c
字号:
/* eeprom reads */static unsigned8toggle(hw_eeprom_device *eeprom, unsigned8 byte){ eeprom->toggle_bit = eeprom->toggle_bit ^ 0x40; /* le-bit 6 */ return eeprom->toggle_bit ^ byte;}static unsigned8read_byte(device *me, hw_eeprom_device *eeprom, unsigned_word address){ /* may need multiple iterations of this */ while (1) { switch (eeprom->state) { case read_reset: return eeprom->memory[address]; case autoselect: if ((address & 0xff) == 0x00) return eeprom->manufacture_code; else if ((address & 0xff) == 0x01) return eeprom->device_code; else return 0; /* not certain about this */ case byte_programming: if (device_event_queue_time(me) > eeprom->program_finish_time) { finish_programming_byte(me, eeprom); eeprom->state = read_reset; continue; } else if (address == eeprom->byte_program_address) { return toggle(eeprom, eeprom->memory[address]); } else { /* trash that memory location */ invalid_read(me, eeprom->state, address, "not byte program address"); eeprom->memory[address] = (eeprom->memory[address] & eeprom->byte_program_byte); return toggle(eeprom, eeprom->memory[eeprom->byte_program_address]); } case chip_erase: if (device_event_queue_time(me) > eeprom->program_finish_time) { finish_erasing_chip(me, eeprom); eeprom->state = read_reset; continue; } else { return toggle(eeprom, eeprom->memory[address]); } case sector_erase: if (device_event_queue_time(me) > eeprom->program_finish_time) { finish_erasing_sector(me, eeprom); eeprom->state = read_reset; continue; } else if (!eeprom->sectors[address / eeprom->sizeof_sector]) { /* read to wrong sector */ invalid_read(me, eeprom->state, address, "sector not being erased"); return toggle(eeprom, eeprom->memory[address]) & ~0x8; } else if (device_event_queue_time(me) > eeprom->sector_start_time) { return toggle(eeprom, eeprom->memory[address]) | 0x8; } else { return toggle(eeprom, eeprom->memory[address]) & ~0x8; } case sector_erase_suspend: if (!eeprom->sectors[address / eeprom->sizeof_sector]) { return eeprom->memory[address]; } else { invalid_read(me, eeprom->state, address, "sector being erased"); return eeprom->memory[address]; } default: invalid_read(me, eeprom->state, address, "invalid state"); return eeprom->memory[address]; } } return 0;} static unsignedhw_eeprom_io_read_buffer(device *me, void *dest, int space, unsigned_word addr, unsigned nr_bytes, cpu *processor, unsigned_word cia){ hw_eeprom_device *eeprom = (hw_eeprom_device*)device_data(me); int i; for (i = 0; i < nr_bytes; i++) { unsigned_word address = (addr + i) % eeprom->sizeof_memory; unsigned8 byte = read_byte(me, eeprom, address); ((unsigned8*)dest)[i] = byte; } return nr_bytes;}/* eeprom writes */static voidwrite_byte(device *me, hw_eeprom_device *eeprom, unsigned_word address, unsigned8 data){ /* may need multiple transitions to process a write */ while (1) { switch (eeprom->state) { case read_reset: if (address == 0x5555 && data == 0xaa) eeprom->state = write_nr_2; else if (data == 0xf0) eeprom->state = read_reset; else { invalid_write(me, eeprom->state, address, data, "unexpected"); eeprom->state = read_reset; } return; case write_nr_2: if (address == 0x2aaa && data == 0x55) eeprom->state = write_nr_3; else { invalid_write(me, eeprom->state, address, data, "unexpected"); eeprom->state = read_reset; } return; case write_nr_3: if (address == 0x5555 && data == 0xf0) eeprom->state = read_reset; else if (address == 0x5555 && data == 0x90) eeprom->state = autoselect; else if (address == 0x5555 && data == 0xa0) { eeprom->state = byte_program; } else if (address == 0x5555 && data == 0x80) eeprom->state = write_nr_4; else { invalid_write(me, eeprom->state, address, data, "unexpected"); eeprom->state = read_reset; } return; case write_nr_4: if (address == 0x5555 && data == 0xaa) eeprom->state = write_nr_5; else { invalid_write(me, eeprom->state, address, data, "unexpected"); eeprom->state = read_reset; } return; case write_nr_5: if (address == 0x2aaa && data == 0x55) eeprom->state = write_nr_6; else { invalid_write(me, eeprom->state, address, data, "unexpected"); eeprom->state = read_reset; } return; case write_nr_6: if (address == 0x5555 && data == 0x10) { start_erasing_chip(me, eeprom); eeprom->state = chip_erase; } else { start_erasing_sector(me, eeprom, address); eeprom->sector_state = read_reset; eeprom->state = sector_erase; } return; case autoselect: if (data == 0xf0) eeprom->state = read_reset; else if (address == 0x5555 && data == 0xaa) eeprom->state = write_nr_2; else { invalid_write(me, eeprom->state, address, data, "unsupported address"); eeprom->state = read_reset; } return; case byte_program: start_programming_byte(me, eeprom, address, data); eeprom->state = byte_programming; return; case byte_programming: if (device_event_queue_time(me) > eeprom->program_finish_time) { finish_programming_byte(me, eeprom); eeprom->state = read_reset; continue; } /* ignore it */ return; case chip_erase: if (device_event_queue_time(me) > eeprom->program_finish_time) { finish_erasing_chip(me, eeprom); eeprom->state = read_reset; continue; } /* ignore it */ return; case sector_erase: if (device_event_queue_time(me) > eeprom->program_finish_time) { finish_erasing_sector(me, eeprom); eeprom->state = eeprom->sector_state; continue; } else if (device_event_queue_time(me) > eeprom->sector_start_time && data == 0xb0) { eeprom->sector_state = read_reset; eeprom->state = sector_erase_suspend; } else { if (eeprom->sector_state == read_reset && address == 0x5555 && data == 0xaa) eeprom->sector_state = write_nr_2; else if (eeprom->sector_state == write_nr_2 && address == 0x2aaa && data == 0x55) eeprom->sector_state = write_nr_3; else if (eeprom->sector_state == write_nr_3 && address == 0x5555 && data == 0x80) eeprom->sector_state = write_nr_4; else if (eeprom->sector_state == write_nr_4 && address == 0x5555 && data == 0xaa) eeprom->sector_state = write_nr_5; else if (eeprom->sector_state == write_nr_5 && address == 0x2aaa && data == 0x55) eeprom->sector_state = write_nr_6; else if (eeprom->sector_state == write_nr_6 && address != 0x5555 && data == 0x30) { if (device_event_queue_time(me) > eeprom->sector_start_time) { DTRACE(eeprom, ("sector erase command after window closed\n")); eeprom->sector_state = read_reset; } else { start_erasing_sector(me, eeprom, address); eeprom->sector_state = read_reset; } } else { invalid_write(me, eeprom->state, address, data, state2a(eeprom->sector_state)); eeprom->state = read_reset; } } return; case sector_erase_suspend: if (data == 0x30) eeprom->state = sector_erase; else { invalid_write(me, eeprom->state, address, data, "not resume command"); eeprom->state = read_reset; } return; } }}static unsignedhw_eeprom_io_write_buffer(device *me, const void *source, int space, unsigned_word addr, unsigned nr_bytes, cpu *processor, unsigned_word cia){ hw_eeprom_device *eeprom = (hw_eeprom_device*)device_data(me); int i; for (i = 0; i < nr_bytes; i++) { unsigned_word address = (addr + i) % eeprom->sizeof_memory; unsigned8 byte = ((unsigned8*)source)[i]; write_byte(me, eeprom, address, byte); } return nr_bytes;}/* An instance of the eeprom */typedef struct _hw_eeprom_instance { unsigned_word pos; hw_eeprom_device *eeprom; device *me;} hw_eeprom_instance;static voidhw_eeprom_instance_delete(device_instance *instance){ hw_eeprom_instance *data = device_instance_data(instance); zfree(data);}static inthw_eeprom_instance_read(device_instance *instance, void *buf, unsigned_word len){ hw_eeprom_instance *data = device_instance_data(instance); int i; if (data->eeprom->state != read_reset) DITRACE(eeprom, ("eeprom not idle during instance read\n")); for (i = 0; i < len; i++) { ((unsigned8*)buf)[i] = data->eeprom->memory[data->pos]; data->pos = (data->pos + 1) % data->eeprom->sizeof_memory; } return len;}static inthw_eeprom_instance_write(device_instance *instance, const void *buf, unsigned_word len){ hw_eeprom_instance *data = device_instance_data(instance); int i; if (data->eeprom->state != read_reset) DITRACE(eeprom, ("eeprom not idle during instance write\n")); for (i = 0; i < len; i++) { data->eeprom->memory[data->pos] = ((unsigned8*)buf)[i]; data->pos = (data->pos + 1) % data->eeprom->sizeof_memory; } dump_eeprom(data->me, data->eeprom); return len;}static inthw_eeprom_instance_seek(device_instance *instance, unsigned_word pos_hi, unsigned_word pos_lo){ hw_eeprom_instance *data = device_instance_data(instance); if (pos_lo >= data->eeprom->sizeof_memory) device_error(data->me, "seek value 0x%lx out of range\n", (unsigned long)pos_lo); data->pos = pos_lo; return 0;}static const device_instance_callbacks hw_eeprom_instance_callbacks = { hw_eeprom_instance_delete, hw_eeprom_instance_read, hw_eeprom_instance_write, hw_eeprom_instance_seek,};static device_instance *hw_eeprom_create_instance(device *me, const char *path, const char *args){ hw_eeprom_device *eeprom = device_data(me); hw_eeprom_instance *data = ZALLOC(hw_eeprom_instance); data->eeprom = eeprom; data->me = me; return device_create_instance_from(me, NULL, data, path, args, &hw_eeprom_instance_callbacks);}static device_callbacks const hw_eeprom_callbacks = { { generic_device_init_address, hw_eeprom_init_data }, { NULL, }, /* address */ { hw_eeprom_io_read_buffer, hw_eeprom_io_write_buffer }, /* IO */ { NULL, }, /* DMA */ { NULL, }, /* interrupt */ { NULL, }, /* unit */ hw_eeprom_create_instance,};static void *hw_eeprom_create(const char *name, const device_unit *unit_address, const char *args){ hw_eeprom_device *eeprom = ZALLOC(hw_eeprom_device); return eeprom;}const device_descriptor hw_eeprom_device_descriptor[] = { { "eeprom", hw_eeprom_create, &hw_eeprom_callbacks }, { NULL },};#endif /* _HW_EEPROM_C_ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -