From 145831eb35ec847e49cb9f64a09ba0056c041c29 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Tue, 11 Mar 2025 17:21:36 +0000 Subject: [PATCH] Update cache0 put address on object creation, too --- src/include/86box/nv/vid_nv.h | 26 +++++------ src/include/86box/nv/vid_nv3.h | 18 ++++---- src/video/nv/nv3/subsystems/nv3_pfifo.c | 58 ++++++++++++++---------- src/video/nv/nv3/subsystems/nv3_pgraph.c | 18 +++++++- src/video/nv/nv3/subsystems/nv3_pramin.c | 24 +++++----- 5 files changed, 85 insertions(+), 59 deletions(-) diff --git a/src/include/86box/nv/vid_nv.h b/src/include/86box/nv/vid_nv.h index 2927b91c6..c58d3b0ba 100644 --- a/src/include/86box/nv/vid_nv.h +++ b/src/include/86box/nv/vid_nv.h @@ -21,7 +21,7 @@ * - People who prevented me from giving up (various) * * Authors: Connor Hyde / starfrost - * + * * Copyright 2024-2025 Connor Hyde */ #ifdef EMU_DEVICE_H // what @@ -55,19 +55,19 @@ void nv_log(const char *fmt, ...); #define PCI_DEVICE_NV3T 0x0019 // Nvidia NV3T (Riva 128 ZX) #define PCI_DEVICE_NV4 0x0020 // Nvidia NV4 (RIVA TNT) -#define CHIP_REVISION_NV1_A0 0x0000 -#define CHIP_REVISION_NV1_B0 0x0010 -#define CHIP_REVISION_NV1_C0 0x0020 +#define CHIP_REVISION_NV1_A0 0x0000 // 1994 +#define CHIP_REVISION_NV1_B0 0x0010 // 1995 +#define CHIP_REVISION_NV1_C0 0x0020 // #define CHIP_REVISION_NV3_A0 0x0000 // January 1997 #define CHIP_REVISION_NV3_B0 0x0010 // October 1997 #define CHIP_REVISION_NV3_C0 0x0020 // 1998 // Architecture IDs -#define NV_ARCHITECTURE_NV1 1 -#define NV_ARCHITECTURE_NV2 2 -#define NV_ARCHITECTURE_NV3 3 - +#define NV_ARCHITECTURE_NV1 1 // NV1/STG2000 +#define NV_ARCHITECTURE_NV2 2 // Nvidia 'Mutara V08' +#define NV_ARCHITECTURE_NV3 3 // Riva 128 +#define NV_ARCHITECTURE_NV4 4 // Riva TNT and later typedef enum nv_bus_generation_e { @@ -119,7 +119,7 @@ typedef struct nv_base_s void* ddc; // Display Data Channel for EDID } nv_base_t; -#define NV_REG_LIST_END 0xD15EA5E +#define NV_REG_LIST_END 0xD15EA5E // The NV architectures are very complex. // There are hundreds of registers at minimum, and implementing these in a standard way would lead to @@ -131,11 +131,11 @@ typedef struct nv_base_s // Typically, unless they are for a special purpose (and handled specially) e.g. vga all register reads and writes are also 32-bit aligned typedef struct nv_register_s { - int32_t address; // MMIO Address - char* friendly_name; // Friendly name + int32_t address; // MMIO Address + char* friendly_name; // Friendly name // reg_ptr not needed as a parameter, because we implicitly know which register si being tiwddled - uint32_t (*on_read)(); // Optional on-read function - void (*on_write)(uint32_t value);// Optional on-write fucntion + uint32_t (*on_read)(); // Optional on-read function + void (*on_write)(uint32_t value); // Optional on-write fucntion } nv_register_t; nv_register_t* nv_get_register(uint32_t address, nv_register_t* register_list, uint32_t num_regs); diff --git a/src/include/86box/nv/vid_nv3.h b/src/include/86box/nv/vid_nv3.h index d18aa8754..d9d0a6ad3 100644 --- a/src/include/86box/nv/vid_nv3.h +++ b/src/include/86box/nv/vid_nv3.h @@ -271,10 +271,10 @@ extern const device_config_t nv3_config[]; #define NV3_PFIFO_CACHE0_STATUS_EMPTY 4 // 1 if ramro is empty #define NV3_PFIFO_CACHE0_STATUS_FULL 8 #define NV3_PFIFO_CACHE0_PUT_ADDRESS 2 // 1 bit -#define NV3_PFIFO_CACHE0_PULLER_CONTROL 0x3040 -#define NV3_PFIFO_CACHE0_PULLER_CONTROL_ENABLED 0 -#define NV3_PFIFO_CACHE0_PULLER_CONTROL_HASH_FAILURE 4 -#define NV3_PFIFO_CACHE0_PULLER_CONTROL_SOFTWARE_METHOD 8 +#define NV3_PFIFO_CACHE0_DMA_PULL0 0x3040 +#define NV3_PFIFO_CACHE0_DMA_PULL0_ENABLED 0 +#define NV3_PFIFO_CACHE0_DMA_PULL0_HASH_FAILURE 4 +#define NV3_PFIFO_CACHE0_DMA_PULL0_SOFTWARE_METHOD 8 #define NV3_PFIFO_CACHE0_PULLER_CTX_STATE 0x3050 #define NV3_PFIFO_CACHE0_PULLER_CTX_STATE_DIRTY 4 // 1=dirty 0=clean #define NV3_PFIFO_CACHE0_GET 0x3070 @@ -307,11 +307,11 @@ extern const device_config_t nv3_config[]; #define NV3_PFIFO_CACHE1_DMA_TLB_TAG 0x3230 #define NV3_PFIFO_CACHE1_DMA_TLB_PTE 0x3234 // Base of pagetableor DMA #define NV3_PFIFO_CACHE1_DMA_TLB_PT_BASE 0x3238 // Base of pagetable for DMA -#define NV3_PFIFO_CACHE1_PULL0 0x3240 +#define NV3_PFIFO_CACHE1_DMA_PULL0 0x3240 //todo: merge stuff -#define NV3_PFIFO_CACHE1_PULL0_ENABLED 0 -#define NV3_PFIFO_CACHE1_PULL0_HASH_FAILURE 4 -#define NV3_PFIFO_CACHE1_PULL0_SOFTWARE_METHOD 8 // 0=software, 1=hardware +#define NV3_PFIFO_CACHE1_DMA_PULL0_ENABLED 0 +#define NV3_PFIFO_CACHE1_DMA_PULL0_HASH_FAILURE 4 +#define NV3_PFIFO_CACHE1_DMA_PULL0_SOFTWARE_METHOD 8 // 0=software, 1=hardware #define NV3_PFIFO_CACHE1_PULLER_CTX_STATE 0x3250 #define NV3_PFIFO_CACHE1_PULLER_CTX_STATE_DIRTY 4 #define NV3_PFIFO_CACHE1_GET 0x3270 @@ -932,7 +932,7 @@ typedef struct nv3_pfifo_cache_s uint8_t get_address; // Trigger a DMA from the value you put here into where you were going. uint8_t channel; // The DMA channel ID of this cache. uint32_t status; - uint32_t puller_control; + uint32_t dma_pull0; uint32_t context[NV3_DMA_SUBCHANNELS_PER_CHANNEL]; // Only one of these exists for cache0 /* cache1 only diff --git a/src/video/nv/nv3/subsystems/nv3_pfifo.c b/src/video/nv/nv3/subsystems/nv3_pfifo.c index 1743750ba..9857afbd7 100644 --- a/src/video/nv/nv3/subsystems/nv3_pfifo.c +++ b/src/video/nv/nv3/subsystems/nv3_pfifo.c @@ -43,19 +43,20 @@ nv_register_t pfifo_registers[] = { { NV3_PFIFO_CONFIG_RAMHT, "PFIFO - RAMIN RAMHT Config", NULL, NULL }, { NV3_PFIFO_CONFIG_RAMRO, "PFIFO - RAMIN RAMRO Config", NULL, NULL }, { NV3_PFIFO_CACHE_REASSIGNMENT, "PFIFO - Allow Cache Channel Reassignment", NULL, NULL }, - { NV3_PFIFO_CACHE0_PULLER_CONTROL, "PFIFO - Cache0 Puller Control", NULL, NULL}, - { NV3_PFIFO_CACHE1_PULL0, "PFIFO - Cache1 Puller Control"}, + { NV3_PFIFO_CACHE0_DMA_PULL0, "PFIFO - Cache0 Puller Control", NULL, NULL}, + { NV3_PFIFO_CACHE1_DMA_PULL0, "PFIFO - Cache1 Puller Control"}, { NV3_PFIFO_CACHE0_PULLER_CTX_STATE, "PFIFO - Cache0 Puller State1 (Is context clean?)", NULL, NULL}, - { NV3_PFIFO_CACHE1_PULL0, "PFIFO - Cache1 Puller State0", NULL, NULL}, + { NV3_PFIFO_CACHE1_DMA_PULL0, "PFIFO - Cache1 Puller State0", NULL, NULL}, { NV3_PFIFO_CACHE1_PULLER_CTX_STATE, "PFIFO - Cache1 Puller State1 (Is context clean?)", NULL, NULL}, { NV3_PFIFO_CACHE0_DMA_PUSH0, "PFIFO - Cache0 Access", NULL, NULL, }, { NV3_PFIFO_CACHE1_DMA_PUSH0, "PFIFO - Cache1 Access", NULL, NULL, }, - { NV3_PFIFO_CACHE0_PUSH_CHANNEL_ID, "PFIFO - Cache0 DMA Channel ID", NULL, NULL, }, - { NV3_PFIFO_CACHE1_PUSH_CHANNEL_ID, "PFIFO - Cache1 DMA Channel ID", NULL, NULL, }, + { NV3_PFIFO_CACHE0_PUSH_CHANNEL_ID, "PFIFO - Cache0 Push Channel ID", NULL, NULL, }, + { NV3_PFIFO_CACHE1_PUSH_CHANNEL_ID, "PFIFO - Cache1 Push Channel ID", NULL, NULL, }, { NV3_PFIFO_CACHE0_ERROR_PENDING, "PFIFO - Cache0 DMA Error Pending?", NULL, NULL, }, { NV3_PFIFO_CACHE0_STATUS, "PFIFO - Cache0 Status", NULL, NULL}, { NV3_PFIFO_CACHE1_STATUS, "PFIFO - Cache1 Status", NULL, NULL}, { NV3_PFIFO_CACHE0_GET, "PFIFO - Cache0 Get", NULL, NULL }, + { NV3_PFIFO_CACHE0_CTX, "PFIFO - Cache0 Context", NULL, NULL }, { NV3_PFIFO_CACHE1_GET, "PFIFO - Cache1 Get", NULL, NULL }, { NV3_PFIFO_CACHE0_PUT, "PFIFO - Cache0 Put", NULL, NULL }, { NV3_PFIFO_CACHE1_PUT, "PFIFO - Cache1 Put", NULL, NULL }, @@ -145,11 +146,11 @@ uint32_t nv3_pfifo_read(uint32_t address) case NV3_PFIFO_CONFIG_RAMRO: ret = nv3->pfifo.ramro_config; break; - case NV3_PFIFO_CACHE0_PULLER_CONTROL: - ret = nv3->pfifo.cache0_settings.puller_control; + case NV3_PFIFO_CACHE0_DMA_PULL0: + ret = nv3->pfifo.cache0_settings.dma_pull0; break; - case NV3_PFIFO_CACHE1_PULL0: - ret = nv3->pfifo.cache1_settings.puller_control; + case NV3_PFIFO_CACHE1_DMA_PULL0: + ret = nv3->pfifo.cache1_settings.dma_pull0; break; case NV3_PFIFO_CACHE0_PULLER_CTX_STATE: ret = (nv3->pfifo.cache0_settings.context_is_dirty) ? (1 << NV3_PFIFO_CACHE0_PULLER_CTX_STATE_DIRTY) : 0; @@ -285,11 +286,13 @@ uint32_t nv3_pfifo_read(uint32_t address) uint32_t ctx_entry_id = ((address - NV3_PFIFO_CACHE1_CTX_START) / 16) % 8; ret = nv3->pfifo.cache1_settings.context[ctx_entry_id]; - nv_log("PFIFO Cache1 CTX Read Entry=%d Value=0x%04x", ctx_entry_id, ret); + nv_log("PFIFO Cache1 CTX Read Entry=%d Value=0x%04x\n", ctx_entry_id, ret); } /* Direct cache read stuff */ else if (address >= NV3_PFIFO_CACHE0_METHOD_START && address <= NV3_PFIFO_CACHE0_METHOD_END) { + nv_log("PFIFO Cache0 Read\n"); + if (address & 4) return nv3->pfifo.cache0_entry.data; else @@ -305,6 +308,8 @@ uint32_t nv3_pfifo_read(uint32_t address) else slot = (address >> 3) & 0x1F; + nv_log("PFIFO Cache1 Read slot=%d\n", slot); + // See if we want the object name or the channel/subchannel information. if (address & 4) return nv3->pfifo.cache1_entries[slot].data; @@ -341,11 +346,15 @@ void nv3_pfifo_trigger_dma_if_required() /* PUSH - System to GPU (?) */ if (nv3->pfifo.cache1_settings.dma_push0) { - + /* PULL - GPU to System */ + nv_log("Initiating System to NV DMA - Probably we are trying to notify\n"); + } + else if (nv3->pfifo.cache1_settings.dma_pull0) + { + /* PULL - GPU to System */ + nv_log("Initiating NV to System DMA - Probably we are trying to notify\n"); } - /* PULL - GPU to System */ - nv_log("Initiating NV to System DMA - Probably we are trying to notify"); } } @@ -447,11 +456,11 @@ void nv3_pfifo_write(uint32_t address, uint32_t val) nv3->pfifo.cache_reassignment = val & 0x01; //1bit meaningful break; // Control - case NV3_PFIFO_CACHE0_PULLER_CONTROL: - nv3->pfifo.cache0_settings.puller_control = val; // 8bits meaningful + case NV3_PFIFO_CACHE0_DMA_PULL0: + nv3->pfifo.cache0_settings.dma_pull0 = val; // 8bits meaningful break; - case NV3_PFIFO_CACHE1_PULL0: - nv3->pfifo.cache1_settings.puller_control = val; // 8bits meaningful + case NV3_PFIFO_CACHE1_DMA_PULL0: + nv3->pfifo.cache1_settings.dma_pull0 = val; // 8bits meaningful break; case NV3_PFIFO_CACHE0_PULLER_CTX_STATE: nv3->pfifo.cache0_settings.context_is_dirty = (val >> NV3_PFIFO_CACHE0_PULLER_CTX_STATE_DIRTY) & 0x01; @@ -628,7 +637,7 @@ void nv3_pfifo_cache0_push() void nv3_pfifo_cache0_pull() { // Do nothing if PFIFO CACHE0 is disabled - if (!nv3->pfifo.cache0_settings.puller_control & (1 >> NV3_PFIFO_CACHE0_PULLER_CONTROL_ENABLED)) + if (!nv3->pfifo.cache0_settings.dma_pull0 & (1 >> NV3_PFIFO_CACHE0_DMA_PULL0_ENABLED)) return; // Do nothing if there is nothing in cache0 to pull @@ -644,6 +653,9 @@ void nv3_pfifo_cache0_pull() // i.e. there is no method in cache0, so we have to find the object. if (!current_method) { + // flip the get address over + nv3->pfifo.cache0_settings.get_address ^= 0x04; + if (!nv3_ramin_find_object(current_name, 0, current_channel, current_subchannel)) return; // interrupt was fired, and we went to ramro } @@ -654,8 +666,8 @@ void nv3_pfifo_cache0_pull() // Tell the CPU if we found a software method if (current_context & 0x800000) { - nv3->pfifo.cache0_settings.puller_control |= NV3_PFIFO_CACHE0_PULLER_CONTROL_SOFTWARE_METHOD; - nv3->pfifo.cache0_settings.puller_control &= ~NV3_PFIFO_CACHE0_PULLER_CONTROL_ENABLED; + nv3->pfifo.cache0_settings.dma_pull0 |= NV3_PFIFO_CACHE0_DMA_PULL0_SOFTWARE_METHOD; + nv3->pfifo.cache0_settings.dma_pull0 &= ~NV3_PFIFO_CACHE0_DMA_PULL0_ENABLED; nv3_pfifo_interrupt(NV3_PFIFO_INTR_CACHE_ERROR, true); } @@ -780,7 +792,7 @@ void nv3_pfifo_cache1_push(uint32_t addr, uint32_t object_name) void nv3_pfifo_cache1_pull() { // Do nothing if PFIFO CACHE1 is disabled - if (!nv3->pfifo.cache1_settings.puller_control & (1 >> NV3_PFIFO_CACHE1_PULL0_ENABLED)) + if (!nv3->pfifo.cache1_settings.dma_pull0 & (1 >> NV3_PFIFO_CACHE1_DMA_PULL0_ENABLED)) return; // Do nothing if there is nothing in cache1 to pull @@ -808,8 +820,8 @@ void nv3_pfifo_cache1_pull() // Tell the CPU if we found a software method if (current_context & 0x800000) { - nv3->pfifo.cache1_settings.puller_control |= NV3_PFIFO_CACHE0_PULLER_CONTROL_SOFTWARE_METHOD; - nv3->pfifo.cache1_settings.puller_control &= ~NV3_PFIFO_CACHE0_PULLER_CONTROL_ENABLED; + nv3->pfifo.cache1_settings.dma_pull0 |= NV3_PFIFO_CACHE0_DMA_PULL0_SOFTWARE_METHOD; + nv3->pfifo.cache1_settings.dma_pull0 &= ~NV3_PFIFO_CACHE0_DMA_PULL0_ENABLED; nv3_pfifo_interrupt(NV3_PFIFO_INTR_CACHE_ERROR, true); } diff --git a/src/video/nv/nv3/subsystems/nv3_pgraph.c b/src/video/nv/nv3/subsystems/nv3_pgraph.c index 1c5750596..50089c410 100644 --- a/src/video/nv/nv3/subsystems/nv3_pgraph.c +++ b/src/video/nv/nv3/subsystems/nv3_pgraph.c @@ -468,16 +468,30 @@ void nv3_pgraph_vblank_start(svga_t* svga) nv3_pgraph_interrupt_valid(NV3_PGRAPH_INTR_EN_0_VBLANK); } +void nv3_pgraph_arbitrate_method(uint8_t name, uint16_t method, uint8_t channel, uint8_t subchannel, uint8_t class_id, uint32_t context) +{ + switch (class_id) + { + + } +} + /* Arbitrates graphics object submission to the right object types */ void nv3_pgraph_submit(uint8_t name, uint16_t method, uint8_t channel, uint8_t subchannel, uint8_t class_id, uint32_t context) { // class id can be derived from the context but we debug log it before we get here - + // Do we need to read grobj here? + switch (method) { // This method is how we figure out which methods exist. case NV3_ROOT_HI_IM_OBJECT_MCOBJECTYFACE: - nv_log("Hi, I'm an NVidia object :)\n"); + nv_log("I'm an Nvidia Object! name=0x%08x channel=%d.%d class=0x%02x (%s) method=0x%04x, context=0x%08x\n", + name, channel, subchannel, class_id, nv3_class_names[class_id], method, context); + break; + default: + // Object Method orchestration + nv3_pgraph_arbitrate_method(name, method, channel, subchannel, class_id, context); break; } } \ No newline at end of file diff --git a/src/video/nv/nv3/subsystems/nv3_pramin.c b/src/video/nv/nv3/subsystems/nv3_pramin.c index e1a2a6442..55de2616b 100644 --- a/src/video/nv/nv3/subsystems/nv3_pramin.c +++ b/src/video/nv/nv3/subsystems/nv3_pramin.c @@ -409,16 +409,16 @@ bool nv3_ramin_find_object(uint32_t name, uint32_t cache_num, uint8_t channel, u if (!cache_num) { nv3->pfifo.debug_0 |= NV3_PFIFO_CACHE0_ERROR_PENDING; - nv3->pfifo.cache0_settings.puller_control |= NV3_PFIFO_CACHE0_PULLER_CONTROL_HASH_FAILURE; + nv3->pfifo.cache0_settings.dma_pull0 |= NV3_PFIFO_CACHE0_DMA_PULL0_HASH_FAILURE; //It turns itself off on failure, the drivers turn it back on - nv3->pfifo.cache0_settings.puller_control &= ~NV3_PFIFO_CACHE0_PULLER_CONTROL_ENABLED; + nv3->pfifo.cache0_settings.dma_pull0 &= ~NV3_PFIFO_CACHE0_DMA_PULL0_ENABLED; } else { nv3->pfifo.debug_0 |= NV3_PFIFO_CACHE1_ERROR_PENDING; - nv3->pfifo.cache1_settings.puller_control |= NV3_PFIFO_CACHE1_PULL0_HASH_FAILURE; + nv3->pfifo.cache1_settings.dma_pull0 |= NV3_PFIFO_CACHE1_DMA_PULL0_HASH_FAILURE; //It turns itself off on failure, the drivers turn it back on - nv3->pfifo.cache1_settings.puller_control &= ~NV3_PFIFO_CACHE1_PULL0_ENABLED; + nv3->pfifo.cache1_settings.dma_pull0 &= ~NV3_PFIFO_CACHE1_DMA_PULL0_ENABLED; } nv3_pfifo_interrupt(NV3_PFIFO_INTR_CACHE_ERROR, true); @@ -452,9 +452,9 @@ bool nv3_ramin_find_object(uint32_t name, uint32_t cache_num, uint8_t channel, u // By definition we can't have a cache error by here so take it off if (!cache_num) - nv3->pfifo.cache0_settings.puller_control &= ~NV3_PFIFO_CACHE0_PULLER_CONTROL_HASH_FAILURE; + nv3->pfifo.cache0_settings.dma_pull0 &= ~NV3_PFIFO_CACHE0_DMA_PULL0_HASH_FAILURE; else - nv3->pfifo.cache1_settings.puller_control &= ~NV3_PFIFO_CACHE1_PULL0_HASH_FAILURE; + nv3->pfifo.cache1_settings.dma_pull0 &= ~NV3_PFIFO_CACHE1_DMA_PULL0_HASH_FAILURE; // Caches store all the subchannels for our current dma channel and basically get stale every context switch // Also we have to check that a osftware object didn't end up in here... @@ -471,13 +471,13 @@ bool nv3_ramin_find_object(uint32_t name, uint32_t cache_num, uint8_t channel, u // handle it as an error if (!cache_num) { - nv3->pfifo.cache0_settings.puller_control |= NV3_PFIFO_CACHE0_PULLER_CONTROL_SOFTWARE_METHOD; - nv3->pfifo.cache0_settings.puller_control &= ~NV3_PFIFO_CACHE0_PULLER_CONTROL_ENABLED; + nv3->pfifo.cache0_settings.dma_pull0 |= NV3_PFIFO_CACHE0_DMA_PULL0_SOFTWARE_METHOD; + nv3->pfifo.cache0_settings.dma_pull0 &= ~NV3_PFIFO_CACHE0_DMA_PULL0_ENABLED; } else { - nv3->pfifo.cache1_settings.puller_control |= NV3_PFIFO_CACHE1_PULL0_SOFTWARE_METHOD; - nv3->pfifo.cache0_settings.puller_control &= ~NV3_PFIFO_CACHE1_PULL0_ENABLED; + nv3->pfifo.cache1_settings.dma_pull0 |= NV3_PFIFO_CACHE1_DMA_PULL0_SOFTWARE_METHOD; + nv3->pfifo.cache0_settings.dma_pull0 &= ~NV3_PFIFO_CACHE1_DMA_PULL0_ENABLED; } // It's an error but it isn't lol @@ -488,9 +488,9 @@ bool nv3_ramin_find_object(uint32_t name, uint32_t cache_num, uint8_t channel, u { // obviously turn off the "is software" if it's not if (!cache_num) - nv3->pfifo.cache0_settings.puller_control &= ~NV3_PFIFO_CACHE0_PULLER_CONTROL_SOFTWARE_METHOD; + nv3->pfifo.cache0_settings.dma_pull0 &= ~NV3_PFIFO_CACHE0_DMA_PULL0_SOFTWARE_METHOD; else - nv3->pfifo.cache1_settings.puller_control &= ~NV3_PFIFO_CACHE1_PULL0_SOFTWARE_METHOD; + nv3->pfifo.cache1_settings.dma_pull0 &= ~NV3_PFIFO_CACHE1_DMA_PULL0_SOFTWARE_METHOD; } // Ok we found it. Lol