ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

videoprt.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.