migrate substitution keywords to SVN
[reactos.git] / reactos / ntoskrnl / io / mdl.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/mdl.c
6 * PURPOSE: Io manager mdl functions
7 * PROGRAMMER: David Welch (welch@mcmail.com)
8 * UPDATE HISTORY:
9 * Created 22/05/98
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ntoskrnl.h>
15 #define NDEBUG
16 #include <internal/debug.h>
17
18 /* GLOBALS *******************************************************************/
19
20 #define TAG_MDL TAG('M', 'D', 'L', ' ')
21
22 /* FUNCTIONS *****************************************************************/
23
24 /*
25 * @implemented
26 */
27 PMDL
28 STDCALL
29 IoAllocateMdl(PVOID VirtualAddress,
30 ULONG Length,
31 BOOLEAN SecondaryBuffer,
32 BOOLEAN ChargeQuota,
33 PIRP Irp)
34 {
35 PMDL Mdl;
36
37 if (ChargeQuota)
38 {
39 // Mdl = ExAllocatePoolWithQuota(NonPagedPool,
40 // MmSizeOfMdl(VirtualAddress,Length));
41 Mdl = ExAllocatePoolWithTag(NonPagedPool,
42 MmSizeOfMdl(VirtualAddress,Length),
43 TAG_MDL);
44 }
45 else
46 {
47 Mdl = ExAllocatePoolWithTag(NonPagedPool,
48 MmSizeOfMdl(VirtualAddress,Length),
49 TAG_MDL);
50 }
51 MmInitializeMdl(Mdl, (char*)VirtualAddress, Length);
52
53 if (Irp)
54 {
55 if (SecondaryBuffer)
56 {
57 ASSERT(Irp->MdlAddress);
58
59 /* FIXME: add to end of list maybe?? */
60 Mdl->Next = Irp->MdlAddress->Next;
61 Irp->MdlAddress->Next = Mdl;
62 }
63 else
64 {
65 /*
66 * What if there's allready an mdl at Irp->MdlAddress?
67 * Is that bad and should we do something about it?
68 */
69 Irp->MdlAddress = Mdl;
70 }
71 }
72
73 return(Mdl);
74 }
75
76 /*
77 * @implemented
78 *
79 * You must IoFreeMdl the slave before freeing the master.
80 *
81 * IoBuildPartialMdl is more similar to MmBuildMdlForNonPagedPool, the difference
82 * is that the former takes the physical addresses from the master MDL, while the
83 * latter - from the known location of the NPP.
84 */
85 VOID
86 STDCALL
87 IoBuildPartialMdl(PMDL SourceMdl,
88 PMDL TargetMdl,
89 PVOID VirtualAddress,
90 ULONG Length)
91 {
92 PPFN_TYPE TargetPages = (PPFN_TYPE)(TargetMdl + 1);
93 PPFN_TYPE SourcePages = (PPFN_TYPE)(SourceMdl + 1);
94 ULONG Count;
95 ULONG Delta;
96
97 DPRINT("VirtualAddress %x, SourceMdl->StartVa %x, SourceMdl->MappedSystemVa %x\n",
98 VirtualAddress, SourceMdl->StartVa, SourceMdl->MappedSystemVa);
99
100 TargetMdl->StartVa = (PVOID)PAGE_ROUND_DOWN(VirtualAddress);
101 TargetMdl->ByteOffset = (ULONG_PTR)VirtualAddress - (ULONG_PTR)TargetMdl->StartVa;
102 TargetMdl->ByteCount = Length;
103 TargetMdl->Process = SourceMdl->Process;
104 Delta = (ULONG_PTR)VirtualAddress - ((ULONG_PTR)SourceMdl->StartVa + SourceMdl->ByteOffset);
105 TargetMdl->MappedSystemVa = (char*)SourceMdl->MappedSystemVa + Delta;
106
107 TargetMdl->MdlFlags = SourceMdl->MdlFlags & (MDL_IO_PAGE_READ|MDL_SOURCE_IS_NONPAGED_POOL|MDL_MAPPED_TO_SYSTEM_VA);
108 TargetMdl->MdlFlags |= MDL_PARTIAL;
109
110 Delta = ((ULONG_PTR)TargetMdl->StartVa - (ULONG_PTR)SourceMdl->StartVa) / PAGE_SIZE;
111 Count = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress,Length);
112
113 SourcePages += Delta;
114
115 DPRINT("Delta %d, Count %d\n", Delta, Count);
116
117 memcpy(TargetPages, SourcePages, Count * sizeof(PFN_TYPE));
118
119 }
120
121 /*
122 * @implemented
123 */
124 VOID STDCALL
125 IoFreeMdl(PMDL Mdl)
126 {
127 /*
128 * This unmaps partial mdl's from kernel space but also asserts that non-partial
129 * mdl's isn't still mapped into kernel space.
130 */
131 MmPrepareMdlForReuse(Mdl);
132
133 ExFreePool(Mdl);
134 }
135
136
137 /* EOF */