450 lines
8.7 KiB
C
450 lines
8.7 KiB
C
/*++
|
|
|
|
Copyright (c) 1997 FORE Systems, Inc.
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
debug.c
|
|
|
|
Abstract:
|
|
|
|
This file contains debugging support.
|
|
|
|
Author:
|
|
|
|
Larry Cleeton, FORE Systems (v-lcleet@microsoft.com, lrc@fore.com)
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
|
|
#pragma hdrstop
|
|
|
|
|
|
#if DBG
|
|
|
|
ULONG DbgVerbosity = 0;
|
|
#if DBG_TRACE
|
|
ULONG DbgLogSize = 128*1024;
|
|
TRACELOG TraceLog;
|
|
PUCHAR pTraceLogSpace;
|
|
#endif
|
|
#include "oidstrng.h"
|
|
#include "irpstrng.h"
|
|
|
|
#define MAX_HD_LENGTH 128
|
|
|
|
VOID
|
|
DbgOut(ULONG Level, PUCHAR Message, ...)
|
|
{
|
|
char buf[DBG_OUTBUF_SIZE];
|
|
va_list ap;
|
|
LONG numchars;
|
|
|
|
if (Level > DbgVerbosity)
|
|
return;
|
|
|
|
va_start(ap, Message);
|
|
|
|
numchars = _vsnprintf(buf, DBG_OUTBUF_SIZE, Message, ap);
|
|
|
|
buf[DBG_OUTBUF_SIZE-1] = '\0';
|
|
|
|
DbgPrint("ATMLANE: %s", buf);
|
|
}
|
|
|
|
//
|
|
// Careful! Uses static storage for string
|
|
//
|
|
PUCHAR
|
|
UnicodeToString(PUNICODE_STRING unicodeString)
|
|
{
|
|
static CHAR ansiStringBuffer[129];
|
|
ANSI_STRING ansiString;
|
|
|
|
ansiString.Length = 0;
|
|
ansiString.MaximumLength = 128;
|
|
ansiString.Buffer = ansiStringBuffer;
|
|
|
|
if (unicodeString->Length > 0)
|
|
{
|
|
NdisUnicodeStringToAnsiString(
|
|
&ansiString,
|
|
unicodeString);
|
|
}
|
|
|
|
ansiStringBuffer[ansiString.Length] = '\0';
|
|
|
|
return ansiStringBuffer;
|
|
}
|
|
|
|
|
|
//
|
|
// Careful! Uses static storage for string.
|
|
//
|
|
PUCHAR
|
|
MacAddrToString(PVOID In)
|
|
{
|
|
static UCHAR String[20];
|
|
static PUCHAR HexChars = "0123456789abcdef";
|
|
PUCHAR EthAddr = (PUCHAR) In;
|
|
UINT i;
|
|
PUCHAR s;
|
|
|
|
for (i = 0, s = String; i < 6; i++, EthAddr++)
|
|
{
|
|
*s++ = HexChars[(*EthAddr)>>4];
|
|
*s++ = HexChars[(*EthAddr)&0xf];
|
|
}
|
|
*s = '\0';
|
|
return String;
|
|
}
|
|
|
|
//
|
|
// Careful! Uses static storage for string.
|
|
//
|
|
PUCHAR
|
|
AtmAddrToString(PVOID In)
|
|
{
|
|
static UCHAR String[80];
|
|
static PUCHAR HexChars = "0123456789abcdef";
|
|
PUCHAR AtmAddr = (PUCHAR) In;
|
|
UINT i;
|
|
PUCHAR s = String;
|
|
|
|
*s++ = HexChars[(*AtmAddr)>>4];
|
|
*s++ = HexChars[(*AtmAddr++)&0xf]; // 1
|
|
*s++ = '.';
|
|
*s++ = HexChars[(*AtmAddr)>>4];
|
|
*s++ = HexChars[(*AtmAddr++)&0xf]; // 2
|
|
*s++ = HexChars[(*AtmAddr)>>4];
|
|
*s++ = HexChars[(*AtmAddr++)&0xf]; // 3
|
|
*s++ = '.';
|
|
*s++ = HexChars[(*AtmAddr)>>4];
|
|
*s++ = HexChars[(*AtmAddr++)&0xf]; // 4
|
|
*s++ = '.';
|
|
*s++ = HexChars[(*AtmAddr)>>4];
|
|
*s++ = HexChars[(*AtmAddr++)&0xf]; // 5
|
|
*s++ = HexChars[(*AtmAddr)>>4];
|
|
*s++ = HexChars[(*AtmAddr++)&0xf]; // 6
|
|
*s++ = HexChars[(*AtmAddr)>>4];
|
|
*s++ = HexChars[(*AtmAddr++)&0xf]; // 7
|
|
*s++ = '.';
|
|
*s++ = HexChars[(*AtmAddr)>>4];
|
|
*s++ = HexChars[(*AtmAddr++)&0xf]; // 8
|
|
*s++ = HexChars[(*AtmAddr)>>4];
|
|
*s++ = HexChars[(*AtmAddr++)&0xf]; // 9
|
|
*s++ = '.';
|
|
*s++ = HexChars[(*AtmAddr)>>4];
|
|
*s++ = HexChars[(*AtmAddr++)&0xf]; // 10
|
|
*s++ = HexChars[(*AtmAddr)>>4];
|
|
*s++ = HexChars[(*AtmAddr++)&0xf]; // 11
|
|
*s++ = '.';
|
|
*s++ = HexChars[(*AtmAddr)>>4];
|
|
*s++ = HexChars[(*AtmAddr++)&0xf]; // 12
|
|
*s++ = HexChars[(*AtmAddr)>>4];
|
|
*s++ = HexChars[(*AtmAddr++)&0xf]; // 13
|
|
*s++ = '.';
|
|
*s++ = HexChars[(*AtmAddr)>>4];
|
|
*s++ = HexChars[(*AtmAddr++)&0xf]; // 14
|
|
*s++ = HexChars[(*AtmAddr)>>4];
|
|
*s++ = HexChars[(*AtmAddr++)&0xf]; // 15
|
|
*s++ = HexChars[(*AtmAddr)>>4];
|
|
*s++ = HexChars[(*AtmAddr++)&0xf]; // 16
|
|
*s++ = HexChars[(*AtmAddr)>>4];
|
|
*s++ = HexChars[(*AtmAddr++)&0xf]; // 17
|
|
*s++ = HexChars[(*AtmAddr)>>4];
|
|
*s++ = HexChars[(*AtmAddr++)&0xf]; // 18
|
|
*s++ = HexChars[(*AtmAddr)>>4];
|
|
*s++ = HexChars[(*AtmAddr++)&0xf]; // 19
|
|
*s++ = '.';
|
|
*s++ = HexChars[(*AtmAddr)>>4];
|
|
*s++ = HexChars[(*AtmAddr++)&0xf]; // 20
|
|
*s = '\0';
|
|
return String;
|
|
}
|
|
|
|
PUCHAR
|
|
OidToString(ULONG Oid)
|
|
{
|
|
struct _string_table *oidtab;
|
|
|
|
|
|
for (oidtab = &oid_string_table[0]; oidtab->value != 0; oidtab++)
|
|
if (oidtab->value == Oid)
|
|
return oidtab->string;
|
|
|
|
return oid_string_table[(sizeof(oid_string_table) /
|
|
sizeof(struct _string_table)) - 1].string;
|
|
}
|
|
|
|
PUCHAR
|
|
IrpToString(ULONG Irp)
|
|
{
|
|
struct _string_table *irptab;
|
|
|
|
|
|
for (irptab = &irp_string_table[0]; irptab->value != 0xffffffff; irptab++)
|
|
if (irptab->value == Irp)
|
|
return irptab->string;
|
|
|
|
return irp_string_table[(sizeof(irp_string_table) /
|
|
sizeof(struct _string_table)) - 1].string;
|
|
}
|
|
|
|
VOID
|
|
DbgPrintHexDump(
|
|
IN ULONG Level,
|
|
IN PUCHAR pBuffer,
|
|
IN ULONG Length
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print a hex dump of the given contiguous buffer. If the length
|
|
is too long, we truncate it.
|
|
|
|
Arguments:
|
|
|
|
pBuffer - Points to start of data to be dumped
|
|
Length - Length of above.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
ULONG i;
|
|
|
|
if (Level > DbgVerbosity)
|
|
return;
|
|
|
|
if (Length > MAX_HD_LENGTH)
|
|
{
|
|
Length = MAX_HD_LENGTH;
|
|
}
|
|
|
|
for (i = 0; i < Length; i++)
|
|
{
|
|
//
|
|
// Check if we are at the end of a line
|
|
//
|
|
if ((i > 0) && ((i & 0xf) == 0))
|
|
{
|
|
DbgPrint("\n");
|
|
}
|
|
|
|
//
|
|
// Print addr if we are at start of a new line
|
|
//
|
|
if ((i & 0xf) == 0)
|
|
{
|
|
DbgPrint("%08x ", pBuffer);
|
|
}
|
|
|
|
DbgPrint(" %02x", *pBuffer++);
|
|
}
|
|
|
|
//
|
|
// Terminate the last line.
|
|
//
|
|
if (Length > 0)
|
|
{
|
|
DbgPrint("\n");
|
|
}
|
|
}
|
|
|
|
VOID
|
|
TraceLogWritePkt(
|
|
IN PTRACELOG pTraceLog,
|
|
IN PNDIS_PACKET pNdisPacket
|
|
)
|
|
{
|
|
PNDIS_BUFFER pBuffer[5] = {(PNDIS_BUFFER)NULL};
|
|
|
|
do
|
|
{
|
|
pBuffer[0] = pNdisPacket->Private.Head;
|
|
if (pBuffer[0] == (PNDIS_BUFFER)NULL)
|
|
break;
|
|
pBuffer[1] = pBuffer[0]->Next;
|
|
if (pBuffer[1] == (PNDIS_BUFFER)NULL)
|
|
break;
|
|
pBuffer[2] = pBuffer[1]->Next;
|
|
if (pBuffer[2] == (PNDIS_BUFFER)NULL)
|
|
break;
|
|
pBuffer[3] = pBuffer[2]->Next;
|
|
if (pBuffer[3] == (PNDIS_BUFFER)NULL)
|
|
break;
|
|
pBuffer[4] = pBuffer[3]->Next;
|
|
}
|
|
while (FALSE);
|
|
|
|
|
|
TraceLogWrite(
|
|
pTraceLog,
|
|
TL_NDISPACKET,
|
|
pNdisPacket,
|
|
pNdisPacket->Private.PhysicalCount,
|
|
pNdisPacket->Private.TotalLength,
|
|
pBuffer[0],
|
|
pBuffer[1],
|
|
pBuffer[2],
|
|
pBuffer[3],
|
|
pBuffer[4]
|
|
);
|
|
}
|
|
|
|
#endif
|
|
|
|
#if DEBUG_SPIN_LOCK
|
|
|
|
ULONG SpinLockInitDone = 0;
|
|
NDIS_SPIN_LOCK LockLock;
|
|
|
|
VOID
|
|
AtmLaneAllocateSpinLock(
|
|
IN PATMLANE_LOCK pLock,
|
|
IN PUCHAR String,
|
|
IN PUCHAR FileName,
|
|
IN ULONG LineNumber
|
|
)
|
|
{
|
|
DBGP((2, "ALLOCATE LOCK %x %s\n", pLock, String));
|
|
|
|
if (SpinLockInitDone == 0)
|
|
{
|
|
|
|
SpinLockInitDone = 1;
|
|
NdisAllocateSpinLock(&(LockLock));
|
|
}
|
|
|
|
NdisAcquireSpinLock(&(LockLock));
|
|
pLock->Signature = ATMLANE_LOCK_SIG;
|
|
NdisMoveMemory(pLock->TouchedByFileName, FileName, 32);
|
|
pLock->TouchedByFileName[31] = 0x0;
|
|
pLock->TouchedInLineNumber = LineNumber;
|
|
pLock->IsAcquired = 0;
|
|
pLock->OwnerThread = 0;
|
|
NdisAllocateSpinLock(&(pLock->NdisLock));
|
|
NdisReleaseSpinLock(&(LockLock));
|
|
}
|
|
|
|
VOID
|
|
AtmLaneFreeSpinLock(
|
|
IN PATMLANE_LOCK pLock,
|
|
IN PUCHAR String,
|
|
IN PUCHAR FileName,
|
|
IN ULONG LineNumber
|
|
)
|
|
{
|
|
DBGP((2, "FREE LOCK %x %s\n", pLock, String));
|
|
|
|
NdisFreeSpinLock(pLock);
|
|
}
|
|
|
|
VOID
|
|
AtmLaneAcquireSpinLock(
|
|
IN PATMLANE_LOCK pLock,
|
|
IN PUCHAR String,
|
|
IN PUCHAR FileName,
|
|
IN ULONG LineNumber
|
|
)
|
|
{
|
|
PKTHREAD pThread;
|
|
|
|
DBGP((4, "ACQUIRE LOCK %x %s\n", pLock, String));
|
|
|
|
pThread = KeGetCurrentThread();
|
|
NdisAcquireSpinLock(&(LockLock));
|
|
if (pLock->Signature != ATMLANE_LOCK_SIG)
|
|
{
|
|
DbgPrint("Trying to acquire uninited lock %x, File %s, Line %d\n",
|
|
pLock, FileName, LineNumber);
|
|
DbgBreakPoint();
|
|
}
|
|
|
|
if (pLock->IsAcquired != 0)
|
|
{
|
|
if (pLock->OwnerThread == pThread)
|
|
{
|
|
DbgPrint("Detected multiple locking!: pLock %x, File %s, Line %d\n",
|
|
pLock, FileName, LineNumber);
|
|
DbgPrint("pLock %x already acquired in File %s, Line %d\n",
|
|
pLock,
|
|
pLock->TouchedByFileName,
|
|
pLock->TouchedInLineNumber);
|
|
DbgBreakPoint();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Mark this lock.
|
|
//
|
|
pLock->IsAcquired++;
|
|
|
|
NdisReleaseSpinLock(&(LockLock));
|
|
NdisAcquireSpinLock(&(pLock->NdisLock));
|
|
|
|
pLock->OwnerThread = pThread;
|
|
NdisMoveMemory(pLock->TouchedByFileName, FileName, LOCK_FILE_NAME_LEN);
|
|
pLock->TouchedByFileName[LOCK_FILE_NAME_LEN - 1] = 0x0;
|
|
pLock->TouchedInLineNumber = LineNumber;
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
AtmLaneReleaseSpinLock(
|
|
IN PATMLANE_LOCK pLock,
|
|
IN PUCHAR String,
|
|
IN PUCHAR FileName,
|
|
IN ULONG LineNumber
|
|
)
|
|
{
|
|
DBGP((4, "RELEASE LOCK %x %s\n", pLock, String));
|
|
|
|
NdisAcquireSpinLock(&(LockLock));
|
|
if (pLock->Signature != ATMLANE_LOCK_SIG)
|
|
{
|
|
DbgPrint("Trying to release uninited lock %x, File %s, Line %d\n",
|
|
pLock,
|
|
FileName,
|
|
LineNumber);
|
|
DbgBreakPoint();
|
|
}
|
|
|
|
if (pLock->IsAcquired == 0)
|
|
{
|
|
DbgPrint("Detected release of unacquired lock %x, File %s, Line %d\n",
|
|
pLock,
|
|
FileName,
|
|
LineNumber);
|
|
DbgBreakPoint();
|
|
}
|
|
|
|
NdisMoveMemory(pLock->TouchedByFileName, FileName, LOCK_FILE_NAME_LEN);
|
|
pLock->TouchedByFileName[LOCK_FILE_NAME_LEN - 1] = 0x0;
|
|
pLock->TouchedInLineNumber = LineNumber;
|
|
pLock->IsAcquired--;
|
|
pLock->OwnerThread = 0;
|
|
NdisReleaseSpinLock(&(LockLock));
|
|
|
|
NdisReleaseSpinLock(&(pLock->NdisLock));
|
|
}
|
|
#endif // DEBUG_SPIN_LOCK
|
|
|