894 lines
20 KiB
C++
894 lines
20 KiB
C++
//++
|
|
//
|
|
// Copyright (c) Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
//
|
|
// blkd1394.cpp
|
|
//
|
|
// Abstract:
|
|
//
|
|
// This module implements the 1394 transport for KD.
|
|
//
|
|
//--
|
|
|
|
#include "bl.h"
|
|
#include "blkd1394.h"
|
|
|
|
#if defined(BOOT_X64)
|
|
|
|
BOOLEAN
|
|
BlKd1394InitHardware(
|
|
UINT16 Channel,
|
|
PVOID IoRegion
|
|
)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
BOOLEAN
|
|
BlKd1394Connect(
|
|
VOID
|
|
)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
BOOLEAN
|
|
BlKd1394SendPacket(
|
|
UINT16 PacketType,
|
|
PCVOID Header,
|
|
UINT16 HeaderSize,
|
|
PCVOID Data,
|
|
UINT16 DataSize)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
#else // !defined(BOOT_X64)
|
|
|
|
#define PACKET_READY 0x00000000 // Aka STATUS_SUCCESS
|
|
#define PACKET_PENDING 0x00000103 // Aka STATUS_PENDING
|
|
|
|
//
|
|
// Change these macros to debug the debugger transport.
|
|
//
|
|
|
|
#define KDDBG if (0) BlVideoPrintf
|
|
#define KDDBG2 if (0) BlVideoPrintf
|
|
|
|
//
|
|
// 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
|
|
|
|
typedef struct _DEBUG_1394_SEND_PACKET {
|
|
UINT32 TransferStatus;
|
|
UINT32 PacketHeader[4];
|
|
UINT32 Length;
|
|
UINT8 Packet[DEBUG_BUS1394_MAX_PACKET_SIZE];
|
|
UINT8 Padding[72];
|
|
} DEBUG_1394_SEND_PACKET;
|
|
|
|
C_ASSERT(sizeof(DEBUG_1394_SEND_PACKET) == 4096);
|
|
|
|
typedef struct _DEBUG_1394_RECEIVE_PACKET {
|
|
UINT32 TransferStatus;
|
|
UINT32 Length;
|
|
UINT8 Packet[DEBUG_BUS1394_MAX_PACKET_SIZE];
|
|
UINT8 Padding[88];
|
|
} DEBUG_1394_RECEIVE_PACKET;
|
|
|
|
C_ASSERT(sizeof(DEBUG_1394_RECEIVE_PACKET) == 4096);
|
|
|
|
typedef struct _DEBUG_1394_CONFIG {
|
|
UINT32 Tag;
|
|
UINT16 MajorVersion;
|
|
UINT16 MinorVersion;
|
|
UINT32 Id;
|
|
UINT32 BusPresent;
|
|
UINT64 SendPacket;
|
|
UINT64 ReceivePacket;
|
|
} DEBUG_1394_CONFIG;
|
|
|
|
C_ASSERT(sizeof(DEBUG_1394_CONFIG) == 32);
|
|
|
|
typedef struct _DEBUG_1394_DATA {
|
|
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
|
|
} DEBUG_1394_DATA;
|
|
|
|
C_ASSERT(sizeof(DEBUG_1394_DATA) == 1024 + 4096 + 4096);
|
|
|
|
//
|
|
// Timing constants.
|
|
//
|
|
|
|
#define TIMEOUT_COUNT 100000
|
|
#define MAX_REGISTER_READS 400000
|
|
|
|
//
|
|
// Static Data Structures
|
|
//
|
|
|
|
static DEBUG_1394_DATA * Kd1394Data = NULL;
|
|
static volatile OHCI_REGISTER_MAP * KdRegisters = NULL;
|
|
|
|
UINT32
|
|
BlKd1394StallExecution(
|
|
UINT32 LoopCount
|
|
)
|
|
|
|
//++
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Stall for a finite time to allow hardware to respond.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// LoopCount - Number of times to run the outer loop.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// Ignored.
|
|
//
|
|
//--
|
|
|
|
{
|
|
volatile UINT32 b;
|
|
volatile UINT32 k;
|
|
volatile UINT32 i;
|
|
|
|
b = 1;
|
|
|
|
for (k = 0; k < LoopCount; k++) {
|
|
|
|
BlKdSpin();
|
|
|
|
for (i = 1; i < 10000; i++) {
|
|
|
|
b = b * (i>>k);
|
|
}
|
|
}
|
|
return b;
|
|
}
|
|
|
|
UINT32
|
|
BlKd1394ByteSwap(
|
|
UINT32 Source
|
|
)
|
|
|
|
//++
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Reverse the order of byte in the UINT32.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Source - 32-bit UINT32 value.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// The input value with byte pairs 0:3 and 1:2 swapped.
|
|
//
|
|
//--
|
|
|
|
{
|
|
return (((Source) << (8 * 3)) |
|
|
((Source & 0x0000FF00) << (8 * 1)) |
|
|
((Source & 0x00FF0000) >> (8 * 1)) |
|
|
((Source) >> (8 * 3)));
|
|
}
|
|
|
|
UINT32
|
|
BlKd1394Crc16(
|
|
UINT32 Data,
|
|
UINT32 Check
|
|
)
|
|
|
|
//++
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Derive the 16-bit CRC as defined by IEEE 1212 clause 8.1.5. (ISO/IEC 13213)
|
|
// First edition 1994-10-05.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Data - UINT32 data to derive CRC from.
|
|
//
|
|
// Check - check value.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// The 16-bit CRC.
|
|
//
|
|
//--
|
|
|
|
{
|
|
UINT32 Next = Check;
|
|
INT32 Shift;
|
|
|
|
for (Shift = 28; Shift >= 0; Shift -= 4) {
|
|
UINT32 Sum;
|
|
|
|
Sum = ((Next >> 12) ^ (Data >> Shift)) & 0xf;
|
|
Next = (Next << 4) ^ (Sum << 12) ^ (Sum << 5) ^ (Sum);
|
|
}
|
|
return (Next & 0xFFFF);
|
|
}
|
|
|
|
UINT16
|
|
BlKd1394CalculateCrc(
|
|
UINT32 *Quadlet,
|
|
UINT32 Length
|
|
)
|
|
|
|
//++
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Calculate a CRC for the pointer to the Quadlet data.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Quadlet - Pointer to data to CRC.
|
|
//
|
|
// Length - Length of data to CRC.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// The 16-bit CRC.
|
|
//
|
|
//--
|
|
|
|
{
|
|
UINT32 Temp = 0;
|
|
UINT32 Index;
|
|
|
|
Temp = 0;
|
|
|
|
for (Index = 0; Index < Length; Index++) {
|
|
|
|
Temp = BlKd1394Crc16(Quadlet[Index], Temp);
|
|
}
|
|
|
|
return (UINT16)Temp;
|
|
}
|
|
|
|
BOOLEAN
|
|
BlKd1394InitHardware(
|
|
UINT16 Channel,
|
|
PVOID IoRegion
|
|
)
|
|
|
|
//++
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// Initialize the 1394 hardware and connect it to KD.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Channel - KD 1394 Channel. Default is channel 0, but can be changed if 1394 is shared.
|
|
//
|
|
// IoRegion - Pointer to the 1394 registers mapped into our address space.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// The 16-bit CRC.
|
|
//
|
|
//--
|
|
|
|
{
|
|
UINT32 ulVersion;
|
|
UINT8 MajorVersion;
|
|
HC_CONTROL_REGISTER HCControl;
|
|
UINT32 retry;
|
|
LINK_CONTROL_REGISTER LinkControl;
|
|
NODE_ID_REGISTER NodeId;
|
|
BUS_OPTIONS_REGISTER BusOptions;
|
|
CONFIG_ROM_INFO ConfigRomHeader;
|
|
IMMEDIATE_ENTRY CromEntry;
|
|
DIRECTORY_INFO DirInfo;
|
|
PHY_CONTROL_REGISTER PhyControl;
|
|
UINT8 Data;
|
|
volatile OHCI_REGISTER_MAP * Registers;
|
|
|
|
#if KD_VERBOSE
|
|
|
|
BlVideoPrintf("1394: IoRegion: %p\n", IoRegion);
|
|
|
|
#endif
|
|
|
|
//
|
|
// 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.
|
|
// It must be in the low 24-bits of address space to statisfy KD.
|
|
//
|
|
|
|
Kd1394Data = (DEBUG_1394_DATA *) BlSingularityOhci1394Buffer;
|
|
BlRtlZeroMemory(Kd1394Data, sizeof(*Kd1394Data));
|
|
|
|
//
|
|
// Get our base address.
|
|
//
|
|
|
|
Registers = (volatile OHCI_REGISTER_MAP *)IoRegion;
|
|
|
|
//
|
|
// 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;
|
|
Kd1394Data->Config.BusPresent = FALSE;
|
|
Kd1394Data->Config.SendPacket = (UINT64) &Kd1394Data->SendPacket;
|
|
Kd1394Data->Config.ReceivePacket = (UINT64) &Kd1394Data->ReceivePacket;
|
|
|
|
//
|
|
// Get the transport version.
|
|
//
|
|
|
|
ulVersion = Registers->Version.all;
|
|
MajorVersion = (UINT8)(ulVersion >> 16);
|
|
|
|
//
|
|
// Make sure we have a valid version.
|
|
//
|
|
|
|
if (MajorVersion != 1) { // INVESTIGATE
|
|
|
|
#if KD_VERBOSE
|
|
|
|
BlVideoPrintf("1394: MajorVersion != 1\n");
|
|
|
|
#endif
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Soft reset to initialize the controller.
|
|
//
|
|
|
|
HCControl.all = 0;
|
|
HCControl.SoftReset = TRUE;
|
|
Registers->HCControlSet.all = HCControl.all;
|
|
|
|
//
|
|
// wait until reset completes.
|
|
//
|
|
|
|
retry = 1000; // ??
|
|
|
|
do {
|
|
|
|
HCControl.all = Registers->HCControlSet.all;
|
|
|
|
BlKd1394StallExecution(1);
|
|
|
|
} while ((HCControl.SoftReset) && (--retry));
|
|
|
|
if (retry == 0) {
|
|
|
|
#if KD_VERBOSE
|
|
|
|
BlVideoPrintf("1394: Reset failed\n");
|
|
|
|
#endif
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Enable link to phy communication.
|
|
//
|
|
|
|
HCControl.all = 0;
|
|
HCControl.Lps = TRUE;
|
|
Registers->HCControlSet.all = HCControl.all;
|
|
|
|
BlKd1394StallExecution(20);
|
|
|
|
//
|
|
// Initialize HCControl register
|
|
// Send data in little-endian order (i.e. do byte swap).
|
|
//
|
|
|
|
HCControl.all = 0;
|
|
HCControl.NoByteSwapData = TRUE;
|
|
Registers->HCControlClear.all = HCControl.all;
|
|
|
|
//
|
|
// Enable posted writes.
|
|
//
|
|
|
|
HCControl.all = 0;
|
|
HCControl.PostedWriteEnable = TRUE;
|
|
Registers->HCControlSet.all = HCControl.all;
|
|
|
|
//
|
|
// Setup the link control.
|
|
//
|
|
|
|
LinkControl.all = 0;
|
|
LinkControl.CycleTimerEnable = TRUE;
|
|
LinkControl.CycleMaster = TRUE;
|
|
LinkControl.RcvPhyPkt = TRUE;
|
|
LinkControl.RcvSelfId = TRUE;
|
|
Registers->LinkControlClear.all = LinkControl.all;
|
|
|
|
LinkControl.all = 0;
|
|
LinkControl.CycleTimerEnable = TRUE;
|
|
LinkControl.CycleMaster = TRUE;
|
|
Registers->LinkControlSet.all = LinkControl.all;
|
|
|
|
//
|
|
// Set the bus number (hardcoded to 0x3FF) - ??? what about node id??
|
|
//
|
|
|
|
NodeId.all = 0;
|
|
NodeId.BusId = (UINT16)0x3FF;
|
|
Registers->NodeId.all = NodeId.all;
|
|
|
|
//
|
|
// Do something with the crom...
|
|
//
|
|
|
|
//
|
|
// 0xf0000404 - bus id register
|
|
//
|
|
Kd1394Data->CromBuffer[1] = 0x31333934;
|
|
|
|
//
|
|
// 0xf0000408 - bus options register
|
|
//
|
|
|
|
BusOptions.all = BlKd1394ByteSwap(Registers->BusOptions.all);
|
|
BusOptions.Pmc = FALSE;
|
|
BusOptions.Bmc = FALSE;
|
|
BusOptions.Isc = FALSE;
|
|
BusOptions.Cmc = FALSE;
|
|
BusOptions.Irmc = FALSE;
|
|
BusOptions.g = 1;
|
|
Kd1394Data->CromBuffer[2] = BlKd1394ByteSwap(BusOptions.all);
|
|
|
|
//
|
|
// 0xf000040c - global unique id hi
|
|
//
|
|
|
|
Kd1394Data->CromBuffer[3] = Registers->GuidHi;
|
|
|
|
//
|
|
// 0xf0000410 - global unique id lo
|
|
//
|
|
|
|
Kd1394Data->CromBuffer[4] = Registers->GuidLo;
|
|
|
|
//
|
|
// 0xf0000400 - config ROM header - set last to calculate CRC!
|
|
//
|
|
|
|
ConfigRomHeader.all = 0;
|
|
ConfigRomHeader.CRI_Info_Length = 4;
|
|
ConfigRomHeader.CRI_CRC_Length = 4;
|
|
ConfigRomHeader.CRI_CRC_Value = BlKd1394CalculateCrc(&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)
|
|
//
|
|
|
|
CromEntry.all = (UINT32)(ULONG_PTR) &Kd1394Data->Config;
|
|
CromEntry.IE_Key = 0x1E;
|
|
Kd1394Data->CromBuffer[10] = BlKd1394ByteSwap(CromEntry.all);
|
|
|
|
//
|
|
// 0xf0000414 - root directory header - set last to calculate CRC!
|
|
//
|
|
|
|
DirInfo.all = 0;
|
|
DirInfo.DI_Length = 5;
|
|
DirInfo.DI_CRC = BlKd1394CalculateCrc(&Kd1394Data->CromBuffer[6], DirInfo.DI_Length);
|
|
Kd1394Data->CromBuffer[5] = BlKd1394ByteSwap(DirInfo.all);
|
|
|
|
//
|
|
// Write the first few registers.
|
|
//
|
|
|
|
Registers->ConfigRomHeader.all = Kd1394Data->CromBuffer[0];
|
|
Registers->BusId = Kd1394Data->CromBuffer[1];
|
|
Registers->BusOptions.all = Kd1394Data->CromBuffer[2];
|
|
Registers->GuidHi = Kd1394Data->CromBuffer[3];
|
|
Registers->GuidLo = Kd1394Data->CromBuffer[4];
|
|
|
|
//
|
|
// Set our crom.
|
|
//
|
|
|
|
Registers->ConfigRomMap = (UINT32)(ULONG_PTR) &Kd1394Data->CromBuffer;
|
|
|
|
//
|
|
// Disable all interrupts, we use polling for the debugger transport.
|
|
//
|
|
|
|
Registers->IntMaskClear.all = 0xFFFFFFFF;
|
|
|
|
//
|
|
// Enable the link.
|
|
//
|
|
|
|
HCControl.all = 0;
|
|
HCControl.LinkEnable = TRUE;
|
|
Registers->HCControlSet.all = HCControl.all;
|
|
|
|
BlKd1394StallExecution(1000);
|
|
|
|
//
|
|
// Enable access filters to all nodes.
|
|
//
|
|
|
|
Registers->AsynchReqFilterLoSet = 0xFFFFFFFF;
|
|
Registers->AsynchReqFilterHiSet = 0xFFFFFFFF;
|
|
Registers->PhyReqFilterHiSet = 0xFFFFFFFF;
|
|
Registers->PhyReqFilterLoSet = 0xFFFFFFFF;
|
|
|
|
//
|
|
// Hard reset on the bus (so KD will look for us).
|
|
//
|
|
|
|
PhyControl.all = 0;
|
|
PhyControl.RdReg = TRUE;
|
|
PhyControl.RegAddr = 1;
|
|
Registers->PhyControl.all = PhyControl.all;
|
|
|
|
retry = MAX_REGISTER_READS;
|
|
|
|
do {
|
|
|
|
PhyControl.all = Registers->PhyControl.all;
|
|
|
|
} while ((!PhyControl.RdDone) && --retry);
|
|
|
|
if (retry == 0) {
|
|
|
|
#if KD_VERBOSE
|
|
|
|
BlVideoPrintf("1394: Bus read failed.\n");
|
|
|
|
#endif
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
Data = ((UINT8)PhyControl.RdData | PHY_INITIATE_BUS_RESET);
|
|
|
|
PhyControl.all = 0;
|
|
PhyControl.WrReg = TRUE;
|
|
PhyControl.RegAddr = 1;
|
|
PhyControl.WrData = Data;
|
|
Registers->PhyControl.all = PhyControl.all;
|
|
|
|
retry = MAX_REGISTER_READS;
|
|
|
|
do {
|
|
|
|
PhyControl.all = Registers->PhyControl.all;
|
|
|
|
} while (PhyControl.WrReg && --retry);
|
|
|
|
if (retry == 0) {
|
|
|
|
#if KD_VERBOSE
|
|
|
|
BlVideoPrintf("1394: Hard reset of bus failed\n");
|
|
|
|
#endif
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
#if KD_VERBOSE
|
|
|
|
BlVideoPrintf("1394: Hardware init succeeded.\n");
|
|
|
|
#endif
|
|
|
|
KdRegisters = Registers;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
VOID
|
|
BlKd1394EnablePhysicalAccess(
|
|
VOID
|
|
)
|
|
{
|
|
HC_CONTROL_REGISTER HCControl;
|
|
INT_EVENT_MASK_REGISTER IntEvent;
|
|
|
|
//
|
|
// See if ohci1394 is being loaded...
|
|
//
|
|
|
|
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...
|
|
//
|
|
|
|
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;
|
|
}
|
|
|
|
//
|
|
// Re-enable physical access as it may be necessary.
|
|
//
|
|
|
|
KdRegisters->AsynchReqFilterHiSet = 0xFFFFFFFF;
|
|
KdRegisters->AsynchReqFilterLoSet = 0xFFFFFFFF;
|
|
KdRegisters->PhyReqFilterHiSet = 0xFFFFFFFF;
|
|
KdRegisters->PhyReqFilterLoSet = 0xFFFFFFFF;
|
|
|
|
return;
|
|
}
|
|
|
|
BOOLEAN
|
|
BlKd1394SendPacket(
|
|
UINT16 PacketType,
|
|
PCVOID Header,
|
|
UINT16 HeaderSize,
|
|
PCVOID Data,
|
|
UINT16 DataSize)
|
|
|
|
//++
|
|
//
|
|
// 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 the packet to send.
|
|
//
|
|
// Header - Supplies a pointer to the header.
|
|
//
|
|
// HeaderSize - Supplies the size of the header.
|
|
//
|
|
// Data - Supplies a pointer to the data.
|
|
//
|
|
// DataSize - Supplies the size of the data.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// TRUE, if send operation was successful.
|
|
// FALSE, otherwise.
|
|
//
|
|
//--
|
|
|
|
{
|
|
KD_PACKET PacketHeader;
|
|
UINT32 Retries;
|
|
UINT32 count;
|
|
volatile UINT32 *pStatus;
|
|
|
|
KDDBG2("BlKd1394SendPacket\n");
|
|
|
|
//
|
|
// Abort if the hardware hasn't been initialized.
|
|
//
|
|
|
|
if (KdRegisters == NULL) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Initialize the packet header.
|
|
//
|
|
|
|
PacketHeader.PacketLeader = KD_PACKET_LEADER;
|
|
PacketHeader.ByteCount = HeaderSize + DataSize;
|
|
PacketHeader.PacketType = PacketType;
|
|
PacketHeader.PacketId = BlKdNextPacketId++;
|
|
PacketHeader.Checksum = (BlKdComputeChecksum(Header, HeaderSize) +
|
|
BlKdComputeChecksum(Data, DataSize));
|
|
|
|
//
|
|
// Setup our send packet.
|
|
//
|
|
|
|
BlRtlZeroMemory(&Kd1394Data->SendPacket, sizeof(DEBUG_1394_SEND_PACKET));
|
|
Kd1394Data->SendPacket.Length = 0; // Redundant.
|
|
|
|
//
|
|
// Copy our packet header into the transmit region.
|
|
//
|
|
|
|
BlRtlCopyMemory(&Kd1394Data->SendPacket.PacketHeader[0], &PacketHeader, sizeof(KD_PACKET));
|
|
|
|
//
|
|
// Setup our message header.
|
|
//
|
|
|
|
if (HeaderSize > 0) {
|
|
|
|
BlRtlCopyMemory(&Kd1394Data->SendPacket.Packet[0], Header, HeaderSize);
|
|
Kd1394Data->SendPacket.Length = HeaderSize;
|
|
}
|
|
|
|
//
|
|
// Setup our message data.
|
|
//
|
|
|
|
if (DataSize > 0) {
|
|
|
|
BlRtlCopyMemory(&Kd1394Data->SendPacket.Packet[Kd1394Data->SendPacket.Length], Data, DataSize);
|
|
Kd1394Data->SendPacket.Length += DataSize;
|
|
}
|
|
|
|
//
|
|
// Mark the packet as ready for processing by host.
|
|
//
|
|
|
|
Kd1394Data->SendPacket.TransferStatus = PACKET_PENDING;
|
|
|
|
//
|
|
// Wait for our packet to be acknowledged by the host.
|
|
//
|
|
|
|
for (Retries = KD_RETRY_COUNT; Retries > 0; Retries--) {
|
|
|
|
KDDBG2("LOOP %d [SendPacket=%p %08x %08x %08x %02x %02x %02x %02x]\n",
|
|
Retries,
|
|
&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..
|
|
//
|
|
|
|
BlKd1394EnablePhysicalAccess();
|
|
|
|
pStatus = &Kd1394Data->ReceivePacket.TransferStatus;
|
|
|
|
//
|
|
// now sit here and poll for a response from the host machine
|
|
//
|
|
|
|
for (count = 0; count < TIMEOUT_COUNT; count++) {
|
|
|
|
//
|
|
// make sure our link is enabled..
|
|
//
|
|
|
|
BlKd1394EnablePhysicalAccess();
|
|
BlKdSpin();
|
|
|
|
//
|
|
// Check to see if the host has ACK'd our packet.
|
|
//
|
|
|
|
if (Kd1394Data->SendPacket.TransferStatus != PACKET_PENDING) {
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// While in this loop check if the host has submitted a new request.
|
|
// If they did, ACK it, and retry.
|
|
//
|
|
|
|
if (*pStatus == PACKET_PENDING) {
|
|
|
|
//
|
|
// ACK the packet from the debugger so it will accept our packet.
|
|
//
|
|
|
|
*pStatus = PACKET_READY;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOLEAN
|
|
BlKd1394Connect(
|
|
VOID
|
|
)
|
|
|
|
//++
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This function tries to connect to the KD through a COM port.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// TRUE, if connection was successful.
|
|
// FALSE, otherwise.
|
|
//
|
|
//--
|
|
|
|
{
|
|
//
|
|
// Abort if there is no 1394 hardware.
|
|
//
|
|
|
|
if (BlPciOhci1394BaseAddress == 0) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Initialize the underlying hardware.
|
|
//
|
|
|
|
if (BlKd1394InitHardware(0, (PVOID)(ULONG_PTR) BlPciOhci1394BaseAddress)) {
|
|
|
|
KD_DEBUG_IO Packet;
|
|
|
|
//
|
|
// Send a test packet to verify the debugger is attached.
|
|
//
|
|
|
|
BlRtlZeroMemory(&Packet, sizeof(Packet));
|
|
|
|
Packet.ApiNumber = KD_API_PRINT_STRING;
|
|
Packet.u1.PrintString.LengthOfString = 0;
|
|
|
|
if (BlKd1394SendPacket(KD_PACKET_TYPE_KD_DEBUG_IO, &Packet, sizeof(Packet), L"1394!\n", 7)) {
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
BlPciOhci1394BaseAddress = 0;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
#endif // !defined(BOOT_X64)
|