1 /* $Id: pci.c,v 1.2 2002/05/05 14:57:45 chorns Exp $
3 * PROJECT: ReactOS PCI Bus driver
5 * PURPOSE: Driver entry
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * 10-09-2001 CSH Created
18 // Make the initialization routines discardable, so that they
21 #pragma alloc_text(init, DriverEntry)
23 #endif /* ALLOC_PRAGMA */
25 /*** PUBLIC ******************************************************************/
27 PCI_BUS_TYPE PciBusConfigType
= pbtUnknown
;
30 /*** PRIVATE *****************************************************************/
33 PciReadConfigUchar(UCHAR Bus
,
38 switch (PciBusConfigType
)
41 WRITE_PORT_ULONG((PULONG
)0xCF8, CONFIG_CMD(Bus
, Slot
, Offset
));
42 *Value
= READ_PORT_UCHAR((PUCHAR
)0xCFC + (Offset
& 3));
43 return STATUS_SUCCESS
;
46 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, FUNC(Slot
));
47 WRITE_PORT_UCHAR((PUCHAR
)0xCFA, Bus
);
48 *Value
= READ_PORT_UCHAR((PUCHAR
)(IOADDR(Slot
, Offset
)));
49 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, 0);
50 return STATUS_SUCCESS
;
52 return STATUS_UNSUCCESSFUL
;
57 PciReadConfigUshort(UCHAR Bus
,
62 if ((Offset
& 1) != 0)
64 return STATUS_INVALID_PARAMETER
;
67 switch (PciBusConfigType
)
70 WRITE_PORT_ULONG((PULONG
)0xCF8, CONFIG_CMD(Bus
, Slot
, Offset
));
71 *Value
= READ_PORT_USHORT((PUSHORT
)0xCFC + (Offset
& 1));
72 return STATUS_SUCCESS
;
75 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, FUNC(Slot
));
76 WRITE_PORT_UCHAR((PUCHAR
)0xCFA, Bus
);
77 *Value
= READ_PORT_USHORT((PUSHORT
)(IOADDR(Slot
, Offset
)));
78 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, 0);
79 return STATUS_SUCCESS
;
81 return STATUS_UNSUCCESSFUL
;
86 PciReadConfigUlong(UCHAR Bus
,
91 if ((Offset
& 3) != 0)
93 return STATUS_INVALID_PARAMETER
;
96 switch (PciBusConfigType
)
99 WRITE_PORT_ULONG((PULONG
)0xCF8, CONFIG_CMD(Bus
, Slot
, Offset
));
100 *Value
= READ_PORT_ULONG((PULONG
)0xCFC);
101 return STATUS_SUCCESS
;
104 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, FUNC(Slot
));
105 WRITE_PORT_UCHAR((PUCHAR
)0xCFA, Bus
);
106 *Value
= READ_PORT_ULONG((PULONG
)(IOADDR(Slot
, Offset
)));
107 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, 0);
108 return STATUS_SUCCESS
;
110 return STATUS_UNSUCCESSFUL
;
115 PciWriteConfigUchar(UCHAR Bus
,
120 switch (PciBusConfigType
)
123 WRITE_PORT_ULONG((PULONG
)0xCF8, CONFIG_CMD(Bus
, Slot
, Offset
));
124 WRITE_PORT_UCHAR((PUCHAR
)0xCFC + (Offset
&3), Value
);
125 return STATUS_SUCCESS
;
128 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, FUNC(Slot
));
129 WRITE_PORT_UCHAR((PUCHAR
)0xCFA, Bus
);
130 WRITE_PORT_UCHAR((PUCHAR
)(IOADDR(Slot
,Offset
)), Value
);
131 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, 0);
132 return STATUS_SUCCESS
;
134 return STATUS_UNSUCCESSFUL
;
139 PciWriteConfigUshort(UCHAR Bus
,
144 if ((Offset
& 1) != 0)
146 return STATUS_INVALID_PARAMETER
;
149 switch (PciBusConfigType
)
152 WRITE_PORT_ULONG((PULONG
)0xCF8, CONFIG_CMD(Bus
, Slot
, Offset
));
153 WRITE_PORT_USHORT((PUSHORT
)0xCFC + (Offset
& 1), Value
);
154 return STATUS_SUCCESS
;
157 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, FUNC(Slot
));
158 WRITE_PORT_UCHAR((PUCHAR
)0xCFA, Bus
);
159 WRITE_PORT_USHORT((PUSHORT
)(IOADDR(Slot
, Offset
)), Value
);
160 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, 0);
161 return STATUS_SUCCESS
;
163 return STATUS_UNSUCCESSFUL
;
168 PciWriteConfigUlong(UCHAR Bus
,
173 if ((Offset
& 3) != 0)
175 return STATUS_INVALID_PARAMETER
;
178 switch (PciBusConfigType
)
181 WRITE_PORT_ULONG((PULONG
)0xCF8, CONFIG_CMD(Bus
, Slot
, Offset
));
182 WRITE_PORT_ULONG((PULONG
)0xCFC, Value
);
183 return STATUS_SUCCESS
;
186 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, FUNC(Slot
));
187 WRITE_PORT_UCHAR((PUCHAR
)0xCFA, Bus
);
188 WRITE_PORT_ULONG((PULONG
)(IOADDR(Slot
, Offset
)), Value
);
189 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, 0);
190 return STATUS_SUCCESS
;
192 return STATUS_UNSUCCESSFUL
;
197 PciGetBusData(ULONG BusNumber
,
204 ULONG Address
= Offset
;
210 DPRINT(" BusNumber %lu\n", BusNumber
);
211 DPRINT(" SlotNumber %lu\n", SlotNumber
);
212 DPRINT(" Offset 0x%lx\n", Offset
);
213 DPRINT(" Length 0x%lx\n", Length
);
216 if ((Length
== 0) || (PciBusConfigType
== 0))
219 /* 0E=PCI_HEADER_TYPE */
220 PciReadConfigUchar(BusNumber
,
224 if (((HeaderType
& 0x80) == 0) && ((SlotNumber
& 0x07) != 0))
227 PciReadConfigUlong(BusNumber
,
231 /* some broken boards return 0 if a slot is empty: */
232 if (Vendor
== 0xFFFFFFFF || Vendor
== 0)
235 if ((Address
& 1) && (Len
>= 1))
237 PciReadConfigUchar(BusNumber
,
246 if ((Address
& 2) && (Len
>= 2))
248 PciReadConfigUshort(BusNumber
,
259 PciReadConfigUlong(BusNumber
,
270 PciReadConfigUshort(BusNumber
,
281 PciReadConfigUchar(BusNumber
,
295 PciSetBusData(ULONG BusNumber
,
302 ULONG Address
= Offset
;
308 DPRINT(" BusNumber %lu\n", BusNumber
);
309 DPRINT(" SlotNumber %lu\n", SlotNumber
);
310 DPRINT(" Offset 0x%lx\n", Offset
);
311 DPRINT(" Length 0x%lx\n", Length
);
314 if ((Length
== 0) || (PciBusConfigType
== 0))
317 /* 0E=PCI_HEADER_TYPE */
318 PciReadConfigUchar(BusNumber
,
322 if (((HeaderType
& 0x80) == 0) && ((SlotNumber
& 0x07) != 0))
325 PciReadConfigUlong(BusNumber
,
329 /* some broken boards return 0 if a slot is empty: */
330 if (Vendor
== 0xFFFFFFFF || Vendor
== 0)
333 if ((Address
& 1) && (Len
>= 1))
335 PciWriteConfigUchar(BusNumber
,
344 if ((Address
& 2) && (Len
>= 2))
346 PciWriteConfigUshort(BusNumber
,
357 PciWriteConfigUlong(BusNumber
,
368 PciWriteConfigUshort(BusNumber
,
379 PciWriteConfigUchar(BusNumber
,
393 PciGetBusConfigType(VOID
)
399 DPRINT("Checking configuration type 1:\n");
400 WRITE_PORT_UCHAR((PUCHAR
)0xCFB, 0x01);
401 Value
= READ_PORT_ULONG((PULONG
)0xCF8);
402 WRITE_PORT_ULONG((PULONG
)0xCF8, 0x80000000);
403 if (READ_PORT_ULONG((PULONG
)0xCF8) == 0x80000000)
405 WRITE_PORT_ULONG((PULONG
)0xCF8, Value
);
406 DPRINT(" Success!\n");
409 WRITE_PORT_ULONG((PULONG
)0xCF8, Value
);
410 DPRINT(" Unsuccessful!\n");
412 DPRINT("Checking configuration type 2:\n");
413 WRITE_PORT_UCHAR((PUCHAR
)0xCFB, 0x00);
414 WRITE_PORT_UCHAR((PUCHAR
)0xCF8, 0x00);
415 WRITE_PORT_UCHAR((PUCHAR
)0xCFA, 0x00);
416 if (READ_PORT_UCHAR((PUCHAR
)0xCF8) == 0x00 &&
417 READ_PORT_UCHAR((PUCHAR
)0xCFB) == 0x00)
419 DPRINT(" Success!\n");
422 DPRINT(" Unsuccessful!\n");
424 DPRINT("No pci bus found!\n");
431 PciDispatchDeviceControl(
432 IN PDEVICE_OBJECT DeviceObject
,
435 PIO_STACK_LOCATION IrpSp
;
438 DPRINT("Called. IRP is at (0x%X)\n", Irp
);
440 Irp
->IoStatus
.Information
= 0;
442 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
443 switch (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
) {
445 DPRINT("Unknown IOCTL 0x%X\n", IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
);
446 Status
= STATUS_NOT_IMPLEMENTED
;
450 if (Status
!= STATUS_PENDING
) {
451 Irp
->IoStatus
.Status
= Status
;
453 DPRINT("Completing IRP at 0x%X\n", Irp
);
455 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
458 DPRINT("Leaving. Status 0x%X\n", Status
);
467 IN PDEVICE_OBJECT DeviceObject
,
470 * FUNCTION: Handle Plug and Play IRPs
472 * DeviceObject = Pointer to PDO or FDO
473 * Irp = Pointer to IRP that should be handled
478 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
481 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
483 DPRINT("IsFDO %d\n", DeviceExtension
->IsFDO
);
485 if (DeviceExtension
->IsFDO
) {
486 Status
= FdoPnpControl(DeviceObject
, Irp
);
488 Status
= PdoPnpControl(DeviceObject
, Irp
);
498 IN PDEVICE_OBJECT DeviceObject
,
501 * FUNCTION: Handle power management IRPs
503 * DeviceObject = Pointer to PDO or FDO
504 * Irp = Pointer to IRP that should be handled
509 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
512 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
514 if (DeviceExtension
->IsFDO
) {
515 Status
= FdoPowerControl(DeviceObject
, Irp
);
517 Status
= PdoPowerControl(DeviceObject
, Irp
);
527 IN PDRIVER_OBJECT DriverObject
,
528 IN PDEVICE_OBJECT PhysicalDeviceObject
)
530 PFDO_DEVICE_EXTENSION DeviceExtension
;
536 Status
= IoCreateDevice(DriverObject
, sizeof(FDO_DEVICE_EXTENSION
),
537 NULL
, FILE_DEVICE_BUS_EXTENDER
, FILE_DEVICE_SECURE_OPEN
, TRUE
, &Fdo
);
538 if (!NT_SUCCESS(Status
)) {
539 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status
);
543 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)Fdo
->DeviceExtension
;
545 RtlZeroMemory(DeviceExtension
, sizeof(FDO_DEVICE_EXTENSION
));
547 DeviceExtension
->Common
.IsFDO
= TRUE
;
549 DeviceExtension
->Ldo
=
550 IoAttachDeviceToDeviceStack(Fdo
, PhysicalDeviceObject
);
552 DeviceExtension
->State
= dsStopped
;
554 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
556 //Fdo->Flags |= DO_POWER_PAGABLE;
558 DPRINT("Done AddDevice\n");
560 return STATUS_SUCCESS
;
567 IN PDRIVER_OBJECT DriverObject
,
568 IN PUNICODE_STRING RegistryPath
)
570 DbgPrint("Peripheral Component Interconnect Bus Driver\n");
572 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = (PDRIVER_DISPATCH
) PciDispatchDeviceControl
;
573 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = (PDRIVER_DISPATCH
) PciPnpControl
;
574 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = (PDRIVER_DISPATCH
) PciPowerControl
;
575 DriverObject
->DriverExtension
->AddDevice
= PciAddDevice
;
577 return STATUS_SUCCESS
;
582 PciCreateUnicodeString(
583 PUNICODE_STRING Destination
,
591 RtlInitUnicodeString(Destination
, NULL
);
595 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
597 Destination
->Buffer
= ExAllocatePool(PoolType
, Length
);
599 if (Destination
->Buffer
== NULL
)
604 RtlCopyMemory(Destination
->Buffer
, Source
, Length
);
606 Destination
->MaximumLength
= Length
;
608 Destination
->Length
= Length
- sizeof(WCHAR
);