mirror of
https://github.com/reactos/reactos.git
synced 2024-11-01 12:26:32 +00:00
406 lines
12 KiB
C
406 lines
12 KiB
C
/*
|
|
* PROJECT: ReactOS PCI Bus Driver
|
|
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
|
* FILE: drivers/bus/pci/debug.c
|
|
* PURPOSE: Debug Helpers
|
|
* PROGRAMMERS: ReactOS Portable Systems Group
|
|
*/
|
|
|
|
/* INCLUDES *******************************************************************/
|
|
|
|
#include <pci.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
/* GLOBALS ********************************************************************/
|
|
|
|
PCHAR PnpCodes[] =
|
|
{
|
|
"START_DEVICE",
|
|
"QUERY_REMOVE_DEVICE",
|
|
"REMOVE_DEVICE",
|
|
"CANCEL_REMOVE_DEVICE",
|
|
"STOP_DEVICE",
|
|
"QUERY_STOP_DEVICE",
|
|
"CANCEL_STOP_DEVICE",
|
|
"QUERY_DEVICE_RELATIONS",
|
|
"QUERY_INTERFACE",
|
|
"QUERY_CAPABILITIES",
|
|
"QUERY_RESOURCES",
|
|
"QUERY_RESOURCE_REQUIREMENTS",
|
|
"QUERY_DEVICE_TEXT",
|
|
"FILTER_RESOURCE_REQUIREMENTS",
|
|
"** UNKNOWN PNP IRP Minor Code **",
|
|
"READ_CONFIG",
|
|
"WRITE_CONFIG",
|
|
"EJECT",
|
|
"SET_LOCK",
|
|
"QUERY_ID",
|
|
"QUERY_PNP_DEVICE_STATE",
|
|
"QUERY_BUS_INFORMATION",
|
|
"DEVICE_USAGE_NOTIFICATION"
|
|
};
|
|
|
|
PCHAR PoCodes[] =
|
|
{
|
|
"WAIT_WAKE",
|
|
"POWER_SEQUENCE",
|
|
"SET_POWER",
|
|
"QUERY_POWER",
|
|
};
|
|
|
|
PCHAR SystemPowerStates[] =
|
|
{
|
|
"Unspecified",
|
|
"Working",
|
|
"Sleeping1",
|
|
"Sleeping2",
|
|
"Sleeping3",
|
|
"Hibernate",
|
|
"Shutdown"
|
|
};
|
|
|
|
PCHAR DevicePowerStates[] =
|
|
{
|
|
"Unspecified",
|
|
"D0",
|
|
"D1",
|
|
"D2",
|
|
"D3"
|
|
};
|
|
|
|
ULONG PciBreakOnPdoPowerIrp, PciBreakOnFdoPowerIrp;
|
|
ULONG PciBreakOnPdoPnpIrp, PciBreakOnFdoPnpIrp;
|
|
|
|
/* FUNCTIONS ******************************************************************/
|
|
|
|
PCHAR
|
|
NTAPI
|
|
PciDebugPnpIrpTypeToText(IN USHORT MinorFunction)
|
|
{
|
|
PCHAR Text;
|
|
|
|
/* Catch invalid code */
|
|
if (MinorFunction >= IRP_MN_SURPRISE_REMOVAL)
|
|
{
|
|
/* New version of Windows? Or driver bug */
|
|
Text = "** UNKNOWN PNP IRP Minor Code **";
|
|
}
|
|
else
|
|
{
|
|
/* Get the right text for it */
|
|
Text = PnpCodes[MinorFunction];
|
|
}
|
|
|
|
/* Return the symbolic name for the IRP */
|
|
return Text;
|
|
}
|
|
|
|
PCHAR
|
|
NTAPI
|
|
PciDebugPoIrpTypeToText(IN USHORT MinorFunction)
|
|
{
|
|
PCHAR Text;
|
|
|
|
/* Catch invalid code */
|
|
if (MinorFunction >= IRP_MN_QUERY_POWER)
|
|
{
|
|
/* New version of Windows? Or driver bug */
|
|
Text = "** UNKNOWN PO IRP Minor Code **";
|
|
}
|
|
else
|
|
{
|
|
/* Get the right text for it */
|
|
Text = PoCodes[MinorFunction];
|
|
}
|
|
|
|
/* Return the symbolic name for the IRP */
|
|
return Text;
|
|
}
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
PciDebugIrpDispatchDisplay(IN PIO_STACK_LOCATION IoStackLocation,
|
|
IN PPCI_FDO_EXTENSION DeviceExtension,
|
|
IN USHORT MaxMinor)
|
|
{
|
|
PPCI_PDO_EXTENSION PdoDeviceExtension;
|
|
ULONG BreakMask;
|
|
//ULONG DebugLevel = 0;
|
|
PCHAR IrpString;
|
|
|
|
/* Only two functions are recognized */
|
|
switch (IoStackLocation->MajorFunction)
|
|
{
|
|
case IRP_MJ_POWER:
|
|
|
|
/* Get the string and the correct break mask for the extension */
|
|
BreakMask = (DeviceExtension->ExtensionType == PciPdoExtensionType) ?
|
|
PciBreakOnPdoPowerIrp : PciBreakOnFdoPowerIrp;
|
|
IrpString = PciDebugPoIrpTypeToText(IoStackLocation->MinorFunction);
|
|
break;
|
|
|
|
case IRP_MJ_PNP:
|
|
|
|
/* Get the string and the correct break mask for the extension */
|
|
BreakMask = (DeviceExtension->ExtensionType == PciFdoExtensionType) ?
|
|
PciBreakOnPdoPnpIrp : PciBreakOnFdoPnpIrp;
|
|
IrpString = PciDebugPnpIrpTypeToText(IoStackLocation->MinorFunction);
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Other functions are not decoded */
|
|
BreakMask = FALSE;
|
|
IrpString = "";
|
|
break;
|
|
}
|
|
|
|
/* Check if this is a PDO */
|
|
if (DeviceExtension->ExtensionType == PciPdoExtensionType)
|
|
{
|
|
/* Choose the correct debug level based on which function this is */
|
|
if (IoStackLocation->MajorFunction == IRP_MJ_POWER)
|
|
{
|
|
//DebugLevel = 0x500;
|
|
}
|
|
else if (IoStackLocation->MajorFunction == IRP_MJ_PNP)
|
|
{
|
|
//DebugLevel = 0x200;
|
|
}
|
|
|
|
/* For a PDO, print out the bus, device, and function number */
|
|
PdoDeviceExtension = (PVOID)DeviceExtension;
|
|
DPRINT1("PDO(b=0x%x, d=0x%x, f=0x%x)<-%s\n",
|
|
PdoDeviceExtension->ParentFdoExtension->BaseBus,
|
|
PdoDeviceExtension->Slot.u.bits.DeviceNumber,
|
|
PdoDeviceExtension->Slot.u.bits.FunctionNumber,
|
|
IrpString);
|
|
}
|
|
else if (DeviceExtension->ExtensionType == PciFdoExtensionType)
|
|
{
|
|
/* Choose the correct debug level based on which function this is */
|
|
if (IoStackLocation->MajorFunction == IRP_MJ_POWER)
|
|
{
|
|
//DebugLevel = 0x400;
|
|
}
|
|
else if (IoStackLocation->MajorFunction == IRP_MJ_PNP)
|
|
{
|
|
//DebugLevel = 0x100;
|
|
}
|
|
|
|
/* For an FDO, just dump the extension pointer and IRP string */
|
|
DPRINT1("FDO(%p)<-%s\n", DeviceExtension, IrpString);
|
|
}
|
|
|
|
/* If the function is illegal for this extension, complain */
|
|
if (IoStackLocation->MinorFunction > MaxMinor)
|
|
DPRINT1("Unknown IRP, minor = 0x%x\n", IoStackLocation->MinorFunction);
|
|
|
|
/* Return whether or not the debugger should be broken into for this IRP */
|
|
return ((1 << IoStackLocation->MinorFunction) & BreakMask);
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
PciDebugDumpCommonConfig(IN PPCI_COMMON_HEADER PciData)
|
|
{
|
|
USHORT i;
|
|
|
|
/* Loop the PCI header */
|
|
for (i = 0; i < PCI_COMMON_HDR_LENGTH; i += 4)
|
|
{
|
|
/* Dump each DWORD and its offset */
|
|
DPRINT1(" %02x - %08x\n", i, *(PULONG)((ULONG_PTR)PciData + i));
|
|
}
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
PciDebugDumpQueryCapabilities(IN PDEVICE_CAPABILITIES DeviceCaps)
|
|
{
|
|
ULONG i;
|
|
|
|
/* Dump the capabilities */
|
|
DPRINT1("Capabilities\n Lock:%u, Eject:%u, Remove:%u, Dock:%u, UniqueId:%u\n",
|
|
DeviceCaps->LockSupported,
|
|
DeviceCaps->EjectSupported,
|
|
DeviceCaps->Removable,
|
|
DeviceCaps->DockDevice,
|
|
DeviceCaps->UniqueID);
|
|
DbgPrint(" SilentInstall:%u, RawOk:%u, SurpriseOk:%u\n",
|
|
DeviceCaps->SilentInstall,
|
|
DeviceCaps->RawDeviceOK,
|
|
DeviceCaps->SurpriseRemovalOK);
|
|
DbgPrint(" Address %08x, UINumber %08x, Latencies D1 %u, D2 %u, D3 %u\n",
|
|
DeviceCaps->Address,
|
|
DeviceCaps->UINumber,
|
|
DeviceCaps->D1Latency,
|
|
DeviceCaps->D2Latency,
|
|
DeviceCaps->D3Latency);
|
|
|
|
/* Dump and convert the wake levels */
|
|
DbgPrint(" System Wake: %s, Device Wake: %s\n DeviceState[PowerState] [",
|
|
SystemPowerStates[min(DeviceCaps->SystemWake, PowerSystemMaximum)],
|
|
DevicePowerStates[min(DeviceCaps->DeviceWake, PowerDeviceMaximum)]);
|
|
|
|
/* Dump and convert the power state mappings */
|
|
for (i = PowerSystemWorking; i < PowerSystemMaximum; i++)
|
|
DbgPrint(" %s", DevicePowerStates[DeviceCaps->DeviceState[i]]);
|
|
|
|
/* Finish the dump */
|
|
DbgPrint(" ]\n");
|
|
}
|
|
|
|
PCHAR
|
|
NTAPI
|
|
PciDebugCmResourceTypeToText(IN UCHAR Type)
|
|
{
|
|
/* What kind of resource it this? */
|
|
switch (Type)
|
|
{
|
|
/* Pick the correct identifier string based on the type */
|
|
case CmResourceTypeDeviceSpecific: return "CmResourceTypeDeviceSpecific";
|
|
case CmResourceTypePort: return "CmResourceTypePort";
|
|
case CmResourceTypeInterrupt: return "CmResourceTypeInterrupt";
|
|
case CmResourceTypeMemory: return "CmResourceTypeMemory";
|
|
case CmResourceTypeDma: return "CmResourceTypeDma";
|
|
case CmResourceTypeBusNumber: return "CmResourceTypeBusNumber";
|
|
case CmResourceTypeConfigData: return "CmResourceTypeConfigData";
|
|
case CmResourceTypeDevicePrivate: return "CmResourceTypeDevicePrivate";
|
|
case CmResourceTypePcCardConfig: return "CmResourceTypePcCardConfig";
|
|
default: return "*** INVALID RESOURCE TYPE ***";
|
|
}
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
PciDebugPrintIoResource(IN PIO_RESOURCE_DESCRIPTOR Descriptor)
|
|
{
|
|
ULONG i;
|
|
PULONG Data;
|
|
|
|
/* Print out the header */
|
|
DPRINT1(" IoResource Descriptor dump: Descriptor @0x%p\n", Descriptor);
|
|
DPRINT1(" Option = 0x%x\n", Descriptor->Option);
|
|
DPRINT1(" Type = %u (%s)\n", Descriptor->Type, PciDebugCmResourceTypeToText(Descriptor->Type));
|
|
DPRINT1(" ShareDisposition = %u\n", Descriptor->ShareDisposition);
|
|
DPRINT1(" Flags = 0x%04X\n", Descriptor->Flags);
|
|
|
|
/* Loop private data */
|
|
Data = (PULONG)&Descriptor->u.DevicePrivate;
|
|
for (i = 0; i < 6; i += 3)
|
|
{
|
|
/* Dump it in 32-bit triplets */
|
|
DPRINT1(" Data[%u] = %08x %08x %08x\n", i, Data[0], Data[1], Data[2]);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
PciDebugPrintIoResReqList(IN PIO_RESOURCE_REQUIREMENTS_LIST Requirements)
|
|
{
|
|
ULONG AlternativeLists;
|
|
PIO_RESOURCE_LIST List;
|
|
ULONG Count;
|
|
PIO_RESOURCE_DESCRIPTOR Descriptor;
|
|
|
|
/* Make sure there's a list */
|
|
if (!Requirements) return;
|
|
|
|
/* Grab the main list and the alternates as well */
|
|
AlternativeLists = Requirements->AlternativeLists;
|
|
List = Requirements->List;
|
|
|
|
/* Print out the initial header*/
|
|
DPRINT1(" IO_RESOURCE_REQUIREMENTS_LIST (PCI Bus Driver)\n");
|
|
DPRINT1(" InterfaceType %d\n", Requirements->InterfaceType);
|
|
DPRINT1(" BusNumber 0x%x\n", Requirements->BusNumber);
|
|
DPRINT1(" SlotNumber %d (0x%x), (d/f = 0x%x/0x%x)\n",
|
|
Requirements->SlotNumber,
|
|
Requirements->SlotNumber,
|
|
((PCI_SLOT_NUMBER*)&Requirements->SlotNumber)->u.bits.DeviceNumber,
|
|
((PCI_SLOT_NUMBER*)&Requirements->SlotNumber)->u.bits.FunctionNumber);
|
|
DPRINT1(" AlternativeLists %u\n", AlternativeLists);
|
|
|
|
/* Scan alternative lists */
|
|
while (AlternativeLists--)
|
|
{
|
|
/* Get the descriptor array, and the count of descriptors */
|
|
Descriptor = List->Descriptors;
|
|
Count = List->Count;
|
|
|
|
/* Print out each descriptor */
|
|
DPRINT1("\n List[%u].Count = %u\n", AlternativeLists, Count);
|
|
while (Count--) PciDebugPrintIoResource(Descriptor++);
|
|
|
|
/* Should've reached a new list now */
|
|
List = (PIO_RESOURCE_LIST)Descriptor;
|
|
}
|
|
|
|
/* Terminate the dump */
|
|
DPRINT1("\n");
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
PciDebugPrintPartialResource(IN PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource)
|
|
{
|
|
/* Dump all the data in the partial */
|
|
DPRINT1(" Partial Resource Descriptor @0x%p\n", PartialResource);
|
|
DPRINT1(" Type = %u (%s)\n", PartialResource->Type, PciDebugCmResourceTypeToText(PartialResource->Type));
|
|
DPRINT1(" ShareDisposition = %u\n", PartialResource->ShareDisposition);
|
|
DPRINT1(" Flags = 0x%04X\n", PartialResource->Flags);
|
|
DPRINT1(" Data[%d] = %08x %08x %08x\n",
|
|
0,
|
|
PartialResource->u.Generic.Start.LowPart,
|
|
PartialResource->u.Generic.Start.HighPart,
|
|
PartialResource->u.Generic.Length);
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
PciDebugPrintCmResList(IN PCM_RESOURCE_LIST PartialList)
|
|
{
|
|
PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
|
|
ULONG Count, i, ListCount;
|
|
|
|
/* Make sure there's something to dump */
|
|
if (!PartialList) return;
|
|
|
|
/* Get the full list count */
|
|
ListCount = PartialList->Count;
|
|
FullDescriptor = PartialList->List;
|
|
DPRINT1(" CM_RESOURCE_LIST (PCI Bus Driver) (List Count = %u)\n", PartialList->Count);
|
|
|
|
/* Loop full list */
|
|
for (i = 0; i < ListCount; i++)
|
|
{
|
|
/* Loop full descriptor */
|
|
DPRINT1(" InterfaceType %d\n", FullDescriptor->InterfaceType);
|
|
DPRINT1(" BusNumber 0x%x\n", FullDescriptor->BusNumber);
|
|
|
|
/* Get partial count and loop partials */
|
|
Count = FullDescriptor->PartialResourceList.Count;
|
|
for (PartialDescriptor = FullDescriptor->PartialResourceList.PartialDescriptors;
|
|
Count;
|
|
PartialDescriptor = CmiGetNextPartialDescriptor(PartialDescriptor))
|
|
{
|
|
/* Print each partial */
|
|
PciDebugPrintPartialResource(PartialDescriptor);
|
|
Count--;
|
|
}
|
|
|
|
/* Go to the next full descriptor */
|
|
FullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)PartialDescriptor;
|
|
}
|
|
|
|
/* Done printing data */
|
|
DPRINT1("\n");
|
|
}
|
|
|
|
|
|
/* EOF */
|