[USBEHCI]

- Re-implement DMA buffer routines. It is now faster and consumes less memory overhead per allocated memory block.
- IoGetDeviceProperty needs a PDO
- Add few comments
- No need to clear buffer twice in CreateQueueHead / CreateDescriptor




svn path=/branches/cmake-bringup/; revision=51324
This commit is contained in:
Johannes Anderwald 2011-04-13 01:37:14 +00:00
parent f3ddbe5d71
commit 2e8b524c99
8 changed files with 318 additions and 130 deletions

View file

@ -69,7 +69,7 @@ EhciDefferedRoutine(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVO
{
CompletedTD = NextTD;
NextTD = NextTD->NextDescriptor;
FreeDescriptor(CompletedTD);
FreeDescriptor(hcd, CompletedTD);
}
/* If the Event is set then release waiter */
@ -136,7 +136,7 @@ EhciDefferedRoutine(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVO
/* Unlink QueueHead */
UnlinkQueueHead(hcd, CompletedQH);
/* Wait for a complete AsnycList tranversal before deleting? */
DeleteQueueHead(CompletedQH);
DeleteQueueHead(hcd, CompletedQH);
}
/* Port Change */
@ -279,7 +279,7 @@ StartDevice(PDEVICE_OBJECT DeviceObject, PCM_PARTIAL_RESOURCE_LIST raw, PCM_PART
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
Status = IoGetDeviceProperty(FdoDeviceExtension->LowerDevice,
Status = IoGetDeviceProperty(FdoDeviceExtension->Pdo,
DevicePropertyAddress,
sizeof(ULONG),
&DeviceAddress,
@ -289,7 +289,7 @@ StartDevice(PDEVICE_OBJECT DeviceObject, PCM_PARTIAL_RESOURCE_LIST raw, PCM_PART
DPRINT1("--->DeviceAddress: %x\n", DeviceAddress);
}
Status = IoGetDeviceProperty(FdoDeviceExtension->LowerDevice,
Status = IoGetDeviceProperty(FdoDeviceExtension->Pdo,
DevicePropertyBusNumber,
sizeof(ULONG),
&BusNumber,
@ -364,6 +364,7 @@ StartDevice(PDEVICE_OBJECT DeviceObject, PCM_PARTIAL_RESOURCE_LIST raw, PCM_PART
}
}
/* initialize dpc */
KeInitializeDpc(&FdoDeviceExtension->DpcObject,
EhciDefferedRoutine,
FdoDeviceExtension);
@ -377,7 +378,7 @@ StartDevice(PDEVICE_OBJECT DeviceObject, PCM_PARTIAL_RESOURCE_LIST raw, PCM_PART
DeviceDescription.InterfaceType = PCIBus;
DeviceDescription.MaximumLength = EHCI_MAX_SIZE_TRANSFER;
FdoDeviceExtension->pDmaAdapter = IoGetDmaAdapter(FdoDeviceExtension->LowerDevice,
FdoDeviceExtension->pDmaAdapter = IoGetDmaAdapter(FdoDeviceExtension->Pdo,
&DeviceDescription,
&FdoDeviceExtension->MapRegisters);
@ -416,14 +417,33 @@ StartDevice(PDEVICE_OBJECT DeviceObject, PCM_PARTIAL_RESOURCE_LIST raw, PCM_PART
return STATUS_UNSUCCESSFUL;
}
/* Init SpinLock for host controller device lock */
KeInitializeSpinLock(&FdoDeviceExtension->hcd.Lock);
FdoDeviceExtension->hcd.CommonBufferSize = PAGE_SIZE * 16;
/* Zeroize it */
RtlZeroMemory(FdoDeviceExtension->hcd.CommonBufferVA,
PAGE_SIZE * 16);
/* Init SpinLock for host controller device lock */
KeInitializeSpinLock(&FdoDeviceExtension->hcd.Lock);
/* create memory allocator */
Status = DmaMemAllocator_Create(&FdoDeviceExtension->hcd.DmaMemAllocator);
if (FdoDeviceExtension->hcd.DmaMemAllocator == 0)
{
/* FIXME cleanup */
DPRINT1("Ehci: Failed to create dma memory allocator!\n");
return STATUS_UNSUCCESSFUL;
}
/* initialize memory allocator */
Status = DmaMemAllocator_Initialize(FdoDeviceExtension->hcd.DmaMemAllocator, 32, &FdoDeviceExtension->hcd.Lock, FdoDeviceExtension->hcd.CommonBufferPA, FdoDeviceExtension->hcd.CommonBufferVA, FdoDeviceExtension->hcd.CommonBufferSize);
if (!NT_SUCCESS(Status))
{
/* FIXME cleanup */
DPRINT1("Ehci: Failed to initialize dma memory allocator %x\n", Status);
return Status;
}
/* Reserved a Queue Head that will always be in the AsyncList Address Register */
FdoDeviceExtension->hcd.AsyncListQueue = CreateQueueHead(&FdoDeviceExtension->hcd);
@ -436,7 +456,7 @@ StartDevice(PDEVICE_OBJECT DeviceObject, PCM_PARTIAL_RESOURCE_LIST raw, PCM_PART
Status = IoConnectInterrupt(&FdoDeviceExtension->EhciInterrupt,
InterruptService,
FdoDeviceExtension->DeviceObject,
DeviceObject,
NULL,
FdoDeviceExtension->Vector,
FdoDeviceExtension->Irql,
@ -621,7 +641,7 @@ FdoDispatchPnp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
}
NTSTATUS NTAPI
AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT Pdo)
AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PhysicalDeviceObject)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PDEVICE_OBJECT Fdo;
@ -673,6 +693,7 @@ AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT Pdo)
}
}
/* FIXME */
swprintf(CharSymLinkName, L"\\Device\\HCD%d", UsbDeviceNumber);
RtlInitUnicodeString(&SymLinkName, CharSymLinkName);
Status = IoCreateSymbolicLink(&SymLinkName, &DeviceName);
@ -683,15 +704,19 @@ AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT Pdo)
}
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION) Fdo->DeviceExtension;
RtlZeroMemory(FdoDeviceExtension, sizeof(PFDO_DEVICE_EXTENSION));
RtlZeroMemory(FdoDeviceExtension, sizeof(FDO_DEVICE_EXTENSION));
/* initialize timer */
KeInitializeTimerEx(&FdoDeviceExtension->UpdateTimer, SynchronizationTimer);
/* initialize device extension */
FdoDeviceExtension->Common.IsFdo = TRUE;
FdoDeviceExtension->DeviceObject = Fdo;
FdoDeviceExtension->LowerDevice = IoAttachDeviceToDeviceStack(Fdo, Pdo);
FdoDeviceExtension->Common.DriverObject = DriverObject;
FdoDeviceExtension->Common.DeviceObject = Fdo;
FdoDeviceExtension->Pdo = PhysicalDeviceObject;
/* attach to device stack */
FdoDeviceExtension->LowerDevice = IoAttachDeviceToDeviceStack(Fdo, PhysicalDeviceObject);
if (FdoDeviceExtension->LowerDevice == NULL)
{
DPRINT1("UsbEhci: Failed to attach to device stack!\n");
@ -701,12 +726,13 @@ AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT Pdo)
return STATUS_NO_SUCH_DEVICE;
}
Fdo->Flags |= DO_BUFFERED_IO;// | DO_POWER_PAGABLE;
/* setup device flags */
Fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
ASSERT(FdoDeviceExtension->LowerDevice == Pdo);
Status = GetBusInterface(FdoDeviceExtension->LowerDevice, &FdoDeviceExtension->BusInterface);
/* get bus interface */
Status = GetBusInterface(PhysicalDeviceObject, &FdoDeviceExtension->BusInterface);
/* check for success */
if (!NT_SUCCESS(Status))
{
DPRINT1("GetBusInterface() failed with %x\n", Status);
@ -716,6 +742,7 @@ AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT Pdo)
return Status;
}
/* read pci config space */
BytesRead = (*FdoDeviceExtension->BusInterface.GetBusData)(
FdoDeviceExtension->BusInterface.Context,
PCI_WHICHSPACE_CONFIG,
@ -723,7 +750,7 @@ AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT Pdo)
0,
PCI_COMMON_HDR_LENGTH);
/* check for success */
if (BytesRead != PCI_COMMON_HDR_LENGTH)
{
DPRINT1("GetBusData failed!\n");
@ -746,12 +773,16 @@ AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT Pdo)
DPRINT1("Vendor %x\n", PciConfig.VendorID);
DPRINT1("Device %x\n", PciConfig.DeviceID);
FdoDeviceExtension->VendorId = PciConfig.VendorID;
FdoDeviceExtension->DeviceId = PciConfig.DeviceID;
/* update state */
FdoDeviceExtension->DeviceState = DEVICEINTIALIZED;
Status = IoRegisterDeviceInterface(Pdo, &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL, &InterfaceSymLinkName);
/* FIXME: delay this until IRP_MN_START arrives */
Status = IoRegisterDeviceInterface(PhysicalDeviceObject, &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL, &InterfaceSymLinkName);
if (!NT_SUCCESS(Status))
{
DPRINT1("Unable to register device interface!\n");
@ -759,11 +790,14 @@ AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT Pdo)
}
else
{
/* enable device interface */
Status = IoSetDeviceInterfaceState(&InterfaceSymLinkName, TRUE);
DPRINT1("SetInterfaceState %x\n", Status);
if (!NT_SUCCESS(Status))
return Status;
}
/* device is initialized */
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
@ -782,6 +816,9 @@ FdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
/*FIXME: This should never be called by upper drivers as they should only be dealing with the pdo */
ASSERT(0);
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION) FdoDeviceExtension->Pdo->DeviceExtension;

