Added PCI bus driver skeleton

svn path=/trunk/; revision=2253
This commit is contained in:
Casper Hornstrup 2001-09-16 13:18:24 +00:00
parent 1ea7189ed9
commit 9baaca2418
7 changed files with 1847 additions and 0 deletions

View file

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

@ -0,0 +1,13 @@
# $Id: makefile,v 1.1 2001/09/16 13:18:24 chorns Exp $
PATH_TO_TOP = ../../..
TARGET_TYPE = driver
TARGET_NAME = pci
TARGET_OBJECTS = fdo.o pci.o pdo.o
include $(PATH_TO_TOP)/rules.mak
include $(TOOLS_PATH)/helper.mk

View file

@ -0,0 +1,613 @@
/* $Id: pci.c,v 1.1 2001/09/16 13:18:24 chorns Exp $
*
* PROJECT: ReactOS PCI Bus driver
* FILE: pci.c
* PURPOSE: Driver entry
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* UPDATE HISTORY:
* 10-09-2001 CSH Created
*/
#include <pci.h>
#define NDEBUG
#include <debug.h>
#ifdef ALLOC_PRAGMA
// Make the initialization routines discardable, so that they
// don't waste space
#pragma alloc_text(init, DriverEntry)
#endif /* ALLOC_PRAGMA */
/*** 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;
}
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 & 1));
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;
}
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;
}
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;
}
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 & 1), 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;
}
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;
}
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(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status;
DPRINT("Called. IRP is at (0x%X)\n", Irp);
Irp->IoStatus.Information = 0;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
default:
DPRINT("Unknown IOCTL 0x%X\n", IrpSp->Parameters.DeviceIoControl.IoControlCode);
Status = STATUS_NOT_IMPLEMENTED;
break;
}
if (Status != STATUS_PENDING) {
Irp->IoStatus.Status = Status;
DPRINT("Completing IRP at 0x%X\n", Irp);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
DPRINT("Leaving. Status 0x%X\n", Status);
return Status;
}
NTSTATUS
STDCALL
PciPnpControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
/*
* FUNCTION: Handle Plug and Play IRPs
* ARGUMENTS:
* DeviceObject = Pointer to PDO or FDO
* Irp = Pointer to IRP that should be handled
* RETURNS:
* Status
*/
{
PCOMMON_DEVICE_EXTENSION DeviceExtension;
NTSTATUS Status;
DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
DPRINT("IsFDO %d\n", DeviceExtension->IsFDO);
if (DeviceExtension->IsFDO) {
Status = FdoPnpControl(DeviceObject, Irp);
} else {
Status = PdoPnpControl(DeviceObject, Irp);
}
return Status;
}
NTSTATUS
STDCALL
PciPowerControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
/*
* FUNCTION: Handle power management IRPs
* ARGUMENTS:
* DeviceObject = Pointer to PDO or FDO
* Irp = Pointer to IRP that should be handled
* RETURNS:
* Status
*/
{
PCOMMON_DEVICE_EXTENSION DeviceExtension;
NTSTATUS Status;
DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
if (DeviceExtension->IsFDO) {
Status = FdoPowerControl(DeviceObject, Irp);
} else {
Status = PdoPowerControl(DeviceObject, Irp);
}
return Status;
}
NTSTATUS
STDCALL
PciAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject)
{
PFDO_DEVICE_EXTENSION DeviceExtension;
PDEVICE_OBJECT Fdo;
NTSTATUS Status;
DPRINT("Called\n");
Status = IoCreateDevice(DriverObject, sizeof(FDO_DEVICE_EXTENSION),
NULL, FILE_DEVICE_BUS_EXTENDER, FILE_DEVICE_SECURE_OPEN, TRUE, &Fdo);
if (!NT_SUCCESS(Status)) {
DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
return Status;
}
DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension;
RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION));
DeviceExtension->IsFDO = TRUE;
DeviceExtension->Ldo =
IoAttachDeviceToDeviceStack(Fdo, PhysicalDeviceObject);
DeviceExtension->State = dsStopped;
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
//Fdo->Flags |= DO_POWER_PAGABLE;
DPRINT("Done AddDevice\n");
return STATUS_SUCCESS;
}
NTSTATUS
STDCALL
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
DbgPrint("Peripheral Component Interconnect Bus Driver\n");
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PciDispatchDeviceControl;
DriverObject->MajorFunction[IRP_MJ_PNP] = PciPnpControl;
DriverObject->MajorFunction[IRP_MJ_POWER] = PciPowerControl;
DriverObject->DriverExtension->AddDevice = PciAddDevice;
return STATUS_SUCCESS;
}
BOOLEAN
PciCreateUnicodeString(
PUNICODE_STRING Destination,
PWSTR Source,
POOL_TYPE PoolType)
{
ULONG Length;
if (!Source)
{
RtlInitUnicodeString(Destination, NULL);
return TRUE;
}
Length = (wcslen(Source) + 1) * sizeof(WCHAR);
Destination->Buffer = ExAllocatePool(PoolType, Length);
if (Destination->Buffer == NULL)
{
return FALSE;
}
RtlCopyMemory(Destination->Buffer, Source, Length);
Destination->MaximumLength = Length;
Destination->Length = Length - sizeof(WCHAR);
return TRUE;
}
/* EOF */

