Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenvideoprt.c
Go to the documentation of this file.
00001 /* 00002 * VideoPort driver 00003 * 00004 * Copyright (C) 2002-2004, 2007 ReactOS Team 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 * 00020 */ 00021 00022 00023 #include "videoprt.h" 00024 00025 /* GLOBAL VARIABLES ***********************************************************/ 00026 00027 ULONG CsrssInitialized = FALSE; 00028 PKPROCESS Csrss = NULL; 00029 ULONG VideoPortDeviceNumber = 0; 00030 00031 /* PRIVATE FUNCTIONS **********************************************************/ 00032 00033 ULONG NTAPI 00034 DriverEntry( 00035 IN PVOID Context1, 00036 IN PVOID Context2) 00037 { 00038 return STATUS_SUCCESS; 00039 } 00040 00041 PVOID NTAPI 00042 IntVideoPortImageDirectoryEntryToData( 00043 PVOID BaseAddress, 00044 ULONG Directory) 00045 { 00046 PIMAGE_NT_HEADERS NtHeader; 00047 ULONG Va; 00048 00049 NtHeader = RtlImageNtHeader(BaseAddress); 00050 if (NtHeader == NULL) 00051 return NULL; 00052 00053 if (Directory >= NtHeader->OptionalHeader.NumberOfRvaAndSizes) 00054 return NULL; 00055 00056 Va = NtHeader->OptionalHeader.DataDirectory[Directory].VirtualAddress; 00057 if (Va == 0) 00058 return NULL; 00059 00060 return (PVOID)((ULONG_PTR)BaseAddress + Va); 00061 } 00062 00063 VOID NTAPI 00064 IntVideoPortDeferredRoutine( 00065 IN PKDPC Dpc, 00066 IN PVOID DeferredContext, 00067 IN PVOID SystemArgument1, 00068 IN PVOID SystemArgument2) 00069 { 00070 PVOID HwDeviceExtension = 00071 &((PVIDEO_PORT_DEVICE_EXTENSION)DeferredContext)->MiniPortDeviceExtension; 00072 ((PMINIPORT_DPC_ROUTINE)SystemArgument1)(HwDeviceExtension, SystemArgument2); 00073 } 00074 00075 NTSTATUS 00076 IntCreateRegistryPath( 00077 IN PCUNICODE_STRING DriverRegistryPath, 00078 OUT PUNICODE_STRING DeviceRegistryPath) 00079 { 00080 static WCHAR RegistryMachineSystem[] = L"\\REGISTRY\\MACHINE\\SYSTEM\\"; 00081 static WCHAR CurrentControlSet[] = L"CURRENTCONTROLSET\\"; 00082 static WCHAR ControlSet[] = L"CONTROLSET"; 00083 static WCHAR Insert1[] = L"Hardware Profiles\\Current\\System\\CurrentControlSet\\"; 00084 static WCHAR Insert2[] = L"\\Device0"; 00085 BOOLEAN Valid; 00086 UNICODE_STRING AfterControlSet; 00087 00088 AfterControlSet = *DriverRegistryPath; 00089 /* Check if path begins with \\REGISTRY\\MACHINE\\SYSTEM\\ */ 00090 Valid = (DriverRegistryPath->Length > sizeof(RegistryMachineSystem) && 00091 0 == _wcsnicmp(DriverRegistryPath->Buffer, RegistryMachineSystem, 00092 wcslen(RegistryMachineSystem))); 00093 if (Valid) 00094 { 00095 AfterControlSet.Buffer += wcslen(RegistryMachineSystem); 00096 AfterControlSet.Length -= sizeof(RegistryMachineSystem) - sizeof(UNICODE_NULL); 00097 00098 /* Check if path contains CURRENTCONTROLSET */ 00099 if (AfterControlSet.Length > sizeof(CurrentControlSet) && 00100 0 == _wcsnicmp(AfterControlSet.Buffer, CurrentControlSet, wcslen(CurrentControlSet))) 00101 { 00102 AfterControlSet.Buffer += wcslen(CurrentControlSet); 00103 AfterControlSet.Length -= sizeof(CurrentControlSet) - sizeof(UNICODE_NULL); 00104 } 00105 /* Check if path contains CONTROLSETnum */ 00106 else if (AfterControlSet.Length > sizeof(ControlSet) && 00107 0 == _wcsnicmp(AfterControlSet.Buffer, ControlSet, wcslen(ControlSet))) 00108 { 00109 AfterControlSet.Buffer += wcslen(ControlSet); 00110 AfterControlSet.Length -= sizeof(ControlSet) - sizeof(UNICODE_NULL); 00111 while (AfterControlSet.Length > 0 && 00112 *AfterControlSet.Buffer >= L'0' && 00113 *AfterControlSet.Buffer <= L'9') 00114 { 00115 AfterControlSet.Buffer++; 00116 AfterControlSet.Length -= sizeof(WCHAR); 00117 } 00118 Valid = (AfterControlSet.Length > 0 && L'\\' == *AfterControlSet.Buffer); 00119 AfterControlSet.Buffer++; 00120 AfterControlSet.Length -= sizeof(WCHAR); 00121 AfterControlSet.MaximumLength = AfterControlSet.Length; 00122 } 00123 else 00124 { 00125 Valid = FALSE; 00126 } 00127 } 00128 00129 if (Valid) 00130 { 00131 DeviceRegistryPath->MaximumLength = DriverRegistryPath->Length + sizeof(Insert1) + sizeof(Insert2); 00132 DeviceRegistryPath->Buffer = ExAllocatePoolWithTag(PagedPool, 00133 DeviceRegistryPath->MaximumLength, 00134 TAG_VIDEO_PORT); 00135 if (DeviceRegistryPath->Buffer != NULL) 00136 { 00137 /* Build device path */ 00138 wcsncpy(DeviceRegistryPath->Buffer, 00139 DriverRegistryPath->Buffer, 00140 AfterControlSet.Buffer - DriverRegistryPath->Buffer); 00141 DeviceRegistryPath->Length = (AfterControlSet.Buffer - DriverRegistryPath->Buffer) * sizeof(WCHAR); 00142 RtlAppendUnicodeToString(DeviceRegistryPath, Insert1); 00143 RtlAppendUnicodeStringToString(DeviceRegistryPath, &AfterControlSet); 00144 RtlAppendUnicodeToString(DeviceRegistryPath, Insert2); 00145 00146 /* Check if registry key exists */ 00147 Valid = NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, DeviceRegistryPath->Buffer)); 00148 00149 if (!Valid) 00150 ExFreePoolWithTag(DeviceRegistryPath->Buffer, TAG_VIDEO_PORT); 00151 } 00152 else 00153 { 00154 Valid = FALSE; 00155 } 00156 } 00157 else 00158 { 00159 WARN_(VIDEOPRT, "Unparsable registry path %wZ", DriverRegistryPath); 00160 } 00161 00162 /* If path doesn't point to *ControlSet*, use DriverRegistryPath directly */ 00163 if (!Valid) 00164 { 00165 DeviceRegistryPath->MaximumLength = DriverRegistryPath->Length + sizeof(Insert2); 00166 DeviceRegistryPath->Buffer = ExAllocatePoolWithTag( 00167 NonPagedPool, 00168 DeviceRegistryPath->MaximumLength, 00169 TAG_VIDEO_PORT); 00170 00171 if (!DeviceRegistryPath->Buffer) 00172 return STATUS_NO_MEMORY; 00173 00174 RtlCopyUnicodeString(DeviceRegistryPath, DriverRegistryPath); 00175 RtlAppendUnicodeToString(DeviceRegistryPath, Insert2); 00176 } 00177 00178 return STATUS_SUCCESS; 00179 } 00180 00181 NTSTATUS NTAPI 00182 IntVideoPortCreateAdapterDeviceObject( 00183 IN PDRIVER_OBJECT DriverObject, 00184 IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension, 00185 IN PDEVICE_OBJECT PhysicalDeviceObject, 00186 OUT PDEVICE_OBJECT *DeviceObject OPTIONAL) 00187 { 00188 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; 00189 ULONG DeviceNumber; 00190 ULONG PciSlotNumber; 00191 PCI_SLOT_NUMBER SlotNumber; 00192 ULONG Size; 00193 NTSTATUS Status; 00194 WCHAR DeviceBuffer[20]; 00195 UNICODE_STRING DeviceName; 00196 PDEVICE_OBJECT DeviceObject_; 00197 00198 if (DeviceObject == NULL) 00199 DeviceObject = &DeviceObject_; 00200 00201 /* 00202 * Find the first free device number that can be used for video device 00203 * object names and symlinks. 00204 */ 00205 00206 DeviceNumber = VideoPortDeviceNumber; 00207 if (DeviceNumber == 0xFFFFFFFF) 00208 { 00209 WARN_(VIDEOPRT, "Can't find free device number\n"); 00210 return STATUS_UNSUCCESSFUL; 00211 } 00212 00213 /* 00214 * Create the device object. 00215 */ 00216 00217 /* Create a unicode device name. */ 00218 swprintf(DeviceBuffer, L"\\Device\\Video%lu", DeviceNumber); 00219 RtlInitUnicodeString(&DeviceName, DeviceBuffer); 00220 00221 INFO_(VIDEOPRT, "HwDeviceExtension size is: 0x%x\n", 00222 DriverExtension->InitializationData.HwDeviceExtensionSize); 00223 00224 /* Create the device object. */ 00225 Status = IoCreateDevice( 00226 DriverObject, 00227 sizeof(VIDEO_PORT_DEVICE_EXTENSION) + 00228 DriverExtension->InitializationData.HwDeviceExtensionSize, 00229 &DeviceName, 00230 FILE_DEVICE_VIDEO, 00231 0, 00232 TRUE, 00233 DeviceObject); 00234 00235 if (!NT_SUCCESS(Status)) 00236 { 00237 WARN_(VIDEOPRT, "IoCreateDevice call failed with status 0x%08x\n", Status); 00238 return Status; 00239 } 00240 00241 /* 00242 * Set the buffering strategy here. If you change this, remember 00243 * to change VidDispatchDeviceControl too. 00244 */ 00245 00246 (*DeviceObject)->Flags |= DO_BUFFERED_IO; 00247 00248 /* 00249 * Initialize device extension. 00250 */ 00251 00252 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)((*DeviceObject)->DeviceExtension); 00253 DeviceExtension->Common.Fdo = TRUE; 00254 DeviceExtension->DeviceNumber = DeviceNumber; 00255 DeviceExtension->DriverObject = DriverObject; 00256 DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject; 00257 DeviceExtension->FunctionalDeviceObject = *DeviceObject; 00258 DeviceExtension->DriverExtension = DriverExtension; 00259 00260 InitializeListHead(&DeviceExtension->ChildDeviceList); 00261 00262 /* 00263 * Get the registry path associated with this driver. 00264 */ 00265 00266 Status = IntCreateRegistryPath( 00267 &DriverExtension->RegistryPath, 00268 &DeviceExtension->RegistryPath); 00269 if (!NT_SUCCESS(Status)) 00270 { 00271 WARN_(VIDEOPRT, "IntCreateRegistryPath() call failed with status 0x%08x\n", Status); 00272 IoDeleteDevice(*DeviceObject); 00273 *DeviceObject = NULL; 00274 return Status; 00275 } 00276 00277 if (PhysicalDeviceObject != NULL) 00278 { 00279 /* Get bus number from the upper level bus driver. */ 00280 Size = sizeof(ULONG); 00281 Status = IoGetDeviceProperty( 00282 PhysicalDeviceObject, 00283 DevicePropertyBusNumber, 00284 Size, 00285 &DeviceExtension->SystemIoBusNumber, 00286 &Size); 00287 if (!NT_SUCCESS(Status)) 00288 { 00289 WARN_(VIDEOPRT, "Couldn't get an information from bus driver. We will try to\n" 00290 "use legacy detection method, but even that doesn't mean that\n" 00291 "it will work.\n"); 00292 DeviceExtension->PhysicalDeviceObject = NULL; 00293 } 00294 } 00295 00296 DeviceExtension->AdapterInterfaceType = 00297 DriverExtension->InitializationData.AdapterInterfaceType; 00298 00299 if (PhysicalDeviceObject != NULL) 00300 { 00301 /* Get bus type from the upper level bus driver. */ 00302 Size = sizeof(ULONG); 00303 IoGetDeviceProperty( 00304 PhysicalDeviceObject, 00305 DevicePropertyLegacyBusType, 00306 Size, 00307 &DeviceExtension->AdapterInterfaceType, 00308 &Size); 00309 00310 /* Get bus device address from the upper level bus driver. */ 00311 Size = sizeof(ULONG); 00312 IoGetDeviceProperty( 00313 PhysicalDeviceObject, 00314 DevicePropertyAddress, 00315 Size, 00316 &PciSlotNumber, 00317 &Size); 00318 00319 /* Convert slotnumber to PCI_SLOT_NUMBER */ 00320 SlotNumber.u.AsULONG = 0; 00321 SlotNumber.u.bits.DeviceNumber = (PciSlotNumber >> 16) & 0xFFFF; 00322 SlotNumber.u.bits.FunctionNumber = PciSlotNumber & 0xFFFF; 00323 DeviceExtension->SystemIoSlotNumber = SlotNumber.u.AsULONG; 00324 } 00325 00326 InitializeListHead(&DeviceExtension->AddressMappingListHead); 00327 InitializeListHead(&DeviceExtension->DmaAdapterList); 00328 00329 KeInitializeDpc( 00330 &DeviceExtension->DpcObject, 00331 IntVideoPortDeferredRoutine, 00332 DeviceExtension); 00333 00334 KeInitializeMutex(&DeviceExtension->DeviceLock, 0); 00335 00336 /* Attach the device. */ 00337 if (PhysicalDeviceObject != NULL) 00338 DeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack( 00339 *DeviceObject, PhysicalDeviceObject); 00340 00341 /* Remove the initailizing flag */ 00342 (*DeviceObject)->Flags &= ~DO_DEVICE_INITIALIZING; 00343 return STATUS_SUCCESS; 00344 } 00345 00346 00347 NTSTATUS NTAPI 00348 IntVideoPortFindAdapter( 00349 IN PDRIVER_OBJECT DriverObject, 00350 IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension, 00351 IN PDEVICE_OBJECT DeviceObject) 00352 { 00353 WCHAR DeviceVideoBuffer[20]; 00354 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; 00355 SIZE_T Size; 00356 NTSTATUS Status; 00357 VIDEO_PORT_CONFIG_INFO ConfigInfo; 00358 SYSTEM_BASIC_INFORMATION SystemBasicInfo; 00359 UCHAR Again = FALSE; 00360 WCHAR DeviceBuffer[20]; 00361 UNICODE_STRING DeviceName; 00362 WCHAR SymlinkBuffer[20]; 00363 UNICODE_STRING SymlinkName; 00364 BOOL LegacyDetection = FALSE; 00365 ULONG DeviceNumber; 00366 00367 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 00368 DeviceNumber = DeviceExtension->DeviceNumber; 00369 00370 /* 00371 * Setup a ConfigInfo structure that we will pass to HwFindAdapter. 00372 */ 00373 00374 RtlZeroMemory(&ConfigInfo, sizeof(VIDEO_PORT_CONFIG_INFO)); 00375 ConfigInfo.Length = sizeof(VIDEO_PORT_CONFIG_INFO); 00376 ConfigInfo.AdapterInterfaceType = DeviceExtension->AdapterInterfaceType; 00377 if (ConfigInfo.AdapterInterfaceType == PCIBus) 00378 ConfigInfo.InterruptMode = LevelSensitive; 00379 else 00380 ConfigInfo.InterruptMode = Latched; 00381 ConfigInfo.DriverRegistryPath = DriverExtension->RegistryPath.Buffer; 00382 ConfigInfo.VideoPortGetProcAddress = IntVideoPortGetProcAddress; 00383 ConfigInfo.SystemIoBusNumber = DeviceExtension->SystemIoBusNumber; 00384 ConfigInfo.BusInterruptLevel = DeviceExtension->InterruptLevel; 00385 ConfigInfo.BusInterruptVector = DeviceExtension->InterruptVector; 00386 00387 Size = sizeof(SystemBasicInfo); 00388 Status = ZwQuerySystemInformation( 00389 SystemBasicInformation, 00390 &SystemBasicInfo, 00391 Size, 00392 &Size); 00393 00394 if (NT_SUCCESS(Status)) 00395 { 00396 ConfigInfo.SystemMemorySize = 00397 SystemBasicInfo.NumberOfPhysicalPages * 00398 SystemBasicInfo.PageSize; 00399 } 00400 00401 /* 00402 * Call miniport HwVidFindAdapter entry point to detect if 00403 * particular device is present. There are two possible code 00404 * paths. The first one is for Legacy drivers (NT4) and cases 00405 * when we don't have information about what bus we're on. The 00406 * second case is the standard one for Plug & Play drivers. 00407 */ 00408 if (DeviceExtension->PhysicalDeviceObject == NULL) 00409 { 00410 LegacyDetection = TRUE; 00411 } 00412 00413 if (LegacyDetection) 00414 { 00415 ULONG BusNumber, MaxBuses; 00416 00417 MaxBuses = DeviceExtension->AdapterInterfaceType == PCIBus ? PCI_MAX_BRIDGE_NUMBER : 1; 00418 00419 for (BusNumber = 0; BusNumber < MaxBuses; BusNumber++) 00420 { 00421 DeviceExtension->SystemIoBusNumber = 00422 ConfigInfo.SystemIoBusNumber = BusNumber; 00423 00424 RtlZeroMemory(&DeviceExtension->MiniPortDeviceExtension, 00425 DriverExtension->InitializationData.HwDeviceExtensionSize); 00426 00427 /* FIXME: Need to figure out what string to pass as param 3. */ 00428 Status = DriverExtension->InitializationData.HwFindAdapter( 00429 &DeviceExtension->MiniPortDeviceExtension, 00430 DriverExtension->HwContext, 00431 NULL, 00432 &ConfigInfo, 00433 &Again); 00434 00435 if (Status == ERROR_DEV_NOT_EXIST) 00436 { 00437 continue; 00438 } 00439 else if (Status == NO_ERROR) 00440 { 00441 break; 00442 } 00443 else 00444 { 00445 WARN_(VIDEOPRT, "HwFindAdapter call failed with error 0x%X\n", Status); 00446 RtlFreeUnicodeString(&DeviceExtension->RegistryPath); 00447 if (DeviceExtension->NextDeviceObject) 00448 IoDetachDevice(DeviceExtension->NextDeviceObject); 00449 IoDeleteDevice(DeviceObject); 00450 00451 return Status; 00452 } 00453 } 00454 } 00455 else 00456 { 00457 /* FIXME: Need to figure out what string to pass as param 3. */ 00458 Status = DriverExtension->InitializationData.HwFindAdapter( 00459 &DeviceExtension->MiniPortDeviceExtension, 00460 DriverExtension->HwContext, 00461 NULL, 00462 &ConfigInfo, 00463 &Again); 00464 } 00465 00466 if (Status != NO_ERROR) 00467 { 00468 WARN_(VIDEOPRT, "HwFindAdapter call failed with error 0x%X\n", Status); 00469 RtlFreeUnicodeString(&DeviceExtension->RegistryPath); 00470 if (DeviceExtension->NextDeviceObject) 00471 IoDetachDevice(DeviceExtension->NextDeviceObject); 00472 IoDeleteDevice(DeviceObject); 00473 return Status; 00474 } 00475 00476 /* 00477 * Now we know the device is present, so let's do all additional tasks 00478 * such as creating symlinks or setting up interrupts and timer. 00479 */ 00480 00481 /* Create a unicode device name. */ 00482 swprintf(DeviceBuffer, L"\\Device\\Video%lu", DeviceNumber); 00483 RtlInitUnicodeString(&DeviceName, DeviceBuffer); 00484 00485 /* Create symbolic link "\??\DISPLAYx" */ 00486 swprintf(SymlinkBuffer, L"\\??\\DISPLAY%lu", DeviceNumber + 1); 00487 RtlInitUnicodeString(&SymlinkName, SymlinkBuffer); 00488 IoCreateSymbolicLink(&SymlinkName, &DeviceName); 00489 00490 /* Add entry to DEVICEMAP\VIDEO key in registry. */ 00491 swprintf(DeviceVideoBuffer, L"\\Device\\Video%d", DeviceNumber); 00492 RtlWriteRegistryValue( 00493 RTL_REGISTRY_DEVICEMAP, 00494 L"VIDEO", 00495 DeviceVideoBuffer, 00496 REG_SZ, 00497 DeviceExtension->RegistryPath.Buffer, 00498 DeviceExtension->RegistryPath.Length + sizeof(UNICODE_NULL)); 00499 00500 RtlWriteRegistryValue( 00501 RTL_REGISTRY_DEVICEMAP, 00502 L"VIDEO", 00503 L"MaxObjectNumber", 00504 REG_DWORD, 00505 &DeviceNumber, 00506 sizeof(DeviceNumber)); 00507 00508 /* FIXME: Allocate hardware resources for device. */ 00509 00510 /* 00511 * Allocate interrupt for device. 00512 */ 00513 00514 if (!IntVideoPortSetupInterrupt(DeviceObject, DriverExtension, &ConfigInfo)) 00515 { 00516 RtlFreeUnicodeString(&DeviceExtension->RegistryPath); 00517 if (DeviceExtension->NextDeviceObject) 00518 IoDetachDevice(DeviceExtension->NextDeviceObject); 00519 IoDeleteDevice(DeviceObject); 00520 return STATUS_INSUFFICIENT_RESOURCES; 00521 } 00522 00523 /* 00524 * Allocate timer for device. 00525 */ 00526 00527 if (!IntVideoPortSetupTimer(DeviceObject, DriverExtension)) 00528 { 00529 if (DeviceExtension->InterruptObject != NULL) 00530 IoDisconnectInterrupt(DeviceExtension->InterruptObject); 00531 if (DeviceExtension->NextDeviceObject) 00532 IoDetachDevice(DeviceExtension->NextDeviceObject); 00533 RtlFreeUnicodeString(&DeviceExtension->RegistryPath); 00534 IoDeleteDevice(DeviceObject); 00535 WARN_(VIDEOPRT, "STATUS_INSUFFICIENT_RESOURCES\n"); 00536 return STATUS_INSUFFICIENT_RESOURCES; 00537 } 00538 00539 /* 00540 * Query children of the device. 00541 */ 00542 VideoPortEnumerateChildren(&DeviceExtension->MiniPortDeviceExtension, NULL); 00543 00544 INFO_(VIDEOPRT, "STATUS_SUCCESS\n"); 00545 return STATUS_SUCCESS; 00546 } 00547 00548 VOID FASTCALL 00549 IntAttachToCSRSS(PKPROCESS *CallingProcess, PKAPC_STATE ApcState) 00550 { 00551 *CallingProcess = (PKPROCESS)PsGetCurrentProcess(); 00552 if (*CallingProcess != Csrss) 00553 { 00554 KeStackAttachProcess(Csrss, ApcState); 00555 } 00556 } 00557 00558 VOID FASTCALL 00559 IntDetachFromCSRSS(PKPROCESS *CallingProcess, PKAPC_STATE ApcState) 00560 { 00561 if (*CallingProcess != Csrss) 00562 { 00563 KeUnstackDetachProcess(ApcState); 00564 } 00565 } 00566 00567 /* PUBLIC FUNCTIONS ***********************************************************/ 00568 00569 /* 00570 * @implemented 00571 */ 00572 00573 ULONG NTAPI 00574 VideoPortInitialize( 00575 IN PVOID Context1, 00576 IN PVOID Context2, 00577 IN PVIDEO_HW_INITIALIZATION_DATA HwInitializationData, 00578 IN PVOID HwContext) 00579 { 00580 PDRIVER_OBJECT DriverObject = Context1; 00581 PUNICODE_STRING RegistryPath = Context2; 00582 NTSTATUS Status; 00583 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension; 00584 BOOLEAN PnpDriver = FALSE, LegacyDetection = FALSE; 00585 00586 TRACE_(VIDEOPRT, "VideoPortInitialize\n"); 00587 00588 /* 00589 * As a first thing do parameter checks. 00590 */ 00591 00592 if (HwInitializationData->HwInitDataSize > sizeof(VIDEO_HW_INITIALIZATION_DATA)) 00593 { 00594 return STATUS_REVISION_MISMATCH; 00595 } 00596 00597 if (HwInitializationData->HwFindAdapter == NULL || 00598 HwInitializationData->HwInitialize == NULL || 00599 HwInitializationData->HwStartIO == NULL) 00600 { 00601 return STATUS_INVALID_PARAMETER; 00602 } 00603 00604 switch (HwInitializationData->HwInitDataSize) 00605 { 00606 /* 00607 * NT4 drivers are special case, because we must use legacy method 00608 * of detection instead of the Plug & Play one. 00609 */ 00610 00611 case SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA: 00612 INFO_(VIDEOPRT, "We were loaded by a Windows NT miniport driver.\n"); 00613 break; 00614 00615 case SIZE_OF_W2K_VIDEO_HW_INITIALIZATION_DATA: 00616 INFO_(VIDEOPRT, "We were loaded by a Windows 2000 miniport driver.\n"); 00617 break; 00618 00619 case sizeof(VIDEO_HW_INITIALIZATION_DATA): 00620 INFO_(VIDEOPRT, "We were loaded by a Windows XP or later miniport driver.\n"); 00621 break; 00622 00623 default: 00624 WARN_(VIDEOPRT, "Invalid HwInitializationData size.\n"); 00625 return STATUS_UNSUCCESSFUL; 00626 } 00627 00628 /* Set dispatching routines */ 00629 DriverObject->MajorFunction[IRP_MJ_CREATE] = IntVideoPortDispatchOpen; 00630 DriverObject->MajorFunction[IRP_MJ_CLOSE] = IntVideoPortDispatchClose; 00631 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = 00632 IntVideoPortDispatchDeviceControl; 00633 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = 00634 IntVideoPortDispatchDeviceControl; 00635 DriverObject->MajorFunction[IRP_MJ_WRITE] = 00636 IntVideoPortDispatchWrite; // ReactOS-specific hack 00637 DriverObject->DriverUnload = IntVideoPortUnload; 00638 00639 /* Determine type of the miniport driver */ 00640 if ((HwInitializationData->HwInitDataSize >= 00641 FIELD_OFFSET(VIDEO_HW_INITIALIZATION_DATA, HwQueryInterface)) 00642 && HwInitializationData->HwSetPowerState 00643 && HwInitializationData->HwGetPowerState 00644 && HwInitializationData->HwGetVideoChildDescriptor) 00645 { 00646 INFO_(VIDEOPRT, "The miniport is a PnP miniport driver\n"); 00647 PnpDriver = TRUE; 00648 } 00649 00650 /* Check if legacy detection should be applied */ 00651 if (!PnpDriver || HwContext) 00652 { 00653 INFO_(VIDEOPRT, "Legacy detection for adapter interface %d\n", 00654 HwInitializationData->AdapterInterfaceType); 00655 00656 /* FIXME: Move the code for legacy detection 00657 to another function and call it here */ 00658 LegacyDetection = TRUE; 00659 } 00660 00661 /* 00662 * NOTE: 00663 * The driver extension can be already allocated in case that we were 00664 * called by legacy driver and failed detecting device. Some miniport 00665 * drivers in that case adjust parameters and call VideoPortInitialize 00666 * again. 00667 */ 00668 00669 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject); 00670 if (DriverExtension == NULL) 00671 { 00672 Status = IoAllocateDriverObjectExtension( 00673 DriverObject, 00674 DriverObject, 00675 sizeof(VIDEO_PORT_DRIVER_EXTENSION), 00676 (PVOID *)&DriverExtension); 00677 00678 if (!NT_SUCCESS(Status)) 00679 { 00680 return Status; 00681 } 00682 00683 /* 00684 * Save the registry path. This should be done only once even if 00685 * VideoPortInitialize is called multiple times. 00686 */ 00687 00688 if (RegistryPath->Length != 0) 00689 { 00690 DriverExtension->RegistryPath.Length = 0; 00691 DriverExtension->RegistryPath.MaximumLength = 00692 RegistryPath->Length + sizeof(UNICODE_NULL); 00693 DriverExtension->RegistryPath.Buffer = 00694 ExAllocatePoolWithTag( 00695 PagedPool, 00696 DriverExtension->RegistryPath.MaximumLength, 00697 'RTSU'); 00698 if (DriverExtension->RegistryPath.Buffer == NULL) 00699 { 00700 RtlInitUnicodeString(&DriverExtension->RegistryPath, NULL); 00701 return STATUS_INSUFFICIENT_RESOURCES; 00702 } 00703 00704 RtlCopyUnicodeString(&DriverExtension->RegistryPath, RegistryPath); 00705 INFO_(VIDEOPRT, "RegistryPath: %wZ\n", &DriverExtension->RegistryPath); 00706 } 00707 else 00708 { 00709 RtlInitUnicodeString(&DriverExtension->RegistryPath, NULL); 00710 } 00711 } 00712 00713 /* 00714 * Copy the correct miniport initialization data to the device extension. 00715 */ 00716 00717 RtlCopyMemory( 00718 &DriverExtension->InitializationData, 00719 HwInitializationData, 00720 HwInitializationData->HwInitDataSize); 00721 if (HwInitializationData->HwInitDataSize < 00722 sizeof(VIDEO_HW_INITIALIZATION_DATA)) 00723 { 00724 RtlZeroMemory((PVOID)((ULONG_PTR)&DriverExtension->InitializationData + 00725 HwInitializationData->HwInitDataSize), 00726 sizeof(VIDEO_HW_INITIALIZATION_DATA) - 00727 HwInitializationData->HwInitDataSize); 00728 } 00729 DriverExtension->HwContext = HwContext; 00730 00731 /* 00732 * Plug & Play drivers registers the device in AddDevice routine. For 00733 * legacy drivers we must do it now. 00734 */ 00735 00736 if (LegacyDetection) 00737 { 00738 PDEVICE_OBJECT DeviceObject; 00739 00740 if (HwInitializationData->HwInitDataSize != SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA) 00741 { 00742 /* power management */ 00743 DriverObject->MajorFunction[IRP_MJ_POWER] = IntVideoPortDispatchPower; 00744 } 00745 Status = IntVideoPortCreateAdapterDeviceObject(DriverObject, DriverExtension, 00746 NULL, &DeviceObject); 00747 INFO_(VIDEOPRT, "IntVideoPortCreateAdapterDeviceObject returned 0x%x\n", Status); 00748 if (!NT_SUCCESS(Status)) 00749 return Status; 00750 Status = IntVideoPortFindAdapter(DriverObject, DriverExtension, DeviceObject); 00751 INFO_(VIDEOPRT, "IntVideoPortFindAdapter returned 0x%x\n", Status); 00752 if (NT_SUCCESS(Status)) 00753 VideoPortDeviceNumber++; 00754 return Status; 00755 } 00756 else 00757 { 00758 DriverObject->DriverExtension->AddDevice = IntVideoPortAddDevice; 00759 DriverObject->MajorFunction[IRP_MJ_PNP] = IntVideoPortDispatchPnp; 00760 DriverObject->MajorFunction[IRP_MJ_POWER] = IntVideoPortDispatchPower; 00761 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = IntVideoPortDispatchSystemControl; 00762 00763 return STATUS_SUCCESS; 00764 } 00765 } 00766 00767 /* 00768 * @implemented 00769 */ 00770 00771 VOID 00772 VideoPortDebugPrint( 00773 IN VIDEO_DEBUG_LEVEL DebugPrintLevel, 00774 IN PCHAR DebugMessage, ...) 00775 { 00776 va_list ap; 00777 00778 va_start(ap, DebugMessage); 00779 vDbgPrintEx(DPFLTR_IHVVIDEO_ID, DebugPrintLevel, DebugMessage, ap); 00780 va_end(ap); 00781 } 00782 00783 /* 00784 * @unimplemented 00785 */ 00786 00787 VOID NTAPI 00788 VideoPortLogError( 00789 IN PVOID HwDeviceExtension, 00790 IN PVIDEO_REQUEST_PACKET Vrp OPTIONAL, 00791 IN VP_STATUS ErrorCode, 00792 IN ULONG UniqueId) 00793 { 00794 UNIMPLEMENTED; 00795 00796 INFO_(VIDEOPRT, "VideoPortLogError ErrorCode %d (0x%x) UniqueId %lu (0x%lx)\n", 00797 ErrorCode, ErrorCode, UniqueId, UniqueId); 00798 if (Vrp) 00799 INFO_(VIDEOPRT, "Vrp->IoControlCode %lu (0x%lx)\n", Vrp->IoControlCode, Vrp->IoControlCode); 00800 } 00801 00802 /* 00803 * @implemented 00804 */ 00805 00806 UCHAR NTAPI 00807 VideoPortGetCurrentIrql(VOID) 00808 { 00809 return KeGetCurrentIrql(); 00810 } 00811 00812 typedef struct QueryRegistryCallbackContext 00813 { 00814 PVOID HwDeviceExtension; 00815 PVOID HwContext; 00816 PMINIPORT_GET_REGISTRY_ROUTINE HwGetRegistryRoutine; 00817 } QUERY_REGISTRY_CALLBACK_CONTEXT, *PQUERY_REGISTRY_CALLBACK_CONTEXT; 00818 00819 static NTSTATUS NTAPI 00820 QueryRegistryCallback( 00821 IN PWSTR ValueName, 00822 IN ULONG ValueType, 00823 IN PVOID ValueData, 00824 IN ULONG ValueLength, 00825 IN PVOID Context, 00826 IN PVOID EntryContext) 00827 { 00828 PQUERY_REGISTRY_CALLBACK_CONTEXT CallbackContext = (PQUERY_REGISTRY_CALLBACK_CONTEXT) Context; 00829 00830 INFO_(VIDEOPRT, "Found registry value for name %S: type %d, length %d\n", 00831 ValueName, ValueType, ValueLength); 00832 return (*(CallbackContext->HwGetRegistryRoutine))( 00833 CallbackContext->HwDeviceExtension, 00834 CallbackContext->HwContext, 00835 ValueName, 00836 ValueData, 00837 ValueLength); 00838 } 00839 00840 /* 00841 * @unimplemented 00842 */ 00843 00844 VP_STATUS NTAPI 00845 VideoPortGetRegistryParameters( 00846 IN PVOID HwDeviceExtension, 00847 IN PWSTR ParameterName, 00848 IN UCHAR IsParameterFileName, 00849 IN PMINIPORT_GET_REGISTRY_ROUTINE GetRegistryRoutine, 00850 IN PVOID HwContext) 00851 { 00852 RTL_QUERY_REGISTRY_TABLE QueryTable[2] = {{0}}; 00853 QUERY_REGISTRY_CALLBACK_CONTEXT Context; 00854 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; 00855 00856 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); 00857 00858 TRACE_(VIDEOPRT, "VideoPortGetRegistryParameters ParameterName %S, RegPath: %wZ\n", 00859 ParameterName, &DeviceExtension->RegistryPath); 00860 00861 Context.HwDeviceExtension = HwDeviceExtension; 00862 Context.HwContext = HwContext; 00863 Context.HwGetRegistryRoutine = GetRegistryRoutine; 00864 00865 QueryTable[0].QueryRoutine = QueryRegistryCallback; 00866 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED; 00867 QueryTable[0].Name = ParameterName; 00868 00869 if (!NT_SUCCESS(RtlQueryRegistryValues( 00870 RTL_REGISTRY_ABSOLUTE, 00871 DeviceExtension->RegistryPath.Buffer, 00872 QueryTable, 00873 &Context, 00874 NULL))) 00875 { 00876 WARN_(VIDEOPRT, "VideoPortGetRegistryParameters could not find the " 00877 "requested parameter\n"); 00878 return ERROR_INVALID_PARAMETER; 00879 } 00880 00881 if (IsParameterFileName) 00882 { 00883 /* FIXME: need to read the contents of the file */ 00884 UNIMPLEMENTED; 00885 } 00886 00887 return NO_ERROR; 00888 } 00889 00890 /* 00891 * @implemented 00892 */ 00893 00894 VP_STATUS NTAPI 00895 VideoPortSetRegistryParameters( 00896 IN PVOID HwDeviceExtension, 00897 IN PWSTR ValueName, 00898 IN PVOID ValueData, 00899 IN ULONG ValueLength) 00900 { 00901 VP_STATUS Status; 00902 00903 TRACE_(VIDEOPRT, "VideoPortSetRegistryParameters ParameterName %S, RegPath: %wZ\n", 00904 ValueName, 00905 &VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension)->RegistryPath); 00906 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL); 00907 Status = RtlWriteRegistryValue( 00908 RTL_REGISTRY_ABSOLUTE, 00909 VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension)->RegistryPath.Buffer, 00910 ValueName, 00911 REG_BINARY, 00912 ValueData, 00913 ValueLength); 00914 00915 if (Status != NO_ERROR) 00916 WARN_(VIDEOPRT, "VideoPortSetRegistryParameters error 0x%x\n", Status); 00917 00918 return Status; 00919 } 00920 00921 /* 00922 * @implemented 00923 */ 00924 00925 VP_STATUS NTAPI 00926 VideoPortGetVgaStatus( 00927 IN PVOID HwDeviceExtension, 00928 OUT PULONG VgaStatus) 00929 { 00930 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; 00931 00932 TRACE_(VIDEOPRT, "VideoPortGetVgaStatus\n"); 00933 00934 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); 00935 if (KeGetCurrentIrql() == PASSIVE_LEVEL) 00936 { 00937 if (DeviceExtension->AdapterInterfaceType == PCIBus) 00938 { 00939 /* VgaStatus: 0 == VGA not enabled, 1 == VGA enabled. */ 00940 /* Assumed for now */ 00941 *VgaStatus = 1; 00942 return NO_ERROR; 00943 } 00944 } 00945 00946 return ERROR_INVALID_FUNCTION; 00947 } 00948 00949 /* 00950 * @implemented 00951 */ 00952 00953 PVOID NTAPI 00954 VideoPortGetRomImage( 00955 IN PVOID HwDeviceExtension, 00956 IN PVOID Unused1, 00957 IN ULONG Unused2, 00958 IN ULONG Length) 00959 { 00960 static PVOID RomImageBuffer = NULL; 00961 PKPROCESS CallingProcess; 00962 KAPC_STATE ApcState; 00963 00964 TRACE_(VIDEOPRT, "VideoPortGetRomImage(HwDeviceExtension 0x%X Length 0x%X)\n", 00965 HwDeviceExtension, Length); 00966 00967 /* If the length is zero then free the existing buffer. */ 00968 if (Length == 0) 00969 { 00970 if (RomImageBuffer != NULL) 00971 { 00972 ExFreePool(RomImageBuffer); 00973 RomImageBuffer = NULL; 00974 } 00975 return NULL; 00976 } 00977 else 00978 { 00979 /* 00980 * The DDK says we shouldn't use the legacy C0000 method but get the 00981 * rom base address from the corresponding pci or acpi register but 00982 * lets ignore that and use C0000 anyway. We have already mapped the 00983 * bios area into memory so we'll copy from there. 00984 */ 00985 00986 /* Copy the bios. */ 00987 Length = min(Length, 0x10000); 00988 if (RomImageBuffer != NULL) 00989 { 00990 ExFreePool(RomImageBuffer); 00991 } 00992 00993 RomImageBuffer = ExAllocatePool(PagedPool, Length); 00994 if (RomImageBuffer == NULL) 00995 { 00996 return NULL; 00997 } 00998 00999 IntAttachToCSRSS(&CallingProcess, &ApcState); 01000 RtlCopyMemory(RomImageBuffer, (PUCHAR)0xC0000, Length); 01001 IntDetachFromCSRSS(&CallingProcess, &ApcState); 01002 01003 return RomImageBuffer; 01004 } 01005 } 01006 01007 /* 01008 * @implemented 01009 */ 01010 01011 BOOLEAN NTAPI 01012 VideoPortScanRom( 01013 IN PVOID HwDeviceExtension, 01014 IN PUCHAR RomBase, 01015 IN ULONG RomLength, 01016 IN PUCHAR String) 01017 { 01018 ULONG StringLength; 01019 BOOLEAN Found; 01020 PUCHAR SearchLocation; 01021 01022 TRACE_(VIDEOPRT, "VideoPortScanRom RomBase %p RomLength 0x%x String %s\n", RomBase, RomLength, String); 01023 01024 StringLength = strlen((PCHAR)String); 01025 Found = FALSE; 01026 SearchLocation = RomBase; 01027 for (SearchLocation = RomBase; 01028 !Found && SearchLocation < RomBase + RomLength - StringLength; 01029 SearchLocation++) 01030 { 01031 Found = (RtlCompareMemory(SearchLocation, String, StringLength) == StringLength); 01032 if (Found) 01033 { 01034 INFO_(VIDEOPRT, "Match found at %p\n", SearchLocation); 01035 } 01036 } 01037 01038 return Found; 01039 } 01040 01041 /* 01042 * @implemented 01043 */ 01044 01045 BOOLEAN NTAPI 01046 VideoPortSynchronizeExecution( 01047 IN PVOID HwDeviceExtension, 01048 IN VIDEO_SYNCHRONIZE_PRIORITY Priority, 01049 IN PMINIPORT_SYNCHRONIZE_ROUTINE SynchronizeRoutine, 01050 OUT PVOID Context) 01051 { 01052 BOOLEAN Ret; 01053 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; 01054 KIRQL OldIrql; 01055 01056 switch (Priority) 01057 { 01058 case VpLowPriority: 01059 Ret = (*SynchronizeRoutine)(Context); 01060 break; 01061 01062 case VpMediumPriority: 01063 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); 01064 if (DeviceExtension->InterruptObject == NULL) 01065 Ret = (*SynchronizeRoutine)(Context); 01066 else 01067 Ret = KeSynchronizeExecution( 01068 DeviceExtension->InterruptObject, 01069 SynchronizeRoutine, 01070 Context); 01071 break; 01072 01073 case VpHighPriority: 01074 OldIrql = KeGetCurrentIrql(); 01075 if (OldIrql < SYNCH_LEVEL) 01076 KeRaiseIrql(SYNCH_LEVEL, &OldIrql); 01077 01078 Ret = (*SynchronizeRoutine)(Context); 01079 01080 if (OldIrql < SYNCH_LEVEL) 01081 KeLowerIrql(OldIrql); 01082 break; 01083 01084 default: 01085 Ret = FALSE; 01086 } 01087 01088 return Ret; 01089 } 01090 01091 /* 01092 * @implemented 01093 */ 01094 01095 VP_STATUS NTAPI 01096 VideoPortEnumerateChildren( 01097 IN PVOID HwDeviceExtension, 01098 IN PVOID Reserved) 01099 { 01100 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; 01101 ULONG Status; 01102 VIDEO_CHILD_ENUM_INFO ChildEnumInfo; 01103 BOOLEAN bHaveLastMonitorID = FALSE; 01104 UCHAR LastMonitorID[10]; 01105 ULONG Unused; 01106 UINT i; 01107 PDEVICE_OBJECT ChildDeviceObject; 01108 PVIDEO_PORT_CHILD_EXTENSION ChildExtension; 01109 01110 INFO_(VIDEOPRT, "Starting child device probe\n"); 01111 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); 01112 if (DeviceExtension->DriverExtension->InitializationData.HwGetVideoChildDescriptor == NULL) 01113 { 01114 WARN_(VIDEOPRT, "Miniport's HwGetVideoChildDescriptor is NULL!\n"); 01115 return NO_ERROR; 01116 } 01117 01118 if (!IsListEmpty(&DeviceExtension->ChildDeviceList)) 01119 { 01120 ERR_(VIDEOPRT, "FIXME: Support calling VideoPortEnumerateChildren again!\n"); 01121 return NO_ERROR; 01122 } 01123 01124 /* Enumerate the children */ 01125 for (i = 1; ; i++) 01126 { 01127 Status = IoCreateDevice(DeviceExtension->DriverObject, 01128 sizeof(VIDEO_PORT_CHILD_EXTENSION) + 01129 DeviceExtension->DriverExtension->InitializationData.HwChildDeviceExtensionSize, 01130 NULL, 01131 FILE_DEVICE_CONTROLLER, 01132 FILE_DEVICE_SECURE_OPEN, 01133 FALSE, 01134 &ChildDeviceObject); 01135 if (!NT_SUCCESS(Status)) 01136 return Status; 01137 01138 ChildExtension = ChildDeviceObject->DeviceExtension; 01139 01140 RtlZeroMemory(ChildExtension, sizeof(VIDEO_PORT_CHILD_EXTENSION) + 01141 DeviceExtension->DriverExtension->InitializationData.HwChildDeviceExtensionSize); 01142 01143 ChildExtension->Common.Fdo = FALSE; 01144 ChildExtension->ChildId = i; 01145 ChildExtension->PhysicalDeviceObject = ChildDeviceObject; 01146 ChildExtension->DriverObject = DeviceExtension->DriverObject; 01147 01148 /* Setup the ChildEnumInfo */ 01149 ChildEnumInfo.Size = sizeof(ChildEnumInfo); 01150 ChildEnumInfo.ChildDescriptorSize = sizeof(ChildExtension->ChildDescriptor); 01151 ChildEnumInfo.ACPIHwId = 0; 01152 01153 if (DeviceExtension->DriverExtension->InitializationData.HwChildDeviceExtensionSize) 01154 ChildEnumInfo.ChildHwDeviceExtension = VIDEO_PORT_GET_CHILD_EXTENSION(ChildExtension); 01155 else 01156 ChildEnumInfo.ChildHwDeviceExtension = NULL; 01157 01158 ChildEnumInfo.ChildIndex = ChildExtension->ChildId; 01159 01160 INFO_(VIDEOPRT, "Probing child: %d\n", ChildEnumInfo.ChildIndex); 01161 Status = DeviceExtension->DriverExtension->InitializationData.HwGetVideoChildDescriptor( 01162 HwDeviceExtension, 01163 &ChildEnumInfo, 01164 &ChildExtension->ChildType, 01165 ChildExtension->ChildDescriptor, 01166 &ChildExtension->ChildId, 01167 &Unused); 01168 if (Status == VIDEO_ENUM_MORE_DEVICES) 01169 { 01170 if (ChildExtension->ChildType == Monitor) 01171 { 01172 // Check if the EDID is valid 01173 if (ChildExtension->ChildDescriptor[0] == 0x00 && 01174 ChildExtension->ChildDescriptor[1] == 0xFF && 01175 ChildExtension->ChildDescriptor[2] == 0xFF && 01176 ChildExtension->ChildDescriptor[3] == 0xFF && 01177 ChildExtension->ChildDescriptor[4] == 0xFF && 01178 ChildExtension->ChildDescriptor[5] == 0xFF && 01179 ChildExtension->ChildDescriptor[6] == 0xFF && 01180 ChildExtension->ChildDescriptor[7] == 0x00) 01181 { 01182 if (bHaveLastMonitorID) 01183 { 01184 // Compare the previous monitor ID with the current one, break the loop if they are identical 01185 if (RtlCompareMemory(LastMonitorID, &ChildExtension->ChildDescriptor[8], sizeof(LastMonitorID)) == sizeof(LastMonitorID)) 01186 { 01187 INFO_(VIDEOPRT, "Found identical Monitor ID two times, stopping enumeration\n"); 01188 IoDeleteDevice(ChildDeviceObject); 01189 break; 01190 } 01191 } 01192 01193 // Copy 10 bytes from the EDID, which can be used to uniquely identify the monitor 01194 RtlCopyMemory(LastMonitorID, &ChildExtension->ChildDescriptor[8], sizeof(LastMonitorID)); 01195 bHaveLastMonitorID = TRUE; 01196 01197 /* Mark it valid */ 01198 ChildExtension->EdidValid = TRUE; 01199 } 01200 else 01201 { 01202 /* Mark it invalid */ 01203 ChildExtension->EdidValid = FALSE; 01204 } 01205 } 01206 } 01207 else if (Status == VIDEO_ENUM_INVALID_DEVICE) 01208 { 01209 WARN_(VIDEOPRT, "Child device %d is invalid!\n", ChildEnumInfo.ChildIndex); 01210 IoDeleteDevice(ChildDeviceObject); 01211 continue; 01212 } 01213 else if (Status == VIDEO_ENUM_NO_MORE_DEVICES) 01214 { 01215 INFO_(VIDEOPRT, "End of child enumeration! (%d children enumerated)\n", i - 1); 01216 IoDeleteDevice(ChildDeviceObject); 01217 break; 01218 } 01219 else 01220 { 01221 WARN_(VIDEOPRT, "HwGetVideoChildDescriptor returned unknown status code 0x%x!\n", Status); 01222 IoDeleteDevice(ChildDeviceObject); 01223 break; 01224 } 01225 01226 if (ChildExtension->ChildType == Monitor) 01227 { 01228 UINT j; 01229 PUCHAR p = ChildExtension->ChildDescriptor; 01230 INFO_(VIDEOPRT, "Monitor device enumerated! (ChildId = 0x%x)\n", ChildExtension->ChildId); 01231 for (j = 0; j < sizeof (ChildExtension->ChildDescriptor); j += 8) 01232 { 01233 INFO_(VIDEOPRT, "%02x %02x %02x %02x %02x %02x %02x %02x\n", 01234 p[j+0], p[j+1], p[j+2], p[j+3], 01235 p[j+4], p[j+5], p[j+6], p[j+7]); 01236 } 01237 } 01238 else if (ChildExtension->ChildType == Other) 01239 { 01240 INFO_(VIDEOPRT, "\"Other\" device enumerated: DeviceId = %S\n", (PWSTR)ChildExtension->ChildDescriptor); 01241 } 01242 else 01243 { 01244 ERR_(VIDEOPRT, "HwGetVideoChildDescriptor returned unsupported type: %d\n", ChildExtension->ChildType); 01245 } 01246 01247 /* Clear the init flag */ 01248 ChildDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 01249 01250 InsertTailList(&DeviceExtension->ChildDeviceList, 01251 &ChildExtension->ListEntry); 01252 } 01253 01254 /* Trigger reenumeration by the PnP manager */ 01255 IoInvalidateDeviceRelations(DeviceExtension->PhysicalDeviceObject, BusRelations); 01256 01257 return NO_ERROR; 01258 } 01259 01260 /* 01261 * @unimplemented 01262 */ 01263 01264 VP_STATUS NTAPI 01265 VideoPortCreateSecondaryDisplay( 01266 IN PVOID HwDeviceExtension, 01267 IN OUT PVOID *SecondaryDeviceExtension, 01268 IN ULONG Flag) 01269 { 01270 UNIMPLEMENTED; 01271 return ERROR_DEV_NOT_EXIST; 01272 } 01273 01274 /* 01275 * @implemented 01276 */ 01277 01278 BOOLEAN NTAPI 01279 VideoPortQueueDpc( 01280 IN PVOID HwDeviceExtension, 01281 IN PMINIPORT_DPC_ROUTINE CallbackRoutine, 01282 IN PVOID Context) 01283 { 01284 return KeInsertQueueDpc( 01285 &VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension)->DpcObject, 01286 (PVOID)CallbackRoutine, 01287 (PVOID)Context); 01288 } 01289 01290 /* 01291 * @implemented 01292 */ 01293 01294 PVOID NTAPI 01295 VideoPortGetAssociatedDeviceExtension(IN PVOID DeviceObject) 01296 { 01297 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; 01298 01299 TRACE_(VIDEOPRT, "VideoPortGetAssociatedDeviceExtension\n"); 01300 DeviceExtension = ((PDEVICE_OBJECT)DeviceObject)->DeviceExtension; 01301 if (!DeviceExtension) 01302 return NULL; 01303 return DeviceExtension->MiniPortDeviceExtension; 01304 } 01305 01306 /* 01307 * @implemented 01308 */ 01309 01310 VP_STATUS NTAPI 01311 VideoPortGetVersion( 01312 IN PVOID HwDeviceExtension, 01313 IN OUT PVPOSVERSIONINFO VpOsVersionInfo) 01314 { 01315 RTL_OSVERSIONINFOEXW Version; 01316 01317 Version.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW); 01318 if (VpOsVersionInfo->Size >= sizeof(VPOSVERSIONINFO)) 01319 { 01320 #if 1 01321 if (NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW)&Version))) 01322 { 01323 VpOsVersionInfo->MajorVersion = Version.dwMajorVersion; 01324 VpOsVersionInfo->MinorVersion = Version.dwMinorVersion; 01325 VpOsVersionInfo->BuildNumber = Version.dwBuildNumber; 01326 VpOsVersionInfo->ServicePackMajor = Version.wServicePackMajor; 01327 VpOsVersionInfo->ServicePackMinor = Version.wServicePackMinor; 01328 return NO_ERROR; 01329 } 01330 return ERROR_INVALID_PARAMETER; 01331 #else 01332 VpOsVersionInfo->MajorVersion = 5; 01333 VpOsVersionInfo->MinorVersion = 0; 01334 VpOsVersionInfo->BuildNumber = 2195; 01335 VpOsVersionInfo->ServicePackMajor = 4; 01336 VpOsVersionInfo->ServicePackMinor = 0; 01337 return NO_ERROR; 01338 #endif 01339 } 01340 01341 return ERROR_INVALID_PARAMETER; 01342 } 01343 01344 /* 01345 * @implemented 01346 */ 01347 01348 BOOLEAN NTAPI 01349 VideoPortCheckForDeviceExistence( 01350 IN PVOID HwDeviceExtension, 01351 IN USHORT VendorId, 01352 IN USHORT DeviceId, 01353 IN UCHAR RevisionId, 01354 IN USHORT SubVendorId, 01355 IN USHORT SubSystemId, 01356 IN ULONG Flags) 01357 { 01358 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; 01359 PCI_DEVICE_PRESENT_INTERFACE PciDevicePresentInterface; 01360 IO_STATUS_BLOCK IoStatusBlock; 01361 IO_STACK_LOCATION IoStack; 01362 ULONG PciFlags = 0; 01363 NTSTATUS Status; 01364 BOOL DevicePresent; 01365 01366 TRACE_(VIDEOPRT, "VideoPortCheckForDeviceExistence\n"); 01367 01368 if (Flags & ~(CDE_USE_REVISION | CDE_USE_SUBSYSTEM_IDS)) 01369 { 01370 WARN_(VIDEOPRT, "VideoPortCheckForDeviceExistence: Unknown flags 0x%lx\n", Flags & ~(CDE_USE_REVISION | CDE_USE_SUBSYSTEM_IDS)); 01371 return FALSE; 01372 } 01373 01374 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); 01375 01376 PciDevicePresentInterface.Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE); 01377 PciDevicePresentInterface.Version = 1; 01378 IoStack.Parameters.QueryInterface.Size = PciDevicePresentInterface.Size; 01379 IoStack.Parameters.QueryInterface.Version = PciDevicePresentInterface.Version; 01380 IoStack.Parameters.QueryInterface.Interface = (PINTERFACE)&PciDevicePresentInterface; 01381 IoStack.Parameters.QueryInterface.InterfaceType = 01382 &GUID_PCI_DEVICE_PRESENT_INTERFACE; 01383 Status = IopInitiatePnpIrp(DeviceExtension->NextDeviceObject, 01384 &IoStatusBlock, IRP_MN_QUERY_INTERFACE, &IoStack); 01385 if (!NT_SUCCESS(Status)) 01386 { 01387 WARN_(VIDEOPRT, "IopInitiatePnpIrp() failed! (Status 0x%lx)\n", Status); 01388 return FALSE; 01389 } 01390 01391 if (Flags & CDE_USE_REVISION) 01392 PciFlags |= PCI_USE_REVISION; 01393 if (Flags & CDE_USE_SUBSYSTEM_IDS) 01394 PciFlags |= PCI_USE_SUBSYSTEM_IDS; 01395 01396 DevicePresent = PciDevicePresentInterface.IsDevicePresent( 01397 VendorId, DeviceId, RevisionId, 01398 SubVendorId, SubSystemId, PciFlags); 01399 01400 PciDevicePresentInterface.InterfaceDereference(PciDevicePresentInterface.Context); 01401 01402 return DevicePresent; 01403 } 01404 01405 /* 01406 * @unimplemented 01407 */ 01408 01409 VP_STATUS NTAPI 01410 VideoPortRegisterBugcheckCallback( 01411 IN PVOID HwDeviceExtension, 01412 IN ULONG BugcheckCode, 01413 IN PVIDEO_BUGCHECK_CALLBACK Callback, 01414 IN ULONG BugcheckDataSize) 01415 { 01416 UNIMPLEMENTED; 01417 return NO_ERROR; 01418 } 01419 01420 /* 01421 * @implemented 01422 */ 01423 01424 LONGLONG NTAPI 01425 VideoPortQueryPerformanceCounter( 01426 IN PVOID HwDeviceExtension, 01427 OUT PLONGLONG PerformanceFrequency OPTIONAL) 01428 { 01429 LARGE_INTEGER Result; 01430 01431 TRACE_(VIDEOPRT, "VideoPortQueryPerformanceCounter\n"); 01432 Result = KeQueryPerformanceCounter((PLARGE_INTEGER)PerformanceFrequency); 01433 return Result.QuadPart; 01434 } 01435 01436 /* 01437 * @implemented 01438 */ 01439 01440 VOID NTAPI 01441 VideoPortAcquireDeviceLock( 01442 IN PVOID HwDeviceExtension) 01443 { 01444 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; 01445 NTSTATUS Status; 01446 (void)Status; 01447 01448 TRACE_(VIDEOPRT, "VideoPortAcquireDeviceLock\n"); 01449 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); 01450 Status = KeWaitForMutexObject(&DeviceExtension->DeviceLock, Executive, 01451 KernelMode, FALSE, NULL); 01452 // ASSERT(Status == STATUS_SUCCESS); 01453 } 01454 01455 /* 01456 * @implemented 01457 */ 01458 01459 VOID NTAPI 01460 VideoPortReleaseDeviceLock( 01461 IN PVOID HwDeviceExtension) 01462 { 01463 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; 01464 LONG Status; 01465 (void)Status; 01466 01467 TRACE_(VIDEOPRT, "VideoPortReleaseDeviceLock\n"); 01468 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); 01469 Status = KeReleaseMutex(&DeviceExtension->DeviceLock, FALSE); 01470 //ASSERT(Status == STATUS_SUCCESS); 01471 } 01472 01473 /* 01474 * @unimplemented 01475 */ 01476 01477 VOID NTAPI 01478 VpNotifyEaData( 01479 IN PDEVICE_OBJECT DeviceObject, 01480 IN PVOID Data) 01481 { 01482 UNIMPLEMENTED; 01483 } 01484 01485 /* 01486 * @implemented 01487 */ 01488 PVOID NTAPI 01489 VideoPortAllocateContiguousMemory( 01490 IN PVOID HwDeviceExtension, 01491 IN ULONG NumberOfBytes, 01492 IN PHYSICAL_ADDRESS HighestAcceptableAddress 01493 ) 01494 { 01495 01496 return MmAllocateContiguousMemory(NumberOfBytes, HighestAcceptableAddress); 01497 } 01498 01499 /* 01500 * @implemented 01501 */ 01502 BOOLEAN NTAPI 01503 VideoPortIsNoVesa(VOID) 01504 { 01505 NTSTATUS Status; 01506 HANDLE KeyHandle; 01507 UNICODE_STRING Path = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control"); 01508 UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"SystemStartOptions"); 01509 OBJECT_ATTRIBUTES ObjectAttributes; 01510 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo; 01511 ULONG Length, NewLength; 01512 01513 /* Initialize object attributes with the path we want */ 01514 InitializeObjectAttributes(&ObjectAttributes, 01515 &Path, 01516 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 01517 NULL, 01518 NULL); 01519 01520 /* Open the key */ 01521 Status = ZwOpenKey(&KeyHandle, 01522 KEY_QUERY_VALUE, 01523 &ObjectAttributes); 01524 01525 if (!NT_SUCCESS(Status)) 01526 { 01527 VideoPortDebugPrint(Error, "ZwOpenKey failed (0x%x)\n", Status); 01528 return FALSE; 01529 } 01530 01531 /* Find out how large our buffer should be */ 01532 Status = ZwQueryValueKey(KeyHandle, 01533 &ValueName, 01534 KeyValuePartialInformation, 01535 NULL, 01536 0, 01537 &Length); 01538 if (Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_BUFFER_TOO_SMALL) 01539 { 01540 VideoPortDebugPrint(Error, "ZwQueryValueKey failed (0x%x)\n", Status); 01541 ZwClose(KeyHandle); 01542 return FALSE; 01543 } 01544 01545 /* Allocate it */ 01546 KeyInfo = ExAllocatePool(PagedPool, Length); 01547 if (!KeyInfo) 01548 { 01549 VideoPortDebugPrint(Error, "Out of memory\n"); 01550 ZwClose(KeyHandle); 01551 return FALSE; 01552 } 01553 01554 /* Now for real this time */ 01555 Status = ZwQueryValueKey(KeyHandle, 01556 &ValueName, 01557 KeyValuePartialInformation, 01558 KeyInfo, 01559 Length, 01560 &NewLength); 01561 01562 ZwClose(KeyHandle); 01563 01564 if (!NT_SUCCESS(Status)) 01565 { 01566 VideoPortDebugPrint(Error, "ZwQueryValueKey failed (0x%x)\n", Status); 01567 ExFreePool(KeyInfo); 01568 return FALSE; 01569 } 01570 01571 /* Sanity check */ 01572 if (KeyInfo->Type != REG_SZ) 01573 { 01574 VideoPortDebugPrint(Error, "Invalid type for SystemStartOptions\n"); 01575 ExFreePool(KeyInfo); 01576 return FALSE; 01577 } 01578 01579 /* Check if NOVESA or BASEVIDEO is present in the start options */ 01580 if (wcsstr((PWCHAR)KeyInfo->Data, L"NOVESA") || 01581 wcsstr((PWCHAR)KeyInfo->Data, L"BASEVIDEO")) 01582 { 01583 VideoPortDebugPrint(Info, "VESA mode disabled\n"); 01584 ExFreePool(KeyInfo); 01585 return TRUE; 01586 } 01587 01588 ExFreePool(KeyInfo); 01589 01590 VideoPortDebugPrint(Info, "VESA mode enabled\n"); 01591 01592 return FALSE; 01593 } 01594 Generated on Sun May 27 2012 04:38:15 for ReactOS by
1.7.6.1
|