singrdk/base/Kernel/Native/HalKd1394.cpp

809 lines
27 KiB
C++
Raw Normal View History

2008-03-05 09:52:00 -05:00
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// halkd1394.cpp: runtime support for debugging over 1394.
//
// For more information see:
// \nt\base\ntos\kd64
// \nt\base\boot\kdcom
// \nt\base\boot\kd1394
// \nt\base\boot\kdusb2
// \nt\sdktools\debuggers\ntsd64
//
#include "hal.h"
#include "halkd.h"
#include "halkd1394.h"
extern "C" void * __cdecl memcpy(void *, const void *, size_t);
extern "C" void * __cdecl memset(void *, int, size_t);
//
// Debugger Debugging
//
#define KDDBG if (0) kdprintf
#define KDDBG2 if (0) kdprintf
///////////////////////////////////////////////////////// Debugger Structures.
//
// These structures are accessed directly by the host using RDMA.
//
#define DEBUG_BUS1394_MAX_PACKET_SIZE 4000
#define DEBUG_1394_MAJOR_VERSION 0x1
#define DEBUG_1394_MINOR_VERSION 0x0
#define DEBUG_1394_CONFIG_TAG 0xBABABABA
struct DEBUG_1394_SEND_PACKET {
ULONG TransferStatus;
ULONG PacketHeader[4];
ULONG Length;
UCHAR Packet[DEBUG_BUS1394_MAX_PACKET_SIZE];
UCHAR Padding[72];
};
STATIC_ASSERT(sizeof(DEBUG_1394_SEND_PACKET) == 4096);
struct DEBUG_1394_RECEIVE_PACKET {
ULONG TransferStatus;
ULONG Length;
UCHAR Packet[DEBUG_BUS1394_MAX_PACKET_SIZE];
UCHAR Padding[88];
};
STATIC_ASSERT(sizeof(DEBUG_1394_RECEIVE_PACKET) == 4096);
// exists on target, host reads it to match for id.
struct DEBUG_1394_CONFIG {
ULONG Tag;
USHORT MajorVersion;
USHORT MinorVersion;
ULONG Id;
ULONG BusPresent;
ULONG64 SendPacket;
ULONG64 ReceivePacket;
};
STATIC_ASSERT(sizeof(DEBUG_1394_CONFIG) == 32);
struct DEBUG_1394_DATA {
// POHCI_REGISTER_MAP BaseAddress; // our OHCI register map
ULONG CromBuffer[248]; // our config ROM - must be 1k aligned
DEBUG_1394_CONFIG Config; // our config for this session
DEBUG_1394_SEND_PACKET SendPacket; // our send packet (isoch packet)
DEBUG_1394_RECEIVE_PACKET ReceivePacket; // our receive packet
};
STATIC_ASSERT(sizeof(DEBUG_1394_DATA) == 1024 + 4096 + 4096);
STATIC_ASSERT(sizeof(DEBUG_1394_DATA) <= 3 * 4096); // we allocate 12KB in boot.
//////////////////////////////////////////////////////////////////////////////
//
#define TIMEOUT_COUNT 1024*500
#define MAX_REGISTER_READS 400000
//
// Global Data Structures
//
static DEBUG_1394_DATA * Kd1394Data;
static volatile OHCI_REGISTER_MAP * KdRegisters;
//
static ULONG_PTR MmGetPhysicalAddress(PVOID pv)
{
return (ULONG_PTR)pv;
}
// ?? need to look into this
static ULONG Dbg1394_StallExecution(ULONG LoopCount)
{
ULONG b = 1;
for (ULONG k = 0; k < LoopCount; k++) {
for (ULONG i = 1; i < 100000; i++) {
__asm pause;
b = b * (i>>k);
}
}
return b;
}
// Exchange byte pairs 0:3 and 1:2 of Source and returns the resulting ULONG.
static inline ULONG Dbg1394_ByteSwap(ULONG Source)
{
return (((Source) << (8 * 3)) |
((Source & 0x0000FF00) << (8 * 1)) |
((Source & 0x00FF0000) >> (8 * 1)) |
((Source) >> (8 * 3)));
}
// Derive the 16 bit CRC as defined by IEEE 1212 clause 8.1.5.
// (ISO/IEC 13213) First edition 1994-10-05.
// data - ULONG data to derive CRC from.
// check - check value.
static ULONG Dbg1394_Crc16(ULONG data, ULONG check)
{
ULONG next = check;
for (LONG shift = 28; shift >= 0; shift -= 4) {
ULONG sum = ((next >> 12) ^ (data >> shift)) & 0xf;
next = (next << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
}
return (next & 0xFFFF);
}
// Calculate a CRC for the pointer to the Quadlet data.
// Quadlet - Pointer to data to CRC
// length - length of data to CRC
static USHORT Dbg1394_CalculateCrc(PULONG Quadlet, ULONG length)
{
ULONG temp = 0;
for (ULONG index = 0; index < length; index++) {
temp = Dbg1394_Crc16(Quadlet[index], temp);
}
return (USHORT)temp;
}
////////////////////////////////////////////////// Initialize the controller!
//
bool Kdp1394Init(Struct_Microsoft_Singularity_BootInfo *bi)
{
if (bi->Ohci1394Base == 0 ||
bi->Ohci1394BufferAddr32 == 0 ||
bi->Ohci1394BufferSize32 < sizeof(DEBUG_1394_DATA)) {
bi->Ohci1394Base = 0;
bi->Ohci1394BufferAddr32 = 0;
bi->Ohci1394BufferSize32 = 0;
return FALSE;
}
// Note: Kd1394Data must be in the low 32-bits of address space due to
// limits on valid 1394 DMA addresses. It must also be contiguous.
Kd1394Data = (DEBUG_1394_DATA *)bi->Ohci1394BufferAddr32;
memset(Kd1394Data, 0, sizeof(*Kd1394Data));
// get our base address
KdRegisters = (volatile OHCI_REGISTER_MAP *)bi->Ohci1394Base;
// initialize our config info for host debugger to read.
Kd1394Data->Config.Tag = DEBUG_1394_CONFIG_TAG;
Kd1394Data->Config.MajorVersion = DEBUG_1394_MAJOR_VERSION;
Kd1394Data->Config.MinorVersion = DEBUG_1394_MINOR_VERSION;
Kd1394Data->Config.Id = (bi->DebugBasePort < 0x100) ? bi->DebugBasePort : 0;
Kd1394Data->Config.BusPresent = FALSE;
Kd1394Data->Config.SendPacket = MmGetPhysicalAddress(&Kd1394Data->SendPacket);
Kd1394Data->Config.ReceivePacket = MmGetPhysicalAddress(&Kd1394Data->ReceivePacket);
// get our version
ULONG ulVersion = KdRegisters->Version.all;
UCHAR MajorVersion = (UCHAR)(ulVersion >> 16);
// make sure we have a valid version
if (MajorVersion != 1) { // INVESTIGATE
kdprintf("1394: MajorVersion != 1\n");
return FALSE;
}
// soft reset to initialize the controller
HC_CONTROL_REGISTER HCControl;
HCControl.all = 0;
HCControl.SoftReset = TRUE;
KdRegisters->HCControlSet.all = HCControl.all;
// wait until reset complete - ??
ULONG retry = 1000; // ??
do {
HCControl.all = KdRegisters->HCControlSet.all;
Dbg1394_StallExecution(1);
} while ((HCControl.SoftReset) && (--retry));
if (retry == 0) {
kdprintf("1394: Reset failed\n");
return FALSE;
}
// enable link to phy communication.
HCControl.all = 0;
HCControl.Lps = TRUE;
KdRegisters->HCControlSet.all = HCControl.all;
Dbg1394_StallExecution(20);
// initialize HCControl register
// send data in little-endian order (i.e. do byte swap).
HCControl.all = 0;
HCControl.NoByteSwapData = TRUE;
KdRegisters->HCControlClear.all = HCControl.all;
// enable posted writes.
HCControl.all = 0;
HCControl.PostedWriteEnable = TRUE;
KdRegisters->HCControlSet.all = HCControl.all;
// setup the link control
LINK_CONTROL_REGISTER LinkControl;
LinkControl.all = 0;
LinkControl.CycleTimerEnable = TRUE;
LinkControl.CycleMaster = TRUE;
LinkControl.RcvPhyPkt = TRUE;
LinkControl.RcvSelfId = TRUE;
KdRegisters->LinkControlClear.all = LinkControl.all;
LinkControl.all = 0;
LinkControl.CycleTimerEnable = TRUE;
LinkControl.CycleMaster = TRUE;
KdRegisters->LinkControlSet.all = LinkControl.all;
// set the bus number (hardcoded to 0x3FF) - ??? what about node id??
NODE_ID_REGISTER NodeId;
NodeId.all = 0;
NodeId.BusId = (USHORT)0x3FF;
KdRegisters->NodeId.all = NodeId.all;
// do something with the crom...
// 0xf0000404 - bus id register
Kd1394Data->CromBuffer[1] = 0x31333934;
// 0xf0000408 - bus options register
BUS_OPTIONS_REGISTER BusOptions;
BusOptions.all = Dbg1394_ByteSwap(KdRegisters->BusOptions.all);
BusOptions.Pmc = FALSE;
BusOptions.Bmc = FALSE;
BusOptions.Isc = FALSE;
BusOptions.Cmc = FALSE;
BusOptions.Irmc = FALSE;
BusOptions.g = 1;
Kd1394Data->CromBuffer[2] = Dbg1394_ByteSwap(BusOptions.all);
// 0xf000040c - global unique id hi
Kd1394Data->CromBuffer[3] = KdRegisters->GuidHi;
// 0xf0000410 - global unique id lo
Kd1394Data->CromBuffer[4] = KdRegisters->GuidLo;
// 0xf0000400 - config ROM header - set last to calculate CRC!
CONFIG_ROM_INFO ConfigRomHeader;
ConfigRomHeader.all = 0;
ConfigRomHeader.CRI_Info_Length = 4;
ConfigRomHeader.CRI_CRC_Length = 4;
ConfigRomHeader.CRI_CRC_Value = Dbg1394_CalculateCrc(&Kd1394Data->CromBuffer[1],
ConfigRomHeader.CRI_CRC_Length);
Kd1394Data->CromBuffer[0] = ConfigRomHeader.all;
Kd1394Data->CromBuffer[6] = 0xC083000C; // 0xf0000418 - node capabilities
Kd1394Data->CromBuffer[7] = 0xF2500003; // 0xf000041C - module vendor id
// KD's state machine looks for 1c w/ 50f2, 1d w/ 02, then 1e w/ address.
Kd1394Data->CromBuffer[8] = 0xF250001C; // 0xf0000420 - extended key (for KD)
Kd1394Data->CromBuffer[9] = 0x0200001D; // 0xf0000424 - debug key (for KD)
// 0xf0000428 - debug value (for KD)
IMMEDIATE_ENTRY CromEntry;
CromEntry.all = MmGetPhysicalAddress(&Kd1394Data->Config);
CromEntry.IE_Key = 0x1E;
Kd1394Data->CromBuffer[10] = Dbg1394_ByteSwap(CromEntry.all);
// 0xf0000414 - root directory header - set last to calculate CRC!
DIRECTORY_INFO DirectoryInfo;
DirectoryInfo.all = 0;
DirectoryInfo.DI_Length = 5;
DirectoryInfo.DI_CRC = Dbg1394_CalculateCrc(&Kd1394Data->CromBuffer[6],
DirectoryInfo.DI_Length);
Kd1394Data->CromBuffer[5] = Dbg1394_ByteSwap(DirectoryInfo.all);
// write the first few registers
KdRegisters->ConfigRomHeader.all = Kd1394Data->CromBuffer[0];
KdRegisters->BusId = Kd1394Data->CromBuffer[1];
KdRegisters->BusOptions.all = Kd1394Data->CromBuffer[2];
KdRegisters->GuidHi = Kd1394Data->CromBuffer[3];
KdRegisters->GuidLo = Kd1394Data->CromBuffer[4];
// set our crom
KdRegisters->ConfigRomMap = MmGetPhysicalAddress(&Kd1394Data->CromBuffer);
// disable all interrupts. wdm driver will enable them later - ??
KdRegisters->IntMaskClear.all = 0xFFFFFFFF;
// enable the link
HCControl.all = 0;
HCControl.LinkEnable = TRUE;
KdRegisters->HCControlSet.all = HCControl.all;
Dbg1394_StallExecution(1000);
// enable access filters to all nodes
KdRegisters->AsynchReqFilterLoSet = 0xFFFFFFFF;
KdRegisters->AsynchReqFilterHiSet = 0xFFFFFFFF;
KdRegisters->PhyReqFilterHiSet = 0xFFFFFFFF;
KdRegisters->PhyReqFilterLoSet = 0xFFFFFFFF;
// hard reset on the bus (so KD will look for us)
PHY_CONTROL_REGISTER PhyControl;
PhyControl.all = 0;
PhyControl.RdReg = TRUE;
PhyControl.RegAddr = 1;
KdRegisters->PhyControl.all = PhyControl.all;
retry = MAX_REGISTER_READS;
do {
PhyControl.all = KdRegisters->PhyControl.all;
} while ((!PhyControl.RdDone) && --retry);
if (retry == 0) {
kdprintf("1394: Read on bus failed\n");
return FALSE;
}
UCHAR Data = ((UCHAR)PhyControl.RdData | PHY_INITIATE_BUS_RESET);
PhyControl.all = 0;
PhyControl.WrReg = TRUE;
PhyControl.RegAddr = 1;
PhyControl.WrData = Data;
KDDBG2("1394: Writing to PhyControl=%08x\n", PhyControl.all);
KdRegisters->PhyControl.all = PhyControl.all;
retry = MAX_REGISTER_READS;
do {
PhyControl.all = KdRegisters->PhyControl.all;
} while (PhyControl.WrReg && --retry);
if (retry == 0) {
kdprintf("1394: Hard reset on bus failed\n");
return FALSE;
}
kdprintf("1394: Init Succeeded\n");
return TRUE;
}
static void Dbg1394_EnablePhysicalAccess()
{
// see if ohci1394 is being loaded...
HC_CONTROL_REGISTER HCControl;
HCControl.all = KdRegisters->HCControlSet.all;
if (!HCControl.LinkEnable || !HCControl.Lps || HCControl.SoftReset) {
KDDBG("1394: EnablePhysicalAccess HCControl=%08x!\n", HCControl.all);
return;
}
// if the bus reset interrupt is not cleared, we have to clear it...
INT_EVENT_MASK_REGISTER IntEvent;
IntEvent.all = KdRegisters->IntEventSet.all;
if (IntEvent.BusReset) {
KDDBG("1394: EnablePhysicalAccess IntEvent =%08x!\n", IntEvent.all);
IntEvent.all = 0;
IntEvent.BusReset = 1;
KdRegisters->IntEventClear.all = IntEvent.all;
}
// we might need to re-enable physical access. If so, do it.
KdRegisters->AsynchReqFilterHiSet = 0xFFFFFFFF;
KdRegisters->AsynchReqFilterLoSet = 0xFFFFFFFF;
KdRegisters->PhyReqFilterHiSet = 0xFFFFFFFF;
KdRegisters->PhyReqFilterLoSet = 0xFFFFFFFF;
}
static KDP_STATUS
Dbg1394_ReadPacket(
OUT PKD_PACKET PacketHeader,
OUT PSTRING MessageHeader,
OUT PSTRING MessageData,
bool Wait
)
// KDP_PACKET_RESEND - if resend is required. = 2 = CP_GET_ERROR
// KDP_PACKET_TIMEOUT - if timeout. = 1 = CP_GET_NODATA
// KDP_PACKET_RECEIVED - if packet received. = 0 = CP_GET_SUCCESS
{
ULONG timeoutLimit = 0;
do {
// make sure our link is enabled..
Dbg1394_EnablePhysicalAccess();
KdpSpin();
if (Kd1394Data->ReceivePacket.TransferStatus == STATUS_PENDING) {
KdDebuggerNotPresent = FALSE;
memcpy(PacketHeader,
&Kd1394Data->ReceivePacket.Packet[0],
sizeof(KD_PACKET));
// make sure we have a valid PacketHeader
if (Kd1394Data->ReceivePacket.Length < sizeof(KD_PACKET)) {
// short packet, we are done...
Kd1394Data->ReceivePacket.TransferStatus = STATUS_SUCCESS;
return(KDP_PACKET_RESEND);
}
if (MessageHeader) {
memcpy(MessageHeader->Buffer,
&Kd1394Data->ReceivePacket.Packet[sizeof(KD_PACKET)],
MessageHeader->MaximumLength);
if (Kd1394Data->ReceivePacket.Length <= (USHORT)(sizeof(KD_PACKET)+MessageHeader->MaximumLength)) {
Kd1394Data->ReceivePacket.TransferStatus = STATUS_SUCCESS;
return(KDP_PACKET_RECEIVED);
}
if (MessageData) {
memcpy(MessageData->Buffer,
&Kd1394Data->ReceivePacket.Packet[sizeof(KD_PACKET) + MessageHeader->MaximumLength],
Kd1394Data->ReceivePacket.Length - (sizeof(KD_PACKET) + MessageHeader->MaximumLength));
}
}
Kd1394Data->ReceivePacket.TransferStatus = STATUS_SUCCESS;
return(KDP_PACKET_RECEIVED);
}
timeoutLimit++;
if (Wait == FALSE) {
return(KDP_PACKET_RESEND);
}
} while (timeoutLimit <= TIMEOUT_COUNT);
return(KDP_PACKET_TIMEOUT);
}
//
// Send a control packet to the host machine that is running the
// kernel debugger and wait for an ACK.
//
// PacketType - Supplies the type of packet to send.
//
static void KdpSendControlPacket(IN USHORT PacketType)
{
KD_PACKET PacketHeader;
//
// Initialize and send the packet header.
//
PacketHeader.PacketLeader = CONTROL_PACKET_LEADER;
PacketHeader.PacketId = 0;
PacketHeader.ByteCount = 0;
PacketHeader.Checksum = 0;
PacketHeader.PacketType = PacketType;
// setup our send packet
memset(&Kd1394Data->SendPacket, 0, sizeof(DEBUG_1394_SEND_PACKET));
Kd1394Data->SendPacket.Length = 0;
memcpy(&Kd1394Data->SendPacket.PacketHeader[0],
&PacketHeader, sizeof(KD_PACKET));
Kd1394Data->SendPacket.TransferStatus = STATUS_PENDING;
}
KDP_STATUS
Kdp1394ReceivePacket(
IN ULONG PacketType,
OUT PSTRING MessageHeader,
OUT PSTRING MessageData,
OUT PULONG DataLength,
IN OUT PKD_CONTEXT KdContext
)
// Routine Description:
// This routine receives a packet from the host machine that is running
// the kernel debugger UI. This routine is ALWAYS called after packet being
// sent by caller. It first waits for ACK packet for the packet sent and
// then waits for the packet desired.
//
// N.B. If caller is KdPrintString, the parameter PacketType is
// PACKET_TYPE_KD_ACKNOWLEDGE. In this case, this routine will return
// right after the ack packet is received.
//
// Arguments:
// PacketType - Supplies the type of packet that is excepted.
// MessageHeader - Supplies a pointer to a string descriptor for the input
// message.
// MessageData - Supplies a pointer to a string descriptor for the input data.
// DataLength - Supplies pointer to ULONG to receive length of recv. data.
// KdContext - Supplies a pointer to the kernel debugger context.
//
// Return Value:
// KDP_PACKET_RESEND - if resend is required. = 2 = CP_GET_ERROR
// KDP_PACKET_TIMEOUT - if timeout. = 1 = CP_GET_NODATA
// KDP_PACKET_RECEIVED - if packet received. = 0 = CP_GET_SUCCESS
{
ULONG MessageLength;
KD_PACKET PacketHeader;
KDP_STATUS ReturnCode;
ULONG Checksum;
KDDBG2("Kdp1394ReceivePacket\n");
// this dispatch gets called with PacketType != PACKET_TYPE_KD_POLL_BREAKIN for
// the number of times specified in KdCompNumberRetries (??).
WaitForPacketLeader:
// read in our packet, if available...
ReturnCode = Dbg1394_ReadPacket(&PacketHeader,
MessageHeader,
MessageData,
TRUE);
//
// If we can successfully read packet leader, it has high possibility that
// kernel debugger is alive. So reset count.
//
if (ReturnCode != KDP_PACKET_TIMEOUT) {
KdCompNumberRetries = KdCompRetryCount;
}
if (ReturnCode != KDP_PACKET_RECEIVED) {
// see if it's a breakin packet...
if ((PacketHeader.PacketLeader & 0xFF) == BREAKIN_PACKET_BYTE) {
KdContext->KdpControlCPending = TRUE;
return(KDP_PACKET_RESEND);
}
return(ReturnCode);
}
//
// if the packet we received is a resend request, we return true and
// let caller resend the packet.
//
if (PacketHeader.PacketLeader == CONTROL_PACKET_LEADER &&
PacketHeader.PacketType == PACKET_TYPE_KD_RESEND) {
return(KDP_PACKET_RESEND);
}
//
// Check ByteCount received is valid
//
MessageLength = MessageHeader->MaximumLength;
if ((PacketHeader.ByteCount > (USHORT)PACKET_MAX_SIZE) ||
(PacketHeader.ByteCount < (USHORT)MessageLength)) {
goto SendResendPacket;
}
*DataLength = PacketHeader.ByteCount - MessageLength;
MessageData->Length = (USHORT)*DataLength;
MessageHeader->Length = (USHORT)MessageLength;
//
// Check PacketType is what we are waiting for.
//
if (PacketType != PacketHeader.PacketType) {
goto SendResendPacket;
}
//
// Check checksum is valid.
//
Checksum = KdpComputeChecksum(MessageHeader->Buffer, MessageHeader->Length);
Checksum += KdpComputeChecksum(MessageData->Buffer, MessageData->Length);
if (Checksum != PacketHeader.Checksum) {
goto SendResendPacket;
}
return(KDP_PACKET_RECEIVED);
SendResendPacket:
KdpSendControlPacket(PACKET_TYPE_KD_RESEND);
goto WaitForPacketLeader;
}
void
Kdp1394SendPacket(
IN ULONG PacketType,
IN PSTRING MessageHeader,
IN PSTRING MessageData OPTIONAL,
IN OUT PKD_CONTEXT KdContext
)
// Routine Description:
// This routine sends a packet to the host machine that is running the
// kernel debugger and waits for an ACK.
//
// Arguments:
// PacketType - Supplies the type of packet to send.
// MessageHeader - Supplies a pointer to a string descriptor that describes
// the message information.
// MessageData - Supplies a pointer to a string descriptor that describes
// the optional message data.
// KdContext - Supplies a pointer to the kernel debugger context.
//
// Return Value:
// None.
{
KD_PACKET PacketHeader;
ULONG MessageDataLength;
ULONG ReturnCode;
bool bException = FALSE;
KDDBG2("Kdp1394SendPacket\n");
PacketHeader.Checksum = 0;
if (MessageData != NULL) {
MessageDataLength = MessageData->Length;
PacketHeader.Checksum = KdpComputeChecksum(MessageData->Buffer, MessageData->Length);
}
else {
MessageDataLength = 0;
PacketHeader.Checksum = 0;
}
PacketHeader.Checksum += KdpComputeChecksum(MessageHeader->Buffer, MessageHeader->Length);
//
// Initialize and send the packet header.
//
PacketHeader.PacketLeader = PACKET_LEADER;
PacketHeader.ByteCount = (USHORT)(MessageHeader->Length + MessageDataLength);
PacketHeader.PacketType = (USHORT)PacketType;
PacketHeader.PacketId = KdPacketId;
KdPacketId++;
KdCompNumberRetries = KdCompRetryCount;
// setup our send packet
memset(&Kd1394Data->SendPacket, 0, sizeof(DEBUG_1394_SEND_PACKET));
Kd1394Data->SendPacket.Length = 0;
// copy our packet header...
memcpy(&Kd1394Data->SendPacket.PacketHeader[0],
&PacketHeader, sizeof(KD_PACKET));
// setup our message header
if (MessageHeader) {
memcpy(&Kd1394Data->SendPacket.Packet[0],
MessageHeader->Buffer, MessageHeader->Length);
Kd1394Data->SendPacket.Length += MessageHeader->Length;
}
// setup our message data
if (MessageData != NULL) {
memcpy(&Kd1394Data->SendPacket.Packet[Kd1394Data->SendPacket.Length],
MessageData->Buffer, MessageData->Length);
Kd1394Data->SendPacket.Length += MessageData->Length;
}
Kd1394Data->SendPacket.TransferStatus = STATUS_PENDING;
//
// We sync on first STATE_CHANGE64 message like NT. If this
// is the first such message, drain receive pipe as nothing
// said before this instant is interesting (and any buffered
// packets may interact badly with SendWaitContinue).
//
if (PacketType == PACKET_TYPE_KD_STATE_CHANGE64 /* && !KdStateChange64Sent*/) {
// need to do this to fix pre-logging (eventually).
#if 0
UCHAR uDummy;
DWORD dwDrained = 0;
KdCompNextPacketIdToSend |= SYNC_PACKET_ID;
KdStateChange64Sent = TRUE;
while (KdCompGetByte(&uDummy) == CP_GET_SUCCESS)
dwDrained++;
#endif // 0
}
do {
KDDBG2("LOOP %d/%d [SendPacket=%p %08x %08x %08x %02x %02x %02x %02x]\n",
KdCompNumberRetries, KdCompRetryCount,
&Kd1394Data->SendPacket,
Kd1394Data->SendPacket.TransferStatus,
*(ULONG*)&Kd1394Data->SendPacket.PacketHeader,
Kd1394Data->SendPacket.Length,
Kd1394Data->SendPacket.Packet[0],
Kd1394Data->SendPacket.Packet[1],
Kd1394Data->SendPacket.Packet[2],
Kd1394Data->SendPacket.Packet[3]);
// make sure our link is enabled..
Dbg1394_EnablePhysicalAccess();
if (KdCompNumberRetries == 0) {
//
// If the packet is not for reporting exception, we give up
// and declare debugger not present.
//
if (PacketType == PACKET_TYPE_KD_DEBUG_IO) {
PDBGKD_DEBUG_IO DebugIo
= (PDBGKD_DEBUG_IO)MessageHeader->Buffer;
if (DebugIo->ApiNumber == DbgKdPrintStringApi) {
KdDebuggerNotPresent = TRUE;
Kd1394Data->SendPacket.TransferStatus = STATUS_SUCCESS;
return;
}
}
else if (PacketType == PACKET_TYPE_KD_STATE_CHANGE64) {
PDBGKD_ANY_WAIT_STATE_CHANGE StateChange
= (PDBGKD_ANY_WAIT_STATE_CHANGE)MessageHeader->Buffer;
if (StateChange->NewState == DbgKdLoadSymbolsStateChange) {
KdDebuggerNotPresent = TRUE;
Kd1394Data->SendPacket.TransferStatus = STATUS_SUCCESS;
return;
}
}
#if 0
else if (PacketType == PACKET_TYPE_KD_FILE_IO) {
PDBGKD_FILE_IO FileIo
= (PDBGKD_FILE_IO)MessageHeader->Buffer;
if (FileIo->ApiNumber == DbgKdCreateFileApi) {
KdDebuggerNotPresent = TRUE;
Kd1394Data->SendPacket.TransferStatus = STATUS_SUCCESS;
return;
}
}
#endif
else {
bException = TRUE;
}
}
ReturnCode = KDP_PACKET_TIMEOUT;
{
ULONG count = 0;
volatile NTSTATUS *pStatus;
pStatus = &Kd1394Data->ReceivePacket.TransferStatus;
//
// now sit here and poll for a response from the host machine
//
do {
// make sure our link is enabled..
Dbg1394_EnablePhysicalAccess();
KdpSpin();
//
// while in this loop check if the host has submitted a new request.
// If they did, abort processing of the current request.
//
count++;
if (Kd1394Data->SendPacket.TransferStatus != STATUS_PENDING) {
ReturnCode = KDP_PACKET_RECEIVED;
break;
}
if ((*pStatus == STATUS_PENDING) && (!bException)) {
ReturnCode = KDP_PACKET_RECEIVED;
break;
}
} while (count < TIMEOUT_COUNT);
}
if (ReturnCode == KDP_PACKET_TIMEOUT) {
KdCompNumberRetries--;
}
} while (ReturnCode != KDP_PACKET_RECEIVED);
//
// Since we are able to talk to debugger, the retrycount is set to
// maximum value.
//
KdCompRetryCount = KdContext->KdpDefaultRetries;
}
// Returns TRUE if a breakin packet is pending.
// A packet is present if: There is a valid character which matches BREAK_CHAR.
bool Kdp1394PollBreakIn(VOID)
{
KDDBG2("Kdp1394PollBreakIn\n");
// make sure our link is enabled..
Dbg1394_EnablePhysicalAccess();
// let's peak into our receive packet and see if it's a breakin
if ((Kd1394Data->ReceivePacket.TransferStatus == STATUS_PENDING) &&
(Kd1394Data->ReceivePacket.Packet[0] == BREAKIN_PACKET_BYTE)) {
KdDebuggerNotPresent = FALSE;
// we have a breakin packet
Kd1394Data->ReceivePacket.TransferStatus = STATUS_SUCCESS;
return true;
}
return false;
}
//
///////////////////////////////////////////////////////////////// End of File.