Author: cgutman
Date: Tue Jan 3 17:54:01 2012
New Revision: 54818
URL:
http://svn.reactos.org/svn/reactos?rev=54818&view=rev
Log:
[NDISUIO]
- Implement IOCTL_CANCEL_READ
- Implement IRP_MJ_READ and IRP_MJ_WRITE handling
- Misc fixes
Modified:
branches/wlan-bringup/drivers/network/ndisuio/ioctl.c
branches/wlan-bringup/drivers/network/ndisuio/misc.c
branches/wlan-bringup/drivers/network/ndisuio/ndisuio.h
branches/wlan-bringup/drivers/network/ndisuio/protocol.c
branches/wlan-bringup/drivers/network/ndisuio/readwrite.c
Modified: branches/wlan-bringup/drivers/network/ndisuio/ioctl.c
URL:
http://svn.reactos.org/svn/reactos/branches/wlan-bringup/drivers/network/nd…
==============================================================================
--- branches/wlan-bringup/drivers/network/ndisuio/ioctl.c [iso-8859-1] (original)
+++ branches/wlan-bringup/drivers/network/ndisuio/ioctl.c [iso-8859-1] Tue Jan 3 17:54:01
2012
@@ -12,6 +12,40 @@
#include <debug.h>
NTSTATUS
+CancelPacketRead(PIRP Irp, PIO_STACK_LOCATION IrpSp)
+{
+ PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
+ PNDISUIO_PACKET_ENTRY PacketEntry;
+ NTSTATUS Status;
+
+ /* Indicate a 0-byte packet on the queue so one read returns 0 */
+ PacketEntry = ExAllocatePool(PagedPool, sizeof(NDISUIO_PACKET_ENTRY));
+ if (PacketEntry)
+ {
+ PacketEntry->PacketLength = 0;
+
+ ExInterlockedInsertTailList(&AdapterContext->PacketList,
+ &PacketEntry->ListEntry,
+ &AdapterContext->Spinlock);
+
+ KeSetEvent(&AdapterContext->PacketReadEvent, IO_NO_INCREMENT, FALSE);
+
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ Status = STATUS_NO_MEMORY;
+ }
+
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = 0;
+
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return Status;
+}
+
+NTSTATUS
SetAdapterOid(PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
@@ -232,6 +266,9 @@
/* Now handle other IOCTLs */
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
{
+ case IOCTL_CANCEL_READ:
+ return CancelPacketRead(Irp, IrpSp);
+
case IOCTL_NDISUIO_QUERY_OID_VALUE:
return QueryAdapterOid(Irp, IrpSp);
Modified: branches/wlan-bringup/drivers/network/ndisuio/misc.c
URL:
http://svn.reactos.org/svn/reactos/branches/wlan-bringup/drivers/network/nd…
==============================================================================
--- branches/wlan-bringup/drivers/network/ndisuio/misc.c [iso-8859-1] (original)
+++ branches/wlan-bringup/drivers/network/ndisuio/misc.c [iso-8859-1] Tue Jan 3 17:54:01
2012
@@ -10,6 +10,98 @@
#define NDEBUG
#include <debug.h>
+
+NDIS_STATUS
+AllocateAndChainBuffer(PNDIS_PACKET Packet, PVOID Buffer, ULONG BufferSize, BOOLEAN
Front)
+{
+ NDIS_STATUS Status;
+
+ /* Allocate the NDIS buffer mapping the pool */
+ NdisAllocateBuffer(&Status,
+ &Buffer,
+ GlobalBufferPoolHandle,
+ Buffer,
+ Length);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DPRINT1("No free buffer descriptors\n");
+ return Status;
+ }
+
+ if (Front)
+ {
+ /* Chain the buffer to front */
+ NdisChainBufferAtFront(Packet, Buffer);
+ }
+ else
+ {
+ /* Chain the buffer to back */
+ NdisChainBufferAtBack(Packet, Buffer);
+ }
+
+ /* Return success */
+ return NDIS_STATUS_SUCCESS;
+}
+
+PNDIS_PACKET
+CreatePacketFromPoolBuffer(PVOID Buffer, ULONG BufferSize)
+{
+ PNDIS_PACKET Packet;
+ NDIS_STATUS Status;
+
+ /* Allocate a packet descriptor */
+ NdisAllocatePacket(&Status,
+ &Packet,
+ GlobalPacketPoolHandle);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DPRINT1("No free packet descriptors\n");
+ return NULL;
+ }
+
+ /* Use the helper to chain the buffer */
+ Status = AllocateAndChainBuffer(Packet, Buffer, BufferSize, TRUE);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ NdisFreePacket(Packet);
+ return NULL;
+ }
+
+ /* Return the packet */
+ return Packet;
+}
+
+VOID
+CleanupAndFreePacket(PNDIS_PACKET Packet, BOOLEAN FreePool)
+{
+ PNDIS_BUFFER Buffer;
+ PVOID Data;
+ ULONG Length;
+
+ /* Free each buffer and its backing pool memory */
+ while (TRUE)
+ {
+ /* Unchain each buffer */
+ NdisUnchainBufferAtFront(Packet, &Buffer);
+ if (!Buffer)
+ break;
+
+ /* Get the backing memory */
+ NdisQueryBuffer(Buffer, &Data, &Length);
+
+ /* Free the buffer */
+ NdisFreeBuffer(Buffer);
+
+ if (FreePool)
+ {
+ /* Free the backing memory */
+ ExFreePool(Data);
+ }
+ }
+
+ /* Free the packet descriptor */
+ NdisFreePacket(Packet);
+}
PNDISUIO_ADAPTER_CONTEXT
FindAdapterContextByName(PNDIS_STRING DeviceName)
@@ -70,19 +162,7 @@
/* Free the open entry */
ExFreePool(OpenEntry);
}
-
- /* See if this binding can be destroyed */
- if (AdapterContext->OpenCount == 0)
- {
- /* Unlock the context */
- KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
- /* Destroy the adapter context */
- UnbindAdapterByContext(AdapterContext);
- }
- else
- {
- /* Still more references on it */
- KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
- }
+ /* Release the adapter context lock */
+ KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
}
Modified: branches/wlan-bringup/drivers/network/ndisuio/ndisuio.h
URL:
http://svn.reactos.org/svn/reactos/branches/wlan-bringup/drivers/network/nd…
==============================================================================
--- branches/wlan-bringup/drivers/network/ndisuio/ndisuio.h [iso-8859-1] (original)
+++ branches/wlan-bringup/drivers/network/ndisuio/ndisuio.h [iso-8859-1] Tue Jan 3
17:54:01 2012
@@ -28,9 +28,7 @@
/* Receive packet list */
LIST_ENTRY PacketList;
-
- /* Cancel read */
- BOOLEAN CancelRead;
+ KEVENT PacketReadEvent;
/* Global list entry */
LIST_ENTRY ListEntry;
Modified: branches/wlan-bringup/drivers/network/ndisuio/protocol.c
URL:
http://svn.reactos.org/svn/reactos/branches/wlan-bringup/drivers/network/nd…
==============================================================================
--- branches/wlan-bringup/drivers/network/ndisuio/protocol.c [iso-8859-1] (original)
+++ branches/wlan-bringup/drivers/network/ndisuio/protocol.c [iso-8859-1] Tue Jan 3
17:54:01 2012
@@ -48,7 +48,13 @@
PNDIS_PACKET Packet,
NDIS_STATUS Status)
{
- /* FIXME: Implement send/receive */
+ PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
+
+ DPRINT("Asynchronous adapter send completed\n");
+
+ /* Store the final status and signal the event */
+ AdapterContext->AsyncStatus = Status;
+ KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE);
}
VOID
@@ -58,7 +64,13 @@
NDIS_STATUS Status,
UINT BytesTransferred)
{
- /* FIXME: Implement send/receive */
+ PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
+
+ DPRINT("Asynchronous adapter transfer completed\n");
+
+ /* Store the final status and signal the event */
+ AdapterContext->AsyncStatus = Status;
+ KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE);
}
VOID
@@ -100,8 +112,82 @@
UINT LookaheadBufferSize,
UINT PacketSize)
{
- /* FIXME: Implement send/receive */
- return NDIS_STATUS_NOT_ACCEPTED;
+ PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
+ PVOID PacketBuffer;
+ PNDIS_PACKET Packet;
+ NDIS_STATUS Status;
+ ULONG BytesTransferred;
+
+ /* Allocate a buffer to hold the packet data and header */
+ PacketBuffer = ExAllocatePool(NonPagedPool, PacketSize);
+ if (!PacketBuffer)
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ /* Allocate the packet descriptor and buffer */
+ Packet = CreatePacketFromPoolBuffer((PUCHAR)PacketBuffer + HeaderBufferSize,
+ PacketSize);
+ if (!Packet)
+ {
+ ExFreePool(PacketBuffer);
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+ /* Transfer the packet data into our data buffer */
+ NdisTransferData(&Status,
+ AdapterContext->BindingHandle,
+ MacReceiveContext,
+ 0,
+ PacketSize,
+ &BytesTransferred);
+ if (Status == NDIS_STATUS_PENDING)
+ {
+ KeWaitForSingleObject(&AdapterContext->AsyncEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ Status = AdapterContext->AsyncStatus;
+ }
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DPRINT1("Failed to transfer data with status 0x%x\n", Status);
+ CleanupAndFreePacket(Packet, TRUE);
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+ /* Copy the header data */
+ RtlCopyMemory(PacketBuffer, HeaderBuffer, HeaderBufferSize);
+
+ /* Free the packet descriptor and buffers
+ but not the pool because we still need it */
+ CleanupAndFreePacket(Packet, FALSE);
+
+ /* Allocate a packet entry from paged pool */
+ PacketEntry = ExAllocatePool(PagedPool, sizeof(NDISUIO_PACKET_ENTRY) +
BytesTransferred + HeaderBufferSize - 1);
+ if (!PacketEntry)
+ {
+ ExFreePool(PacketBuffer);
+ return NDIS_STATUS_RESOURCES;
+ }
+
+ /* Initialize the packet entry and copy in packet data */
+ PacketEntry->PacketLength = BytesTransferred + HeaderBufferSize;
+ RtlCopyMemory(&PacketEntry->PacketData[0], PacketBuffer,
PacketEntry->PacketLength);
+
+ /* Free the old non-paged buffer */
+ ExFreePool(PacketBuffer);
+
+ /* Insert the packet on the adapter's packet list */
+ ExInterlockedInsertTailList(&AdapterContext->PacketList,
+ &PacketEntry->ListEntry,
+ &AdapterContext->Spinlock);
+
+ /* Signal the read event */
+ KeSetEvent(&AdapterContext->PacketReadEvent,
+ IO_NETWORK_INCREMENT,
+ FALSE);
+
+ return NDIS_STATUS_SUCCESS;
}
VOID
@@ -134,7 +220,7 @@
KIRQL OldIrql;
PLIST_ENTRY CurrentOpenEntry;
PNDISUIO_OPEN_ENTRY OpenEntry;
-
+
/* Remove the adapter context from the global list */
KeAcquireSpinLock(&GlobalAdapterListLock, &OldIrql);
RemoveEntryList(&AdapterContext->ListEntry);
@@ -167,7 +253,7 @@
/* If this fails, we have a refcount mismatch somewhere */
ASSERT(AdapterContext->OpenCount == 0);
-
+
/* Send the close request */
NdisCloseAdapter(Status,
AdapterContext->BindingHandle);
@@ -206,6 +292,7 @@
/* Set up the adapter context */
RtlZeroMemory(AdapterContext, sizeof(*AdapterContext));
KeInitializeEvent(&AdapterContext->AsyncEvent, SynchronizationEvent, FALSE);
+ KeInitializeEvent(&AdapterContext->PacketReadEvent, SynchronizationEvent,
FALSE);
KeInitializeSpinLock(&AdapterContext->Spinlock);
InitializeListHead(&AdapterContext->PacketList);
InitializeListHead(&AdapterContext->OpenEntryList);
Modified: branches/wlan-bringup/drivers/network/ndisuio/readwrite.c
URL:
http://svn.reactos.org/svn/reactos/branches/wlan-bringup/drivers/network/nd…
==============================================================================
--- branches/wlan-bringup/drivers/network/ndisuio/readwrite.c [iso-8859-1] (original)
+++ branches/wlan-bringup/drivers/network/ndisuio/readwrite.c [iso-8859-1] Tue Jan 3
17:54:01 2012
@@ -11,34 +11,134 @@
#define NDEBUG
#include <debug.h>
-VOID
+NTSTATUS
NTAPI
NduDispatchRead(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
+ PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
+ PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
+ KIRQL OldIrql;
+ NTSTATUS Status;
+ PLIST_ENTRY ListEntry;
+ PNDISUIO_PACKET_ENTRY PacketEntry = NULL;
+ ULONG BytesCopied = 0;
+
ASSERT(DeviceObject == GlobalDeviceObject);
- /* FIXME: Not implemented */
- Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
- Irp->IoStatus.Information = 0;
+ while (TRUE)
+ {
+ KeAcquireSpinLock(&AdapterContext->Spinlock, &OldIrql);
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ /* Check if we have a packet */
+ if (IsListEmpty(&AdapterContext->PacketList))
+ {
+ KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
- return STATUS_NOT_IMPLEMENTED;
+ /* Wait for a packet (in the context of the calling user thread) */
+ Status = KeWaitForSingleObject(&AdapterContext->PacketReadEvent,
+ UserRequest,
+ UserMode,
+ TRUE,
+ NULL);
+ if (Status != STATUS_SUCCESS)
+ break;
+ }
+ else
+ {
+ /* Remove the first packet in the list */
+ ListEntry = RemoveHeadList(&AdapterContext->PacketList);
+ PacketEntry = CONTAINING_RECORD(ListEntry, NDISUIO_PACKET_ENTRY, ListEntry);
+
+ /* Release the adapter lock */
+ KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
+
+ /* And we're done with this loop */
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ }
+
+ /* Check if we got a packet */
+ if (PacketEntry != NULL)
+ {
+ /* Find the right amount of bytes to copy */
+ BytesCopied = PacketEntry->PacketLength;
+ if (BytesCopied > IrpSp->Parameters.Read.Length)
+ BytesCopied = IrpSp->Parameters.Read.Length;
+
+ /* Copy the packet */
+ RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
+ &PacketEntry->PacketBuffer[0],
+ BytesCopied);
+
+ /* Free the packet entry */
+ ExFreePool(PacketEntry);
+ }
+ else
+ {
+ /* Something failed */
+ BytesCopied = 0;
+ }
+
+ /* Complete the IRP */
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = BytesCopied;
+ IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
+
+ return Status;
}
-VOID
+NTSTATUS
NTAPI
NduDispatchWrite(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
+ PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
+ PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
+ PNDIS_PACKET Packet;
+ NDIS_STATUS Status;
+ ULONG BytesCopied = 0;
+
ASSERT(DeviceObject == GlobalDeviceObject);
+
+ /* Create a packet and buffer descriptor for this user buffer */
+ Packet = CreatePacketFromPoolBuffer(Irp->AssociatedIrp.SystemBuffer,
+ IrpSp->Parameters.Write.Length);
+ if (Packet)
+ {
+ /* Send it via NDIS */
+ NdisSend(&Status,
+ AdapterContext->BindingHandle,
+ Packet);
- /* FIXME: Not implemented */
- Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
- Irp->IoStatus.Information = 0;
+ /* Wait for the send */
+ if (Status == NDIS_STATUS_PENDING)
+ {
+ KeWaitForSingleObject(&AdapterContext->AsyncEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ Status = AdapterContext->AsyncStatus;
+ }
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ /* Check if it succeeded */
+ if (Status == NDIS_STATUS_SUCCESS)
+ BytesCopied = IrpSp->Parameters.Write.Length;
- return STATUS_NOT_IMPLEMENTED;
+ CleanupAndFreePacket(Packet);
+ }
+ else
+ {
+ /* No memory */
+ Status = STATUS_NO_MEMORY;
+ }
+
+ /* Complete the IRP */
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = BytesCopied;
+ IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
+
+ return Status;
}