diff --git a/readme.txt b/readme.txt index 62612f3..06d9104 100644 --- a/readme.txt +++ b/readme.txt @@ -256,6 +256,26 @@ ROM files needed: SIS496-1.AWA +Intel Premiere/PCI (Batman's Revenge) (1994) +A Socket 4 based board with 430LX chipset. + +ROM files needed: + +1009AF2_.BI0 +1009AF2_.BI1 + + +Intel Advanced/EV (Endeavor) (1995) +A Socket 5/7 based board with 430FX chipset. The real board has a Sound Blaster Vibra 16 on board, +which is not emulated - use a discrete card instead. Some Advanced/EVs also had a Trio64 on board, +the emulated board does not have this either. + +ROM files needed: + +1006CB0_.BI0 +1006CB0_.BI1 + + Award 430VX PCI (1996) A generic Socket 5/7 board with 430VX chipset. diff --git a/roms/endeavor/roms.txt b/roms/endeavor/roms.txt new file mode 100644 index 0000000..4e9bbdc --- /dev/null +++ b/roms/endeavor/roms.txt @@ -0,0 +1 @@ +This directory needs to contain some ROM files. \ No newline at end of file diff --git a/roms/revenge/roms.txt b/roms/revenge/roms.txt new file mode 100644 index 0000000..4e9bbdc --- /dev/null +++ b/roms/revenge/roms.txt @@ -0,0 +1 @@ +This directory needs to contain some ROM files. \ No newline at end of file diff --git a/src/386.c b/src/386.c index 9c2bf81..3bb5a18 100644 --- a/src/386.c +++ b/src/386.c @@ -320,10 +320,10 @@ int rep386(int fv) ea_seg = &_gs; goto startrep; case 0x66: case 0x166: case 0x266: case 0x366: /*Data size prefix*/ - rep32^=0x100; + rep32 = (rep32 & 0x200) | (use32 ^ 0x100); goto startrep; case 0x67: case 0x167: case 0x267: case 0x367: /*Address size prefix*/ - rep32^=0x200; + rep32 = (rep32 & 0x100) | (use32 ^ 0x200); goto startrep; case 0x6C: case 0x16C: /*REP INSB*/ if (c>0) diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 1756333..3249263 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -335,10 +335,10 @@ int rep386(int fv) ea_seg = &_gs; goto startrep; case 0x66: case 0x166: case 0x266: case 0x366: /*Data size prefix*/ - rep32^=0x100; + rep32 = (rep32 & 0x200) | (use32 ^ 0x100); goto startrep; case 0x67: case 0x167: case 0x267: case 0x367: /*Address size prefix*/ - rep32^=0x200; + rep32 = (rep32 & 0x100) | (use32 ^ 0x200); goto startrep; case 0x6C: case 0x16C: /*REP INSB*/ // cpu_notreps++; diff --git a/src/Makefile.mingw b/src/Makefile.mingw index d94b5b6..9db8194 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -4,21 +4,21 @@ CC = gcc.exe WINDRES = windres.exe CFLAGS = -O3 -march=i686 -fomit-frame-pointer OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o \ - codegen.o codegen_timing_486.o codegen_timing_pentium.o codegen_x86.o config.o cpu.o dac.o device.o dma.o fdc.o gameport.o \ - headland.o i430vx.o ide.o io.o jim.o keyboard.o keyboard_amstrad.o keyboard_at.o \ - keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o model.o \ - mouse.o mouse_ps2.o mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o \ - opti.o pc.o pci.o pic.o piix.o pit.o ppi.o rom.o serial.o sis496.o sound.o sound_ad1848.o sound_adlib.o \ - sound_adlibgold.o sound_cms.o sound_dbopl.o sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o \ - sound_pas16.o sound_resid.o sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o \ - sound_ssi2001.o sound_wss.o soundopenal.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_ega.o vid_et4000.o vid_et4000w32.o vid_et4000w32i.o \ - vid_hercules.o vid_icd2061.o vid_ics2595.o vid_mda.o vid_olivetti_m24.o \ - vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o vid_pcjr.o vid_s3.o \ - vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o vid_svga_render.o \ - vid_tandy.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o \ - vid_voodoo.o video.o wd76c10.o win.o win-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \ + codegen.o codegen_timing_486.o codegen_timing_pentium.o codegen_x86.o config.o cpu.o dac.o \ + device.o dma.o fdc.o gameport.o headland.o i430lx.o i430fx.o i430vx.o ide.o intel.o \ + intel_flash.o io.o jim.o keyboard.o keyboard_amstrad.o keyboard_at.o keyboard_olim24.o \ + keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o model.o mouse.o mouse_ps2.o mouse_serial.o \ + neat.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pci.o pic.o piix.o pit.o ppi.o rom.o serial.o \ + sis496.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o sound_dbopl.o \ + sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_resid.o \ + sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \ + soundopenal.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_ega.o vid_et4000.o \ + vid_et4000w32.o vid_et4000w32i.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_mda.o \ + vid_olivetti_m24.o vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \ + vid_pcjr.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o \ + vid_svga_render.o vid_tandy.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o \ + vid_vga.o vid_voodoo.o video.o wd76c10.o win.o win-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \ win-ddraw-fs.o win-deviceconfig.o win-hdconf.o win-joystick.o win-keyboard.o win-midi.o win-mouse.o \ win-status.o win-time.o win-video.o x86seg.o x87.o xtide.o pc.res FMOBJ = dbopl.o diff --git a/src/i430fx.c b/src/i430fx.c new file mode 100644 index 0000000..1abe254 --- /dev/null +++ b/src/i430fx.c @@ -0,0 +1,143 @@ +#include + +#include "ibm.h" +#include "mem.h" +#include "pci.h" + +#include "i430fx.h" + +static uint8_t card_i430fx[256]; + +static void i430fx_map(uint32_t addr, uint32_t size, int state) +{ + switch (state & 3) + { + case 0: + mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + break; + case 1: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + break; + case 2: + mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + break; + case 3: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + } + flushmmucache_nopc(); +} + +void i430fx_write(int func, int addr, uint8_t val, void *priv) +{ + if (func) + return; + + switch (addr) + { + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0e: + return; + + case 0x59: /*PAM0*/ + if ((card_i430fx[0x59] ^ val) & 0xf0) + { + i430fx_map(0xf0000, 0x10000, val >> 4); + shadowbios = (val & 0x10); + } + pclog("i430fx_write : PAM0 write %02X\n", val); + break; + case 0x5a: /*PAM1*/ + if ((card_i430fx[0x5a] ^ val) & 0x0f) + i430fx_map(0xc0000, 0x04000, val & 0xf); + if ((card_i430fx[0x5a] ^ val) & 0xf0) + i430fx_map(0xc4000, 0x04000, val >> 4); + break; + case 0x5b: /*PAM2*/ + if ((card_i430fx[0x5b] ^ val) & 0x0f) + i430fx_map(0xc8000, 0x04000, val & 0xf); + if ((card_i430fx[0x5b] ^ val) & 0xf0) + i430fx_map(0xcc000, 0x04000, val >> 4); + break; + case 0x5c: /*PAM3*/ + if ((card_i430fx[0x5c] ^ val) & 0x0f) + i430fx_map(0xd0000, 0x04000, val & 0xf); + if ((card_i430fx[0x5c] ^ val) & 0xf0) + i430fx_map(0xd4000, 0x04000, val >> 4); + break; + case 0x5d: /*PAM4*/ + if ((card_i430fx[0x5d] ^ val) & 0x0f) + i430fx_map(0xd8000, 0x04000, val & 0xf); + if ((card_i430fx[0x5d] ^ val) & 0xf0) + i430fx_map(0xdc000, 0x04000, val >> 4); + break; + case 0x5e: /*PAM5*/ + if ((card_i430fx[0x5e] ^ val) & 0x0f) + i430fx_map(0xe0000, 0x04000, val & 0xf); + if ((card_i430fx[0x5e] ^ val) & 0xf0) + i430fx_map(0xe4000, 0x04000, val >> 4); + pclog("i430fx_write : PAM5 write %02X\n", val); + break; + case 0x5f: /*PAM6*/ + if ((card_i430fx[0x5f] ^ val) & 0x0f) + i430fx_map(0xe8000, 0x04000, val & 0xf); + if ((card_i430fx[0x5f] ^ val) & 0xf0) + i430fx_map(0xec000, 0x04000, val >> 4); + pclog("i430fx_write : PAM6 write %02X\n", val); + break; + } + + card_i430fx[addr] = val; +} + +uint8_t i430fx_read(int func, int addr, void *priv) +{ + if (func) + return 0xff; + + return card_i430fx[addr]; +} + +/*The Turbo-Reset Control Register isn't listed in the i430FX datasheet, however + the Advanced/EV BIOS seems to assume it exists. It aliases with one of the PCI + registers.*/ +static uint8_t trc = 0; + +void i430fx_trc_write(uint16_t port, uint8_t val, void *p) +{ + if ((val & 4) && !(trc & 4)) + { + if (val & 2) /*Hard reset*/ + i430fx_write(0, 0x59, 0xf, NULL); /*Should reset all PCI devices, but just set PAM0 to point to ROM for now*/ + resetx86(); + } + + trc = val; +} + +void i430fx_init() +{ + pci_add_specific(0, i430fx_read, i430fx_write, NULL); + + memset(card_i430fx, 0, 256); + card_i430fx[0x00] = 0x86; card_i430fx[0x01] = 0x80; /*Intel*/ + card_i430fx[0x02] = 0x22; card_i430fx[0x03] = 0x01; /*SB82437FX-66*/ + card_i430fx[0x04] = 0x06; card_i430fx[0x05] = 0x00; + card_i430fx[0x06] = 0x00; card_i430fx[0x07] = 0x82; + card_i430fx[0x08] = 0x00; /*A0 stepping*/ + card_i430fx[0x09] = 0x00; card_i430fx[0x0a] = 0x00; card_i430fx[0x0b] = 0x06; + card_i430fx[0x52] = 0x40; /*256kb PLB cache*/ +// card_i430fx[0x53] = 0x14; +// card_i430fx[0x56] = 0x52; /*DRAM control*/ + card_i430fx[0x57] = 0x01; + card_i430fx[0x60] = card_i430fx[0x61] = card_i430fx[0x62] = card_i430fx[0x63] = card_i430fx[0x64] = 0x02; +// card_i430fx[0x67] = 0x11; +// card_i430fx[0x69] = 0x03; +// card_i430fx[0x70] = 0x20; + card_i430fx[0x72] = 0x02; +// card_i430fx[0x74] = 0x0e; +// card_i430fx[0x78] = 0x23; + + io_sethandler(0x0cf9, 0x0001, NULL, NULL, NULL, i430fx_trc_write, NULL, NULL, NULL); +} diff --git a/src/i430fx.h b/src/i430fx.h new file mode 100644 index 0000000..fff11d2 --- /dev/null +++ b/src/i430fx.h @@ -0,0 +1 @@ +void i430fx_init(); diff --git a/src/i430lx.c b/src/i430lx.c new file mode 100644 index 0000000..ec82583 --- /dev/null +++ b/src/i430lx.c @@ -0,0 +1,146 @@ +#include + +#include "ibm.h" +#include "mem.h" +#include "pci.h" + +#include "i430lx.h" + +static uint8_t card_i430lx[256]; + +static void i430lx_map(uint32_t addr, uint32_t size, int state) +{ + switch (state & 3) + { + case 0: + mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + break; + case 1: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + break; + case 2: + mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + break; + case 3: + mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + } + flushmmucache_nopc(); +} + +void i430lx_write(int func, int addr, uint8_t val, void *priv) +{ + if (func) + return; + + switch (addr) + { + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0e: + return; + + case 0x59: /*PAM0*/ + if ((card_i430lx[0x59] ^ val) & 0xf0) + { + i430lx_map(0xf0000, 0x10000, val >> 4); + shadowbios = (val & 0x10); + } + pclog("i430lx_write : PAM0 write %02X\n", val); + break; + case 0x5a: /*PAM1*/ + if ((card_i430lx[0x5a] ^ val) & 0x0f) + i430lx_map(0xc0000, 0x04000, val & 0xf); + if ((card_i430lx[0x5a] ^ val) & 0xf0) + i430lx_map(0xc4000, 0x04000, val >> 4); + break; + case 0x5b: /*PAM2*/ + if ((card_i430lx[0x5b] ^ val) & 0x0f) + i430lx_map(0xc8000, 0x04000, val & 0xf); + if ((card_i430lx[0x5b] ^ val) & 0xf0) + i430lx_map(0xcc000, 0x04000, val >> 4); + break; + case 0x5c: /*PAM3*/ + if ((card_i430lx[0x5c] ^ val) & 0x0f) + i430lx_map(0xd0000, 0x04000, val & 0xf); + if ((card_i430lx[0x5c] ^ val) & 0xf0) + i430lx_map(0xd4000, 0x04000, val >> 4); + break; + case 0x5d: /*PAM4*/ + if ((card_i430lx[0x5d] ^ val) & 0x0f) + i430lx_map(0xd8000, 0x04000, val & 0xf); + if ((card_i430lx[0x5d] ^ val) & 0xf0) + i430lx_map(0xdc000, 0x04000, val >> 4); + break; + case 0x5e: /*PAM5*/ + if ((card_i430lx[0x5e] ^ val) & 0x0f) + i430lx_map(0xe0000, 0x04000, val & 0xf); + if ((card_i430lx[0x5e] ^ val) & 0xf0) + i430lx_map(0xe4000, 0x04000, val >> 4); + pclog("i430lx_write : PAM5 write %02X\n", val); + break; + case 0x5f: /*PAM6*/ + if ((card_i430lx[0x5f] ^ val) & 0x0f) + i430lx_map(0xe8000, 0x04000, val & 0xf); + if ((card_i430lx[0x5f] ^ val) & 0xf0) + i430lx_map(0xec000, 0x04000, val >> 4); + pclog("i430lx_write : PAM6 write %02X\n", val); + break; + } + + card_i430lx[addr] = val; +} + +uint8_t i430lx_read(int func, int addr, void *priv) +{ + if (func) + return 0xff; + + return card_i430lx[addr]; +} + +static uint8_t trc = 0; + +uint8_t i430lx_trc_read(uint16_t port, void *p) +{ + return trc; +} + +void i430lx_trc_write(uint16_t port, uint8_t val, void *p) +{ + if ((val & 4) && !(trc & 4)) + { + if (val & 2) /*Hard reset*/ + i430lx_write(0, 0x59, 0xf, NULL); /*Should reset all PCI devices, but just set PAM0 to point to ROM for now*/ + resetx86(); + } + + trc = val; +} + +void i430lx_init() +{ + pci_add_specific(0, i430lx_read, i430lx_write, NULL); + + memset(card_i430lx, 0, 256); + card_i430lx[0x00] = 0x86; card_i430lx[0x01] = 0x80; /*Intel*/ + card_i430lx[0x02] = 0xa3; card_i430lx[0x03] = 0x04; /*82434LX*/ + card_i430lx[0x04] = 0x06; card_i430lx[0x05] = 0x00; + card_i430lx[0x06] = 0x00; card_i430lx[0x07] = 0x02; + card_i430lx[0x08] = 0x03; /*A3 stepping*/ + card_i430lx[0x09] = 0x00; card_i430lx[0x0a] = 0x00; card_i430lx[0x0b] = 0x06; + card_i430lx[0x50] = 0x80; + card_i430lx[0x52] = 0x40; /*256kb PLB cache*/ +// card_i430lx[0x53] = 0x14; +// card_i430lx[0x56] = 0x52; /*DRAM control*/ + card_i430lx[0x57] = 0x31; + card_i430lx[0x60] = card_i430lx[0x61] = card_i430lx[0x62] = card_i430lx[0x63] = card_i430lx[0x64] = 0x02; +// card_i430lx[0x67] = 0x11; +// card_i430lx[0x69] = 0x03; +// card_i430lx[0x70] = 0x20; +// card_i430lx[0x72] = 0x02; +// card_i430lx[0x74] = 0x0e; +// card_i430lx[0x78] = 0x23; + + io_sethandler(0x0cf9, 0x0001, i430lx_trc_read, NULL, NULL, i430lx_trc_write, NULL, NULL, NULL); +} diff --git a/src/i430lx.h b/src/i430lx.h new file mode 100644 index 0000000..8669fa2 --- /dev/null +++ b/src/i430lx.h @@ -0,0 +1 @@ +void i430lx_init(); diff --git a/src/ibm.h b/src/ibm.h index b56a22c..738f84f 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -316,6 +316,8 @@ enum ROM_PCI486, ROM_SIS496, ROM_430VX, + ROM_ENDEAVOR, + ROM_REVENGE, ROM_MAX }; diff --git a/src/intel.c b/src/intel.c new file mode 100644 index 0000000..bba57ca --- /dev/null +++ b/src/intel.c @@ -0,0 +1,80 @@ +#include "ibm.h" +#include "io.h" +#include "mem.h" +#include "pit.h" +#include "timer.h" + +#include "intel.h" + +uint8_t batman_brdconfig(uint16_t port, void *p) +{ +// pclog("batman_brdconfig read port=%04x\n", port); + switch (port) + { + case 0x73: + return 0xff; + case 0x75: + return 0xdf; + } + return 0; +} + +static uint16_t batman_timer_latch; +static int batman_timer = 0; +static void batman_timer_over(void *p) +{ + batman_timer = 0; +} + +static void batman_timer_write(uint16_t addr, uint8_t val, void *p) +{ + if (addr & 1) + batman_timer_latch = (batman_timer_latch & 0xff) | (val << 8); + else + batman_timer_latch = (batman_timer_latch & 0xff00) | val; + batman_timer = batman_timer_latch * TIMER_USEC; +} + +static uint8_t batman_timer_read(uint16_t addr, void *p) +{ + uint16_t batman_timer_latch; + + cycles -= (int)PITCONST; + + timer_clock(); + + if (batman_timer < 0) + return 0; + + batman_timer_latch = batman_timer / TIMER_USEC; + + if (addr & 1) + return batman_timer_latch >> 8; + return batman_timer_latch & 0xff; +} + +void intel_batman_init() +{ + io_sethandler(0x0073, 0x0001, batman_brdconfig, NULL, NULL, NULL, NULL, NULL, NULL); + io_sethandler(0x0075, 0x0001, batman_brdconfig, NULL, NULL, NULL, NULL, NULL, NULL); + + io_sethandler(0x0078, 0x0002, batman_timer_read, NULL, NULL, batman_timer_write, NULL, NULL, NULL); + timer_add(batman_timer_over, &batman_timer, &batman_timer, NULL); +} + + +uint8_t endeavor_brdconfig(uint16_t port, void *p) +{ +// pclog("endeavor_brdconfig read port=%04x\n", port); + switch (port) + { + case 0x79: + return 0xff; + } + return 0; +} + +void intel_endeavor_init() +{ + io_sethandler(0x0079, 0x0001, endeavor_brdconfig, NULL, NULL, NULL, NULL, NULL, NULL); +} diff --git a/src/intel.h b/src/intel.h new file mode 100644 index 0000000..eccd668 --- /dev/null +++ b/src/intel.h @@ -0,0 +1,2 @@ +void intel_batman_init(); +void intel_endeavor_init(); diff --git a/src/intel_flash.c b/src/intel_flash.c new file mode 100644 index 0000000..1cdb6e0 --- /dev/null +++ b/src/intel_flash.c @@ -0,0 +1,176 @@ +#include +#include "ibm.h" +#include "device.h" +#include "mem.h" + +enum +{ + CMD_READ_ARRAY = 0xff, + CMD_IID = 0x90, + CMD_READ_STATUS = 0x70, + CMD_CLEAR_STATUS = 0x50, + CMD_ERASE_SETUP = 0x20, + CMD_ERASE_CONFIRM = 0xd0, + CMD_ERASE_SUSPEND = 0xb0, + CMD_PROGRAM_SETUP = 0x40 +}; + +typedef struct flash_t +{ + uint8_t command, status; + mem_mapping_t read_mapping, write_mapping; +} flash_t; + +static flash_t flash; + +static uint8_t flash_read(uint32_t addr, void *p) +{ + flash_t *flash = (flash_t *)p; +// pclog("flash_read : addr=%08x command=%02x %04x:%08x\n", addr, flash->command, CS, pc); + switch (flash->command) + { + case CMD_IID: + if (addr & 1) + return 0x94; + return 0x89; + + default: + return flash->status; + } +} + +static void flash_write(uint32_t addr, uint8_t val, void *p) +{ + flash_t *flash = (flash_t *)p; +// pclog("flash_write : addr=%08x val=%02x command=%02x %04x:%08x\n", addr, val, flash->command, CS, pc); + switch (flash->command) + { + case CMD_ERASE_SETUP: + if (val == CMD_ERASE_CONFIRM) + { +// pclog("flash_write: erase %05x\n", addr & 0x1ffff); + if ((addr & 0x1f000) == 0x0d000) + memset(&rom[0x0d000], 0xff, 0x1000); + if ((addr & 0x1f000) == 0x0c000) + memset(&rom[0x0c000], 0xff, 0x1000); + if ((addr & 0x1f000) < 0x0c000 || (addr & 0x1f000) >= 0x10000) + { + memset(rom, 0xff, 0xc000); + memset(&rom[0x10000], 0xff, 0x10000); + } + flash->status = 0x80; + } + flash->command = CMD_READ_STATUS; + break; + + case CMD_PROGRAM_SETUP: +// pclog("flash_write: program %05x %02x\n", addr & 0x1ffff, val); + if ((addr & 0x1e000) != 0x0e000) + rom[addr & 0x1ffff] = val; + flash->command = CMD_READ_STATUS; + flash->status = 0x80; + break; + + default: + flash->command = val; + switch (val) + { + case CMD_CLEAR_STATUS: + flash->status = 0; + break; + + case CMD_IID: + case CMD_READ_STATUS: + mem_mapping_disable(&bios_mapping[0]); + mem_mapping_disable(&bios_mapping[1]); + mem_mapping_disable(&bios_mapping[2]); + mem_mapping_disable(&bios_mapping[3]); + mem_mapping_disable(&bios_mapping[4]); + mem_mapping_disable(&bios_mapping[5]); + mem_mapping_disable(&bios_mapping[6]); + mem_mapping_disable(&bios_mapping[7]); + mem_mapping_enable(&flash->read_mapping); + break; + + case CMD_READ_ARRAY: + mem_mapping_enable(&bios_mapping[0]); + mem_mapping_enable(&bios_mapping[1]); + mem_mapping_enable(&bios_mapping[2]); + mem_mapping_enable(&bios_mapping[3]); + mem_mapping_enable(&bios_mapping[4]); + mem_mapping_enable(&bios_mapping[5]); + mem_mapping_enable(&bios_mapping[6]); + mem_mapping_enable(&bios_mapping[7]); + mem_mapping_disable(&flash->read_mapping); + break; + } + } +} + +void *intel_flash_init() +{ + FILE *f; + flash_t *flash = malloc(sizeof(flash_t)); + memset(flash, 0, sizeof(flash_t)); + + mem_mapping_add(&flash->read_mapping, + 0xe0000, + 0x20000, + flash_read, NULL, NULL, + NULL, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, (void *)flash); + mem_mapping_add(&flash->write_mapping, + 0xe0000, + 0x20000, + NULL, NULL, NULL, + flash_write, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, (void *)flash); + mem_mapping_disable(&flash->read_mapping); + flash->command = CMD_READ_ARRAY; + flash->status = 0; + + memset(&rom[0xc000], 0, 0x2000); + + f = romfopen("roms/endeavor/oemlogo.bin", "rb"); + if (f) + { + fread(&rom[0xc000], 0x1000, 1, f); + fclose(f); + } + f = romfopen("roms/endeavor/ecsd.bin", "rb"); + if (f) + { + fread(&rom[0xd000], 0x1000, 1, f); + fclose(f); + } + + return flash; +} + +void intel_flash_close(void *p) +{ + FILE *f; + flash_t *flash = (flash_t *)p; + + f = romfopen("roms/endeavor/oemlogo.bin", "wb"); + fwrite(&rom[0xc000], 0x1000, 1, f); + fclose(f); + f = romfopen("roms/endeavor/ecsd.bin", "wb"); + fwrite(&rom[0xd000], 0x1000, 1, f); + fclose(f); + + free(flash); +} + +device_t intel_flash_device = +{ + "Intel 28F001BXT Flash BIOS", + 0, + intel_flash_init, + intel_flash_close, + NULL, + NULL, + NULL, + NULL, + NULL +}; diff --git a/src/intel_flash.h b/src/intel_flash.h new file mode 100644 index 0000000..379a8d3 --- /dev/null +++ b/src/intel_flash.h @@ -0,0 +1 @@ +extern device_t intel_flash_device; diff --git a/src/keyboard_at.c b/src/keyboard_at.c index ebdbb10..f411113 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -254,6 +254,11 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv) case 0xf4: /*Enable keyboard*/ keyboard_scan = 1; + keyboard_at_adddata_keyboard(0xfa); + break; + case 0xf5: /*Disable keyboard*/ + keyboard_scan = 0; + keyboard_at_adddata_keyboard(0xfa); break; case 0xff: /*Reset*/ diff --git a/src/mem.c b/src/mem.c index fb0b7a3..134a995 100644 --- a/src/mem.c +++ b/src/mem.c @@ -37,7 +37,7 @@ static mem_mapping_t base_mapping; static mem_mapping_t ram_low_mapping; static mem_mapping_t ram_high_mapping; static mem_mapping_t ram_mid_mapping; -static mem_mapping_t bios_mapping[8]; +mem_mapping_t bios_mapping[8]; static mem_mapping_t bios_high_mapping[8]; static mem_mapping_t romext_mapping; @@ -90,6 +90,7 @@ int loadbios() biosmask = 0xffff; memset(romext,0x63,0x4000); + memset(rom, 0xff, 0x20000); pclog("Starting with romset %i\n", romset); @@ -419,6 +420,35 @@ int loadbios() biosmask = 0x1ffff; //is486=1; return 1; + + case ROM_REVENGE: + f = romfopen("roms/revenge/1009AF2_.BIO", "rb"); + if (!f) break; + fseek(f, 0x80, SEEK_SET); + fread(rom + 0x10000, 0x10000, 1, f); + fclose(f); + f = romfopen("roms/revenge/1009AF2_.BI1", "rb"); + if (!f) break; + fseek(f, 0x80, SEEK_SET); + fread(rom, 0xc000, 1, f); + fclose(f); + biosmask = 0x1ffff; + //is486=1; + return 1; + case ROM_ENDEAVOR: + f = romfopen("roms/endeavor/1006CB0_.BIO", "rb"); + if (!f) break; + fseek(f, 0x80, SEEK_SET); + fread(rom + 0x10000, 0x10000, 1, f); + fclose(f); + f = romfopen("roms/endeavor/1006CB0_.BI1", "rb"); + if (!f) break; + fseek(f, 0x80, SEEK_SET); + fread(rom, 0xc000, 1, f); + fclose(f); + biosmask = 0x1ffff; + //is486=1; + return 1; } printf("Failed to load ROM!\n"); if (f) fclose(f); diff --git a/src/mem.h b/src/mem.h index b130239..6991e00 100644 --- a/src/mem.h +++ b/src/mem.h @@ -96,3 +96,5 @@ void mem_write_nullw(uint32_t addr, uint16_t val, void *p); void mem_write_nulll(uint32_t addr, uint32_t val, void *p); FILE *romfopen(char *fn, char *mode); + +mem_mapping_t bios_mapping[8]; diff --git a/src/model.c b/src/model.c index f120fdf..21b0ffe 100644 --- a/src/model.c +++ b/src/model.c @@ -11,8 +11,12 @@ #include "fdc.h" #include "gameport.h" #include "headland.h" +#include "i430fx.h" +#include "i430lx.h" #include "i430vx.h" #include "ide.h" +#include "intel.h" +#include "intel_flash.h" #include "jim.h" #include "keyboard_amstrad.h" #include "keyboard_at.h" @@ -38,53 +42,58 @@ #include "wd76c10.h" #include "xtide.h" -void xt_init(); -void pcjr_init(); -void tandy1k_init(); -void ams_init(); -void europc_init(); -void olim24_init(); -void at_init(); -void at_neat_init(); -void at_acer386sx_init(); -void at_wd76c10_init(); -void at_ali1429_init(); -void at_headland_init(); -void at_um8881f_init(); -void at_sis496_init(); -void at_i430vx_init(); +void xt_init(); +void pcjr_init(); +void tandy1k_init(); +void ams_init(); +void europc_init(); +void olim24_init(); +void at_init(); +void at_neat_init(); +void at_acer386sx_init(); +void at_wd76c10_init(); +void at_ali1429_init(); +void at_headland_init(); +void at_um8881f_init(); +void at_sis496_init(); +void at_i430vx_init(); +void at_batman_init(); +void at_endeavor_init(); int model; MODEL models[] = { - {"IBM PC", ROM_IBMPC, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init}, - {"IBM XT", ROM_IBMXT, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init}, - {"IBM PCjr", ROM_IBMPCJR, { "", cpus_pcjr, "", NULL, "", NULL}, 1, pcjr_init}, - {"Generic XT clone", ROM_GENXT, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init}, - {"DTK XT clone", ROM_DTKXT, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init}, - {"Tandy 1000", ROM_TANDY, { "", cpus_8088, "", NULL, "", NULL}, 1, tandy1k_init}, - {"Amstrad PC1512", ROM_PC1512, { "", cpus_pc1512, "", NULL, "", NULL}, 1, ams_init}, - {"Sinclair PC200", ROM_PC200, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init}, - {"Euro PC", ROM_EUROPC, { "", cpus_8086, "", NULL, "", NULL}, 0, europc_init}, - {"Olivetti M24", ROM_OLIM24, { "", cpus_8086, "", NULL, "", NULL}, 1, olim24_init}, - {"Amstrad PC1640", ROM_PC1640, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init}, - {"Amstrad PC2086", ROM_PC2086, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init}, - {"Amstrad PC3086", ROM_PC3086, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init}, - {"IBM AT", ROM_IBMAT, { "", cpus_ibmat, "", NULL, "", NULL}, 0, at_init}, - {"Commodore PC 30 III", ROM_CMDPC30, { "", cpus_286, "", NULL, "", NULL}, 0, at_init}, - {"AMI 286 clone", ROM_AMI286, { "", cpus_286, "", NULL, "", NULL}, 0, at_neat_init}, - {"DELL System 200", ROM_DELL200, { "", cpus_286, "", NULL, "", NULL}, 0, at_init}, - {"Acer 386SX25/N", ROM_ACER386, { "Intel", cpus_acer, "", NULL, "", NULL}, 1, at_acer386sx_init}, - {"Amstrad MegaPC", ROM_MEGAPC, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 1, at_wd76c10_init}, - {"AMI 386 clone", ROM_AMI386, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 0, at_headland_init}, - {"AMI 486 clone", ROM_AMI486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, at_ali1429_init}, - {"AMI WinBIOS 486", ROM_WIN486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, at_ali1429_init}, + {"IBM PC", ROM_IBMPC, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init}, + {"IBM XT", ROM_IBMXT, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init}, + {"IBM PCjr", ROM_IBMPCJR, { "", cpus_pcjr, "", NULL, "", NULL}, 1, pcjr_init}, + {"Generic XT clone", ROM_GENXT, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init}, + {"DTK XT clone", ROM_DTKXT, { "", cpus_8088, "", NULL, "", NULL}, 0, xt_init}, + {"Tandy 1000", ROM_TANDY, { "", cpus_8088, "", NULL, "", NULL}, 1, tandy1k_init}, + {"Amstrad PC1512", ROM_PC1512, { "", cpus_pc1512, "", NULL, "", NULL}, 1, ams_init}, + {"Sinclair PC200", ROM_PC200, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init}, + {"Euro PC", ROM_EUROPC, { "", cpus_8086, "", NULL, "", NULL}, 0, europc_init}, + {"Olivetti M24", ROM_OLIM24, { "", cpus_8086, "", NULL, "", NULL}, 1, olim24_init}, + {"Amstrad PC1640", ROM_PC1640, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init}, + {"Amstrad PC2086", ROM_PC2086, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init}, + {"Amstrad PC3086", ROM_PC3086, { "", cpus_8086, "", NULL, "", NULL}, 1, ams_init}, + {"IBM AT", ROM_IBMAT, { "", cpus_ibmat, "", NULL, "", NULL}, 0, at_init}, + {"Commodore PC 30 III", ROM_CMDPC30, { "", cpus_286, "", NULL, "", NULL}, 0, at_init}, + {"AMI 286 clone", ROM_AMI286, { "", cpus_286, "", NULL, "", NULL}, 0, at_neat_init}, + {"DELL System 200", ROM_DELL200, { "", cpus_286, "", NULL, "", NULL}, 0, at_init}, + {"Acer 386SX25/N", ROM_ACER386, { "Intel", cpus_acer, "", NULL, "", NULL}, 1, at_acer386sx_init}, + {"Amstrad MegaPC", ROM_MEGAPC, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 1, at_wd76c10_init}, + {"AMI 386 clone", ROM_AMI386, { "Intel", cpus_i386, "AMD", cpus_Am386, "Cyrix", cpus_486SDLC}, 0, at_headland_init}, + {"AMI 486 clone", ROM_AMI486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, at_ali1429_init}, + {"AMI WinBIOS 486", ROM_WIN486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, at_ali1429_init}, /* {"AMI WinBIOS 486 PCI", ROM_PCI486, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, at_um8881f_init},*/ {"Award SiS 496/497", ROM_SIS496, { "Intel", cpus_i486, "AMD", cpus_Am486, "Cyrix", cpus_Cx486}, 0, at_sis496_init}, #ifdef DYNAREC + {"Intel Premiere/PCI", ROM_REVENGE, { "Intel", cpus_Pentium5V, "", NULL, "", NULL}, 0, at_batman_init}, + {"Intel Advanced/EV", ROM_ENDEAVOR, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "", NULL}, 0, at_endeavor_init}, {"Award 430VX PCI", ROM_430VX, { "Intel", cpus_Pentium, "IDT", cpus_WinChip, "", NULL}, 0, at_i430vx_init}, #else + {"Intel Advanced/EV", ROM_ENDEAVOR, { "IDT", cpus_WinChip, "", NULL, "", NULL}, 0, at_endeavor_init}, {"Award 430VX PCI", ROM_430VX, { "IDT", cpus_WinChip, "", NULL, "", NULL}, 0, at_i430vx_init}, #endif {"", -1, {"", 0, "", 0, "", 0}, 0} @@ -245,7 +254,7 @@ void at_um8881f_init() { at_init(); mouse_serial_init(); - pci_init(); + pci_init(PCI_CONFIG_TYPE_1, 0, 31); um8881f_init(); } @@ -253,15 +262,36 @@ void at_sis496_init() { at_init(); mouse_serial_init(); - pci_init(); + pci_init(PCI_CONFIG_TYPE_1, 0, 31); device_add(&sis496_device); } +void at_batman_init() +{ + at_init(); + mouse_serial_init(); + pci_init(PCI_CONFIG_TYPE_2, 0xd, 0x10); + i430lx_init(); + um8669f_init(); + intel_batman_init(); +} +void at_endeavor_init() +{ + at_init(); + mouse_serial_init(); + pci_init(PCI_CONFIG_TYPE_1, 0xd, 0x10); + i430fx_init(); + piix_init(7); + um8669f_init(); + intel_endeavor_init(); + device_add(&intel_flash_device); +} + void at_i430vx_init() { at_init(); mouse_serial_init(); - pci_init(); + pci_init(PCI_CONFIG_TYPE_1, 0, 31); i430vx_init(); piix_init(7); um8669f_init(); diff --git a/src/nvr.c b/src/nvr.c index a26c70e..f5d4601 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -130,24 +130,26 @@ void loadnvr() oldromset=romset; switch (romset) { - case ROM_PC1512: f = romfopen("pc1512.nvr", "rb"); break; - case ROM_PC1640: f = romfopen("pc1640.nvr", "rb"); break; - case ROM_PC200: f = romfopen("pc200.nvr", "rb"); break; - case ROM_PC2086: f = romfopen("pc2086.nvr", "rb"); break; - case ROM_PC3086: f = romfopen("pc3086.nvr", "rb"); break; - case ROM_IBMAT: f = romfopen("at.nvr" , "rb"); break; - case ROM_CMDPC30: f = romfopen("cmdpc30.nvr", "rb"); nvrmask = 127; break; - case ROM_AMI286: f = romfopen("ami286.nvr", "rb"); nvrmask = 127; break; - case ROM_DELL200: f = romfopen("dell200.nvr", "rb"); nvrmask = 127; break; - case ROM_IBMAT386: f = romfopen("at386.nvr" , "rb"); nvrmask = 127; break; - case ROM_ACER386: f = romfopen("acer386.nvr", "rb"); nvrmask = 127; break; - case ROM_MEGAPC: f = romfopen("megapc.nvr", "rb"); nvrmask = 127; break; - case ROM_AMI386: f = romfopen("ami386.nvr", "rb"); nvrmask = 127; break; - case ROM_AMI486: f = romfopen("ami486.nvr", "rb"); nvrmask = 127; break; - case ROM_WIN486: f = romfopen("win486.nvr", "rb"); nvrmask = 127; break; - case ROM_PCI486: f = romfopen("hot-433.nvr", "rb"); nvrmask = 127; break; - case ROM_SIS496: f = romfopen("sis496.nvr", "rb"); nvrmask = 127; break; - case ROM_430VX: f = romfopen("430vx.nvr", "rb"); nvrmask = 127; break; + case ROM_PC1512: f = romfopen("pc1512.nvr", "rb"); break; + case ROM_PC1640: f = romfopen("pc1640.nvr", "rb"); break; + case ROM_PC200: f = romfopen("pc200.nvr", "rb"); break; + case ROM_PC2086: f = romfopen("pc2086.nvr", "rb"); break; + case ROM_PC3086: f = romfopen("pc3086.nvr", "rb"); break; + case ROM_IBMAT: f = romfopen("at.nvr", "rb"); break; + case ROM_CMDPC30: f = romfopen("cmdpc30.nvr", "rb"); nvrmask = 127; break; + case ROM_AMI286: f = romfopen("ami286.nvr", "rb"); nvrmask = 127; break; + case ROM_DELL200: f = romfopen("dell200.nvr", "rb"); nvrmask = 127; break; + case ROM_IBMAT386: f = romfopen("at386.nvr", "rb"); nvrmask = 127; break; + case ROM_ACER386: f = romfopen("acer386.nvr", "rb"); nvrmask = 127; break; + case ROM_MEGAPC: f = romfopen("megapc.nvr", "rb"); nvrmask = 127; break; + case ROM_AMI386: f = romfopen("ami386.nvr", "rb"); nvrmask = 127; break; + case ROM_AMI486: f = romfopen("ami486.nvr", "rb"); nvrmask = 127; break; + case ROM_WIN486: f = romfopen("win486.nvr", "rb"); nvrmask = 127; break; + case ROM_PCI486: f = romfopen("hot-433.nvr", "rb"); nvrmask = 127; break; + case ROM_SIS496: f = romfopen("sis496.nvr", "rb"); nvrmask = 127; break; + case ROM_430VX: f = romfopen("430vx.nvr", "rb"); nvrmask = 127; break; + case ROM_REVENGE: f = romfopen("revenge.nvr", "rb"); nvrmask = 127; break; + case ROM_ENDEAVOR: f = romfopen("endeavor.nvr", "rb"); nvrmask = 127; break; default: return; } if (!f) @@ -167,24 +169,26 @@ void savenvr() FILE *f; switch (oldromset) { - case ROM_PC1512: f = romfopen("pc1512.nvr" , "wb"); break; - case ROM_PC1640: f = romfopen("pc1640.nvr" , "wb"); break; - case ROM_PC200: f = romfopen("pc200.nvr" , "wb"); break; - case ROM_PC2086: f = romfopen("pc2086.nvr" , "wb"); break; - case ROM_PC3086: f = romfopen("pc3086.nvr" , "wb"); break; - case ROM_IBMAT: f = romfopen("at.nvr" , "wb"); break; - case ROM_CMDPC30: f = romfopen("cmdpc30.nvr", "wb"); break; - case ROM_AMI286: f = romfopen("ami286.nvr" , "wb"); break; - case ROM_DELL200: f = romfopen("dell200.nvr", "wb"); break; - case ROM_IBMAT386: f = romfopen("at386.nvr" , "wb"); break; - case ROM_ACER386: f = romfopen("acer386.nvr", "wb"); break; - case ROM_MEGAPC: f = romfopen("megapc.nvr" , "wb"); break; - case ROM_AMI386: f = romfopen("ami386.nvr" , "wb"); break; - case ROM_AMI486: f = romfopen("ami486.nvr" , "wb"); break; - case ROM_WIN486: f = romfopen("win486.nvr" , "wb"); break; - case ROM_PCI486: f = romfopen("hot-433.nvr", "wb"); break; - case ROM_SIS496: f = romfopen("sis496.nvr" , "wb"); break; - case ROM_430VX: f = romfopen("430vx.nvr" , "wb"); break; + case ROM_PC1512: f = romfopen("pc1512.nvr", "wb"); break; + case ROM_PC1640: f = romfopen("pc1640.nvr", "wb"); break; + case ROM_PC200: f = romfopen("pc200.nvr", "wb"); break; + case ROM_PC2086: f = romfopen("pc2086.nvr", "wb"); break; + case ROM_PC3086: f = romfopen("pc3086.nvr", "wb"); break; + case ROM_IBMAT: f = romfopen("at.nvr", "wb"); break; + case ROM_CMDPC30: f = romfopen("cmdpc30.nvr", "wb"); break; + case ROM_AMI286: f = romfopen("ami286.nvr", "wb"); break; + case ROM_DELL200: f = romfopen("dell200.nvr", "wb"); break; + case ROM_IBMAT386: f = romfopen("at386.nvr", "wb"); break; + case ROM_ACER386: f = romfopen("acer386.nvr", "wb"); break; + case ROM_MEGAPC: f = romfopen("megapc.nvr", "wb"); break; + case ROM_AMI386: f = romfopen("ami386.nvr", "wb"); break; + case ROM_AMI486: f = romfopen("ami486.nvr", "wb"); break; + case ROM_WIN486: f = romfopen("win486.nvr", "wb"); break; + case ROM_PCI486: f = romfopen("hot-433.nvr", "wb"); break; + case ROM_SIS496: f = romfopen("sis496.nvr", "wb"); break; + case ROM_430VX: f = romfopen("430vx.nvr", "wb"); break; + case ROM_REVENGE: f = romfopen("revenge.nvr", "wb"); break; + case ROM_ENDEAVOR: f = romfopen("endeavor.nvr", "wb"); break; default: return; } fwrite(nvrram,128,1,f); diff --git a/src/pc.c b/src/pc.c index 8f83040..a760e4c 100644 --- a/src/pc.c +++ b/src/pc.c @@ -238,18 +238,6 @@ void initpc() else #endif ioctl_open(cdrom_drive); - model_init(); - video_init(); - speaker_init(); - sound_card_init(sound_card_current); - if (GUS) - device_add(&gus_device); - if (GAMEBLASTER) - device_add(&cms_device); - if (SSI2001) - device_add(&ssi2001_device); - - pc_reset(); pit_reset(); /* if (romset==ROM_AMI386 || romset==ROM_AMI486) */fullspeed(); diff --git a/src/pci.c b/src/pci.c index 309edec..da535ce 100644 --- a/src/pci.c +++ b/src/pci.c @@ -7,26 +7,28 @@ void (*pci_card_write[32])(int func, int addr, uint8_t val, void *priv); uint8_t (*pci_card_read[32])(int func, int addr, void *priv); void *pci_priv[32]; -static int pci_index, pci_func, pci_card, pci_bus, pci_enable; +static int pci_index, pci_func, pci_card, pci_bus, pci_enable, pci_key; +static int pci_min_card, pci_max_card; + +void pci_cf8_write(uint16_t port, uint32_t val, void *p) +{ + pci_index = val & 0xff; + pci_func = (val >> 8) & 7; + pci_card = (val >> 11) & 31; + pci_bus = (val >> 16) & 0xff; + pci_enable = (val >> 31) & 1; +} + +uint32_t pci_cf8_read(uint16_t port, void *p) +{ + return pci_index | (pci_func << 8) | (pci_card << 11) | (pci_bus << 16) | (pci_enable << 31); +} void pci_write(uint16_t port, uint8_t val, void *priv) { +// pclog("pci_write: port=%04x val=%02x %08x:%08x\n", port, val, cs, pc); switch (port) { - case 0xcf8: - pci_index = val; - break; - case 0xcf9: - pci_func = val & 7; - pci_card = val >> 3; - break; - case 0xcfa: - pci_bus = val; - break; - case 0xcfb: - pci_enable = val & 0x80; - break; - case 0xcfc: case 0xcfd: case 0xcfe: case 0xcff: if (!pci_enable) return; @@ -42,17 +44,9 @@ void pci_write(uint16_t port, uint8_t val, void *priv) uint8_t pci_read(uint16_t port, void *priv) { +// pclog("pci_read: port=%04x %08x:%08x\n", port, cs, pc); switch (port) { - case 0xcf8: - return pci_index; - case 0xcf9: - return pci_card << 3; - case 0xcfa: - return pci_bus; - case 0xcfb: - return pci_enable; - case 0xcfc: case 0xcfd: case 0xcfe: case 0xcff: if (!pci_enable) return 0xff; @@ -65,15 +59,82 @@ uint8_t pci_read(uint16_t port, void *priv) return 0xff; } } + +void pci_type2_write(uint16_t port, uint8_t val, void *priv); +uint8_t pci_type2_read(uint16_t port, void *priv); + +void pci_type2_write(uint16_t port, uint8_t val, void *priv) +{ +// pclog("pci_type2_write: port=%04x val=%02x %08x:%08x\n", port, val, cs, pc); + if (port == 0xcf8) + { + pci_func = (val >> 1) & 7; + if (!pci_key && (val & 0xf0)) + io_sethandler(0xc000, 0x1000, pci_type2_read, NULL, NULL, pci_type2_write, NULL, NULL, NULL); + else + io_removehandler(0xc000, 0x1000, pci_type2_read, NULL, NULL, pci_type2_write, NULL, NULL, NULL); + pci_key = val & 0xf0; + } + else if (port == 0xcfa) + { + pci_bus = val; + } + else + { + pci_card = (port >> 8) & 0xf; + pci_index = port & 0xff; + +// pclog("PCI write bus %i card %i func %i index %02X val %02X %04X:%04X\n", pci_bus, pci_card, pci_func, pci_index | (port & 3), val, CS, pc); -void pci_init() + if (!pci_bus && pci_card_write[pci_card]) + pci_card_write[pci_card](pci_func, pci_index | (port & 3), val, pci_priv[pci_card]); + } +} + +uint8_t pci_type2_read(uint16_t port, void *priv) +{ +// pclog("pci_type2_read: port=%04x %08x:%08x\n", port, cs, pc); + if (port == 0xcf8) + { + return pci_key | (pci_func << 1); + } + else if (port == 0xcfa) + { + return pci_bus; + } + else + { + pci_card = (port >> 8) & 0xf; + pci_index = port & 0xff; + +// pclog("PCI read bus %i card %i func %i index %02X %04X:%04X\n", pci_bus, pci_card, pci_func, pci_index | (port & 3), CS, pc); + + if (!pci_bus && pci_card_write[pci_card]) + return pci_card_read[pci_card](pci_func, pci_index | (port & 3), pci_priv[pci_card]); + } + return 0xff; +} + +void pci_init(int type, int min_card, int max_card) { int c; - io_sethandler(0x0cf8, 0x0008, pci_read, NULL, NULL, pci_write, NULL, NULL, NULL); + if (type == PCI_CONFIG_TYPE_1) + { + io_sethandler(0x0cf8, 0x0001, NULL, NULL, pci_cf8_read, NULL, NULL, pci_cf8_write, NULL); + io_sethandler(0x0cfc, 0x0004, pci_read, NULL, NULL, pci_write, NULL, NULL, NULL); + } + else + { + io_sethandler(0x0cf8, 0x0001, pci_type2_read, NULL, NULL, pci_type2_write, NULL, NULL, NULL); + io_sethandler(0x0cfa, 0x0001, pci_type2_read, NULL, NULL, pci_type2_write, NULL, NULL, NULL); + } for (c = 0; c < 32; c++) pci_card_read[c] = pci_card_write[c] = pci_priv[c] = NULL; + + pci_min_card = min_card; + pci_max_card = max_card; } void pci_add_specific(int card, uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv) @@ -87,7 +148,7 @@ void pci_add(uint8_t (*read)(int func, int addr, void *priv), void (*write)(int { int c; - for (c = 0; c < 32; c++) + for (c = pci_min_card; c <= pci_max_card; c++) { if (!pci_card_read[c] && !pci_card_write[c]) { diff --git a/src/pci.h b/src/pci.h index f053f2f..321d7ca 100644 --- a/src/pci.h +++ b/src/pci.h @@ -1,4 +1,4 @@ -void pci_init(); +void pci_init(int type, int min_card, int max_card); void pci_add_specific(int card, uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv); void pci_add(uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv); @@ -6,3 +6,6 @@ void pci_add(uint8_t (*read)(int func, int addr, void *priv), void (*write)(int #define PCI_COMMAND_IO 0x01 #define PCI_COMMAND_MEM 0x02 + +#define PCI_CONFIG_TYPE_1 1 +#define PCI_CONFIG_TYPE_2 2 diff --git a/src/win.c b/src/win.c index b3a83e5..f9b2ae6 100644 --- a/src/win.c +++ b/src/win.c @@ -542,7 +542,8 @@ int WINAPI WinMain (HINSTANCE hThisInstance, } loadbios(); - + resetpchard(); + timeBeginPeriod(1); atexit(releasemouse);