View file

@ -0,0 +1,129 @@
/* $Id: pci.h,v 1.1 2001/09/16 13:18:24 chorns Exp $ */
#ifndef __PCI_H
#define __PCI_H
#include <ddk/ntddk.h>
#include <pcidef.h>
typedef enum {
pbtUnknown = 0,
pbtType1,
pbtType2,
} PCI_BUS_TYPE;
typedef struct _PCI_DEVICE
{
// Entry on device list
LIST_ENTRY ListEntry;
// Physical Device Object of device
PDEVICE_OBJECT Pdo;
// PCI configuration data
PCI_COMMON_CONFIG PciConfig;
// Flag used during enumeration to locate removed devices
BOOLEAN RemovePending;
} PCI_DEVICE, *PPCI_DEVICE;
typedef enum {
dsStopped,
dsStarted,
dsPaused,
dsRemoved,
dsSurpriseRemoved
} PCI_DEVICE_STATE;
typedef struct _COMMON_DEVICE_EXTENSION
{
// Pointer to device object, this device extension is associated with
PDEVICE_OBJECT DeviceObject;
// Wether this device extension is for an FDO or PDO
BOOLEAN IsFDO;
// Wether the device is removed
BOOLEAN Removed;
// Current device power state for the device
DEVICE_POWER_STATE DevicePowerState;
} __attribute((packed)) COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
/* Physical Device Object device extension for a child device */
typedef struct _PDO_DEVICE_EXTENSION
{
// Common device data
COMMON_DEVICE_EXTENSION;
// Device ID
UNICODE_STRING DeviceID;
// Instance ID
UNICODE_STRING InstanceID;
// Hardware IDs
UNICODE_STRING HardwareIDs;
// Compatible IDs
UNICODE_STRING CompatibleIDs;
// Textual description of device
UNICODE_STRING DeviceText;
// Textual description of device
UNICODE_STRING DeviceTextLocation;
} __attribute((packed)) PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
/* Functional Device Object device extension for the PCI driver device object */
typedef struct _FDO_DEVICE_EXTENSION
{
// Common device data
COMMON_DEVICE_EXTENSION;
// Physical Device Object
PDEVICE_OBJECT Pdo;
// Current state of the driver
PCI_DEVICE_STATE State;
// Namespace device list
LIST_ENTRY DeviceListHead;
// Number of (not removed) devices in device list
ULONG DeviceListCount;
// Lock for namespace device list
KSPIN_LOCK DeviceListLock;
// PCI bus number
ULONG BusNumber;
// Lower device object
PDEVICE_OBJECT Ldo;
} __attribute((packed)) FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
/* fdo.c */
NTSTATUS
FdoPnpControl(
PDEVICE_OBJECT DeviceObject,
PIRP Irp);
NTSTATUS
FdoPowerControl(
PDEVICE_OBJECT DeviceObject,
PIRP Irp);
/* pci.c */
extern PCI_BUS_TYPE PciBusConfigType;
PCI_BUS_TYPE
PciGetBusConfigType(VOID);
BOOLEAN
PciCreateUnicodeString(
PUNICODE_STRING Destination,
PWSTR Source,
POOL_TYPE PoolType);
/* pdo.c */
NTSTATUS
PdoPnpControl(
PDEVICE_OBJECT DeviceObject,
PIRP Irp);
NTSTATUS
PdoPowerControl(
PDEVICE_OBJECT DeviceObject,
PIRP Irp);
#endif /* __PCI_H */

View file

