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