- 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,459 +1,491 @@
/* $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 * PROJECT: ReactOS PCI bus driver
* FILE: fdo.c * FILE: fdo.c
* PURPOSE: PCI device object dispatch routines * PURPOSE: PCI device object dispatch routines
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* UPDATE HISTORY: * UPDATE HISTORY:
* 10-09-2001 CSH Created * 10-09-2001 CSH Created
*/ */
#include <pci.h>
#include <ddk/ntddk.h>
#define NDEBUG
#include <debug.h> #include "pcidef.h"
#include "pci.h"
/*** PRIVATE *****************************************************************/
#define NDEBUG
NTSTATUS #include <debug.h>
FdoLocateChildDevice(
PPCI_DEVICE *Device, /*** PRIVATE *****************************************************************/
PFDO_DEVICE_EXTENSION DeviceExtension,
PPCI_COMMON_CONFIG PciConfig) static NTSTATUS
{ FdoLocateChildDevice(
PLIST_ENTRY CurrentEntry; PPCI_DEVICE *Device,
PPCI_DEVICE CurrentDevice; PFDO_DEVICE_EXTENSION DeviceExtension,
PCI_SLOT_NUMBER SlotNumber,
CurrentEntry = DeviceExtension->DeviceListHead.Flink; PPCI_COMMON_CONFIG PciConfig)
while (CurrentEntry != &DeviceExtension->DeviceListHead) { {
CurrentDevice = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry); PLIST_ENTRY CurrentEntry;
PPCI_DEVICE CurrentDevice;
/* If both vendor ID and device ID match, it is the same device */
if ((PciConfig->VendorID == CurrentDevice->PciConfig.VendorID) && DPRINT("Called\n");
(PciConfig->DeviceID == CurrentDevice->PciConfig.DeviceID)) {
*Device = CurrentDevice; CurrentEntry = DeviceExtension->DeviceListHead.Flink;
return STATUS_SUCCESS; while (CurrentEntry != &DeviceExtension->DeviceListHead) {
} CurrentDevice = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
CurrentEntry = CurrentEntry->Flink; /* If both vendor ID and device ID match, it is the same device */
} if ((PciConfig->VendorID == CurrentDevice->PciConfig.VendorID) &&
(PciConfig->DeviceID == CurrentDevice->PciConfig.DeviceID) &&
*Device = NULL; (SlotNumber.u.AsULONG == CurrentDevice->SlotNumber.u.AsULONG)) {
return STATUS_UNSUCCESSFUL; *Device = CurrentDevice;
} DPRINT("Done\n");
return STATUS_SUCCESS;
}
NTSTATUS
FdoEnumerateDevices( CurrentEntry = CurrentEntry->Flink;
PDEVICE_OBJECT DeviceObject) }
{
PFDO_DEVICE_EXTENSION DeviceExtension; *Device = NULL;
PCI_COMMON_CONFIG PciConfig; DPRINT("Done\n");
PLIST_ENTRY CurrentEntry; return STATUS_UNSUCCESSFUL;
PPCI_DEVICE Device; }
NTSTATUS Status;
ULONG Slot;
ULONG Size; static NTSTATUS
FdoEnumerateDevices(
DPRINT("Called\n"); PDEVICE_OBJECT DeviceObject)
{
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; PFDO_DEVICE_EXTENSION DeviceExtension;
PCI_COMMON_CONFIG PciConfig;
/* Mark all devices to be removed. If we don't discover them again during PLIST_ENTRY CurrentEntry;
enumeration, assume that they have been surprise removed */ PPCI_DEVICE Device;
CurrentEntry = DeviceExtension->DeviceListHead.Flink; PCI_SLOT_NUMBER SlotNumber;
while (CurrentEntry != &DeviceExtension->DeviceListHead) { ULONG DeviceNumber;
Device = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry); ULONG FunctionNumber;
Device->RemovePending = TRUE; ULONG Size;
CurrentEntry = CurrentEntry->Flink; NTSTATUS Status;
}
DPRINT("Called\n");
DeviceExtension->DeviceListCount = 0;
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* Enumerate devices on the PCI bus */
for (Slot = 0; Slot < 256; Slot++) /* Mark all devices to be removed. If we don't discover them again during
{ enumeration, assume that they have been surprise removed */
Size = PciGetBusData( CurrentEntry = DeviceExtension->DeviceListHead.Flink;
DeviceExtension->BusNumber, while (CurrentEntry != &DeviceExtension->DeviceListHead) {
Slot, Device = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
&PciConfig, Device->RemovePending = TRUE;
0, CurrentEntry = CurrentEntry->Flink;
sizeof(PCI_COMMON_CONFIG)); }
if (Size != 0)
{ DeviceExtension->DeviceListCount = 0;
DPRINT("Bus %1lu Device %2lu Func %1lu VenID 0x%04hx DevID 0x%04hx\n",
DeviceExtension->BusNumber, /* Enumerate devices on the PCI bus */
Slot>>3, SlotNumber.u.AsULONG = 0;
Slot & 0x07, for (DeviceNumber = 0; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++)
PciConfig.VendorID, {
PciConfig.DeviceID); SlotNumber.u.bits.DeviceNumber = DeviceNumber;
for (FunctionNumber = 0; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
Status = FdoLocateChildDevice(&Device, DeviceExtension, &PciConfig); {
if (!NT_SUCCESS(Status)) { SlotNumber.u.bits.FunctionNumber = FunctionNumber;
Device = (PPCI_DEVICE)ExAllocatePool(PagedPool, sizeof(PCI_DEVICE));
if (!Device) Size= HalGetBusData(PCIConfiguration,
{ DeviceExtension->BusNumber,
/* FIXME: Cleanup resources for already discovered devices */ SlotNumber.u.AsULONG,
return STATUS_INSUFFICIENT_RESOURCES; &PciConfig,
} sizeof(PCI_COMMON_CONFIG));
DPRINT("Size %lu\n", Size);
RtlZeroMemory(Device, sizeof(PCI_DEVICE)); if (Size < sizeof(PCI_COMMON_CONFIG))
{
RtlMoveMemory(&Device->PciConfig, &PciConfig, sizeof(PCI_COMMON_CONFIG)); if (FunctionNumber == 0)
{
ExInterlockedInsertTailList( break;
&DeviceExtension->DeviceListHead, }
&Device->ListEntry, else
&DeviceExtension->DeviceListLock); {
} continue;
}
/* Don't remove this device */ }
Device->RemovePending = FALSE;
DPRINT("Bus %1lu Device %2lu Func %1lu VenID 0x%04hx DevID 0x%04hx\n",
DeviceExtension->DeviceListCount++; DeviceExtension->BusNumber,
} DeviceNumber,
} FunctionNumber,
PciConfig.VendorID,
return STATUS_SUCCESS; PciConfig.DeviceID);
}
Status = FdoLocateChildDevice(&Device, DeviceExtension, SlotNumber, &PciConfig);
if (!NT_SUCCESS(Status))
NTSTATUS {
FdoQueryBusRelations( Device = (PPCI_DEVICE)ExAllocatePool(PagedPool, sizeof(PCI_DEVICE));
IN PDEVICE_OBJECT DeviceObject, if (!Device)
IN PIRP Irp, {
PIO_STACK_LOCATION IrpSp) /* FIXME: Cleanup resources for already discovered devices */
{ return STATUS_INSUFFICIENT_RESOURCES;
PPDO_DEVICE_EXTENSION PdoDeviceExtension; }
PFDO_DEVICE_EXTENSION DeviceExtension;
PDEVICE_RELATIONS Relations; RtlZeroMemory (Device,
PLIST_ENTRY CurrentEntry; sizeof(PCI_DEVICE));
PPCI_DEVICE Device;
NTSTATUS Status; RtlCopyMemory (&Device->SlotNumber,
BOOLEAN ErrorOccurred; &SlotNumber,
NTSTATUS ErrorStatus; sizeof(PCI_SLOT_NUMBER));
WCHAR Buffer[MAX_PATH];
ULONG Size; RtlCopyMemory (&Device->PciConfig,
ULONG i; &PciConfig,
sizeof(PCI_COMMON_CONFIG));
DPRINT("Called\n");
ExInterlockedInsertTailList(
ErrorStatus = STATUS_INSUFFICIENT_RESOURCES; &DeviceExtension->DeviceListHead,
&Device->ListEntry,
Status = STATUS_SUCCESS; &DeviceExtension->DeviceListLock);
}
ErrorOccurred = FALSE;
/* Don't remove this device */
FdoEnumerateDevices(DeviceObject); Device->RemovePending = FALSE;
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; DeviceExtension->DeviceListCount++;
}
if (Irp->IoStatus.Information) { }
/* FIXME: Another bus driver has already created a DEVICE_RELATIONS
structure so we must merge this structure with our own */ DPRINT("Done\n");
}
return STATUS_SUCCESS;
Size = sizeof(DEVICE_RELATIONS) + sizeof(Relations->Objects) * }
(DeviceExtension->DeviceListCount - 1);
Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size);
if (!Relations) static NTSTATUS
return STATUS_INSUFFICIENT_RESOURCES; FdoQueryBusRelations(
IN PDEVICE_OBJECT DeviceObject,
Relations->Count = DeviceExtension->DeviceListCount; IN PIRP Irp,
PIO_STACK_LOCATION IrpSp)
i = 0; {
CurrentEntry = DeviceExtension->DeviceListHead.Flink; PPDO_DEVICE_EXTENSION PdoDeviceExtension;
while (CurrentEntry != &DeviceExtension->DeviceListHead) { PFDO_DEVICE_EXTENSION DeviceExtension;
Device = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry); PDEVICE_RELATIONS Relations;
PLIST_ENTRY CurrentEntry;
PdoDeviceExtension = NULL; PPCI_DEVICE Device;
NTSTATUS Status;
if (!Device->Pdo) { BOOLEAN ErrorOccurred;
/* Create a physical device object for the NTSTATUS ErrorStatus;
device as it does not already have one */ WCHAR Buffer[MAX_PATH];
Status = IoCreateDevice( ULONG Size;
DeviceObject->DriverObject, ULONG i;
sizeof(PDO_DEVICE_EXTENSION),
NULL, DPRINT("Called\n");
FILE_DEVICE_CONTROLLER,
0, ErrorStatus = STATUS_INSUFFICIENT_RESOURCES;
FALSE,
&Device->Pdo); Status = STATUS_SUCCESS;
if (!NT_SUCCESS(Status)) {
DPRINT("IoCreateDevice() failed with status 0x%X\n", Status); ErrorOccurred = FALSE;
ErrorStatus = Status;
ErrorOccurred = TRUE; FdoEnumerateDevices(DeviceObject);
break;
} DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; if (Irp->IoStatus.Information) {
/* FIXME: Another bus driver has already created a DEVICE_RELATIONS
Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING; structure so we must merge this structure with our own */
}
//Device->Pdo->Flags |= DO_POWER_PAGABLE;
Size = sizeof(DEVICE_RELATIONS) + sizeof(Relations->Objects) *
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension; (DeviceExtension->DeviceListCount - 1);
Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size);
RtlZeroMemory(PdoDeviceExtension, sizeof(PDO_DEVICE_EXTENSION)); if (!Relations)
return STATUS_INSUFFICIENT_RESOURCES;
PdoDeviceExtension->Common.IsFDO = FALSE;
Relations->Count = DeviceExtension->DeviceListCount;
PdoDeviceExtension->Common.DeviceObject = Device->Pdo;
i = 0;
PdoDeviceExtension->Common.DevicePowerState = PowerDeviceD0; CurrentEntry = DeviceExtension->DeviceListHead.Flink;
while (CurrentEntry != &DeviceExtension->DeviceListHead) {
/* FIXME: Get device properties (Hardware IDs, etc.) */ Device = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
swprintf( PdoDeviceExtension = NULL;
Buffer,
L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X", if (!Device->Pdo) {
Device->PciConfig.VendorID, /* Create a physical device object for the
Device->PciConfig.DeviceID, device as it does not already have one */
(Device->PciConfig.u.type0.SubSystemID << 16) + Status = IoCreateDevice(
Device->PciConfig.u.type0.SubVendorID, DeviceObject->DriverObject,
Device->PciConfig.RevisionID); sizeof(PDO_DEVICE_EXTENSION),
NULL,
if (!PciCreateUnicodeString( FILE_DEVICE_CONTROLLER,
&PdoDeviceExtension->DeviceID, 0,
Buffer, FALSE,
PagedPool)) { &Device->Pdo);
ErrorOccurred = TRUE; if (!NT_SUCCESS(Status)) {
break; DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
} ErrorStatus = Status;
ErrorOccurred = TRUE;
DPRINT("DeviceID: %S\n", PdoDeviceExtension->DeviceID.Buffer); break;
} }
if (!Device->RemovePending) { Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
/* Reference the physical device object. The PnP manager
will dereference it again when it is no longer needed */ Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
ObReferenceObject(Device->Pdo);
//Device->Pdo->Flags |= DO_POWER_PAGABLE;
Relations->Objects[i] = Device->Pdo;
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;
i++;
} RtlZeroMemory(PdoDeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
CurrentEntry = CurrentEntry->Flink; PdoDeviceExtension->Common.IsFDO = FALSE;
}
PdoDeviceExtension->Common.DeviceObject = Device->Pdo;
if (ErrorOccurred) {
/* FIXME: Cleanup all new PDOs created in this call. Please give me SEH!!! ;-) */ PdoDeviceExtension->Common.DevicePowerState = PowerDeviceD0;
/* FIXME: Should IoAttachDeviceToDeviceStack() be undone? */
if (PdoDeviceExtension) { /* FIXME: Get device properties (Hardware IDs, etc.) */
RtlFreeUnicodeString(&PdoDeviceExtension->DeviceID);
ExFreePool(PdoDeviceExtension); swprintf(
} Buffer,
L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X",
ExFreePool(Relations); Device->PciConfig.VendorID,
return ErrorStatus; Device->PciConfig.DeviceID,
} (Device->PciConfig.u.type0.SubSystemID << 16) +
Device->PciConfig.u.type0.SubVendorID,
Irp->IoStatus.Information = (ULONG_PTR)Relations; Device->PciConfig.RevisionID);
return Status; if (!PciCreateUnicodeString(
} &PdoDeviceExtension->DeviceID,
Buffer,
PagedPool)) {
NTSTATUS ErrorOccurred = TRUE;
FdoStartDevice( break;
IN PDEVICE_OBJECT DeviceObject, }
IN PIRP Irp)
{ DPRINT("DeviceID: %S\n", PdoDeviceExtension->DeviceID.Buffer);
PFDO_DEVICE_EXTENSION DeviceExtension; }
DPRINT("Called\n"); if (!Device->RemovePending) {
/* Reference the physical device object. The PnP manager
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; will dereference it again when it is no longer needed */
ObReferenceObject(Device->Pdo);
assert(DeviceExtension->State == dsStopped);
Relations->Objects[i] = Device->Pdo;
InitializeListHead(&DeviceExtension->DeviceListHead);
KeInitializeSpinLock(&DeviceExtension->DeviceListLock); i++;
DeviceExtension->DeviceListCount = 0; }
PciBusConfigType = PciGetBusConfigType(); CurrentEntry = CurrentEntry->Flink;
}
DPRINT("Bus configuration is %d\n", PciBusConfigType);
if (ErrorOccurred) {
if (PciBusConfigType != pbtUnknown) { /* FIXME: Cleanup all new PDOs created in this call. Please give me SEH!!! ;-) */
/* At least one PCI bus is found */ /* FIXME: Should IoAttachDeviceToDeviceStack() be undone? */
} if (PdoDeviceExtension) {
RtlFreeUnicodeString(&PdoDeviceExtension->DeviceID);
/* FIXME: Find a way to get this information */ ExFreePool(PdoDeviceExtension);
DeviceExtension->BusNumber = 0; }
DeviceExtension->State = dsStarted; ExFreePool(Relations);
return ErrorStatus;
//Irp->IoStatus.Information = 0; }
return STATUS_SUCCESS; Irp->IoStatus.Information = (ULONG_PTR)Relations;
}
DPRINT("Done\n");
NTSTATUS return Status;
FdoSetPower( }
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
PIO_STACK_LOCATION IrpSp) static NTSTATUS
{ FdoStartDevice(
PFDO_DEVICE_EXTENSION DeviceExtension; IN PDEVICE_OBJECT DeviceObject,
NTSTATUS Status; IN PIRP Irp)
{
DPRINT("Called\n"); PFDO_DEVICE_EXTENSION DeviceExtension;
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; DPRINT("Called\n");
if (IrpSp->Parameters.Power.Type == DevicePowerState) { DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* FIXME: Set device power state for the device */
Status = STATUS_UNSUCCESSFUL; assert(DeviceExtension->State == dsStopped);
} else {
Status = STATUS_UNSUCCESSFUL; InitializeListHead(&DeviceExtension->DeviceListHead);
} KeInitializeSpinLock(&DeviceExtension->DeviceListLock);
DeviceExtension->DeviceListCount = 0;
return Status;
} /* FIXME: Find a way to get this information */
DeviceExtension->BusNumber = 0;
/*** PUBLIC ******************************************************************/ DeviceExtension->State = dsStarted;
NTSTATUS //Irp->IoStatus.Information = 0;
FdoPnpControl(
PDEVICE_OBJECT DeviceObject, return STATUS_SUCCESS;
PIRP Irp) }
/*
* FUNCTION: Handle Plug and Play IRPs for the PCI device object
* ARGUMENTS: static NTSTATUS
* DeviceObject = Pointer to functional device object of the PCI driver FdoSetPower(
* Irp = Pointer to IRP that should be handled IN PDEVICE_OBJECT DeviceObject,
* RETURNS: IN PIRP Irp,
* Status PIO_STACK_LOCATION IrpSp)
*/ {
{ PFDO_DEVICE_EXTENSION DeviceExtension;
PFDO_DEVICE_EXTENSION DeviceExtension; NTSTATUS Status;
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status; DPRINT("Called\n");
DPRINT("Called\n"); DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; if (IrpSp->Parameters.Power.Type == DevicePowerState) {
/* FIXME: Set device power state for the device */
IrpSp = IoGetCurrentIrpStackLocation(Irp); Status = STATUS_UNSUCCESSFUL;
switch (IrpSp->MinorFunction) { } else {
#if 0 Status = STATUS_UNSUCCESSFUL;
case IRP_MN_CANCEL_REMOVE_DEVICE: }
Status = STATUS_NOT_IMPLEMENTED;
break; return Status;
}
case IRP_MN_CANCEL_STOP_DEVICE:
Status = STATUS_NOT_IMPLEMENTED;
break; /*** PUBLIC ******************************************************************/
case IRP_MN_DEVICE_USAGE_NOTIFICATION: NTSTATUS
Status = STATUS_NOT_IMPLEMENTED; FdoPnpControl(
break; PDEVICE_OBJECT DeviceObject,
PIRP Irp)
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /*
Status = STATUS_NOT_IMPLEMENTED; * FUNCTION: Handle Plug and Play IRPs for the PCI device object
break; * ARGUMENTS:
#endif * DeviceObject = Pointer to functional device object of the PCI driver
case IRP_MN_QUERY_DEVICE_RELATIONS: * Irp = Pointer to IRP that should be handled
Status = FdoQueryBusRelations(DeviceObject, Irp, IrpSp); * RETURNS:
break; * Status
#if 0 */
case IRP_MN_QUERY_PNP_DEVICE_STATE: {
Status = STATUS_NOT_IMPLEMENTED; PFDO_DEVICE_EXTENSION DeviceExtension;
break; PIO_STACK_LOCATION IrpSp;
NTSTATUS Status;
case IRP_MN_QUERY_REMOVE_DEVICE:
Status = STATUS_NOT_IMPLEMENTED; DPRINT("Called\n");
break;
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
case IRP_MN_QUERY_STOP_DEVICE:
Status = STATUS_NOT_IMPLEMENTED; IrpSp = IoGetCurrentIrpStackLocation(Irp);
break; switch (IrpSp->MinorFunction) {
#if 0
case IRP_MN_REMOVE_DEVICE: case IRP_MN_CANCEL_REMOVE_DEVICE:
Status = STATUS_NOT_IMPLEMENTED; Status = STATUS_NOT_IMPLEMENTED;
break; break;
#endif
case IRP_MN_START_DEVICE: case IRP_MN_CANCEL_STOP_DEVICE:
DPRINT("IRP_MN_START_DEVICE received\n"); Status = STATUS_NOT_IMPLEMENTED;
Status = FdoStartDevice(DeviceObject, Irp); break;
break;
case IRP_MN_STOP_DEVICE: case IRP_MN_DEVICE_USAGE_NOTIFICATION:
/* Currently not supported */ Status = STATUS_NOT_IMPLEMENTED;
Status = STATUS_UNSUCCESSFUL; break;
break;
#if 0 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
case IRP_MN_SURPRISE_REMOVAL: Status = STATUS_NOT_IMPLEMENTED;
Status = STATUS_NOT_IMPLEMENTED; break;
break; #endif
#endif case IRP_MN_QUERY_DEVICE_RELATIONS:
default: Status = FdoQueryBusRelations(DeviceObject, Irp, IrpSp);
DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction); break;
#if 0
/* case IRP_MN_QUERY_PNP_DEVICE_STATE:
* Do NOT complete the IRP as it will be processed by the lower Status = STATUS_NOT_IMPLEMENTED;
* device object, which will complete the IRP break;
*/
IoSkipCurrentIrpStackLocation(Irp); case IRP_MN_QUERY_REMOVE_DEVICE:
Status = IoCallDriver(DeviceExtension->Ldo, Irp); Status = STATUS_NOT_IMPLEMENTED;
return Status; break;
break;
} case IRP_MN_QUERY_STOP_DEVICE:
Status = STATUS_NOT_IMPLEMENTED;
break;
if (Status != STATUS_PENDING) {
if (Status != STATUS_NOT_IMPLEMENTED) case IRP_MN_REMOVE_DEVICE:
Irp->IoStatus.Status = Status; Status = STATUS_NOT_IMPLEMENTED;
IoCompleteRequest(Irp, IO_NO_INCREMENT); break;
} #endif
case IRP_MN_START_DEVICE:
DPRINT("Leaving. Status 0x%X\n", Status); DPRINT("IRP_MN_START_DEVICE received\n");
Status = FdoStartDevice(DeviceObject, Irp);
return Status; break;
} case IRP_MN_STOP_DEVICE:
/* Currently not supported */
Status = STATUS_UNSUCCESSFUL;
NTSTATUS break;
FdoPowerControl( #if 0
PDEVICE_OBJECT DeviceObject, case IRP_MN_SURPRISE_REMOVAL:
PIRP Irp) Status = STATUS_NOT_IMPLEMENTED;
/* break;
* FUNCTION: Handle power management IRPs for the PCI device object #endif
* ARGUMENTS: default:
* DeviceObject = Pointer to functional device object of the PCI driver DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
* Irp = Pointer to IRP that should be handled
* RETURNS: /*
* Status * Do NOT complete the IRP as it will be processed by the lower
*/ * device object, which will complete the IRP
{ */
PIO_STACK_LOCATION IrpSp; IoSkipCurrentIrpStackLocation(Irp);
NTSTATUS Status; Status = IoCallDriver(DeviceExtension->Ldo, Irp);
return Status;
DPRINT("Called\n"); break;
}
IrpSp = IoGetCurrentIrpStackLocation(Irp);
switch (IrpSp->MinorFunction) { if (Status != STATUS_PENDING) {
case IRP_MN_SET_POWER: if (Status != STATUS_NOT_IMPLEMENTED)
Status = FdoSetPower(DeviceObject, Irp, IrpSp); Irp->IoStatus.Status = Status;
break; IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
default:
DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction); DPRINT("Leaving. Status 0x%X\n", Status);
Status = STATUS_NOT_IMPLEMENTED;
break; return Status;
} }
if (Status != STATUS_PENDING) {
Irp->IoStatus.Status = Status; NTSTATUS
IoCompleteRequest(Irp, IO_NO_INCREMENT); FdoPowerControl(
} PDEVICE_OBJECT DeviceObject,
PIRP Irp)
DPRINT("Leaving. Status 0x%X\n", Status); /*
* FUNCTION: Handle power management IRPs for the PCI device object
return Status; * ARGUMENTS:
} * DeviceObject = Pointer to functional device object of the PCI driver
* Irp = Pointer to IRP that should be handled
/* EOF */ * RETURNS:
* Status
*/
{
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status;
DPRINT("Called\n");
IrpSp = IoGetCurrentIrpStackLocation(Irp);
switch (IrpSp->MinorFunction) {
case IRP_MN_SET_POWER:
Status = FdoSetPower(DeviceObject, Irp, IrpSp);
break;
default:
DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
Status = STATUS_NOT_IMPLEMENTED;
break;
}
if (Status != STATUS_PENDING) {
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
DPRINT("Leaving. Status 0x%X\n", Status);
return Status;
}
/* EOF */

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 * PROJECT: ReactOS PCI Bus driver
* FILE: pci.c * FILE: pci.c
@ -7,7 +7,11 @@
* UPDATE HISTORY: * UPDATE HISTORY:
* 10-09-2001 CSH Created * 10-09-2001 CSH Created
*/ */
#include <pci.h>
#include <ddk/ntddk.h>
#include "pcidef.h"
#include "pci.h"
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
@ -24,420 +28,9 @@
/*** PUBLIC ******************************************************************/ /*** PUBLIC ******************************************************************/
PCI_BUS_TYPE PciBusConfigType = pbtUnknown;
/*** PRIVATE *****************************************************************/ /*** 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 NTSTATUS
STDCALL STDCALL
PciDispatchDeviceControl( 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 #ifndef __PCI_H
#define __PCI_H #define __PCI_H
#include <ddk/ntddk.h>
#include <pcidef.h>
typedef enum { typedef enum {
pbtUnknown = 0, pbtUnknown = 0,
@ -20,6 +17,8 @@ typedef struct _PCI_DEVICE
LIST_ENTRY ListEntry; LIST_ENTRY ListEntry;
// Physical Device Object of device // Physical Device Object of device
PDEVICE_OBJECT Pdo; PDEVICE_OBJECT Pdo;
/* PCI Slot number */
PCI_SLOT_NUMBER SlotNumber;
// PCI configuration data // PCI configuration data
PCI_COMMON_CONFIG PciConfig; PCI_COMMON_CONFIG PciConfig;
// Flag used during enumeration to locate removed devices // Flag used during enumeration to locate removed devices
@ -103,21 +102,9 @@ FdoPowerControl(
/* pci.c */ /* 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 BOOLEAN
PciCreateUnicodeString( PciCreateUnicodeString(
PUNICODE_STRING Destination, PUNICODE_STRING Destination,
PWSTR Source, PWSTR Source,
POOL_TYPE PoolType); 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 * PCI defines and function prototypes
* Copyright 1994, Drew Eckhardt * Copyright 1994, Drew Eckhardt
@ -298,18 +298,7 @@
#define PCI_ROM_RESOURCE 6 #define PCI_ROM_RESOURCE 6
#define PCI_BRIDGE_RESOURCES 7 #define PCI_BRIDGE_RESOURCES 7
#define PCI_NUM_RESOURCES 11 #define PCI_NUM_RESOURCES 11
#define PCI_REGION_FLAG_MASK 0x0f /* These bits of resource flags tell us the PCI region flags */ #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 */ #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 * PROJECT: ReactOS PCI bus driver
* FILE: pdo.c * FILE: pdo.c
@ -7,7 +7,11 @@
* UPDATE HISTORY: * UPDATE HISTORY:
* 10-09-2001 CSH Created * 10-09-2001 CSH Created
*/ */
#include <pci.h>
#include <ddk/ntddk.h>
#include "pcidef.h"
#include "pci.h"
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>