Allow mapping of MDLs which describe I/O memory (device memory) into usermode. I hope the changes are correct :-/
Modified: trunk/reactos/ntoskrnl/include/internal/mm.h
Modified: trunk/reactos/ntoskrnl/mm/freelist.c
Modified: trunk/reactos/ntoskrnl/mm/mdl.c
Modified: trunk/reactos/ntoskrnl/mm/section.c

Modified: trunk/reactos/ntoskrnl/include/internal/mm.h
--- trunk/reactos/ntoskrnl/include/internal/mm.h	2005-03-15 22:06:41 UTC (rev 14108)
+++ trunk/reactos/ntoskrnl/include/internal/mm.h	2005-03-15 22:07:05 UTC (rev 14109)
@@ -628,6 +628,7 @@
 VOID MmSetLRULastPage(PFN_TYPE Page);
 
 VOID MmLockPage(PFN_TYPE Page);
+VOID MmLockPageUnsafe(PFN_TYPE Page);
 
 VOID MmUnlockPage(PFN_TYPE Page);
 
@@ -712,6 +713,7 @@
 VOID MmDereferencePage(PFN_TYPE Page);
 
 VOID MmReferencePage(PFN_TYPE Page);
+VOID MmReferencePageUnsafe(PFN_TYPE Page);
 
 BOOLEAN MmIsAccessedAndResetAccessPage(struct _EPROCESS* Process, PVOID Address);
 

Modified: trunk/reactos/ntoskrnl/mm/freelist.c
--- trunk/reactos/ntoskrnl/mm/freelist.c	2005-03-15 22:06:41 UTC (rev 14108)
+++ trunk/reactos/ntoskrnl/mm/freelist.c	2005-03-15 22:07:05 UTC (rev 14109)
@@ -623,15 +623,15 @@
 }
 
 VOID
-MmReferencePage(PFN_TYPE Pfn)
+MmReferencePageUnsafe(PFN_TYPE Pfn)
 {
    KIRQL oldIrql;
 
-   DPRINT("MmReferencePage(PysicalAddress %x)\n", Pfn << PAGE_SHIFT);
+   DPRINT("MmReferencePageUnsafe(PysicalAddress %x)\n", Pfn << PAGE_SHIFT);
 
    if (Pfn == 0 || Pfn >= MmPageArraySize)
    {
-      KEBUGCHECK(0);
+      return;
    }
 
    KeAcquireSpinLock(&PageListLock, &oldIrql);
@@ -646,6 +646,19 @@
    KeReleaseSpinLock(&PageListLock, oldIrql);
 }
 
+VOID
+MmReferencePage(PFN_TYPE Pfn)
+{
+   DPRINT("MmReferencePage(PysicalAddress %x)\n", Pfn << PAGE_SHIFT);
+
+   if (Pfn == 0 || Pfn >= MmPageArraySize)
+   {
+      KEBUGCHECK(0);
+   }
+
+   MmReferencePageUnsafe(Pfn);
+}
+
 ULONG
 MmGetReferenceCountPage(PFN_TYPE Pfn)
 {
@@ -792,15 +805,15 @@
 }
 
 VOID
