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 *****************************************************************/
23 #include <ioaccess.h> /* port intrinsics */
25 typedef struct _KD_PORT_INFORMATION
29 ULONG_PTR BaseAddress
;
30 } KD_PORT_INFORMATION
, *PKD_PORT_INFORMATION
;
35 IN PKD_PORT_INFORMATION PortInformation
,
42 IN PKD_PORT_INFORMATION PortInformation
,
43 OUT PUCHAR ByteReceived
);
48 IN PKD_PORT_INFORMATION PortInformation
,
49 OUT PUCHAR ByteReceived
);
54 IN PKD_PORT_INFORMATION PortInformation
,
57 /* serial debug connection */
58 #define DEFAULT_DEBUG_PORT 2 /* COM2 */
59 #define DEFAULT_DEBUG_COM1_IRQ 4 /* COM1 IRQ */
60 #define DEFAULT_DEBUG_COM2_IRQ 3 /* COM2 IRQ */
61 #define DEFAULT_DEBUG_BAUD_RATE 115200 /* 115200 Baud */
63 #define DEFAULT_BAUD_RATE 19200
66 const ULONG BaseArray
[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};
68 const ULONG BaseArray
[2] = {0, 0x800003f8};
69 #elif defined(_M_MIPS)
70 const ULONG BaseArray
[3] = {0, 0x80006000, 0x80007000};
72 const ULONG BaseArray
[2] = {0, 0xF1012000};
73 #elif defined(_M_AMD64)
74 const ULONG BaseArray
[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};
76 #error Unknown architecture
79 /* MACROS *******************************************************************/
81 #define SER_RBR(x) ((PUCHAR)(x)+0)
82 #define SER_THR(x) ((PUCHAR)(x)+0)
83 #define SER_DLL(x) ((PUCHAR)(x)+0)
84 #define SER_IER(x) ((PUCHAR)(x)+1)
85 #define SR_IER_ERDA 0x01
86 #define SR_IER_ETHRE 0x02
87 #define SR_IER_ERLSI 0x04
88 #define SR_IER_EMS 0x08
89 #define SR_IER_ALL 0x0F
90 #define SER_DLM(x) ((PUCHAR)(x)+1)
91 #define SER_IIR(x) ((PUCHAR)(x)+2)
92 #define SER_FCR(x) ((PUCHAR)(x)+2)
93 #define SR_FCR_ENABLE_FIFO 0x01
94 #define SR_FCR_CLEAR_RCVR 0x02
95 #define SR_FCR_CLEAR_XMIT 0x04
96 #define SER_LCR(x) ((PUCHAR)(x)+3)
97 #define SR_LCR_CS5 0x00
98 #define SR_LCR_CS6 0x01
99 #define SR_LCR_CS7 0x02
100 #define SR_LCR_CS8 0x03
101 #define SR_LCR_ST1 0x00
102 #define SR_LCR_ST2 0x04
103 #define SR_LCR_PNO 0x00
104 #define SR_LCR_POD 0x08
105 #define SR_LCR_PEV 0x18
106 #define SR_LCR_PMK 0x28
107 #define SR_LCR_PSP 0x38
108 #define SR_LCR_BRK 0x40
109 #define SR_LCR_DLAB 0x80
110 #define SER_MCR(x) ((PUCHAR)(x)+4)
111 #define SR_MCR_DTR 0x01
112 #define SR_MCR_RTS 0x02
113 #define SR_MCR_OUT1 0x04
114 #define SR_MCR_OUT2 0x08
115 #define SR_MCR_LOOP 0x10
116 #define SER_LSR(x) ((PUCHAR)(x)+5)
117 #define SR_LSR_DR 0x01
118 #define SR_LSR_TBE 0x20
119 #define SER_MSR(x) ((PUCHAR)(x)+6)
120 #define SR_MSR_CTS 0x10
121 #define SR_MSR_DSR 0x20
122 #define SER_SCR(x) ((PUCHAR)(x)+7)
125 /* GLOBAL VARIABLES *********************************************************/
127 ULONG CurrentPacketId
= INITIAL_PACKET_ID
;
129 /* STATIC VARIABLES *********************************************************/
131 static KD_PORT_INFORMATION DefaultPort
= { 0, 0, 0 };
133 /* The com port must only be initialized once! */
134 static BOOLEAN PortInitialized
= FALSE
;
140 typedef ULONG (*DBGRNT
)(const char *Format
, ...);
141 DBGRNT FrLdrDbgPrint
= 0;
143 /* STATIC FUNCTIONS *********************************************************/
147 IN ULONG_PTR BaseAddress
)
155 /* save Modem Control Register (MCR) */
156 mcr
= READ_PORT_UCHAR(SER_MCR(BaseAddress
));
158 /* enable loop mode (set Bit 4 of the MCR) */
159 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), SR_MCR_LOOP
);
161 /* clear all modem output bits */
162 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), SR_MCR_LOOP
);
164 /* read the Modem Status Register */
165 msr
= READ_PORT_UCHAR(SER_MSR(BaseAddress
));
168 * the upper nibble of the MSR (modem output bits) must be
169 * equal to the lower nibble of the MCR (modem input bits)
171 if ((msr
& 0xF0) == 0x00)
173 /* set all modem output bits */
174 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), SR_MCR_DTR
| SR_MCR_RTS
| SR_MCR_OUT1
| SR_MCR_OUT2
| SR_MCR_LOOP
);
176 /* read the Modem Status Register */
177 msr
= READ_PORT_UCHAR(SER_MSR(BaseAddress
));
180 * the upper nibble of the MSR (modem output bits) must be
181 * equal to the lower nibble of the MCR (modem input bits)
183 if ((msr
& 0xF0) == 0xF0)
186 * setup a resonable state for the port:
187 * enable fifo and clear recieve/transmit buffers
189 WRITE_PORT_UCHAR(SER_FCR(BaseAddress
),
190 (SR_FCR_ENABLE_FIFO
| SR_FCR_CLEAR_RCVR
| SR_FCR_CLEAR_XMIT
));
191 WRITE_PORT_UCHAR(SER_FCR(BaseAddress
), 0);
192 READ_PORT_UCHAR(SER_RBR(BaseAddress
));
193 WRITE_PORT_UCHAR(SER_IER(BaseAddress
), 0);
199 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), mcr
);
205 /* FUNCTIONS ****************************************************************/
209 IN PDRIVER_OBJECT DriverObject
,
210 IN PUNICODE_STRING RegistryPath
)
212 return STATUS_SUCCESS
;
215 /* HAL.KdPortInitialize */
219 IN PKD_PORT_INFORMATION PortInformation
,
226 if (!PortInitialized
)
228 DefaultPort
.BaudRate
= PortInformation
->BaudRate
;
230 if (PortInformation
->ComPort
== 0)
232 for (i
= sizeof(BaseArray
) / sizeof(BaseArray
[0]) - 1; i
> 0; i
--)
234 if (KdpDoesComPortExist(BaseArray
[i
]))
236 DefaultPort
.BaseAddress
= BaseArray
[i
];
237 DefaultPort
.ComPort
= i
;
238 PortInformation
->BaseAddress
= DefaultPort
.BaseAddress
;
239 PortInformation
->ComPort
= DefaultPort
.ComPort
;
246 "\nKernel Debugger: No COM port found!\n\n");
247 HalDisplayString(buffer
);
252 PortInitialized
= TRUE
;
255 /* initialize port */
256 if (!KdPortInitializeEx(&DefaultPort
, Unknown1
, Unknown2
))
259 /* set global info */
260 KdComPortInUse
= (PUCHAR
)DefaultPort
.BaseAddress
;
266 /* HAL.KdPortInitializeEx */
270 IN PKD_PORT_INFORMATION PortInformation
,
274 ULONG_PTR ComPortBase
;
284 if (PortInformation
->BaudRate
== 0)
285 PortInformation
->BaudRate
= DEFAULT_BAUD_RATE
;
287 if (PortInformation
->ComPort
== 0)
290 if (!KdpDoesComPortExist(BaseArray
[PortInformation
->ComPort
]))
293 "\nKernel Debugger: Serial port not found!\n\n");
294 HalDisplayString(buffer
);
298 ComPortBase
= BaseArray
[PortInformation
->ComPort
];
299 PortInformation
->BaseAddress
= ComPortBase
;
302 "\nSerial port COM%ld found at 0x%lx\n",
303 PortInformation
->ComPort
,
305 HalDisplayString(buffer
);
308 /* set baud rate and data format (8N1) */
310 /* turn on DTR and RTS */
311 WRITE_PORT_UCHAR(SER_MCR(ComPortBase
), SR_MCR_DTR
| SR_MCR_RTS
);
314 lcr
= READ_PORT_UCHAR(SER_LCR(ComPortBase
)) | SR_LCR_DLAB
;
315 WRITE_PORT_UCHAR(SER_LCR(ComPortBase
), lcr
);
318 divisor
= 115200 / PortInformation
->BaudRate
;
319 WRITE_PORT_UCHAR(SER_DLL(ComPortBase
), (UCHAR
)(divisor
& 0xff));
320 WRITE_PORT_UCHAR(SER_DLM(ComPortBase
), (UCHAR
)((divisor
>> 8) & 0xff));
322 /* reset DLAB and set 8N1 format */
323 WRITE_PORT_UCHAR(SER_LCR(ComPortBase
),
324 SR_LCR_CS8
| SR_LCR_ST1
| SR_LCR_PNO
);
326 /* read junk out of the RBR */
327 lcr
= READ_PORT_UCHAR(SER_RBR(ComPortBase
));
330 /* print message to blue screen */
332 "\nKernel Debugger: COM%ld (Port 0x%lx) BaudRate %ld\n\n",
333 PortInformation
->ComPort
,
335 PortInformation
->BaudRate
);
337 HalDisplayString(buffer
);
344 /* HAL.KdPortGetByte */
348 OUT PUCHAR ByteReceived
)
350 if (!PortInitialized
)
352 return KdPortGetByteEx(&DefaultPort
, ByteReceived
);
356 /* HAL.KdPortGetByteEx */
360 IN PKD_PORT_INFORMATION PortInformation
,
361 OUT PUCHAR ByteReceived
)
363 PUCHAR ComPortBase
= (PUCHAR
)PortInformation
->BaseAddress
;
365 if ((READ_PORT_UCHAR(SER_LSR(ComPortBase
)) & SR_LSR_DR
))
367 *ByteReceived
= READ_PORT_UCHAR(SER_RBR(ComPortBase
));
375 /* HAL.KdPortPollByte */
379 OUT PUCHAR ByteReceived
)
381 if (!PortInitialized
)
383 return KdPortPollByteEx(&DefaultPort
, ByteReceived
);
387 /* HAL.KdPortPollByteEx */
391 IN PKD_PORT_INFORMATION PortInformation
,
392 OUT PUCHAR ByteReceived
)
394 PUCHAR ComPortBase
= (PUCHAR
)PortInformation
->BaseAddress
;
396 while ((READ_PORT_UCHAR(SER_LSR(ComPortBase
)) & SR_LSR_DR
) == 0)
399 *ByteReceived
= READ_PORT_UCHAR(SER_RBR(ComPortBase
));
405 /* HAL.KdPortPutByte */
411 if (!PortInitialized
)
413 KdPortPutByteEx(&DefaultPort
, ByteToSend
);
416 /* HAL.KdPortPutByteEx */
420 IN PKD_PORT_INFORMATION PortInformation
,
423 PUCHAR ComPortBase
= (PUCHAR
)PortInformation
->BaseAddress
;
425 while ((READ_PORT_UCHAR(SER_LSR(ComPortBase
)) & SR_LSR_TBE
) == 0)
428 WRITE_PORT_UCHAR(SER_THR(ComPortBase
), ByteToSend
);
432 /* HAL.KdPortRestore */
450 /* HAL.KdPortDisableInterrupts */
453 KdPortDisableInterrupts(VOID
)
457 if (!PortInitialized
)
460 ch
= READ_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
));
461 ch
&= (~(SR_MCR_OUT1
| SR_MCR_OUT2
));
462 WRITE_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
), ch
);
464 ch
= READ_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
));
466 WRITE_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
), ch
);
472 /* HAL.KdPortEnableInterrupts */
475 KdPortEnableInterrupts(VOID
)
479 if (PortInitialized
== FALSE
)
482 ch
= READ_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
));
485 WRITE_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
), ch
);
487 ch
= READ_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
));
488 ch
&= (~SR_MCR_LOOP
);
489 ch
|= (SR_MCR_OUT1
| SR_MCR_OUT2
);
490 WRITE_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
), ch
);
495 /* NEW INTERNAL FUNCTIONS ****************************************************/
497 /******************************************************************************
498 * \name KdpCalculateChecksum
499 * \brief Calculates the checksum for the packet data.
500 * \param Buffer Pointer to the packet data.
501 * \param Length Length of data in bytes.
502 * \return The calculated checksum.
503 * \sa http://www.vista-xp.co.uk/forums/technical-reference-library/2540-basics-debugging.html
507 KdpCalculateChecksum(
511 ULONG i
, Checksum
= 0;
513 for (i
= 0; i
< Length
; i
++)
515 Checksum
+= ((PUCHAR
)Buffer
)[i
];
520 /******************************************************************************
521 * \name KdpSendBuffer
522 * \brief Sends a buffer of data to the KD port.
523 * \param Buffer Pointer to the data.
524 * \param Size Size of data in bytes.
533 for (i
= 0; i
< Size
; i
++)
535 KdPortPutByteEx(&DefaultPort
, ((PUCHAR
)Buffer
)[i
]);
540 /******************************************************************************
541 * \name KdpReceiveBuffer
542 * \brief Recieves data from the KD port and fills a buffer.
543 * \param Buffer Pointer to a buffer that receives the data.
544 * \param Size Size of data to receive in bytes.
545 * \return KdPacketReceived if successful.
546 * KdPacketTimedOut if the receice timed out (10 seconds).
547 * \todo Handle timeout.
556 PUCHAR ByteBuffer
= Buffer
;
557 BOOLEAN Ret
, TimeOut
;
559 for (i
= 0; i
< Size
; i
++)
563 Ret
= KdPortGetByteEx(&DefaultPort
, &ByteBuffer
[i
]);
564 TimeOut
= FALSE
; // FIXME timeout after 10 Sec
566 while (!Ret
|| TimeOut
);
570 return KdPacketTimedOut
;
572 // FrLdrDbgPrint("Received byte: %x\n", ByteBuffer[i]);
575 return KdPacketReceived
;
580 KdpReceivePacketLeader(
581 OUT PULONG PacketLeader
)
583 UCHAR Byte
, PrevByte
;
589 for (i
= 0; i
< 4; i
++)
591 RcvCode
= KdpReceiveBuffer(&Byte
, sizeof(UCHAR
));
592 Temp
= (Temp
<< 8) | Byte
;
593 if ( (RcvCode
!= KdPacketReceived
) ||
594 ((Byte
!= PACKET_LEADER_BYTE
) &&
595 (Byte
!= CONTROL_PACKET_LEADER_BYTE
)) ||
596 (PrevByte
!= 0 && Byte
!= PrevByte
) )
598 return KdPacketNeedsResend
;
603 *PacketLeader
= Temp
;
605 return KdPacketReceived
;
611 KdpSendControlPacket(
612 IN USHORT PacketType
,
613 IN ULONG PacketId OPTIONAL
)
617 Packet
.PacketLeader
= CONTROL_PACKET_LEADER
;
618 Packet
.PacketId
= PacketId
;
619 Packet
.ByteCount
= 0;
621 Packet
.PacketType
= PacketType
;
623 KdpSendBuffer(&Packet
, sizeof(KD_PACKET
));
627 /* NEW PUBLIC FUNCTIONS ******************************************************/
629 /******************************************************************************
630 * \name KdDebuggerInitialize0
631 * \brief Phase 0 initialization.
632 * \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL.
637 KdDebuggerInitialize0(
638 IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL
)
641 PCHAR CommandLine
, Port
, BaudRate
, Irq
;
643 /* Apply default values */
645 DefaultPort
.ComPort
= DEFAULT_DEBUG_PORT
;
646 DefaultPort
.BaudRate
= DEFAULT_DEBUG_BAUD_RATE
;
648 /* Check if e have a LoaderBlock */
651 /* Get the Command Line */
652 CommandLine
= LoaderBlock
->LoadOptions
;
655 _strupr(CommandLine
);
657 /* Get the port and baud rate */
658 Port
= strstr(CommandLine
, "DEBUGPORT");
659 BaudRate
= strstr(CommandLine
, "BAUDRATE");
660 Irq
= strstr(CommandLine
, "IRQ");
662 /* Check if we got the /DEBUGPORT parameter */
665 /* Move past the actual string, to reach the port*/
666 Port
+= strlen("DEBUGPORT");
668 /* Now get past any spaces and skip the equal sign */
669 while (*Port
== ' ') Port
++;
672 /* Do we have a serial port? */
673 if (strncmp(Port
, "COM", 3) != 0)
675 return STATUS_INVALID_PARAMETER
;
678 /* Gheck for a valid Serial Port */
683 return STATUS_INVALID_PARAMETER
;
686 /* Set the port to use */
687 DefaultPort
.ComPort
= Value
;
690 /* Check if we got a baud rate */
693 /* Move past the actual string, to reach the rate */
694 BaudRate
+= strlen("BAUDRATE");
696 /* Now get past any spaces */
697 while (*BaudRate
== ' ') BaudRate
++;
699 /* And make sure we have a rate */
702 /* Read and set it */
703 Value
= atol(BaudRate
+ 1);
704 if (Value
) DefaultPort
.BaudRate
= Value
;
708 /* Check Serial Port Settings [IRQ] */
711 /* Move past the actual string, to reach the rate */
712 Irq
+= strlen("IRQ");
714 /* Now get past any spaces */
715 while (*Irq
== ' ') Irq
++;
717 /* And make sure we have an IRQ */
720 /* Read and set it */
721 Value
= atol(Irq
+ 1);
722 if (Value
) KdpPortIrq
= Value
;
727 // HACK use com1 for FrLdrDbg, com2 for WinDbg
728 DefaultPort
.ComPort
= 2;
730 /* Get base address */
731 DefaultPort
.BaseAddress
= BaseArray
[DefaultPort
.ComPort
];
733 /* Check if the COM port does exist */
734 if (!KdpDoesComPortExist(DefaultPort
.BaseAddress
))
736 return STATUS_INVALID_PARAMETER
;
739 /* Initialize the port */
740 KdPortInitializeEx(&DefaultPort
, 0, 0);
741 PortInitialized
= TRUE
;
743 return STATUS_SUCCESS
;
746 /******************************************************************************
747 * \name KdDebuggerInitialize1
748 * \brief Phase 1 initialization.
749 * \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL.
754 KdDebuggerInitialize1(
755 IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL
)
757 // HACK: misuse this function to get a pointer to FrLdrDbgPrint
758 FrLdrDbgPrint
= (PVOID
)LoaderBlock
;
759 return STATUS_NOT_IMPLEMENTED
;
768 IN BOOLEAN SleepTransition
)
770 /* Nothing to do on COM ports */
771 return STATUS_SUCCESS
;
780 IN BOOLEAN SleepTransition
)
782 /* Nothing to do on COM ports */
783 return STATUS_SUCCESS
;
793 IN PSTRING MessageHeader
,
794 IN PSTRING MessageData
,
795 IN OUT PKD_CONTEXT Context
)
802 /* Initialize a KD_PACKET */
803 Packet
.PacketLeader
= PACKET_LEADER
;
804 Packet
.PacketType
= PacketType
;
805 Packet
.ByteCount
= MessageHeader
->Length
;
806 Packet
.Checksum
= KdpCalculateChecksum(MessageHeader
->Buffer
,
807 MessageHeader
->Length
);
809 /* If we have message data, add it to the packet */
812 Packet
.ByteCount
+= MessageData
->Length
;
813 Packet
.Checksum
+= KdpCalculateChecksum(MessageData
->Buffer
,
814 MessageData
->Length
);
817 // FIXME: this looks wrong, but makes dbgprints work
818 if (PacketType
== PACKET_TYPE_KD_DEBUG_IO
)
820 CurrentPacketId
|= SYNC_PACKET_ID
;
823 /* Set the packet id */
824 Packet
.PacketId
= CurrentPacketId
;
826 /* Send the packet header to the KD port */
827 KdpSendBuffer(&Packet
, sizeof(KD_PACKET
));
829 /* Send the message header */
830 KdpSendBuffer(MessageHeader
->Buffer
, MessageHeader
->Length
);
832 /* If we have meesage data, also send it */
835 KdpSendBuffer(MessageData
->Buffer
, MessageData
->Length
);
838 /* Finalize with a trailing byte */
839 KdPortPutByte(PACKET_TRAILING_BYTE
);
841 /* Wait for acknowledge */
842 RcvCode
= KdReceivePacket(PACKET_TYPE_KD_ACKNOWLEDGE
,
848 /* Did we succeed? */
849 if (RcvCode
== KdPacketReceived
)
851 CurrentPacketId
&= ~SYNC_PACKET_ID
;
855 /* PACKET_TYPE_KD_DEBUG_IO is allowed to instantly timeout */
856 if (PacketType
== PACKET_TYPE_KD_DEBUG_IO
)
858 /* No response, silently fail. */
862 /* Packet timed out, send it again */
869 /******************************************************************************
870 * \name KdReceivePacket
871 * \brief Receive a packet from the KD port.
872 * \param [in] PacketType Describes the type of the packet to receive.
873 * This can be one of the PACKET_TYPE_ constants.
874 * \param [out] MessageHeader Pointer to a STRING structure for the header.
875 * \param [out] MessageData Pointer to a STRING structure for the data.
876 * \return KdPacketReceived if successful, KdPacketTimedOut if the receive
877 * timed out, KdPacketNeedsResend to signal that the last packet needs
879 * \note If PacketType is PACKET_TYPE_KD_POLL_BREAKIN, the function doesn't
880 * wait for any data, but returns KdPacketTimedOut instantly if no breakin
881 * packet byte is received.
882 * \sa http://www.nynaeve.net/?p=169
888 OUT PSTRING MessageHeader
,
889 OUT PSTRING MessageData
,
890 OUT PULONG DataLength
,
891 IN OUT PKD_CONTEXT Context
)
898 /* Special handling for breakin packet */
899 if(PacketType
== PACKET_TYPE_KD_POLL_BREAKIN
)
901 if (KdPortGetByteEx(&DefaultPort
, &Byte
))
903 if (Byte
== BREAKIN_PACKET_BYTE
)
905 return KdPacketReceived
;
908 return KdPacketTimedOut
;
913 /* Step 1 - Read PacketLeader */
914 RcvCode
= KdpReceivePacketLeader(&Packet
.PacketLeader
);
915 if (RcvCode
!= KdPacketReceived
)
917 /* Couldn't read a correct packet leader. Start over. */
921 /* Step 2 - Read PacketType */
922 RcvCode
= KdpReceiveBuffer(&Packet
.PacketType
, sizeof(USHORT
));
923 if (RcvCode
!= KdPacketReceived
)
925 /* Didn't receive a PacketType or PacketType is bad. Start over. */
929 /* Step 3 - Read ByteCount */
930 RcvCode
= KdpReceiveBuffer(&Packet
.ByteCount
, sizeof(USHORT
));
931 if (RcvCode
!= KdPacketReceived
|| Packet
.ByteCount
> PACKET_MAX_SIZE
)
933 /* Didn't receive ByteCount or it's too big. Start over. */
937 /* Step 4 - Read PacketId */
938 RcvCode
= KdpReceiveBuffer(&Packet
.PacketId
, sizeof(ULONG
));
939 if (RcvCode
!= KdPacketReceived
)
941 /* Didn't receive PacketId. Start over. */
946 if (Packet.PacketId != ExpectedPacketId)
953 /* Step 5 - Read Checksum */
954 RcvCode
= KdpReceiveBuffer(&Packet
.Checksum
, sizeof(ULONG
));
955 if (RcvCode
!= KdPacketReceived
)
957 /* Didn't receive Checksum. Start over. */
961 /* Step 6 - Handle control packets */
962 if (Packet
.PacketLeader
== CONTROL_PACKET_LEADER
)
964 switch (Packet
.PacketType
)
966 case PACKET_TYPE_KD_ACKNOWLEDGE
:
967 if (PacketType
== PACKET_TYPE_KD_ACKNOWLEDGE
)
969 /* Remote acknowledges the last packet */
970 return KdPacketReceived
;
972 /* That's not what we were waiting for, start over. */
975 case PACKET_TYPE_KD_RESET
:
976 FrLdrDbgPrint("KdReceivePacket - got a reset packet\n");
977 KdpSendControlPacket(PACKET_TYPE_KD_RESET
, 0);
978 CurrentPacketId
= INITIAL_PACKET_ID
;
981 case PACKET_TYPE_KD_RESEND
:
982 /* Remote wants us to resend the last packet */
983 return KdPacketNeedsResend
;
986 FrLdrDbgPrint("KdReceivePacket - got unknown control packet\n");
987 return KdPacketNeedsResend
;
991 /* Did we wait for an ack packet? */
992 if (PacketType
== PACKET_TYPE_KD_ACKNOWLEDGE
)
994 /* We received something different, start over */
998 /* Did we get the right packet type? */
999 if (PacketType
!= Packet
.PacketType
)
1001 /* We received something different, start over */
1005 /* Get size of the message header */
1006 switch (Packet
.PacketType
)
1008 case PACKET_TYPE_KD_STATE_CHANGE64
:
1009 MessageHeader
->Length
= sizeof(DBGKD_WAIT_STATE_CHANGE64
);
1012 case PACKET_TYPE_KD_STATE_MANIPULATE
:
1013 MessageHeader
->Length
= sizeof(DBGKD_MANIPULATE_STATE64
);
1016 case PACKET_TYPE_KD_DEBUG_IO
:
1017 MessageHeader
->Length
= sizeof(DBGKD_DEBUG_IO
);
1021 FrLdrDbgPrint("KdReceivePacket - unknown PacketType\n");
1022 return KdPacketNeedsResend
;
1025 //FrLdrDbgPrint("KdReceivePacket - got normal PacketType\n");
1027 /* Packet smaller than expected? */
1028 if (MessageHeader
->Length
> Packet
.ByteCount
)
1030 FrLdrDbgPrint("KdReceivePacket - too few data (%d) for type %d\n",
1031 Packet
.ByteCount
, MessageHeader
->Length
);
1032 MessageHeader
->Length
= Packet
.ByteCount
;
1035 //FrLdrDbgPrint("KdReceivePacket - got normal PacketType, Buffer = %p\n", MessageHeader->Buffer);
1037 /* Receive the message header data */
1038 RcvCode
= KdpReceiveBuffer(MessageHeader
->Buffer
,
1039 MessageHeader
->Length
);
1040 if (RcvCode
!= KdPacketReceived
)
1042 /* Didn't receive data. Start over. */
1043 FrLdrDbgPrint("KdReceivePacket - Didn't receive message header data. Start over\n");
1047 //FrLdrDbgPrint("KdReceivePacket - got normal PacketType 3\n");
1049 /* Calculate checksum for the header data */
1050 Checksum
= KdpCalculateChecksum(MessageHeader
->Buffer
,
1051 MessageHeader
->Length
);
1053 /* Shall we receive messsage data? */
1056 /* Calculate the length of the message data */
1057 MessageData
->Length
= Packet
.ByteCount
- MessageHeader
->Length
;
1059 /* Do we have data? */
1060 if (MessageData
->Length
)
1062 FrLdrDbgPrint("KdReceivePacket - got data\n");
1064 /* Receive the message data */
1065 RcvCode
= KdpReceiveBuffer(MessageData
->Buffer
,
1066 MessageData
->Length
);
1067 if (RcvCode
!= KdPacketReceived
)
1069 /* Didn't receive data. Start over. */
1070 FrLdrDbgPrint("KdReceivePacket - Didn't receive message data. Start over\n");
1074 /* Add cheksum for message data */
1075 Checksum
+= KdpCalculateChecksum(MessageData
->Buffer
,
1076 MessageData
->Length
);
1080 /* Compare checksum */
1081 if (Packet
.Checksum
!= Checksum
)
1083 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, CurrentPacketId
);
1084 FrLdrDbgPrint("KdReceivePacket - wrong cheksum, got %x, calculated %x\n",
1085 Packet
.Checksum
, Checksum
);
1089 /* We must receive a PACKET_TRAILING_BYTE now */
1090 RcvCode
= KdpReceiveBuffer(&Byte
, sizeof(UCHAR
));
1092 /* Acknowledge the received packet */
1093 KdpSendControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE
, CurrentPacketId
);
1094 CurrentPacketId
^= 1;
1096 //FrLdrDbgPrint("KdReceivePacket - all ok\n");
1098 return KdPacketReceived
;
1101 return KdPacketReceived
;