View file

@ -264,6 +264,18 @@ typedef struct _EHCI_CAPS {
UCHAR PortRoute [8];
} EHCI_CAPS, *PEHCI_CAPS;
typedef struct
{
PKSPIN_LOCK Lock;
RTL_BITMAP Bitmap;
PULONG BitmapBuffer;
ULONG BlockSize;
PVOID VirtualBase;
PHYSICAL_ADDRESS PhysicalBase;
ULONG Length;
}DMA_MEMORY_ALLOCATOR, *LPDMA_MEMORY_ALLOCATOR;
typedef struct _EHCI_HOST_CONTROLLER
{
ULONG OpRegisters;
@ -273,6 +285,7 @@ typedef struct _EHCI_HOST_CONTROLLER
ULONG CommonBufferSize;
PQUEUE_HEAD AsyncListQueue;
KSPIN_LOCK Lock;
LPDMA_MEMORY_ALLOCATOR DmaMemAllocator;
} EHCI_HOST_CONTROLLER, *PEHCI_HOST_CONTROLLER;
ULONG

View file

@ -18,16 +18,20 @@
/* Queue Element Transfer Descriptors */
PQUEUE_TRANSFER_DESCRIPTOR
CreateDescriptor(PEHCI_HOST_CONTROLLER hcd, UCHAR PIDCode, ULONG TotalBytesToTransfer)
CreateDescriptor(
PEHCI_HOST_CONTROLLER hcd,
UCHAR PIDCode,
ULONG TotalBytesToTransfer)
{
PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
ULONG PhysicalAddress;
UCHAR i;
KIRQL OldIrql;
NTSTATUS Status;
KeAcquireSpinLock(&hcd->Lock, &OldIrql);
Status = DmaMemAllocator_Allocate(hcd->DmaMemAllocator, sizeof(QUEUE_TRANSFER_DESCRIPTOR), (PVOID*)&Descriptor, &PhysicalAddress);
if (!NT_SUCCESS(Status))
return NULL;
Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)AllocateMemory(hcd, sizeof(QUEUE_TRANSFER_DESCRIPTOR), &PhysicalAddress);
RtlZeroMemory(Descriptor, sizeof(QUEUE_TRANSFER_DESCRIPTOR));
Descriptor->NextPointer = TERMINATE_POINTER;
Descriptor->AlternateNextPointer = TERMINATE_POINTER;
@ -38,18 +42,16 @@ CreateDescriptor(PEHCI_HOST_CONTROLLER hcd, UCHAR PIDCode, ULONG TotalBytesToTra
Descriptor->Token.Bits.PIDCode = PIDCode;
Descriptor->Token.Bits.TotalBytesToTransfer = TotalBytesToTransfer;
Descriptor->PhysicalAddr = PhysicalAddress;
for (i=0;i<5;i++)
Descriptor->BufferPointer[i] = 0;
KeReleaseSpinLock(&hcd->Lock, OldIrql);
return Descriptor;
}
VOID
FreeDescriptor(PQUEUE_TRANSFER_DESCRIPTOR Descriptor)
FreeDescriptor(
PEHCI_HOST_CONTROLLER hcd,
PQUEUE_TRANSFER_DESCRIPTOR Descriptor)
{
ReleaseMemory((ULONG)Descriptor);
DmaMemAllocator_Free(hcd->DmaMemAllocator, Descriptor, sizeof(QUEUE_TRANSFER_DESCRIPTOR));
}
/* Queue Head */
@ -84,16 +86,17 @@ PQUEUE_HEAD
CreateQueueHead(PEHCI_HOST_CONTROLLER hcd)
{
PQUEUE_HEAD CurrentQH;
ULONG PhysicalAddress , i;
KIRQL OldIrql;
NTSTATUS Status;
PHYSICAL_ADDRESS PhysicalAddress;
KeAcquireSpinLock(&hcd->Lock, &OldIrql);
Status = DmaMemAllocator_Allocate(hcd->DmaMemAllocator, sizeof(QUEUE_HEAD), (PVOID*)&CurrentQH, &PhysicalAddress);
if (!NT_SUCCESS(Status))
return NULL;
CurrentQH = (PQUEUE_HEAD)AllocateMemory(hcd, sizeof(QUEUE_HEAD), &PhysicalAddress);
RtlZeroMemory(CurrentQH, sizeof(QUEUE_HEAD));
ASSERT(CurrentQH);
CurrentQH->PhysicalAddr = PhysicalAddress;
CurrentQH->PhysicalAddr = PhysicalAddress.LowPart;
CurrentQH->HorizontalLinkPointer = TERMINATE_POINTER;
CurrentQH->CurrentLinkPointer = TERMINATE_POINTER;
CurrentQH->AlternateNextPointer = TERMINATE_POINTER;
@ -118,12 +121,9 @@ CreateQueueHead(PEHCI_HOST_CONTROLLER hcd)
CurrentQH->Token.DWord = 0;
CurrentQH->NextQueueHead = NULL;
CurrentQH->PreviousQueueHead = NULL;
for (i=0; i<5; i++)
CurrentQH->BufferPointer[i] = 0;
CurrentQH->Token.Bits.InterruptOnComplete = TRUE;
KeReleaseSpinLock(&hcd->Lock, OldIrql);
return CurrentQH;
}
@ -169,8 +169,10 @@ UnlinkQueueHead(PEHCI_HOST_CONTROLLER hcd, PQUEUE_HEAD QueueHead)
}
VOID
DeleteQueueHead(PQUEUE_HEAD QueueHead)
DeleteQueueHead(
PEHCI_HOST_CONTROLLER hcd,
PQUEUE_HEAD QueueHead)
{
ReleaseMemory((ULONG)QueueHead);
DmaMemAllocator_Free(hcd->DmaMemAllocator, QueueHead, sizeof(QUEUE_HEAD));
}

