mirror of
https://github.com/86Box/86Box.git
synced 2026-02-23 09:58:19 -07:00
Implement some basic i2c shit and more SVGA shit, so that the drivers don't magically explode. LOL
This commit is contained in:
@@ -28,6 +28,8 @@
|
||||
|
||||
//TODO: split this all into nv1, nv3, nv4...
|
||||
|
||||
#include <86box/i2c.h>
|
||||
#include <86box/vid_ddc.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/vid_svga.h>
|
||||
#include <86box/vid_svga_render.h>
|
||||
@@ -68,16 +70,19 @@ void nv_log(const char *fmt, ...);
|
||||
|
||||
typedef enum nv_bus_generation_e
|
||||
{
|
||||
// NV1 - Prototype version
|
||||
nv_bus_vlb = 0,
|
||||
|
||||
// NV1
|
||||
// NV3
|
||||
nv_bus_pci = 0,
|
||||
nv_bus_pci = 1,
|
||||
|
||||
// NV3
|
||||
nv_bus_agp_1x = 1,
|
||||
nv_bus_agp_1x = 2,
|
||||
|
||||
// NV3T
|
||||
// NV4
|
||||
nv_bus_agp_2x = 2,
|
||||
nv_bus_agp_2x = 3,
|
||||
|
||||
} nv_bus_generation;
|
||||
|
||||
@@ -103,11 +108,13 @@ typedef struct nv_base_s
|
||||
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
|
||||
rivatimer_t* pixel_clock_timer;
|
||||
rivatimer_t* pixel_clock_timer; // Timer for measuring pixel clock
|
||||
bool pixel_clock_enabled; // Pixel Clock Enabled - stupid crap used to prevent us enabling the timer multiple times
|
||||
double memory_clock_period; // Period in seconds for pixel clock
|
||||
rivatimer_t* memory_clock_timer;
|
||||
rivatimer_t* memory_clock_timer; // Timer for measuring memory/gpu clock
|
||||
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;
|
||||
} nv_base_t;
|
||||
|
||||
#define NV_REG_LIST_END 0xD15EA5E
|
||||
|
||||
@@ -568,7 +568,10 @@ extern const device_config_t nv3_config[];
|
||||
#define NV3_CRTC_REGISTER_PIXELMODE_16BPP 0x02
|
||||
#define NV3_CRTC_REGISTER_PIXELMODE_32BPP 0x03
|
||||
|
||||
#define NV3_CRTC_REGISTER_RMA 0x38 // REAL MODE ACCESS!
|
||||
#define NV3_CRTC_REGISTER_RL0 0x34
|
||||
#define NV3_CRTC_REGISTER_RL1 0x35
|
||||
#define NV3_CRTC_REGISTER_RMA 0x38 // REAL MODE ACCESS!
|
||||
#define NV3_CRTC_REGISTER_I2C 0x3F
|
||||
|
||||
// where the fuck is GDC?
|
||||
#define NV3_CRTC_BANKED_128K_A0000 0x00
|
||||
|
||||
@@ -243,7 +243,7 @@ uint8_t nv3_pci_read(int32_t func, int32_t addr, void* priv)
|
||||
break;
|
||||
|
||||
case PCI_REG_COMMAND_H:
|
||||
ret = nv3->pci_config.pci_regs[PCI_REG_COMMAND_H] | NV3_PCI_COMMAND_H_FAST_BACK2BACK; // always enable fast back2back
|
||||
ret = nv3->pci_config.pci_regs[PCI_REG_COMMAND_H] & NV3_PCI_COMMAND_H_FAST_BACK2BACK; // always enable fast back2back
|
||||
break;
|
||||
|
||||
// pci status register
|
||||
@@ -447,15 +447,6 @@ void nv3_pci_write(int32_t func, int32_t addr, uint8_t val, void* priv)
|
||||
}
|
||||
}
|
||||
|
||||
void nv3_close(void* priv)
|
||||
{
|
||||
rivatimer_destroy(nv3->nvbase.pixel_clock_timer);
|
||||
rivatimer_destroy(nv3->nvbase.memory_clock_timer);
|
||||
svga_close(&nv3->nvbase.svga);
|
||||
free(nv3);
|
||||
nv3 = NULL;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// SVGA functions
|
||||
@@ -575,6 +566,18 @@ uint8_t nv3_svga_in(uint16_t addr, void* priv)
|
||||
// Support the extended NVIDIA CRTC register range
|
||||
switch (nv3->nvbase.svga.crtcreg)
|
||||
{
|
||||
case NV3_CRTC_REGISTER_RL0:
|
||||
ret = nv3->nvbase.svga.displine & 0xFF;
|
||||
break;
|
||||
/* Is rl1?*/
|
||||
case NV3_CRTC_REGISTER_RL1:
|
||||
ret = (nv3->nvbase.svga.displine >> 8) & 7;
|
||||
break;
|
||||
case NV3_CRTC_REGISTER_I2C:
|
||||
ret = i2c_gpio_get_sda((nv3->nvbase.i2c) << 3)
|
||||
| i2c_gpio_get_scl((nv3->nvbase.i2c) << 2);
|
||||
|
||||
break;
|
||||
default:
|
||||
ret = nv3->nvbase.svga.crtc[nv3->nvbase.svga.crtcreg];
|
||||
}
|
||||
@@ -641,6 +644,8 @@ void nv3_svga_out(uint16_t addr, uint8_t val, void* priv)
|
||||
val = (nv3->nvbase.svga.crtc[NV3_CRTC_REGISTER_OVERFLOW] & ~0x10) | (val & 0x10);
|
||||
|
||||
// set the register value...
|
||||
uint8_t old_value = nv3->nvbase.svga.crtc[crtcreg];
|
||||
|
||||
nv3->nvbase.svga.crtc[crtcreg] = val;
|
||||
// ...now act on it
|
||||
|
||||
@@ -664,6 +669,27 @@ void nv3_svga_out(uint16_t addr, uint8_t val, void* priv)
|
||||
case NV3_CRTC_REGISTER_RMA:
|
||||
nv3->pbus.rma.mode = val & NV3_CRTC_REGISTER_RMA_MODE_MAX;
|
||||
break;
|
||||
case NV3_CRTC_REGISTER_I2C:
|
||||
uint8_t scl = !!(val & 0x20);
|
||||
uint8_t sda = !!(val & 0x10);
|
||||
// Set an I2C GPIO register
|
||||
i2c_gpio_set(nv3->nvbase.i2c, scl, sda);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Recalculate the timings if we actually changed them
|
||||
Additionally only do it if the value actually changed*/
|
||||
if (old_value != val)
|
||||
{
|
||||
// Thx to Fuel who basically wrote all the SVGA compatibility code already (although I fixed some issues), because VGA is boring
|
||||
// and in the words of an ex-Rendition/3dfx/NVIDIA engineer, "VGA was basically an undocumented bundle of steaming you-know-what.
|
||||
// And it was essential that any cores the PC 3D startups acquired had to work with all the undocumented modes and timing tweaks (mode X, etc.)"
|
||||
if (nv3->nvbase.svga.crtcreg < 0xE
|
||||
&& nv3->nvbase.svga.crtcreg > 0x10)
|
||||
{
|
||||
nv3->nvbase.svga.fullchange = changeframecount;
|
||||
svga_recalctimings(&nv3->nvbase.svga);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -937,7 +963,9 @@ void* nv3_init(const device_t *info)
|
||||
nv3_ptimer_init(); // Initialise programmable interval timer
|
||||
nv3_pvideo_init(); // Initialise video overlay engine
|
||||
|
||||
nv_log("NV3: Initialising timers...\n");
|
||||
nv_log("NV3: Initialising I2C...");
|
||||
nv3->nvbase.i2c = i2c_gpio_init("nv3_i2c");
|
||||
nv3->nvbase.ddc = ddc_init(i2c_gpio_get_bus(nv3->nvbase.i2c));
|
||||
|
||||
return nv3;
|
||||
}
|
||||
@@ -958,6 +986,38 @@ void* nv3_init_agp(const device_t* info)
|
||||
nv3_init(info);
|
||||
}
|
||||
|
||||
void nv3_close(void* priv)
|
||||
{
|
||||
// Shut down I2C and the DDC
|
||||
i2c_gpio_close(nv3->nvbase.i2c);
|
||||
ddc_close(nv3->nvbase.ddc);
|
||||
|
||||
// Destroy the Rivatimers. (It doesn't matter if they are running.)
|
||||
rivatimer_destroy(nv3->nvbase.pixel_clock_timer);
|
||||
rivatimer_destroy(nv3->nvbase.memory_clock_timer);
|
||||
|
||||
// Shut down SVGA
|
||||
svga_close(&nv3->nvbase.svga);
|
||||
free(nv3);
|
||||
nv3 = NULL;
|
||||
}
|
||||
|
||||
// See if the bios rom is available.
|
||||
void nv3_available()
|
||||
{
|
||||
return rom_present(NV3_VBIOS_ASUS_V3000_V151)
|
||||
|| rom_present(NV3_VBIOS_DIAMOND_V330_V162)
|
||||
|| rom_present(NV3_VBIOS_ERAZOR_V14700)
|
||||
|| rom_present(NV3_VBIOS_ERAZOR_V15403)
|
||||
|| rom_present(NV3_VBIOS_ERAZOR_V15500)
|
||||
|| rom_present(NV3_VBIOS_STB_V128_V182)
|
||||
|| rom_present(NV3_VBIOS_STB_V128_V182)
|
||||
|| rom_present(NV3T_VBIOS_ASUS_V170)
|
||||
|| rom_present(NV3T_VBIOS_DIAMOND_V330_V182B)
|
||||
|| rom_present(NV3T_VBIOS_REFERENCE_CEK_V171)
|
||||
|| rom_present(NV3T_VBIOS_REFERENCE_CEK_V172);
|
||||
}
|
||||
|
||||
// NV3 (RIVA 128)
|
||||
// PCI
|
||||
// 2MB or 4MB VRAM
|
||||
@@ -971,6 +1031,7 @@ const device_t nv3_device_pci =
|
||||
.close = nv3_close,
|
||||
.speed_changed = nv3_speed_changed,
|
||||
.force_redraw = nv3_force_redraw,
|
||||
.available = nv3_available,
|
||||
.config = nv3_config,
|
||||
};
|
||||
|
||||
@@ -987,5 +1048,6 @@ const device_t nv3_device_agp =
|
||||
.close = nv3_close,
|
||||
.speed_changed = nv3_speed_changed,
|
||||
.force_redraw = nv3_force_redraw,
|
||||
.available = nv3_available,
|
||||
.config = nv3_config,
|
||||
};
|
||||
@@ -72,7 +72,7 @@ uint32_t nv3_pmc_handle_interrupts(bool send_now)
|
||||
// PGRAPH DMA INTR_EN (there is no DMA engine yet)
|
||||
// PRM Real-Mode Compatibility Interrupts
|
||||
|
||||
uint32_t new_intr_value;
|
||||
uint32_t new_intr_value = 0x00;
|
||||
|
||||
// set the new interrupt value
|
||||
// PAUDIO not used
|
||||
|
||||
Reference in New Issue
Block a user