/*++ Copyright (c) 1997-2000 Microsoft Corporation Module Name: debug.c Abstract: This module provides debugging support. Author: Andy Thornton (andrewth) 20-Oct-97 Revision History: --*/ #include "SpSim.h" // // Get mappings from status codes to strings // #include #undef MAP #define MAP(_Value) { (_Value), #_Value } #define END_STRING_MAP { 0xFFFFFFFF, NULL } #if DBG LONG SpSimDebug = -1; PSPSIM_STRING_MAP SpSimDbgStatusStringMap = (PSPSIM_STRING_MAP) ntstatusSymbolicNames; SPSIM_STRING_MAP SpSimDbgPnpIrpStringMap[] = { MAP(IRP_MN_START_DEVICE), MAP(IRP_MN_QUERY_REMOVE_DEVICE), MAP(IRP_MN_REMOVE_DEVICE), MAP(IRP_MN_CANCEL_REMOVE_DEVICE), MAP(IRP_MN_STOP_DEVICE), MAP(IRP_MN_QUERY_STOP_DEVICE), MAP(IRP_MN_CANCEL_STOP_DEVICE), MAP(IRP_MN_QUERY_DEVICE_RELATIONS), MAP(IRP_MN_QUERY_INTERFACE), MAP(IRP_MN_QUERY_CAPABILITIES), MAP(IRP_MN_QUERY_RESOURCES), MAP(IRP_MN_QUERY_RESOURCE_REQUIREMENTS), MAP(IRP_MN_QUERY_DEVICE_TEXT), MAP(IRP_MN_FILTER_RESOURCE_REQUIREMENTS), MAP(IRP_MN_READ_CONFIG), MAP(IRP_MN_WRITE_CONFIG), MAP(IRP_MN_EJECT), MAP(IRP_MN_SET_LOCK), MAP(IRP_MN_QUERY_ID), MAP(IRP_MN_QUERY_PNP_DEVICE_STATE), MAP(IRP_MN_QUERY_BUS_INFORMATION), MAP(IRP_MN_DEVICE_USAGE_NOTIFICATION), MAP(IRP_MN_SURPRISE_REMOVAL), END_STRING_MAP }; SPSIM_STRING_MAP SpSimDbgPoIrpStringMap[] = { MAP(IRP_MN_WAIT_WAKE), MAP(IRP_MN_POWER_SEQUENCE), MAP(IRP_MN_SET_POWER), MAP(IRP_MN_QUERY_POWER), END_STRING_MAP }; SPSIM_STRING_MAP SpSimDbgDeviceRelationStringMap[] = { MAP(BusRelations), MAP(EjectionRelations), MAP(PowerRelations), MAP(RemovalRelations), MAP(TargetDeviceRelation), END_STRING_MAP }; SPSIM_STRING_MAP SpSimDbgSystemPowerStringMap[] = { MAP(PowerSystemUnspecified), MAP(PowerSystemWorking), MAP(PowerSystemSleeping1), MAP(PowerSystemSleeping2), MAP(PowerSystemSleeping3), MAP(PowerSystemHibernate), MAP(PowerSystemShutdown), MAP(PowerSystemMaximum), END_STRING_MAP }; SPSIM_STRING_MAP SpSimDbgDevicePowerStringMap[] = { MAP(PowerDeviceUnspecified), MAP(PowerDeviceD0), MAP(PowerDeviceD1), MAP(PowerDeviceD2), MAP(PowerDeviceD3), MAP(PowerDeviceMaximum), END_STRING_MAP }; PCHAR SpSimDbgLookupString( IN PSPSIM_STRING_MAP Map, IN ULONG Id ) /*++ Routine Description: Looks up the string associated with Id in string map Map Arguments: Map - The string map Id - The id to lookup Return Value: The string --*/ { PSPSIM_STRING_MAP current = Map; while(current->Id != 0xFFFFFFFF) { if (current->Id == Id) { return current->String; } current++; } return "** UNKNOWN **"; } VOID SpSimDbgPrintMultiSz( LONG DebugLevel, PWSTR MultiSz ) /*++ Routine Description: Prints a registry style REG_MULTI_SZ Arguments: DebugLevel - The debug level at which or above the data should be displayed. MultiSz - The string to print Return Value: None --*/ { PWSTR current = MultiSz; if (DebugLevel <= SpSimDebug) { if (MultiSz) { while(*current) { DbgPrint("%S", current); current += wcslen(current) + 1; // include the NULL DbgPrint(*current ? ", " : "\n"); } } else { DbgPrint("*** None ***\n"); } } } // // Printing resource descriptors and resource lists (stolen from PCI) // PUCHAR SpSimDbgCmResourceTypeToText( UCHAR Type ) { switch (Type) { case CmResourceTypePort: return "CmResourceTypePort"; case CmResourceTypeInterrupt: return "CmResourceTypeInterrupt"; case CmResourceTypeMemory: return "CmResourceTypeMemory"; case CmResourceTypeDma: return "CmResourceTypeDma"; case CmResourceTypeDeviceSpecific: return "CmResourceTypeDeviceSpecific"; case CmResourceTypeBusNumber: return "CmResourceTypeBusNumber"; case CmResourceTypeConfigData: return "CmResourceTypeConfigData"; case CmResourceTypeDevicePrivate: return "CmResourceTypeDevicePrivate"; case CmResourceTypePcCardConfig: return "CmResourceTypePcCardConfig"; default: return "*** INVALID RESOURCE TYPE ***"; } } VOID SpSimDbgPrintIoResource( IN LONG Level, IN PIO_RESOURCE_DESCRIPTOR D ) { ULONG i; PUCHAR t; if (Level <= SpSimDebug) { t = SpSimDbgCmResourceTypeToText(D->Type); DbgPrint(" IoResource Descriptor dump: Descriptor @0x%x\n", D); DbgPrint(" Option = 0x%x\n", D->Option); DbgPrint(" Type = %d (%s)\n", D->Type, t); DbgPrint(" ShareDisposition = %d\n", D->ShareDisposition); DbgPrint(" Flags = 0x%04X\n", D->Flags); for ( i = 0; i < 6 ; i+=3 ) { DbgPrint(" Data[%d] = %08x %08x %08x\n", i, D->u.DevicePrivate.Data[i], D->u.DevicePrivate.Data[i+1], D->u.DevicePrivate.Data[i+2]); } } } VOID SpSimDbgPrintIoResReqList( IN LONG Level, IN PIO_RESOURCE_REQUIREMENTS_LIST IoResReqList ) { ULONG numlists; PIO_RESOURCE_LIST list; if (Level <= SpSimDebug) { if (IoResReqList) { numlists = IoResReqList->AlternativeLists; list = IoResReqList->List; DbgPrint(" IO_RESOURCE_REQUIREMENTS_LIST\n"); DbgPrint(" AlternativeLists %d\n", numlists ); while (numlists--) { PIO_RESOURCE_DESCRIPTOR resource = list->Descriptors; ULONG count = list->Count; DbgPrint("\n List[%d].Count = %d\n", numlists, count); while (count--) { SpSimDbgPrintIoResource(Level, resource++); } list = (PIO_RESOURCE_LIST)resource; } DbgPrint("\n"); } else { DbgPrint(" IO_RESOURCE_REQUIREMENTS_LIST\n"); DbgPrint(" *** EMPTY ***\n"); } } } VOID SpSimDbgPrintPartialResource( IN LONG Level, IN PCM_PARTIAL_RESOURCE_DESCRIPTOR D ) { ULONG i; PUCHAR t; if (Level <= SpSimDebug) { if (D) { t = SpSimDbgCmResourceTypeToText(D->Type); DbgPrint(" Partial Resource Descriptor @0x%x\n", D); DbgPrint(" Type = %d (%s)\n", D->Type, t); DbgPrint(" ShareDisposition = %d\n", D->ShareDisposition); DbgPrint(" Flags = 0x%04X\n", D->Flags); for ( i = 0; i < 3 ; i+=3 ) { DbgPrint(" Data[%d] = %08x %08x %08x\n", i, D->u.DevicePrivate.Data[i], D->u.DevicePrivate.Data[i+1], D->u.DevicePrivate.Data[i+2]); } } else { DbgPrint(" Partial Resource Descriptor EMPTY!!\n"); } } } PCM_PARTIAL_RESOURCE_DESCRIPTOR SpSimNextPartialDescriptor( PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor ) /*++ Routine Description: Given a pointer to a CmPartialResourceDescriptor, return a pointer to the next descriptor in the same list. This is only done in a routine (rather than a simple descriptor++) because if the variable length resource CmResourceTypeDeviceSpecific. Arguments: Descriptor - Pointer to the descriptor being advanced over. Return Value: Pointer to the next descriptor in the same list (or byte beyond end of list). --*/ { PCM_PARTIAL_RESOURCE_DESCRIPTOR nextDescriptor; nextDescriptor = Descriptor + 1; if (Descriptor->Type == CmResourceTypeDeviceSpecific) { // // This (old) descriptor is followed by DataSize bytes // of device specific data, ie, not immediatelly by the // next descriptor. Adjust nextDescriptor by this amount. // nextDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PCHAR)nextDescriptor + Descriptor->u.DeviceSpecificData.DataSize); } return nextDescriptor; } VOID SpSimDbgPrintCmResList( IN LONG Level, IN PCM_RESOURCE_LIST ResourceList ) { ULONG numlists; PCM_FULL_RESOURCE_DESCRIPTOR full; PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor; if (Level <= SpSimDebug) { if (ResourceList) { numlists = ResourceList->Count; full = ResourceList->List; DbgPrint(" CM_RESOURCE_LIST (List Count = %d)\n", numlists); while (numlists--) { PCM_PARTIAL_RESOURCE_LIST partial = &full->PartialResourceList; ULONG count = partial->Count; descriptor = partial->PartialDescriptors; while (count--) { SpSimDbgPrintPartialResource(Level, descriptor); descriptor = SpSimNextPartialDescriptor(descriptor); } full = (PCM_FULL_RESOURCE_DESCRIPTOR)descriptor; } DbgPrint("\n"); } else { DbgPrint(" CM_RESOURCE_LIST EMPTY!!!\n"); } } } #endif