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