2 * PROJECT: ReactOS PCI Bus driver
4 * PURPOSE: Driver entry
5 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * 10-09-2001 CSH Created
17 static DRIVER_DISPATCH PciDispatchDeviceControl
;
18 static NTSTATUS NTAPI
PciDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
20 static DRIVER_ADD_DEVICE PciAddDevice
;
21 static NTSTATUS NTAPI
PciAddDevice(IN PDRIVER_OBJECT DriverObject
, IN PDEVICE_OBJECT PhysicalDeviceObject
);
23 static DRIVER_DISPATCH PciPowerControl
;
24 static NTSTATUS NTAPI
PciPowerControl(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
26 static DRIVER_DISPATCH PciPnpControl
;
27 static NTSTATUS NTAPI
PciPnpControl(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
29 /*** PUBLIC ******************************************************************/
31 PPCI_DRIVER_EXTENSION DriverExtension
= NULL
;
32 BOOLEAN HasDebuggingDevice
= FALSE
;
33 PCI_TYPE1_CFG_CYCLE_BITS PciDebuggingDevice
[2] = {0};
35 /*** PRIVATE *****************************************************************/
39 PciDispatchDeviceControl(
40 IN PDEVICE_OBJECT DeviceObject
,
43 PIO_STACK_LOCATION IrpSp
;
46 UNREFERENCED_PARAMETER(DeviceObject
);
47 DPRINT("Called. IRP is at (0x%p)\n", Irp
);
49 Irp
->IoStatus
.Information
= 0;
51 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
52 switch (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
)
55 DPRINT("Unknown IOCTL 0x%X\n", IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
);
56 Status
= STATUS_NOT_IMPLEMENTED
;
60 if (Status
!= STATUS_PENDING
)
62 Irp
->IoStatus
.Status
= Status
;
64 DPRINT("Completing IRP at 0x%p\n", Irp
);
66 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
69 DPRINT("Leaving. Status 0x%X\n", Status
);
78 IN PDEVICE_OBJECT DeviceObject
,
81 * FUNCTION: Handle Plug and Play IRPs
83 * DeviceObject = Pointer to PDO or FDO
84 * Irp = Pointer to IRP that should be handled
89 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
92 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
94 DPRINT("IsFDO %u\n", DeviceExtension
->IsFDO
);
96 if (DeviceExtension
->IsFDO
)
98 Status
= FdoPnpControl(DeviceObject
, Irp
);
102 Status
= PdoPnpControl(DeviceObject
, Irp
);
112 IN PDEVICE_OBJECT DeviceObject
,
115 * FUNCTION: Handle power management IRPs
117 * DeviceObject = Pointer to PDO or FDO
118 * Irp = Pointer to IRP that should be handled
123 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
126 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
128 if (DeviceExtension
->IsFDO
)
130 Status
= FdoPowerControl(DeviceObject
, Irp
);
134 Status
= PdoPowerControl(DeviceObject
, Irp
);
144 IN PDRIVER_OBJECT DriverObject
,
145 IN PDEVICE_OBJECT PhysicalDeviceObject
)
147 PFDO_DEVICE_EXTENSION DeviceExtension
;
152 if (PhysicalDeviceObject
== NULL
)
153 return STATUS_SUCCESS
;
155 Status
= IoCreateDevice(DriverObject
,
156 sizeof(FDO_DEVICE_EXTENSION
),
158 FILE_DEVICE_BUS_EXTENDER
,
159 FILE_DEVICE_SECURE_OPEN
,
162 if (!NT_SUCCESS(Status
))
164 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status
);
168 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)Fdo
->DeviceExtension
;
170 RtlZeroMemory(DeviceExtension
, sizeof(FDO_DEVICE_EXTENSION
));
172 DeviceExtension
->Common
.IsFDO
= TRUE
;
174 DeviceExtension
->Ldo
= IoAttachDeviceToDeviceStack(Fdo
,
175 PhysicalDeviceObject
);
177 DeviceExtension
->State
= dsStopped
;
179 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
181 //Fdo->Flags |= DO_POWER_PAGABLE;
183 DPRINT("Done AddDevice\n");
185 return STATUS_SUCCESS
;
188 DRIVER_UNLOAD PciUnload
;
193 IN PDRIVER_OBJECT DriverObject
)
195 /* The driver object extension is destroyed by the I/O manager */
196 UNREFERENCED_PARAMETER(DriverObject
);
202 PciLocateKdDevices(VOID
)
206 WCHAR KeyNameBuffer
[16];
207 ULONG BusNumber
, SlotNumber
;
208 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
210 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
211 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
212 QueryTable
[0].Name
= L
"Bus";
213 QueryTable
[0].EntryContext
= &BusNumber
;
214 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
215 QueryTable
[1].Name
= L
"Slot";
216 QueryTable
[1].EntryContext
= &SlotNumber
;
218 for (i
= 0; i
< RTL_NUMBER_OF(PciDebuggingDevice
); ++i
)
220 PCI_SLOT_NUMBER PciSlot
;
222 RtlStringCbPrintfW(KeyNameBuffer
, sizeof(KeyNameBuffer
), L
"PCI\\Debug\\%d", i
);
224 Status
= RtlQueryRegistryValues(RTL_REGISTRY_SERVICES
,
229 if (!NT_SUCCESS(Status
))
232 HasDebuggingDevice
= TRUE
;
234 PciSlot
.u
.AsULONG
= SlotNumber
;
235 PciDebuggingDevice
[i
].DeviceNumber
= PciSlot
.u
.bits
.DeviceNumber
;
236 PciDebuggingDevice
[i
].FunctionNumber
= PciSlot
.u
.bits
.FunctionNumber
;
237 PciDebuggingDevice
[i
].BusNumber
= BusNumber
;
238 PciDebuggingDevice
[i
].InUse
= TRUE
;
240 DPRINT1("PCI debugging device %02x:%02x.%x\n",
242 PciSlot
.u
.bits
.DeviceNumber
,
243 PciSlot
.u
.bits
.FunctionNumber
);
251 IN PDRIVER_OBJECT DriverObject
,
252 IN PUNICODE_STRING RegistryPath
)
256 UNREFERENCED_PARAMETER(RegistryPath
);
257 DPRINT("Peripheral Component Interconnect Bus Driver\n");
259 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = PciDispatchDeviceControl
;
260 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = PciPnpControl
;
261 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = PciPowerControl
;
262 DriverObject
->DriverExtension
->AddDevice
= PciAddDevice
;
263 DriverObject
->DriverUnload
= PciUnload
;
265 Status
= IoAllocateDriverObjectExtension(DriverObject
,
267 sizeof(PCI_DRIVER_EXTENSION
),
268 (PVOID
*)&DriverExtension
);
269 if (!NT_SUCCESS(Status
))
272 RtlZeroMemory(DriverExtension
, sizeof(PCI_DRIVER_EXTENSION
));
274 InitializeListHead(&DriverExtension
->BusListHead
);
275 KeInitializeSpinLock(&DriverExtension
->BusListLock
);
277 PciLocateKdDevices();
279 return STATUS_SUCCESS
;
284 PciCreateDeviceIDString(PUNICODE_STRING DeviceID
,
290 L
"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X",
291 Device
->PciConfig
.VendorID
,
292 Device
->PciConfig
.DeviceID
,
293 (Device
->PciConfig
.u
.type0
.SubSystemID
<< 16) +
294 Device
->PciConfig
.u
.type0
.SubVendorID
,
295 Device
->PciConfig
.RevisionID
);
297 return RtlCreateUnicodeString(DeviceID
, Buffer
) ? STATUS_SUCCESS
: STATUS_INSUFFICIENT_RESOURCES
;
302 PciCreateInstanceIDString(PUNICODE_STRING InstanceID
,
307 swprintf(Buffer
, L
"%02X", Device
->SlotNumber
.u
.AsULONG
& 0xff);
309 return RtlCreateUnicodeString(InstanceID
, Buffer
) ? STATUS_SUCCESS
: STATUS_INSUFFICIENT_RESOURCES
;
314 PciCreateHardwareIDsString(PUNICODE_STRING HardwareIDs
,
318 UNICODE_STRING BufferU
;
322 Index
+= swprintf(&Buffer
[Index
],
323 L
"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X",
324 Device
->PciConfig
.VendorID
,
325 Device
->PciConfig
.DeviceID
,
326 (Device
->PciConfig
.u
.type0
.SubSystemID
<< 16) +
327 Device
->PciConfig
.u
.type0
.SubVendorID
,
328 Device
->PciConfig
.RevisionID
);
331 Index
+= swprintf(&Buffer
[Index
],
332 L
"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X",
333 Device
->PciConfig
.VendorID
,
334 Device
->PciConfig
.DeviceID
,
335 (Device
->PciConfig
.u
.type0
.SubSystemID
<< 16) +
336 Device
->PciConfig
.u
.type0
.SubVendorID
);
339 Index
+= swprintf(&Buffer
[Index
],
340 L
"PCI\\VEN_%04X&DEV_%04X&CC_%02X%02X%02X",
341 Device
->PciConfig
.VendorID
,
342 Device
->PciConfig
.DeviceID
,
343 Device
->PciConfig
.BaseClass
,
344 Device
->PciConfig
.SubClass
,
345 Device
->PciConfig
.ProgIf
);
348 Index
+= swprintf(&Buffer
[Index
],
349 L
"PCI\\VEN_%04X&DEV_%04X&CC_%02X%02X",
350 Device
->PciConfig
.VendorID
,
351 Device
->PciConfig
.DeviceID
,
352 Device
->PciConfig
.BaseClass
,
353 Device
->PciConfig
.SubClass
);
356 Buffer
[Index
] = UNICODE_NULL
;
358 BufferU
.Length
= BufferU
.MaximumLength
= (USHORT
) Index
* sizeof(WCHAR
);
359 BufferU
.Buffer
= Buffer
;
361 return PciDuplicateUnicodeString(0, &BufferU
, HardwareIDs
);
366 PciCreateCompatibleIDsString(PUNICODE_STRING CompatibleIDs
,
370 UNICODE_STRING BufferU
;
374 Index
+= swprintf(&Buffer
[Index
],
375 L
"PCI\\VEN_%04X&DEV_%04X&REV_%02X",
376 Device
->PciConfig
.VendorID
,
377 Device
->PciConfig
.DeviceID
,
378 Device
->PciConfig
.RevisionID
);
381 Index
+= swprintf(&Buffer
[Index
],
382 L
"PCI\\VEN_%04X&DEV_%04X",
383 Device
->PciConfig
.VendorID
,
384 Device
->PciConfig
.DeviceID
);
387 Index
+= swprintf(&Buffer
[Index
],
388 L
"PCI\\VEN_%04X&CC_%02X%02X%02X",
389 Device
->PciConfig
.VendorID
,
390 Device
->PciConfig
.BaseClass
,
391 Device
->PciConfig
.SubClass
,
392 Device
->PciConfig
.ProgIf
);
395 Index
+= swprintf(&Buffer
[Index
],
396 L
"PCI\\VEN_%04X&CC_%02X%02X",
397 Device
->PciConfig
.VendorID
,
398 Device
->PciConfig
.BaseClass
,
399 Device
->PciConfig
.SubClass
);
402 Index
+= swprintf(&Buffer
[Index
],
404 Device
->PciConfig
.VendorID
);
407 Index
+= swprintf(&Buffer
[Index
],
408 L
"PCI\\CC_%02X%02X%02X",
409 Device
->PciConfig
.BaseClass
,
410 Device
->PciConfig
.SubClass
,
411 Device
->PciConfig
.ProgIf
);
414 Index
+= swprintf(&Buffer
[Index
],
416 Device
->PciConfig
.BaseClass
,
417 Device
->PciConfig
.SubClass
);
420 Buffer
[Index
] = UNICODE_NULL
;
422 BufferU
.Length
= BufferU
.MaximumLength
= (USHORT
)Index
* sizeof(WCHAR
);
423 BufferU
.Buffer
= Buffer
;
425 return PciDuplicateUnicodeString(0, &BufferU
, CompatibleIDs
);
430 PciCreateDeviceDescriptionString(PUNICODE_STRING DeviceDescription
,
435 switch (Device
->PciConfig
.BaseClass
)
437 case PCI_CLASS_PRE_20
:
438 switch (Device
->PciConfig
.SubClass
)
440 case PCI_SUBCLASS_PRE_20_VGA
:
441 Description
= L
"VGA device";
445 case PCI_SUBCLASS_PRE_20_NON_VGA
:
446 Description
= L
"PCI device";
451 case PCI_CLASS_MASS_STORAGE_CTLR
:
452 switch (Device
->PciConfig
.SubClass
)
454 case PCI_SUBCLASS_MSC_SCSI_BUS_CTLR
:
455 Description
= L
"SCSI controller";
458 case PCI_SUBCLASS_MSC_IDE_CTLR
:
459 Description
= L
"IDE controller";
462 case PCI_SUBCLASS_MSC_FLOPPY_CTLR
:
463 Description
= L
"Floppy disk controller";
466 case PCI_SUBCLASS_MSC_IPI_CTLR
:
467 Description
= L
"IPI controller";
470 case PCI_SUBCLASS_MSC_RAID_CTLR
:
471 Description
= L
"RAID controller";
475 Description
= L
"Mass storage controller";
480 case PCI_CLASS_NETWORK_CTLR
:
481 switch (Device
->PciConfig
.SubClass
)
483 case PCI_SUBCLASS_NET_ETHERNET_CTLR
:
484 Description
= L
"Ethernet controller";
487 case PCI_SUBCLASS_NET_TOKEN_RING_CTLR
:
488 Description
= L
"Token-Ring controller";
491 case PCI_SUBCLASS_NET_FDDI_CTLR
:
492 Description
= L
"FDDI controller";
495 case PCI_SUBCLASS_NET_ATM_CTLR
:
496 Description
= L
"ATM controller";
500 Description
= L
"Network controller";
505 case PCI_CLASS_DISPLAY_CTLR
:
506 switch (Device
->PciConfig
.SubClass
)
508 case PCI_SUBCLASS_VID_VGA_CTLR
:
509 Description
= L
"VGA display controller";
512 case PCI_SUBCLASS_VID_XGA_CTLR
:
513 Description
= L
"XGA display controller";
516 case PCI_SUBCLASS_VID_3D_CTLR
:
517 Description
= L
"Multimedia display controller";
521 Description
= L
"Other display controller";
526 case PCI_CLASS_MULTIMEDIA_DEV
:
527 switch (Device
->PciConfig
.SubClass
)
529 case PCI_SUBCLASS_MM_VIDEO_DEV
:
530 Description
= L
"Multimedia video device";
533 case PCI_SUBCLASS_MM_AUDIO_DEV
:
534 Description
= L
"Multimedia audio device";
537 case PCI_SUBCLASS_MM_TELEPHONY_DEV
:
538 Description
= L
"Multimedia telephony device";
542 Description
= L
"Other multimedia device";
547 case PCI_CLASS_MEMORY_CTLR
:
548 switch (Device
->PciConfig
.SubClass
)
550 case PCI_SUBCLASS_MEM_RAM
:
551 Description
= L
"PCI Memory";
554 case PCI_SUBCLASS_MEM_FLASH
:
555 Description
= L
"PCI Flash Memory";
559 Description
= L
"Other memory controller";
564 case PCI_CLASS_BRIDGE_DEV
:
565 switch (Device
->PciConfig
.SubClass
)
567 case PCI_SUBCLASS_BR_HOST
:
568 Description
= L
"PCI-Host bridge";
571 case PCI_SUBCLASS_BR_ISA
:
572 Description
= L
"PCI-ISA bridge";
575 case PCI_SUBCLASS_BR_EISA
:
576 Description
= L
"PCI-EISA bridge";
579 case PCI_SUBCLASS_BR_MCA
:
580 Description
= L
"PCI-Micro Channel bridge";
583 case PCI_SUBCLASS_BR_PCI_TO_PCI
:
584 Description
= L
"PCI-PCI bridge";
587 case PCI_SUBCLASS_BR_PCMCIA
:
588 Description
= L
"PCI-PCMCIA bridge";
591 case PCI_SUBCLASS_BR_NUBUS
:
592 Description
= L
"PCI-NUBUS bridge";
595 case PCI_SUBCLASS_BR_CARDBUS
:
596 Description
= L
"PCI-CARDBUS bridge";
600 Description
= L
"Other bridge device";
605 case PCI_CLASS_SIMPLE_COMMS_CTLR
:
606 switch (Device
->PciConfig
.SubClass
)
610 Description
= L
"Communication device";
615 case PCI_CLASS_BASE_SYSTEM_DEV
:
616 switch (Device
->PciConfig
.SubClass
)
620 Description
= L
"System device";
625 case PCI_CLASS_INPUT_DEV
:
626 switch (Device
->PciConfig
.SubClass
)
630 Description
= L
"Input device";
635 case PCI_CLASS_DOCKING_STATION
:
636 switch (Device
->PciConfig
.SubClass
)
640 Description
= L
"Docking station";
645 case PCI_CLASS_PROCESSOR
:
646 switch (Device
->PciConfig
.SubClass
)
650 Description
= L
"Processor";
655 case PCI_CLASS_SERIAL_BUS_CTLR
:
656 switch (Device
->PciConfig
.SubClass
)
658 case PCI_SUBCLASS_SB_IEEE1394
:
659 Description
= L
"FireWire controller";
662 case PCI_SUBCLASS_SB_ACCESS
:
663 Description
= L
"ACCESS bus controller";
666 case PCI_SUBCLASS_SB_SSA
:
667 Description
= L
"SSA controller";
670 case PCI_SUBCLASS_SB_USB
:
671 Description
= L
"USB controller";
674 case PCI_SUBCLASS_SB_FIBRE_CHANNEL
:
675 Description
= L
"Fibre Channel controller";
678 case PCI_SUBCLASS_SB_SMBUS
:
679 Description
= L
"SMBus controller";
683 Description
= L
"Other serial bus controller";
689 Description
= L
"Other PCI Device";
693 return RtlCreateUnicodeString(DeviceDescription
, Description
) ? STATUS_SUCCESS
: STATUS_INSUFFICIENT_RESOURCES
;
698 PciCreateDeviceLocationString(PUNICODE_STRING DeviceLocation
,
704 L
"PCI-Bus %lu, Device %u, Function %u",
706 Device
->SlotNumber
.u
.bits
.DeviceNumber
,
707 Device
->SlotNumber
.u
.bits
.FunctionNumber
);
709 return RtlCreateUnicodeString(DeviceLocation
, Buffer
) ? STATUS_SUCCESS
: STATUS_INSUFFICIENT_RESOURCES
;
713 PciDuplicateUnicodeString(
715 IN PCUNICODE_STRING SourceString
,
716 OUT PUNICODE_STRING DestinationString
)
718 if (SourceString
== NULL
||
719 DestinationString
== NULL
||
720 SourceString
->Length
> SourceString
->MaximumLength
||
721 (SourceString
->Length
== 0 && SourceString
->MaximumLength
> 0 && SourceString
->Buffer
== NULL
) ||
722 Flags
== RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
||
725 return STATUS_INVALID_PARAMETER
;
728 if ((SourceString
->Length
== 0) &&
729 (Flags
!= (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
|
730 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
)))
732 DestinationString
->Length
= 0;
733 DestinationString
->MaximumLength
= 0;
734 DestinationString
->Buffer
= NULL
;
738 USHORT DestMaxLength
= SourceString
->Length
;
740 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
741 DestMaxLength
+= sizeof(UNICODE_NULL
);
743 DestinationString
->Buffer
= ExAllocatePoolWithTag(PagedPool
, DestMaxLength
, TAG_PCI
);
744 if (DestinationString
->Buffer
== NULL
)
745 return STATUS_NO_MEMORY
;
747 RtlCopyMemory(DestinationString
->Buffer
, SourceString
->Buffer
, SourceString
->Length
);
748 DestinationString
->Length
= SourceString
->Length
;
749 DestinationString
->MaximumLength
= DestMaxLength
;
751 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
752 DestinationString
->Buffer
[DestinationString
->Length
/ sizeof(WCHAR
)] = 0;
755 return STATUS_SUCCESS
;