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