View file

@ -5,7 +5,7 @@ PQUEUE_TRANSFER_DESCRIPTOR
CreateDescriptor(PEHCI_HOST_CONTROLLER hcd, UCHAR PIDCode, ULONG TotalBytesToTransfer);
VOID
FreeDescriptor(PQUEUE_TRANSFER_DESCRIPTOR Descriptor);
FreeDescriptor(PEHCI_HOST_CONTROLLER hcd, PQUEUE_TRANSFER_DESCRIPTOR Descriptor);
VOID
DumpQueueHeadList(PEHCI_HOST_CONTROLLER hcd);
@ -20,5 +20,5 @@ VOID
UnlinkQueueHead(PEHCI_HOST_CONTROLLER hcd, PQUEUE_HEAD QueueHead);
VOID
DeleteQueueHead(PQUEUE_HEAD QueueHead);
DeleteQueueHead(PEHCI_HOST_CONTROLLER hcd, PQUEUE_HEAD QueueHead);

View file

@ -10,89 +10,207 @@
#include "physmem.h"
#include "debug.h"
#define SMALL_ALLOCATION_SIZE 32
VOID
DumpPages()
NTAPI
DmaMemAllocator_Destroy(
IN LPDMA_MEMORY_ALLOCATOR Allocator)
{
//PMEM_HEADER MemBlock = (PMEM_HEADER)EhciSharedMemory.VirtualAddr;
/* is there a bitmap buffer */
if (Allocator->BitmapBuffer)
{
/* free bitmap buffer */
ExFreePool(Allocator->BitmapBuffer);
}
/* free struct */
ExFreePool(Allocator);
}
// Returns Virtual Address of Allocated Memory
ULONG
AllocateMemory(PEHCI_HOST_CONTROLLER hcd, ULONG Size, ULONG *PhysicalAddress)
NTSTATUS
NTAPI
DmaMemAllocator_Create(
IN LPDMA_MEMORY_ALLOCATOR *OutMemoryAllocator)
{
PMEM_HEADER MemoryPage = (PMEM_HEADER)hcd->CommonBufferVA;
ULONG PageCount = 0;
ULONG NumberOfPages = hcd->CommonBufferSize / PAGE_SIZE;
ULONG BlocksNeeded;
ULONG i,j, freeCount;
ULONG RetAddr = 0;
LPDMA_MEMORY_ALLOCATOR Allocator;
Size = ((Size + SMALL_ALLOCATION_SIZE - 1) / SMALL_ALLOCATION_SIZE) * SMALL_ALLOCATION_SIZE;
BlocksNeeded = Size / SMALL_ALLOCATION_SIZE;
/* sanity check */
ASSERT(OutMemoryAllocator);
/* allocate struct - must be non paged as it contains a spin lock */
Allocator = ExAllocatePool(NonPagedPool, sizeof(DMA_MEMORY_ALLOCATOR));
if (!Allocator)
{
/* no memory */
return STATUS_INSUFFICIENT_RESOURCES;
}
/* zero struct */
RtlZeroMemory(Allocator, sizeof(DMA_MEMORY_ALLOCATOR));
/* store result */
*OutMemoryAllocator = Allocator;
/* done */
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
DmaMemAllocator_Initialize(
IN OUT LPDMA_MEMORY_ALLOCATOR Allocator,
IN ULONG DefaultBlockSize,
IN PKSPIN_LOCK Lock,
IN PHYSICAL_ADDRESS PhysicalBase,
IN PVOID VirtualBase,
IN ULONG Length)
{
PULONG BitmapBuffer;
ULONG BitmapLength;
/* sanity checks */
ASSERT(Length >= PAGE_SIZE);
ASSERT(Length % PAGE_SIZE == 0);
ASSERT(DefaultBlockSize == 32 || DefaultBlockSize == 64 || DefaultBlockSize == 128);
/* calculate bitmap length */
BitmapLength = (Length / DefaultBlockSize) / sizeof(ULONG);
/* allocate bitmap buffer from nonpaged pool */
BitmapBuffer = ExAllocatePool(NonPagedPool, BitmapLength);
if (!BitmapBuffer)
{
/* out of memory */
return STATUS_INSUFFICIENT_RESOURCES;
}
/* initialize bitmap */
RtlInitializeBitMap(&Allocator->Bitmap, BitmapBuffer, BitmapLength);
RtlClearAllBits(&Allocator->Bitmap);
/* initialize rest of allocator */
Allocator->PhysicalBase = PhysicalBase;
Allocator->VirtualBase = VirtualBase;
Allocator->Length = Length;
Allocator->BitmapBuffer = BitmapBuffer;
Allocator->Lock = Lock;
Allocator->BlockSize = DefaultBlockSize;
/* done */
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
DmaMemAllocator_Allocate(
IN LPDMA_MEMORY_ALLOCATOR Allocator,
IN ULONG Size,
OUT PVOID *OutVirtualAddress,
OUT PPHYSICAL_ADDRESS OutPhysicalAddress)
{
ULONG Length, BlockCount, FreeIndex, StartPage, EndPage;
KIRQL OldLevel;
/* sanity check */
ASSERT(Size < PAGE_SIZE);
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
/* align request size to block size */
Length = (Size + Allocator->BlockSize -1) & ~(Allocator->BlockSize -1);
/* sanity check */
ASSERT(Length);
/* convert to block count */
BlockCount = Length / Allocator->BlockSize;
/* acquire lock */
KeAcquireSpinLock(Allocator->Lock, &OldLevel);
/* start search */
FreeIndex = 0;
do
{
if (MemoryPage->IsFull)
/* search for an free index */
FreeIndex = RtlFindClearBits(&Allocator->Bitmap, BlockCount, FreeIndex);
/* check if there were bits found */
if (FreeIndex == MAXULONG)
break;
/* check that the allocation does not spawn over page boundaries */
StartPage = (FreeIndex * Allocator->BlockSize);
StartPage = (StartPage != 0 ? StartPage / PAGE_SIZE : 0);
EndPage = ((FreeIndex + BlockCount) * Allocator->BlockSize) / PAGE_SIZE;
if (StartPage == EndPage)
{
PageCount++;
MemoryPage = (PMEM_HEADER)((ULONG)MemoryPage + PAGE_SIZE);
continue;
/* reserve bits */
RtlSetBits(&Allocator->Bitmap, FreeIndex, BlockCount);
/* done */
break;
}
freeCount = 0;
for (i = 0; i < sizeof(MemoryPage->Entry); i++)
else
{
if (!MemoryPage->Entry[i].InUse)
{
freeCount++;
}
else
{
freeCount = 0;
}
if ((i-freeCount+1 + BlocksNeeded) > sizeof(MemoryPage->Entry))
{
freeCount = 0;
continue;
}
if (freeCount == BlocksNeeded)
{
for (j = 0; j < freeCount; j++)
{
MemoryPage->Entry[i-j].InUse = 1;
MemoryPage->Entry[i-j].Blocks = 0;
}
MemoryPage->Entry[i-freeCount + 1].Blocks = BlocksNeeded;
RetAddr = (ULONG)MemoryPage + (SMALL_ALLOCATION_SIZE * (i - freeCount + 1)) + sizeof(MEM_HEADER);
*PhysicalAddress = (ULONG)hcd->CommonBufferPA.LowPart + (RetAddr - (ULONG)hcd->CommonBufferVA);
return RetAddr;
}
/* request spaws a page boundary */
FreeIndex++;
}
}
while(TRUE);
PageCount++;
MemoryPage = (PMEM_HEADER)((ULONG)MemoryPage + PAGE_SIZE);
} while (PageCount < NumberOfPages);
/* release bitmap lock */
KeReleaseSpinLock(Allocator->Lock, OldLevel);
return 0;
/* check if allocation failed */
if (FreeIndex == MAXULONG)
{
/* allocation failed */
return STATUS_UNSUCCESSFUL;
}
/* return result */
*OutVirtualAddress = (PVOID)((ULONG_PTR)Allocator->VirtualBase + FreeIndex * Allocator->BlockSize);
OutPhysicalAddress->QuadPart = Allocator->PhysicalBase.QuadPart + FreeIndex * Allocator->BlockSize;
/* done */
return STATUS_SUCCESS;
}
VOID
ReleaseMemory(ULONG Address)
NTAPI
DmaMemAllocator_Free(
IN LPDMA_MEMORY_ALLOCATOR Allocator,
IN OPTIONAL PVOID VirtualAddress,
IN ULONG Size)
{
PMEM_HEADER MemoryPage;
ULONG Index, i, BlockSize;
KIRQL OldLevel;
ULONG BlockOffset = 0, BlockLength;
MemoryPage = (PMEM_HEADER)(Address & ~(PAGE_SIZE - 1));
/* sanity check */
ASSERT(VirtualAddress);
Index = (Address - ((ULONG)MemoryPage + sizeof(MEM_HEADER))) / SMALL_ALLOCATION_SIZE;
BlockSize = MemoryPage->Entry[Index].Blocks;
for (i = 0; i < BlockSize; i++)
/* calculate block length */
BlockLength = ((ULONG_PTR)VirtualAddress - (ULONG_PTR)Allocator->VirtualBase);
/* is block offset zero */
if (BlockLength)
{
MemoryPage->Entry[Index + i].InUse = 0;
MemoryPage->Entry[Index + i].Blocks = 0;
/* divide by base block size */
BlockOffset = BlockLength / Allocator->BlockSize;
}
/* align size to base block */
Size = (Size + Allocator->BlockSize - 1) & ~(Allocator->BlockSize - 1);
/* acquire bitmap lock */
KeAcquireSpinLock(Allocator->Lock, &OldLevel);
/* clear bits */
RtlClearBits(&Allocator->Bitmap, BlockOffset, Size);
/* release bitmap lock */
KeReleaseSpinLock(Allocator->Lock, OldLevel);
}

View file

@ -2,25 +2,42 @@
#include "hardware.h"
typedef struct _MEM_ENTRY
{
UCHAR InUse:1;
UCHAR Blocks:7;
} MEM_ENTRY, *PMEM_ENTRY;
typedef struct _MEM_HEADER
{
UCHAR IsFull;
MEM_ENTRY Entry[124];
UCHAR Reserved[3];
} MEM_HEADER, *PMEM_HEADER;
/* destroys memory allocator */
VOID
DumpPages(VOID);
NTAPI
DmaMemAllocator_Destroy(
IN LPDMA_MEMORY_ALLOCATOR Allocator);
ULONG
AllocateMemory(PEHCI_HOST_CONTROLLER hcd, ULONG Size, ULONG *PhysicalAddress);
/* create memory allocator */
NTSTATUS
NTAPI
DmaMemAllocator_Create(
IN LPDMA_MEMORY_ALLOCATOR *OutMemoryAllocator);
/* initializes memory allocator */
NTSTATUS
NTAPI
DmaMemAllocator_Initialize(
IN OUT LPDMA_MEMORY_ALLOCATOR Allocator,
IN ULONG DefaultBlockSize,
IN PKSPIN_LOCK Lock,
IN PHYSICAL_ADDRESS PhysicalBase,
IN PVOID VirtualBase,
IN ULONG Length);
/* allocates memory from allocator */
NTSTATUS
NTAPI
DmaMemAllocator_Allocate(
IN LPDMA_MEMORY_ALLOCATOR Allocator,
IN ULONG Size,
OUT PVOID *OutVirtualAddress,
OUT PPHYSICAL_ADDRESS OutPhysicalAddress);
/* frees memory block from allocator */
VOID
ReleaseMemory(ULONG Address);
NTAPI
DmaMemAllocator_Free(
IN LPDMA_MEMORY_ALLOCATOR Allocator,
IN PVOID VirtualAddress,
IN ULONG Size);

View file

@ -143,11 +143,13 @@ SubmitControlTransfer(PEHCI_HOST_CONTROLLER hcd,
ULONG MdlPhysicalAddr;
PKEVENT Event = NULL;
PMDL pMdl = NULL;
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetupVA, CtrlPhysicalPA;
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetupVA;
NTSTATUS Status;
PHYSICAL_ADDRESS PhysicalAddress;
CtrlSetupVA = (PUSB_DEFAULT_PIPE_SETUP_PACKET)AllocateMemory(hcd,
sizeof(USB_DEFAULT_PIPE_SETUP_PACKET),
(ULONG*)&CtrlPhysicalPA);
/* allocate memory */
Status = DmaMemAllocator_Allocate(hcd->DmaMemAllocator, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET), (PVOID*)&CtrlSetupVA, &PhysicalAddress);
ASSERT(Status == STATUS_SUCCESS);
RtlCopyMemory(CtrlSetupVA, CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
/* If no Irp then wait on completion */
@ -214,7 +216,7 @@ SubmitControlTransfer(PEHCI_HOST_CONTROLLER hcd,
}
/* Assign the descritors buffers */
Descriptor[0]->BufferPointer[0] = (ULONG)CtrlPhysicalPA;
Descriptor[0]->BufferPointer[0] = PhysicalAddress.LowPart;
if (TransferBuffer)
{

View file

@ -104,8 +104,7 @@ typedef struct _EHCIPORTS
typedef struct _FDO_DEVICE_EXTENSION
{
COMMON_DEVICE_EXTENSION Common;
PDRIVER_OBJECT DriverObject;
PDEVICE_OBJECT DeviceObject;
PDEVICE_OBJECT LowerDevice;
PDEVICE_OBJECT Pdo;
ULONG DeviceState;