- Fix Unix line breaks.

- Use HAL PCI bus routines in order avoid race conditions.
- Use slot number to distinguish multiple device of the same kind.

svn path=/trunk/; revision=6980
This commit is contained in:
Eric Kohl 2003-12-12 21:54:42 +00:00
parent 0dc6bcee53
commit 6010d1fd63
5 changed files with 509 additions and 904 deletions

View file

@ -1,4 +1,4 @@
/* $Id: fdo.c,v 1.4 2003/11/24 16:15:00 gvg Exp $
/* $Id: fdo.c,v 1.5 2003/12/12 21:54:42 ekohl Exp $
*
* PROJECT: ReactOS PCI bus driver
* FILE: fdo.c
@ -7,30 +7,39 @@
* UPDATE HISTORY:
* 10-09-2001 CSH Created
*/
#include <pci.h>
#include <ddk/ntddk.h>
#include "pcidef.h"
#include "pci.h"
#define NDEBUG
#include <debug.h>
/*** PRIVATE *****************************************************************/
NTSTATUS
static NTSTATUS
FdoLocateChildDevice(
PPCI_DEVICE *Device,
PFDO_DEVICE_EXTENSION DeviceExtension,
PCI_SLOT_NUMBER SlotNumber,
PPCI_COMMON_CONFIG PciConfig)
{
PLIST_ENTRY CurrentEntry;
PPCI_DEVICE CurrentDevice;
DPRINT("Called\n");
CurrentEntry = DeviceExtension->DeviceListHead.Flink;
while (CurrentEntry != &DeviceExtension->DeviceListHead) {
CurrentDevice = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
/* If both vendor ID and device ID match, it is the same device */
if ((PciConfig->VendorID == CurrentDevice->PciConfig.VendorID) &&
(PciConfig->DeviceID == CurrentDevice->PciConfig.DeviceID)) {
(PciConfig->DeviceID == CurrentDevice->PciConfig.DeviceID) &&
(SlotNumber.u.AsULONG == CurrentDevice->SlotNumber.u.AsULONG)) {
*Device = CurrentDevice;
DPRINT("Done\n");
return STATUS_SUCCESS;
}
@ -38,11 +47,12 @@ FdoLocateChildDevice(
}
*Device = NULL;
DPRINT("Done\n");
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
static NTSTATUS
FdoEnumerateDevices(
PDEVICE_OBJECT DeviceObject)
{
@ -50,9 +60,11 @@ FdoEnumerateDevices(
PCI_COMMON_CONFIG PciConfig;
PLIST_ENTRY CurrentEntry;
PPCI_DEVICE Device;
NTSTATUS Status;
ULONG Slot;
PCI_SLOT_NUMBER SlotNumber;
ULONG DeviceNumber;
ULONG FunctionNumber;
ULONG Size;
NTSTATUS Status;
DPRINT("Called\n");
@ -70,25 +82,42 @@ FdoEnumerateDevices(
DeviceExtension->DeviceListCount = 0;
/* Enumerate devices on the PCI bus */
for (Slot = 0; Slot < 256; Slot++)
{
Size = PciGetBusData(
DeviceExtension->BusNumber,
Slot,
&PciConfig,
0,
sizeof(PCI_COMMON_CONFIG));
if (Size != 0)
SlotNumber.u.AsULONG = 0;
for (DeviceNumber = 0; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++)
{
SlotNumber.u.bits.DeviceNumber = DeviceNumber;
for (FunctionNumber = 0; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
{
DPRINT("Bus %1lu Device %2lu Func %1lu VenID 0x%04hx DevID 0x%04hx\n",
DeviceExtension->BusNumber,
Slot>>3,
Slot & 0x07,
PciConfig.VendorID,
PciConfig.DeviceID);
SlotNumber.u.bits.FunctionNumber = FunctionNumber;
Status = FdoLocateChildDevice(&Device, DeviceExtension, &PciConfig);
if (!NT_SUCCESS(Status)) {
Size= HalGetBusData(PCIConfiguration,
DeviceExtension->BusNumber,
SlotNumber.u.AsULONG,
&PciConfig,
sizeof(PCI_COMMON_CONFIG));
DPRINT("Size %lu\n", Size);
if (Size < sizeof(PCI_COMMON_CONFIG))
{
if (FunctionNumber == 0)
{
break;
}
else
{
continue;
}
}
DPRINT("Bus %1lu Device %2lu Func %1lu VenID 0x%04hx DevID 0x%04hx\n",
DeviceExtension->BusNumber,
DeviceNumber,
FunctionNumber,
PciConfig.VendorID,
PciConfig.DeviceID);
Status = FdoLocateChildDevice(&Device, DeviceExtension, SlotNumber, &PciConfig);
if (!NT_SUCCESS(Status))
{
Device = (PPCI_DEVICE)ExAllocatePool(PagedPool, sizeof(PCI_DEVICE));
if (!Device)
{
@ -96,9 +125,16 @@ FdoEnumerateDevices(
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(Device, sizeof(PCI_DEVICE));
RtlZeroMemory (Device,
sizeof(PCI_DEVICE));
RtlMoveMemory(&Device->PciConfig, &PciConfig, sizeof(PCI_COMMON_CONFIG));
RtlCopyMemory (&Device->SlotNumber,
&SlotNumber,
sizeof(PCI_SLOT_NUMBER));
RtlCopyMemory (&Device->PciConfig,
&PciConfig,
sizeof(PCI_COMMON_CONFIG));
ExInterlockedInsertTailList(
&DeviceExtension->DeviceListHead,
@ -111,13 +147,15 @@ FdoEnumerateDevices(
DeviceExtension->DeviceListCount++;
}
}
}
DPRINT("Done\n");
return STATUS_SUCCESS;
}
NTSTATUS
static NTSTATUS
FdoQueryBusRelations(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
@ -250,11 +288,13 @@ FdoQueryBusRelations(
Irp->IoStatus.Information = (ULONG_PTR)Relations;
DPRINT("Done\n");
return Status;
}
NTSTATUS
static NTSTATUS
FdoStartDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
@ -271,14 +311,6 @@ FdoStartDevice(
KeInitializeSpinLock(&DeviceExtension->DeviceListLock);
DeviceExtension->DeviceListCount = 0;
PciBusConfigType = PciGetBusConfigType();
DPRINT("Bus configuration is %d\n", PciBusConfigType);
if (PciBusConfigType != pbtUnknown) {
/* At least one PCI bus is found */
}
/* FIXME: Find a way to get this information */
DeviceExtension->BusNumber = 0;
@ -286,11 +318,11 @@ FdoStartDevice(
//Irp->IoStatus.Information = 0;
return STATUS_SUCCESS;
return STATUS_SUCCESS;
}
NTSTATUS
static NTSTATUS
FdoSetPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,

View file

@ -1,4 +1,4 @@
/* $Id: pci.c,v 1.4 2003/11/14 17:13:24 weiden Exp $
/* $Id: pci.c,v 1.5 2003/12/12 21:54:42 ekohl Exp $
*
* PROJECT: ReactOS PCI Bus driver
* FILE: pci.c
@ -7,7 +7,11 @@
* UPDATE HISTORY:
* 10-09-2001 CSH Created
*/
#include <pci.h>
#include <ddk/ntddk.h>
#include "pcidef.h"
#include "pci.h"
#define NDEBUG
#include <debug.h>
@ -24,420 +28,9 @@
/*** PUBLIC ******************************************************************/
PCI_BUS_TYPE PciBusConfigType = pbtUnknown;
/*** PRIVATE *****************************************************************/
static NTSTATUS
PciReadConfigUchar(UCHAR Bus,
UCHAR Slot,
UCHAR Offset,
PUCHAR Value)
{
switch (PciBusConfigType)
{
case pbtType1:
WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
*Value = READ_PORT_UCHAR((PUCHAR)0xCFC + (Offset & 3));
return STATUS_SUCCESS;
case pbtType2:
WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
*Value = READ_PORT_UCHAR((PUCHAR)(IOADDR(Slot, Offset)));
WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
return STATUS_SUCCESS;
case pbtUnknown:
break;
}
return STATUS_UNSUCCESSFUL;
}
static NTSTATUS
PciReadConfigUshort(UCHAR Bus,
UCHAR Slot,
UCHAR Offset,
PUSHORT Value)
{
if ((Offset & 1) != 0)
{
return STATUS_INVALID_PARAMETER;
}
switch (PciBusConfigType)
{
case pbtType1:
WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
*Value = READ_PORT_USHORT((PUSHORT)0xCFC + (Offset & 2));
return STATUS_SUCCESS;
case pbtType2:
WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
*Value = READ_PORT_USHORT((PUSHORT)(IOADDR(Slot, Offset)));
WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
return STATUS_SUCCESS;
case pbtUnknown:
break;
}
return STATUS_UNSUCCESSFUL;
}
static NTSTATUS
PciReadConfigUlong(UCHAR Bus,
UCHAR Slot,
UCHAR Offset,
PULONG Value)
{
if ((Offset & 3) != 0)
{
return STATUS_INVALID_PARAMETER;
}
switch (PciBusConfigType)
{
case pbtType1:
WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
*Value = READ_PORT_ULONG((PULONG)0xCFC);
return STATUS_SUCCESS;
case pbtType2:
WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
*Value = READ_PORT_ULONG((PULONG)(IOADDR(Slot, Offset)));
WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
return STATUS_SUCCESS;
case pbtUnknown:
break;
}
return STATUS_UNSUCCESSFUL;
}
static NTSTATUS
PciWriteConfigUchar(UCHAR Bus,
UCHAR Slot,
UCHAR Offset,
UCHAR Value)
{
switch (PciBusConfigType)
{
case pbtType1:
WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
WRITE_PORT_UCHAR((PUCHAR)0xCFC + (Offset&3), Value);
return STATUS_SUCCESS;
case pbtType2:
WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
WRITE_PORT_UCHAR((PUCHAR)(IOADDR(Slot,Offset)), Value);
WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
return STATUS_SUCCESS;
case pbtUnknown:
break;
}
return STATUS_UNSUCCESSFUL;
}
static NTSTATUS
PciWriteConfigUshort(UCHAR Bus,
UCHAR Slot,
UCHAR Offset,
USHORT Value)
{
if ((Offset & 1) != 0)
{
return STATUS_INVALID_PARAMETER;
}
switch (PciBusConfigType)
{
case pbtType1:
WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
WRITE_PORT_USHORT((PUSHORT)0xCFC + (Offset & 2), Value);
return STATUS_SUCCESS;
case pbtType2:
WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
WRITE_PORT_USHORT((PUSHORT)(IOADDR(Slot, Offset)), Value);
WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
return STATUS_SUCCESS;
case pbtUnknown:
break;
}
return STATUS_UNSUCCESSFUL;
}
static NTSTATUS
PciWriteConfigUlong(UCHAR Bus,
UCHAR Slot,
UCHAR Offset,
ULONG Value)
{
if ((Offset & 3) != 0)
{
return STATUS_INVALID_PARAMETER;
}
switch (PciBusConfigType)
{
case pbtType1:
WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
WRITE_PORT_ULONG((PULONG)0xCFC, Value);
return STATUS_SUCCESS;
case pbtType2:
WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
WRITE_PORT_ULONG((PULONG)(IOADDR(Slot, Offset)), Value);
WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
return STATUS_SUCCESS;
case pbtUnknown:
break;
}
return STATUS_UNSUCCESSFUL;
}
ULONG
PciGetBusData(ULONG BusNumber,
ULONG SlotNumber,
PVOID Buffer,
ULONG Offset,
ULONG Length)
{
PVOID Ptr = Buffer;
ULONG Address = Offset;
ULONG Len = Length;
ULONG Vendor;
UCHAR HeaderType;
#if 0
DPRINT(" BusNumber %lu\n", BusNumber);
DPRINT(" SlotNumber %lu\n", SlotNumber);
DPRINT(" Offset 0x%lx\n", Offset);
DPRINT(" Length 0x%lx\n", Length);
#endif
if ((Length == 0) || (PciBusConfigType == 0))
return 0;
/* 0E=PCI_HEADER_TYPE */
PciReadConfigUchar(BusNumber,
SlotNumber & 0xF8,
0x0E,
&HeaderType);
if (((HeaderType & 0x80) == 0) && ((SlotNumber & 0x07) != 0))
return 0;
PciReadConfigUlong(BusNumber,
SlotNumber,
0x00,
&Vendor);
/* some broken boards return 0 if a slot is empty: */
if (Vendor == 0xFFFFFFFF || Vendor == 0)
return 0;
if ((Address & 1) && (Len >= 1))
{
PciReadConfigUchar(BusNumber,
SlotNumber,
Address,
Ptr);
Ptr = Ptr + 1;
Address++;
Len--;
}
if ((Address & 2) && (Len >= 2))
{
PciReadConfigUshort(BusNumber,
SlotNumber,
Address,
Ptr);
Ptr = Ptr + 2;
Address += 2;
Len -= 2;
}
while (Len >= 4)
{
PciReadConfigUlong(BusNumber,
SlotNumber,
Address,
Ptr);
Ptr = Ptr + 4;
Address += 4;
Len -= 4;
}
if (Len >= 2)
{
PciReadConfigUshort(BusNumber,
SlotNumber,
Address,
Ptr);
Ptr = Ptr + 2;
Address += 2;
Len -= 2;
}
if (Len >= 1)
{
PciReadConfigUchar(BusNumber,
SlotNumber,
Address,
Ptr);
Ptr = Ptr + 1;
Address++;
Len--;
}
return Length - Len;
}
ULONG
PciSetBusData(ULONG BusNumber,
ULONG SlotNumber,
PVOID Buffer,
ULONG Offset,
ULONG Length)
{
PVOID Ptr = Buffer;
ULONG Address = Offset;
ULONG Len = Length;
ULONG Vendor;
UCHAR HeaderType;
#if 0
DPRINT(" BusNumber %lu\n", BusNumber);
DPRINT(" SlotNumber %lu\n", SlotNumber);
DPRINT(" Offset 0x%lx\n", Offset);
DPRINT(" Length 0x%lx\n", Length);
#endif
if ((Length == 0) || (PciBusConfigType == 0))
return 0;
/* 0E=PCI_HEADER_TYPE */
PciReadConfigUchar(BusNumber,
SlotNumber & 0xF8,
0x0E,
&HeaderType);
if (((HeaderType & 0x80) == 0) && ((SlotNumber & 0x07) != 0))
return 0;
PciReadConfigUlong(BusNumber,
SlotNumber,
0x00,
&Vendor);
/* some broken boards return 0 if a slot is empty: */
if (Vendor == 0xFFFFFFFF || Vendor == 0)
return 0;
if ((Address & 1) && (Len >= 1))
{
PciWriteConfigUchar(BusNumber,
SlotNumber,
Address,
*(PUCHAR)Ptr);
Ptr = Ptr + 1;
Address++;
Len--;
}
if ((Address & 2) && (Len >= 2))
{
PciWriteConfigUshort(BusNumber,
SlotNumber,
Address,
*(PUSHORT)Ptr);
Ptr = Ptr + 2;
Address += 2;
Len -= 2;
}
while (Len >= 4)
{
PciWriteConfigUlong(BusNumber,
SlotNumber,
Address,
*(PULONG)Ptr);
Ptr = Ptr + 4;
Address += 4;
Len -= 4;
}
if (Len >= 2)
{
PciWriteConfigUshort(BusNumber,
SlotNumber,
Address,
*(PUSHORT)Ptr);
Ptr = Ptr + 2;
Address += 2;
Len -= 2;
}
if (Len >= 1)
{
PciWriteConfigUchar(BusNumber,
SlotNumber,
Address,
*(PUCHAR)Ptr);
Ptr = Ptr + 1;
Address++;
Len--;
}
return Length - Len;
}
PCI_BUS_TYPE
PciGetBusConfigType(VOID)
{
ULONG Value;
DPRINT("Called\n");
DPRINT("Checking configuration type 1:\n");
WRITE_PORT_UCHAR((PUCHAR)0xCFB, 0x01);
Value = READ_PORT_ULONG((PULONG)0xCF8);
WRITE_PORT_ULONG((PULONG)0xCF8, 0x80000000);
if (READ_PORT_ULONG((PULONG)0xCF8) == 0x80000000)
{
WRITE_PORT_ULONG((PULONG)0xCF8, Value);
DPRINT(" Success!\n");
return pbtType1;
}
WRITE_PORT_ULONG((PULONG)0xCF8, Value);
DPRINT(" Unsuccessful!\n");
DPRINT("Checking configuration type 2:\n");
WRITE_PORT_UCHAR((PUCHAR)0xCFB, 0x00);
WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0x00);
WRITE_PORT_UCHAR((PUCHAR)0xCFA, 0x00);
if (READ_PORT_UCHAR((PUCHAR)0xCF8) == 0x00 &&
READ_PORT_UCHAR((PUCHAR)0xCFB) == 0x00)
{
DPRINT(" Success!\n");
return pbtType2;
}
DPRINT(" Unsuccessful!\n");
DPRINT("No pci bus found!\n");
return pbtUnknown;
}
NTSTATUS
STDCALL
PciDispatchDeviceControl(

View file

@ -1,11 +1,8 @@
/* $Id: pci.h,v 1.3 2003/11/14 17:13:24 weiden Exp $ */
/* $Id: pci.h,v 1.4 2003/12/12 21:54:42 ekohl Exp $ */
#ifndef __PCI_H
#define __PCI_H
#include <ddk/ntddk.h>
#include <pcidef.h>
typedef enum {
pbtUnknown = 0,
@ -20,6 +17,8 @@ typedef struct _PCI_DEVICE
LIST_ENTRY ListEntry;
// Physical Device Object of device
PDEVICE_OBJECT Pdo;
/* PCI Slot number */
PCI_SLOT_NUMBER SlotNumber;
// PCI configuration data
PCI_COMMON_CONFIG PciConfig;
// Flag used during enumeration to locate removed devices
@ -103,21 +102,9 @@ FdoPowerControl(
/* pci.c */
extern PCI_BUS_TYPE PciBusConfigType;
PCI_BUS_TYPE
PciGetBusConfigType(VOID);
ULONG
PciGetBusData(ULONG BusNumber,
ULONG SlotNumber,
PVOID Buffer,
ULONG Offset,
ULONG Length);
BOOLEAN
PciCreateUnicodeString(
PUNICODE_STRING Destination,
PUNICODE_STRING Destination,
PWSTR Source,
POOL_TYPE PoolType);

View file

@ -1,5 +1,5 @@
/*
* $Id: pcidef.h,v 1.2 2001/11/01 23:17:10 ekohl Exp $
* $Id: pcidef.h,v 1.3 2003/12/12 21:54:42 ekohl Exp $
*
* PCI defines and function prototypes
* Copyright 1994, Drew Eckhardt
@ -301,15 +301,4 @@
#define PCI_REGION_FLAG_MASK 0x0f /* These bits of resource flags tell us the PCI region flags */
#define CONFIG_CMD(bus, device_fn, where) \
(0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))
#define IOADDR(devfn, where) \
((0xC000 | ((devfn & 0x78) << 5)) + where)
#define FUNC(devfn) \
(((devfn & 7) << 1) | 0xf0)
#endif /* _PCIDEF_H */

View file

@ -1,4 +1,4 @@
/* $Id: pdo.c,v 1.1 2001/09/16 13:18:24 chorns Exp $
/* $Id: pdo.c,v 1.2 2003/12/12 21:54:42 ekohl Exp $
*
* PROJECT: ReactOS PCI bus driver
* FILE: pdo.c
@ -7,7 +7,11 @@
* UPDATE HISTORY:
* 10-09-2001 CSH Created
*/
#include <pci.h>
#include <ddk/ntddk.h>
#include "pcidef.h"
#include "pci.h"
#define NDEBUG
#include <debug.h>