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