4 * Copyright (C) 2002-2004, 2007 ReactOS Team
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.
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.
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
25 /* GLOBAL VARIABLES ***********************************************************/
27 ULONG CsrssInitialized
= FALSE
;
28 PKPROCESS Csrss
= NULL
;
29 ULONG VideoPortDeviceNumber
= 0;
31 /* PRIVATE FUNCTIONS **********************************************************/
39 return STATUS_SUCCESS
;
44 IntVideoPortImageDirectoryEntryToData(
48 PIMAGE_NT_HEADERS NtHeader
;
51 NtHeader
= RtlImageNtHeader(BaseAddress
);
55 if (Directory
>= NtHeader
->OptionalHeader
.NumberOfRvaAndSizes
)
58 Va
= NtHeader
->OptionalHeader
.DataDirectory
[Directory
].VirtualAddress
;
62 return (PVOID
)((ULONG_PTR
)BaseAddress
+ Va
);
67 IntVideoPortDeferredRoutine(
69 IN PVOID DeferredContext
,
70 IN PVOID SystemArgument1
,
71 IN PVOID SystemArgument2
)
73 PVOID HwDeviceExtension
=
74 &((PVIDEO_PORT_DEVICE_EXTENSION
)DeferredContext
)->MiniPortDeviceExtension
;
75 ((PMINIPORT_DPC_ROUTINE
)SystemArgument1
)(HwDeviceExtension
, SystemArgument2
);
80 IntCreateRegistryPath(
81 IN PCUNICODE_STRING DriverRegistryPath
,
82 OUT PUNICODE_STRING DeviceRegistryPath
)
84 static WCHAR RegistryMachineSystem
[] = L
"\\REGISTRY\\MACHINE\\SYSTEM\\";
85 static WCHAR CurrentControlSet
[] = L
"CURRENTCONTROLSET\\";
86 static WCHAR ControlSet
[] = L
"CONTROLSET";
87 static WCHAR Insert1
[] = L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
88 static WCHAR Insert2
[] = L
"\\Device0";
90 UNICODE_STRING AfterControlSet
;
92 AfterControlSet
= *DriverRegistryPath
;
94 /* Check if path begins with \\REGISTRY\\MACHINE\\SYSTEM\\ */
95 Valid
= (DriverRegistryPath
->Length
> sizeof(RegistryMachineSystem
) &&
96 0 == _wcsnicmp(DriverRegistryPath
->Buffer
, RegistryMachineSystem
,
97 wcslen(RegistryMachineSystem
)));
100 AfterControlSet
.Buffer
+= wcslen(RegistryMachineSystem
);
101 AfterControlSet
.Length
-= sizeof(RegistryMachineSystem
) - sizeof(UNICODE_NULL
);
103 /* Check if path contains CURRENTCONTROLSET */
104 if (AfterControlSet
.Length
> sizeof(CurrentControlSet
) &&
105 0 == _wcsnicmp(AfterControlSet
.Buffer
, CurrentControlSet
, wcslen(CurrentControlSet
)))
107 AfterControlSet
.Buffer
+= wcslen(CurrentControlSet
);
108 AfterControlSet
.Length
-= sizeof(CurrentControlSet
) - sizeof(UNICODE_NULL
);
110 /* Check if path contains CONTROLSETnum */
111 else if (AfterControlSet
.Length
> sizeof(ControlSet
) &&
112 0 == _wcsnicmp(AfterControlSet
.Buffer
, ControlSet
, wcslen(ControlSet
)))
114 AfterControlSet
.Buffer
+= wcslen(ControlSet
);
115 AfterControlSet
.Length
-= sizeof(ControlSet
) - sizeof(UNICODE_NULL
);
116 while (AfterControlSet
.Length
> 0 &&
117 *AfterControlSet
.Buffer
>= L
'0' &&
118 *AfterControlSet
.Buffer
<= L
'9')
120 AfterControlSet
.Buffer
++;
121 AfterControlSet
.Length
-= sizeof(WCHAR
);
124 Valid
= (AfterControlSet
.Length
> 0 && L
'\\' == *AfterControlSet
.Buffer
);
125 AfterControlSet
.Buffer
++;
126 AfterControlSet
.Length
-= sizeof(WCHAR
);
127 AfterControlSet
.MaximumLength
= AfterControlSet
.Length
;
137 DeviceRegistryPath
->MaximumLength
= DriverRegistryPath
->Length
+ sizeof(Insert1
) + sizeof(Insert2
);
138 DeviceRegistryPath
->Buffer
= ExAllocatePoolWithTag(PagedPool
,
139 DeviceRegistryPath
->MaximumLength
,
141 if (DeviceRegistryPath
->Buffer
!= NULL
)
143 /* Build device path */
144 wcsncpy(DeviceRegistryPath
->Buffer
,
145 DriverRegistryPath
->Buffer
,
146 AfterControlSet
.Buffer
- DriverRegistryPath
->Buffer
);
147 DeviceRegistryPath
->Length
= (AfterControlSet
.Buffer
- DriverRegistryPath
->Buffer
) * sizeof(WCHAR
);
148 RtlAppendUnicodeToString(DeviceRegistryPath
, Insert1
);
149 RtlAppendUnicodeStringToString(DeviceRegistryPath
, &AfterControlSet
);
150 RtlAppendUnicodeToString(DeviceRegistryPath
, Insert2
);
152 /* Check if registry key exists */
153 Valid
= NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE
, DeviceRegistryPath
->Buffer
));
156 ExFreePoolWithTag(DeviceRegistryPath
->Buffer
, TAG_VIDEO_PORT
);
165 WARN_(VIDEOPRT
, "Unparsable registry path %wZ", DriverRegistryPath
);
168 /* If path doesn't point to *ControlSet*, use DriverRegistryPath directly */
171 DeviceRegistryPath
->MaximumLength
= DriverRegistryPath
->Length
+ sizeof(Insert2
);
172 DeviceRegistryPath
->Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
173 DeviceRegistryPath
->MaximumLength
,
176 if (!DeviceRegistryPath
->Buffer
)
177 return STATUS_NO_MEMORY
;
179 RtlCopyUnicodeString(DeviceRegistryPath
, DriverRegistryPath
);
180 RtlAppendUnicodeToString(DeviceRegistryPath
, Insert2
);
183 return STATUS_SUCCESS
;
188 IntVideoPortCreateAdapterDeviceObject(
189 IN PDRIVER_OBJECT DriverObject
,
190 IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension
,
191 IN PDEVICE_OBJECT PhysicalDeviceObject
,
192 OUT PDEVICE_OBJECT
*DeviceObject OPTIONAL
)
194 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
197 PCI_SLOT_NUMBER SlotNumber
;
200 WCHAR DeviceBuffer
[20];
201 UNICODE_STRING DeviceName
;
202 PDEVICE_OBJECT DeviceObject_
;
204 if (DeviceObject
== NULL
)
205 DeviceObject
= &DeviceObject_
;
208 * Find the first free device number that can be used for video device
209 * object names and symlinks.
211 DeviceNumber
= VideoPortDeviceNumber
;
212 if (DeviceNumber
== 0xFFFFFFFF)
214 WARN_(VIDEOPRT
, "Can't find free device number\n");
215 return STATUS_UNSUCCESSFUL
;
219 * Create the device object.
222 /* Create a unicode device name. */
223 swprintf(DeviceBuffer
, L
"\\Device\\Video%lu", DeviceNumber
);
224 RtlInitUnicodeString(&DeviceName
, DeviceBuffer
);
226 INFO_(VIDEOPRT
, "HwDeviceExtension size is: 0x%x\n",
227 DriverExtension
->InitializationData
.HwDeviceExtensionSize
);
229 /* Create the device object. */
230 Status
= IoCreateDevice(
232 sizeof(VIDEO_PORT_DEVICE_EXTENSION
) +
233 DriverExtension
->InitializationData
.HwDeviceExtensionSize
,
240 if (!NT_SUCCESS(Status
))
242 WARN_(VIDEOPRT
, "IoCreateDevice call failed with status 0x%08x\n", Status
);
247 * Set the buffering strategy here. If you change this, remember
248 * to change VidDispatchDeviceControl too.
251 (*DeviceObject
)->Flags
|= DO_BUFFERED_IO
;
253 /* Initialize device extension. */
254 DeviceExtension
= (PVIDEO_PORT_DEVICE_EXTENSION
)((*DeviceObject
)->DeviceExtension
);
255 DeviceExtension
->Common
.Fdo
= TRUE
;
256 DeviceExtension
->DeviceNumber
= DeviceNumber
;
257 DeviceExtension
->DriverObject
= DriverObject
;
258 DeviceExtension
->PhysicalDeviceObject
= PhysicalDeviceObject
;
259 DeviceExtension
->FunctionalDeviceObject
= *DeviceObject
;
260 DeviceExtension
->DriverExtension
= DriverExtension
;
262 InitializeListHead(&DeviceExtension
->ChildDeviceList
);
264 /* Get the registry path associated with this driver. */
265 Status
= IntCreateRegistryPath(&DriverExtension
->RegistryPath
,
266 &DeviceExtension
->RegistryPath
);
267 if (!NT_SUCCESS(Status
))
269 WARN_(VIDEOPRT
, "IntCreateRegistryPath() call failed with status 0x%08x\n", Status
);
270 IoDeleteDevice(*DeviceObject
);
271 *DeviceObject
= NULL
;
275 if (PhysicalDeviceObject
!= NULL
)
277 /* Get bus number from the upper level bus driver. */
278 Size
= sizeof(ULONG
);
279 Status
= IoGetDeviceProperty(
280 PhysicalDeviceObject
,
281 DevicePropertyBusNumber
,
283 &DeviceExtension
->SystemIoBusNumber
,
285 if (!NT_SUCCESS(Status
))
287 WARN_(VIDEOPRT
, "Couldn't get an information from bus driver. We will try to\n"
288 "use legacy detection method, but even that doesn't mean that\n"
290 DeviceExtension
->PhysicalDeviceObject
= NULL
;
294 DeviceExtension
->AdapterInterfaceType
=
295 DriverExtension
->InitializationData
.AdapterInterfaceType
;
297 if (PhysicalDeviceObject
!= NULL
)
299 /* Get bus type from the upper level bus driver. */
300 Size
= sizeof(ULONG
);
301 IoGetDeviceProperty(PhysicalDeviceObject
,
302 DevicePropertyLegacyBusType
,
304 &DeviceExtension
->AdapterInterfaceType
,
307 /* Get bus device address from the upper level bus driver. */
308 Size
= sizeof(ULONG
);
309 IoGetDeviceProperty(PhysicalDeviceObject
,
310 DevicePropertyAddress
,
315 /* Convert slotnumber to PCI_SLOT_NUMBER */
316 SlotNumber
.u
.AsULONG
= 0;
317 SlotNumber
.u
.bits
.DeviceNumber
= (PciSlotNumber
>> 16) & 0xFFFF;
318 SlotNumber
.u
.bits
.FunctionNumber
= PciSlotNumber
& 0xFFFF;
319 DeviceExtension
->SystemIoSlotNumber
= SlotNumber
.u
.AsULONG
;
322 InitializeListHead(&DeviceExtension
->AddressMappingListHead
);
323 InitializeListHead(&DeviceExtension
->DmaAdapterList
);
325 KeInitializeDpc(&DeviceExtension
->DpcObject
,
326 IntVideoPortDeferredRoutine
,
329 KeInitializeMutex(&DeviceExtension
->DeviceLock
, 0);
331 /* Attach the device. */
332 if (PhysicalDeviceObject
!= NULL
)
333 DeviceExtension
->NextDeviceObject
= IoAttachDeviceToDeviceStack(
335 PhysicalDeviceObject
);
337 /* Remove the initailizing flag */
338 (*DeviceObject
)->Flags
&= ~DO_DEVICE_INITIALIZING
;
339 return STATUS_SUCCESS
;
345 IntVideoPortFindAdapter(
346 IN PDRIVER_OBJECT DriverObject
,
347 IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension
,
348 IN PDEVICE_OBJECT DeviceObject
)
350 WCHAR DeviceVideoBuffer
[20];
351 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
354 VIDEO_PORT_CONFIG_INFO ConfigInfo
;
355 SYSTEM_BASIC_INFORMATION SystemBasicInfo
;
357 WCHAR DeviceBuffer
[20];
358 UNICODE_STRING DeviceName
;
359 WCHAR SymlinkBuffer
[20];
360 UNICODE_STRING SymlinkName
;
361 BOOL LegacyDetection
= FALSE
;
364 DeviceExtension
= (PVIDEO_PORT_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
365 DeviceNumber
= DeviceExtension
->DeviceNumber
;
367 /* Setup a ConfigInfo structure that we will pass to HwFindAdapter. */
368 RtlZeroMemory(&ConfigInfo
, sizeof(VIDEO_PORT_CONFIG_INFO
));
369 ConfigInfo
.Length
= sizeof(VIDEO_PORT_CONFIG_INFO
);
370 ConfigInfo
.AdapterInterfaceType
= DeviceExtension
->AdapterInterfaceType
;
371 if (ConfigInfo
.AdapterInterfaceType
== PCIBus
)
372 ConfigInfo
.InterruptMode
= LevelSensitive
;
374 ConfigInfo
.InterruptMode
= Latched
;
375 ConfigInfo
.DriverRegistryPath
= DriverExtension
->RegistryPath
.Buffer
;
376 ConfigInfo
.VideoPortGetProcAddress
= IntVideoPortGetProcAddress
;
377 ConfigInfo
.SystemIoBusNumber
= DeviceExtension
->SystemIoBusNumber
;
378 ConfigInfo
.BusInterruptLevel
= DeviceExtension
->InterruptLevel
;
379 ConfigInfo
.BusInterruptVector
= DeviceExtension
->InterruptVector
;
381 Size
= sizeof(SystemBasicInfo
);
382 Status
= ZwQuerySystemInformation(SystemBasicInformation
,
386 if (NT_SUCCESS(Status
))
388 ConfigInfo
.SystemMemorySize
= SystemBasicInfo
.NumberOfPhysicalPages
*
389 SystemBasicInfo
.PageSize
;
393 * Call miniport HwVidFindAdapter entry point to detect if
394 * particular device is present. There are two possible code
395 * paths. The first one is for Legacy drivers (NT4) and cases
396 * when we don't have information about what bus we're on. The
397 * second case is the standard one for Plug & Play drivers.
399 if (DeviceExtension
->PhysicalDeviceObject
== NULL
)
401 LegacyDetection
= TRUE
;
406 ULONG BusNumber
, MaxBuses
;
408 MaxBuses
= DeviceExtension
->AdapterInterfaceType
== PCIBus
? PCI_MAX_BRIDGE_NUMBER
: 1;
410 for (BusNumber
= 0; BusNumber
< MaxBuses
; BusNumber
++)
412 DeviceExtension
->SystemIoBusNumber
=
413 ConfigInfo
.SystemIoBusNumber
= BusNumber
;
415 RtlZeroMemory(&DeviceExtension
->MiniPortDeviceExtension
,
416 DriverExtension
->InitializationData
.HwDeviceExtensionSize
);
418 /* FIXME: Need to figure out what string to pass as param 3. */
419 Status
= DriverExtension
->InitializationData
.HwFindAdapter(
420 &DeviceExtension
->MiniPortDeviceExtension
,
421 DriverExtension
->HwContext
,
426 if (Status
== ERROR_DEV_NOT_EXIST
)
430 else if (Status
== NO_ERROR
)
436 ERR_(VIDEOPRT
, "HwFindAdapter call failed with error 0x%X\n", Status
);
437 RtlFreeUnicodeString(&DeviceExtension
->RegistryPath
);
438 if (DeviceExtension
->NextDeviceObject
)
439 IoDetachDevice(DeviceExtension
->NextDeviceObject
);
440 IoDeleteDevice(DeviceObject
);
448 /* FIXME: Need to figure out what string to pass as param 3. */
449 Status
= DriverExtension
->InitializationData
.HwFindAdapter(
450 &DeviceExtension
->MiniPortDeviceExtension
,
451 DriverExtension
->HwContext
,
457 if (Status
!= NO_ERROR
)
459 ERR_(VIDEOPRT
, "HwFindAdapter call failed with error 0x%X\n", Status
);
460 RtlFreeUnicodeString(&DeviceExtension
->RegistryPath
);
461 if (DeviceExtension
->NextDeviceObject
)
462 IoDetachDevice(DeviceExtension
->NextDeviceObject
);
463 IoDeleteDevice(DeviceObject
);
468 * Now we know the device is present, so let's do all additional tasks
469 * such as creating symlinks or setting up interrupts and timer.
472 /* Create a unicode device name. */
473 swprintf(DeviceBuffer
, L
"\\Device\\Video%lu", DeviceNumber
);
474 RtlInitUnicodeString(&DeviceName
, DeviceBuffer
);
476 /* Create symbolic link "\??\DISPLAYx" */
477 swprintf(SymlinkBuffer
, L
"\\??\\DISPLAY%lu", DeviceNumber
+ 1);
478 RtlInitUnicodeString(&SymlinkName
, SymlinkBuffer
);
479 IoCreateSymbolicLink(&SymlinkName
, &DeviceName
);
481 /* Add entry to DEVICEMAP\VIDEO key in registry. */
482 swprintf(DeviceVideoBuffer
, L
"\\Device\\Video%d", DeviceNumber
);
483 RtlWriteRegistryValue(
484 RTL_REGISTRY_DEVICEMAP
,
488 DeviceExtension
->RegistryPath
.Buffer
,
489 DeviceExtension
->RegistryPath
.Length
+ sizeof(UNICODE_NULL
));
491 RtlWriteRegistryValue(
492 RTL_REGISTRY_DEVICEMAP
,
497 sizeof(DeviceNumber
));
499 /* FIXME: Allocate hardware resources for device. */
501 /* Allocate interrupt for device. */
502 if (!IntVideoPortSetupInterrupt(DeviceObject
, DriverExtension
, &ConfigInfo
))
504 RtlFreeUnicodeString(&DeviceExtension
->RegistryPath
);
505 if (DeviceExtension
->NextDeviceObject
)
506 IoDetachDevice(DeviceExtension
->NextDeviceObject
);
507 IoDeleteDevice(DeviceObject
);
508 return STATUS_INSUFFICIENT_RESOURCES
;
512 * Allocate timer for device.
515 if (!IntVideoPortSetupTimer(DeviceObject
, DriverExtension
))
517 if (DeviceExtension
->InterruptObject
!= NULL
)
518 IoDisconnectInterrupt(DeviceExtension
->InterruptObject
);
519 if (DeviceExtension
->NextDeviceObject
)
520 IoDetachDevice(DeviceExtension
->NextDeviceObject
);
521 RtlFreeUnicodeString(&DeviceExtension
->RegistryPath
);
522 IoDeleteDevice(DeviceObject
);
523 ERR_(VIDEOPRT
, "IntVideoPortSetupTimer failed\n");
524 return STATUS_INSUFFICIENT_RESOURCES
;
527 /* Query children of the device. */
528 VideoPortEnumerateChildren(&DeviceExtension
->MiniPortDeviceExtension
, NULL
);
530 INFO_(VIDEOPRT
, "STATUS_SUCCESS\n");
531 return STATUS_SUCCESS
;
537 PKPROCESS
*CallingProcess
,
538 PKAPC_STATE ApcState
)
540 *CallingProcess
= (PKPROCESS
)PsGetCurrentProcess();
541 if (*CallingProcess
!= Csrss
)
543 KeStackAttachProcess(Csrss
, ApcState
);
550 PKPROCESS
*CallingProcess
,
551 PKAPC_STATE ApcState
)
553 if (*CallingProcess
!= Csrss
)
555 KeUnstackDetachProcess(ApcState
);
559 /* PUBLIC FUNCTIONS ***********************************************************/
569 IN PVIDEO_HW_INITIALIZATION_DATA HwInitializationData
,
572 PDRIVER_OBJECT DriverObject
= Context1
;
573 PUNICODE_STRING RegistryPath
= Context2
;
575 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension
;
576 BOOLEAN PnpDriver
= FALSE
, LegacyDetection
= FALSE
;
578 TRACE_(VIDEOPRT
, "VideoPortInitialize\n");
580 /* As a first thing do parameter checks. */
581 if (HwInitializationData
->HwInitDataSize
> sizeof(VIDEO_HW_INITIALIZATION_DATA
))
583 ERR_(VIDEOPRT
, "Invalid HwInitializationData\n");
584 return STATUS_REVISION_MISMATCH
;
587 if (HwInitializationData
->HwFindAdapter
== NULL
||
588 HwInitializationData
->HwInitialize
== NULL
||
589 HwInitializationData
->HwStartIO
== NULL
)
591 ERR_(VIDEOPRT
, "Invalid HwInitializationData\n");
592 return STATUS_INVALID_PARAMETER
;
595 switch (HwInitializationData
->HwInitDataSize
)
598 * NT4 drivers are special case, because we must use legacy method
599 * of detection instead of the Plug & Play one.
601 case SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA
:
602 INFO_(VIDEOPRT
, "We were loaded by a Windows NT miniport driver.\n");
605 case SIZE_OF_W2K_VIDEO_HW_INITIALIZATION_DATA
:
606 INFO_(VIDEOPRT
, "We were loaded by a Windows 2000 miniport driver.\n");
609 case sizeof(VIDEO_HW_INITIALIZATION_DATA
):
610 INFO_(VIDEOPRT
, "We were loaded by a Windows XP or later miniport driver.\n");
614 ERR_(VIDEOPRT
, "Invalid HwInitializationData size.\n");
615 return STATUS_UNSUCCESSFUL
;
618 /* Set dispatching routines */
619 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = IntVideoPortDispatchOpen
;
620 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = IntVideoPortDispatchClose
;
621 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] =
622 IntVideoPortDispatchDeviceControl
;
623 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] =
624 IntVideoPortDispatchDeviceControl
;
625 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] =
626 IntVideoPortDispatchWrite
; // ReactOS-specific hack
627 DriverObject
->DriverUnload
= IntVideoPortUnload
;
629 /* Determine type of the miniport driver */
630 if ((HwInitializationData
->HwInitDataSize
>=
631 FIELD_OFFSET(VIDEO_HW_INITIALIZATION_DATA
, HwQueryInterface
))
632 && HwInitializationData
->HwSetPowerState
633 && HwInitializationData
->HwGetPowerState
634 && HwInitializationData
->HwGetVideoChildDescriptor
)
636 INFO_(VIDEOPRT
, "The miniport is a PnP miniport driver\n");
640 /* Check if legacy detection should be applied */
641 if (!PnpDriver
|| HwContext
)
643 INFO_(VIDEOPRT
, "Legacy detection for adapter interface %d\n",
644 HwInitializationData
->AdapterInterfaceType
);
646 /* FIXME: Move the code for legacy detection
647 to another function and call it here */
648 LegacyDetection
= TRUE
;
653 * The driver extension can be already allocated in case that we were
654 * called by legacy driver and failed detecting device. Some miniport
655 * drivers in that case adjust parameters and call VideoPortInitialize
658 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
659 if (DriverExtension
== NULL
)
661 Status
= IoAllocateDriverObjectExtension(
664 sizeof(VIDEO_PORT_DRIVER_EXTENSION
),
665 (PVOID
*)&DriverExtension
);
667 if (!NT_SUCCESS(Status
))
669 ERR_(VIDEOPRT
, "IoAllocateDriverObjectExtension failed 0x%x\n", Status
);
674 * Save the registry path. This should be done only once even if
675 * VideoPortInitialize is called multiple times.
677 if (RegistryPath
->Length
!= 0)
679 DriverExtension
->RegistryPath
.Length
= 0;
680 DriverExtension
->RegistryPath
.MaximumLength
=
681 RegistryPath
->Length
+ sizeof(UNICODE_NULL
);
682 DriverExtension
->RegistryPath
.Buffer
=
683 ExAllocatePoolWithTag(
685 DriverExtension
->RegistryPath
.MaximumLength
,
687 if (DriverExtension
->RegistryPath
.Buffer
== NULL
)
689 RtlInitUnicodeString(&DriverExtension
->RegistryPath
, NULL
);
690 return STATUS_INSUFFICIENT_RESOURCES
;
693 RtlCopyUnicodeString(&DriverExtension
->RegistryPath
, RegistryPath
);
694 INFO_(VIDEOPRT
, "RegistryPath: %wZ\n", &DriverExtension
->RegistryPath
);
698 RtlInitUnicodeString(&DriverExtension
->RegistryPath
, NULL
);
703 * Copy the correct miniport initialization data to the device extension.
705 RtlCopyMemory(&DriverExtension
->InitializationData
,
706 HwInitializationData
,
707 HwInitializationData
->HwInitDataSize
);
708 if (HwInitializationData
->HwInitDataSize
<
709 sizeof(VIDEO_HW_INITIALIZATION_DATA
))
711 RtlZeroMemory((PVOID
)((ULONG_PTR
)&DriverExtension
->InitializationData
+
712 HwInitializationData
->HwInitDataSize
),
713 sizeof(VIDEO_HW_INITIALIZATION_DATA
) -
714 HwInitializationData
->HwInitDataSize
);
716 DriverExtension
->HwContext
= HwContext
;
719 * Plug & Play drivers registers the device in AddDevice routine. For
720 * legacy drivers we must do it now.
724 PDEVICE_OBJECT DeviceObject
;
726 if (HwInitializationData
->HwInitDataSize
!= SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA
)
728 /* power management */
729 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = IntVideoPortDispatchPower
;
731 Status
= IntVideoPortCreateAdapterDeviceObject(DriverObject
,
735 if (!NT_SUCCESS(Status
))
737 ERR_(VIDEOPRT
, "IntVideoPortCreateAdapterDeviceObject returned 0x%x\n", Status
);
741 Status
= IntVideoPortFindAdapter(DriverObject
, DriverExtension
, DeviceObject
);
742 if (NT_SUCCESS(Status
))
743 VideoPortDeviceNumber
++;
745 ERR_(VIDEOPRT
, "IntVideoPortFindAdapter returned 0x%x\n", Status
);
751 DriverObject
->DriverExtension
->AddDevice
= IntVideoPortAddDevice
;
752 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = IntVideoPortDispatchPnp
;
753 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = IntVideoPortDispatchPower
;
754 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = IntVideoPortDispatchSystemControl
;
756 return STATUS_SUCCESS
;
765 IN VIDEO_DEBUG_LEVEL DebugPrintLevel
,
766 IN PCHAR DebugMessage
,
771 va_start(ap
, DebugMessage
);
772 vDbgPrintEx(DPFLTR_IHVVIDEO_ID
, DebugPrintLevel
, DebugMessage
, ap
);
782 IN PVOID HwDeviceExtension
,
783 IN PVIDEO_REQUEST_PACKET Vrp OPTIONAL
,
784 IN VP_STATUS ErrorCode
,
789 INFO_(VIDEOPRT
, "VideoPortLogError ErrorCode %d (0x%x) UniqueId %lu (0x%lx)\n",
790 ErrorCode
, ErrorCode
, UniqueId
, UniqueId
);
792 INFO_(VIDEOPRT
, "Vrp->IoControlCode %lu (0x%lx)\n", Vrp
->IoControlCode
, Vrp
->IoControlCode
);
800 VideoPortGetCurrentIrql(VOID
)
802 return KeGetCurrentIrql();
805 typedef struct QueryRegistryCallbackContext
807 PVOID HwDeviceExtension
;
809 PMINIPORT_GET_REGISTRY_ROUTINE HwGetRegistryRoutine
;
810 } QUERY_REGISTRY_CALLBACK_CONTEXT
, *PQUERY_REGISTRY_CALLBACK_CONTEXT
;
815 QueryRegistryCallback(
819 IN ULONG ValueLength
,
821 IN PVOID EntryContext
)
823 PQUERY_REGISTRY_CALLBACK_CONTEXT CallbackContext
= (PQUERY_REGISTRY_CALLBACK_CONTEXT
) Context
;
825 INFO_(VIDEOPRT
, "Found registry value for name %S: type %d, length %d\n",
826 ValueName
, ValueType
, ValueLength
);
827 return (*(CallbackContext
->HwGetRegistryRoutine
))(
828 CallbackContext
->HwDeviceExtension
,
829 CallbackContext
->HwContext
,
841 VideoPortGetRegistryParameters(
842 IN PVOID HwDeviceExtension
,
843 IN PWSTR ParameterName
,
844 IN UCHAR IsParameterFileName
,
845 IN PMINIPORT_GET_REGISTRY_ROUTINE GetRegistryRoutine
,
848 RTL_QUERY_REGISTRY_TABLE QueryTable
[2] = {{0}};
849 QUERY_REGISTRY_CALLBACK_CONTEXT Context
;
850 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
853 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
855 TRACE_(VIDEOPRT
, "VideoPortGetRegistryParameters ParameterName %S, RegPath: %wZ\n",
856 ParameterName
, &DeviceExtension
->RegistryPath
);
858 Context
.HwDeviceExtension
= HwDeviceExtension
;
859 Context
.HwContext
= HwContext
;
860 Context
.HwGetRegistryRoutine
= GetRegistryRoutine
;
862 QueryTable
[0].QueryRoutine
= QueryRegistryCallback
;
863 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
;
864 QueryTable
[0].Name
= ParameterName
;
866 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
867 DeviceExtension
->RegistryPath
.Buffer
,
871 if (!NT_SUCCESS(Status
))
873 WARN_(VIDEOPRT
, "VideoPortGetRegistryParameters could not find the "
874 "requested parameter\n");
875 return ERROR_INVALID_PARAMETER
;
878 if (IsParameterFileName
)
880 /* FIXME: need to read the contents of the file */
892 VideoPortSetRegistryParameters(
893 IN PVOID HwDeviceExtension
,
896 IN ULONG ValueLength
)
898 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
901 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
902 TRACE_(VIDEOPRT
, "VideoPortSetRegistryParameters ParameterName %S, RegPath: %wZ\n",
904 &DeviceExtension
->RegistryPath
);
905 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL
);
906 Status
= RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE
,
907 DeviceExtension
->RegistryPath
.Buffer
,
912 if (Status
!= NO_ERROR
)
913 WARN_(VIDEOPRT
, "VideoPortSetRegistryParameters error 0x%x\n", Status
);
923 VideoPortGetVgaStatus(
924 IN PVOID HwDeviceExtension
,
925 OUT PULONG VgaStatus
)
927 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
929 TRACE_(VIDEOPRT
, "VideoPortGetVgaStatus\n");
931 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
932 if (KeGetCurrentIrql() == PASSIVE_LEVEL
)
934 if (DeviceExtension
->AdapterInterfaceType
== PCIBus
)
936 /* VgaStatus: 0 == VGA not enabled, 1 == VGA enabled. */
937 /* Assumed for now */
943 return ERROR_INVALID_FUNCTION
;
951 VideoPortGetRomImage(
952 IN PVOID HwDeviceExtension
,
957 static PVOID RomImageBuffer
= NULL
;
958 PKPROCESS CallingProcess
;
961 TRACE_(VIDEOPRT
, "VideoPortGetRomImage(HwDeviceExtension 0x%X Length 0x%X)\n",
962 HwDeviceExtension
, Length
);
964 /* If the length is zero then free the existing buffer. */
967 if (RomImageBuffer
!= NULL
)
969 ExFreePool(RomImageBuffer
);
970 RomImageBuffer
= NULL
;
977 * The DDK says we shouldn't use the legacy C0000 method but get the
978 * rom base address from the corresponding pci or acpi register but
979 * lets ignore that and use C0000 anyway. We have already mapped the
980 * bios area into memory so we'll copy from there.
984 Length
= min(Length
, 0x10000);
985 if (RomImageBuffer
!= NULL
)
987 ExFreePool(RomImageBuffer
);
990 RomImageBuffer
= ExAllocatePool(PagedPool
, Length
);
991 if (RomImageBuffer
== NULL
)
996 IntAttachToCSRSS(&CallingProcess
, &ApcState
);
997 RtlCopyMemory(RomImageBuffer
, (PUCHAR
)0xC0000, Length
);
998 IntDetachFromCSRSS(&CallingProcess
, &ApcState
);
1000 return RomImageBuffer
;
1010 IN PVOID HwDeviceExtension
,
1017 PUCHAR SearchLocation
;
1019 TRACE_(VIDEOPRT
, "VideoPortScanRom RomBase %p RomLength 0x%x String %s\n", RomBase
, RomLength
, String
);
1021 StringLength
= strlen((PCHAR
)String
);
1023 SearchLocation
= RomBase
;
1024 for (SearchLocation
= RomBase
;
1025 !Found
&& SearchLocation
< RomBase
+ RomLength
- StringLength
;
1028 Found
= (RtlCompareMemory(SearchLocation
, String
, StringLength
) == StringLength
);
1031 INFO_(VIDEOPRT
, "Match found at %p\n", SearchLocation
);
1043 VideoPortSynchronizeExecution(
1044 IN PVOID HwDeviceExtension
,
1045 IN VIDEO_SYNCHRONIZE_PRIORITY Priority
,
1046 IN PMINIPORT_SYNCHRONIZE_ROUTINE SynchronizeRoutine
,
1050 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
1056 Ret
= (*SynchronizeRoutine
)(Context
);
1059 case VpMediumPriority
:
1060 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
1061 if (DeviceExtension
->InterruptObject
== NULL
)
1062 Ret
= (*SynchronizeRoutine
)(Context
);
1064 Ret
= KeSynchronizeExecution(
1065 DeviceExtension
->InterruptObject
,
1070 case VpHighPriority
:
1071 OldIrql
= KeGetCurrentIrql();
1072 if (OldIrql
< SYNCH_LEVEL
)
1073 KeRaiseIrql(SYNCH_LEVEL
, &OldIrql
);
1075 Ret
= (*SynchronizeRoutine
)(Context
);
1077 if (OldIrql
< SYNCH_LEVEL
)
1078 KeLowerIrql(OldIrql
);
1093 VideoPortEnumerateChildren(
1094 IN PVOID HwDeviceExtension
,
1097 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
1099 VIDEO_CHILD_ENUM_INFO ChildEnumInfo
;
1100 BOOLEAN bHaveLastMonitorID
= FALSE
;
1101 UCHAR LastMonitorID
[10];
1104 PDEVICE_OBJECT ChildDeviceObject
;
1105 PVIDEO_PORT_CHILD_EXTENSION ChildExtension
;
1107 INFO_(VIDEOPRT
, "Starting child device probe\n");
1108 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
1109 if (DeviceExtension
->DriverExtension
->InitializationData
.HwGetVideoChildDescriptor
== NULL
)
1111 WARN_(VIDEOPRT
, "Miniport's HwGetVideoChildDescriptor is NULL!\n");
1115 if (!IsListEmpty(&DeviceExtension
->ChildDeviceList
))
1117 ERR_(VIDEOPRT
, "FIXME: Support calling VideoPortEnumerateChildren again!\n");
1121 /* Enumerate the children */
1124 Status
= IoCreateDevice(DeviceExtension
->DriverObject
,
1125 sizeof(VIDEO_PORT_CHILD_EXTENSION
) +
1126 DeviceExtension
->DriverExtension
->InitializationData
.HwChildDeviceExtensionSize
,
1128 FILE_DEVICE_CONTROLLER
,
1129 FILE_DEVICE_SECURE_OPEN
,
1131 &ChildDeviceObject
);
1132 if (!NT_SUCCESS(Status
))
1135 ChildExtension
= ChildDeviceObject
->DeviceExtension
;
1137 RtlZeroMemory(ChildExtension
,
1138 sizeof(VIDEO_PORT_CHILD_EXTENSION
) +
1139 DeviceExtension
->DriverExtension
->InitializationData
.HwChildDeviceExtensionSize
);
1141 ChildExtension
->Common
.Fdo
= FALSE
;
1142 ChildExtension
->ChildId
= i
;
1143 ChildExtension
->PhysicalDeviceObject
= ChildDeviceObject
;
1144 ChildExtension
->DriverObject
= DeviceExtension
->DriverObject
;
1146 /* Setup the ChildEnumInfo */
1147 ChildEnumInfo
.Size
= sizeof(ChildEnumInfo
);
1148 ChildEnumInfo
.ChildDescriptorSize
= sizeof(ChildExtension
->ChildDescriptor
);
1149 ChildEnumInfo
.ACPIHwId
= 0;
1151 if (DeviceExtension
->DriverExtension
->InitializationData
.HwChildDeviceExtensionSize
)
1152 ChildEnumInfo
.ChildHwDeviceExtension
= VIDEO_PORT_GET_CHILD_EXTENSION(ChildExtension
);
1154 ChildEnumInfo
.ChildHwDeviceExtension
= NULL
;
1156 ChildEnumInfo
.ChildIndex
= ChildExtension
->ChildId
;
1158 INFO_(VIDEOPRT
, "Probing child: %d\n", ChildEnumInfo
.ChildIndex
);
1159 Status
= DeviceExtension
->DriverExtension
->InitializationData
.HwGetVideoChildDescriptor(
1162 &ChildExtension
->ChildType
,
1163 ChildExtension
->ChildDescriptor
,
1164 &ChildExtension
->ChildId
,
1166 if (Status
== VIDEO_ENUM_MORE_DEVICES
)
1168 if (ChildExtension
->ChildType
== Monitor
)
1170 // Check if the EDID is valid
1171 if (ChildExtension
->ChildDescriptor
[0] == 0x00 &&
1172 ChildExtension
->ChildDescriptor
[1] == 0xFF &&
1173 ChildExtension
->ChildDescriptor
[2] == 0xFF &&
1174 ChildExtension
->ChildDescriptor
[3] == 0xFF &&
1175 ChildExtension
->ChildDescriptor
[4] == 0xFF &&
1176 ChildExtension
->ChildDescriptor
[5] == 0xFF &&
1177 ChildExtension
->ChildDescriptor
[6] == 0xFF &&
1178 ChildExtension
->ChildDescriptor
[7] == 0x00)
1180 if (bHaveLastMonitorID
)
1182 // Compare the previous monitor ID with the current one, break the loop if they are identical
1183 if (RtlCompareMemory(LastMonitorID
, &ChildExtension
->ChildDescriptor
[8], sizeof(LastMonitorID
)) == sizeof(LastMonitorID
))
1185 INFO_(VIDEOPRT
, "Found identical Monitor ID two times, stopping enumeration\n");
1186 IoDeleteDevice(ChildDeviceObject
);
1191 // Copy 10 bytes from the EDID, which can be used to uniquely identify the monitor
1192 RtlCopyMemory(LastMonitorID
, &ChildExtension
->ChildDescriptor
[8], sizeof(LastMonitorID
));
1193 bHaveLastMonitorID
= TRUE
;
1196 ChildExtension
->EdidValid
= TRUE
;
1200 /* Mark it invalid */
1201 ChildExtension
->EdidValid
= FALSE
;
1205 else if (Status
== VIDEO_ENUM_INVALID_DEVICE
)
1207 WARN_(VIDEOPRT
, "Child device %d is invalid!\n", ChildEnumInfo
.ChildIndex
);
1208 IoDeleteDevice(ChildDeviceObject
);
1211 else if (Status
== VIDEO_ENUM_NO_MORE_DEVICES
)
1213 INFO_(VIDEOPRT
, "End of child enumeration! (%d children enumerated)\n", i
- 1);
1214 IoDeleteDevice(ChildDeviceObject
);
1219 WARN_(VIDEOPRT
, "HwGetVideoChildDescriptor returned unknown status code 0x%x!\n", Status
);
1220 IoDeleteDevice(ChildDeviceObject
);
1224 if (ChildExtension
->ChildType
== Monitor
)
1227 PUCHAR p
= ChildExtension
->ChildDescriptor
;
1228 INFO_(VIDEOPRT
, "Monitor device enumerated! (ChildId = 0x%x)\n", ChildExtension
->ChildId
);
1229 for (j
= 0; j
< sizeof (ChildExtension
->ChildDescriptor
); j
+= 8)
1231 INFO_(VIDEOPRT
, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
1232 p
[j
+ 0], p
[j
+ 1], p
[j
+ 2], p
[j
+ 3],
1233 p
[j
+ 4], p
[j
+ 5], p
[j
+ 6], p
[j
+ 7]);
1236 else if (ChildExtension
->ChildType
== Other
)
1238 INFO_(VIDEOPRT
, "\"Other\" device enumerated: DeviceId = %S\n", (PWSTR
)ChildExtension
->ChildDescriptor
);
1242 ERR_(VIDEOPRT
, "HwGetVideoChildDescriptor returned unsupported type: %d\n", ChildExtension
->ChildType
);
1245 /* Clear the init flag */
1246 ChildDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1248 InsertTailList(&DeviceExtension
->ChildDeviceList
,
1249 &ChildExtension
->ListEntry
);
1252 /* Trigger reenumeration by the PnP manager */
1253 IoInvalidateDeviceRelations(DeviceExtension
->PhysicalDeviceObject
, BusRelations
);
1263 VideoPortCreateSecondaryDisplay(
1264 IN PVOID HwDeviceExtension
,
1265 IN OUT PVOID
*SecondaryDeviceExtension
,
1269 return ERROR_DEV_NOT_EXIST
;
1278 IN PVOID HwDeviceExtension
,
1279 IN PMINIPORT_DPC_ROUTINE CallbackRoutine
,
1282 return KeInsertQueueDpc(
1283 &VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
)->DpcObject
,
1284 (PVOID
)CallbackRoutine
,
1293 VideoPortGetAssociatedDeviceExtension(
1294 IN PVOID DeviceObject
)
1296 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
1298 TRACE_(VIDEOPRT
, "VideoPortGetAssociatedDeviceExtension\n");
1299 DeviceExtension
= ((PDEVICE_OBJECT
)DeviceObject
)->DeviceExtension
;
1300 if (!DeviceExtension
)
1302 return DeviceExtension
->MiniPortDeviceExtension
;
1310 VideoPortGetVersion(
1311 IN PVOID HwDeviceExtension
,
1312 IN OUT PVPOSVERSIONINFO VpOsVersionInfo
)
1314 RTL_OSVERSIONINFOEXW Version
;
1316 Version
.dwOSVersionInfoSize
= sizeof(RTL_OSVERSIONINFOEXW
);
1317 if (VpOsVersionInfo
->Size
>= sizeof(VPOSVERSIONINFO
))
1320 if (NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW
)&Version
)))
1322 VpOsVersionInfo
->MajorVersion
= Version
.dwMajorVersion
;
1323 VpOsVersionInfo
->MinorVersion
= Version
.dwMinorVersion
;
1324 VpOsVersionInfo
->BuildNumber
= Version
.dwBuildNumber
;
1325 VpOsVersionInfo
->ServicePackMajor
= Version
.wServicePackMajor
;
1326 VpOsVersionInfo
->ServicePackMinor
= Version
.wServicePackMinor
;
1329 return ERROR_INVALID_PARAMETER
;
1331 VpOsVersionInfo
->MajorVersion
= 5;
1332 VpOsVersionInfo
->MinorVersion
= 0;
1333 VpOsVersionInfo
->BuildNumber
= 2195;
1334 VpOsVersionInfo
->ServicePackMajor
= 4;
1335 VpOsVersionInfo
->ServicePackMinor
= 0;
1340 return ERROR_INVALID_PARAMETER
;
1348 VideoPortCheckForDeviceExistence(
1349 IN PVOID HwDeviceExtension
,
1352 IN UCHAR RevisionId
,
1353 IN USHORT SubVendorId
,
1354 IN USHORT SubSystemId
,
1357 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
1358 PCI_DEVICE_PRESENT_INTERFACE PciDevicePresentInterface
;
1359 IO_STATUS_BLOCK IoStatusBlock
;
1360 IO_STACK_LOCATION IoStack
;
1365 TRACE_(VIDEOPRT
, "VideoPortCheckForDeviceExistence\n");
1367 if (Flags
& ~(CDE_USE_REVISION
| CDE_USE_SUBSYSTEM_IDS
))
1369 WARN_(VIDEOPRT
, "VideoPortCheckForDeviceExistence: Unknown flags 0x%lx\n", Flags
& ~(CDE_USE_REVISION
| CDE_USE_SUBSYSTEM_IDS
));
1373 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
1375 PciDevicePresentInterface
.Size
= sizeof(PCI_DEVICE_PRESENT_INTERFACE
);
1376 PciDevicePresentInterface
.Version
= 1;
1377 IoStack
.Parameters
.QueryInterface
.Size
= PciDevicePresentInterface
.Size
;
1378 IoStack
.Parameters
.QueryInterface
.Version
= PciDevicePresentInterface
.Version
;
1379 IoStack
.Parameters
.QueryInterface
.Interface
= (PINTERFACE
)&PciDevicePresentInterface
;
1380 IoStack
.Parameters
.QueryInterface
.InterfaceType
=
1381 &GUID_PCI_DEVICE_PRESENT_INTERFACE
;
1382 Status
= IopInitiatePnpIrp(DeviceExtension
->NextDeviceObject
,
1383 &IoStatusBlock
, IRP_MN_QUERY_INTERFACE
, &IoStack
);
1384 if (!NT_SUCCESS(Status
))
1386 WARN_(VIDEOPRT
, "IopInitiatePnpIrp() failed! (Status 0x%lx)\n", Status
);
1390 if (Flags
& CDE_USE_REVISION
)
1391 PciFlags
|= PCI_USE_REVISION
;
1392 if (Flags
& CDE_USE_SUBSYSTEM_IDS
)
1393 PciFlags
|= PCI_USE_SUBSYSTEM_IDS
;
1395 DevicePresent
= PciDevicePresentInterface
.IsDevicePresent(
1396 VendorId
, DeviceId
, RevisionId
,
1397 SubVendorId
, SubSystemId
, PciFlags
);
1399 PciDevicePresentInterface
.InterfaceDereference(PciDevicePresentInterface
.Context
);
1401 return DevicePresent
;
1409 VideoPortRegisterBugcheckCallback(
1410 IN PVOID HwDeviceExtension
,
1411 IN ULONG BugcheckCode
,
1412 IN PVIDEO_BUGCHECK_CALLBACK Callback
,
1413 IN ULONG BugcheckDataSize
)
1424 VideoPortQueryPerformanceCounter(
1425 IN PVOID HwDeviceExtension
,
1426 OUT PLONGLONG PerformanceFrequency OPTIONAL
)
1428 LARGE_INTEGER Result
;
1430 TRACE_(VIDEOPRT
, "VideoPortQueryPerformanceCounter\n");
1431 Result
= KeQueryPerformanceCounter((PLARGE_INTEGER
)PerformanceFrequency
);
1432 return Result
.QuadPart
;
1440 VideoPortAcquireDeviceLock(
1441 IN PVOID HwDeviceExtension
)
1443 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
1447 TRACE_(VIDEOPRT
, "VideoPortAcquireDeviceLock\n");
1448 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
1449 Status
= KeWaitForMutexObject(&DeviceExtension
->DeviceLock
, Executive
,
1450 KernelMode
, FALSE
, NULL
);
1451 // ASSERT(Status == STATUS_SUCCESS);
1459 VideoPortReleaseDeviceLock(
1460 IN PVOID HwDeviceExtension
)
1462 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
1466 TRACE_(VIDEOPRT
, "VideoPortReleaseDeviceLock\n");
1467 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
1468 Status
= KeReleaseMutex(&DeviceExtension
->DeviceLock
, FALSE
);
1469 //ASSERT(Status == STATUS_SUCCESS);
1478 IN PDEVICE_OBJECT DeviceObject
,
1489 VideoPortAllocateContiguousMemory(
1490 IN PVOID HwDeviceExtension
,
1491 IN ULONG NumberOfBytes
,
1492 IN PHYSICAL_ADDRESS HighestAcceptableAddress
1496 return MmAllocateContiguousMemory(NumberOfBytes
, HighestAcceptableAddress
);
1504 VideoPortIsNoVesa(VOID
)
1508 UNICODE_STRING Path
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control");
1509 UNICODE_STRING ValueName
= RTL_CONSTANT_STRING(L
"SystemStartOptions");
1510 OBJECT_ATTRIBUTES ObjectAttributes
;
1511 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
1512 ULONG Length
, NewLength
;
1514 /* Initialize object attributes with the path we want */
1515 InitializeObjectAttributes(&ObjectAttributes
,
1517 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
1522 Status
= ZwOpenKey(&KeyHandle
,
1526 if (!NT_SUCCESS(Status
))
1528 VideoPortDebugPrint(Error
, "ZwOpenKey failed (0x%x)\n", Status
);
1532 /* Find out how large our buffer should be */
1533 Status
= ZwQueryValueKey(KeyHandle
,
1535 KeyValuePartialInformation
,
1539 if (Status
!= STATUS_BUFFER_OVERFLOW
&& Status
!= STATUS_BUFFER_TOO_SMALL
)
1541 VideoPortDebugPrint(Error
, "ZwQueryValueKey failed (0x%x)\n", Status
);
1547 KeyInfo
= ExAllocatePool(PagedPool
, Length
);
1550 VideoPortDebugPrint(Error
, "Out of memory\n");
1555 /* Now for real this time */
1556 Status
= ZwQueryValueKey(KeyHandle
,
1558 KeyValuePartialInformation
,
1565 if (!NT_SUCCESS(Status
))
1567 VideoPortDebugPrint(Error
, "ZwQueryValueKey failed (0x%x)\n", Status
);
1568 ExFreePool(KeyInfo
);
1573 if (KeyInfo
->Type
!= REG_SZ
)
1575 VideoPortDebugPrint(Error
, "Invalid type for SystemStartOptions\n");
1576 ExFreePool(KeyInfo
);
1580 /* Check if NOVESA or BASEVIDEO is present in the start options */
1581 if (wcsstr((PWCHAR
)KeyInfo
->Data
, L
"NOVESA") ||
1582 wcsstr((PWCHAR
)KeyInfo
->Data
, L
"BASEVIDEO"))
1584 VideoPortDebugPrint(Info
, "VESA mode disabled\n");
1585 ExFreePool(KeyInfo
);
1589 ExFreePool(KeyInfo
);
1591 VideoPortDebugPrint(Info
, "VESA mode enabled\n");