Fix 32bpp bsod by actually creating framebuffer mappings. Don't remap memory if it's 0 (prevents trashing the low/real-mode memory map), general code simplification (some things were enabled 3 times what

This commit is contained in:
starfrost013
2025-03-26 01:43:46 +00:00
parent 8b6185eeb1
commit 64b16a43a1
9 changed files with 140 additions and 68 deletions

Binary file not shown.

View File

@@ -93,6 +93,7 @@ typedef struct nv_base_s
rom_t vbios; // NVIDIA/OEm VBIOS
// move to nv3_cio_t?
svga_t svga; // SVGA core (separate to nv3) - Weitek licensed
uint32_t vram_amount; // The amount of VRAM
void* log; // new logging engine
// stuff that doesn't fit in the svga structure
uint32_t cio_read_bank; // SVGA read bank

View File

@@ -31,7 +31,7 @@ extern const device_config_t nv3_config[];
#define NV3_MMIO_SIZE 0x1000000 // Max MMIO size
#define NV3_LFB_RAMIN_MIRROR_START 0x400000 // Mirror of ramin (VERIFY ON HARDWARE)
#define NV3_LFB_2NDHALF_START 0x800000 // The second half of LFB(?)
#define NV3_LFB_MIRROR_START 0x800000 // The second half of LFB(?)
#define NV3_LFB_RAMIN_START 0xC00000 // RAMIN mapping start
#define NV3_LFB_MAPPING_SIZE 0x400000 // Size of RAMIN
@@ -78,9 +78,9 @@ extern const device_config_t nv3_config[];
#define NV3_VBIOS_DEFAULT NV3_VBIOS_ERAZOR_V15403
// Temporary, will be loaded from settings
#define VRAM_SIZE_2MB 0x200000 // 2MB
#define VRAM_SIZE_4MB 0x400000 // 4MB
#define VRAM_SIZE_8MB 0x800000 // NV3T only
#define NV3_VRAM_SIZE_2MB 0x200000 // 2MB
#define NV3_VRAM_SIZE_4MB 0x400000 // 4MB
#define NV3_VRAM_SIZE_8MB 0x800000 // NV3T only
// There is also 1mb supported by the card but it was never used
// PCI config
@@ -1421,7 +1421,7 @@ typedef struct nv3_s
nv3_pmc_t pmc; // Master Control
nv3_pfb_t pfb; // Framebuffer/VRAM
nv3_pbus_t pbus; // Bus Control
nv3_pfifo_t pfifo; // FIFO for command submisison
nv3_pfifo_t pfifo; // FIFO for command submission
nv3_pramdac_t pramdac; // RAMDAC (CLUT etc)
nv3_pgraph_t pgraph; // 2D/3D Graphics
@@ -1462,6 +1462,14 @@ void nv3_mmio_write8(uint32_t addr, uint8_t val, void* priv);
void nv3_mmio_write16(uint32_t addr, uint16_t val, void* priv); // Write 16-bit MMIO
void nv3_mmio_write32(uint32_t addr, uint32_t val, void* priv); // Write 32-bit MMIO
/* BAR1 Dumb Framebuffer Read */
uint8_t nv3_dfb_read8(uint32_t addr, void* priv); // Write 8-bit DFB
uint16_t nv3_dfb_read16(uint32_t addr, void* priv); // Write 16-bit DFB
uint32_t nv3_dfb_read32(uint32_t addr, void* priv); // Write 32-bit DFB
void nv3_dfb_write8(uint32_t addr, uint8_t val, void* priv); // Write 8-bit DFB
void nv3_dfb_write16(uint32_t addr, uint16_t val, void* priv); // Write 16-bit DFB
void nv3_dfb_write32(uint32_t addr, uint32_t val, void* priv); // Write 32-bit DFB
uint8_t nv3_svga_in(uint16_t addr, void* priv); // Read SVGA compatibility registers
void nv3_svga_out(uint16_t addr, uint8_t val, void* priv); // Write SVGA registers
uint8_t nv3_pci_read(int32_t func, int32_t addr, void* priv); // Read PCI configuration registers

View File

@@ -59,7 +59,7 @@ void nv3_class_01c_method(uint32_t param, uint32_t method_id, nv3_ramin_context_
/* Set the format */
nv3->pgraph.bpixel[src_buffer_id] = ((real_format & 0x03) | NV3_BPIXEL_FORMAT_IS_VALID);
nv3->pgraph.bpixel[src_buffer_id] = (real_format | NV3_BPIXEL_FORMAT_IS_VALID);
nv_log("Image in Memory BUF%d COLOR_FORMAT=0x%04x", src_buffer_id, param);

View File

@@ -166,10 +166,10 @@ void nv3_notify_if_needed(uint32_t name, uint32_t method_id, nv3_ramin_context_t
switch (info_notification_target)
{
case NV3_NOTIFICATION_TARGET_NVM:
svga_writel_linear(final_address, (notify.nanoseconds & 0xFFFFFFFF), nv3);
svga_writel_linear(final_address + 4, (notify.nanoseconds >> 32), nv3);
svga_writel_linear(final_address + 8, notify.info32, nv3);
svga_writel_linear(final_address + 0x0C, (notify.info16 | notify.status), nv3);
svga_writel_linear(final_address, (notify.nanoseconds & 0xFFFFFFFF), &nv3->nvbase.svga);
svga_writel_linear(final_address + 4, (notify.nanoseconds >> 32), &nv3->nvbase.svga);
svga_writel_linear(final_address + 8, notify.info32, &nv3->nvbase.svga);
svga_writel_linear(final_address + 0x0C, (notify.info16 | notify.status), &nv3->nvbase.svga);
break;
case NV3_NOTIFICATION_TARGET_PCI:
case NV3_NOTIFICATION_TARGET_AGP:

View File

@@ -129,9 +129,6 @@ uint32_t nv3_mmio_read32(uint32_t addr, void* priv)
ret = nv3_mmio_arbitrate_read(addr);
// This may get around the riva shredding its own cache
//nv3_pfifo_cache0_pull();
//nv3_pfifo_cache1_pull();
return ret;
@@ -261,7 +258,7 @@ uint8_t nv3_pci_read(int32_t func, int32_t addr, void* priv)
// 66Mhz FSB capable
case PCI_REG_COMMAND_L:
ret = nv3->pci_config.pci_regs[PCI_REG_COMMAND_L]; // we actually respond to the fucking
ret = nv3->pci_config.pci_regs[PCI_REG_COMMAND_L] ; // we actually respond to the fucking
break;
case PCI_REG_COMMAND_H:
@@ -396,6 +393,11 @@ void nv3_pci_write(int32_t func, int32_t addr, uint8_t val, void* priv)
// actually update the mappings
nv3_update_mappings();
break;
case PCI_REG_COMMAND_H:
nv3->pci_config.pci_regs[PCI_REG_COMMAND_H] = val;
// actually update the mappings
nv3_update_mappings();
break;
// pci status register
case PCI_REG_STATUS_L:
nv3->pci_config.pci_regs[PCI_REG_STATUS_L] = val | (NV3_PCI_STATUS_L_66MHZ_CAPABLE);
@@ -736,13 +738,57 @@ void nv3_svga_out(uint16_t addr, uint8_t val, void* priv)
}
/* DFB, sets up a dumb framebuffer */
uint8_t nv3_dfb_read8(uint32_t addr, void* priv)
{
addr &= (nv3->nvbase.svga.vram_mask);
return nv3->nvbase.svga.vram[addr];
}
uint16_t nv3_dfb_read16(uint32_t addr, void* priv)
{
addr &= (nv3->nvbase.svga.vram_mask);
return (nv3->nvbase.svga.vram[addr + 1] << 8) | nv3->nvbase.svga.vram[addr];
}
uint32_t nv3_dfb_read32(uint32_t addr, void* priv)
{
addr &= (nv3->nvbase.svga.vram_mask);
return (nv3->nvbase.svga.vram[addr + 3] << 24) | (nv3->nvbase.svga.vram[addr + 2] << 16) +
(nv3->nvbase.svga.vram[addr + 1] << 8) | nv3->nvbase.svga.vram[addr];
}
void nv3_dfb_write8(uint32_t addr, uint8_t val, void* priv)
{
addr &= (nv3->nvbase.svga.vram_mask);
nv3->nvbase.svga.vram[addr] = val;
}
void nv3_dfb_write16(uint32_t addr, uint16_t val, void* priv)
{
addr &= (nv3->nvbase.svga.vram_mask);
nv3->nvbase.svga.vram[addr + 1] = (val >> 8) & 0xFF;
nv3->nvbase.svga.vram[addr] = (val) & 0xFF;
}
void nv3_dfb_write32(uint32_t addr, uint32_t val, void* priv)
{
addr &= (nv3->nvbase.svga.vram_mask);
nv3->nvbase.svga.vram[addr + 3] = (val >> 24) & 0xFF;
nv3->nvbase.svga.vram[addr + 2] = (val >> 16) & 0xFF;
nv3->nvbase.svga.vram[addr + 1] = (val >> 8) & 0xFF;
nv3->nvbase.svga.vram[addr] = (val) & 0xFF;
}
/* Cursor shit */
void nv3_draw_cursor(svga_t* svga, int32_t drawline)
{
// sanity check
if (!nv3)
return;
// this is a 2kb bitmap in vram...somewhere...
// On windows, this shows up using NV_IMAGE_IN_MEMORY.
// Do we need to emulate it?
nv_log("nv3_draw_cursor drawline=0x%04x", drawline);
}
@@ -829,25 +875,26 @@ void nv3_init_mappings_svga()
{
nv_log("Initialising SVGA core memory mapping\n");
// setup the svga mappings
mem_mapping_set(&nv3->nvbase.framebuffer_mapping, 0, 0,
svga_read_linear,
svga_readw_linear,
svga_readl_linear,
svga_write_linear,
svga_writew_linear,
svga_writel_linear,
NULL, 0, &nv3->nvbase.svga);
mem_mapping_add(&nv3->nvbase.framebuffer_mapping, 0, 0,
nv3_dfb_read8,
nv3_dfb_read16,
nv3_dfb_read32,
nv3_dfb_write8,
nv3_dfb_write16,
nv3_dfb_write32,
nv3->nvbase.svga.vram, 0, &nv3->nvbase.svga);
// the SVGA/LFB mapping is also mirrored
mem_mapping_set(&nv3->nvbase.framebuffer_mapping_mirror, 0, 0,
svga_read_linear,
svga_readw_linear,
svga_readl_linear,
svga_write_linear,
svga_writew_linear,
svga_writel_linear,
NULL, 0, &nv3->nvbase.svga);
mem_mapping_add(&nv3->nvbase.framebuffer_mapping_mirror, 0, 0,
nv3_dfb_read8,
nv3_dfb_read16,
nv3_dfb_read32,
nv3_dfb_write8,
nv3_dfb_write16,
nv3_dfb_write32,
nv3->nvbase.svga.vram, 0, &nv3->nvbase.svga);
io_sethandler(0x03c0, 0x0020,
nv3_svga_in, NULL, NULL,
@@ -885,6 +932,12 @@ void nv3_update_mappings()
nv3_svga_out, NULL, NULL,
nv3);
if (!(nv3->pci_config.pci_regs[PCI_REG_COMMAND]) & PCI_COMMAND_MEM)
{
nv_log("The memory was turned off, not much is going to happen.\n");
return;
}
// turn off bar0 and bar1 by defualt
mem_mapping_disable(&nv3->nvbase.mmio_mapping);
mem_mapping_disable(&nv3->nvbase.framebuffer_mapping);
@@ -892,50 +945,56 @@ void nv3_update_mappings()
mem_mapping_disable(&nv3->nvbase.ramin_mapping);
mem_mapping_disable(&nv3->nvbase.ramin_mapping_mirror);
if (!(nv3->pci_config.pci_regs[PCI_REG_COMMAND]) & PCI_COMMAND_MEM)
{
nv_log("The memory was turned off, not much is going to happen.\n");
return;
}
mem_mapping_enable(&nv3->nvbase.mmio_mapping);
mem_mapping_enable(&nv3->nvbase.framebuffer_mapping);
mem_mapping_enable(&nv3->nvbase.framebuffer_mapping_mirror);
mem_mapping_enable(&nv3->nvbase.ramin_mapping);
mem_mapping_enable(&nv3->nvbase.ramin_mapping_mirror);
// first map bar0
// Setup BAR0 (MMIO)
nv_log("BAR0 (MMIO Base) = 0x%08x\n", nv3->nvbase.bar0_mmio_base);
//mem_mapping_enable(&nv3->nvbase.mmio_mapping); // should have no effect if already enabled
mem_mapping_set_addr(&nv3->nvbase.mmio_mapping, nv3->nvbase.bar0_mmio_base, NV3_MMIO_SIZE);
if (nv3->nvbase.bar0_mmio_base)
mem_mapping_set_addr(&nv3->nvbase.mmio_mapping, nv3->nvbase.bar0_mmio_base, NV3_MMIO_SIZE);
// if this breaks anything, remove it
// skeptical that 0 is used to disable...
nv_log("BAR1 (Linear Framebuffer / NV_USER Base & RAMIN) = 0x%08x\n", nv3->nvbase.bar1_lfb_base);
// this is likely mirrored
// 4x on 2mb cards
// 2x on 4mb cards
// and not at all on 8mb
mem_mapping_enable(&nv3->nvbase.framebuffer_mapping);
mem_mapping_enable(&nv3->nvbase.framebuffer_mapping_mirror);
mem_mapping_enable(&nv3->nvbase.ramin_mapping);
mem_mapping_enable(&nv3->nvbase.ramin_mapping_mirror);
mem_mapping_set_addr(&nv3->nvbase.framebuffer_mapping, nv3->nvbase.bar1_lfb_base, NV3_MMIO_SIZE);
/* TODO: 2MB */
// 4MB VRAM memory map:
// LFB_BASE+VRAM_SIZE=RAMIN Mirror(?) 0x1400000 (VERIFY PCBOX)
// LFB_BASE+VRAM_SIZE*2=LFB Mirror(?) 0x1800000
// LFB_BASE+VRAM_SIZE*3=Definitely RAMIN (then it ends, the total ram space is 16mb) 0x1C00000
mem_mapping_set_addr(&nv3->nvbase.ramin_mapping_mirror, nv3->nvbase.bar1_lfb_base + NV3_LFB_RAMIN_MIRROR_START, NV3_LFB_MAPPING_SIZE);
mem_mapping_set_addr(&nv3->nvbase.framebuffer_mapping_mirror, nv3->nvbase.bar1_lfb_base + NV3_LFB_2NDHALF_START, NV3_LFB_MAPPING_SIZE);
mem_mapping_set_addr(&nv3->nvbase.ramin_mapping, nv3->nvbase.bar1_lfb_base + NV3_LFB_RAMIN_START, NV3_LFB_MAPPING_SIZE);
// TODO: RAMIN and its mirror
// 8MB VRAM memory map:
// LFB_BASE->LFB_BASE+VRAM_SIZE=LFB
// What is in 800000-c00000?
// LFB_BASE+0xC00000 = RAMIN
if (nv3->nvbase.bar1_lfb_base)
{
if (nv3->nvbase.vram_amount == NV3_VRAM_SIZE_4MB)
{
mem_mapping_set_addr(&nv3->nvbase.framebuffer_mapping, nv3->nvbase.bar1_lfb_base, NV3_VRAM_SIZE_4MB);
mem_mapping_set_addr(&nv3->nvbase.ramin_mapping_mirror, nv3->nvbase.bar1_lfb_base + NV3_LFB_RAMIN_MIRROR_START, NV3_LFB_MAPPING_SIZE);
mem_mapping_set_addr(&nv3->nvbase.framebuffer_mapping_mirror, nv3->nvbase.bar1_lfb_base + NV3_LFB_MIRROR_START, NV3_VRAM_SIZE_4MB);
mem_mapping_set_addr(&nv3->nvbase.ramin_mapping, nv3->nvbase.bar1_lfb_base + NV3_LFB_RAMIN_START, NV3_LFB_MAPPING_SIZE);
}
else if (nv3->nvbase.vram_amount == NV3_VRAM_SIZE_8MB)
{
// we don't need this one in the case of 8mb, because regular mapping is 8mb
mem_mapping_disable(&nv3->nvbase.ramin_mapping_mirror);
mem_mapping_set_addr(&nv3->nvbase.framebuffer_mapping, nv3->nvbase.bar1_lfb_base, NV3_VRAM_SIZE_8MB);
mem_mapping_set_addr(&nv3->nvbase.framebuffer_mapping_mirror, nv3->nvbase.bar1_lfb_base + NV3_LFB_MIRROR_START, NV3_LFB_MAPPING_SIZE);
mem_mapping_set_addr(&nv3->nvbase.ramin_mapping, nv3->nvbase.bar1_lfb_base + NV3_LFB_RAMIN_START, NV3_LFB_MAPPING_SIZE);
}
else
{
fatal("NV3-2MB not implemented yet (It never existed anyway)");
}
}
// Did we change the banked SVGA mode?
switch (nv3->nvbase.svga.gdcreg[0x06] & 0x0c)
@@ -977,7 +1036,7 @@ void* nv3_init(const device_t *info)
// Allows nv_log to be used for multiple nvidia devices
nv_log_set_device(nv3->nvbase.log);
#endif
nv_log("initialising core\n");
nv_log("Initialising core\n");
// Figure out which vbios the user selected
const char* vbios_id = device_get_config_bios("vbios");
@@ -1001,7 +1060,7 @@ void* nv3_init(const device_t *info)
nv_log("Successfully loaded VBIOS %s located at %s\n", vbios_id, vbios_file);
// set the vram amount and gpu revision
uint32_t vram_amount = device_get_config_int("vram_size");
nv3->nvbase.vram_amount = device_get_config_int("vram_size");
nv3->nvbase.gpu_revision = device_get_config_int("chip_revision");
// set up the bus and start setting up SVGA core
@@ -1011,7 +1070,7 @@ void* nv3_init(const device_t *info)
pci_add_card(PCI_ADD_NORMAL, nv3_pci_read, nv3_pci_write, NULL, &nv3->nvbase.pci_slot);
svga_init(&nv3_device_pci, &nv3->nvbase.svga, nv3, vram_amount,
svga_init(&nv3_device_pci, &nv3->nvbase.svga, nv3, nv3->nvbase.vram_amount,
nv3_recalc_timings, nv3_svga_in, nv3_svga_out, nv3_draw_cursor, NULL);
}
else if (nv3->nvbase.bus_generation == nv_bus_agp_1x)
@@ -1020,7 +1079,7 @@ void* nv3_init(const device_t *info)
pci_add_card(PCI_ADD_AGP, nv3_pci_read, nv3_pci_write, NULL, &nv3->nvbase.pci_slot);
svga_init(&nv3_device_agp, &nv3->nvbase.svga, nv3, vram_amount,
svga_init(&nv3_device_agp, &nv3->nvbase.svga, nv3, nv3->nvbase.vram_amount,
nv3_recalc_timings, nv3_svga_in, nv3_svga_out, nv3_draw_cursor, NULL);
}

View File

@@ -140,23 +140,23 @@ const device_config_t nv3_config[] =
.name = "vram_size",
.description = "VRAM Size",
.type = CONFIG_SELECTION,
.default_int = VRAM_SIZE_4MB,
.default_int = NV3_VRAM_SIZE_4MB,
.selection =
{
#ifndef RELEASE_BUILD
// This never existed officially but was planned. Debug only
{
.description = "2 MB (Never officially sold)",
.value = VRAM_SIZE_2MB,
.value = NV3_VRAM_SIZE_2MB,
},
#endif
{
.description = "4 MB",
.value = VRAM_SIZE_4MB,
.value = NV3_VRAM_SIZE_4MB,
},
{
.description = "8 MB",
.value = VRAM_SIZE_8MB,
.value = NV3_VRAM_SIZE_8MB,
},
}

View File

@@ -57,9 +57,13 @@ void nv3_pfb_init()
| (NV3_PFB_BOOT_RAM_DATA_TWIDDLE_OFF << NV3_PFB_BOOT_RAM_DATA_TWIDDLE)
| (NV3_PFB_BOOT_RAM_BANKS_4 << NV3_PFB_BOOT_RAM_BANKS)
| (NV3_PFB_BOOT_RAM_WIDTH_128 << NV3_PFB_BOOT_RAM_WIDTH)
| (NV3_PFB_BOOT_RAM_AMOUNT_4MB << NV3_PFB_BOOT_RAM_AMOUNT)
);
if (nv3->nvbase.vram_amount == NV3_VRAM_SIZE_4MB)
nv3->pfb.boot |= (NV3_PFB_BOOT_RAM_AMOUNT_4MB << NV3_PFB_BOOT_RAM_AMOUNT);
else
nv3->pfb.boot |= (NV3_PFB_BOOT_RAM_AMOUNT_8MB << NV3_PFB_BOOT_RAM_AMOUNT);
nv_log("Done\n");
}

View File

@@ -218,7 +218,7 @@ uint32_t nv3_pfifo_read(uint32_t address)
ret = nv3->pfifo.cache1_settings.dma_state;
break;
case NV3_PFIFO_CACHE1_DMA_CONFIG_1:
ret = nv3->pfifo.cache1_settings.dma_length & (VRAM_SIZE_8MB) - 4; //MAX vram size
ret = nv3->pfifo.cache1_settings.dma_length & (NV3_VRAM_SIZE_8MB) - 4; //MAX vram size
break;
case NV3_PFIFO_CACHE1_DMA_CONFIG_2:
ret = nv3->pfifo.cache1_settings.dma_address;