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