1 /* $Id: pci.c,v 1.3 2002/09/07 15:12:10 chorns Exp $
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 *****************************************************************/
24 #include <internal/debug.h>
27 /* MACROS ******************************************************************/
29 /* access type 1 macros */
30 #define PCI_FUNC(devfn) \
32 #define CONFIG_CMD(bus, device_fn, where) \
33 (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))
35 /* access type 2 macros */
36 #define IOADDR(devfn, where) \
37 ((0xC000 | ((devfn & 0x78) << 5)) + where)
39 (((devfn & 7) << 1) | 0xf0)
42 #define PCIBIOS_SUCCESSFUL 0x00
43 #define PCIBIOS_DEVICE_NOT_FOUND 0x86
44 #define PCIBIOS_BAD_REGISTER_NUMBER 0x87
47 /* GLOBALS ******************************************************************/
49 static ULONG BusConfigType
= 0; /* undetermined config type */
52 /* FUNCTIONS ****************************************************************/
55 ReadPciConfigUchar(UCHAR Bus
,
60 switch (BusConfigType
)
63 WRITE_PORT_ULONG((PULONG
)0xCF8, CONFIG_CMD(Bus
, Slot
, Offset
));
64 *Value
= READ_PORT_UCHAR((PUCHAR
)0xCFC + (Offset
& 3));
65 return STATUS_SUCCESS
;
68 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, FUNC(Slot
));
69 WRITE_PORT_UCHAR((PUCHAR
)0xCFA, Bus
);
70 *Value
= READ_PORT_UCHAR((PUCHAR
)(IOADDR(Slot
, Offset
)));
71 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, 0);
72 return STATUS_SUCCESS
;
74 return STATUS_UNSUCCESSFUL
;
79 ReadPciConfigUshort(UCHAR Bus
,
84 if ((Offset
& 1) != 0)
86 return PCIBIOS_BAD_REGISTER_NUMBER
;
89 switch (BusConfigType
)
92 WRITE_PORT_ULONG((PULONG
)0xCF8, CONFIG_CMD(Bus
, Slot
, Offset
));
93 *Value
= READ_PORT_USHORT((PUSHORT
)0xCFC + (Offset
& 1));
94 return STATUS_SUCCESS
;
97 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, FUNC(Slot
));
98 WRITE_PORT_UCHAR((PUCHAR
)0xCFA, Bus
);
99 *Value
= READ_PORT_USHORT((PUSHORT
)(IOADDR(Slot
, Offset
)));
100 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, 0);
101 return STATUS_SUCCESS
;
103 return STATUS_UNSUCCESSFUL
;
108 ReadPciConfigUlong(UCHAR Bus
,
113 if ((Offset
& 3) != 0)
115 return PCIBIOS_BAD_REGISTER_NUMBER
;
118 switch (BusConfigType
)
121 WRITE_PORT_ULONG((PULONG
)0xCF8, CONFIG_CMD(Bus
, Slot
, Offset
));
122 *Value
= READ_PORT_ULONG((PULONG
)0xCFC);
123 return STATUS_SUCCESS
;
126 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, FUNC(Slot
));
127 WRITE_PORT_UCHAR((PUCHAR
)0xCFA, Bus
);
128 *Value
= READ_PORT_ULONG((PULONG
)(IOADDR(Slot
, Offset
)));
129 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, 0);
130 return STATUS_SUCCESS
;
132 return STATUS_UNSUCCESSFUL
;
137 WritePciConfigUchar(UCHAR Bus
,
142 switch (BusConfigType
)
145 WRITE_PORT_ULONG((PULONG
)0xCF8, CONFIG_CMD(Bus
, Slot
, Offset
));
146 WRITE_PORT_UCHAR((PUCHAR
)0xCFC + (Offset
&3), Value
);
147 return STATUS_SUCCESS
;
150 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, FUNC(Slot
));
151 WRITE_PORT_UCHAR((PUCHAR
)0xCFA, Bus
);
152 WRITE_PORT_UCHAR((PUCHAR
)(IOADDR(Slot
,Offset
)), Value
);
153 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, 0);
154 return STATUS_SUCCESS
;
156 return STATUS_UNSUCCESSFUL
;
161 WritePciConfigUshort(UCHAR Bus
,
166 if ((Offset
& 1) != 0)
168 return PCIBIOS_BAD_REGISTER_NUMBER
;
171 switch (BusConfigType
)
174 WRITE_PORT_ULONG((PULONG
)0xCF8, CONFIG_CMD(Bus
, Slot
, Offset
));
175 WRITE_PORT_USHORT((PUSHORT
)0xCFC + (Offset
& 1), Value
);
176 return STATUS_SUCCESS
;
179 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, FUNC(Slot
));
180 WRITE_PORT_UCHAR((PUCHAR
)0xCFA, Bus
);
181 WRITE_PORT_USHORT((PUSHORT
)(IOADDR(Slot
, Offset
)), Value
);
182 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, 0);
183 return STATUS_SUCCESS
;
185 return STATUS_UNSUCCESSFUL
;
190 WritePciConfigUlong(UCHAR Bus
,
195 if ((Offset
& 3) != 0)
197 return PCIBIOS_BAD_REGISTER_NUMBER
;
200 switch (BusConfigType
)
203 WRITE_PORT_ULONG((PULONG
)0xCF8, CONFIG_CMD(Bus
, Slot
, Offset
));
204 WRITE_PORT_ULONG((PULONG
)0xCFC, Value
);
205 return STATUS_SUCCESS
;
208 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, FUNC(Slot
));
209 WRITE_PORT_UCHAR((PUCHAR
)0xCFA, Bus
);
210 WRITE_PORT_ULONG((PULONG
)(IOADDR(Slot
, Offset
)), Value
);
211 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, 0);
212 return STATUS_SUCCESS
;
214 return STATUS_UNSUCCESSFUL
;
219 HalpGetPciData(PBUS_HANDLER BusHandler
,
227 ULONG Address
= Offset
;
232 DPRINT("HalpGetPciData() called.\n");
233 DPRINT(" BusNumber %lu\n", BusNumber
);
234 DPRINT(" SlotNumber %lu\n", SlotNumber
);
235 DPRINT(" Offset 0x%lx\n", Offset
);
236 DPRINT(" Length 0x%lx\n", Length
);
238 if ((Length
== 0) || (BusConfigType
== 0))
241 /* 0E=PCI_HEADER_TYPE */
242 ReadPciConfigUchar(BusNumber
,
246 if (((HeaderType
& 0x80) == 0) && ((SlotNumber
& 0x07) != 0))
249 ReadPciConfigUlong(BusNumber
,
253 /* some broken boards return 0 if a slot is empty: */
254 if (Vendor
== 0xFFFFFFFF || Vendor
== 0)
257 if ((Address
& 1) && (Len
>= 1))
259 ReadPciConfigUchar(BusNumber
,
268 if ((Address
& 2) && (Len
>= 2))
270 ReadPciConfigUshort(BusNumber
,
281 ReadPciConfigUlong(BusNumber
,
292 ReadPciConfigUshort(BusNumber
,
303 ReadPciConfigUchar(BusNumber
,
317 HalpSetPciData(PBUS_HANDLER BusHandler
,
325 ULONG Address
= Offset
;
330 DPRINT("HalpSetPciData() called.\n");
331 DPRINT(" BusNumber %lu\n", BusNumber
);
332 DPRINT(" SlotNumber %lu\n", SlotNumber
);
333 DPRINT(" Offset 0x%lx\n", Offset
);
334 DPRINT(" Length 0x%lx\n", Length
);
336 if ((Length
== 0) || (BusConfigType
== 0))
339 /* 0E=PCI_HEADER_TYPE */
340 ReadPciConfigUchar(BusNumber
,
344 if (((HeaderType
& 0x80) == 0) && ((SlotNumber
& 0x07) != 0))
347 ReadPciConfigUlong(BusNumber
,
351 /* some broken boards return 0 if a slot is empty: */
352 if (Vendor
== 0xFFFFFFFF || Vendor
== 0)
355 if ((Address
& 1) && (Len
>= 1))
357 WritePciConfigUchar(BusNumber
,
366 if ((Address
& 2) && (Len
>= 2))
368 WritePciConfigUshort(BusNumber
,
379 WritePciConfigUlong(BusNumber
,
390 WritePciConfigUshort(BusNumber
,
401 WritePciConfigUchar(BusNumber
,
415 GetBusConfigType(VOID
)
419 DPRINT("GetBusConfigType() called\n");
421 DPRINT("Checking configuration type 1:");
422 WRITE_PORT_UCHAR((PUCHAR
)0xCFB, 0x01);
423 Value
= READ_PORT_ULONG((PULONG
)0xCF8);
424 WRITE_PORT_ULONG((PULONG
)0xCF8, 0x80000000);
425 if (READ_PORT_ULONG((PULONG
)0xCF8) == 0x80000000)
427 WRITE_PORT_ULONG((PULONG
)0xCF8, Value
);
428 DPRINT(" Success!\n");
431 WRITE_PORT_ULONG((PULONG
)0xCF8, Value
);
432 DPRINT(" Unsuccessful!\n");
434 DPRINT("Checking configuration type 2:");
435 WRITE_PORT_UCHAR((PUCHAR
)0xCFB, 0x00);
436 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, 0x00);
437 WRITE_PORT_UCHAR((PUCHAR
)0xCFA, 0x00);
438 if (READ_PORT_UCHAR((PUCHAR
)0xCF8) == 0x00 &&
439 READ_PORT_UCHAR((PUCHAR
)0xCFB) == 0x00)
441 DPRINT(" Success!\n");
444 DPRINT(" Unsuccessful!\n");
446 DPRINT("No pci bus found!\n");
452 HalpGetPciInterruptVector(PVOID BusHandler
,
454 ULONG BusInterruptLevel
,
455 ULONG BusInterruptVector
,
459 *Irql
= HIGH_LEVEL
- BusInterruptVector
;
460 *Affinity
= 0xFFFFFFFF;
461 return BusInterruptVector
;
468 PBUS_HANDLER BusHandler
;
470 DPRINT("HalpInitPciBus() called.\n");
472 BusConfigType
= GetBusConfigType();
473 if (BusConfigType
== 0)
476 DPRINT("Bus configuration %lu used\n", BusConfigType
);
478 /* pci bus (bus 0) handler */
479 BusHandler
= HalpAllocateBusHandler(PCIBus
,
482 BusHandler
->GetBusData
= (pGetSetBusData
)HalpGetPciData
;
483 BusHandler
->SetBusData
= (pGetSetBusData
)HalpSetPciData
;
484 BusHandler
->GetInterruptVector
=
485 (pGetInterruptVector
)HalpGetPciInterruptVector
;
486 // BusHandler->AdjustResourceList =
487 // (pGetSetBusData)HalpAdjustPciResourceList;
488 // BusHandler->AssignSlotResources =
489 // (pGetSetBusData)HalpAssignPciSlotResources;
492 /* agp bus (bus 1) handler */
493 BusHandler
= HalpAllocateBusHandler(PCIBus
,
496 BusHandler
->GetBusData
= (pGetSetBusData
)HalpGetPciData
;
497 BusHandler
->SetBusData
= (pGetSetBusData
)HalpSetPciData
;
498 BusHandler
->GetInterruptVector
=
499 (pGetInterruptVector
)HalpGetPciInterruptVector
;
500 // BusHandler->AdjustResourceList =
501 // (pGetSetBusData)HalpAdjustPciResourceList;
502 // BusHandler->AssignSlotResources =
503 // (pGetSetBusData)HalpAssignPciSlotResources;
505 DPRINT("HalpInitPciBus() finished.\n");