[NDIS]
[reactos.git] / reactos / drivers / network / ndis / ndis / buffer.c
index 2a7264b..dc6f1ca 100644 (file)
@@ -357,6 +357,7 @@ NdisAllocateBuffer(
         (*Buffer)->Next = NULL;
         *Status = NDIS_STATUS_SUCCESS;
     } else {
+        NDIS_DbgPrint(MIN_TRACE, ("IoAllocateMdl failed (%x, %lx)\n", VirtualAddress, Length));
         *Status = NDIS_STATUS_FAILURE;
     }
 }
@@ -401,38 +402,13 @@ NdisAllocatePacket(
  *     PoolHandle = Handle returned by NdisAllocatePacketPool
  */
 {
-    KIRQL OldIrql;
-    PNDIS_PACKET Temp;
     PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)PoolHandle;
 
-    NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X)  Packet (0x%X)  PoolHandle (0x%X).\n",
-        Status, Packet, PoolHandle));
-
-    *Packet = NULL;
-
-    if (Pool == NULL)
-    {
-        *Status = NDIS_STATUS_FAILURE;
-        return;
-    }
-
-    KeAcquireSpinLock(&Pool->SpinLock.SpinLock, &OldIrql);
-
-    if (Pool->FreeList) {
-        Temp           = Pool->FreeList;
-        Pool->FreeList = (PNDIS_PACKET)Temp->Reserved[0];
-
-        KeReleaseSpinLock(&Pool->SpinLock.SpinLock, OldIrql);
-
-        RtlZeroMemory(Temp, sizeof(NDIS_PACKET));
-        Temp->Private.Pool = Pool;
-
-        *Packet = Temp;
-        *Status = NDIS_STATUS_SUCCESS;
-    } else {
-        *Status = NDIS_STATUS_RESOURCES;
-        KeReleaseSpinLock(&Pool->SpinLock.SpinLock, OldIrql);
-    }
+    KeAcquireSpinLock(&Pool->SpinLock.SpinLock, &Pool->SpinLock.OldIrql);
+    NdisDprAllocatePacketNonInterlocked(Status,
+                                        Packet,
+                                        PoolHandle);
+    KeReleaseSpinLock(&Pool->SpinLock.SpinLock, Pool->SpinLock.OldIrql);
 }
 
 
@@ -494,6 +470,7 @@ NdisAllocatePacketPoolEx(
 
     if (NumberOfDescriptors > 0xffff)
     {
+        NDIS_DbgPrint(MIN_TRACE, ("Invalid number of descriptors (%lx)\n", NumberOfDescriptors))
         *Status = NDIS_STATUS_RESOURCES;
     }
     else
@@ -501,10 +478,12 @@ NdisAllocatePacketPoolEx(
         NumberOfDescriptors += NumberOfOverflowDescriptors;
         if (NumberOfDescriptors > 0xffff)
         {
+            NDIS_DbgPrint(MIN_TRACE, ("Total number of descriptors > 0xffff (%lx)\n", NumberOfDescriptors));
             NumberOfDescriptors = 0xffff;
         }
 
-        Length = sizeof(NDIS_PACKET) + ProtocolReservedLength;
+        Length = sizeof(NDIS_PACKET) + sizeof(NDIS_PACKET_OOB_DATA) + 
+                 sizeof(NDIS_PACKET_EXTENSION) + ProtocolReservedLength;
         Size   = sizeof(NDISI_PACKET_POOL) + Length * NumberOfDescriptors;
 
         Pool   = ExAllocatePool(NonPagedPool, Size);
@@ -527,8 +506,10 @@ NdisAllocatePacketPoolEx(
                 }
                 Packet->Reserved[0] = 0;
             }
-            else
+            else {
+                NDIS_DbgPrint(MIN_TRACE, ("Attempted to allocate a packet pool with 0 descriptors\n"));
                 Pool->FreeList = NULL;
+            }
 
             *Status     = NDIS_STATUS_SUCCESS;
             *PoolHandle = (PNDIS_HANDLE)Pool;
@@ -683,37 +664,13 @@ NdisDprAllocatePacket(
  *     PoolHandle = Handle returned by NdisAllocatePacketPool
  */
 {
-    PNDIS_PACKET Temp;
     PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)PoolHandle;
 
-    NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X)  Packet (0x%X)  PoolHandle (0x%X).\n",
-        Status, Packet, PoolHandle));
-
-    *Packet = NULL;
-
-    if (Pool == NULL)
-    {
-        *Status = NDIS_STATUS_FAILURE;
-        return;
-    }
-
     KeAcquireSpinLockAtDpcLevel(&Pool->SpinLock.SpinLock);
