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 IntVideoPortCreateAdapterDeviceObject(
81 IN PDRIVER_OBJECT DriverObject
,
82 IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension
,
83 IN PDEVICE_OBJECT PhysicalDeviceObject
,
84 OUT PDEVICE_OBJECT
*DeviceObject OPTIONAL
)
86 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
89 PCI_SLOT_NUMBER SlotNumber
;
92 WCHAR DeviceBuffer
[20];
93 UNICODE_STRING DeviceName
;
94 PDEVICE_OBJECT DeviceObject_
;
96 if (DeviceObject
== NULL
)
97 DeviceObject
= &DeviceObject_
;
100 * Find the first free device number that can be used for video device
101 * object names and symlinks.
103 DeviceNumber
= VideoPortDeviceNumber
;
104 if (DeviceNumber
== 0xFFFFFFFF)
106 WARN_(VIDEOPRT
, "Can't find free device number\n");
107 return STATUS_UNSUCCESSFUL
;
111 * Create the device object.
114 /* Create a unicode device name. */
115 swprintf(DeviceBuffer
, L
"\\Device\\Video%lu", DeviceNumber
);
116 RtlInitUnicodeString(&DeviceName
, DeviceBuffer
);
118 INFO_(VIDEOPRT
, "HwDeviceExtension size is: 0x%x\n",
119 DriverExtension
->InitializationData
.HwDeviceExtensionSize
);
121 /* Create the device object. */
122 Size
= sizeof(VIDEO_PORT_DEVICE_EXTENSION
) +
123 DriverExtension
->InitializationData
.HwDeviceExtensionSize
;
124 Status
= IoCreateDevice(DriverObject
,
132 if (!NT_SUCCESS(Status
))
134 WARN_(VIDEOPRT
, "IoCreateDevice call failed with status 0x%08x\n", Status
);
139 * Set the buffering strategy here. If you change this, remember
140 * to change VidDispatchDeviceControl too.
143 (*DeviceObject
)->Flags
|= DO_BUFFERED_IO
;
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 DeviceExtension
->SessionId
= -1;
155 InitializeListHead(&DeviceExtension
->ChildDeviceList
);
157 /* Get the registry path associated with this device. */
158 Status
= IntCreateRegistryPath(&DriverExtension
->RegistryPath
,
159 &DeviceExtension
->RegistryPath
);
160 if (!NT_SUCCESS(Status
))
162 WARN_(VIDEOPRT
, "IntCreateRegistryPath() call failed with status 0x%08x\n", Status
);
163 IoDeleteDevice(*DeviceObject
);
164 *DeviceObject
= NULL
;
168 if (PhysicalDeviceObject
!= NULL
)
170 /* Get bus number from the upper level bus driver. */
171 Size
= sizeof(ULONG
);
172 Status
= IoGetDeviceProperty(PhysicalDeviceObject
,
173 DevicePropertyBusNumber
,
175 &DeviceExtension
->SystemIoBusNumber
,
177 if (!NT_SUCCESS(Status
))
179 WARN_(VIDEOPRT
, "Couldn't get an information from bus driver. We will try to\n"
180 "use legacy detection method, but even that doesn't mean that\n"
182 DeviceExtension
->PhysicalDeviceObject
= NULL
;
186 DeviceExtension
->AdapterInterfaceType
=
187 DriverExtension
->InitializationData
.AdapterInterfaceType
;
189 if (PhysicalDeviceObject
!= NULL
)
191 /* Get bus type from the upper level bus driver. */
192 Size
= sizeof(ULONG
);
193 IoGetDeviceProperty(PhysicalDeviceObject
,
194 DevicePropertyLegacyBusType
,
196 &DeviceExtension
->AdapterInterfaceType
,
199 /* Get bus device address from the upper level bus driver. */
200 Size
= sizeof(ULONG
);
201 IoGetDeviceProperty(PhysicalDeviceObject
,
202 DevicePropertyAddress
,
207 /* Convert slotnumber to PCI_SLOT_NUMBER */
208 SlotNumber
.u
.AsULONG
= 0;
209 SlotNumber
.u
.bits
.DeviceNumber
= (PciSlotNumber
>> 16) & 0xFFFF;
210 SlotNumber
.u
.bits
.FunctionNumber
= PciSlotNumber
& 0xFFFF;
211 DeviceExtension
->SystemIoSlotNumber
= SlotNumber
.u
.AsULONG
;
214 InitializeListHead(&DeviceExtension
->AddressMappingListHead
);
215 InitializeListHead(&DeviceExtension
->DmaAdapterList
);
217 KeInitializeDpc(&DeviceExtension
->DpcObject
,
218 IntVideoPortDeferredRoutine
,
221 KeInitializeMutex(&DeviceExtension
->DeviceLock
, 0);
223 /* Attach the device. */
224 if (PhysicalDeviceObject
!= NULL
)
225 DeviceExtension
->NextDeviceObject
= IoAttachDeviceToDeviceStack(
227 PhysicalDeviceObject
);
229 IntCreateNewRegistryPath(DeviceExtension
);
230 IntSetupDeviceSettingsKey(DeviceExtension
);
232 /* Remove the initailizing flag */
233 (*DeviceObject
)->Flags
&= ~DO_DEVICE_INITIALIZING
;
234 return STATUS_SUCCESS
;
240 IntVideoPortFindAdapter(
241 IN PDRIVER_OBJECT DriverObject
,
242 IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension
,
243 IN PDEVICE_OBJECT DeviceObject
)
245 WCHAR DeviceVideoBuffer
[20];
246 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
249 VIDEO_PORT_CONFIG_INFO ConfigInfo
;
250 SYSTEM_BASIC_INFORMATION SystemBasicInfo
;
252 WCHAR DeviceBuffer
[20];
253 UNICODE_STRING DeviceName
;
254 WCHAR SymlinkBuffer
[20];
255 UNICODE_STRING SymlinkName
;
256 BOOL LegacyDetection
= FALSE
;
259 DeviceExtension
= (PVIDEO_PORT_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
260 DeviceNumber
= DeviceExtension
->DeviceNumber
;
262 /* Setup a ConfigInfo structure that we will pass to HwFindAdapter. */
263 RtlZeroMemory(&ConfigInfo
, sizeof(VIDEO_PORT_CONFIG_INFO
));
264 ConfigInfo
.Length
= sizeof(VIDEO_PORT_CONFIG_INFO
);
265 ConfigInfo
.AdapterInterfaceType
= DeviceExtension
->AdapterInterfaceType
;
266 if (ConfigInfo
.AdapterInterfaceType
== PCIBus
)
267 ConfigInfo
.InterruptMode
= LevelSensitive
;
269 ConfigInfo
.InterruptMode
= Latched
;
270 ConfigInfo
.DriverRegistryPath
= DriverExtension
->RegistryPath
.Buffer
;
271 ConfigInfo
.VideoPortGetProcAddress
= IntVideoPortGetProcAddress
;
272 ConfigInfo
.SystemIoBusNumber
= DeviceExtension
->SystemIoBusNumber
;
273 ConfigInfo
.BusInterruptLevel
= DeviceExtension
->InterruptLevel
;
274 ConfigInfo
.BusInterruptVector
= DeviceExtension
->InterruptVector
;
276 Size
= sizeof(SystemBasicInfo
);
277 Status
= ZwQuerySystemInformation(SystemBasicInformation
,
281 if (NT_SUCCESS(Status
))
283 ConfigInfo
.SystemMemorySize
= SystemBasicInfo
.NumberOfPhysicalPages
*
284 SystemBasicInfo
.PageSize
;
288 * Call miniport HwVidFindAdapter entry point to detect if
289 * particular device is present. There are two possible code
290 * paths. The first one is for Legacy drivers (NT4) and cases
291 * when we don't have information about what bus we're on. The
292 * second case is the standard one for Plug & Play drivers.
294 if (DeviceExtension
->PhysicalDeviceObject
== NULL
)
296 LegacyDetection
= TRUE
;
301 ULONG BusNumber
, MaxBuses
;
303 MaxBuses
= DeviceExtension
->AdapterInterfaceType
== PCIBus
? PCI_MAX_BRIDGE_NUMBER
: 1;
305 for (BusNumber
= 0; BusNumber
< MaxBuses
; BusNumber
++)
307 DeviceExtension
->SystemIoBusNumber
=
308 ConfigInfo
.SystemIoBusNumber
= BusNumber
;
310 RtlZeroMemory(&DeviceExtension
->MiniPortDeviceExtension
,
311 DriverExtension
->InitializationData
.HwDeviceExtensionSize
);
313 /* FIXME: Need to figure out what string to pass as param 3. */
314 Status
= DriverExtension
->InitializationData
.HwFindAdapter(
315 &DeviceExtension
->MiniPortDeviceExtension
,
316 DriverExtension
->HwContext
,
321 if (Status
== ERROR_DEV_NOT_EXIST
)
325 else if (Status
== NO_ERROR
)
331 ERR_(VIDEOPRT
, "HwFindAdapter call failed with error 0x%X\n", Status
);
338 /* FIXME: Need to figure out what string to pass as param 3. */
339 Status
= DriverExtension
->InitializationData
.HwFindAdapter(
340 &DeviceExtension
->MiniPortDeviceExtension
,
341 DriverExtension
->HwContext
,
347 if (Status
!= NO_ERROR
)
349 ERR_(VIDEOPRT
, "HwFindAdapter call failed with error 0x%X\n", Status
);
354 * Now we know the device is present, so let's do all additional tasks
355 * such as creating symlinks or setting up interrupts and timer.
358 /* Create a unicode device name. */
359 swprintf(DeviceBuffer
, L
"\\Device\\Video%lu", DeviceNumber
);
360 RtlInitUnicodeString(&DeviceName
, DeviceBuffer
);
362 /* Create symbolic link "\??\DISPLAYx" */
363 swprintf(SymlinkBuffer
, L
"\\??\\DISPLAY%lu", DeviceNumber
+ 1);
364 RtlInitUnicodeString(&SymlinkName
, SymlinkBuffer
);
365 IoCreateSymbolicLink(&SymlinkName
, &DeviceName
);
367 /* Add entry to DEVICEMAP\VIDEO key in registry. */
368 swprintf(DeviceVideoBuffer
, L
"\\Device\\Video%d", DeviceNumber
);
369 RtlWriteRegistryValue(
370 RTL_REGISTRY_DEVICEMAP
,
374 DeviceExtension
->RegistryPath
.Buffer
,
375 DeviceExtension
->RegistryPath
.Length
+ sizeof(UNICODE_NULL
));
377 RtlWriteRegistryValue(
378 RTL_REGISTRY_DEVICEMAP
,
383 sizeof(DeviceNumber
));
385 /* FIXME: Allocate hardware resources for device. */
387 /* Allocate interrupt for device. */
388 if (!IntVideoPortSetupInterrupt(DeviceObject
, DriverExtension
, &ConfigInfo
))
390 Status
= STATUS_INSUFFICIENT_RESOURCES
;
394 /* Allocate timer for device. */
395 if (!IntVideoPortSetupTimer(DeviceObject
, DriverExtension
))
397 if (DeviceExtension
->InterruptObject
!= NULL
)
398 IoDisconnectInterrupt(DeviceExtension
->InterruptObject
);
399 ERR_(VIDEOPRT
, "IntVideoPortSetupTimer failed\n");
400 Status
= STATUS_INSUFFICIENT_RESOURCES
;
404 /* Query children of the device. */
405 VideoPortEnumerateChildren(&DeviceExtension
->MiniPortDeviceExtension
, NULL
);
407 INFO_(VIDEOPRT
, "STATUS_SUCCESS\n");
408 return STATUS_SUCCESS
;
411 RtlFreeUnicodeString(&DeviceExtension
->RegistryPath
);
412 if (DeviceExtension
->NextDeviceObject
)
413 IoDetachDevice(DeviceExtension
->NextDeviceObject
);
414 IoDeleteDevice(DeviceObject
);
421 PKPROCESS
*CallingProcess
,
422 PKAPC_STATE ApcState
)
424 *CallingProcess
= (PKPROCESS
)PsGetCurrentProcess();
425 if (*CallingProcess
!= Csrss
)
427 KeStackAttachProcess(Csrss
, ApcState
);
434 PKPROCESS
*CallingProcess
,
435 PKAPC_STATE ApcState
)
437 if (*CallingProcess
!= Csrss
)
439 KeUnstackDetachProcess(ApcState
);
443 /* PUBLIC FUNCTIONS ***********************************************************/
453 IN PVIDEO_HW_INITIALIZATION_DATA HwInitializationData
,
456 PDRIVER_OBJECT DriverObject
= Context1
;
457 PUNICODE_STRING RegistryPath
= Context2
;
459 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension
;
460 BOOLEAN PnpDriver
= FALSE
, LegacyDetection
= FALSE
;
462 TRACE_(VIDEOPRT
, "VideoPortInitialize\n");
464 /* As a first thing do parameter checks. */
465 if (HwInitializationData
->HwInitDataSize
> sizeof(VIDEO_HW_INITIALIZATION_DATA
))
467 ERR_(VIDEOPRT
, "Invalid HwInitializationData\n");
468 return STATUS_REVISION_MISMATCH
;
471 if ((HwInitializationData
->HwFindAdapter
== NULL
) ||
472 (HwInitializationData
->HwInitialize
== NULL
) ||
473 (HwInitializationData
->HwStartIO
== NULL
))
475 ERR_(VIDEOPRT
, "Invalid HwInitializationData\n");
476 return STATUS_INVALID_PARAMETER
;
479 switch (HwInitializationData
->HwInitDataSize
)
482 * NT4 drivers are special case, because we must use legacy method
483 * of detection instead of the Plug & Play one.
485 case SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA
:
486 INFO_(VIDEOPRT
, "We were loaded by a Windows NT miniport driver.\n");
489 case SIZE_OF_W2K_VIDEO_HW_INITIALIZATION_DATA
:
490 INFO_(VIDEOPRT
, "We were loaded by a Windows 2000 miniport driver.\n");
493 case sizeof(VIDEO_HW_INITIALIZATION_DATA
):
494 INFO_(VIDEOPRT
, "We were loaded by a Windows XP or later miniport driver.\n");
498 ERR_(VIDEOPRT
, "Invalid HwInitializationData size.\n");
499 return STATUS_UNSUCCESSFUL
;
502 /* Set dispatching routines */
503 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = IntVideoPortDispatchOpen
;
504 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = IntVideoPortDispatchClose
;
505 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] =
506 IntVideoPortDispatchDeviceControl
;
507 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] =
508 IntVideoPortDispatchDeviceControl
;
509 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] =
510 IntVideoPortDispatchWrite
; // ReactOS-specific hack
511 DriverObject
->DriverUnload
= IntVideoPortUnload
;
513 /* Determine type of the miniport driver */
514 if ((HwInitializationData
->HwInitDataSize
>=
515 FIELD_OFFSET(VIDEO_HW_INITIALIZATION_DATA
, HwQueryInterface
)) &&
516 (HwInitializationData
->HwSetPowerState
!= NULL
) &&
517 (HwInitializationData
->HwGetPowerState
!= NULL
) &&
518 (HwInitializationData
->HwGetVideoChildDescriptor
!= NULL
))
520 INFO_(VIDEOPRT
, "The miniport is a PnP miniport driver\n");
524 /* Check if legacy detection should be applied */
525 if (!PnpDriver
|| HwContext
)
527 INFO_(VIDEOPRT
, "Legacy detection for adapter interface %d\n",
528 HwInitializationData
->AdapterInterfaceType
);
530 /* FIXME: Move the code for legacy detection
531 to another function and call it here */
532 LegacyDetection
= TRUE
;
537 * The driver extension can be already allocated in case that we were
538 * called by legacy driver and failed detecting device. Some miniport
539 * drivers in that case adjust parameters and call VideoPortInitialize
542 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
543 if (DriverExtension
== NULL
)
545 Status
= IoAllocateDriverObjectExtension(DriverObject
,
547 sizeof(VIDEO_PORT_DRIVER_EXTENSION
),
548 (PVOID
*)&DriverExtension
);
549 if (!NT_SUCCESS(Status
))
551 ERR_(VIDEOPRT
, "IoAllocateDriverObjectExtension failed 0x%x\n", Status
);
556 * Save the registry path. This should be done only once even if
557 * VideoPortInitialize is called multiple times.
559 if (RegistryPath
->Length
!= 0)
561 DriverExtension
->RegistryPath
.Length
= 0;
562 DriverExtension
->RegistryPath
.MaximumLength
=
563 RegistryPath
->Length
+ sizeof(UNICODE_NULL
);
564 DriverExtension
->RegistryPath
.Buffer
=
565 ExAllocatePoolWithTag(
567 DriverExtension
->RegistryPath
.MaximumLength
,
569 if (DriverExtension
->RegistryPath
.Buffer
== NULL
)
571 RtlInitUnicodeString(&DriverExtension
->RegistryPath
, NULL
);
572 return STATUS_INSUFFICIENT_RESOURCES
;
575 RtlCopyUnicodeString(&DriverExtension
->RegistryPath
, RegistryPath
);
576 INFO_(VIDEOPRT
, "RegistryPath: %wZ\n", &DriverExtension
->RegistryPath
);
580 RtlInitUnicodeString(&DriverExtension
->RegistryPath
, NULL
);
584 /* Copy the correct miniport initialization data to the device extension. */
585 RtlCopyMemory(&DriverExtension
->InitializationData
,
586 HwInitializationData
,
587 HwInitializationData
->HwInitDataSize
);
588 if (HwInitializationData
->HwInitDataSize
<
589 sizeof(VIDEO_HW_INITIALIZATION_DATA
))
591 RtlZeroMemory((PVOID
)((ULONG_PTR
)&DriverExtension
->InitializationData
+
592 HwInitializationData
->HwInitDataSize
),
593 sizeof(VIDEO_HW_INITIALIZATION_DATA
) -
594 HwInitializationData
->HwInitDataSize
);
596 DriverExtension
->HwContext
= HwContext
;
599 * Plug & Play drivers registers the device in AddDevice routine. For
600 * legacy drivers we must do it now.
604 PDEVICE_OBJECT DeviceObject
;
606 if (HwInitializationData
->HwInitDataSize
!= SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA
)
608 /* power management */
609 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = IntVideoPortDispatchPower
;
612 Status
= IntVideoPortCreateAdapterDeviceObject(DriverObject
,
616 if (!NT_SUCCESS(Status
))
618 ERR_(VIDEOPRT
, "IntVideoPortCreateAdapterDeviceObject returned 0x%x\n", Status
);
622 Status
= IntVideoPortFindAdapter(DriverObject
, DriverExtension
, DeviceObject
);
623 if (NT_SUCCESS(Status
))
624 VideoPortDeviceNumber
++;
626 ERR_(VIDEOPRT
, "IntVideoPortFindAdapter returned 0x%x\n", Status
);
632 DriverObject
->DriverExtension
->AddDevice
= IntVideoPortAddDevice
;
633 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = IntVideoPortDispatchPnp
;
634 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = IntVideoPortDispatchPower
;
635 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = IntVideoPortDispatchSystemControl
;
637 return STATUS_SUCCESS
;
646 IN VIDEO_DEBUG_LEVEL DebugPrintLevel
,
647 IN PCHAR DebugMessage
,
652 va_start(ap
, DebugMessage
);
653 vDbgPrintEx(DPFLTR_IHVVIDEO_ID
, DebugPrintLevel
, DebugMessage
, ap
);
663 IN PVOID HwDeviceExtension
,
664 IN PVIDEO_REQUEST_PACKET Vrp OPTIONAL
,
665 IN VP_STATUS ErrorCode
,
670 INFO_(VIDEOPRT
, "VideoPortLogError ErrorCode %d (0x%x) UniqueId %lu (0x%lx)\n",
671 ErrorCode
, ErrorCode
, UniqueId
, UniqueId
);
673 INFO_(VIDEOPRT
, "Vrp->IoControlCode %lu (0x%lx)\n", Vrp
->IoControlCode
, Vrp
->IoControlCode
);
681 VideoPortGetCurrentIrql(VOID
)
683 return KeGetCurrentIrql();
686 typedef struct QueryRegistryCallbackContext
688 PVOID HwDeviceExtension
;
690 PMINIPORT_GET_REGISTRY_ROUTINE HwGetRegistryRoutine
;
691 } QUERY_REGISTRY_CALLBACK_CONTEXT
, *PQUERY_REGISTRY_CALLBACK_CONTEXT
;
696 QueryRegistryCallback(
700 IN ULONG ValueLength
,
702 IN PVOID EntryContext
)
704 PQUERY_REGISTRY_CALLBACK_CONTEXT CallbackContext
= (PQUERY_REGISTRY_CALLBACK_CONTEXT
) Context
;
706 INFO_(VIDEOPRT
, "Found registry value for name %S: type %d, length %d\n",
707 ValueName
, ValueType
, ValueLength
);
708 return (*(CallbackContext
->HwGetRegistryRoutine
))(
709 CallbackContext
->HwDeviceExtension
,
710 CallbackContext
->HwContext
,
722 VideoPortGetRegistryParameters(
723 IN PVOID HwDeviceExtension
,
724 IN PWSTR ParameterName
,
725 IN UCHAR IsParameterFileName
,
726 IN PMINIPORT_GET_REGISTRY_ROUTINE GetRegistryRoutine
,
729 RTL_QUERY_REGISTRY_TABLE QueryTable
[2] = {{0}};
730 QUERY_REGISTRY_CALLBACK_CONTEXT Context
;
731 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
734 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
736 TRACE_(VIDEOPRT
, "VideoPortGetRegistryParameters ParameterName %S, RegPath: %wZ\n",
737 ParameterName
, &DeviceExtension
->RegistryPath
);
739 Context
.HwDeviceExtension
= HwDeviceExtension
;
740 Context
.HwContext
= HwContext
;
741 Context
.HwGetRegistryRoutine
= GetRegistryRoutine
;
743 QueryTable
[0].QueryRoutine
= QueryRegistryCallback
;
744 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
;
745 QueryTable
[0].Name
= ParameterName
;
747 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
748 DeviceExtension
->RegistryPath
.Buffer
,
752 if (!NT_SUCCESS(Status
))
754 WARN_(VIDEOPRT
, "VideoPortGetRegistryParameters could not find the "
755 "requested parameter\n");
756 return ERROR_INVALID_PARAMETER
;
759 if (IsParameterFileName
)
761 /* FIXME: need to read the contents of the file */
773 VideoPortSetRegistryParameters(
774 IN PVOID HwDeviceExtension
,
777 IN ULONG ValueLength
)
779 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
782 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
783 TRACE_(VIDEOPRT
, "VideoPortSetRegistryParameters ParameterName %S, RegPath: %wZ\n",
785 &DeviceExtension
->RegistryPath
);
786 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL
);
787 Status
= RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE
,
788 DeviceExtension
->RegistryPath
.Buffer
,
793 if (Status
!= NO_ERROR
)
794 WARN_(VIDEOPRT
, "VideoPortSetRegistryParameters error 0x%x\n", Status
);
804 VideoPortGetVgaStatus(
805 IN PVOID HwDeviceExtension
,
806 OUT PULONG VgaStatus
)
808 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
810 TRACE_(VIDEOPRT
, "VideoPortGetVgaStatus\n");
812 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
813 if (KeGetCurrentIrql() == PASSIVE_LEVEL
)
815 if (DeviceExtension
->AdapterInterfaceType
== PCIBus
)
817 /* VgaStatus: 0 == VGA not enabled, 1 == VGA enabled. */
818 /* Assumed for now */
824 return ERROR_INVALID_FUNCTION
;
832 VideoPortGetRomImage(
833 IN PVOID HwDeviceExtension
,
838 static PVOID RomImageBuffer
= NULL
;
839 PKPROCESS CallingProcess
;
842 TRACE_(VIDEOPRT
, "VideoPortGetRomImage(HwDeviceExtension 0x%X Length 0x%X)\n",
843 HwDeviceExtension
, Length
);
845 /* If the length is zero then free the existing buffer. */
848 if (RomImageBuffer
!= NULL
)
850 ExFreePool(RomImageBuffer
);
851 RomImageBuffer
= NULL
;
858 * The DDK says we shouldn't use the legacy C0000 method but get the
859 * rom base address from the corresponding pci or acpi register but
860 * lets ignore that and use C0000 anyway. We have already mapped the
861 * bios area into memory so we'll copy from there.
865 Length
= min(Length
, 0x10000);
866 if (RomImageBuffer
!= NULL
)
868 ExFreePool(RomImageBuffer
);
871 RomImageBuffer
= ExAllocatePool(PagedPool
, Length
);
872 if (RomImageBuffer
== NULL
)
877 IntAttachToCSRSS(&CallingProcess
, &ApcState
);
878 RtlCopyMemory(RomImageBuffer
, (PUCHAR
)0xC0000, Length
);
879 IntDetachFromCSRSS(&CallingProcess
, &ApcState
);
881 return RomImageBuffer
;
891 IN PVOID HwDeviceExtension
,
898 PUCHAR SearchLocation
;
900 TRACE_(VIDEOPRT
, "VideoPortScanRom RomBase %p RomLength 0x%x String %s\n", RomBase
, RomLength
, String
);
902 StringLength
= strlen((PCHAR
)String
);
904 SearchLocation
= RomBase
;
905 for (SearchLocation
= RomBase
;
906 !Found
&& SearchLocation
< RomBase
+ RomLength
- StringLength
;
909 Found
= (RtlCompareMemory(SearchLocation
, String
, StringLength
) == StringLength
);
912 INFO_(VIDEOPRT
, "Match found at %p\n", SearchLocation
);
924 VideoPortSynchronizeExecution(
925 IN PVOID HwDeviceExtension
,
926 IN VIDEO_SYNCHRONIZE_PRIORITY Priority
,
927 IN PMINIPORT_SYNCHRONIZE_ROUTINE SynchronizeRoutine
,
931 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
937 Ret
= (*SynchronizeRoutine
)(Context
);
940 case VpMediumPriority
:
941 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
942 if (DeviceExtension
->InterruptObject
== NULL
)
943 Ret
= (*SynchronizeRoutine
)(Context
);
945 Ret
= KeSynchronizeExecution(
946 DeviceExtension
->InterruptObject
,
952 OldIrql
= KeGetCurrentIrql();
953 if (OldIrql
< SYNCH_LEVEL
)
954 KeRaiseIrql(SYNCH_LEVEL
, &OldIrql
);
956 Ret
= (*SynchronizeRoutine
)(Context
);
958 if (OldIrql
< SYNCH_LEVEL
)
959 KeLowerIrql(OldIrql
);
974 VideoPortEnumerateChildren(
975 IN PVOID HwDeviceExtension
,
978 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
980 VIDEO_CHILD_ENUM_INFO ChildEnumInfo
;
981 BOOLEAN bHaveLastMonitorID
= FALSE
;
982 UCHAR LastMonitorID
[10];
985 PDEVICE_OBJECT ChildDeviceObject
;
986 PVIDEO_PORT_CHILD_EXTENSION ChildExtension
;
988 INFO_(VIDEOPRT
, "Starting child device probe\n");
989 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
990 if (DeviceExtension
->DriverExtension
->InitializationData
.HwGetVideoChildDescriptor
== NULL
)
992 WARN_(VIDEOPRT
, "Miniport's HwGetVideoChildDescriptor is NULL!\n");
996 if (!IsListEmpty(&DeviceExtension
->ChildDeviceList
))
998 ERR_(VIDEOPRT
, "FIXME: Support calling VideoPortEnumerateChildren again!\n");
1002 /* Enumerate the children */
1005 Status
= IoCreateDevice(DeviceExtension
->DriverObject
,
1006 sizeof(VIDEO_PORT_CHILD_EXTENSION
) +
1007 DeviceExtension
->DriverExtension
->InitializationData
.HwChildDeviceExtensionSize
,
1009 FILE_DEVICE_CONTROLLER
,
1010 FILE_DEVICE_SECURE_OPEN
,
1012 &ChildDeviceObject
);
1013 if (!NT_SUCCESS(Status
))
1016 ChildExtension
= ChildDeviceObject
->DeviceExtension
;
1018 RtlZeroMemory(ChildExtension
,
1019 sizeof(VIDEO_PORT_CHILD_EXTENSION
) +
1020 DeviceExtension
->DriverExtension
->InitializationData
.HwChildDeviceExtensionSize
);
1022 ChildExtension
->Common
.Fdo
= FALSE
;
1023 ChildExtension
->ChildId
= i
;
1024 ChildExtension
->PhysicalDeviceObject
= ChildDeviceObject
;
1025 ChildExtension
->DriverObject
= DeviceExtension
->DriverObject
;
1027 /* Setup the ChildEnumInfo */
1028 ChildEnumInfo
.Size
= sizeof(ChildEnumInfo
);
1029 ChildEnumInfo
.ChildDescriptorSize
= sizeof(ChildExtension
->ChildDescriptor
);
1030 ChildEnumInfo
.ACPIHwId
= 0;
1032 if (DeviceExtension
->DriverExtension
->InitializationData
.HwChildDeviceExtensionSize
)
1033 ChildEnumInfo
.ChildHwDeviceExtension
= VIDEO_PORT_GET_CHILD_EXTENSION(ChildExtension
);
1035 ChildEnumInfo
.ChildHwDeviceExtension
= NULL
;
1037 ChildEnumInfo
.ChildIndex
= ChildExtension
->ChildId
;
1039 INFO_(VIDEOPRT
, "Probing child: %d\n", ChildEnumInfo
.ChildIndex
);
1040 Status
= DeviceExtension
->DriverExtension
->InitializationData
.HwGetVideoChildDescriptor(
1043 &ChildExtension
->ChildType
,
1044 ChildExtension
->ChildDescriptor
,
1045 &ChildExtension
->ChildId
,
1047 if (Status
== VIDEO_ENUM_MORE_DEVICES
)
1049 if (ChildExtension
->ChildType
== Monitor
)
1051 // Check if the EDID is valid
1052 if (ChildExtension
->ChildDescriptor
[0] == 0x00 &&
1053 ChildExtension
->ChildDescriptor
[1] == 0xFF &&
1054 ChildExtension
->ChildDescriptor
[2] == 0xFF &&
1055 ChildExtension
->ChildDescriptor
[3] == 0xFF &&
1056 ChildExtension
->ChildDescriptor
[4] == 0xFF &&
1057 ChildExtension
->ChildDescriptor
[5] == 0xFF &&
1058 ChildExtension
->ChildDescriptor
[6] == 0xFF &&
1059 ChildExtension
->ChildDescriptor
[7] == 0x00)
1061 if (bHaveLastMonitorID
)
1063 // Compare the previous monitor ID with the current one, break the loop if they are identical
1064 if (RtlCompareMemory(LastMonitorID
, &ChildExtension
->ChildDescriptor
[8], sizeof(LastMonitorID
)) == sizeof(LastMonitorID
))
1066 INFO_(VIDEOPRT
, "Found identical Monitor ID two times, stopping enumeration\n");
1067 IoDeleteDevice(ChildDeviceObject
);
1072 // Copy 10 bytes from the EDID, which can be used to uniquely identify the monitor
1073 RtlCopyMemory(LastMonitorID
, &ChildExtension
->ChildDescriptor
[8], sizeof(LastMonitorID
));
1074 bHaveLastMonitorID
= TRUE
;
1077 ChildExtension
->EdidValid
= TRUE
;
1081 /* Mark it invalid */
1082 ChildExtension
->EdidValid
= FALSE
;
1086 else if (Status
== VIDEO_ENUM_INVALID_DEVICE
)
1088 WARN_(VIDEOPRT
, "Child device %d is invalid!\n", ChildEnumInfo
.ChildIndex
);
1089 IoDeleteDevice(ChildDeviceObject
);
1092 else if (Status
== VIDEO_ENUM_NO_MORE_DEVICES
)
1094 INFO_(VIDEOPRT
, "End of child enumeration! (%d children enumerated)\n", i
- 1);
1095 IoDeleteDevice(ChildDeviceObject
);
1100 WARN_(VIDEOPRT
, "HwGetVideoChildDescriptor returned unknown status code 0x%x!\n", Status
);
1101 IoDeleteDevice(ChildDeviceObject
);
1105 if (ChildExtension
->ChildType
== Monitor
)
1108 PUCHAR p
= ChildExtension
->ChildDescriptor
;
1109 INFO_(VIDEOPRT
, "Monitor device enumerated! (ChildId = 0x%x)\n", ChildExtension
->ChildId
);
1110 for (j
= 0; j
< sizeof (ChildExtension
->ChildDescriptor
); j
+= 8)
1112 INFO_(VIDEOPRT
, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
1113 p
[j
+ 0], p
[j
+ 1], p
[j
+ 2], p
[j
+ 3],
1114 p
[j
+ 4], p
[j
+ 5], p
[j
+ 6], p
[j
+ 7]);
1117 else if (ChildExtension
->ChildType
== Other
)
1119 INFO_(VIDEOPRT
, "\"Other\" device enumerated: DeviceId = %S\n", (PWSTR
)ChildExtension
->ChildDescriptor
);
1123 ERR_(VIDEOPRT
, "HwGetVideoChildDescriptor returned unsupported type: %d\n", ChildExtension
->ChildType
);
1126 /* Clear the init flag */
1127 ChildDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1129 InsertTailList(&DeviceExtension
->ChildDeviceList
,
1130 &ChildExtension
->ListEntry
);
1133 /* Trigger reenumeration by the PnP manager */
1134 IoInvalidateDeviceRelations(DeviceExtension
->PhysicalDeviceObject
, BusRelations
);
1144 VideoPortCreateSecondaryDisplay(
1145 IN PVOID HwDeviceExtension
,
1146 IN OUT PVOID
*SecondaryDeviceExtension
,
1150 return ERROR_DEV_NOT_EXIST
;
1159 IN PVOID HwDeviceExtension
,
1160 IN PMINIPORT_DPC_ROUTINE CallbackRoutine
,
1163 return KeInsertQueueDpc(
1164 &VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
)->DpcObject
,
1165 (PVOID
)CallbackRoutine
,
1174 VideoPortGetAssociatedDeviceExtension(
1175 IN PVOID DeviceObject
)
1177 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
1179 TRACE_(VIDEOPRT
, "VideoPortGetAssociatedDeviceExtension\n");
1180 DeviceExtension
= ((PDEVICE_OBJECT
)DeviceObject
)->DeviceExtension
;
1181 if (!DeviceExtension
)
1183 return DeviceExtension
->MiniPortDeviceExtension
;
1191 VideoPortGetVersion(
1192 IN PVOID HwDeviceExtension
,
1193 IN OUT PVPOSVERSIONINFO VpOsVersionInfo
)
1195 RTL_OSVERSIONINFOEXW Version
;
1197 Version
.dwOSVersionInfoSize
= sizeof(RTL_OSVERSIONINFOEXW
);
1198 if (VpOsVersionInfo
->Size
>= sizeof(VPOSVERSIONINFO
))
1201 if (NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW
)&Version
)))
1203 VpOsVersionInfo
->MajorVersion
= Version
.dwMajorVersion
;
1204 VpOsVersionInfo
->MinorVersion
= Version
.dwMinorVersion
;
1205 VpOsVersionInfo
->BuildNumber
= Version
.dwBuildNumber
;
1206 VpOsVersionInfo
->ServicePackMajor
= Version
.wServicePackMajor
;
1207 VpOsVersionInfo
->ServicePackMinor
= Version
.wServicePackMinor
;
1210 return ERROR_INVALID_PARAMETER
;
1212 VpOsVersionInfo
->MajorVersion
= 5;
1213 VpOsVersionInfo
->MinorVersion
= 0;
1214 VpOsVersionInfo
->BuildNumber
= 2195;
1215 VpOsVersionInfo
->ServicePackMajor
= 4;
1216 VpOsVersionInfo
->ServicePackMinor
= 0;
1221 return ERROR_INVALID_PARAMETER
;
1229 VideoPortCheckForDeviceExistence(
1230 IN PVOID HwDeviceExtension
,
1233 IN UCHAR RevisionId
,
1234 IN USHORT SubVendorId
,
1235 IN USHORT SubSystemId
,
1238 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
1239 PCI_DEVICE_PRESENT_INTERFACE PciDevicePresentInterface
;
1240 IO_STATUS_BLOCK IoStatusBlock
;
1241 IO_STACK_LOCATION IoStack
;
1246 TRACE_(VIDEOPRT
, "VideoPortCheckForDeviceExistence\n");
1248 if (Flags
& ~(CDE_USE_REVISION
| CDE_USE_SUBSYSTEM_IDS
))
1250 WARN_(VIDEOPRT
, "VideoPortCheckForDeviceExistence: Unknown flags 0x%lx\n", Flags
& ~(CDE_USE_REVISION
| CDE_USE_SUBSYSTEM_IDS
));
1254 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
1256 PciDevicePresentInterface
.Size
= sizeof(PCI_DEVICE_PRESENT_INTERFACE
);
1257 PciDevicePresentInterface
.Version
= 1;
1258 IoStack
.Parameters
.QueryInterface
.Size
= PciDevicePresentInterface
.Size
;
1259 IoStack
.Parameters
.QueryInterface
.Version
= PciDevicePresentInterface
.Version
;
1260 IoStack
.Parameters
.QueryInterface
.Interface
= (PINTERFACE
)&PciDevicePresentInterface
;
1261 IoStack
.Parameters
.QueryInterface
.InterfaceType
=
1262 &GUID_PCI_DEVICE_PRESENT_INTERFACE
;
1263 Status
= IopInitiatePnpIrp(DeviceExtension
->NextDeviceObject
,
1264 &IoStatusBlock
, IRP_MN_QUERY_INTERFACE
, &IoStack
);
1265 if (!NT_SUCCESS(Status
))
1267 WARN_(VIDEOPRT
, "IopInitiatePnpIrp() failed! (Status 0x%lx)\n", Status
);
1271 if (Flags
& CDE_USE_REVISION
)
1272 PciFlags
|= PCI_USE_REVISION
;
1273 if (Flags
& CDE_USE_SUBSYSTEM_IDS
)
1274 PciFlags
|= PCI_USE_SUBSYSTEM_IDS
;
1276 DevicePresent
= PciDevicePresentInterface
.IsDevicePresent(
1277 VendorId
, DeviceId
, RevisionId
,
1278 SubVendorId
, SubSystemId
, PciFlags
);
1280 PciDevicePresentInterface
.InterfaceDereference(PciDevicePresentInterface
.Context
);
1282 return DevicePresent
;
1290 VideoPortRegisterBugcheckCallback(
1291 IN PVOID HwDeviceExtension
,
1292 IN ULONG BugcheckCode
,
1293 IN PVIDEO_BUGCHECK_CALLBACK Callback
,
1294 IN ULONG BugcheckDataSize
)
1305 VideoPortQueryPerformanceCounter(
1306 IN PVOID HwDeviceExtension
,
1307 OUT PLONGLONG PerformanceFrequency OPTIONAL
)
1309 LARGE_INTEGER Result
;
1311 TRACE_(VIDEOPRT
, "VideoPortQueryPerformanceCounter\n");
1312 Result
= KeQueryPerformanceCounter((PLARGE_INTEGER
)PerformanceFrequency
);
1313 return Result
.QuadPart
;
1321 VideoPortAcquireDeviceLock(
1322 IN PVOID HwDeviceExtension
)
1324 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
1328 TRACE_(VIDEOPRT
, "VideoPortAcquireDeviceLock\n");
1329 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
1330 Status
= KeWaitForMutexObject(&DeviceExtension
->DeviceLock
, Executive
,
1331 KernelMode
, FALSE
, NULL
);
1332 // ASSERT(Status == STATUS_SUCCESS);
1340 VideoPortReleaseDeviceLock(
1341 IN PVOID HwDeviceExtension
)
1343 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
1347 TRACE_(VIDEOPRT
, "VideoPortReleaseDeviceLock\n");
1348 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
1349 Status
= KeReleaseMutex(&DeviceExtension
->DeviceLock
, FALSE
);
1350 //ASSERT(Status == STATUS_SUCCESS);
1359 IN PDEVICE_OBJECT DeviceObject
,
1370 VideoPortAllocateContiguousMemory(
1371 IN PVOID HwDeviceExtension
,
1372 IN ULONG NumberOfBytes
,
1373 IN PHYSICAL_ADDRESS HighestAcceptableAddress
1377 return MmAllocateContiguousMemory(NumberOfBytes
, HighestAcceptableAddress
);
1385 VideoPortIsNoVesa(VOID
)
1389 UNICODE_STRING Path
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control");
1390 UNICODE_STRING ValueName
= RTL_CONSTANT_STRING(L
"SystemStartOptions");
1391 OBJECT_ATTRIBUTES ObjectAttributes
;
1392 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
1393 ULONG Length
, NewLength
;
1395 /* Initialize object attributes with the path we want */
1396 InitializeObjectAttributes(&ObjectAttributes
,
1398 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
1403 Status
= ZwOpenKey(&KeyHandle
,
1407 if (!NT_SUCCESS(Status
))
1409 VideoPortDebugPrint(Error
, "ZwOpenKey failed (0x%x)\n", Status
);
1413 /* Find out how large our buffer should be */
1414 Status
= ZwQueryValueKey(KeyHandle
,
1416 KeyValuePartialInformation
,
1420 if (Status
!= STATUS_BUFFER_OVERFLOW
&& Status
!= STATUS_BUFFER_TOO_SMALL
)
1422 VideoPortDebugPrint(Error
, "ZwQueryValueKey failed (0x%x)\n", Status
);
1428 KeyInfo
= ExAllocatePool(PagedPool
, Length
);
1431 VideoPortDebugPrint(Error
, "Out of memory\n");
1436 /* Now for real this time */
1437 Status
= ZwQueryValueKey(KeyHandle
,
1439 KeyValuePartialInformation
,
1446 if (!NT_SUCCESS(Status
))
1448 VideoPortDebugPrint(Error
, "ZwQueryValueKey failed (0x%x)\n", Status
);
1449 ExFreePool(KeyInfo
);
1454 if (KeyInfo
->Type
!= REG_SZ
)
1456 VideoPortDebugPrint(Error
, "Invalid type for SystemStartOptions\n");
1457 ExFreePool(KeyInfo
);
1461 /* Check if NOVESA or BASEVIDEO is present in the start options */
1462 if (wcsstr((PWCHAR
)KeyInfo
->Data
, L
"NOVESA") ||
1463 wcsstr((PWCHAR
)KeyInfo
->Data
, L
"BASEVIDEO"))
1465 VideoPortDebugPrint(Info
, "VESA mode disabled\n");
1466 ExFreePool(KeyInfo
);
1470 ExFreePool(KeyInfo
);
1472 VideoPortDebugPrint(Info
, "VESA mode enabled\n");