mirror of
https://github.com/86Box/86Box.git
synced 2026-02-22 17:45:31 -07:00
Add register framework
This commit is contained in:
@@ -136,6 +136,10 @@ typedef struct nv_base_s
|
||||
bool pixel_clock_enabled; // Pixel Clock Enabled - stupid crap used to prevent us enabling the timer multiple times
|
||||
double memory_clock_frequency; // Source Frequency for PTIMER
|
||||
rivatimer_t* memory_clock_timer; // Timer for measuring memory/gpu clock
|
||||
|
||||
// VCLK / NVCLK do not have timers set here.
|
||||
pc_timer_t* nv4_vclk_timer; // NV4+ MCLK (Video RAM) timer
|
||||
|
||||
bool memory_clock_enabled; // Memory Clock Enabled - stupid crap used to prevent us eanbling the timer multiple times
|
||||
void* i2c; // I2C for monitor EDID
|
||||
void* ddc; // Display Data Channel for EDID
|
||||
|
||||
@@ -62,6 +62,7 @@ typedef struct nv4_pramdac_s
|
||||
uint32_t mclk;
|
||||
uint32_t vclk;
|
||||
uint32_t nvclk;
|
||||
uint32_t clk_coeff_select; // Clock coefficient selection
|
||||
uint32_t cursor_address;
|
||||
} nv4_pramdac_t;
|
||||
|
||||
@@ -83,6 +84,13 @@ extern const device_config_t nv4_config[];
|
||||
|
||||
extern nv4_t* nv4; // Allocated at device startup
|
||||
|
||||
#ifdef NV_LOG
|
||||
|
||||
// Debug register list
|
||||
extern nv_register_t nv4_registers[];
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// Functions
|
||||
//
|
||||
@@ -120,9 +128,22 @@ void nv4_ramin_write32(uint32_t addr, uint32_t val, void* priv);
|
||||
uint8_t nv4_pci_read(int32_t func, int32_t addr, void* priv);
|
||||
void nv4_pci_write(int32_t func, int32_t addr, uint8_t val, void* priv);
|
||||
|
||||
// PRAMDAC
|
||||
|
||||
// SVGA
|
||||
uint8_t nv4_svga_read(uint16_t addr, void* priv);
|
||||
void nv4_svga_write(uint16_t addr, uint8_t val, void* priv);
|
||||
|
||||
void nv4_update_mappings();
|
||||
// Memory
|
||||
void nv4_update_mappings();
|
||||
|
||||
// PRAMDAC
|
||||
uint32_t nv4_pramdac_read(uint32_t address);
|
||||
void nv4_pramdac_write(uint32_t address, uint32_t data);
|
||||
|
||||
// We don't implement NVCLK/VCLK because they are too fast
|
||||
void nv4_pramdac_set_vclk();
|
||||
|
||||
void nv4_vclk_tick();
|
||||
|
||||
// PTIMER
|
||||
uint32_t nv4_ptimer_read(uint32_t address);
|
||||
void nv4_ptimer_write(uint32_t address, uint32_t data);
|
||||
@@ -201,6 +201,8 @@ add_library(vid OBJECT
|
||||
nv/nv4/nv4_core.c
|
||||
nv/nv4/nv4_core_io.c
|
||||
nv/nv4/nv4_core_config.c
|
||||
nv/nv4/nv4_debug_register_list.c
|
||||
nv/nv4/subsystems/nv4_pramdac.c
|
||||
nv/nv4/subsystems/nv4_ptimer.c
|
||||
|
||||
# Generic
|
||||
|
||||
@@ -199,7 +199,6 @@ bool nv4_init()
|
||||
/* Set log device name based on card model */
|
||||
const char* log_device_name = "NV4";
|
||||
|
||||
|
||||
/* Just hardcode full logging */
|
||||
|
||||
if (device_get_config_int("nv_debug_fulllog"))
|
||||
@@ -234,6 +233,15 @@ bool nv4_init()
|
||||
|
||||
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_nv4_agp);
|
||||
|
||||
// Setup clock information. These values don't matter, I pulled them out of an STB BIOS, we don't need to macro them
|
||||
nv4->pramdac.nvclk = 0x17809;
|
||||
nv4->pramdac.mclk = 0x1a30a;
|
||||
nv4->pramdac.vclk = 0x1400c;
|
||||
|
||||
//timer_add(nv4->pramdac.nvclk, )
|
||||
|
||||
|
||||
|
||||
nv4_init_mappings();
|
||||
//nv4_update_mappings();
|
||||
|
||||
@@ -250,6 +258,21 @@ void* nv4_init_stb4400(const device_t *info)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void nv4_nvclk_tick()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void nv4_mclk_tick()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void nv4_vclk_tick()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void nv4_close(void* priv)
|
||||
{
|
||||
free(nv4);
|
||||
@@ -278,7 +301,7 @@ void nv4_recalc_timings(svga_t* svga)
|
||||
|
||||
nv4_t* nv4 = (nv4_t*)svga->priv;
|
||||
|
||||
// TODO: Everything, this code sucks, incl. NV4_PRAMDAC_GENERAL_CONTROL_BPC and the OFFSET register
|
||||
// TODO: Everything, this code sucks, incl. NV4_PRAMDAC_GENERAL_CONTROL_BPC and the offset register
|
||||
uint32_t pixel_mode = svga->crtc[NV4_CIO_CRE_PIXEL_INDEX] & 0x03;
|
||||
|
||||
svga->memaddr_latch += (svga->crtc[NV4_CIO_CRE_RPC0_INDEX] & 0x1F) << 16;
|
||||
|
||||
@@ -44,12 +44,47 @@ void nv4_svga_write(uint16_t addr, uint8_t val, void* priv);
|
||||
|
||||
uint32_t nv4_mmio_arbitrate_read(uint32_t addr)
|
||||
{
|
||||
nv_log_verbose_only("MMIO read from address=0x%08x\n", addr);
|
||||
uint32_t ret = 0x00;
|
||||
|
||||
if (addr >= NV4_PTIMER_START && addr <= NV4_PTIMER_END)
|
||||
ret = nv4_ptimer_read(addr);
|
||||
else if (addr >= NV4_PRAMDAC_START && addr <= NV4_PRAMDAC_END)
|
||||
ret = nv4_pramdac_read(addr);
|
||||
|
||||
#ifdef NV_LOG
|
||||
nv_register_t reg = nv_get_register(addr, &nv4_registers, sizeof(nv4_registers)/sizeof(nv4_registers[0]));
|
||||
|
||||
if (reg)
|
||||
{
|
||||
if (reg->on_read)
|
||||
ret = reg->on_read();
|
||||
|
||||
nv_log_verbose_only("Register read from 0x%08x value=%08x", addr, ret);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void nv4_mmio_arbitrate_write(uint32_t addr, uint32_t val)
|
||||
{
|
||||
nv_log_verbose_only("MMIO write to address=0x%08x value %08x\n", addr, val);
|
||||
if (addr >= NV4_PTIMER_START && addr <= NV4_PTIMER_END)
|
||||
nv4_ptimer_write(addr, val);
|
||||
else if (addr >= NV4_PRAMDAC_START && addr <= NV4_PRAMDAC_END)
|
||||
nv4_pramdac_write(addr, val);
|
||||
|
||||
#ifdef NV_LOG
|
||||
nv_register_t reg = nv_get_register(addr, &nv4_registers, sizeof(nv4_registers)/sizeof(nv4_registers[0]));
|
||||
|
||||
if (reg)
|
||||
{
|
||||
if (reg->on_write)
|
||||
reg->on_write(val);
|
||||
|
||||
nv_log_verbose_only("Register write from 0x%08x value=%08x", addr, val);
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Determine if this address needs to be redirected to the SVGA subsystem.
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* NV4 debug register list
|
||||
*
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
|
||||
*
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/pci.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/nv/vid_nv.h>
|
||||
#include <86box/nv/vid_nv4.h>
|
||||
|
||||
#ifdef NV_LOG
|
||||
|
||||
nv_register_t nv4_registers[] = {
|
||||
{ NV4_PTIMER_INTR, "NV4 PTIMER - Interrupt Status", NULL, NULL},
|
||||
{ NV4_PTIMER_INTR_EN, "NV4 PTIMER - Interrupt Enable", NULL, NULL,},
|
||||
{ NV4_PTIMER_NUMERATOR, "NV4 PTIMER - Numerator", NULL, NULL, },
|
||||
{ NV4_PTIMER_DENOMINATOR, "NV4 PTIMER - Denominator", NULL, NULL, },
|
||||
{ NV4_PTIMER_TIME_0_NSEC, "NV4 PTIMER - Time0", NULL, NULL, },
|
||||
{ NV4_PTIMER_TIME_1_NSEC, "NV4 PTIMER - Time1", NULL, NULL, },
|
||||
{ NV4_PTIMER_ALARM_NSEC, "NV4 PTIMER - Alarm", NULL, NULL, },
|
||||
{ NV4_PRAMDAC_VPLL_COEFF, "NV4 PRAMDAC - Pixel Clock Coefficient", NULL, NULL, },
|
||||
{ NV4_PRAMDAC_NVPLL_COEFF, "NV4 PRAMDAC - GPU Core Clock Coefficient", NULL, NULL, },
|
||||
{ NV4_PRAMDAC_MPLL_COEFF, "NV4 PRAMDAC - VRAM Clock Coefficient", NULL, NULL, },
|
||||
{ NV_REG_LIST_END, NULL, NULL, NULL}, // sentinel value
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -14,3 +14,71 @@
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/pci.h>
|
||||
#include <86box/rom.h> // DEPENDENT!!!
|
||||
#include <86box/video.h>
|
||||
#include <86box/nv/vid_nv.h>
|
||||
#include <86box/nv/vid_nv4.h>
|
||||
|
||||
|
||||
uint64_t nv4_pramdac_get_hz(uint32_t coeff, bool apply_divider)
|
||||
{
|
||||
uint32_t m = coeff & 0xFF;
|
||||
uint32_t n = (coeff >> 8) & 0xFF;
|
||||
uint32_t p = (coeff >> 16) & 0x07;
|
||||
|
||||
// Check clock base
|
||||
uint32_t hz_base = (nv4->straps & (1 << NV4_STRAP_CRYSTAL)) ? 14318180 : 13500000;
|
||||
uint32_t final_hz = (hz_base * n) / (m << p);
|
||||
|
||||
// Check VCLK divider
|
||||
|
||||
if (apply_divider)
|
||||
{
|
||||
if (nv4->pramdac.clk_coeff_select & (1 << NV4_PRAMDAC_PLL_COEFF_SELECT_VCLK_RATIO))
|
||||
final_hz >>= 1;
|
||||
}
|
||||
|
||||
return final_hz;
|
||||
}
|
||||
|
||||
void nv4_pramdac_set_vclk()
|
||||
{
|
||||
uint64_t final_hz = nv4_pramdac_get_hz(nv4->pramdac.nvclk, false);
|
||||
|
||||
//TODO: Everything
|
||||
if (!nv4->nvbase.nv4_vclk_timer)
|
||||
timer_set_delay_u64(nv4->nvbase.nv4_vclk_timer, final_hz / TIMER_USEC);
|
||||
|
||||
}
|
||||
|
||||
uint32_t nv4_pramdac_read(uint32_t address)
|
||||
{
|
||||
uint32_t ret = 0x00;
|
||||
|
||||
switch (address)
|
||||
{
|
||||
case NV4_PRAMDAC_VPLL_COEFF: // Pixel clock
|
||||
ret = nv4->pramdac.vclk;
|
||||
break;
|
||||
case NV4_PRAMDAC_NVPLL_COEFF: // System clock
|
||||
ret = nv4->pramdac.nvclk;
|
||||
break;
|
||||
case NV4_PRAMDAC_MPLL_COEFF: // Memory clock
|
||||
ret = nv4->pramdac.mclk;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void nv4_pramdac_write(uint32_t address, uint32_t data)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user