-
-    if (Pool->FreeList) {
-        Temp           = Pool->FreeList;
-        Pool->FreeList = (PNDIS_PACKET)Temp->Reserved[0];
-
-        KeReleaseSpinLockFromDpcLevel(&Pool->SpinLock.SpinLock);
-
-        RtlZeroMemory(&Temp->Private, sizeof(NDIS_PACKET_PRIVATE));
-        Temp->Private.Pool = Pool;
-
-        *Packet = Temp;
-        *Status = NDIS_STATUS_SUCCESS;
-    } else {
-        *Status = NDIS_STATUS_RESOURCES;
-        KeReleaseSpinLockFromDpcLevel(&Pool->SpinLock.SpinLock);
-    }
+    NdisDprAllocatePacketNonInterlocked(Status,
+                                        Packet,
+                                        PoolHandle);
+    KeReleaseSpinLockFromDpcLevel(&Pool->SpinLock.SpinLock);
 }
 
 
@@ -745,6 +702,7 @@ NdisDprAllocatePacketNonInterlocked(
     if (Pool == NULL)
     {
         *Status = NDIS_STATUS_FAILURE;
+        NDIS_DbgPrint(MIN_TRACE, ("Called passed a bad pool handle\n"));
         return;
     }
 
@@ -752,12 +710,18 @@ NdisDprAllocatePacketNonInterlocked(
         Temp           = Pool->FreeList;
         Pool->FreeList = (PNDIS_PACKET)Temp->Reserved[0];
 
-        RtlZeroMemory(&Temp->Private, sizeof(NDIS_PACKET_PRIVATE));
+        RtlZeroMemory(Temp, Pool->PacketLength);
         Temp->Private.Pool = Pool;
+        Temp->Private.ValidCounts = TRUE;
+        Temp->Private.NdisPacketFlags = fPACKET_ALLOCATED_BY_NDIS;
+        Temp->Private.NdisPacketOobOffset = Pool->PacketLength -
+                                            (sizeof(NDIS_PACKET_OOB_DATA) +
+                                             sizeof(NDIS_PACKET_EXTENSION));
 
         *Packet = Temp;
         *Status = NDIS_STATUS_SUCCESS;
     } else {
+        NDIS_DbgPrint(MIN_TRACE, ("No more free descriptors\n"));
         *Status = NDIS_STATUS_RESOURCES;
     }
 }
@@ -776,12 +740,11 @@ NdisDprFreePacket(
  *     Packet = Pointer to packet to free
  */
 {
-    NDIS_DbgPrint(MAX_TRACE, ("Packet (0x%X).\n", Packet));
+    PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)Packet->Private.Pool;
 
-    KeAcquireSpinLockAtDpcLevel(&((NDISI_PACKET_POOL*)Packet->Private.Pool)->SpinLock.SpinLock);
-    Packet->Reserved[0]           = (ULONG_PTR)((NDISI_PACKET_POOL*)Packet->Private.Pool)->FreeList;
-    ((NDISI_PACKET_POOL*)Packet->Private.Pool)->FreeList = Packet;
-    KeReleaseSpinLockFromDpcLevel(&((NDISI_PACKET_POOL*)Packet->Private.Pool)->SpinLock.SpinLock);
+    KeAcquireSpinLockAtDpcLevel(&Pool->SpinLock.SpinLock);
+    NdisDprFreePacketNonInterlocked(Packet);
+    KeReleaseSpinLockFromDpcLevel(&Pool->SpinLock.SpinLock);
 }
 
 
