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