mirror of
https://github.com/reactos/reactos.git
synced 2025-06-26 20:09:44 +00:00
[KDCOM]
- Merge r43682 - Copy new kdcom from amd64 branch. It's only built when _WINKD_ is set to 1 in the config file. Happy testing. svn path=/trunk/; revision=43688
This commit is contained in:
parent
7a50eb63fc
commit
4d06b94a31
11 changed files with 1051 additions and 10 deletions
|
@ -7,9 +7,16 @@
|
|||
<directory name="bootvid">
|
||||
<xi:include href="bootvid/bootvid.rbuild" />
|
||||
</directory>
|
||||
<directory name="kdcom">
|
||||
<xi:include href="kdcom/kdcom.rbuild" />
|
||||
</directory>
|
||||
<ifnot property="_WINKD_" value="1">
|
||||
<directory name="kdcom">
|
||||
<xi:include href="kdcom/kdcom.rbuild" />
|
||||
</directory>
|
||||
</if>
|
||||
<if property="_WINKD_" value="1">
|
||||
<directory name="kddll">
|
||||
<xi:include href="kddll/kddll.rbuild" />
|
||||
</directory>
|
||||
</if>
|
||||
<directory name="null">
|
||||
<xi:include href="null/null.rbuild" />
|
||||
</directory>
|
||||
|
|
291
reactos/drivers/base/kddll/kdcom.c
Normal file
291
reactos/drivers/base/kddll/kdcom.c
Normal file
|
@ -0,0 +1,291 @@
|
|||
/*
|
||||
* COPYRIGHT: GPL, see COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: drivers/base/kddll/kdcom.c
|
||||
* PURPOSE: COM port functions for the kernel debugger.
|
||||
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@ewactos.org)
|
||||
*/
|
||||
|
||||
#include "kddll.h"
|
||||
#include "kdcom.h"
|
||||
|
||||
/* Define wait timeout value. */
|
||||
#define REPEAT_COUNT (1000 * 1000)
|
||||
|
||||
/* serial debug connection */
|
||||
#define DEFAULT_DEBUG_PORT 2 /* COM2 */
|
||||
#define DEFAULT_DEBUG_COM1_IRQ 4 /* COM1 IRQ */
|
||||
#define DEFAULT_DEBUG_COM2_IRQ 3 /* COM2 IRQ */
|
||||
#define DEFAULT_DEBUG_BAUD_RATE 115200 /* 115200 Baud */
|
||||
|
||||
#define DEFAULT_BAUD_RATE 19200
|
||||
|
||||
|
||||
#if defined(_M_IX86) || defined(_M_AMD64)
|
||||
const ULONG BaseArray[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};
|
||||
#elif defined(_M_PPC)
|
||||
const ULONG BaseArray[2] = {0, 0x800003f8};
|
||||
#elif defined(_M_MIPS)
|
||||
const ULONG BaseArray[3] = {0, 0x80006000, 0x80007000};
|
||||
#elif defined(_M_ARM)
|
||||
const ULONG BaseArray[2] = {0, 0xF1012000};
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
PUCHAR ComPortBase;
|
||||
ULONG ComPortNumber = DEFAULT_DEBUG_PORT;
|
||||
ULONG ComPortBaudRate = DEFAULT_DEBUG_BAUD_RATE;
|
||||
ULONG ComPortIrq = 0;
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdpPortInitialize()
|
||||
{
|
||||
ULONG Mode;
|
||||
|
||||
KDDBGPRINT("KdpPortInitialize\n");
|
||||
|
||||
/* Enable loop mode (set Bit 4 of the MCR) */
|
||||
WRITE_PORT_UCHAR(ComPortBase + COM_MCR, MCR_LOOP);
|
||||
|
||||
/* Clear all modem output bits */
|
||||
WRITE_PORT_UCHAR(ComPortBase + COM_MCR, MCR_LOOP);
|
||||
|
||||
/* The upper nibble of the MSR (modem output bits) must be
|
||||
* equal to the lower nibble of the MCR (modem input bits) */
|
||||
if ((READ_PORT_UCHAR(ComPortBase + COM_MSR) & 0xF0) != 0x00)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Set all modem output bits */
|
||||
WRITE_PORT_UCHAR(ComPortBase + COM_MCR, MCR_ALL);
|
||||
|
||||
/* The upper nibble of the MSR (modem output bits) must be
|
||||
* equal to the lower nibble of the MCR (modem input bits) */
|
||||
if ((READ_PORT_UCHAR(ComPortBase + COM_MSR) & 0xF0) != 0xF0)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Enable FIFO */
|
||||
WRITE_PORT_UCHAR(ComPortBase + COM_FCR,
|
||||
FCR_ENABLE_FIFO | FCR_CLEAR_RCVR | FCR_CLEAR_XMIT);
|
||||
|
||||
/* Disable interrupts */
|
||||
WRITE_PORT_UCHAR(ComPortBase + COM_LCR, 0);
|
||||
WRITE_PORT_UCHAR(ComPortBase + COM_IEN, 0);
|
||||
|
||||
/* Enable on DTR and RTS */
|
||||
WRITE_PORT_UCHAR(ComPortBase + COM_MCR, MCR_DTR | MCR_RTS);
|
||||
|
||||
/* Set DLAB */
|
||||
WRITE_PORT_UCHAR(ComPortBase + COM_LCR, LCR_DLAB);
|
||||
|
||||
/* Set baud rate */
|
||||
Mode = 115200 / ComPortBaudRate;
|
||||
WRITE_PORT_UCHAR(ComPortBase + COM_DLL, (UCHAR)(Mode & 0xff));
|
||||
WRITE_PORT_UCHAR(ComPortBase + COM_DLM, (UCHAR)((Mode >> 8) & 0xff));
|
||||
|
||||
/* Reset DLAB and set 8 data bits, 1 stop bit, no parity, no break */
|
||||
WRITE_PORT_UCHAR(ComPortBase + COM_LCR, LCR_CS8 | LCR_ST1 | LCR_PNO);
|
||||
|
||||
/* Check for 16450/16550 scratch register */
|
||||
WRITE_PORT_UCHAR(ComPortBase + COM_SCR, 0xff);
|
||||
if (READ_PORT_UCHAR(ComPortBase + COM_SCR) != 0xff)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
WRITE_PORT_UCHAR(ComPortBase + COM_SCR, 0x00);
|
||||
if (READ_PORT_UCHAR(ComPortBase + COM_SCR) != 0x00)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* \name KdDebuggerInitialize0
|
||||
* \brief Phase 0 initialization.
|
||||
* \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL.
|
||||
* \return Status
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdDebuggerInitialize0(
|
||||
IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
|
||||
{
|
||||
PCHAR CommandLine, PortString, BaudString, IrqString;
|
||||
ULONG Value;
|
||||
|
||||
/* Check if e have a LoaderBlock */
|
||||
if (LoaderBlock)
|
||||
{
|
||||
/* Get the Command Line */
|
||||
CommandLine = LoaderBlock->LoadOptions;
|
||||
|
||||
/* Upcase it */
|
||||
_strupr(CommandLine);
|
||||
|
||||
/* Get the port and baud rate */
|
||||
PortString = strstr(CommandLine, "DEBUGPORT");
|
||||
BaudString = strstr(CommandLine, "BAUDRATE");
|
||||
IrqString = strstr(CommandLine, "IRQ");
|
||||
|
||||
/* Check if we got the /DEBUGPORT parameter */
|
||||
if (PortString)
|
||||
{
|
||||
/* Move past the actual string, to reach the port*/
|
||||
PortString += strlen("DEBUGPORT");
|
||||
|
||||
/* Now get past any spaces and skip the equal sign */
|
||||
while (*PortString == ' ') PortString++;
|
||||
PortString++;
|
||||
|
||||
/* Do we have a serial port? */
|
||||
if (strncmp(PortString, "COM", 3) != 0)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Gheck for a valid Serial Port */
|
||||
PortString += 3;
|
||||
Value = atol(PortString);
|
||||
if (Value > 4)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Set the port to use */
|
||||
ComPortNumber = Value;
|
||||
}
|
||||
|
||||
/* Check if we got a baud rate */
|
||||
if (BaudString)
|
||||
{
|
||||
/* Move past the actual string, to reach the rate */
|
||||
BaudString += strlen("BAUDRATE");
|
||||
|
||||
/* Now get past any spaces */
|
||||
while (*BaudString == ' ') BaudString++;
|
||||
|
||||
/* And make sure we have a rate */
|
||||
if (*BaudString)
|
||||
{
|
||||
/* Read and set it */
|
||||
Value = atol(BaudString + 1);
|
||||
if (Value) ComPortBaudRate = Value;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check Serial Port Settings [IRQ] */
|
||||
if (IrqString)
|
||||
{
|
||||
/* Move past the actual string, to reach the rate */
|
||||
IrqString += strlen("IRQ");
|
||||
|
||||
/* Now get past any spaces */
|
||||
while (*IrqString == ' ') IrqString++;
|
||||
|
||||
/* And make sure we have an IRQ */
|
||||
if (*IrqString)
|
||||
{
|
||||
/* Read and set it */
|
||||
Value = atol(IrqString + 1);
|
||||
if (Value) ComPortIrq = Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get base address */
|
||||
ComPortBase = UlongToPtr(BaseArray[ComPortNumber]);
|
||||
|
||||
/* Initialize the port */
|
||||
return KdpPortInitialize();
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KdpSendByte(IN BYTE Byte)
|
||||
{
|
||||
/* Wait for the port to be ready */
|
||||
while ((READ_PORT_UCHAR(ComPortBase + COM_LSR) & LSR_TBE) == 0);
|
||||
|
||||
/* Send the byte */
|
||||
WRITE_PORT_UCHAR(ComPortBase + COM_DAT, Byte);
|
||||
}
|
||||
|
||||
KDP_STATUS
|
||||
NTAPI
|
||||
KdpPollByte(OUT PBYTE OutByte)
|
||||
{
|
||||
/* Check if data is available */
|
||||
if ((READ_PORT_UCHAR(ComPortBase + COM_LSR) & LSR_DR))
|
||||
{
|
||||
/* Yes, return the byte */
|
||||
*OutByte = READ_PORT_UCHAR(ComPortBase + COM_DAT);
|
||||
return KDP_PACKET_RECEIVED;
|
||||
}
|
||||
|
||||
/* Timed out */
|
||||
return KDP_PACKET_TIMEOUT;
|
||||
}
|
||||
|
||||
KDP_STATUS
|
||||
NTAPI
|
||||
KdpReceiveByte(OUT PBYTE OutByte)
|
||||
{
|
||||
ULONG Repeats = REPEAT_COUNT;
|
||||
|
||||
while (Repeats--)
|
||||
{
|
||||
/* Check if data is available */
|
||||
if (KdpPollByte(OutByte) == KDP_PACKET_RECEIVED)
|
||||
{
|
||||
/* We successfully got a byte */
|
||||
return KDP_PACKET_RECEIVED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Timed out */
|
||||
return KDP_PACKET_TIMEOUT;
|
||||
}
|
||||
|
||||
KDP_STATUS
|
||||
NTAPI
|
||||
KdpPollBreakIn()
|
||||
{
|
||||
UCHAR Byte;
|
||||
if (KdpPollByte(&Byte) == KDP_PACKET_RECEIVED)
|
||||
{
|
||||
if (Byte == BREAKIN_PACKET_BYTE)
|
||||
{
|
||||
return KDP_PACKET_RECEIVED;
|
||||
}
|
||||
}
|
||||
return KDP_PACKET_TIMEOUT;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdSave(
|
||||
IN BOOLEAN SleepTransition)
|
||||
{
|
||||
/* Nothing to do on COM ports */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdRestore(
|
||||
IN BOOLEAN SleepTransition)
|
||||
{
|
||||
/* Nothing to do on COM ports */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
57
reactos/drivers/base/kddll/kdcom.h
Normal file
57
reactos/drivers/base/kddll/kdcom.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* COPYRIGHT: GPL, see COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: drivers/base/kddll/kdcom.h
|
||||
* PURPOSE: COM port definitions for the kernel debugger.
|
||||
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@ewactos.org)
|
||||
*/
|
||||
|
||||
#ifndef _KDCOM_H_
|
||||
#define _KDCOM_H_
|
||||
|
||||
#define COM_DAT 0x00
|
||||
#define COM_IEN 0x01 /* interrupt enable register */
|
||||
#define COM_FCR 0x02 /* FIFO Control Register */
|
||||
#define COM_LCR 0x03 /* line control registers */
|
||||
#define COM_MCR 0x04 /* modem control reg */
|
||||
#define COM_LSR 0x05 /* line status register */
|
||||
#define COM_MSR 0x06 /* modem status register */
|
||||
#define COM_SCR 0x07 /* scratch register */
|
||||
#define COM_DLL 0x00 /* divisor latch least sig */
|
||||
#define COM_DLM 0x01 /* divisor latch most sig */
|
||||
|
||||
#define IEN_ERDA 0x01
|
||||
#define IEN_ETHRE 0x02
|
||||
#define IEN_ERLSI 0x04
|
||||
#define IEN_EMS 0x08
|
||||
#define IEN_ALL 0x0F
|
||||
#define FCR_ENABLE_FIFO 0x01
|
||||
#define FCR_CLEAR_RCVR 0x02
|
||||
#define FCR_CLEAR_XMIT 0x04
|
||||
#define LCR_CS5 0x00
|
||||
#define LCR_CS6 0x01
|
||||
#define LCR_CS7 0x02
|
||||
#define LCR_CS8 0x03
|
||||
#define LCR_ST1 0x00
|
||||
#define LCR_ST2 0x04
|
||||
#define LCR_PNO 0x00
|
||||
#define LCR_POD 0x08
|
||||
#define LCR_PEV 0x18
|
||||
#define LCR_PMK 0x28
|
||||
#define LCR_PSP 0x38
|
||||
#define LCR_BRK 0x40
|
||||
#define LCR_DLAB 0x80
|
||||
#define MCR_DTR 0x01
|
||||
#define MCR_RTS 0x02
|
||||
#define MCR_OUT1 0x04 /* general purpose output */
|
||||
#define MCR_OUT2 0x08
|
||||
#define MCR_LOOP 0x10 /* loopback testing mode */
|
||||
#define MCR_ALL (MCR_DTR | MCR_RTS | MCR_OUT1 | MCR_OUT2 | MCR_LOOP)
|
||||
#define LSR_DR 0x01
|
||||
#define LSR_TBE 0x20
|
||||
#define MSR_CTS 0x10 /* (complemented) state of clear to send (CTS). */
|
||||
#define MSR_DSR 0x20 /* (complemented) state of data set ready (DSR). */
|
||||
#define MSR_RI 0x40 /* (complemented) state of ring indicator (RI). */
|
||||
#define MSR_DCD 0x80 /* (complemented) state of data carrier detect (DCD). */
|
||||
|
||||
#endif /* !_KDCOM_H_ */
|
421
reactos/drivers/base/kddll/kddll.c
Normal file
421
reactos/drivers/base/kddll/kddll.c
Normal file
|
@ -0,0 +1,421 @@
|
|||
/*
|
||||
* COPYRIGHT: GPL, see COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: drivers/base/kddll/kddll.c
|
||||
* PURPOSE: Base functions for the kernel debugger.
|
||||
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@ewactos.org)
|
||||
*/
|
||||
|
||||
//#define KDDEBUG /* uncomment to enable debugging this dll */
|
||||
#include "kddll.h"
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
PFNDBGPRNT KdpDbgPrint = NULL;
|
||||
ULONG CurrentPacketId = INITIAL_PACKET_ID | SYNC_PACKET_ID;
|
||||
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
* \name KdpCalculateChecksum
|
||||
* \brief Calculates the checksum for the packet data.
|
||||
* \param Buffer Pointer to the packet data.
|
||||
* \param Length Length of data in bytes.
|
||||
* \return The calculated checksum.
|
||||
* \sa http://www.vista-xp.co.uk/forums/technical-reference-library/2540-basics-debugging.html
|
||||
*/
|
||||
ULONG
|
||||
NTAPI
|
||||
KdpCalculateChecksum(
|
||||
IN PVOID Buffer,
|
||||
IN ULONG Length)
|
||||
{
|
||||
ULONG i, Checksum = 0;
|
||||
|
||||
for (i = 0; i < Length; i++)
|
||||
{
|
||||
Checksum += ((PUCHAR)Buffer)[i];
|
||||
}
|
||||
|
||||
return Checksum;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KdpSendControlPacket(
|
||||
IN USHORT PacketType,
|
||||
IN ULONG PacketId OPTIONAL)
|
||||
{
|
||||
KD_PACKET Packet;
|
||||
|
||||
Packet.PacketLeader = CONTROL_PACKET_LEADER;
|
||||
Packet.PacketId = PacketId;
|
||||
Packet.ByteCount = 0;
|
||||
Packet.Checksum = 0;
|
||||
Packet.PacketType = PacketType;
|
||||
|
||||
KdpSendBuffer(&Packet, sizeof(KD_PACKET));
|
||||
}
|
||||
|
||||
|
||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdD0Transition(VOID)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdD3Transition(VOID)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* \name KdDebuggerInitialize1
|
||||
* \brief Phase 1 initialization.
|
||||
* \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL.
|
||||
* \return Status
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdDebuggerInitialize1(
|
||||
IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
|
||||
{
|
||||
// HACK: misuse this function to get a pointer to FrLdrDbgPrint
|
||||
KdpDbgPrint = (PVOID)LoaderBlock;
|
||||
KDDBGPRINT("KdDebuggerInitialize1\n");
|
||||
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* \name KdReceivePacket
|
||||
* \brief Receive a packet from the KD port.
|
||||
* \param [in] PacketType Describes the type of the packet to receive.
|
||||
* This can be one of the PACKET_TYPE_ constants.
|
||||
* \param [out] MessageHeader Pointer to a STRING structure for the header.
|
||||
* \param [out] MessageData Pointer to a STRING structure for the data.
|
||||
* \return KdPacketReceived if successful, KdPacketTimedOut if the receive
|
||||
* timed out, KdPacketNeedsResend to signal that the last packet needs
|
||||
* to be sent again.
|
||||
* \note If PacketType is PACKET_TYPE_KD_POLL_BREAKIN, the function doesn't
|
||||
* wait for any data, but returns KdPacketTimedOut instantly if no breakin
|
||||
* packet byte is received.
|
||||
* \sa http://www.nynaeve.net/?p=169
|
||||
*/
|
||||
KDP_STATUS
|
||||
NTAPI
|
||||
KdReceivePacket(
|
||||
IN ULONG PacketType,
|
||||
OUT PSTRING MessageHeader,
|
||||
OUT PSTRING MessageData,
|
||||
OUT PULONG DataLength,
|
||||
IN OUT PKD_CONTEXT KdContext)
|
||||
{
|
||||
UCHAR Byte = 0;
|
||||
KDP_STATUS KdStatus;
|
||||
KD_PACKET Packet;
|
||||
ULONG Checksum;
|
||||
|
||||
/* Special handling for breakin packet */
|
||||
if(PacketType == PACKET_TYPE_KD_POLL_BREAKIN)
|
||||
{
|
||||
return KdpPollBreakIn();
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* Step 1 - Read PacketLeader */
|
||||
KdStatus = KdpReceivePacketLeader(&Packet.PacketLeader);
|
||||
if (KdStatus != KDP_PACKET_RECEIVED)
|
||||
{
|
||||
/* Check if we got a breakin */
|
||||
if (KdStatus == KDP_PACKET_RESEND)
|
||||
{
|
||||
KdContext->BreakInRequested = TRUE;
|
||||
}
|
||||
return KdStatus;
|
||||
}
|
||||
|
||||
/* Step 2 - Read PacketType */
|
||||
KdStatus = KdpReceiveBuffer(&Packet.PacketType, sizeof(USHORT));
|
||||
if (KdStatus != KDP_PACKET_RECEIVED)
|
||||
{
|
||||
/* Didn't receive a PacketType or PacketType is bad. Start over. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Step 3 - Read ByteCount */
|
||||
KdStatus = KdpReceiveBuffer(&Packet.ByteCount, sizeof(USHORT));
|
||||
if (KdStatus != KDP_PACKET_RECEIVED || Packet.ByteCount > PACKET_MAX_SIZE)
|
||||
{
|
||||
/* Didn't receive ByteCount or it's too big. Start over. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Step 4 - Read PacketId */
|
||||
KdStatus = KdpReceiveBuffer(&Packet.PacketId, sizeof(ULONG));
|
||||
if (KdStatus != KDP_PACKET_RECEIVED)
|
||||
{
|
||||
/* Didn't receive PacketId. Start over. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
if (Packet.PacketId != ExpectedPacketId)
|
||||
{
|
||||
// Ask for a resend!
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
|
||||
/* Step 5 - Read Checksum */
|
||||
KdStatus = KdpReceiveBuffer(&Packet.Checksum, sizeof(ULONG));
|
||||
if (KdStatus != KDP_PACKET_RECEIVED)
|
||||
{
|
||||
/* Didn't receive Checksum. Start over. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Step 6 - Handle control packets */
|
||||
if (Packet.PacketLeader == CONTROL_PACKET_LEADER)
|
||||
{
|
||||
switch (Packet.PacketType)
|
||||
{
|
||||
case PACKET_TYPE_KD_ACKNOWLEDGE:
|
||||
/* Are we waiting for an ACK packet? */
|
||||
if (PacketType == PACKET_TYPE_KD_ACKNOWLEDGE &&
|
||||
Packet.PacketId == (CurrentPacketId & ~SYNC_PACKET_ID))
|
||||
{
|
||||
/* Remote acknowledges the last packet */
|
||||
CurrentPacketId ^= 1;
|
||||
return KDP_PACKET_RECEIVED;
|
||||
}
|
||||
/* That's not what we were waiting for, start over. */
|
||||
continue;
|
||||
|
||||
case PACKET_TYPE_KD_RESET:
|
||||
KDDBGPRINT("KdReceivePacket - got a reset packet\n");
|
||||
KdpSendControlPacket(PACKET_TYPE_KD_RESET, 0);
|
||||
CurrentPacketId = INITIAL_PACKET_ID;
|
||||
/* Fall through */
|
||||
|
||||
case PACKET_TYPE_KD_RESEND:
|
||||
KDDBGPRINT("KdReceivePacket - got PACKET_TYPE_KD_RESEND\n");
|
||||
/* Remote wants us to resend the last packet */
|
||||
return KDP_PACKET_RESEND;
|
||||
|
||||
default:
|
||||
KDDBGPRINT("KdReceivePacket - got unknown control packet\n");
|
||||
return KDP_PACKET_RESEND;
|
||||
}
|
||||
}
|
||||
|
||||
/* Did we wait for an ack packet? */
|
||||
if (PacketType == PACKET_TYPE_KD_ACKNOWLEDGE)
|
||||
{
|
||||
/* We received something different */
|
||||
KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0);
|
||||
CurrentPacketId ^= 1;
|
||||
return KDP_PACKET_RECEIVED;
|
||||
}
|
||||
|
||||
/* Did we get the right packet type? */
|
||||
if (PacketType != Packet.PacketType)
|
||||
{
|
||||
/* We received something different, start over */
|
||||
KDDBGPRINT("KdReceivePacket - wrong PacketType\n");
|
||||
KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Get size of the message header */
|
||||
switch (Packet.PacketType)
|
||||
{
|
||||
case PACKET_TYPE_KD_STATE_CHANGE64:
|
||||
MessageHeader->Length = sizeof(DBGKD_WAIT_STATE_CHANGE64);
|
||||
break;
|
||||
|
||||
case PACKET_TYPE_KD_STATE_MANIPULATE:
|
||||
MessageHeader->Length = sizeof(DBGKD_MANIPULATE_STATE64);
|
||||
break;
|
||||
|
||||
case PACKET_TYPE_KD_DEBUG_IO:
|
||||
MessageHeader->Length = sizeof(DBGKD_DEBUG_IO);
|
||||
break;
|
||||
|
||||
default:
|
||||
KDDBGPRINT("KdReceivePacket - unknown PacketType\n");
|
||||
return KDP_PACKET_RESEND;
|
||||
}
|
||||
|
||||
//KDDBGPRINT("KdReceivePacket - got normal PacketType\n");
|
||||
|
||||
/* Packet smaller than expected? */
|
||||
if (MessageHeader->Length > Packet.ByteCount)
|
||||
{
|
||||
KDDBGPRINT("KdReceivePacket - too few data (%d) for type %d\n",
|
||||
Packet.ByteCount, MessageHeader->Length);
|
||||
MessageHeader->Length = Packet.ByteCount;
|
||||
}
|
||||
|
||||
//KDDBGPRINT("KdReceivePacket - got normal PacketType, Buffer = %p\n", MessageHeader->Buffer);
|
||||
|
||||
/* Receive the message header data */
|
||||
KdStatus = KdpReceiveBuffer(MessageHeader->Buffer,
|
||||
MessageHeader->Length);
|
||||
if (KdStatus != KDP_PACKET_RECEIVED)
|
||||
{
|
||||
/* Didn't receive data. Packet needs to be resent. */
|
||||
KDDBGPRINT("KdReceivePacket - Didn't receive message header data.\n");
|
||||
KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
//KDDBGPRINT("KdReceivePacket - got normal PacketType 3\n");
|
||||
|
||||
/* Calculate checksum for the header data */
|
||||
Checksum = KdpCalculateChecksum(MessageHeader->Buffer,
|
||||
MessageHeader->Length);
|
||||
|
||||
/* Calculate the length of the message data */
|
||||
*DataLength = Packet.ByteCount - MessageHeader->Length;
|
||||
|
||||
/* Shall we receive messsage data? */
|
||||
if (MessageData)
|
||||
{
|
||||
/* Set the length of the message data */
|
||||
MessageData->Length = *DataLength;
|
||||
|
||||
/* Do we have data? */
|
||||
if (MessageData->Length)
|
||||
{
|
||||
KDDBGPRINT("KdReceivePacket - got data\n");
|
||||
|
||||
/* Receive the message data */
|
||||
KdStatus = KdpReceiveBuffer(MessageData->Buffer,
|
||||
MessageData->Length);
|
||||
if (KdStatus != KDP_PACKET_RECEIVED)
|
||||
{
|
||||
/* Didn't receive data. Start over. */
|
||||
KDDBGPRINT("KdReceivePacket - Didn't receive message data.\n");
|
||||
KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Add cheksum for message data */
|
||||
Checksum += KdpCalculateChecksum(MessageData->Buffer,
|
||||
MessageData->Length);
|
||||
}
|
||||
}
|
||||
|
||||
/* Compare checksum */
|
||||
if (Packet.Checksum != Checksum)
|
||||
{
|
||||
KDDBGPRINT("KdReceivePacket - wrong cheksum, got %x, calculated %x\n",
|
||||
Packet.Checksum, Checksum);
|
||||
KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We must receive a PACKET_TRAILING_BYTE now */
|
||||
KdStatus = KdpReceiveBuffer(&Byte, sizeof(UCHAR));
|
||||
if (KdStatus != KDP_PACKET_RECEIVED || Byte != PACKET_TRAILING_BYTE)
|
||||
{
|
||||
KDDBGPRINT("KdReceivePacket - wrong trailing byte (0x%x), status 0x%x\n", Byte, KdStatus);
|
||||
KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Acknowledge the received packet */
|
||||
KdpSendControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE, Packet.PacketId);
|
||||
|
||||
//KDDBGPRINT("KdReceivePacket - all ok\n");
|
||||
|
||||
return KDP_PACKET_RECEIVED;
|
||||
}
|
||||
|
||||
return KDP_PACKET_RECEIVED;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KdSendPacket(
|
||||
IN ULONG PacketType,
|
||||
IN PSTRING MessageHeader,
|
||||
IN PSTRING MessageData,
|
||||
IN OUT PKD_CONTEXT Context)
|
||||
{
|
||||
KD_PACKET Packet;
|
||||
KDP_STATUS KdStatus;
|
||||
|
||||
/* Initialize a KD_PACKET */
|
||||
Packet.PacketLeader = PACKET_LEADER;
|
||||
Packet.PacketType = PacketType;
|
||||
Packet.ByteCount = MessageHeader->Length;
|
||||
Packet.Checksum = KdpCalculateChecksum(MessageHeader->Buffer,
|
||||
MessageHeader->Length);
|
||||
|
||||
/* If we have message data, add it to the packet */
|
||||
if (MessageData)
|
||||
{
|
||||
Packet.ByteCount += MessageData->Length;
|
||||
Packet.Checksum += KdpCalculateChecksum(MessageData->Buffer,
|
||||
MessageData->Length);
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* Set the packet id */
|
||||
Packet.PacketId = CurrentPacketId;
|
||||
|
||||
/* Send the packet header to the KD port */
|
||||
KdpSendBuffer(&Packet, sizeof(KD_PACKET));
|
||||
|
||||
/* Send the message header */
|
||||
KdpSendBuffer(MessageHeader->Buffer, MessageHeader->Length);
|
||||
|
||||
/* If we have meesage data, also send it */
|
||||
if (MessageData)
|
||||
{
|
||||
KdpSendBuffer(MessageData->Buffer, MessageData->Length);
|
||||
}
|
||||
|
||||
/* Finalize with a trailing byte */
|
||||
KdpSendByte(PACKET_TRAILING_BYTE);
|
||||
|
||||
/* Wait for acknowledge */
|
||||
KdStatus = KdReceivePacket(PACKET_TYPE_KD_ACKNOWLEDGE,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
/* Did we succeed? */
|
||||
if (KdStatus == KDP_PACKET_RECEIVED)
|
||||
{
|
||||
CurrentPacketId &= ~SYNC_PACKET_ID;
|
||||
break;
|
||||
}
|
||||
|
||||
/* PACKET_TYPE_KD_DEBUG_IO is allowed to instantly timeout */
|
||||
if (PacketType == PACKET_TYPE_KD_DEBUG_IO)
|
||||
{
|
||||
/* No response, silently fail. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Packet timed out, send it again */
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
85
reactos/drivers/base/kddll/kddll.h
Normal file
85
reactos/drivers/base/kddll/kddll.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* COPYRIGHT: GPL, see COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: drivers/base/kddll/kddll.h
|
||||
* PURPOSE: Base definitions for the kernel debugger.
|
||||
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@ewactos.org)
|
||||
*/
|
||||
|
||||
#ifndef _KDDLL_H_
|
||||
#define _KDDLL_H_
|
||||
|
||||
#define NOEXTAPI
|
||||
#include <ntddk.h>
|
||||
#define NDEBUG
|
||||
#include <halfuncs.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <debug.h>
|
||||
#include "arc/arc.h"
|
||||
#include "windbgkd.h"
|
||||
|
||||
#include <wdbgexts.h>
|
||||
#include <ioaccess.h> /* port intrinsics */
|
||||
|
||||
typedef UCHAR BYTE, *PBYTE;
|
||||
|
||||
typedef ULONG (*PFNDBGPRNT)(const char *Format, ...);
|
||||
extern PFNDBGPRNT KdpDbgPrint;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KDP_PACKET_RECEIVED = 0,
|
||||
KDP_PACKET_TIMEOUT = 1,
|
||||
KDP_PACKET_RESEND = 2
|
||||
} KDP_STATUS;
|
||||
|
||||
#ifndef KDDEBUG
|
||||
#define KDDBGPRINT(...)
|
||||
#else
|
||||
#define KDDBGPRINT KdpDbgPrint
|
||||
#endif
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KdpSendBuffer(
|
||||
IN PVOID Buffer,
|
||||
IN ULONG Size);
|
||||
|
||||
KDP_STATUS
|
||||
NTAPI
|
||||
KdpReceiveBuffer(
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG Size);
|
||||
|
||||
KDP_STATUS
|
||||
NTAPI
|
||||
KdpReceivePacketLeader(
|
||||
OUT PULONG PacketLeader);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KdpSendByte(IN BYTE Byte);
|
||||
|
||||
KDP_STATUS
|
||||
NTAPI
|
||||
KdpPollByte(OUT PBYTE OutByte);
|
||||
|
||||
KDP_STATUS
|
||||
NTAPI
|
||||
KdpReceiveByte(OUT PBYTE OutByte);
|
||||
|
||||
KDP_STATUS
|
||||
NTAPI
|
||||
KdpPollBreakIn();
|
||||
|
||||
|
||||
#if 0
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdDebuggerInitialize0(
|
||||
IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL);
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* !_KDDLL_H_ */
|
23
reactos/drivers/base/kddll/kddll.rbuild
Normal file
23
reactos/drivers/base/kddll/kddll.rbuild
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
|
||||
<module name="kdlib" type="staticlibrary">
|
||||
<include base="kdlib">.</include>
|
||||
<library>ntoskrnl</library>
|
||||
<library>hal</library>
|
||||
<file>kddll.c</file>
|
||||
</module>
|
||||
|
||||
<module name="kdserial" type="staticlibrary">
|
||||
<include base="kdserial">.</include>
|
||||
<file>kdserial.c</file>
|
||||
</module>
|
||||
|
||||
<module name="kdcom" type="kernelmodedll" entrypoint="0" installbase="system32" installname="kdcom.dll">
|
||||
<importlibrary definition="kddll.spec"></importlibrary>
|
||||
<bootstrap installbase="$(CDOUTPUT)" nameoncd="kdcom.dll" />
|
||||
<include base="kdcom">.</include>
|
||||
<library>kdlib</library>
|
||||
<library>kdserial</library>
|
||||
<file>kdcom.c</file>
|
||||
</module>
|
8
reactos/drivers/base/kddll/kddll.spec
Normal file
8
reactos/drivers/base/kddll/kddll.spec
Normal file
|
@ -0,0 +1,8 @@
|
|||
@ stdcall KdD0Transition()
|
||||
@ stdcall KdD3Transition()
|
||||
@ stdcall KdDebuggerInitialize0(ptr)
|
||||
@ stdcall KdDebuggerInitialize1(ptr)
|
||||
@ stdcall KdReceivePacket(long ptr ptr ptr ptr)
|
||||
@ stdcall KdRestore(long)
|
||||
@ stdcall KdSave(long)
|
||||
@ stdcall KdSendPacket(long ptr ptr ptr)
|
149
reactos/drivers/base/kddll/kdserial.c
Normal file
149
reactos/drivers/base/kddll/kdserial.c
Normal file
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* COPYRIGHT: GPL, see COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: drivers/base/kddll/kdserial.c
|
||||
* PURPOSE: Serial communication functions for the kernel debugger.
|
||||
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@ewactos.org)
|
||||
*/
|
||||
|
||||
#include "kddll.h"
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* \name KdpSendBuffer
|
||||
* \brief Sends a buffer of data to the serial KD port.
|
||||
* \param Buffer Pointer to the data.
|
||||
* \param Size Size of data in bytes.
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
KdpSendBuffer(
|
||||
IN PVOID Buffer,
|
||||
IN ULONG Size)
|
||||
{
|
||||
INT i;
|
||||
for (i = 0; i < Size; i++)
|
||||
{
|
||||
KdpSendByte(((PUCHAR)Buffer)[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* \name KdpReceiveBuffer
|
||||
* \brief Recieves data from the KD port and fills a buffer.
|
||||
* \param Buffer Pointer to a buffer that receives the data.
|
||||
* \param Size Size of data to receive in bytes.
|
||||
* \return KDP_PACKET_RECEIVED if successful.
|
||||
* KDP_PACKET_TIMEOUT if the receice timed out.
|
||||
*/
|
||||
KDP_STATUS
|
||||
NTAPI
|
||||
KdpReceiveBuffer(
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG Size)
|
||||
{
|
||||
ULONG i;
|
||||
PUCHAR ByteBuffer = Buffer;
|
||||
KDP_STATUS Status;
|
||||
|
||||
for (i = 0; i < Size; i++)
|
||||
{
|
||||
/* Try to get a byte from the port */
|
||||
Status = KdpReceiveByte(&ByteBuffer[i]);
|
||||
|
||||
if (Status != KDP_PACKET_RECEIVED)
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
return KDP_PACKET_RECEIVED;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* \name KdpReceivePacketLeader
|
||||
* \brief Recieves a packet leadr from the KD port.
|
||||
* \param PacketLeader Pointer to an ULONG that receives the packet leader.
|
||||
* \return KDP_PACKET_RECEIVED if successful.
|
||||
* KDP_PACKET_TIMEOUT if the receive timed out.
|
||||
* KDP_PACKET_RESEND if a breakin byte was detected.
|
||||
*/
|
||||
KDP_STATUS
|
||||
NTAPI
|
||||
KdpReceivePacketLeader(
|
||||
OUT PULONG PacketLeader)
|
||||
{
|
||||
UCHAR Index = 0, Byte, Buffer[4];
|
||||
KDP_STATUS KdStatus;
|
||||
|
||||
/* Set first character to 0 */
|
||||
Buffer[0] = 0;
|
||||
|
||||
do
|
||||
{
|
||||
/* Receive a single byte */
|
||||
KdStatus = KdpReceiveByte(&Byte);
|
||||
|
||||
/* Check for timeout */
|
||||
if (KdStatus == KDP_PACKET_TIMEOUT)
|
||||
{
|
||||
/* Check if we already got a breakin byte */
|
||||
if (Buffer[0] == BREAKIN_PACKET_BYTE)
|
||||
{
|
||||
return KDP_PACKET_RESEND;
|
||||
}
|
||||
|
||||
/* Report timeout */
|
||||
return KDP_PACKET_TIMEOUT;
|
||||
}
|
||||
|
||||
/* Check if we received a byte */
|
||||
if (KdStatus == KDP_PACKET_RECEIVED)
|
||||
{
|
||||
/* Check if this is a valid packet leader byte */
|
||||
if (Byte == PACKET_LEADER_BYTE ||
|
||||
Byte == CONTROL_PACKET_LEADER_BYTE)
|
||||
{
|
||||
/* Check if we match the first byte */
|
||||
if (Byte != Buffer[0])
|
||||
{
|
||||
/* No, this is the new byte 0! */
|
||||
Index = 0;
|
||||
}
|
||||
|
||||
/* Store the byte in the buffer */
|
||||
Buffer[Index] = Byte;
|
||||
|
||||
/* Continue with next byte */
|
||||
Index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check for breakin byte */
|
||||
if (Byte == BREAKIN_PACKET_BYTE)
|
||||
{
|
||||
KdpDbgPrint("BREAKIN_PACKET_BYTE\n");
|
||||
Index = 0;
|
||||
Buffer[0] = Byte;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Restart */
|
||||
Index = 0;
|
||||
Buffer[0] = 0;
|
||||
}
|
||||
while (Index < 4);
|
||||
|
||||
/* Enable the debugger */
|
||||
// KdDebuggerNotPresent = FALSE;
|
||||
SharedUserData->KdDebuggerEnabled |= 0x00000002;
|
||||
|
||||
/* Return the received packet leader */
|
||||
*PacketLeader = *(PULONG)Buffer;
|
||||
|
||||
return KDP_PACKET_RECEIVED;
|
||||
}
|
||||
|
|
@ -211,8 +211,8 @@ typedef struct _KD_PACKET
|
|||
//
|
||||
typedef struct _KD_CONTEXT
|
||||
{
|
||||
ULONG KdpDefaultRetries;
|
||||
BOOLEAN KdpControlCPending;
|
||||
ULONG RetryCount;
|
||||
BOOLEAN BreakInRequested;
|
||||
} KD_CONTEXT, *PKD_CONTEXT;
|
||||
|
||||
//
|
||||
|
|
|
@ -284,7 +284,7 @@ KdInitSystem(IN ULONG BootPhase,
|
|||
if (!KdpDebuggerStructuresInitialized)
|
||||
{
|
||||
/* Set the Debug Switch Routine and Retries*/
|
||||
KdpContext.KdpDefaultRetries = 20;
|
||||
KdpContext.RetryCount = 20;
|
||||
KiDebugSwitchRoutine = KdpSwitchProcessor;
|
||||
|
||||
/* Initialize the Time Slip DPC */
|
||||
|
|
|
@ -40,11 +40,11 @@ KdpPollBreakInWithPortLock(VOID)
|
|||
if (KdDebuggerEnabled)
|
||||
{
|
||||
/* Check if a CTRL-C is in the queue */
|
||||
if (KdpContext.KdpControlCPending)
|
||||
if (KdpContext.BreakInRequested)
|
||||
{
|
||||
/* Set it and prepare for break */
|
||||
DoBreak = TRUE;
|
||||
KdpContext.KdpControlCPending = FALSE;
|
||||
KdpContext.BreakInRequested = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -83,12 +83,12 @@ KdPollBreakIn(VOID)
|
|||
Enable = KeDisableInterrupts();
|
||||
|
||||
/* Check if a CTRL-C is in the queue */
|
||||
if (KdpContext.KdpControlCPending)
|
||||
if (KdpContext.BreakInRequested)
|
||||
{
|
||||
/* Set it and prepare for break */
|
||||
KdpControlCPressed = TRUE;
|
||||
DoBreak = TRUE;
|
||||
KdpContext.KdpControlCPending = FALSE;
|
||||
KdpContext.BreakInRequested = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue