|
|
/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
dbg.c
Abstract:
Debug functions and services
Environment:
kernel mode only
Notes:
Revision History:
6-20-99 : created
--*/
#include "stdarg.h"
#include "stdio.h"
#include "common.h"
// paged functions
#ifdef ALLOC_PRAGMA
#endif
// non paged functions
//USBPORT_GetGlobalDebugRegistryParameters
//USBPORT_AssertFailure
//USBPORT_KdPrintX
//
ULONG USBPORT_LogMask = (LOG_MINIPORT | LOG_XFERS | LOG_PNP | LOG_MEM | LOG_POWER | LOG_RH | LOG_URB | LOG_MISC | LOG_IRPS | LOG_ISO);
//ULONG USBPORT_LogMask = (
// LOG_IRPS |
// LOG_URB);
ULONG USBPORT_DebugLogEnable = #if DBG
1; #else
1; #endif
ULONG USBPORT_CatcTrapEnable = 0;
#if DBG
/******
DEBUG ******/
#define DEFAULT_DEBUG_LEVEL 0
#ifdef DEBUG1
#undef DEFAULT_DEBUG_LEVEL
#define DEFAULT_DEBUG_LEVEL 1
#endif
#ifdef DEBUG2
#undef DEFAULT_DEBUG_LEVEL
#define DEFAULT_DEBUG_LEVEL 2
#endif
ULONG USBPORT_TestPath = 0; ULONG USBPORT_W98_Debug_Trace = 0; ULONG USBPORT_Debug_Trace_Level = DEFAULT_DEBUG_LEVEL; ULONG USBPORT_Client_Debug = 0; ULONG USBPORT_BreakOn = 0;
VOID USB2LIB_DbgPrint( PCH Format, int Arg0, int Arg1, int Arg2, int Arg3, int Arg4, int Arg5 ) { if (USBPORT_Debug_Trace_Level) { DbgPrint(Format, Arg0, Arg1, Arg2, Arg3, Arg4, Arg5); } }
VOID USB2LIB_DbgBreak( VOID ) { DbgPrint("<Break in USB2LIB>\n"); DbgBreakPoint(); }
VOID USBPORTSVC_DbgPrint( PDEVICE_DATA DeviceData, ULONG Level, PCH Format, int Arg0, int Arg1, int Arg2, int Arg3, int Arg4, int Arg5 ) {
if (USBPORT_Debug_Trace_Level >= Level) { if (Level <= 1) { // dump line to debugger
if (USBPORT_W98_Debug_Trace) { DbgPrint("xMP.SYS: "); *Format = ' '; } else { DbgPrint("'xMP.SYS: "); } } else { // dump line to NTKERN buffer
DbgPrint("'xMP.SYS: "); if (USBPORT_W98_Debug_Trace) { *Format = 0x27; } }
DbgPrint(Format, Arg0, Arg1, Arg2, Arg3, Arg4, Arg5); } }
VOID USBPORTSVC_TestDebugBreak( PDEVICE_DATA DeviceData ) { DEBUG_BREAK(); }
VOID USBPORTSVC_AssertFailure( PDEVICE_DATA DeviceData, PVOID FailedAssertion, PVOID FileName, ULONG LineNumber, PCHAR Message ) { USBPORT_AssertFailure( FailedAssertion, FileName, LineNumber, Message); }
NTSTATUS USBPORT_GetGlobalDebugRegistryParameters( VOID ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { #define MAX_KEYS 8
NTSTATUS ntStatus; RTL_QUERY_REGISTRY_TABLE QueryTable[MAX_KEYS]; PWCHAR usb = L"usb"; ULONG k = 0;
PAGED_CODE();
//
// Set up QueryTable to do the following:
//
// spew level - 0
QueryTable[k].QueryRoutine = USBPORT_GetConfigValue; QueryTable[k].Flags = 0; QueryTable[k].Name = DEBUG_LEVEL_KEY; QueryTable[k].EntryContext = &USBPORT_Debug_Trace_Level; QueryTable[k].DefaultType = REG_DWORD; QueryTable[k].DefaultData = &USBPORT_Debug_Trace_Level; QueryTable[k].DefaultLength = sizeof(USBPORT_Debug_Trace_Level); k++; USBPORT_ASSERT(k < MAX_KEYS);
// use ntkern trace buffer - 1
QueryTable[k].QueryRoutine = USBPORT_GetConfigValue; QueryTable[k].Flags = 0; QueryTable[k].Name = DEBUG_WIN9X_KEY; QueryTable[k].EntryContext = &USBPORT_W98_Debug_Trace; QueryTable[k].DefaultType = REG_DWORD; QueryTable[k].DefaultData = &USBPORT_W98_Debug_Trace; QueryTable[k].DefaultLength = sizeof(USBPORT_W98_Debug_Trace); k++; USBPORT_ASSERT(k < MAX_KEYS);
// break on start - 2
QueryTable[k].QueryRoutine = USBPORT_GetConfigValue; QueryTable[k].Flags = 0; QueryTable[k].Name = DEBUG_BREAK_ON; QueryTable[k].EntryContext = &USBPORT_BreakOn; QueryTable[k].DefaultType = REG_DWORD; QueryTable[k].DefaultData = &USBPORT_BreakOn; QueryTable[k].DefaultLength = sizeof(USBPORT_BreakOn); k++; USBPORT_ASSERT(k < MAX_KEYS);
// log mask - 3
QueryTable[k].QueryRoutine = USBPORT_GetConfigValue; QueryTable[k].Flags = 0; QueryTable[k].Name = DEBUG_LOG_MASK; QueryTable[k].EntryContext = &USBPORT_LogMask; QueryTable[k].DefaultType = REG_DWORD; QueryTable[k].DefaultData = &USBPORT_LogMask; QueryTable[k].DefaultLength = sizeof(USBPORT_LogMask); k++; USBPORT_ASSERT(k < MAX_KEYS);
// log mask - 4
QueryTable[k].QueryRoutine = USBPORT_GetConfigValue; QueryTable[k].Flags = 0; QueryTable[k].Name = DEBUG_CLIENTS; QueryTable[k].EntryContext = &USBPORT_Client_Debug; QueryTable[k].DefaultType = REG_DWORD; QueryTable[k].DefaultData = &USBPORT_Client_Debug; QueryTable[k].DefaultLength = sizeof(USBPORT_LogMask); k++; USBPORT_ASSERT(k < MAX_KEYS);
// log enable - 5
QueryTable[k].QueryRoutine = USBPORT_GetConfigValue; QueryTable[k].Flags = 0; QueryTable[k].Name = DEBUG_LOG_ENABLE; QueryTable[k].EntryContext = &USBPORT_DebugLogEnable; QueryTable[k].DefaultType = REG_DWORD; QueryTable[k].DefaultData = &USBPORT_DebugLogEnable; QueryTable[k].DefaultLength = sizeof(USBPORT_DebugLogEnable); k++; USBPORT_ASSERT(k < MAX_KEYS);
// catc trap enable - 6
QueryTable[k].QueryRoutine = USBPORT_GetConfigValue; QueryTable[k].Flags = 0; QueryTable[k].Name = DEBUG_CATC_ENABLE; QueryTable[k].EntryContext = &USBPORT_CatcTrapEnable; QueryTable[k].DefaultType = REG_DWORD; QueryTable[k].DefaultData = &USBPORT_CatcTrapEnable; QueryTable[k].DefaultLength = sizeof(USBPORT_CatcTrapEnable); k++; USBPORT_ASSERT(k < MAX_KEYS);
//
// Stop
//
QueryTable[k].QueryRoutine = NULL; QueryTable[k].Flags = 0; QueryTable[k].Name = NULL;
ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_SERVICES, usb, QueryTable, // QueryTable
NULL, // Context
NULL); // Environment
if (NT_SUCCESS(ntStatus)) { USBPORT_KdPrint((1, "'Debug Trace Level Set: (%d)\n", USBPORT_Debug_Trace_Level));
if (USBPORT_W98_Debug_Trace) { USBPORT_KdPrint((1, "'NTKERN Trace is ON\n")); } else { USBPORT_KdPrint((1, "'NTKERN Trace is OFF\n")); }
if (USBPORT_DebugLogEnable) { USBPORT_KdPrint((1, "'DEBUG-LOG is ON\n")); } else { USBPORT_KdPrint((1, "'DEBUG-LOG is OFF\n")); }
if (USBPORT_BreakOn) { USBPORT_KdPrint((1, "'DEBUG BREAK is ON\n")); }
USBPORT_KdPrint((1, "'DEBUG Log Mask is 0x%08.8x\n", USBPORT_LogMask));
if (USBPORT_Debug_Trace_Level > 0) { ULONG USBPORT_Debug_Asserts = 1; }
if (USBPORT_Client_Debug) { USBPORT_KdPrint((1, "'DEBUG CLIENTS (verifier) is ON\n")); }
if (USBPORT_CatcTrapEnable) { USBPORT_KdPrint((0, "'DEBUG ANALYZER TRIGGER is ON\n")); } }
if ( STATUS_OBJECT_NAME_NOT_FOUND == ntStatus ) { ntStatus = STATUS_SUCCESS; }
return ntStatus; }
VOID USBPORT_AssertTransferUrb( PTRANSFER_URB Urb ) { PDEVICE_OBJECT fdoDeviceObject; PHCD_TRANSFER_CONTEXT transfer; PHCD_ENDPOINT endpoint;
transfer = Urb->pd.HcdTransferContext; ASSERT_TRANSFER(transfer);
USBPORT_ASSERT(transfer->Urb == Urb);
endpoint = transfer->Endpoint; ASSERT_ENDPOINT(endpoint);
fdoDeviceObject = endpoint->FdoDeviceObject; LOGENTRY(NULL, fdoDeviceObject, LOG_URB, 'Aurb', Urb, transfer, 0);
USBPORT_ASSERT(Urb->pd.UrbSig == URB_SIG); }
VOID USBPORT_AssertFailure( PVOID FailedAssertion, PVOID FileName, ULONG LineNumber, PCHAR Message ) /*++
Routine Description:
Debug Assert function.
on NT the debugger does this for us but on win9x it does not. so we have to do it ourselves.
Arguments:
Return Value:
--*/ {
// this makes the compiler generate a ret
ULONG stop = 0;
assert_loop:
// 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
DbgBreakPoint(); if (stop) { goto assert_loop; }
return; }
ULONG _cdecl USBPORT_DebugClientX( PCH Format, ... ) /*++
Routine Description:
Special debug print function for debugging client USB drivers.
if the client debug mode is set then this function will print a message and break in the debugger. This is the embedded USBPORT equivalent of Verifier.
Arguments:
Return Value:
--*/ { va_list list; int i; int arg[6];
if (USBPORT_Debug_Trace_Level > 1 || USBPORT_Client_Debug) { DbgPrint(" *** USBPORT(VERIFIER) - CLIENT DRIVER BUG:\n"); DbgPrint(" * "); 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]); DbgPrint(" ***\n ");
DbgBreakPoint(); }
return 0; }
ULONG _cdecl USBPORT_KdPrintX( ULONG l, PCH Format, ... ) /*++
Routine Description:
Debug Print function.
Prints based on the value of the USBPORT_DEBUG_TRACE_LEVEL
Also if USBPORT_W98_Debug_Trace is set then all debug messages with a level greater than one are modified to go in to the ntkern trace buffer.
It is only valid to set USBPORT_W98_Debug_Trace on Win9x becuse the static data segments for drivers are marked read-only by the NT OS.
Arguments:
Return Value:
--*/ { va_list list; int i; int arg[6];
if (USBPORT_Debug_Trace_Level >= l) { if (l <= 1) { // dump line to debugger
if (USBPORT_W98_Debug_Trace) { DbgPrint("USBPORT.SYS: "); *Format = ' '; } else { DbgPrint("'USBPORT.SYS: "); } } else { // dump line to NTKERN buffer
DbgPrint("'USBPORT.SYS: "); if (USBPORT_W98_Debug_Trace) { *Format = 0x27; } } 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 USBPORT_DebugTransfer_LogEntry( PDEVICE_OBJECT FdoDeviceObject, PHCD_ENDPOINT Endpoint, PHCD_TRANSFER_CONTEXT Transfer, PTRANSFER_URB Urb, PIRP Irp, NTSTATUS IrpStatus ) /*++
Routine Description:
Adds an entry to transfer log.
Arguments:
Return Value:
None.
--*/ { KIRQL irql; PDEVICE_EXTENSION devExt;
GET_DEVICE_EXT(devExt, FdoDeviceObject); ASSERT_FDOEXT(devExt);
if (devExt->TransferLog.LogStart == 0) { return; }
USBPORT_AddLogEntry( &devExt->TransferLog, 0xFFFFFFFF, '1rfx', (ULONG_PTR) Endpoint, (ULONG_PTR) Irp, (ULONG_PTR) Urb, FALSE);
// decode some info about the transfer and log it as well
USBPORT_AddLogEntry( &devExt->TransferLog, 0xFFFFFFFF, '2rfx', (ULONG_PTR) Urb->Hdr.Function, IrpStatus, (ULONG_PTR) Urb->TransferBufferLength, FALSE); }
#else
/********
RETAIL ********/
VOID USB2LIB_DbgPrint( PCH Format, int Arg0, int Arg1, int Arg2, int Arg3, int Arg4, int Arg5 ) { // nop
}
VOID USB2LIB_DbgBreak( VOID ) { // nop
}
VOID USBPORTSVC_DbgPrint( PDEVICE_DATA DeviceData, ULONG Level, PCH Format, int Arg0, int Arg1, int Arg2, int Arg3, int Arg4, int Arg5 ) { // nop
}
VOID USBPORTSVC_AssertFailure( PDEVICE_DATA DeviceData, PVOID FailedAssertion, PVOID FileName, ULONG LineNumber, PCHAR Message ) { // nop
}
VOID USBPORTSVC_TestDebugBreak( PDEVICE_DATA DeviceData ) { // nop
}
#endif /* DBG */
/********
LOG CODE enabled in both retail and debug builds *********/
VOID USBPORTSVC_LogEntry( PDEVICE_DATA DeviceData, ULONG Mask, ULONG Sig, ULONG_PTR Info1, ULONG_PTR Info2, ULONG_PTR Info3 ) /*++
Routine Description:
Service for miniport to add log entries.
Arguments:
Return Value:
None.
--*/ { PDEVICE_EXTENSION devExt; PDEBUG_LOG l; extern ULONG USBPORT_DebugLogEnable;\ extern ULONG USBPORT_LogMask;\ DEVEXT_FROM_DEVDATA(devExt, DeviceData); ASSERT_FDOEXT(devExt); if (USBPORT_DebugLogEnable && devExt->Log.LogStart != NULL && (LOG_MINIPORT & USBPORT_LogMask)) { l = &devExt->Log; USBPORT_AddLogEntry(l, LOG_MINIPORT, Sig, Info1, Info2, Info3, TRUE); } }
VOID USBPORT_LogAlloc( PDEBUG_LOG Log, ULONG Pages ) /*++
Routine Description:
Init the debug log - remember interesting information in a circular buffer
Arguments:
Return Value:
None.
--*/ { ULONG logSize = 4096*Pages;
if (USBPORT_DebugLogEnable) {
// we won't track the mem we alloc for the log
// we will let the verifier do that
ALLOC_POOL_Z(Log->LogStart, NonPagedPool, logSize);
if (Log->LogStart) { Log->LogIdx = 0; Log->LogSizeMask = (logSize/sizeof(LOG_ENTRY)); Log->LogSizeMask-=1; // Point the end (and first entry) 1 entry from the end
// of the segment
Log->LogEnd = Log->LogStart + (logSize / sizeof(struct LOG_ENTRY)) - 1; } else { DEBUG_BREAK(); } }
return; }
VOID USBPORT_LogFree( PDEVICE_OBJECT FdoDeviceObject, PDEBUG_LOG Log ) /*++
Routine Description:
Arguments:
Return Value:
None.
--*/ {
if (Log->LogStart != NULL) { // log the free of the log in order to debug
// verifier bugs
FREE_POOL(FdoDeviceObject, Log->LogStart); // this will indicate that we have freed the
// log, other log pointers will remain intact
Log->LogStart = NULL; }
return; }
/*
Transmit the analyzer trigger packet */
VOID USBPORT_BeginTransmitTriggerPacket( PDEVICE_OBJECT FdoDeviceObject ) /*++
Routine Description:
Arguments:
DeviceObject - Fdo for USB HC
Return Value:
none.
--*/ { PDEVICE_EXTENSION devExt; USB_MINIPORT_STATUS mpStatus; HW_32BIT_PHYSICAL_ADDRESS phys; PUCHAR va, mpData; ULONG length, mpDataLength; MP_PACKET_PARAMETERS mpPacket; USBD_STATUS usbdStatus; USB_USER_ERROR_CODE usbUserStatus; UCHAR data[4]; USBPORT_KdPrint((1, "'USBPORT_TransmitTriggerPacket\n"));
ASSERT_PASSIVE(); GET_DEVICE_EXT(devExt, FdoDeviceObject); ASSERT_FDOEXT(devExt);
LOGENTRY(NULL, FdoDeviceObject, LOG_MISC, 'TRIG', &mpPacket, 0, 0);
// build up request for miniport
length = devExt->Fdo.ScratchCommonBuffer->MiniportLength; va = devExt->Fdo.ScratchCommonBuffer->MiniportVa; phys = devExt->Fdo.ScratchCommonBuffer->MiniportPhys;
mpPacket.DeviceAddress = 127; mpPacket.EndpointAddress = 8; mpPacket.MaximumPacketSize = 64; mpPacket.Type = ss_Out; mpPacket.Speed = ss_Full; mpPacket.Toggle = ss_Toggle0;
data[0] = 'G'; data[1] = 'O'; data[2] = 'A'; data[3] = 'T'; mpData = &data[0]; mpDataLength = sizeof(data); MP_StartSendOnePacket(devExt, &mpPacket, mpData, &mpDataLength, va, phys, length, &usbdStatus, mpStatus);
}
VOID USBPORT_EndTransmitTriggerPacket( PDEVICE_OBJECT FdoDeviceObject ) /*++
Routine Description:
Arguments:
DeviceObject - Fdo for USB HC
Return Value:
none.
--*/ { PDEVICE_EXTENSION devExt; USB_MINIPORT_STATUS mpStatus; HW_32BIT_PHYSICAL_ADDRESS phys; PUCHAR va, mpData; ULONG length, mpDataLength; MP_PACKET_PARAMETERS mpPacket; USBD_STATUS usbdStatus; UCHAR data[4]; USBPORT_KdPrint((1, "'USBPORT_TransmitTriggerPacket\n"));
ASSERT_PASSIVE(); GET_DEVICE_EXT(devExt, FdoDeviceObject); ASSERT_FDOEXT(devExt); mpData = &data[0]; mpDataLength = sizeof(data);
length = devExt->Fdo.ScratchCommonBuffer->MiniportLength; va = devExt->Fdo.ScratchCommonBuffer->MiniportVa; phys = devExt->Fdo.ScratchCommonBuffer->MiniportPhys;
USBPORT_Wait(FdoDeviceObject, 10); MP_EndSendOnePacket(devExt, &mpPacket, mpData, &mpDataLength, va, phys, length, &usbdStatus, mpStatus);
USBPORT_KdPrint((1, "'<ANALYZER TRIGER FIRED>\n")); DbgBreakPoint(); }
VOID USBPORT_CatcTrap( PDEVICE_OBJECT FdoDeviceObject ) /*++
Routine Description:
Arguments:
Return Value:
none.
--*/ { PDEVICE_EXTENSION devExt;
GET_DEVICE_EXT(devExt, FdoDeviceObject); ASSERT_FDOEXT(devExt);
if (KeGetCurrentIrql() > PASSIVE_LEVEL) { USBPORT_BeginTransmitTriggerPacket(FdoDeviceObject); SET_FDO_FLAG(devExt, USBPORT_FDOFLAG_CATC_TRAP); } else { TEST_TRAP(); USBPORT_BeginTransmitTriggerPacket(FdoDeviceObject); USBPORT_EndTransmitTriggerPacket(FdoDeviceObject); } }
VOID USBPORT_EnumLogEntry( PDEVICE_OBJECT FdoDeviceObject, ULONG DriverTag, ULONG EnumTag, ULONG P1, ULONG P2 ) /*++
Routine Description:
Enumeration Log, this is where any USB device driver may log a failure to track failure causes
Arguments:
Return Value:
None.
--*/ { KIRQL irql; PDEVICE_EXTENSION devExt;
GET_DEVICE_EXT(devExt, FdoDeviceObject); ASSERT_FDOEXT(devExt);
if (devExt->EnumLog.LogStart == 0) { return; }
USBPORT_AddLogEntry( &devExt->EnumLog, 0xFFFFFFFF, EnumTag, (ULONG_PTR) DriverTag, (ULONG_PTR) P1, (ULONG_PTR) P2, FALSE); }
|