[KDCOM]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Thu, 22 Oct 2009 14:58:33 +0000 (14:58 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Thu, 22 Oct 2009 14:58:33 +0000 (14:58 +0000)
- 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

reactos/drivers/base/directory.rbuild
reactos/drivers/base/kddll/kdcom.c [new file with mode: 0644]
reactos/drivers/base/kddll/kdcom.h [new file with mode: 0644]
reactos/drivers/base/kddll/kddll.c [new file with mode: 0644]
reactos/drivers/base/kddll/kddll.h [new file with mode: 0644]
reactos/drivers/base/kddll/kddll.rbuild [new file with mode: 0644]
reactos/drivers/base/kddll/kddll.spec [new file with mode: 0644]
reactos/drivers/base/kddll/kdserial.c [new file with mode: 0644]
reactos/include/reactos/windbgkd.h
reactos/ntoskrnl/kd64/kdinit.c
reactos/ntoskrnl/kd64/kdlock.c

index 72ad22d..659f8e6 100644 (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>
diff --git a/reactos/drivers/base/kddll/kdcom.c b/reactos/drivers/base/kddll/kdcom.c
new file mode 100644 (file)
index 0000000..409b88e
--- /dev/null
@@ -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;
+}
+
diff --git a/reactos/drivers/base/kddll/kdcom.h b/reactos/drivers/base/kddll/kdcom.h
new file mode 100644 (file)
index 0000000..b7cc9af
--- /dev/null
@@ -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_ */
diff --git a/reactos/drivers/base/kddll/kddll.c b/reactos/drivers/base/kddll/kddll.c
new file mode 100644 (file)
index 0000000..4e4c1eb
--- /dev/null
@@ -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;
+}
+
diff --git a/reactos/drivers/base/kddll/kddll.h b/reactos/drivers/base/kddll/kddll.h
new file mode 100644 (file)
index 0000000..81a20c5
--- /dev/null
@@ -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_ */
diff --git a/reactos/drivers/base/kddll/kddll.rbuild b/reactos/drivers/base/kddll/kddll.rbuild
new file mode 100644 (file)
index 0000000..4e243be
--- /dev/null
@@ -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>
diff --git a/reactos/drivers/base/kddll/kddll.spec b/reactos/drivers/base/kddll/kddll.spec
new file mode 100644 (file)
index 0000000..4098dd6
--- /dev/null
@@ -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)
diff --git a/reactos/drivers/base/kddll/kdserial.c b/reactos/drivers/base/kddll/kdserial.c
new file mode 100644 (file)
index 0000000..6964ab9
--- /dev/null
@@ -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;
+}
+
index bc88bf5..38c6ae8 100644 (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;
 
 //
index e5c487c..1b1ac48 100644 (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 */
index f332eb1..0afbbf6 100644 (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
         {