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]