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
7f87a695bSStanislav Motylkov * Copyright 2019-2020 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
19b54a38b8SStanislav Motylkov #include <debug.h>
20b54a38b8SStanislav Motylkov #include <dpfilter.h>
21c2c66affSColin Finck
222a77e359SStanislav Motylkov #include <drivers/xbox/xgpu.h>
232a77e359SStanislav Motylkov
24c2c66affSColin Finck /* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/
25c2c66affSColin Finck
26816149e0SStanislav Motylkov ULONG
27816149e0SStanislav Motylkov NTAPI
DriverEntry(IN PVOID Context1,IN PVOID Context2)28816149e0SStanislav Motylkov DriverEntry(
29816149e0SStanislav Motylkov IN PVOID Context1,
30816149e0SStanislav Motylkov IN PVOID Context2)
31c2c66affSColin Finck {
32c2c66affSColin Finck VIDEO_HW_INITIALIZATION_DATA InitData;
33c2c66affSColin Finck
34c2c66affSColin Finck VideoPortZeroMemory(&InitData, sizeof(InitData));
35c2c66affSColin Finck InitData.AdapterInterfaceType = PCIBus;
36c2c66affSColin Finck InitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA);
37c2c66affSColin Finck InitData.HwFindAdapter = XboxVmpFindAdapter;
38c2c66affSColin Finck InitData.HwInitialize = XboxVmpInitialize;
39c2c66affSColin Finck InitData.HwStartIO = XboxVmpStartIO;
40c2c66affSColin Finck InitData.HwResetHw = XboxVmpResetHw;
41c2c66affSColin Finck InitData.HwGetPowerState = XboxVmpGetPowerState;
42c2c66affSColin Finck InitData.HwSetPowerState = XboxVmpSetPowerState;
43c2c66affSColin Finck InitData.HwDeviceExtensionSize = sizeof(XBOXVMP_DEVICE_EXTENSION);
44c2c66affSColin Finck
45c2c66affSColin Finck return VideoPortInitialize(Context1, Context2, &InitData, NULL);
46c2c66affSColin Finck }
47c2c66affSColin Finck
48c2c66affSColin Finck /*
49c2c66affSColin Finck * XboxVmpFindAdapter
50c2c66affSColin Finck *
51c2c66affSColin Finck * Detects the Xbox Nvidia display adapter.
52c2c66affSColin Finck */
53c2c66affSColin Finck
54816149e0SStanislav Motylkov VP_STATUS
55816149e0SStanislav Motylkov NTAPI
XboxVmpFindAdapter(IN PVOID HwDeviceExtension,IN PVOID HwContext,IN PWSTR ArgumentString,IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo,OUT PUCHAR Again)56c2c66affSColin Finck XboxVmpFindAdapter(
57c2c66affSColin Finck IN PVOID HwDeviceExtension,
58c2c66affSColin Finck IN PVOID HwContext,
59c2c66affSColin Finck IN PWSTR ArgumentString,
60c2c66affSColin Finck IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo,
61c2c66affSColin Finck OUT PUCHAR Again)
62c2c66affSColin Finck {
63c2c66affSColin Finck PXBOXVMP_DEVICE_EXTENSION XboxVmpDeviceExtension;
64c2c66affSColin Finck VP_STATUS Status;
65*61c77d1fSHermès Bélusca-Maïto /* 3 access ranges: for MMIO, VRAM, and Indirect memory access IO ports */
66*61c77d1fSHermès Bélusca-Maïto VIDEO_ACCESS_RANGE AccessRanges[3];
678c361450SStanislav Motylkov USHORT VendorId = 0x10DE; /* NVIDIA Corporation */
688c361450SStanislav Motylkov USHORT DeviceId = 0x02A0; /* NV2A XGPU */
6961012eb5SHermès Bélusca-Maïto ULONG Slot = 0;
70c2c66affSColin Finck
71b54a38b8SStanislav Motylkov TRACE_(IHVVIDEO, "XboxVmpFindAdapter\n");
72c2c66affSColin Finck
73c2c66affSColin Finck XboxVmpDeviceExtension = (PXBOXVMP_DEVICE_EXTENSION)HwDeviceExtension;
74816149e0SStanislav Motylkov
7561012eb5SHermès Bélusca-Maïto VideoPortZeroMemory(&AccessRanges, sizeof(AccessRanges));
7661012eb5SHermès Bélusca-Maïto Status = VideoPortGetAccessRanges(HwDeviceExtension, 0, NULL,
7761012eb5SHermès Bélusca-Maïto RTL_NUMBER_OF(AccessRanges), AccessRanges,
7861012eb5SHermès Bélusca-Maïto &VendorId, &DeviceId, &Slot);
798c361450SStanislav Motylkov if (Status == NO_ERROR)
80c2c66affSColin Finck {
81c2c66affSColin Finck XboxVmpDeviceExtension->PhysControlStart = AccessRanges[0].RangeStart;
82c2c66affSColin Finck XboxVmpDeviceExtension->ControlLength = AccessRanges[0].RangeLength;
83c2c66affSColin Finck XboxVmpDeviceExtension->PhysFrameBufferStart = AccessRanges[1].RangeStart;
84c2c66affSColin Finck }
85c2c66affSColin Finck
86c2c66affSColin Finck return Status;
87c2c66affSColin Finck }
88c2c66affSColin Finck
89c2c66affSColin Finck /*
90c2c66affSColin Finck * XboxVmpInitialize
91c2c66affSColin Finck *
92c2c66affSColin Finck * Performs the first initialization of the adapter, after the HAL has given
93c2c66affSColin Finck * up control of the video hardware to the video port driver.
94c2c66affSColin Finck */
95c2c66affSColin Finck
96816149e0SStanislav Motylkov BOOLEAN
97816149e0SStanislav Motylkov NTAPI
XboxVmpInitialize(PVOID HwDeviceExtension)98816149e0SStanislav Motylkov XboxVmpInitialize(
99816149e0SStanislav Motylkov PVOID HwDeviceExtension)
100c2c66affSColin Finck {
101c2c66affSColin Finck PXBOXVMP_DEVICE_EXTENSION XboxVmpDeviceExtension;
102c2c66affSColin Finck ULONG inIoSpace = VIDEO_MEMORY_SPACE_MEMORY;
103c2c66affSColin Finck ULONG Length;
104c2c66affSColin Finck
105b54a38b8SStanislav Motylkov TRACE_(IHVVIDEO, "XboxVmpInitialize\n");
106c2c66affSColin Finck
107c2c66affSColin Finck XboxVmpDeviceExtension = (PXBOXVMP_DEVICE_EXTENSION)HwDeviceExtension;
108c2c66affSColin Finck
109c2c66affSColin Finck Length = XboxVmpDeviceExtension->ControlLength;
110c2c66affSColin Finck XboxVmpDeviceExtension->VirtControlStart = NULL;
111816149e0SStanislav Motylkov
112816149e0SStanislav Motylkov if (VideoPortMapMemory(HwDeviceExtension,
113c2c66affSColin Finck XboxVmpDeviceExtension->PhysControlStart,
114816149e0SStanislav Motylkov &Length,
115816149e0SStanislav Motylkov &inIoSpace,
116816149e0SStanislav Motylkov &XboxVmpDeviceExtension->VirtControlStart) != NO_ERROR)
117c2c66affSColin Finck {
118b54a38b8SStanislav Motylkov ERR_(IHVVIDEO, "Failed to map control memory\n");
119c2c66affSColin Finck return FALSE;
120c2c66affSColin Finck }
121816149e0SStanislav Motylkov
122b54a38b8SStanislav Motylkov INFO_(IHVVIDEO, "Mapped 0x%x bytes of control mem at 0x%x to virt addr 0x%x\n",
123c2c66affSColin Finck XboxVmpDeviceExtension->ControlLength,
124c2c66affSColin Finck XboxVmpDeviceExtension->PhysControlStart.u.LowPart,
125c2c66affSColin Finck XboxVmpDeviceExtension->VirtControlStart);
126c2c66affSColin Finck
127c2c66affSColin Finck return TRUE;
128c2c66affSColin Finck }
129c2c66affSColin Finck
130c2c66affSColin Finck /*
131c2c66affSColin Finck * XboxVmpStartIO
132c2c66affSColin Finck *
133c2c66affSColin Finck * Processes the specified Video Request Packet.
134c2c66affSColin Finck */
135c2c66affSColin Finck
136816149e0SStanislav Motylkov BOOLEAN
137816149e0SStanislav Motylkov NTAPI
XboxVmpStartIO(PVOID HwDeviceExtension,PVIDEO_REQUEST_PACKET RequestPacket)138c2c66affSColin Finck XboxVmpStartIO(
139c2c66affSColin Finck PVOID HwDeviceExtension,
140c2c66affSColin Finck PVIDEO_REQUEST_PACKET RequestPacket)
141c2c66affSColin Finck {
142c2c66affSColin Finck BOOLEAN Result;
143c2c66affSColin Finck
144c2c66affSColin Finck RequestPacket->StatusBlock->Status = ERROR_INVALID_PARAMETER;
145c2c66affSColin Finck
146c2c66affSColin Finck switch (RequestPacket->IoControlCode)
147c2c66affSColin Finck {
148c2c66affSColin Finck case IOCTL_VIDEO_SET_CURRENT_MODE:
149816149e0SStanislav Motylkov {
150b54a38b8SStanislav Motylkov TRACE_(IHVVIDEO, "XboxVmpStartIO IOCTL_VIDEO_SET_CURRENT_MODE\n");
151816149e0SStanislav Motylkov
152c2c66affSColin Finck if (RequestPacket->InputBufferLength < sizeof(VIDEO_MODE))
153c2c66affSColin Finck {
154c2c66affSColin Finck RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
155c2c66affSColin Finck return TRUE;
156c2c66affSColin Finck }
157816149e0SStanislav Motylkov
158c2c66affSColin Finck Result = XboxVmpSetCurrentMode(
159c2c66affSColin Finck (PXBOXVMP_DEVICE_EXTENSION)HwDeviceExtension,
160c2c66affSColin Finck (PVIDEO_MODE)RequestPacket->InputBuffer,
161c2c66affSColin Finck RequestPacket->StatusBlock);
162c2c66affSColin Finck break;
163816149e0SStanislav Motylkov }
164c2c66affSColin Finck
165c2c66affSColin Finck case IOCTL_VIDEO_RESET_DEVICE:
166816149e0SStanislav Motylkov {
167b54a38b8SStanislav Motylkov TRACE_(IHVVIDEO, "XboxVmpStartIO IOCTL_VIDEO_RESET_DEVICE\n");
168816149e0SStanislav Motylkov
169c2c66affSColin Finck Result = XboxVmpResetDevice(
170c2c66affSColin Finck (PXBOXVMP_DEVICE_EXTENSION)HwDeviceExtension,
171c2c66affSColin Finck RequestPacket->StatusBlock);
172c2c66affSColin Finck break;
173816149e0SStanislav Motylkov }
174c2c66affSColin Finck
175c2c66affSColin Finck case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
176816149e0SStanislav Motylkov {
177b54a38b8SStanislav Motylkov TRACE_(IHVVIDEO, "XboxVmpStartIO IOCTL_VIDEO_MAP_VIDEO_MEMORY\n");
178816149e0SStanislav Motylkov
179c2c66affSColin Finck if (RequestPacket->OutputBufferLength < sizeof(VIDEO_MEMORY_INFORMATION) ||
180c2c66affSColin Finck RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))
181c2c66affSColin Finck {
182c2c66affSColin Finck RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
183c2c66affSColin Finck return TRUE;
184c2c66affSColin Finck }
185816149e0SStanislav Motylkov
186c2c66affSColin Finck Result = XboxVmpMapVideoMemory(
187c2c66affSColin Finck (PXBOXVMP_DEVICE_EXTENSION)HwDeviceExtension,
188c2c66affSColin Finck (PVIDEO_MEMORY)RequestPacket->InputBuffer,
189c2c66affSColin Finck (PVIDEO_MEMORY_INFORMATION)RequestPacket->OutputBuffer,
190c2c66affSColin Finck RequestPacket->StatusBlock);
191c2c66affSColin Finck break;
192816149e0SStanislav Motylkov }
193c2c66affSColin Finck
194c2c66affSColin Finck case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
195816149e0SStanislav Motylkov {
196b54a38b8SStanislav Motylkov TRACE_(IHVVIDEO, "XboxVmpStartIO IOCTL_VIDEO_UNMAP_VIDEO_MEMORY\n");
197816149e0SStanislav Motylkov
198c2c66affSColin Finck if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))
199c2c66affSColin Finck {
200c2c66affSColin Finck RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
201c2c66affSColin Finck return TRUE;
202c2c66affSColin Finck }
203816149e0SStanislav Motylkov
204c2c66affSColin Finck Result = XboxVmpUnmapVideoMemory(
205c2c66affSColin Finck (PXBOXVMP_DEVICE_EXTENSION)HwDeviceExtension,
206c2c66affSColin Finck (PVIDEO_MEMORY)RequestPacket->InputBuffer,
207c2c66affSColin Finck RequestPacket->StatusBlock);
208c2c66affSColin Finck break;
209816149e0SStanislav Motylkov }
210c2c66affSColin Finck
211c2c66affSColin Finck case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
212816149e0SStanislav Motylkov {
213b54a38b8SStanislav Motylkov TRACE_(IHVVIDEO, "XboxVmpStartIO IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES\n");
214816149e0SStanislav Motylkov
215c2c66affSColin Finck if (RequestPacket->OutputBufferLength < sizeof(VIDEO_NUM_MODES))
216c2c66affSColin Finck {
217c2c66affSColin Finck RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
218c2c66affSColin Finck return TRUE;
219c2c66affSColin Finck }
220816149e0SStanislav Motylkov
221c2c66affSColin Finck Result = XboxVmpQueryNumAvailModes(
222c2c66affSColin Finck (PXBOXVMP_DEVICE_EXTENSION)HwDeviceExtension,
223c2c66affSColin Finck (PVIDEO_NUM_MODES)RequestPacket->OutputBuffer,
224c2c66affSColin Finck RequestPacket->StatusBlock);
225c2c66affSColin Finck break;
226816149e0SStanislav Motylkov }
227c2c66affSColin Finck
228c2c66affSColin Finck case IOCTL_VIDEO_QUERY_AVAIL_MODES:
229816149e0SStanislav Motylkov {
230b54a38b8SStanislav Motylkov TRACE_(IHVVIDEO, "XboxVmpStartIO IOCTL_VIDEO_QUERY_AVAIL_MODES\n");
231816149e0SStanislav Motylkov
232c2c66affSColin Finck if (RequestPacket->OutputBufferLength < sizeof(VIDEO_MODE_INFORMATION))
233c2c66affSColin Finck {
234c2c66affSColin Finck RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
235c2c66affSColin Finck return TRUE;
236c2c66affSColin Finck }
237816149e0SStanislav Motylkov
238c2c66affSColin Finck Result = XboxVmpQueryAvailModes(
239c2c66affSColin Finck (PXBOXVMP_DEVICE_EXTENSION)HwDeviceExtension,
240c2c66affSColin Finck (PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer,
241c2c66affSColin Finck RequestPacket->StatusBlock);
242c2c66affSColin Finck break;
243816149e0SStanislav Motylkov }
244c2c66affSColin Finck
245c2c66affSColin Finck case IOCTL_VIDEO_QUERY_CURRENT_MODE:
246816149e0SStanislav Motylkov {
247b54a38b8SStanislav Motylkov TRACE_(IHVVIDEO, "XboxVmpStartIO IOCTL_VIDEO_QUERY_CURRENT_MODE\n");
248816149e0SStanislav Motylkov
249c2c66affSColin Finck if (RequestPacket->OutputBufferLength < sizeof(VIDEO_MODE_INFORMATION))
250c2c66affSColin Finck {
251c2c66affSColin Finck RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
252c2c66affSColin Finck return TRUE;
253c2c66affSColin Finck }
254816149e0SStanislav Motylkov
255c2c66affSColin Finck Result = XboxVmpQueryCurrentMode(
256c2c66affSColin Finck (PXBOXVMP_DEVICE_EXTENSION)HwDeviceExtension,
257c2c66affSColin Finck (PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer,
258c2c66affSColin Finck RequestPacket->StatusBlock);
259c2c66affSColin Finck break;
260816149e0SStanislav Motylkov }
261c2c66affSColin Finck
262c2c66affSColin Finck default:
263816149e0SStanislav Motylkov {
264b54a38b8SStanislav Motylkov WARN_(IHVVIDEO, "XboxVmpStartIO 0x%x not implemented\n", RequestPacket->IoControlCode);
265816149e0SStanislav Motylkov
266c2c66affSColin Finck RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
267c2c66affSColin Finck return FALSE;
268c2c66affSColin Finck }
269816149e0SStanislav Motylkov }
270c2c66affSColin Finck
271c2c66affSColin Finck if (Result)
272c2c66affSColin Finck {
273c2c66affSColin Finck RequestPacket->StatusBlock->Status = NO_ERROR;
274c2c66affSColin Finck }
275c2c66affSColin Finck
276c2c66affSColin Finck return TRUE;
277c2c66affSColin Finck }
278c2c66affSColin Finck
279c2c66affSColin Finck /*
280c2c66affSColin Finck * XboxVmpResetHw
281c2c66affSColin Finck *
282c2c66affSColin Finck * This function is called to reset the hardware to a known state.
283c2c66affSColin Finck */
284c2c66affSColin Finck
285816149e0SStanislav Motylkov BOOLEAN
286816149e0SStanislav Motylkov NTAPI
XboxVmpResetHw(PVOID DeviceExtension,ULONG Columns,ULONG Rows)287c2c66affSColin Finck XboxVmpResetHw(
288c2c66affSColin Finck PVOID DeviceExtension,
289c2c66affSColin Finck ULONG Columns,
290c2c66affSColin Finck ULONG Rows)
291c2c66affSColin Finck {
292b54a38b8SStanislav Motylkov TRACE_(IHVVIDEO, "XboxVmpResetHw\n");
293c2c66affSColin Finck
294c2c66affSColin Finck if (!XboxVmpResetDevice((PXBOXVMP_DEVICE_EXTENSION)DeviceExtension, NULL))
295c2c66affSColin Finck {
296c2c66affSColin Finck return FALSE;
297c2c66affSColin Finck }
298c2c66affSColin Finck
299c2c66affSColin Finck return TRUE;
300c2c66affSColin Finck }
301c2c66affSColin Finck
302c2c66affSColin Finck /*
303c2c66affSColin Finck * XboxVmpGetPowerState
304c2c66affSColin Finck *
305c2c66affSColin Finck * Queries whether the device can support the requested power state.
306c2c66affSColin Finck */
307c2c66affSColin Finck
308816149e0SStanislav Motylkov VP_STATUS
309816149e0SStanislav Motylkov NTAPI
XboxVmpGetPowerState(PVOID HwDeviceExtension,ULONG HwId,PVIDEO_POWER_MANAGEMENT VideoPowerControl)310c2c66affSColin Finck XboxVmpGetPowerState(
311c2c66affSColin Finck PVOID HwDeviceExtension,
312c2c66affSColin Finck ULONG HwId,
313c2c66affSColin Finck PVIDEO_POWER_MANAGEMENT VideoPowerControl)
314c2c66affSColin Finck {
315b54a38b8SStanislav Motylkov ERR_(IHVVIDEO, "XboxVmpGetPowerState is not supported\n");
316c2c66affSColin Finck
317c2c66affSColin Finck return ERROR_INVALID_FUNCTION;
318c2c66affSColin Finck }
319c2c66affSColin Finck
320c2c66affSColin Finck /*
321c2c66affSColin Finck * XboxVmpSetPowerState
322c2c66affSColin Finck *
323c2c66affSColin Finck * Sets the power state of the specified device
324c2c66affSColin Finck */
325c2c66affSColin Finck
326816149e0SStanislav Motylkov VP_STATUS
327816149e0SStanislav Motylkov NTAPI
XboxVmpSetPowerState(PVOID HwDeviceExtension,ULONG HwId,PVIDEO_POWER_MANAGEMENT VideoPowerControl)328c2c66affSColin Finck XboxVmpSetPowerState(
329c2c66affSColin Finck PVOID HwDeviceExtension,
330c2c66affSColin Finck ULONG HwId,
331c2c66affSColin Finck PVIDEO_POWER_MANAGEMENT VideoPowerControl)
332c2c66affSColin Finck {
333b54a38b8SStanislav Motylkov ERR_(IHVVIDEO, "XboxVmpSetPowerState not supported\n");
334c2c66affSColin Finck
335c2c66affSColin Finck return ERROR_INVALID_FUNCTION;
336c2c66affSColin Finck }
337c2c66affSColin Finck
338c2c66affSColin Finck /*
339c2c66affSColin Finck * VBESetCurrentMode
340c2c66affSColin Finck *
341c2c66affSColin Finck * Sets the adapter to the specified operating mode.
342c2c66affSColin Finck */
343c2c66affSColin Finck
344816149e0SStanislav Motylkov BOOLEAN
345816149e0SStanislav Motylkov FASTCALL
XboxVmpSetCurrentMode(PXBOXVMP_DEVICE_EXTENSION DeviceExtension,PVIDEO_MODE RequestedMode,PSTATUS_BLOCK StatusBlock)346c2c66affSColin Finck XboxVmpSetCurrentMode(
347c2c66affSColin Finck PXBOXVMP_DEVICE_EXTENSION DeviceExtension,
348c2c66affSColin Finck PVIDEO_MODE RequestedMode,
349c2c66affSColin Finck PSTATUS_BLOCK StatusBlock)
350c2c66affSColin Finck {
351816149e0SStanislav Motylkov if (RequestedMode->RequestedMode != 0)
352c2c66affSColin Finck {
353c2c66affSColin Finck return FALSE;
354c2c66affSColin Finck }
355c2c66affSColin Finck
356c2c66affSColin Finck /* Nothing to do, really. We only support a single mode and we're already
357816149e0SStanislav Motylkov * in that mode
358816149e0SStanislav Motylkov */
359c2c66affSColin Finck return TRUE;
360c2c66affSColin Finck }
361c2c66affSColin Finck
362c2c66affSColin Finck /*
363c2c66affSColin Finck * XboxVmpResetDevice
364c2c66affSColin Finck *
365c2c66affSColin Finck * Resets the video hardware to the default mode, to which it was initialized
366c2c66affSColin Finck * at system boot.
367c2c66affSColin Finck */
368c2c66affSColin Finck
369816149e0SStanislav Motylkov BOOLEAN
370816149e0SStanislav Motylkov FASTCALL
XboxVmpResetDevice(PXBOXVMP_DEVICE_EXTENSION DeviceExtension,PSTATUS_BLOCK StatusBlock)371c2c66affSColin Finck XboxVmpResetDevice(
372c2c66affSColin Finck PXBOXVMP_DEVICE_EXTENSION DeviceExtension,
373c2c66affSColin Finck PSTATUS_BLOCK StatusBlock)
374c2c66affSColin Finck {
375c2c66affSColin Finck /* There is nothing to be done here */
376c2c66affSColin Finck
377c2c66affSColin Finck return TRUE;
378c2c66affSColin Finck }
379c2c66affSColin Finck
380c2c66affSColin Finck /*
381c2c66affSColin Finck * XboxVmpMapVideoMemory
382c2c66affSColin Finck *
383c2c66affSColin Finck * Maps the video hardware frame buffer and video RAM into the virtual address
384c2c66affSColin Finck * space of the requestor.
385c2c66affSColin Finck */
386c2c66affSColin Finck
387816149e0SStanislav Motylkov BOOLEAN
388816149e0SStanislav Motylkov FASTCALL
XboxVmpMapVideoMemory(PXBOXVMP_DEVICE_EXTENSION DeviceExtension,PVIDEO_MEMORY RequestedAddress,PVIDEO_MEMORY_INFORMATION MapInformation,PSTATUS_BLOCK StatusBlock)389c2c66affSColin Finck XboxVmpMapVideoMemory(
390c2c66affSColin Finck PXBOXVMP_DEVICE_EXTENSION DeviceExtension,
391c2c66affSColin Finck PVIDEO_MEMORY RequestedAddress,
392c2c66affSColin Finck PVIDEO_MEMORY_INFORMATION MapInformation,
393c2c66affSColin Finck PSTATUS_BLOCK StatusBlock)
394c2c66affSColin Finck {
395c2c66affSColin Finck PHYSICAL_ADDRESS FrameBuffer;
396c2c66affSColin Finck ULONG inIoSpace = VIDEO_MEMORY_SPACE_MEMORY;
397c2c66affSColin Finck
398c2c66affSColin Finck StatusBlock->Information = sizeof(VIDEO_MEMORY_INFORMATION);
399c2c66affSColin Finck
400b3301df5SStanislav Motylkov /* Reuse framebuffer that was set up by firmware */
4012a77e359SStanislav Motylkov FrameBuffer.QuadPart = READ_REGISTER_ULONG((ULONG_PTR)DeviceExtension->VirtControlStart + NV2A_CRTC_FRAMEBUFFER_START);
402afdb4202SStanislav Motylkov /* Framebuffer address offset value is coming from the GPU within
403afdb4202SStanislav Motylkov * memory mapped I/O address space, so we're comparing only low
404afdb4202SStanislav Motylkov * 28 bits of the address within actual RAM address space */
405afdb4202SStanislav Motylkov FrameBuffer.QuadPart &= 0x0FFFFFFF;
406b3301df5SStanislav Motylkov if (FrameBuffer.QuadPart != 0x3C00000 && FrameBuffer.QuadPart != 0x7C00000)
407c2c66affSColin Finck {
408b3301df5SStanislav Motylkov /* Check framebuffer address (high 4 MB of either 64 or 128 MB RAM) */
409b3301df5SStanislav Motylkov WARN_(IHVVIDEO, "Non-standard framebuffer address 0x%p\n", FrameBuffer.QuadPart);
410c2c66affSColin Finck }
411b3301df5SStanislav Motylkov /* Verify that framebuffer address is page-aligned */
412b3301df5SStanislav Motylkov ASSERT(FrameBuffer.QuadPart % PAGE_SIZE == 0);
413c2c66affSColin Finck
414afdb4202SStanislav Motylkov /* Return the address back to GPU memory mapped I/O */
415c2c66affSColin Finck FrameBuffer.QuadPart += DeviceExtension->PhysFrameBufferStart.QuadPart;
416c2c66affSColin Finck MapInformation->VideoRamBase = RequestedAddress->RequestedVirtualAddress;
417b3301df5SStanislav Motylkov /* FIXME: obtain fb size from firmware somehow (Cromwell reserves high 4 MB of RAM) */
418297abde7SStanislav Motylkov MapInformation->VideoRamLength = NV2A_VIDEO_MEMORY_SIZE;
419816149e0SStanislav Motylkov
420816149e0SStanislav Motylkov VideoPortMapMemory(
421816149e0SStanislav Motylkov DeviceExtension,
422816149e0SStanislav Motylkov FrameBuffer,
423816149e0SStanislav Motylkov &MapInformation->VideoRamLength,
424816149e0SStanislav Motylkov &inIoSpace,
425c2c66affSColin Finck &MapInformation->VideoRamBase);
426c2c66affSColin Finck
427c2c66affSColin Finck MapInformation->FrameBufferBase = MapInformation->VideoRamBase;
428c2c66affSColin Finck MapInformation->FrameBufferLength = MapInformation->VideoRamLength;
429c2c66affSColin Finck
430c2c66affSColin Finck /* Tell the nVidia controller about the framebuffer */
4312a77e359SStanislav Motylkov WRITE_REGISTER_ULONG((ULONG_PTR)DeviceExtension->VirtControlStart + NV2A_CRTC_FRAMEBUFFER_START, FrameBuffer.u.LowPart);
432c2c66affSColin Finck
433b54a38b8SStanislav Motylkov INFO_(IHVVIDEO, "Mapped 0x%x bytes of phys mem at 0x%lx to virt addr 0x%p\n",
434c2c66affSColin Finck MapInformation->VideoRamLength, FrameBuffer.u.LowPart, MapInformation->VideoRamBase);
435c2c66affSColin Finck
436c2c66affSColin Finck return TRUE;
437c2c66affSColin Finck }
438c2c66affSColin Finck
439c2c66affSColin Finck /*
440c2c66affSColin Finck * VBEUnmapVideoMemory
441c2c66affSColin Finck *
442c2c66affSColin Finck * Releases a mapping between the virtual address space and the adapter's
443c2c66affSColin Finck * frame buffer and video RAM.
444c2c66affSColin Finck */
445c2c66affSColin Finck
446816149e0SStanislav Motylkov BOOLEAN
447816149e0SStanislav Motylkov FASTCALL
XboxVmpUnmapVideoMemory(PXBOXVMP_DEVICE_EXTENSION DeviceExtension,PVIDEO_MEMORY VideoMemory,PSTATUS_BLOCK StatusBlock)448c2c66affSColin Finck XboxVmpUnmapVideoMemory(
449c2c66affSColin Finck PXBOXVMP_DEVICE_EXTENSION DeviceExtension,
450c2c66affSColin Finck PVIDEO_MEMORY VideoMemory,
451c2c66affSColin Finck PSTATUS_BLOCK StatusBlock)
452c2c66affSColin Finck {
453816149e0SStanislav Motylkov VideoPortUnmapMemory(
454816149e0SStanislav Motylkov DeviceExtension,
455816149e0SStanislav Motylkov VideoMemory->RequestedVirtualAddress,
456c2c66affSColin Finck NULL);
457c2c66affSColin Finck
458c2c66affSColin Finck return TRUE;
459c2c66affSColin Finck }
460c2c66affSColin Finck
461c2c66affSColin Finck /*
462c2c66affSColin Finck * XboxVmpQueryNumAvailModes
463c2c66affSColin Finck *
464c2c66affSColin Finck * Returns the number of video modes supported by the adapter and the size
465c2c66affSColin Finck * in bytes of the video mode information, which can be used to allocate a
466c2c66affSColin Finck * buffer for an IOCTL_VIDEO_QUERY_AVAIL_MODES request.
467c2c66affSColin Finck */
468c2c66affSColin Finck
469816149e0SStanislav Motylkov BOOLEAN
470816149e0SStanislav Motylkov FASTCALL
XboxVmpQueryNumAvailModes(PXBOXVMP_DEVICE_EXTENSION DeviceExtension,PVIDEO_NUM_MODES Modes,PSTATUS_BLOCK StatusBlock)471c2c66affSColin Finck XboxVmpQueryNumAvailModes(
472c2c66affSColin Finck PXBOXVMP_DEVICE_EXTENSION DeviceExtension,
473c2c66affSColin Finck PVIDEO_NUM_MODES Modes,
474c2c66affSColin Finck PSTATUS_BLOCK StatusBlock)
475c2c66affSColin Finck {
476c2c66affSColin Finck Modes->NumModes = 1;
477c2c66affSColin Finck Modes->ModeInformationLength = sizeof(VIDEO_MODE_INFORMATION);
478c2c66affSColin Finck StatusBlock->Information = sizeof(VIDEO_NUM_MODES);
479c2c66affSColin Finck return TRUE;
480c2c66affSColin Finck }
481c2c66affSColin Finck
482c2c66affSColin Finck /*
483c2c66affSColin Finck * XboxVmpQueryAvailModes
484c2c66affSColin Finck *
485c2c66affSColin Finck * Returns information about each video mode supported by the adapter.
486c2c66affSColin Finck */
487c2c66affSColin Finck
488816149e0SStanislav Motylkov BOOLEAN
489816149e0SStanislav Motylkov FASTCALL
XboxVmpQueryAvailModes(PXBOXVMP_DEVICE_EXTENSION DeviceExtension,PVIDEO_MODE_INFORMATION VideoMode,PSTATUS_BLOCK StatusBlock)490c2c66affSColin Finck XboxVmpQueryAvailModes(
491c2c66affSColin Finck PXBOXVMP_DEVICE_EXTENSION DeviceExtension,
492c2c66affSColin Finck PVIDEO_MODE_INFORMATION VideoMode,
493c2c66affSColin Finck PSTATUS_BLOCK StatusBlock)
494c2c66affSColin Finck {
495c2c66affSColin Finck return XboxVmpQueryCurrentMode(DeviceExtension, VideoMode, StatusBlock);
496c2c66affSColin Finck }
497c2c66affSColin Finck
498297abde7SStanislav Motylkov UCHAR
NvGetCrtc(PXBOXVMP_DEVICE_EXTENSION DeviceExtension,UCHAR Index)499297abde7SStanislav Motylkov NvGetCrtc(
500297abde7SStanislav Motylkov PXBOXVMP_DEVICE_EXTENSION DeviceExtension,
501297abde7SStanislav Motylkov UCHAR Index)
502297abde7SStanislav Motylkov {
503f87a695bSStanislav Motylkov WRITE_REGISTER_UCHAR((ULONG_PTR)DeviceExtension->VirtControlStart + NV2A_CRTC_REGISTER_INDEX, Index);
504f87a695bSStanislav Motylkov return READ_REGISTER_UCHAR((ULONG_PTR)DeviceExtension->VirtControlStart + NV2A_CRTC_REGISTER_VALUE);
505297abde7SStanislav Motylkov }
506297abde7SStanislav Motylkov
507297abde7SStanislav Motylkov UCHAR
NvGetBytesPerPixel(PXBOXVMP_DEVICE_EXTENSION DeviceExtension,ULONG ScreenWidth)508297abde7SStanislav Motylkov NvGetBytesPerPixel(
509297abde7SStanislav Motylkov PXBOXVMP_DEVICE_EXTENSION DeviceExtension,
510297abde7SStanislav Motylkov ULONG ScreenWidth)
511297abde7SStanislav Motylkov {
512297abde7SStanislav Motylkov UCHAR BytesPerPixel;
513297abde7SStanislav Motylkov
514297abde7SStanislav Motylkov /* Get BPP directly from NV2A CRTC (magic constants are from Cromwell) */
515297abde7SStanislav Motylkov BytesPerPixel = 8 * (((NvGetCrtc(DeviceExtension, 0x19) & 0xE0) << 3) | (NvGetCrtc(DeviceExtension, 0x13) & 0xFF)) / ScreenWidth;
516297abde7SStanislav Motylkov
517297abde7SStanislav Motylkov if (BytesPerPixel == 4)
518297abde7SStanislav Motylkov {
519297abde7SStanislav Motylkov ASSERT((NvGetCrtc(DeviceExtension, 0x28) & 0xF) == BytesPerPixel - 1);
520297abde7SStanislav Motylkov }
521297abde7SStanislav Motylkov else
522297abde7SStanislav Motylkov {
523297abde7SStanislav Motylkov ASSERT((NvGetCrtc(DeviceExtension, 0x28) & 0xF) == BytesPerPixel);
524297abde7SStanislav Motylkov }
525297abde7SStanislav Motylkov
526297abde7SStanislav Motylkov return BytesPerPixel;
527297abde7SStanislav Motylkov }
528297abde7SStanislav Motylkov
529c2c66affSColin Finck /*
530c2c66affSColin Finck * VBEQueryCurrentMode
531c2c66affSColin Finck *
532c2c66affSColin Finck * Returns information about current video mode.
533c2c66affSColin Finck */
534c2c66affSColin Finck
535816149e0SStanislav Motylkov BOOLEAN
536816149e0SStanislav Motylkov FASTCALL
XboxVmpQueryCurrentMode(PXBOXVMP_DEVICE_EXTENSION DeviceExtension,PVIDEO_MODE_INFORMATION VideoMode,PSTATUS_BLOCK StatusBlock)537c2c66affSColin Finck XboxVmpQueryCurrentMode(
538c2c66affSColin Finck PXBOXVMP_DEVICE_EXTENSION DeviceExtension,
539c2c66affSColin Finck PVIDEO_MODE_INFORMATION VideoMode,
540c2c66affSColin Finck PSTATUS_BLOCK StatusBlock)
541c2c66affSColin Finck {
542297abde7SStanislav Motylkov UCHAR BytesPerPixel;
543c2c66affSColin Finck
544c2c66affSColin Finck VideoMode->Length = sizeof(VIDEO_MODE_INFORMATION);
545c2c66affSColin Finck VideoMode->ModeIndex = 0;
546816149e0SStanislav Motylkov
547f87a695bSStanislav Motylkov VideoMode->VisScreenWidth = READ_REGISTER_ULONG((ULONG_PTR)DeviceExtension->VirtControlStart + NV2A_RAMDAC_FP_HVALID_END) + 1;
548f87a695bSStanislav Motylkov VideoMode->VisScreenHeight = READ_REGISTER_ULONG((ULONG_PTR)DeviceExtension->VirtControlStart + NV2A_RAMDAC_FP_VVALID_END) + 1;
549297abde7SStanislav Motylkov
550297abde7SStanislav Motylkov if (VideoMode->VisScreenWidth <= 1 || VideoMode->VisScreenHeight <= 1)
551c2c66affSColin Finck {
552297abde7SStanislav Motylkov ERR_(IHVVIDEO, "Cannot obtain current screen resolution!\n");
553297abde7SStanislav Motylkov return FALSE;
554c2c66affSColin Finck }
555816149e0SStanislav Motylkov
556297abde7SStanislav Motylkov BytesPerPixel = NvGetBytesPerPixel(DeviceExtension, VideoMode->VisScreenWidth);
557297abde7SStanislav Motylkov ASSERT(BytesPerPixel >= 1 && BytesPerPixel <= 4);
558297abde7SStanislav Motylkov
559297abde7SStanislav Motylkov VideoMode->ScreenStride = VideoMode->VisScreenWidth * BytesPerPixel;
560c2c66affSColin Finck VideoMode->NumberOfPlanes = 1;
561297abde7SStanislav Motylkov VideoMode->BitsPerPlane = BytesPerPixel * 8;
562c2c66affSColin Finck VideoMode->Frequency = 1;
563c2c66affSColin Finck VideoMode->XMillimeter = 0; /* FIXME */
564c2c66affSColin Finck VideoMode->YMillimeter = 0; /* FIXME */
565297abde7SStanislav Motylkov if (BytesPerPixel >= 3)
566297abde7SStanislav Motylkov {
567c2c66affSColin Finck VideoMode->NumberRedBits = 8;
568c2c66affSColin Finck VideoMode->NumberGreenBits = 8;
569c2c66affSColin Finck VideoMode->NumberBlueBits = 8;
570816149e0SStanislav Motylkov VideoMode->RedMask = 0xFF0000;
571816149e0SStanislav Motylkov VideoMode->GreenMask = 0x00FF00;
572816149e0SStanislav Motylkov VideoMode->BlueMask = 0x0000FF;
573297abde7SStanislav Motylkov }
574297abde7SStanislav Motylkov else
575297abde7SStanislav Motylkov {
576297abde7SStanislav Motylkov /* FIXME: not implemented */
577297abde7SStanislav Motylkov WARN_(IHVVIDEO, "BytesPerPixel %d - not implemented\n", BytesPerPixel);
578297abde7SStanislav Motylkov }
579c2c66affSColin Finck VideoMode->VideoMemoryBitmapWidth = VideoMode->VisScreenWidth;
580c2c66affSColin Finck VideoMode->VideoMemoryBitmapHeight = VideoMode->VisScreenHeight;
581c2c66affSColin Finck VideoMode->AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR |
582c2c66affSColin Finck VIDEO_MODE_NO_OFF_SCREEN;
583c2c66affSColin Finck VideoMode->DriverSpecificAttributeFlags = 0;
584c2c66affSColin Finck
585c2c66affSColin Finck StatusBlock->Information = sizeof(VIDEO_MODE_INFORMATION);
586c2c66affSColin Finck
587297abde7SStanislav Motylkov /* Verify that screen fits framebuffer size */
588297abde7SStanislav Motylkov if (VideoMode->VisScreenWidth * VideoMode->VisScreenHeight * (VideoMode->BitsPerPlane / 8) > NV2A_VIDEO_MEMORY_SIZE)
589297abde7SStanislav Motylkov {
590297abde7SStanislav Motylkov ERR_(IHVVIDEO, "Current screen resolution exceeds video memory bounds!\n");
591297abde7SStanislav Motylkov return FALSE;
592297abde7SStanislav Motylkov }
593297abde7SStanislav Motylkov
594c2c66affSColin Finck return TRUE;
595c2c66affSColin Finck }
596c2c66affSColin Finck
597c2c66affSColin Finck /* EOF */
598