2 * ReactOS Xbox miniport video driver
3 * Copyright (C) 2004 Gé van Geldorp
5 * Based on VBE miniport video driver
6 * Copyright (C) 2004 Filip Navara
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 * - Check input parameters everywhere.
24 * - Call VideoPortVerifyAccessRanges to reserve the memory we're about
28 /* INCLUDES *******************************************************************/
32 #define I2C_IO_BASE 0xc000
34 #define CONTROL_FRAMEBUFFER_ADDRESS_OFFSET 0x600800
36 /* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/
39 DriverEntry(IN PVOID Context1
, IN PVOID Context2
)
41 VIDEO_HW_INITIALIZATION_DATA InitData
;
43 VideoPortZeroMemory(&InitData
, sizeof(InitData
));
44 InitData
.AdapterInterfaceType
= PCIBus
;
45 InitData
.HwInitDataSize
= sizeof(VIDEO_HW_INITIALIZATION_DATA
);
46 InitData
.HwFindAdapter
= XboxVmpFindAdapter
;
47 InitData
.HwInitialize
= XboxVmpInitialize
;
48 InitData
.HwStartIO
= XboxVmpStartIO
;
49 InitData
.HwResetHw
= XboxVmpResetHw
;
50 InitData
.HwGetPowerState
= XboxVmpGetPowerState
;
51 InitData
.HwSetPowerState
= XboxVmpSetPowerState
;
52 InitData
.HwDeviceExtensionSize
= sizeof(XBOXVMP_DEVICE_EXTENSION
);
54 return VideoPortInitialize(Context1
, Context2
, &InitData
, NULL
);
60 * Detects the Xbox Nvidia display adapter.
65 IN PVOID HwDeviceExtension
,
67 IN PWSTR ArgumentString
,
68 IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo
,
71 PXBOXVMP_DEVICE_EXTENSION XboxVmpDeviceExtension
;
72 VIDEO_ACCESS_RANGE AccessRanges
[3];
74 USHORT VendorId
= 0x10DE; /* NVIDIA Corporation */
75 USHORT DeviceId
= 0x02A0; /* NV2A XGPU */
77 VideoPortDebugPrint(Trace
, "XboxVmpFindAdapter\n");
79 XboxVmpDeviceExtension
= (PXBOXVMP_DEVICE_EXTENSION
) HwDeviceExtension
;
80 Status
= VideoPortGetAccessRanges(HwDeviceExtension
, 0, NULL
, 3, AccessRanges
,
81 &VendorId
, &DeviceId
, NULL
);
83 if (Status
== NO_ERROR
)
85 XboxVmpDeviceExtension
->PhysControlStart
= AccessRanges
[0].RangeStart
;
86 XboxVmpDeviceExtension
->ControlLength
= AccessRanges
[0].RangeLength
;
87 XboxVmpDeviceExtension
->PhysFrameBufferStart
= AccessRanges
[1].RangeStart
;
96 * Performs the first initialization of the adapter, after the HAL has given
97 * up control of the video hardware to the video port driver.
101 XboxVmpInitialize(PVOID HwDeviceExtension
)
103 PXBOXVMP_DEVICE_EXTENSION XboxVmpDeviceExtension
;
104 ULONG inIoSpace
= VIDEO_MEMORY_SPACE_MEMORY
;
107 VideoPortDebugPrint(Trace
, "XboxVmpInitialize\n");
109 XboxVmpDeviceExtension
= (PXBOXVMP_DEVICE_EXTENSION
) HwDeviceExtension
;
111 Length
= XboxVmpDeviceExtension
->ControlLength
;
112 XboxVmpDeviceExtension
->VirtControlStart
= NULL
;
113 if (NO_ERROR
!= VideoPortMapMemory(HwDeviceExtension
,
114 XboxVmpDeviceExtension
->PhysControlStart
,
116 &XboxVmpDeviceExtension
->VirtControlStart
))
118 VideoPortDebugPrint(Error
, "Failed to map control memory\n");
121 VideoPortDebugPrint(Info
, "Mapped 0x%x bytes of control mem at 0x%x to virt addr 0x%x\n",
122 XboxVmpDeviceExtension
->ControlLength
,
123 XboxVmpDeviceExtension
->PhysControlStart
.u
.LowPart
,
124 XboxVmpDeviceExtension
->VirtControlStart
);
132 * Processes the specified Video Request Packet.
137 PVOID HwDeviceExtension
,
138 PVIDEO_REQUEST_PACKET RequestPacket
)
142 RequestPacket
->StatusBlock
->Status
= ERROR_INVALID_PARAMETER
;
144 switch (RequestPacket
->IoControlCode
)
146 case IOCTL_VIDEO_SET_CURRENT_MODE
:
147 VideoPortDebugPrint(Trace
, "XboxVmpStartIO IOCTL_VIDEO_SET_CURRENT_MODE\n");
148 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MODE
))
150 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
153 Result
= XboxVmpSetCurrentMode(
154 (PXBOXVMP_DEVICE_EXTENSION
)HwDeviceExtension
,
155 (PVIDEO_MODE
)RequestPacket
->InputBuffer
,
156 RequestPacket
->StatusBlock
);
159 case IOCTL_VIDEO_RESET_DEVICE
:
160 VideoPortDebugPrint(Trace
, "XboxVmpStartIO IOCTL_VIDEO_RESET_DEVICE\n");
161 Result
= XboxVmpResetDevice(
162 (PXBOXVMP_DEVICE_EXTENSION
)HwDeviceExtension
,
163 RequestPacket
->StatusBlock
);
166 case IOCTL_VIDEO_MAP_VIDEO_MEMORY
:
167 VideoPortDebugPrint(Trace
, "XboxVmpStartIO IOCTL_VIDEO_MAP_VIDEO_MEMORY\n");
168 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MEMORY_INFORMATION
) ||
169 RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
171 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
174 Result
= XboxVmpMapVideoMemory(
175 (PXBOXVMP_DEVICE_EXTENSION
)HwDeviceExtension
,
176 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
177 (PVIDEO_MEMORY_INFORMATION
)RequestPacket
->OutputBuffer
,
178 RequestPacket
->StatusBlock
);
181 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY
:
182 VideoPortDebugPrint(Trace
, "XboxVmpStartIO IOCTL_VIDEO_UNMAP_VIDEO_MEMORY\n");
183 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
185 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
188 Result
= XboxVmpUnmapVideoMemory(
189 (PXBOXVMP_DEVICE_EXTENSION
)HwDeviceExtension
,
190 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
191 RequestPacket
->StatusBlock
);
194 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES
:
195 VideoPortDebugPrint(Trace
, "XboxVmpStartIO IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES\n");
196 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_NUM_MODES
))
198 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
201 Result
= XboxVmpQueryNumAvailModes(
202 (PXBOXVMP_DEVICE_EXTENSION
)HwDeviceExtension
,
203 (PVIDEO_NUM_MODES
)RequestPacket
->OutputBuffer
,
204 RequestPacket
->StatusBlock
);
207 case IOCTL_VIDEO_QUERY_AVAIL_MODES
:
208 VideoPortDebugPrint(Trace
, "XboxVmpStartIO IOCTL_VIDEO_QUERY_AVAIL_MODES\n");
209 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MODE_INFORMATION
))
211 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
214 Result
= XboxVmpQueryAvailModes(
215 (PXBOXVMP_DEVICE_EXTENSION
)HwDeviceExtension
,
216 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
217 RequestPacket
->StatusBlock
);
220 case IOCTL_VIDEO_QUERY_CURRENT_MODE
:
221 VideoPortDebugPrint(Trace
, "XboxVmpStartIO IOCTL_VIDEO_QUERY_CURRENT_MODE\n");
222 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MODE_INFORMATION
))
224 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
227 Result
= XboxVmpQueryCurrentMode(
228 (PXBOXVMP_DEVICE_EXTENSION
)HwDeviceExtension
,
229 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
230 RequestPacket
->StatusBlock
);
234 VideoPortDebugPrint(Warn
, "XboxVmpStartIO 0x%x not implemented\n");
235 RequestPacket
->StatusBlock
->Status
= ERROR_INVALID_FUNCTION
;
241 RequestPacket
->StatusBlock
->Status
= NO_ERROR
;
250 * This function is called to reset the hardware to a known state.
255 PVOID DeviceExtension
,
259 VideoPortDebugPrint(Trace
, "XboxVmpResetHw\n");
261 if (! XboxVmpResetDevice((PXBOXVMP_DEVICE_EXTENSION
) DeviceExtension
, NULL
))
270 * XboxVmpGetPowerState
272 * Queries whether the device can support the requested power state.
276 XboxVmpGetPowerState(
277 PVOID HwDeviceExtension
,
279 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
281 VideoPortDebugPrint(Error
, "XboxVmpGetPowerState is not supported\n");
283 return ERROR_INVALID_FUNCTION
;
287 * XboxVmpSetPowerState
289 * Sets the power state of the specified device
293 XboxVmpSetPowerState(
294 PVOID HwDeviceExtension
,
296 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
298 VideoPortDebugPrint(Error
, "XboxVmpSetPowerState not supported\n");
300 return ERROR_INVALID_FUNCTION
;
306 * Sets the adapter to the specified operating mode.
310 XboxVmpSetCurrentMode(
311 PXBOXVMP_DEVICE_EXTENSION DeviceExtension
,
312 PVIDEO_MODE RequestedMode
,
313 PSTATUS_BLOCK StatusBlock
)
315 if (0 != RequestedMode
->RequestedMode
)
320 /* Nothing to do, really. We only support a single mode and we're already
328 * Resets the video hardware to the default mode, to which it was initialized
334 PXBOXVMP_DEVICE_EXTENSION DeviceExtension
,
335 PSTATUS_BLOCK StatusBlock
)
337 /* There is nothing to be done here */
343 * XboxVmpMapVideoMemory
345 * Maps the video hardware frame buffer and video RAM into the virtual address
346 * space of the requestor.
350 XboxVmpMapVideoMemory(
351 PXBOXVMP_DEVICE_EXTENSION DeviceExtension
,
352 PVIDEO_MEMORY RequestedAddress
,
353 PVIDEO_MEMORY_INFORMATION MapInformation
,
354 PSTATUS_BLOCK StatusBlock
)
356 PHYSICAL_ADDRESS FrameBuffer
;
357 ULONG inIoSpace
= VIDEO_MEMORY_SPACE_MEMORY
;
358 SYSTEM_BASIC_INFORMATION BasicInfo
;
361 /* FIXME: this should probably be done differently, without native API */
362 StatusBlock
->Information
= sizeof(VIDEO_MEMORY_INFORMATION
);
364 FrameBuffer
.u
.HighPart
= 0;
365 if (ZwQuerySystemInformation(SystemBasicInformation
,
367 sizeof(SYSTEM_BASIC_INFORMATION
),
368 &Length
) == NO_ERROR
)
370 FrameBuffer
.u
.LowPart
= BasicInfo
.HighestPhysicalPageNumber
* PAGE_SIZE
;
374 VideoPortDebugPrint(Error
, "ZwQueryBasicInformation failed, assuming 64MB total memory\n");
375 FrameBuffer
.u
.LowPart
= 60 * 1024 * 1024;
378 FrameBuffer
.QuadPart
+= DeviceExtension
->PhysFrameBufferStart
.QuadPart
;
379 MapInformation
->VideoRamBase
= RequestedAddress
->RequestedVirtualAddress
;
380 MapInformation
->VideoRamLength
= 4 * 1024 * 1024;
381 VideoPortMapMemory(DeviceExtension
, FrameBuffer
,
382 &MapInformation
->VideoRamLength
, &inIoSpace
,
383 &MapInformation
->VideoRamBase
);
385 MapInformation
->FrameBufferBase
= MapInformation
->VideoRamBase
;
386 MapInformation
->FrameBufferLength
= MapInformation
->VideoRamLength
;
388 /* Tell the nVidia controller about the framebuffer */
389 *((PULONG
)((char *) DeviceExtension
->VirtControlStart
+ CONTROL_FRAMEBUFFER_ADDRESS_OFFSET
)) = FrameBuffer
.u
.LowPart
;
391 VideoPortDebugPrint(Info
, "Mapped 0x%x bytes of phys mem at 0x%lx to virt addr 0x%p\n",
392 MapInformation
->VideoRamLength
, FrameBuffer
.u
.LowPart
, MapInformation
->VideoRamBase
);
398 * VBEUnmapVideoMemory
400 * Releases a mapping between the virtual address space and the adapter's
401 * frame buffer and video RAM.
405 XboxVmpUnmapVideoMemory(
406 PXBOXVMP_DEVICE_EXTENSION DeviceExtension
,
407 PVIDEO_MEMORY VideoMemory
,
408 PSTATUS_BLOCK StatusBlock
)
410 VideoPortUnmapMemory(DeviceExtension
, VideoMemory
->RequestedVirtualAddress
,
417 * XboxVmpQueryNumAvailModes
419 * Returns the number of video modes supported by the adapter and the size
420 * in bytes of the video mode information, which can be used to allocate a
421 * buffer for an IOCTL_VIDEO_QUERY_AVAIL_MODES request.
425 XboxVmpQueryNumAvailModes(
426 PXBOXVMP_DEVICE_EXTENSION DeviceExtension
,
427 PVIDEO_NUM_MODES Modes
,
428 PSTATUS_BLOCK StatusBlock
)
431 Modes
->ModeInformationLength
= sizeof(VIDEO_MODE_INFORMATION
);
432 StatusBlock
->Information
= sizeof(VIDEO_NUM_MODES
);
437 ReadfromSMBus(UCHAR Address
, UCHAR bRegister
, UCHAR Size
, ULONG
*Data_to_smbus
)
439 int nRetriesToLive
=50;
441 while (0 != (VideoPortReadPortUshort((PUSHORT
) (I2C_IO_BASE
+ 0)) & 0x0800))
443 ; /* Franz's spin while bus busy with any master traffic */
446 while (0 != nRetriesToLive
--)
451 VideoPortWritePortUchar((PUCHAR
) (I2C_IO_BASE
+ 4), (Address
<< 1) | 1);
452 VideoPortWritePortUchar((PUCHAR
) (I2C_IO_BASE
+ 8), bRegister
);
454 temp
= VideoPortReadPortUshort((PUSHORT
) (I2C_IO_BASE
+ 0));
455 VideoPortWritePortUshort((PUSHORT
) (I2C_IO_BASE
+ 0), temp
); /* clear down all preexisting errors */
460 VideoPortWritePortUchar((PUCHAR
) (I2C_IO_BASE
+ 2), 0x0d); /* DWORD modus ? */
463 VideoPortWritePortUchar((PUCHAR
) (I2C_IO_BASE
+ 2), 0x0b); /* WORD modus */
466 VideoPortWritePortUchar((PUCHAR
) (I2C_IO_BASE
+ 2), 0x0a); // BYTE
472 while (0 == (b
& 0x36))
474 b
= VideoPortReadPortUchar((PUCHAR
) (I2C_IO_BASE
+ 0));
479 /* printf("I2CTransmitByteGetReturn error %x\n", b); */
484 /* printf("I2CTransmitByteGetReturn no complete, retry\n"); */
491 VideoPortReadPortUchar((PUCHAR
) (I2C_IO_BASE
+ 6));
492 VideoPortReadPortUchar((PUCHAR
) (I2C_IO_BASE
+ 9));
493 VideoPortReadPortUchar((PUCHAR
) (I2C_IO_BASE
+ 9));
494 VideoPortReadPortUchar((PUCHAR
) (I2C_IO_BASE
+ 9));
495 VideoPortReadPortUchar((PUCHAR
) (I2C_IO_BASE
+ 9));
498 *Data_to_smbus
= VideoPortReadPortUshort((PUSHORT
) (I2C_IO_BASE
+ 6));
501 *Data_to_smbus
= VideoPortReadPortUchar((PUCHAR
) (I2C_IO_BASE
+ 6));
515 I2CTransmitByteGetReturn(UCHAR bPicAddressI2cFormat
, UCHAR bDataToWrite
, ULONG
*Return
)
517 return ReadfromSMBus(bPicAddressI2cFormat
, bDataToWrite
, 1, Return
);
521 * XboxVmpQueryAvailModes
523 * Returns information about each video mode supported by the adapter.
527 XboxVmpQueryAvailModes(
528 PXBOXVMP_DEVICE_EXTENSION DeviceExtension
,
529 PVIDEO_MODE_INFORMATION VideoMode
,
530 PSTATUS_BLOCK StatusBlock
)
532 return XboxVmpQueryCurrentMode(DeviceExtension
, VideoMode
, StatusBlock
);
536 * VBEQueryCurrentMode
538 * Returns information about current video mode.
542 XboxVmpQueryCurrentMode(
543 PXBOXVMP_DEVICE_EXTENSION DeviceExtension
,
544 PVIDEO_MODE_INFORMATION VideoMode
,
545 PSTATUS_BLOCK StatusBlock
)
549 VideoMode
->Length
= sizeof(VIDEO_MODE_INFORMATION
);
550 VideoMode
->ModeIndex
= 0;
551 if (I2CTransmitByteGetReturn(0x10, 0x04, &AvMode
))
553 if (1 == AvMode
) /* HDTV */
555 VideoMode
->VisScreenWidth
= 720;
559 /* FIXME Other possible values of AvMode:
567 VideoMode
->VisScreenWidth
= 640;
572 VideoMode
->VisScreenWidth
= 640;
574 VideoMode
->VisScreenHeight
= 480;
575 VideoMode
->ScreenStride
= VideoMode
->VisScreenWidth
* 4;
576 VideoMode
->NumberOfPlanes
= 1;
577 VideoMode
->BitsPerPlane
= 32;
578 VideoMode
->Frequency
= 1;
579 VideoMode
->XMillimeter
= 0; /* FIXME */
580 VideoMode
->YMillimeter
= 0; /* FIXME */
581 VideoMode
->NumberRedBits
= 8;
582 VideoMode
->NumberGreenBits
= 8;
583 VideoMode
->NumberBlueBits
= 8;
584 VideoMode
->RedMask
= 0xff0000;
585 VideoMode
->GreenMask
= 0x00ff00;
586 VideoMode
->BlueMask
= 0x0000ff;
587 VideoMode
->VideoMemoryBitmapWidth
= VideoMode
->VisScreenWidth
;
588 VideoMode
->VideoMemoryBitmapHeight
= VideoMode
->VisScreenHeight
;
589 VideoMode
->AttributeFlags
= VIDEO_MODE_GRAPHICS
| VIDEO_MODE_COLOR
|
590 VIDEO_MODE_NO_OFF_SCREEN
;
591 VideoMode
->DriverSpecificAttributeFlags
= 0;
593 StatusBlock
->Information
= sizeof(VIDEO_MODE_INFORMATION
);