/* 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; } }