[ros-diffs] [cgutman] 54818: [NDISUIO] - Implement IOCTL_CANCEL_READ - Implement IRP_MJ_READ and IRP_MJ_WRITE handling - Misc fixes

cgutman at svn.reactos.org cgutman at svn.reactos.org
Tue Jan 3 17:54:01 UTC 2012


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/ndisuio/ioctl.c?rev=54818&r1=54817&r2=54818&view=diff
==============================================================================
--- 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/ndisuio/misc.c?rev=54818&r1=54817&r2=54818&view=diff
==============================================================================
--- 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/ndisuio/ndisuio.h?rev=54818&r1=54817&r2=54818&view=diff
==============================================================================
--- 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/ndisuio/protocol.c?rev=54818&r1=54817&r2=54818&view=diff
==============================================================================
--- 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/ndisuio/readwrite.c?rev=54818&r1=54817&r2=54818&view=diff
==============================================================================
--- 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;
 }




More information about the Ros-diffs mailing list