[VIDEOPRT/WINSERV] Move mapping the BIOS memory from winsrv to videoprt, where it...
[reactos.git] / reactos / win32ss / drivers / videoprt / videoprt.c
1 /*
2 * VideoPort driver
3 *
4 * Copyright (C) 2002-2004, 2007 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
23 #include "videoprt.h"
24
25 /* GLOBAL VARIABLES ***********************************************************/
26
27 ULONG CsrssInitialized = FALSE;
28 PKPROCESS Csrss = NULL;
29 ULONG VideoPortDeviceNumber = 0;
30
31 /* PRIVATE FUNCTIONS **********************************************************/
32
33 ULONG
34 NTAPI
35 DriverEntry(
36 IN PVOID Context1,
37 IN PVOID Context2)
38 {
39 return STATUS_SUCCESS;
40 }
41
42 PVOID
43 NTAPI
44 IntVideoPortImageDirectoryEntryToData(
45 PVOID BaseAddress,
46 ULONG Directory)
47 {
48 PIMAGE_NT_HEADERS NtHeader;
49 ULONG Va;
50
51 NtHeader = RtlImageNtHeader(BaseAddress);
52 if (NtHeader == NULL)
53 return NULL;
54
55 if (Directory >= NtHeader->OptionalHeader.NumberOfRvaAndSizes)
56 return NULL;
57
58 Va = NtHeader->OptionalHeader.DataDirectory[Directory].VirtualAddress;
59 if (Va == 0)
60 return NULL;
61
62 return (PVOID)((ULONG_PTR)BaseAddress + Va);
63 }
64
65 VOID
66 NTAPI
67 IntVideoPortDeferredRoutine(
68 IN PKDPC Dpc,
69 IN PVOID DeferredContext,
70 IN PVOID SystemArgument1,
71 IN PVOID SystemArgument2)
72 {
73 PVOID HwDeviceExtension =
74 &((PVIDEO_PORT_DEVICE_EXTENSION)DeferredContext)->MiniPortDeviceExtension;
75 ((PMINIPORT_DPC_ROUTINE)SystemArgument1)(HwDeviceExtension, SystemArgument2);
76 }
77
78 NTSTATUS
79 NTAPI
80 IntVideoPortCreateAdapterDeviceObject(
81 IN PDRIVER_OBJECT DriverObject,
82 IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension,
83 IN PDEVICE_OBJECT PhysicalDeviceObject,
84 OUT PDEVICE_OBJECT *DeviceObject OPTIONAL)
85 {
86 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
87 ULONG DeviceNumber;
88 ULONG PciSlotNumber;
89 PCI_SLOT_NUMBER SlotNumber;
90 ULONG Size;
91 NTSTATUS Status;
92 WCHAR DeviceBuffer[20];
93 UNICODE_STRING DeviceName;
94 PDEVICE_OBJECT DeviceObject_;
95
96 if (DeviceObject == NULL)
97 DeviceObject = &DeviceObject_;
98
99 /*
100 * Find the first free device number that can be used for video device
101 * object names and symlinks.
102 */
103 DeviceNumber = VideoPortDeviceNumber;
104 if (DeviceNumber == 0xFFFFFFFF)
105 {
106 WARN_(VIDEOPRT, "Can't find free device number\n");
107 return STATUS_UNSUCCESSFUL;
108 }
109
110 /*
111 * Create the device object.
112 */
113
114 /* Create a unicode device name. */
115 swprintf(DeviceBuffer, L"\\Device\\Video%lu", DeviceNumber);
116 RtlInitUnicodeString(&DeviceName, DeviceBuffer);
117
118 INFO_(VIDEOPRT, "HwDeviceExtension size is: 0x%x\n",
119 DriverExtension->InitializationData.HwDeviceExtensionSize);
120
121 /* Create the device object. */
122 Size = sizeof(VIDEO_PORT_DEVICE_EXTENSION) +
123 DriverExtension->InitializationData.HwDeviceExtensionSize;
124 Status = IoCreateDevice(DriverObject,
125 Size,
126 &DeviceName,
127 FILE_DEVICE_VIDEO,
128 0,
129 TRUE,
130 DeviceObject);
131
132 if (!NT_SUCCESS(Status))
133 {
134 WARN_(VIDEOPRT, "IoCreateDevice call failed with status 0x%08x\n", Status);
135 return Status;
136 }
137
138 /*
139 * Set the buffering strategy here. If you change this, remember
140 * to change VidDispatchDeviceControl too.
141 */
142
143 (*DeviceObject)->Flags |= DO_BUFFERED_IO;
144
145 /* Initialize device extension. */
146 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)((*DeviceObject)->DeviceExtension);
147 DeviceExtension->Common.Fdo = TRUE;
148 DeviceExtension->DeviceNumber = DeviceNumber;
149 DeviceExtension->DriverObject = DriverObject;
150 DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
151 DeviceExtension->FunctionalDeviceObject = *DeviceObject;
152 DeviceExtension->DriverExtension = DriverExtension;
153
154 InitializeListHead(&DeviceExtension->ChildDeviceList);
155
156 /* Get the registry path associated with this device. */
157 Status = IntCreateRegistryPath(&DriverExtension->RegistryPath,
158 &DeviceExtension->RegistryPath);
159 if (!NT_SUCCESS(Status))
160 {
161 WARN_(VIDEOPRT, "IntCreateRegistryPath() call failed with status 0x%08x\n", Status);
162 IoDeleteDevice(*DeviceObject);
163 *DeviceObject = NULL;
164 return Status;
165 }
166
167 if (PhysicalDeviceObject != NULL)
168 {
169 /* Get bus number from the upper level bus driver. */
170 Size = sizeof(ULONG);
171 Status = IoGetDeviceProperty(PhysicalDeviceObject,
172 DevicePropertyBusNumber,
173 Size,
174 &DeviceExtension->SystemIoBusNumber,
175 &Size);
176 if (!NT_SUCCESS(Status))
177 {
178 WARN_(VIDEOPRT, "Couldn't get an information from bus driver. We will try to\n"
179 "use legacy detection method, but even that doesn't mean that\n"
180 "it will work.\n");
181 DeviceExtension->PhysicalDeviceObject = NULL;
182 }
183 }
184
185 DeviceExtension->AdapterInterfaceType =
186 DriverExtension->InitializationData.AdapterInterfaceType;
187
188 if (PhysicalDeviceObject != NULL)
189 {
190 /* Get bus type from the upper level bus driver. */
191 Size = sizeof(ULONG);
192 IoGetDeviceProperty(PhysicalDeviceObject,
193 DevicePropertyLegacyBusType,
194 Size,
195 &DeviceExtension->AdapterInterfaceType,
196 &Size);
197
198 /* Get bus device address from the upper level bus driver. */
199 Size = sizeof(ULONG);
200 IoGetDeviceProperty(PhysicalDeviceObject,
201 DevicePropertyAddress,
202 Size,
203 &PciSlotNumber,
204 &Size);
205
206 /* Convert slotnumber to PCI_SLOT_NUMBER */
207 SlotNumber.u.AsULONG = 0;
208 SlotNumber.u.bits.DeviceNumber = (PciSlotNumber >> 16) & 0xFFFF;
209 SlotNumber.u.bits.FunctionNumber = PciSlotNumber & 0xFFFF;
210 DeviceExtension->SystemIoSlotNumber = SlotNumber.u.AsULONG;
211 }
212
213 InitializeListHead(&DeviceExtension->AddressMappingListHead);
214 InitializeListHead(&DeviceExtension->DmaAdapterList);
215
216 KeInitializeDpc(&DeviceExtension->DpcObject,
217 IntVideoPortDeferredRoutine,
218 DeviceExtension);
219
220 KeInitializeMutex(&DeviceExtension->DeviceLock, 0);
221
222 /* Attach the device. */
223 if (PhysicalDeviceObject != NULL)
224 DeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack(
225 *DeviceObject,
226 PhysicalDeviceObject);
227
228 IntCreateNewRegistryPath(DeviceExtension);
229 IntSetupDeviceSettingsKey(DeviceExtension);
230
231 /* Remove the initailizing flag */
232 (*DeviceObject)->Flags &= ~DO_DEVICE_INITIALIZING;
233 return STATUS_SUCCESS;
234 }
235
236
237 NTSTATUS
238 NTAPI
239 IntVideoPortFindAdapter(
240 IN PDRIVER_OBJECT DriverObject,
241 IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension,
242 IN PDEVICE_OBJECT DeviceObject)
243 {
244 WCHAR DeviceVideoBuffer[20];
245 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
246 SIZE_T Size;
247 NTSTATUS Status;
248 VIDEO_PORT_CONFIG_INFO ConfigInfo;
249 SYSTEM_BASIC_INFORMATION SystemBasicInfo;
250 UCHAR Again = FALSE;
251 WCHAR DeviceBuffer[20];
252 UNICODE_STRING DeviceName;
253 WCHAR SymlinkBuffer[20];
254 UNICODE_STRING SymlinkName;
255 BOOL LegacyDetection = FALSE;
256 ULONG DeviceNumber;
257
258 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
259 DeviceNumber = DeviceExtension->DeviceNumber;
260
261 /* Setup a ConfigInfo structure that we will pass to HwFindAdapter. */
262 RtlZeroMemory(&ConfigInfo, sizeof(VIDEO_PORT_CONFIG_INFO));
263 ConfigInfo.Length = sizeof(VIDEO_PORT_CONFIG_INFO);
264 ConfigInfo.AdapterInterfaceType = DeviceExtension->AdapterInterfaceType;
265 if (ConfigInfo.AdapterInterfaceType == PCIBus)
266 ConfigInfo.InterruptMode = LevelSensitive;
267 else
268 ConfigInfo.InterruptMode = Latched;
269 ConfigInfo.DriverRegistryPath = DriverExtension->RegistryPath.Buffer;
270 ConfigInfo.VideoPortGetProcAddress = IntVideoPortGetProcAddress;
271 ConfigInfo.SystemIoBusNumber = DeviceExtension->SystemIoBusNumber;
272 ConfigInfo.BusInterruptLevel = DeviceExtension->InterruptLevel;
273 ConfigInfo.BusInterruptVector = DeviceExtension->InterruptVector;
274
275 Size = sizeof(SystemBasicInfo);
276 Status = ZwQuerySystemInformation(SystemBasicInformation,
277 &SystemBasicInfo,
278 Size,
279 &Size);
280 if (NT_SUCCESS(Status))
281 {
282 ConfigInfo.SystemMemorySize = SystemBasicInfo.NumberOfPhysicalPages *
283 SystemBasicInfo.PageSize;
284 }
285
286 /*
287 * Call miniport HwVidFindAdapter entry point to detect if
288 * particular device is present. There are two possible code
289 * paths. The first one is for Legacy drivers (NT4) and cases
290 * when we don't have information about what bus we're on. The
291 * second case is the standard one for Plug & Play drivers.
292 */
293 if (DeviceExtension->PhysicalDeviceObject == NULL)
294 {
295 LegacyDetection = TRUE;
296 }
297
298 if (LegacyDetection)
299 {
300 ULONG BusNumber, MaxBuses;
301
302 MaxBuses = DeviceExtension->AdapterInterfaceType == PCIBus ? PCI_MAX_BRIDGE_NUMBER : 1;
303
304 for (BusNumber = 0; BusNumber < MaxBuses; BusNumber++)
305 {
306 DeviceExtension->SystemIoBusNumber =
307 ConfigInfo.SystemIoBusNumber = BusNumber;
308
309 RtlZeroMemory(&DeviceExtension->MiniPortDeviceExtension,
310 DriverExtension->InitializationData.HwDeviceExtensionSize);
311
312 /* FIXME: Need to figure out what string to pass as param 3. */
313 Status = DriverExtension->InitializationData.HwFindAdapter(
314 &DeviceExtension->MiniPortDeviceExtension,
315 DriverExtension->HwContext,
316 NULL,
317 &ConfigInfo,
318 &Again);
319
320 if (Status == ERROR_DEV_NOT_EXIST)
321 {
322 continue;
323 }
324 else if (Status == NO_ERROR)
325 {
326 break;
327 }
328 else
329 {
330 ERR_(VIDEOPRT, "HwFindAdapter call failed with error 0x%X\n", Status);
331 goto Failure;
332 }
333 }
334 }
335 else
336 {
337 /* FIXME: Need to figure out what string to pass as param 3. */
338 Status = DriverExtension->InitializationData.HwFindAdapter(
339 &DeviceExtension->MiniPortDeviceExtension,
340 DriverExtension->HwContext,
341 NULL,
342 &ConfigInfo,
343 &Again);
344 }
345
346 if (Status != NO_ERROR)
347 {
348 ERR_(VIDEOPRT, "HwFindAdapter call failed with error 0x%X\n", Status);
349 goto Failure;
350 }
351
352 /*
353 * Now we know the device is present, so let's do all additional tasks
354 * such as creating symlinks or setting up interrupts and timer.
355 */
356
357 /* Create a unicode device name. */
358 swprintf(DeviceBuffer, L"\\Device\\Video%lu", DeviceNumber);
359 RtlInitUnicodeString(&DeviceName, DeviceBuffer);
360
361 /* Create symbolic link "\??\DISPLAYx" */
362 swprintf(SymlinkBuffer, L"\\??\\DISPLAY%lu", DeviceNumber + 1);
363 RtlInitUnicodeString(&SymlinkName, SymlinkBuffer);
364 IoCreateSymbolicLink(&SymlinkName, &DeviceName);
365
366 /* Add entry to DEVICEMAP\VIDEO key in registry. */
367 swprintf(DeviceVideoBuffer, L"\\Device\\Video%d", DeviceNumber);
368 RtlWriteRegistryValue(
369 RTL_REGISTRY_DEVICEMAP,
370 L"VIDEO",
371 DeviceVideoBuffer,
372 REG_SZ,
373 DeviceExtension->RegistryPath.Buffer,
374 DeviceExtension->RegistryPath.Length + sizeof(UNICODE_NULL));
375
376 RtlWriteRegistryValue(
377 RTL_REGISTRY_DEVICEMAP,
378 L"VIDEO",
379 L"MaxObjectNumber",
380 REG_DWORD,
381 &DeviceNumber,
382 sizeof(DeviceNumber));
383
384 /* FIXME: Allocate hardware resources for device. */
385
386 /* Allocate interrupt for device. */
387 if (!IntVideoPortSetupInterrupt(DeviceObject, DriverExtension, &ConfigInfo))
388 {
389 Status = STATUS_INSUFFICIENT_RESOURCES;
390 goto Failure;
391 }
392
393 /* Allocate timer for device. */
394 if (!IntVideoPortSetupTimer(DeviceObject, DriverExtension))
395 {
396 if (DeviceExtension->InterruptObject != NULL)
397 IoDisconnectInterrupt(DeviceExtension->InterruptObject);
398 ERR_(VIDEOPRT, "IntVideoPortSetupTimer failed\n");
399 Status = STATUS_INSUFFICIENT_RESOURCES;
400 goto Failure;
401 }
402
403 /* Query children of the device. */
404 VideoPortEnumerateChildren(&DeviceExtension->MiniPortDeviceExtension, NULL);
405
406 INFO_(VIDEOPRT, "STATUS_SUCCESS\n");
407 return STATUS_SUCCESS;
408
409 Failure:
410 RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
411 if (DeviceExtension->NextDeviceObject)
412 IoDetachDevice(DeviceExtension->NextDeviceObject);
413 IoDeleteDevice(DeviceObject);
414 return Status;
415 }
416
417 VOID
418 FASTCALL
419 IntAttachToCSRSS(
420 PKPROCESS *CallingProcess,
421 PKAPC_STATE ApcState)
422 {
423 *CallingProcess = (PKPROCESS)PsGetCurrentProcess();
424 if (*CallingProcess != Csrss)
425 {
426 KeStackAttachProcess(Csrss, ApcState);
427 }
428 }
429
430 VOID
431 FASTCALL
432 IntDetachFromCSRSS(
433 PKPROCESS *CallingProcess,
434 PKAPC_STATE ApcState)
435 {
436 if (*CallingProcess != Csrss)
437 {
438 KeUnstackDetachProcess(ApcState);
439 }
440 }
441
442 /* PUBLIC FUNCTIONS ***********************************************************/
443
444 /*
445 * @implemented
446 */
447 ULONG
448 NTAPI
449 VideoPortInitialize(
450 IN PVOID Context1,
451 IN PVOID Context2,
452 IN PVIDEO_HW_INITIALIZATION_DATA HwInitializationData,
453 IN PVOID HwContext)
454 {
455 PDRIVER_OBJECT DriverObject = Context1;
456 PUNICODE_STRING RegistryPath = Context2;
457 NTSTATUS Status;
458 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
459 BOOLEAN PnpDriver = FALSE, LegacyDetection = FALSE;
460
461 TRACE_(VIDEOPRT, "VideoPortInitialize\n");
462
463 /* As a first thing do parameter checks. */
464 if (HwInitializationData->HwInitDataSize > sizeof(VIDEO_HW_INITIALIZATION_DATA))
465 {
466 ERR_(VIDEOPRT, "Invalid HwInitializationData\n");
467 return STATUS_REVISION_MISMATCH;
468 }
469
470 if ((HwInitializationData->HwFindAdapter == NULL) ||
471 (HwInitializationData->HwInitialize == NULL) ||
472 (HwInitializationData->HwStartIO == NULL))
473 {
474 ERR_(VIDEOPRT, "Invalid HwInitializationData\n");
475 return STATUS_INVALID_PARAMETER;
476 }
477
478 switch (HwInitializationData->HwInitDataSize)
479 {
480 /*
481 * NT4 drivers are special case, because we must use legacy method
482 * of detection instead of the Plug & Play one.
483 */
484 case SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA:
485 INFO_(VIDEOPRT, "We were loaded by a Windows NT miniport driver.\n");
486 break;
487
488 case SIZE_OF_W2K_VIDEO_HW_INITIALIZATION_DATA:
489 INFO_(VIDEOPRT, "We were loaded by a Windows 2000 miniport driver.\n");
490 break;
491
492 case sizeof(VIDEO_HW_INITIALIZATION_DATA):
493 INFO_(VIDEOPRT, "We were loaded by a Windows XP or later miniport driver.\n");
494 break;
495
496 default:
497 ERR_(VIDEOPRT, "Invalid HwInitializationData size.\n");
498 return STATUS_UNSUCCESSFUL;
499 }
500
501 /* Set dispatching routines */
502 DriverObject->MajorFunction[IRP_MJ_CREATE] = IntVideoPortDispatchOpen;
503 DriverObject->MajorFunction[IRP_MJ_CLOSE] = IntVideoPortDispatchClose;
504 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
505 IntVideoPortDispatchDeviceControl;
506 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
507 IntVideoPortDispatchDeviceControl;
508 DriverObject->MajorFunction[IRP_MJ_WRITE] =
509 IntVideoPortDispatchWrite; // ReactOS-specific hack
510 DriverObject->DriverUnload = IntVideoPortUnload;
511
512 /* Determine type of the miniport driver */
513 if ((HwInitializationData->HwInitDataSize >=
514 FIELD_OFFSET(VIDEO_HW_INITIALIZATION_DATA, HwQueryInterface)) &&
515 (HwInitializationData->HwSetPowerState != NULL) &&
516 (HwInitializationData->HwGetPowerState != NULL) &&
517 (HwInitializationData->HwGetVideoChildDescriptor != NULL))
518 {
519 INFO_(VIDEOPRT, "The miniport is a PnP miniport driver\n");
520 PnpDriver = TRUE;
521 }
522
523 /* Check if legacy detection should be applied */
524 if (!PnpDriver || HwContext)
525 {
526 INFO_(VIDEOPRT, "Legacy detection for adapter interface %d\n",
527 HwInitializationData->AdapterInterfaceType);
528
529 /* FIXME: Move the code for legacy detection
530 to another function and call it here */
531 LegacyDetection = TRUE;
532 }
533
534 /*
535 * NOTE:
536 * The driver extension can be already allocated in case that we were
537 * called by legacy driver and failed detecting device. Some miniport
538 * drivers in that case adjust parameters and call VideoPortInitialize
539 * again.
540 */
541 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
542 if (DriverExtension == NULL)
543 {
544 Status = IoAllocateDriverObjectExtension(DriverObject,
545 DriverObject,
546 sizeof(VIDEO_PORT_DRIVER_EXTENSION),
547 (PVOID *)&DriverExtension);
548 if (!NT_SUCCESS(Status))
549 {
550 ERR_(VIDEOPRT, "IoAllocateDriverObjectExtension failed 0x%x\n", Status);
551 return Status;
552 }
553
554 /*
555 * Save the registry path. This should be done only once even if
556 * VideoPortInitialize is called multiple times.
557 */
558 if (RegistryPath->Length != 0)
559 {
560 DriverExtension->RegistryPath.Length = 0;
561 DriverExtension->RegistryPath.MaximumLength =
562 RegistryPath->Length + sizeof(UNICODE_NULL);
563 DriverExtension->RegistryPath.Buffer =
564 ExAllocatePoolWithTag(
565 PagedPool,
566 DriverExtension->RegistryPath.MaximumLength,
567 'RTSU');
568 if (DriverExtension->RegistryPath.Buffer == NULL)
569 {
570 RtlInitUnicodeString(&DriverExtension->RegistryPath, NULL);
571 return STATUS_INSUFFICIENT_RESOURCES;
572 }
573
574 RtlCopyUnicodeString(&DriverExtension->RegistryPath, RegistryPath);
575 INFO_(VIDEOPRT, "RegistryPath: %wZ\n", &DriverExtension->RegistryPath);
576 }
577 else
578 {
579 RtlInitUnicodeString(&DriverExtension->RegistryPath, NULL);
580 }
581 }
582
583 /* Copy the correct miniport initialization data to the device extension. */
584 RtlCopyMemory(&DriverExtension->InitializationData,
585 HwInitializationData,
586 HwInitializationData->HwInitDataSize);
587 if (HwInitializationData->HwInitDataSize <
588 sizeof(VIDEO_HW_INITIALIZATION_DATA))
589 {
590 RtlZeroMemory((PVOID)((ULONG_PTR)&DriverExtension->InitializationData +
591 HwInitializationData->HwInitDataSize),
592 sizeof(VIDEO_HW_INITIALIZATION_DATA) -
593 HwInitializationData->HwInitDataSize);
594 }
595 DriverExtension->HwContext = HwContext;
596
597 /*
598 * Plug & Play drivers registers the device in AddDevice routine. For
599 * legacy drivers we must do it now.
600 */
601 if (LegacyDetection)
602 {
603 PDEVICE_OBJECT DeviceObject;
604
605 if (HwInitializationData->HwInitDataSize != SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA)
606 {
607 /* power management */
608 DriverObject->MajorFunction[IRP_MJ_POWER] = IntVideoPortDispatchPower;
609 }
610
611 Status = IntVideoPortCreateAdapterDeviceObject(DriverObject,
612 DriverExtension,
613 NULL,
614 &DeviceObject);
615 if (!NT_SUCCESS(Status))
616 {
617 ERR_(VIDEOPRT, "IntVideoPortCreateAdapterDeviceObject returned 0x%x\n", Status);
618 return Status;
619 }
620
621 Status = IntVideoPortFindAdapter(DriverObject, DriverExtension, DeviceObject);
622 if (NT_SUCCESS(Status))
623 VideoPortDeviceNumber++;
624 else
625 ERR_(VIDEOPRT, "IntVideoPortFindAdapter returned 0x%x\n", Status);
626
627 return Status;
628 }
629 else
630 {
631 DriverObject->DriverExtension->AddDevice = IntVideoPortAddDevice;
632 DriverObject->MajorFunction[IRP_MJ_PNP] = IntVideoPortDispatchPnp;
633 DriverObject->MajorFunction[IRP_MJ_POWER] = IntVideoPortDispatchPower;
634 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = IntVideoPortDispatchSystemControl;
635
636 return STATUS_SUCCESS;
637 }
638 }
639
640 /*
641 * @implemented
642 */
643 VOID
644 VideoPortDebugPrint(
645 IN VIDEO_DEBUG_LEVEL DebugPrintLevel,
646 IN PCHAR DebugMessage,
647 ...)
648 {
649 va_list ap;
650
651 va_start(ap, DebugMessage);
652 vDbgPrintEx(DPFLTR_IHVVIDEO_ID, DebugPrintLevel, DebugMessage, ap);
653 va_end(ap);
654 }
655
656 /*
657 * @unimplemented
658 */
659 VOID
660 NTAPI
661 VideoPortLogError(
662 IN PVOID HwDeviceExtension,
663 IN PVIDEO_REQUEST_PACKET Vrp OPTIONAL,
664 IN VP_STATUS ErrorCode,
665 IN ULONG UniqueId)
666 {
667 UNIMPLEMENTED;
668
669 INFO_(VIDEOPRT, "VideoPortLogError ErrorCode %d (0x%x) UniqueId %lu (0x%lx)\n",
670 ErrorCode, ErrorCode, UniqueId, UniqueId);
671 if (Vrp)
672 INFO_(VIDEOPRT, "Vrp->IoControlCode %lu (0x%lx)\n", Vrp->IoControlCode, Vrp->IoControlCode);
673 }
674
675 /*
676 * @implemented
677 */
678 UCHAR
679 NTAPI
680 VideoPortGetCurrentIrql(VOID)
681 {
682 return KeGetCurrentIrql();
683 }
684
685 typedef struct QueryRegistryCallbackContext
686 {
687 PVOID HwDeviceExtension;
688 PVOID HwContext;
689 PMINIPORT_GET_REGISTRY_ROUTINE HwGetRegistryRoutine;
690 } QUERY_REGISTRY_CALLBACK_CONTEXT, *PQUERY_REGISTRY_CALLBACK_CONTEXT;
691
692 static
693 NTSTATUS
694 NTAPI
695 QueryRegistryCallback(
696 IN PWSTR ValueName,
697 IN ULONG ValueType,
698 IN PVOID ValueData,
699 IN ULONG ValueLength,
700 IN PVOID Context,
701 IN PVOID EntryContext)
702 {
703 PQUERY_REGISTRY_CALLBACK_CONTEXT CallbackContext = (PQUERY_REGISTRY_CALLBACK_CONTEXT) Context;
704
705 INFO_(VIDEOPRT, "Found registry value for name %S: type %d, length %d\n",
706 ValueName, ValueType, ValueLength);
707 return (*(CallbackContext->HwGetRegistryRoutine))(
708 CallbackContext->HwDeviceExtension,
709 CallbackContext->HwContext,
710 ValueName,
711 ValueData,
712 ValueLength);
713 }
714
715 /*
716 * @unimplemented
717 */
718
719 VP_STATUS
720 NTAPI
721 VideoPortGetRegistryParameters(
722 IN PVOID HwDeviceExtension,
723 IN PWSTR ParameterName,
724 IN UCHAR IsParameterFileName,
725 IN PMINIPORT_GET_REGISTRY_ROUTINE GetRegistryRoutine,
726 IN PVOID HwContext)
727 {
728 RTL_QUERY_REGISTRY_TABLE QueryTable[2] = {{0}};
729 QUERY_REGISTRY_CALLBACK_CONTEXT Context;
730 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
731 NTSTATUS Status;
732
733 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
734
735 TRACE_(VIDEOPRT, "VideoPortGetRegistryParameters ParameterName %S, RegPath: %wZ\n",
736 ParameterName, &DeviceExtension->RegistryPath);
737
738 Context.HwDeviceExtension = HwDeviceExtension;
739 Context.HwContext = HwContext;
740 Context.HwGetRegistryRoutine = GetRegistryRoutine;
741
742 QueryTable[0].QueryRoutine = QueryRegistryCallback;
743 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
744 QueryTable[0].Name = ParameterName;
745
746 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
747 DeviceExtension->RegistryPath.Buffer,
748 QueryTable,
749 &Context,
750 NULL);
751 if (!NT_SUCCESS(Status))
752 {
753 WARN_(VIDEOPRT, "VideoPortGetRegistryParameters could not find the "
754 "requested parameter\n");
755 return ERROR_INVALID_PARAMETER;
756 }
757
758 if (IsParameterFileName)
759 {
760 /* FIXME: need to read the contents of the file */
761 UNIMPLEMENTED;
762 }
763
764 return NO_ERROR;
765 }
766
767 /*
768 * @implemented
769 */
770 VP_STATUS
771 NTAPI
772 VideoPortSetRegistryParameters(
773 IN PVOID HwDeviceExtension,
774 IN PWSTR ValueName,
775 IN PVOID ValueData,
776 IN ULONG ValueLength)
777 {
778 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
779 VP_STATUS Status;
780
781 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
782 TRACE_(VIDEOPRT, "VideoPortSetRegistryParameters ParameterName %S, RegPath: %wZ\n",
783 ValueName,
784 &DeviceExtension->RegistryPath);
785 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL);
786 Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
787 DeviceExtension->RegistryPath.Buffer,
788 ValueName,
789 REG_BINARY,
790 ValueData,
791 ValueLength);
792 if (Status != NO_ERROR)
793 WARN_(VIDEOPRT, "VideoPortSetRegistryParameters error 0x%x\n", Status);
794
795 return Status;
796 }
797
798 /*
799 * @implemented
800 */
801 VP_STATUS
802 NTAPI
803 VideoPortGetVgaStatus(
804 IN PVOID HwDeviceExtension,
805 OUT PULONG VgaStatus)
806 {
807 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
808
809 TRACE_(VIDEOPRT, "VideoPortGetVgaStatus\n");
810
811 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
812 if (KeGetCurrentIrql() == PASSIVE_LEVEL)
813 {
814 if (DeviceExtension->AdapterInterfaceType == PCIBus)
815 {
816 /* VgaStatus: 0 == VGA not enabled, 1 == VGA enabled. */
817 /* Assumed for now */
818 *VgaStatus = 1;
819 return NO_ERROR;
820 }
821 }
822
823 return ERROR_INVALID_FUNCTION;
824 }
825
826 /*
827 * @implemented
828 */
829 PVOID
830 NTAPI
831 VideoPortGetRomImage(
832 IN PVOID HwDeviceExtension,
833 IN PVOID Unused1,
834 IN ULONG Unused2,
835 IN ULONG Length)
836 {
837 static PVOID RomImageBuffer = NULL;
838 PKPROCESS CallingProcess;
839 KAPC_STATE ApcState;
840
841 TRACE_(VIDEOPRT, "VideoPortGetRomImage(HwDeviceExtension 0x%X Length 0x%X)\n",
842 HwDeviceExtension, Length);
843
844 /* If the length is zero then free the existing buffer. */
845 if (Length == 0)
846 {
847 if (RomImageBuffer != NULL)
848 {
849 ExFreePool(RomImageBuffer);
850 RomImageBuffer = NULL;
851 }
852 return NULL;
853 }
854 else
855 {
856 /*
857 * The DDK says we shouldn't use the legacy C0000 method but get the
858 * rom base address from the corresponding pci or acpi register but
859 * lets ignore that and use C0000 anyway. We have already mapped the
860 * bios area into memory so we'll copy from there.
861 */
862
863 /* Copy the bios. */
864 Length = min(Length, 0x10000);
865 if (RomImageBuffer != NULL)
866 {
867 ExFreePool(RomImageBuffer);
868 }
869
870 RomImageBuffer = ExAllocatePool(PagedPool, Length);
871 if (RomImageBuffer == NULL)
872 {
873 return NULL;
874 }
875
876 IntAttachToCSRSS(&CallingProcess, &ApcState);
877 RtlCopyMemory(RomImageBuffer, (PUCHAR)0xC0000, Length);
878 IntDetachFromCSRSS(&CallingProcess, &ApcState);
879
880 return RomImageBuffer;
881 }
882 }
883
884 /*
885 * @implemented
886 */
887 BOOLEAN
888 NTAPI
889 VideoPortScanRom(
890 IN PVOID HwDeviceExtension,
891 IN PUCHAR RomBase,
892 IN ULONG RomLength,
893 IN PUCHAR String)
894 {
895 ULONG StringLength;
896 BOOLEAN Found;
897 PUCHAR SearchLocation;
898
899 TRACE_(VIDEOPRT, "VideoPortScanRom RomBase %p RomLength 0x%x String %s\n", RomBase, RomLength, String);
900
901 StringLength = strlen((PCHAR)String);
902 Found = FALSE;
903 SearchLocation = RomBase;
904 for (SearchLocation = RomBase;
905 !Found && SearchLocation < RomBase + RomLength - StringLength;
906 SearchLocation++)
907 {
908 Found = (RtlCompareMemory(SearchLocation, String, StringLength) == StringLength);
909 if (Found)
910 {
911 INFO_(VIDEOPRT, "Match found at %p\n", SearchLocation);
912 }
913 }
914
915 return Found;
916 }
917
918 /*
919 * @implemented
920 */
921 BOOLEAN
922 NTAPI
923 VideoPortSynchronizeExecution(
924 IN PVOID HwDeviceExtension,
925 IN VIDEO_SYNCHRONIZE_PRIORITY Priority,
926 IN PMINIPORT_SYNCHRONIZE_ROUTINE SynchronizeRoutine,
927 OUT PVOID Context)
928 {
929 BOOLEAN Ret;
930 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
931 KIRQL OldIrql;
932
933 switch (Priority)
934 {
935 case VpLowPriority:
936 Ret = (*SynchronizeRoutine)(Context);
937 break;
938
939 case VpMediumPriority:
940 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
941 if (DeviceExtension->InterruptObject == NULL)
942 Ret = (*SynchronizeRoutine)(Context);
943 else
944 Ret = KeSynchronizeExecution(
945 DeviceExtension->InterruptObject,
946 SynchronizeRoutine,
947 Context);
948 break;
949
950 case VpHighPriority:
951 OldIrql = KeGetCurrentIrql();
952 if (OldIrql < SYNCH_LEVEL)
953 KeRaiseIrql(SYNCH_LEVEL, &OldIrql);
954
955 Ret = (*SynchronizeRoutine)(Context);
956
957 if (OldIrql < SYNCH_LEVEL)
958 KeLowerIrql(OldIrql);
959 break;
960
961 default:
962 Ret = FALSE;
963 }
964
965 return Ret;
966 }
967
968 /*
969 * @implemented
970 */
971 VP_STATUS
972 NTAPI
973 VideoPortEnumerateChildren(
974 IN PVOID HwDeviceExtension,
975 IN PVOID Reserved)
976 {
977 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
978 ULONG Status;
979 VIDEO_CHILD_ENUM_INFO ChildEnumInfo;
980 BOOLEAN bHaveLastMonitorID = FALSE;
981 UCHAR LastMonitorID[10];
982 ULONG Unused;
983 UINT i;
984 PDEVICE_OBJECT ChildDeviceObject;
985 PVIDEO_PORT_CHILD_EXTENSION ChildExtension;
986
987 INFO_(VIDEOPRT, "Starting child device probe\n");
988 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
989 if (DeviceExtension->DriverExtension->InitializationData.HwGetVideoChildDescriptor == NULL)
990 {
991 WARN_(VIDEOPRT, "Miniport's HwGetVideoChildDescriptor is NULL!\n");
992 return NO_ERROR;
993 }
994
995 if (!IsListEmpty(&DeviceExtension->ChildDeviceList))
996 {
997 ERR_(VIDEOPRT, "FIXME: Support calling VideoPortEnumerateChildren again!\n");
998 return NO_ERROR;
999 }
1000
1001 /* Enumerate the children */
1002 for (i = 1; ; i++)
1003 {
1004 Status = IoCreateDevice(DeviceExtension->DriverObject,
1005 sizeof(VIDEO_PORT_CHILD_EXTENSION) +
1006 DeviceExtension->DriverExtension->InitializationData.HwChildDeviceExtensionSize,
1007 NULL,
1008 FILE_DEVICE_CONTROLLER,
1009 FILE_DEVICE_SECURE_OPEN,
1010 FALSE,
1011 &ChildDeviceObject);
1012 if (!NT_SUCCESS(Status))
1013 return Status;
1014
1015 ChildExtension = ChildDeviceObject->DeviceExtension;
1016
1017 RtlZeroMemory(ChildExtension,
1018 sizeof(VIDEO_PORT_CHILD_EXTENSION) +
1019 DeviceExtension->DriverExtension->InitializationData.HwChildDeviceExtensionSize);
1020
1021 ChildExtension->Common.Fdo = FALSE;
1022 ChildExtension->ChildId = i;
1023 ChildExtension->PhysicalDeviceObject = ChildDeviceObject;
1024 ChildExtension->DriverObject = DeviceExtension->DriverObject;
1025
1026 /* Setup the ChildEnumInfo */
1027 ChildEnumInfo.Size = sizeof(ChildEnumInfo);
1028 ChildEnumInfo.ChildDescriptorSize = sizeof(ChildExtension->ChildDescriptor);
1029 ChildEnumInfo.ACPIHwId = 0;
1030
1031 if (DeviceExtension->DriverExtension->InitializationData.HwChildDeviceExtensionSize)
1032 ChildEnumInfo.ChildHwDeviceExtension = VIDEO_PORT_GET_CHILD_EXTENSION(ChildExtension);
1033 else
1034 ChildEnumInfo.ChildHwDeviceExtension = NULL;
1035
1036 ChildEnumInfo.ChildIndex = ChildExtension->ChildId;
1037
1038 INFO_(VIDEOPRT, "Probing child: %d\n", ChildEnumInfo.ChildIndex);
1039 Status = DeviceExtension->DriverExtension->InitializationData.HwGetVideoChildDescriptor(
1040 HwDeviceExtension,
1041 &ChildEnumInfo,
1042 &ChildExtension->ChildType,
1043 ChildExtension->ChildDescriptor,
1044 &ChildExtension->ChildId,
1045 &Unused);
1046 if (Status == VIDEO_ENUM_MORE_DEVICES)
1047 {
1048 if (ChildExtension->ChildType == Monitor)
1049 {
1050 // Check if the EDID is valid
1051 if (ChildExtension->ChildDescriptor[0] == 0x00 &&
1052 ChildExtension->ChildDescriptor[1] == 0xFF &&
1053 ChildExtension->ChildDescriptor[2] == 0xFF &&
1054 ChildExtension->ChildDescriptor[3] == 0xFF &&
1055 ChildExtension->ChildDescriptor[4] == 0xFF &&
1056 ChildExtension->ChildDescriptor[5] == 0xFF &&
1057 ChildExtension->ChildDescriptor[6] == 0xFF &&
1058 ChildExtension->ChildDescriptor[7] == 0x00)
1059 {
1060 if (bHaveLastMonitorID)
1061 {
1062 // Compare the previous monitor ID with the current one, break the loop if they are identical
1063 if (RtlCompareMemory(LastMonitorID, &ChildExtension->ChildDescriptor[8], sizeof(LastMonitorID)) == sizeof(LastMonitorID))
1064 {
1065 INFO_(VIDEOPRT, "Found identical Monitor ID two times, stopping enumeration\n");
1066 IoDeleteDevice(ChildDeviceObject);
1067 break;
1068 }
1069 }
1070
1071 // Copy 10 bytes from the EDID, which can be used to uniquely identify the monitor
1072 RtlCopyMemory(LastMonitorID, &ChildExtension->ChildDescriptor[8], sizeof(LastMonitorID));
1073 bHaveLastMonitorID = TRUE;
1074
1075 /* Mark it valid */
1076 ChildExtension->EdidValid = TRUE;
1077 }
1078 else
1079 {
1080 /* Mark it invalid */
1081 ChildExtension->EdidValid = FALSE;
1082 }
1083 }
1084 }
1085 else if (Status == VIDEO_ENUM_INVALID_DEVICE)
1086 {
1087 WARN_(VIDEOPRT, "Child device %d is invalid!\n", ChildEnumInfo.ChildIndex);
1088 IoDeleteDevice(ChildDeviceObject);
1089 continue;
1090 }
1091 else if (Status == VIDEO_ENUM_NO_MORE_DEVICES)
1092 {
1093 INFO_(VIDEOPRT, "End of child enumeration! (%d children enumerated)\n", i - 1);
1094 IoDeleteDevice(ChildDeviceObject);
1095 break;
1096 }
1097 else
1098 {
1099 WARN_(VIDEOPRT, "HwGetVideoChildDescriptor returned unknown status code 0x%x!\n", Status);
1100 IoDeleteDevice(ChildDeviceObject);
1101 break;
1102 }
1103
1104 if (ChildExtension->ChildType == Monitor)
1105 {
1106 UINT j;
1107 PUCHAR p = ChildExtension->ChildDescriptor;
1108 INFO_(VIDEOPRT, "Monitor device enumerated! (ChildId = 0x%x)\n", ChildExtension->ChildId);
1109 for (j = 0; j < sizeof (ChildExtension->ChildDescriptor); j += 8)
1110 {
1111 INFO_(VIDEOPRT, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
1112 p[j + 0], p[j + 1], p[j + 2], p[j + 3],
1113 p[j + 4], p[j + 5], p[j + 6], p[j + 7]);
1114 }
1115 }
1116 else if (ChildExtension->ChildType == Other)
1117 {
1118 INFO_(VIDEOPRT, "\"Other\" device enumerated: DeviceId = %S\n", (PWSTR)ChildExtension->ChildDescriptor);
1119 }
1120 else
1121 {
1122 ERR_(VIDEOPRT, "HwGetVideoChildDescriptor returned unsupported type: %d\n", ChildExtension->ChildType);
1123 }
1124
1125 /* Clear the init flag */
1126 ChildDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
1127
1128 InsertTailList(&DeviceExtension->ChildDeviceList,
1129 &ChildExtension->ListEntry);
1130 }
1131
1132 /* Trigger reenumeration by the PnP manager */
1133 IoInvalidateDeviceRelations(DeviceExtension->PhysicalDeviceObject, BusRelations);
1134
1135 return NO_ERROR;
1136 }
1137
1138 /*
1139 * @unimplemented
1140 */
1141 VP_STATUS
1142 NTAPI
1143 VideoPortCreateSecondaryDisplay(
1144 IN PVOID HwDeviceExtension,
1145 IN OUT PVOID *SecondaryDeviceExtension,
1146 IN ULONG Flag)
1147 {
1148 UNIMPLEMENTED;
1149 return ERROR_DEV_NOT_EXIST;
1150 }
1151
1152 /*
1153 * @implemented
1154 */
1155 BOOLEAN
1156 NTAPI
1157 VideoPortQueueDpc(
1158 IN PVOID HwDeviceExtension,
1159 IN PMINIPORT_DPC_ROUTINE CallbackRoutine,
1160 IN PVOID Context)
1161 {
1162 return KeInsertQueueDpc(
1163 &VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension)->DpcObject,
1164 (PVOID)CallbackRoutine,
1165 (PVOID)Context);
1166 }
1167
1168 /*
1169 * @implemented
1170 */
1171 PVOID
1172 NTAPI
1173 VideoPortGetAssociatedDeviceExtension(
1174 IN PVOID DeviceObject)
1175 {
1176 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1177
1178 TRACE_(VIDEOPRT, "VideoPortGetAssociatedDeviceExtension\n");
1179 DeviceExtension = ((PDEVICE_OBJECT)DeviceObject)->DeviceExtension;
1180 if (!DeviceExtension)
1181 return NULL;
1182 return DeviceExtension->MiniPortDeviceExtension;
1183 }
1184
1185 /*
1186 * @implemented
1187 */
1188 VP_STATUS
1189 NTAPI
1190 VideoPortGetVersion(
1191 IN PVOID HwDeviceExtension,
1192 IN OUT PVPOSVERSIONINFO VpOsVersionInfo)
1193 {
1194 RTL_OSVERSIONINFOEXW Version;
1195
1196 Version.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
1197 if (VpOsVersionInfo->Size >= sizeof(VPOSVERSIONINFO))
1198 {
1199 #if 1
1200 if (NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW)&Version)))
1201 {
1202 VpOsVersionInfo->MajorVersion = Version.dwMajorVersion;
1203 VpOsVersionInfo->MinorVersion = Version.dwMinorVersion;
1204 VpOsVersionInfo->BuildNumber = Version.dwBuildNumber;
1205 VpOsVersionInfo->ServicePackMajor = Version.wServicePackMajor;
1206 VpOsVersionInfo->ServicePackMinor = Version.wServicePackMinor;
1207 return NO_ERROR;
1208 }
1209 return ERROR_INVALID_PARAMETER;
1210 #else
1211 VpOsVersionInfo->MajorVersion = 5;
1212 VpOsVersionInfo->MinorVersion = 0;
1213 VpOsVersionInfo->BuildNumber = 2195;
1214 VpOsVersionInfo->ServicePackMajor = 4;
1215 VpOsVersionInfo->ServicePackMinor = 0;
1216 return NO_ERROR;
1217 #endif
1218 }
1219
1220 return ERROR_INVALID_PARAMETER;
1221 }
1222
1223 /*
1224 * @implemented
1225 */
1226 BOOLEAN
1227 NTAPI
1228 VideoPortCheckForDeviceExistence(
1229 IN PVOID HwDeviceExtension,
1230 IN USHORT VendorId,
1231 IN USHORT DeviceId,
1232 IN UCHAR RevisionId,
1233 IN USHORT SubVendorId,
1234 IN USHORT SubSystemId,
1235 IN ULONG Flags)
1236 {
1237 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1238 PCI_DEVICE_PRESENT_INTERFACE PciDevicePresentInterface;
1239 IO_STATUS_BLOCK IoStatusBlock;
1240 IO_STACK_LOCATION IoStack;
1241 ULONG PciFlags = 0;
1242 NTSTATUS Status;
1243 BOOL DevicePresent;
1244
1245 TRACE_(VIDEOPRT, "VideoPortCheckForDeviceExistence\n");
1246
1247 if (Flags & ~(CDE_USE_REVISION | CDE_USE_SUBSYSTEM_IDS))
1248 {
1249 WARN_(VIDEOPRT, "VideoPortCheckForDeviceExistence: Unknown flags 0x%lx\n", Flags & ~(CDE_USE_REVISION | CDE_USE_SUBSYSTEM_IDS));
1250 return FALSE;
1251 }
1252
1253 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
1254
1255 PciDevicePresentInterface.Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
1256 PciDevicePresentInterface.Version = 1;
1257 IoStack.Parameters.QueryInterface.Size = PciDevicePresentInterface.Size;
1258 IoStack.Parameters.QueryInterface.Version = PciDevicePresentInterface.Version;
1259 IoStack.Parameters.QueryInterface.Interface = (PINTERFACE)&PciDevicePresentInterface;
1260 IoStack.Parameters.QueryInterface.InterfaceType =
1261 &GUID_PCI_DEVICE_PRESENT_INTERFACE;
1262 Status = IopInitiatePnpIrp(DeviceExtension->NextDeviceObject,
1263 &IoStatusBlock, IRP_MN_QUERY_INTERFACE, &IoStack);
1264 if (!NT_SUCCESS(Status))
1265 {
1266 WARN_(VIDEOPRT, "IopInitiatePnpIrp() failed! (Status 0x%lx)\n", Status);
1267 return FALSE;
1268 }
1269
1270 if (Flags & CDE_USE_REVISION)
1271 PciFlags |= PCI_USE_REVISION;
1272 if (Flags & CDE_USE_SUBSYSTEM_IDS)
1273 PciFlags |= PCI_USE_SUBSYSTEM_IDS;
1274
1275 DevicePresent = PciDevicePresentInterface.IsDevicePresent(
1276 VendorId, DeviceId, RevisionId,
1277 SubVendorId, SubSystemId, PciFlags);
1278
1279 PciDevicePresentInterface.InterfaceDereference(PciDevicePresentInterface.Context);
1280
1281 return DevicePresent;
1282 }
1283
1284 /*
1285 * @unimplemented
1286 */
1287 VP_STATUS
1288 NTAPI
1289 VideoPortRegisterBugcheckCallback(
1290 IN PVOID HwDeviceExtension,
1291 IN ULONG BugcheckCode,
1292 IN PVIDEO_BUGCHECK_CALLBACK Callback,
1293 IN ULONG BugcheckDataSize)
1294 {
1295 UNIMPLEMENTED;
1296 return NO_ERROR;
1297 }
1298
1299 /*
1300 * @implemented
1301 */
1302 LONGLONG
1303 NTAPI
1304 VideoPortQueryPerformanceCounter(
1305 IN PVOID HwDeviceExtension,
1306 OUT PLONGLONG PerformanceFrequency OPTIONAL)
1307 {
1308 LARGE_INTEGER Result;
1309
1310 TRACE_(VIDEOPRT, "VideoPortQueryPerformanceCounter\n");
1311 Result = KeQueryPerformanceCounter((PLARGE_INTEGER)PerformanceFrequency);
1312 return Result.QuadPart;
1313 }
1314
1315 /*
1316 * @implemented
1317 */
1318 VOID
1319 NTAPI
1320 VideoPortAcquireDeviceLock(
1321 IN PVOID HwDeviceExtension)
1322 {
1323 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1324 NTSTATUS Status;
1325 (void)Status;
1326
1327 TRACE_(VIDEOPRT, "VideoPortAcquireDeviceLock\n");
1328 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
1329 Status = KeWaitForMutexObject(&DeviceExtension->DeviceLock, Executive,
1330 KernelMode, FALSE, NULL);
1331 // ASSERT(Status == STATUS_SUCCESS);
1332 }
1333
1334 /*
1335 * @implemented
1336 */
1337 VOID
1338 NTAPI
1339 VideoPortReleaseDeviceLock(
1340 IN PVOID HwDeviceExtension)
1341 {
1342 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1343 LONG Status;
1344 (void)Status;
1345
1346 TRACE_(VIDEOPRT, "VideoPortReleaseDeviceLock\n");
1347 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
1348 Status = KeReleaseMutex(&DeviceExtension->DeviceLock, FALSE);
1349 //ASSERT(Status == STATUS_SUCCESS);
1350 }
1351
1352 /*
1353 * @unimplemented
1354 */
1355 VOID
1356 NTAPI
1357 VpNotifyEaData(
1358 IN PDEVICE_OBJECT DeviceObject,
1359 IN PVOID Data)
1360 {
1361 UNIMPLEMENTED;
1362 }
1363
1364 /*
1365 * @implemented
1366 */
1367 PVOID
1368 NTAPI
1369 VideoPortAllocateContiguousMemory(
1370 IN PVOID HwDeviceExtension,
1371 IN ULONG NumberOfBytes,
1372 IN PHYSICAL_ADDRESS HighestAcceptableAddress
1373 )
1374 {
1375
1376 return MmAllocateContiguousMemory(NumberOfBytes, HighestAcceptableAddress);
1377 }
1378
1379 /*
1380 * @implemented
1381 */
1382 BOOLEAN
1383 NTAPI
1384 VideoPortIsNoVesa(VOID)
1385 {
1386 NTSTATUS Status;
1387 HANDLE KeyHandle;
1388 UNICODE_STRING Path = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control");
1389 UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"SystemStartOptions");
1390 OBJECT_ATTRIBUTES ObjectAttributes;
1391 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
1392 ULONG Length, NewLength;
1393
1394 /* Initialize object attributes with the path we want */
1395 InitializeObjectAttributes(&ObjectAttributes,
1396 &Path,
1397 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
1398 NULL,
1399 NULL);
1400
1401 /* Open the key */
1402 Status = ZwOpenKey(&KeyHandle,
1403 KEY_QUERY_VALUE,
1404 &ObjectAttributes);
1405
1406 if (!NT_SUCCESS(Status))
1407 {
1408 VideoPortDebugPrint(Error, "ZwOpenKey failed (0x%x)\n", Status);
1409 return FALSE;
1410 }
1411
1412 /* Find out how large our buffer should be */
1413 Status = ZwQueryValueKey(KeyHandle,
1414 &ValueName,
1415 KeyValuePartialInformation,
1416 NULL,
1417 0,
1418 &Length);
1419 if (Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_BUFFER_TOO_SMALL)
1420 {
1421 VideoPortDebugPrint(Error, "ZwQueryValueKey failed (0x%x)\n", Status);
1422 ZwClose(KeyHandle);
1423 return FALSE;
1424 }
1425
1426 /* Allocate it */
1427 KeyInfo = ExAllocatePool(PagedPool, Length);
1428 if (!KeyInfo)
1429 {
1430 VideoPortDebugPrint(Error, "Out of memory\n");
1431 ZwClose(KeyHandle);
1432 return FALSE;
1433 }
1434
1435 /* Now for real this time */
1436 Status = ZwQueryValueKey(KeyHandle,
1437 &ValueName,
1438 KeyValuePartialInformation,
1439 KeyInfo,
1440 Length,
1441 &NewLength);
1442
1443 ZwClose(KeyHandle);
1444
1445 if (!NT_SUCCESS(Status))
1446 {
1447 VideoPortDebugPrint(Error, "ZwQueryValueKey failed (0x%x)\n", Status);
1448 ExFreePool(KeyInfo);
1449 return FALSE;
1450 }
1451
1452 /* Sanity check */
1453 if (KeyInfo->Type != REG_SZ)
1454 {
1455 VideoPortDebugPrint(Error, "Invalid type for SystemStartOptions\n");
1456 ExFreePool(KeyInfo);
1457 return FALSE;
1458 }
1459
1460 /* Check if NOVESA or BASEVIDEO is present in the start options */
1461 if (wcsstr((PWCHAR)KeyInfo->Data, L"NOVESA") ||
1462 wcsstr((PWCHAR)KeyInfo->Data, L"BASEVIDEO"))
1463 {
1464 VideoPortDebugPrint(Info, "VESA mode disabled\n");
1465 ExFreePool(KeyInfo);
1466 return TRUE;
1467 }
1468
1469 ExFreePool(KeyInfo);
1470
1471 VideoPortDebugPrint(Info, "VESA mode enabled\n");
1472
1473 return FALSE;
1474 }
1475