1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: ntoskrnl/io/iomgr/iomdl.c 5 * PURPOSE: I/O Wrappers for MDL Allocation and Deallocation 6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7 */ 8 9 /* INCLUDES *****************************************************************/ 10 11 #include <ntoskrnl.h> 12 #define NDEBUG 13 #include <debug.h> 14 15 /* FUNCTIONS *****************************************************************/ 16 17 /* 18 * @implemented 19 */ 20 PMDL 21 NTAPI 22 IoAllocateMdl(IN PVOID VirtualAddress, 23 IN ULONG Length, 24 IN BOOLEAN SecondaryBuffer, 25 IN BOOLEAN ChargeQuota, 26 IN PIRP Irp) 27 { 28 PMDL Mdl = NULL, p; 29 ULONG Flags = 0; 30 ULONG Size; 31 32 /* Make sure we got a valid length */ 33 ASSERT(Length != 0); 34 35 /* Fail if allocation is over 2GB */ 36 if (Length & 0x80000000) return NULL; 37 38 /* Calculate the number of pages for the allocation */ 39 Size = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length); 40 if (Size > 23) 41 { 42 /* This is bigger then our fixed-size MDLs. Calculate real size */ 43 Size *= sizeof(PFN_NUMBER); 44 Size += sizeof(MDL); 45 if (Size > MAXUSHORT) return NULL; 46 } 47 else 48 { 49 /* Use an internal fixed MDL size */ 50 Size = (23 * sizeof(PFN_NUMBER)) + sizeof(MDL); 51 Flags |= MDL_ALLOCATED_FIXED_SIZE; 52 53 /* Allocate one from the lookaside list */ 54 Mdl = IopAllocateMdlFromLookaside(LookasideMdlList); 55 } 56 57 /* Check if we don't have an mdl yet */ 58 if (!Mdl) 59 { 60 /* Allocate one from pool */ 61 Mdl = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_MDL); 62 if (!Mdl) return NULL; 63 } 64 65 /* Initialize it */ 66 MmInitializeMdl(Mdl, VirtualAddress, Length); 67 Mdl->MdlFlags |= Flags; 68 69 /* Check if an IRP was given too */ 70 if (Irp) 71 { 72 /* Check if it came with a secondary buffer */ 73 if (SecondaryBuffer) 74 { 75 /* Insert the MDL at the end */ 76 p = Irp->MdlAddress; 77 while (p->Next) p = p->Next; 78 p->Next = Mdl; 79 } 80 else 81 { 82 /* Otherwise, insert it directly */ 83 Irp->MdlAddress = Mdl; 84 } 85 } 86 87 /* Return the allocated mdl */ 88 return Mdl; 89 } 90 91 /* 92 * @implemented 93 */ 94 VOID 95 NTAPI 96 IoBuildPartialMdl(IN PMDL SourceMdl, 97 IN PMDL TargetMdl, 98 IN PVOID VirtualAddress, 99 IN ULONG Length) 100 { 101 PPFN_NUMBER TargetPages = (PPFN_NUMBER)(TargetMdl + 1); 102 PPFN_NUMBER SourcePages = (PPFN_NUMBER)(SourceMdl + 1); 103 ULONG Offset; 104 ULONG FlagsMask = (MDL_IO_PAGE_READ | 105 MDL_SOURCE_IS_NONPAGED_POOL | 106 MDL_MAPPED_TO_SYSTEM_VA | 107 MDL_IO_SPACE); 108 109 /* Calculate the offset */ 110 Offset = (ULONG)((ULONG_PTR)VirtualAddress - 111 (ULONG_PTR)SourceMdl->StartVa) - 112 SourceMdl->ByteOffset; 113 114 /* Check if we don't have a length and calculate it */ 115 if (!Length) Length = SourceMdl->ByteCount - Offset; 116 117 /* Write the process, start VA and byte data */ 118 TargetMdl->StartVa = (PVOID)PAGE_ROUND_DOWN(VirtualAddress); 119 TargetMdl->Process = SourceMdl->Process; 120 TargetMdl->ByteCount = Length; 121 TargetMdl->ByteOffset = BYTE_OFFSET(VirtualAddress); 122 123 /* Recalculate the length in pages */ 124 Length = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length); 125 126 /* Set the MDL Flags */ 127 TargetMdl->MdlFlags &= (MDL_ALLOCATED_FIXED_SIZE | MDL_ALLOCATED_MUST_SUCCEED); 128 TargetMdl->MdlFlags |= SourceMdl->MdlFlags & FlagsMask; 129 TargetMdl->MdlFlags |= MDL_PARTIAL; 130 131 /* Set the mapped VA */ 132 TargetMdl->MappedSystemVa = (PCHAR)SourceMdl->MappedSystemVa + Offset; 133 134 /* Now do the copy */ 135 Offset = (ULONG)(((ULONG_PTR)TargetMdl->StartVa - 136 (ULONG_PTR)SourceMdl->StartVa) >> PAGE_SHIFT); 137 SourcePages += Offset; 138 RtlCopyMemory(TargetPages, SourcePages, Length * sizeof(PFN_NUMBER)); 139 } 140 141 /* 142 * @implemented 143 */ 144 VOID 145 NTAPI 146 IoFreeMdl(PMDL Mdl) 147 { 148 /* Tell Mm to reuse the MDL */ 149 MmPrepareMdlForReuse(Mdl); 150 151 /* Check if this was a pool allocation */ 152 if (!(Mdl->MdlFlags & MDL_ALLOCATED_FIXED_SIZE)) 153 { 154 /* Free it from the pool */ 155 ExFreePoolWithTag(Mdl, TAG_MDL); 156 } 157 else 158 { 159 /* Free it from the lookaside */ 160 IopFreeMdlFromLookaside(Mdl, LookasideMdlList); 161 } 162 } 163 164 /* EOF */ 165