added      agp.c         First try of implementing the AGP functions (Untested)
added      ddc.c         First try of implementing DDC functions (Untested)
modified   dispatch.c    Handle IRP_MJ_PNP:IRP_MN_START_DEVICE. Let AddDevice create the device object and call HwFindAdapter from IRP_MN_START_DEVICE.
modified   int10.c       Make VideoPortInt10 return ERROR_INVALID_PARAMETER when called while CSRSS is not initialized.
modified   Makefile      Add agp.o and ddc.o
modified   resource.c    Don't remember usermode mappings - they are valid only in the context of the process which they were created in. Add IntVideoPortMapPhysicalMemory() to map part of \Device\PhysicalMemory into UserMode. Make VideoPortGetAccessRanges use DeviceExtension->AllocatedResources (from the IRP_MJ_PNP:IRP_MN_START_DEVICE) if present.
modified   services.c    Implement VideoPortGetAgpServices. VideoPortQueryServices support for VideoPortServicesAGP.
modified   videoprt.c    Split IntVideoPortFindAdapter into IntVideoPortCreateAdapterDeviceObject and IntVideoPortFindAdapter. Basic implementation of VideoPortEnumerateChildren. Implement VideoPortAcquireDeviceLock/VideoPortReleaseDeviceLock.
modified   videoprt.def  Export VideoPortAcquireDeviceLock/VideoPortReleaseDeviceLock.
modified   videoprt.h    Various stuff.
Modified: trunk/reactos/drivers/video/videoprt/Makefile
Added: trunk/reactos/drivers/video/videoprt/agp.c
Added: trunk/reactos/drivers/video/videoprt/ddc.c
Modified: trunk/reactos/drivers/video/videoprt/dispatch.c
Modified: trunk/reactos/drivers/video/videoprt/int10.c
Modified: trunk/reactos/drivers/video/videoprt/resource.c
Modified: trunk/reactos/drivers/video/videoprt/services.c
Modified: trunk/reactos/drivers/video/videoprt/videoprt.c
Modified: trunk/reactos/drivers/video/videoprt/videoprt.def
Modified: trunk/reactos/drivers/video/videoprt/videoprt.h

Modified: trunk/reactos/drivers/video/videoprt/Makefile
--- trunk/reactos/drivers/video/videoprt/Makefile	2005-01-07 00:02:56 UTC (rev 12859)
+++ trunk/reactos/drivers/video/videoprt/Makefile	2005-01-07 01:03:34 UTC (rev 12860)
@@ -9,6 +9,8 @@
 TARGET_CFLAGS += -Wall -Werror -D__USE_W32API -I$(PATH_TO_TOP)/ntoskrnl/include
 
 TARGET_OBJECTS = \
+	agp.o \
+	ddc.o \
 	dispatch.o \
 	dma.o \
 	event.o \

