From 2aa5d8f5b29dcc4964c972d8d3a9f273d184b97e Mon Sep 17 00:00:00 2001 From: Adrien Moulin Date: Sat, 23 Jul 2022 13:38:10 +0200 Subject: [PATCH 1/2] PIT: add alternative faster PIT This is enabled by default on 486+ CPUs and can be forced disabled/enabled with pit_mode=0/1 --- src/86box.c | 1 + src/CMakeLists.txt | 2 +- src/config.c | 7 + src/device/keyboard_xt.c | 2 +- src/include/86box/86box.h | 1 + src/include/86box/pit.h | 43 ++- src/include/86box/pit_fast.h | 72 ++++ src/machine/m_amstrad.c | 2 +- src/machine/m_at.c | 2 +- src/machine/m_europc.c | 2 +- src/machine/m_pcjr.c | 16 +- src/machine/m_ps1.c | 2 +- src/machine/m_ps2_isa.c | 2 +- src/machine/m_ps2_mca.c | 3 +- src/machine/m_xt.c | 2 +- src/machine/m_xt_compaq.c | 4 +- src/machine/m_xt_laserxt.c | 2 +- src/machine/m_xt_olivetti.c | 6 +- src/machine/m_xt_philips.c | 2 +- src/machine/m_xt_t1000.c | 4 +- src/machine/m_xt_zenith.c | 2 +- src/machine/machine.c | 17 +- src/pic.c | 4 +- src/pit.c | 168 +++++---- src/pit_fast.c | 706 +++++++++++++++++++++++++++++++++++ src/port_6x.c | 2 +- 26 files changed, 968 insertions(+), 108 deletions(-) create mode 100644 src/include/86box/pit_fast.h create mode 100644 src/pit_fast.c diff --git a/src/86box.c b/src/86box.c index 805cc60bf..cb9fa52a7 100644 --- a/src/86box.c +++ b/src/86box.c @@ -182,6 +182,7 @@ int confirm_reset = 1; /* (C) enable reset confirmation */ int confirm_exit = 1; /* (C) enable exit confirmation */ int confirm_save = 1; /* (C) enable save confirmation */ int enable_discord = 0; /* (C) enable Discord integration */ +int pit_mode = -1; /* (C) force setting PIT mode */ /* Statistics. */ extern int mmuflush; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d1da45172..1420aaa89 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,7 +16,7 @@ # add_executable(86Box 86box.c config.c log.c random.c timer.c io.c acpi.c apm.c - dma.c ddma.c discord.c nmi.c pic.c pit.c port_6x.c port_92.c ppi.c pci.c + dma.c ddma.c discord.c nmi.c pic.c pit.c pit_fast.c port_6x.c port_92.c ppi.c pci.c mca.c usb.c fifo8.c device.c nvr.c nvr_at.c nvr_ps2.c machine_status.c) if(CMAKE_SYSTEM_NAME MATCHES "Linux") diff --git a/src/config.c b/src/config.c index c44c69d4a..8554dcc7a 100644 --- a/src/config.c +++ b/src/config.c @@ -886,6 +886,8 @@ load_machine(void) } else time_sync = !!config_get_int(cat, "enable_sync", 1); + pit_mode = config_get_int(cat, "pit_mode", -1); + /* Remove this after a while.. */ config_delete_var(cat, "nvr_path"); config_delete_var(cat, "enable_sync"); @@ -2479,6 +2481,11 @@ save_machine(void) else config_set_string(cat, "time_sync", "disabled"); + if (pit_mode == -1) + config_delete_var(cat, "pit_mode"); + else + config_set_int(cat, "pit_mode", pit_mode); + delete_section_if_empty(cat); } diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index 9b19669e2..d13bab56d 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -535,7 +535,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) if (speaker_enable) was_speaker_enable = 1; - pit_ctr_set_gate(&pit->counters[2], val & 1); + pit_devs[0].set_gate(pit_devs[0].data, 2, val & 1); if (val & 0x80) { kbd->pa = 0; diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 6afa66695..86fe740c9 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -135,6 +135,7 @@ extern int is_pentium; /* TODO: Move back to cpu/cpu.h when it's figured out, how to remove that hack from the ET4000/W32p. */ extern int fixed_size_x, fixed_size_y; extern double mouse_sensitivity; /* (C) Mouse sensitivity scale */ +extern int pit_mode; /* (C) force setting PIT mode */ extern char exe_path[2048]; /* path (dir) of executable */ diff --git a/src/include/86box/pit.h b/src/include/86box/pit.h index e823794df..95541014b 100644 --- a/src/include/86box/pit.h +++ b/src/include/86box/pit.h @@ -58,9 +58,33 @@ typedef struct PIT { uint8_t ctrl; } pit_t; +enum { + PIT_8253 = 0, + PIT_8254, + PIT_8253_FAST, + PIT_8254_FAST +}; + +typedef struct { + uint8_t (*read)(uint16_t addr, void *priv); + void (*write)(uint16_t addr, uint8_t val, void *priv); + /* Gets a counter's count. */ + uint16_t (*get_count)(void *data, int counter_id); + /* Sets a counter's GATE input. */ + void (*set_gate)(void *data, int counter_id, int gate); + /* Sets if a counter's CLOCK input is from the timer or not - used by PCjr. */ + void(*set_using_timer)(void *data, int counter_id, int using_timer); + /* Sets a counter's OUT output handler. */ + void (*set_out_func)(void *data, int counter_id, void (*func)(int new_out, int old_out)); + /* Sets a counter's load count handler. */ + void (*set_load_func)(void *data, int counter_id, void (*func)(uint8_t new_m, int new_count)); + void (*ctr_clock)(void *data, int counter_id); + void *data; +} pit_intf_t; + +extern pit_intf_t pit_devs[2]; +extern const pit_intf_t pit_classic_intf; -extern pit_t *pit, - *pit2; extern double SYSCLK, PCICLK, AGPCLK; @@ -74,26 +98,13 @@ extern uint64_t PITCONST, ISACONST, extern int refresh_at_enable; - -/* Gets a counter's count. */ -extern uint16_t pit_ctr_get_count(ctr_t *ctr); -/* Sets a counter's load count handler. */ -extern void pit_ctr_set_load_func(ctr_t *ctr, void (*func)(uint8_t new_m, int new_count)); -/* Sets a counter's OUT output handler. */ -extern void pit_ctr_set_out_func(ctr_t *ctr, void (*func)(int new_out, int old_out)); -/* Sets a counter's GATE input. */ -extern void pit_ctr_set_gate(ctr_t *ctr, int gate); /* Sets a counter's CLOCK input. */ extern void pit_ctr_set_clock(ctr_t *ctr, int clock); -/* Sets if a counter's CLOCK input is from the timer or not - used by PCjr. */ -extern void pit_ctr_set_using_timer(ctr_t *ctr, int using_timer); extern pit_t * pit_common_init(int type, void (*out0)(int new_out, int old_out), void (*out1)(int new_out, int old_out)); -extern pit_t * pit_ps2_init(void); +extern pit_t * pit_ps2_init(int type); extern void pit_reset(pit_t *dev); -extern void pit_irq0_timer(int new_out, int old_out); -extern void pit_irq0_timer_pcjr(int new_out, int old_out); extern void pit_irq0_timer_ps2(int new_out, int old_out); extern void pit_refresh_timer_xt(int new_out, int old_out); diff --git a/src/include/86box/pit_fast.h b/src/include/86box/pit_fast.h new file mode 100644 index 000000000..bc09174fb --- /dev/null +++ b/src/include/86box/pit_fast.h @@ -0,0 +1,72 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Header of the implementation of the Intel 8253/8254 + * Programmable Interval Timer. + * + * + * + * Author: Miran Grca, + * Copyright 2019,2020 Miran Grca. + */ + +#ifndef EMU_PIT_FAST_H +#define EMU_PIT_FAST_H + +typedef struct { + uint8_t m, ctrl, + read_status, latch, bcd; + + uint16_t rl; + + int rm, wm, gate, out, + newcount, clock, using_timer, latched, + do_read_status; + int enabled; + int disabled; + int initial; + int thit; + int running; + int rereadlatch; + + union { + int count; + struct { + int units : 4; + int tens : 4; + int hundreds : 4; + int thousands : 4; + int myriads : 4; + }; + }; + + uint32_t l; + pc_timer_t timer; + + void (*load_func)(uint8_t new_m, int new_count); + void (*out_func)(int new_out, int old_out); +} ctrf_t; + +typedef struct { + int flags; + ctrf_t counters[3]; + + uint8_t ctrl; +} pitf_t; + +extern const pit_intf_t pit_fast_intf; + +#ifdef EMU_DEVICE_H +extern const device_t i8253_fast_device; +extern const device_t i8254_fast_device; +extern const device_t i8254_sec_fast_device; +extern const device_t i8254_ext_io_fast_device; +extern const device_t i8254_ps2_fast_device; +#endif + +#endif /*EMU_PIT_FAST_H*/ diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index 43a8093c8..3b0235d51 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -2059,7 +2059,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) speaker_enable = val & 0x02; if (speaker_enable) was_speaker_enable = 1; - pit_ctr_set_gate(&pit->counters[2], val & 0x01); + pit_devs[0].set_gate(pit_devs[0].data, 2, val & 0x01); if (val & 0x80) { /* Keyboard enabled, so enable PA reading. */ diff --git a/src/machine/m_at.c b/src/machine/m_at.c index dc47b6207..df3c4bd8b 100644 --- a/src/machine/m_at.c +++ b/src/machine/m_at.c @@ -66,7 +66,7 @@ machine_at_common_init_ex(const machine_t *model, int type) machine_common_init(model); refresh_at_enable = 1; - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_at); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_at); pic2_init(); dma16_init(); diff --git a/src/machine/m_europc.c b/src/machine/m_europc.c index 2c035ded1..905515225 100644 --- a/src/machine/m_europc.c +++ b/src/machine/m_europc.c @@ -718,7 +718,7 @@ machine_europc_init(const machine_t *model) return ret; machine_common_init(model); - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); nmi_init(); diff --git a/src/machine/m_pcjr.c b/src/machine/m_pcjr.c index 2491e5064..2665ea164 100644 --- a/src/machine/m_pcjr.c +++ b/src/machine/m_pcjr.c @@ -627,7 +627,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) speaker_enable = val & 2; if (speaker_enable) was_speaker_enable = 1; - pit_ctr_set_gate(&pit->counters[2], val & 1); + pit_devs[0].set_gate(pit_devs[0].data, 2, val & 1); sn76489_mute = speaker_mute = 1; switch (val & 0x60) { case 0x00: @@ -642,7 +642,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) case 0xa0: nmi_mask = val & 0x80; - pit_ctr_set_using_timer(&pit->counters[1], !(val & 0x20)); + pit_devs[0].set_using_timer(pit_devs[0].data, 1, !(val & 0x20)); break; } } @@ -770,6 +770,18 @@ speed_changed(void *priv) recalc_timings(pcjr); } +void +pit_irq0_timer_pcjr(int new_out, int old_out) +{ + if (new_out && !old_out) { + picint(1); + pit_devs[0].ctr_clock(pit_devs[0].data, 1); + } + + if (!new_out) + picintc(1); +} + static const device_config_t pcjr_config[] = { { .name = "display_type", diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index 101746a03..19abb00bf 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -327,7 +327,7 @@ ps1_common_init(const machine_t *model) machine_common_init(model); refresh_at_enable = 1; - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_at); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_at); dma16_init(); pic2_init(); diff --git a/src/machine/m_ps2_isa.c b/src/machine/m_ps2_isa.c index 24fa0dfb1..094fc8a5f 100644 --- a/src/machine/m_ps2_isa.c +++ b/src/machine/m_ps2_isa.c @@ -190,7 +190,7 @@ ps2_isa_common_init(const machine_t *model) machine_common_init(model); refresh_at_enable = 1; - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_at); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_at); dma16_init(); pic2_init(); diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index 7aea5a319..665d42972 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -1363,7 +1363,8 @@ machine_ps2_common_init(const machine_t *model) device_add(&ps_no_nmi_nvr_device); pic2_init(); - pit_ps2_init(); + int pit_type = ((pit_mode == -1 && is486) || pit_mode == 1) ? PIT_8254_FAST : PIT_8254; + pit_ps2_init(pit_type); nmi_mask = 0x80; diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index f95ee2fe0..5b31920c5 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -24,7 +24,7 @@ machine_xt_common_init(const machine_t *model) { machine_common_init(model); - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); if (fdc_type == FDC_INTERNAL) device_add(&fdc_xt_device); diff --git a/src/machine/m_xt_compaq.c b/src/machine/m_xt_compaq.c index bd355a161..a705f0e2b 100644 --- a/src/machine/m_xt_compaq.c +++ b/src/machine/m_xt_compaq.c @@ -50,7 +50,7 @@ machine_xt_compaq_deskpro_init(const machine_t *model) machine_common_init(model); - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); device_add(&keyboard_xt_compaq_device); if (fdc_type == FDC_INTERNAL) @@ -78,7 +78,7 @@ machine_xt_compaq_portable_init(const machine_t *model) machine_common_init(model); - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); device_add(&keyboard_xt_compaq_device); if (fdc_type == FDC_INTERNAL) diff --git a/src/machine/m_xt_laserxt.c b/src/machine/m_xt_laserxt.c index 58b7d3774..21681a5c2 100644 --- a/src/machine/m_xt_laserxt.c +++ b/src/machine/m_xt_laserxt.c @@ -167,7 +167,7 @@ machine_xt_lxt3_init(const machine_t *model) machine_common_init(model); - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); device_add(&keyboard_xt_lxt3_device); diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c index 716bb9c18..62fcda138 100644 --- a/src/machine/m_xt_olivetti.c +++ b/src/machine/m_xt_olivetti.c @@ -241,7 +241,7 @@ m24_kbd_write(uint16_t port, uint8_t val, void *priv) speaker_enable = val & 2; if (speaker_enable) was_speaker_enable = 1; - pit_ctr_set_gate(&pit->counters[2], val & 1); + pit_devs[0].set_gate(pit_devs[0].data, 2, val & 1); break; } } @@ -792,7 +792,7 @@ machine_xt_m240_init(const machine_t *model) machine_common_init(model); - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); /* Address 66-67 = mainboard dip-switch settings */ io_sethandler(0x0066, 2, m24_read, NULL, NULL, NULL, NULL, NULL, NULL); @@ -846,7 +846,7 @@ machine_xt_m19_init(const machine_t *model) machine_common_init(model); - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); /* On-board FDC cannot be disabled */ device_add(&fdc_xt_device); diff --git a/src/machine/m_xt_philips.c b/src/machine/m_xt_philips.c index cafccf061..b10e3a37e 100644 --- a/src/machine/m_xt_philips.c +++ b/src/machine/m_xt_philips.c @@ -152,7 +152,7 @@ machine_xt_philips_common_init(const machine_t *model) { machine_common_init(model); - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); nmi_init(); diff --git a/src/machine/m_xt_t1000.c b/src/machine/m_xt_t1000.c index 961cc627a..ba96b74e7 100644 --- a/src/machine/m_xt_t1000.c +++ b/src/machine/m_xt_t1000.c @@ -911,7 +911,7 @@ machine_xt_t1000_init(const machine_t *model) machine_common_init(model); - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); device_add(&keyboard_xt_device); t1000.fdc = device_add(&fdc_xt_device); nmi_init(); @@ -979,7 +979,7 @@ machine_xt_t1200_init(const machine_t *model) write_t1200_nvram, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, &t1000); - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); device_add(&keyboard_xt_device); t1000.fdc = device_add(&fdc_xt_t1x00_device); nmi_init(); diff --git a/src/machine/m_xt_zenith.c b/src/machine/m_xt_zenith.c index f9806b610..6eab9aee2 100644 --- a/src/machine/m_xt_zenith.c +++ b/src/machine/m_xt_zenith.c @@ -122,7 +122,7 @@ machine_zenith_init(const machine_t *model){ device_add(&zenith_scratchpad_device); - pit_ctr_set_out_func(&pit->counters[1], pit_refresh_timer_xt); + pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); device_add(&keyboard_xt_zenith_device); diff --git a/src/machine/machine.c b/src/machine/machine.c index 67819b247..774b972c2 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -161,6 +161,16 @@ machine_available(int m) } +void +pit_irq0_timer(int new_out, int old_out) +{ + if (new_out && !old_out) + picint(1); + + if (!new_out) + picintc(1); +} + void machine_common_init(const machine_t *model) { @@ -168,5 +178,10 @@ machine_common_init(const machine_t *model) pic_init(); dma_init(); - pit_common_init(!!IS_AT(machine), pit_irq0_timer, NULL); + int pit_type = IS_AT(machine) ? PIT_8254 : PIT_8253; + /* Select fast PIT if needed */ + if ((pit_mode == -1 && is486) || pit_mode == 1) + pit_type += 2; + + pit_common_init(pit_type, pit_irq0_timer, NULL); } diff --git a/src/pic.c b/src/pic.c index ca2bff2f7..fe6b29fc8 100644 --- a/src/pic.c +++ b/src/pic.c @@ -750,8 +750,8 @@ picinterrupt() pic.interrupt |= 0x40; /* Mark slave pending. */ } - if ((pic.interrupt == 0) && (pit2 != NULL)) - pit_ctr_set_gate(&pit2->counters[0], 0); + if ((pic.interrupt == 0) && (pit_devs[1].data != NULL)) + pit_devs[1].set_gate(pit_devs[1].data, 0, 0); /* Two ACK's - do them in a loop to avoid potential compiler misoptimizations. */ for (i = 0; i < 2; i++) { diff --git a/src/pit.c b/src/pit.c index f19a1acf7..ba71928ca 100644 --- a/src/pit.c +++ b/src/pit.c @@ -34,14 +34,15 @@ #include <86box/pic.h> #include <86box/timer.h> #include <86box/pit.h> +#include <86box/pit_fast.h> #include <86box/ppi.h> #include <86box/machine.h> #include <86box/sound.h> #include <86box/snd_speaker.h> #include <86box/video.h> +pit_intf_t pit_devs[2]; -pit_t *pit, *pit2; double cpuclock, PITCONSTD, SYSCLK, isa_timing, @@ -67,12 +68,6 @@ int64_t firsttime = 1; #define PIT_SECONDARY 128 /* The PIT is secondary (ports 0048-004B). */ -enum { - PIT_8253 = 0, - PIT_8254 -}; - - #ifdef ENABLE_PIT_LOG int pit_do_log = ENABLE_PIT_LOG; @@ -293,8 +288,11 @@ ctr_tick(ctr_t *ctr) static void -ctr_clock(ctr_t *ctr) +ctr_clock(void *data, int counter_id) { + pit_t *pit = (pit_t *)data; + ctr_t *ctr = &pit->counters[counter_id]; + /* FIXME: Is this even needed? */ if ((ctr->state == 3) && (ctr->m != 2) && (ctr->m != 3)) return; @@ -379,35 +377,47 @@ ctr_latch_count(ctr_t *ctr) uint16_t -pit_ctr_get_count(ctr_t *ctr) +pit_ctr_get_count(void *data, int counter_id) { + pit_t *pit = (pit_t *)data; + ctr_t *ctr = &pit->counters[counter_id]; + return (uint16_t) ctr->l; } void -pit_ctr_set_load_func(ctr_t *ctr, void (*func)(uint8_t new_m, int new_count)) +pit_ctr_set_load_func(void *data, int counter_id, void (*func)(uint8_t new_m, int new_count)) { - if (ctr == NULL) + if (data == NULL) return; + pit_t *pit = (pit_t *)data; + ctr_t *ctr = &pit->counters[counter_id]; + ctr->load_func = func; } void -pit_ctr_set_out_func(ctr_t *ctr, void (*func)(int new_out, int old_out)) +pit_ctr_set_out_func(void *data, int counter_id, void (*func)(int new_out, int old_out)) { - if (ctr == NULL) + if (data == NULL) return; + pit_t *pit = (pit_t *)data; + ctr_t *ctr = &pit->counters[counter_id]; + ctr->out_func = func; } void -pit_ctr_set_gate(ctr_t *ctr, int gate) +pit_ctr_set_gate(void *data, int counter_id, int gate) { + pit_t *pit = (pit_t *)data; + ctr_t *ctr = &pit->counters[counter_id]; + int old = ctr->gate; uint8_t mode = ctr->m & 3; @@ -470,10 +480,12 @@ pit_ctr_set_clock(ctr_t *ctr, int clock) void -pit_ctr_set_using_timer(ctr_t *ctr, int using_timer) +pit_ctr_set_using_timer(void *data, int counter_id, int using_timer) { - timer_process(); - + if (tsc > 0) + timer_process(); + pit_t *pit = (pit_t *)data; + ctr_t *ctr = &pit->counters[counter_id]; ctr->using_timer = using_timer; } @@ -673,46 +685,19 @@ pit_read(uint16_t addr, void *priv) } -/* FIXME: Should be moved to machine.c (default for most machine). */ -void -pit_irq0_timer(int new_out, int old_out) -{ - if (new_out && !old_out) - picint(1); - - if (!new_out) - picintc(1); -} - - -void -pit_irq0_timer_pcjr(int new_out, int old_out) -{ - if (new_out && !old_out) { - picint(1); - ctr_clock(&pit->counters[1]); - } - - if (!new_out) - picintc(1); -} - - void pit_irq0_timer_ps2(int new_out, int old_out) { - ctr_t *ctr = &pit2->counters[0]; - if (new_out && !old_out) { picint(1); - pit_ctr_set_gate(ctr, 1); + pit_devs[1].set_gate(pit_devs[1].data, 0, 1); } if (!new_out) picintc(1); if (!new_out && old_out) - ctr_clock(ctr); + pit_devs[1].ctr_clock(pit_devs[1].data, 0); } @@ -742,7 +727,8 @@ pit_speaker_timer(int new_out, int old_out) speaker_update(); - l = pit->counters[2].l ? pit->counters[2].l : 0x10000; + uint16_t count = pit_devs[0].get_count(pit_devs[0].data, 2); + l = count ? count : 0x10000; if (l < 25) speakon = 0; else @@ -809,11 +795,11 @@ pit_close(void *priv) { pit_t *dev = (pit_t *) priv; - if (dev == pit) - pit = NULL; + if (dev == pit_devs[0].data) + pit_devs[0].data = NULL; - if (dev == pit2) - pit2 = NULL; + if (dev == pit_devs[1].data) + pit_devs[1].data = NULL; if (dev != NULL) free(dev); @@ -915,47 +901,83 @@ pit_t * pit_common_init(int type, void (*out0)(int new_out, int old_out), void (*out1)(int new_out, int old_out)) { int i; + void *pit; + + pit_intf_t *pit_intf = &pit_devs[0]; switch (type) { case PIT_8253: default: pit = device_add(&i8253_device); + *pit_intf = pit_classic_intf; break; case PIT_8254: pit = device_add(&i8254_device); + *pit_intf = pit_classic_intf; break; + case PIT_8253_FAST: + pit = device_add(&i8253_fast_device); + *pit_intf = pit_fast_intf; + break; + case PIT_8254_FAST: + pit = device_add(&i8254_fast_device); + *pit_intf = pit_fast_intf; + break; + } + pit_intf->data = pit; + for (i = 0; i < 3; i++) { - pit->counters[i].gate = 1; - pit->counters[i].using_timer = 1; + pit_intf->set_gate(pit_intf->data, i, 1); + pit_intf->set_using_timer(pit_intf->data, i, 1); } - pit_ctr_set_out_func(&pit->counters[0], out0); - pit_ctr_set_out_func(&pit->counters[1], out1); - pit_ctr_set_out_func(&pit->counters[2], pit_speaker_timer); - pit_ctr_set_load_func(&pit->counters[2], speaker_set_count); - pit->counters[2].gate = 0; + pit_intf->set_out_func(pit_intf->data, 0, out0); + pit_intf->set_out_func(pit_intf->data, 1, out1); + pit_intf->set_out_func(pit_intf->data, 2, pit_speaker_timer); + pit_intf->set_load_func(pit_intf->data, 2, speaker_set_count); + + pit_intf->set_gate(pit_intf->data, 2, 0); return pit; } pit_t * -pit_ps2_init(void) +pit_ps2_init(int type) { - pit2 = device_add(&i8254_ps2_device); + void *pit; - pit_handler(1, 0x0044, 0x0001, pit2); - pit_handler(1, 0x0047, 0x0001, pit2); + pit_intf_t *ps2_pit = &pit_devs[1]; - pit2->counters[0].gate = 0; - pit2->counters[0].using_timer = pit2->counters[1].using_timer = pit2->counters[2].using_timer = 0; + switch (type) { + case PIT_8254: + default: + pit = device_add(&i8254_ps2_device); + *ps2_pit = pit_classic_intf; + break; - pit_ctr_set_out_func(&pit->counters[0], pit_irq0_timer_ps2); - pit_ctr_set_out_func(&pit2->counters[0], pit_nmi_timer_ps2); + case PIT_8254_FAST: + pit = device_add(&i8254_ps2_fast_device); + *ps2_pit = pit_fast_intf; + break; + } - return pit2; + ps2_pit->data = pit; + + ps2_pit->set_gate(ps2_pit->data, 0, 0); + for (int i = 0; i < 3; i++) { + ps2_pit->set_using_timer(ps2_pit->data, i, 0); + } + + io_sethandler(0x0044, 0x0001, ps2_pit->read, NULL, NULL, ps2_pit->write, NULL, NULL, pit); + io_sethandler(0x0047, 0x0001, ps2_pit->read, NULL, NULL, ps2_pit->write, NULL, NULL, pit); + + pit_devs[0].set_out_func(pit_devs[0].data, 0, pit_irq0_timer_ps2); + ps2_pit->set_out_func(ps2_pit->data, 0, pit_nmi_timer_ps2); + + return pit; } @@ -1063,3 +1085,15 @@ pit_set_clock(int clock) device_speed_changed(); } + +const pit_intf_t pit_classic_intf = { + &pit_read, + &pit_write, + &pit_ctr_get_count, + &pit_ctr_set_gate, + &pit_ctr_set_using_timer, + &pit_ctr_set_out_func, + &pit_ctr_set_load_func, + &ctr_clock, + NULL, +}; \ No newline at end of file diff --git a/src/pit_fast.c b/src/pit_fast.c new file mode 100644 index 000000000..704cfd68c --- /dev/null +++ b/src/pit_fast.c @@ -0,0 +1,706 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the Intel 8253/8254 Programmable Interval + * Timer. + * + * + * + * Author: Miran Grca, + * Copyright 2019 Miran Grca. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/device.h> +#include <86box/timer.h> +#include <86box/cassette.h> +#include <86box/dma.h> +#include <86box/io.h> +#include <86box/nmi.h> +#include <86box/pic.h> +#include <86box/timer.h> +#include <86box/pit.h> +#include <86box/pit_fast.h> +#include <86box/ppi.h> +#include <86box/machine.h> +#include <86box/sound.h> +#include <86box/snd_speaker.h> +#include <86box/video.h> + +#define PIT_PS2 16 /* The PIT is the PS/2's second PIT. */ +#define PIT_EXT_IO 32 /* The PIT has externally specified port I/O. */ +#define PIT_CUSTOM_CLOCK 64 /* The PIT uses custom clock inputs provided by another provider. */ +#define PIT_SECONDARY 128 /* The PIT is secondary (ports 0048-004B). */ + +#ifdef ENABLE_PIT_LOG +int pit_do_log = ENABLE_PIT_LOG; + +static void +pit_log(const char *fmt, ...) +{ + va_list ap; + + if (pit_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define pit_log(fmt, ...) +#endif + +static void +pitf_ctr_set_out(ctrf_t *ctr, int out) +{ + if (ctr == NULL) + return; + + if (ctr->out_func != NULL) + ctr->out_func(out, ctr->out); + ctr->out = out; +} + +static void +pitf_ctr_set_load_func(void *data, int counter_id, void (*func)(uint8_t new_m, int new_count)) +{ + if (data == NULL) + return; + + pitf_t *pit = (pitf_t *)data; + ctrf_t *ctr = &pit->counters[counter_id]; + + ctr->load_func = func; +} + +static uint16_t +pitf_ctr_get_count(void *data, int counter_id) +{ + pitf_t *pit = (pitf_t *)data; + ctrf_t *ctr = &pit->counters[counter_id]; + return (uint16_t) ctr->l; +} + +static void +pitf_ctr_set_out_func(void *data, int counter_id, void (*func)(int new_out, int old_out)) +{ + if (data == NULL) + return; + + pitf_t *pit = (pitf_t *)data; + ctrf_t *ctr = &pit->counters[counter_id]; + + ctr->out_func = func; +} + +static void +pitf_ctr_set_using_timer(void *data, int counter_id, int using_timer) +{ + if (tsc > 0) + timer_process(); + + pitf_t *pit = (pitf_t *)data; + ctrf_t *ctr = &pit->counters[counter_id]; + ctr->using_timer = using_timer; +} + +static int +pitf_read_timer(ctrf_t *ctr) +{ + if (ctr->using_timer && !(ctr->m == 3 && !ctr->gate) && timer_is_enabled(&ctr->timer)) { + int read = (int) ((timer_get_remaining_u64(&ctr->timer)) / PITCONST); + if (ctr->m == 2) + read++; + if (read < 0) + read = 0; + if (read > 0x10000) + read = 0x10000; + if (ctr->m == 3) + read <<= 1; + return read; + } + if (ctr->m == 2) + return ctr->count + 1; + return ctr->count; +} + +/*Dump timer count back to pit->count[], and disable timer. This should be used + when stopping a PIT timer, to ensure the correct value can be read back.*/ +static void +pitf_dump_and_disable_timer(ctrf_t *ctr) +{ + if (ctr->using_timer && timer_is_enabled(&ctr->timer)) { + ctr->count = pitf_read_timer(ctr); + timer_disable(&ctr->timer); + } +} + +static void +pitf_ctr_load(ctrf_t *ctr) +{ + int l = ctr->l ? ctr->l : 0x10000; + + ctr->newcount = 0; + ctr->disabled = 0; + + switch (ctr->m) { + case 0: /*Interrupt on terminal count*/ + ctr->count = l; + if (ctr->using_timer) + timer_set_delay_u64(&ctr->timer, (uint64_t) (l * PITCONST)); + pitf_ctr_set_out(ctr, 0); + ctr->thit = 0; + ctr->enabled = ctr->gate; + break; + case 1: /*Hardware retriggerable one-shot*/ + ctr->enabled = 1; + break; + case 2: /*Rate generator*/ + if (ctr->initial) { + ctr->count = l - 1; + if (ctr->using_timer) + timer_set_delay_u64(&ctr->timer, (uint64_t) ((l - 1) * PITCONST)); + pitf_ctr_set_out(ctr, 1); + ctr->thit = 0; + } + ctr->enabled = ctr->gate; + break; + case 3: /*Square wave mode*/ + if (ctr->initial) { + ctr->count = l; + if (ctr->using_timer) + timer_set_delay_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * PITCONST)); + pitf_ctr_set_out(ctr, 1); + ctr->thit = 0; + } + ctr->enabled = ctr->gate; + break; + case 4: /*Software triggered stobe*/ + if (!ctr->thit && !ctr->initial) + ctr->newcount = 1; + else { + ctr->count = l; + if (ctr->using_timer) + timer_set_delay_u64(&ctr->timer, (uint64_t) (l * PITCONST)); + pitf_ctr_set_out(ctr, 0); + ctr->thit = 0; + } + ctr->enabled = ctr->gate; + break; + case 5: /*Hardware triggered stobe*/ + ctr->enabled = 1; + break; + } + + if (ctr->load_func != NULL) + ctr->load_func(ctr->m, l); + + ctr->initial = 0; + ctr->running = ctr->enabled && ctr->using_timer && !ctr->disabled; + if (ctr->using_timer && !ctr->running) + pitf_dump_and_disable_timer(ctr); +} + +static void +pitf_set_gate_no_timer(ctrf_t *ctr, int gate) +{ + int l = ctr->l ? ctr->l : 0x10000; + + if (ctr->disabled) { + ctr->gate = gate; + return; + } + + switch (ctr->m) { + case 0: /*Interrupt on terminal count*/ + case 4: /*Software triggered stobe*/ + if (ctr->using_timer && !ctr->running) + timer_set_delay_u64(&ctr->timer, (uint64_t) (l * PITCONST)); + ctr->enabled = gate; + break; + case 1: /*Hardware retriggerable one-shot*/ + case 5: /*Hardware triggered stobe*/ + if (gate && !ctr->gate) { + ctr->count = l; + if (ctr->using_timer) + timer_set_delay_u64(&ctr->timer, (uint64_t) (l * PITCONST)); + pitf_ctr_set_out(ctr, 0); + ctr->thit = 0; + ctr->enabled = 1; + } + break; + case 2: /*Rate generator*/ + if (gate && !ctr->gate) { + ctr->count = l - 1; + if (ctr->using_timer) + timer_set_delay_u64(&ctr->timer, (uint64_t) (l * PITCONST)); + pitf_ctr_set_out(ctr, 1); + ctr->thit = 0; + } + ctr->enabled = gate; + break; + case 3: /*Square wave mode*/ + if (gate && !ctr->gate) { + ctr->count = l; + if (ctr->using_timer) + timer_set_delay_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * PITCONST)); + pitf_ctr_set_out(ctr, 1); + ctr->thit = 0; + } + ctr->enabled = gate; + break; + } + ctr->gate = gate; + ctr->running = ctr->enabled && ctr->using_timer && !ctr->disabled; + if (ctr->using_timer && !ctr->running) + pitf_dump_and_disable_timer(ctr); +} + +static void +pitf_ctr_set_gate(void *data, int counter_id, int gate) +{ + pitf_t *pit = (pitf_t *)data; + ctrf_t *ctr = &pit->counters[counter_id]; + + if (ctr->disabled) { + ctr->gate = gate; + return; + } + + pitf_set_gate_no_timer(ctr, gate); +} + +static void +pitf_over(ctrf_t *ctr) +{ + int l = ctr->l ? ctr->l : 0x10000; + if (ctr->disabled) { + ctr->count += 0xffff; + if (ctr->using_timer) + timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * PITCONST)); + return; + } + + switch (ctr->m) { + case 0: /*Interrupt on terminal count*/ + case 1: /*Hardware retriggerable one-shot*/ + if (!ctr->thit) + pitf_ctr_set_out(ctr, 1); + ctr->thit = 1; + ctr->count += 0xffff; + if (ctr->using_timer) + timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * PITCONST)); + break; + case 2: /*Rate generator*/ + ctr->count += l; + if (ctr->using_timer) + timer_advance_u64(&ctr->timer, (uint64_t) (l * PITCONST)); + pitf_ctr_set_out(ctr, 0); + pitf_ctr_set_out(ctr, 1); + break; + case 3: /*Square wave mode*/ + if (ctr->out) { + pitf_ctr_set_out(ctr, 0); + ctr->count += (l >> 1); + if (ctr->using_timer) + timer_advance_u64(&ctr->timer, (uint64_t) ((l >> 1) * PITCONST)); + } else { + pitf_ctr_set_out(ctr, 1); + ctr->count += ((l + 1) >> 1); + if (ctr->using_timer) + timer_advance_u64(&ctr->timer, (uint64_t) (((l + 1) >> 1) * PITCONST)); + } + // if (!t) pclog("pit_over: square wave mode c=%x %lli %f\n", pit.c[t], tsc, PITCONST); + break; + case 4: /*Software triggered strove*/ + if (!ctr->thit) { + pitf_ctr_set_out(ctr, 0); + pitf_ctr_set_out(ctr, 1); + } + if (ctr->newcount) { + ctr->newcount = 0; + ctr->count += l; + if (ctr->using_timer) + timer_advance_u64(&ctr->timer, (uint64_t) (l * PITCONST)); + } else { + ctr->thit = 1; + ctr->count += 0xffff; + if (ctr->using_timer) + timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * PITCONST)); + } + break; + case 5: /*Hardware triggered strove*/ + if (!ctr->thit) { + pitf_ctr_set_out(ctr, 0); + pitf_ctr_set_out(ctr, 1); + } + ctr->thit = 1; + ctr->count += 0xffff; + if (ctr->using_timer) + timer_advance_u64(&ctr->timer, (uint64_t) (0xffff * PITCONST)); + break; + } + ctr->running = ctr->enabled && ctr->using_timer && !ctr->disabled; + if (ctr->using_timer && !ctr->running) + pitf_dump_and_disable_timer(ctr); +} + +static __inline void +pitf_ctr_latch_count(ctrf_t *ctr) +{ + ctr->rl = pitf_read_timer(ctr); + // pclog("Timer latch %f %04X %04X\n",pit->c[0],pit->rl[0],pit->l[0]); + // pit->ctrl |= 0x30; + ctr->rereadlatch = 0; + ctr->rm = 3; + ctr->latched = 1; +} + +static __inline void +pitf_ctr_latch_status(ctrf_t *ctr) +{ + ctr->read_status = (ctr->ctrl & 0x3f) | (ctr->out ? 0x80 : 0); + ctr->do_read_status = 1; +} + +static void +pitf_write(uint16_t addr, uint8_t val, void *priv) +{ + pitf_t *dev = (pitf_t *) priv; + int t = (addr & 3); + ctrf_t *ctr; + + pit_log("[%04X:%08X] pit_write(%04X, %02X, %08X)\n", CS, cpu_state.pc, addr, val, priv); + + switch (addr & 3) { + case 3: /* control */ + t = val >> 6; + + if (t == 3) { + if (dev->flags & PIT_8254) { + /* This is 8254-only. */ + if (!(val & 0x20)) { + if (val & 2) + pitf_ctr_latch_count(&dev->counters[0]); + if (val & 4) + pitf_ctr_latch_count(&dev->counters[1]); + if (val & 8) + pitf_ctr_latch_count(&dev->counters[2]); + pit_log("PIT %i: Initiated readback command\n", t); + } + if (!(val & 0x10)) { + if (val & 2) + pitf_ctr_latch_status(&dev->counters[0]); + if (val & 4) + pitf_ctr_latch_status(&dev->counters[1]); + if (val & 8) + pitf_ctr_latch_status(&dev->counters[2]); + } + } + } else { + dev->ctrl = val; + ctr = &dev->counters[t]; + + if (!(dev->ctrl & 0x30)) { + pitf_ctr_latch_count(ctr); + dev->ctrl |= 0x30; + pit_log("PIT %i: Initiated latched read, %i bytes latched\n", + t, ctr->latched); + } else { + ctr->ctrl = val; + ctr->rm = ctr->wm = (ctr->ctrl >> 4) & 3; + ctr->m = (val >> 1) & 7; + if (ctr->m > 5) + ctr->m &= 3; + if (!(ctr->rm)) { + ctr->rm = 3; + ctr->rl = pitf_read_timer(ctr); + } + ctr->rereadlatch = 1; + ctr->initial = 1; + if (!ctr->m) + pitf_ctr_set_out(ctr, 0); + else + pitf_ctr_set_out(ctr, 1); + ctr->disabled = 1; + + pit_log("PIT %i: M = %i, RM/WM = %i, State = %i, Out = %i\n", t, ctr->m, ctr->rm, ctr->state, ctr->out); + } + ctr->thit = 0; + } + break; + + case 0: + case 1: + case 2: /* the actual timers */ + ctr = &dev->counters[t]; + + switch (ctr->wm) { + case 1: + ctr->l = val; + pitf_ctr_load(ctr); + break; + case 2: + ctr->l = (val << 8); + pitf_ctr_load(ctr); + break; + case 0: + ctr->l &= 0xFF; + ctr->l |= (val << 8); + pitf_ctr_load(ctr); + ctr->wm = 3; + break; + case 3: + ctr->l &= 0xFF00; + ctr->l |= val; + ctr->wm = 0; + break; + } + break; + } +} + +static uint8_t +pitf_read(uint16_t addr, void *priv) +{ + pitf_t *dev = (pitf_t *) priv; + uint8_t ret = 0xff; + int t = (addr & 3); + ctrf_t *ctr; + + switch (addr & 3) { + case 3: /* Control. */ + /* This is 8254-only, 8253 returns 0x00. */ + ret = (dev->flags & PIT_8254) ? dev->ctrl : 0x00; + break; + + case 0: + case 1: + case 2: /* The actual timers. */ + ctr = &dev->counters[t]; + + if (ctr->do_read_status) { + ctr->do_read_status = 0; + ret = ctr->read_status; + break; + } + + if (ctr->rereadlatch && !ctr->latched) { + ctr->rereadlatch = 0; + ctr->rl = pitf_read_timer(ctr); + } + switch (ctr->rm) { + case 0: + ret = ctr->rl >> 8; + ctr->rm = 3; + ctr->latched = 0; + ctr->rereadlatch = 1; + break; + case 1: + ret = (ctr->rl) & 0xFF; + ctr->latched = 0; + ctr->rereadlatch = 1; + break; + case 2: + ret = (ctr->rl) >> 8; + ctr->latched = 0; + ctr->rereadlatch = 1; + break; + case 3: + ret = (ctr->rl) & 0xFF; + if (ctr->m & 0x80) + ctr->m &= 7; + else + ctr->rm = 0; + break; + } + break; + } + + pit_log("[%04X:%08X] pit_read(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret); + + return ret; +} + +static void +pitf_timer_over(void *p) +{ + ctrf_t *ctr = (ctrf_t *) p; + pitf_over(ctr); +} + +static void +pitf_ctr_clock(void *data, int counter_id) +{ + pitf_t *pit = (pitf_t *)data; + ctrf_t *ctr = &pit->counters[counter_id]; + + if (ctr->thit || !ctr->enabled) + return; + + if (ctr->using_timer) + return; + + ctr->count -= (ctr->m == 3) ? 2 : 1; + if (!ctr->count) + pitf_over(ctr); +} + +static void +ctr_reset(ctrf_t *ctr) +{ + ctr->ctrl = 0; + ctr->m = 0; + ctr->gate = 0; + ctr->l = 0xffff; + ctr->thit = 1; + ctr->using_timer = 1; +} + +static void +pitf_reset(pitf_t *dev) +{ + int i; + + memset(dev, 0, sizeof(pitf_t)); + + for (i = 0; i < 3; i++) + ctr_reset(&dev->counters[i]); + + /* Disable speaker gate. */ + dev->counters[2].gate = 0; +} + +static void +pitf_close(void *priv) +{ + pitf_t *dev = (pitf_t *) priv; + + if (dev == pit_devs[0].data) + pit_devs[0].data = NULL; + + if (dev == pit_devs[1].data) + pit_devs[1].data = NULL; + + if (dev != NULL) + free(dev); +} + +static void * +pitf_init(const device_t *info) +{ + pitf_t *dev = (pitf_t *) malloc(sizeof(pitf_t)); + pitf_reset(dev); + + dev->flags = info->local; + + if (!(dev->flags & PIT_PS2) && !(dev->flags & PIT_CUSTOM_CLOCK)) { + for (int i = 0; i < 3; i++) { + ctrf_t *ctr = &dev->counters[i]; + timer_add(&ctr->timer, pitf_timer_over, (void *)ctr, 0); + } + } + + if (!(dev->flags & PIT_EXT_IO)) { + io_sethandler((dev->flags & PIT_SECONDARY) ? 0x0048 : 0x0040, 0x0004, + pitf_read, NULL, NULL, pitf_write, NULL, NULL, dev); + } + + return dev; +} + +const device_t i8253_fast_device = { + .name = "Intel 8253/8253-5 Programmable Interval Timer", + .internal_name = "i8253_fast", + .flags = DEVICE_ISA, + .local = PIT_8253, + .init = pitf_init, + .close = pitf_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t i8254_fast_device = { + .name = "Intel 8254 Programmable Interval Timer", + .internal_name = "i8254_fast", + .flags = DEVICE_ISA, + .local = PIT_8254, + .init = pitf_init, + .close = pitf_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t i8254_sec_fast_device = { + .name = "Intel 8254 Programmable Interval Timer (Secondary)", + .internal_name = "i8254_sec_fast", + .flags = DEVICE_ISA, + .local = PIT_8254 | PIT_SECONDARY, + .init = pitf_init, + .close = pitf_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t i8254_ext_io_fast_device = { + .name = "Intel 8254 Programmable Interval Timer (External I/O)", + .internal_name = "i8254_ext_io_fast", + .flags = DEVICE_ISA, + .local = PIT_8254 | PIT_EXT_IO, + .init = pitf_init, + .close = pitf_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t i8254_ps2_fast_device = { + .name = "Intel 8254 Programmable Interval Timer (PS/2)", + .internal_name = "i8254_ps2_fast", + .flags = DEVICE_ISA, + .local = PIT_8254 | PIT_PS2 | PIT_EXT_IO, + .init = pitf_init, + .close = pitf_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const pit_intf_t pit_fast_intf = { + &pitf_read, + &pitf_write, + &pitf_ctr_get_count, + &pitf_ctr_set_gate, + &pitf_ctr_set_using_timer, + &pitf_ctr_set_out_func, + &pitf_ctr_set_load_func, + &pitf_ctr_clock, + NULL, +}; \ No newline at end of file diff --git a/src/port_6x.c b/src/port_6x.c index c583ffdf0..0fe168a3c 100644 --- a/src/port_6x.c +++ b/src/port_6x.c @@ -63,7 +63,7 @@ port_6x_write(uint16_t port, uint8_t val, void *priv) speaker_enable = val & 2; if (speaker_enable) was_speaker_enable = 1; - pit_ctr_set_gate(&pit->counters[2], val & 1); + pit_devs[0].set_gate(pit_devs[0].data, 2, val & 1); if (dev->flags & PORT_6X_TURBO) xi8088_turbo_set(!!(val & 0x04)); From 5d7db9d4c5f217b701a1e01d8c71e911dc2365b1 Mon Sep 17 00:00:00 2001 From: Adrien Moulin Date: Sat, 23 Jul 2022 14:03:54 +0200 Subject: [PATCH 2/2] Add pit_fast.o to Makefile.mingw --- src/win/Makefile.mingw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 50b2b820b..8c29a24a1 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -535,7 +535,7 @@ CXXFLAGS := $(CFLAGS) # Create the (final) list of objects to build. # ######################################################################### MAINOBJ := 86box.o config.o log.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \ - nmi.o pic.o pit.o port_6x.o port_92.o ppi.o pci.o mca.o fifo8.o \ + nmi.o pic.o pit.o pit_fast.o port_6x.o port_92.o ppi.o pci.o mca.o fifo8.o \ usb.o device.o nvr.o nvr_at.o nvr_ps2.o machine_status.o \ $(VNCOBJ)