3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/hal/x86/pci.c
6 * PURPOSE: Interfaces to the PCI bus
7 * PROGRAMMER: David Welch (welch@mcmail.com)
8 * Eric Kohl (ekohl@rz-online.de)
11 * 17/08/2000: Added preliminary pci bus scanner
12 * 13/06/2001: Implemented access to pci configuration space
16 * NOTES: Sections copied from the Linux pci support
19 /* INCLUDES *****************************************************************/
21 #include <ddk/ntddk.h>
25 #include <internal/debug.h>
28 /* MACROS ******************************************************************/
30 /* access type 1 macros */
31 #define PCI_FUNC(devfn) \
33 #define CONFIG_CMD(bus, device_fn, where) \
34 (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))
36 /* access type 2 macros */
37 #define IOADDR(devfn, where) \
38 ((0xC000 | ((devfn & 0x78) << 5)) + where)
40 (((devfn & 7) << 1) | 0xf0)
43 #define PCIBIOS_SUCCESSFUL 0x00
44 #define PCIBIOS_DEVICE_NOT_FOUND 0x86
45 #define PCIBIOS_BAD_REGISTER_NUMBER 0x87
48 /* GLOBALS ******************************************************************/
50 static ULONG BusConfigType = 0; /* undetermined config type */
53 /* FUNCTIONS ****************************************************************/
56 ReadPciConfigUchar(UCHAR Bus,
61 switch (BusConfigType)
64 WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
65 *Value = READ_PORT_UCHAR((PUCHAR)0xCFC + (Offset & 3));
66 return STATUS_SUCCESS;
69 WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
70 WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
71 *Value = READ_PORT_UCHAR((PUCHAR)(IOADDR(Slot, Offset)));
72 WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
73 return STATUS_SUCCESS;
75 return STATUS_UNSUCCESSFUL;
80 ReadPciConfigUshort(UCHAR Bus,
85 if ((Offset & 1) != 0)
87 return PCIBIOS_BAD_REGISTER_NUMBER;
90 switch (BusConfigType)
93 WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
94 *Value = READ_PORT_USHORT((PUSHORT)0xCFC + (Offset & 1));
95 return STATUS_SUCCESS;
98 WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
99 WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
100 *Value = READ_PORT_USHORT((PUSHORT)(IOADDR(Slot, Offset)));
101 WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
102 return STATUS_SUCCESS;
104 return STATUS_UNSUCCESSFUL;
109 ReadPciConfigUlong(UCHAR Bus,
114 if ((Offset & 3) != 0)
116 return PCIBIOS_BAD_REGISTER_NUMBER;
119 switch (BusConfigType)
122 WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
123 *Value = READ_PORT_ULONG((PULONG)0xCFC);
124 return STATUS_SUCCESS;
127 WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
128 WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
129 *Value = READ_PORT_ULONG((PULONG)(IOADDR(Slot, Offset)));
130 WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
131 return STATUS_SUCCESS;
133 return STATUS_UNSUCCESSFUL;
138 WritePciConfigUchar(UCHAR Bus,
143 switch (BusConfigType)
146 WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
147 WRITE_PORT_UCHAR((PUCHAR)0xCFC + (Offset&3), Value);
148 return STATUS_SUCCESS;
151 WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
152 WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
153 WRITE_PORT_UCHAR((PUCHAR)(IOADDR(Slot,Offset)), Value);
154 WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
155 return STATUS_SUCCESS;
157 return STATUS_UNSUCCESSFUL;
162 WritePciConfigUshort(UCHAR Bus,
167 if ((Offset & 1) != 0)
169 return PCIBIOS_BAD_REGISTER_NUMBER;
172 switch (BusConfigType)
175 WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
176 WRITE_PORT_USHORT((PUSHORT)0xCFC + (Offset & 1), Value);
177 return STATUS_SUCCESS;
180 WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
181 WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
182 WRITE_PORT_USHORT((PUSHORT)(IOADDR(Slot, Offset)), Value);
183 WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
184 return STATUS_SUCCESS;
186 return STATUS_UNSUCCESSFUL;
191 WritePciConfigUlong(UCHAR Bus,
196 if ((Offset & 3) != 0)
198 return PCIBIOS_BAD_REGISTER_NUMBER;
201 switch (BusConfigType)
204 WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
205 WRITE_PORT_ULONG((PULONG)0xCFC, Value);
206 return STATUS_SUCCESS;
209 WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
210 WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
211 WRITE_PORT_ULONG((PULONG)(IOADDR(Slot, Offset)), Value);
212 WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
213 return STATUS_SUCCESS;
215 return STATUS_UNSUCCESSFUL;
220 HalpGetPciData(PBUS_HANDLER BusHandler,
228 ULONG Address = Offset;
233 DPRINT("HalpGetPciData() called.\n");
234 DPRINT(" BusNumber %lu\n", BusNumber);
235 DPRINT(" SlotNumber %lu\n", SlotNumber);
236 DPRINT(" Offset 0x%lx\n", Offset);
237 DPRINT(" Length 0x%lx\n", Length);
239 if ((Length == 0) || (BusConfigType == 0))
242 /* 0E=PCI_HEADER_TYPE */
243 ReadPciConfigUchar(BusNumber,
247 if (((HeaderType & 0x80) == 0) && ((SlotNumber & 0x07) != 0))
250 ReadPciConfigUlong(BusNumber,
254 /* some broken boards return 0 if a slot is empty: */
255 if (Vendor == 0xFFFFFFFF || Vendor == 0)
258 if ((Address & 1) && (Len >= 1))
260 ReadPciConfigUchar(BusNumber,
269 if ((Address & 2) && (Len >= 2))
271 ReadPciConfigUshort(BusNumber,
282 ReadPciConfigUlong(BusNumber,
293 ReadPciConfigUshort(BusNumber,
304 ReadPciConfigUchar(BusNumber,
318 HalpSetPciData(PBUS_HANDLER BusHandler,
326 ULONG Address = Offset;
331 DPRINT("HalpSetPciData() called.\n");
332 DPRINT(" BusNumber %lu\n", BusNumber);
333 DPRINT(" SlotNumber %lu\n", SlotNumber);
334 DPRINT(" Offset 0x%lx\n", Offset);
335 DPRINT(" Length 0x%lx\n", Length);
337 if ((Length == 0) || (BusConfigType == 0))
340 /* 0E=PCI_HEADER_TYPE */
341 ReadPciConfigUchar(BusNumber,
345 if (((HeaderType & 0x80) == 0) && ((SlotNumber & 0x07) != 0))
348 ReadPciConfigUlong(BusNumber,
352 /* some broken boards return 0 if a slot is empty: */
353 if (Vendor == 0xFFFFFFFF || Vendor == 0)
356 if ((Address & 1) && (Len >= 1))
358 WritePciConfigUchar(BusNumber,
367 if ((Address & 2) && (Len >= 2))
369 WritePciConfigUshort(BusNumber,
380 WritePciConfigUlong(BusNumber,
391 WritePciConfigUshort(BusNumber,
402 WritePciConfigUchar(BusNumber,
416 GetBusConfigType(VOID)
420 DPRINT("GetBusConfigType() called\n");
422 DPRINT("Checking configuration type 1:");
423 WRITE_PORT_UCHAR((PUCHAR)0xCFB, 0x01);
424 Value = READ_PORT_ULONG((PULONG)0xCF8);
425 WRITE_PORT_ULONG((PULONG)0xCF8, 0x80000000);
426 if (READ_PORT_ULONG((PULONG)0xCF8) == 0x80000000)
428 WRITE_PORT_ULONG((PULONG)0xCF8, Value);
429 DPRINT(" Success!\n");
432 WRITE_PORT_ULONG((PULONG)0xCF8, Value);
433 DPRINT(" Unsuccessful!\n");
435 DPRINT("Checking configuration type 2:");
436 WRITE_PORT_UCHAR((PUCHAR)0xCFB, 0x00);
437 WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0x00);
438 WRITE_PORT_UCHAR((PUCHAR)0xCFA, 0x00);
439 if (READ_PORT_UCHAR((PUCHAR)0xCF8) == 0x00 &&
440 READ_PORT_UCHAR((PUCHAR)0xCFB) == 0x00)
442 DPRINT(" Success!\n");
445 DPRINT(" Unsuccessful!\n");
447 DPRINT("No pci bus found!\n");
453 HalpGetPciInterruptVector(PVOID BusHandler,
455 ULONG BusInterruptLevel,
456 ULONG BusInterruptVector,
460 *Irql = HIGH_LEVEL - BusInterruptVector;
461 *Affinity = 0xFFFFFFFF;
462 return BusInterruptVector;
469 PBUS_HANDLER BusHandler;
471 DPRINT("HalpInitPciBus() called.\n");
473 BusConfigType = GetBusConfigType();
474 if (BusConfigType == 0)
477 DPRINT("Bus configuration %lu used\n", BusConfigType);
479 /* pci bus (bus 0) handler */
480 BusHandler = HalpAllocateBusHandler(PCIBus,
483 BusHandler->GetBusData = (pGetSetBusData)HalpGetPciData;
484 BusHandler->SetBusData = (pGetSetBusData)HalpSetPciData;
485 BusHandler->GetInterruptVector =
486 (pGetInterruptVector)HalpGetPciInterruptVector;
487 // BusHandler->AdjustResourceList =
488 // (pGetSetBusData)HalpAdjustPciResourceList;
489 // BusHandler->AssignSlotResources =
490 // (pGetSetBusData)HalpAssignPciSlotResources;
493 /* agp bus (bus 1) handler */
494 BusHandler = HalpAllocateBusHandler(PCIBus,
497 BusHandler->GetBusData = (pGetSetBusData)HalpGetPciData;
498 BusHandler->SetBusData = (pGetSetBusData)HalpSetPciData;
499 BusHandler->GetInterruptVector =
500 (pGetInterruptVector)HalpGetPciInterruptVector;
501 // BusHandler->AdjustResourceList =
502 // (pGetSetBusData)HalpAdjustPciResourceList;
503 // BusHandler->AssignSlotResources =
504 // (pGetSetBusData)HalpAssignPciSlotResources;
506 DPRINT("HalpInitPciBus() finished.\n");