diff --git a/src/Makefile.am b/src/Makefile.am index 9b2795b..7d2b106 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -33,7 +33,7 @@ laserxt.c lpt.c lpt_dac.c lpt_dss.c mca.c mcr.c mem.c mem_bios.c mfm_at.c mfm_xe opti495.c paths.c pc.c pc87306.c pci.c pic.c piix.c pit.c ppi.c ps1.c ps2.c ps2_mca.c ps2_nvr.c nvr_tc8521.c rom.c rtc.c rtc_tc8521.c scat.c scsi.c scsi_53c400.c scsi_aha1540.c scsi_cd.c scsi_hd.c scsi_zip.c \ serial.c sio.c sis496.c sl82c460.c sound.c sound_ad1848.c sound_adlib.c sound_adlibgold.c sound_audiopci.c sound_cms.c sound_emu8k.c sound_gus.c \ sound_mpu401_uart.c sound_opl.c sound_pas16.c sound_ps1.c sound_pssj.c sound_sb.c sound_sb_dsp.c sound_sn76489.c \ -sound_speaker.c sound_ssi2001.c sound_wss.c sound_ym7128.c soundopenal.c tandy_eeprom.c tandy_rom.c \ +sound_speaker.c sound_ssi2001.c sound_wss.c sound_ym7128.c soundopenal.c sst39sf010.c tandy_eeprom.c tandy_rom.c \ t1000.c t3100e.c \ timer.c um8669f.c um8881f.c vid_ati_eeprom.c vid_ati_mach64.c vid_ati18800.c vid_ati28800.c \ vid_ati68860_ramdac.c vid_cga.c vid_cl5429.c vid_colorplus.c vid_compaq_cga.c vid_ega.c vid_et4000.c vid_et4000w32.c vid_genius.c vid_hercules.c \ diff --git a/src/Makefile.mingw-wx-sdl2 b/src/Makefile.mingw-wx-sdl2 index 435aaf5..8414549 100644 --- a/src/Makefile.mingw-wx-sdl2 +++ b/src/Makefile.mingw-wx-sdl2 @@ -29,7 +29,7 @@ OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer38 sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_cms.o sound_dbopl.o \ sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o \ sound_resid.o sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \ - sound_ym7128.o soundopenal.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o \ + sound_ym7128.o soundopenal.o sst39sf010.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o \ vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o \ vid_cl5429.o vid_colorplus.o vid_compaq_cga.o vid_ega.o vid_et4000.o vid_et4000w32.o \ vid_et4000w32i.o vid_genius.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o \ diff --git a/src/model.c b/src/model.c index d060d67..bed454f 100644 --- a/src/model.c +++ b/src/model.c @@ -56,6 +56,7 @@ #include "sound_ps1.h" #include "sound_pssj.h" #include "sound_sn76489.h" +#include "sst39sf010.h" #include "tandy_eeprom.h" #include "tandy_rom.h" #include "um8669f.h" @@ -675,6 +676,7 @@ void at_mvp3_init() mvp3_init(); vt82c586b_init(7, 8, 9, 10, 0); w83877tf_init(); + device_add(&sst_39sf010_device); } void model_init() diff --git a/src/sst39sf010.c b/src/sst39sf010.c new file mode 100644 index 0000000..57969b4 --- /dev/null +++ b/src/sst39sf010.c @@ -0,0 +1,218 @@ +#include +#include "ibm.h" +#include "device.h" +#include "mem.h" +#include "sst39sf010.h" + +typedef struct sst_t +{ + int command_state; + int id_mode; + int erase; + int dirty; + + char flash_path[1024]; +} sst_t; + +#define SST_CHIP_ERASE 0x10 +#define SST_SECTOR_ERASE 0x30 +#define SST_ERASE 0x80 +#define SST_SET_ID_MODE 0x90 +#define SST_BYTE_PROGRAM 0xa0 +#define SST_CLEAR_ID_MODE 0xf0 + +static void set_id_mode(sst_t *sst); +static void clear_id_mode(sst_t *sst); + +static void sst_new_command(sst_t *sst, uint8_t val) +{ + switch (val) + { + case SST_CHIP_ERASE: + if (sst->erase) + memset(rom, 0xff, 0x20000); + sst->command_state = 0; + sst->erase = 0; + break; + + case SST_ERASE: + sst->command_state = 0; + sst->erase = 1; + break; + + case SST_SET_ID_MODE: + if (!sst->id_mode) + set_id_mode(sst); + sst->command_state = 0; + sst->erase = 0; + break; + + case SST_BYTE_PROGRAM: + sst->command_state = 3; + sst->erase = 0; + break; + + case SST_CLEAR_ID_MODE: + if (sst->id_mode) + clear_id_mode(sst); + sst->command_state = 0; + sst->erase = 0; + break; + + default: + sst->command_state = 0; + sst->erase = 0; + } +} + +static void sst_sector_erase(sst_t *sst, uint32_t addr) +{ +// pclog("SST sector erase %08x\n", addr); + memset(&rom[addr & 0x1f000], 0xff, 4096); + sst->dirty = 1; +} + +static uint8_t sst_read_id(uint32_t addr, void *p) +{ + if ((addr & 0xffff) == 0) + return 0xbf; /*SST*/ + else if ((addr & 0xffff) == 1) + return 0xb5; /*39SF010*/ + else + return 0xff; +// fatal("sst_read_id: addr=%08x\n", addr); +} + +static void sst_write(uint32_t addr, uint8_t val, void *p) +{ + sst_t *sst = (sst_t *)p; + +// pclog("sst_write: addr=%08x val=%02x state=%i\n", addr, val, sst->command_state); + switch (sst->command_state) + { + case 0: + if (val == 0xf0) + { + if (sst->id_mode) + clear_id_mode(sst); + } + else if ((addr & 0xffff) == 0x5555 && val == 0xaa) + sst->command_state = 1; + else + sst->command_state = 0; + break; + case 1: + if ((addr & 0xffff) == 0x2aaa && val == 0x55) + sst->command_state = 2; + else + sst->command_state = 0; + break; + case 2: + if ((addr & 0xffff) == 0x5555) + sst_new_command(sst, val); + else if (val == SST_SECTOR_ERASE && sst->erase) + { + sst_sector_erase(sst, addr); + sst->command_state = 0; + } + else + sst->command_state = 0; + break; + case 3: +// pclog("Byte program %08x %02x\n", addr, val); + rom[addr & 0x1ffff] = val; + sst->command_state = 0; + sst->dirty = 1; + break; + } +} + +static void set_id_mode(sst_t *sst) +{ + int c; + + for (c = 0; c < 8; c++) + { + mem_mapping_set_handler(&bios_mapping[c], + sst_read_id, NULL, NULL, + sst_write, NULL, NULL); + mem_mapping_set_p(&bios_mapping[c], sst); + mem_mapping_set_handler(&bios_high_mapping[c], + sst_read_id, NULL, NULL, + sst_write, NULL, NULL); + mem_mapping_set_p(&bios_high_mapping[c], sst); + } + sst->id_mode = 1; +} + +static void clear_id_mode(sst_t *sst) +{ + int c; + + for (c = 0; c < 8; c++) + { + mem_mapping_set_handler(&bios_mapping[c], + mem_read_bios, mem_read_biosw, mem_read_biosl, + sst_write, NULL, NULL); + mem_mapping_set_p(&bios_mapping[c], sst); + mem_mapping_set_handler(&bios_high_mapping[c], + mem_read_bios, mem_read_biosw, mem_read_biosl, + sst_write, NULL, NULL); + mem_mapping_set_p(&bios_high_mapping[c], sst); + } + sst->id_mode = 0; +} + +static void *sst_39sf010_init() +{ + FILE *f; + sst_t *sst = malloc(sizeof(sst_t)); + memset(sst, 0, sizeof(sst_t)); + + switch(romset) + { + case ROM_FIC_VA503P: + strcpy(sst->flash_path, "fic_va503p/"); + break; + default: + fatal("sst_39sf010_init on unsupported ROM set %i\n", romset); + } + strcat(sst->flash_path, "flash.bin"); + f = romfopen(sst->flash_path, "rb"); + if (f) + { + fread(rom, 0x20000, 1, f); + fclose(f); + } + + clear_id_mode(sst); + + return sst; +} + +static void sst_39sf010_close(void *p) +{ + sst_t *sst = (sst_t *)p; + + if (sst->dirty) + { + FILE *f = romfopen(sst->flash_path, "wb"); + fwrite(rom, 0x20000, 1, f); + fclose(f); + } + + free(sst); +} + +device_t sst_39sf010_device = +{ + "SST 39SF010 Flash BIOS", + 0, + sst_39sf010_init, + sst_39sf010_close, + NULL, + NULL, + NULL, + NULL, + NULL +}; diff --git a/src/sst39sf010.h b/src/sst39sf010.h new file mode 100644 index 0000000..97d4a63 --- /dev/null +++ b/src/sst39sf010.h @@ -0,0 +1 @@ +extern device_t sst_39sf010_device;