@@ -869,14 +832,11 @@ NdisFreePacket(
  *     Packet = Pointer to packet descriptor
  */
 {
-    KIRQL OldIrql;
+    PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)Packet->Private.Pool;
 
-    NDIS_DbgPrint(MAX_TRACE, ("Packet (0x%X).\n", Packet));
-
-    KeAcquireSpinLock(&((NDISI_PACKET_POOL*)Packet->Private.Pool)->SpinLock.SpinLock, &OldIrql);
-    Packet->Reserved[0]           = (ULONG_PTR)((NDISI_PACKET_POOL*)Packet->Private.Pool)->FreeList;
-    ((NDISI_PACKET_POOL*)Packet->Private.Pool)->FreeList = Packet;
-    KeReleaseSpinLock(&((NDISI_PACKET_POOL*)Packet->Private.Pool)->SpinLock.SpinLock, OldIrql);
+    KeAcquireSpinLock(&Pool->SpinLock.SpinLock, &Pool->SpinLock.OldIrql);
+    NdisDprFreePacketNonInterlocked(Packet);
+    KeReleaseSpinLock(&Pool->SpinLock.SpinLock, Pool->SpinLock.OldIrql);
 }
 
 
@@ -935,6 +895,7 @@ NdisGetFirstBufferFromPacket(
         *_FirstBufferVA = MmGetSystemAddressForMdl(Buffer);
         Buffer = Buffer->Next;
     } else {
+        NDIS_DbgPrint(MIN_TRACE, ("No buffers linked to this packet\n"));
         *_FirstBufferLength = 0;
         *_FirstBufferVA = NULL;
     }
@@ -947,6 +908,42 @@ NdisGetFirstBufferFromPacket(
     }
 }
 