@ -0,0 +1,38 @@
#include <defines.h>
#include <reactos/resource.h>
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
VS_VERSION_INFO VERSIONINFO
FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", RES_STR_COMPANY_NAME
VALUE "FileDescription", "PCI Bus Driver\0"
VALUE "FileVersion", "0.0.0\0"
VALUE "InternalName", "pci\0"
VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
VALUE "OriginalFilename", "pci.sys\0"
VALUE "ProductName", RES_STR_PRODUCT_NAME
VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

View file

@ -0,0 +1,354 @@
/*
* $Id: pcidef.h,v 1.1 2001/09/16 13:18:24 chorns Exp $
*
* PCI defines and function prototypes
* Copyright 1994, Drew Eckhardt
* Copyright 1997--1999 Martin Mares <mj@suse.cz>
*
* For more information, please consult the following manuals (look at
* http://www.pcisig.com/ for how to get them):
*
* PCI BIOS Specification
* PCI Local Bus Specification
* PCI to PCI Bridge Specification
* PCI System Design Guide
*
* Ported from linux pci.h to ReactOS by:
* Casper S. Hornstrup (chorns@users.sourceforge.net)
*/
#ifndef _PCIDEF_H
#define _PCIDEF_H
/*
* Under PCI, each device has 256 bytes of configuration address space,
* of which the first 64 bytes are standardized as follows:
*/
#define PCI_VENDOR_ID 0x00 /* 16 bits */
#define PCI_DEVICE_ID 0x02 /* 16 bits */
#define PCI_COMMAND 0x04 /* 16 bits */
#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */
#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */
#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */
#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */
#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */
#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */
#define PCI_COMMAND_SERR 0x100 /* Enable SERR */
#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */
#define PCI_STATUS 0x06 /* 16 bits */
#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */
#define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */
#define PCI_STATUS_UDF 0x40 /* Support User Definable Features [obsolete] */
#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */
#define PCI_STATUS_PARITY 0x100 /* Detected parity error */
#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */
#define PCI_STATUS_DEVSEL_FAST 0x000
#define PCI_STATUS_DEVSEL_MEDIUM 0x200
#define PCI_STATUS_DEVSEL_SLOW 0x400
#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */
#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */
#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */
#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */
#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */
#define PCI_CLASS_REVISION 0x08 /* High 24 bits are class, low 8
revision */
#define PCI_REVISION_ID 0x08 /* Revision ID */
#define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */
#define PCI_CLASS_DEVICE 0x0a /* Device class */
#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */
#define PCI_LATENCY_TIMER 0x0d /* 8 bits */
#define PCI_HEADER_TYPE 0x0e /* 8 bits */
#define PCI_HEADER_TYPE_NORMAL 0
#define PCI_HEADER_TYPE_BRIDGE 1
#define PCI_HEADER_TYPE_CARDBUS 2
#define PCI_BIST 0x0f /* 8 bits */
#define PCI_BIST_CODE_MASK 0x0f /* Return result */
#define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or less */
#define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */
/*
* Base addresses specify locations in memory or I/O space.
* Decoded size can be determined by writing a value of
* 0xffffffff to the register, and reading it back. Only
* 1 bits are decoded.
*/
#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */
#define PCI_BASE_ADDRESS_1 0x14 /* 32 bits [htype 0,1 only] */
#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits [htype 0 only] */
#define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */
#define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */
#define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */
#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */
#define PCI_BASE_ADDRESS_SPACE_IO 0x01
#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */
#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */
#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */
#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */
#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL)
#define PCI_BASE_ADDRESS_IO_MASK (~0x03UL)
/* bit 1 is reserved if address_space = 1 */
/* Header type 0 (normal devices) */
#define PCI_CARDBUS_CIS 0x28
#define PCI_SUBSYSTEM_VENDOR_ID 0x2c
#define PCI_SUBSYSTEM_ID 0x2e
#define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */
#define PCI_ROM_ADDRESS_ENABLE 0x01
#define PCI_ROM_ADDRESS_MASK (~0x7ffUL)
#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */
/* 0x35-0x3b are reserved */
#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
#define PCI_MIN_GNT 0x3e /* 8 bits */
#define PCI_MAX_LAT 0x3f /* 8 bits */
/* Header type 1 (PCI-to-PCI bridges) */
#define PCI_PRIMARY_BUS 0x18 /* Primary bus number */
#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */
#define PCI_SUBORDINATE_BUS 0x1a /* Highest bus number behind the bridge */
#define PCI_SEC_LATENCY_TIMER 0x1b /* Latency timer for secondary interface */
#define PCI_IO_BASE 0x1c /* I/O range behind the bridge */
#define PCI_IO_LIMIT 0x1d
#define PCI_IO_RANGE_TYPE_MASK 0x0f /* I/O bridging type */
#define PCI_IO_RANGE_TYPE_16 0x00
#define PCI_IO_RANGE_TYPE_32 0x01
#define PCI_IO_RANGE_MASK ~0x0f
#define PCI_SEC_STATUS 0x1e /* Secondary status register, only bit 14 used */
#define PCI_MEMORY_BASE 0x20 /* Memory range behind */
#define PCI_MEMORY_LIMIT 0x22
#define PCI_MEMORY_RANGE_TYPE_MASK 0x0f
#define PCI_MEMORY_RANGE_MASK ~0x0f
#define PCI_PREF_MEMORY_BASE 0x24 /* Prefetchable memory range behind */
#define PCI_PREF_MEMORY_LIMIT 0x26
#define PCI_PREF_RANGE_TYPE_MASK 0x0f
#define PCI_PREF_RANGE_TYPE_32 0x00
#define PCI_PREF_RANGE_TYPE_64 0x01
#define PCI_PREF_RANGE_MASK ~0x0f
#define PCI_PREF_BASE_UPPER32 0x28 /* Upper half of prefetchable memory range */
#define PCI_PREF_LIMIT_UPPER32 0x2c
#define PCI_IO_BASE_UPPER16 0x30 /* Upper half of I/O addresses */
#define PCI_IO_LIMIT_UPPER16 0x32
/* 0x34 same as for htype 0 */
/* 0x35-0x3b is reserved */
#define PCI_ROM_ADDRESS1 0x38 /* Same as PCI_ROM_ADDRESS, but for htype 1 */
/* 0x3c-0x3d are same as for htype 0 */
#define PCI_BRIDGE_CONTROL 0x3e
#define PCI_BRIDGE_CTL_PARITY 0x01 /* Enable parity detection on secondary interface */
#define PCI_BRIDGE_CTL_SERR 0x02 /* The same for SERR forwarding */
#define PCI_BRIDGE_CTL_NO_ISA 0x04 /* Disable bridging of ISA ports */
#define PCI_BRIDGE_CTL_VGA 0x08 /* Forward VGA addresses */
#define PCI_BRIDGE_CTL_MASTER_ABORT 0x20 /* Report master aborts */
#define PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */
#define PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */
/* Header type 2 (CardBus bridges) */
#define PCI_CB_CAPABILITY_LIST 0x14
/* 0x15 reserved */
#define PCI_CB_SEC_STATUS 0x16 /* Secondary status */
#define PCI_CB_PRIMARY_BUS 0x18 /* PCI bus number */
#define PCI_CB_CARD_BUS 0x19 /* CardBus bus number */
#define PCI_CB_SUBORDINATE_BUS 0x1a /* Subordinate bus number */
#define PCI_CB_LATENCY_TIMER 0x1b /* CardBus latency timer */
#define PCI_CB_MEMORY_BASE_0 0x1c
#define PCI_CB_MEMORY_LIMIT_0 0x20
#define PCI_CB_MEMORY_BASE_1 0x24
#define PCI_CB_MEMORY_LIMIT_1 0x28
#define PCI_CB_IO_BASE_0 0x2c
#define PCI_CB_IO_BASE_0_HI 0x2e
#define PCI_CB_IO_LIMIT_0 0x30
#define PCI_CB_IO_LIMIT_0_HI 0x32
#define PCI_CB_IO_BASE_1 0x34
#define PCI_CB_IO_BASE_1_HI 0x36
#define PCI_CB_IO_LIMIT_1 0x38
#define PCI_CB_IO_LIMIT_1_HI 0x3a
#define PCI_CB_IO_RANGE_MASK ~0x03
/* 0x3c-0x3d are same as for htype 0 */
#define PCI_CB_BRIDGE_CONTROL 0x3e
#define PCI_CB_BRIDGE_CTL_PARITY 0x01 /* Similar to standard bridge control register */
#define PCI_CB_BRIDGE_CTL_SERR 0x02
#define PCI_CB_BRIDGE_CTL_ISA 0x04
#define PCI_CB_BRIDGE_CTL_VGA 0x08
#define PCI_CB_BRIDGE_CTL_MASTER_ABORT 0x20
#define PCI_CB_BRIDGE_CTL_CB_RESET 0x40 /* CardBus reset */
#define PCI_CB_BRIDGE_CTL_16BIT_INT 0x80 /* Enable interrupt for 16-bit cards */
#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100 /* Prefetch enable for both memory regions */
#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200
#define PCI_CB_BRIDGE_CTL_POST_WRITES 0x400
#define PCI_CB_SUBSYSTEM_VENDOR_ID 0x40
#define PCI_CB_SUBSYSTEM_ID 0x42
#define PCI_CB_LEGACY_MODE_BASE 0x44 /* 16-bit PC Card legacy mode base address (ExCa) */
/* 0x48-0x7f reserved */
/* Capability lists */
#define PCI_CAP_LIST_ID 0 /* Capability ID */
#define PCI_CAP_ID_PM 0x01 /* Power Management */
#define PCI_CAP_ID_AGP 0x02 /* Accelerated Graphics Port */
#define PCI_CAP_ID_VPD 0x03 /* Vital Product Data */
#define PCI_CAP_ID_SLOTID 0x04 /* Slot Identification */
#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */
#define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */
#define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */
#define PCI_CAP_FLAGS 2 /* Capability defined flags (16 bits) */
#define PCI_CAP_SIZEOF 4
/* Power Management Registers */
#define PCI_PM_PMC 2 /* PM Capabilities Register */
#define PCI_PM_CAP_VER_MASK 0x0007 /* Version */
#define PCI_PM_CAP_PME_CLOCK 0x0008 /* PME clock required */
#define PCI_PM_CAP_RESERVED 0x0010 /* Reserved field */
#define PCI_PM_CAP_DSI 0x0020 /* Device specific initialization */
#define PCI_PM_CAP_AUX_POWER 0x01C0 /* Auxilliary power support mask */
#define PCI_PM_CAP_D1 0x0200 /* D1 power state support */
#define PCI_PM_CAP_D2 0x0400 /* D2 power state support */
#define PCI_PM_CAP_PME 0x0800 /* PME pin supported */
#define PCI_PM_CAP_PME_MASK 0xF800 /* PME Mask of all supported states */
#define PCI_PM_CAP_PME_D0 0x0800 /* PME# from D0 */
#define PCI_PM_CAP_PME_D1 0x1000 /* PME# from D1 */
#define PCI_PM_CAP_PME_D2 0x2000 /* PME# from D2 */
#define PCI_PM_CAP_PME_D3 0x4000 /* PME# from D3 (hot) */
#define PCI_PM_CAP_PME_D3cold 0x8000 /* PME# from D3 (cold) */
#define PCI_PM_CTRL 4 /* PM control and status register */
#define PCI_PM_CTRL_STATE_MASK 0x0003 /* Current power state (D0 to D3) */
#define PCI_PM_CTRL_PME_ENABLE 0x0100 /* PME pin enable */
#define PCI_PM_CTRL_DATA_SEL_MASK 0x1e00 /* Data select (??) */
#define PCI_PM_CTRL_DATA_SCALE_MASK 0x6000 /* Data scale (??) */
#define PCI_PM_CTRL_PME_STATUS 0x8000 /* PME pin status */
#define PCI_PM_PPB_EXTENSIONS 6 /* PPB support extensions (??) */
#define PCI_PM_PPB_B2_B3 0x40 /* Stop clock when in D3hot (??) */
#define PCI_PM_BPCC_ENABLE 0x80 /* Bus power/clock control enable (??) */
#define PCI_PM_DATA_REGISTER 7 /* (??) */
#define PCI_PM_SIZEOF 8
/* AGP registers */
#define PCI_AGP_VERSION 2 /* BCD version number */
#define PCI_AGP_RFU 3 /* Rest of capability flags */
#define PCI_AGP_STATUS 4 /* Status register */
#define PCI_AGP_STATUS_RQ_MASK 0xff000000 /* Maximum number of requests - 1 */
#define PCI_AGP_STATUS_SBA 0x0200 /* Sideband addressing supported */
#define PCI_AGP_STATUS_64BIT 0x0020 /* 64-bit addressing supported */
#define PCI_AGP_STATUS_FW 0x0010 /* FW transfers supported */
#define PCI_AGP_STATUS_RATE4 0x0004 /* 4x transfer rate supported */
#define PCI_AGP_STATUS_RATE2 0x0002 /* 2x transfer rate supported */
#define PCI_AGP_STATUS_RATE1 0x0001 /* 1x transfer rate supported */
#define PCI_AGP_COMMAND 8 /* Control register */
#define PCI_AGP_COMMAND_RQ_MASK 0xff000000 /* Master: Maximum number of requests */
#define PCI_AGP_COMMAND_SBA 0x0200 /* Sideband addressing enabled */
#define PCI_AGP_COMMAND_AGP 0x0100 /* Allow processing of AGP transactions */
#define PCI_AGP_COMMAND_64BIT 0x0020 /* Allow processing of 64-bit addresses */
#define PCI_AGP_COMMAND_FW 0x0010 /* Force FW transfers */
#define PCI_AGP_COMMAND_RATE4 0x0004 /* Use 4x rate */
#define PCI_AGP_COMMAND_RATE2 0x0002 /* Use 4x rate */
#define PCI_AGP_COMMAND_RATE1 0x0001 /* Use 4x rate */
#define PCI_AGP_SIZEOF 12
/* Slot Identification */
#define PCI_SID_ESR 2 /* Expansion Slot Register */
#define PCI_SID_ESR_NSLOTS 0x1f /* Number of expansion slots available */
#define PCI_SID_ESR_FIC 0x20 /* First In Chassis Flag */
#define PCI_SID_CHASSIS_NR 3 /* Chassis Number */
/* Message Signalled Interrupts registers */
#define PCI_MSI_FLAGS 2 /* Various flags */
#define PCI_MSI_FLAGS_64BIT 0x80 /* 64-bit addresses allowed */
#define PCI_MSI_FLAGS_QSIZE 0x70 /* Message queue size configured */
#define PCI_MSI_FLAGS_QMASK 0x0e /* Maximum queue size available */
#define PCI_MSI_FLAGS_ENABLE 0x01 /* MSI feature enabled */
#define PCI_MSI_RFU 3 /* Rest of capability flags */
#define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */
#define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
#define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */
#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */
/*
* The PCI interface treats multi-function devices as independent
* devices. The slot/function address of each device is encoded
* in a single byte as follows:
*
* 7:3 = slot
* 2:0 = function
*/
#define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
#define PCI_FUNC(devfn) ((devfn) & 0x07)
/*
* For PCI devices, the region numbers are assigned this way:
*
* 0-5 standard PCI regions
* 6 expansion ROM
* 7-10 bridges: address space assigned to buses behind the bridge
*/
#define PCI_ROM_RESOURCE 6
#define PCI_BRIDGE_RESOURCES 7
#define PCI_NUM_RESOURCES 11
#define PCI_REGION_FLAG_MASK 0x0f /* These bits of resource flags tell us the PCI region flags */
#define PCI_TYPE0_ADDRESSES 6
#define PCI_TYPE1_ADDRESSES 2
typedef struct _PCI_COMMON_CONFIG
{
USHORT VendorID; // (ro)
USHORT DeviceID; // (ro)
USHORT Command; // Device control
USHORT Status;
UCHAR RevisionID; // (ro)
UCHAR ProgIf; // (ro)
UCHAR SubClass; // (ro)
UCHAR BaseClass; // (ro)
UCHAR CacheLineSize; // (ro+)
UCHAR LatencyTimer; // (ro+)
UCHAR HeaderType; // (ro)
UCHAR BIST; // Built in self test
union
{
struct _PCI_HEADER_TYPE_0
{
ULONG BaseAddresses[PCI_TYPE0_ADDRESSES];
ULONG CIS;
USHORT SubVendorID;
USHORT SubSystemID;
ULONG ROMBaseAddress;
UCHAR Capabilities;
UCHAR Reserved2[3];
ULONG Reserved3;
UCHAR InterruptLine; //
UCHAR InterruptPin; // (ro)
UCHAR MinimumGrant; /* read-only */
UCHAR MaximumLatency; /* read-only */
} type0;
} u;
UCHAR DeviceSpecific[192];
} __attribute__((packed)) PCI_COMMON_CONFIG, *PPCI_COMMON_CONFIG;
#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

