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];
75 VideoPortDebugPrint(Trace
, "XboxVmpFindAdapter\n");
77 XboxVmpDeviceExtension
= (PXBOXVMP_DEVICE_EXTENSION
) HwDeviceExtension
;
78 Status
= VideoPortGetAccessRanges(HwDeviceExtension
, 0, NULL
, 3, AccessRanges
,
81 if (NO_ERROR
== Status
)
83 XboxVmpDeviceExtension
->PhysControlStart
= AccessRanges
[0].RangeStart
;
84 XboxVmpDeviceExtension
->ControlLength
= AccessRanges
[0].RangeLength
;
85 XboxVmpDeviceExtension
->PhysFrameBufferStart
= AccessRanges
[1].RangeStart
;
94 * Performs the first initialization of the adapter, after the HAL has given
95 * up control of the video hardware to the video port driver.
99 XboxVmpInitialize(PVOID HwDeviceExtension
)
101 PXBOXVMP_DEVICE_EXTENSION XboxVmpDeviceExtension
;
102 ULONG inIoSpace
= VIDEO_MEMORY_SPACE_MEMORY
;
105 VideoPortDebugPrint(Trace
, "XboxVmpInitialize\n");
107 XboxVmpDeviceExtension
= (PXBOXVMP_DEVICE_EXTENSION
) HwDeviceExtension
;
109 Length
= XboxVmpDeviceExtension
->ControlLength
;
110 XboxVmpDeviceExtension
->VirtControlStart
= NULL
;
111 if (NO_ERROR
!= VideoPortMapMemory(HwDeviceExtension
,
112 XboxVmpDeviceExtension
->PhysControlStart
,
114 &XboxVmpDeviceExtension
->VirtControlStart
))
116 VideoPortDebugPrint(Error
, "Failed to map control memory\n");
119 VideoPortDebugPrint(Info
, "Mapped 0x%x bytes of control mem at 0x%x to virt addr 0x%x\n",
120 XboxVmpDeviceExtension
->ControlLength
,
121 XboxVmpDeviceExtension
->PhysControlStart
.u
.LowPart
,
122 XboxVmpDeviceExtension
->VirtControlStart
);
130 * Processes the specified Video Request Packet.
135 PVOID HwDeviceExtension
,
136 PVIDEO_REQUEST_PACKET RequestPacket
)
140 RequestPacket
->StatusBlock
->Status
= ERROR_INVALID_PARAMETER
;
142 switch (RequestPacket
->IoControlCode
)
144 case IOCTL_VIDEO_SET_CURRENT_MODE
:
145 VideoPortDebugPrint(Trace
, "XboxVmpStartIO IOCTL_VIDEO_SET_CURRENT_MODE\n");
146 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MODE
))
148 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
151 Result
= XboxVmpSetCurrentMode(
152 (PXBOXVMP_DEVICE_EXTENSION
)HwDeviceExtension
,
153 (PVIDEO_MODE
)RequestPacket
->InputBuffer
,
154 RequestPacket
->StatusBlock
);
157 case IOCTL_VIDEO_RESET_DEVICE
:
158 VideoPortDebugPrint(Trace
, "XboxVmpStartIO IOCTL_VIDEO_RESET_DEVICE\n");
159 Result
= XboxVmpResetDevice(
160 (PXBOXVMP_DEVICE_EXTENSION
)HwDeviceExtension
,
161 RequestPacket
->StatusBlock
);
164 case IOCTL_VIDEO_MAP_VIDEO_MEMORY
:
165 VideoPortDebugPrint(Trace
, "XboxVmpStartIO IOCTL_VIDEO_MAP_VIDEO_MEMORY\n");
166 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MEMORY_INFORMATION
) ||
167 RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
169 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
172 Result
= XboxVmpMapVideoMemory(
173 (PXBOXVMP_DEVICE_EXTENSION
)HwDeviceExtension
,
174 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
175 (PVIDEO_MEMORY_INFORMATION
)RequestPacket
->OutputBuffer
,
176 RequestPacket
->StatusBlock
);
179 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY
:
180 VideoPortDebugPrint(Trace
, "XboxVmpStartIO IOCTL_VIDEO_UNMAP_VIDEO_MEMORY\n");
181 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
183 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
186 Result
= XboxVmpUnmapVideoMemory(
187 (PXBOXVMP_DEVICE_EXTENSION
)HwDeviceExtension
,
188 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
189 RequestPacket
->StatusBlock
);
192 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES
:
193 VideoPortDebugPrint(Trace
, "XboxVmpStartIO IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES\n");
194 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_NUM_MODES
))
196 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
199 Result
= XboxVmpQueryNumAvailModes(
200 (PXBOXVMP_DEVICE_EXTENSION
)HwDeviceExtension
,
201 (PVIDEO_NUM_MODES
)RequestPacket
->OutputBuffer
,
202 RequestPacket
->StatusBlock
);
205 case IOCTL_VIDEO_QUERY_AVAIL_MODES
:
206 VideoPortDebugPrint(Trace
, "XboxVmpStartIO IOCTL_VIDEO_QUERY_AVAIL_MODES\n");
207 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MODE_INFORMATION
))
209 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
212 Result
= XboxVmpQueryAvailModes(
213 (PXBOXVMP_DEVICE_EXTENSION
)HwDeviceExtension
,
214 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
215 RequestPacket
->StatusBlock
);
218 case IOCTL_VIDEO_QUERY_CURRENT_MODE
:
219 VideoPortDebugPrint(Trace
, "XboxVmpStartIO IOCTL_VIDEO_QUERY_CURRENT_MODE\n");
220 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MODE_INFORMATION
))
222 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
225 Result
= XboxVmpQueryCurrentMode(
226 (PXBOXVMP_DEVICE_EXTENSION
)HwDeviceExtension
,
227 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
228 RequestPacket
->StatusBlock
);
232 VideoPortDebugPrint(Warn
, "XboxVmpStartIO 0x%x not implemented\n");
233 RequestPacket
->StatusBlock
->Status
= ERROR_INVALID_FUNCTION
;
239 RequestPacket
->StatusBlock
->Status
= NO_ERROR
;
248 * This function is called to reset the hardware to a known state.
253 PVOID DeviceExtension
,
257 VideoPortDebugPrint(Trace
, "XboxVmpResetHw\n");
259 if (! XboxVmpResetDevice((PXBOXVMP_DEVICE_EXTENSION
) DeviceExtension
, NULL
))
268 * XboxVmpGetPowerState
270 * Queries whether the device can support the requested power state.
274 XboxVmpGetPowerState(
275 PVOID HwDeviceExtension
,
277 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
279 VideoPortDebugPrint(Error
, "XboxVmpGetPowerState is not supported\n");
281 return ERROR_INVALID_FUNCTION
;
285 * XboxVmpSetPowerState
287 * Sets the power state of the specified device
291 XboxVmpSetPowerState(
292 PVOID HwDeviceExtension
,
294 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
296 VideoPortDebugPrint(Error
, "XboxVmpSetPowerState not supported\n");
298 return ERROR_INVALID_FUNCTION
;
304 * Sets the adapter to the specified operating mode.
308 XboxVmpSetCurrentMode(
309 PXBOXVMP_DEVICE_EXTENSION DeviceExtension
,
310 PVIDEO_MODE RequestedMode
,
311 PSTATUS_BLOCK StatusBlock
)
313 if (0 != RequestedMode
->RequestedMode
)
318 /* Nothing to do, really. We only support a single mode and we're already
326 * Resets the video hardware to the default mode, to which it was initialized
332 PXBOXVMP_DEVICE_EXTENSION DeviceExtension
,
333 PSTATUS_BLOCK StatusBlock
)
335 /* There is nothing to be done here */
341 * XboxVmpMapVideoMemory
343 * Maps the video hardware frame buffer and video RAM into the virtual address
344 * space of the requestor.
348 XboxVmpMapVideoMemory(
349 PXBOXVMP_DEVICE_EXTENSION DeviceExtension
,
350 PVIDEO_MEMORY RequestedAddress
,
351 PVIDEO_MEMORY_INFORMATION MapInformation
,
352 PSTATUS_BLOCK StatusBlock
)
354 PHYSICAL_ADDRESS FrameBuffer
;
355 ULONG inIoSpace
= VIDEO_MEMORY_SPACE_MEMORY
;
356 SYSTEM_BASIC_INFORMATION BasicInfo
;
359 /* FIXME: this should probably be done differently, without native API */
360 StatusBlock
->Information
= sizeof(VIDEO_MEMORY_INFORMATION
);
362 FrameBuffer
.u
.HighPart
= 0;
363 if (ZwQuerySystemInformation(SystemBasicInformation
,
365 sizeof(SYSTEM_BASIC_INFORMATION
),
366 &Length
) == NO_ERROR
)
368 FrameBuffer
.u
.LowPart
= BasicInfo
.HighestPhysicalPageNumber
* PAGE_SIZE
;
372 VideoPortDebugPrint(Error
, "ZwQueryBasicInformation failed, assuming 64MB total memory\n");
373 FrameBuffer
.u
.LowPart
= 60 * 1024 * 1024;
376 FrameBuffer
.QuadPart
+= DeviceExtension
->PhysFrameBufferStart
.QuadPart
;
377 MapInformation
->VideoRamBase
= RequestedAddress
->RequestedVirtualAddress
;
378 MapInformation
->VideoRamLength
= 4 * 1024 * 1024;
379 VideoPortMapMemory(DeviceExtension
, FrameBuffer
,
380 &MapInformation
->VideoRamLength
, &inIoSpace
,
381 &MapInformation
->VideoRamBase
);
383 MapInformation
->FrameBufferBase
= MapInformation
->VideoRamBase
;
384 MapInformation
->FrameBufferLength
= MapInformation
->VideoRamLength
;
386 /* Tell the nVidia controller about the framebuffer */
387 *((PULONG
)((char *) DeviceExtension
->VirtControlStart
+ CONTROL_FRAMEBUFFER_ADDRESS_OFFSET
)) = FrameBuffer
.u
.LowPart
;
389 VideoPortDebugPrint(Info
, "Mapped 0x%x bytes of phys mem at 0x%lx to virt addr 0x%p\n",
390 MapInformation
->VideoRamLength
, FrameBuffer
.u
.LowPart
, MapInformation
->VideoRamBase
);
396 * VBEUnmapVideoMemory
398 * Releases a mapping between the virtual address space and the adapter's
399 * frame buffer and video RAM.
403 XboxVmpUnmapVideoMemory(
404 PXBOXVMP_DEVICE_EXTENSION DeviceExtension
,
405 PVIDEO_MEMORY VideoMemory
,
406 PSTATUS_BLOCK StatusBlock
)
408 VideoPortUnmapMemory(DeviceExtension
, VideoMemory
->RequestedVirtualAddress
,
415 * XboxVmpQueryNumAvailModes
417 * Returns the number of video modes supported by the adapter and the size
418 * in bytes of the video mode information, which can be used to allocate a
419 * buffer for an IOCTL_VIDEO_QUERY_AVAIL_MODES request.
423 XboxVmpQueryNumAvailModes(
424 PXBOXVMP_DEVICE_EXTENSION DeviceExtension
,
425 PVIDEO_NUM_MODES Modes
,
426 PSTATUS_BLOCK StatusBlock
)
429 Modes
->ModeInformationLength
= sizeof(VIDEO_MODE_INFORMATION
);
430 StatusBlock
->Information
= sizeof(VIDEO_NUM_MODES
);
435 ReadfromSMBus(UCHAR Address
, UCHAR bRegister
, UCHAR Size
, ULONG
*Data_to_smbus
)
437 int nRetriesToLive
=50;
439 while (0 != (VideoPortReadPortUshort((PUSHORT
) (I2C_IO_BASE
+ 0)) & 0x0800))
441 ; /* Franz's spin while bus busy with any master traffic */
444 while (0 != nRetriesToLive
--)
449 VideoPortWritePortUchar((PUCHAR
) (I2C_IO_BASE
+ 4), (Address
<< 1) | 1);
450 VideoPortWritePortUchar((PUCHAR
) (I2C_IO_BASE
+ 8), bRegister
);
452 temp
= VideoPortReadPortUshort((PUSHORT
) (I2C_IO_BASE
+ 0));
453 VideoPortWritePortUshort((PUSHORT
) (I2C_IO_BASE
+ 0), temp
); /* clear down all preexisting errors */
458 VideoPortWritePortUchar((PUCHAR
) (I2C_IO_BASE
+ 2), 0x0d); /* DWORD modus ? */
461 VideoPortWritePortUchar((PUCHAR
) (I2C_IO_BASE
+ 2), 0x0b); /* WORD modus */
464 VideoPortWritePortUchar((PUCHAR
) (I2C_IO_BASE
+ 2), 0x0a); // BYTE
470 while (0 == (b
& 0x36))
472 b
= VideoPortReadPortUchar((PUCHAR
) (I2C_IO_BASE
+ 0));
477 /* printf("I2CTransmitByteGetReturn error %x\n", b); */
482 /* printf("I2CTransmitByteGetReturn no complete, retry\n"); */
489 VideoPortReadPortUchar((PUCHAR
) (I2C_IO_BASE
+ 6));
490 VideoPortReadPortUchar((PUCHAR
) (I2C_IO_BASE
+ 9));
491 VideoPortReadPortUchar((PUCHAR
) (I2C_IO_BASE
+ 9));
492 VideoPortReadPortUchar((PUCHAR
) (I2C_IO_BASE
+ 9));
493 VideoPortReadPortUchar((PUCHAR
) (I2C_IO_BASE
+ 9));
496 *Data_to_smbus
= VideoPortReadPortUshort((PUSHORT
) (I2C_IO_BASE
+ 6));
499 *Data_to_smbus
= VideoPortReadPortUchar((PUCHAR
) (I2C_IO_BASE
+ 6));
513 I2CTransmitByteGetReturn(UCHAR bPicAddressI2cFormat
, UCHAR bDataToWrite
, ULONG
*Return
)
515 return ReadfromSMBus(bPicAddressI2cFormat
, bDataToWrite
, 1, Return
);
519 * XboxVmpQueryAvailModes
521 * Returns information about each video mode supported by the adapter.
525 XboxVmpQueryAvailModes(
526 PXBOXVMP_DEVICE_EXTENSION DeviceExtension
,
527 PVIDEO_MODE_INFORMATION VideoMode
,
528 PSTATUS_BLOCK StatusBlock
)
530 return XboxVmpQueryCurrentMode(DeviceExtension
, VideoMode
, StatusBlock
);
534 * VBEQueryCurrentMode
536 * Returns information about current video mode.
540 XboxVmpQueryCurrentMode(
541 PXBOXVMP_DEVICE_EXTENSION DeviceExtension
,
542 PVIDEO_MODE_INFORMATION VideoMode
,
543 PSTATUS_BLOCK StatusBlock
)
547 VideoMode
->Length
= sizeof(VIDEO_MODE_INFORMATION
);
548 VideoMode
->ModeIndex
= 0;
549 if (I2CTransmitByteGetReturn(0x10, 0x04, &AvMode
))
551 if (1 == AvMode
) /* HDTV */
553 VideoMode
->VisScreenWidth
= 720;
557 /* FIXME Other possible values of AvMode:
565 VideoMode
->VisScreenWidth
= 640;
570 VideoMode
->VisScreenWidth
= 640;
572 VideoMode
->VisScreenHeight
= 480;
573 VideoMode
->ScreenStride
= VideoMode
->VisScreenWidth
* 4;
574 VideoMode
->NumberOfPlanes
= 1;
575 VideoMode
->BitsPerPlane
= 32;
576 VideoMode
->Frequency
= 1;
577 VideoMode
->XMillimeter
= 0; /* FIXME */
578 VideoMode
->YMillimeter
= 0; /* FIXME */
579 VideoMode
->NumberRedBits
= 8;
580 VideoMode
->NumberGreenBits
= 8;
581 VideoMode
->NumberBlueBits
= 8;
582 VideoMode
->RedMask
= 0xff0000;
583 VideoMode
->GreenMask
= 0x00ff00;
584 VideoMode
->BlueMask
= 0x0000ff;
585 VideoMode
->VideoMemoryBitmapWidth
= VideoMode
->VisScreenWidth
;
586 VideoMode
->VideoMemoryBitmapHeight
= VideoMode
->VisScreenHeight
;
587 VideoMode
->AttributeFlags
= VIDEO_MODE_GRAPHICS
| VIDEO_MODE_COLOR
|
588 VIDEO_MODE_NO_OFF_SCREEN
;
589 VideoMode
->DriverSpecificAttributeFlags
= 0;
591 StatusBlock
->Information
= sizeof(VIDEO_MODE_INFORMATION
);