NV3 memory mapping
Understanding the memory mapping of the NV3 is critical for understanding its overall operation.
The memory mapping architecture is implemented internally by the NV3 on-die memory controller and exposed to the user via the configuration register interface of the Peripheral Connect Interface (PCI) bus and its siblings and successors, such as AGP (or in later models, PCIe). Two of the maximum fsix base address registers are exposed using this mechanism, BAR0 and BAR1; BAR2 is claimed to exist by some sources, including envytools, but doesn't seem to actually exist. BAR0 contains a gigantic slab (16MB) of MMIO containing all of the GPU's registers, and BAR1, also 16MB, contains both a copy of the current framebuffer (or all of VRAM?) for dumb framebuffer use, and, at 0xC00000
, instance memory mapped as it is intended to be addressed.
Memory mapping
BAR0 (MMIO)
Start | End | Name | Purpose |
---|---|---|---|
0x0 |
0xFFF |
PMC |
Control GPU subsystems, some manufacture-time config info & global GPU interrupt status and control |
0x1000 |
0x1FFF |
PBUS |
PCI/AGP electrical configuration, memory controller, DMA controller |
0x1800 |
0x18FF |
PCI config space mirror |
PCI configuration for exposing the GPU to the rest of the machine, including vendor and device IDs, BARs for MMIO and VRAM mapping by the OS and various other characteristics. Technically a part of PBUS [1]
|
0x2000 |
0x3FFF |
PFIFO |
FIFO buffer using Gray code indexing; allows objects to be submitted in one of two caches (the one-entry CACHE0 used for software method injection and the 32 or 64 (NV3T)-deep CACHE1), storing them in a queue their methods can be executed; supports up to 8 DMA channels for object submission with 8 subchannels each, "context switching" is needed (see RAMFC) to change which DMA channel is selected. This area also has the configuration registers for the various control structures - RAMHT, RAMRO and RAMFC can all have their addresses and sizes here. |
0x4000 |
0x5FFF |
PRM |
Legacy Sound Blaster/MPU-401 support on MS-DOS |
0x6000 |
0x6FFF |
PRAM |
NV1 leftover that controlled the amount of RAM used for GPU control structures, unused. |
0x7000 |
0x7FFF |
PRMIO |
Real Mode I/O. In practice only used for the Real Mode Access (RMA) feature (at MMIO 0x7100 ) that allows reading and writing, to the GPU's MMIO space from real-mode (by using the x86 in /out instructions on legacy SVGA ports) without mapping any of the BARs; this is used by the VBIOS to talk to the main part of the GPU.
|
0x9000 |
0x9FFF |
PTIMER |
56-bit programmable interval timer for measuring events that need to happen at a precise real-world time interval. |
0xA0000 |
0xBFFFF |
PRMVGA |
Legacy VGA video memory |
0xC0000 |
0xCFFFF |
PRMVIO |
Legacy VGA I/O, extended sequencer registers, unknown "GX" registers; mirrored as legacy I/O ports. Lines up with where the VBIOS is in the real mode memory map but is entirely different. |
0x100000 |
0x100FFF |
PFB |
Framebuffer configuration and interface; power configuration; memory timings and configuration; some manufacture-time configuration information; debug facilities including tetris mode. |
0x101000 |
0x101FFF |
PEXTDEV |
External devices configuration; in theory a much wider feature, but in practice used for straps and OEM-level configuration. |
0x110000 |
0x11FFFF |
PROM / VBIOS |
Mirror of the Video BIOS (repeated for 64kb, even though the VBIOS is only 32kb) |
0x120000 |
0x120FFF |
PALT |
Alternative(?) VBIOS |
0x200000 |
0x200FFF |
PME |
Mediaport; allows plugging in of external MPEG decoder (in theory) - Warning: All known cases of attempts to read these registers have resulted in hard locking of the entire system! |
0x400000 |
0x401FFF |
PGRAPH |
2D & 3D graphics rendering engine. Allows up to 4 buffers to be used for rendering 2D and 3D graphics (mostly DirectX 5.0 and OpenGL 1.1 compliant); can render graphics at 8, 16 or 32bpp in 2D at up to theoretical maximum resolution (set by PFB ) of 2048*1536 (but in practice 1920*1200, sometimes 1600*1200) and up to 960*720 (NV3) or 1600*1200 (?) (NV3T) at 16bpp for 3D.
|
0x400648 (index) |
0x40064C (address/data) |
DPRAM |
Internal port (as part of PGRAPH ) to access on-die texture and vertex cache (12 KB)
|
0x410000 |
0x411FFF |
UBETA |
Internal write-only registers used while executing methods for the beta factor object |
0x420000 |
0x421FFF |
UROP |
Internal write-only registers used while executing methods for the GDI ternary ROP object |
0x430000 |
0x431FFF |
UCHROMA |
Internal write-only registers used while executing methods for the chroma key object |
0x440000 |
0x441FFF |
UPLANE |
Internal write-only registers used while executing methods for the plane mask object |
0x450000 |
0x451FFF |
UCLIP |
Internal write-only registers used while executing methods for the clipping rectangle object |
0x460000 |
0x461FFF |
UPATT |
Internal write-only registers used while executing methods for the GDI pattern object |
0x470000 |
0x471FFF |
URECT |
Internal write-only registers used while executing methods for the rectangle object |
0x480000 |
0x481FFF |
UPOINT |
Internal write-only registers used while executing methods for the point object |
0x490000 |
0x491FFF |
ULINE |
Internal write-only registers used while executing methods for the line object |
0x4A0000 |
0x4A1FFF |
ULIN |
Internal write-only registers used while executing methods for the lin (line without starting or ending pixels) object |
0x4B0000 |
0x4B1FFF |
UTRI |
Internal write-only registers used while executing methods for the triangle object |
0x4C0000 |
0x4C1FFF |
UW95TXT |
Internal write-only registers used while executing methods for the Win95 GDI (GDI rectangles + monochrome text + 1 bpp colour-expanded bitblit) text and bitmap object |
0x4D0000 |
0x4D1FFF |
UMEMFMT |
Internal write-only registers used while executing methods for the "memory to memory format" (glorified DMA) object |
0x4E0000 |
0x4E1FFF |
USCALED |
Internal write-only registers used while executing methods for the transfer to memory object |
0x500000 |
0x501FFF |
UBLIT |
Internal write-only registers used while executing methods for the bitblit object |
0x510000 |
0x511FFF |
UIMAGE |
Internal write-only registers used while executing methods for the image object |
0x520000 |
0x521FFF |
UBITMAP |
Internal write-only registers used while executing methods for the bitmap (basically monochrome version of Image above) object |
0x540000 |
0x541FFF |
UTOMEM |
Internal write-only registers used while executing methods for the "transfer image on screen to memory" object |
0x550000 |
0x551FFF |
USTRTCH |
Internal write-only registers used while executing methods for the "take image from CPU [really object methods] and stretch it while doing so" object. |
0x570000 |
0x571FFF |
UD3D0Z |
Internal write-only registers used while executing methods for the Direct3D 5.0 (also used for OpenGL) accelerated and some combination or none of flat shaded, Gouraud shaded, textured (optionally offset), blended, fogged, and specular (and many options for all of these) Z- and stencil-buffered (interleaved via the "zeta buffer") triangle object. |
0x580000 |
0x581FFF |
UPOINTZ |
Internal write-only registers used while executing methods for the point object, with the zeta buffer enabled. |
0x5C0000 |
0x5C1FFF |
UINMEM |
Internal write-only registers used while executing methods for the "image in memory" object, which sets the rendering parameter for each of the four hardware-supported buffers. |
0x601000 |
0x601FFF |
PRMCIO |
Part of the RAMDAC: Weitek CRTC for controlling both legacy VGA and the display device the GPU is connected to. A lot of this is mirrored as legacy SVGA x86 I/O ports (named as CIO in that case).
|
0x680000 |
0x6802FF |
PVIDEO (part of PDAC ) |
Video overlay control; controls current state of RAMDAC and video output; controls how GPU communicates with RAMDAC. |
0x680300 |
0x680FFF |
PRAMDAC (part of PDAC ) |
RAMDAC: Converts framebuffer to analog signal for display; display parameters (e.g. vblank); clock generation for GPU core and VRAM (MPLL ) and pixel clock for driving a CRT (VPLL ) 15bpp non-alpha blended hardware cursor (the cursor itself is stored in RAMIN); test registers; palette and colour output control, including 5-6-5 mode for true 16bpp operation instead of 5-5-5 15bpp.
|
0x681200 |
0x6813FF |
USER_DAC |
DAC registers intended for the user - indexed colour mode palette and pixel mask |
0x800000 |
0xFFFFFF |
NV_USER |
PIO-mode object submission area. Each channel is 64 KB in size and is further divided into 8 KB subchannels, which are written to at addresses corresponding to methods of the class of the object that has been set up in them. |
BAR1 (VRAM / RAMIN)
Start | End | Name | Purpose |
---|---|---|---|
0x0 |
End of VRAM:
|
PNVM , PDFB |
Raw contents of video RAM. Can be used to address the screen as a dumb linear framebuffer. If the VRAM does not fill up this entire space, it will repeat until 0x800000. |
0x800000 |
0xC00000 |
VRAM mirror | A mirror of Video RAM. The address basically has bits 24 and above masked off. If the card uses an NV3T chip and has 8 MB of VRAM, the mirror will not be complete. |
0xC00000 |
0xC00FFF (maximum extent, depending on size) |
RAMHT |
Hashtable used for referencing objects in PFIFO, so RAMIN can store more info about them than PFIFO allows. The actual RAMIN memory (which this subsystem is a part of) is not addressed linearly, this area is seemingly created by the memory controller to make RAMIN easier to use. |
0xC01000 |
0xC01BFF (maximum extent, depending on size) |
RAMAU |
Unused leftover from Rev A NV3 cards (and NV1) that still had a sound chip integrated on-die. The actual RAMIN memory (which this subsystem is a part of) is not addressed linearly, this area is seemingly created by the memory controller to make RAMIN easier to use. |
0xC01C00 |
0xC01DFF (maximum extent, depending on size) |
RAMFC |
Area used to store unused contexts after a context switch has occurred. Only really practically relevant during 3D rendering. The actual RAMIN memory (which this subsystem is a part of) is not addressed linearly, this area is seemingly created by the memory controller to make RAMIN easier to use. |
0xC01E00 |
0xC01FFF (maximum extent, depending on size) |
RAMRO |
Area that invalid object submissions are sent to. Ideally, you don't want anything to be written here. Has its own get and put address registers in PFIFO and is also Gray code indexed. The actual RAMIN memory (which this subsystem is a part of) is not addressed linearly, this area is seemingly created by the memory controller to make RAMIN easier to use. |
0xC02000 |
0xC02FFF (maximum extent, depending on size) |
RAMRM |
Real-mode compatibility RAM. The actual RAMIN memory (which this subsystem is a part of) is not addressed linearly, this area is seemingly created by the memory controller to make RAMIN easier to use. |
0xC03000 |
0xFFFFFF |
RAMIN |
The rest of instance memory used to store graphics objects. In practice, the grobj structures that correspond to the hashtable entries are usually stored between 0x4000 and 0x5000 (or, from the context of BAR1, 0xC04000 and 0xC05000 ). Part of this, in practice, may be more VRAM mirroring, possibly using the RAMIN addressing mode.
|
Unmapped memory
When reading from unmapped memory, one of four possible results may occur:
- If the unmapped memory is inside an area that, while not mapped to a register, is mapped to a real GPU subsystem: Repeat a register. The length of the repeat is variable and may depend on how many bits inside the GPU logic are used internally to "select" a subsystem's registers.
- If the unmapped memory is actually mapped, but is inside NV_USER or another write-only region: This always returns zero, except for how much space is left in the "virtual FIFO" abstraction for the channel and subchannel being written to.
- If the unmapped memory does not map to any subsystem: You will get a repeating 32-bit pattern of garbage. This always seems to start as
0x20 0x07 0x20 0x07
, but unpredictably and very rapidly changes to a random set of values. It seems to be different for each subsystem, or may change very quickly, faster than nvplayground can dump it. The cause of this behaviour is unknown, although it could be a form of open bus behaviour (just returning the last value read on the bus) like on older consoles, although, since the NV3 memory controller would seem to read the address first. - If the memory address is meant to be mapped to a subsystem, but the subsystem does not actually exist: Your system will hard lock and will need to be power cycled (not by the power button, even hard reset will not work).
PPMI
PPMI (Performance Monitoring and Instrumentation?) is a subsystem for performance monitoring that does not expose any registers. It may be a leftover of the development process and may not actually exist.
Notes
^ Repeated from 0x1900-0x19FF
due to incomplete address decoding