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