1c2c66affSColin Finck /* 2816149e0SStanislav Motylkov * PROJECT: ReactOS Xbox miniport video driver 3816149e0SStanislav Motylkov * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4816149e0SStanislav Motylkov * PURPOSE: Simple framebuffer driver for NVIDIA NV2A XGPU 5816149e0SStanislav Motylkov * COPYRIGHT: Copyright 2004 Gé van Geldorp 6816149e0SStanislav Motylkov * Copyright 2004 Filip Navara 7816149e0SStanislav Motylkov * Copyright 2019 Stanislav Motylkov (x86corez@gmail.com) 8c2c66affSColin Finck * 9c2c66affSColin Finck * TODO: 10c2c66affSColin Finck * - Check input parameters everywhere. 11c2c66affSColin Finck * - Call VideoPortVerifyAccessRanges to reserve the memory we're about 12c2c66affSColin Finck * to map. 13c2c66affSColin Finck */ 14c2c66affSColin Finck 15c2c66affSColin Finck /* INCLUDES *******************************************************************/ 16c2c66affSColin Finck 17c2c66affSColin Finck #include "xboxvmp.h" 18c2c66affSColin Finck 19*b54a38b8SStanislav Motylkov #include <debug.h> 20*b54a38b8SStanislav Motylkov #include <dpfilter.h> 21c2c66affSColin Finck 22c2c66affSColin Finck /* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/ 23c2c66affSColin Finck 24816149e0SStanislav Motylkov ULONG 25816149e0SStanislav Motylkov NTAPI 26816149e0SStanislav Motylkov DriverEntry( 27816149e0SStanislav Motylkov IN PVOID Context1, 28816149e0SStanislav Motylkov IN PVOID Context2) 29c2c66affSColin Finck { 30c2c66affSColin Finck VIDEO_HW_INITIALIZATION_DATA InitData; 31c2c66affSColin Finck 32c2c66affSColin Finck VideoPortZeroMemory(&InitData, sizeof(InitData)); 33c2c66affSColin Finck InitData.AdapterInterfaceType = PCIBus; 34c2c66affSColin Finck InitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA); 35c2c66affSColin Finck InitData.HwFindAdapter = XboxVmpFindAdapter; 36c2c66affSColin Finck InitData.HwInitialize = XboxVmpInitialize; 37c2c66affSColin Finck InitData.HwStartIO = XboxVmpStartIO; 38c2c66affSColin Finck InitData.HwResetHw = XboxVmpResetHw; 39c2c66affSColin Finck InitData.HwGetPowerState = XboxVmpGetPowerState; 40c2c66affSColin Finck InitData.HwSetPowerState = XboxVmpSetPowerState; 41c2c66affSColin Finck InitData.HwDeviceExtensionSize = sizeof(XBOXVMP_DEVICE_EXTENSION); 42c2c66affSColin Finck 43c2c66affSColin Finck return VideoPortInitialize(Context1, Context2, &InitData, NULL); 44c2c66affSColin Finck } 45c2c66affSColin Finck 46c2c66affSColin Finck /* 47c2c66affSColin Finck * XboxVmpFindAdapter 48c2c66affSColin Finck * 49c2c66affSColin Finck * Detects the Xbox Nvidia display adapter. 50c2c66affSColin Finck */ 51c2c66affSColin Finck 52816149e0SStanislav Motylkov VP_STATUS 53816149e0SStanislav Motylkov NTAPI 54c2c66affSColin Finck XboxVmpFindAdapter( 55c2c66affSColin Finck IN PVOID HwDeviceExtension, 56c2c66affSColin Finck IN PVOID HwContext, 57c2c66affSColin Finck IN PWSTR ArgumentString, 58c2c66affSColin Finck IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo, 59c2c66affSColin Finck OUT PUCHAR Again) 60c2c66affSColin Finck { 61c2c66affSColin Finck PXBOXVMP_DEVICE_EXTENSION XboxVmpDeviceExtension; 62c2c66affSColin Finck VIDEO_ACCESS_RANGE AccessRanges[3]; 63c2c66affSColin Finck VP_STATUS Status; 648c361450SStanislav Motylkov USHORT VendorId = 0x10DE; /* NVIDIA Corporation */ 658c361450SStanislav Motylkov USHORT DeviceId = 0x02A0; /* NV2A XGPU */ 66c2c66affSColin Finck 67*b54a38b8SStanislav Motylkov TRACE_(IHVVIDEO, "XboxVmpFindAdapter\n"); 68c2c66affSColin Finck 69c2c66affSColin Finck XboxVmpDeviceExtension = (PXBOXVMP_DEVICE_EXTENSION)HwDeviceExtension; 70816149e0SStanislav Motylkov 71c2c66affSColin Finck Status = VideoPortGetAccessRanges(HwDeviceExtension, 0, NULL, 3, AccessRanges, 728c361450SStanislav Motylkov &VendorId, &DeviceId, NULL); 73c2c66affSColin Finck 748c361450SStanislav Motylkov if (Status == NO_ERROR) 75c2c66affSColin Finck { 76c2c66affSColin Finck XboxVmpDeviceExtension->PhysControlStart = AccessRanges[0].RangeStart; 77c2c66affSColin Finck XboxVmpDeviceExtension->ControlLength = AccessRanges[0].RangeLength; 78c2c66affSColin Finck XboxVmpDeviceExtension->PhysFrameBufferStart = AccessRanges[1].RangeStart; 79c2c66affSColin Finck } 80c2c66affSColin Finck 81c2c66affSColin Finck return Status; 82c2c66affSColin Finck } 83c2c66affSColin Finck 84c2c66affSColin Finck /* 85c2c66affSColin Finck * XboxVmpInitialize 86c2c66affSColin Finck * 87c2c66affSColin Finck * Performs the first initialization of the adapter, after the HAL has given 88c2c66affSColin Finck * up control of the video hardware to the video port driver. 89c2c66affSColin Finck */ 90c2c66affSColin Finck 91816149e0SStanislav Motylkov BOOLEAN 92816149e0SStanislav Motylkov NTAPI 93816149e0SStanislav Motylkov XboxVmpInitialize( 94816149e0SStanislav Motylkov PVOID HwDeviceExtension) 95c2c66affSColin Finck { 96c2c66affSColin Finck PXBOXVMP_DEVICE_EXTENSION XboxVmpDeviceExtension; 97c2c66affSColin Finck ULONG inIoSpace = VIDEO_MEMORY_SPACE_MEMORY; 98c2c66affSColin Finck ULONG Length; 99c2c66affSColin Finck 100*b54a38b8SStanislav Motylkov TRACE_(IHVVIDEO, "XboxVmpInitialize\n"); 101c2c66affSColin Finck 102c2c66affSColin Finck XboxVmpDeviceExtension = (PXBOXVMP_DEVICE_EXTENSION)HwDeviceExtension; 103c2c66affSColin Finck 104c2c66affSColin Finck Length = XboxVmpDeviceExtension->ControlLength; 105c2c66affSColin Finck XboxVmpDeviceExtension->VirtControlStart = NULL; 106816149e0SStanislav Motylkov 107816149e0SStanislav Motylkov if (VideoPortMapMemory(HwDeviceExtension, 108c2c66affSColin Finck XboxVmpDeviceExtension->PhysControlStart, 109816149e0SStanislav Motylkov &Length, 110816149e0SStanislav Motylkov &inIoSpace, 111816149e0SStanislav Motylkov &XboxVmpDeviceExtension->VirtControlStart) != NO_ERROR) 112c2c66affSColin Finck { 113*b54a38b8SStanislav Motylkov ERR_(IHVVIDEO, "Failed to map control memory\n"); 114c2c66affSColin Finck return FALSE; 115c2c66affSColin Finck } 116816149e0SStanislav Motylkov 117*b54a38b8SStanislav Motylkov INFO_(IHVVIDEO, "Mapped 0x%x bytes of control mem at 0x%x to virt addr 0x%x\n", 118c2c66affSColin Finck XboxVmpDeviceExtension->ControlLength, 119c2c66affSColin Finck XboxVmpDeviceExtension->PhysControlStart.u.LowPart, 120c2c66affSColin Finck XboxVmpDeviceExtension->VirtControlStart); 121c2c66affSColin Finck 122c2c66affSColin Finck return TRUE; 123c2c66affSColin Finck } 124c2c66affSColin Finck 125c2c66affSColin Finck /* 126c2c66affSColin Finck * XboxVmpStartIO 127c2c66affSColin Finck * 128c2c66affSColin Finck * Processes the specified Video Request Packet. 129c2c66affSColin Finck */ 130c2c66affSColin Finck 131816149e0SStanislav Motylkov BOOLEAN 132816149e0SStanislav Motylkov NTAPI 133c2c66affSColin Finck XboxVmpStartIO( 134c2c66affSColin Finck PVOID HwDeviceExtension, 135c2c66affSColin Finck PVIDEO_REQUEST_PACKET RequestPacket) 136c2c66affSColin Finck { 137c2c66affSColin Finck BOOLEAN Result; 138c2c66affSColin Finck 139c2c66affSColin Finck RequestPacket->StatusBlock->Status = ERROR_INVALID_PARAMETER; 140c2c66affSColin Finck 141c2c66affSColin Finck switch (RequestPacket->IoControlCode) 142c2c66affSColin Finck { 143c2c66affSColin Finck case IOCTL_VIDEO_SET_CURRENT_MODE: 144816149e0SStanislav Motylkov { 145*b54a38b8SStanislav Motylkov TRACE_(IHVVIDEO, "XboxVmpStartIO IOCTL_VIDEO_SET_CURRENT_MODE\n"); 146816149e0SStanislav Motylkov 147c2c66affSColin Finck if (RequestPacket->InputBufferLength < sizeof(VIDEO_MODE)) 148c2c66affSColin Finck { 149c2c66affSColin Finck RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER; 150c2c66affSColin Finck return TRUE; 151c2c66affSColin Finck } 152816149e0SStanislav Motylkov 153c2c66affSColin Finck Result = XboxVmpSetCurrentMode( 154c2c66affSColin Finck (PXBOXVMP_DEVICE_EXTENSION)HwDeviceExtension, 155c2c66affSColin Finck (PVIDEO_MODE)RequestPacket->InputBuffer, 156c2c66affSColin Finck RequestPacket->StatusBlock); 157c2c66affSColin Finck break; 158816149e0SStanislav Motylkov } 159c2c66affSColin Finck 160c2c66affSColin Finck case IOCTL_VIDEO_RESET_DEVICE: 161816149e0SStanislav Motylkov { 162*b54a38b8SStanislav Motylkov TRACE_(IHVVIDEO, "XboxVmpStartIO IOCTL_VIDEO_RESET_DEVICE\n"); 163816149e0SStanislav Motylkov 164c2c66affSColin Finck Result = XboxVmpResetDevice( 165c2c66affSColin Finck (PXBOXVMP_DEVICE_EXTENSION)HwDeviceExtension, 166c2c66affSColin Finck RequestPacket->StatusBlock); 167c2c66affSColin Finck break; 168816149e0SStanislav Motylkov } 169c2c66affSColin Finck 170c2c66affSColin Finck case IOCTL_VIDEO_MAP_VIDEO_MEMORY: 171816149e0SStanislav Motylkov { 172*b54a38b8SStanislav Motylkov TRACE_(IHVVIDEO, "XboxVmpStartIO IOCTL_VIDEO_MAP_VIDEO_MEMORY\n"); 173816149e0SStanislav Motylkov 174c2c66affSColin Finck if (RequestPacket->OutputBufferLength < sizeof(VIDEO_MEMORY_INFORMATION) || 175c2c66affSColin Finck RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) 176c2c66affSColin Finck { 177c2c66affSColin Finck RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER; 178c2c66affSColin Finck return TRUE; 179c2c66affSColin Finck } 180816149e0SStanislav Motylkov 181c2c66affSColin Finck Result = XboxVmpMapVideoMemory( 182c2c66affSColin Finck (PXBOXVMP_DEVICE_EXTENSION)HwDeviceExtension, 183c2c66affSColin Finck (PVIDEO_MEMORY)RequestPacket->InputBuffer, 184c2c66affSColin Finck (PVIDEO_MEMORY_INFORMATION)RequestPacket->OutputBuffer, 185c2c66affSColin Finck RequestPacket->StatusBlock); 186c2c66affSColin Finck break; 187816149e0SStanislav Motylkov } 188c2c66affSColin Finck 189c2c66affSColin Finck case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY: 190816149e0SStanislav Motylkov { 191*b54a38b8SStanislav Motylkov TRACE_(IHVVIDEO, "XboxVmpStartIO IOCTL_VIDEO_UNMAP_VIDEO_MEMORY\n"); 192816149e0SStanislav Motylkov 193c2c66affSColin Finck if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) 194c2c66affSColin Finck { 195c2c66affSColin Finck RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER; 196c2c66affSColin Finck return TRUE; 197c2c66affSColin Finck } 198816149e0SStanislav Motylkov 199c2c66affSColin Finck Result = XboxVmpUnmapVideoMemory( 200c2c66affSColin Finck (PXBOXVMP_DEVICE_EXTENSION)HwDeviceExtension, 201c2c66affSColin Finck (PVIDEO_MEMORY)RequestPacket->InputBuffer, 202c2c66affSColin Finck RequestPacket->StatusBlock); 203c2c66affSColin Finck break; 204816149e0SStanislav Motylkov } 205c2c66affSColin Finck 206c2c66affSColin Finck case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES: 207816149e0SStanislav Motylkov { 208*b54a38b8SStanislav Motylkov TRACE_(IHVVIDEO, "XboxVmpStartIO IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES\n"); 209816149e0SStanislav Motylkov 210c2c66affSColin Finck if (RequestPacket->OutputBufferLength < sizeof(VIDEO_NUM_MODES)) 211c2c66affSColin Finck { 212c2c66affSColin Finck RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER; 213c2c66affSColin Finck return TRUE; 214c2c66affSColin Finck } 215816149e0SStanislav Motylkov 216c2c66affSColin Finck Result = XboxVmpQueryNumAvailModes( 217c2c66affSColin Finck (PXBOXVMP_DEVICE_EXTENSION)HwDeviceExtension, 218c2c66affSColin Finck (PVIDEO_NUM_MODES)RequestPacket->OutputBuffer, 219c2c66affSColin Finck RequestPacket->StatusBlock); 220c2c66affSColin Finck break; 221816149e0SStanislav Motylkov } 222c2c66affSColin Finck 223c2c66affSColin Finck case IOCTL_VIDEO_QUERY_AVAIL_MODES: 224816149e0SStanislav Motylkov { 225*b54a38b8SStanislav Motylkov TRACE_(IHVVIDEO, "XboxVmpStartIO IOCTL_VIDEO_QUERY_AVAIL_MODES\n"); 226816149e0SStanislav Motylkov 227c2c66affSColin Finck if (RequestPacket->OutputBufferLength < sizeof(VIDEO_MODE_INFORMATION)) 228c2c66affSColin Finck { 229c2c66affSColin Finck RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER; 230c2c66affSColin Finck return TRUE; 231c2c66affSColin Finck } 232816149e0SStanislav Motylkov 233c2c66affSColin Finck Result = XboxVmpQueryAvailModes( 234c2c66affSColin Finck (PXBOXVMP_DEVICE_EXTENSION)HwDeviceExtension, 235c2c66affSColin Finck (PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer, 236c2c66affSColin Finck RequestPacket->StatusBlock); 237c2c66affSColin Finck break; 238816149e0SStanislav Motylkov } 239c2c66affSColin Finck 240c2c66affSColin Finck case IOCTL_VIDEO_QUERY_CURRENT_MODE: 241816149e0SStanislav Motylkov { 242*b54a38b8SStanislav Motylkov TRACE_(IHVVIDEO, "XboxVmpStartIO IOCTL_VIDEO_QUERY_CURRENT_MODE\n"); 243816149e0SStanislav Motylkov 244c2c66affSColin Finck if (RequestPacket->OutputBufferLength < sizeof(VIDEO_MODE_INFORMATION)) 245c2c66affSColin Finck { 246c2c66affSColin Finck RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER; 247c2c66affSColin Finck return TRUE; 248c2c66affSColin Finck } 249816149e0SStanislav Motylkov 250c2c66affSColin Finck Result = XboxVmpQueryCurrentMode( 251c2c66affSColin Finck (PXBOXVMP_DEVICE_EXTENSION)HwDeviceExtension, 252c2c66affSColin Finck (PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer, 253c2c66affSColin Finck RequestPacket->StatusBlock); 254c2c66affSColin Finck break; 255816149e0SStanislav Motylkov } 256c2c66affSColin Finck 257c2c66affSColin Finck default: 258816149e0SStanislav Motylkov { 259*b54a38b8SStanislav Motylkov WARN_(IHVVIDEO, "XboxVmpStartIO 0x%x not implemented\n", RequestPacket->IoControlCode); 260816149e0SStanislav Motylkov 261c2c66affSColin Finck RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION; 262c2c66affSColin Finck return FALSE; 263c2c66affSColin Finck } 264816149e0SStanislav Motylkov } 265c2c66affSColin Finck 266c2c66affSColin Finck if (Result) 267c2c66affSColin Finck { 268c2c66affSColin Finck RequestPacket->StatusBlock->Status = NO_ERROR; 269c2c66affSColin Finck } 270c2c66affSColin Finck 271c2c66affSColin Finck return TRUE; 272c2c66affSColin Finck } 273c2c66affSColin Finck 274c2c66affSColin Finck /* 275c2c66affSColin Finck * XboxVmpResetHw 276c2c66affSColin Finck * 277c2c66affSColin Finck * This function is called to reset the hardware to a known state. 278c2c66affSColin Finck */ 279c2c66affSColin Finck 280816149e0SStanislav Motylkov BOOLEAN 281816149e0SStanislav Motylkov NTAPI 282c2c66affSColin Finck XboxVmpResetHw( 283c2c66affSColin Finck PVOID DeviceExtension, 284c2c66affSColin Finck ULONG Columns, 285c2c66affSColin Finck ULONG Rows) 286c2c66affSColin Finck { 287*b54a38b8SStanislav Motylkov TRACE_(IHVVIDEO, "XboxVmpResetHw\n"); 288c2c66affSColin Finck 289c2c66affSColin Finck if (!XboxVmpResetDevice((PXBOXVMP_DEVICE_EXTENSION)DeviceExtension, NULL)) 290c2c66affSColin Finck { 291c2c66affSColin Finck return FALSE; 292c2c66affSColin Finck } 293c2c66affSColin Finck 294c2c66affSColin Finck return TRUE; 295c2c66affSColin Finck } 296c2c66affSColin Finck 297c2c66affSColin Finck /* 298c2c66affSColin Finck * XboxVmpGetPowerState 299c2c66affSColin Finck * 300c2c66affSColin Finck * Queries whether the device can support the requested power state. 301c2c66affSColin Finck */ 302c2c66affSColin Finck 303816149e0SStanislav Motylkov VP_STATUS 304816149e0SStanislav Motylkov NTAPI 305c2c66affSColin Finck XboxVmpGetPowerState( 306c2c66affSColin Finck PVOID HwDeviceExtension, 307c2c66affSColin Finck ULONG HwId, 308c2c66affSColin Finck PVIDEO_POWER_MANAGEMENT VideoPowerControl) 309c2c66affSColin Finck { 310*b54a38b8SStanislav Motylkov ERR_(IHVVIDEO, "XboxVmpGetPowerState is not supported\n"); 311c2c66affSColin Finck 312c2c66affSColin Finck return ERROR_INVALID_FUNCTION; 313c2c66affSColin Finck } 314c2c66affSColin Finck 315c2c66affSColin Finck /* 316c2c66affSColin Finck * XboxVmpSetPowerState 317c2c66affSColin Finck * 318c2c66affSColin Finck * Sets the power state of the specified device 319c2c66affSColin Finck */ 320c2c66affSColin Finck 321816149e0SStanislav Motylkov VP_STATUS 322816149e0SStanislav Motylkov NTAPI 323c2c66affSColin Finck XboxVmpSetPowerState( 324c2c66affSColin Finck PVOID HwDeviceExtension, 325c2c66affSColin Finck ULONG HwId, 326c2c66affSColin Finck PVIDEO_POWER_MANAGEMENT VideoPowerControl) 327c2c66affSColin Finck { 328*b54a38b8SStanislav Motylkov ERR_(IHVVIDEO, "XboxVmpSetPowerState not supported\n"); 329c2c66affSColin Finck 330c2c66affSColin Finck return ERROR_INVALID_FUNCTION; 331c2c66affSColin Finck } 332c2c66affSColin Finck 333c2c66affSColin Finck /* 334c2c66affSColin Finck * VBESetCurrentMode 335c2c66affSColin Finck * 336c2c66affSColin Finck * Sets the adapter to the specified operating mode. 337c2c66affSColin Finck */ 338c2c66affSColin Finck 339816149e0SStanislav Motylkov BOOLEAN 340816149e0SStanislav Motylkov FASTCALL 341c2c66affSColin Finck XboxVmpSetCurrentMode( 342c2c66affSColin Finck PXBOXVMP_DEVICE_EXTENSION DeviceExtension, 343c2c66affSColin Finck PVIDEO_MODE RequestedMode, 344c2c66affSColin Finck PSTATUS_BLOCK StatusBlock) 345c2c66affSColin Finck { 346816149e0SStanislav Motylkov if (RequestedMode->RequestedMode != 0) 347c2c66affSColin Finck { 348c2c66affSColin Finck return FALSE; 349c2c66affSColin Finck } 350c2c66affSColin Finck 351c2c66affSColin Finck /* Nothing to do, really. We only support a single mode and we're already 352816149e0SStanislav Motylkov * in that mode 353816149e0SStanislav Motylkov */ 354c2c66affSColin Finck return TRUE; 355c2c66affSColin Finck } 356c2c66affSColin Finck 357c2c66affSColin Finck /* 358c2c66affSColin Finck * XboxVmpResetDevice 359c2c66affSColin Finck * 360c2c66affSColin Finck * Resets the video hardware to the default mode, to which it was initialized 361c2c66affSColin Finck * at system boot. 362c2c66affSColin Finck */ 363c2c66affSColin Finck 364816149e0SStanislav Motylkov BOOLEAN 365816149e0SStanislav Motylkov FASTCALL 366c2c66affSColin Finck XboxVmpResetDevice( 367c2c66affSColin Finck PXBOXVMP_DEVICE_EXTENSION DeviceExtension, 368c2c66affSColin Finck PSTATUS_BLOCK StatusBlock) 369c2c66affSColin Finck { 370c2c66affSColin Finck /* There is nothing to be done here */ 371c2c66affSColin Finck 372c2c66affSColin Finck return TRUE; 373c2c66affSColin Finck } 374c2c66affSColin Finck 375c2c66affSColin Finck /* 376c2c66affSColin Finck * XboxVmpMapVideoMemory 377c2c66affSColin Finck * 378c2c66affSColin Finck * Maps the video hardware frame buffer and video RAM into the virtual address 379c2c66affSColin Finck * space of the requestor. 380c2c66affSColin Finck */ 381c2c66affSColin Finck 382816149e0SStanislav Motylkov BOOLEAN 383816149e0SStanislav Motylkov FASTCALL 384c2c66affSColin Finck XboxVmpMapVideoMemory( 385c2c66affSColin Finck PXBOXVMP_DEVICE_EXTENSION DeviceExtension, 386c2c66affSColin Finck PVIDEO_MEMORY RequestedAddress, 387c2c66affSColin Finck PVIDEO_MEMORY_INFORMATION MapInformation, 388c2c66affSColin Finck PSTATUS_BLOCK StatusBlock) 389c2c66affSColin Finck { 390c2c66affSColin Finck PHYSICAL_ADDRESS FrameBuffer; 391c2c66affSColin Finck ULONG inIoSpace = VIDEO_MEMORY_SPACE_MEMORY; 392c2c66affSColin Finck SYSTEM_BASIC_INFORMATION BasicInfo; 393c2c66affSColin Finck ULONG Length; 394c2c66affSColin Finck 395c2c66affSColin Finck /* FIXME: this should probably be done differently, without native API */ 396c2c66affSColin Finck StatusBlock->Information = sizeof(VIDEO_MEMORY_INFORMATION); 397c2c66affSColin Finck 398c2c66affSColin Finck FrameBuffer.u.HighPart = 0; 399c2c66affSColin Finck if (ZwQuerySystemInformation(SystemBasicInformation, 400c2c66affSColin Finck (PVOID)&BasicInfo, 401c2c66affSColin Finck sizeof(SYSTEM_BASIC_INFORMATION), 402c2c66affSColin Finck &Length) == NO_ERROR) 403c2c66affSColin Finck { 404c2c66affSColin Finck FrameBuffer.u.LowPart = BasicInfo.HighestPhysicalPageNumber * PAGE_SIZE; 405c2c66affSColin Finck } 406c2c66affSColin Finck else 407c2c66affSColin Finck { 408*b54a38b8SStanislav Motylkov ERR_(IHVVIDEO, "ZwQueryBasicInformation failed, assuming 64MB total memory\n"); 409c2c66affSColin Finck FrameBuffer.u.LowPart = 60 * 1024 * 1024; 410c2c66affSColin Finck } 411c2c66affSColin Finck 412c2c66affSColin Finck FrameBuffer.QuadPart += DeviceExtension->PhysFrameBufferStart.QuadPart; 413c2c66affSColin Finck MapInformation->VideoRamBase = RequestedAddress->RequestedVirtualAddress; 414c2c66affSColin Finck MapInformation->VideoRamLength = 4 * 1024 * 1024; 415816149e0SStanislav Motylkov 416816149e0SStanislav Motylkov VideoPortMapMemory( 417816149e0SStanislav Motylkov DeviceExtension, 418816149e0SStanislav Motylkov FrameBuffer, 419816149e0SStanislav Motylkov &MapInformation->VideoRamLength, 420816149e0SStanislav Motylkov &inIoSpace, 421c2c66affSColin Finck &MapInformation->VideoRamBase); 422c2c66affSColin Finck 423c2c66affSColin Finck MapInformation->FrameBufferBase = MapInformation->VideoRamBase; 424c2c66affSColin Finck MapInformation->FrameBufferLength = MapInformation->VideoRamLength; 425c2c66affSColin Finck 426c2c66affSColin Finck /* Tell the nVidia controller about the framebuffer */ 427*b54a38b8SStanislav Motylkov *((PULONG)((char *)DeviceExtension->VirtControlStart + NV2A_CONTROL_FRAMEBUFFER_ADDRESS_OFFSET)) = FrameBuffer.u.LowPart; 428c2c66affSColin Finck 429*b54a38b8SStanislav Motylkov INFO_(IHVVIDEO, "Mapped 0x%x bytes of phys mem at 0x%lx to virt addr 0x%p\n", 430c2c66affSColin Finck MapInformation->VideoRamLength, FrameBuffer.u.LowPart, MapInformation->VideoRamBase); 431c2c66affSColin Finck 432c2c66affSColin Finck return TRUE; 433c2c66affSColin Finck } 434c2c66affSColin Finck 435c2c66affSColin Finck /* 436c2c66affSColin Finck * VBEUnmapVideoMemory 437c2c66affSColin Finck * 438c2c66affSColin Finck * Releases a mapping between the virtual address space and the adapter's 439c2c66affSColin Finck * frame buffer and video RAM. 440c2c66affSColin Finck */ 441c2c66affSColin Finck 442816149e0SStanislav Motylkov BOOLEAN 443816149e0SStanislav Motylkov FASTCALL 444c2c66affSColin Finck XboxVmpUnmapVideoMemory( 445c2c66affSColin Finck PXBOXVMP_DEVICE_EXTENSION DeviceExtension, 446c2c66affSColin Finck PVIDEO_MEMORY VideoMemory, 447c2c66affSColin Finck PSTATUS_BLOCK StatusBlock) 448c2c66affSColin Finck { 449816149e0SStanislav Motylkov VideoPortUnmapMemory( 450816149e0SStanislav Motylkov DeviceExtension, 451816149e0SStanislav Motylkov VideoMemory->RequestedVirtualAddress, 452c2c66affSColin Finck NULL); 453c2c66affSColin Finck 454c2c66affSColin Finck return TRUE; 455c2c66affSColin Finck } 456c2c66affSColin Finck 457c2c66affSColin Finck /* 458c2c66affSColin Finck * XboxVmpQueryNumAvailModes 459c2c66affSColin Finck * 460c2c66affSColin Finck * Returns the number of video modes supported by the adapter and the size 461c2c66affSColin Finck * in bytes of the video mode information, which can be used to allocate a 462c2c66affSColin Finck * buffer for an IOCTL_VIDEO_QUERY_AVAIL_MODES request. 463c2c66affSColin Finck */ 464c2c66affSColin Finck 465816149e0SStanislav Motylkov BOOLEAN 466816149e0SStanislav Motylkov FASTCALL 467c2c66affSColin Finck XboxVmpQueryNumAvailModes( 468c2c66affSColin Finck PXBOXVMP_DEVICE_EXTENSION DeviceExtension, 469c2c66affSColin Finck PVIDEO_NUM_MODES Modes, 470c2c66affSColin Finck PSTATUS_BLOCK StatusBlock) 471c2c66affSColin Finck { 472c2c66affSColin Finck Modes->NumModes = 1; 473c2c66affSColin Finck Modes->ModeInformationLength = sizeof(VIDEO_MODE_INFORMATION); 474c2c66affSColin Finck StatusBlock->Information = sizeof(VIDEO_NUM_MODES); 475c2c66affSColin Finck return TRUE; 476c2c66affSColin Finck } 477c2c66affSColin Finck 478816149e0SStanislav Motylkov static 479816149e0SStanislav Motylkov BOOLEAN 480816149e0SStanislav Motylkov ReadfromSMBus( 481816149e0SStanislav Motylkov UCHAR Address, 482816149e0SStanislav Motylkov UCHAR bRegister, 483816149e0SStanislav Motylkov UCHAR Size, 484816149e0SStanislav Motylkov ULONG *Data_to_smbus) 485c2c66affSColin Finck { 486c2c66affSColin Finck int nRetriesToLive = 50; 487c2c66affSColin Finck 488816149e0SStanislav Motylkov while ((VideoPortReadPortUshort((PUSHORT) (I2C_IO_BASE + 0)) & 0x0800) != 0) 489c2c66affSColin Finck { 490c2c66affSColin Finck ; /* Franz's spin while bus busy with any master traffic */ 491c2c66affSColin Finck } 492c2c66affSColin Finck 493816149e0SStanislav Motylkov while (nRetriesToLive-- != 0) 494c2c66affSColin Finck { 495c2c66affSColin Finck UCHAR b; 496c2c66affSColin Finck int temp; 497c2c66affSColin Finck 498c2c66affSColin Finck VideoPortWritePortUchar((PUCHAR) (I2C_IO_BASE + 4), (Address << 1) | 1); 499c2c66affSColin Finck VideoPortWritePortUchar((PUCHAR) (I2C_IO_BASE + 8), bRegister); 500c2c66affSColin Finck 501c2c66affSColin Finck temp = VideoPortReadPortUshort((PUSHORT) (I2C_IO_BASE + 0)); 502c2c66affSColin Finck VideoPortWritePortUshort((PUSHORT) (I2C_IO_BASE + 0), temp); /* clear down all preexisting errors */ 503c2c66affSColin Finck 504c2c66affSColin Finck switch (Size) 505c2c66affSColin Finck { 506c2c66affSColin Finck case 4: 507816149e0SStanislav Motylkov { 508c2c66affSColin Finck VideoPortWritePortUchar((PUCHAR) (I2C_IO_BASE + 2), 0x0d); /* DWORD modus ? */ 509c2c66affSColin Finck break; 510816149e0SStanislav Motylkov } 511816149e0SStanislav Motylkov 512c2c66affSColin Finck case 2: 513816149e0SStanislav Motylkov { 514c2c66affSColin Finck VideoPortWritePortUchar((PUCHAR) (I2C_IO_BASE + 2), 0x0b); /* WORD modus */ 515c2c66affSColin Finck break; 516816149e0SStanislav Motylkov } 517816149e0SStanislav Motylkov 518c2c66affSColin Finck default: 519816149e0SStanislav Motylkov { 520816149e0SStanislav Motylkov VideoPortWritePortUchar((PUCHAR) (I2C_IO_BASE + 2), 0x0a); /* BYTE */ 521816149e0SStanislav Motylkov } 522c2c66affSColin Finck } 523c2c66affSColin Finck 524c2c66affSColin Finck b = 0; 525c2c66affSColin Finck 526816149e0SStanislav Motylkov while ((b & 0x36) == 0) 527c2c66affSColin Finck { 528c2c66affSColin Finck b = VideoPortReadPortUchar((PUCHAR) (I2C_IO_BASE + 0)); 529c2c66affSColin Finck } 530c2c66affSColin Finck 531816149e0SStanislav Motylkov if ((b & 0x24) != 0) 532c2c66affSColin Finck { 533*b54a38b8SStanislav Motylkov ERR_(IHVVIDEO, "I2CTransmitByteGetReturn error %x\n", b); 534c2c66affSColin Finck } 535c2c66affSColin Finck 536816149e0SStanislav Motylkov if ((b & 0x10) == 0) 537c2c66affSColin Finck { 538*b54a38b8SStanislav Motylkov ERR_(IHVVIDEO, "I2CTransmitByteGetReturn no complete, retry\n"); 539c2c66affSColin Finck } 540c2c66affSColin Finck else 541c2c66affSColin Finck { 542c2c66affSColin Finck switch (Size) 543c2c66affSColin Finck { 544c2c66affSColin Finck case 4: 545816149e0SStanislav Motylkov { 546c2c66affSColin Finck VideoPortReadPortUchar((PUCHAR) (I2C_IO_BASE + 6)); 547c2c66affSColin Finck VideoPortReadPortUchar((PUCHAR) (I2C_IO_BASE + 9)); 548c2c66affSColin Finck VideoPortReadPortUchar((PUCHAR) (I2C_IO_BASE + 9)); 549c2c66affSColin Finck VideoPortReadPortUchar((PUCHAR) (I2C_IO_BASE + 9)); 550c2c66affSColin Finck VideoPortReadPortUchar((PUCHAR) (I2C_IO_BASE + 9)); 551c2c66affSColin Finck break; 552816149e0SStanislav Motylkov } 553816149e0SStanislav Motylkov 554c2c66affSColin Finck case 2: 555816149e0SStanislav Motylkov { 556c2c66affSColin Finck *Data_to_smbus = VideoPortReadPortUshort((PUSHORT) (I2C_IO_BASE + 6)); 557c2c66affSColin Finck break; 558c2c66affSColin Finck } 559c2c66affSColin Finck 560816149e0SStanislav Motylkov default: 561816149e0SStanislav Motylkov { 562816149e0SStanislav Motylkov *Data_to_smbus = VideoPortReadPortUchar((PUCHAR) (I2C_IO_BASE + 6)); 563816149e0SStanislav Motylkov } 564816149e0SStanislav Motylkov } 565c2c66affSColin Finck 566c2c66affSColin Finck return TRUE; 567c2c66affSColin Finck } 568c2c66affSColin Finck } 569c2c66affSColin Finck 570c2c66affSColin Finck return FALSE; 571c2c66affSColin Finck } 572c2c66affSColin Finck 573c2c66affSColin Finck 574816149e0SStanislav Motylkov static 575816149e0SStanislav Motylkov BOOLEAN 576816149e0SStanislav Motylkov I2CTransmitByteGetReturn( 577816149e0SStanislav Motylkov UCHAR bPicAddressI2cFormat, 578816149e0SStanislav Motylkov UCHAR bDataToWrite, 579816149e0SStanislav Motylkov ULONG *Return) 580c2c66affSColin Finck { 581c2c66affSColin Finck return ReadfromSMBus(bPicAddressI2cFormat, bDataToWrite, 1, Return); 582c2c66affSColin Finck } 583c2c66affSColin Finck 584c2c66affSColin Finck /* 585c2c66affSColin Finck * XboxVmpQueryAvailModes 586c2c66affSColin Finck * 587c2c66affSColin Finck * Returns information about each video mode supported by the adapter. 588c2c66affSColin Finck */ 589c2c66affSColin Finck 590816149e0SStanislav Motylkov BOOLEAN 591816149e0SStanislav Motylkov FASTCALL 592c2c66affSColin Finck XboxVmpQueryAvailModes( 593c2c66affSColin Finck PXBOXVMP_DEVICE_EXTENSION DeviceExtension, 594c2c66affSColin Finck PVIDEO_MODE_INFORMATION VideoMode, 595c2c66affSColin Finck PSTATUS_BLOCK StatusBlock) 596c2c66affSColin Finck { 597c2c66affSColin Finck return XboxVmpQueryCurrentMode(DeviceExtension, VideoMode, StatusBlock); 598c2c66affSColin Finck } 599c2c66affSColin Finck 600c2c66affSColin Finck /* 601c2c66affSColin Finck * VBEQueryCurrentMode 602c2c66affSColin Finck * 603c2c66affSColin Finck * Returns information about current video mode. 604c2c66affSColin Finck */ 605c2c66affSColin Finck 606816149e0SStanislav Motylkov BOOLEAN 607816149e0SStanislav Motylkov FASTCALL 608c2c66affSColin Finck XboxVmpQueryCurrentMode( 609c2c66affSColin Finck PXBOXVMP_DEVICE_EXTENSION DeviceExtension, 610c2c66affSColin Finck PVIDEO_MODE_INFORMATION VideoMode, 611c2c66affSColin Finck PSTATUS_BLOCK StatusBlock) 612c2c66affSColin Finck { 613c2c66affSColin Finck ULONG AvMode = 0; 614c2c66affSColin Finck 615c2c66affSColin Finck VideoMode->Length = sizeof(VIDEO_MODE_INFORMATION); 616c2c66affSColin Finck VideoMode->ModeIndex = 0; 617816149e0SStanislav Motylkov 618c2c66affSColin Finck if (I2CTransmitByteGetReturn(0x10, 0x04, &AvMode)) 619c2c66affSColin Finck { 620816149e0SStanislav Motylkov if (AvMode == 1) /* HDTV */ 621c2c66affSColin Finck { 622c2c66affSColin Finck VideoMode->VisScreenWidth = 720; 623c2c66affSColin Finck } 624c2c66affSColin Finck else 625c2c66affSColin Finck { 626c2c66affSColin Finck /* FIXME Other possible values of AvMode: 627c2c66affSColin Finck * 0 - AV_SCART_RGB 628c2c66affSColin Finck * 2 - AV_VGA_SOG 629c2c66affSColin Finck * 4 - AV_SVIDEO 630c2c66affSColin Finck * 6 - AV_COMPOSITE 631c2c66affSColin Finck * 7 - AV_VGA 632c2c66affSColin Finck * other AV_COMPOSITE 633c2c66affSColin Finck */ 634c2c66affSColin Finck VideoMode->VisScreenWidth = 640; 635c2c66affSColin Finck } 636c2c66affSColin Finck } 637c2c66affSColin Finck else 638c2c66affSColin Finck { 639c2c66affSColin Finck VideoMode->VisScreenWidth = 640; 640c2c66affSColin Finck } 641816149e0SStanislav Motylkov 642c2c66affSColin Finck VideoMode->VisScreenHeight = 480; 643c2c66affSColin Finck VideoMode->ScreenStride = VideoMode->VisScreenWidth * 4; 644c2c66affSColin Finck VideoMode->NumberOfPlanes = 1; 645c2c66affSColin Finck VideoMode->BitsPerPlane = 32; 646c2c66affSColin Finck VideoMode->Frequency = 1; 647c2c66affSColin Finck VideoMode->XMillimeter = 0; /* FIXME */ 648c2c66affSColin Finck VideoMode->YMillimeter = 0; /* FIXME */ 649c2c66affSColin Finck VideoMode->NumberRedBits = 8; 650c2c66affSColin Finck VideoMode->NumberGreenBits = 8; 651c2c66affSColin Finck VideoMode->NumberBlueBits = 8; 652816149e0SStanislav Motylkov VideoMode->RedMask = 0xFF0000; 653816149e0SStanislav Motylkov VideoMode->GreenMask = 0x00FF00; 654816149e0SStanislav Motylkov VideoMode->BlueMask = 0x0000FF; 655c2c66affSColin Finck VideoMode->VideoMemoryBitmapWidth = VideoMode->VisScreenWidth; 656c2c66affSColin Finck VideoMode->VideoMemoryBitmapHeight = VideoMode->VisScreenHeight; 657c2c66affSColin Finck VideoMode->AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | 658c2c66affSColin Finck VIDEO_MODE_NO_OFF_SCREEN; 659c2c66affSColin Finck VideoMode->DriverSpecificAttributeFlags = 0; 660c2c66affSColin Finck 661c2c66affSColin Finck StatusBlock->Information = sizeof(VIDEO_MODE_INFORMATION); 662c2c66affSColin Finck 663c2c66affSColin Finck return TRUE; 664c2c66affSColin Finck } 665c2c66affSColin Finck 666c2c66affSColin Finck /* EOF */ 667