Remove some debug messages at boot (DPRINT1 changed to DPRINT)
[reactos.git] / reactos / ntoskrnl / io / iomgr.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/io/iomgr.c
5 * PURPOSE: I/O Manager Initialization and Misc Utility Functions
6 *
7 * PROGRAMMERS: David Welch (welch@mcmail.com)
8 */
9
10 /* INCLUDES ****************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <internal/debug.h>
15
16 /* DATA ********************************************************************/
17
18 POBJECT_TYPE EXPORTED IoDeviceObjectType = NULL;
19 POBJECT_TYPE EXPORTED IoFileObjectType = NULL;
20 extern POBJECT_TYPE IoControllerObjectType;
21 ULONG EXPORTED IoReadOperationCount = 0;
22 ULONGLONG EXPORTED IoReadTransferCount = 0;
23 ULONG EXPORTED IoWriteOperationCount = 0;
24 ULONGLONG EXPORTED IoWriteTransferCount = 0;
25 ULONG IoOtherOperationCount = 0;
26 ULONGLONG IoOtherTransferCount = 0;
27 KSPIN_LOCK EXPORTED IoStatisticsLock = 0;
28
29 GENERIC_MAPPING IopFileMapping = {
30 FILE_GENERIC_READ,
31 FILE_GENERIC_WRITE,
32 FILE_GENERIC_EXECUTE,
33 FILE_ALL_ACCESS};
34
35 static KSPIN_LOCK CancelSpinLock;
36 extern LIST_ENTRY ShutdownListHead;
37 extern KSPIN_LOCK ShutdownListLock;
38 extern NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside;
39 NPAGED_LOOKASIDE_LIST IoLargeIrpLookaside;
40 NPAGED_LOOKASIDE_LIST IoSmallIrpLookaside;
41
42 /* INIT FUNCTIONS ************************************************************/
43
44 VOID
45 INIT_FUNCTION
46 IoInitCancelHandling(VOID)
47 {
48 KeInitializeSpinLock(&CancelSpinLock);
49 }
50
51 VOID
52 INIT_FUNCTION
53 IoInitShutdownNotification (VOID)
54 {
55 InitializeListHead(&ShutdownListHead);
56 KeInitializeSpinLock(&ShutdownListLock);
57 }
58
59 VOID
60 INIT_FUNCTION
61 IopInitLookasideLists(VOID)
62 {
63 ULONG LargeIrpSize, SmallIrpSize;
64 ULONG i;
65 PKPRCB Prcb;
66 PNPAGED_LOOKASIDE_LIST CurrentList = NULL;
67
68 /* Calculate the sizes */
69 LargeIrpSize = sizeof(IRP) + (8 * sizeof(IO_STACK_LOCATION));
70 SmallIrpSize = sizeof(IRP) + sizeof(IO_STACK_LOCATION);
71
72 /* Initialize the Lookaside List for Large IRPs */
73 ExInitializeNPagedLookasideList(&IoLargeIrpLookaside,
74 NULL,
75 NULL,
76 0,
77 LargeIrpSize,
78 IO_LARGEIRP,
79 0);
80
81 /* Initialize the Lookaside List for Small IRPs */
82 ExInitializeNPagedLookasideList(&IoSmallIrpLookaside,
83 NULL,
84 NULL,
85 0,
86 SmallIrpSize,
87 IO_SMALLIRP,
88 0);
89
90 /* Initialize the Lookaside List for I\O Completion */
91 ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside,
92 NULL,
93 NULL,
94 0,
95 sizeof(IO_COMPLETION_PACKET),
96 IOC_TAG1,
97 0);
98
99 /* Now allocate the per-processor lists */
100 for (i = 0; i < KeNumberProcessors; i++)
101 {
102 /* Get the PRCB for this CPU */
103 Prcb = ((PKPCR)(KPCR_BASE + i * PAGE_SIZE))->Prcb;
104 DPRINT("Setting up lookaside for CPU: %x, PRCB: %p\n", i, Prcb);
105
106 /* Set the Large IRP List */
107 Prcb->PPLookasideList[LookasideLargeIrpList].L = &IoLargeIrpLookaside.L;
108 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
109 sizeof(NPAGED_LOOKASIDE_LIST),
110 IO_LARGEIRP_CPU);
111 if (CurrentList)
112 {
113 /* Initialize the Lookaside List for Large IRPs */
114 ExInitializeNPagedLookasideList(CurrentList,
115 NULL,
116 NULL,
117 0,
118 LargeIrpSize,
119 IO_LARGEIRP_CPU,
120 0);
121 }
122 else
123 {
124 CurrentList = &IoLargeIrpLookaside;
125 }
126 Prcb->PPLookasideList[LookasideLargeIrpList].P = &CurrentList->L;
127
128 /* Set the Small IRP List */
129 Prcb->PPLookasideList[LookasideSmallIrpList].L = &IoSmallIrpLookaside.L;
130 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
131 sizeof(NPAGED_LOOKASIDE_LIST),
132 IO_SMALLIRP_CPU);
133 if (CurrentList)
134 {
135 /* Initialize the Lookaside List for Large IRPs */
136 ExInitializeNPagedLookasideList(CurrentList,
137 NULL,
138 NULL,
139 0,
140 SmallIrpSize,
141 IO_SMALLIRP_CPU,
142 0);
143 }
144 else
145 {
146 CurrentList = &IoSmallIrpLookaside;
147 }
148 Prcb->PPLookasideList[LookasideSmallIrpList].P = &CurrentList->L;
149
150 /* Set the I/O Completion List */
151 Prcb->PPLookasideList[LookasideCompletionList].L = &IoCompletionPacketLookaside.L;
152 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
153 sizeof(NPAGED_LOOKASIDE_LIST),
154 IO_SMALLIRP_CPU);
155 if (CurrentList)
156 {
157 /* Initialize the Lookaside List for Large IRPs */
158 ExInitializeNPagedLookasideList(CurrentList,
159 NULL,
160 NULL,
161 0,
162 SmallIrpSize,
163 IOC_CPU,
164 0);
165 }
166 else
167 {
168 CurrentList = &IoCompletionPacketLookaside;
169 }
170 Prcb->PPLookasideList[LookasideCompletionList].P = &CurrentList->L;
171 }
172
173 DPRINT("Done allocation\n");
174 }
175
176 VOID
177 INIT_FUNCTION
178 IoInit (VOID)
179 {
180 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
181 UNICODE_STRING Name;
182 OBJECT_ATTRIBUTES ObjectAttributes;
183 UNICODE_STRING DirName;
184 UNICODE_STRING LinkName;
185 HANDLE Handle;
186
187 IopInitDriverImplementation();
188
189 DPRINT("Creating Device Object Type\n");
190
191 /* Initialize the Driver object type */
192 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
193 RtlInitUnicodeString(&Name, L"Device");
194 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
195 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(DEVICE_OBJECT);
196 ObjectTypeInitializer.PoolType = NonPagedPool;
197 ObjectTypeInitializer.ValidAccessMask = FILE_ALL_ACCESS;
198 ObjectTypeInitializer.UseDefaultObject = TRUE;
199 ObjectTypeInitializer.GenericMapping = IopFileMapping;
200 ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &IoDeviceObjectType);
201
202 /* Do the Adapter Type */
203 RtlInitUnicodeString(&Name, L"Adapter");
204 ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &IoAdapterObjectType);
205
206 /* Do the Controller Type */
207 RtlInitUnicodeString(&Name, L"Controller");
208 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(CONTROLLER_OBJECT);
209 ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &IoControllerObjectType);
210
211 /* Initialize the File object type */
212 RtlInitUnicodeString(&Name, L"File");
213 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
214 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(FILE_OBJECT);
215 ObjectTypeInitializer.CloseProcedure = IopCloseFile;
216 ObjectTypeInitializer.DeleteProcedure = IopDeleteFile;
217 ObjectTypeInitializer.SecurityProcedure = IopSecurityFile;
218 ObjectTypeInitializer.QueryNameProcedure = IopQueryNameFile;
219 ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &IoFileObjectType);
220
221 /*
222 * Create the '\Driver' object directory
223 */
224 RtlRosInitUnicodeStringFromLiteral(&DirName, L"\\Driver");
225 InitializeObjectAttributes(&ObjectAttributes,
226 &DirName,
227 0,
228 NULL,
229 NULL);
230 ZwCreateDirectoryObject(&Handle,
231 0,
232 &ObjectAttributes);
233
234 /*
235 * Create the '\FileSystem' object directory
236 */
237 RtlRosInitUnicodeStringFromLiteral(&DirName,
238 L"\\FileSystem");
239 InitializeObjectAttributes(&ObjectAttributes,
240 &DirName,
241 0,
242 NULL,
243 NULL);
244 ZwCreateDirectoryObject(&Handle,
245 0,
246 &ObjectAttributes);
247
248 /*
249 * Create the '\Device' directory
250 */
251 RtlRosInitUnicodeStringFromLiteral(&DirName,
252 L"\\Device");
253 InitializeObjectAttributes(&ObjectAttributes,
254 &DirName,
255 0,
256 NULL,
257 NULL);
258 ZwCreateDirectoryObject(&Handle,
259 0,
260 &ObjectAttributes);
261
262 /*
263 * Create the '\??' directory
264 */
265 RtlRosInitUnicodeStringFromLiteral(&DirName,
266 L"\\??");
267 InitializeObjectAttributes(&ObjectAttributes,
268 &DirName,
269 0,
270 NULL,
271 NULL);
272 ZwCreateDirectoryObject(&Handle,
273 0,
274 &ObjectAttributes);
275
276 /*
277 * Create the '\ArcName' directory
278 */
279 RtlRosInitUnicodeStringFromLiteral(&DirName,
280 L"\\ArcName");
281 InitializeObjectAttributes(&ObjectAttributes,
282 &DirName,
283 0,
284 NULL,
285 NULL);
286 ZwCreateDirectoryObject(&Handle,
287 0,
288 &ObjectAttributes);
289
290 /*
291 * Initialize remaining subsubsystem
292 */
293 IoInitCancelHandling();
294 IoInitFileSystemImplementation();
295 IoInitVpbImplementation();
296 IoInitShutdownNotification();
297 IopInitPnpNotificationImplementation();
298 IopInitErrorLog();
299 IopInitTimerImplementation();
300 IopInitIoCompletionImplementation();
301 IopInitLookasideLists();
302
303 /*
304 * Create link from '\DosDevices' to '\??' directory
305 */
306 RtlRosInitUnicodeStringFromLiteral(&LinkName,
307 L"\\DosDevices");
308 RtlRosInitUnicodeStringFromLiteral(&DirName,
309 L"\\??");
310 IoCreateSymbolicLink(&LinkName,
311 &DirName);
312
313 /*
314 * Initialize PnP manager
315 */
316 PnpInit();
317 }
318
319 VOID
320 INIT_FUNCTION
321 IoInit2(BOOLEAN BootLog)
322 {
323 PDEVICE_NODE DeviceNode;
324 PDRIVER_OBJECT DriverObject;
325 MODULE_OBJECT ModuleObject;
326 NTSTATUS Status;
327
328 IoCreateDriverList();
329
330 KeInitializeSpinLock (&IoStatisticsLock);
331
332 /* Initialize raw filesystem driver */
333
334 /* Use IopRootDeviceNode for now */
335 Status = IopCreateDeviceNode(IopRootDeviceNode,
336 NULL,
337 &DeviceNode);
338 if (!NT_SUCCESS(Status))
339 {
340 CPRINT("IopCreateDeviceNode() failed with status (%x)\n", Status);
341 return;
342 }
343
344 ModuleObject.Base = NULL;
345 ModuleObject.Length = 0;
346 ModuleObject.EntryPoint = RawFsDriverEntry;
347
348 Status = IopInitializeDriverModule(
349 DeviceNode,
350 &ModuleObject,
351 &DeviceNode->ServiceName,
352 TRUE,
353 &DriverObject);
354 if (!NT_SUCCESS(Status))
355 {
356 IopFreeDeviceNode(DeviceNode);
357 CPRINT("IopInitializeDriver() failed with status (%x)\n", Status);
358 return;
359 }
360
361 Status = IopInitializeDevice(DeviceNode, DriverObject);
362 if (!NT_SUCCESS(Status))
363 {
364 IopFreeDeviceNode(DeviceNode);
365 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status);
366 return;
367 }
368
369 Status = IopStartDevice(DeviceNode);
370 if (!NT_SUCCESS(Status))
371 {
372 IopFreeDeviceNode(DeviceNode);
373 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status);
374 return;
375 }
376
377 /*
378 * Initialize PnP root releations
379 */
380 IopInvalidateDeviceRelations(
381 IopRootDeviceNode,
382 BusRelations);
383
384 /* Start boot logging */
385 IopInitBootLog(BootLog);
386
387 /* Load boot start drivers */
388 IopInitializeBootDrivers();
389 }
390
391 VOID
392 STDCALL
393 INIT_FUNCTION
394 IoInit3(VOID)
395 {
396 NTSTATUS Status;
397
398 /* Create ARC names for boot devices */
399 IoCreateArcNames();
400
401 /* Create the SystemRoot symbolic link */
402 DPRINT("CommandLine: %s\n", (PCHAR)KeLoaderBlock.CommandLine);
403 Status = IoCreateSystemRootLink((PCHAR)KeLoaderBlock.CommandLine);
404 if (!NT_SUCCESS(Status)) {
405 CPRINT("IoCreateSystemRootLink FAILED: (0x%x) - ", Status);
406 KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE);
407 }
408
409 /* Read KDB Data */
410 KdbInit();
411
412 /* I/O is now setup for disk access, so phase 3 */
413 KdInitSystem(3, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
414
415 /* Load services for devices found by PnP manager */
416 IopInitializePnpServices(IopRootDeviceNode, FALSE);
417
418 /* Load system start drivers */
419 IopInitializeSystemDrivers();
420 IoDestroyDriverList();
421
422 /* Stop boot logging */
423 IopStopBootLog();
424
425 /* Assign drive letters */
426 IoAssignDriveLetters((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
427 NULL,
428 NULL,
429 NULL);
430 }
431
432 /* FUNCTIONS *****************************************************************/
433
434 /*
435 * @implemented
436 */
437 VOID
438 STDCALL
439 IoAcquireCancelSpinLock(PKIRQL Irql)
440 {
441 KeAcquireSpinLock(&CancelSpinLock,Irql);
442 }
443
444 /*
445 * @implemented
446 */
447 PVOID
448 STDCALL
449 IoGetInitialStack(VOID)
450 {
451 return(PsGetCurrentThread()->Tcb.InitialStack);
452 }
453
454 /*
455 * @implemented
456 */
457 VOID
458 STDCALL
459 IoGetStackLimits(OUT PULONG LowLimit,
460 OUT PULONG HighLimit)
461 {
462 *LowLimit = (ULONG)NtCurrentTeb()->Tib.StackLimit;
463 *HighLimit = (ULONG)NtCurrentTeb()->Tib.StackBase;
464 }
465
466 /*
467 * @implemented
468 */
469 BOOLEAN
470 STDCALL
471 IoIsSystemThread(IN PETHREAD Thread)
472 {
473 /* Call the Ps Function */
474 return PsIsSystemThread(Thread);
475 }
476
477 /*
478 * @implemented
479 */
480 BOOLEAN STDCALL
481 IoIsWdmVersionAvailable(IN UCHAR MajorVersion,
482 IN UCHAR MinorVersion)
483 {
484 if (MajorVersion <= 1 && MinorVersion <= 10)
485 return TRUE;
486 return FALSE;
487 }
488
489 /*
490 * @implemented
491 */
492 VOID
493 STDCALL
494 IoReleaseCancelSpinLock(KIRQL Irql)
495 {
496 KeReleaseSpinLock(&CancelSpinLock,Irql);
497 }
498
499 /*
500 * @implemented
501 */
502 PEPROCESS
503 STDCALL
504 IoThreadToProcess(IN PETHREAD Thread)
505 {
506 return(Thread->ThreadsProcess);
507 }
508
509 /* EOF */