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