From 4c2477a4cf05c040f4368e6149034dd6a7c849f5 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Mon, 9 Dec 2024 11:57:54 +0000 Subject: [PATCH] Add read and write PTIMER registers. Doesn't actually do anything as a timer yet. Fix software and hardware interrupts being the wrong way around --- src/include/86box/nv/vid_nv.h | 8 +++- src/include/86box/nv/vid_nv3.h | 5 +++ src/video/nv/nv3/nv3_core.c | 2 +- src/video/nv/nv3/subsystems/nv3_pmc.c | 2 +- src/video/nv/nv3/subsystems/nv3_ptimer.c | 47 +++++++++++++++++++++++- 5 files changed, 59 insertions(+), 5 deletions(-) diff --git a/src/include/86box/nv/vid_nv.h b/src/include/86box/nv/vid_nv.h index bac0220ea..31191833f 100644 --- a/src/include/86box/nv/vid_nv.h +++ b/src/include/86box/nv/vid_nv.h @@ -290,8 +290,12 @@ typedef struct nv3_pextdev_s typedef struct nv3_ptimer_s { - uint32_t interrupt_status; // Interrupt status - uint32_t interrupt_enable; // Interrupt enable + uint32_t interrupt_status; // PTIMER Interrupt status + uint32_t interrupt_enable; // PTIMER Interrupt enable + uint32_t clock_numerator; // PTIMER (tick?) numerator + uint32_t clock_denominator; // PTIMER (tick?) denominator + uint64_t time; // time + uint32_t alarm; // The value of time when there should be an alarm } nv3_ptimer_t; // Graphics object hashtable diff --git a/src/include/86box/nv/vid_nv3.h b/src/include/86box/nv/vid_nv3.h index 1e9b8064c..1a2f75d0b 100644 --- a/src/include/86box/nv/vid_nv3.h +++ b/src/include/86box/nv/vid_nv3.h @@ -194,6 +194,11 @@ extern const device_config_t nv3_config[]; #define NV3_PTIMER_START 0x9000 // Programmable Interval Timer #define NV3_PTIMER_INTR 0x9100 #define NV3_PTIMER_INTR_EN 0x9140 +#define NV3_PTIMER_NUMERATOR 0x9200 +#define NV3_PTIMER_DENOMINATOR 0x9210 +#define NV3_PTIMER_TIME_0_NSEC 0x9400 // nanoseconds [31:5] +#define NV3_PTIMER_TIME_1_NSEC 0x9410 // nanoseconds [28:0] +#define NV3_PTIMER_ALARM_NSEC 0x9420 // nanoseconds [31:5] #define NV3_PTIMER_END 0x9FFF #define NV3_VGA_VRAM_START 0xA0000 // VGA Emulation VRAM #define NV3_VGA_VRAM_END 0xBFFFF diff --git a/src/video/nv/nv3/nv3_core.c b/src/video/nv/nv3/nv3_core.c index 033563998..d0cbdae3b 100644 --- a/src/video/nv/nv3/nv3_core.c +++ b/src/video/nv/nv3/nv3_core.c @@ -797,7 +797,7 @@ void* nv3_init(const device_t *info) nv3_pfifo_init(); // Initialise FIFO for graphics object submission nv3_pgraph_init(); // Initialise accelerated graphics engine nv3_ptimer_init(); // Initialise programmable interval timer - nv3_pvideo_init(); // Initialise video overlay engines + nv3_pvideo_init(); // Initialise video overlay engine return nv3; } diff --git a/src/video/nv/nv3/subsystems/nv3_pmc.c b/src/video/nv/nv3/subsystems/nv3_pmc.c index 50eccfae3..379c4ed7c 100644 --- a/src/video/nv/nv3/subsystems/nv3_pmc.c +++ b/src/video/nv/nv3/subsystems/nv3_pmc.c @@ -137,7 +137,7 @@ uint32_t nv3_pmc_handle_interrupts(bool send_now) return nv3->pmc.interrupt_status; } - if (!(nv3->pmc.interrupt_status & 0x7FFFFFFF)) + if ((nv3->pmc.interrupt_status & 0x7FFFFFFF)) { if (nv3->pmc.interrupt_enable & NV3_PMC_INTERRUPT_ENABLE_HARDWARE) { diff --git a/src/video/nv/nv3/subsystems/nv3_ptimer.c b/src/video/nv/nv3/subsystems/nv3_ptimer.c index 9e15a1035..1a6c9d73d 100644 --- a/src/video/nv/nv3/subsystems/nv3_ptimer.c +++ b/src/video/nv/nv3/subsystems/nv3_ptimer.c @@ -32,6 +32,11 @@ nv_register_t ptimer_registers[] = { { NV3_PTIMER_INTR, "PTIMER - Interrupt Status", NULL, NULL}, { NV3_PTIMER_INTR_EN, "PTIMER - Interrupt Enable", NULL, NULL,}, + { NV3_PTIMER_NUMERATOR, "PTIMER - Numerator", NULL, NULL, }, + { NV3_PTIMER_DENOMINATOR, "PTIMER - Denominator", NULL, NULL, }, + { NV3_PTIMER_TIME_0_NSEC, "PTIMER - Time0", NULL, NULL, }, + { NV3_PTIMER_TIME_1_NSEC, "PTIMER - Time1", NULL, NULL, }, + { NV3_PTIMER_ALARM_NSEC, "PTIMER - Alarm", NULL, NULL, }, { NV_REG_LIST_END, NULL, NULL, NULL}, // sentinel value }; @@ -75,6 +80,24 @@ uint32_t nv3_ptimer_read(uint32_t address) return nv3->ptimer.interrupt_status; case NV3_PTIMER_INTR_EN: return nv3->ptimer.interrupt_enable; + case NV3_PTIMER_NUMERATOR: + return nv3->ptimer.clock_denominator; // 15:0 + break; + case NV3_PTIMER_DENOMINATOR: + return nv3->ptimer.clock_denominator ; //15:0 + break; + // 64-bit value + // High part + case NV3_PTIMER_TIME_0_NSEC: + return nv3->ptimer.time & 0xFFFFFFFF; //28:0 + break; + // Low part + case NV3_PTIMER_TIME_1_NSEC: + return nv3->ptimer.time >> 32; // 31:5 + break; + case NV3_PTIMER_ALARM_NSEC: + return nv3->ptimer.alarm; // 31:5 + break; } } } @@ -112,7 +135,29 @@ void nv3_ptimer_write(uint32_t address, uint32_t value) nv3_pmc_clear_interrupts(); break; case NV3_PTIMER_INTR_EN: - nv3->ptimer.interrupt_enable = value & 0x00000001; + nv3->ptimer.interrupt_enable = value & 0x1; + break; + case NV3_PTIMER_NUMERATOR: + nv3->ptimer.clock_denominator = value & 0xFFFF; // 15:0 + break; + case NV3_PTIMER_DENOMINATOR: + // prevent Div0 + if (!value) + value = 1; + + nv3->ptimer.clock_denominator = value & 0xFFFF; //15:0 + break; + // 64-bit value + // High part + case NV3_PTIMER_TIME_0_NSEC: + nv3->ptimer.time = (value >> 32) & 0xFFFFFFE0; //28:0 + break; + // Low part + case NV3_PTIMER_TIME_1_NSEC: + nv3->ptimer.time = ((value & 0xFFFFFFE0) << 32); // 31:5 + break; + case NV3_PTIMER_ALARM_NSEC: + nv3->ptimer.alarm = value & 0xFFFFFFE0; // 31:5 break; } }