xref: /reactos/drivers/bus/pci/pdo.c (revision 2b9941e7)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * PROJECT:         ReactOS PCI bus driver
3c2c66affSColin Finck  * FILE:            pdo.c
4c2c66affSColin Finck  * PURPOSE:         Child device object dispatch routines
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 <initguid.h>
13c2c66affSColin Finck #include <wdmguid.h>
14c2c66affSColin Finck 
15c2c66affSColin Finck #define NDEBUG
16c2c66affSColin Finck #include <debug.h>
17c2c66affSColin Finck 
18c2c66affSColin Finck #if 0
19c2c66affSColin Finck #define DBGPRINT(...) DbgPrint(__VA_ARGS__)
20c2c66affSColin Finck #else
21c2c66affSColin Finck #define DBGPRINT(...)
22c2c66affSColin Finck #endif
23c2c66affSColin Finck 
24c2c66affSColin Finck #define PCI_ADDRESS_MEMORY_ADDRESS_MASK_64     0xfffffffffffffff0ull
25c2c66affSColin Finck #define PCI_ADDRESS_IO_ADDRESS_MASK_64         0xfffffffffffffffcull
26c2c66affSColin Finck 
27c2c66affSColin Finck /*** PRIVATE *****************************************************************/
28c2c66affSColin Finck 
29c2c66affSColin Finck static NTSTATUS
30c2c66affSColin Finck PdoQueryDeviceText(
31c2c66affSColin Finck     IN PDEVICE_OBJECT DeviceObject,
32c2c66affSColin Finck     IN PIRP Irp,
33c2c66affSColin Finck     PIO_STACK_LOCATION IrpSp)
34c2c66affSColin Finck {
35c2c66affSColin Finck     PPDO_DEVICE_EXTENSION DeviceExtension;
36c2c66affSColin Finck     UNICODE_STRING String;
37c2c66affSColin Finck     NTSTATUS Status;
38c2c66affSColin Finck 
39c2c66affSColin Finck     DPRINT("Called\n");
40c2c66affSColin Finck 
41c2c66affSColin Finck     DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
42c2c66affSColin Finck 
43c2c66affSColin Finck     switch (IrpSp->Parameters.QueryDeviceText.DeviceTextType)
44c2c66affSColin Finck     {
45c2c66affSColin Finck         case DeviceTextDescription:
46c2c66affSColin Finck             Status = PciDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
47c2c66affSColin Finck                                                &DeviceExtension->DeviceDescription,
48c2c66affSColin Finck                                                &String);
49c2c66affSColin Finck 
50c2c66affSColin Finck             DPRINT("DeviceTextDescription\n");
51c2c66affSColin Finck             Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
52c2c66affSColin Finck             break;
53c2c66affSColin Finck 
54c2c66affSColin Finck         case DeviceTextLocationInformation:
55c2c66affSColin Finck             Status = PciDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
56c2c66affSColin Finck                                                &DeviceExtension->DeviceLocation,
57c2c66affSColin Finck                                                &String);
58c2c66affSColin Finck 
59c2c66affSColin Finck             DPRINT("DeviceTextLocationInformation\n");
60c2c66affSColin Finck             Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
61c2c66affSColin Finck             break;
62c2c66affSColin Finck 
63c2c66affSColin Finck         default:
64c2c66affSColin Finck             Irp->IoStatus.Information = 0;
65c2c66affSColin Finck             Status = STATUS_INVALID_PARAMETER;
66c2c66affSColin Finck             break;
67c2c66affSColin Finck     }
68c2c66affSColin Finck 
69c2c66affSColin Finck     return Status;
70c2c66affSColin Finck }
71c2c66affSColin Finck 
72c2c66affSColin Finck 
73c2c66affSColin Finck static NTSTATUS
74c2c66affSColin Finck PdoQueryId(
75c2c66affSColin Finck     IN PDEVICE_OBJECT DeviceObject,
76c2c66affSColin Finck     IN PIRP Irp,
77c2c66affSColin Finck     PIO_STACK_LOCATION IrpSp)
78c2c66affSColin Finck {
79c2c66affSColin Finck     PPDO_DEVICE_EXTENSION DeviceExtension;
80c2c66affSColin Finck     UNICODE_STRING String;
81c2c66affSColin Finck     NTSTATUS Status;
82c2c66affSColin Finck 
83c2c66affSColin Finck     DPRINT("Called\n");
84c2c66affSColin Finck 
85c2c66affSColin Finck     DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
86c2c66affSColin Finck 
87c2c66affSColin Finck //    Irp->IoStatus.Information = 0;
88c2c66affSColin Finck 
89c2c66affSColin Finck     Status = STATUS_SUCCESS;
90c2c66affSColin Finck 
91c2c66affSColin Finck     RtlInitUnicodeString(&String, NULL);
92c2c66affSColin Finck 
93c2c66affSColin Finck     switch (IrpSp->Parameters.QueryId.IdType)
94c2c66affSColin Finck     {
95c2c66affSColin Finck         case BusQueryDeviceID:
96c2c66affSColin Finck             Status = PciDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
97c2c66affSColin Finck                                                &DeviceExtension->DeviceID,
98c2c66affSColin Finck                                                &String);
99c2c66affSColin Finck 
100c2c66affSColin Finck             DPRINT("DeviceID: %S\n", String.Buffer);
101c2c66affSColin Finck 
102c2c66affSColin Finck             Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
103c2c66affSColin Finck             break;
104c2c66affSColin Finck 
105c2c66affSColin Finck         case BusQueryHardwareIDs:
106c2c66affSColin Finck             Status = PciDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
107c2c66affSColin Finck                                                &DeviceExtension->HardwareIDs,
108c2c66affSColin Finck                                                &String);
109c2c66affSColin Finck 
110c2c66affSColin Finck             Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
111c2c66affSColin Finck             break;
112c2c66affSColin Finck 
113c2c66affSColin Finck         case BusQueryCompatibleIDs:
114c2c66affSColin Finck             Status = PciDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
115c2c66affSColin Finck                                                &DeviceExtension->CompatibleIDs,
116c2c66affSColin Finck                                                &String);
117c2c66affSColin Finck 
118c2c66affSColin Finck             Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
119c2c66affSColin Finck             break;
120c2c66affSColin Finck 
121c2c66affSColin Finck         case BusQueryInstanceID:
122c2c66affSColin Finck             Status = PciDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
123c2c66affSColin Finck                                                &DeviceExtension->InstanceID,
124c2c66affSColin Finck                                                &String);
125c2c66affSColin Finck 
126c2c66affSColin Finck             DPRINT("InstanceID: %S\n", String.Buffer);
127c2c66affSColin Finck 
128c2c66affSColin Finck             Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
129c2c66affSColin Finck             break;
130c2c66affSColin Finck 
131c2c66affSColin Finck         case BusQueryDeviceSerialNumber:
132c2c66affSColin Finck         default:
133c2c66affSColin Finck             Status = STATUS_NOT_IMPLEMENTED;
134c2c66affSColin Finck     }
135c2c66affSColin Finck 
136c2c66affSColin Finck     return Status;
137c2c66affSColin Finck }
138c2c66affSColin Finck 
139c2c66affSColin Finck 
140c2c66affSColin Finck static NTSTATUS
141c2c66affSColin Finck PdoQueryBusInformation(
142c2c66affSColin Finck     IN PDEVICE_OBJECT DeviceObject,
143c2c66affSColin Finck     IN PIRP Irp,
144c2c66affSColin Finck     PIO_STACK_LOCATION IrpSp)
145c2c66affSColin Finck {
146c2c66affSColin Finck     PPDO_DEVICE_EXTENSION DeviceExtension;
147c2c66affSColin Finck     PPNP_BUS_INFORMATION BusInformation;
148c2c66affSColin Finck 
149c2c66affSColin Finck     UNREFERENCED_PARAMETER(IrpSp);
150c2c66affSColin Finck     DPRINT("Called\n");
151c2c66affSColin Finck 
152c2c66affSColin Finck     DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
153c2c66affSColin Finck     BusInformation = ExAllocatePoolWithTag(PagedPool, sizeof(PNP_BUS_INFORMATION), TAG_PCI);
154c2c66affSColin Finck     Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
155c2c66affSColin Finck     if (BusInformation != NULL)
156c2c66affSColin Finck     {
157c2c66affSColin Finck         BusInformation->BusTypeGuid = GUID_BUS_TYPE_PCI;
158c2c66affSColin Finck         BusInformation->LegacyBusType = PCIBus;
159c2c66affSColin Finck         BusInformation->BusNumber = DeviceExtension->PciDevice->BusNumber;
160c2c66affSColin Finck 
161c2c66affSColin Finck         return STATUS_SUCCESS;
162c2c66affSColin Finck     }
163c2c66affSColin Finck 
164c2c66affSColin Finck     return STATUS_INSUFFICIENT_RESOURCES;
165c2c66affSColin Finck }
166c2c66affSColin Finck 
167c2c66affSColin Finck 
168c2c66affSColin Finck static NTSTATUS
169c2c66affSColin Finck PdoQueryCapabilities(
170c2c66affSColin Finck     IN PDEVICE_OBJECT DeviceObject,
171c2c66affSColin Finck     IN PIRP Irp,
172c2c66affSColin Finck     PIO_STACK_LOCATION IrpSp)
173c2c66affSColin Finck {
174c2c66affSColin Finck     PPDO_DEVICE_EXTENSION DeviceExtension;
175c2c66affSColin Finck     PDEVICE_CAPABILITIES DeviceCapabilities;
176c2c66affSColin Finck     ULONG DeviceNumber, FunctionNumber;
177c2c66affSColin Finck 
178c2c66affSColin Finck     UNREFERENCED_PARAMETER(Irp);
179c2c66affSColin Finck     DPRINT("Called\n");
180c2c66affSColin Finck 
181c2c66affSColin Finck     DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
182c2c66affSColin Finck     DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
183c2c66affSColin Finck 
184c2c66affSColin Finck     if (DeviceCapabilities->Version != 1)
185c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
186c2c66affSColin Finck 
187c2c66affSColin Finck     DeviceNumber = DeviceExtension->PciDevice->SlotNumber.u.bits.DeviceNumber;
188c2c66affSColin Finck     FunctionNumber = DeviceExtension->PciDevice->SlotNumber.u.bits.FunctionNumber;
189c2c66affSColin Finck 
190c2c66affSColin Finck     DeviceCapabilities->UniqueID = FALSE;
191c2c66affSColin Finck     DeviceCapabilities->Address = ((DeviceNumber << 16) & 0xFFFF0000) + (FunctionNumber & 0xFFFF);
192c2c66affSColin Finck     DeviceCapabilities->UINumber = MAXULONG; /* FIXME */
193c2c66affSColin Finck 
194c2c66affSColin Finck     return STATUS_SUCCESS;
195c2c66affSColin Finck }
196c2c66affSColin Finck 
197c2c66affSColin Finck static BOOLEAN
198c2c66affSColin Finck PdoReadPciBar(PPDO_DEVICE_EXTENSION DeviceExtension,
199c2c66affSColin Finck               ULONG Offset,
200c2c66affSColin Finck               PULONG OriginalValue,
201c2c66affSColin Finck               PULONG NewValue)
202c2c66affSColin Finck {
203c2c66affSColin Finck     ULONG Size;
204c2c66affSColin Finck     ULONG AllOnes;
205c2c66affSColin Finck 
206c2c66affSColin Finck     /* Read the original value */
207c2c66affSColin Finck     Size = HalGetBusDataByOffset(PCIConfiguration,
208c2c66affSColin Finck                                  DeviceExtension->PciDevice->BusNumber,
209c2c66affSColin Finck                                  DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
210c2c66affSColin Finck                                  OriginalValue,
211c2c66affSColin Finck                                  Offset,
212c2c66affSColin Finck                                  sizeof(ULONG));
213c2c66affSColin Finck     if (Size != sizeof(ULONG))
214c2c66affSColin Finck     {
215c2c66affSColin Finck         DPRINT1("Wrong size %lu\n", Size);
216c2c66affSColin Finck         return FALSE;
217c2c66affSColin Finck     }
218c2c66affSColin Finck 
219c2c66affSColin Finck     /* Write all ones to determine which bits are held to zero */
220c2c66affSColin Finck     AllOnes = MAXULONG;
221c2c66affSColin Finck     Size = HalSetBusDataByOffset(PCIConfiguration,
222c2c66affSColin Finck                                  DeviceExtension->PciDevice->BusNumber,
223c2c66affSColin Finck                                  DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
224c2c66affSColin Finck                                  &AllOnes,
225c2c66affSColin Finck                                  Offset,
226c2c66affSColin Finck                                  sizeof(ULONG));
227c2c66affSColin Finck     if (Size != sizeof(ULONG))
228c2c66affSColin Finck     {
229c2c66affSColin Finck         DPRINT1("Wrong size %lu\n", Size);
230c2c66affSColin Finck         return FALSE;
231c2c66affSColin Finck     }
232c2c66affSColin Finck 
233c2c66affSColin Finck     /* Get the range length */
234c2c66affSColin Finck     Size = HalGetBusDataByOffset(PCIConfiguration,
235c2c66affSColin Finck                                  DeviceExtension->PciDevice->BusNumber,
236c2c66affSColin Finck                                  DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
237c2c66affSColin Finck                                  NewValue,
238c2c66affSColin Finck                                  Offset,
239c2c66affSColin Finck                                  sizeof(ULONG));
240c2c66affSColin Finck     if (Size != sizeof(ULONG))
241c2c66affSColin Finck     {
242c2c66affSColin Finck         DPRINT1("Wrong size %lu\n", Size);
243c2c66affSColin Finck         return FALSE;
244c2c66affSColin Finck     }
245c2c66affSColin Finck 
246c2c66affSColin Finck     /* Restore original value */
247c2c66affSColin Finck     Size = HalSetBusDataByOffset(PCIConfiguration,
248c2c66affSColin Finck                                  DeviceExtension->PciDevice->BusNumber,
249c2c66affSColin Finck                                  DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
250c2c66affSColin Finck                                  OriginalValue,
251c2c66affSColin Finck                                  Offset,
252c2c66affSColin Finck                                  sizeof(ULONG));
253c2c66affSColin Finck     if (Size != sizeof(ULONG))
254c2c66affSColin Finck     {
255c2c66affSColin Finck         DPRINT1("Wrong size %lu\n", Size);
256c2c66affSColin Finck         return FALSE;
257c2c66affSColin Finck     }
258c2c66affSColin Finck 
259c2c66affSColin Finck     return TRUE;
260c2c66affSColin Finck }
261c2c66affSColin Finck 
262c2c66affSColin Finck static BOOLEAN
263c2c66affSColin Finck PdoGetRangeLength(PPDO_DEVICE_EXTENSION DeviceExtension,
264c2c66affSColin Finck                   UCHAR Bar,
265c2c66affSColin Finck                   PULONGLONG Base,
266c2c66affSColin Finck                   PULONGLONG Length,
267c2c66affSColin Finck                   PULONG Flags,
268c2c66affSColin Finck                   PUCHAR NextBar,
269c2c66affSColin Finck                   PULONGLONG MaximumAddress)
270c2c66affSColin Finck {
271c2c66affSColin Finck     union {
272c2c66affSColin Finck         struct {
273c2c66affSColin Finck             ULONG Bar0;
274c2c66affSColin Finck             ULONG Bar1;
275c2c66affSColin Finck         } Bars;
276c2c66affSColin Finck         ULONGLONG Bar;
277c2c66affSColin Finck     } OriginalValue;
278c2c66affSColin Finck     union {
279c2c66affSColin Finck         struct {
280c2c66affSColin Finck             ULONG Bar0;
281c2c66affSColin Finck             ULONG Bar1;
282c2c66affSColin Finck         } Bars;
283c2c66affSColin Finck         ULONGLONG Bar;
284c2c66affSColin Finck     } NewValue;
285c2c66affSColin Finck     ULONG Offset;
286c2c66affSColin Finck 
287c2c66affSColin Finck     /* Compute the offset of this BAR in PCI config space */
288c2c66affSColin Finck     Offset = 0x10 + Bar * 4;
289c2c66affSColin Finck 
290c2c66affSColin Finck     /* Assume this is a 32-bit BAR until we find wrong */
291c2c66affSColin Finck     *NextBar = Bar + 1;
292c2c66affSColin Finck 
293c2c66affSColin Finck     /* Initialize BAR values to zero */
294c2c66affSColin Finck     OriginalValue.Bar = 0ULL;
295c2c66affSColin Finck     NewValue.Bar = 0ULL;
296c2c66affSColin Finck 
297c2c66affSColin Finck     /* Read the first BAR */
298c2c66affSColin Finck     if (!PdoReadPciBar(DeviceExtension, Offset,
299c2c66affSColin Finck                        &OriginalValue.Bars.Bar0,
300c2c66affSColin Finck                        &NewValue.Bars.Bar0))
301c2c66affSColin Finck     {
302c2c66affSColin Finck         return FALSE;
303c2c66affSColin Finck     }
304c2c66affSColin Finck 
305c2c66affSColin Finck     /* Check if this is a memory BAR */
306c2c66affSColin Finck     if (!(OriginalValue.Bars.Bar0 & PCI_ADDRESS_IO_SPACE))
307c2c66affSColin Finck     {
308c2c66affSColin Finck         /* Write the maximum address if the caller asked for it */
309c2c66affSColin Finck         if (MaximumAddress != NULL)
310c2c66affSColin Finck         {
311c2c66affSColin Finck             if ((OriginalValue.Bars.Bar0 & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_32BIT)
312c2c66affSColin Finck             {
313c2c66affSColin Finck                 *MaximumAddress = 0x00000000FFFFFFFFULL;
314c2c66affSColin Finck             }
315c2c66affSColin Finck             else if ((OriginalValue.Bars.Bar0 & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_20BIT)
316c2c66affSColin Finck             {
317c2c66affSColin Finck                 *MaximumAddress = 0x00000000000FFFFFULL;
318c2c66affSColin Finck             }
319c2c66affSColin Finck             else if ((OriginalValue.Bars.Bar0 & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT)
320c2c66affSColin Finck             {
321c2c66affSColin Finck                 *MaximumAddress = 0xFFFFFFFFFFFFFFFFULL;
322c2c66affSColin Finck             }
323c2c66affSColin Finck         }
324c2c66affSColin Finck 
325c2c66affSColin Finck         /* Check if this is a 64-bit BAR */
326c2c66affSColin Finck         if ((OriginalValue.Bars.Bar0 & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT)
327c2c66affSColin Finck         {
328c2c66affSColin Finck             /* We've now consumed the next BAR too */
329c2c66affSColin Finck             *NextBar = Bar + 2;
330c2c66affSColin Finck 
331c2c66affSColin Finck             /* Read the next BAR */
332c2c66affSColin Finck             if (!PdoReadPciBar(DeviceExtension, Offset + 4,
333c2c66affSColin Finck                                &OriginalValue.Bars.Bar1,
334c2c66affSColin Finck                                &NewValue.Bars.Bar1))
335c2c66affSColin Finck             {
336c2c66affSColin Finck                 return FALSE;
337c2c66affSColin Finck             }
338c2c66affSColin Finck         }
339c2c66affSColin Finck     }
340c2c66affSColin Finck     else
341c2c66affSColin Finck     {
342c2c66affSColin Finck         /* Write the maximum I/O port address */
343c2c66affSColin Finck         if (MaximumAddress != NULL)
344c2c66affSColin Finck         {
345c2c66affSColin Finck             *MaximumAddress = 0x00000000FFFFFFFFULL;
346c2c66affSColin Finck         }
347c2c66affSColin Finck     }
348c2c66affSColin Finck 
349c2c66affSColin Finck     if (NewValue.Bar == 0)
350c2c66affSColin Finck     {
351c2c66affSColin Finck         DPRINT("Unused address register\n");
352c2c66affSColin Finck         *Base = 0;
353c2c66affSColin Finck         *Length = 0;
354c2c66affSColin Finck         *Flags = 0;
355c2c66affSColin Finck         return TRUE;
356c2c66affSColin Finck     }
357c2c66affSColin Finck 
358c2c66affSColin Finck     *Base = ((OriginalValue.Bar & PCI_ADDRESS_IO_SPACE)
359c2c66affSColin Finck              ? (OriginalValue.Bar & PCI_ADDRESS_IO_ADDRESS_MASK_64)
360c2c66affSColin Finck              : (OriginalValue.Bar & PCI_ADDRESS_MEMORY_ADDRESS_MASK_64));
361c2c66affSColin Finck 
362c2c66affSColin Finck     *Length = ~((NewValue.Bar & PCI_ADDRESS_IO_SPACE)
363c2c66affSColin Finck                 ? (NewValue.Bar & PCI_ADDRESS_IO_ADDRESS_MASK_64)
364c2c66affSColin Finck                 : (NewValue.Bar & PCI_ADDRESS_MEMORY_ADDRESS_MASK_64)) + 1;
365c2c66affSColin Finck 
366c2c66affSColin Finck     *Flags = (NewValue.Bar & PCI_ADDRESS_IO_SPACE)
367c2c66affSColin Finck              ? (NewValue.Bar & ~PCI_ADDRESS_IO_ADDRESS_MASK_64)
368c2c66affSColin Finck              : (NewValue.Bar & ~PCI_ADDRESS_MEMORY_ADDRESS_MASK_64);
369c2c66affSColin Finck 
370c2c66affSColin Finck     return TRUE;
371c2c66affSColin Finck }
372c2c66affSColin Finck 
373c2c66affSColin Finck 
374c2c66affSColin Finck static NTSTATUS
375c2c66affSColin Finck PdoQueryResourceRequirements(
376c2c66affSColin Finck     IN PDEVICE_OBJECT DeviceObject,
377c2c66affSColin Finck     IN PIRP Irp,
378c2c66affSColin Finck     PIO_STACK_LOCATION IrpSp)
379c2c66affSColin Finck {
380c2c66affSColin Finck     PPDO_DEVICE_EXTENSION DeviceExtension;
381c2c66affSColin Finck     PCI_COMMON_CONFIG PciConfig;
382c2c66affSColin Finck     PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
383c2c66affSColin Finck     PIO_RESOURCE_DESCRIPTOR Descriptor;
384c2c66affSColin Finck     ULONG Size;
385c2c66affSColin Finck     ULONG ResCount = 0;
386c2c66affSColin Finck     ULONG ListSize;
387c2c66affSColin Finck     UCHAR Bar;
388c2c66affSColin Finck     ULONGLONG Base;
389c2c66affSColin Finck     ULONGLONG Length;
390c2c66affSColin Finck     ULONG Flags;
391c2c66affSColin Finck     ULONGLONG MaximumAddress;
392c2c66affSColin Finck 
393c2c66affSColin Finck     UNREFERENCED_PARAMETER(IrpSp);
394c2c66affSColin Finck     DPRINT("PdoQueryResourceRequirements() called\n");
395c2c66affSColin Finck 
396c2c66affSColin Finck     DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
397c2c66affSColin Finck 
398c2c66affSColin Finck     /* Get PCI configuration space */
399c2c66affSColin Finck     Size= HalGetBusData(PCIConfiguration,
400c2c66affSColin Finck                         DeviceExtension->PciDevice->BusNumber,
401c2c66affSColin Finck                         DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
402c2c66affSColin Finck                         &PciConfig,
403c2c66affSColin Finck                         PCI_COMMON_HDR_LENGTH);
404c2c66affSColin Finck     DPRINT("Size %lu\n", Size);
405c2c66affSColin Finck     if (Size < PCI_COMMON_HDR_LENGTH)
406c2c66affSColin Finck     {
407c2c66affSColin Finck         Irp->IoStatus.Information = 0;
408c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
409c2c66affSColin Finck     }
410c2c66affSColin Finck 
411c2c66affSColin Finck     DPRINT("Command register: 0x%04hx\n", PciConfig.Command);
412c2c66affSColin Finck 
413c2c66affSColin Finck     /* Count required resource descriptors */
414c2c66affSColin Finck     ResCount = 0;
415c2c66affSColin Finck     if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
416c2c66affSColin Finck     {
417c2c66affSColin Finck         for (Bar = 0; Bar < PCI_TYPE0_ADDRESSES;)
418c2c66affSColin Finck         {
419c2c66affSColin Finck             if (!PdoGetRangeLength(DeviceExtension,
420c2c66affSColin Finck                                    Bar,
421c2c66affSColin Finck                                    &Base,
422c2c66affSColin Finck                                    &Length,
423c2c66affSColin Finck                                    &Flags,
424c2c66affSColin Finck                                    &Bar,
425c2c66affSColin Finck                                    NULL))
426c2c66affSColin Finck                 break;
427c2c66affSColin Finck 
428c2c66affSColin Finck             if (Length != 0)
429c2c66affSColin Finck                 ResCount += 2;
430c2c66affSColin Finck         }
431c2c66affSColin Finck 
432c2c66affSColin Finck         /* FIXME: Check ROM address */
433c2c66affSColin Finck 
434c2c66affSColin Finck         if (PciConfig.u.type0.InterruptPin != 0)
435c2c66affSColin Finck             ResCount++;
436c2c66affSColin Finck     }
437c2c66affSColin Finck     else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
438c2c66affSColin Finck     {
439c2c66affSColin Finck         for (Bar = 0; Bar < PCI_TYPE1_ADDRESSES;)
440c2c66affSColin Finck         {
441c2c66affSColin Finck             if (!PdoGetRangeLength(DeviceExtension,
442c2c66affSColin Finck                                    Bar,
443c2c66affSColin Finck                                    &Base,
444c2c66affSColin Finck                                    &Length,
445c2c66affSColin Finck                                    &Flags,
446c2c66affSColin Finck                                    &Bar,
447c2c66affSColin Finck                                    NULL))
448c2c66affSColin Finck                 break;
449c2c66affSColin Finck 
450c2c66affSColin Finck             if (Length != 0)
451c2c66affSColin Finck                 ResCount += 2;
452c2c66affSColin Finck         }
453c2c66affSColin Finck 
454c2c66affSColin Finck         if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
455c2c66affSColin Finck             ResCount++;
456c2c66affSColin Finck     }
457c2c66affSColin Finck     else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
458c2c66affSColin Finck     {
459c2c66affSColin Finck         /* FIXME: Count Cardbus bridge resources */
460c2c66affSColin Finck     }
461c2c66affSColin Finck     else
462c2c66affSColin Finck     {
463c2c66affSColin Finck         DPRINT1("Unsupported header type %d\n", PCI_CONFIGURATION_TYPE(&PciConfig));
464c2c66affSColin Finck     }
465c2c66affSColin Finck 
466c2c66affSColin Finck     if (ResCount == 0)
467c2c66affSColin Finck     {
468c2c66affSColin Finck         Irp->IoStatus.Information = 0;
469c2c66affSColin Finck         return STATUS_SUCCESS;
470c2c66affSColin Finck     }
471c2c66affSColin Finck 
472c2c66affSColin Finck     /* Calculate the resource list size */
473c2c66affSColin Finck     ListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List[0].Descriptors) +
474c2c66affSColin Finck                ResCount * sizeof(IO_RESOURCE_DESCRIPTOR);
475c2c66affSColin Finck 
476c2c66affSColin Finck     DPRINT("ListSize %lu (0x%lx)\n", ListSize, ListSize);
477c2c66affSColin Finck 
478c2c66affSColin Finck     /* Allocate the resource requirements list */
479c2c66affSColin Finck     ResourceList = ExAllocatePoolWithTag(PagedPool,
480c2c66affSColin Finck                                          ListSize,
481c2c66affSColin Finck                                          TAG_PCI);
482c2c66affSColin Finck     if (ResourceList == NULL)
483c2c66affSColin Finck     {
484c2c66affSColin Finck         Irp->IoStatus.Information = 0;
485c2c66affSColin Finck         return STATUS_INSUFFICIENT_RESOURCES;
486c2c66affSColin Finck     }
487c2c66affSColin Finck 
488c2c66affSColin Finck     RtlZeroMemory(ResourceList, ListSize);
489c2c66affSColin Finck     ResourceList->ListSize = ListSize;
490c2c66affSColin Finck     ResourceList->InterfaceType = PCIBus;
491c2c66affSColin Finck     ResourceList->BusNumber = DeviceExtension->PciDevice->BusNumber;
492c2c66affSColin Finck     ResourceList->SlotNumber = DeviceExtension->PciDevice->SlotNumber.u.AsULONG;
493c2c66affSColin Finck     ResourceList->AlternativeLists = 1;
494c2c66affSColin Finck 
495c2c66affSColin Finck     ResourceList->List[0].Version = 1;
496c2c66affSColin Finck     ResourceList->List[0].Revision = 1;
497c2c66affSColin Finck     ResourceList->List[0].Count = ResCount;
498c2c66affSColin Finck 
499c2c66affSColin Finck     Descriptor = &ResourceList->List[0].Descriptors[0];
500c2c66affSColin Finck     if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
501c2c66affSColin Finck     {
502c2c66affSColin Finck         for (Bar = 0; Bar < PCI_TYPE0_ADDRESSES;)
503c2c66affSColin Finck         {
504c2c66affSColin Finck             if (!PdoGetRangeLength(DeviceExtension,
505c2c66affSColin Finck                                    Bar,
506c2c66affSColin Finck                                    &Base,
507c2c66affSColin Finck                                    &Length,
508c2c66affSColin Finck                                    &Flags,
509c2c66affSColin Finck                                    &Bar,
510c2c66affSColin Finck                                    &MaximumAddress))
511c2c66affSColin Finck             {
512c2c66affSColin Finck                 DPRINT1("PdoGetRangeLength() failed\n");
513c2c66affSColin Finck                 break;
514c2c66affSColin Finck             }
515c2c66affSColin Finck 
516c2c66affSColin Finck             if (Length == 0)
517c2c66affSColin Finck             {
518c2c66affSColin Finck                 DPRINT("Unused address register\n");
519c2c66affSColin Finck                 continue;
520c2c66affSColin Finck             }
521c2c66affSColin Finck 
522c2c66affSColin Finck             /* Set preferred descriptor */
523c2c66affSColin Finck             Descriptor->Option = IO_RESOURCE_PREFERRED;
524c2c66affSColin Finck             if (Flags & PCI_ADDRESS_IO_SPACE)
525c2c66affSColin Finck             {
526c2c66affSColin Finck                 Descriptor->Type = CmResourceTypePort;
527c2c66affSColin Finck                 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
528c2c66affSColin Finck                 Descriptor->Flags = CM_RESOURCE_PORT_IO |
529c2c66affSColin Finck                                     CM_RESOURCE_PORT_16_BIT_DECODE |
530c2c66affSColin Finck                                     CM_RESOURCE_PORT_POSITIVE_DECODE;
531c2c66affSColin Finck 
532c2c66affSColin Finck                 Descriptor->u.Port.Length = Length;
533c2c66affSColin Finck                 Descriptor->u.Port.Alignment = 1;
534c2c66affSColin Finck                 Descriptor->u.Port.MinimumAddress.QuadPart = Base;
535c2c66affSColin Finck                 Descriptor->u.Port.MaximumAddress.QuadPart = Base + Length - 1;
536c2c66affSColin Finck             }
537c2c66affSColin Finck             else
538c2c66affSColin Finck             {
539c2c66affSColin Finck                 Descriptor->Type = CmResourceTypeMemory;
540c2c66affSColin Finck                 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
541c2c66affSColin Finck                 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE |
542c2c66affSColin Finck                     (Flags & PCI_ADDRESS_MEMORY_PREFETCHABLE) ? CM_RESOURCE_MEMORY_PREFETCHABLE : 0;
543c2c66affSColin Finck 
544c2c66affSColin Finck                 Descriptor->u.Memory.Length = Length;
545c2c66affSColin Finck                 Descriptor->u.Memory.Alignment = 1;
546c2c66affSColin Finck                 Descriptor->u.Memory.MinimumAddress.QuadPart = Base;
547c2c66affSColin Finck                 Descriptor->u.Memory.MaximumAddress.QuadPart = Base + Length - 1;
548c2c66affSColin Finck             }
549c2c66affSColin Finck             Descriptor++;
550c2c66affSColin Finck 
551c2c66affSColin Finck             /* Set alternative descriptor */
552c2c66affSColin Finck             Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
553c2c66affSColin Finck             if (Flags & PCI_ADDRESS_IO_SPACE)
554c2c66affSColin Finck             {
555c2c66affSColin Finck                 Descriptor->Type = CmResourceTypePort;
556c2c66affSColin Finck                 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
557c2c66affSColin Finck                 Descriptor->Flags = CM_RESOURCE_PORT_IO |
558c2c66affSColin Finck                                     CM_RESOURCE_PORT_16_BIT_DECODE |
559c2c66affSColin Finck                                     CM_RESOURCE_PORT_POSITIVE_DECODE;
560c2c66affSColin Finck 
561c2c66affSColin Finck                 Descriptor->u.Port.Length = Length;
562c2c66affSColin Finck                 Descriptor->u.Port.Alignment = Length;
563c2c66affSColin Finck                 Descriptor->u.Port.MinimumAddress.QuadPart = 0;
564c2c66affSColin Finck                 Descriptor->u.Port.MaximumAddress.QuadPart = MaximumAddress;
565c2c66affSColin Finck             }
566c2c66affSColin Finck             else
567c2c66affSColin Finck             {
568c2c66affSColin Finck                 Descriptor->Type = CmResourceTypeMemory;
569c2c66affSColin Finck                 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
570c2c66affSColin Finck                 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE |
571c2c66affSColin Finck                     (Flags & PCI_ADDRESS_MEMORY_PREFETCHABLE) ? CM_RESOURCE_MEMORY_PREFETCHABLE : 0;
572c2c66affSColin Finck 
573c2c66affSColin Finck                 Descriptor->u.Memory.Length = Length;
574c2c66affSColin Finck                 Descriptor->u.Memory.Alignment = Length;
575c2c66affSColin Finck                 Descriptor->u.Port.MinimumAddress.QuadPart = 0;
576c2c66affSColin Finck                 Descriptor->u.Port.MaximumAddress.QuadPart = MaximumAddress;
577c2c66affSColin Finck             }
578c2c66affSColin Finck             Descriptor++;
579c2c66affSColin Finck         }
580c2c66affSColin Finck 
581c2c66affSColin Finck         /* FIXME: Check ROM address */
582c2c66affSColin Finck 
583c2c66affSColin Finck         if (PciConfig.u.type0.InterruptPin != 0)
584c2c66affSColin Finck         {
585c2c66affSColin Finck             Descriptor->Option = 0; /* Required */
586c2c66affSColin Finck             Descriptor->Type = CmResourceTypeInterrupt;
587c2c66affSColin Finck             Descriptor->ShareDisposition = CmResourceShareShared;
588c2c66affSColin Finck             Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
589c2c66affSColin Finck 
590c2c66affSColin Finck             Descriptor->u.Interrupt.MinimumVector = 0;
591c2c66affSColin Finck             Descriptor->u.Interrupt.MaximumVector = 0xFF;
592c2c66affSColin Finck         }
593c2c66affSColin Finck     }
594c2c66affSColin Finck     else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
595c2c66affSColin Finck     {
596c2c66affSColin Finck         for (Bar = 0; Bar < PCI_TYPE1_ADDRESSES;)
597c2c66affSColin Finck         {
598c2c66affSColin Finck             if (!PdoGetRangeLength(DeviceExtension,
599c2c66affSColin Finck                                    Bar,
600c2c66affSColin Finck                                    &Base,
601c2c66affSColin Finck                                    &Length,
602c2c66affSColin Finck                                    &Flags,
603c2c66affSColin Finck                                    &Bar,
604c2c66affSColin Finck                                    &MaximumAddress))
605c2c66affSColin Finck             {
606c2c66affSColin Finck                 DPRINT1("PdoGetRangeLength() failed\n");
607c2c66affSColin Finck                 break;
608c2c66affSColin Finck             }
609c2c66affSColin Finck 
610c2c66affSColin Finck             if (Length == 0)
611c2c66affSColin Finck             {
612c2c66affSColin Finck                 DPRINT("Unused address register\n");
613c2c66affSColin Finck                 continue;
614c2c66affSColin Finck             }
615c2c66affSColin Finck 
616c2c66affSColin Finck             /* Set preferred descriptor */
617c2c66affSColin Finck             Descriptor->Option = IO_RESOURCE_PREFERRED;
618c2c66affSColin Finck             if (Flags & PCI_ADDRESS_IO_SPACE)
619c2c66affSColin Finck             {
620c2c66affSColin Finck                 Descriptor->Type = CmResourceTypePort;
621c2c66affSColin Finck                 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
622c2c66affSColin Finck                 Descriptor->Flags = CM_RESOURCE_PORT_IO |
623c2c66affSColin Finck                                     CM_RESOURCE_PORT_16_BIT_DECODE |
624c2c66affSColin Finck                                     CM_RESOURCE_PORT_POSITIVE_DECODE;
625c2c66affSColin Finck 
626c2c66affSColin Finck                 Descriptor->u.Port.Length = Length;
627c2c66affSColin Finck                 Descriptor->u.Port.Alignment = 1;
628c2c66affSColin Finck                 Descriptor->u.Port.MinimumAddress.QuadPart = Base;
629c2c66affSColin Finck                 Descriptor->u.Port.MaximumAddress.QuadPart = Base + Length - 1;
630c2c66affSColin Finck             }
631c2c66affSColin Finck             else
632c2c66affSColin Finck             {
633c2c66affSColin Finck                 Descriptor->Type = CmResourceTypeMemory;
634c2c66affSColin Finck                 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
635c2c66affSColin Finck                 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE |
636c2c66affSColin Finck                     (Flags & PCI_ADDRESS_MEMORY_PREFETCHABLE) ? CM_RESOURCE_MEMORY_PREFETCHABLE : 0;
637c2c66affSColin Finck 
638c2c66affSColin Finck                 Descriptor->u.Memory.Length = Length;
639c2c66affSColin Finck                 Descriptor->u.Memory.Alignment = 1;
640c2c66affSColin Finck                 Descriptor->u.Memory.MinimumAddress.QuadPart = Base;
641c2c66affSColin Finck                 Descriptor->u.Memory.MaximumAddress.QuadPart = Base + Length - 1;
642c2c66affSColin Finck             }
643c2c66affSColin Finck             Descriptor++;
644c2c66affSColin Finck 
645c2c66affSColin Finck             /* Set alternative descriptor */
646c2c66affSColin Finck             Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
647c2c66affSColin Finck             if (Flags & PCI_ADDRESS_IO_SPACE)
648c2c66affSColin Finck             {
649c2c66affSColin Finck                 Descriptor->Type = CmResourceTypePort;
650c2c66affSColin Finck                 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
651c2c66affSColin Finck                 Descriptor->Flags = CM_RESOURCE_PORT_IO |
652c2c66affSColin Finck                                     CM_RESOURCE_PORT_16_BIT_DECODE |
653c2c66affSColin Finck                                     CM_RESOURCE_PORT_POSITIVE_DECODE;
654c2c66affSColin Finck 
655c2c66affSColin Finck                 Descriptor->u.Port.Length = Length;
656c2c66affSColin Finck                 Descriptor->u.Port.Alignment = Length;
657c2c66affSColin Finck                 Descriptor->u.Port.MinimumAddress.QuadPart = 0;
658c2c66affSColin Finck                 Descriptor->u.Port.MaximumAddress.QuadPart = MaximumAddress;
659c2c66affSColin Finck             }
660c2c66affSColin Finck             else
661c2c66affSColin Finck             {
662c2c66affSColin Finck                 Descriptor->Type = CmResourceTypeMemory;
663c2c66affSColin Finck                 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
664c2c66affSColin Finck                 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE |
665c2c66affSColin Finck                     (Flags & PCI_ADDRESS_MEMORY_PREFETCHABLE) ? CM_RESOURCE_MEMORY_PREFETCHABLE : 0;
666c2c66affSColin Finck 
667c2c66affSColin Finck                 Descriptor->u.Memory.Length = Length;
668c2c66affSColin Finck                 Descriptor->u.Memory.Alignment = Length;
669c2c66affSColin Finck                 Descriptor->u.Port.MinimumAddress.QuadPart = 0;
670c2c66affSColin Finck                 Descriptor->u.Port.MaximumAddress.QuadPart = MaximumAddress;
671c2c66affSColin Finck             }
672c2c66affSColin Finck             Descriptor++;
673c2c66affSColin Finck         }
674c2c66affSColin Finck 
675c2c66affSColin Finck         if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
676c2c66affSColin Finck         {
677c2c66affSColin Finck             Descriptor->Option = 0; /* Required */
678c2c66affSColin Finck             Descriptor->Type = CmResourceTypeBusNumber;
679c2c66affSColin Finck             Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
680c2c66affSColin Finck 
681c2c66affSColin Finck             ResourceList->BusNumber =
682c2c66affSColin Finck             Descriptor->u.BusNumber.MinBusNumber =
683c2c66affSColin Finck             Descriptor->u.BusNumber.MaxBusNumber = DeviceExtension->PciDevice->PciConfig.u.type1.SecondaryBus;
684c2c66affSColin Finck             Descriptor->u.BusNumber.Length = 1;
685c2c66affSColin Finck             Descriptor->u.BusNumber.Reserved = 0;
686c2c66affSColin Finck         }
687c2c66affSColin Finck     }
688c2c66affSColin Finck     else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
689c2c66affSColin Finck     {
690c2c66affSColin Finck         /* FIXME: Add Cardbus bridge resources */
691c2c66affSColin Finck     }
692c2c66affSColin Finck 
693c2c66affSColin Finck     Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
694c2c66affSColin Finck 
695c2c66affSColin Finck     return STATUS_SUCCESS;
696c2c66affSColin Finck }
697c2c66affSColin Finck 
698c2c66affSColin Finck 
699c2c66affSColin Finck static NTSTATUS
700c2c66affSColin Finck PdoQueryResources(
701c2c66affSColin Finck     IN PDEVICE_OBJECT DeviceObject,
702c2c66affSColin Finck     IN PIRP Irp,
703c2c66affSColin Finck     PIO_STACK_LOCATION IrpSp)
704c2c66affSColin Finck {
705c2c66affSColin Finck     PPDO_DEVICE_EXTENSION DeviceExtension;
706c2c66affSColin Finck     PCI_COMMON_CONFIG PciConfig;
707c2c66affSColin Finck     PCM_RESOURCE_LIST ResourceList;
708c2c66affSColin Finck     PCM_PARTIAL_RESOURCE_LIST PartialList;
709c2c66affSColin Finck     PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
710c2c66affSColin Finck     ULONG Size;
711c2c66affSColin Finck     ULONG ResCount = 0;
712c2c66affSColin Finck     ULONG ListSize;
713c2c66affSColin Finck     UCHAR Bar;
714c2c66affSColin Finck     ULONGLONG Base;
715c2c66affSColin Finck     ULONGLONG Length;
716c2c66affSColin Finck     ULONG Flags;
717c2c66affSColin Finck 
718c2c66affSColin Finck     DPRINT("PdoQueryResources() called\n");
719c2c66affSColin Finck 
720c2c66affSColin Finck     UNREFERENCED_PARAMETER(IrpSp);
721c2c66affSColin Finck     DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
722c2c66affSColin Finck 
723c2c66affSColin Finck     /* Get PCI configuration space */
724c2c66affSColin Finck     Size= HalGetBusData(PCIConfiguration,
725c2c66affSColin Finck                         DeviceExtension->PciDevice->BusNumber,
726c2c66affSColin Finck                         DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
727c2c66affSColin Finck                         &PciConfig,
728c2c66affSColin Finck                         PCI_COMMON_HDR_LENGTH);
729c2c66affSColin Finck     DPRINT("Size %lu\n", Size);
730c2c66affSColin Finck     if (Size < PCI_COMMON_HDR_LENGTH)
731c2c66affSColin Finck     {
732c2c66affSColin Finck         Irp->IoStatus.Information = 0;
733c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
734c2c66affSColin Finck     }
735c2c66affSColin Finck 
736c2c66affSColin Finck     DPRINT("Command register: 0x%04hx\n", PciConfig.Command);
737c2c66affSColin Finck 
738c2c66affSColin Finck     /* Count required resource descriptors */
739c2c66affSColin Finck     ResCount = 0;
740c2c66affSColin Finck     if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
741c2c66affSColin Finck     {
742c2c66affSColin Finck         for (Bar = 0; Bar < PCI_TYPE0_ADDRESSES;)
743c2c66affSColin Finck         {
744c2c66affSColin Finck             if (!PdoGetRangeLength(DeviceExtension,
745c2c66affSColin Finck                                    Bar,
746c2c66affSColin Finck                                    &Base,
747c2c66affSColin Finck                                    &Length,
748c2c66affSColin Finck                                    &Flags,
749c2c66affSColin Finck                                    &Bar,
750c2c66affSColin Finck                                    NULL))
751c2c66affSColin Finck                 break;
752c2c66affSColin Finck 
753c2c66affSColin Finck             if (Length)
754c2c66affSColin Finck                 ResCount++;
755c2c66affSColin Finck         }
756c2c66affSColin Finck 
757c2c66affSColin Finck         if ((PciConfig.u.type0.InterruptPin != 0) &&
758c2c66affSColin Finck             (PciConfig.u.type0.InterruptLine != 0) &&
759c2c66affSColin Finck             (PciConfig.u.type0.InterruptLine != 0xFF))
760c2c66affSColin Finck             ResCount++;
761c2c66affSColin Finck     }
762c2c66affSColin Finck     else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
763c2c66affSColin Finck     {
764c2c66affSColin Finck         for (Bar = 0; Bar < PCI_TYPE1_ADDRESSES;)
765c2c66affSColin Finck         {
766c2c66affSColin Finck             if (!PdoGetRangeLength(DeviceExtension,
767c2c66affSColin Finck                                    Bar,
768c2c66affSColin Finck                                    &Base,
769c2c66affSColin Finck                                    &Length,
770c2c66affSColin Finck                                    &Flags,
771c2c66affSColin Finck                                    &Bar,
772c2c66affSColin Finck                                    NULL))
773c2c66affSColin Finck                 break;
774c2c66affSColin Finck 
775c2c66affSColin Finck             if (Length != 0)
776c2c66affSColin Finck                 ResCount++;
777c2c66affSColin Finck         }
778c2c66affSColin Finck 
779c2c66affSColin Finck         if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
780c2c66affSColin Finck             ResCount++;
781c2c66affSColin Finck     }
782c2c66affSColin Finck     else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
783c2c66affSColin Finck     {
784c2c66affSColin Finck         /* FIXME: Count Cardbus bridge resources */
785c2c66affSColin Finck     }
786c2c66affSColin Finck     else
787c2c66affSColin Finck     {
788c2c66affSColin Finck         DPRINT1("Unsupported header type %d\n", PCI_CONFIGURATION_TYPE(&PciConfig));
789c2c66affSColin Finck     }
790c2c66affSColin Finck 
791c2c66affSColin Finck     if (ResCount == 0)
792c2c66affSColin Finck     {
793c2c66affSColin Finck         Irp->IoStatus.Information = 0;
794c2c66affSColin Finck         return STATUS_SUCCESS;
795c2c66affSColin Finck     }
796c2c66affSColin Finck 
797c2c66affSColin Finck     /* Calculate the resource list size */
798c2c66affSColin Finck     ListSize = FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.PartialDescriptors) +
799c2c66affSColin Finck                ResCount * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
800c2c66affSColin Finck 
801c2c66affSColin Finck     /* Allocate the resource list */
802c2c66affSColin Finck     ResourceList = ExAllocatePoolWithTag(PagedPool,
803c2c66affSColin Finck                                          ListSize,
804c2c66affSColin Finck                                          TAG_PCI);
805c2c66affSColin Finck     if (ResourceList == NULL)
806c2c66affSColin Finck         return STATUS_INSUFFICIENT_RESOURCES;
807c2c66affSColin Finck 
808c2c66affSColin Finck     RtlZeroMemory(ResourceList, ListSize);
809c2c66affSColin Finck     ResourceList->Count = 1;
810c2c66affSColin Finck     ResourceList->List[0].InterfaceType = PCIBus;
811c2c66affSColin Finck     ResourceList->List[0].BusNumber = DeviceExtension->PciDevice->BusNumber;
812c2c66affSColin Finck 
813c2c66affSColin Finck     PartialList = &ResourceList->List[0].PartialResourceList;
814c2c66affSColin Finck     PartialList->Version = 1;
815c2c66affSColin Finck     PartialList->Revision = 1;
816c2c66affSColin Finck     PartialList->Count = ResCount;
817c2c66affSColin Finck 
818c2c66affSColin Finck     Descriptor = &PartialList->PartialDescriptors[0];
819c2c66affSColin Finck     if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
820c2c66affSColin Finck     {
821c2c66affSColin Finck         for (Bar = 0; Bar < PCI_TYPE0_ADDRESSES;)
822c2c66affSColin Finck         {
823c2c66affSColin Finck             if (!PdoGetRangeLength(DeviceExtension,
824c2c66affSColin Finck                                    Bar,
825c2c66affSColin Finck                                    &Base,
826c2c66affSColin Finck                                    &Length,
827c2c66affSColin Finck                                    &Flags,
828c2c66affSColin Finck                                    &Bar,
829c2c66affSColin Finck                                    NULL))
830c2c66affSColin Finck                 break;
831c2c66affSColin Finck 
832c2c66affSColin Finck             if (Length == 0)
833c2c66affSColin Finck             {
834c2c66affSColin Finck                 DPRINT("Unused address register\n");
835c2c66affSColin Finck                 continue;
836c2c66affSColin Finck             }
837c2c66affSColin Finck 
838c2c66affSColin Finck             if (Flags & PCI_ADDRESS_IO_SPACE)
839c2c66affSColin Finck             {
840c2c66affSColin Finck                 Descriptor->Type = CmResourceTypePort;
841c2c66affSColin Finck                 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
842c2c66affSColin Finck                 Descriptor->Flags = CM_RESOURCE_PORT_IO |
843c2c66affSColin Finck                                     CM_RESOURCE_PORT_16_BIT_DECODE |
844c2c66affSColin Finck                                     CM_RESOURCE_PORT_POSITIVE_DECODE;
845c2c66affSColin Finck                 Descriptor->u.Port.Start.QuadPart = (ULONGLONG)Base;
846c2c66affSColin Finck                 Descriptor->u.Port.Length = Length;
847c2c66affSColin Finck 
848c2c66affSColin Finck                 /* Enable IO space access */
849c2c66affSColin Finck                 DeviceExtension->PciDevice->EnableIoSpace = TRUE;
850c2c66affSColin Finck             }
851c2c66affSColin Finck             else
852c2c66affSColin Finck             {
853c2c66affSColin Finck                 Descriptor->Type = CmResourceTypeMemory;
854c2c66affSColin Finck                 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
855c2c66affSColin Finck                 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE |
856c2c66affSColin Finck                     (Flags & PCI_ADDRESS_MEMORY_PREFETCHABLE) ? CM_RESOURCE_MEMORY_PREFETCHABLE : 0;
857c2c66affSColin Finck                 Descriptor->u.Memory.Start.QuadPart = (ULONGLONG)Base;
858c2c66affSColin Finck                 Descriptor->u.Memory.Length = Length;
859c2c66affSColin Finck 
860c2c66affSColin Finck                 /* Enable memory space access */
861c2c66affSColin Finck                 DeviceExtension->PciDevice->EnableMemorySpace = TRUE;
862c2c66affSColin Finck             }
863c2c66affSColin Finck 
864c2c66affSColin Finck             Descriptor++;
865c2c66affSColin Finck         }
866c2c66affSColin Finck 
867c2c66affSColin Finck         /* Add interrupt resource */
868c2c66affSColin Finck         if ((PciConfig.u.type0.InterruptPin != 0) &&
869c2c66affSColin Finck             (PciConfig.u.type0.InterruptLine != 0) &&
870c2c66affSColin Finck             (PciConfig.u.type0.InterruptLine != 0xFF))
871c2c66affSColin Finck         {
872c2c66affSColin Finck             Descriptor->Type = CmResourceTypeInterrupt;
873c2c66affSColin Finck             Descriptor->ShareDisposition = CmResourceShareShared;
874c2c66affSColin Finck             Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
875c2c66affSColin Finck             Descriptor->u.Interrupt.Level = PciConfig.u.type0.InterruptLine;
876c2c66affSColin Finck             Descriptor->u.Interrupt.Vector = PciConfig.u.type0.InterruptLine;
877c2c66affSColin Finck             Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
878c2c66affSColin Finck         }
879c2c66affSColin Finck 
880c2c66affSColin Finck         /* Allow bus master mode */
881c2c66affSColin Finck        DeviceExtension->PciDevice->EnableBusMaster = TRUE;
882c2c66affSColin Finck     }
883c2c66affSColin Finck     else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
884c2c66affSColin Finck     {
885c2c66affSColin Finck         for (Bar = 0; Bar < PCI_TYPE1_ADDRESSES;)
886c2c66affSColin Finck         {
887c2c66affSColin Finck             if (!PdoGetRangeLength(DeviceExtension,
888c2c66affSColin Finck                                    Bar,
889c2c66affSColin Finck                                    &Base,
890c2c66affSColin Finck                                    &Length,
891c2c66affSColin Finck                                    &Flags,
892c2c66affSColin Finck                                    &Bar,
893c2c66affSColin Finck                                    NULL))
894c2c66affSColin Finck                 break;
895c2c66affSColin Finck 
896c2c66affSColin Finck             if (Length == 0)
897c2c66affSColin Finck             {
898c2c66affSColin Finck                 DPRINT("Unused address register\n");
899c2c66affSColin Finck                 continue;
900c2c66affSColin Finck             }
901c2c66affSColin Finck 
902c2c66affSColin Finck             if (Flags & PCI_ADDRESS_IO_SPACE)
903c2c66affSColin Finck             {
904c2c66affSColin Finck                 Descriptor->Type = CmResourceTypePort;
905c2c66affSColin Finck                 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
906c2c66affSColin Finck                 Descriptor->Flags = CM_RESOURCE_PORT_IO |
907c2c66affSColin Finck                                     CM_RESOURCE_PORT_16_BIT_DECODE |
908c2c66affSColin Finck                                     CM_RESOURCE_PORT_POSITIVE_DECODE;
909c2c66affSColin Finck                 Descriptor->u.Port.Start.QuadPart = (ULONGLONG)Base;
910c2c66affSColin Finck                 Descriptor->u.Port.Length = Length;
911c2c66affSColin Finck 
912c2c66affSColin Finck                 /* Enable IO space access */
913c2c66affSColin Finck                 DeviceExtension->PciDevice->EnableIoSpace = TRUE;
914c2c66affSColin Finck             }
915c2c66affSColin Finck             else
916c2c66affSColin Finck             {
917c2c66affSColin Finck                 Descriptor->Type = CmResourceTypeMemory;
918c2c66affSColin Finck                 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
919c2c66affSColin Finck                 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE |
920c2c66affSColin Finck                     (Flags & PCI_ADDRESS_MEMORY_PREFETCHABLE) ? CM_RESOURCE_MEMORY_PREFETCHABLE : 0;
921c2c66affSColin Finck                 Descriptor->u.Memory.Start.QuadPart = (ULONGLONG)Base;
922c2c66affSColin Finck                 Descriptor->u.Memory.Length = Length;
923c2c66affSColin Finck 
924c2c66affSColin Finck                 /* Enable memory space access */
925c2c66affSColin Finck                 DeviceExtension->PciDevice->EnableMemorySpace = TRUE;
926c2c66affSColin Finck             }
927c2c66affSColin Finck 
928c2c66affSColin Finck             Descriptor++;
929c2c66affSColin Finck         }
930c2c66affSColin Finck 
931c2c66affSColin Finck         if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
932c2c66affSColin Finck         {
933c2c66affSColin Finck             Descriptor->Type = CmResourceTypeBusNumber;
934c2c66affSColin Finck             Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
935c2c66affSColin Finck 
936c2c66affSColin Finck             ResourceList->List[0].BusNumber =
937c2c66affSColin Finck             Descriptor->u.BusNumber.Start = DeviceExtension->PciDevice->PciConfig.u.type1.SecondaryBus;
938c2c66affSColin Finck             Descriptor->u.BusNumber.Length = 1;
939c2c66affSColin Finck             Descriptor->u.BusNumber.Reserved = 0;
940c2c66affSColin Finck         }
941c2c66affSColin Finck     }
942c2c66affSColin Finck     else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
943c2c66affSColin Finck     {
944c2c66affSColin Finck         /* FIXME: Add Cardbus bridge resources */
945c2c66affSColin Finck     }
946c2c66affSColin Finck 
947c2c66affSColin Finck     Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
948c2c66affSColin Finck 
949c2c66affSColin Finck     return STATUS_SUCCESS;
950c2c66affSColin Finck }
951c2c66affSColin Finck 
952c2c66affSColin Finck 
953c2c66affSColin Finck static VOID NTAPI
954c2c66affSColin Finck InterfaceReference(
955c2c66affSColin Finck     IN PVOID Context)
956c2c66affSColin Finck {
957c2c66affSColin Finck     PPDO_DEVICE_EXTENSION DeviceExtension;
958c2c66affSColin Finck 
959c2c66affSColin Finck     DPRINT("InterfaceReference(%p)\n", Context);
960c2c66affSColin Finck 
961c2c66affSColin Finck     DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
962c2c66affSColin Finck     InterlockedIncrement(&DeviceExtension->References);
963c2c66affSColin Finck }
964c2c66affSColin Finck 
965c2c66affSColin Finck 
966c2c66affSColin Finck static VOID NTAPI
967c2c66affSColin Finck InterfaceDereference(
968c2c66affSColin Finck     IN PVOID Context)
969c2c66affSColin Finck {
970c2c66affSColin Finck     PPDO_DEVICE_EXTENSION DeviceExtension;
971c2c66affSColin Finck 
972c2c66affSColin Finck     DPRINT("InterfaceDereference(%p)\n", Context);
973c2c66affSColin Finck 
974c2c66affSColin Finck     DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
975c2c66affSColin Finck     InterlockedDecrement(&DeviceExtension->References);
976c2c66affSColin Finck }
977c2c66affSColin Finck 
978c2c66affSColin Finck static TRANSLATE_BUS_ADDRESS InterfaceBusTranslateBusAddress;
979c2c66affSColin Finck 
980c2c66affSColin Finck static
981c2c66affSColin Finck BOOLEAN
982c2c66affSColin Finck NTAPI
983c2c66affSColin Finck InterfaceBusTranslateBusAddress(
984c2c66affSColin Finck     IN PVOID Context,
985c2c66affSColin Finck     IN PHYSICAL_ADDRESS BusAddress,
986c2c66affSColin Finck     IN ULONG Length,
987c2c66affSColin Finck     IN OUT PULONG AddressSpace,
988c2c66affSColin Finck     OUT PPHYSICAL_ADDRESS TranslatedAddress)
989c2c66affSColin Finck {
990c2c66affSColin Finck     PPDO_DEVICE_EXTENSION DeviceExtension;
991c2c66affSColin Finck 
992c2c66affSColin Finck     DPRINT("InterfaceBusTranslateBusAddress(%p %p 0x%lx %p %p)\n",
993c2c66affSColin Finck            Context, BusAddress, Length, AddressSpace, TranslatedAddress);
994c2c66affSColin Finck 
995c2c66affSColin Finck     DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
996c2c66affSColin Finck 
997c2c66affSColin Finck     return HalTranslateBusAddress(PCIBus,
998c2c66affSColin Finck                                   DeviceExtension->PciDevice->BusNumber,
999c2c66affSColin Finck                                   BusAddress,
1000c2c66affSColin Finck                                   AddressSpace,
1001c2c66affSColin Finck                                   TranslatedAddress);
1002c2c66affSColin Finck }
1003c2c66affSColin Finck 
1004c2c66affSColin Finck static GET_DMA_ADAPTER InterfaceBusGetDmaAdapter;
1005c2c66affSColin Finck 
1006c2c66affSColin Finck static
1007c2c66affSColin Finck PDMA_ADAPTER
1008c2c66affSColin Finck NTAPI
1009c2c66affSColin Finck InterfaceBusGetDmaAdapter(
1010c2c66affSColin Finck     IN PVOID Context,
1011c2c66affSColin Finck     IN PDEVICE_DESCRIPTION DeviceDescription,
1012c2c66affSColin Finck     OUT PULONG NumberOfMapRegisters)
1013c2c66affSColin Finck {
1014c2c66affSColin Finck     DPRINT("InterfaceBusGetDmaAdapter(%p %p %p)\n",
1015c2c66affSColin Finck            Context, DeviceDescription, NumberOfMapRegisters);
1016c2c66affSColin Finck     return (PDMA_ADAPTER)HalGetAdapter(DeviceDescription, NumberOfMapRegisters);
1017c2c66affSColin Finck }
1018c2c66affSColin Finck 
1019c2c66affSColin Finck static GET_SET_DEVICE_DATA InterfaceBusSetBusData;
1020c2c66affSColin Finck 
1021c2c66affSColin Finck static
1022c2c66affSColin Finck ULONG
1023c2c66affSColin Finck NTAPI
1024c2c66affSColin Finck InterfaceBusSetBusData(
1025c2c66affSColin Finck     IN PVOID Context,
1026c2c66affSColin Finck     IN ULONG DataType,
1027c2c66affSColin Finck     IN PVOID Buffer,
1028c2c66affSColin Finck     IN ULONG Offset,
1029c2c66affSColin Finck     IN ULONG Length)
1030c2c66affSColin Finck {
1031c2c66affSColin Finck     PPDO_DEVICE_EXTENSION DeviceExtension;
1032c2c66affSColin Finck     ULONG Size;
1033c2c66affSColin Finck 
1034c2c66affSColin Finck     DPRINT("InterfaceBusSetBusData(%p 0x%lx %p 0x%lx 0x%lx)\n",
1035c2c66affSColin Finck            Context, DataType, Buffer, Offset, Length);
1036c2c66affSColin Finck 
1037c2c66affSColin Finck     if (DataType != PCI_WHICHSPACE_CONFIG)
1038c2c66affSColin Finck     {
1039c2c66affSColin Finck         DPRINT("Unknown DataType %lu\n", DataType);
1040c2c66affSColin Finck         return 0;
1041c2c66affSColin Finck     }
1042c2c66affSColin Finck 
1043c2c66affSColin Finck     DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
1044c2c66affSColin Finck 
1045c2c66affSColin Finck     /* Get PCI configuration space */
1046c2c66affSColin Finck     Size = HalSetBusDataByOffset(PCIConfiguration,
1047c2c66affSColin Finck                                  DeviceExtension->PciDevice->BusNumber,
1048c2c66affSColin Finck                                  DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
1049c2c66affSColin Finck                                  Buffer,
1050c2c66affSColin Finck                                  Offset,
1051c2c66affSColin Finck                                  Length);
1052c2c66affSColin Finck     return Size;
1053c2c66affSColin Finck }
1054c2c66affSColin Finck 
1055c2c66affSColin Finck static GET_SET_DEVICE_DATA InterfaceBusGetBusData;
1056c2c66affSColin Finck 
1057c2c66affSColin Finck static
1058c2c66affSColin Finck ULONG
1059c2c66affSColin Finck NTAPI
1060c2c66affSColin Finck InterfaceBusGetBusData(
1061c2c66affSColin Finck     IN PVOID Context,
1062c2c66affSColin Finck     IN ULONG DataType,
1063c2c66affSColin Finck     IN PVOID Buffer,
1064c2c66affSColin Finck     IN ULONG Offset,
1065c2c66affSColin Finck     IN ULONG Length)
1066c2c66affSColin Finck {
1067c2c66affSColin Finck     PPDO_DEVICE_EXTENSION DeviceExtension;
1068c2c66affSColin Finck     ULONG Size;
1069c2c66affSColin Finck 
1070c2c66affSColin Finck     DPRINT("InterfaceBusGetBusData(%p 0x%lx %p 0x%lx 0x%lx) called\n",
1071c2c66affSColin Finck            Context, DataType, Buffer, Offset, Length);
1072c2c66affSColin Finck 
1073c2c66affSColin Finck     if (DataType != PCI_WHICHSPACE_CONFIG)
1074c2c66affSColin Finck     {
1075c2c66affSColin Finck         DPRINT("Unknown DataType %lu\n", DataType);
1076c2c66affSColin Finck         return 0;
1077c2c66affSColin Finck     }
1078c2c66affSColin Finck 
1079c2c66affSColin Finck     DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
1080c2c66affSColin Finck 
1081c2c66affSColin Finck     /* Get PCI configuration space */
1082c2c66affSColin Finck     Size = HalGetBusDataByOffset(PCIConfiguration,
1083c2c66affSColin Finck                                  DeviceExtension->PciDevice->BusNumber,
1084c2c66affSColin Finck                                  DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
1085c2c66affSColin Finck                                  Buffer,
1086c2c66affSColin Finck                                  Offset,
1087c2c66affSColin Finck                                  Length);
1088c2c66affSColin Finck     return Size;
1089c2c66affSColin Finck }
1090c2c66affSColin Finck 
1091c2c66affSColin Finck 
1092c2c66affSColin Finck static BOOLEAN NTAPI
1093c2c66affSColin Finck InterfacePciDevicePresent(
1094c2c66affSColin Finck     IN USHORT VendorID,
1095c2c66affSColin Finck     IN USHORT DeviceID,
1096c2c66affSColin Finck     IN UCHAR RevisionID,
1097c2c66affSColin Finck     IN USHORT SubVendorID,
1098c2c66affSColin Finck     IN USHORT SubSystemID,
1099c2c66affSColin Finck     IN ULONG Flags)
1100c2c66affSColin Finck {
1101c2c66affSColin Finck     PFDO_DEVICE_EXTENSION FdoDeviceExtension;
1102c2c66affSColin Finck     PPCI_DEVICE PciDevice;
1103c2c66affSColin Finck     PLIST_ENTRY CurrentBus, CurrentEntry;
1104c2c66affSColin Finck     KIRQL OldIrql;
1105c2c66affSColin Finck     BOOLEAN Found = FALSE;
1106c2c66affSColin Finck 
1107c2c66affSColin Finck     KeAcquireSpinLock(&DriverExtension->BusListLock, &OldIrql);
1108c2c66affSColin Finck     CurrentBus = DriverExtension->BusListHead.Flink;
1109c2c66affSColin Finck     while (!Found && CurrentBus != &DriverExtension->BusListHead)
1110c2c66affSColin Finck     {
1111c2c66affSColin Finck         FdoDeviceExtension = CONTAINING_RECORD(CurrentBus, FDO_DEVICE_EXTENSION, ListEntry);
1112c2c66affSColin Finck 
1113c2c66affSColin Finck         KeAcquireSpinLockAtDpcLevel(&FdoDeviceExtension->DeviceListLock);
1114c2c66affSColin Finck         CurrentEntry = FdoDeviceExtension->DeviceListHead.Flink;
1115c2c66affSColin Finck         while (!Found && CurrentEntry != &FdoDeviceExtension->DeviceListHead)
1116c2c66affSColin Finck         {
1117c2c66affSColin Finck             PciDevice = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
1118c2c66affSColin Finck             if (PciDevice->PciConfig.VendorID == VendorID &&
1119c2c66affSColin Finck                 PciDevice->PciConfig.DeviceID == DeviceID)
1120c2c66affSColin Finck             {
1121c2c66affSColin Finck                 if (!(Flags & PCI_USE_SUBSYSTEM_IDS) ||
1122c2c66affSColin Finck                     (PciDevice->PciConfig.u.type0.SubVendorID == SubVendorID &&
1123c2c66affSColin Finck                      PciDevice->PciConfig.u.type0.SubSystemID == SubSystemID))
1124c2c66affSColin Finck                 {
1125c2c66affSColin Finck                     if (!(Flags & PCI_USE_REVISION) ||
1126c2c66affSColin Finck                         PciDevice->PciConfig.RevisionID == RevisionID)
1127c2c66affSColin Finck                     {
1128c2c66affSColin Finck                         DPRINT("Found the PCI device\n");
1129c2c66affSColin Finck                         Found = TRUE;
1130c2c66affSColin Finck                     }
1131c2c66affSColin Finck                 }
1132c2c66affSColin Finck             }
1133c2c66affSColin Finck 
1134c2c66affSColin Finck             CurrentEntry = CurrentEntry->Flink;
1135c2c66affSColin Finck         }
1136c2c66affSColin Finck 
1137c2c66affSColin Finck         KeReleaseSpinLockFromDpcLevel(&FdoDeviceExtension->DeviceListLock);
1138c2c66affSColin Finck         CurrentBus = CurrentBus->Flink;
1139c2c66affSColin Finck     }
1140c2c66affSColin Finck     KeReleaseSpinLock(&DriverExtension->BusListLock, OldIrql);
1141c2c66affSColin Finck 
1142c2c66affSColin Finck     return Found;
1143c2c66affSColin Finck }
1144c2c66affSColin Finck 
1145c2c66affSColin Finck 
1146c2c66affSColin Finck static BOOLEAN
1147c2c66affSColin Finck CheckPciDevice(
1148c2c66affSColin Finck     IN PPCI_COMMON_CONFIG PciConfig,
1149c2c66affSColin Finck     IN PPCI_DEVICE_PRESENCE_PARAMETERS Parameters)
1150c2c66affSColin Finck {
1151c2c66affSColin Finck     if ((Parameters->Flags & PCI_USE_VENDEV_IDS) &&
1152c2c66affSColin Finck         (PciConfig->VendorID != Parameters->VendorID ||
1153c2c66affSColin Finck          PciConfig->DeviceID != Parameters->DeviceID))
1154c2c66affSColin Finck     {
1155c2c66affSColin Finck         return FALSE;
1156c2c66affSColin Finck     }
1157c2c66affSColin Finck 
1158c2c66affSColin Finck     if ((Parameters->Flags & PCI_USE_CLASS_SUBCLASS) &&
1159c2c66affSColin Finck         (PciConfig->BaseClass != Parameters->BaseClass ||
1160c2c66affSColin Finck          PciConfig->SubClass != Parameters->SubClass))
1161c2c66affSColin Finck     {
1162c2c66affSColin Finck         return FALSE;
1163c2c66affSColin Finck     }
1164c2c66affSColin Finck 
1165c2c66affSColin Finck     if ((Parameters->Flags & PCI_USE_PROGIF) &&
1166c2c66affSColin Finck          PciConfig->ProgIf != Parameters->ProgIf)
1167c2c66affSColin Finck     {
1168c2c66affSColin Finck         return FALSE;
1169c2c66affSColin Finck     }
1170c2c66affSColin Finck 
1171c2c66affSColin Finck     if ((Parameters->Flags & PCI_USE_SUBSYSTEM_IDS) &&
1172c2c66affSColin Finck         (PciConfig->u.type0.SubVendorID != Parameters->SubVendorID ||
1173c2c66affSColin Finck          PciConfig->u.type0.SubSystemID != Parameters->SubSystemID))
1174c2c66affSColin Finck     {
1175c2c66affSColin Finck         return FALSE;
1176c2c66affSColin Finck     }
1177c2c66affSColin Finck 
1178c2c66affSColin Finck     if ((Parameters->Flags & PCI_USE_REVISION) &&
1179c2c66affSColin Finck         PciConfig->RevisionID != Parameters->RevisionID)
1180c2c66affSColin Finck     {
1181c2c66affSColin Finck         return FALSE;
1182c2c66affSColin Finck     }
1183c2c66affSColin Finck 
1184c2c66affSColin Finck     return TRUE;
1185c2c66affSColin Finck }
1186c2c66affSColin Finck 
1187c2c66affSColin Finck 
1188c2c66affSColin Finck static BOOLEAN NTAPI
1189c2c66affSColin Finck InterfacePciDevicePresentEx(
1190c2c66affSColin Finck     IN PVOID Context,
1191c2c66affSColin Finck     IN PPCI_DEVICE_PRESENCE_PARAMETERS Parameters)
1192c2c66affSColin Finck {
1193c2c66affSColin Finck     PPDO_DEVICE_EXTENSION DeviceExtension;
1194c2c66affSColin Finck     PFDO_DEVICE_EXTENSION MyFdoDeviceExtension;
1195c2c66affSColin Finck     PFDO_DEVICE_EXTENSION FdoDeviceExtension;
1196c2c66affSColin Finck     PPCI_DEVICE PciDevice;
1197c2c66affSColin Finck     PLIST_ENTRY CurrentBus, CurrentEntry;
1198c2c66affSColin Finck     KIRQL OldIrql;
1199c2c66affSColin Finck     BOOLEAN Found = FALSE;
1200c2c66affSColin Finck 
1201c2c66affSColin Finck     DPRINT("InterfacePciDevicePresentEx(%p %p) called\n",
1202c2c66affSColin Finck            Context, Parameters);
1203c2c66affSColin Finck 
1204c2c66affSColin Finck     if (!Parameters || Parameters->Size != sizeof(PCI_DEVICE_PRESENCE_PARAMETERS))
1205c2c66affSColin Finck         return FALSE;
1206c2c66affSColin Finck 
1207c2c66affSColin Finck     DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
1208c2c66affSColin Finck     MyFdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->Fdo->DeviceExtension;
1209c2c66affSColin Finck 
1210c2c66affSColin Finck     if (Parameters->Flags & PCI_USE_LOCAL_DEVICE)
1211c2c66affSColin Finck     {
1212c2c66affSColin Finck         return CheckPciDevice(&DeviceExtension->PciDevice->PciConfig, Parameters);
1213c2c66affSColin Finck     }
1214c2c66affSColin Finck 
1215c2c66affSColin Finck     KeAcquireSpinLock(&DriverExtension->BusListLock, &OldIrql);
1216c2c66affSColin Finck     CurrentBus = DriverExtension->BusListHead.Flink;
1217c2c66affSColin Finck     while (!Found && CurrentBus != &DriverExtension->BusListHead)
1218c2c66affSColin Finck     {
1219c2c66affSColin Finck         FdoDeviceExtension = CONTAINING_RECORD(CurrentBus, FDO_DEVICE_EXTENSION, ListEntry);
1220c2c66affSColin Finck         if (!(Parameters->Flags & PCI_USE_LOCAL_BUS) || FdoDeviceExtension == MyFdoDeviceExtension)
1221c2c66affSColin Finck         {
1222c2c66affSColin Finck             KeAcquireSpinLockAtDpcLevel(&FdoDeviceExtension->DeviceListLock);
1223c2c66affSColin Finck             CurrentEntry = FdoDeviceExtension->DeviceListHead.Flink;
1224c2c66affSColin Finck             while (!Found && CurrentEntry != &FdoDeviceExtension->DeviceListHead)
1225c2c66affSColin Finck             {
1226c2c66affSColin Finck                 PciDevice = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
1227c2c66affSColin Finck 
1228c2c66affSColin Finck                 if (CheckPciDevice(&PciDevice->PciConfig, Parameters))
1229c2c66affSColin Finck                 {
1230c2c66affSColin Finck                     DPRINT("Found the PCI device\n");
1231c2c66affSColin Finck                     Found = TRUE;
1232c2c66affSColin Finck                 }
1233c2c66affSColin Finck 
1234c2c66affSColin Finck                 CurrentEntry = CurrentEntry->Flink;
1235c2c66affSColin Finck             }
1236c2c66affSColin Finck 
1237c2c66affSColin Finck             KeReleaseSpinLockFromDpcLevel(&FdoDeviceExtension->DeviceListLock);
1238c2c66affSColin Finck         }
1239c2c66affSColin Finck         CurrentBus = CurrentBus->Flink;
1240c2c66affSColin Finck     }
1241c2c66affSColin Finck     KeReleaseSpinLock(&DriverExtension->BusListLock, OldIrql);
1242c2c66affSColin Finck 
1243c2c66affSColin Finck     return Found;
1244c2c66affSColin Finck }
1245c2c66affSColin Finck 
1246c2c66affSColin Finck 
1247c2c66affSColin Finck static NTSTATUS
1248c2c66affSColin Finck PdoQueryInterface(
1249c2c66affSColin Finck     IN PDEVICE_OBJECT DeviceObject,
1250c2c66affSColin Finck     IN PIRP Irp,
1251c2c66affSColin Finck     PIO_STACK_LOCATION IrpSp)
1252c2c66affSColin Finck {
1253c2c66affSColin Finck     NTSTATUS Status;
1254c2c66affSColin Finck 
1255c2c66affSColin Finck     UNREFERENCED_PARAMETER(Irp);
1256c2c66affSColin Finck 
1257c2c66affSColin Finck     if (RtlCompareMemory(IrpSp->Parameters.QueryInterface.InterfaceType,
1258c2c66affSColin Finck                          &GUID_BUS_INTERFACE_STANDARD, sizeof(GUID)) == sizeof(GUID))
1259c2c66affSColin Finck     {
1260c2c66affSColin Finck         /* BUS_INTERFACE_STANDARD */
1261c2c66affSColin Finck         if (IrpSp->Parameters.QueryInterface.Version < 1)
1262c2c66affSColin Finck             Status = STATUS_NOT_SUPPORTED;
1263c2c66affSColin Finck         else if (IrpSp->Parameters.QueryInterface.Size < sizeof(BUS_INTERFACE_STANDARD))
1264c2c66affSColin Finck             Status = STATUS_BUFFER_TOO_SMALL;
1265c2c66affSColin Finck         else
1266c2c66affSColin Finck         {
1267c2c66affSColin Finck             PBUS_INTERFACE_STANDARD BusInterface;
1268c2c66affSColin Finck             BusInterface = (PBUS_INTERFACE_STANDARD)IrpSp->Parameters.QueryInterface.Interface;
1269c2c66affSColin Finck             BusInterface->Size = sizeof(BUS_INTERFACE_STANDARD);
1270c2c66affSColin Finck             BusInterface->Version = 1;
1271c2c66affSColin Finck             BusInterface->TranslateBusAddress = InterfaceBusTranslateBusAddress;
1272c2c66affSColin Finck             BusInterface->GetDmaAdapter = InterfaceBusGetDmaAdapter;
1273c2c66affSColin Finck             BusInterface->SetBusData = InterfaceBusSetBusData;
1274c2c66affSColin Finck             BusInterface->GetBusData = InterfaceBusGetBusData;
1275c2c66affSColin Finck             Status = STATUS_SUCCESS;
1276c2c66affSColin Finck         }
1277c2c66affSColin Finck     }
1278c2c66affSColin Finck     else if (RtlCompareMemory(IrpSp->Parameters.QueryInterface.InterfaceType,
1279c2c66affSColin Finck                               &GUID_PCI_DEVICE_PRESENT_INTERFACE, sizeof(GUID)) == sizeof(GUID))
1280c2c66affSColin Finck     {
1281c2c66affSColin Finck         /* PCI_DEVICE_PRESENT_INTERFACE */
1282c2c66affSColin Finck         if (IrpSp->Parameters.QueryInterface.Version < 1)
1283c2c66affSColin Finck             Status = STATUS_NOT_SUPPORTED;
1284c2c66affSColin Finck         else if (IrpSp->Parameters.QueryInterface.Size < sizeof(PCI_DEVICE_PRESENT_INTERFACE))
1285c2c66affSColin Finck             Status = STATUS_BUFFER_TOO_SMALL;
1286c2c66affSColin Finck         else
1287c2c66affSColin Finck         {
1288c2c66affSColin Finck             PPCI_DEVICE_PRESENT_INTERFACE PciDevicePresentInterface;
1289c2c66affSColin Finck             PciDevicePresentInterface = (PPCI_DEVICE_PRESENT_INTERFACE)IrpSp->Parameters.QueryInterface.Interface;
1290c2c66affSColin Finck             PciDevicePresentInterface->Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
1291c2c66affSColin Finck             PciDevicePresentInterface->Version = 1;
1292c2c66affSColin Finck             PciDevicePresentInterface->IsDevicePresent = InterfacePciDevicePresent;
1293c2c66affSColin Finck             PciDevicePresentInterface->IsDevicePresentEx = InterfacePciDevicePresentEx;
1294c2c66affSColin Finck             Status = STATUS_SUCCESS;
1295c2c66affSColin Finck         }
1296c2c66affSColin Finck     }
1297c2c66affSColin Finck     else
1298c2c66affSColin Finck     {
1299c2c66affSColin Finck         /* Not a supported interface */
1300c2c66affSColin Finck         return STATUS_NOT_SUPPORTED;
1301c2c66affSColin Finck     }
1302c2c66affSColin Finck 
1303c2c66affSColin Finck     if (NT_SUCCESS(Status))
1304c2c66affSColin Finck     {
1305c2c66affSColin Finck         /* Add a reference for the returned interface */
1306c2c66affSColin Finck         PINTERFACE Interface;
1307c2c66affSColin Finck         Interface = (PINTERFACE)IrpSp->Parameters.QueryInterface.Interface;
1308c2c66affSColin Finck         Interface->Context = DeviceObject;
1309c2c66affSColin Finck         Interface->InterfaceReference = InterfaceReference;
1310c2c66affSColin Finck         Interface->InterfaceDereference = InterfaceDereference;
1311c2c66affSColin Finck         Interface->InterfaceReference(Interface->Context);
1312c2c66affSColin Finck     }
1313c2c66affSColin Finck 
1314c2c66affSColin Finck     return Status;
1315c2c66affSColin Finck }
1316c2c66affSColin Finck 
1317c2c66affSColin Finck static NTSTATUS
1318c2c66affSColin Finck PdoStartDevice(
1319c2c66affSColin Finck     IN PDEVICE_OBJECT DeviceObject,
1320c2c66affSColin Finck     IN PIRP Irp,
1321c2c66affSColin Finck     PIO_STACK_LOCATION IrpSp)
1322c2c66affSColin Finck {
1323c2c66affSColin Finck     PCM_RESOURCE_LIST RawResList = IrpSp->Parameters.StartDevice.AllocatedResources;
1324c2c66affSColin Finck     PCM_FULL_RESOURCE_DESCRIPTOR RawFullDesc;
1325c2c66affSColin Finck     PCM_PARTIAL_RESOURCE_DESCRIPTOR RawPartialDesc;
1326c2c66affSColin Finck     ULONG i, ii;
1327c2c66affSColin Finck     PPDO_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
1328c2c66affSColin Finck     UCHAR Irq;
1329c2c66affSColin Finck     USHORT Command;
1330c2c66affSColin Finck 
1331c2c66affSColin Finck     UNREFERENCED_PARAMETER(Irp);
1332c2c66affSColin Finck 
1333c2c66affSColin Finck     if (!RawResList)
1334c2c66affSColin Finck         return STATUS_SUCCESS;
1335c2c66affSColin Finck 
1336c2c66affSColin Finck     /* TODO: Assign the other resources we get to the card */
1337c2c66affSColin Finck 
1338b82bf8ceSTimo Kreuzer     RawFullDesc = &RawResList->List[0];
1339b82bf8ceSTimo Kreuzer     for (i = 0; i < RawResList->Count; i++, RawFullDesc = CmiGetNextResourceDescriptor(RawFullDesc))
1340c2c66affSColin Finck     {
1341c2c66affSColin Finck         for (ii = 0; ii < RawFullDesc->PartialResourceList.Count; ii++)
1342c2c66affSColin Finck         {
1343b82bf8ceSTimo Kreuzer             /* Partial resource descriptors can be of variable size (CmResourceTypeDeviceSpecific),
1344b82bf8ceSTimo Kreuzer                but only one is allowed and it must be the last one in the list! */
1345c2c66affSColin Finck             RawPartialDesc = &RawFullDesc->PartialResourceList.PartialDescriptors[ii];
1346c2c66affSColin Finck 
1347c2c66affSColin Finck             if (RawPartialDesc->Type == CmResourceTypeInterrupt)
1348c2c66affSColin Finck             {
1349c2c66affSColin Finck                 DPRINT("Assigning IRQ %u to PCI device 0x%x on bus 0x%x\n",
1350c2c66affSColin Finck                         RawPartialDesc->u.Interrupt.Vector,
1351c2c66affSColin Finck                         DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
1352c2c66affSColin Finck                         DeviceExtension->PciDevice->BusNumber);
1353c2c66affSColin Finck 
1354c2c66affSColin Finck                 Irq = (UCHAR)RawPartialDesc->u.Interrupt.Vector;
1355c2c66affSColin Finck                 HalSetBusDataByOffset(PCIConfiguration,
1356c2c66affSColin Finck                                       DeviceExtension->PciDevice->BusNumber,
1357c2c66affSColin Finck                                       DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
1358c2c66affSColin Finck                                       &Irq,
1359c2c66affSColin Finck                                       0x3c /* PCI_INTERRUPT_LINE */,
1360c2c66affSColin Finck                                       sizeof(UCHAR));
1361c2c66affSColin Finck             }
1362c2c66affSColin Finck         }
1363c2c66affSColin Finck     }
1364c2c66affSColin Finck 
1365c2c66affSColin Finck     Command = 0;
1366c2c66affSColin Finck 
1367c2c66affSColin Finck     DBGPRINT("pci!PdoStartDevice: Enabling command flags for PCI device 0x%x on bus 0x%x: ",
1368c2c66affSColin Finck             DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
1369c2c66affSColin Finck             DeviceExtension->PciDevice->BusNumber);
1370c2c66affSColin Finck     if (DeviceExtension->PciDevice->EnableBusMaster)
1371c2c66affSColin Finck     {
1372c2c66affSColin Finck         Command |= PCI_ENABLE_BUS_MASTER;
1373c2c66affSColin Finck         DBGPRINT("[Bus master] ");
1374c2c66affSColin Finck     }
1375c2c66affSColin Finck 
1376c2c66affSColin Finck     if (DeviceExtension->PciDevice->EnableMemorySpace)
1377c2c66affSColin Finck     {
1378c2c66affSColin Finck         Command |= PCI_ENABLE_MEMORY_SPACE;
1379c2c66affSColin Finck         DBGPRINT("[Memory space enable] ");
1380c2c66affSColin Finck     }
1381c2c66affSColin Finck 
1382c2c66affSColin Finck     if (DeviceExtension->PciDevice->EnableIoSpace)
1383c2c66affSColin Finck     {
1384c2c66affSColin Finck         Command |= PCI_ENABLE_IO_SPACE;
1385c2c66affSColin Finck         DBGPRINT("[I/O space enable] ");
1386c2c66affSColin Finck     }
1387c2c66affSColin Finck 
1388c2c66affSColin Finck     if (Command != 0)
1389c2c66affSColin Finck     {
1390c2c66affSColin Finck         DBGPRINT("\n");
1391c2c66affSColin Finck 
1392c2c66affSColin Finck         /* OR with the previous value */
1393c2c66affSColin Finck         Command |= DeviceExtension->PciDevice->PciConfig.Command;
1394c2c66affSColin Finck 
1395c2c66affSColin Finck         HalSetBusDataByOffset(PCIConfiguration,
1396c2c66affSColin Finck                               DeviceExtension->PciDevice->BusNumber,
1397c2c66affSColin Finck                               DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
1398c2c66affSColin Finck                               &Command,
1399c2c66affSColin Finck                               FIELD_OFFSET(PCI_COMMON_CONFIG, Command),
1400c2c66affSColin Finck                               sizeof(USHORT));
1401c2c66affSColin Finck     }
1402c2c66affSColin Finck     else
1403c2c66affSColin Finck     {
1404c2c66affSColin Finck         DBGPRINT("None\n");
1405c2c66affSColin Finck     }
1406c2c66affSColin Finck 
1407c2c66affSColin Finck     return STATUS_SUCCESS;
1408c2c66affSColin Finck }
1409c2c66affSColin Finck 
1410c2c66affSColin Finck static NTSTATUS
1411c2c66affSColin Finck PdoReadConfig(
1412c2c66affSColin Finck     IN PDEVICE_OBJECT DeviceObject,
1413c2c66affSColin Finck     IN PIRP Irp,
1414c2c66affSColin Finck     PIO_STACK_LOCATION IrpSp)
1415c2c66affSColin Finck {
1416c2c66affSColin Finck     ULONG Size;
1417c2c66affSColin Finck 
1418c2c66affSColin Finck     DPRINT("PdoReadConfig() called\n");
1419c2c66affSColin Finck 
1420c2c66affSColin Finck     Size = InterfaceBusGetBusData(DeviceObject,
1421c2c66affSColin Finck                                   IrpSp->Parameters.ReadWriteConfig.WhichSpace,
1422c2c66affSColin Finck                                   IrpSp->Parameters.ReadWriteConfig.Buffer,
1423c2c66affSColin Finck                                   IrpSp->Parameters.ReadWriteConfig.Offset,
1424c2c66affSColin Finck                                   IrpSp->Parameters.ReadWriteConfig.Length);
1425c2c66affSColin Finck 
1426c2c66affSColin Finck     if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
1427c2c66affSColin Finck     {
1428c2c66affSColin Finck         DPRINT1("Size %lu  Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
1429c2c66affSColin Finck         Irp->IoStatus.Information = 0;
1430c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
1431c2c66affSColin Finck     }
1432c2c66affSColin Finck 
1433c2c66affSColin Finck     Irp->IoStatus.Information = Size;
1434c2c66affSColin Finck 
1435c2c66affSColin Finck     return STATUS_SUCCESS;
1436c2c66affSColin Finck }
1437c2c66affSColin Finck 
1438c2c66affSColin Finck 
1439c2c66affSColin Finck static NTSTATUS
1440c2c66affSColin Finck PdoWriteConfig(
1441c2c66affSColin Finck     IN PDEVICE_OBJECT DeviceObject,
1442c2c66affSColin Finck     IN PIRP Irp,
1443c2c66affSColin Finck     PIO_STACK_LOCATION IrpSp)
1444c2c66affSColin Finck {
1445c2c66affSColin Finck     ULONG Size;
1446c2c66affSColin Finck 
1447c2c66affSColin Finck     DPRINT1("PdoWriteConfig() called\n");
1448c2c66affSColin Finck 
1449c2c66affSColin Finck     /* Get PCI configuration space */
1450c2c66affSColin Finck     Size = InterfaceBusSetBusData(DeviceObject,
1451c2c66affSColin Finck                                   IrpSp->Parameters.ReadWriteConfig.WhichSpace,
1452c2c66affSColin Finck                                   IrpSp->Parameters.ReadWriteConfig.Buffer,
1453c2c66affSColin Finck                                   IrpSp->Parameters.ReadWriteConfig.Offset,
1454c2c66affSColin Finck                                   IrpSp->Parameters.ReadWriteConfig.Length);
1455c2c66affSColin Finck 
1456c2c66affSColin Finck     if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
1457c2c66affSColin Finck     {
1458c2c66affSColin Finck         DPRINT1("Size %lu  Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
1459c2c66affSColin Finck         Irp->IoStatus.Information = 0;
1460c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
1461c2c66affSColin Finck     }
1462c2c66affSColin Finck 
1463c2c66affSColin Finck     Irp->IoStatus.Information = Size;
1464c2c66affSColin Finck 
1465c2c66affSColin Finck     return STATUS_SUCCESS;
1466c2c66affSColin Finck }
1467c2c66affSColin Finck 
1468c2c66affSColin Finck static NTSTATUS
1469c2c66affSColin Finck PdoQueryDeviceRelations(
1470c2c66affSColin Finck     IN PDEVICE_OBJECT DeviceObject,
1471c2c66affSColin Finck     IN PIRP Irp,
1472c2c66affSColin Finck     PIO_STACK_LOCATION IrpSp)
1473c2c66affSColin Finck {
1474c2c66affSColin Finck     PDEVICE_RELATIONS DeviceRelations;
1475c2c66affSColin Finck 
1476c2c66affSColin Finck     /* We only support TargetDeviceRelation for child PDOs */
1477c2c66affSColin Finck     if (IrpSp->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
1478c2c66affSColin Finck         return Irp->IoStatus.Status;
1479c2c66affSColin Finck 
1480c2c66affSColin Finck     /* We can do this because we only return 1 PDO for TargetDeviceRelation */
1481c2c66affSColin Finck     DeviceRelations = ExAllocatePoolWithTag(PagedPool, sizeof(*DeviceRelations), TAG_PCI);
1482c2c66affSColin Finck     if (!DeviceRelations)
1483c2c66affSColin Finck         return STATUS_INSUFFICIENT_RESOURCES;
1484c2c66affSColin Finck 
1485c2c66affSColin Finck     DeviceRelations->Count = 1;
1486c2c66affSColin Finck     DeviceRelations->Objects[0] = DeviceObject;
1487c2c66affSColin Finck 
1488c2c66affSColin Finck     /* The PnP manager will remove this when it is done with the PDO */
1489c2c66affSColin Finck     ObReferenceObject(DeviceObject);
1490c2c66affSColin Finck 
1491c2c66affSColin Finck     Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
1492c2c66affSColin Finck 
1493c2c66affSColin Finck     return STATUS_SUCCESS;
1494c2c66affSColin Finck }
1495c2c66affSColin Finck 
1496c2c66affSColin Finck 
1497c2c66affSColin Finck /*** PUBLIC ******************************************************************/
1498c2c66affSColin Finck 
1499c2c66affSColin Finck NTSTATUS
1500c2c66affSColin Finck PdoPnpControl(
1501c2c66affSColin Finck     PDEVICE_OBJECT DeviceObject,
1502c2c66affSColin Finck     PIRP Irp)
1503c2c66affSColin Finck /*
1504c2c66affSColin Finck  * FUNCTION: Handle Plug and Play IRPs for the child device
1505c2c66affSColin Finck  * ARGUMENTS:
1506c2c66affSColin Finck  *     DeviceObject = Pointer to physical device object of the child device
1507c2c66affSColin Finck  *     Irp          = Pointer to IRP that should be handled
1508c2c66affSColin Finck  * RETURNS:
1509c2c66affSColin Finck  *     Status
1510c2c66affSColin Finck  */
1511c2c66affSColin Finck {
1512c2c66affSColin Finck     PIO_STACK_LOCATION IrpSp;
1513c2c66affSColin Finck     NTSTATUS Status;
1514c2c66affSColin Finck 
1515c2c66affSColin Finck     DPRINT("Called\n");
1516c2c66affSColin Finck 
1517c2c66affSColin Finck     Status = Irp->IoStatus.Status;
1518c2c66affSColin Finck 
1519c2c66affSColin Finck     IrpSp = IoGetCurrentIrpStackLocation(Irp);
1520c2c66affSColin Finck 
1521c2c66affSColin Finck     switch (IrpSp->MinorFunction)
1522c2c66affSColin Finck     {
1523c2c66affSColin Finck         case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1524c2c66affSColin Finck             DPRINT("Unimplemented IRP_MN_DEVICE_USAGE_NOTIFICATION received\n");
1525c2c66affSColin Finck             break;
1526c2c66affSColin Finck 
1527c2c66affSColin Finck         case IRP_MN_EJECT:
1528c2c66affSColin Finck             DPRINT("Unimplemented IRP_MN_EJECT received\n");
1529c2c66affSColin Finck             break;
1530c2c66affSColin Finck 
1531c2c66affSColin Finck         case IRP_MN_QUERY_BUS_INFORMATION:
1532c2c66affSColin Finck             Status = PdoQueryBusInformation(DeviceObject, Irp, IrpSp);
1533c2c66affSColin Finck             break;
1534c2c66affSColin Finck 
1535c2c66affSColin Finck         case IRP_MN_QUERY_CAPABILITIES:
1536c2c66affSColin Finck             Status = PdoQueryCapabilities(DeviceObject, Irp, IrpSp);
1537c2c66affSColin Finck             break;
1538c2c66affSColin Finck 
1539c2c66affSColin Finck         case IRP_MN_QUERY_DEVICE_RELATIONS:
1540c2c66affSColin Finck             Status = PdoQueryDeviceRelations(DeviceObject, Irp, IrpSp);
1541c2c66affSColin Finck             break;
1542c2c66affSColin Finck 
1543c2c66affSColin Finck         case IRP_MN_QUERY_DEVICE_TEXT:
1544c2c66affSColin Finck             DPRINT("IRP_MN_QUERY_DEVICE_TEXT received\n");
1545c2c66affSColin Finck             Status = PdoQueryDeviceText(DeviceObject, Irp, IrpSp);
1546c2c66affSColin Finck             break;
1547c2c66affSColin Finck 
1548c2c66affSColin Finck         case IRP_MN_QUERY_ID:
1549c2c66affSColin Finck             DPRINT("IRP_MN_QUERY_ID received\n");
1550c2c66affSColin Finck             Status = PdoQueryId(DeviceObject, Irp, IrpSp);
1551c2c66affSColin Finck             break;
1552c2c66affSColin Finck 
1553c2c66affSColin Finck         case IRP_MN_QUERY_PNP_DEVICE_STATE:
1554c2c66affSColin Finck             DPRINT("Unimplemented IRP_MN_QUERY_ID received\n");
1555c2c66affSColin Finck             break;
1556c2c66affSColin Finck 
1557c2c66affSColin Finck         case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
1558c2c66affSColin Finck             DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS received\n");
1559c2c66affSColin Finck             Status = PdoQueryResourceRequirements(DeviceObject, Irp, IrpSp);
1560c2c66affSColin Finck             break;
1561c2c66affSColin Finck 
1562c2c66affSColin Finck         case IRP_MN_QUERY_RESOURCES:
1563c2c66affSColin Finck             DPRINT("IRP_MN_QUERY_RESOURCES received\n");
1564c2c66affSColin Finck             Status = PdoQueryResources(DeviceObject, Irp, IrpSp);
1565c2c66affSColin Finck             break;
1566c2c66affSColin Finck 
1567c2c66affSColin Finck         case IRP_MN_SET_LOCK:
1568c2c66affSColin Finck             DPRINT("Unimplemented IRP_MN_SET_LOCK received\n");
1569c2c66affSColin Finck             break;
1570c2c66affSColin Finck 
1571c2c66affSColin Finck         case IRP_MN_START_DEVICE:
1572c2c66affSColin Finck             Status = PdoStartDevice(DeviceObject, Irp, IrpSp);
1573c2c66affSColin Finck             break;
1574c2c66affSColin Finck 
1575c2c66affSColin Finck         case IRP_MN_QUERY_STOP_DEVICE:
1576c2c66affSColin Finck         case IRP_MN_CANCEL_STOP_DEVICE:
1577c2c66affSColin Finck         case IRP_MN_STOP_DEVICE:
1578c2c66affSColin Finck         case IRP_MN_QUERY_REMOVE_DEVICE:
1579c2c66affSColin Finck         case IRP_MN_CANCEL_REMOVE_DEVICE:
1580*2b9941e7SHervé Poussineau         case IRP_MN_REMOVE_DEVICE:
1581c2c66affSColin Finck         case IRP_MN_SURPRISE_REMOVAL:
1582c2c66affSColin Finck             Status = STATUS_SUCCESS;
1583c2c66affSColin Finck             break;
1584c2c66affSColin Finck 
1585c2c66affSColin Finck         case IRP_MN_QUERY_INTERFACE:
1586c2c66affSColin Finck             DPRINT("IRP_MN_QUERY_INTERFACE received\n");
1587c2c66affSColin Finck             Status = PdoQueryInterface(DeviceObject, Irp, IrpSp);
1588c2c66affSColin Finck             break;
1589c2c66affSColin Finck 
1590c2c66affSColin Finck         case IRP_MN_READ_CONFIG:
1591c2c66affSColin Finck             DPRINT("IRP_MN_READ_CONFIG received\n");
1592c2c66affSColin Finck             Status = PdoReadConfig(DeviceObject, Irp, IrpSp);
1593c2c66affSColin Finck             break;
1594c2c66affSColin Finck 
1595c2c66affSColin Finck         case IRP_MN_WRITE_CONFIG:
1596c2c66affSColin Finck             DPRINT("IRP_MN_WRITE_CONFIG received\n");
1597c2c66affSColin Finck             Status = PdoWriteConfig(DeviceObject, Irp, IrpSp);
1598c2c66affSColin Finck             break;
1599c2c66affSColin Finck 
1600c2c66affSColin Finck         case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
1601c2c66affSColin Finck             DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS received\n");
1602c2c66affSColin Finck             /* Nothing to do */
1603c2c66affSColin Finck             Irp->IoStatus.Status = Status;
1604c2c66affSColin Finck             break;
1605c2c66affSColin Finck 
1606c2c66affSColin Finck         default:
1607c2c66affSColin Finck             DPRINT1("Unknown IOCTL 0x%lx\n", IrpSp->MinorFunction);
1608c2c66affSColin Finck             break;
1609c2c66affSColin Finck     }
1610c2c66affSColin Finck 
1611c2c66affSColin Finck     if (Status != STATUS_PENDING)
1612c2c66affSColin Finck     {
1613c2c66affSColin Finck         Irp->IoStatus.Status = Status;
1614c2c66affSColin Finck         IoCompleteRequest(Irp, IO_NO_INCREMENT);
1615c2c66affSColin Finck     }
1616c2c66affSColin Finck 
1617c2c66affSColin Finck     DPRINT("Leaving. Status 0x%X\n", Status);
1618c2c66affSColin Finck 
1619c2c66affSColin Finck     return Status;
1620c2c66affSColin Finck }
1621c2c66affSColin Finck 
1622c2c66affSColin Finck NTSTATUS
1623c2c66affSColin Finck PdoPowerControl(
1624c2c66affSColin Finck     PDEVICE_OBJECT DeviceObject,
1625c2c66affSColin Finck     PIRP Irp)
1626c2c66affSColin Finck /*
1627c2c66affSColin Finck  * FUNCTION: Handle power management IRPs for the child device
1628c2c66affSColin Finck  * ARGUMENTS:
1629c2c66affSColin Finck  *     DeviceObject = Pointer to physical device object of the child device
1630c2c66affSColin Finck  *     Irp          = Pointer to IRP that should be handled
1631c2c66affSColin Finck  * RETURNS:
1632c2c66affSColin Finck  *     Status
1633c2c66affSColin Finck  */
1634c2c66affSColin Finck {
1635c2c66affSColin Finck     PIO_STACK_LOCATION IrpSp;
1636c2c66affSColin Finck     NTSTATUS Status = Irp->IoStatus.Status;
1637c2c66affSColin Finck 
1638c2c66affSColin Finck     DPRINT("Called\n");
1639c2c66affSColin Finck 
1640c2c66affSColin Finck     IrpSp = IoGetCurrentIrpStackLocation(Irp);
1641c2c66affSColin Finck 
1642c2c66affSColin Finck     switch (IrpSp->MinorFunction)
1643c2c66affSColin Finck     {
1644c2c66affSColin Finck         case IRP_MN_QUERY_POWER:
1645c2c66affSColin Finck         case IRP_MN_SET_POWER:
1646c2c66affSColin Finck             Status = STATUS_SUCCESS;
1647c2c66affSColin Finck             break;
1648c2c66affSColin Finck     }
1649c2c66affSColin Finck 
1650c2c66affSColin Finck     PoStartNextPowerIrp(Irp);
1651c2c66affSColin Finck     Irp->IoStatus.Status = Status;
1652c2c66affSColin Finck     IoCompleteRequest(Irp, IO_NO_INCREMENT);
1653c2c66affSColin Finck 
1654c2c66affSColin Finck     DPRINT("Leaving. Status 0x%X\n", Status);
1655c2c66affSColin Finck 
1656c2c66affSColin Finck     return Status;
1657c2c66affSColin Finck }
1658c2c66affSColin Finck 
1659c2c66affSColin Finck /* EOF */
1660