mirror of
https://github.com/86Box/86Box.git
synced 2026-02-23 18:08:20 -07:00
Correctly set the timers, but setting it all breaks?
This commit is contained in:
@@ -98,7 +98,9 @@ typedef struct nv_base_s
|
||||
uint32_t bar1_lfb_base; // PCI Base Address Register 1 - Linear Framebuffer (NV_BASE)
|
||||
nv_bus_generation bus_generation; // current bus (see nv_bus_generation documentation)
|
||||
uint32_t gpu_revision; // GPU Stepping
|
||||
double pixel_clock_period; // Period in seconds for pixel clock
|
||||
pc_timer_t pixel_clock_timer; // Pixel Clock Timer
|
||||
double memory_clock_period; // Period in seconds for pixel clock
|
||||
pc_timer_t memory_clock_timer; // Memory Clock Timer
|
||||
} nv_base_t;
|
||||
|
||||
@@ -496,6 +498,8 @@ void nv3_pbus_rma_write(uint16_t addr, uint8_t val);
|
||||
void nv3_pramdac_init();
|
||||
void nv3_pramdac_set_vram_clock();
|
||||
void nv3_pramdac_set_pixel_clock();
|
||||
void nv3_pramdac_pixel_clock_poll(void* priv);
|
||||
void nv3_pramdac_memory_clock_poll(void* priv);
|
||||
|
||||
// NV3 PTIMER
|
||||
void nv3_ptimer_init();
|
||||
|
||||
@@ -29,6 +29,9 @@ extern const device_config_t nv3_config[];
|
||||
#define NV3_LFB_RAMIN_START 0xC00000 // RAMIN mapping start
|
||||
#define NV3_LFB_MAPPING_SIZE 0x400000 // Size of RAMIN
|
||||
|
||||
#define NV3_86BOX_TIMER_SYSTEM_FIX_QUOTIENT 100 // The amount by which we have to ration out the memory clock because it's not fast enough...
|
||||
// Multiply by this value to get the real clock speed.
|
||||
|
||||
// various vbioses for testing
|
||||
// Coming soon: MIROmagic Premium BIOS (when I get mine dumped)
|
||||
//todo: move to hash system
|
||||
|
||||
@@ -728,19 +728,7 @@ void nv3_update_mappings()
|
||||
}
|
||||
}
|
||||
|
||||
// Polls the pixel clock.
|
||||
// This updates the 2D/3D engine PGRAPH
|
||||
void nv3_pixel_clock_poll(void* priv)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Polls the memory clock.
|
||||
void nv3_memory_clock_poll(void* poll)
|
||||
{
|
||||
// Let's hope qeeg was right here.
|
||||
nv3_ptimer_tick();
|
||||
}
|
||||
|
||||
//
|
||||
// Init code
|
||||
@@ -813,12 +801,13 @@ void* nv3_init(const device_t *info)
|
||||
nv3_ptimer_init(); // Initialise programmable interval timer
|
||||
nv3_pvideo_init(); // Initialise video overlay engine
|
||||
|
||||
nv_log("NV3: Starting timers...");
|
||||
|
||||
// Add the
|
||||
timer_add(&nv3->nvbase.pixel_clock_timer, nv3_pixel_clock_poll, nv3, true);
|
||||
timer_add(&nv3->nvbase.memory_clock_timer, nv3_memory_clock_poll, nv3, true);
|
||||
nv_log("NV3: Initialising timers...\n");
|
||||
|
||||
// These only get turned on when the requisite registers are twiddled
|
||||
timer_add(&nv3->nvbase.pixel_clock_timer, nv3_pramdac_pixel_clock_poll, nv3, false);
|
||||
nv_log("NV3: Pixel clock OK. Will be started when the VBIOS tells us to start\n");
|
||||
timer_add(&nv3->nvbase.memory_clock_timer, nv3_pramdac_memory_clock_poll, nv3, false);
|
||||
nv_log("NV3: Memory clock OK. Will be started when the VBIOS tells us to start\n");
|
||||
return nv3;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,15 +42,34 @@ void nv3_pramdac_init()
|
||||
nv3->pramdac.memory_clock_n = nv3->pramdac.pixel_clock_n = 0xc8;
|
||||
nv3->pramdac.memory_clock_p = nv3->pramdac.pixel_clock_p = 0x0c;
|
||||
|
||||
|
||||
nv3_pramdac_set_pixel_clock();
|
||||
nv3_pramdac_set_vram_clock();
|
||||
|
||||
nv_log("NV3: Initialising PRAMDAC: Done\n");
|
||||
}
|
||||
|
||||
// Polls the pixel clock.
|
||||
// This updates the 2D/3D engine PGRAPH
|
||||
void nv3_pramdac_pixel_clock_poll(void* priv)
|
||||
{
|
||||
timer_on_auto(&nv3->nvbase.pixel_clock_timer, nv3->nvbase.pixel_clock_period);
|
||||
|
||||
}
|
||||
|
||||
// Polls the memory clock.
|
||||
void nv3_pramdac_memory_clock_poll(void* poll)
|
||||
{
|
||||
// Let's hope qeeg was right here.
|
||||
nv3_ptimer_tick();
|
||||
|
||||
timer_on_auto(&nv3->nvbase.memory_clock_timer, nv3->nvbase.memory_clock_period);
|
||||
}
|
||||
|
||||
// Gets the vram clock register.
|
||||
uint32_t nv3_pramdac_get_vram_clock_register()
|
||||
{
|
||||
// pack into 19 bits
|
||||
// the clock format is packed into 19 bits
|
||||
// M divisor [7-0]
|
||||
// N divisor [16-8]
|
||||
// P divisor [18-16]
|
||||
@@ -95,39 +114,51 @@ void nv3_pramdac_set_vram_clock()
|
||||
else
|
||||
frequency = (frequency * nv3->pramdac.memory_clock_n) / (nv3->pramdac.memory_clock_m << nv3->pramdac.memory_clock_p);
|
||||
|
||||
double time = (1000000.0 * NV3_86BOX_TIMER_SYSTEM_FIX_QUOTIENT) / (double)frequency; // needs to be a double for 86box
|
||||
|
||||
nv_log("NV3: Memory clock = %.2f MHz\n", frequency / 1000000.0f);
|
||||
|
||||
nv3->nvbase.memory_clock_period = time;
|
||||
//Breaks everything?
|
||||
//timer_set_delay_u64(&nv3->nvbase.memory_clock_timer, time * TIMER_USEC); // do we need to decrease
|
||||
}
|
||||
|
||||
void nv3_pramdac_set_pixel_clock()
|
||||
{
|
||||
// frequency divider algorithm from old varcem/86box/pcbox riva driver,
|
||||
// verified by reversing NT drivers v1.50e CalcMNP [symbols] function
|
||||
// frequency divider algorithm from old varcem/86box/pcbox riva driver,
|
||||
// verified by reversing NT drivers v1.50e CalcMNP [symbols] function
|
||||
|
||||
// todo: actually implement it
|
||||
// todo: actually implement it
|
||||
|
||||
// missing section
|
||||
// not really needed.
|
||||
// if (nv3->pfb.boot.clock_crystal == CLOCK_CRYSTAL_13500)
|
||||
// {
|
||||
// freq = 13500000.0f;
|
||||
// }
|
||||
// else
|
||||
//
|
||||
// {
|
||||
// freq = 14318000.0f;
|
||||
// }
|
||||
// missing section
|
||||
// not really needed.
|
||||
// if (nv3->pfb.boot.clock_crystal == CLOCK_CRYSTAL_13500)
|
||||
// {
|
||||
// freq = 13500000.0f;
|
||||
// }
|
||||
// else
|
||||
//
|
||||
// {
|
||||
// freq = 14318000.0f;
|
||||
// }
|
||||
|
||||
float frequency = 13500000.0f;
|
||||
float frequency = 13500000.0f;
|
||||
|
||||
// prevent division by 0
|
||||
if (nv3->pramdac.pixel_clock_m == 0)
|
||||
nv3->pramdac.pixel_clock_m == 1;
|
||||
else
|
||||
// prevent division by 0
|
||||
if (nv3->pramdac.pixel_clock_m == 0)
|
||||
nv3->pramdac.pixel_clock_m == 1;
|
||||
else
|
||||
frequency = (frequency * nv3->pramdac.pixel_clock_n) / (nv3->pramdac.pixel_clock_m << nv3->pramdac.pixel_clock_p);
|
||||
|
||||
nv3->nvbase.svga.clock = cpuclock / frequency;
|
||||
nv3->nvbase.svga.clock = cpuclock / frequency;
|
||||
|
||||
nv_log("NV3: Pixel clock = %.2f MHz\n", frequency / 1000000.0f);
|
||||
double time = (1000000.0 * NV3_86BOX_TIMER_SYSTEM_FIX_QUOTIENT) / (double)frequency; // needs to be a double for 86box
|
||||
|
||||
nv_log("NV3: Pixel clock = %.2f MHz\n", frequency / 1000000.0f);
|
||||
|
||||
nv3->nvbase.pixel_clock_period = time;
|
||||
//Breaks everything?
|
||||
//timer_set_delay_u64(&nv3->nvbase.pixel_clock_timer, time * TIMER_USEC); // do we need to decrease
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -59,8 +59,15 @@ void nv3_ptimer_interrupt(uint32_t num)
|
||||
// Ticks the timer.
|
||||
void nv3_ptimer_tick()
|
||||
{
|
||||
// do not divide by zero
|
||||
if (nv3->ptimer.clock_numerator == 0
|
||||
|| nv3->ptimer.clock_denominator == 0)
|
||||
return;
|
||||
|
||||
// get the current time
|
||||
double current_time = ((double)nv3->ptimer.clock_numerator) / (double)nv3->ptimer.clock_denominator; // *10.0?
|
||||
// Due to timer system limitations, the timer system is not capable of running at 100 megahertz. Therefore, we have to scale it down and then scale up the level of changes
|
||||
// to the state.
|
||||
double current_time = ((double)nv3->ptimer.clock_numerator * NV3_86BOX_TIMER_SYSTEM_FIX_QUOTIENT) / (double)nv3->ptimer.clock_denominator; // *10.0?
|
||||
|
||||
// truncate it
|
||||
nv3->ptimer.time += (uint64_t)current_time;
|
||||
@@ -127,7 +134,7 @@ void nv3_ptimer_write(uint32_t address, uint32_t value)
|
||||
// before doing anything, check the subsystem enablement
|
||||
nv_register_t* reg = nv_get_register(address, ptimer_registers, sizeof(ptimer_registers)/sizeof(ptimer_registers[0]));
|
||||
|
||||
nv_log("NV3: PTIMER Write 0x%08x -> 0x%08x\n", value, address);
|
||||
nv_log("NV3: PTIMER Write 0x%08x -> 0x%08x", value, address);
|
||||
|
||||
// if the register actually exists
|
||||
if (reg)
|
||||
@@ -156,7 +163,7 @@ void nv3_ptimer_write(uint32_t address, uint32_t value)
|
||||
case NV3_PTIMER_INTR_EN:
|
||||
nv3->ptimer.interrupt_enable = value & 0x1;
|
||||
break;
|
||||
//
|
||||
// nUMERATOR
|
||||
case NV3_PTIMER_NUMERATOR:
|
||||
nv3->ptimer.clock_numerator = value & 0xFFFF; // 15:0
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user