+#undef NdisGetFirstBufferFromPacketSafe
+/*
+ * @implemented
+ */
+VOID
+EXPORT
+NdisGetFirstBufferFromPacketSafe(
+    IN  PNDIS_PACKET     _Packet,
+    OUT PNDIS_BUFFER     *_FirstBuffer,
+    OUT PVOID            *_FirstBufferVA,
+    OUT PUINT            _FirstBufferLength,
+    OUT PUINT            _TotalBufferLength,
+    IN  MM_PAGE_PRIORITY Priority)
+{
+    PNDIS_BUFFER Buffer;
+
+    Buffer          = _Packet->Private.Head;
+    *_FirstBuffer   = Buffer;
+
+    if (Buffer != NULL) {
+        *_FirstBufferLength = MmGetMdlByteCount(Buffer);
+        *_FirstBufferVA = MmGetSystemAddressForMdlSafe(Buffer, Priority);
+        Buffer = Buffer->Next;
+    } else {
+        NDIS_DbgPrint(MIN_TRACE, ("No buffers linked to this packet\n"));
+        *_FirstBufferLength = 0;
+        *_FirstBufferVA = NULL;
+    }
+
+    *_TotalBufferLength = *_FirstBufferLength;
+
+    while (Buffer != NULL) {
+        *_TotalBufferLength += MmGetMdlByteCount(Buffer);
+        Buffer = Buffer->Next;
+    }
+}
 
 /*
  * @implemented
@@ -1038,6 +1035,7 @@ NdisUnchainBufferAtBack(
                     &NdisBuffer,
                     NULL);
     if (!NdisBuffer) {
+        NDIS_DbgPrint(MIN_TRACE, ("No buffer to unchain\n"));
         *Buffer = NULL;
         return;
     }
@@ -1086,6 +1084,7 @@ NdisUnchainBufferAtFront(
                     &NdisBuffer,
                     NULL);
     if (!NdisBuffer) {
+        NDIS_DbgPrint(MIN_TRACE, ("No buffer to unchain\n"));
         *Buffer = NULL;
         return;
     }
@@ -1102,4 +1101,228 @@ NdisUnchainBufferAtFront(
     *Buffer = NdisBuffer;
 }
 
+/*
+ * @implemented
+ */
+VOID
+EXPORT
+NdisCopyBuffer(
+    OUT PNDIS_STATUS    Status,
+    OUT PNDIS_BUFFER    *Buffer,
+    IN  NDIS_HANDLE     PoolHandle,
+    IN  PVOID           MemoryDescriptor,
+    IN  UINT            Offset,
+    IN  UINT            Length)
+/*
+ * FUNCTION: Returns a new buffer descriptor for a (partial) buffer
+ * ARGUMENTS:
+ *     Status           = Address of a buffer to place status of operation
+ *     Buffer           = Address of a buffer to place new buffer descriptor
+ *     PoolHandle       = Handle returned by NdisAllocateBufferPool
+ *     MemoryDescriptor = Pointer to a memory descriptor (possibly NDIS_BUFFER)
+ *     Offset           = Offset in buffer to start copying
+ *     Length           = Number of bytes to copy
+ */
+{
+    PVOID CurrentVa = (PUCHAR)(MmGetMdlVirtualAddress((PNDIS_BUFFER)MemoryDescriptor)) + Offset;
+
+    NDIS_DbgPrint(MAX_TRACE, ("Called\n"));
+
+    *Buffer = IoAllocateMdl(CurrentVa, Length, FALSE, FALSE, NULL);
+    if (!*Buffer)
+    {
+        NDIS_DbgPrint(MIN_TRACE, ("IoAllocateMdl failed (%x, %lx)\n", CurrentVa, Length));
+        *Status = NDIS_STATUS_FAILURE;
+        return;
+    }
+
+    IoBuildPartialMdl((PNDIS_BUFFER)MemoryDescriptor,
+                      *Buffer,
+                      CurrentVa,
+                      Length);
+
+    (*Buffer)->Next = NULL;
+    *Status = NDIS_STATUS_SUCCESS;
+}
+
+/*
+ * @implemented
+ */
+NDIS_HANDLE
+EXPORT
+NdisGetPoolFromPacket(
+    IN PNDIS_PACKET  Packet)
+{
+    return Packet->Private.Pool;
+}
+
+/*
+ * @implemented
+ */
+UINT
+EXPORT
+NdisPacketSize(
+    IN UINT  ProtocolReservedSize)
+{
+    return sizeof(NDIS_PACKET) + sizeof(NDIS_PACKET_OOB_DATA) + 
+                 sizeof(NDIS_PACKET_EXTENSION) + ProtocolReservedSize;
+}
+
+/*
+ * @implemented
+ */
+#undef NdisGetPacketCancelId
+PVOID
+EXPORT
+NdisGetPacketCancelId(
+    IN PNDIS_PACKET  Packet)
+{
+    return NDIS_GET_PACKET_CANCEL_ID(Packet);
+}
+
+/*
+ * @implemented
+ */
+#undef NdisSetPacketCancelId
+VOID
+EXPORT
+NdisSetPacketCancelId(
+    IN PNDIS_PACKET  Packet,
+    IN PVOID  CancelId)
+{
+    NDIS_SET_PACKET_CANCEL_ID(Packet, CancelId);
+}
+
+/*
+ * @implemented
+ */
+VOID
+EXPORT
+NdisCopyFromPacketToPacketSafe(
+    IN  PNDIS_PACKET     Destination,
+    IN  UINT             DestinationOffset,
+    IN  UINT             BytesToCopy,
+    IN  PNDIS_PACKET     Source,
+    IN  UINT             SourceOffset,
+    OUT PUINT            BytesCopied,
+    IN  MM_PAGE_PRIORITY Priority)
+{
+    PNDIS_BUFFER SrcBuffer;
+    PNDIS_BUFFER DstBuffer;
+    PUCHAR DstData, SrcData;
+    UINT DstSize, SrcSize;
+    UINT Count, Total;
+
+    *BytesCopied = 0;
+
+    /* Skip DestinationOffset bytes in the destination packet */
+    NdisGetFirstBufferFromPacketSafe(Destination, &DstBuffer, (PVOID*)&DstData, &DstSize, &Total, Priority);
+    if (!DstData || SkipToOffset(DstBuffer, DestinationOffset, &DstData, &DstSize) == 0xFFFFFFFF)
+        return;
+
+    /* Skip SourceOffset bytes in the source packet */
+    NdisGetFirstBufferFromPacketSafe(Source, &SrcBuffer, (PVOID*)&SrcData, &SrcSize, &Total, Priority);
+    if (!SrcData || SkipToOffset(SrcBuffer, SourceOffset, &SrcData, &SrcSize) == 0xFFFFFFFF)
+        return;
+
+    /* Copy the data */
+    for (Total = 0;;) {
+        /* Find out how many bytes we can copy at one time */
+        if (BytesToCopy < SrcSize)
+            Count = BytesToCopy;
+        else
+            Count = SrcSize;
+        if (DstSize < Count)
+            Count = DstSize;
+
+        RtlCopyMemory(DstData, SrcData, Count);
+
+        Total       += Count;
+        BytesToCopy -= Count;
+        if (BytesToCopy == 0)
+            break;
+
+        DstSize -= Count;
+        if (DstSize == 0) {
+            /* No more bytes in destination buffer. Proceed to
+               the next buffer in the destination buffer chain */
+            NdisGetNextBuffer(DstBuffer, &DstBuffer);
+            if (!DstBuffer)
+                break;
+
+            NdisQueryBufferSafe(DstBuffer, (PVOID)&DstData, &DstSize, Priority);
+            if (!DstData)
+                break;
+        }
+
+        SrcSize -= Count;
+        if (SrcSize == 0) {
+            /* No more bytes in source buffer. Proceed to
+               the next buffer in the source buffer chain */
+            NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
+            if (!SrcBuffer)
+                break;
+
+            NdisQueryBufferSafe(SrcBuffer, (PVOID)&SrcData, &SrcSize, Priority);
+            if (!SrcData)
+                break;
+        }
+    }
+
+    *BytesCopied = Total;
+}
+
+/*
+ * @implemented
+ */
+VOID
+EXPORT
+NdisIMCopySendCompletePerPacketInfo(
+    IN  PNDIS_PACKET    DstPacket,
+    IN  PNDIS_PACKET    SrcPacket)
+/*
+ * FUNCTION:
+ * ARGUMENTS:
+ * NOTES:
+ *    NDIS 5.0
+ */
+{
+    /* FIXME: What is the difference between NdisIMCopySendPerPacketInfo and
+     * NdisIMCopySendCompletePerPacketInfo?
+     */
+
+    NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+    RtlCopyMemory(NDIS_PACKET_EXTENSION_FROM_PACKET(DstPacket),
+                  NDIS_PACKET_EXTENSION_FROM_PACKET(SrcPacket),
+                  sizeof(NDIS_PACKET_EXTENSION));
+}
+
+
+/*
+ * @implemented
+ */
+VOID
+EXPORT
+NdisIMCopySendPerPacketInfo(
+    IN  PNDIS_PACKET    DstPacket,
+    IN  PNDIS_PACKET    SrcPacket)
+/*
+ * FUNCTION:
+ * ARGUMENTS:
+ * NOTES:
+ *    NDIS 5.0
+ */
+{
+    /* FIXME: What is the difference between NdisIMCopySendPerPacketInfo and
+     * NdisIMCopySendCompletePerPacketInfo?
+     */
+
+    NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+    RtlCopyMemory(NDIS_PACKET_EXTENSION_FROM_PACKET(DstPacket),
+                  NDIS_PACKET_EXTENSION_FROM_PACKET(SrcPacket),
+                  sizeof(NDIS_PACKET_EXTENSION));
+}
+
 /* EOF */