811 lines
27 KiB
C++
811 lines
27 KiB
C++
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft Research Singularity
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// File: 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
|
|
//
|
|
// Note: Kernel Only
|
|
//
|
|
|
|
#include "hal.h"
|
|
#include "halkd.h"
|
|
#include "halkd1394.h"
|
|
|
|
//
|
|
// 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 {
|
|
UINT32 TransferStatus;
|
|
UINT32 PacketHeader[4];
|
|
UINT32 Length;
|
|
UCHAR Packet[DEBUG_BUS1394_MAX_PACKET_SIZE];
|
|
UCHAR Padding[72];
|
|
};
|
|
STATIC_ASSERT(sizeof(DEBUG_1394_SEND_PACKET) == 4096);
|
|
|
|
struct DEBUG_1394_RECEIVE_PACKET {
|
|
UINT32 TransferStatus;
|
|
UINT32 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 {
|
|
UINT32 Tag;
|
|
UINT16 MajorVersion;
|
|
UINT16 MinorVersion;
|
|
UINT32 Id;
|
|
UINT32 BusPresent;
|
|
UINT64 SendPacket;
|
|
UINT64 ReceivePacket;
|
|
};
|
|
STATIC_ASSERT(sizeof(DEBUG_1394_CONFIG) == 32);
|
|
|
|
struct DEBUG_1394_DATA {
|
|
// POHCI_REGISTER_MAP BaseAddress; // our OHCI register map
|
|
UINT32 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 UINT32 Dbg1394_StallExecution(UINT32 LoopCount)
|
|
{
|
|
volatile UINT32 b = 1;
|
|
|
|
for (volatile UINT32 k = 0; k < LoopCount; k++) {
|
|
for (volatile UINT32 i = 1; i < 100000; i++) {
|
|
#ifdef ISA_IX86
|
|
__asm pause;
|
|
#endif
|
|
b = b * (i>>k);
|
|
}
|
|
}
|
|
|
|
return b;
|
|
}
|
|
|
|
// Exchange byte pairs 0:3 and 1:2 of Source and returns the resulting ULONG.
|
|
static inline UINT32 Dbg1394_ByteSwap(UINT32 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 - UINT32 data to derive CRC from.
|
|
// check - check value.
|
|
static UINT32 Dbg1394_Crc16(UINT32 data, UINT32 check)
|
|
{
|
|
UINT32 next = check;
|
|
|
|
for (INT32 shift = 28; shift >= 0; shift -= 4) {
|
|
UINT32 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 UINT16 Dbg1394_CalculateCrc(UINT32 *Quadlet, UINT32 length)
|
|
{
|
|
UINT32 temp = 0;
|
|
|
|
for (UINT32 index = 0; index < length; index++) {
|
|
temp = Dbg1394_Crc16(Quadlet[index], temp);
|
|
}
|
|
return (UINT16)temp;
|
|
}
|
|
|
|
////////////////////////////////////////////////// Initialize the controller!
|
|
//
|
|
bool Kdp1394Init(UINT16 Channel, ULONG_PTR Base, ULONG_PTR BufferAddr32, UINT32 BufferSize32)
|
|
{
|
|
if (Base == 0 ||
|
|
BufferAddr32 == 0 ||
|
|
BufferSize32 < sizeof(DEBUG_1394_DATA)) {
|
|
|
|
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 *)BufferAddr32;
|
|
memset(Kd1394Data, 0, sizeof(*Kd1394Data));
|
|
|
|
// get our base address
|
|
KdRegisters = (volatile OHCI_REGISTER_MAP *)Base;
|
|
|
|
// 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 = (Channel < 0x100) ? Channel : 0;
|
|
Kd1394Data->Config.BusPresent = false;
|
|
Kd1394Data->Config.SendPacket = MmGetPhysicalAddress(&Kd1394Data->SendPacket);
|
|
Kd1394Data->Config.ReceivePacket = MmGetPhysicalAddress(&Kd1394Data->ReceivePacket);
|
|
|
|
// get our version
|
|
UINT32 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 - ??
|
|
UINT32 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 = (UINT16)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 = (UINT32)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 = (UINT32)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
|
|
{
|
|
UINT32 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 <= (UINT16)(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 UINT16 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 UINT32 PacketType,
|
|
OUT PSTRING MessageHeader,
|
|
OUT PSTRING MessageData,
|
|
OUT UINT32 * 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 UINT32 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
|
|
{
|
|
UINT32 MessageLength;
|
|
KD_PACKET PacketHeader;
|
|
KDP_STATUS ReturnCode;
|
|
UINT32 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 > (UINT16)PACKET_MAX_SIZE) ||
|
|
(PacketHeader.ByteCount < (UINT16)MessageLength)) {
|
|
goto SendResendPacket;
|
|
}
|
|
*DataLength = PacketHeader.ByteCount - MessageLength;
|
|
|
|
MessageData->Length = (UINT16)*DataLength;
|
|
MessageHeader->Length = (UINT16)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 UINT32 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;
|
|
UINT32 MessageDataLength;
|
|
UINT32 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 = (UINT16)(MessageHeader->Length + MessageDataLength);
|
|
PacketHeader.PacketType = (UINT16)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;
|
|
uint32 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,
|
|
*(UINT32*)&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;
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
else {
|
|
bException = true;
|
|
}
|
|
}
|
|
|
|
ReturnCode = KDP_PACKET_TIMEOUT;
|
|
|
|
{
|
|
UINT32 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.
|