mirror of
https://github.com/86Box/86Box.git
synced 2026-02-23 01:48:21 -07:00
Move notifications to DMA code
This commit is contained in:
@@ -36,8 +36,7 @@
|
||||
"name": "debug",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"NV_LOG": "ON",
|
||||
"NV_LOG_ULTRA": "ON"
|
||||
"NV_LOG": "ON"
|
||||
},
|
||||
"inherits": "base"
|
||||
},
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user