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