From 84409cef86f71d5a9d620b37cfe2940357d9d11b Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Mon, 24 Oct 2011 20:38:36 +0000 Subject: [PATCH] [NDIS] - Implement NdisMSetupDmaTransfer, NdisMCompleteDmaTransfer, NdisSetupDmaTransfer, NdisCompleteDmaTransfer, and NdisAllocateDmaChannel svn path=/trunk/; revision=54251 --- reactos/drivers/network/ndis/ndis/30stubs.c | 32 ---- reactos/drivers/network/ndis/ndis/40stubs.c | 23 --- reactos/drivers/network/ndis/ndis/io.c | 190 ++++++++++++++++++-- 3 files changed, 175 insertions(+), 70 deletions(-) diff --git a/reactos/drivers/network/ndis/ndis/30stubs.c b/reactos/drivers/network/ndis/ndis/30stubs.c index d217ec4008d..f7091f3d7e1 100644 --- a/reactos/drivers/network/ndis/ndis/30stubs.c +++ b/reactos/drivers/network/ndis/ndis/30stubs.c @@ -11,23 +11,6 @@ #include "ndissys.h" -/* - * @unimplemented - */ -VOID -EXPORT -NdisCompleteDmaTransfer( - OUT PNDIS_STATUS Status, - IN PNDIS_HANDLE NdisDmaHandle, - IN PNDIS_BUFFER Buffer, - IN ULONG Offset, - IN ULONG Length, - IN BOOLEAN WriteToDevice) -{ - UNIMPLEMENTED -} - - /* * @unimplemented */ @@ -87,21 +70,6 @@ FddiFilterDprIndicateReceiveComplete( } -/* - * @unimplemented - */ -VOID -EXPORT -NdisAllocateDmaChannel( - OUT PNDIS_STATUS Status, - OUT PNDIS_HANDLE NdisDmaHandle, - IN NDIS_HANDLE NdisAdapterHandle, - IN PNDIS_DMA_DESCRIPTION DmaDescription, - IN ULONG MaximumLength) -{ - UNIMPLEMENTED -} - /* * @unimplemented */ diff --git a/reactos/drivers/network/ndis/ndis/40stubs.c b/reactos/drivers/network/ndis/ndis/40stubs.c index 9abea9a4f28..97376a8a700 100644 --- a/reactos/drivers/network/ndis/ndis/40stubs.c +++ b/reactos/drivers/network/ndis/ndis/40stubs.c @@ -241,29 +241,6 @@ NdisReleaseAdapterResources( } -/* - * @unimplemented - */ -VOID -EXPORT -NdisSetupDmaTransfer( - OUT PNDIS_STATUS Status, - IN PNDIS_HANDLE NdisDmaHandle, - IN PNDIS_BUFFER Buffer, - IN ULONG Offset, - IN ULONG Length, - IN BOOLEAN WriteToDevice) -/* - * FUNCTION: - * ARGUMENTS: - * NOTES: - * NDIS 4.0 - */ -{ - UNIMPLEMENTED -} - - /* * @implemented */ diff --git a/reactos/drivers/network/ndis/ndis/io.c b/reactos/drivers/network/ndis/ndis/io.c index a83e24464f5..87b9537ee97 100644 --- a/reactos/drivers/network/ndis/ndis/io.c +++ b/reactos/drivers/network/ndis/ndis/io.c @@ -184,8 +184,36 @@ NdisImmediateWritePortUshort( WRITE_PORT_USHORT(UlongToPtr(Port), Data); // FIXME: What to do with WrapperConfigurationContext? } - -IO_ALLOCATION_ACTION NTAPI NdisMapRegisterCallback ( +IO_ALLOCATION_ACTION NTAPI NdisSubordinateMapRegisterCallback ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID MapRegisterBase, + IN PVOID Context) +/* + * FUNCTION: Called back during reservation of map registers + * ARGUMENTS: + * DeviceObject: Device object of the deivce setting up DMA + * Irp: Reserved; must be ignored + * MapRegisterBase: Map registers assigned for transfer + * Context: LOGICAL_ADAPTER object of the requesting miniport + * NOTES: + * - Called at IRQL = DISPATCH_LEVEL + */ +{ + PNDIS_DMA_BLOCK DmaBlock = Context; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + DmaBlock->MapRegisterBase = MapRegisterBase; + + NDIS_DbgPrint(MAX_TRACE, ("setting event and leaving.\n")); + + KeSetEvent(&DmaBlock->AllocationEvent, 0, FALSE); + + /* We have to hold the object open to keep our lock on the system DMA controller */ + return KeepObject; +} +IO_ALLOCATION_ACTION NTAPI NdisBusMasterMapRegisterCallback ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID MapRegisterBase, @@ -212,11 +240,9 @@ IO_ALLOCATION_ACTION NTAPI NdisMapRegisterCallback ( KeSetEvent(Adapter->NdisMiniportBlock.AllocationEvent, 0, FALSE); - /* this is only the thing to do for busmaster NICs */ + /* We're a bus master so we can go ahead and deallocate the object now */ return DeallocateObjectKeepRegisters; -} - - +} /* * @implemented */ @@ -359,7 +385,7 @@ NdisMAllocateMapRegisters( { NtStatus = AdapterObject->DmaOperations->AllocateAdapterChannel( AdapterObject, DeviceObject, MapRegistersPerBaseRegister, - NdisMapRegisterCallback, Adapter); + NdisBusMasterMapRegisterCallback, Adapter); } KeLowerIrql(OldIrql); @@ -398,7 +424,7 @@ NdisMAllocateMapRegisters( /* - * @unimplemented + * @implemented */ VOID EXPORT @@ -409,12 +435,87 @@ NdisMSetupDmaTransfer(OUT PNDIS_STATUS Status, IN ULONG Length, IN BOOLEAN WriteToDevice) { - UNIMPLEMENTED - *Status = NDIS_STATUS_FAILURE; + PNDIS_DMA_BLOCK DmaBlock = MiniportDmaHandle; + NTSTATUS NtStatus; + PLOGICAL_ADAPTER Adapter; + KIRQL OldIrql; + PDMA_ADAPTER AdapterObject; + ULONG MapRegistersNeeded; + + NDIS_DbgPrint(MAX_TRACE, ("called: Handle 0x%x, Buffer 0x%x, Offset 0x%x, Length 0x%x, WriteToDevice 0x%x\n", + MiniportDmaHandle, Buffer, Offset, Length, WriteToDevice)); + + Adapter = (PLOGICAL_ADAPTER)DmaBlock->Miniport; + AdapterObject = (PDMA_ADAPTER)DmaBlock->SystemAdapterObject; + + MapRegistersNeeded = (Length + (PAGE_SIZE - 1)) / PAGE_SIZE; + + KeFlushIoBuffers(Buffer, !WriteToDevice, TRUE); + + KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); + { + NtStatus = AdapterObject->DmaOperations->AllocateAdapterChannel(AdapterObject, + Adapter->NdisMiniportBlock.PhysicalDeviceObject, + MapRegistersNeeded, + NdisSubordinateMapRegisterCallback, Adapter); + } + KeLowerIrql(OldIrql); + + if(!NT_SUCCESS(NtStatus)) + { + NDIS_DbgPrint(MIN_TRACE, ("AllocateAdapterChannel failed: 0x%x\n", NtStatus)); + AdapterObject->DmaOperations->FreeAdapterChannel(AdapterObject); + *Status = NDIS_STATUS_RESOURCES; + return; + } + + NtStatus = KeWaitForSingleObject(&DmaBlock->AllocationEvent, Executive, KernelMode, FALSE, 0); + + if(!NT_SUCCESS(NtStatus)) + { + NDIS_DbgPrint(MIN_TRACE, ("KeWaitForSingleObject failed: 0x%x\n", NtStatus)); + AdapterObject->DmaOperations->FreeAdapterChannel(AdapterObject); + *Status = NDIS_STATUS_RESOURCES; + return; + } + + /* We must throw away the return value of MapTransfer for a system DMA device */ + AdapterObject->DmaOperations->MapTransfer(AdapterObject, Buffer, + DmaBlock->MapRegisterBase, + (PUCHAR)MmGetMdlVirtualAddress(Buffer) + Offset, &Length, WriteToDevice); + + NDIS_DbgPrint(MAX_TRACE, ("returning success\n")); + *Status = NDIS_STATUS_SUCCESS; } /* - * @unimplemented + * @implemented + */ +VOID +EXPORT +NdisSetupDmaTransfer(OUT PNDIS_STATUS Status, + IN PNDIS_HANDLE NdisDmaHandle, + IN PNDIS_BUFFER Buffer, + IN ULONG Offset, + IN ULONG Length, + IN BOOLEAN WriteToDevice) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + NdisMSetupDmaTransfer(Status, + NdisDmaHandle, + Buffer, + Offset, + Length, + WriteToDevice); +} + +/* + * @implemented */ VOID EXPORT @@ -425,10 +526,50 @@ NdisMCompleteDmaTransfer(OUT PNDIS_STATUS Status, IN ULONG Length, IN BOOLEAN WriteToDevice) { - UNIMPLEMENTED - *Status = NDIS_STATUS_FAILURE; + PNDIS_DMA_BLOCK DmaBlock = MiniportDmaHandle; + PDMA_ADAPTER AdapterObject = (PDMA_ADAPTER)DmaBlock->SystemAdapterObject; + + NDIS_DbgPrint(MAX_TRACE, ("called: Handle 0x%x, Buffer 0x%x, Offset 0x%x, Length 0x%x, WriteToDevice 0x%x\n", + MiniportDmaHandle, Buffer, Offset, Length, WriteToDevice)); + + if (!AdapterObject->DmaOperations->FlushAdapterBuffers(AdapterObject, + Buffer, + DmaBlock->MapRegisterBase, + (PUCHAR)MmGetMdlVirtualAddress(Buffer) + Offset, + Length, + WriteToDevice)) + { + NDIS_DbgPrint(MIN_TRACE, ("FlushAdapterBuffers failed\n")); + *Status = NDIS_STATUS_FAILURE; + return; + } + + AdapterObject->DmaOperations->FreeAdapterChannel(AdapterObject); + + NDIS_DbgPrint(MAX_TRACE, ("returning success\n")); + *Status = NDIS_STATUS_SUCCESS; } - + +/* + * @implemented + */ +VOID +EXPORT +NdisCompleteDmaTransfer(OUT PNDIS_STATUS Status, + IN PNDIS_HANDLE NdisDmaHandle, + IN PNDIS_BUFFER Buffer, + IN ULONG Offset, + IN ULONG Length, + IN BOOLEAN WriteToDevice) +{ + NdisMCompleteDmaTransfer(Status, + NdisDmaHandle, + Buffer, + Offset, + Length, + WriteToDevice); +} + /* * @implemented */ @@ -768,6 +909,8 @@ NdisMRegisterDmaChannel( } Adapter->NdisMiniportBlock.SystemAdapterObject = (PDMA_ADAPTER)DmaBlock->SystemAdapterObject; + + KeInitializeEvent(&DmaBlock->AllocationEvent, NotificationEvent, FALSE); DmaBlock->Miniport = Adapter; @@ -776,7 +919,24 @@ NdisMRegisterDmaChannel( return NDIS_STATUS_SUCCESS; } - +/* + * @implemented + */ +VOID +EXPORT +NdisAllocateDmaChannel(OUT PNDIS_STATUS Status, + OUT PNDIS_HANDLE NdisDmaHandle, + IN NDIS_HANDLE NdisAdapterHandle, + IN PNDIS_DMA_DESCRIPTION DmaDescription, + IN ULONG MaximumLength) +{ + *Status = NdisMRegisterDmaChannel(NdisDmaHandle, + NdisAdapterHandle, + 0, + FALSE, + DmaDescription, + MaximumLength); +} /* * @implemented */