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;
@ -62,17 +62,32 @@ IntVideoPortMapMemory(
if (IoAddress.QuadPart == AddressMapping->IoAddress.QuadPart && if (IoAddress.QuadPart == AddressMapping->IoAddress.QuadPart &&
NumberOfUchars <= AddressMapping->NumberOfUchars) NumberOfUchars <= AddressMapping->NumberOfUchars)
{ {
AddressMapping->MappingCount++; if ((InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) != 0 &&
if (Status) AddressMapping->MappedUserAddress != NULL)
*Status = NO_ERROR; {
AddressMapping->UserMappingCount++;
return AddressMapping->MappedAddress; if (Status)
*Status = NO_ERROR;
return AddressMapping->MappedUserAddress;
}
else if ((InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) == 0 &&
AddressMapping->MappedUserAddress != NULL)
{
AddressMapping->MappingCount++;
if (Status)
*Status = NO_ERROR;
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,45 +111,109 @@ IntVideoPortMapMemory(
return (PVOID)TranslatedAddress.u.LowPart; return (PVOID)TranslatedAddress.u.LowPart;
} }
MappedAddress = MmMapIoSpace( /* user space */
TranslatedAddress, if ((InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) != 0)
NumberOfUchars,
MmNonCached);
if (MappedAddress)
{ {
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(
TranslatedAddress,
NumberOfUchars,
MmNonCached);
}
if (MappedAddress != NULL)
{
BOOL InsertIntoList = FALSE;
if (Status) if (Status)
{ {
*Status = NO_ERROR; *Status = NO_ERROR;
} }
AddressMapping = ExAllocatePoolWithTag(
PagedPool,
sizeof(VIDEO_PORT_ADDRESS_MAPPING),
TAG_VIDEO_PORT);
if (AddressMapping == NULL) if (AddressMapping == NULL)
return MappedAddress; {
AddressMapping = ExAllocatePoolWithTag(
PagedPool,
sizeof(VIDEO_PORT_ADDRESS_MAPPING),
TAG_VIDEO_PORT);
AddressMapping->MappedAddress = MappedAddress; if (AddressMapping == NULL)
AddressMapping->NumberOfUchars = NumberOfUchars; return MappedAddress;
AddressMapping->IoAddress = IoAddress;
AddressMapping->SystemIoBusNumber = DeviceExtension->SystemIoBusNumber;
AddressMapping->MappingCount = 1;
InsertHeadList( InsertIntoList = TRUE;
&DeviceExtension->AddressMappingListHead, RtlZeroMemory(AddressMapping, sizeof(VIDEO_PORT_ADDRESS_MAPPING));
&AddressMapping->List); AddressMapping->NumberOfUchars = NumberOfUchars;
AddressMapping->IoAddress = IoAddress;
AddressMapping->SystemIoBusNumber = DeviceExtension->SystemIoBusNumber;
}
if ((InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) != 0)
{
AddressMapping->MappedUserAddress = MappedAddress;
AddressMapping->UserMappingCount = 1;
}
else
{
AddressMapping->MappedAddress = MappedAddress;
AddressMapping->MappingCount = 1;
}
if (InsertIntoList)
{
InsertHeadList(
&DeviceExtension->AddressMappingListHead,
&AddressMapping->List);
}
return MappedAddress; return MappedAddress;
} }
else
{
if (Status)
*Status = NO_ERROR;
return NULL; if (Status)
} *Status = NO_ERROR;
return NULL;
} }
VOID STDCALL VOID STDCALL
@ -152,20 +231,40 @@ 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);
RemoveEntryList(Entry); AddressMapping->MappedAddress = NULL;
ExFreePool(AddressMapping); if (AddressMapping->UserMappingCount == 0)
{
return; RemoveEntryList(Entry);
ExFreePool(AddressMapping);
}
} }
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