Support mapping of video device memory into usermode - unfortunately this is not correctly supported by the memory manager yet.

svn path=/trunk/; revision=12207
This commit is contained in:
Gregor Anich 2004-12-18 22:14:39 +00:00
parent 5016bfecf7
commit c37ff99746
2 changed files with 142 additions and 41 deletions

View file

@ -18,7 +18,7 @@
* If not, write to the Free Software Foundation, * If not, write to the Free Software Foundation,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* *
* $Id: resource.c,v 1.4 2004/10/15 22:48:43 gvg Exp $ * $Id: resource.c,v 1.5 2004/12/18 22:14:38 blight Exp $
*/ */
#include "videoprt.h" #include "videoprt.h"
@ -34,7 +34,7 @@ IntVideoPortMapMemory(
OUT VP_STATUS *Status) OUT VP_STATUS *Status)
{ {
PHYSICAL_ADDRESS TranslatedAddress; PHYSICAL_ADDRESS TranslatedAddress;
PVIDEO_PORT_ADDRESS_MAPPING AddressMapping; PVIDEO_PORT_ADDRESS_MAPPING AddressMapping = NULL;
ULONG AddressSpace; ULONG AddressSpace;
PVOID MappedAddress; PVOID MappedAddress;
PLIST_ENTRY Entry; PLIST_ENTRY Entry;
@ -61,18 +61,33 @@ IntVideoPortMapMemory(
List); List);
if (IoAddress.QuadPart == AddressMapping->IoAddress.QuadPart && if (IoAddress.QuadPart == AddressMapping->IoAddress.QuadPart &&
NumberOfUchars <= AddressMapping->NumberOfUchars) NumberOfUchars <= AddressMapping->NumberOfUchars)
{
if ((InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) != 0 &&
AddressMapping->MappedUserAddress != NULL)
{
AddressMapping->UserMappingCount++;
if (Status)
*Status = NO_ERROR;
return AddressMapping->MappedUserAddress;
}
else if ((InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) == 0 &&
AddressMapping->MappedUserAddress != NULL)
{ {
AddressMapping->MappingCount++; AddressMapping->MappingCount++;
if (Status) if (Status)
*Status = NO_ERROR; *Status = NO_ERROR;
return AddressMapping->MappedAddress; return AddressMapping->MappedAddress;
} }
break;
}
Entry = Entry->Flink; Entry = Entry->Flink;
} }
if (Entry == &DeviceExtension->AddressMappingListHead)
AddressMapping = NULL;
} }
AddressSpace = (ULONG)InIoSpace; AddressSpace = (ULONG)InIoSpace;
AddressSpace &= ~VIDEO_MEMORY_SPACE_USER_MODE;
if (HalTranslateBusAddress( if (HalTranslateBusAddress(
DeviceExtension->AdapterInterfaceType, DeviceExtension->AdapterInterfaceType,
DeviceExtension->SystemIoBusNumber, DeviceExtension->SystemIoBusNumber,
@ -96,18 +111,69 @@ IntVideoPortMapMemory(
return (PVOID)TranslatedAddress.u.LowPart; return (PVOID)TranslatedAddress.u.LowPart;
} }
/* user space */
if ((InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) != 0)
{
OBJECT_ATTRIBUTES ObjAttribs;
UNICODE_STRING UnicodeString;
HANDLE hMemObj;
NTSTATUS NtStatus;
SIZE_T Size;
RtlInitUnicodeString(&UnicodeString, L"\\Device\\PhysicalMemory");
InitializeObjectAttributes(&ObjAttribs,
&UnicodeString,
OBJ_CASE_INSENSITIVE/* | OBJ_KERNEL_HANDLE*/,
NULL, NULL);
NtStatus = ZwOpenSection(&hMemObj, SECTION_ALL_ACCESS, &ObjAttribs);
if (!NT_SUCCESS(NtStatus))
{
DPRINT("ZwOpenSection() failed! (0x%x)\n", NtStatus);
if (Status)
*Status = NO_ERROR;
return NULL;
}
Size = NumberOfUchars;
MappedAddress = NULL;
NtStatus = ZwMapViewOfSection(hMemObj,
NtCurrentProcess(),
&MappedAddress,
0,
NumberOfUchars,
(PLARGE_INTEGER)(&TranslatedAddress),
&Size,
ViewUnmap,
0,
PAGE_READWRITE/* | PAGE_WRITECOMBINE*/);
if (!NT_SUCCESS(NtStatus))
{
DPRINT("ZwMapViewOfSection() failed! (0x%x)\n", NtStatus);
ZwClose(hMemObj);
if (Status)
*Status = NO_ERROR;
return NULL;
}
ZwClose(hMemObj);
DPRINT("Mapped user address = 0x%08x\n", MappedAddress);
}
else /* kernel space */
{
MappedAddress = MmMapIoSpace( MappedAddress = MmMapIoSpace(
TranslatedAddress, TranslatedAddress,
NumberOfUchars, NumberOfUchars,
MmNonCached); MmNonCached);
}
if (MappedAddress) if (MappedAddress != NULL)
{ {
BOOL InsertIntoList = FALSE;
if (Status) if (Status)
{ {
*Status = NO_ERROR; *Status = NO_ERROR;
} }
if (AddressMapping == NULL)
{
AddressMapping = ExAllocatePoolWithTag( AddressMapping = ExAllocatePoolWithTag(
PagedPool, PagedPool,
sizeof(VIDEO_PORT_ADDRESS_MAPPING), sizeof(VIDEO_PORT_ADDRESS_MAPPING),
@ -116,26 +182,39 @@ IntVideoPortMapMemory(
if (AddressMapping == NULL) if (AddressMapping == NULL)
return MappedAddress; return MappedAddress;
AddressMapping->MappedAddress = MappedAddress; InsertIntoList = TRUE;
RtlZeroMemory(AddressMapping, sizeof(VIDEO_PORT_ADDRESS_MAPPING));
AddressMapping->NumberOfUchars = NumberOfUchars; AddressMapping->NumberOfUchars = NumberOfUchars;
AddressMapping->IoAddress = IoAddress; AddressMapping->IoAddress = IoAddress;
AddressMapping->SystemIoBusNumber = DeviceExtension->SystemIoBusNumber; AddressMapping->SystemIoBusNumber = DeviceExtension->SystemIoBusNumber;
AddressMapping->MappingCount = 1; }
InsertHeadList( if ((InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) != 0)
&DeviceExtension->AddressMappingListHead, {
&AddressMapping->List); AddressMapping->MappedUserAddress = MappedAddress;
AddressMapping->UserMappingCount = 1;
return MappedAddress;
} }
else else
{ {
AddressMapping->MappedAddress = MappedAddress;
AddressMapping->MappingCount = 1;
}
if (InsertIntoList)
{
InsertHeadList(
&DeviceExtension->AddressMappingListHead,
&AddressMapping->List);
}
return MappedAddress;
}
if (Status) if (Status)
*Status = NO_ERROR; *Status = NO_ERROR;
return NULL; return NULL;
} }
}
VOID STDCALL VOID STDCALL
IntVideoPortUnmapMemory( IntVideoPortUnmapMemory(
@ -152,21 +231,41 @@ IntVideoPortUnmapMemory(
Entry, Entry,
VIDEO_PORT_ADDRESS_MAPPING, VIDEO_PORT_ADDRESS_MAPPING,
List); List);
if (AddressMapping->MappedAddress == MappedAddress) if (AddressMapping->MappedUserAddress == MappedAddress)
{ {
ASSERT(AddressMapping->MappingCount >= 0); ASSERT(AddressMapping->UserMappingCount > 0);
AddressMapping->UserMappingCount--;
if (AddressMapping->UserMappingCount == 0)
{
ZwUnmapViewOfSection(NtCurrentProcess(),
AddressMapping->MappedUserAddress);
AddressMapping->MappedUserAddress = NULL;
if (AddressMapping->MappingCount == 0)
{
RemoveEntryList(Entry);
ExFreePool(AddressMapping);
}
}
return;
}
else if (AddressMapping->MappedAddress == MappedAddress)
{
ASSERT(AddressMapping->MappingCount > 0);
AddressMapping->MappingCount--; AddressMapping->MappingCount--;
if (AddressMapping->MappingCount == 0) if (AddressMapping->MappingCount == 0)
{ {
MmUnmapIoSpace( MmUnmapIoSpace(
AddressMapping->MappedAddress, AddressMapping->MappedAddress,
AddressMapping->NumberOfUchars); AddressMapping->NumberOfUchars);
AddressMapping->MappedAddress = NULL;
if (AddressMapping->UserMappingCount == 0)
{
RemoveEntryList(Entry); RemoveEntryList(Entry);
ExFreePool(AddressMapping); ExFreePool(AddressMapping);
return;
} }
} }
return;
}
Entry = Entry->Flink; Entry = Entry->Flink;
} }

View file

@ -18,7 +18,7 @@
* If not, write to the Free Software Foundation, * If not, write to the Free Software Foundation,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* *
* $Id: videoprt.h,v 1.11 2004/10/23 23:43:23 ion Exp $ * $Id: videoprt.h,v 1.12 2004/12/18 22:14:39 blight Exp $
*/ */
#ifndef VIDEOPRT_H #ifndef VIDEOPRT_H
@ -51,10 +51,12 @@ typedef struct _VIDEO_PORT_ADDRESS_MAPPING
{ {
LIST_ENTRY List; LIST_ENTRY List;
PVOID MappedAddress; PVOID MappedAddress;
PVOID MappedUserAddress;
ULONG NumberOfUchars; ULONG NumberOfUchars;
PHYSICAL_ADDRESS IoAddress; PHYSICAL_ADDRESS IoAddress;
ULONG SystemIoBusNumber; ULONG SystemIoBusNumber;
UINT MappingCount; UINT MappingCount;
UINT UserMappingCount;
} VIDEO_PORT_ADDRESS_MAPPING, *PVIDEO_PORT_ADDRESS_MAPPING; } VIDEO_PORT_ADDRESS_MAPPING, *PVIDEO_PORT_ADDRESS_MAPPING;
typedef struct _VIDEO_PORT_DRIVER_EXTENSION typedef struct _VIDEO_PORT_DRIVER_EXTENSION