- 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:
Timo Kreuzer 2009-10-22 14:58:33 +00:00
parent 7a50eb63fc
commit 4d06b94a31
11 changed files with 1051 additions and 10 deletions

View file

@ -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>

View 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;
}

View 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_ */

View 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;
}

View 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_ */

View 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>

View 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)

View 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;
}

View file

@ -211,8 +211,8 @@ typedef struct _KD_PACKET
//
typedef struct _KD_CONTEXT
{
ULONG KdpDefaultRetries;
BOOLEAN KdpControlCPending;
ULONG RetryCount;
BOOLEAN BreakInRequested;
} KD_CONTEXT, *PKD_CONTEXT;
//

View file

@ -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 */

View file

@ -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
{