2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/base/kdcom/kdbg.c
5 * PURPOSE: Serial i/o functions for the kernel debugger.
6 * PROGRAMMER: Alex Ionescu
11 /* INCLUDES *****************************************************************/
24 #include <ioaccess.h> /* port intrinsics */
26 typedef struct _KD_PORT_INFORMATION
30 ULONG_PTR BaseAddress
;
31 } KD_PORT_INFORMATION
, *PKD_PORT_INFORMATION
;
36 IN PKD_PORT_INFORMATION PortInformation
,
43 IN PKD_PORT_INFORMATION PortInformation
,
44 OUT PUCHAR ByteReceived
);
49 IN PKD_PORT_INFORMATION PortInformation
,
50 OUT PUCHAR ByteReceived
);
55 IN PKD_PORT_INFORMATION PortInformation
,
58 /* serial debug connection */
59 #define DEFAULT_DEBUG_PORT 2 /* COM2 */
60 #define DEFAULT_DEBUG_COM1_IRQ 4 /* COM1 IRQ */
61 #define DEFAULT_DEBUG_COM2_IRQ 3 /* COM2 IRQ */
62 #define DEFAULT_DEBUG_BAUD_RATE 115200 /* 115200 Baud */
64 #define DEFAULT_BAUD_RATE 19200
67 const ULONG BaseArray
[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};
69 const ULONG BaseArray
[2] = {0, 0x800003f8};
70 #elif defined(_M_MIPS)
71 const ULONG BaseArray
[3] = {0, 0x80006000, 0x80007000};
73 const ULONG BaseArray
[2] = {0, 0xF1012000};
74 #elif defined(_M_AMD64)
75 const ULONG BaseArray
[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};
77 #error Unknown architecture
80 /* MACROS *******************************************************************/
82 #define SER_RBR(x) ((PUCHAR)(x)+0)
83 #define SER_THR(x) ((PUCHAR)(x)+0)
84 #define SER_DLL(x) ((PUCHAR)(x)+0)
85 #define SER_IER(x) ((PUCHAR)(x)+1)
86 #define SR_IER_ERDA 0x01
87 #define SR_IER_ETHRE 0x02
88 #define SR_IER_ERLSI 0x04
89 #define SR_IER_EMS 0x08
90 #define SR_IER_ALL 0x0F
91 #define SER_DLM(x) ((PUCHAR)(x)+1)
92 #define SER_IIR(x) ((PUCHAR)(x)+2)
93 #define SER_FCR(x) ((PUCHAR)(x)+2)
94 #define SR_FCR_ENABLE_FIFO 0x01
95 #define SR_FCR_CLEAR_RCVR 0x02
96 #define SR_FCR_CLEAR_XMIT 0x04
97 #define SER_LCR(x) ((PUCHAR)(x)+3)
98 #define SR_LCR_CS5 0x00
99 #define SR_LCR_CS6 0x01
100 #define SR_LCR_CS7 0x02
101 #define SR_LCR_CS8 0x03
102 #define SR_LCR_ST1 0x00
103 #define SR_LCR_ST2 0x04
104 #define SR_LCR_PNO 0x00
105 #define SR_LCR_POD 0x08
106 #define SR_LCR_PEV 0x18
107 #define SR_LCR_PMK 0x28
108 #define SR_LCR_PSP 0x38
109 #define SR_LCR_BRK 0x40
110 #define SR_LCR_DLAB 0x80
111 #define SER_MCR(x) ((PUCHAR)(x)+4)
112 #define SR_MCR_DTR 0x01
113 #define SR_MCR_RTS 0x02
114 #define SR_MCR_OUT1 0x04
115 #define SR_MCR_OUT2 0x08
116 #define SR_MCR_LOOP 0x10
117 #define SER_LSR(x) ((PUCHAR)(x)+5)
118 #define SR_LSR_DR 0x01
119 #define SR_LSR_TBE 0x20
120 #define SER_MSR(x) ((PUCHAR)(x)+6)
121 #define SR_MSR_CTS 0x10
122 #define SR_MSR_DSR 0x20
123 #define SER_SCR(x) ((PUCHAR)(x)+7)
126 /* GLOBAL VARIABLES *********************************************************/
128 ULONG CurrentPacketId
= INITIAL_PACKET_ID
;
130 /* STATIC VARIABLES *********************************************************/
132 static KD_PORT_INFORMATION DefaultPort
= { 0, 0, 0 };
134 /* The com port must only be initialized once! */
135 static BOOLEAN PortInitialized
= FALSE
;
141 typedef ULONG (*DBGRNT
)(const char *Format
, ...);
142 DBGRNT FrLdrDbgPrint
= 0;
144 /* STATIC FUNCTIONS *********************************************************/
148 IN ULONG_PTR BaseAddress
)
156 /* save Modem Control Register (MCR) */
157 mcr
= READ_PORT_UCHAR(SER_MCR(BaseAddress
));
159 /* enable loop mode (set Bit 4 of the MCR) */
160 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), SR_MCR_LOOP
);
162 /* clear all modem output bits */
163 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), SR_MCR_LOOP
);
165 /* read the Modem Status Register */
166 msr
= READ_PORT_UCHAR(SER_MSR(BaseAddress
));
169 * the upper nibble of the MSR (modem output bits) must be
170 * equal to the lower nibble of the MCR (modem input bits)
172 if ((msr
& 0xF0) == 0x00)
174 /* set all modem output bits */
175 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), SR_MCR_DTR
| SR_MCR_RTS
| SR_MCR_OUT1
| SR_MCR_OUT2
| SR_MCR_LOOP
);
177 /* read the Modem Status Register */
178 msr
= READ_PORT_UCHAR(SER_MSR(BaseAddress
));
181 * the upper nibble of the MSR (modem output bits) must be
182 * equal to the lower nibble of the MCR (modem input bits)
184 if ((msr
& 0xF0) == 0xF0)
187 * setup a resonable state for the port:
188 * enable fifo and clear recieve/transmit buffers
190 WRITE_PORT_UCHAR(SER_FCR(BaseAddress
),
191 (SR_FCR_ENABLE_FIFO
| SR_FCR_CLEAR_RCVR
| SR_FCR_CLEAR_XMIT
));
192 WRITE_PORT_UCHAR(SER_FCR(BaseAddress
), 0);
193 READ_PORT_UCHAR(SER_RBR(BaseAddress
));
194 WRITE_PORT_UCHAR(SER_IER(BaseAddress
), 0);
200 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), mcr
);
206 /* FUNCTIONS ****************************************************************/
210 IN PDRIVER_OBJECT DriverObject
,
211 IN PUNICODE_STRING RegistryPath
)
213 return STATUS_SUCCESS
;
216 /* HAL.KdPortInitialize */
220 IN PKD_PORT_INFORMATION PortInformation
,
227 if (!PortInitialized
)
229 DefaultPort
.BaudRate
= PortInformation
->BaudRate
;
231 if (PortInformation
->ComPort
== 0)
233 for (i
= sizeof(BaseArray
) / sizeof(BaseArray
[0]) - 1; i
> 0; i
--)
235 if (KdpDoesComPortExist(BaseArray
[i
]))
237 DefaultPort
.BaseAddress
= BaseArray
[i
];
238 DefaultPort
.ComPort
= i
;
239 PortInformation
->BaseAddress
= DefaultPort
.BaseAddress
;
240 PortInformation
->ComPort
= DefaultPort
.ComPort
;
247 "\nKernel Debugger: No COM port found!\n\n");
248 HalDisplayString(buffer
);
253 PortInitialized
= TRUE
;
256 /* initialize port */
257 if (!KdPortInitializeEx(&DefaultPort
, Unknown1
, Unknown2
))
260 /* set global info */
261 KdComPortInUse
= (PUCHAR
)DefaultPort
.BaseAddress
;
267 /* HAL.KdPortInitializeEx */
271 IN PKD_PORT_INFORMATION PortInformation
,
275 ULONG_PTR ComPortBase
;
285 if (PortInformation
->BaudRate
== 0)
286 PortInformation
->BaudRate
= DEFAULT_BAUD_RATE
;
288 if (PortInformation
->ComPort
== 0)
291 if (!KdpDoesComPortExist(BaseArray
[PortInformation
->ComPort
]))
294 "\nKernel Debugger: Serial port not found!\n\n");
295 HalDisplayString(buffer
);
299 ComPortBase
= BaseArray
[PortInformation
->ComPort
];
300 PortInformation
->BaseAddress
= ComPortBase
;
303 "\nSerial port COM%ld found at 0x%lx\n",
304 PortInformation
->ComPort
,
306 HalDisplayString(buffer
);
309 /* set baud rate and data format (8N1) */
311 /* turn on DTR and RTS */
312 WRITE_PORT_UCHAR(SER_MCR(ComPortBase
), SR_MCR_DTR
| SR_MCR_RTS
);
315 lcr
= READ_PORT_UCHAR(SER_LCR(ComPortBase
)) | SR_LCR_DLAB
;
316 WRITE_PORT_UCHAR(SER_LCR(ComPortBase
), lcr
);
319 divisor
= 115200 / PortInformation
->BaudRate
;
320 WRITE_PORT_UCHAR(SER_DLL(ComPortBase
), (UCHAR
)(divisor
& 0xff));
321 WRITE_PORT_UCHAR(SER_DLM(ComPortBase
), (UCHAR
)((divisor
>> 8) & 0xff));
323 /* reset DLAB and set 8N1 format */
324 WRITE_PORT_UCHAR(SER_LCR(ComPortBase
),
325 SR_LCR_CS8
| SR_LCR_ST1
| SR_LCR_PNO
);
327 /* read junk out of the RBR */
328 lcr
= READ_PORT_UCHAR(SER_RBR(ComPortBase
));
331 /* print message to blue screen */
333 "\nKernel Debugger: COM%ld (Port 0x%lx) BaudRate %ld\n\n",
334 PortInformation
->ComPort
,
336 PortInformation
->BaudRate
);
338 HalDisplayString(buffer
);
345 /* HAL.KdPortGetByte */
349 OUT PUCHAR ByteReceived
)
351 if (!PortInitialized
)
353 return KdPortGetByteEx(&DefaultPort
, ByteReceived
);
357 /* HAL.KdPortGetByteEx */
361 IN PKD_PORT_INFORMATION PortInformation
,
362 OUT PUCHAR ByteReceived
)
364 PUCHAR ComPortBase
= (PUCHAR
)PortInformation
->BaseAddress
;
366 if ((READ_PORT_UCHAR(SER_LSR(ComPortBase
)) & SR_LSR_DR
))
368 *ByteReceived
= READ_PORT_UCHAR(SER_RBR(ComPortBase
));
376 /* HAL.KdPortPollByte */
380 OUT PUCHAR ByteReceived
)
382 if (!PortInitialized
)
384 return KdPortPollByteEx(&DefaultPort
, ByteReceived
);
388 /* HAL.KdPortPollByteEx */
392 IN PKD_PORT_INFORMATION PortInformation
,
393 OUT PUCHAR ByteReceived
)
395 PUCHAR ComPortBase
= (PUCHAR
)PortInformation
->BaseAddress
;
397 while ((READ_PORT_UCHAR(SER_LSR(ComPortBase
)) & SR_LSR_DR
) == 0)
400 *ByteReceived
= READ_PORT_UCHAR(SER_RBR(ComPortBase
));
406 /* HAL.KdPortPutByte */
412 if (!PortInitialized
)
414 KdPortPutByteEx(&DefaultPort
, ByteToSend
);
417 /* HAL.KdPortPutByteEx */
421 IN PKD_PORT_INFORMATION PortInformation
,
424 PUCHAR ComPortBase
= (PUCHAR
)PortInformation
->BaseAddress
;
426 while ((READ_PORT_UCHAR(SER_LSR(ComPortBase
)) & SR_LSR_TBE
) == 0)
429 WRITE_PORT_UCHAR(SER_THR(ComPortBase
), ByteToSend
);
433 /* HAL.KdPortRestore */
451 /* HAL.KdPortDisableInterrupts */
454 KdPortDisableInterrupts(VOID
)
458 if (!PortInitialized
)
461 ch
= READ_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
));
462 ch
&= (~(SR_MCR_OUT1
| SR_MCR_OUT2
));
463 WRITE_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
), ch
);
465 ch
= READ_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
));
467 WRITE_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
), ch
);
473 /* HAL.KdPortEnableInterrupts */
476 KdPortEnableInterrupts(VOID
)
480 if (PortInitialized
== FALSE
)
483 ch
= READ_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
));
486 WRITE_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
), ch
);
488 ch
= READ_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
));
489 ch
&= (~SR_MCR_LOOP
);
490 ch
|= (SR_MCR_OUT1
| SR_MCR_OUT2
);
491 WRITE_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
), ch
);
496 /* NEW INTERNAL FUNCTIONS ****************************************************/
498 /******************************************************************************
499 * \name KdpCalculateChecksum
500 * \brief Calculates the checksum for the packet data.
501 * \param Buffer Pointer to the packet data.
502 * \param Length Length of data in bytes.
503 * \return The calculated checksum.
504 * \sa http://www.vista-xp.co.uk/forums/technical-reference-library/2540-basics-debugging.html
508 KdpCalculateChecksum(
512 ULONG i
, Checksum
= 0;
514 for (i
= 0; i
< Length
; i
++)
516 Checksum
+= ((PUCHAR
)Buffer
)[i
];
521 /******************************************************************************
522 * \name KdpSendBuffer
523 * \brief Sends a buffer of data to the KD port.
524 * \param Buffer Pointer to the data.
525 * \param Size Size of data in bytes.
534 for (i
= 0; i
< Size
; i
++)
536 KdPortPutByteEx(&DefaultPort
, ((PUCHAR
)Buffer
)[i
]);
541 /******************************************************************************
542 * \name KdpReceiveBuffer
543 * \brief Recieves data from the KD port and fills a buffer.
544 * \param Buffer Pointer to a buffer that receives the data.
545 * \param Size Size of data to receive in bytes.
546 * \return KdPacketReceived if successful.
547 * KdPacketTimedOut if the receice timed out (10 seconds).
548 * \todo Handle timeout.
557 PUCHAR ByteBuffer
= Buffer
;
558 BOOLEAN Ret
, TimeOut
;
560 for (i
= 0; i
< Size
; i
++)
564 Ret
= KdPortGetByteEx(&DefaultPort
, &ByteBuffer
[i
]);
565 TimeOut
= FALSE
; // FIXME timeout after 10 Sec
567 while (!Ret
|| TimeOut
);
571 return KdPacketTimedOut
;
573 // FrLdrDbgPrint("Received byte: %x\n", ByteBuffer[i]);
576 return KdPacketReceived
;
581 KdpReceivePacketLeader(
582 OUT PULONG PacketLeader
)
584 UCHAR Byte
, PrevByte
;
590 for (i
= 0; i
< 4; i
++)
592 RcvCode
= KdpReceiveBuffer(&Byte
, sizeof(UCHAR
));
593 Temp
= (Temp
<< 8) | Byte
;
594 if ( (RcvCode
!= KdPacketReceived
) ||
595 ((Byte
!= PACKET_LEADER_BYTE
) &&
596 (Byte
!= CONTROL_PACKET_LEADER_BYTE
)) ||
597 (PrevByte
!= 0 && Byte
!= PrevByte
) )
599 return KdPacketNeedsResend
;
604 *PacketLeader
= Temp
;
606 return KdPacketReceived
;
612 KdpSendControlPacket(
613 IN USHORT PacketType
,
614 IN ULONG PacketId OPTIONAL
)
618 Packet
.PacketLeader
= CONTROL_PACKET_LEADER
;
619 Packet
.PacketId
= PacketId
;
620 Packet
.ByteCount
= 0;
622 Packet
.PacketType
= PacketType
;
624 KdpSendBuffer(&Packet
, sizeof(KD_PACKET
));
628 /* NEW PUBLIC FUNCTIONS ******************************************************/
630 /******************************************************************************
631 * \name KdDebuggerInitialize0
632 * \brief Phase 0 initialization.
633 * \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL.
638 KdDebuggerInitialize0(
639 IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL
)
642 PCHAR CommandLine
, Port
, BaudRate
, Irq
;
644 /* Apply default values */
646 DefaultPort
.ComPort
= DEFAULT_DEBUG_PORT
;
647 DefaultPort
.BaudRate
= DEFAULT_DEBUG_BAUD_RATE
;
649 /* Check if e have a LoaderBlock */
652 /* Get the Command Line */
653 CommandLine
= LoaderBlock
->LoadOptions
;
656 _strupr(CommandLine
);
658 /* Get the port and baud rate */
659 Port
= strstr(CommandLine
, "DEBUGPORT");
660 BaudRate
= strstr(CommandLine
, "BAUDRATE");
661 Irq
= strstr(CommandLine
, "IRQ");
663 /* Check if we got the /DEBUGPORT parameter */
666 /* Move past the actual string, to reach the port*/
667 Port
+= strlen("DEBUGPORT");
669 /* Now get past any spaces and skip the equal sign */
670 while (*Port
== ' ') Port
++;
673 /* Do we have a serial port? */
674 if (strncmp(Port
, "COM", 3) != 0)
676 return STATUS_INVALID_PARAMETER
;
679 /* Gheck for a valid Serial Port */
684 return STATUS_INVALID_PARAMETER
;
687 /* Set the port to use */
688 DefaultPort
.ComPort
= Value
;
691 /* Check if we got a baud rate */
694 /* Move past the actual string, to reach the rate */
695 BaudRate
+= strlen("BAUDRATE");
697 /* Now get past any spaces */
698 while (*BaudRate
== ' ') BaudRate
++;
700 /* And make sure we have a rate */
703 /* Read and set it */
704 Value
= atol(BaudRate
+ 1);
705 if (Value
) DefaultPort
.BaudRate
= Value
;
709 /* Check Serial Port Settings [IRQ] */
712 /* Move past the actual string, to reach the rate */
713 Irq
+= strlen("IRQ");
715 /* Now get past any spaces */
716 while (*Irq
== ' ') Irq
++;
718 /* And make sure we have an IRQ */
721 /* Read and set it */
722 Value
= atol(Irq
+ 1);
723 if (Value
) KdpPortIrq
= Value
;
728 // HACK use com1 for FrLdrDbg, com2 for WinDbg
729 DefaultPort
.ComPort
= 2;
731 /* Get base address */
732 DefaultPort
.BaseAddress
= BaseArray
[DefaultPort
.ComPort
];
734 /* Check if the COM port does exist */
735 if (!KdpDoesComPortExist(DefaultPort
.BaseAddress
))
737 return STATUS_INVALID_PARAMETER
;
740 /* Initialize the port */
741 KdPortInitializeEx(&DefaultPort
, 0, 0);
742 PortInitialized
= TRUE
;
744 return STATUS_SUCCESS
;
747 /******************************************************************************
748 * \name KdDebuggerInitialize1
749 * \brief Phase 1 initialization.
750 * \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL.
755 KdDebuggerInitialize1(
756 IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL
)
758 // HACK: misuse this function to get a pointer to FrLdrDbgPrint
759 FrLdrDbgPrint
= (PVOID
)LoaderBlock
;
760 return STATUS_NOT_IMPLEMENTED
;
769 IN BOOLEAN SleepTransition
)
771 /* Nothing to do on COM ports */
772 return STATUS_SUCCESS
;
781 IN BOOLEAN SleepTransition
)
783 /* Nothing to do on COM ports */
784 return STATUS_SUCCESS
;
794 IN PSTRING MessageHeader
,
795 IN PSTRING MessageData
,
796 IN OUT PKD_CONTEXT Context
)
803 /* Initialize a KD_PACKET */
804 Packet
.PacketLeader
= PACKET_LEADER
;
805 Packet
.PacketType
= PacketType
;
806 Packet
.ByteCount
= MessageHeader
->Length
;
807 Packet
.Checksum
= KdpCalculateChecksum(MessageHeader
->Buffer
,
808 MessageHeader
->Length
);
810 /* If we have message data, add it to the packet */
813 Packet
.ByteCount
+= MessageData
->Length
;
814 Packet
.Checksum
+= KdpCalculateChecksum(MessageData
->Buffer
,
815 MessageData
->Length
);
818 /* Set the packet id */
819 Packet
.PacketId
= CurrentPacketId
;
821 /* Send the packet header to the KD port */
822 KdpSendBuffer(&Packet
, sizeof(KD_PACKET
));
824 /* Send the message header */
825 KdpSendBuffer(MessageHeader
->Buffer
, MessageHeader
->Length
);
827 /* If we have meesage data, also send it */
830 KdpSendBuffer(MessageData
->Buffer
, MessageData
->Length
);
833 /* Finalize with a trailing byte */
834 KdPortPutByte(PACKET_TRAILING_BYTE
);
836 /* Wait for acknowledge */
837 RcvCode
= KdReceivePacket(PACKET_TYPE_KD_ACKNOWLEDGE
,
843 /* Did we succeed? */
844 if (RcvCode
== KdPacketReceived
)
846 CurrentPacketId
&= ~SYNC_PACKET_ID
;
850 /* PACKET_TYPE_KD_DEBUG_IO is allowed to instantly timeout */
851 if (PacketType
== PACKET_TYPE_KD_DEBUG_IO
)
853 /* No response, silently fail. */
857 /* Packet timed out, send it again */
864 /******************************************************************************
865 * \name KdReceivePacket
866 * \brief Receive a packet from the KD port.
867 * \param [in] PacketType Describes the type of the packet to receive.
868 * This can be one of the PACKET_TYPE_ constants.
869 * \param [out] MessageHeader Pointer to a STRING structure for the header.
870 * \param [out] MessageData Pointer to a STRING structure for the data.
871 * \return KdPacketReceived if successful, KdPacketTimedOut if the receive
872 * timed out, KdPacketNeedsResend to signal that the last packet needs
874 * \note If PacketType is PACKET_TYPE_KD_POLL_BREAKIN, the function doesn't
875 * wait for any data, but returns KdPacketTimedOut instantly if no breakin
876 * packet byte is received.
877 * \sa http://www.nynaeve.net/?p=169
883 OUT PSTRING MessageHeader
,
884 OUT PSTRING MessageData
,
885 OUT PULONG DataLength
,
886 IN OUT PKD_CONTEXT Context
)
893 /* Special handling for breakin packet */
894 if(PacketType
== PACKET_TYPE_KD_POLL_BREAKIN
)
896 if (KdPortGetByteEx(&DefaultPort
, &Byte
))
898 if (Byte
== BREAKIN_PACKET_BYTE
)
900 return KdPacketReceived
;
903 return KdPacketTimedOut
;
908 /* Step 1 - Read PacketLeader */
909 RcvCode
= KdpReceivePacketLeader(&Packet
.PacketLeader
);
910 if (RcvCode
!= KdPacketReceived
)
912 /* Couldn't read a correct packet leader. Start over. */
916 /* Step 2 - Read PacketType */
917 RcvCode
= KdpReceiveBuffer(&Packet
.PacketType
, sizeof(USHORT
));
918 if (RcvCode
!= KdPacketReceived
)
920 /* Didn't receive a PacketType or PacketType is bad. Start over. */
924 /* Step 3 - Read ByteCount */
925 RcvCode
= KdpReceiveBuffer(&Packet
.ByteCount
, sizeof(USHORT
));
926 if (RcvCode
!= KdPacketReceived
|| Packet
.ByteCount
> PACKET_MAX_SIZE
)
928 /* Didn't receive ByteCount or it's too big. Start over. */
932 /* Step 4 - Read PacketId */
933 RcvCode
= KdpReceiveBuffer(&Packet
.PacketId
, sizeof(ULONG
));
934 if (RcvCode
!= KdPacketReceived
)
936 /* Didn't receive PacketId. Start over. */
941 if (Packet.PacketId != ExpectedPacketId)
948 /* Step 5 - Read Checksum */
949 RcvCode
= KdpReceiveBuffer(&Packet
.Checksum
, sizeof(ULONG
));
950 if (RcvCode
!= KdPacketReceived
)
952 /* Didn't receive Checksum. Start over. */
956 /* Step 6 - Handle control packets */
957 if (Packet
.PacketLeader
== CONTROL_PACKET_LEADER
)
959 switch (Packet
.PacketType
)
961 case PACKET_TYPE_KD_ACKNOWLEDGE
:
962 if (PacketType
== PACKET_TYPE_KD_ACKNOWLEDGE
)
964 /* Remote acknowledges the last packet */
965 CurrentPacketId
^= 1;
966 return KdPacketReceived
;
968 /* That's not what we were waiting for, start over. */
971 case PACKET_TYPE_KD_RESET
:
972 FrLdrDbgPrint("KdReceivePacket - got a reset packet\n");
973 KdpSendControlPacket(PACKET_TYPE_KD_RESET
, 0);
974 CurrentPacketId
= INITIAL_PACKET_ID
;
977 case PACKET_TYPE_KD_RESEND
:
978 /* Remote wants us to resend the last packet */
979 return KdPacketNeedsResend
;
982 FrLdrDbgPrint("KdReceivePacket - got unknown control packet\n");
983 return KdPacketNeedsResend
;
987 /* Did we wait for an ack packet? */
988 if (PacketType
== PACKET_TYPE_KD_ACKNOWLEDGE
)
990 /* We received something different, start over */
994 /* Did we get the right packet type? */
995 if (PacketType
!= Packet
.PacketType
)
997 /* We received something different, start over */
1001 /* Get size of the message header */
1002 switch (Packet
.PacketType
)
1004 case PACKET_TYPE_KD_STATE_CHANGE64
:
1005 MessageHeader
->Length
= sizeof(DBGKD_WAIT_STATE_CHANGE64
);
1008 case PACKET_TYPE_KD_STATE_MANIPULATE
:
1009 MessageHeader
->Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
1012 case PACKET_TYPE_KD_DEBUG_IO
:
1013 MessageHeader
->Length
= sizeof(DBGKD_DEBUG_IO
);
1017 FrLdrDbgPrint("KdReceivePacket - unknown PacketType\n");
1018 return KdPacketNeedsResend
;
1021 //FrLdrDbgPrint("KdReceivePacket - got normal PacketType\n");
1023 /* Packet smaller than expected? */
1024 if (MessageHeader
->Length
> Packet
.ByteCount
)
1026 FrLdrDbgPrint("KdReceivePacket - too few data (%d) for type %d\n",
1027 Packet
.ByteCount
, MessageHeader
->Length
);
1028 MessageHeader
->Length
= Packet
.ByteCount
;
1031 //FrLdrDbgPrint("KdReceivePacket - got normal PacketType, Buffer = %p\n", MessageHeader->Buffer);
1033 /* Receive the message header data */
1034 RcvCode
= KdpReceiveBuffer(MessageHeader
->Buffer
,
1035 MessageHeader
->Length
);
1036 if (RcvCode
!= KdPacketReceived
)
1038 /* Didn't receive data. Start over. */
1039 FrLdrDbgPrint("KdReceivePacket - Didn't receive message header data. Start over\n");
1043 //FrLdrDbgPrint("KdReceivePacket - got normal PacketType 3\n");
1045 /* Calculate checksum for the header data */
1046 Checksum
= KdpCalculateChecksum(MessageHeader
->Buffer
,
1047 MessageHeader
->Length
);
1049 /* Shall we receive messsage data? */
1052 /* Calculate the length of the message data */
1053 MessageData
->Length
= Packet
.ByteCount
- MessageHeader
->Length
;
1055 /* Do we have data? */
1056 if (MessageData
->Length
)
1058 FrLdrDbgPrint("KdReceivePacket - got data\n");
1060 /* Receive the message data */
1061 RcvCode
= KdpReceiveBuffer(MessageData
->Buffer
,
1062 MessageData
->Length
);
1063 if (RcvCode
!= KdPacketReceived
)
1065 /* Didn't receive data. Start over. */
1066 FrLdrDbgPrint("KdReceivePacket - Didn't receive message data. Start over\n");
1070 /* Add cheksum for message data */
1071 Checksum
+= KdpCalculateChecksum(MessageData
->Buffer
,
1072 MessageData
->Length
);
1076 /* Compare checksum */
1077 if (Packet
.Checksum
!= Checksum
)
1079 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, CurrentPacketId
);
1080 FrLdrDbgPrint("KdReceivePacket - wrong cheksum, got %x, calculated %x\n",
1081 Packet
.Checksum
, Checksum
);
1085 /* We must receive a PACKET_TRAILING_BYTE now */
1086 RcvCode
= KdpReceiveBuffer(&Byte
, sizeof(UCHAR
));
1088 /* Acknowledge the received packet */
1089 KdpSendControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE
, Packet
.PacketId
);
1091 //FrLdrDbgPrint("KdReceivePacket - all ok\n");
1093 return KdPacketReceived
;
1096 return KdPacketReceived
;