All task switching is done in software.
[reactos.git] / reactos / ntoskrnl / io / irp.c
1 /* $Id: irp.c,v 1.33 2000/12/23 02:37:39 dwelch Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/irp.c
6 * PURPOSE: Handle IRPs
7 * PROGRAMMER: David Welch (welch@mcmail.com)
8 * UPDATE HISTORY:
9 * 24/05/98: Created
10 */
11
12 /* NOTES *******************************************************************
13 *
14 * Layout of an IRP
15 *
16 * ################
17 * # Headers #
18 * ################
19 * # #
20 * # Variable #
21 * # length list #
22 * # of io stack #
23 * # locations #
24 * # #
25 * ################
26 *
27 *
28 *
29 */
30
31 /* INCLUDES ****************************************************************/
32
33 #include <ddk/ntddk.h>
34 #include <internal/io.h>
35 #include <internal/ps.h>
36
37 #define NDEBUG
38 #include <internal/debug.h>
39
40 /* FUNCTIONS ****************************************************************/
41
42
43 VOID STDCALL
44 IoFreeIrp (PIRP Irp)
45 /*
46 * FUNCTION: Releases a caller allocated irp
47 * ARGUMENTS:
48 * Irp = Irp to free
49 */
50 {
51 ExFreePool(Irp);
52 }
53
54
55 PIRP STDCALL
56 IoMakeAssociatedIrp (PIRP Irp, CCHAR StackSize)
57 /*
58 * FUNCTION: Allocates and initializes an irp to associated with a master irp
59 * ARGUMENTS:
60 * Irp = Master irp
61 * StackSize = Number of stack locations to be allocated in the irp
62 * RETURNS: The irp allocated
63 */
64 {
65 PIRP AssocIrp;
66
67 AssocIrp = IoAllocateIrp(StackSize,FALSE);
68 UNIMPLEMENTED;
69 }
70
71
72 VOID STDCALL
73 IoInitializeIrp (PIRP Irp, USHORT PacketSize, CCHAR StackSize)
74 /*
75 * FUNCTION: Initalizes an irp allocated by the caller
76 * ARGUMENTS:
77 * Irp = IRP to initalize
78 * PacketSize = Size in bytes of the IRP
79 * StackSize = Number of stack locations in the IRP
80 */
81 {
82 assert(Irp != NULL);
83
84 memset(Irp, 0, PacketSize);
85 Irp->Size = PacketSize;
86 Irp->StackCount = StackSize;
87 Irp->CurrentLocation = StackSize;
88 Irp->Tail.Overlay.CurrentStackLocation = IoGetCurrentIrpStackLocation(Irp);
89 }
90
91
92 NTSTATUS FASTCALL
93 IofCallDriver (PDEVICE_OBJECT DeviceObject, PIRP Irp)
94 /*
95 * FUNCTION: Sends an IRP to the next lower driver
96 */
97 {
98 NTSTATUS Status;
99 PDRIVER_OBJECT DriverObject;
100 PIO_STACK_LOCATION Param;
101
102 // DPRINT("IoCallDriver(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
103
104 DriverObject = DeviceObject->DriverObject;
105 Param = IoGetNextIrpStackLocation(Irp);
106
107 Irp->Tail.Overlay.CurrentStackLocation--;
108 Irp->CurrentLocation--;
109
110 // DPRINT("MajorFunction %d\n", Param->MajorFunction);
111 // DPRINT("DriverObject->MajorFunction[Param->MajorFunction] %x\n",
112 // DriverObject->MajorFunction[Param->MajorFunction]);
113 Status = DriverObject->MajorFunction[Param->MajorFunction](DeviceObject,
114 Irp);
115 return Status;
116 }
117
118
119 NTSTATUS
120 STDCALL
121 IoCallDriver (PDEVICE_OBJECT DeviceObject, PIRP Irp)
122 {
123 return IofCallDriver (
124 DeviceObject,
125 Irp
126 );
127 }
128
129
130 PIRP
131 STDCALL
132 IoAllocateIrp (CCHAR StackSize, BOOLEAN ChargeQuota)
133 /*
134 * FUNCTION: Allocates an IRP
135 * ARGUMENTS:
136 * StackSize = the size of the stack required for the irp
137 * ChargeQuota = Charge allocation to current threads quota
138 * RETURNS: Irp allocated
139 */
140 {
141 PIRP Irp;
142
143 #if 0
144 DbgPrint("IoAllocateIrp(StackSize %d ChargeQuota %d)\n",
145 StackSize,
146 ChargeQuota);
147 KeDumpStackFrames(0,8);
148 #endif
149
150 if (ChargeQuota)
151 {
152 // Irp = ExAllocatePoolWithQuota(NonPagedPool,IoSizeOfIrp(StackSize));
153 Irp = ExAllocatePool(NonPagedPool,IoSizeOfIrp(StackSize));
154 }
155 else
156 {
157 Irp = ExAllocatePool(NonPagedPool,IoSizeOfIrp(StackSize));
158 }
159
160 if (Irp==NULL)
161 {
162 return(NULL);
163 }
164
165 IoInitializeIrp(Irp, IoSizeOfIrp(StackSize), StackSize);
166
167 // DPRINT("Irp %x Irp->StackPtr %d\n", Irp, Irp->CurrentLocation);
168
169 return Irp;
170 }
171
172
173 VOID IopCompleteRequest(struct _KAPC* Apc,
174 PKNORMAL_ROUTINE* NormalRoutine,
175 PVOID* NormalContext,
176 PVOID* SystemArgument1,
177 PVOID* SystemArgument2)
178 {
179 DPRINT("IopCompleteRequest(Apc %x, SystemArgument1 %x, "
180 "(*SystemArgument1) %x\n", Apc, SystemArgument1,
181 *SystemArgument1);
182 IoSecondStageCompletion((PIRP)(*SystemArgument1),
183 (KPRIORITY)(*SystemArgument2));
184 }
185
186
187 VOID
188 FASTCALL
189 IofCompleteRequest (PIRP Irp, CCHAR PriorityBoost)
190 /*
191 * FUNCTION: Indicates the caller has finished all processing for a given
192 * I/O request and is returning the given IRP to the I/O manager
193 * ARGUMENTS:
194 * Irp = Irp to be cancelled
195 * PriorityBoost = Increment by which to boost the priority of the
196 * thread making the request
197 */
198 {
199 unsigned int i;
200 NTSTATUS Status;
201 PKTHREAD Thread;
202
203 DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d) Event %x THread %x\n",
204 Irp,PriorityBoost, Irp->UserEvent, PsGetCurrentThread());
205
206 for (i=0;i<Irp->StackCount;i++)
207 {
208 if (Irp->Stack[i].CompletionRoutine != NULL)
209 {
210 Status = Irp->Stack[i].CompletionRoutine(
211 Irp->Stack[i].DeviceObject,
212 Irp,
213 Irp->Stack[i].CompletionContext);
214 if (Status == STATUS_MORE_PROCESSING_REQUIRED)
215 {
216 return;
217 }
218 }
219 if (Irp->Stack[i].Control & SL_PENDING_RETURNED)
220 {
221 Irp->PendingReturned = TRUE;
222 }
223 }
224
225 if (Irp->PendingReturned)
226 {
227 DPRINT("Dispatching APC\n");
228 Thread = &Irp->Tail.Overlay.Thread->Tcb;
229 KeInitializeApc(&Irp->Tail.Apc,
230 Thread,
231 0,
232 IopCompleteRequest,
233 NULL,
234 (PKNORMAL_ROUTINE)
235 NULL,
236 KernelMode,
237 NULL);
238 KeInsertQueueApc(&Irp->Tail.Apc,
239 (PVOID)Irp,
240 (PVOID)(ULONG)PriorityBoost,
241 KernelMode);
242 DPRINT("Finished dispatching APC\n");
243 }
244 else
245 {
246 DPRINT("Calling completion routine directly\n");
247 IoSecondStageCompletion(Irp,PriorityBoost);
248 DPRINT("Finished completition routine\n");
249 }
250 }
251
252
253 VOID
254 STDCALL
255 IoCompleteRequest (PIRP Irp, CCHAR PriorityBoost)
256 {
257 IofCompleteRequest (
258 Irp,
259 PriorityBoost
260 );
261 }
262
263
264 /**********************************************************************
265 * NAME EXPORTED
266 * IoIsOperationSynchronous@4
267 *
268 * DESCRIPTION
269 * Check if the I/O operation associated with the given IRP
270 * is synchronous.
271 *
272 * ARGUMENTS
273 * Irp Packet to check.
274 *
275 * RETURN VALUE
276 * TRUE if Irp's operation is synchronous; otherwise FALSE.
277 */
278 BOOLEAN
279 STDCALL
280 IoIsOperationSynchronous (
281 IN PIRP Irp
282 )
283 {
284 ULONG Flags = 0;
285 PFILE_OBJECT FileObject = NULL;
286
287 /*
288 * Check the associated FILE_OBJECT's
289 * flags first.
290 */
291 FileObject = Irp->Tail.Overlay.OriginalFileObject;
292 if (!(FO_SYNCHRONOUS_IO & FileObject->Flags))
293 {
294 /* Check IRP's flags. */
295 Flags = Irp->Flags;
296 if (!( (IRP_SYNCHRONOUS_API | IRP_SYNCHRONOUS_PAGING_IO)
297 & Flags
298 ))
299 {
300 return FALSE;
301 }
302 }
303 /*
304 * Check more IRP's flags.
305 */
306 Flags = Irp->Flags;
307 if ( !(IRP_MOUNT_COMPLETION & Flags)
308 || (IRP_SYNCHRONOUS_PAGING_IO & Flags)
309 )
310 {
311 return TRUE;
312 }
313 /*
314 * Otherwise, it is an
315 * asynchronous operation.
316 */
317 return FALSE;
318 }
319
320
321 VOID
322 STDCALL
323 IoEnqueueIrp (
324 PIRP Irp
325 )
326 {
327 UNIMPLEMENTED;
328 }
329
330
331 VOID
332 STDCALL
333 IoSetTopLevelIrp (
334 IN PIRP Irp
335 )
336 {
337 PETHREAD Thread;
338
339 Thread = PsGetCurrentThread ();
340 Thread->TopLevelIrp->TopLevelIrp = Irp;
341 }
342
343
344 PIRP
345 STDCALL
346 IoGetTopLevelIrp (
347 VOID
348 )
349 {
350 return (PsGetCurrentThread ()->TopLevelIrp->TopLevelIrp);
351 }
352
353
354 VOID
355 STDCALL
356 IoQueueThreadIrp (
357 PVOID Unknown0
358 )
359 {
360 UNIMPLEMENTED;
361 }
362
363 /* EOF */