[VIDEOPRT/WINSERV] Move mapping the BIOS memory from winsrv to videoprt, where it...
[reactos.git] / reactos / win32ss / drivers / videoprt / dispatch.c
1 /*
2 * VideoPort driver
3 *
4 * Copyright (C) 2002, 2003, 2004 ReactOS Team
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 */
21
22 #include "videoprt.h"
23
24 /* GLOBAL VARIABLES ***********************************************************/
25
26 PVIDEO_PORT_DEVICE_EXTENSION ResetDisplayParametersDeviceExtension = NULL;
27 PVIDEO_WIN32K_CALLOUT Win32kCallout;
28
29 /* PRIVATE FUNCTIONS **********************************************************/
30
31 /*
32 * Reset display to blue screen
33 */
34 BOOLEAN
35 NTAPI
36 IntVideoPortResetDisplayParameters(ULONG Columns, ULONG Rows)
37 {
38 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
39
40 if (ResetDisplayParametersDeviceExtension == NULL)
41 return FALSE;
42
43 DriverExtension = ResetDisplayParametersDeviceExtension->DriverExtension;
44
45 if (DriverExtension->InitializationData.HwResetHw != NULL)
46 {
47 if (DriverExtension->InitializationData.HwResetHw(
48 &ResetDisplayParametersDeviceExtension->MiniPortDeviceExtension,
49 Columns, Rows))
50 {
51 ResetDisplayParametersDeviceExtension = NULL;
52 return TRUE;
53 }
54 }
55
56 ResetDisplayParametersDeviceExtension = NULL;
57 return FALSE;
58 }
59
60 NTSTATUS
61 NTAPI
62 IntVideoPortAddDevice(
63 IN PDRIVER_OBJECT DriverObject,
64 IN PDEVICE_OBJECT PhysicalDeviceObject)
65 {
66 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
67 PDEVICE_OBJECT DeviceObject;
68 NTSTATUS Status;
69
70 /* Get the initialization data we saved in VideoPortInitialize. */
71 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
72
73 /* Create adapter device object. */
74 Status = IntVideoPortCreateAdapterDeviceObject(DriverObject,
75 DriverExtension,
76 PhysicalDeviceObject,
77 &DeviceObject);
78 if (NT_SUCCESS(Status))
79 VideoPortDeviceNumber++;
80
81 return Status;
82 }
83
84 /*
85 * IntVideoPortDispatchOpen
86 *
87 * Answer requests for Open calls.
88 *
89 * Run Level
90 * PASSIVE_LEVEL
91 */
92 NTSTATUS
93 NTAPI
94 IntVideoPortDispatchOpen(
95 IN PDEVICE_OBJECT DeviceObject,
96 IN PIRP Irp)
97 {
98 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
99 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
100
101 TRACE_(VIDEOPRT, "IntVideoPortDispatchOpen\n");
102
103 if (CsrssInitialized == FALSE)
104 {
105 /*
106 * We know the first open call will be from the CSRSS process
107 * to let us know its handle.
108 */
109
110 INFO_(VIDEOPRT, "Referencing CSRSS\n");
111 Csrss = (PKPROCESS)PsGetCurrentProcess();
112 INFO_(VIDEOPRT, "Csrss %p\n", Csrss);
113
114 IntInitializeVideoAddressSpace();
115
116 CsrssInitialized = TRUE;
117 }
118
119 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
120 DriverExtension = DeviceExtension->DriverExtension;
121
122 if (DriverExtension->InitializationData.HwInitialize(&DeviceExtension->MiniPortDeviceExtension))
123 {
124 Irp->IoStatus.Status = STATUS_SUCCESS;
125 InterlockedIncrement((PLONG)&DeviceExtension->DeviceOpened);
126 }
127 else
128 {
129 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
130 }
131
132 Irp->IoStatus.Information = FILE_OPENED;
133 IoCompleteRequest(Irp, IO_NO_INCREMENT);
134
135 return STATUS_SUCCESS;
136 }
137
138 /*
139 * IntVideoPortDispatchClose
140 *
141 * Answer requests for Close calls.
142 *
143 * Run Level
144 * PASSIVE_LEVEL
145 */
146 NTSTATUS
147 NTAPI
148 IntVideoPortDispatchClose(
149 IN PDEVICE_OBJECT DeviceObject,
150 IN PIRP Irp)
151 {
152 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
153
154 TRACE_(VIDEOPRT, "IntVideoPortDispatchClose\n");
155
156 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
157 if ((DeviceExtension->DeviceOpened >= 1) &&
158 (InterlockedDecrement((PLONG)&DeviceExtension->DeviceOpened) == 0))
159 {
160 ResetDisplayParametersDeviceExtension = NULL;
161 InbvNotifyDisplayOwnershipLost(NULL);
162 ResetDisplayParametersDeviceExtension = DeviceExtension;
163 IntVideoPortResetDisplayParameters(80, 50);
164 }
165
166 Irp->IoStatus.Status = STATUS_SUCCESS;
167 IoCompleteRequest(Irp, IO_NO_INCREMENT);
168
169 return STATUS_SUCCESS;
170 }
171
172 PSTR
173 IoctlName(ULONG Ioctl)
174 {
175 switch(Ioctl)
176 {
177 case IOCTL_VIDEO_ENABLE_VDM:
178 return "IOCTL_VIDEO_ENABLE_VDM"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x00, METHOD_BUFFERED, FILE_ANY_ACCESS)
179 case IOCTL_VIDEO_DISABLE_VDM:
180 return "IOCTL_VIDEO_DISABLE_VDM"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x01, METHOD_BUFFERED, FILE_ANY_ACCESS)
181 case IOCTL_VIDEO_REGISTER_VDM:
182 return "IOCTL_VIDEO_REGISTER_VDM"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS)
183 case IOCTL_VIDEO_SET_OUTPUT_DEVICE_POWER_STATE:
184 return "IOCTL_VIDEO_SET_OUTPUT_DEVICE_POWER_STATE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x03, METHOD_BUFFERED, FILE_ANY_ACCESS)
185 case IOCTL_VIDEO_GET_OUTPUT_DEVICE_POWER_STATE:
186 return "IOCTL_VIDEO_GET_OUTPUT_DEVICE_POWER_STATE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x04, METHOD_BUFFERED, FILE_ANY_ACCESS)
187 case IOCTL_VIDEO_MONITOR_DEVICE:
188 return "IOCTL_VIDEO_MONITOR_DEVICE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x05, METHOD_BUFFERED, FILE_ANY_ACCESS)
189 case IOCTL_VIDEO_ENUM_MONITOR_PDO:
190 return "IOCTL_VIDEO_ENUM_MONITOR_PDO"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x06, METHOD_BUFFERED, FILE_ANY_ACCESS)
191 case IOCTL_VIDEO_INIT_WIN32K_CALLBACKS:
192 return "IOCTL_VIDEO_INIT_WIN32K_CALLBACKS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x07, METHOD_BUFFERED, FILE_ANY_ACCESS)
193 case IOCTL_VIDEO_HANDLE_VIDEOPARAMETERS:
194 return "IOCTL_VIDEO_HANDLE_VIDEOPARAMETERS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x08, METHOD_BUFFERED, FILE_ANY_ACCESS)
195 case IOCTL_VIDEO_IS_VGA_DEVICE:
196 return "IOCTL_VIDEO_IS_VGA_DEVICE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x09, METHOD_BUFFERED, FILE_ANY_ACCESS)
197 case IOCTL_VIDEO_USE_DEVICE_IN_SESSION:
198 return "IOCTL_VIDEO_USE_DEVICE_IN_SESSION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x0a, METHOD_BUFFERED, FILE_ANY_ACCESS)
199 case IOCTL_VIDEO_PREPARE_FOR_EARECOVERY:
200 return "IOCTL_VIDEO_PREPARE_FOR_EARECOVERY"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x0b, METHOD_BUFFERED, FILE_ANY_ACCESS)
201 case IOCTL_VIDEO_SAVE_HARDWARE_STATE:
202 return "IOCTL_VIDEO_SAVE_HARDWARE_STATE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x80, METHOD_BUFFERED, FILE_ANY_ACCESS)
203 case IOCTL_VIDEO_RESTORE_HARDWARE_STATE:
204 return "IOCTL_VIDEO_RESTORE_HARDWARE_STATE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x81, METHOD_BUFFERED, FILE_ANY_ACCESS)
205 case IOCTL_VIDEO_QUERY_AVAIL_MODES:
206 return "IOCTL_VIDEO_QUERY_AVAIL_MODES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x100, METHOD_BUFFERED, FILE_ANY_ACCESS)
207 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
208 return "IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x101, METHOD_BUFFERED, FILE_ANY_ACCESS)
209 case IOCTL_VIDEO_QUERY_CURRENT_MODE:
210 return "IOCTL_VIDEO_QUERY_CURRENT_MODE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x102, METHOD_BUFFERED, FILE_ANY_ACCESS)
211 case IOCTL_VIDEO_SET_CURRENT_MODE:
212 return "IOCTL_VIDEO_SET_CURRENT_MODE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x103, METHOD_BUFFERED, FILE_ANY_ACCESS)
213 case IOCTL_VIDEO_RESET_DEVICE:
214 return "IOCTL_VIDEO_RESET_DEVICE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x104, METHOD_BUFFERED, FILE_ANY_ACCESS)
215 case IOCTL_VIDEO_LOAD_AND_SET_FONT:
216 return "IOCTL_VIDEO_LOAD_AND_SET_FONT"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x105, METHOD_BUFFERED, FILE_ANY_ACCESS)
217 case IOCTL_VIDEO_SET_PALETTE_REGISTERS:
218 return "IOCTL_VIDEO_SET_PALETTE_REGISTERS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x106, METHOD_BUFFERED, FILE_ANY_ACCESS)
219 case IOCTL_VIDEO_SET_COLOR_REGISTERS:
220 return "IOCTL_VIDEO_SET_COLOR_REGISTERS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x107, METHOD_BUFFERED, FILE_ANY_ACCESS)
221 case IOCTL_VIDEO_ENABLE_CURSOR:
222 return "IOCTL_VIDEO_ENABLE_CURSOR"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x108, METHOD_BUFFERED, FILE_ANY_ACCESS)
223 case IOCTL_VIDEO_DISABLE_CURSOR:
224 return "IOCTL_VIDEO_DISABLE_CURSOR"; // CTL_CODE (FILE_DEVICE_VIDEO, 0x109, METHOD_BUFFERED, FILE_ANY_ACCESS)
225 case IOCTL_VIDEO_SET_CURSOR_ATTR:
226 return "IOCTL_VIDEO_SET_CURSOR_ATTR"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10a, METHOD_BUFFERED, FILE_ANY_ACCESS)
227 case IOCTL_VIDEO_QUERY_CURSOR_ATTR:
228 return "IOCTL_VIDEO_QUERY_CURSOR_ATTR"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10b, METHOD_BUFFERED, FILE_ANY_ACCESS)
229 case IOCTL_VIDEO_SET_CURSOR_POSITION:
230 return "IOCTL_VIDEO_SET_CURSOR_POSITION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10c, METHOD_BUFFERED, FILE_ANY_ACCESS)
231 case IOCTL_VIDEO_QUERY_CURSOR_POSITION:
232 return "IOCTL_VIDEO_QUERY_CURSOR_POSITION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10d, METHOD_BUFFERED, FILE_ANY_ACCESS)
233 case IOCTL_VIDEO_ENABLE_POINTER:
234 return "IOCTL_VIDEO_ENABLE_POINTER"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10e, METHOD_BUFFERED, FILE_ANY_ACCESS)
235 case IOCTL_VIDEO_DISABLE_POINTER:
236 return "IOCTL_VIDEO_DISABLE_POINTER"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10f, METHOD_BUFFERED, FILE_ANY_ACCESS)
237 case IOCTL_VIDEO_SET_POINTER_ATTR:
238 return "IOCTL_VIDEO_SET_POINTER_ATTR"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x110, METHOD_BUFFERED, FILE_ANY_ACCESS)
239 case IOCTL_VIDEO_QUERY_POINTER_ATTR:
240 return "IOCTL_VIDEO_QUERY_POINTER_ATTR"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x111, METHOD_BUFFERED, FILE_ANY_ACCESS)
241 case IOCTL_VIDEO_SET_POINTER_POSITION:
242 return "IOCTL_VIDEO_SET_POINTER_POSITION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x112, METHOD_BUFFERED, FILE_ANY_ACCESS)
243 case IOCTL_VIDEO_QUERY_POINTER_POSITION:
244 return "IOCTL_VIDEO_QUERY_POINTER_POSITION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x113, METHOD_BUFFERED, FILE_ANY_ACCESS)
245 case IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES:
246 return "IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x114, METHOD_BUFFERED, FILE_ANY_ACCESS)
247 case IOCTL_VIDEO_GET_BANK_SELECT_CODE:
248 return "IOCTL_VIDEO_GET_BANK_SELECT_CODE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x115, METHOD_BUFFERED, FILE_ANY_ACCESS)
249 case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
250 return "IOCTL_VIDEO_MAP_VIDEO_MEMORY"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x116, METHOD_BUFFERED, FILE_ANY_ACCESS)
251 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
252 return "IOCTL_VIDEO_UNMAP_VIDEO_MEMORY"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x117, METHOD_BUFFERED, FILE_ANY_ACCESS)
253 case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES:
254 return "IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x118, METHOD_BUFFERED, FILE_ANY_ACCESS)
255 case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES:
256 return "IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x119, METHOD_BUFFERED, FILE_ANY_ACCESS)
257 case IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES:
258 return "IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11a, METHOD_BUFFERED, FILE_ANY_ACCESS)
259 case IOCTL_VIDEO_SET_POWER_MANAGEMENT:
260 return "IOCTL_VIDEO_SET_POWER_MANAGEMENT"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11b, METHOD_BUFFERED, FILE_ANY_ACCESS)
261 case IOCTL_VIDEO_GET_POWER_MANAGEMENT:
262 return "IOCTL_VIDEO_GET_POWER_MANAGEMENT"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11c, METHOD_BUFFERED, FILE_ANY_ACCESS)
263 case IOCTL_VIDEO_SHARE_VIDEO_MEMORY:
264 return "IOCTL_VIDEO_SHARE_VIDEO_MEMORY"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11d, METHOD_BUFFERED, FILE_ANY_ACCESS)
265 case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY:
266 return "IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11e, METHOD_BUFFERED, FILE_ANY_ACCESS)
267 case IOCTL_VIDEO_SET_COLOR_LUT_DATA:
268 return "IOCTL_VIDEO_SET_COLOR_LUT_DATA"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11f, METHOD_BUFFERED, FILE_ANY_ACCESS)
269 case IOCTL_VIDEO_GET_CHILD_STATE:
270 return "IOCTL_VIDEO_GET_CHILD_STATE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x120, METHOD_BUFFERED, FILE_ANY_ACCESS)
271 case IOCTL_VIDEO_VALIDATE_CHILD_STATE_CONFIGURATION:
272 return "IOCTL_VIDEO_VALIDATE_CHILD_STATE_CONFIGURATION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x121, METHOD_BUFFERED, FILE_ANY_ACCESS)
273 case IOCTL_VIDEO_SET_CHILD_STATE_CONFIGURATION:
274 return "IOCTL_VIDEO_SET_CHILD_STATE_CONFIGURATION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x122, METHOD_BUFFERED, FILE_ANY_ACCESS)
275 case IOCTL_VIDEO_SWITCH_DUALVIEW:
276 return "IOCTL_VIDEO_SWITCH_DUALVIEW"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x123, METHOD_BUFFERED, FILE_ANY_ACCESS)
277 case IOCTL_VIDEO_SET_BANK_POSITION:
278 return "IOCTL_VIDEO_SET_BANK_POSITION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x124, METHOD_BUFFERED, FILE_ANY_ACCESS)
279 case IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS:
280 return "IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x125, METHOD_BUFFERED, FILE_ANY_ACCESS)
281 case IOCTL_VIDEO_QUERY_DISPLAY_BRIGHTNESS:
282 return "IOCTL_VIDEO_QUERY_DISPLAY_BRIGHTNESS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x126, METHOD_BUFFERED, FILE_ANY_ACCESS)
283 case IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS:
284 return "IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x127, METHOD_BUFFERED, FILE_ANY_ACCESS)
285 }
286
287 return "<unknown ioctl code";
288 }
289
290 static
291 NTSTATUS
292 VideoPortInitWin32kCallbacks(
293 IN PDEVICE_OBJECT DeviceObject,
294 PVIDEO_WIN32K_CALLBACKS Win32kCallbacks,
295 ULONG BufferLength)
296 {
297 if (BufferLength < sizeof(VIDEO_WIN32K_CALLBACKS))
298 {
299 return STATUS_BUFFER_TOO_SMALL;
300 }
301
302 /* Save the callout function globally */
303 Win32kCallout = Win32kCallbacks->Callout;
304
305 /* Return reasonable values to win32k */
306 Win32kCallbacks->bACPI = FALSE;
307 Win32kCallbacks->pPhysDeviceObject = DeviceObject;
308 Win32kCallbacks->DualviewFlags = 0;
309
310 return STATUS_SUCCESS;
311 }
312
313 static
314 NTSTATUS
315 VideoPortForwardDeviceControl(
316 IN PDEVICE_OBJECT DeviceObject,
317 IN PIRP Irp)
318 {
319 PIO_STACK_LOCATION IrpStack;
320 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
321 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
322 VIDEO_REQUEST_PACKET vrp;
323
324 TRACE_(VIDEOPRT, "VideoPortForwardDeviceControl\n");
325
326 IrpStack = IoGetCurrentIrpStackLocation(Irp);
327 DeviceExtension = DeviceObject->DeviceExtension;
328 DriverExtension = DeviceExtension->DriverExtension;
329
330 /* Translate the IRP to a VRP */
331 vrp.StatusBlock = (PSTATUS_BLOCK)&Irp->IoStatus;
332 vrp.IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
333
334 INFO_(VIDEOPRT, "- IoControlCode: %x\n", vrp.IoControlCode);
335
336 /* We're assuming METHOD_BUFFERED */
337 vrp.InputBuffer = Irp->AssociatedIrp.SystemBuffer;
338 vrp.InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
339 vrp.OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
340 vrp.OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
341
342 /* Call the Miniport Driver with the VRP */
343 DriverExtension->InitializationData.HwStartIO(&DeviceExtension->MiniPortDeviceExtension,
344 &vrp);
345
346 INFO_(VIDEOPRT, "- Returned status: %x\n", Irp->IoStatus.Status);
347
348 /* Map from win32 error codes to NT status values. */
349 switch (Irp->IoStatus.Status)
350 {
351 case NO_ERROR:
352 return STATUS_SUCCESS;
353 case ERROR_NOT_ENOUGH_MEMORY:
354 return STATUS_INSUFFICIENT_RESOURCES;
355 case ERROR_MORE_DATA:
356 return STATUS_BUFFER_OVERFLOW;
357 case ERROR_INVALID_FUNCTION:
358 return STATUS_NOT_IMPLEMENTED;
359 case ERROR_INVALID_PARAMETER:
360 return STATUS_INVALID_PARAMETER;
361 case ERROR_INSUFFICIENT_BUFFER:
362 return STATUS_BUFFER_TOO_SMALL;
363 case ERROR_DEV_NOT_EXIST:
364 return STATUS_DEVICE_DOES_NOT_EXIST;
365 case ERROR_IO_PENDING:
366 return STATUS_PENDING;
367 default:
368 return STATUS_UNSUCCESSFUL;
369 }
370 }
371
372 /*
373 * IntVideoPortDispatchDeviceControl
374 *
375 * Answer requests for device control calls.
376 *
377 * Run Level
378 * PASSIVE_LEVEL
379 */
380 NTSTATUS
381 NTAPI
382 IntVideoPortDispatchDeviceControl(
383 IN PDEVICE_OBJECT DeviceObject,
384 IN PIRP Irp)
385 {
386 PIO_STACK_LOCATION IrpStack;
387 NTSTATUS Status;
388 ULONG IoControlCode;
389
390 TRACE_(VIDEOPRT, "IntVideoPortDispatchDeviceControl\n");
391
392 IrpStack = IoGetCurrentIrpStackLocation(Irp);
393
394 IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
395
396 INFO_(VIDEOPRT, "- IoControlCode: %x: %s\n", IoControlCode, IoctlName(IoControlCode));
397
398 switch(IoControlCode)
399 {
400 case IOCTL_VIDEO_INIT_WIN32K_CALLBACKS:
401 INFO_(VIDEOPRT, "- IOCTL_VIDEO_INIT_WIN32K_CALLBACKS\n");
402 Status = VideoPortInitWin32kCallbacks(DeviceObject,
403 Irp->AssociatedIrp.SystemBuffer,
404 IrpStack->Parameters.DeviceIoControl.InputBufferLength);
405 break;
406
407 default:
408 /* Forward to the Miniport Driver */
409 Status = VideoPortForwardDeviceControl(DeviceObject, Irp);
410 break;
411 }
412
413 INFO_(VIDEOPRT, "- Returned status: %x\n", Irp->IoStatus.Status);
414
415 Irp->IoStatus.Status = Status;
416 IoCompleteRequest(Irp, IO_NO_INCREMENT);
417
418 return Status;
419 }
420
421 /*
422 * IntVideoPortWrite
423 *
424 * This is a bit of a hack. We want to take ownership of the display as late
425 * as possible, just before the switch to graphics mode. Win32k knows when
426 * this happens, we don't. So we need Win32k to inform us. This could be done
427 * using an IOCTL, but there's no way of knowing which IOCTL codes are unused
428 * in the communication between GDI driver and miniport driver. So we use
429 * IRP_MJ_WRITE as the signal that win32k is ready to switch to graphics mode,
430 * since we know for certain that there is no read/write activity going on
431 * between GDI and miniport drivers.
432 * We don't actually need the data that is passed, we just trigger on the fact
433 * that an IRP_MJ_WRITE was sent.
434 *
435 * Run Level
436 * PASSIVE_LEVEL
437 */
438 NTSTATUS
439 NTAPI
440 IntVideoPortDispatchWrite(
441 IN PDEVICE_OBJECT DeviceObject,
442 IN PIRP Irp)
443 {
444 PIO_STACK_LOCATION piosStack = IoGetCurrentIrpStackLocation(Irp);
445 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
446 NTSTATUS nErrCode;
447
448 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
449
450 /*
451 * Storing the device extension pointer in a static variable is an
452 * ugly hack. Unfortunately, we need it in IntVideoPortResetDisplayParameters
453 * and InbvNotifyDisplayOwnershipLost doesn't allow us to pass a userdata
454 * parameter. On the bright side, the DISPLAY device is opened
455 * exclusively, so there can be only one device extension active at
456 * any point in time.
457 *
458 * FIXME: We should process all opened display devices in
459 * IntVideoPortResetDisplayParameters.
460 */
461 ResetDisplayParametersDeviceExtension = DeviceExtension;
462 InbvNotifyDisplayOwnershipLost(IntVideoPortResetDisplayParameters);
463
464 nErrCode = STATUS_SUCCESS;
465 Irp->IoStatus.Information = piosStack->Parameters.Write.Length;
466 Irp->IoStatus.Status = nErrCode;
467 IoCompleteRequest(Irp, IO_NO_INCREMENT);
468
469 return nErrCode;
470 }
471
472 NTSTATUS
473 NTAPI
474 IntVideoPortPnPStartDevice(
475 IN PDEVICE_OBJECT DeviceObject,
476 IN PIRP Irp)
477 {
478 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
479 PDRIVER_OBJECT DriverObject;
480 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
481 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
482 PCM_RESOURCE_LIST AllocatedResources;
483
484 /* Get the initialization data we saved in VideoPortInitialize.*/
485 DriverObject = DeviceObject->DriverObject;
486 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
487 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
488
489 /* Store some resources in the DeviceExtension. */
490 AllocatedResources = Stack->Parameters.StartDevice.AllocatedResources;
491 if (AllocatedResources != NULL)
492 {
493 CM_FULL_RESOURCE_DESCRIPTOR *FullList;
494 CM_PARTIAL_RESOURCE_DESCRIPTOR *Descriptor;
495 ULONG ResourceCount;
496 ULONG ResourceListSize;
497
498 /* Save the resource list */
499 ResourceCount = AllocatedResources->List[0].PartialResourceList.Count;
500 ResourceListSize =
501 FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
502 PartialDescriptors[ResourceCount]);
503 DeviceExtension->AllocatedResources = ExAllocatePool(PagedPool, ResourceListSize);
504 if (DeviceExtension->AllocatedResources == NULL)
505 {
506 return STATUS_INSUFFICIENT_RESOURCES;
507 }
508
509 RtlCopyMemory(DeviceExtension->AllocatedResources,
510 AllocatedResources,
511 ResourceListSize);
512
513 /* Get the interrupt level/vector - needed by HwFindAdapter sometimes */
514 for (FullList = AllocatedResources->List;
515 FullList < AllocatedResources->List + AllocatedResources->Count;
516 FullList++)
517 {
518 INFO_(VIDEOPRT, "InterfaceType %u BusNumber List %u Device BusNumber %u Version %u Revision %u\n",
519 FullList->InterfaceType, FullList->BusNumber, DeviceExtension->SystemIoBusNumber, FullList->PartialResourceList.Version, FullList->PartialResourceList.Revision);
520
521 /* FIXME: Is this ASSERT ok for resources from the PNP manager? */
522 ASSERT(FullList->InterfaceType == PCIBus);
523 ASSERT(FullList->BusNumber == DeviceExtension->SystemIoBusNumber);
524 ASSERT(1 == FullList->PartialResourceList.Version);
525 ASSERT(1 == FullList->PartialResourceList.Revision);
526 for (Descriptor = FullList->PartialResourceList.PartialDescriptors;
527 Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count;
528 Descriptor++)
529 {
530 if (Descriptor->Type == CmResourceTypeInterrupt)
531 {
532 DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level;
533 DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector;
534 if (Descriptor->ShareDisposition == CmResourceShareShared)
535 DeviceExtension->InterruptShared = TRUE;
536 else
537 DeviceExtension->InterruptShared = FALSE;
538 }
539 }
540 }
541 }
542
543 INFO_(VIDEOPRT, "Interrupt level: 0x%x Interrupt Vector: 0x%x\n",
544 DeviceExtension->InterruptLevel,
545 DeviceExtension->InterruptVector);
546
547 /* Create adapter device object. */
548 return IntVideoPortFindAdapter(DriverObject,
549 DriverExtension,
550 DeviceObject);
551 }
552
553
554 NTSTATUS
555 NTAPI
556 IntVideoPortForwardIrpAndWaitCompletionRoutine(
557 PDEVICE_OBJECT Fdo,
558 PIRP Irp,
559 PVOID Context)
560 {
561 PKEVENT Event = Context;
562
563 if (Irp->PendingReturned)
564 KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
565
566 return STATUS_MORE_PROCESSING_REQUIRED;
567 }
568
569 NTSTATUS
570 NTAPI
571 IntVideoPortQueryBusRelations(PDEVICE_OBJECT DeviceObject, PIRP Irp)
572 {
573 PDEVICE_RELATIONS DeviceRelations;
574 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
575 PVIDEO_PORT_CHILD_EXTENSION ChildExtension;
576 ULONG i;
577 PLIST_ENTRY CurrentEntry;
578
579 /* Count the children */
580 i = 0;
581 CurrentEntry = DeviceExtension->ChildDeviceList.Flink;
582 while (CurrentEntry != &DeviceExtension->ChildDeviceList)
583 {
584 i++;
585 CurrentEntry = CurrentEntry->Flink;
586 }
587
588 if (i == 0)
589 return Irp->IoStatus.Status;
590
591 DeviceRelations = ExAllocatePool(PagedPool,
592 sizeof(DEVICE_RELATIONS) + ((i - 1) * sizeof(PVOID)));
593 if (!DeviceRelations) return STATUS_NO_MEMORY;
594
595 DeviceRelations->Count = i;
596
597 /* Add the children */
598 i = 0;
599 CurrentEntry = DeviceExtension->ChildDeviceList.Flink;
600 while (CurrentEntry != &DeviceExtension->ChildDeviceList)
601 {
602 ChildExtension = CONTAINING_RECORD(CurrentEntry, VIDEO_PORT_CHILD_EXTENSION, ListEntry);
603
604 ObReferenceObject(ChildExtension->PhysicalDeviceObject);
605 DeviceRelations->Objects[i] = ChildExtension->PhysicalDeviceObject;
606
607 i++;
608 CurrentEntry = CurrentEntry->Flink;
609 }
610
611 INFO_(VIDEOPRT, "Reported %d PDOs\n", i);
612 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
613
614 return STATUS_SUCCESS;
615 }
616
617 NTSTATUS
618 NTAPI
619 IntVideoPortForwardIrpAndWait(PDEVICE_OBJECT DeviceObject, PIRP Irp)
620 {
621 KEVENT Event;
622 NTSTATUS Status;
623 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension =
624 (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
625
626 KeInitializeEvent(&Event, NotificationEvent, FALSE);
627 IoCopyCurrentIrpStackLocationToNext(Irp);
628 IoSetCompletionRoutine(Irp,
629 IntVideoPortForwardIrpAndWaitCompletionRoutine,
630 &Event,
631 TRUE,
632 TRUE,
633 TRUE);
634
635 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
636 if (Status == STATUS_PENDING)
637 {
638 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
639 Status = Irp->IoStatus.Status;
640 }
641
642 return Status;
643 }
644
645 NTSTATUS
646 NTAPI
647 IntVideoPortDispatchFdoPnp(
648 IN PDEVICE_OBJECT DeviceObject,
649 IN PIRP Irp)
650 {
651 PIO_STACK_LOCATION IrpSp;
652 NTSTATUS Status;
653 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
654
655 IrpSp = IoGetCurrentIrpStackLocation(Irp);
656
657 switch (IrpSp->MinorFunction)
658 {
659 case IRP_MN_START_DEVICE:
660 Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
661 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
662 Status = IntVideoPortPnPStartDevice(DeviceObject, Irp);
663 Irp->IoStatus.Status = Status;
664 Irp->IoStatus.Information = 0;
665 IoCompleteRequest(Irp, IO_NO_INCREMENT);
666 break;
667
668 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
669 Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
670 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
671 Status = IntVideoPortFilterResourceRequirements(DeviceObject, Irp);
672 Irp->IoStatus.Status = Status;
673 Irp->IoStatus.Information = 0;
674 IoCompleteRequest(Irp, IO_NO_INCREMENT);
675 break;
676
677 case IRP_MN_QUERY_DEVICE_RELATIONS:
678 if (IrpSp->Parameters.QueryDeviceRelations.Type != BusRelations)
679 {
680 IoSkipCurrentIrpStackLocation(Irp);
681 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
682 }
683 else
684 {
685 Status = IntVideoPortQueryBusRelations(DeviceObject, Irp);
686 Irp->IoStatus.Status = Status;
687 IoCompleteRequest(Irp, IO_NO_INCREMENT);
688 }
689 break;
690
691 case IRP_MN_REMOVE_DEVICE:
692 case IRP_MN_QUERY_REMOVE_DEVICE:
693 case IRP_MN_CANCEL_REMOVE_DEVICE:
694 case IRP_MN_SURPRISE_REMOVAL:
695
696 case IRP_MN_STOP_DEVICE:
697 Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
698 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
699 Status = STATUS_SUCCESS;
700 Irp->IoStatus.Status = Status;
701 Irp->IoStatus.Information = 0;
702 IoCompleteRequest(Irp, IO_NO_INCREMENT);
703 break;
704
705 case IRP_MN_QUERY_STOP_DEVICE:
706 case IRP_MN_CANCEL_STOP_DEVICE:
707 Status = STATUS_SUCCESS;
708 Irp->IoStatus.Status = STATUS_SUCCESS;
709 Irp->IoStatus.Information = 0;
710 IoCompleteRequest(Irp, IO_NO_INCREMENT);
711 break;
712
713 default:
714 Status = Irp->IoStatus.Status;
715 IoCompleteRequest(Irp, IO_NO_INCREMENT);
716 break;
717 }
718
719 return Status;
720 }
721
722 NTSTATUS
723 NTAPI
724 IntVideoPortDispatchPnp(
725 IN PDEVICE_OBJECT DeviceObject,
726 IN PIRP Irp)
727 {
728 PVIDEO_PORT_COMMON_EXTENSION CommonExtension = DeviceObject->DeviceExtension;
729
730 if (CommonExtension->Fdo)
731 return IntVideoPortDispatchFdoPnp(DeviceObject, Irp);
732 else
733 return IntVideoPortDispatchPdoPnp(DeviceObject, Irp);
734 }
735
736 NTSTATUS
737 NTAPI
738 IntVideoPortDispatchCleanup(
739 IN PDEVICE_OBJECT DeviceObject,
740 IN PIRP Irp)
741 {
742 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
743
744 DeviceExtension = DeviceObject->DeviceExtension;
745 RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
746
747 Irp->IoStatus.Status = STATUS_SUCCESS;
748 Irp->IoStatus.Information = 0;
749 IoCompleteRequest(Irp, IO_NO_INCREMENT);
750
751 return STATUS_SUCCESS;
752 }
753
754 NTSTATUS
755 NTAPI
756 IntVideoPortDispatchPower(
757 IN PDEVICE_OBJECT DeviceObject,
758 IN PIRP Irp)
759 {
760 return STATUS_NOT_IMPLEMENTED;
761 }
762
763 NTSTATUS
764 NTAPI
765 IntVideoPortDispatchSystemControl(
766 IN PDEVICE_OBJECT DeviceObject,
767 IN PIRP Irp)
768 {
769 return STATUS_NOT_IMPLEMENTED;
770 }
771
772 VOID
773 NTAPI
774 IntVideoPortUnload(PDRIVER_OBJECT DriverObject)
775 {
776 }