mirror of
https://github.com/86Box/86Box.git
synced 2026-02-23 18:08:20 -07:00
NV_USER and the other half of submitting (to cache1)
This commit is contained in:
@@ -254,6 +254,8 @@ extern const device_config_t nv3_config[];
|
||||
#define NV3_PFIFO_RUNOUT_GET 0x2420
|
||||
#define NV3_PFIFO_RUNOUT_GET_ADDRESS 3 // 13:3
|
||||
|
||||
#define NV3_PFIFO_RUNOUT_RAMIN_ERR 28
|
||||
|
||||
#define NV3_PFIFO_CACHE0_SIZE 1 // This is for software-injected notified only!
|
||||
#define NV3_PFIFO_CACHE1_SIZE_REV_AB 32
|
||||
#define NV3_PFIFO_CACHE1_SIZE_REV_C 64
|
||||
@@ -589,6 +591,8 @@ extern const device_config_t nv3_config[];
|
||||
|
||||
// easier name
|
||||
#define NV3_OBJECT_SUBMIT_START NV3_USER_START
|
||||
#define NV3_OBJECT_SUBMIT_SUBCHANNEL 13
|
||||
#define NV3_OBJECT_SUBMIT_CHANNEL 16
|
||||
#define NV3_OBJECT_SUBMIT_END NV3_USER_END
|
||||
|
||||
// also PDFB (Debug Framebuffer?)
|
||||
@@ -850,12 +854,8 @@ typedef struct nv3_pfifo_s
|
||||
|
||||
nv3_pfifo_cache_entry_t cache0_entry; // It only has 1 entry
|
||||
nv3_pfifo_cache_entry_t cache1_entries[NV3_PFIFO_CACHE1_SIZE_MAX]; // ONLY 32 USED ON REVISION A/B CARDS
|
||||
|
||||
|
||||
} nv3_pfifo_t;
|
||||
|
||||
// create_object(uint32_t type) here
|
||||
|
||||
// RAMDAC
|
||||
typedef struct nv3_pramdac_s
|
||||
{
|
||||
@@ -1328,7 +1328,7 @@ void nv3_pfifo_interrupt(uint32_t id, bool fire_now);
|
||||
// NV3 PFIFO - Caches
|
||||
void nv3_pfifo_cache0_push();
|
||||
void nv3_pfifo_cache0_pull();
|
||||
void nv3_pfifo_cache1_push();
|
||||
void nv3_pfifo_cache1_push(uint32_t addr, uint32_t val);
|
||||
void nv3_pfifo_cache1_pull();
|
||||
uint32_t nv3_pfifo_cache1_normal2gray(uint32_t val);
|
||||
uint32_t nv3_pfifo_cache1_gray2normal(uint32_t val);
|
||||
|
||||
@@ -31,8 +31,13 @@ add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.c
|
||||
vid_ibm_rgb528_ramdac.c vid_sdac_ramdac.c vid_ogc.c vid_mga.c vid_nga.c
|
||||
vid_tvp3026_ramdac.c vid_att2xc498_ramdac.c vid_xga.c
|
||||
vid_bochs_vbe.c
|
||||
|
||||
nv/nv_base.c nv/nv_rivatimer.c
|
||||
nv/nv3/nv3_core.c nv/nv3/nv3_core_config.c nv/nv3/nv3_core_arbiter.c
|
||||
|
||||
nv/nv3/nv3_core.c
|
||||
nv/nv3/nv3_core_config.c
|
||||
nv/nv3/nv3_core_arbiter.c
|
||||
|
||||
nv/nv3/subsystems/nv3_pramdac.c
|
||||
nv/nv3/subsystems/nv3_pfifo.c
|
||||
nv/nv3/subsystems/nv3_pgraph.c
|
||||
@@ -44,8 +49,10 @@ add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.c
|
||||
nv/nv3/subsystems/nv3_ptimer.c
|
||||
nv/nv3/subsystems/nv3_pramin.c nv/nv3/subsystems/nv3_pramin_ramht.c nv/nv3/subsystems/nv3_pramin_ramfc.c nv/nv3/subsystems/nv3_pramin_ramro.c
|
||||
nv/nv3/subsystems/nv3_pvideo.c
|
||||
nv/nv3/subsystems/nv3_user.c
|
||||
|
||||
nv/nv3/classes/nv3_class_names.c
|
||||
nv/nv3/classes/nv3_class_shared_methods.c
|
||||
nv/nv3/classes/nv3_class_001_beta_factor.c
|
||||
nv/nv3/classes/nv3_class_002_rop.c
|
||||
nv/nv3/classes/nv3_class_003_chroma_key.c
|
||||
|
||||
@@ -200,5 +200,3 @@ void nv3_prmcio_write(uint32_t address, uint32_t value) {};
|
||||
uint32_t nv3_vram_read(uint32_t address) { return 0; };
|
||||
void nv3_vram_write(uint32_t address, uint32_t value) {};
|
||||
|
||||
uint32_t nv3_user_read(uint32_t address) { return 0; };
|
||||
void nv3_user_write(uint32_t address, uint32_t value) {};
|
||||
@@ -462,11 +462,13 @@ uint32_t nv3_pfifo_cache1_gray2normal(uint32_t val)
|
||||
return val;
|
||||
}
|
||||
|
||||
// Submits graphics objects INTO cache0
|
||||
void nv3_pfifo_cache0_push()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Pulls graphics objects OUT of cache0
|
||||
void nv3_pfifo_cache0_pull()
|
||||
{
|
||||
// Do nothing if PFIFO CACHE0 is disabled
|
||||
@@ -511,11 +513,98 @@ void nv3_pfifo_cache0_pull()
|
||||
|
||||
}
|
||||
|
||||
void nv3_pfifo_cache1_push()
|
||||
void nv3_pfifo_context_switch(uint32_t new_channel)
|
||||
{
|
||||
|
||||
/* Send our contexts to RAMFC. Load the new ones from RAMFC. */
|
||||
}
|
||||
|
||||
// NV_USER writes go here!
|
||||
// Pushes graphics objects into cache1
|
||||
void nv3_pfifo_cache1_push(uint32_t addr, uint32_t val)
|
||||
{
|
||||
bool oh_shit = false; // RAMRO needed
|
||||
nv3_ramin_ramro_reason oh_shit_reason = 0x00; // It's all good for now
|
||||
|
||||
// bit 23 of a ramin dword means it's a write...
|
||||
uint32_t new_address = 0;
|
||||
|
||||
uint32_t method_offset = (addr & 0x1FFC); // size of dma object is 0x2000 and some universal methods are implemented at this point, like free
|
||||
|
||||
// Up to 128 per envytools?
|
||||
uint32_t channel = (addr >> NV3_OBJECT_SUBMIT_CHANNEL) & 0x7F;
|
||||
uint32_t subchannel = (addr >> NV3_OBJECT_SUBMIT_SUBCHANNEL) & 0x07;
|
||||
|
||||
// first make sure there is even any cache available
|
||||
if (!nv3->pfifo.cache1_settings.access_enabled)
|
||||
{
|
||||
oh_shit = true;
|
||||
oh_shit_reason = nv3_runout_reason_no_cache_available;
|
||||
}
|
||||
|
||||
// Check if runout is full
|
||||
if (nv3->pfifo.runout_get != nv3->pfifo.runout_put)
|
||||
{
|
||||
oh_shit = true;
|
||||
oh_shit_reason = nv3_runout_reason_cache_ran_out; // ? really ? I guess this means we already ran out..
|
||||
new_address |= (nv3_runout_reason_cache_ran_out << NV3_PFIFO_RUNOUT_RAMIN_ERR);
|
||||
}
|
||||
|
||||
if (!nv3_pfifo_cache1_is_free())
|
||||
{
|
||||
oh_shit = true;
|
||||
oh_shit_reason = nv3_runout_reason_free_count_overrun;
|
||||
new_address |= (nv3_runout_reason_free_count_overrun << NV3_PFIFO_RUNOUT_RAMIN_ERR);
|
||||
}
|
||||
|
||||
if (method_offset > 0 && method_offset <= 0x100)
|
||||
{
|
||||
// Reserved NVIDIA Objects
|
||||
oh_shit = true;
|
||||
oh_shit_reason = nv3_runout_reason_reserved_access;
|
||||
new_address |= (nv3_runout_reason_free_count_overrun << NV3_PFIFO_RUNOUT_RAMIN_ERR);
|
||||
|
||||
}
|
||||
|
||||
// Now check for context switching
|
||||
|
||||
if (channel != nv3->pfifo.cache1_settings.channel)
|
||||
{
|
||||
if (!nv3->pfifo.cache_reassignment
|
||||
|| (nv3->pfifo.cache0_settings.get_address != nv3->pfifo.cache0_settings.get_address))
|
||||
{
|
||||
oh_shit = true;
|
||||
oh_shit_reason = nv3_runout_reason_no_cache_available;
|
||||
new_address |= (nv3_runout_reason_no_cache_available << NV3_PFIFO_RUNOUT_RAMIN_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
// Did we fuck up?
|
||||
if (oh_shit)
|
||||
{
|
||||
nv_log("NV3: WE ARE FUCKED Runout Error=%d Channel=%d Subchannel=%d Method=0x%04x IMPLEMENT THIS OR DIE!!!", oh_shit_reason, channel, subchannel, method_offset);
|
||||
return;
|
||||
}
|
||||
|
||||
// We didn't. Let's put it in CACHE1
|
||||
uint32_t current_put_address = nv3->pfifo.cache1_settings.put_address >> 2;
|
||||
nv3->pfifo.cache1_entries[current_put_address].subchannel = subchannel;
|
||||
nv3->pfifo.cache1_entries[current_put_address].method = method_offset;
|
||||
nv3->pfifo.cache1_entries[current_put_address].data = val;
|
||||
|
||||
// now we have to recalculate the cache1 put address
|
||||
uint32_t next_put_address = nv3_pfifo_cache1_gray2normal(current_put_address);
|
||||
|
||||
if (nv3->nvbase.gpu_revision >= NV3_BOOT_REG_REV_C00) // RIVA 128ZX#
|
||||
next_put_address &= NV3_PFIFO_CACHE1_SIZE_REV_C;
|
||||
else
|
||||
next_put_address &= NV3_PFIFO_CACHE1_SIZE_REV_AB;
|
||||
|
||||
nv3->pfifo.cache1_settings.put_address = nv3_pfifo_cache1_normal2gray(next_put_address);
|
||||
|
||||
// Now we're done. Phew!
|
||||
}
|
||||
|
||||
// Pulls graphics objects OUT of cache1
|
||||
void nv3_pfifo_cache1_pull()
|
||||
{
|
||||
// Do nothing if PFIFO CACHE1 is disabled
|
||||
|
||||
@@ -36,4 +36,9 @@ uint32_t nv3_ramro_read(uint32_t address)
|
||||
void nv3_ramro_write(uint32_t address, uint32_t value)
|
||||
{
|
||||
nv_log("NV3: RAM Runout WRITE, OH CRAP!!!! (0x%04x -> 0x%04x), UNIMPLEMENTED\n (Todo: Read the entries...)\n", value, address);
|
||||
}
|
||||
|
||||
void nv3_ramro_send()
|
||||
{
|
||||
|
||||
}
|
||||
47
src/video/nv/nv3/subsystems/nv3_user.c
Normal file
47
src/video/nv/nv3/subsystems/nv3_user.c
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* NV3 User Submission Area (NV_USER, conceptually considered "Cache1 Pusher")
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Connor Hyde, <mario64crashed@gmail.com> I need a better email address ;^)
|
||||
*
|
||||
* Copyright 2024-2025 starfrost
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <86Box/86box.h>
|
||||
#include <86Box/device.h>
|
||||
#include <86Box/mem.h>
|
||||
#include <86box/pci.h>
|
||||
#include <86Box/rom.h> // DEPENDENT!!!
|
||||
#include <86Box/video.h>
|
||||
#include <86Box/nv/vid_nv.h>
|
||||
#include <86Box/nv/vid_nv3.h>
|
||||
|
||||
// 128 channels conceptually supported - a hangover from nv1 where multiple windows all directly programming the gpu were supported? total lunacy.
|
||||
uint32_t nv3_user_read(uint32_t address)
|
||||
{
|
||||
uint8_t method_offset = (address & 0x1FFC);
|
||||
|
||||
nv_log("NV3: User Submission Area method_offset=0x%04x OH SHIT!! NOT IMPLEMENTED!!!", method_offset);
|
||||
|
||||
// 0x10 is free CACHE1 object, other stuff?
|
||||
return 0x00;
|
||||
};
|
||||
|
||||
// Although NV3 doesn't have DMA mode unlike NV4 and later, it's conceptually similar to a "pusher" that pushes graphics commands that you write into CACHE1 that are then pulled out.
|
||||
// So we send the writes here. This might do other stuff, so we keep this function
|
||||
void nv3_user_write(uint32_t address, uint32_t value)
|
||||
{
|
||||
nv3_pfifo_cache1_push(address, value);
|
||||
}
|
||||
Reference in New Issue
Block a user