diff --git a/CMakePresets.json b/CMakePresets.json index b2ed64e97..30feab8ab 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -36,8 +36,7 @@ "name": "debug", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", - "NV_LOG": "ON", - "NV_LOG_ULTRA": "ON" + "NV_LOG": "ON" }, "inherits": "base" }, diff --git a/src/include/86box/nv/vid_nv3.h b/src/include/86box/nv/vid_nv3.h index 48170bfcd..05281a5ac 100644 --- a/src/include/86box/nv/vid_nv3.h +++ b/src/include/86box/nv/vid_nv3.h @@ -75,7 +75,7 @@ extern const device_config_t nv3t_config[]; // Confi #define NV3T_VBIOS_ASUS_V170 "roms/video/nvidia/nv3/A170D03T.rom" // ASUS AGP-V3000 ZXTV BIOS - V1.70D.03 (C) 1996-98 Nvidia Corporation #define NV3T_VBIOS_REFERENCE_CEK_V171 "roms/video/nvidia/nv3/BIOS_49_Riva 128" // Reference BIOS: RIVA 128 ZX BIOS - V1.71B-N (C) 1996-98 NVidia Corporation #define NV3T_VBIOS_REFERENCE_CEK_V172 "roms/video/nvidia/nv3/vgasgram.rom" // Reference(?) BIOS: RIVA 128 ZX BIOS - V1.72B (C) 1996-98 NVidia Corporation -# + // The default VBIOS to use #define NV3_VBIOS_DEFAULT NV3_VBIOS_ERAZOR_V15403 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 80c635a21..89473d829 100644 --- a/src/video/nv/nv3/classes/nv3_class_shared_methods.c +++ b/src/video/nv/nv3/classes/nv3_class_shared_methods.c @@ -65,118 +65,3 @@ void nv3_generic_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t return; } } - - -/* Sees if any notification is required after an object method is executed. If so, executes it... */ -void nv3_notify_if_needed(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) -{ - if (!nv3->pgraph.notify_pending) - return; - - uint32_t current_notification_object = nv3->pgraph.notifier; - uint32_t notification_type = ((current_notification_object >> NV3_PGRAPH_NOTIFY_REQUEST_TYPE) & 0x07); - - // check for a software method (0 = hardware, 1 = software) - if (notification_type != 0) - { - nv_log("Software Notification, firing interrupt"); - nv3_pgraph_interrupt_valid(NV3_PGRAPH_INTR_0_SOFTWARE_NOTIFY); - //return; - } - - // set up the NvNotification structure - nv3_notification_t notify = {0}; - notify.nanoseconds = nv3->ptimer.time; - notify.status = NV3_NOTIFICATION_STATUS_DONE_OK; // it should be fine to just signal that it's ok - - // these are only nonzero when there is an error - notify.info32 = notify.info16 = 0; - - // notify object base=grobj_1 >> 12 - uint32_t notify_obj_base = grobj.grobj_1 >> 12; - - uint32_t notify_obj_info = nv3_ramin_read32(notify_obj_base, nv3); - uint32_t notify_obj_limit = nv3_ramin_read32(notify_obj_base + 0x04, nv3); - uint32_t notify_obj_page = nv3_ramin_read32(notify_obj_base + 0x08, nv3); - - /* extract some important information*/ - uint32_t info_adjust = notify_obj_info & 0xFFF; - bool info_pt_present = (notify_obj_info >> NV3_NOTIFICATION_PT_PRESENT) & 0x01; - uint8_t info_notification_target = (notify_obj_info >> NV3_NOTIFICATION_TARGET) & 0x03; - - /* paging information */ - bool page_is_present = notify_obj_page & 0x01; - bool page_is_readwrite = (notify_obj_page >> NV3_NOTIFICATION_PAGE_ACCESS); - uint32_t frame_base = notify_obj_page & 0xFFFFF000; - - // This code is temporary and will probably be moved somewhere else - // Print torns of debug info - #ifdef DEBUG - nv_log_verbose_only("******* WARNING: IF THIS OPERATION FUCKS UP, RANDOM MEMORY WILL BE CORRUPTED, YOUR ENTIRE SYSTEM MAY BE HOSED *******\n"); - - nv_log_verbose_only("Notification Information:\n"); - nv_log_verbose_only("Adjust Value: 0x%08x\n", info_adjust); - (info_pt_present) ? nv_log_verbose_only("Pagetable Present: True\n") : nv_log_verbose_only("Pagetable Present: False\n"); - - switch (info_notification_target) - { - case NV3_NOTIFICATION_TARGET_NVM: - nv_log_verbose_only("Notification Target: VRAM\n"); - break; - case NV3_NOTIFICATION_TARGET_CART: - nv_log_verbose_only("VERY BAD WARNING: Notification detected with Notification Target: Cartridge. THIS SHOULD NEVER HAPPEN!!!!!\n"); - break; - case NV3_NOTIFICATION_TARGET_PCI: - (nv3->nvbase.bus_generation == nv_bus_pci) ? nv_log_verbose_only("Notification Target: PCI Bus\n") : nv_log_verbose_only("Notification Target: PCI Bus (On AGP card?)\n"); - break; - case NV3_NOTIFICATION_TARGET_AGP: - (nv3->nvbase.bus_generation == nv_bus_agp_1x - || nv3->nvbase.bus_generation == nv_bus_agp_2x) ? nv_log_verbose_only("Notification Target: AGP Bus\n") : nv_log_verbose_only("Notification Target: AGP Bus (On PCI card?)\n"); - break; - } - - nv_log_verbose_only("Limit: 0x%08x\n", notify_obj_limit); - (page_is_present) ? nv_log_verbose_only("Page is present\n") : nv_log_verbose_only("Page is not present\n"); - (page_is_readwrite) ? nv_log_verbose_only("Page is read-write\n") : nv_log_verbose_only("Page is read-only\n"); - nv_log_verbose_only("Pageframe Address: 0x%08x\n", frame_base); - #endif - - // set up the dma transfer. we need to translate to a physical address. - - uint32_t final_address = 0; - - /* Simple case: hardware notification, we can just take the pte since it's based on the type */ - if (notification_type == 0) - { - final_address = frame_base + info_adjust; - } - else - { - // for software we have to calculate the pte index - uint32_t pte_num = ((notification_type << 4) + info_adjust) >> 12; - - /* ramin entries are sorted - 1 object for each pte entry...*/ - final_address = nv3_ramin_read32(notify_obj_base + (0x10 * pte_num) + 8, nv3); - final_address += (info_adjust & 0xFFF); - } - - /* send the notification off */ - nv_log("About to send hardware notification to 0x%08x (Check target)\n", final_address); - - switch (info_notification_target) - { - case NV3_NOTIFICATION_TARGET_NVM: - 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: - dma_bm_write(final_address, (uint8_t*)¬ify, sizeof(nv3_notification_t), 4); - break; - } - - // we're done - nv3->pgraph.notify_pending = false; -} diff --git a/src/video/nv/nv3/nv3_core.c b/src/video/nv/nv3/nv3_core.c index fbb248de7..46b6cf9c3 100644 --- a/src/video/nv/nv3/nv3_core.c +++ b/src/video/nv/nv3/nv3_core.c @@ -315,7 +315,7 @@ uint8_t nv3_pci_read(int32_t func, int32_t addr, void* priv) ret = (NV_PCI_DEVICE_NV3 & 0xFF); break; - case NV3_PCI_CFG_DEVICE_ID+1: + case NV3_PCI_CFG_DEVICE_ID + 1: ret = (NV_PCI_DEVICE_NV3 >> 8); break; diff --git a/src/video/nv/nv3/subsystems/nv3_pbus_dma.c b/src/video/nv/nv3/subsystems/nv3_pbus_dma.c index da068e07f..49c844404 100644 --- a/src/video/nv/nv3/subsystems/nv3_pbus_dma.c +++ b/src/video/nv/nv3/subsystems/nv3_pbus_dma.c @@ -30,7 +30,158 @@ /* Nvidia DMA Engine */ -void nv3_dma_translate_address(void) +void nv3_perform_dma_m2mf(nv3_grobj_t grobj) +{ + switch (method_id) + { + /* mthdCreate in software(?)*/ + case NV3_ROOT_HI_IM_OBJECT_MCOBJECTYFACE: + //nv_log("mthdCreate obj_name=0x%08x\n", param); + nv3_pgraph_interrupt_invalid(NV3_PGRAPH_INTR_1_SOFTWARE_METHOD_PENDING); + break; + // set up the current notification request/object + // and check for double notifiers. + case NV3_SET_NOTIFY: + if (nv3->pgraph.notify_pending) + { + nv_log("Executed method NV3_SET_NOTIFY with nv3->pgraph.notify_pending already set. param=0x%08x, method=0x%04x, grobj=0x%08x 0x%08x 0x%08x 0x%08x\n"); + nv_log("IF THIS IS A DEBUG BUILD, YOU SHOULD SEE A CONTEXT BELOW"); + nv3_debug_ramin_print_context_info(param, context); + nv3_pgraph_interrupt_invalid(NV3_PGRAPH_INTR_1_DOUBLE_NOTIFY); + + // disable + nv3->pgraph.notify_pending = false; + nv3_pgraph_interrupt_invalid(NV3_PGRAPH_INTR_1_DOUBLE_NOTIFY); + /* may need to disable fifo in this state */ + return; + } + + // set a notify as pending. + nv3->pgraph.notifier = param; + nv3->pgraph.notify_pending = true; + break; + default: + nv_log("Shared Generic Methods: Invalid or Unimplemented method 0x%04x", method_id); + nv3_pgraph_interrupt_invalid(NV3_PGRAPH_INTR_1_SOFTWARE_METHOD_PENDING); + return; + } +} + + +/* Sees if any notification is required after an object method is executed. If so, executes it... */ +void nv3_notify_if_needed(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) { + if (!nv3->pgraph.notify_pending) + return; + + uint32_t current_notification_object = nv3->pgraph.notifier; + uint32_t notification_type = ((current_notification_object >> NV3_PGRAPH_NOTIFY_REQUEST_TYPE) & 0x07); + + // check for a software method (0 = hardware, 1 = software) + if (notification_type != 0) + { + nv_log("Software Notification, firing interrupt"); + nv3_pgraph_interrupt_valid(NV3_PGRAPH_INTR_0_SOFTWARE_NOTIFY); + //return; + } + + // set up the NvNotification structure + nv3_notification_t notify = {0}; + notify.nanoseconds = nv3->ptimer.time; + notify.status = NV3_NOTIFICATION_STATUS_DONE_OK; // it should be fine to just signal that it's ok + // these are only nonzero when there is an error + notify.info32 = notify.info16 = 0; + + // notify object base=grobj_1 >> 12 + uint32_t notify_obj_base = grobj.grobj_1 >> 12; + + uint32_t notify_obj_info = nv3_ramin_read32(notify_obj_base, nv3); + uint32_t notify_obj_limit = nv3_ramin_read32(notify_obj_base + 0x04, nv3); + uint32_t notify_obj_page = nv3_ramin_read32(notify_obj_base + 0x08, nv3); + + /* extract some important information*/ + uint32_t info_adjust = notify_obj_info & 0xFFF; + bool info_pt_present = (notify_obj_info >> NV3_NOTIFICATION_PT_PRESENT) & 0x01; + uint8_t info_notification_target = (notify_obj_info >> NV3_NOTIFICATION_TARGET) & 0x03; + + /* paging information */ + bool page_is_present = notify_obj_page & 0x01; + bool page_is_readwrite = (notify_obj_page >> NV3_NOTIFICATION_PAGE_ACCESS); + uint32_t frame_base = notify_obj_page & 0xFFFFF000; + + // This code is temporary and will probably be moved somewhere else + // Print torns of debug info + #ifdef DEBUG + nv_log_verbose_only("******* WARNING: IF THIS OPERATION FUCKS UP, RANDOM MEMORY WILL BE CORRUPTED, YOUR ENTIRE SYSTEM MAY BE HOSED *******\n"); + + nv_log_verbose_only("Notification Information:\n"); + nv_log_verbose_only("Adjust Value: 0x%08x\n", info_adjust); + (info_pt_present) ? nv_log_verbose_only("Pagetable Present: True\n") : nv_log_verbose_only("Pagetable Present: False\n"); + + switch (info_notification_target) + { + case NV3_NOTIFICATION_TARGET_NVM: + nv_log_verbose_only("Notification Target: VRAM\n"); + break; + case NV3_NOTIFICATION_TARGET_CART: + nv_log_verbose_only("VERY BAD WARNING: Notification detected with Notification Target: Cartridge. THIS SHOULD NEVER HAPPEN!!!!!\n"); + break; + case NV3_NOTIFICATION_TARGET_PCI: + (nv3->nvbase.bus_generation == nv_bus_pci) ? nv_log_verbose_only("Notification Target: PCI Bus\n") : nv_log_verbose_only("Notification Target: PCI Bus (On AGP card?)\n"); + break; + case NV3_NOTIFICATION_TARGET_AGP: + (nv3->nvbase.bus_generation == nv_bus_agp_1x + || nv3->nvbase.bus_generation == nv_bus_agp_2x) ? nv_log_verbose_only("Notification Target: AGP Bus\n") : nv_log_verbose_only("Notification Target: AGP Bus (On PCI card?)\n"); + break; + } + + nv_log_verbose_only("Limit: 0x%08x\n", notify_obj_limit); + (page_is_present) ? nv_log_verbose_only("Page is present\n") : nv_log_verbose_only("Page is not present\n"); + (page_is_readwrite) ? nv_log_verbose_only("Page is read-write\n") : nv_log_verbose_only("Page is read-only\n"); + nv_log_verbose_only("Pageframe Address: 0x%08x\n", frame_base); + #endif + + // set up the dma transfer. we need to translate to a physical address. + + uint32_t final_address = 0; + + /* Simple case: hardware notification, we can just take the pte since it's based on the type */ + if (notification_type == 0) + { + final_address = frame_base + info_adjust; + } + else + { + // for software we have to calculate the pte index + uint32_t pte_num = ((notification_type << 4) + info_adjust) >> 12; + + /* ramin entries are sorted - 1 object for each pte entry...*/ + final_address = nv3_ramin_read32(notify_obj_base + (0x10 * pte_num) + 8, nv3); + final_address += (info_adjust & 0xFFF); + } + + /* send the notification off */ + nv_log("About to send hardware notification to 0x%08x (Check target)\n", final_address); + + switch (info_notification_target) + { + case NV3_NOTIFICATION_TARGET_NVM: + + uint32_t* vram_32 = (uint32_t*)nv3->nvbase.svga.vram; + + // increment by 1 because each index increments by 4 + vram_32[final_address] = (notify.nanoseconds & 0xFFFFFFFF); + vram_32[final_address + 1] = (notify.nanoseconds >> 32); + vram_32[final_address + 2] = notify.info32; + vram_32[final_address + 3] = (notify.info16 | notify.status); + break; + case NV3_NOTIFICATION_TARGET_PCI: + case NV3_NOTIFICATION_TARGET_AGP: + dma_bm_write(final_address, (uint8_t*)¬ify, sizeof(nv3_notification_t), 4); + break; + } + + // we're done + nv3->pgraph.notify_pending = false; } \ No newline at end of file