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