Added: trunk/reactos/drivers/video/videoprt/agp.c
--- trunk/reactos/drivers/video/videoprt/agp.c	2005-01-07 00:02:56 UTC (rev 12859)
+++ trunk/reactos/drivers/video/videoprt/agp.c	2005-01-07 01:03:34 UTC (rev 12860)
@@ -0,0 +1,566 @@
+/*
+ * VideoPort driver
+ *
+ * Copyright (C) 2002, 2003, 2004 ReactOS Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; see the file COPYING.LIB.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id$
+ */
+
+#include "videoprt.h"
+#include <initguid.h>
+#include <ddk/wdmguid.h>
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+STATIC NTSTATUS
+IopInitiatePnpIrp(
+  PDEVICE_OBJECT DeviceObject,
+  PIO_STATUS_BLOCK IoStatusBlock,
+  ULONG MinorFunction,
+  PIO_STACK_LOCATION Stack OPTIONAL)
+{
+  PDEVICE_OBJECT TopDeviceObject;
+  PIO_STACK_LOCATION IrpSp;
+  NTSTATUS Status;
+  KEVENT Event;
+  PIRP Irp;
+
+  /* Always call the top of the device stack */
+  TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject);
+
+  KeInitializeEvent(
+    &Event,
+    NotificationEvent,
+    FALSE);
+
+  Irp = IoBuildSynchronousFsdRequest(
+    IRP_MJ_PNP,
+    TopDeviceObject,
+    NULL,
+    0,
+    NULL,
+    &Event,
+    IoStatusBlock);
+
+  /* PNP IRPs are always initialized with a status code of
+     STATUS_NOT_IMPLEMENTED */
+  Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
+  Irp->IoStatus.Information = 0;
+
+  IrpSp = IoGetNextIrpStackLocation(Irp);
+  IrpSp->MinorFunction = MinorFunction;
+
+  if (Stack)
+  {
+    RtlMoveMemory(
+      &IrpSp->Parameters,
+      &Stack->Parameters,
+      sizeof(Stack->Parameters));
+  }
+
+  Status = IoCallDriver(TopDeviceObject, Irp);
+  if (Status == STATUS_PENDING)
+    {
+      KeWaitForSingleObject(
+        &Event,
+        Executive,
+        KernelMode,
+        FALSE,
+        NULL);
+      Status = IoStatusBlock->Status;
+    }
+
+  ObDereferenceObject(TopDeviceObject);
+
+  return Status;
+}
+
+
+BOOLEAN STDCALL
+IntAgpCommitPhysical(
+   IN PVOID HwDeviceExtension,
+   IN PVOID PhysicalContext,
+   IN ULONG Pages,
+   IN ULONG Offset)
+{
+   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
+   PAGP_BUS_INTERFACE_STANDARD AgpBusInterface;
+   PHYSICAL_ADDRESS MappingAddr = {{0}};
+   PVIDEO_PORT_AGP_MAPPING AgpMapping;
+   NTSTATUS Status;
+
+   DPRINT("AgpCommitPhysical - PhysicalContext: 0x%x Pages: %d, Offset: 0x%x\n",
+          PhysicalContext, Pages, Offset);
+
+   DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
+   AgpBusInterface = &DeviceExtension->AgpInterface;
+   AgpMapping = (PVIDEO_PORT_AGP_MAPPING)PhysicalContext;
+
+   Status = AgpBusInterface->CommitMemory(AgpBusInterface->AgpContext,
+                                          AgpMapping->MapHandle, Pages, Offset,
+                                          NULL, &MappingAddr);
+
+   if (!NT_SUCCESS(Status))
+   {
+      DPRINT1("Warning: AgpBusInterface->CommitMemory failed (Status = 0x%x)\n",
+              Status);
+   }
+   return NT_SUCCESS(Status);
+}
+
+VOID STDCALL
+IntAgpFreePhysical(
+   IN PVOID HwDeviceExtension,
+   IN PVOID PhysicalContext,
+   IN ULONG Pages,
+   IN ULONG Offset)
+{
+   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
+   PAGP_BUS_INTERFACE_STANDARD AgpBusInterface;
+   PVIDEO_PORT_AGP_MAPPING AgpMapping;
+   NTSTATUS Status;
+
+   DPRINT("AgpFreePhysical - PhysicalContext: 0x%x Pages: %d, Offset: 0x%x\n",
+          PhysicalContext, Pages, Offset);
+
+   DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
+   AgpBusInterface = &DeviceExtension->AgpInterface;
+   AgpMapping = (PVIDEO_PORT_AGP_MAPPING)PhysicalContext;
+
+   Status = AgpBusInterface->FreeMemory(AgpBusInterface->AgpContext,
+                                        AgpMapping->MapHandle, Pages, Offset);
+   if (!NT_SUCCESS(Status))
+   {
+      DPRINT1("Warning: AgpBusInterface->FreeMemory failed (Status = 0x%x)\n",
+              Status);
+   }
+}
+
+VOID STDCALL
+IntAgpReleasePhysical(
+   IN PVOID HwDeviceExtension,
+   IN PVOID PhysicalContext)
+{
+   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
+   PAGP_BUS_INTERFACE_STANDARD AgpBusInterface;
+   PVIDEO_PORT_AGP_MAPPING AgpMapping;
+   NTSTATUS Status;
+
+   DPRINT("AgpReleasePhysical - PhysicalContext: 0x%x\n", PhysicalContext);
+
+   DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
+   AgpBusInterface = &DeviceExtension->AgpInterface;
+   AgpMapping = (PVIDEO_PORT_AGP_MAPPING)PhysicalContext;
+   
+   /* Release memory */
+   Status = AgpBusInterface->ReleaseMemory(AgpBusInterface->AgpContext,
+                                           AgpMapping->MapHandle);
+   if (!NT_SUCCESS(Status))
+   {
+      DPRINT1("Warning: AgpBusInterface->ReleaseMemory failed (Status = 0x%x)\n",
+              Status);
+   }
+   
+   /* Free resources */
+   ExFreePool(AgpMapping);
+}
+
+PHYSICAL_ADDRESS STDCALL
+IntAgpReservePhysical(
+   IN  PVOID HwDeviceExtension,
+   IN  ULONG Pages,
+   IN  VIDEO_PORT_CACHE_TYPE Caching,
+   OUT PVOID *PhysicalContext)
+{
+   PHYSICAL_ADDRESS ZeroAddress = {{0}};
+   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
+   PAGP_BUS_INTERFACE_STANDARD AgpBusInterface;
+   MEMORY_CACHING_TYPE MemCachingType;
+   PVIDEO_PORT_AGP_MAPPING AgpMapping;
+   NTSTATUS Status;
+
+   DPRINT("AgpReservePhysical - Pages: %d, Caching: 0x%x\n", Pages, Caching);
+
+   DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
+   AgpBusInterface = &DeviceExtension->AgpInterface;
+
+   /* Translate memory caching type */
+   if (Caching == VpNonCached)
+     MemCachingType = MmNonCached;
+   else if (Caching == VpCached)
+     MemCachingType = MmCached;
+   else if (Caching == VpWriteCombined)
+     MemCachingType = MmWriteCombined;
+   else
+   {
+      DPRINT1("Invalid caching type %d!\n", Caching);
+      return ZeroAddress;
+   }
+
+   /* Allocate an AGP mapping structure */
+   AgpMapping = ExAllocatePoolWithTag(PagedPool,
+                                      sizeof(VIDEO_PORT_AGP_MAPPING),
+                                      TAG_VIDEO_PORT);
+   if (AgpMapping == NULL)
+   {
+      DPRINT1("Out of memory! Couldn't allocate AGP mapping structure!\n");
+      return ZeroAddress;
+   }
+   RtlZeroMemory(AgpMapping, sizeof(VIDEO_PORT_AGP_MAPPING));
+
+   /* Reserve memory for the AGP bus */
+   Status = AgpBusInterface->ReserveMemory(AgpBusInterface->AgpContext,
+                                           Pages,
+                                           MemCachingType,
+                                           &AgpMapping->MapHandle,
+                                           &AgpMapping->PhysicalAddress);
+   if (!NT_SUCCESS(Status) || AgpMapping->MapHandle == NULL)
+   {
+      ExFreePool(AgpMapping);
+      DPRINT1("Warning: AgpBusInterface->ReserveMemory failed (Status = 0x%x)\n",
+              Status);
+      return ZeroAddress;
+   }
+
+   /* Fill the rest of the AGP mapping */
+   AgpMapping->NumberOfPages = Pages;
+
+   *PhysicalContext = (PVOID)AgpMapping;
+   return AgpMapping->PhysicalAddress;
+}
+   
+
+PVOID STDCALL
+IntAgpCommitVirtual(
+   IN PVOID HwDeviceExtension,
+   IN PVOID VirtualContext,
+   IN ULONG Pages,
+   IN ULONG Offset)
+{
+   PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping;
+   PVOID BaseAddress = NULL;
+   NTSTATUS Status;
+
+   DPRINT("AgpCommitVirtual - VirtualContext: 0x%x Pages: %d, Offset: 0x%x\n",
+          VirtualContext, Pages, Offset);
+
+   VirtualMapping = (PVIDEO_PORT_AGP_VIRTUAL_MAPPING)VirtualContext;
+
+   /* I think the NT API provides no way of reserving a part of the address space
+    * and setting it up to map into a specified range of physical memory later.
+    * This means that we will have to release some of the reserved virtual memory
+    * and map the physical memory into it using MapViewOfSection.
+    *
+    * - blight (2004-12-21)
+    */
+
+   if (VirtualMapping->ProcessHandle == NULL)
+   {
+      /* FIXME: not implemented */
+   }
+   else /* ProcessHandle != NULL */
+   {
+      /* Release some virtual memory */
+      ULONG Size = Pages * PAGE_SIZE;
+      ULONG OffsetInBytes = Offset * PAGE_SIZE;
+      BaseAddress = (PVOID)((ULONG_PTR)VirtualMapping->MappedAddress +
+                                       OffsetInBytes);
+      PHYSICAL_ADDRESS PhysicalAddress = VirtualMapping->AgpMapping->PhysicalAddress;
+      PhysicalAddress.QuadPart += OffsetInBytes;
+
+      Status = ZwFreeVirtualMemory(VirtualMapping->ProcessHandle,
+                                   &BaseAddress,
+                                   &Size, MEM_RELEASE);
+      if (!NT_SUCCESS(Status))
+      {
+         DPRINT1("Warning: ZwFreeVirtualMemory() failed: Status = 0x%x\n", Status);
+         return NULL;
+      }
+      ASSERT(Size == Pages * PAGE_SIZE);
+      ASSERT(BaseAddress == (PVOID)((ULONG_PTR)VirtualMapping->MappedAddress +
+                                               OffsetInBytes));
+      
+      /* Map the physical memory into the released virtual memory area */
+      Status = IntVideoPortMapPhysicalMemory(VirtualMapping->ProcessHandle,
+                                             PhysicalAddress,
+                                             Size,
+                                             PAGE_READWRITE,
+                                             &BaseAddress);
+      if (!NT_SUCCESS(Status))
+      {
+         DPRINT1("Warning: IntVideoPortMapPhysicalMemory() failed: Status = 0x%x\n", Status);
+         /* Reserve the released virtual memory area again */
+         Status = ZwAllocateVirtualMemory(VirtualMapping->ProcessHandle,
+                                          &BaseAddress, 0, &Size, MEM_RESERVE,
+                                          PAGE_NOACCESS);
+         if (!NT_SUCCESS(Status))
+         {
+            DPRINT1("Warning: ZwAllocateVirtualMemory() failed: Status = 0x%x\n", Status);
+            /* FIXME: What to do now?? */
+            ASSERT(0);
+            return NULL;
+         }
+         ASSERT(Size == Pages * PAGE_SIZE);
+         ASSERT(BaseAddress == (PVOID)((ULONG_PTR)VirtualMapping->MappedAddress +
+                                               OffsetInBytes));
+         return NULL;
+      }
+      ASSERT(BaseAddress == (PVOID)((ULONG_PTR)VirtualMapping->MappedAddress +
+                                               OffsetInBytes));
+   }
+
+   return BaseAddress;
+}
+
+VOID STDCALL
+IntAgpFreeVirtual(
+   IN PVOID HwDeviceExtension,
+   IN PVOID VirtualContext,
+   IN ULONG Pages,
+   IN ULONG Offset)
+{
+   PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping;
+   PVOID BaseAddress = NULL;
+   NTSTATUS Status;
+
+   DPRINT("AgpFreeVirtual - VirtualContext: 0x%x Pages: %d, Offset: 0x%x\n",
+          VirtualContext, Pages, Offset);
+
+   VirtualMapping = (PVIDEO_PORT_AGP_VIRTUAL_MAPPING)VirtualContext;
+
+   if (VirtualMapping->ProcessHandle == NULL)
+   {
+      /* FIXME: not implemented */
+   }
+   else /* ProcessHandle != NULL */
+   {
+      /* Unmap the section view */
+      ULONG Size = Pages * PAGE_SIZE;
+      ULONG OffsetInBytes = Offset * PAGE_SIZE;
+      BaseAddress = (PVOID)((ULONG_PTR)VirtualMapping->MappedAddress +
+                                       OffsetInBytes);
+
+      Status = ZwUnmapViewOfSection(VirtualMapping->ProcessHandle, BaseAddress);
+      if (!NT_SUCCESS(Status))
+      {
+         DPRINT1("Warning: ZwUnmapViewOfSection() failed: Status = 0x%x\n", Status);
+         /* FIXME: What to do now?? */
+         ASSERT(0);
+         return;
+      }
+
+      /* And reserve the virtual memory area again */
+      Status = ZwAllocateVirtualMemory(VirtualMapping->ProcessHandle,
+                                       &BaseAddress, 0, &Size, MEM_RESERVE,
+                                       PAGE_NOACCESS);
+      if (!NT_SUCCESS(Status))
+      {
+         DPRINT1("Warning: ZwAllocateVirtualMemory() failed: Status = 0x%x\n", Status);
+         /* FIXME: What to do now?? */
+         ASSERT(0);
+         return;
+      }
+      ASSERT(Size == Pages * PAGE_SIZE);
+      ASSERT(BaseAddress == (PVOID)((ULONG_PTR)VirtualMapping->MappedAddress +
+                                               OffsetInBytes));
+   }
+}
+
+VOID STDCALL
+IntAgpReleaseVirtual(
+   IN PVOID HwDeviceExtension,
+   IN PVOID VirtualContext)
+{
+   PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping;
+   NTSTATUS Status;
+
+   DPRINT("AgpReleaseVirtual - VirtualContext: 0x%x\n", VirtualContext);
+
+   VirtualMapping = (PVIDEO_PORT_AGP_VIRTUAL_MAPPING)VirtualContext;
+   
+   /* Release the virtual memory */
+   if (VirtualMapping->ProcessHandle == NULL)
+   {
+      /* FIXME: not implemented */
+   }
+   else /* ProcessHandle != NULL */
+   {
+      /* Release the allocated virtual memory */
+      ULONG Size = VirtualMapping->AgpMapping->NumberOfPages * PAGE_SIZE;
+      Status = ZwFreeVirtualMemory(VirtualMapping->ProcessHandle,
+                                   &VirtualMapping->MappedAddress,
+                                   &Size, MEM_RELEASE);
+      if (!NT_SUCCESS(Status))
+      {
+         DPRINT1("Warning: ZwFreeVirtualMemory() failed: Status = 0x%x\n", Status);
+      }
+   }
+   
+   /* Free resources */
+   ExFreePool(VirtualMapping);
+}
+
+PVOID STDCALL
+IntAgpReserveVirtual(
+   IN  PVOID HwDeviceExtension,
+   IN  HANDLE ProcessHandle,
+   IN  PVOID PhysicalContext,
+   OUT PVOID *VirtualContext)
+{
+   PVIDEO_PORT_AGP_MAPPING AgpMapping;
+   PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping;
+   PVOID MappedAddress;
+   NTSTATUS Status;
+
+   DPRINT("AgpReserveVirtual - ProcessHandle: 0x%x PhysicalContext: 0x%x\n",
+          ProcessHandle, PhysicalContext);
+
+   AgpMapping = (PVIDEO_PORT_AGP_MAPPING)PhysicalContext;
+
+   /* Allocate an AGP virtual mapping structure */
+   VirtualMapping = ExAllocatePoolWithTag(PagedPool,
+                                          sizeof(VIDEO_PORT_AGP_VIRTUAL_MAPPING),
+                                          TAG_VIDEO_PORT);
+   if (VirtualMapping == NULL)
+   {
+      DPRINT1("Out of memory! Couldn't allocate AGP virtual mapping structure!\n");
+      return NULL;
+   }
+   RtlZeroMemory(VirtualMapping, sizeof(VIDEO_PORT_AGP_VIRTUAL_MAPPING));
+
+   /* Reserve a virtual memory area for the physical pages. */
+   if (ProcessHandle == NULL)
+   {
+      /* FIXME: What to do in this case? */
+      ExFreePool(VirtualMapping);
+      return NULL;
+   }
+   else /* ProcessHandle != NULL */
+   {
+      /* Reserve memory for usermode */
+      ULONG Size = AgpMapping->NumberOfPages * PAGE_SIZE;
+      MappedAddress = NULL;
+      Status = ZwAllocateVirtualMemory(ProcessHandle, &MappedAddress, 0, &Size,
+                                       MEM_RESERVE, PAGE_NOACCESS);
+      if (!NT_SUCCESS(Status))
+      {
+         ExFreePool(VirtualMapping);
+         DPRINT("ZwAllocateVirtualMemory() failed: Status = 0x%x\n", Status);
+         return NULL;
+      }
+   }
+
+   /* Fill the AGP virtual mapping */
+   VirtualMapping->AgpMapping = AgpMapping;
+   VirtualMapping->ProcessHandle = ProcessHandle;
+   VirtualMapping->MappedAddress = MappedAddress;
+
+   *VirtualContext = (PVOID)VirtualMapping;
+   return MappedAddress;
+}
+
+
+BOOLEAN STDCALL
+IntAgpSetRate(
+   IN PVOID HwDeviceExtension,
+   IN ULONG Rate)
+{
+   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
+   PAGP_BUS_INTERFACE_STANDARD AgpBusInterface;
+
+   DPRINT("AgpSetRate - Rate: %d\n", Rate);
+
+   DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
+   AgpBusInterface = &DeviceExtension->AgpInterface;
+   
+   return NT_SUCCESS(AgpBusInterface->SetRate(AgpBusInterface->AgpContext, Rate));
+}
+
+
+NTSTATUS STDCALL
+IntAgpGetInterface(
+   IN PVOID HwDeviceExtension,
+   IN OUT PINTERFACE Interface)
+{
+   IO_STATUS_BLOCK IoStatusBlock;
+   IO_STACK_LOCATION IoStack;
+   NTSTATUS Status;
+   PVIDEO_PORT_AGP_INTERFACE_2 AgpInterface;
+   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
+   PAGP_BUS_INTERFACE_STANDARD AgpBusInterface;
+
+   DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
+   AgpBusInterface = &DeviceExtension->AgpInterface;
+   AgpInterface = (PVIDEO_PORT_AGP_INTERFACE_2)Interface;
+
+   ASSERT((Interface->Version == VIDEO_PORT_AGP_INTERFACE_VERSION_2 &&
+           Interface->Size >= sizeof(VIDEO_PORT_AGP_INTERFACE_2)) ||
+          (Interface->Version == VIDEO_PORT_AGP_INTERFACE_VERSION_1 &&
+           Interface->Size >= sizeof(VIDEO_PORT_AGP_INTERFACE)));
+
+   if (DeviceExtension->NextDeviceObject == NULL)
+   {
+      DPRINT("DeviceExtension->NextDeviceObject is NULL!\n");
+      return STATUS_UNSUCCESSFUL;
+   }
+
+   /* Query the interface from the AGP bus driver */
+   if (DeviceExtension->AgpInterface.Size == 0)
+   {
+      AgpBusInterface->Size = sizeof(AGP_BUS_INTERFACE_STANDARD);
+      if (Interface->Version == VIDEO_PORT_AGP_INTERFACE_VERSION_1)
+         AgpBusInterface->Version = AGP_BUS_INTERFACE_V1;
+      else /* if (InterfaceVersion == VIDEO_PORT_AGP_INTERFACE_VERSION_2) */
+         AgpBusInterface->Version = AGP_BUS_INTERFACE_V2;
+      IoStack.Parameters.QueryInterface.Size = AgpBusInterface->Size;
+      IoStack.Parameters.QueryInterface.Version = AgpBusInterface->Version;
+      IoStack.Parameters.QueryInterface.Interface = (PINTERFACE)AgpBusInterface;
+      IoStack.Parameters.QueryInterface.InterfaceType =
+         &GUID_AGP_TARGET_BUS_INTERFACE_STANDARD;
+      Status = IopInitiatePnpIrp(DeviceExtension->NextDeviceObject,
+         &IoStatusBlock, IRP_MN_QUERY_INTERFACE, &IoStack);
+      if (!NT_SUCCESS(Status))
+      {
+         DPRINT("IopInitiatePnpIrp() failed! (Status 0x%x)\n", Status);
+         return Status;
+      }
+      DPRINT("Got AGP driver interface!\n");
+   }
+
+   /* FIXME: Not sure if we should wrap the reference/dereference functions */
+   AgpInterface->Context = AgpBusInterface->AgpContext;
+   AgpInterface->InterfaceReference = AgpBusInterface->InterfaceReference;
+   AgpInterface->InterfaceDereference = AgpBusInterface->InterfaceDereference;
+   AgpInterface->AgpReservePhysical = IntAgpReservePhysical;
+   AgpInterface->AgpReleasePhysical = IntAgpReleasePhysical;
+   AgpInterface->AgpCommitPhysical = IntAgpCommitPhysical;
+   AgpInterface->AgpFreePhysical = IntAgpFreePhysical;
+   AgpInterface->AgpReserveVirtual = IntAgpReserveVirtual;
+   AgpInterface->AgpReleaseVirtual = IntAgpReleaseVirtual;
+   AgpInterface->AgpCommitVirtual = IntAgpCommitVirtual;
+   AgpInterface->AgpFreeVirtual = IntAgpFreeVirtual;
+   AgpInterface->AgpAllocationLimit = 0x1000000; /* FIXME: using 16 MB for now */
+
+   if (AgpInterface->Version >= VIDEO_PORT_AGP_INTERFACE_VERSION_2)
+   {
+      AgpInterface->AgpSetRate = IntAgpSetRate;
+   }
+
+   return STATUS_SUCCESS;
+}
+

