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