Synchronize with trunk revision 59636 (just before Alex's CreateProcess revamp).
[reactos.git] / drivers / bus / pci / pci.c
1 /*
2 * PROJECT: ReactOS PCI Bus driver
3 * FILE: pci.c
4 * PURPOSE: Driver entry
5 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
6 * UPDATE HISTORY:
7 * 10-09-2001 CSH Created
8 */
9
10 #define INITGUID
11 #include "pci.h"
12
13 #ifndef NDEBUG
14 #define NDEBUG
15 #endif
16 #include <debug.h>
17
18 static DRIVER_DISPATCH PciDispatchDeviceControl;
19 static NTSTATUS NTAPI PciDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
20
21 static DRIVER_ADD_DEVICE PciAddDevice;
22 static NTSTATUS NTAPI PciAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject);
23
24 static DRIVER_DISPATCH PciPowerControl;
25 static NTSTATUS NTAPI PciPowerControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
26
27 static DRIVER_DISPATCH PciPnpControl;
28 static NTSTATUS NTAPI PciPnpControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
29
30
31 #ifdef ALLOC_PRAGMA
32
33 // Make the initialization routines discardable, so that they
34 // don't waste space
35
36 #pragma alloc_text(init, DriverEntry)
37
38 #endif /* ALLOC_PRAGMA */
39
40 /*** PUBLIC ******************************************************************/
41
42 PPCI_DRIVER_EXTENSION DriverExtension = NULL;
43
44 /*** PRIVATE *****************************************************************/
45
46 static NTSTATUS
47 NTAPI
48 PciDispatchDeviceControl(
49 IN PDEVICE_OBJECT DeviceObject,
50 IN PIRP Irp)
51 {
52 PIO_STACK_LOCATION IrpSp;
53 NTSTATUS Status;
54
55 UNREFERENCED_PARAMETER(DeviceObject);
56 DPRINT("Called. IRP is at (0x%p)\n", Irp);
57
58 Irp->IoStatus.Information = 0;
59
60 IrpSp = IoGetCurrentIrpStackLocation(Irp);
61 switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
62 default:
63 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->Parameters.DeviceIoControl.IoControlCode);
64 Status = STATUS_NOT_IMPLEMENTED;
65 break;
66 }
67
68 if (Status != STATUS_PENDING) {
69 Irp->IoStatus.Status = Status;
70
71 DPRINT("Completing IRP at 0x%p\n", Irp);
72
73 IoCompleteRequest(Irp, IO_NO_INCREMENT);
74 }
75
76 DPRINT("Leaving. Status 0x%X\n", Status);
77
78 return Status;
79 }
80
81
82 static NTSTATUS
83 NTAPI
84 PciPnpControl(
85 IN PDEVICE_OBJECT DeviceObject,
86 IN PIRP Irp)
87 /*
88 * FUNCTION: Handle Plug and Play IRPs
89 * ARGUMENTS:
90 * DeviceObject = Pointer to PDO or FDO
91 * Irp = Pointer to IRP that should be handled
92 * RETURNS:
93 * Status
94 */
95 {
96 PCOMMON_DEVICE_EXTENSION DeviceExtension;
97 NTSTATUS Status;
98
99 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
100
101 DPRINT("IsFDO %u\n", DeviceExtension->IsFDO);
102
103 if (DeviceExtension->IsFDO) {
104 Status = FdoPnpControl(DeviceObject, Irp);
105 } else {
106 Status = PdoPnpControl(DeviceObject, Irp);
107 }
108
109 return Status;
110 }
111
112
113 static NTSTATUS
114 NTAPI
115 PciPowerControl(
116 IN PDEVICE_OBJECT DeviceObject,
117 IN PIRP Irp)
118 /*
119 * FUNCTION: Handle power management IRPs
120 * ARGUMENTS:
121 * DeviceObject = Pointer to PDO or FDO
122 * Irp = Pointer to IRP that should be handled
123 * RETURNS:
124 * Status
125 */
126 {
127 PCOMMON_DEVICE_EXTENSION DeviceExtension;
128 NTSTATUS Status;
129
130 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
131
132 if (DeviceExtension->IsFDO) {
133 Status = FdoPowerControl(DeviceObject, Irp);
134 } else {
135 Status = PdoPowerControl(DeviceObject, Irp);
136 }
137
138 return Status;
139 }
140
141
142 static NTSTATUS
143 NTAPI
144 PciAddDevice(
145 IN PDRIVER_OBJECT DriverObject,
146 IN PDEVICE_OBJECT PhysicalDeviceObject)
147 {
148 PFDO_DEVICE_EXTENSION DeviceExtension;
149 PDEVICE_OBJECT Fdo;
150 NTSTATUS Status;
151
152 DPRINT("Called\n");
153 if (PhysicalDeviceObject == NULL)
154 return STATUS_SUCCESS;
155
156 Status = IoCreateDevice(DriverObject, sizeof(FDO_DEVICE_EXTENSION),
157 NULL, FILE_DEVICE_BUS_EXTENDER, FILE_DEVICE_SECURE_OPEN, TRUE, &Fdo);
158 if (!NT_SUCCESS(Status)) {
159 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
160 return Status;
161 }
162
163 DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension;
164
165 RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION));
166
167 DeviceExtension->Common.IsFDO = TRUE;
168
169 DeviceExtension->Ldo =
170 IoAttachDeviceToDeviceStack(Fdo, PhysicalDeviceObject);
171
172 DeviceExtension->State = dsStopped;
173
174 Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
175
176 //Fdo->Flags |= DO_POWER_PAGABLE;
177
178 DPRINT("Done AddDevice\n");
179
180 return STATUS_SUCCESS;
181 }
182
183 DRIVER_UNLOAD PciUnload;
184
185 VOID
186 NTAPI
187 PciUnload(
188 IN PDRIVER_OBJECT DriverObject)
189 {
190 /* The driver object extension is destroyed by the I/O manager */
191 UNREFERENCED_PARAMETER(DriverObject);
192 }
193
194 NTSTATUS
195 NTAPI
196 DriverEntry(
197 IN PDRIVER_OBJECT DriverObject,
198 IN PUNICODE_STRING RegistryPath)
199 {
200 NTSTATUS Status;
201
202 UNREFERENCED_PARAMETER(RegistryPath);
203 DPRINT("Peripheral Component Interconnect Bus Driver\n");
204
205 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PciDispatchDeviceControl;
206 DriverObject->MajorFunction[IRP_MJ_PNP] = PciPnpControl;
207 DriverObject->MajorFunction[IRP_MJ_POWER] = PciPowerControl;
208 DriverObject->DriverExtension->AddDevice = PciAddDevice;
209 DriverObject->DriverUnload = PciUnload;
210
211 Status = IoAllocateDriverObjectExtension(
212 DriverObject,
213 DriverObject,
214 sizeof(PCI_DRIVER_EXTENSION),
215 (PVOID*)&DriverExtension);
216 if (!NT_SUCCESS(Status))
217 return Status;
218 RtlZeroMemory(DriverExtension, sizeof(PCI_DRIVER_EXTENSION));
219
220 InitializeListHead(&DriverExtension->BusListHead);
221 KeInitializeSpinLock(&DriverExtension->BusListLock);
222
223 return STATUS_SUCCESS;
224 }
225
226
227 NTSTATUS
228 PciCreateDeviceIDString(PUNICODE_STRING DeviceID,
229 PPCI_DEVICE Device)
230 {
231 WCHAR Buffer[256];
232
233 swprintf(Buffer,
234 L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X",
235 Device->PciConfig.VendorID,
236 Device->PciConfig.DeviceID,
237 (Device->PciConfig.u.type0.SubSystemID << 16) +
238 Device->PciConfig.u.type0.SubVendorID,
239 Device->PciConfig.RevisionID);
240
241 return RtlCreateUnicodeString(DeviceID, Buffer) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
242 }
243
244
245 NTSTATUS
246 PciCreateInstanceIDString(PUNICODE_STRING InstanceID,
247 PPCI_DEVICE Device)
248 {
249 WCHAR Buffer[3];
250
251 swprintf(Buffer, L"%02X", Device->SlotNumber.u.AsULONG & 0xff);
252
253 return RtlCreateUnicodeString(InstanceID, Buffer) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
254 }
255
256
257 NTSTATUS
258 PciCreateHardwareIDsString(PUNICODE_STRING HardwareIDs,
259 PPCI_DEVICE Device)
260 {
261 WCHAR Buffer[256];
262 UNICODE_STRING BufferU;
263 ULONG Index;
264
265 Index = 0;
266 Index += swprintf(&Buffer[Index],
267 L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X",
268 Device->PciConfig.VendorID,
269 Device->PciConfig.DeviceID,
270 (Device->PciConfig.u.type0.SubSystemID << 16) +
271 Device->PciConfig.u.type0.SubVendorID,
272 Device->PciConfig.RevisionID);
273 Index++;
274
275 Index += swprintf(&Buffer[Index],
276 L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X",
277 Device->PciConfig.VendorID,
278 Device->PciConfig.DeviceID,
279 (Device->PciConfig.u.type0.SubSystemID << 16) +
280 Device->PciConfig.u.type0.SubVendorID);
281 Index++;
282
283 Index += swprintf(&Buffer[Index],
284 L"PCI\\VEN_%04X&DEV_%04X&CC_%02X%02X%02X",
285 Device->PciConfig.VendorID,
286 Device->PciConfig.DeviceID,
287 Device->PciConfig.BaseClass,
288 Device->PciConfig.SubClass,
289 Device->PciConfig.ProgIf);
290 Index++;
291
292 Index += swprintf(&Buffer[Index],
293 L"PCI\\VEN_%04X&DEV_%04X&CC_%02X%02X",
294 Device->PciConfig.VendorID,
295 Device->PciConfig.DeviceID,
296 Device->PciConfig.BaseClass,
297 Device->PciConfig.SubClass);
298 Index++;
299
300 Buffer[Index] = UNICODE_NULL;
301
302 BufferU.Length = BufferU.MaximumLength = (USHORT) Index * sizeof(WCHAR);
303 BufferU.Buffer = Buffer;
304
305 return PciDuplicateUnicodeString(0, &BufferU, HardwareIDs);
306 }
307
308
309 NTSTATUS
310 PciCreateCompatibleIDsString(PUNICODE_STRING CompatibleIDs,
311 PPCI_DEVICE Device)
312 {
313 WCHAR Buffer[256];
314 UNICODE_STRING BufferU;
315 ULONG Index;
316
317 Index = 0;
318 Index += swprintf(&Buffer[Index],
319 L"PCI\\VEN_%04X&DEV_%04X&REV_%02X",
320 Device->PciConfig.VendorID,
321 Device->PciConfig.DeviceID,
322 Device->PciConfig.RevisionID);
323 Index++;
324
325 Index += swprintf(&Buffer[Index],
326 L"PCI\\VEN_%04X&DEV_%04X",
327 Device->PciConfig.VendorID,
328 Device->PciConfig.DeviceID);
329 Index++;
330
331 Index += swprintf(&Buffer[Index],
332 L"PCI\\VEN_%04X&CC_%02X%02X%02X",
333 Device->PciConfig.VendorID,
334 Device->PciConfig.BaseClass,
335 Device->PciConfig.SubClass,
336 Device->PciConfig.ProgIf);
337 Index++;
338
339 Index += swprintf(&Buffer[Index],
340 L"PCI\\VEN_%04X&CC_%02X%02X",
341 Device->PciConfig.VendorID,
342 Device->PciConfig.BaseClass,
343 Device->PciConfig.SubClass);
344 Index++;
345
346 Index += swprintf(&Buffer[Index],
347 L"PCI\\VEN_%04X",
348 Device->PciConfig.VendorID);
349 Index++;
350
351 Index += swprintf(&Buffer[Index],
352 L"PCI\\CC_%02X%02X%02X",
353 Device->PciConfig.BaseClass,
354 Device->PciConfig.SubClass,
355 Device->PciConfig.ProgIf);
356 Index++;
357
358 Index += swprintf(&Buffer[Index],
359 L"PCI\\CC_%02X%02X",
360 Device->PciConfig.BaseClass,
361 Device->PciConfig.SubClass);
362 Index++;
363
364 Buffer[Index] = UNICODE_NULL;
365
366 BufferU.Length = BufferU.MaximumLength = (USHORT)Index * sizeof(WCHAR);
367 BufferU.Buffer = Buffer;
368
369 return PciDuplicateUnicodeString(0, &BufferU, CompatibleIDs);
370 }
371
372
373 NTSTATUS
374 PciCreateDeviceDescriptionString(PUNICODE_STRING DeviceDescription,
375 PPCI_DEVICE Device)
376 {
377 PCWSTR Description;
378
379 switch (Device->PciConfig.BaseClass)
380 {
381 case PCI_CLASS_PRE_20:
382 switch (Device->PciConfig.SubClass)
383 {
384 case PCI_SUBCLASS_PRE_20_VGA:
385 Description = L"VGA device";
386 break;
387
388 default:
389 case PCI_SUBCLASS_PRE_20_NON_VGA:
390 Description = L"PCI device";
391 break;
392 }
393 break;
394
395 case PCI_CLASS_MASS_STORAGE_CTLR:
396 switch (Device->PciConfig.SubClass)
397 {
398 case PCI_SUBCLASS_MSC_SCSI_BUS_CTLR:
399 Description = L"SCSI controller";
400 break;
401
402 case PCI_SUBCLASS_MSC_IDE_CTLR:
403 Description = L"IDE controller";
404 break;
405
406 case PCI_SUBCLASS_MSC_FLOPPY_CTLR:
407 Description = L"Floppy disk controller";
408 break;
409
410 case PCI_SUBCLASS_MSC_IPI_CTLR:
411 Description = L"IPI controller";
412 break;
413
414 case PCI_SUBCLASS_MSC_RAID_CTLR:
415 Description = L"RAID controller";
416 break;
417
418 default:
419 Description = L"Mass storage controller";
420 break;
421 }
422 break;
423
424 case PCI_CLASS_NETWORK_CTLR:
425 switch (Device->PciConfig.SubClass)
426 {
427 case PCI_SUBCLASS_NET_ETHERNET_CTLR:
428 Description = L"Ethernet controller";
429 break;
430
431 case PCI_SUBCLASS_NET_TOKEN_RING_CTLR:
432 Description = L"Token-Ring controller";
433 break;
434
435 case PCI_SUBCLASS_NET_FDDI_CTLR:
436 Description = L"FDDI controller";
437 break;
438
439 case PCI_SUBCLASS_NET_ATM_CTLR:
440 Description = L"ATM controller";
441 break;
442
443 default:
444 Description = L"Network controller";
445 break;
446 }
447 break;
448
449 case PCI_CLASS_DISPLAY_CTLR:
450 switch (Device->PciConfig.SubClass)
451 {
452 case PCI_SUBCLASS_VID_VGA_CTLR:
453 Description = L"VGA display controller";
454 break;
455
456 case PCI_SUBCLASS_VID_XGA_CTLR:
457 Description = L"XGA display controller";
458 break;
459
460 case PCI_SUBCLASS_VID_3D_CTLR:
461 Description = L"Multimedia display controller";
462 break;
463
464 default:
465 Description = L"Other display controller";
466 break;
467 }
468 break;
469
470 case PCI_CLASS_MULTIMEDIA_DEV:
471 switch (Device->PciConfig.SubClass)
472 {
473 case PCI_SUBCLASS_MM_VIDEO_DEV:
474 Description = L"Multimedia video device";
475 break;
476
477 case PCI_SUBCLASS_MM_AUDIO_DEV:
478 Description = L"Multimedia audio device";
479 break;
480
481 case PCI_SUBCLASS_MM_TELEPHONY_DEV:
482 Description = L"Multimedia telephony device";
483 break;
484
485 default:
486 Description = L"Other multimedia device";
487 break;
488 }
489 break;
490
491 case PCI_CLASS_MEMORY_CTLR:
492 switch (Device->PciConfig.SubClass)
493 {
494 case PCI_SUBCLASS_MEM_RAM:
495 Description = L"PCI Memory";
496 break;
497
498 case PCI_SUBCLASS_MEM_FLASH:
499 Description = L"PCI Flash Memory";
500 break;
501
502 default:
503 Description = L"Other memory controller";
504 break;
505 }
506 break;
507
508 case PCI_CLASS_BRIDGE_DEV:
509 switch (Device->PciConfig.SubClass)
510 {
511 case PCI_SUBCLASS_BR_HOST:
512 Description = L"PCI-Host bridge";
513 break;
514
515 case PCI_SUBCLASS_BR_ISA:
516 Description = L"PCI-ISA bridge";
517 break;
518
519 case PCI_SUBCLASS_BR_EISA:
520 Description = L"PCI-EISA bridge";
521 break;
522
523 case PCI_SUBCLASS_BR_MCA:
524 Description = L"PCI-Micro Channel bridge";
525 break;
526
527 case PCI_SUBCLASS_BR_PCI_TO_PCI:
528 Description = L"PCI-PCI bridge";
529 break;
530
531 case PCI_SUBCLASS_BR_PCMCIA:
532 Description = L"PCI-PCMCIA bridge";
533 break;
534
535 case PCI_SUBCLASS_BR_NUBUS:
536 Description = L"PCI-NUBUS bridge";
537 break;
538
539 case PCI_SUBCLASS_BR_CARDBUS:
540 Description = L"PCI-CARDBUS bridge";
541 break;
542
543 default:
544 Description = L"Other bridge device";
545 break;
546 }
547 break;
548
549 case PCI_CLASS_SIMPLE_COMMS_CTLR:
550 switch (Device->PciConfig.SubClass)
551 {
552
553 default:
554 Description = L"Communication device";
555 break;
556 }
557 break;
558
559 case PCI_CLASS_BASE_SYSTEM_DEV:
560 switch (Device->PciConfig.SubClass)
561 {
562
563 default:
564 Description = L"System device";
565 break;
566 }
567 break;
568
569 case PCI_CLASS_INPUT_DEV:
570 switch (Device->PciConfig.SubClass)
571 {
572
573 default:
574 Description = L"Input device";
575 break;
576 }
577 break;
578
579 case PCI_CLASS_DOCKING_STATION:
580 switch (Device->PciConfig.SubClass)
581 {
582
583 default:
584 Description = L"Docking station";
585 break;
586 }
587 break;
588
589 case PCI_CLASS_PROCESSOR:
590 switch (Device->PciConfig.SubClass)
591 {
592
593 default:
594 Description = L"Processor";
595 break;
596 }
597 break;
598
599 case PCI_CLASS_SERIAL_BUS_CTLR:
600 switch (Device->PciConfig.SubClass)
601 {
602 case PCI_SUBCLASS_SB_IEEE1394:
603 Description = L"FireWire controller";
604 break;
605
606 case PCI_SUBCLASS_SB_ACCESS:
607 Description = L"ACCESS bus controller";
608 break;
609
610 case PCI_SUBCLASS_SB_SSA:
611 Description = L"SSA controller";
612 break;
613
614 case PCI_SUBCLASS_SB_USB:
615 Description = L"USB controller";
616 break;
617
618 case PCI_SUBCLASS_SB_FIBRE_CHANNEL:
619 Description = L"Fibre Channel controller";
620 break;
621
622 case PCI_SUBCLASS_SB_SMBUS:
623 Description = L"SMBus controller";
624 break;
625
626 default:
627 Description = L"Other serial bus controller";
628 break;
629 }
630 break;
631
632 default:
633 Description = L"Other PCI Device";
634 break;
635 }
636
637 return RtlCreateUnicodeString(DeviceDescription, Description) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
638 }
639
640
641 NTSTATUS
642 PciCreateDeviceLocationString(PUNICODE_STRING DeviceLocation,
643 PPCI_DEVICE Device)
644 {
645 WCHAR Buffer[256];
646
647 swprintf(Buffer,
648 L"PCI-Bus %lu, Device %u, Function %u",
649 Device->BusNumber,
650 Device->SlotNumber.u.bits.DeviceNumber,
651 Device->SlotNumber.u.bits.FunctionNumber);
652
653 return RtlCreateUnicodeString(DeviceLocation, Buffer) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
654 }
655
656 NTSTATUS
657 PciDuplicateUnicodeString(
658 IN ULONG Flags,
659 IN PCUNICODE_STRING SourceString,
660 OUT PUNICODE_STRING DestinationString)
661 {
662 if (SourceString == NULL || DestinationString == NULL
663 || SourceString->Length > SourceString->MaximumLength
664 || (SourceString->Length == 0 && SourceString->MaximumLength > 0 && SourceString->Buffer == NULL)
665 || Flags == RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING || Flags >= 4)
666 {
667 return STATUS_INVALID_PARAMETER;
668 }
669
670
671 if ((SourceString->Length == 0)
672 && (Flags != (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE |
673 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING)))
674 {
675 DestinationString->Length = 0;
676 DestinationString->MaximumLength = 0;
677 DestinationString->Buffer = NULL;
678 }
679 else
680 {
681 USHORT DestMaxLength = SourceString->Length;
682
683 if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE)
684 DestMaxLength += sizeof(UNICODE_NULL);
685
686 DestinationString->Buffer = ExAllocatePoolWithTag(PagedPool, DestMaxLength, TAG_PCI);
687 if (DestinationString->Buffer == NULL)
688 return STATUS_NO_MEMORY;
689
690 RtlCopyMemory(DestinationString->Buffer, SourceString->Buffer, SourceString->Length);
691 DestinationString->Length = SourceString->Length;
692 DestinationString->MaximumLength = DestMaxLength;
693
694 if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE)
695 DestinationString->Buffer[DestinationString->Length / sizeof(WCHAR)] = 0;
696 }
697
698 return STATUS_SUCCESS;
699 }
700
701 /* EOF */