-MmLockPage(PFN_TYPE Pfn)
+MmLockPageUnsafe(PFN_TYPE Pfn)
 {
    KIRQL oldIrql;
 
-   DPRINT("MmLockPage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
+   DPRINT("MmLockPageUnsafe(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
 
    if (Pfn == 0 || Pfn >= MmPageArraySize)
    {
-      KEBUGCHECK(0);
+      return;
    }
 
    KeAcquireSpinLock(&PageListLock, &oldIrql);
@@ -816,6 +829,19 @@
 }
 
 VOID
+MmLockPage(PFN_TYPE Pfn)
+{
+   DPRINT("MmLockPage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
+
+   if (Pfn == 0 || Pfn >= MmPageArraySize)
+   {
+      KEBUGCHECK(0);
+   }
+   
+   MmLockPageUnsafe(Pfn);
+}
+
+VOID
 MmUnlockPage(PFN_TYPE Pfn)
 {
    KIRQL oldIrql;

Modified: trunk/reactos/ntoskrnl/mm/mdl.c
--- trunk/reactos/ntoskrnl/mm/mdl.c	2005-03-15 22:06:41 UTC (rev 14108)
+++ trunk/reactos/ntoskrnl/mm/mdl.c	2005-03-15 22:07:05 UTC (rev 14109)
@@ -29,7 +29,7 @@
 /*
 MDL Flags desc.
 
-MDL_PAGES_LOCKED              MmProbelAndLockPages has been called for this mdl
+MDL_PAGES_LOCKED              MmProbeAndLockPages has been called for this mdl
 MDL_SOURCE_IS_NONPAGED_POOL   mdl has been build by MmBuildMdlForNonPagedPool
 MDL_PARTIAL                   mdl has been built by IoBuildPartialMdl
 MDL_MAPPING_CAN_FAIL          in case of an error, MmMapLockedPages will return NULL instead of to bugcheck
@@ -233,7 +233,7 @@
    /* Unmap all the pages. */
    for (i = 0; i < PageCount; i++)
    {
-      MmDeleteVirtualMapping(NULL,
+      MmDeleteVirtualMapping(Mdl->Process,
                              (char*)BaseAddress + (i * PAGE_SIZE),
                              FALSE,
                              NULL,
@@ -300,7 +300,7 @@
 {
    memcpy(Mdl + 1, Pages, sizeof(PFN_TYPE) * (PAGE_ROUND_UP(Mdl->ByteOffset+Mdl->ByteCount)/PAGE_SIZE));
 
-   //FIXME: this flag should be set by the caller perhaps?
+   /* FIXME: this flag should be set by the caller perhaps? */
    Mdl->MdlFlags |= MDL_IO_PAGE_READ;
 }
 
@@ -375,8 +375,8 @@
    ASSERT(NrPages <= (Mdl->Size - sizeof(MDL))/sizeof(PFN_TYPE));
 
 
-   if (Mdl->StartVa >= (PVOID)KERNEL_BASE && 
-       MmGetPfnForProcess(NULL, Mdl->StartVa) > MmPageArraySize)
+   if (Mdl->StartVa >= (PVOID)KERNEL_BASE &&
+       MmGetPfnForProcess(NULL, Mdl->StartVa) >= MmPageArraySize)
    {
        /* phys addr is not phys memory so this must be io memory */
        
@@ -392,14 +392,14 @@
 
    if (Mdl->StartVa >= (PVOID)KERNEL_BASE)
    {
-      //FIXME: why isn't AccessMode used?
+      /* FIXME: why isn't AccessMode used? */
       Mode = KernelMode;
       Mdl->Process = NULL;
       AddressSpace = MmGetKernelAddressSpace();
    }
    else
    {
-      //FIXME: why isn't AccessMode used?
+      /* FIXME: why isn't AccessMode used? */
       Mode = UserMode;
       Mdl->Process = CurrentProcess;      
       AddressSpace = &CurrentProcess->AddressSpace;
@@ -430,8 +430,11 @@
             for (j = 0; j < i; j++)
             {
 	       Page = MdlPages[j];
-               MmUnlockPage(Page);
-               MmDereferencePage(Page);
+               if (Page < MmPageArraySize)
+               {
+                  MmUnlockPage(Page);
+                  MmDereferencePage(Page);
+               }
             }
             MmUnlockAddressSpace(AddressSpace);
             ExRaiseStatus(Status);
@@ -451,8 +454,11 @@
             for (j = 0; j < i; j++)
             {
 	       Page = MdlPages[j];
-               MmUnlockPage(Page);
-               MmDereferencePage(Page);
+               if (Page < MmPageArraySize)
+               {
+                  MmUnlockPage(Page);
+                  MmDereferencePage(Page);
+               }
             }
             MmUnlockAddressSpace(AddressSpace);
             ExRaiseStatus(Status);
@@ -460,7 +466,10 @@
       }
       Page = MmGetPfnForProcess(NULL, Address);
       MdlPages[i] = Page;
-      MmReferencePage(Page);
+      if (Page >= MmPageArraySize)
+         Mdl->MdlFlags |= MDL_IO_SPACE;
+      else
+         MmReferencePage(Page);
    }
    
    MmUnlockAddressSpace(AddressSpace);
@@ -843,6 +852,8 @@
       }
 
       KeReleaseSpinLock(&MiMdlMappingRegionLock, oldIrql);
+      
+      Mdl->Process = NULL;
    }
 
    /* Set the virtual mappings for the MDL pages. */
@@ -853,11 +864,18 @@
       Protect |= PAGE_NOCACHE;
    else if (CacheType == MmWriteCombined)
       DPRINT("CacheType MmWriteCombined not supported!\n");
-   Status = MmCreateVirtualMapping(CurrentProcess,
-                                   Base,
-                                   Protect,
-                                   MdlPages,
-                                   PageCount);
+   if (Mdl->MdlFlags & MDL_IO_SPACE)
+      Status = MmCreateVirtualMappingUnsafe(CurrentProcess,
+                                            Base,
+                                            Protect,
+                                            MdlPages,
+                                            PageCount);
+   else
+      Status = MmCreateVirtualMapping(CurrentProcess,
+                                      Base,
+                                      Protect,
+                                      MdlPages,
+                                      PageCount);
    if (!NT_SUCCESS(Status))
    {
       DbgPrint("Unable to create virtual mapping\n");

Modified: trunk/reactos/ntoskrnl/mm/section.c
--- trunk/reactos/ntoskrnl/mm/section.c	2005-03-15 22:06:41 UTC (rev 14108)
+++ trunk/reactos/ntoskrnl/mm/section.c	2005-03-15 22:07:05 UTC (rev 14109)
@@ -727,6 +727,9 @@
 
          MmSharePageEntrySectionSegment(Segment, Offset);
 
+         /* FIXME: Should we call MmCreateVirtualMappingUnsafe if
+          * (Section->AllocationAttributes & SEC_PHYSICALMEMORY) is true?
+          */
          Status = MmCreateVirtualMapping(MemoryArea->Process,
                                          Address,
                                          Attributes,
@@ -829,14 +832,14 @@
       * Just map the desired physical page
       */
       Page = (Offset + MemoryArea->Data.SectionData.ViewOffset) >> PAGE_SHIFT;
-      Status = MmCreateVirtualMapping(AddressSpace->Process,
-                                      Address,
-                                      Region->Protect,
-                                      &Page,
-                                      1);
+      Status = MmCreateVirtualMappingUnsafe(AddressSpace->Process,
+                                            Address,
+                                            Region->Protect,
+                                            &Page,
+                                            1);
       if (!NT_SUCCESS(Status))
       {
-         DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
+         DPRINT("MmCreateVirtualMappingUnsafe failed, not out of memory\n");
          KEBUGCHECK(0);
          return(Status);
       }
@@ -846,7 +849,7 @@
       */
       if (Locked)
       {
-         MmLockPage(Page);
+         MmLockPageUnsafe(Page);
       }
 
       /*