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