@ -0,0 +1,242 @@
/* $Id: pdo.c,v 1.1 2001/09/16 13:18:24 chorns Exp $
*
* PROJECT: ReactOS PCI bus driver
* FILE: pdo.c
* PURPOSE: Child device object dispatch routines
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* UPDATE HISTORY:
* 10-09-2001 CSH Created
*/
#include <pci.h>
#define NDEBUG
#include <debug.h>
/*** PRIVATE *****************************************************************/
NTSTATUS
PdoQueryId(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
PIO_STACK_LOCATION IrpSp)
{
PPDO_DEVICE_EXTENSION DeviceExtension;
UNICODE_STRING String;
NTSTATUS Status;
DPRINT("Called\n");
DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
// Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS;
RtlInitUnicodeString(&String, NULL);
switch (IrpSp->Parameters.QueryId.IdType) {
case BusQueryDeviceID:
Status = PciCreateUnicodeString(
&String,
DeviceExtension->DeviceID.Buffer,
PagedPool);
DPRINT("DeviceID: %S\n", String.Buffer);
Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
break;
case BusQueryHardwareIDs:
case BusQueryCompatibleIDs:
Status = STATUS_NOT_IMPLEMENTED;
break;
case BusQueryInstanceID:
Status = PciCreateUnicodeString(
&String,
L"0000",
PagedPool);
DPRINT("InstanceID: %S\n", String.Buffer);
Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
break;
case BusQueryDeviceSerialNumber:
default:
Status = STATUS_NOT_IMPLEMENTED;
}
return Status;
}
NTSTATUS
PdoSetPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
PIO_STACK_LOCATION IrpSp)
{
PPDO_DEVICE_EXTENSION DeviceExtension;
NTSTATUS Status;
DPRINT("Called\n");
DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
if (IrpSp->Parameters.Power.Type == DevicePowerState) {
Status = STATUS_SUCCESS;
switch (IrpSp->Parameters.Power.State.SystemState) {
default:
Status = STATUS_UNSUCCESSFUL;
}
} else {
Status = STATUS_UNSUCCESSFUL;
}
return Status;
}
/*** PUBLIC ******************************************************************/
NTSTATUS
PdoPnpControl(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
/*
* FUNCTION: Handle Plug and Play IRPs for the child device
* ARGUMENTS:
* DeviceObject = Pointer to physical device object of the child device
* Irp = Pointer to IRP that should be handled
* RETURNS:
* Status
*/
{
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status;
DPRINT("Called\n");
Status = Irp->IoStatus.Status;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
switch (IrpSp->MinorFunction) {
#if 0
case IRP_MN_CANCEL_REMOVE_DEVICE:
break;
case IRP_MN_CANCEL_STOP_DEVICE:
break;
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
break;
case IRP_MN_EJECT:
break;
case IRP_MN_QUERY_BUS_INFORMATION:
break;
case IRP_MN_QUERY_CAPABILITIES:
break;
case IRP_MN_QUERY_DEVICE_RELATIONS:
/* FIXME: Possibly handle for RemovalRelations */
break;
case IRP_MN_QUERY_DEVICE_TEXT:
break;
#endif
case IRP_MN_QUERY_ID:
Status = PdoQueryId(DeviceObject, Irp, IrpSp);
break;
#if 0
case IRP_MN_QUERY_PNP_DEVICE_STATE:
break;
case IRP_MN_QUERY_REMOVE_DEVICE:
break;
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
break;
case IRP_MN_QUERY_RESOURCES:
break;
case IRP_MN_QUERY_STOP_DEVICE:
break;
case IRP_MN_REMOVE_DEVICE:
break;
case IRP_MN_SET_LOCK:
break;
case IRP_MN_START_DEVICE:
break;
case IRP_MN_STOP_DEVICE:
break;
case IRP_MN_SURPRISE_REMOVAL:
break;
#endif
default:
DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
break;
}
if (Status != STATUS_PENDING) {
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
DPRINT("Leaving. Status 0x%X\n", Status);
return Status;
}
NTSTATUS
PdoPowerControl(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
/*
* FUNCTION: Handle power management IRPs for the child device
* ARGUMENTS:
* DeviceObject = Pointer to physical device object of the child device
* Irp = Pointer to IRP that should be handled
* RETURNS:
* Status
*/
{
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status;
DPRINT("Called\n");
IrpSp = IoGetCurrentIrpStackLocation(Irp);
switch (IrpSp->MinorFunction) {
case IRP_MN_SET_POWER:
Status = PdoSetPower(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 */