add some asserts
[reactos.git] / reactos / ntoskrnl / io / mdl.c
index 90558de..b4b423f 100644 (file)
@@ -1,20 +1,17 @@
-/* $Id: mdl.c,v 1.7 2001/03/16 16:05:33 dwelch Exp $
+/* $Id$
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/io/mdl.c
  * PURPOSE:         Io manager mdl functions
- * PROGRAMMER:      David Welch (welch@mcmail.com)
- * UPDATE HISTORY:
- *                  Created 22/05/98
+ *
+ * PROGRAMMERS:     David Welch (welch@mcmail.com)
  */
 
 /* INCLUDES *****************************************************************/
 
-#include <ddk/ntddk.h>
-#include <internal/mmhal.h>
-#include <internal/pool.h>
-
+#include <ntoskrnl.h>
+#define NDEBUG
 #include <internal/debug.h>
 
 /* GLOBALS *******************************************************************/
@@ -23,6 +20,9 @@
 
 /* FUNCTIONS *****************************************************************/
 
+/*
+ * @implemented
+ */
 PMDL
 STDCALL
 IoAllocateMdl(PVOID VirtualAddress,
@@ -32,7 +32,7 @@ IoAllocateMdl(PVOID VirtualAddress,
                   PIRP Irp)
 {
    PMDL Mdl;
-   
+
    if (ChargeQuota)
      {
 //     Mdl = ExAllocatePoolWithQuota(NonPagedPool,
@@ -47,14 +47,40 @@ IoAllocateMdl(PVOID VirtualAddress,
                                    MmSizeOfMdl(VirtualAddress,Length),
                                    TAG_MDL);
      }
-   MmInitializeMdl(Mdl,VirtualAddress,Length);
-   if (Irp!=NULL && !SecondaryBuffer)
-     {
-       Irp->MdlAddress = Mdl;
-     }
+   MmInitializeMdl(Mdl, (char*)VirtualAddress, Length);
+
+   if (Irp)
+   {
+      if (SecondaryBuffer)
+      {
+         ASSERT(Irp->MdlAddress);
+
+         /* FIXME: add to end of list maybe?? */
+         Mdl->Next = Irp->MdlAddress->Next;
+         Irp->MdlAddress->Next = Mdl;
+      }
+      else
+      {
+         /*
+          * What if there's allready an mdl at Irp->MdlAddress?
+          * Is that bad and should we do something about it?
+          */
+         Irp->MdlAddress = Mdl;
+      }
+   }
+
    return(Mdl);
 }
 
+/*
+ * @implemented
+ *
+ * You must IoFreeMdl the slave before freeing the master.
+ *
+ * IoBuildPartialMdl is more similar to MmBuildMdlForNonPagedPool, the difference
+ * is that the former takes the physical addresses from the master MDL, while the
+ * latter - from the known location of the NPP.
+ */
 VOID
 STDCALL
 IoBuildPartialMdl(PMDL SourceMdl,
@@ -62,23 +88,50 @@ IoBuildPartialMdl(PMDL SourceMdl,
                       PVOID VirtualAddress,
                       ULONG Length)
 {
-   PULONG TargetPages = (PULONG)(TargetMdl + 1);
-   PULONG SourcePages = (PULONG)(SourceMdl + 1);
-   ULONG Va;
-   ULONG Delta = (PAGE_ROUND_DOWN(VirtualAddress) - (ULONG)SourceMdl->StartVa)/
-                 PAGESIZE;
+   PPFN_TYPE TargetPages = (PPFN_TYPE)(TargetMdl + 1);
+   PPFN_TYPE SourcePages = (PPFN_TYPE)(SourceMdl + 1);
+   ULONG Count;
+   ULONG Delta;
+
+   DPRINT("VirtualAddress %x, SourceMdl->StartVa %x, SourceMdl->MappedSystemVa %x\n",
+          VirtualAddress, SourceMdl->StartVa, SourceMdl->MappedSystemVa);
+
+   TargetMdl->StartVa = (PVOID)PAGE_ROUND_DOWN(VirtualAddress);
+   TargetMdl->ByteOffset = (ULONG_PTR)VirtualAddress - (ULONG_PTR)TargetMdl->StartVa;
+   TargetMdl->ByteCount = Length;
+   TargetMdl->Process = SourceMdl->Process;
+   Delta = (ULONG_PTR)VirtualAddress - ((ULONG_PTR)SourceMdl->StartVa + SourceMdl->ByteOffset);
+   TargetMdl->MappedSystemVa = (char*)SourceMdl->MappedSystemVa + Delta;
+
+   TargetMdl->MdlFlags = SourceMdl->MdlFlags & (MDL_IO_PAGE_READ|MDL_SOURCE_IS_NONPAGED_POOL|MDL_MAPPED_TO_SYSTEM_VA);
+   TargetMdl->MdlFlags |= MDL_PARTIAL;
+
+   Delta = ((ULONG_PTR)TargetMdl->StartVa - (ULONG_PTR)SourceMdl->StartVa) / PAGE_SIZE;
+   Count = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress,Length);
+
+   SourcePages += Delta;
+
+   DPRINT("Delta %d, Count %d\n", Delta, Count);
+
+   memcpy(TargetPages, SourcePages, Count * sizeof(PFN_TYPE));
 
-   for (Va = 0; Va < (PAGE_ROUND_UP(Length)/PAGESIZE); Va++)
-     {
-       TargetPages[Va] = SourcePages[Va+Delta];
-     }
 }
 
+/*
+ * @implemented
+ */
 VOID STDCALL
 IoFreeMdl(PMDL Mdl)
-{   
-   MmUnmapLockedPages(MmGetSystemAddressForMdl(Mdl), Mdl);
-   MmUnlockPages(Mdl);
+{
+   /*
+    * This unmaps partial mdl's from kernel space but also asserts that non-partial
+    * mdl's isn't still mapped into kernel space.
+    */
+   ASSERT(Mdl);
+   ASSERT_IRQL(DISPATCH_LEVEL);
+
+   MmPrepareMdlForReuse(Mdl);
+
    ExFreePool(Mdl);
 }