mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-26 20:01:13 +01:00
1125 lines
49 KiB
C++
1125 lines
49 KiB
C++
/* Portions adapted with reference to RXDK-Libs (2026 Team Resurgent),
|
|
* GPL-3.0-or-later. See libs/d3d8/PROVENANCE.md and libs/d3d8/LICENSE.GPL-3.0.
|
|
* Original January target bytes and PDB remain the matching authority. */
|
|
/* NV2A hardware helpers reconstructed from the January target and its PDB.
|
|
* Volatile accesses are actual MMIO, not optimizer steering. No hardware
|
|
* code in this file has been executed against a live GPU by this campaign. */
|
|
#include "hardware_internal.h"
|
|
#include "miniport_constants.h"
|
|
#include "kernel_gpu.h"
|
|
#include "graphics_context_internal.h"
|
|
#pragma code_seg("D3D")
|
|
namespace D3D
|
|
{
|
|
void CMiniport::HalVideoControlInit(
|
|
void)
|
|
{
|
|
_HWREG *base = (_HWREG *)m_RegisterBase;
|
|
for (DWORD i = 0; i < 2; ++i)
|
|
{
|
|
REG_WR32(base, 0x8910 + i * 4, 0x1000);
|
|
REG_WR32(base, 0x8918 + i * 4, 0x1000);
|
|
REG_WR32(base, 0x8938 + i * 4, 0x100000);
|
|
REG_WR32(base, 0x8940 + i * 4, 0x100000);
|
|
REG_WR32(base, 0x8930 + i * 4, 0);
|
|
REG_WR32(base, 0x8928 + i * 4, 0xffffffffUL);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void CMiniport::HalGrControlInit(
|
|
void)
|
|
{
|
|
_HWREG *base = (_HWREG *)m_RegisterBase;
|
|
DWORD context = m_HalInfo.GrCtxTableBase;
|
|
REG_WR32(base, 0x400780, context & 0xffff);
|
|
for (DWORD i = 0; i < 2; ++i)
|
|
{
|
|
REG_WR32(base, ((context + 0x70000) << 4) + i * 4, 0);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void CMiniport::HalGrIdle(
|
|
void)
|
|
{
|
|
_HWREG *base = (_HWREG *)m_RegisterBase;
|
|
while (REG_RD32(base, 0x400700))
|
|
{
|
|
DWORD interrupts = REG_RD32(base, 0x100);
|
|
if (interrupts & 0x1000)
|
|
{
|
|
ServiceGrInterrupt();
|
|
}
|
|
if (interrupts & 0x1000000)
|
|
{
|
|
VBlank();
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
void CMiniport::HalGrUnloadChannelContext(
|
|
DWORD channel)
|
|
{
|
|
_HWREG *base = (_HWREG *)m_RegisterBase;
|
|
if (channel != 2)
|
|
{
|
|
REG_WR32(base, 0x400784, m_HalInfo.GrCtxTable[channel] & 0xffff);
|
|
REG_WR32(base, 0x400788, 2);
|
|
HalGrIdle();
|
|
REG_WR32(base, 0x400144, 0x10000000);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void CMiniport::HalDacUnload(
|
|
void)
|
|
{
|
|
_HWREG *base = (_HWREG *)m_RegisterBase;
|
|
REG_WR32(base, 0x600100, 1);
|
|
REG_WR32(base, 0x600140, 0);
|
|
return;
|
|
}
|
|
|
|
void CMiniport::HalDacLoad(
|
|
void)
|
|
{
|
|
_HWREG *base = (_HWREG *)m_RegisterBase;
|
|
REG_WR32(base, 0x600100, 1);
|
|
REG_WR32(base, 0x600140, 1);
|
|
return;
|
|
}
|
|
|
|
void CMiniport::HalFifoHashAdd(
|
|
DWORD index,
|
|
DWORD handle,
|
|
DWORD channel,
|
|
DWORD instance,
|
|
DWORD engine)
|
|
{
|
|
_HWREG *base = (_HWREG *)m_RegisterBase;
|
|
DWORD entry = m_HalInfo.HashTableAddr + index * sizeof(HW_HASHENTRY);
|
|
REG_WR32(base, entry, handle);
|
|
DWORD context = ((((channel | 0x80) << 8) | engine) << 16) | (instance & 0xffff);
|
|
REG_WR32(base, entry + 4, context);
|
|
return;
|
|
}
|
|
|
|
void CMiniport::HalGrInitObjectContext(
|
|
DWORD instance,
|
|
DWORD classNumber)
|
|
{
|
|
_HWREG *base = (_HWREG *)m_RegisterBase;
|
|
DWORD context = classNumber & 0xff;
|
|
DWORD extra;
|
|
switch (classNumber)
|
|
{
|
|
case NV03_MEMORY_TO_MEMORY_FORMAT:
|
|
context |= 0x1000000;
|
|
extra = 0;
|
|
break;
|
|
case NV10_CONTEXT_SURFACES_2D:
|
|
extra = 0;
|
|
break;
|
|
case NV20_KELVIN_PRIMITIVE:
|
|
extra = 0xa00;
|
|
break;
|
|
default:
|
|
extra = 0;
|
|
break;
|
|
}
|
|
REG_WR32(base, (0x70000 + instance) << 4, context);
|
|
REG_WR32(base, 0x700004 + (instance << 4), extra);
|
|
REG_WR32(base, 0x700008 + (instance << 4), 0);
|
|
REG_WR32(base, 0x70000c + (instance << 4), 0);
|
|
return;
|
|
}
|
|
}
|
|
|
|
namespace D3D
|
|
{
|
|
void CMiniport::HalFifoControlInit(
|
|
void)
|
|
{
|
|
_HWREG *base = (_HWREG *)m_RegisterBase;
|
|
m_HalInfo.FifoRetryCount = 0xff;
|
|
m_HalInfo.FifoUserBase = 0x800000;
|
|
m_HalInfo.FifoIntrEn0 = 0x01111111;
|
|
REG_WR32(base, 0x3210, 0);
|
|
REG_WR32(base, 0x3270, 0);
|
|
REG_WR32(base, 0x3240, 0);
|
|
REG_WR32(base, 0x3244, 0);
|
|
REG_WR32(base, 0x3058, 0);
|
|
REG_WR32(base, 0x3258, 0);
|
|
REG_WR32(base, 0x2504, m_HalInfo.FifoMode);
|
|
REG_WR32(base, 0x2508, 0);
|
|
REG_WR32(base, 0x250c, 0);
|
|
REG_WR32(base, 0x3228, 0);
|
|
REG_WR32(base, 0x2410, 0);
|
|
REG_WR32(base, 0x2420, 0);
|
|
return;
|
|
}
|
|
|
|
void CMiniport::HalFifoControlLoad(
|
|
void)
|
|
{
|
|
_HWREG *base = (_HWREG *)m_RegisterBase;
|
|
REG_WR32(base, 0x3224, 0xf0078);
|
|
REG_WR32(base, 0x2044, 0x0101ffff);
|
|
REG_WR32(base, 0x2040, m_HalInfo.FifoRetryCount & 0x3ff);
|
|
REG_WR32(base, 0x2500, 0);
|
|
REG_WR32(base, 0x3000, 0);
|
|
REG_WR32(base, 0x3050, 0);
|
|
REG_WR32(base, 0x3200, 0);
|
|
REG_WR32(base, 0x3250, 0);
|
|
REG_WR32(base, 0x3220, 0);
|
|
HalFifoContextSwitch(1);
|
|
REG_WR32(base, 0x3210, 0);
|
|
REG_WR32(base, 0x3270, 0);
|
|
REG_WR32(base, 0x3250, 1);
|
|
REG_WR32(base, 0x3200, 1);
|
|
REG_WR32(base, 0x2500, 1);
|
|
REG_WR32(base, 0x2500, 0);
|
|
return;
|
|
}
|
|
|
|
void CMiniport::HalDacControlInit(
|
|
void)
|
|
{
|
|
_HWREG *base = (_HWREG *)m_RegisterBase;
|
|
REG_WR08(base, 0x6013d4, 0x1f);
|
|
BYTE lock = REG_RD08(base, 0x6013d5);
|
|
REG_WR08(base, 0x6013d4, 0x1f);
|
|
REG_WR08(base, 0x6013d5, 0x57);
|
|
REG_WR08(base, 0x6013d4, 0x52);
|
|
BYTE value = REG_RD08(base, 0x6013d5);
|
|
REG_WR08(base, 0x6013d4, 0x52);
|
|
value += 4;
|
|
REG_WR08(base, 0x6013d5, value);
|
|
REG_WR32(base, 0x8088, (REG_RD32(base, 0x8088) & 0xfffff43f) | 0x400);
|
|
REG_WR32(base, 0x8088, (REG_RD32(base, 0x8088) & 0xf43fffff) | 0x4000000);
|
|
REG_WR32(base, 0x808c, (REG_RD32(base, 0x808c) & 0xfffff40f) | 0x400);
|
|
REG_WR32(base, 0x808c, (REG_RD32(base, 0x808c) & 0xf40fffff) | 0x4000000);
|
|
REG_WR08(base, 0x6013d4, 0x20);
|
|
REG_WR08(base, 0x6013d5, 0x29);
|
|
REG_WR08(base, 0x6013d4, 0x1b);
|
|
REG_WR08(base, 0x6013d5, 5);
|
|
REG_WR32(base, 0x600804, (REG_RD32(base, 0x600804) & ~5UL) | 2);
|
|
if (!lock)
|
|
{
|
|
REG_WR08(base, 0x6013d4, 0x1f);
|
|
REG_WR08(base, 0x6013d5, 0x99);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void CMiniport::HalMpControlInit(
|
|
void)
|
|
{
|
|
_HWREG *base = (_HWREG *)m_RegisterBase;
|
|
/* The initial read is a real hardware probe; its value is discarded by
|
|
* the January implementation, not a temporary introduced for allocation. */
|
|
(void)*(volatile DWORD *)((BYTE *)base + 0x200200);
|
|
m_GenInfo.MpVIPSlavePresent = FALSE;
|
|
REG_WR32(base, 0x200140, 0);
|
|
REG_WR32(base, 0x200200, (REG_RD32(base, 0x200200) & ~0x1fUL) | 0x20);
|
|
REG_WR32(base, 0x200200, REG_RD32(base, 0x200200) | 0x80);
|
|
REG_WR32(base, 0x200200, (REG_RD32(base, 0x200200) & ~0x800UL) | 0x700);
|
|
REG_WR32(base, 0x200428, 0);
|
|
REG_WR32(base, 0x20042c, 0);
|
|
REG_WR32(base, 0x200430, 0);
|
|
REG_WR32(base, 0x200458, 0);
|
|
REG_WR32(base, 0x20045c, 0);
|
|
REG_WR32(base, 0x200460, 0);
|
|
REG_WR32(base, 0x200488, 0);
|
|
REG_WR32(base, 0x20048c, 0);
|
|
REG_WR32(base, 0x200490, 0);
|
|
REG_WR32(base, 0x200350, 0);
|
|
REG_WR32(base, 0x200354, 0);
|
|
REG_WR32(base, 0x200358, 0);
|
|
REG_WR32(base, 0x200390, 0);
|
|
REG_WR32(base, 0x200394, 0);
|
|
REG_WR32(base, 0x200398, 0);
|
|
REG_WR32(base, 0x200400, 0);
|
|
REG_WR32(base, 0x200204, (REG_RD32(base, 0x200204) & ~0xbUL) | 4);
|
|
REG_WR32(base, 0x200204, REG_RD32(base, 0x200204) & ~0x300UL);
|
|
REG_WR32(base, 0x200208, (REG_RD32(base, 0x200208) & ~0xaUL) | 5);
|
|
REG_WR32(base, 0x200208, REG_RD32(base, 0x200208) & ~0x300UL);
|
|
return;
|
|
}
|
|
}
|
|
|
|
namespace D3D
|
|
{
|
|
void CMiniport::HalMcControlInit(
|
|
void)
|
|
{
|
|
_HWREG *base = (_HWREG *)m_RegisterBase;
|
|
m_HalInfo.McSave = REG_RD32(base, 0x200);
|
|
if (m_HalInfo.McSave == 0)
|
|
{
|
|
REG_WR32(base, 0x200, 0);
|
|
}
|
|
m_HalInfo.McSaveIntrEn0 = REG_RD32(base, 0x140);
|
|
REG_WR32(base, 0x200, 0xffffffffUL);
|
|
|
|
DWORD m = REG_RD32(base, 0x680504) & 0xff;
|
|
DWORD n = (REG_RD32(base, 0x680504) >> 8) & 0xff;
|
|
DWORD p = (REG_RD32(base, 0x680504) >> 16) & 7;
|
|
m_DacInfo.MPllM = m;
|
|
m_DacInfo.MPllN = n;
|
|
m_DacInfo.MPllO = 1;
|
|
m_DacInfo.MPllP = p;
|
|
m_DacInfo.MClk = m ? (m_GenInfo.CrystalFreq * n) / (1UL << p) / m : 0;
|
|
|
|
m = REG_RD32(base, 0x680508) & 0xff;
|
|
n = (REG_RD32(base, 0x680508) >> 8) & 0xff;
|
|
p = (REG_RD32(base, 0x680508) >> 16) & 7;
|
|
m_DacInfo.VPllM = m;
|
|
m_DacInfo.VPllN = n;
|
|
m_DacInfo.VPllO = 1;
|
|
m_DacInfo.VPllP = p;
|
|
m_DacInfo.VClk = m ? (m_GenInfo.CrystalFreq * n) / (1UL << p) / m : 0;
|
|
|
|
m = REG_RD32(base, 0x680500) & 0xff;
|
|
n = (REG_RD32(base, 0x680500) >> 8) & 0xff;
|
|
p = (REG_RD32(base, 0x680500) >> 16) & 7;
|
|
m_DacInfo.NVPllM = m;
|
|
m_DacInfo.NVPllN = n;
|
|
m_DacInfo.NVPllO = 1;
|
|
m_DacInfo.NVPllP = p;
|
|
m_DacInfo.NVClk = m ? (m_GenInfo.CrystalFreq * n) / (1UL << p) / m : 0;
|
|
return;
|
|
}
|
|
|
|
void CMiniport::HalFbControlInit(
|
|
void)
|
|
{
|
|
_HWREG *base = (_HWREG *)m_RegisterBase;
|
|
m_HalInfo.FbSave0 = REG_RD32(base, 0x100200);
|
|
m_HalInfo.FbSave1 = REG_RD32(base, 0x100204);
|
|
m_GenInfo.VideoRamType = (REG_RD32(base, 0x1218) & 0x100) == 0x100 ? 2 : 3;
|
|
|
|
DWORD instancePadding;
|
|
// The returned pointer marks the upper end of the reserved instance area.
|
|
// Both it and its 20 KiB prefix lie in the kernel-owned instance mapping.
|
|
m_InstMem = (BYTE *)MmClaimGpuInstanceMemory(20 * 1024, &instancePadding) - 20 * 1024;
|
|
DWORD instance = 0x700000 + instancePadding;
|
|
m_HalInfo.HashTableAddr = instance;
|
|
REG_WR32(base, 0x2210, ((instancePadding >> 8) & 0x1f0) | 0x03000000);
|
|
|
|
instance += 0x1000;
|
|
m_HalInfo.FifoContextAddr1 = instance;
|
|
instance += 0x80;
|
|
m_HalInfo.FifoContextAddr2 = instance;
|
|
REG_WR32(base, 0x2214,
|
|
((m_HalInfo.FifoContextAddr1 >> 8) & 0x1fc) |
|
|
(((m_HalInfo.FifoContextAddr2 & 0x1fc00) | 0x200) << 7));
|
|
instance += 0x20;
|
|
m_FreeInstAddr = (instance - 0x700000) >> 4;
|
|
REG_WR32(base, 0x100214, REG_RD32(base, 0x100214) & ~1UL);
|
|
for (DWORD address = 0x700000; address < 0x705000; address += sizeof(DWORD))
|
|
{
|
|
REG_WR32(base, address + instancePadding, 0);
|
|
}
|
|
m_HalInfo.GrCtxTableBase = ReserveInstMem(8);
|
|
return;
|
|
}
|
|
}
|
|
|
|
namespace D3D
|
|
{
|
|
void CMiniport::HalGrLoadChannelContext(
|
|
DWORD channel)
|
|
{
|
|
_HWREG *base = (_HWREG *)m_RegisterBase;
|
|
if (REG_RD32(base, 0x400100))
|
|
{
|
|
ServiceGrInterrupt();
|
|
}
|
|
DWORD savedFifo = REG_RD32(base, 0x400720);
|
|
REG_WR32(base, 0x400720, 0);
|
|
HalGrIdle();
|
|
if (m_HalInfo.GrChID != channel)
|
|
{
|
|
HalGrUnloadChannelContext(m_HalInfo.GrChID);
|
|
}
|
|
m_HalInfo.GrChID = channel;
|
|
if (channel == 2)
|
|
{
|
|
REG_WR32(base, 0x400144, 0x10000100);
|
|
REG_WR32(base, 0x400764, 0x08000000);
|
|
REG_WR32(base, 0x400720, savedFifo | 1);
|
|
return;
|
|
}
|
|
if (m_HalInfo.GrCurrentObjects3d[channel])
|
|
{
|
|
REG_WR32(base, 0x400080, 0x70000);
|
|
// Hardware readbacks bracket this reset; values are deliberately ignored.
|
|
(void)*(volatile DWORD *)((BYTE *)base + 0x400080);
|
|
REG_WR32(base, 0x400080, 0);
|
|
(void)*(volatile DWORD *)((BYTE *)base + 0x400080);
|
|
REG_WR32(base, 0x400750, 0x3d0000);
|
|
for (DWORD i = 0; i < 15; ++i)
|
|
{
|
|
REG_WR32(base, 0x400754, 0);
|
|
}
|
|
}
|
|
REG_WR32(base, 0x400084, REG_RD32(base, 0x400084) | 0x01000000);
|
|
REG_WR32(base, 0x400148, (channel & 31) << 24);
|
|
REG_WR32(base, 0x400784, m_HalInfo.GrCtxTable[channel] & 0xffff);
|
|
REG_WR32(base, 0x400788, 1);
|
|
HalGrIdle();
|
|
REG_WR32(base, 0x400148,
|
|
(REG_RD32(base, 0x400148) & 0xe0ffffffUL) | ((channel & 31) << 24));
|
|
REG_WR32(base, 0x400144, 0x10010100);
|
|
REG_WR32(base, 0x400764, REG_RD32(base, 0x400764) & 0xcfffffffUL);
|
|
return;
|
|
}
|
|
|
|
void CMiniport::HalGrControlLoad(
|
|
void)
|
|
{
|
|
_HWREG *base = (_HWREG *)m_RegisterBase;
|
|
REG_WR32(base, 0x200, REG_RD32(base, 0x200) & ~0x1000UL);
|
|
REG_WR32(base, 0x200, REG_RD32(base, 0x200) | 0x1000UL);
|
|
m_DebugRegister[6] = 0x45ead10e;
|
|
m_DebugRegister[1] = 0x00118700;
|
|
m_DebugRegister[2] = 0x0008c3ff;
|
|
m_DebugRegister[3] = 0xf3de0479;
|
|
m_DebugRegister[4] = 0;
|
|
m_DebugRegister[5] = 4;
|
|
m_DebugRegister[0] = 0;
|
|
m_DebugRegister[6] = (REG_RD32(base, 0x1218) & 0x100) == 0x100 ?
|
|
0x45ead10f : 0x45ead10e;
|
|
m_DebugRegister[7] = 0;
|
|
m_DebugRegister[8] = 0x78;
|
|
m_DebugRegister[9] = 0x40;
|
|
m_DebugRegister[10] = 0;
|
|
REG_WR32(base, 0x400080, 0);
|
|
REG_WR32(base, 0x400084, m_DebugRegister[1]);
|
|
REG_WR32(base, 0x400880, m_DebugRegister[2]);
|
|
REG_WR32(base, 0x40008c, m_DebugRegister[3]);
|
|
REG_WR32(base, 0x400090, m_DebugRegister[4]);
|
|
REG_WR32(base, 0x400094, m_DebugRegister[5]);
|
|
REG_WR32(base, 0x400b80, m_DebugRegister[6]);
|
|
REG_WR32(base, 0x400b84, m_DebugRegister[7]);
|
|
REG_WR32(base, 0x400098, m_DebugRegister[8]);
|
|
REG_WR32(base, 0x40009c, m_DebugRegister[9]);
|
|
REG_WR32(base, 0x400b88, m_DebugRegister[10]);
|
|
REG_WR32(base, 0x400780, m_HalInfo.GrCtxTableBase & 0xffff);
|
|
HalGrIdle();
|
|
|
|
// Mirror each framebuffer tile's limit, pitch and base into PGRAPH and RDI.
|
|
DWORD value;
|
|
for (long tile = 0; tile < 8; ++tile)
|
|
{
|
|
value = REG_RD32(base, 0x100244 + tile * 16);
|
|
REG_WR32(base, 0x400904 + tile * 16, value);
|
|
REG_WR32(base, 0x400750, 0xea0000 | ((0x30 + tile * 4) & 0x1ffc));
|
|
REG_WR32(base, 0x400754, value);
|
|
value = REG_RD32(base, 0x100248 + tile * 16);
|
|
REG_WR32(base, 0x400908 + tile * 16, value);
|
|
REG_WR32(base, 0x400750, 0xea0000 | ((0x50 + tile * 4) & 0x1ffc));
|
|
REG_WR32(base, 0x400754, value);
|
|
value = REG_RD32(base, 0x100240 + tile * 16);
|
|
REG_WR32(base, 0x400900 + tile * 16, value);
|
|
REG_WR32(base, 0x400750, 0xea0000 | ((0x10 + tile * 4) & 0x1ffc));
|
|
REG_WR32(base, 0x400754, value);
|
|
}
|
|
for (long tile = 0; tile < 8; ++tile)
|
|
{
|
|
value = REG_RD32(base, 0x100300 + tile * 4);
|
|
REG_WR32(base, 0x400980 + tile * 4, value);
|
|
REG_WR32(base, 0x400750, 0xea0000 | ((0x90 + tile * 4) & 0x1ffc));
|
|
REG_WR32(base, 0x400754, value);
|
|
}
|
|
value = REG_RD32(base, 0x100324);
|
|
REG_WR32(base, 0x4009a0, value);
|
|
REG_WR32(base, 0x400750, 0xea000c);
|
|
REG_WR32(base, 0x400754, value);
|
|
value = REG_RD32(base, 0x100200);
|
|
REG_WR32(base, 0x4009a4, value);
|
|
REG_WR32(base, 0x400750, 0xea0000);
|
|
REG_WR32(base, 0x400754, value);
|
|
value = REG_RD32(base, 0x100204);
|
|
REG_WR32(base, 0x4009a8, value);
|
|
REG_WR32(base, 0x400750, 0xea0004);
|
|
REG_WR32(base, 0x400754, value);
|
|
REG_WR32(base, 0x40014c, 0);
|
|
REG_WR32(base, 0x400150, 0);
|
|
REG_WR32(base, 0x400154, 0);
|
|
REG_WR32(base, 0x400158, 0);
|
|
REG_WR32(base, 0x400144, 0x10000000);
|
|
REG_WR32(base, 0x400764, 0x08000000);
|
|
HalGrLoadChannelContext(m_HalInfo.GrChID);
|
|
return;
|
|
}
|
|
}
|
|
|
|
namespace D3D
|
|
{
|
|
void CMiniport::HalFifoContextSwitch(
|
|
DWORD channel)
|
|
{
|
|
_HWREG *base = (_HWREG *)m_RegisterBase;
|
|
DWORD contextBase = m_HalInfo.FifoContextAddr1;
|
|
DWORD fifoReassign = REG_RD32(base, 0x2500);
|
|
DWORD fifoPush = REG_RD32(base, 0x3200);
|
|
DWORD fifoPull = REG_RD32(base, 0x3250);
|
|
REG_WR32(base, 0x2500, 0);
|
|
REG_WR32(base, 0x3200, 0);
|
|
REG_WR32(base, 0x3250, 0);
|
|
|
|
DWORD oldChannel = REG_RD32(base, 0x3204) & 31;
|
|
volatile FifoChannelContext *context = (volatile FifoChannelContext *)
|
|
((BYTE *)base + contextBase + oldChannel * sizeof(FifoChannelContext));
|
|
context->Put = REG_RD32(base, 0x3240);
|
|
context->Get = REG_RD32(base, 0x3244);
|
|
context->Ref = REG_RD32(base, 0x3248);
|
|
context->Instance = REG_RD32(base, 0x322c);
|
|
context->State = REG_RD32(base, 0x3228);
|
|
context->Fetch = REG_RD32(base, 0x3224);
|
|
context->Engine = REG_RD32(base, 0x3280);
|
|
context->Pull = REG_RD32(base, 0x3254);
|
|
context->AcquireValue = REG_RD32(base, 0x3268);
|
|
context->AcquireTimestamp = REG_RD32(base, 0x3264);
|
|
context->AcquireTimeout = REG_RD32(base, 0x3260);
|
|
context->Semaphore = REG_RD32(base, 0x326c);
|
|
context->Subroutine = REG_RD32(base, 0x324c);
|
|
|
|
if (REG_RD32(base, 0x3204) & 0x100)
|
|
{
|
|
DWORD pending = REG_RD32(base, 0x2508) & ~(1UL << oldChannel);
|
|
if (REG_RD32(base, 0x3240) != REG_RD32(base, 0x3244))
|
|
{
|
|
pending |= 1UL << oldChannel;
|
|
}
|
|
REG_WR32(base, 0x2508, pending);
|
|
}
|
|
REG_WR32(base, 0x3204, channel & 31);
|
|
if ((m_HalInfo.FifoMode & (1UL << channel)) && channel != 1)
|
|
{
|
|
REG_WR32(base, 0x3204, REG_RD32(base, 0x3204) | 0x100);
|
|
}
|
|
context = (volatile FifoChannelContext *)
|
|
((BYTE *)base + (contextBase + channel * sizeof(FifoChannelContext)));
|
|
REG_WR32(base, 0x3240, context->Put);
|
|
REG_WR32(base, 0x3244, context->Get);
|
|
REG_WR32(base, 0x3248, context->Ref);
|
|
REG_WR32(base, 0x322c, context->Instance);
|
|
REG_WR32(base, 0x3228, context->State);
|
|
REG_WR32(base, 0x3224, context->Fetch);
|
|
REG_WR32(base, 0x3280, context->Engine);
|
|
REG_WR32(base, 0x3254, context->Pull);
|
|
REG_WR32(base, 0x3268, context->AcquireValue);
|
|
REG_WR32(base, 0x3264, context->AcquireTimestamp);
|
|
REG_WR32(base, 0x3260, context->AcquireTimeout);
|
|
REG_WR32(base, 0x326c, context->Semaphore);
|
|
REG_WR32(base, 0x324c, context->Subroutine);
|
|
if ((m_HalInfo.FifoMode & (1UL << channel)) && channel != 1)
|
|
{
|
|
REG_WR32(base, 0x3220, 1);
|
|
}
|
|
REG_WR32(base, 0x204c, 0x1fffff);
|
|
REG_WR32(base, 0x3250, fifoPull);
|
|
REG_WR32(base, 0x3200, fifoPush);
|
|
REG_WR32(base, 0x2500, fifoReassign);
|
|
return;
|
|
}
|
|
|
|
void CMiniport::HalFifoAllocDMA(
|
|
DWORD fetchTrigger,
|
|
DWORD fetchSize,
|
|
DWORD fetchRequests,
|
|
OBJECTINFO *dataContext)
|
|
{
|
|
_HWREG *base = (_HWREG *)m_RegisterBase;
|
|
DWORD channel = m_HalInfo.FifoChID;
|
|
// Read the reassignment latch before disabling it.
|
|
(void)*(volatile DWORD *)((BYTE *)base + 0x2500);
|
|
REG_WR32(base, 0x2500, 0);
|
|
for (DWORD i = 0; i < 0xdfc; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (m_HalInfo.FifoInstance << 4) + i * 4, 0);
|
|
}
|
|
REG_WR32(base, 0x700000 + (m_HalInfo.GrCtxTableBase << 4) + channel * 4,
|
|
m_HalInfo.FifoInstance);
|
|
m_HalInfo.GrCtxTable[channel] = m_HalInfo.FifoInstance;
|
|
|
|
volatile FifoChannelContext *context = (volatile FifoChannelContext *)
|
|
((BYTE *)base + m_HalInfo.FifoContextAddr1 + channel * sizeof(FifoChannelContext));
|
|
for (DWORD i = 0; i < sizeof(FifoChannelContext); i += sizeof(DWORD))
|
|
{
|
|
*(volatile DWORD *)((BYTE *)context + i) = 0;
|
|
}
|
|
context->Instance = dataContext->Instance;
|
|
if (fetchTrigger < 8) fetchTrigger = 8;
|
|
if (fetchTrigger > 256) fetchTrigger = 256;
|
|
fetchTrigger = (fetchTrigger >> 3) - 1;
|
|
if (fetchSize < 32) fetchSize = 32;
|
|
if (fetchSize > 256) fetchSize = 256;
|
|
fetchSize = (fetchSize >> 5) - 1;
|
|
if (fetchRequests > 15) fetchRequests = 15;
|
|
DWORD fetch = (((((fetchRequests & 31) << 3) | (fetchSize & 7)) << 10) |
|
|
(fetchTrigger & 31)) << 3;
|
|
context->Fetch = fetch;
|
|
m_HalInfo.FifoMode |= 1UL << channel;
|
|
REG_WR32(base, 0x2504, m_HalInfo.FifoMode);
|
|
REG_WR32(base, 0x3200, 0);
|
|
REG_WR32(base, 0x3250, 0);
|
|
REG_WR32(base, 0x3204, channel & 31);
|
|
if (m_HalInfo.FifoMode & (1UL << channel))
|
|
{
|
|
REG_WR32(base, 0x3204, REG_RD32(base, 0x3204) | 0x100);
|
|
}
|
|
REG_WR32(base, 0x3240, 0);
|
|
REG_WR32(base, 0x3244, 0);
|
|
REG_WR32(base, 0x322c, dataContext->Instance);
|
|
REG_WR32(base, 0x3230, 0);
|
|
REG_WR32(base, 0x3228, 0);
|
|
REG_WR32(base, 0x3280, 0);
|
|
REG_WR32(base, 0x3224, fetch);
|
|
if (m_HalInfo.FifoMode & (1UL << channel))
|
|
{
|
|
REG_WR32(base, 0x3220, 1);
|
|
}
|
|
REG_WR32(base, 0x3250, 1);
|
|
REG_WR32(base, 0x3200, 1);
|
|
REG_WR32(base, 0x2500, 1);
|
|
m_HalInfo.FifoInUse |= 1UL << channel;
|
|
return;
|
|
}
|
|
}
|
|
|
|
namespace D3D
|
|
{
|
|
/* Adapted from the NV2A context initialization layout described in RXDK-Libs
|
|
* (GPL-3.0-or-later), pinned at 29e018674a3443f9df5b5cb4478bb9c54d8a2a3a.
|
|
* January target bytes determine the actual values and ordering below.
|
|
* Requires the reserved, mapped instance-memory context for FifoChID. */
|
|
void CMiniport::HalGrInit3d(
|
|
void)
|
|
{
|
|
_HWREG *base = (_HWREG *)m_RegisterBase;
|
|
DWORD grCtxBuffer = m_HalInfo.GrCtxTable[m_HalInfo.FifoChID];
|
|
DWORD ctxUser = REG_RD32(base, 0x700000 + (grCtxBuffer << 4));
|
|
ctxUser |= 1;
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4), ctxUser);
|
|
|
|
DWORD offset = GRCTX_COMMON_DWORDS;
|
|
DWORD i;
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0xffff0000); /* AntiAliasing */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* Blend */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BlendColor */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BorderColor0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BorderColor1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BorderColor2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BorderColor3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BumpMat00_1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BumpMat00_2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BumpMat00_3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BumpMat01_1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BumpMat01_2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BumpMat01_3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BumpMat10_1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BumpMat10_2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BumpMat10_3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BumpMat11_1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BumpMat11_2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BumpMat11_3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BumpOffset1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BumpOffset2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BumpOffset3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BumpScale1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BumpScale2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BumpScale3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0xfff0000); /* ClearRectX */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0xfff0000); /* ClearRectY */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* ColorClearValue */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* ColorKeyColor0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* ColorKeyColor1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* ColorKeyColor2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* ColorKeyColor3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineFactor0_0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineFactor0_1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineFactor0_2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineFactor0_3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineFactor0_4 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineFactor0_5 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineFactor0_6 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineFactor0_7 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineFactor1_0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineFactor1_1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineFactor1_2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineFactor1_3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineFactor1_4 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineFactor1_5 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineFactor1_6 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineFactor1_7 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineAlphaI0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineAlphaI1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineAlphaI2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineAlphaI3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineAlphaI4 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineAlphaI5 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineAlphaI6 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineAlphaI7 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineAlphaO0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineAlphaO1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineAlphaO2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineAlphaO3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineAlphaO4 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineAlphaO5 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineAlphaO6 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineAlphaO7 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineColorI0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineColorI1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineColorI2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineColorI3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineColorI4 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineColorI5 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineColorI6 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineColorI7 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineColorO0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineColorO1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineColorO2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineColorO3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineColorO4 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineColorO5 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineColorO6 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineColorO7 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x101); /* CombineCtl */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineSpecFog0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CombineSpecFog1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* Control0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* Control1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x111); /* Control2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* Control3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* FogColor */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* FogParam0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* FogParam1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* PointSize */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x44400000); /* SetupRaster */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* ShaderClipMode */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* ShaderCtl */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* ShaderProg */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* SemaphoreOffset */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* ShadowCtl */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* ShadowZSlopeThreshold */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* SpecFogFactor0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* SpecFogFactor1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* SurfaceClipX */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* SurfaceClipY */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x30303); /* TexAddress0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x30303); /* TexAddress1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x30303); /* TexAddress2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x30303); /* TexAddress3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* TexCtl0_0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* TexCtl0_1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* TexCtl0_2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* TexCtl0_3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x80000); /* TexCtl1_0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x80000); /* TexCtl1_1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x80000); /* TexCtl1_2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x80000); /* TexCtl1_3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* TexCtl2_0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* TexCtl2_1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x1012000); /* TexFilter0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x1012000); /* TexFilter1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x1012000); /* TexFilter2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x1012000); /* TexFilter3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x105b8); /* TexFormat0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x105b8); /* TexFormat1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x105b8); /* TexFormat2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x105b8); /* TexFormat3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x80008); /* TexImageRect0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x80008); /* TexImageRect1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x80008); /* TexImageRect2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x80008); /* TexImageRect3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* TexOffset0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* TexOffset1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* TexOffset2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* TexOffset3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* TexPalette0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* TexPalette1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* TexPalette2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* TexPalette3 */
|
|
for (i = 0; i < 8; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x7ff0000); /* WindowClipX */
|
|
}
|
|
for (i = 0; i < 8; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x7ff0000); /* WindowClipY */
|
|
}
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* ZCompressOcclude */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* ZStencilClearValue */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x4b7fffff); /* ZClipMax */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* ZClipMin */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* ContextDmaA */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* ContextDmaB */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* ContextDmaVtxA */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* ContextDmaVtxB */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* ZOffsetBias */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* ZOffsetFactor */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* Eyevec0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* Eyevec1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* Eyevec2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* Shadow */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* FdData */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* FdSwatch */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* FdExtras */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* Emission0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* Emission1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* Emission2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* SceneAmb0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* SceneAmb1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* SceneAmb2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* ContextDmaGetState */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x1); /* BeginPatch0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BeginPatch1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x4000); /* BeginPatch2 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BeginPatch3 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BeginCurve */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x1); /* BeginTrans0 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* BeginTrans1 */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x40000); /* Csv0_D */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x10000); /* Csv0_C */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* Csv1_B */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* Csv1_A */
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0); /* CheopsOffset */
|
|
|
|
// The pipeline banks immediately follow the 3D register context.
|
|
for (i = 0; i < IDX_FMT_COUNT; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
for (i = 0; i < CAS0_COUNT; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
for (i = 0; i < CAS1_COUNT; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
for (i = 0; i < CAS2_COUNT; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
for (i = 0; i < ASSM_STATE_COUNT; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
for (i = 0; i < IDX_CACHE0_COUNT; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
for (i = 0; i < IDX_CACHE1_COUNT; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
for (i = 0; i < IDX_CACHE2_COUNT; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
for (i = 0; i < IDX_CACHE3_COUNT; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
for (i = 0; i < VTX_FILE0_COUNT; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
for (i = 0; i < VTX_FILE1_COUNT; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
for (i = 0; i < XL_P_COUNT; i += 4)
|
|
{
|
|
// Safe initial transform-program instruction, encoded for NV2A.
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x10700ff9);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x436086c);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0xc001b);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
DWORD cheopsCtxOffset = offset;
|
|
for (i = 0; i < XL_XFCTX_COUNT; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
DWORD zoserCtxAoffset = offset;
|
|
for (i = 0; i < XL_LTCTXA_COUNT; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
for (i = 0; i < XL_LTCTXB_COUNT; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
DWORD zoserC0Offset = offset;
|
|
for (i = 0; i < XL_LTC0_COUNT; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
DWORD zoserC1Offset = offset;
|
|
for (i = 0; i < XL_LTC1_COUNT; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
for (i = 0; i < XL_LTC2_COUNT; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
for (i = 0; i < XL_LTC3_COUNT; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
for (i = 0; i < XL_VAB_COUNT; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
for (i = 0; i < CRSTR_STIPP_COUNT; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
for (i = 0; i < FD_CTRL_COUNT; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
for (i = 0; i < ROP_REGS_COUNT; ++i)
|
|
{
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
}
|
|
|
|
// eye position.
|
|
offset = cheopsCtxOffset + 0xe0;
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x3f800000);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
|
|
// transform constants 0.
|
|
offset = cheopsCtxOffset + 0xf0;
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x40000000);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x3f800000);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x3f000000);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
|
|
// transform constants 1.
|
|
offset = cheopsCtxOffset + 0xf4;
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x40000000);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x3f800000);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0xbf800000);
|
|
|
|
// transform constants 2.
|
|
offset = cheopsCtxOffset + 0xf8;
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0xbf800000);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
|
|
// fog plane.
|
|
offset = cheopsCtxOffset + 0xe4;
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x3f800000);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
|
|
// transform constants 3.
|
|
offset = cheopsCtxOffset + 0xfc;
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
|
|
// lighting zero vector.
|
|
offset = zoserCtxAoffset + 0x58;
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
|
|
// lighting eye direction, 22-bit.
|
|
offset = zoserCtxAoffset + 0x40;
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0xfe000);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
|
|
// front ambient.
|
|
offset = zoserCtxAoffset + 0x44;
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
|
|
// color material.
|
|
offset = zoserCtxAoffset + 0x4c;
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
|
|
// linear fog.
|
|
offset = zoserCtxAoffset + 0x60;
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0x3f8);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset++ << 2), 0);
|
|
|
|
// Negative one and per-light range values use the 22-bit lighting format.
|
|
offset = zoserC0Offset + 1;
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset << 2), 0xbf800000UL >> 10);
|
|
offset = zoserC1Offset + 4;
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset << 2), 0x7149f2caUL >> 10);
|
|
offset = zoserC1Offset + 5;
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset << 2), 0x7149f2caUL >> 10);
|
|
offset = zoserC1Offset + 6;
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset << 2), 0x7149f2caUL >> 10);
|
|
offset = zoserC1Offset + 7;
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset << 2), 0x7149f2caUL >> 10);
|
|
offset = zoserC1Offset + 8;
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset << 2), 0x7149f2caUL >> 10);
|
|
offset = zoserC1Offset + 9;
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset << 2), 0x7149f2caUL >> 10);
|
|
offset = zoserC1Offset + 10;
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset << 2), 0x7149f2caUL >> 10);
|
|
offset = zoserC1Offset + 11;
|
|
REG_WR32(base, 0x700000 + (grCtxBuffer << 4) + (offset << 2), 0x7149f2caUL >> 10);
|
|
return;
|
|
}
|
|
}
|
|
|
|
namespace D3D
|
|
{
|
|
/* PLL sequencing is reconstructed against January machine code. The related
|
|
* pinned RXDK mphal source corroborates the PLL and refresh-period meanings.
|
|
* Assumes valid nonzero clock divisors in the device's DAC information. */
|
|
void CMiniport::HalDacProgramMClk(
|
|
void)
|
|
{
|
|
_HWREG *base = (_HWREG *)m_RegisterBase;
|
|
DWORD mNew = m_DacInfo.MPllM;
|
|
DWORD nNew = m_DacInfo.MPllN;
|
|
DWORD pNew = m_DacInfo.MPllP;
|
|
DWORD coeff = REG_RD32(base, NV_PRAMDAC_MPLL_COEFF);
|
|
DWORD newCoeff = (mNew & 255) | ((nNew & 255) << 8) | ((pNew & 7) << 16);
|
|
if (coeff != newCoeff)
|
|
{
|
|
DWORD mOld = coeff & 255;
|
|
DWORD nOld = (coeff >> 8) & 255;
|
|
DWORD pOld = (coeff >> 16) & 7;
|
|
if (pNew < pOld)
|
|
{
|
|
REG_WR32(base, NV_PRAMDAC_MPLL_COEFF,
|
|
(mNew & 255) | ((nNew & 255) << 8) | ((pOld & 7) << 16));
|
|
for (DWORD loops = 100; loops; --loops)
|
|
{
|
|
if (((REG_RD32(base, NV_PRAMDAC_PLL_TEST_COUNTER) >> 30) & 1) == 1)
|
|
{
|
|
if (((REG_RD32(base, NV_PRAMDAC_PLL_TEST_COUNTER) >> 30) & 1) == 1)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
KeStallExecutionProcessor(1000);
|
|
}
|
|
}
|
|
REG_WR32(base, NV_PRAMDAC_MPLL_COEFF, newCoeff);
|
|
KeStallExecutionProcessor(64 * 1000);
|
|
REG_WR32(base, NV_PFB_EMRS,
|
|
REG_RD32(base, NV_PFB_EMRS) | 0x100000);
|
|
REG_WR32(base, NV_PFB_MRS,
|
|
REG_RD32(base, NV_PFB_MRS) | 0x100);
|
|
|
|
DWORD oldMClk = nOld * m_GenInfo.CrystalFreq / (1UL << pOld) / mOld;
|
|
DWORD oldCyclesPerRefresh = ((REG_RD32(base, NV_PFB_TIMING2) >> 5) & 0x7ff) * 32;
|
|
DWORD oldPeriod = oldCyclesPerRefresh * 1024 / (oldMClk / 1000);
|
|
DWORD newCyclesPerRefresh = (m_DacInfo.MClk / 1000) * oldPeriod / 1024;
|
|
REG_WR32(base, NV_PFB_TIMING2,
|
|
(REG_RD32(base, NV_PFB_TIMING2) & ~0xffe0UL) |
|
|
(((newCyclesPerRefresh / 32) & 0x7ff) << 5));
|
|
}
|
|
return;
|
|
}
|
|
|
|
void CMiniport::HalDacProgramNVClk(
|
|
void)
|
|
{
|
|
_HWREG *base = (_HWREG *)m_RegisterBase;
|
|
DWORD mNew = m_DacInfo.NVPllM;
|
|
DWORD nNew = m_DacInfo.NVPllN;
|
|
DWORD pNew = m_DacInfo.NVPllP;
|
|
DWORD pOld = (REG_RD32(base, NV_PRAMDAC_NVPLL_COEFF) >> 16) & 7;
|
|
if (pNew < pOld)
|
|
{
|
|
REG_WR32(base, NV_PRAMDAC_NVPLL_COEFF,
|
|
(mNew & 255) | ((nNew & 255) << 8) | ((pOld & 7) << 16));
|
|
for (DWORD loops = 100; loops; --loops)
|
|
{
|
|
if (((REG_RD32(base, NV_PRAMDAC_PLL_TEST_COUNTER) >> 29) & 1) == 1)
|
|
{
|
|
if (((REG_RD32(base, NV_PRAMDAC_PLL_TEST_COUNTER) >> 29) & 1) == 1)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
KeStallExecutionProcessor(1000);
|
|
}
|
|
}
|
|
REG_WR32(base, NV_PRAMDAC_NVPLL_COEFF,
|
|
(mNew & 255) | ((nNew & 255) << 8) | ((pNew & 7) << 16));
|
|
DWORD setting = 4;
|
|
switch (m_DacInfo.NVClk)
|
|
{
|
|
case AGP_CLOCK_133_MHZ: setting = 15; break;
|
|
case AGP_CLOCK_126_MHZ: setting = 14; break;
|
|
case AGP_CLOCK_120_MHZ: setting = 13; break;
|
|
case AGP_CLOCK_113_MHZ: setting = 12; break;
|
|
case AGP_CLOCK_106_MHZ: setting = 11; break;
|
|
case AGP_CLOCK_100_MHZ: setting = 10; break;
|
|
case AGP_CLOCK_94_MHZ: setting = 9; break;
|
|
case AGP_CLOCK_87_MHZ: setting = 8; break;
|
|
case AGP_CLOCK_80_MHZ: setting = 7; break;
|
|
case AGP_CLOCK_73_MHZ: setting = 6; break;
|
|
case AGP_CLOCK_66_MHZ: setting = 5; break;
|
|
}
|
|
REG_WR32(base, NV_PBUS_DEBUG_3,
|
|
(REG_RD32(base, NV_PBUS_DEBUG_3) & ~0xf0UL) | ((setting & 15) << 4));
|
|
return;
|
|
}
|
|
|
|
void CMiniport::HalDacProgramPClk(
|
|
void)
|
|
{
|
|
_HWREG *base = (_HWREG *)m_RegisterBase;
|
|
DWORD mNew = m_DacInfo.VPllM;
|
|
DWORD nNew = m_DacInfo.VPllN;
|
|
DWORD pNew = m_DacInfo.VPllP;
|
|
DWORD pOld = (REG_RD32(base, NV_PRAMDAC_VPLL_COEFF) >> 16) & 7;
|
|
if (pNew < pOld)
|
|
{
|
|
REG_WR32(base, NV_PRAMDAC_VPLL_COEFF,
|
|
(mNew & 255) | ((nNew & 255) << 8) | ((pOld & 7) << 16));
|
|
for (DWORD loops = 100; loops; --loops)
|
|
{
|
|
// Pixel PLL requires two consecutive locked status samples.
|
|
if (((REG_RD32(base, NV_PRAMDAC_PLL_TEST_COUNTER) >> 31) & 1) == 1)
|
|
{
|
|
if (((REG_RD32(base, NV_PRAMDAC_PLL_TEST_COUNTER) >> 31) & 1) == 1)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
KeStallExecutionProcessor(1000);
|
|
}
|
|
}
|
|
REG_WR32(base, NV_PRAMDAC_VPLL_COEFF,
|
|
(mNew & 255) | ((nNew & 255) << 8) | ((pNew & 7) << 16));
|
|
return;
|
|
}
|
|
}
|