xref: /reactos/hal/halx86/legacy/bus/pcibus.c (revision 734cd5e8)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * PROJECT:         ReactOS HAL
3c2c66affSColin Finck  * LICENSE:         GPL - See COPYING in the top level directory
4c2c66affSColin Finck  * FILE:            hal/halx86/legacy/bus/pcibus.c
5c2c66affSColin Finck  * PURPOSE:         PCI Bus Support (Configuration Space, Resource Allocation)
6c2c66affSColin Finck  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
7c2c66affSColin Finck  */
8c2c66affSColin Finck 
9c2c66affSColin Finck /* INCLUDES ******************************************************************/
10c2c66affSColin Finck 
11c2c66affSColin Finck #include <hal.h>
12c2c66affSColin Finck #define NDEBUG
13c2c66affSColin Finck #include <debug.h>
14c2c66affSColin Finck 
15c2c66affSColin Finck /* GLOBALS *******************************************************************/
16c2c66affSColin Finck 
17c2c66affSColin Finck extern BOOLEAN HalpPciLockSettings;
18c2c66affSColin Finck ULONG HalpBusType;
19c2c66affSColin Finck 
20c2c66affSColin Finck BOOLEAN HalpPCIConfigInitialized;
21c2c66affSColin Finck ULONG HalpMinPciBus, HalpMaxPciBus;
22c2c66affSColin Finck KSPIN_LOCK HalpPCIConfigLock;
23c2c66affSColin Finck PCI_CONFIG_HANDLER PCIConfigHandler;
24c2c66affSColin Finck 
25c2c66affSColin Finck /* PCI Operation Matrix */
26c2c66affSColin Finck UCHAR PCIDeref[4][4] =
27c2c66affSColin Finck {
28c2c66affSColin Finck     {0, 1, 2, 2},   // ULONG-aligned offset
29c2c66affSColin Finck     {1, 1, 1, 1},   // UCHAR-aligned offset
30c2c66affSColin Finck     {2, 1, 2, 2},   // USHORT-aligned offset
31c2c66affSColin Finck     {1, 1, 1, 1}    // UCHAR-aligned offset
32c2c66affSColin Finck };
33c2c66affSColin Finck 
34c2c66affSColin Finck /* Type 1 PCI Bus */
35c2c66affSColin Finck PCI_CONFIG_HANDLER PCIConfigHandlerType1 =
36c2c66affSColin Finck {
37c2c66affSColin Finck     /* Synchronization */
38c2c66affSColin Finck     (FncSync)HalpPCISynchronizeType1,
39c2c66affSColin Finck     (FncReleaseSync)HalpPCIReleaseSynchronzationType1,
40c2c66affSColin Finck 
41c2c66affSColin Finck     /* Read */
42c2c66affSColin Finck     {
43c2c66affSColin Finck         (FncConfigIO)HalpPCIReadUlongType1,
44c2c66affSColin Finck         (FncConfigIO)HalpPCIReadUcharType1,
45c2c66affSColin Finck         (FncConfigIO)HalpPCIReadUshortType1
46c2c66affSColin Finck     },
47c2c66affSColin Finck 
48c2c66affSColin Finck     /* Write */
49c2c66affSColin Finck     {
50c2c66affSColin Finck         (FncConfigIO)HalpPCIWriteUlongType1,
51c2c66affSColin Finck         (FncConfigIO)HalpPCIWriteUcharType1,
52c2c66affSColin Finck         (FncConfigIO)HalpPCIWriteUshortType1
53c2c66affSColin Finck     }
54c2c66affSColin Finck };
55c2c66affSColin Finck 
56c2c66affSColin Finck /* Type 2 PCI Bus */
57c2c66affSColin Finck PCI_CONFIG_HANDLER PCIConfigHandlerType2 =
58c2c66affSColin Finck {
59c2c66affSColin Finck     /* Synchronization */
60c2c66affSColin Finck     (FncSync)HalpPCISynchronizeType2,
61c2c66affSColin Finck     (FncReleaseSync)HalpPCIReleaseSynchronizationType2,
62c2c66affSColin Finck 
63c2c66affSColin Finck     /* Read */
64c2c66affSColin Finck     {
65c2c66affSColin Finck         (FncConfigIO)HalpPCIReadUlongType2,
66c2c66affSColin Finck         (FncConfigIO)HalpPCIReadUcharType2,
67c2c66affSColin Finck         (FncConfigIO)HalpPCIReadUshortType2
68c2c66affSColin Finck     },
69c2c66affSColin Finck 
70c2c66affSColin Finck     /* Write */
71c2c66affSColin Finck     {
72c2c66affSColin Finck         (FncConfigIO)HalpPCIWriteUlongType2,
73c2c66affSColin Finck         (FncConfigIO)HalpPCIWriteUcharType2,
74c2c66affSColin Finck         (FncConfigIO)HalpPCIWriteUshortType2
75c2c66affSColin Finck     }
76c2c66affSColin Finck };
77c2c66affSColin Finck 
78c2c66affSColin Finck PCIPBUSDATA HalpFakePciBusData =
79c2c66affSColin Finck {
80c2c66affSColin Finck     {
81c2c66affSColin Finck         PCI_DATA_TAG,
82c2c66affSColin Finck         PCI_DATA_VERSION,
83c2c66affSColin Finck         HalpReadPCIConfig,
84c2c66affSColin Finck         HalpWritePCIConfig,
85c2c66affSColin Finck         NULL,
86c2c66affSColin Finck         NULL,
87c2c66affSColin Finck         {{{0, 0, 0}}},
88c2c66affSColin Finck         {0, 0, 0, 0}
89c2c66affSColin Finck     },
90c2c66affSColin Finck     {{0, 0}},
91c2c66affSColin Finck     32,
92c2c66affSColin Finck };
93c2c66affSColin Finck 
94c2c66affSColin Finck BUS_HANDLER HalpFakePciBusHandler =
95c2c66affSColin Finck {
96c2c66affSColin Finck     1,
97c2c66affSColin Finck     PCIBus,
98c2c66affSColin Finck     PCIConfiguration,
99c2c66affSColin Finck     0,
100c2c66affSColin Finck     NULL,
101c2c66affSColin Finck     NULL,
102c2c66affSColin Finck     &HalpFakePciBusData,
103c2c66affSColin Finck     0,
104c2c66affSColin Finck     NULL,
105c2c66affSColin Finck     {0, 0, 0, 0},
106c2c66affSColin Finck     (PGETSETBUSDATA)HalpGetPCIData,
107c2c66affSColin Finck     (PGETSETBUSDATA)HalpSetPCIData,
108c2c66affSColin Finck     NULL,
109c2c66affSColin Finck     HalpAssignPCISlotResources,
110c2c66affSColin Finck     NULL,
111c2c66affSColin Finck     NULL
112c2c66affSColin Finck };
113c2c66affSColin Finck 
114c2c66affSColin Finck /* TYPE 1 FUNCTIONS **********************************************************/
115c2c66affSColin Finck 
116c2c66affSColin Finck VOID
117c2c66affSColin Finck NTAPI
HalpPCISynchronizeType1(IN PBUS_HANDLER BusHandler,IN PCI_SLOT_NUMBER Slot,OUT PKIRQL OldIrql,OUT PPCI_TYPE1_CFG_BITS PciCfg1)118c2c66affSColin Finck HalpPCISynchronizeType1(IN PBUS_HANDLER BusHandler,
119c2c66affSColin Finck                         IN PCI_SLOT_NUMBER Slot,
120a0fb02f7STimo Kreuzer                         OUT PKIRQL OldIrql,
121a0fb02f7STimo Kreuzer                         OUT PPCI_TYPE1_CFG_BITS PciCfg1)
122c2c66affSColin Finck {
123c2c66affSColin Finck     /* Setup the PCI Configuration Register */
124c2c66affSColin Finck     PciCfg1->u.AsULONG = 0;
125c2c66affSColin Finck     PciCfg1->u.bits.BusNumber = BusHandler->BusNumber;
126c2c66affSColin Finck     PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber;
127c2c66affSColin Finck     PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber;
128c2c66affSColin Finck     PciCfg1->u.bits.Enable = TRUE;
129c2c66affSColin Finck 
130c2c66affSColin Finck     /* Acquire the lock */
131a0fb02f7STimo Kreuzer     KeRaiseIrql(HIGH_LEVEL, OldIrql);
132a0fb02f7STimo Kreuzer     KeAcquireSpinLockAtDpcLevel(&HalpPCIConfigLock);
133c2c66affSColin Finck }
134c2c66affSColin Finck 
135c2c66affSColin Finck VOID
136c2c66affSColin Finck NTAPI
HalpPCIReleaseSynchronzationType1(IN PBUS_HANDLER BusHandler,IN KIRQL OldIrql)137c2c66affSColin Finck HalpPCIReleaseSynchronzationType1(IN PBUS_HANDLER BusHandler,
138a0fb02f7STimo Kreuzer                                   IN KIRQL OldIrql)
139c2c66affSColin Finck {
140c2c66affSColin Finck     PCI_TYPE1_CFG_BITS PciCfg1;
141c2c66affSColin Finck 
142c2c66affSColin Finck     /* Clear the PCI Configuration Register */
143c2c66affSColin Finck     PciCfg1.u.AsULONG = 0;
144c2c66affSColin Finck     WRITE_PORT_ULONG(((PPCIPBUSDATA)BusHandler->BusData)->Config.Type1.Address,
145c2c66affSColin Finck                      PciCfg1.u.AsULONG);
146c2c66affSColin Finck 
147c2c66affSColin Finck     /* Release the lock */
148a0fb02f7STimo Kreuzer     KeReleaseSpinLock(&HalpPCIConfigLock, OldIrql);
149c2c66affSColin Finck }
150c2c66affSColin Finck 
TYPE1_READ(HalpPCIReadUcharType1,UCHAR)151c2c66affSColin Finck TYPE1_READ(HalpPCIReadUcharType1, UCHAR)
152c2c66affSColin Finck TYPE1_READ(HalpPCIReadUshortType1, USHORT)
153c2c66affSColin Finck TYPE1_READ(HalpPCIReadUlongType1, ULONG)
154c2c66affSColin Finck TYPE1_WRITE(HalpPCIWriteUcharType1, UCHAR)
155c2c66affSColin Finck TYPE1_WRITE(HalpPCIWriteUshortType1, USHORT)
156c2c66affSColin Finck TYPE1_WRITE(HalpPCIWriteUlongType1, ULONG)
157c2c66affSColin Finck 
158c2c66affSColin Finck /* TYPE 2 FUNCTIONS **********************************************************/
159c2c66affSColin Finck 
160c2c66affSColin Finck VOID
161c2c66affSColin Finck NTAPI
162c2c66affSColin Finck HalpPCISynchronizeType2(IN PBUS_HANDLER BusHandler,
163c2c66affSColin Finck                         IN PCI_SLOT_NUMBER Slot,
164a0fb02f7STimo Kreuzer                         OUT PKIRQL OldIrql,
165a0fb02f7STimo Kreuzer                         OUT PPCI_TYPE2_ADDRESS_BITS PciCfg)
166c2c66affSColin Finck {
167c2c66affSColin Finck     PCI_TYPE2_CSE_BITS PciCfg2Cse;
168c2c66affSColin Finck     PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData;
169c2c66affSColin Finck 
170c2c66affSColin Finck     /* Setup the configuration register */
171c2c66affSColin Finck     PciCfg->u.AsUSHORT = 0;
172c2c66affSColin Finck     PciCfg->u.bits.Agent = (USHORT)Slot.u.bits.DeviceNumber;
173c2c66affSColin Finck     PciCfg->u.bits.AddressBase = (USHORT)BusData->Config.Type2.Base;
174c2c66affSColin Finck 
175c2c66affSColin Finck     /* Acquire the lock */
176a0fb02f7STimo Kreuzer     KeRaiseIrql(HIGH_LEVEL, OldIrql);
177a0fb02f7STimo Kreuzer     KeAcquireSpinLockAtDpcLevel(&HalpPCIConfigLock);
178c2c66affSColin Finck 
179c2c66affSColin Finck     /* Setup the CSE Register */
180c2c66affSColin Finck     PciCfg2Cse.u.AsUCHAR = 0;
181c2c66affSColin Finck     PciCfg2Cse.u.bits.Enable = TRUE;
182c2c66affSColin Finck     PciCfg2Cse.u.bits.FunctionNumber = (UCHAR)Slot.u.bits.FunctionNumber;
183c2c66affSColin Finck     PciCfg2Cse.u.bits.Key = -1;
184c2c66affSColin Finck 
185c2c66affSColin Finck     /* Write the bus number and CSE */
186c2c66affSColin Finck     WRITE_PORT_UCHAR(BusData->Config.Type2.Forward,
187c2c66affSColin Finck                      (UCHAR)BusHandler->BusNumber);
188c2c66affSColin Finck     WRITE_PORT_UCHAR(BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
189c2c66affSColin Finck }
190c2c66affSColin Finck 
191c2c66affSColin Finck VOID
192c2c66affSColin Finck NTAPI
HalpPCIReleaseSynchronizationType2(IN PBUS_HANDLER BusHandler,IN KIRQL OldIrql)193c2c66affSColin Finck HalpPCIReleaseSynchronizationType2(IN PBUS_HANDLER BusHandler,
194a0fb02f7STimo Kreuzer                                    IN KIRQL OldIrql)
195c2c66affSColin Finck {
196c2c66affSColin Finck     PCI_TYPE2_CSE_BITS PciCfg2Cse;
197c2c66affSColin Finck     PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData;
198c2c66affSColin Finck 
199c2c66affSColin Finck     /* Clear CSE and bus number */
200c2c66affSColin Finck     PciCfg2Cse.u.AsUCHAR = 0;
201c2c66affSColin Finck     WRITE_PORT_UCHAR(BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
202c2c66affSColin Finck     WRITE_PORT_UCHAR(BusData->Config.Type2.Forward, 0);
203c2c66affSColin Finck 
204c2c66affSColin Finck     /* Release the lock */
205a0fb02f7STimo Kreuzer     KeReleaseSpinLock(&HalpPCIConfigLock, OldIrql);
206c2c66affSColin Finck }
207c2c66affSColin Finck 
TYPE2_READ(HalpPCIReadUcharType2,UCHAR)208c2c66affSColin Finck TYPE2_READ(HalpPCIReadUcharType2, UCHAR)
209c2c66affSColin Finck TYPE2_READ(HalpPCIReadUshortType2, USHORT)
210c2c66affSColin Finck TYPE2_READ(HalpPCIReadUlongType2, ULONG)
211c2c66affSColin Finck TYPE2_WRITE(HalpPCIWriteUcharType2, UCHAR)
212c2c66affSColin Finck TYPE2_WRITE(HalpPCIWriteUshortType2, USHORT)
213c2c66affSColin Finck TYPE2_WRITE(HalpPCIWriteUlongType2, ULONG)
214c2c66affSColin Finck 
215c2c66affSColin Finck /* PCI CONFIGURATION SPACE ***************************************************/
216c2c66affSColin Finck 
217c2c66affSColin Finck VOID
218c2c66affSColin Finck NTAPI
219c2c66affSColin Finck HalpPCIConfig(IN PBUS_HANDLER BusHandler,
220c2c66affSColin Finck               IN PCI_SLOT_NUMBER Slot,
221c2c66affSColin Finck               IN PUCHAR Buffer,
222c2c66affSColin Finck               IN ULONG Offset,
223c2c66affSColin Finck               IN ULONG Length,
224c2c66affSColin Finck               IN FncConfigIO *ConfigIO)
225c2c66affSColin Finck {
226c2c66affSColin Finck     KIRQL OldIrql;
227c2c66affSColin Finck     ULONG i;
228c2c66affSColin Finck     UCHAR State[20];
229c2c66affSColin Finck 
230c2c66affSColin Finck     /* Synchronize the operation */
231c2c66affSColin Finck     PCIConfigHandler.Synchronize(BusHandler, Slot, &OldIrql, State);
232c2c66affSColin Finck 
233c2c66affSColin Finck     /* Loop every increment */
234c2c66affSColin Finck     while (Length)
235c2c66affSColin Finck     {
236c2c66affSColin Finck         /* Find out the type of read/write we need to do */
237c2c66affSColin Finck         i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
238c2c66affSColin Finck 
239c2c66affSColin Finck         /* Do the read/write and return the number of bytes */
240c2c66affSColin Finck         i = ConfigIO[i]((PPCIPBUSDATA)BusHandler->BusData,
241c2c66affSColin Finck                         State,
242c2c66affSColin Finck                         Buffer,
243c2c66affSColin Finck                         Offset);
244c2c66affSColin Finck 
245c2c66affSColin Finck         /* Increment the buffer position and offset, and decrease the length */
246c2c66affSColin Finck         Offset += i;
247c2c66affSColin Finck         Buffer += i;
248c2c66affSColin Finck         Length -= i;
249c2c66affSColin Finck     }
250c2c66affSColin Finck 
251c2c66affSColin Finck     /* Release the lock and PCI bus */
252c2c66affSColin Finck     PCIConfigHandler.ReleaseSynchronzation(BusHandler, OldIrql);
253c2c66affSColin Finck }
254c2c66affSColin Finck 
255c2c66affSColin Finck VOID
256c2c66affSColin Finck NTAPI
HalpReadPCIConfig(IN PBUS_HANDLER BusHandler,IN PCI_SLOT_NUMBER Slot,IN PVOID Buffer,IN ULONG Offset,IN ULONG Length)257c2c66affSColin Finck HalpReadPCIConfig(IN PBUS_HANDLER BusHandler,
258c2c66affSColin Finck                   IN PCI_SLOT_NUMBER Slot,
259c2c66affSColin Finck                   IN PVOID Buffer,
260c2c66affSColin Finck                   IN ULONG Offset,
261c2c66affSColin Finck                   IN ULONG Length)
262c2c66affSColin Finck {
263c2c66affSColin Finck     /* Validate the PCI Slot */
264c2c66affSColin Finck     if (!HalpValidPCISlot(BusHandler, Slot))
265c2c66affSColin Finck     {
266c2c66affSColin Finck         /* Fill the buffer with invalid data */
267c2c66affSColin Finck         RtlFillMemory(Buffer, Length, -1);
268c2c66affSColin Finck     }
269c2c66affSColin Finck     else
270c2c66affSColin Finck     {
271c2c66affSColin Finck         /* Send the request */
272c2c66affSColin Finck         HalpPCIConfig(BusHandler,
273c2c66affSColin Finck                       Slot,
274c2c66affSColin Finck                       Buffer,
275c2c66affSColin Finck                       Offset,
276c2c66affSColin Finck                       Length,
277c2c66affSColin Finck                       PCIConfigHandler.ConfigRead);
278c2c66affSColin Finck     }
279c2c66affSColin Finck }
280c2c66affSColin Finck 
281c2c66affSColin Finck VOID
282c2c66affSColin Finck NTAPI
HalpWritePCIConfig(IN PBUS_HANDLER BusHandler,IN PCI_SLOT_NUMBER Slot,IN PVOID Buffer,IN ULONG Offset,IN ULONG Length)283c2c66affSColin Finck HalpWritePCIConfig(IN PBUS_HANDLER BusHandler,
284c2c66affSColin Finck                    IN PCI_SLOT_NUMBER Slot,
285c2c66affSColin Finck                    IN PVOID Buffer,
286c2c66affSColin Finck                    IN ULONG Offset,
287c2c66affSColin Finck                    IN ULONG Length)
288c2c66affSColin Finck {
289c2c66affSColin Finck     /* Validate the PCI Slot */
290c2c66affSColin Finck     if (HalpValidPCISlot(BusHandler, Slot))
291c2c66affSColin Finck     {
292c2c66affSColin Finck         /* Send the request */
293c2c66affSColin Finck         HalpPCIConfig(BusHandler,
294c2c66affSColin Finck                       Slot,
295c2c66affSColin Finck                       Buffer,
296c2c66affSColin Finck                       Offset,
297c2c66affSColin Finck                       Length,
298c2c66affSColin Finck                       PCIConfigHandler.ConfigWrite);
299c2c66affSColin Finck     }
300c2c66affSColin Finck }
301c2c66affSColin Finck 
302b9927270SStanislav Motylkov #ifdef SARCH_XBOX
303*734cd5e8SDmitry Borisov static
304b9927270SStanislav Motylkov BOOLEAN
HalpXboxBlacklistedPCISlot(_In_ ULONG BusNumber,_In_ PCI_SLOT_NUMBER Slot)305*734cd5e8SDmitry Borisov HalpXboxBlacklistedPCISlot(
306*734cd5e8SDmitry Borisov     _In_ ULONG BusNumber,
307*734cd5e8SDmitry Borisov     _In_ PCI_SLOT_NUMBER Slot)
308b9927270SStanislav Motylkov {
309b9927270SStanislav Motylkov     /* Trying to get PCI config data from devices 0:0:1 and 0:0:2 will completely
310b9927270SStanislav Motylkov      * hang the Xbox. Also, the device number doesn't seem to be decoded for the
311b9927270SStanislav Motylkov      * video card, so it appears to be present on 1:0:0 - 1:31:0.
312b9927270SStanislav Motylkov      * We hack around these problems by indicating "device not present" for devices
313b9927270SStanislav Motylkov      * 0:0:1, 0:0:2, 1:1:0, 1:2:0, 1:3:0, ...., 1:31:0 */
314*734cd5e8SDmitry Borisov     if ((BusNumber == 0 && Slot.u.bits.DeviceNumber == 0 &&
315b9927270SStanislav Motylkov         (Slot.u.bits.FunctionNumber == 1 || Slot.u.bits.FunctionNumber == 2)) ||
316*734cd5e8SDmitry Borisov         (BusNumber == 1 && Slot.u.bits.DeviceNumber != 0))
317b9927270SStanislav Motylkov     {
318*734cd5e8SDmitry Borisov         DPRINT("Blacklisted PCI slot (%d:%d:%d)\n",
319*734cd5e8SDmitry Borisov                BusNumber, Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
320b9927270SStanislav Motylkov         return TRUE;
321b9927270SStanislav Motylkov     }
322b9927270SStanislav Motylkov 
323b9927270SStanislav Motylkov     return FALSE;
324b9927270SStanislav Motylkov }
325b9927270SStanislav Motylkov #endif
326b9927270SStanislav Motylkov 
327c2c66affSColin Finck BOOLEAN
328c2c66affSColin Finck NTAPI
HalpValidPCISlot(IN PBUS_HANDLER BusHandler,IN PCI_SLOT_NUMBER Slot)329c2c66affSColin Finck HalpValidPCISlot(IN PBUS_HANDLER BusHandler,
330c2c66affSColin Finck                  IN PCI_SLOT_NUMBER Slot)
331c2c66affSColin Finck {
332c2c66affSColin Finck     PCI_SLOT_NUMBER MultiSlot;
333c2c66affSColin Finck     PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData;
334c2c66affSColin Finck     UCHAR HeaderType;
335c2c66affSColin Finck     //ULONG Device;
336c2c66affSColin Finck 
337c2c66affSColin Finck     /* Simple validation */
338c2c66affSColin Finck     if (Slot.u.bits.Reserved) return FALSE;
339c2c66affSColin Finck     if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) return FALSE;
340c2c66affSColin Finck 
341251bf491SStanislav Motylkov #ifdef SARCH_XBOX
342*734cd5e8SDmitry Borisov     if (HalpXboxBlacklistedPCISlot(BusHandler->BusNumber, Slot))
343*734cd5e8SDmitry Borisov         return FALSE;
344251bf491SStanislav Motylkov #endif
345251bf491SStanislav Motylkov 
346c2c66affSColin Finck     /* Function 0 doesn't need checking */
347c2c66affSColin Finck     if (!Slot.u.bits.FunctionNumber) return TRUE;
348c2c66affSColin Finck 
349c2c66affSColin Finck     /* Functions 0+ need Multi-Function support, so check the slot */
350c2c66affSColin Finck     //Device = Slot.u.bits.DeviceNumber;
351c2c66affSColin Finck     MultiSlot = Slot;
352c2c66affSColin Finck     MultiSlot.u.bits.FunctionNumber = 0;
353c2c66affSColin Finck 
354c2c66affSColin Finck     /* Send function 0 request to get the header back */
355c2c66affSColin Finck     HalpReadPCIConfig(BusHandler,
356c2c66affSColin Finck                       MultiSlot,
357c2c66affSColin Finck                       &HeaderType,
358c2c66affSColin Finck                       FIELD_OFFSET(PCI_COMMON_CONFIG, HeaderType),
359c2c66affSColin Finck                       sizeof(UCHAR));
360c2c66affSColin Finck 
361c2c66affSColin Finck     /* Now make sure the header is multi-function */
362c2c66affSColin Finck     if (!(HeaderType & PCI_MULTIFUNCTION) || (HeaderType == 0xFF)) return FALSE;
363c2c66affSColin Finck     return TRUE;
364c2c66affSColin Finck }
365c2c66affSColin Finck 
366*734cd5e8SDmitry Borisov CODE_SEG("INIT")
367*734cd5e8SDmitry Borisov ULONG
HalpPhase0GetPciDataByOffset(_In_ ULONG Bus,_In_ PCI_SLOT_NUMBER PciSlot,_Out_writes_bytes_all_ (Length)PVOID Buffer,_In_ ULONG Offset,_In_ ULONG Length)368*734cd5e8SDmitry Borisov HalpPhase0GetPciDataByOffset(
369*734cd5e8SDmitry Borisov     _In_ ULONG Bus,
370*734cd5e8SDmitry Borisov     _In_ PCI_SLOT_NUMBER PciSlot,
371*734cd5e8SDmitry Borisov     _Out_writes_bytes_all_(Length) PVOID Buffer,
372*734cd5e8SDmitry Borisov     _In_ ULONG Offset,
373*734cd5e8SDmitry Borisov     _In_ ULONG Length)
374*734cd5e8SDmitry Borisov {
375*734cd5e8SDmitry Borisov     ULONG BytesLeft = Length;
376*734cd5e8SDmitry Borisov     PUCHAR BufferPtr = Buffer;
377*734cd5e8SDmitry Borisov     PCI_TYPE1_CFG_BITS PciCfg;
378*734cd5e8SDmitry Borisov 
379*734cd5e8SDmitry Borisov #ifdef SARCH_XBOX
380*734cd5e8SDmitry Borisov     if (HalpXboxBlacklistedPCISlot(Bus, PciSlot))
381*734cd5e8SDmitry Borisov     {
382*734cd5e8SDmitry Borisov         RtlFillMemory(Buffer, Length, 0xFF);
383*734cd5e8SDmitry Borisov         return Length;
384*734cd5e8SDmitry Borisov     }
385*734cd5e8SDmitry Borisov #endif
386*734cd5e8SDmitry Borisov 
387*734cd5e8SDmitry Borisov     PciCfg.u.AsULONG = 0;
388*734cd5e8SDmitry Borisov     PciCfg.u.bits.BusNumber = Bus;
389*734cd5e8SDmitry Borisov     PciCfg.u.bits.DeviceNumber = PciSlot.u.bits.DeviceNumber;
390*734cd5e8SDmitry Borisov     PciCfg.u.bits.FunctionNumber = PciSlot.u.bits.FunctionNumber;
391*734cd5e8SDmitry Borisov     PciCfg.u.bits.Enable = TRUE;
392*734cd5e8SDmitry Borisov 
393*734cd5e8SDmitry Borisov     while (BytesLeft)
394*734cd5e8SDmitry Borisov     {
395*734cd5e8SDmitry Borisov         ULONG i;
396*734cd5e8SDmitry Borisov 
397*734cd5e8SDmitry Borisov         PciCfg.u.bits.RegisterNumber = Offset / sizeof(ULONG);
398*734cd5e8SDmitry Borisov         WRITE_PORT_ULONG((PULONG)PCI_TYPE1_ADDRESS_PORT, PciCfg.u.AsULONG);
399*734cd5e8SDmitry Borisov 
400*734cd5e8SDmitry Borisov         i = PCIDeref[Offset % sizeof(ULONG)][BytesLeft % sizeof(ULONG)];
401*734cd5e8SDmitry Borisov         switch (i)
402*734cd5e8SDmitry Borisov         {
403*734cd5e8SDmitry Borisov             case 0:
404*734cd5e8SDmitry Borisov             {
405*734cd5e8SDmitry Borisov                 *(PULONG)BufferPtr = READ_PORT_ULONG((PULONG)PCI_TYPE1_DATA_PORT);
406*734cd5e8SDmitry Borisov 
407*734cd5e8SDmitry Borisov                 /* Number of bytes read */
408*734cd5e8SDmitry Borisov                 i = sizeof(ULONG);
409*734cd5e8SDmitry Borisov                 break;
410*734cd5e8SDmitry Borisov             }
411*734cd5e8SDmitry Borisov             case 1:
412*734cd5e8SDmitry Borisov             {
413*734cd5e8SDmitry Borisov                 *BufferPtr = READ_PORT_UCHAR((PUCHAR)(PCI_TYPE1_DATA_PORT +
414*734cd5e8SDmitry Borisov                                              Offset % sizeof(ULONG)));
415*734cd5e8SDmitry Borisov                 break;
416*734cd5e8SDmitry Borisov             }
417*734cd5e8SDmitry Borisov             case 2:
418*734cd5e8SDmitry Borisov             {
419*734cd5e8SDmitry Borisov                 *(PUSHORT)BufferPtr = READ_PORT_USHORT((PUSHORT)(PCI_TYPE1_DATA_PORT +
420*734cd5e8SDmitry Borisov                                                                  Offset % sizeof(ULONG)));
421*734cd5e8SDmitry Borisov                 break;
422*734cd5e8SDmitry Borisov             }
423*734cd5e8SDmitry Borisov 
424*734cd5e8SDmitry Borisov             DEFAULT_UNREACHABLE;
425*734cd5e8SDmitry Borisov         }
426*734cd5e8SDmitry Borisov 
427*734cd5e8SDmitry Borisov         Offset += i;
428*734cd5e8SDmitry Borisov         BufferPtr += i;
429*734cd5e8SDmitry Borisov         BytesLeft -= i;
430*734cd5e8SDmitry Borisov     }
431*734cd5e8SDmitry Borisov 
432*734cd5e8SDmitry Borisov     return Length;
433*734cd5e8SDmitry Borisov }
434*734cd5e8SDmitry Borisov 
435*734cd5e8SDmitry Borisov CODE_SEG("INIT")
436*734cd5e8SDmitry Borisov ULONG
HalpPhase0SetPciDataByOffset(_In_ ULONG Bus,_In_ PCI_SLOT_NUMBER PciSlot,_In_reads_bytes_ (Length)PVOID Buffer,_In_ ULONG Offset,_In_ ULONG Length)437*734cd5e8SDmitry Borisov HalpPhase0SetPciDataByOffset(
438*734cd5e8SDmitry Borisov     _In_ ULONG Bus,
439*734cd5e8SDmitry Borisov     _In_ PCI_SLOT_NUMBER PciSlot,
440*734cd5e8SDmitry Borisov     _In_reads_bytes_(Length) PVOID Buffer,
441*734cd5e8SDmitry Borisov     _In_ ULONG Offset,
442*734cd5e8SDmitry Borisov     _In_ ULONG Length)
443*734cd5e8SDmitry Borisov {
444*734cd5e8SDmitry Borisov     ULONG BytesLeft = Length;
445*734cd5e8SDmitry Borisov     PUCHAR BufferPtr = Buffer;
446*734cd5e8SDmitry Borisov     PCI_TYPE1_CFG_BITS PciCfg;
447*734cd5e8SDmitry Borisov 
448*734cd5e8SDmitry Borisov #ifdef SARCH_XBOX
449*734cd5e8SDmitry Borisov     if (HalpXboxBlacklistedPCISlot(Bus, PciSlot))
450*734cd5e8SDmitry Borisov     {
451*734cd5e8SDmitry Borisov         return 0;
452*734cd5e8SDmitry Borisov     }
453*734cd5e8SDmitry Borisov #endif
454*734cd5e8SDmitry Borisov 
455*734cd5e8SDmitry Borisov     PciCfg.u.AsULONG = 0;
456*734cd5e8SDmitry Borisov     PciCfg.u.bits.BusNumber = Bus;
457*734cd5e8SDmitry Borisov     PciCfg.u.bits.DeviceNumber = PciSlot.u.bits.DeviceNumber;
458*734cd5e8SDmitry Borisov     PciCfg.u.bits.FunctionNumber = PciSlot.u.bits.FunctionNumber;
459*734cd5e8SDmitry Borisov     PciCfg.u.bits.Enable = TRUE;
460*734cd5e8SDmitry Borisov 
461*734cd5e8SDmitry Borisov     while (BytesLeft)
462*734cd5e8SDmitry Borisov     {
463*734cd5e8SDmitry Borisov         ULONG i;
464*734cd5e8SDmitry Borisov 
465*734cd5e8SDmitry Borisov         PciCfg.u.bits.RegisterNumber = Offset / sizeof(ULONG);
466*734cd5e8SDmitry Borisov         WRITE_PORT_ULONG((PULONG)PCI_TYPE1_ADDRESS_PORT, PciCfg.u.AsULONG);
467*734cd5e8SDmitry Borisov 
468*734cd5e8SDmitry Borisov         i = PCIDeref[Offset % sizeof(ULONG)][BytesLeft % sizeof(ULONG)];
469*734cd5e8SDmitry Borisov         switch (i)
470*734cd5e8SDmitry Borisov         {
471*734cd5e8SDmitry Borisov             case 0:
472*734cd5e8SDmitry Borisov             {
473*734cd5e8SDmitry Borisov                 WRITE_PORT_ULONG((PULONG)PCI_TYPE1_DATA_PORT, *(PULONG)BufferPtr);
474*734cd5e8SDmitry Borisov 
475*734cd5e8SDmitry Borisov                 /* Number of bytes written */
476*734cd5e8SDmitry Borisov                 i = sizeof(ULONG);
477*734cd5e8SDmitry Borisov                 break;
478*734cd5e8SDmitry Borisov             }
479*734cd5e8SDmitry Borisov             case 1:
480*734cd5e8SDmitry Borisov             {
481*734cd5e8SDmitry Borisov                 WRITE_PORT_UCHAR((PUCHAR)(PCI_TYPE1_DATA_PORT + Offset % sizeof(ULONG)),
482*734cd5e8SDmitry Borisov                                  *BufferPtr);
483*734cd5e8SDmitry Borisov                 break;
484*734cd5e8SDmitry Borisov             }
485*734cd5e8SDmitry Borisov             case 2:
486*734cd5e8SDmitry Borisov             {
487*734cd5e8SDmitry Borisov                 WRITE_PORT_USHORT((PUSHORT)(PCI_TYPE1_DATA_PORT + Offset % sizeof(ULONG)),
488*734cd5e8SDmitry Borisov                                   *(PUSHORT)BufferPtr);
489*734cd5e8SDmitry Borisov                 break;
490*734cd5e8SDmitry Borisov             }
491*734cd5e8SDmitry Borisov 
492*734cd5e8SDmitry Borisov             DEFAULT_UNREACHABLE;
493*734cd5e8SDmitry Borisov         }
494*734cd5e8SDmitry Borisov 
495*734cd5e8SDmitry Borisov         Offset += i;
496*734cd5e8SDmitry Borisov         BufferPtr += i;
497*734cd5e8SDmitry Borisov         BytesLeft -= i;
498*734cd5e8SDmitry Borisov     }
499*734cd5e8SDmitry Borisov 
500*734cd5e8SDmitry Borisov     return Length;
501*734cd5e8SDmitry Borisov }
502*734cd5e8SDmitry Borisov 
503c2c66affSColin Finck /* HAL PCI CALLBACKS *********************************************************/
504c2c66affSColin Finck 
505c2c66affSColin Finck ULONG
506c2c66affSColin Finck NTAPI
HalpGetPCIData(IN PBUS_HANDLER BusHandler,IN PBUS_HANDLER RootHandler,IN ULONG SlotNumber,IN PVOID Buffer,IN ULONG Offset,IN ULONG Length)507c2c66affSColin Finck HalpGetPCIData(IN PBUS_HANDLER BusHandler,
508c2c66affSColin Finck                IN PBUS_HANDLER RootHandler,
509c2c66affSColin Finck                IN ULONG SlotNumber,
510c2c66affSColin Finck                IN PVOID Buffer,
511c2c66affSColin Finck                IN ULONG Offset,
512c2c66affSColin Finck                IN ULONG Length)
513c2c66affSColin Finck {
514c2c66affSColin Finck     PCI_SLOT_NUMBER Slot;
515c2c66affSColin Finck     UCHAR PciBuffer[PCI_COMMON_HDR_LENGTH];
516c2c66affSColin Finck     PPCI_COMMON_CONFIG PciConfig = (PPCI_COMMON_CONFIG)PciBuffer;
517c2c66affSColin Finck     ULONG Len = 0;
518c2c66affSColin Finck 
519c2c66affSColin Finck     Slot.u.AsULONG = SlotNumber;
520c2c66affSColin Finck #ifdef SARCH_XBOX
521*734cd5e8SDmitry Borisov     if (HalpXboxBlacklistedPCISlot(BusHandler->BusNumber, Slot))
522c2c66affSColin Finck     {
523*734cd5e8SDmitry Borisov         RtlFillMemory(Buffer, Length, 0xFF);
524*734cd5e8SDmitry Borisov         return Length;
525c2c66affSColin Finck     }
526c2c66affSColin Finck #endif
527c2c66affSColin Finck 
528c2c66affSColin Finck     /* Normalize the length */
529c2c66affSColin Finck     if (Length > sizeof(PCI_COMMON_CONFIG)) Length = sizeof(PCI_COMMON_CONFIG);
530c2c66affSColin Finck 
531c2c66affSColin Finck     /* Check if this is a vendor-specific read */
532c2c66affSColin Finck     if (Offset >= PCI_COMMON_HDR_LENGTH)
533c2c66affSColin Finck     {
534c2c66affSColin Finck         /* Read the header */
535c2c66affSColin Finck         HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, sizeof(ULONG));
536c2c66affSColin Finck 
537c2c66affSColin Finck         /* Make sure the vendor is valid */
538c2c66affSColin Finck         if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0;
539c2c66affSColin Finck     }
540c2c66affSColin Finck     else
541c2c66affSColin Finck     {
542c2c66affSColin Finck         /* Read the entire header */
543c2c66affSColin Finck         Len = PCI_COMMON_HDR_LENGTH;
544c2c66affSColin Finck         HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, Len);
545c2c66affSColin Finck 
546c2c66affSColin Finck         /* Validate the vendor ID */
547c2c66affSColin Finck         if (PciConfig->VendorID == PCI_INVALID_VENDORID)
548c2c66affSColin Finck         {
549c2c66affSColin Finck             /* It's invalid, but we want to return this much */
550c2c66affSColin Finck             Len = sizeof(USHORT);
551c2c66affSColin Finck         }
552c2c66affSColin Finck 
553c2c66affSColin Finck         /* Now check if there's space left */
554c2c66affSColin Finck         if (Len < Offset) return 0;
555c2c66affSColin Finck 
556c2c66affSColin Finck         /* There is, so return what's after the offset and normalize */
557c2c66affSColin Finck         Len -= Offset;
558c2c66affSColin Finck         if (Len > Length) Len = Length;
559c2c66affSColin Finck 
560c2c66affSColin Finck         /* Copy the data into the caller's buffer */
561c2c66affSColin Finck         RtlMoveMemory(Buffer, PciBuffer + Offset, Len);
562c2c66affSColin Finck 
563c2c66affSColin Finck         /* Update buffer and offset, decrement total length */
564c2c66affSColin Finck         Offset += Len;
565c2c66affSColin Finck         Buffer = (PVOID)((ULONG_PTR)Buffer + Len);
566c2c66affSColin Finck         Length -= Len;
567c2c66affSColin Finck     }
568c2c66affSColin Finck 
569c2c66affSColin Finck     /* Now we still have something to copy */
570c2c66affSColin Finck     if (Length)
571c2c66affSColin Finck     {
572c2c66affSColin Finck         /* Check if it's vendor-specific data */
573c2c66affSColin Finck         if (Offset >= PCI_COMMON_HDR_LENGTH)
574c2c66affSColin Finck         {
575c2c66affSColin Finck             /* Read it now */
576c2c66affSColin Finck             HalpReadPCIConfig(BusHandler, Slot, Buffer, Offset, Length);
577c2c66affSColin Finck             Len += Length;
578c2c66affSColin Finck         }
579c2c66affSColin Finck     }
580c2c66affSColin Finck 
581c2c66affSColin Finck     /* Update the total length read */
582c2c66affSColin Finck     return Len;
583c2c66affSColin Finck }
584c2c66affSColin Finck 
585c2c66affSColin Finck ULONG
586c2c66affSColin Finck NTAPI
HalpSetPCIData(IN PBUS_HANDLER BusHandler,IN PBUS_HANDLER RootHandler,IN ULONG SlotNumber,IN PVOID Buffer,IN ULONG Offset,IN ULONG Length)587c2c66affSColin Finck HalpSetPCIData(IN PBUS_HANDLER BusHandler,
588c2c66affSColin Finck                IN PBUS_HANDLER RootHandler,
589c2c66affSColin Finck                IN ULONG SlotNumber,
590c2c66affSColin Finck                IN PVOID Buffer,
591c2c66affSColin Finck                IN ULONG Offset,
592c2c66affSColin Finck                IN ULONG Length)
593c2c66affSColin Finck {
594c2c66affSColin Finck     PCI_SLOT_NUMBER Slot;
595c2c66affSColin Finck     UCHAR PciBuffer[PCI_COMMON_HDR_LENGTH];
596c2c66affSColin Finck     PPCI_COMMON_CONFIG PciConfig = (PPCI_COMMON_CONFIG)PciBuffer;
597c2c66affSColin Finck     ULONG Len = 0;
598c2c66affSColin Finck 
599c2c66affSColin Finck     Slot.u.AsULONG = SlotNumber;
600c2c66affSColin Finck #ifdef SARCH_XBOX
601*734cd5e8SDmitry Borisov     if (HalpXboxBlacklistedPCISlot(BusHandler->BusNumber, Slot))
602*734cd5e8SDmitry Borisov         return 0;
603c2c66affSColin Finck #endif
604c2c66affSColin Finck 
605c2c66affSColin Finck     /* Normalize the length */
606c2c66affSColin Finck     if (Length > sizeof(PCI_COMMON_CONFIG)) Length = sizeof(PCI_COMMON_CONFIG);
607c2c66affSColin Finck 
608c2c66affSColin Finck     /* Check if this is a vendor-specific read */
609c2c66affSColin Finck     if (Offset >= PCI_COMMON_HDR_LENGTH)
610c2c66affSColin Finck     {
611c2c66affSColin Finck         /* Read the header */
612c2c66affSColin Finck         HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, sizeof(ULONG));
613c2c66affSColin Finck 
614c2c66affSColin Finck         /* Make sure the vendor is valid */
615c2c66affSColin Finck         if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0;
616c2c66affSColin Finck     }
617c2c66affSColin Finck     else
618c2c66affSColin Finck     {
619c2c66affSColin Finck         /* Read the entire header and validate the vendor ID */
620c2c66affSColin Finck         Len = PCI_COMMON_HDR_LENGTH;
621c2c66affSColin Finck         HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, Len);
622c2c66affSColin Finck         if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0;
623c2c66affSColin Finck 
624c2c66affSColin Finck         /* Return what's after the offset and normalize */
625c2c66affSColin Finck         Len -= Offset;
626c2c66affSColin Finck         if (Len > Length) Len = Length;
627c2c66affSColin Finck 
628c2c66affSColin Finck         /* Copy the specific caller data */
629c2c66affSColin Finck         RtlMoveMemory(PciBuffer + Offset, Buffer, Len);
630c2c66affSColin Finck 
631c2c66affSColin Finck         /* Write the actual configuration data */
632c2c66affSColin Finck         HalpWritePCIConfig(BusHandler, Slot, PciBuffer + Offset, Offset, Len);
633c2c66affSColin Finck 
634c2c66affSColin Finck         /* Update buffer and offset, decrement total length */
635c2c66affSColin Finck         Offset += Len;
636c2c66affSColin Finck         Buffer = (PVOID)((ULONG_PTR)Buffer + Len);
637c2c66affSColin Finck         Length -= Len;
638c2c66affSColin Finck     }
639c2c66affSColin Finck 
640c2c66affSColin Finck     /* Now we still have something to copy */
641c2c66affSColin Finck     if (Length)
642c2c66affSColin Finck     {
643c2c66affSColin Finck         /* Check if it's vendor-specific data */
644c2c66affSColin Finck         if (Offset >= PCI_COMMON_HDR_LENGTH)
645c2c66affSColin Finck         {
646c2c66affSColin Finck             /* Read it now */
647c2c66affSColin Finck             HalpWritePCIConfig(BusHandler, Slot, Buffer, Offset, Length);
648c2c66affSColin Finck             Len += Length;
649c2c66affSColin Finck         }
650c2c66affSColin Finck     }
651c2c66affSColin Finck 
652c2c66affSColin Finck     /* Update the total length read */
653c2c66affSColin Finck     return Len;
654c2c66affSColin Finck }
655ee514e95STimo Kreuzer #ifndef _MINIHAL_
656c2c66affSColin Finck ULONG
657c2c66affSColin Finck NTAPI
HalpGetPCIIntOnISABus(IN PBUS_HANDLER BusHandler,IN PBUS_HANDLER RootHandler,IN ULONG BusInterruptLevel,IN ULONG BusInterruptVector,OUT PKIRQL Irql,OUT PKAFFINITY Affinity)658c2c66affSColin Finck HalpGetPCIIntOnISABus(IN PBUS_HANDLER BusHandler,
659c2c66affSColin Finck                       IN PBUS_HANDLER RootHandler,
660c2c66affSColin Finck                       IN ULONG BusInterruptLevel,
661c2c66affSColin Finck                       IN ULONG BusInterruptVector,
662c2c66affSColin Finck                       OUT PKIRQL Irql,
663c2c66affSColin Finck                       OUT PKAFFINITY Affinity)
664c2c66affSColin Finck {
665c2c66affSColin Finck     /* Validate the level first */
666c2c66affSColin Finck     if (BusInterruptLevel < 1) return 0;
667c2c66affSColin Finck 
668c2c66affSColin Finck     /* PCI has its IRQs on top of ISA IRQs, so pass it on to the ISA handler */
669c2c66affSColin Finck     return HalGetInterruptVector(Isa,
670c2c66affSColin Finck                                  0,
671c2c66affSColin Finck                                  BusInterruptLevel,
672c2c66affSColin Finck                                  0,
673c2c66affSColin Finck                                  Irql,
674c2c66affSColin Finck                                  Affinity);
675c2c66affSColin Finck }
676ee514e95STimo Kreuzer #endif // _MINIHAL_
677c2c66affSColin Finck 
678c2c66affSColin Finck VOID
679c2c66affSColin Finck NTAPI
HalpPCIPin2ISALine(IN PBUS_HANDLER BusHandler,IN PBUS_HANDLER RootHandler,IN PCI_SLOT_NUMBER SlotNumber,IN PPCI_COMMON_CONFIG PciData)680c2c66affSColin Finck HalpPCIPin2ISALine(IN PBUS_HANDLER BusHandler,
681c2c66affSColin Finck                    IN PBUS_HANDLER RootHandler,
682c2c66affSColin Finck                    IN PCI_SLOT_NUMBER SlotNumber,
683c2c66affSColin Finck                    IN PPCI_COMMON_CONFIG PciData)
684c2c66affSColin Finck {
685c2c66affSColin Finck     UNIMPLEMENTED_DBGBREAK();
686c2c66affSColin Finck }
687c2c66affSColin Finck 
688c2c66affSColin Finck VOID
689c2c66affSColin Finck NTAPI
HalpPCIISALine2Pin(IN PBUS_HANDLER BusHandler,IN PBUS_HANDLER RootHandler,IN PCI_SLOT_NUMBER SlotNumber,IN PPCI_COMMON_CONFIG PciNewData,IN PPCI_COMMON_CONFIG PciOldData)690c2c66affSColin Finck HalpPCIISALine2Pin(IN PBUS_HANDLER BusHandler,
691c2c66affSColin Finck                    IN PBUS_HANDLER RootHandler,
692c2c66affSColin Finck                    IN PCI_SLOT_NUMBER SlotNumber,
693c2c66affSColin Finck                    IN PPCI_COMMON_CONFIG PciNewData,
694c2c66affSColin Finck                    IN PPCI_COMMON_CONFIG PciOldData)
695c2c66affSColin Finck {
696c2c66affSColin Finck     UNIMPLEMENTED_DBGBREAK();
697c2c66affSColin Finck }
698c2c66affSColin Finck 
699ee514e95STimo Kreuzer #ifndef _MINIHAL_
700c2c66affSColin Finck NTSTATUS
701c2c66affSColin Finck NTAPI
HalpGetISAFixedPCIIrq(IN PBUS_HANDLER BusHandler,IN PBUS_HANDLER RootHandler,IN PCI_SLOT_NUMBER PciSlot,OUT PSUPPORTED_RANGE * Range)702c2c66affSColin Finck HalpGetISAFixedPCIIrq(IN PBUS_HANDLER BusHandler,
703c2c66affSColin Finck                       IN PBUS_HANDLER RootHandler,
704c2c66affSColin Finck                       IN PCI_SLOT_NUMBER PciSlot,
705c2c66affSColin Finck                       OUT PSUPPORTED_RANGE *Range)
706c2c66affSColin Finck {
707c2c66affSColin Finck     PCI_COMMON_HEADER PciData;
708c2c66affSColin Finck 
709c2c66affSColin Finck     /* Read PCI configuration data */
710c2c66affSColin Finck     HalGetBusData(PCIConfiguration,
711c2c66affSColin Finck                   BusHandler->BusNumber,
712c2c66affSColin Finck                   PciSlot.u.AsULONG,
713c2c66affSColin Finck                   &PciData,
714c2c66affSColin Finck                   PCI_COMMON_HDR_LENGTH);
715c2c66affSColin Finck 
716c2c66affSColin Finck     /* Make sure it's a real device */
717c2c66affSColin Finck     if (PciData.VendorID == PCI_INVALID_VENDORID) return STATUS_UNSUCCESSFUL;
718c2c66affSColin Finck 
719c2c66affSColin Finck     /* Allocate the supported range structure */
720c2c66affSColin Finck     *Range = ExAllocatePoolWithTag(PagedPool, sizeof(SUPPORTED_RANGE), TAG_HAL);
721c2c66affSColin Finck     if (!*Range) return STATUS_INSUFFICIENT_RESOURCES;
722c2c66affSColin Finck 
723c2c66affSColin Finck     /* Set it up */
724c2c66affSColin Finck     RtlZeroMemory(*Range, sizeof(SUPPORTED_RANGE));
725c2c66affSColin Finck     (*Range)->Base = 1;
726c2c66affSColin Finck 
727c2c66affSColin Finck     /* If the PCI device has no IRQ, nothing to do */
728c2c66affSColin Finck     if (!PciData.u.type0.InterruptPin) return STATUS_SUCCESS;
729c2c66affSColin Finck 
730c2c66affSColin Finck     /* FIXME: The PCI IRQ Routing Miniport should be called */
731c2c66affSColin Finck 
732c2c66affSColin Finck     /* Also if the INT# seems bogus, nothing to do either */
733c2c66affSColin Finck     if ((PciData.u.type0.InterruptLine == 0) ||
734c2c66affSColin Finck         (PciData.u.type0.InterruptLine == 255))
735c2c66affSColin Finck     {
736c2c66affSColin Finck         /* Fake success */
737c2c66affSColin Finck         return STATUS_SUCCESS;
738c2c66affSColin Finck     }
739c2c66affSColin Finck 
740c2c66affSColin Finck     /* Otherwise, the INT# should be valid, return it to the caller */
741c2c66affSColin Finck     (*Range)->Base = PciData.u.type0.InterruptLine;
742c2c66affSColin Finck     (*Range)->Limit = PciData.u.type0.InterruptLine;
743c2c66affSColin Finck     return STATUS_SUCCESS;
744c2c66affSColin Finck }
745ee514e95STimo Kreuzer #endif // _MINIHAL_
746c2c66affSColin Finck 
747c2c66affSColin Finck static ULONG NTAPI
PciSize(ULONG Base,ULONG Mask)748c2c66affSColin Finck PciSize(ULONG Base, ULONG Mask)
749c2c66affSColin Finck {
750c2c66affSColin Finck     ULONG Size = Mask & Base; /* Find the significant bits */
751c2c66affSColin Finck     Size = Size & ~(Size - 1); /* Get the lowest of them to find the decode size */
752c2c66affSColin Finck     return Size;
753c2c66affSColin Finck }
754c2c66affSColin Finck 
755c2c66affSColin Finck NTSTATUS
756c2c66affSColin Finck NTAPI
HalpAdjustPCIResourceList(IN PBUS_HANDLER BusHandler,IN PBUS_HANDLER RootHandler,IN OUT PIO_RESOURCE_REQUIREMENTS_LIST * pResourceList)757c2c66affSColin Finck HalpAdjustPCIResourceList(IN PBUS_HANDLER BusHandler,
758c2c66affSColin Finck                           IN PBUS_HANDLER RootHandler,
759c2c66affSColin Finck                           IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList)
760c2c66affSColin Finck {
761c2c66affSColin Finck     PPCIPBUSDATA BusData;
762c2c66affSColin Finck     PCI_SLOT_NUMBER SlotNumber;
763c2c66affSColin Finck     PSUPPORTED_RANGE Interrupt;
764c2c66affSColin Finck     NTSTATUS Status;
765c2c66affSColin Finck 
766c2c66affSColin Finck     /* Get PCI bus data */
767c2c66affSColin Finck     BusData = BusHandler->BusData;
768c2c66affSColin Finck     SlotNumber.u.AsULONG = (*pResourceList)->SlotNumber;
769c2c66affSColin Finck 
770c2c66affSColin Finck     /* Get the IRQ supported range */
771c2c66affSColin Finck     Status = BusData->GetIrqRange(BusHandler, RootHandler, SlotNumber, &Interrupt);
772c2c66affSColin Finck     if (!NT_SUCCESS(Status)) return Status;
773c2c66affSColin Finck #ifndef _MINIHAL_
774c2c66affSColin Finck     /* Handle the /PCILOCK feature */
775c2c66affSColin Finck     if (HalpPciLockSettings)
776c2c66affSColin Finck     {
777c2c66affSColin Finck         /* /PCILOCK is not yet supported */
778c2c66affSColin Finck         UNIMPLEMENTED_DBGBREAK("/PCILOCK boot switch is not yet supported.");
779c2c66affSColin Finck     }
780c2c66affSColin Finck #endif
781c2c66affSColin Finck     /* Now create the correct resource list based on the supported bus ranges */
782c2c66affSColin Finck #if 0
783c2c66affSColin Finck     Status = HaliAdjustResourceListRange(BusHandler->BusAddresses,
784c2c66affSColin Finck                                          Interrupt,
785c2c66affSColin Finck                                          pResourceList);
786c2c66affSColin Finck #else
787c2c66affSColin Finck     DPRINT1("HAL: No PCI Resource Adjustment done! Hardware may malfunction\n");
788c2c66affSColin Finck     Status = STATUS_SUCCESS;
789c2c66affSColin Finck #endif
790c2c66affSColin Finck 
791c2c66affSColin Finck     /* Return to caller */
792c2c66affSColin Finck     ExFreePool(Interrupt);
793c2c66affSColin Finck     return Status;
794c2c66affSColin Finck }
795c2c66affSColin Finck 
796c2c66affSColin Finck NTSTATUS
797c2c66affSColin Finck NTAPI
HalpAssignPCISlotResources(IN PBUS_HANDLER BusHandler,IN PBUS_HANDLER RootHandler,IN PUNICODE_STRING RegistryPath,IN PUNICODE_STRING DriverClassName OPTIONAL,IN PDRIVER_OBJECT DriverObject,IN PDEVICE_OBJECT DeviceObject OPTIONAL,IN ULONG Slot,IN OUT PCM_RESOURCE_LIST * AllocatedResources)798c2c66affSColin Finck HalpAssignPCISlotResources(IN PBUS_HANDLER BusHandler,
799c2c66affSColin Finck                            IN PBUS_HANDLER RootHandler,
800c2c66affSColin Finck                            IN PUNICODE_STRING RegistryPath,
801c2c66affSColin Finck                            IN PUNICODE_STRING DriverClassName OPTIONAL,
802c2c66affSColin Finck                            IN PDRIVER_OBJECT DriverObject,
803c2c66affSColin Finck                            IN PDEVICE_OBJECT DeviceObject OPTIONAL,
804c2c66affSColin Finck                            IN ULONG Slot,
805c2c66affSColin Finck                            IN OUT PCM_RESOURCE_LIST *AllocatedResources)
806c2c66affSColin Finck {
807c2c66affSColin Finck     PCI_COMMON_CONFIG PciConfig;
808c2c66affSColin Finck     SIZE_T Address;
809c2c66affSColin Finck     ULONG ResourceCount;
810c2c66affSColin Finck     ULONG Size[PCI_TYPE0_ADDRESSES];
811c2c66affSColin Finck     NTSTATUS Status = STATUS_SUCCESS;
812c2c66affSColin Finck     UCHAR Offset;
813c2c66affSColin Finck     PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
814c2c66affSColin Finck     PCI_SLOT_NUMBER SlotNumber;
815c2c66affSColin Finck     ULONG WriteBuffer;
816c2c66affSColin Finck     DPRINT1("WARNING: PCI Slot Resource Assignment is FOOBAR\n");
817c2c66affSColin Finck 
818c2c66affSColin Finck     /* FIXME: Should handle 64-bit addresses */
819c2c66affSColin Finck 
820c2c66affSColin Finck     /* Read configuration data */
821c2c66affSColin Finck     SlotNumber.u.AsULONG = Slot;
822c2c66affSColin Finck     HalpReadPCIConfig(BusHandler, SlotNumber, &PciConfig, 0, PCI_COMMON_HDR_LENGTH);
823c2c66affSColin Finck 
824c2c66affSColin Finck     /* Check if we read it correctly */
825c2c66affSColin Finck     if (PciConfig.VendorID == PCI_INVALID_VENDORID)
826c2c66affSColin Finck         return STATUS_NO_SUCH_DEVICE;
827c2c66affSColin Finck 
828c2c66affSColin Finck     /* Read the PCI configuration space for the device and store base address and
829c2c66affSColin Finck     size information in temporary storage. Count the number of valid base addresses */
830c2c66affSColin Finck     ResourceCount = 0;
831c2c66affSColin Finck     for (Address = 0; Address < PCI_TYPE0_ADDRESSES; Address++)
832c2c66affSColin Finck     {
833c2c66affSColin Finck         if (0xffffffff == PciConfig.u.type0.BaseAddresses[Address])
834c2c66affSColin Finck             PciConfig.u.type0.BaseAddresses[Address] = 0;
835c2c66affSColin Finck 
836c2c66affSColin Finck         /* Memory resource */
837c2c66affSColin Finck         if (0 != PciConfig.u.type0.BaseAddresses[Address])
838c2c66affSColin Finck         {
839c2c66affSColin Finck             ResourceCount++;
840c2c66affSColin Finck 
841c2c66affSColin Finck             Offset = (UCHAR)FIELD_OFFSET(PCI_COMMON_CONFIG, u.type0.BaseAddresses[Address]);
842c2c66affSColin Finck 
843c2c66affSColin Finck             /* Write 0xFFFFFFFF there */
844c2c66affSColin Finck             WriteBuffer = 0xffffffff;
845c2c66affSColin Finck             HalpWritePCIConfig(BusHandler, SlotNumber, &WriteBuffer, Offset, sizeof(ULONG));
846c2c66affSColin Finck 
847c2c66affSColin Finck             /* Read that figure back from the config space */
848c2c66affSColin Finck             HalpReadPCIConfig(BusHandler, SlotNumber, &Size[Address], Offset, sizeof(ULONG));
849c2c66affSColin Finck 
850c2c66affSColin Finck             /* Write back initial value */
851c2c66affSColin Finck             HalpWritePCIConfig(BusHandler, SlotNumber, &PciConfig.u.type0.BaseAddresses[Address], Offset, sizeof(ULONG));
852c2c66affSColin Finck         }
853c2c66affSColin Finck     }
854c2c66affSColin Finck 
855c2c66affSColin Finck     /* Interrupt resource */
856c2c66affSColin Finck     if (0 != PciConfig.u.type0.InterruptPin &&
857c2c66affSColin Finck         0 != PciConfig.u.type0.InterruptLine &&
858c2c66affSColin Finck         0xFF != PciConfig.u.type0.InterruptLine)
859c2c66affSColin Finck         ResourceCount++;
860c2c66affSColin Finck 
861c2c66affSColin Finck     /* Allocate output buffer and initialize */
862c2c66affSColin Finck     *AllocatedResources = ExAllocatePoolWithTag(
863c2c66affSColin Finck         PagedPool,
864c2c66affSColin Finck         sizeof(CM_RESOURCE_LIST) +
865c2c66affSColin Finck         (ResourceCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR),
866c2c66affSColin Finck         TAG_HAL);
867c2c66affSColin Finck 
868c2c66affSColin Finck     if (NULL == *AllocatedResources)
869c2c66affSColin Finck         return STATUS_NO_MEMORY;
870c2c66affSColin Finck 
871c2c66affSColin Finck     (*AllocatedResources)->Count = 1;
872c2c66affSColin Finck     (*AllocatedResources)->List[0].InterfaceType = PCIBus;
873c2c66affSColin Finck     (*AllocatedResources)->List[0].BusNumber = BusHandler->BusNumber;
874c2c66affSColin Finck     (*AllocatedResources)->List[0].PartialResourceList.Version = 1;
875c2c66affSColin Finck     (*AllocatedResources)->List[0].PartialResourceList.Revision = 1;
876c2c66affSColin Finck     (*AllocatedResources)->List[0].PartialResourceList.Count = ResourceCount;
877c2c66affSColin Finck     Descriptor = (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
878c2c66affSColin Finck 
879c2c66affSColin Finck     /* Store configuration information */
880c2c66affSColin Finck     for (Address = 0; Address < PCI_TYPE0_ADDRESSES; Address++)
881c2c66affSColin Finck     {
882c2c66affSColin Finck         if (0 != PciConfig.u.type0.BaseAddresses[Address])
883c2c66affSColin Finck         {
884c2c66affSColin Finck             if (PCI_ADDRESS_MEMORY_SPACE ==
885c2c66affSColin Finck                 (PciConfig.u.type0.BaseAddresses[Address] & 0x1))
886c2c66affSColin Finck             {
887c2c66affSColin Finck                 Descriptor->Type = CmResourceTypeMemory;
888c2c66affSColin Finck                 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; /* FIXME I have no idea... */
889c2c66affSColin Finck                 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;             /* FIXME Just a guess */
890c2c66affSColin Finck                 Descriptor->u.Memory.Start.QuadPart = (PciConfig.u.type0.BaseAddresses[Address] & PCI_ADDRESS_MEMORY_ADDRESS_MASK);
891c2c66affSColin Finck                 Descriptor->u.Memory.Length = PciSize(Size[Address], PCI_ADDRESS_MEMORY_ADDRESS_MASK);
892c2c66affSColin Finck             }
893c2c66affSColin Finck             else if (PCI_ADDRESS_IO_SPACE ==
894c2c66affSColin Finck                 (PciConfig.u.type0.BaseAddresses[Address] & 0x1))
895c2c66affSColin Finck             {
896c2c66affSColin Finck                 Descriptor->Type = CmResourceTypePort;
897c2c66affSColin Finck                 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; /* FIXME I have no idea... */
898c2c66affSColin Finck                 Descriptor->Flags = CM_RESOURCE_PORT_IO;                       /* FIXME Just a guess */
899c2c66affSColin Finck                 Descriptor->u.Port.Start.QuadPart = PciConfig.u.type0.BaseAddresses[Address] &= PCI_ADDRESS_IO_ADDRESS_MASK;
900c2c66affSColin Finck                 Descriptor->u.Port.Length = PciSize(Size[Address], PCI_ADDRESS_IO_ADDRESS_MASK & 0xffff);
901c2c66affSColin Finck             }
902c2c66affSColin Finck             else
903c2c66affSColin Finck             {
904c2c66affSColin Finck                 ASSERT(FALSE);
905c2c66affSColin Finck                 return STATUS_UNSUCCESSFUL;
906c2c66affSColin Finck             }
907c2c66affSColin Finck             Descriptor++;
908c2c66affSColin Finck         }
909c2c66affSColin Finck     }
910c2c66affSColin Finck 
911c2c66affSColin Finck     if (0 != PciConfig.u.type0.InterruptPin &&
912c2c66affSColin Finck         0 != PciConfig.u.type0.InterruptLine &&
913c2c66affSColin Finck         0xFF != PciConfig.u.type0.InterruptLine)
914c2c66affSColin Finck     {
915c2c66affSColin Finck         Descriptor->Type = CmResourceTypeInterrupt;
916c2c66affSColin Finck         Descriptor->ShareDisposition = CmResourceShareShared;          /* FIXME Just a guess */
917c2c66affSColin Finck         Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;     /* FIXME Just a guess */
918c2c66affSColin Finck         Descriptor->u.Interrupt.Level = PciConfig.u.type0.InterruptLine;
919c2c66affSColin Finck         Descriptor->u.Interrupt.Vector = PciConfig.u.type0.InterruptLine;
920c2c66affSColin Finck         Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
921c2c66affSColin Finck 
922c2c66affSColin Finck         Descriptor++;
923c2c66affSColin Finck     }
924c2c66affSColin Finck 
925c2c66affSColin Finck     ASSERT(Descriptor == (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors + ResourceCount);
926c2c66affSColin Finck 
927c2c66affSColin Finck     /* FIXME: Should store the resources in the registry resource map */
928c2c66affSColin Finck 
929c2c66affSColin Finck     return Status;
930c2c66affSColin Finck }
931c2c66affSColin Finck 
932c2c66affSColin Finck ULONG
933c2c66affSColin Finck NTAPI
HaliPciInterfaceReadConfig(IN PBUS_HANDLER RootBusHandler,IN ULONG BusNumber,IN PCI_SLOT_NUMBER SlotNumber,IN PVOID Buffer,IN ULONG Offset,IN ULONG Length)934c2c66affSColin Finck HaliPciInterfaceReadConfig(IN PBUS_HANDLER RootBusHandler,
935c2c66affSColin Finck                            IN ULONG BusNumber,
936c2c66affSColin Finck                            IN PCI_SLOT_NUMBER SlotNumber,
937c2c66affSColin Finck                            IN PVOID Buffer,
938c2c66affSColin Finck                            IN ULONG Offset,
939c2c66affSColin Finck                            IN ULONG Length)
940c2c66affSColin Finck {
941c2c66affSColin Finck     BUS_HANDLER BusHandler;
942c2c66affSColin Finck 
943c2c66affSColin Finck     /* Setup fake PCI Bus handler */
944c2c66affSColin Finck     RtlCopyMemory(&BusHandler, &HalpFakePciBusHandler, sizeof(BUS_HANDLER));
945c2c66affSColin Finck     BusHandler.BusNumber = BusNumber;
946c2c66affSColin Finck 
947c2c66affSColin Finck     /* Read configuration data */
948c2c66affSColin Finck     HalpReadPCIConfig(&BusHandler, SlotNumber, Buffer, Offset, Length);
949c2c66affSColin Finck 
950c2c66affSColin Finck     /* Return length */
951c2c66affSColin Finck     return Length;
952c2c66affSColin Finck }
953c2c66affSColin Finck 
9545c7ce447SVictor Perevertkin CODE_SEG("INIT")
955c2c66affSColin Finck PPCI_REGISTRY_INFO_INTERNAL
956c2c66affSColin Finck NTAPI
HalpQueryPciRegistryInfo(VOID)957c2c66affSColin Finck HalpQueryPciRegistryInfo(VOID)
958c2c66affSColin Finck {
959c2c66affSColin Finck #ifndef _MINIHAL_
960c2c66affSColin Finck     WCHAR NameBuffer[8];
961c2c66affSColin Finck     OBJECT_ATTRIBUTES  ObjectAttributes;
962c2c66affSColin Finck     UNICODE_STRING KeyName, ConfigName, IdentName;
963c2c66affSColin Finck     HANDLE KeyHandle, BusKeyHandle, CardListHandle;
964c2c66affSColin Finck     NTSTATUS Status;
965c2c66affSColin Finck     UCHAR KeyBuffer[sizeof(CM_FULL_RESOURCE_DESCRIPTOR) + 100];
966c2c66affSColin Finck     PKEY_VALUE_FULL_INFORMATION ValueInfo = (PVOID)KeyBuffer;
967c2c66affSColin Finck     UCHAR PartialKeyBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
968c2c66affSColin Finck                            sizeof(PCI_CARD_DESCRIPTOR)];
969c2c66affSColin Finck     PKEY_VALUE_PARTIAL_INFORMATION PartialValueInfo = (PVOID)PartialKeyBuffer;
970c2c66affSColin Finck     KEY_FULL_INFORMATION KeyInformation;
971c2c66affSColin Finck     ULONG ResultLength;
972c2c66affSColin Finck     PWSTR Tag;
973c2c66affSColin Finck     ULONG i, ElementCount;
974c2c66affSColin Finck     PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
975c2c66affSColin Finck     PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
976c2c66affSColin Finck     PPCI_REGISTRY_INFO PciRegInfo;
977c2c66affSColin Finck     PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo;
978c2c66affSColin Finck     PPCI_CARD_DESCRIPTOR CardDescriptor;
979c2c66affSColin Finck 
980c2c66affSColin Finck     /* Setup the object attributes for the key */
981c2c66affSColin Finck     RtlInitUnicodeString(&KeyName,
982c2c66affSColin Finck                          L"\\Registry\\Machine\\Hardware\\Description\\"
983c2c66affSColin Finck                          L"System\\MultiFunctionAdapter");
984c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
985c2c66affSColin Finck                                &KeyName,
986c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
987c2c66affSColin Finck                                NULL,
988c2c66affSColin Finck                                NULL);
989c2c66affSColin Finck 
990c2c66affSColin Finck     /* Open the key */
991c2c66affSColin Finck     Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
992c2c66affSColin Finck     if (!NT_SUCCESS(Status)) return NULL;
993c2c66affSColin Finck 
994c2c66affSColin Finck     /* Setup the receiving string */
995c2c66affSColin Finck     KeyName.Buffer = NameBuffer;
996c2c66affSColin Finck     KeyName.MaximumLength = sizeof(NameBuffer);
997c2c66affSColin Finck 
998c2c66affSColin Finck     /* Setup the configuration and identifier key names */
999c2c66affSColin Finck     RtlInitUnicodeString(&ConfigName, L"Configuration Data");
1000c2c66affSColin Finck     RtlInitUnicodeString(&IdentName, L"Identifier");
1001c2c66affSColin Finck 
1002c2c66affSColin Finck     /* Keep looping for each ID */
1003c2c66affSColin Finck     for (i = 0; TRUE; i++)
1004c2c66affSColin Finck     {
1005c2c66affSColin Finck         /* Setup the key name */
1006c2c66affSColin Finck         RtlIntegerToUnicodeString(i, 10, &KeyName);
1007c2c66affSColin Finck         InitializeObjectAttributes(&ObjectAttributes,
1008c2c66affSColin Finck                                    &KeyName,
1009c2c66affSColin Finck                                    OBJ_CASE_INSENSITIVE,
1010c2c66affSColin Finck                                    KeyHandle,
1011c2c66affSColin Finck                                    NULL);
1012c2c66affSColin Finck 
1013c2c66affSColin Finck         /* Open it */
1014c2c66affSColin Finck         Status = ZwOpenKey(&BusKeyHandle, KEY_READ, &ObjectAttributes);
1015c2c66affSColin Finck         if (!NT_SUCCESS(Status))
1016c2c66affSColin Finck         {
1017c2c66affSColin Finck             /* None left, fail */
1018c2c66affSColin Finck             ZwClose(KeyHandle);
1019c2c66affSColin Finck             return NULL;
1020c2c66affSColin Finck         }
1021c2c66affSColin Finck 
1022c2c66affSColin Finck         /* Read the registry data */
1023c2c66affSColin Finck         Status = ZwQueryValueKey(BusKeyHandle,
1024c2c66affSColin Finck                                  &IdentName,
1025c2c66affSColin Finck                                  KeyValueFullInformation,
1026c2c66affSColin Finck                                  ValueInfo,
1027c2c66affSColin Finck                                  sizeof(KeyBuffer),
1028c2c66affSColin Finck                                  &ResultLength);
1029c2c66affSColin Finck         if (!NT_SUCCESS(Status))
1030c2c66affSColin Finck         {
1031c2c66affSColin Finck             /* Failed, try the next one */
1032c2c66affSColin Finck             ZwClose(BusKeyHandle);
1033c2c66affSColin Finck             continue;
1034c2c66affSColin Finck         }
1035c2c66affSColin Finck 
1036c2c66affSColin Finck         /* Get the PCI Tag and validate it */
1037c2c66affSColin Finck         Tag = (PWSTR)((ULONG_PTR)ValueInfo + ValueInfo->DataOffset);
1038c2c66affSColin Finck         if ((Tag[0] != L'P') ||
1039c2c66affSColin Finck             (Tag[1] != L'C') ||
1040c2c66affSColin Finck             (Tag[2] != L'I') ||
1041c2c66affSColin Finck             (Tag[3]))
1042c2c66affSColin Finck         {
1043c2c66affSColin Finck             /* Not a valid PCI entry, skip it */
1044c2c66affSColin Finck             ZwClose(BusKeyHandle);
1045c2c66affSColin Finck             continue;
1046c2c66affSColin Finck         }
1047c2c66affSColin Finck 
1048c2c66affSColin Finck         /* Now read our PCI structure */
1049c2c66affSColin Finck         Status = ZwQueryValueKey(BusKeyHandle,
1050c2c66affSColin Finck                                  &ConfigName,
1051c2c66affSColin Finck                                  KeyValueFullInformation,
1052c2c66affSColin Finck                                  ValueInfo,
1053c2c66affSColin Finck                                  sizeof(KeyBuffer),
1054c2c66affSColin Finck                                  &ResultLength);
1055c2c66affSColin Finck         ZwClose(BusKeyHandle);
1056c2c66affSColin Finck         if (!NT_SUCCESS(Status)) continue;
1057c2c66affSColin Finck 
1058c2c66affSColin Finck         /* We read it OK! Get the actual resource descriptors */
1059c2c66affSColin Finck         FullDescriptor  = (PCM_FULL_RESOURCE_DESCRIPTOR)
1060c2c66affSColin Finck                           ((ULONG_PTR)ValueInfo + ValueInfo->DataOffset);
1061c2c66affSColin Finck         PartialDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
1062c2c66affSColin Finck                             ((ULONG_PTR)FullDescriptor->
1063c2c66affSColin Finck                                         PartialResourceList.PartialDescriptors);
1064c2c66affSColin Finck 
1065c2c66affSColin Finck         /* Check if this is our PCI Registry Information */
1066c2c66affSColin Finck         if (PartialDescriptor->Type == CmResourceTypeDeviceSpecific)
1067c2c66affSColin Finck         {
1068c2c66affSColin Finck             /* It is, stop searching */
1069c2c66affSColin Finck             break;
1070c2c66affSColin Finck         }
1071c2c66affSColin Finck     }
1072c2c66affSColin Finck 
1073c2c66affSColin Finck     /* Close the key */
1074c2c66affSColin Finck     ZwClose(KeyHandle);
1075c2c66affSColin Finck 
1076c2c66affSColin Finck     /* Save the PCI information for later */
1077c2c66affSColin Finck     PciRegInfo = (PPCI_REGISTRY_INFO)(PartialDescriptor + 1);
1078c2c66affSColin Finck 
1079c2c66affSColin Finck     /* Assume no Card List entries */
1080c2c66affSColin Finck     ElementCount = 0;
1081c2c66affSColin Finck 
1082c2c66affSColin Finck     /* Set up for checking the PCI Card List key */
1083c2c66affSColin Finck     RtlInitUnicodeString(&KeyName,
1084c2c66affSColin Finck                          L"\\Registry\\Machine\\System\\CurrentControlSet\\"
1085c2c66affSColin Finck                          L"Control\\PnP\\PCI\\CardList");
1086c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
1087c2c66affSColin Finck                                &KeyName,
1088c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
1089c2c66affSColin Finck                                NULL,
1090c2c66affSColin Finck                                NULL);
1091c2c66affSColin Finck 
1092c2c66affSColin Finck     /* Attempt to open it */
1093c2c66affSColin Finck     Status = ZwOpenKey(&CardListHandle, KEY_READ, &ObjectAttributes);
1094c2c66affSColin Finck     if (NT_SUCCESS(Status))
1095c2c66affSColin Finck     {
1096c2c66affSColin Finck         /* It exists, so let's query it */
1097c2c66affSColin Finck         Status = ZwQueryKey(CardListHandle,
1098c2c66affSColin Finck                             KeyFullInformation,
1099c2c66affSColin Finck                             &KeyInformation,
1100c2c66affSColin Finck                             sizeof(KEY_FULL_INFORMATION),
1101c2c66affSColin Finck                             &ResultLength);
1102c2c66affSColin Finck         if (!NT_SUCCESS(Status))
1103c2c66affSColin Finck         {
1104c2c66affSColin Finck             /* Failed to query, so no info */
1105c2c66affSColin Finck             PciRegistryInfo = NULL;
1106c2c66affSColin Finck         }
1107c2c66affSColin Finck         else
1108c2c66affSColin Finck         {
1109c2c66affSColin Finck             /* Allocate the full structure */
1110c2c66affSColin Finck             PciRegistryInfo =
1111c2c66affSColin Finck                 ExAllocatePoolWithTag(NonPagedPool,
1112c2c66affSColin Finck                                       sizeof(PCI_REGISTRY_INFO_INTERNAL) +
1113c2c66affSColin Finck                                       (KeyInformation.Values *
1114c2c66affSColin Finck                                        sizeof(PCI_CARD_DESCRIPTOR)),
1115c2c66affSColin Finck                                        TAG_HAL);
1116c2c66affSColin Finck             if (PciRegistryInfo)
1117c2c66affSColin Finck             {
1118c2c66affSColin Finck                 /* Get the first card descriptor entry */
1119c2c66affSColin Finck                 CardDescriptor = (PPCI_CARD_DESCRIPTOR)(PciRegistryInfo + 1);
1120c2c66affSColin Finck 
1121c2c66affSColin Finck                 /* Loop all the values */
1122c2c66affSColin Finck                 for (i = 0; i < KeyInformation.Values; i++)
1123c2c66affSColin Finck                 {
1124c2c66affSColin Finck                     /* Attempt to get the value */
1125c2c66affSColin Finck                     Status = ZwEnumerateValueKey(CardListHandle,
1126c2c66affSColin Finck                                                  i,
1127c2c66affSColin Finck                                                  KeyValuePartialInformation,
1128c2c66affSColin Finck                                                  PartialValueInfo,
1129c2c66affSColin Finck                                                  sizeof(PartialKeyBuffer),
1130c2c66affSColin Finck                                                  &ResultLength);
1131c2c66affSColin Finck                     if (!NT_SUCCESS(Status))
1132c2c66affSColin Finck                     {
1133c2c66affSColin Finck                         /* Something went wrong, stop the search */
1134c2c66affSColin Finck                         break;
1135c2c66affSColin Finck                     }
1136c2c66affSColin Finck 
1137c2c66affSColin Finck                     /* Make sure it is correctly sized */
1138c2c66affSColin Finck                     if (PartialValueInfo->DataLength == sizeof(PCI_CARD_DESCRIPTOR))
1139c2c66affSColin Finck                     {
1140c2c66affSColin Finck                         /* Sure is, copy it over */
1141c2c66affSColin Finck                         *CardDescriptor = *(PPCI_CARD_DESCRIPTOR)
1142c2c66affSColin Finck                                            PartialValueInfo->Data;
1143c2c66affSColin Finck 
1144c2c66affSColin Finck                         /* One more Card List entry */
1145c2c66affSColin Finck                         ElementCount++;
1146c2c66affSColin Finck 
1147c2c66affSColin Finck                         /* Move to the next descriptor */
1148c2c66affSColin Finck                         CardDescriptor = (CardDescriptor + 1);
1149c2c66affSColin Finck                     }
1150c2c66affSColin Finck                 }
1151c2c66affSColin Finck             }
1152c2c66affSColin Finck         }
1153c2c66affSColin Finck 
1154c2c66affSColin Finck         /* Close the Card List key */
1155c2c66affSColin Finck         ZwClose(CardListHandle);
1156c2c66affSColin Finck     }
1157c2c66affSColin Finck     else
1158c2c66affSColin Finck     {
1159c2c66affSColin Finck        /* No key, no Card List */
1160c2c66affSColin Finck        PciRegistryInfo = NULL;
1161c2c66affSColin Finck     }
1162c2c66affSColin Finck 
1163c2c66affSColin Finck     /* Check if we failed to get the full structure */
1164c2c66affSColin Finck     if (!PciRegistryInfo)
1165c2c66affSColin Finck     {
1166c2c66affSColin Finck         /* Just allocate the basic structure then */
1167c2c66affSColin Finck         PciRegistryInfo = ExAllocatePoolWithTag(NonPagedPool,
1168c2c66affSColin Finck                                                 sizeof(PCI_REGISTRY_INFO_INTERNAL),
1169c2c66affSColin Finck                                                 TAG_HAL);
1170c2c66affSColin Finck         if (!PciRegistryInfo) return NULL;
1171c2c66affSColin Finck     }
1172c2c66affSColin Finck 
1173c2c66affSColin Finck     /* Save the info we got */
1174c2c66affSColin Finck     PciRegistryInfo->MajorRevision = PciRegInfo->MajorRevision;
1175c2c66affSColin Finck     PciRegistryInfo->MinorRevision = PciRegInfo->MinorRevision;
1176c2c66affSColin Finck     PciRegistryInfo->NoBuses = PciRegInfo->NoBuses;
1177c2c66affSColin Finck     PciRegistryInfo->HardwareMechanism = PciRegInfo->HardwareMechanism;
1178c2c66affSColin Finck     PciRegistryInfo->ElementCount = ElementCount;
1179c2c66affSColin Finck 
1180c2c66affSColin Finck     /* Return it */
1181c2c66affSColin Finck     return PciRegistryInfo;
1182c2c66affSColin Finck #else
1183c2c66affSColin Finck     return NULL;
1184c2c66affSColin Finck #endif
1185c2c66affSColin Finck }
1186c2c66affSColin Finck 
11875c7ce447SVictor Perevertkin CODE_SEG("INIT")
1188c2c66affSColin Finck VOID
1189c2c66affSColin Finck NTAPI
HalpInitializePciStubs(VOID)1190c2c66affSColin Finck HalpInitializePciStubs(VOID)
1191c2c66affSColin Finck {
1192c2c66affSColin Finck     PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo;
1193c2c66affSColin Finck     UCHAR PciType;
1194c2c66affSColin Finck     PPCIPBUSDATA BusData = (PPCIPBUSDATA)HalpFakePciBusHandler.BusData;
1195c2c66affSColin Finck     ULONG i;
1196c2c66affSColin Finck     PCI_SLOT_NUMBER j;
1197c2c66affSColin Finck     ULONG VendorId = 0;
1198c2c66affSColin Finck     ULONG MaxPciBusNumber;
1199c2c66affSColin Finck 
1200c2c66affSColin Finck     /* Query registry information */
1201c2c66affSColin Finck     PciRegistryInfo = HalpQueryPciRegistryInfo();
1202c2c66affSColin Finck     if (!PciRegistryInfo)
1203c2c66affSColin Finck     {
1204c2c66affSColin Finck         /* Assume type 1 */
1205c2c66affSColin Finck         PciType = 1;
1206c2c66affSColin Finck 
1207c2c66affSColin Finck         /* Force a manual bus scan later */
1208c2c66affSColin Finck         MaxPciBusNumber = MAXULONG;
1209c2c66affSColin Finck     }
1210c2c66affSColin Finck     else
1211c2c66affSColin Finck     {
1212c2c66affSColin Finck         /* Get the PCI type */
1213c2c66affSColin Finck         PciType = PciRegistryInfo->HardwareMechanism & 0xF;
1214c2c66affSColin Finck 
1215c2c66affSColin Finck         /* Get MaxPciBusNumber and make it 0-based */
1216c2c66affSColin Finck         MaxPciBusNumber = PciRegistryInfo->NoBuses - 1;
1217c2c66affSColin Finck 
1218c2c66affSColin Finck         /* Free the info structure */
1219c2c66affSColin Finck         ExFreePoolWithTag(PciRegistryInfo, TAG_HAL);
1220c2c66affSColin Finck     }
1221c2c66affSColin Finck 
1222c2c66affSColin Finck     /* Initialize the PCI lock */
1223c2c66affSColin Finck     KeInitializeSpinLock(&HalpPCIConfigLock);
1224c2c66affSColin Finck 
1225c2c66affSColin Finck     /* Check the type of PCI bus */
1226c2c66affSColin Finck     switch (PciType)
1227c2c66affSColin Finck     {
1228c2c66affSColin Finck         /* Type 1 PCI Bus */
1229c2c66affSColin Finck         case 1:
1230c2c66affSColin Finck 
1231c2c66affSColin Finck             /* Copy the Type 1 handler data */
1232c2c66affSColin Finck             RtlCopyMemory(&PCIConfigHandler,
1233c2c66affSColin Finck                           &PCIConfigHandlerType1,
1234c2c66affSColin Finck                           sizeof(PCIConfigHandler));
1235c2c66affSColin Finck 
1236c2c66affSColin Finck             /* Set correct I/O Ports */
1237c2c66affSColin Finck             BusData->Config.Type1.Address = PCI_TYPE1_ADDRESS_PORT;
1238c2c66affSColin Finck             BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT;
1239c2c66affSColin Finck             break;
1240c2c66affSColin Finck 
1241c2c66affSColin Finck         /* Type 2 PCI Bus */
1242c2c66affSColin Finck         case 2:
1243c2c66affSColin Finck 
1244c2c66affSColin Finck             /* Copy the Type 2 handler data */
1245c2c66affSColin Finck             RtlCopyMemory(&PCIConfigHandler,
1246c2c66affSColin Finck                           &PCIConfigHandlerType2,
1247c2c66affSColin Finck                           sizeof (PCIConfigHandler));
1248c2c66affSColin Finck 
1249c2c66affSColin Finck             /* Set correct I/O Ports */
1250c2c66affSColin Finck             BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT;
1251c2c66affSColin Finck             BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT;
1252c2c66affSColin Finck             BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE;
1253c2c66affSColin Finck 
1254c2c66affSColin Finck             /* Only 16 devices supported, not 32 */
1255c2c66affSColin Finck             BusData->MaxDevice = 16;
1256c2c66affSColin Finck             break;
1257c2c66affSColin Finck 
1258c2c66affSColin Finck         default:
1259c2c66affSColin Finck 
1260c2c66affSColin Finck             /* Invalid type */
1261c2c66affSColin Finck             DbgPrint("HAL: Unknown PCI type\n");
1262c2c66affSColin Finck     }
1263c2c66affSColin Finck 
1264c2c66affSColin Finck     /* Run a forced bus scan if needed */
1265c2c66affSColin Finck     if (MaxPciBusNumber == MAXULONG)
1266c2c66affSColin Finck     {
1267c2c66affSColin Finck         /* Initialize the max bus number to 0xFF */
1268c2c66affSColin Finck         HalpMaxPciBus = 0xFF;
1269c2c66affSColin Finck 
1270c2c66affSColin Finck         /* Initialize the counter */
1271c2c66affSColin Finck         MaxPciBusNumber = 0;
1272c2c66affSColin Finck 
1273c2c66affSColin Finck         /* Loop all possible buses */
1274c2c66affSColin Finck         for (i = 0; i < HalpMaxPciBus; i++)
1275c2c66affSColin Finck         {
1276c2c66affSColin Finck             /* Loop all devices */
1277c2c66affSColin Finck             for (j.u.AsULONG = 0; j.u.AsULONG < BusData->MaxDevice; j.u.AsULONG++)
1278c2c66affSColin Finck             {
1279c2c66affSColin Finck                 /* Query the interface */
1280c2c66affSColin Finck                 if (HaliPciInterfaceReadConfig(NULL,
1281c2c66affSColin Finck                                                i,
1282c2c66affSColin Finck                                                j,
1283c2c66affSColin Finck                                                &VendorId,
1284c2c66affSColin Finck                                                0,
1285c2c66affSColin Finck                                                sizeof(ULONG)))
1286c2c66affSColin Finck                 {
1287c2c66affSColin Finck                     /* Validate the vendor ID */
1288c2c66affSColin Finck                     if ((VendorId & 0xFFFF) != PCI_INVALID_VENDORID)
1289c2c66affSColin Finck                     {
1290c2c66affSColin Finck                         /* Set this as the maximum ID */
1291c2c66affSColin Finck                         MaxPciBusNumber = i;
1292c2c66affSColin Finck                         break;
1293c2c66affSColin Finck                     }
1294c2c66affSColin Finck                 }
1295c2c66affSColin Finck             }
1296c2c66affSColin Finck         }
1297c2c66affSColin Finck     }
1298c2c66affSColin Finck 
1299c2c66affSColin Finck     /* Set the real max bus number */
1300c2c66affSColin Finck     HalpMaxPciBus = MaxPciBusNumber;
1301c2c66affSColin Finck 
1302c2c66affSColin Finck     /* We're done */
1303c2c66affSColin Finck     HalpPCIConfigInitialized = TRUE;
1304c2c66affSColin Finck }
1305c2c66affSColin Finck 
1306c2c66affSColin Finck /* EOF */
1307c2c66affSColin Finck 
1308