Added: trunk/reactos/drivers/video/videoprt/ddc.c
--- trunk/reactos/drivers/video/videoprt/ddc.c	2005-01-07 00:02:56 UTC (rev 12859)
+++ trunk/reactos/drivers/video/videoprt/ddc.c	2005-01-07 01:03:34 UTC (rev 12860)
@@ -0,0 +1,227 @@
+/*
+ * VideoPort driver
+ *
+ * Copyright (C) 2002, 2003, 2004 ReactOS Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; see the file COPYING.LIB.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id$
+ */
+
+#include "videoprt.h"
+
+#define DDC_EEPROM_ADDRESS  0xA0
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+#define LOW               0
+#define HIGH              1
+#define WRITE             0
+#define READ              1
+#define READ_SDA()        (i2c->ReadDataLine(HwDeviceExtension))
+#define READ_SCL()        (i2c->ReadClockLine(HwDeviceExtension))
+#define WRITE_SDA(state)  (i2c->WriteDataLine(HwDeviceExtension, state))
+#define WRITE_SCL(state)  (i2c->WriteClockLine(HwDeviceExtension, state))
+
+STATIC LARGE_INTEGER HalfPeriodDelay = { { 70LL } };
+#define DELAY_HALF()      KeDelayExecutionThread(KernelMode, FALSE, &HalfPeriodDelay)
+
+
+STATIC BOOL
+I2CWrite(PVOID HwDeviceExtension, PI2C_CALLBACKS i2c, UCHAR Data)
+{
+   UCHAR Bit;
+   BOOL Ack;
+
+   /* transmit data */
+   for (Bit = (1 << 7); Bit != 0; Bit >>= 1)
+     {
+        WRITE_SCL(LOW);
+        WRITE_SDA((Data & Bit) ? HIGH : LOW);
+        DELAY_HALF();
+        WRITE_SCL(HIGH);
+        DELAY_HALF();
+     }
+
+   /* get ack */
+   WRITE_SCL(LOW);
+   WRITE_SDA(HIGH);
+   DELAY_HALF();
+   WRITE_SCL(HIGH);
+   do
+     {
+        DELAY_HALF();
+     }
+   while (READ_SCL() != HIGH);
+   Ack = (READ_SDA() == LOW);
+   DELAY_HALF();
+
+   DPRINT("I2CWrite: %s\n", Ack ? "Ack" : "Nak");
+   return Ack;
+}
+
+
+STATIC UCHAR
+I2CRead(PVOID HwDeviceExtension, PI2C_CALLBACKS i2c, BOOL Ack)
+{
+   INT Bit = 0x80;
+   UCHAR Data = 0;
+
+   /* pull down SCL and release SDA */
+   WRITE_SCL(LOW);
+   WRITE_SDA(HIGH);
+
+   /* read byte */
+   for (Bit = (1 << 7); Bit != 0; Bit >>= 1)
+     {
+        WRITE_SCL(LOW);
+        DELAY_HALF();
+        WRITE_SCL(HIGH);
+        DELAY_HALF();
+        if (READ_SDA() == HIGH)
+          Data |= Bit;
+     }
+
+   /* send ack/nak */
+   WRITE_SCL(LOW);
+   WRITE_SDA(Ack ? LOW : HIGH);
+   DELAY_HALF();
+   WRITE_SCL(HIGH);
+   do
+     {
+        DELAY_HALF();
+     }
+   while (READ_SCL() != HIGH);
+
+   return Data;
+}
+
+
+STATIC VOID
+I2CStop(PVOID HwDeviceExtension, PI2C_CALLBACKS i2c)
+{
+   WRITE_SCL(LOW);
+   WRITE_SDA(LOW);
+   DELAY_HALF();
+   WRITE_SCL(HIGH);
+   DELAY_HALF();
+   WRITE_SDA(HIGH);
+}
+
+
+STATIC BOOL
+I2CStart(PVOID HwDeviceExtension, PI2C_CALLBACKS i2c, UCHAR Address)
+{
+   /* make sure the bus is free */
+   if (READ_SDA() == LOW || READ_SCL() == LOW)
+     {
+        DPRINT1("I2CStart: Bus is not free!\n");
+        return FALSE;
+     }
+
+   /* send address */
+   WRITE_SDA(LOW);
+   DELAY_HALF();
+   if (!I2CWrite(HwDeviceExtension, i2c, Address))
+     {
+        /* ??release the bus?? */
+        I2CStop(HwDeviceExtension, i2c);
+        DPRINT1("I2CStart: Device not found (Address = 0x%x)\n", Address);
+        return FALSE;
+     }
+
+   DPRINT("I2CStart: SUCCESS!\n");
+   return TRUE;
+}
+
+
+STATIC BOOL
+I2CRepStart(PVOID HwDeviceExtension, PI2C_CALLBACKS i2c, UCHAR Address)
+{
+   /* setup lines for repeated start condition */
+   WRITE_SCL(LOW);
+   DELAY_HALF();
+   WRITE_SDA(HIGH);
+   DELAY_HALF();
+   WRITE_SCL(HIGH);
+   DELAY_HALF();
+
+   return I2CStart(HwDeviceExtension, i2c, Address);
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+/*
+ * @implemented
+ */
+
+BOOLEAN STDCALL
+VideoPortDDCMonitorHelper(
+   PVOID HwDeviceExtension,
+   PVOID I2CFunctions,
+   PUCHAR pEdidBuffer,
+   ULONG EdidBufferSize
+   )
+{
+   PDDC_CONTROL ddc = (PDDC_CONTROL)I2CFunctions;
+   PI2C_CALLBACKS i2c = &ddc->I2CCallbacks;
+   INT Count, i;
+   PUCHAR pBuffer = (PUCHAR)pEdidBuffer;
+   BOOL Ack;
+
+   DPRINT("VideoPortDDCMonitorHelper()\n");
+
+   ASSERT_IRQL(PASSIVE_LEVEL);
+   if (ddc->Size != sizeof (ddc))
+     {
+        DPRINT("ddc->Size != %d (%d)\n", sizeof (ddc), ddc->Size);
+        return FALSE;
+     }
+
+   /* select eeprom */
+   if (!I2CStart(HwDeviceExtension, i2c, DDC_EEPROM_ADDRESS | WRITE))
+     return FALSE;
+   /* set address */
+   if (!I2CWrite(HwDeviceExtension, i2c, 0x00))
+     return FALSE;
+   /* change into read mode */
+   if (!I2CRepStart(HwDeviceExtension, i2c, DDC_EEPROM_ADDRESS | READ))
+     return FALSE;
+   /* read eeprom */
+   RtlZeroMemory(pEdidBuffer, EdidBufferSize);
+   Count = min(128, EdidBufferSize);
+   for (i = 0; i < Count; i++)
+     {
+        Ack = ((i + 1) < Count);
+        pBuffer[i] = I2CRead(HwDeviceExtension, i2c, Ack);
+     }
+   I2CStop(HwDeviceExtension, i2c);
+
+   /* check EDID header */
+   if (pBuffer[0] != 0x00 || pBuffer[1] != 0xff ||
+       pBuffer[2] != 0xff || pBuffer[3] != 0xff ||
+       pBuffer[4] != 0xff || pBuffer[5] != 0xff ||
+       pBuffer[6] != 0xff || pBuffer[7] != 0x00)
+     {
+        DPRINT1("VideoPortDDCMonitorHelper(): Invalid EDID header!\n");
+        return FALSE;
+     }
+
+   DPRINT("VideoPortDDCMonitorHelper(): EDID version %d rev. %d\n", pBuffer[18], pBuffer[19]);
+   DPRINT("VideoPortDDCMonitorHelper() - SUCCESS!\n");
+   return TRUE;
+}
+

Modified: trunk/reactos/drivers/video/videoprt/dispatch.c
--- trunk/reactos/drivers/video/videoprt/dispatch.c	2005-01-07 00:02:56 UTC (rev 12859)
+++ trunk/reactos/drivers/video/videoprt/dispatch.c	2005-01-07 01:03:34 UTC (rev 12860)
@@ -78,13 +78,14 @@
    DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
 
    /*
-    * Use generic routine to find the adapter and create device object.
+    * Create adapter device object.
     */
 
-   return IntVideoPortFindAdapter(
+   return IntVideoPortCreateAdapterDeviceObject(
       DriverObject,
       DriverExtension,
-      PhysicalDeviceObject);      
+      PhysicalDeviceObject,
+      NULL);
 }
 
 /*
@@ -265,34 +266,177 @@
 }
 
 NTSTATUS STDCALL
+IntVideoPortPnPStartDevice(
+   IN PDEVICE_OBJECT DeviceObject,
+   IN PIRP Irp)
+{
+   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+   PDRIVER_OBJECT DriverObject;
+   PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
+   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
+   PCM_RESOURCE_LIST AllocatedResources;
+
+   /*
+    * Get the initialization data we saved in VideoPortInitialize.
+    */
+
+   DriverObject = DeviceObject->DriverObject;
+   DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
+   DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+   /*
+    * Store some resources in the DeviceExtension.
+    */
+
+   AllocatedResources = Stack->Parameters.StartDevice.AllocatedResources;
+   if (AllocatedResources != NULL)
+   {
+      CM_FULL_RESOURCE_DESCRIPTOR *FullList;
+      CM_PARTIAL_RESOURCE_DESCRIPTOR *Descriptor;
+      ULONG ResourceCount;
+      ULONG ResourceListSize;
+
+      /* Save the resource list */
+      ResourceCount = AllocatedResources->List[0].PartialResourceList.Count;
+      ResourceListSize =
+         FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
+                      PartialDescriptors[ResourceCount]);
+      DeviceExtension->AllocatedResources = ExAllocatePool(PagedPool, ResourceListSize);
+      if (DeviceExtension->AllocatedResources == NULL)
+      {
+         return STATUS_INSUFFICIENT_RESOURCES;
+      }
+
+      RtlCopyMemory(DeviceExtension->AllocatedResources,
+                    AllocatedResources,
+                    ResourceListSize);
+
+      /* Get the interrupt level/vector - needed by HwFindAdapter sometimes */
+      for (FullList = AllocatedResources->List;
+           FullList < AllocatedResources->List + AllocatedResources->Count;
+           FullList++)
+      {
+         /* FIXME: Is this ASSERT ok for resources from the PNP manager? */
+         ASSERT(FullList->InterfaceType == PCIBus &&
+                FullList->BusNumber == DeviceExtension->SystemIoBusNumber &&
+                1 == FullList->PartialResourceList.Version &&
+                1 == FullList->PartialResourceList.Revision);
+	 for (Descriptor = FullList->PartialResourceList.PartialDescriptors;
+              Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count;
+              Descriptor++)
+         {
+            if (Descriptor->Type == CmResourceTypeInterrupt)
+            {
+               DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level;
+               DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector;
+            }
+         }
+      }
+   }
+   DPRINT("Interrupt level: 0x%x Interrupt Vector: 0x%x\n",
+          DeviceExtension->InterruptLevel,
+          DeviceExtension->InterruptVector);
+
+   /*
+    * Create adapter device object.
+    */
+
+   return IntVideoPortFindAdapter(
+      DriverObject,
+      DriverExtension,
+      DeviceObject);
+}
+
+
+NTSTATUS
+STDCALL
+IntVideoPortForwardIrpAndWaitCompletionRoutine(
+    PDEVICE_OBJECT Fdo,
+    PIRP Irp,
+    PVOID Context)
+{
+  PKEVENT Event = Context;
+
+  if (Irp->PendingReturned)
+    KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
+
+  return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+
+NTSTATUS
+STDCALL
+IntVideoPortForwardIrpAndWait(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+   KEVENT Event;
+   NTSTATUS Status;
+   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension =
+                   (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+   KeInitializeEvent(&Event, NotificationEvent, FALSE);
+   IoCopyCurrentIrpStackLocationToNext(Irp);
+   IoSetCompletionRoutine(Irp, IntVideoPortForwardIrpAndWaitCompletionRoutine,
+                          &Event, TRUE, TRUE, TRUE);
+   Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
+   if (Status == STATUS_PENDING)
+   {
+      KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+      Status = Irp->IoStatus.Status;
+   }
+   return Status;
+}
+
+
+NTSTATUS STDCALL
 IntVideoPortDispatchPnp(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp)
 {
    PIO_STACK_LOCATION IrpSp;
+   NTSTATUS Status;
 
    IrpSp = IoGetCurrentIrpStackLocation(Irp);
 
    switch (IrpSp->MinorFunction)
    {
       case IRP_MN_START_DEVICE:
+         Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
+         if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
+            Status = IntVideoPortPnPStartDevice(DeviceObject, Irp);
+         Irp->IoStatus.Status = Status;
+         Irp->IoStatus.Information = 0;
+         IoCompleteRequest(Irp, IO_NO_INCREMENT);
+         break;
 
+
       case IRP_MN_REMOVE_DEVICE:
       case IRP_MN_QUERY_REMOVE_DEVICE:
       case IRP_MN_CANCEL_REMOVE_DEVICE:
       case IRP_MN_SURPRISE_REMOVAL:
 
       case IRP_MN_STOP_DEVICE:
+         Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
+         if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
+            Status = STATUS_SUCCESS;
+         Irp->IoStatus.Status = Status;
+         Irp->IoStatus.Information = 0;
+         IoCompleteRequest(Irp, IO_NO_INCREMENT);
+         break;
+
       case IRP_MN_QUERY_STOP_DEVICE:
[truncated at 1000 lines; 1115 more skipped]