diff --git a/doc/nvidia_notes/status.xlsx b/doc/nvidia_notes/status.xlsx index e23fe6c72..c050432b5 100644 Binary files a/doc/nvidia_notes/status.xlsx and b/doc/nvidia_notes/status.xlsx differ diff --git a/src/include/86box/nv/vid_nv.h b/src/include/86box/nv/vid_nv.h index c58d3b0ba..71c636c78 100644 --- a/src/include/86box/nv/vid_nv.h +++ b/src/include/86box/nv/vid_nv.h @@ -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 diff --git a/src/include/86box/nv/vid_nv3.h b/src/include/86box/nv/vid_nv3.h index e70a0bec6..40aa94ce2 100644 --- a/src/include/86box/nv/vid_nv3.h +++ b/src/include/86box/nv/vid_nv3.h @@ -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 diff --git a/src/video/nv/nv3/classes/nv3_class_01c_image_in_memory.c b/src/video/nv/nv3/classes/nv3_class_01c_image_in_memory.c index a6cb52fbf..5eee663f3 100644 --- a/src/video/nv/nv3/classes/nv3_class_01c_image_in_memory.c +++ b/src/video/nv/nv3/classes/nv3_class_01c_image_in_memory.c @@ -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); diff --git a/src/video/nv/nv3/classes/nv3_class_shared_methods.c b/src/video/nv/nv3/classes/nv3_class_shared_methods.c index 9985845cf..01f0e90c7 100644 --- a/src/video/nv/nv3/classes/nv3_class_shared_methods.c +++ b/src/video/nv/nv3/classes/nv3_class_shared_methods.c @@ -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: diff --git a/src/video/nv/nv3/nv3_core.c b/src/video/nv/nv3/nv3_core.c index 5016329a9..09d8e093a 100644 --- a/src/video/nv/nv3/nv3_core.c +++ b/src/video/nv/nv3/nv3_core.c @@ -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); } diff --git a/src/video/nv/nv3/nv3_core_config.c b/src/video/nv/nv3/nv3_core_config.c index e8beb6df7..256ae9dd9 100644 --- a/src/video/nv/nv3/nv3_core_config.c +++ b/src/video/nv/nv3/nv3_core_config.c @@ -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, }, } diff --git a/src/video/nv/nv3/subsystems/nv3_pfb.c b/src/video/nv/nv3/subsystems/nv3_pfb.c index 644d4090d..0dae5ab39 100644 --- a/src/video/nv/nv3/subsystems/nv3_pfb.c +++ b/src/video/nv/nv3/subsystems/nv3_pfb.c @@ -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"); } diff --git a/src/video/nv/nv3/subsystems/nv3_pfifo.c b/src/video/nv/nv3/subsystems/nv3_pfifo.c index b782f2b56..ef6af049e 100644 --- a/src/video/nv/nv3/subsystems/nv3_pfifo.c +++ b/src/video/nv/nv3/subsystems/nv3_pfifo.c @@ -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;