mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 08:05:43 +00:00
[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:
parent
f3ddbe5d71
commit
2e8b524c99
8 changed files with 318 additions and 130 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue