windows-nt/Source/XPSP1/NT/drivers/wdm/usb/driver/hub.pnp/dbg.c
2020-09-26 16:20:57 +08:00

501 lines
11 KiB
C

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
DBG.C
Abstract:
This module contains debug only code for USB Hub driver
Author:
jdunn
Environment:
kernel mode only
Notes:
Revision History:
11-5-96 : created
--*/
#include <wdm.h>
#ifdef WMI_SUPPORT
#include <wmilib.h>
#endif /* WMI_SUPPORT */
#include "stdarg.h"
#include "stdio.h"
#include "usbhub.h"
#ifdef MAX_DEBUG
#define DEBUG_HEAP
#endif
typedef struct _HEAP_TAG_BUFFER {
ULONG Sig;
ULONG Length;
} HEAP_TAG_BUFFER, *PHEAP_TAG_BUFFER;
#if DBG
// this flag causes us to write a ' in the format string
// so that the string goes to the NTKERN buffer
// this trick causes problems with driver verifier on NT
// and the trace buffer isn't in NT anyway
ULONG USBH_W98_Debug_Trace =
#ifdef NTKERN_TRACE
1;
#else
0;
#endif
VOID
USBH_Assert(
IN PVOID FailedAssertion,
IN PVOID FileName,
IN ULONG LineNumber,
IN PCHAR Message
)
/*++
Routine Description:
Debug Assert function.
Arguments:
DeviceObject - pointer to a device object
Irp - pointer to an I/O Request Packet
Return Value:
--*/
{
#ifdef NTKERN
// this makes the compiler generate a ret
ULONG stop = 1;
assert_loop:
#endif
// just call the NT assert function and stop
// in the debugger.
RtlAssert( FailedAssertion, FileName, LineNumber, Message );
// loop here to prevent users from going past
// are assert before we can look at it
#ifdef NTKERN
DBGBREAK();
if (stop) {
goto assert_loop;
}
#endif
return;
}
ULONG
_cdecl
USBH_KdPrintX(
ULONG l,
PCH Format,
...
)
{
va_list list;
int i;
int arg[6];
if (USBH_Debug_Trace_Level >= l) {
if (l <= 1) {
if (USBH_W98_Debug_Trace) {
//override trace buffer
#ifdef USBHUB20
DbgPrint("USBHUB20.SYS: ");
#else
DbgPrint("USBHUB.SYS: ");
#endif
*Format = ' ';
} else {
#ifdef USBHUB20
DbgPrint("USBHUB20.SYS: ");
#else
DbgPrint("USBHUB.SYS: ");
#endif
}
} else {
#ifdef USBHUB20
DbgPrint("USBHUB20.SYS: ");
#else
DbgPrint("USBHUB.SYS: ");
#endif
}
va_start(list, Format);
for (i=0; i<6; i++)
arg[i] = va_arg(list, int);
DbgPrint(Format, arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]);
}
return 0;
}
VOID
UsbhWarning(
PDEVICE_EXTENSION_PORT DeviceExtensionPort,
PUCHAR Message,
BOOLEAN DebugBreak
)
{
DbgPrint("USBHUB: Warning **************************************************************\n");
if (DeviceExtensionPort) {
DbgPrint("Device PID %04.4x, VID %04.4x\n",
DeviceExtensionPort->DeviceDescriptor.idProduct,
DeviceExtensionPort->DeviceDescriptor.idVendor);
}
DbgPrint("%s", Message);
DbgPrint("******************************************************************************\n");
if (DebugBreak) {
DBGBREAK();
}
}
VOID
UsbhInfo(
PDEVICE_EXTENSION_HUB DeviceExtensionHub
)
{
PUSB_HUB_DESCRIPTOR hubDescriptor;
ULONG i;
hubDescriptor = DeviceExtensionHub->HubDescriptor;
USBH_KdPrint((1, "'*****************************************************\n"));
if (USBH_HubIsBusPowered(DeviceExtensionHub->FunctionalDeviceObject,
DeviceExtensionHub->ConfigurationDescriptor)) {
USBH_KdPrint((1, "'*** Hub VID %04.4x PID %04.4x is BUS POWERED \n",
DeviceExtensionHub->DeviceDescriptor.idVendor,
DeviceExtensionHub->DeviceDescriptor.idProduct));
} else {
USBH_KdPrint((1, "'*** Hub VID %04.4x PID %04.4x is SELF POWERED \n",
DeviceExtensionHub->DeviceDescriptor.idVendor,
DeviceExtensionHub->DeviceDescriptor.idProduct));
}
USBH_KdPrint((1, "'*** has %d ports\n",
hubDescriptor->bNumberOfPorts));
if (HUB_IS_GANG_POWER_SWITCHED(hubDescriptor->wHubCharacteristics)) {
USBH_KdPrint((1,"'*** is 'gang power switched'\n"));
} else if (HUB_IS_NOT_POWER_SWITCHED(hubDescriptor->wHubCharacteristics)) {
USBH_KdPrint((1,"'*** is 'not power switched'\n"));
} else if (HUB_IS_PORT_POWER_SWITCHED(hubDescriptor->wHubCharacteristics)) {
USBH_KdPrint((1,"'*** is 'port power switched'\n"));
} else {
TEST_TRAP();
}
for (i=0; i< hubDescriptor->bNumberOfPorts; i++) {
if (PORT_ALWAYS_POWER_SWITCHED(hubDescriptor, i+1)) {
USBH_KdPrint((1,"'*** port (%d) is power switched\n", i+1));
}
if (PORT_DEVICE_NOT_REMOVABLE(hubDescriptor, i+1)) {
USBH_KdPrint((1,"'*** port (%d) device is not removable\n", i+1));
}
}
USBH_KdPrint((1, "'*****************************************************\n"));
}
PVOID
UsbhGetHeap(
IN POOL_TYPE PoolType,
IN ULONG NumberOfBytes,
IN ULONG Signature,
IN PLONG TotalAllocatedHeapSpace
)
/*++
Routine Description:
Debug routine, used to debug heap problems. We are using this since
most NT debug functions are not supported by NTKERN.
Arguments:
PoolType - pool type passed to ExAllocatePool
NumberOfBytes - number of bytes for item
Signature - four byte signature supplied by caller
TotalAllocatedHeapSpace - pointer to variable where client stores
the total accumulated heap space allocated.
Return Value:
pointer to allocated memory
--*/
{
PUCHAR p;
#ifdef DEBUG_HEAP
PHEAP_TAG_BUFFER tagBuffer;
// we call ExAllocatePoolWithTag but no tag will be added
// when running under NTKERN
p = (PUCHAR) ExAllocatePoolWithTag(PoolType,
NumberOfBytes + sizeof(HEAP_TAG_BUFFER)*2,
Signature);
if (p) {
tagBuffer = (PHEAP_TAG_BUFFER) p;
tagBuffer->Sig = Signature;
tagBuffer->Length = NumberOfBytes;
p += sizeof(HEAP_TAG_BUFFER);
*TotalAllocatedHeapSpace += NumberOfBytes;
tagBuffer = (PHEAP_TAG_BUFFER) (p + NumberOfBytes);
tagBuffer->Sig = Signature;
tagBuffer->Length = NumberOfBytes;
}
// LOGENTRY(LOG_MISC, (PUCHAR) &Signature, 0, 0, 0);
// LOGENTRY(LOG_MISC, "GetH", p, NumberOfBytes, stk[1] & 0x00FFFFFF);
#else
p = (PUCHAR) ExAllocatePoolWithTag(PoolType,
NumberOfBytes,
Signature);
#endif /* DEBUG_HEAP */
return p;
}
VOID
UsbhRetHeap(
IN PVOID P,
IN ULONG Signature,
IN PLONG TotalAllocatedHeapSpace
)
/*++
Routine Description:
Debug routine, used to debug heap problems. We are using this since
most NT debug functions are not supported by NTKERN.
Arguments:
P - pointer to free
Return Value:
none.
--*/
{
#ifdef DEBUG_HEAP
PHEAP_TAG_BUFFER endTagBuffer;
PHEAP_TAG_BUFFER beginTagBuffer;
USBH_ASSERT(P != 0);
beginTagBuffer = (PHEAP_TAG_BUFFER) ((PUCHAR)P - sizeof(HEAP_TAG_BUFFER));
endTagBuffer = (PHEAP_TAG_BUFFER) ((PUCHAR)P + beginTagBuffer->Length);
*TotalAllocatedHeapSpace -= beginTagBuffer->Length;
// LOGENTRY(LOG_MISC, (PUCHAR) &Signature, 0, 0, 0);
// LOGENTRY(LOG_MISC, "RetH", P, tagBuffer->Length, stk[1] & 0x00FFFFFF);
USBH_ASSERT(*TotalAllocatedHeapSpace >= 0);
USBH_ASSERT(beginTagBuffer->Sig == Signature);
USBH_ASSERT(endTagBuffer->Sig == Signature);
USBH_ASSERT(endTagBuffer->Length == beginTagBuffer->Length);
// fill the buffer with bad data
RtlFillMemory(P, beginTagBuffer->Length, 0xff);
beginTagBuffer->Sig = USBHUB_FREE_TAG;
// free the original block
ExFreePool(beginTagBuffer);
#else
ExFreePool(P);
#endif /* DEBUG_HEAP */
}
#endif /* DBG */
#ifdef DEBUG_LOG
KSPIN_LOCK LogSpinLock;
struct USBH_LOG_ENTRY {
CHAR le_name[4]; // Identifying string
ULONG_PTR le_info1; // entry specific info
ULONG_PTR le_info2; // entry specific info
ULONG_PTR le_info3; // entry specific info
}; /* USBD_LOG_ENTRY */
struct USBH_LOG_ENTRY *HubLStart = 0; // No log yet
struct USBH_LOG_ENTRY *HubLPtr;
struct USBH_LOG_ENTRY *HubLEnd;
#ifdef PROFILE
ULONG LogMask = LOG_PROFILE;
#else
ULONG LogMask = 0xFFFFFFFF;
#endif
VOID
USBH_Debug_LogEntry(
IN ULONG Mask,
IN CHAR *Name,
IN ULONG_PTR Info1,
IN ULONG_PTR Info2,
IN ULONG_PTR Info3
)
/*++
Routine Description:
Adds an Entry to USBH log.
Arguments:
Return Value:
None.
--*/
{
KIRQL irql;
if (HubLStart == 0) {
return;
}
if ((Mask & LogMask) == 0) {
return;
}
irql = KeGetCurrentIrql();
if (irql < DISPATCH_LEVEL) {
KeAcquireSpinLock(&LogSpinLock, &irql);
} else {
KeAcquireSpinLockAtDpcLevel(&LogSpinLock);
}
if (HubLPtr > HubLStart) {
HubLPtr -= 1; // Decrement to next entry
} else {
HubLPtr = HubLEnd;
}
if (irql < DISPATCH_LEVEL) {
KeReleaseSpinLock(&LogSpinLock, irql);
} else {
KeReleaseSpinLockFromDpcLevel(&LogSpinLock);
}
USBH_ASSERT(HubLPtr >= HubLStart);
RtlCopyMemory(HubLPtr->le_name, Name, 4);
// LPtr->le_ret = (stk[1] & 0x00ffffff) | (CurVMID()<<24);
HubLPtr->le_info1 = Info1;
HubLPtr->le_info2 = Info2;
HubLPtr->le_info3 = Info3;
return;
}
VOID
USBH_LogInit(
)
/*++
Routine Description:
Init the debug log - remember interesting information in a circular buffer
Arguments:
Return Value:
None.
--*/
{
#ifdef MAX_DEBUG
ULONG logSize = 4096*6;
#else
ULONG logSize = 4096*3;
#endif
KeInitializeSpinLock(&LogSpinLock);
HubLStart = ExAllocatePoolWithTag(NonPagedPool,
logSize,
USBHUB_HEAP_TAG);
if (HubLStart) {
HubLPtr = HubLStart;
// Point the end (and first entry) 1 entry from the end of the segment
HubLEnd = HubLStart + (logSize / sizeof(struct USBH_LOG_ENTRY)) - 1;
} else {
USBH_KdBreak(("no mem for log!\n"));
}
return;
}
VOID
USBH_LogFree(
)
/*++
Routine Description:
Init the debug log - remember interesting information in a circular buffer
Arguments:
Return Value:
None.
--*/
{
if (HubLStart) {
ExFreePool(HubLStart);
}
}
#endif /* DEBUG_LOG */