2 * COPYRIGHT: GPL, see COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/base/kddll/kddll.c
5 * PURPOSE: Base functions for the kernel debugger.
6 * PROGRAMMER: Timo Kreuzer (timo.kreuzer@ewactos.org)
14 /* GLOBALS ********************************************************************/
16 PFNDBGPRNT KdpDbgPrint
= NULL
;
17 ULONG CurrentPacketId
= INITIAL_PACKET_ID
| SYNC_PACKET_ID
;
18 ULONG RemotePacketId
= INITIAL_PACKET_ID
;
21 /* PRIVATE FUNCTIONS **********************************************************/
23 /******************************************************************************
24 * \name KdpCalculateChecksum
25 * \brief Calculates the checksum for the packet data.
26 * \param Buffer Pointer to the packet data.
27 * \param Length Length of data in bytes.
28 * \return The calculated checksum.
29 * \sa http://www.vista-xp.co.uk/forums/technical-reference-library/2540-basics-debugging.html
37 PUCHAR ByteBuffer
= Buffer
;
42 Checksum
+= (ULONG
)*ByteBuffer
++;
51 IN ULONG PacketId OPTIONAL
)
55 Packet
.PacketLeader
= CONTROL_PACKET_LEADER
;
56 Packet
.PacketId
= PacketId
;
59 Packet
.PacketType
= PacketType
;
61 KdpSendBuffer(&Packet
, sizeof(KD_PACKET
));
65 /* PUBLIC FUNCTIONS ***********************************************************/
67 /******************************************************************************
68 * \name KdReceivePacket
69 * \brief Receive a packet from the KD port.
70 * \param [in] PacketType Describes the type of the packet to receive.
71 * This can be one of the PACKET_TYPE_ constants.
72 * \param [out] MessageHeader Pointer to a STRING structure for the header.
73 * \param [out] MessageData Pointer to a STRING structure for the data.
74 * \return KdPacketReceived if successful, KdPacketTimedOut if the receive
75 * timed out, KdPacketNeedsResend to signal that the last packet needs
77 * \note If PacketType is PACKET_TYPE_KD_POLL_BREAKIN, the function doesn't
78 * wait for any data, but returns KdPacketTimedOut instantly if no breakin
79 * packet byte is received.
80 * \sa http://www.nynaeve.net/?p=169
86 OUT PSTRING MessageHeader
,
87 OUT PSTRING MessageData
,
88 OUT PULONG DataLength
,
89 IN OUT PKD_CONTEXT KdContext
)
96 /* Special handling for breakin packet */
97 if(PacketType
== PACKET_TYPE_KD_POLL_BREAKIN
)
99 return KdpPollBreakIn();
104 /* Step 1 - Read PacketLeader */
105 KdStatus
= KdpReceivePacketLeader(&Packet
.PacketLeader
);
106 if (KdStatus
!= KDP_PACKET_RECEIVED
)
108 /* Check if we got a breakin */
109 if (KdStatus
== KDP_PACKET_RESEND
)
111 KdContext
->KdpControlCPending
= TRUE
;
116 /* Step 2 - Read PacketType */
117 KdStatus
= KdpReceiveBuffer(&Packet
.PacketType
, sizeof(USHORT
));
118 if (KdStatus
!= KDP_PACKET_RECEIVED
)
120 /* Didn't receive a PacketType. */
124 /* Check if we got a resend packet */
125 if (Packet
.PacketLeader
== CONTROL_PACKET_LEADER
&&
126 Packet
.PacketType
== PACKET_TYPE_KD_RESEND
)
128 return KDP_PACKET_RESEND
;
131 /* Step 3 - Read ByteCount */
132 KdStatus
= KdpReceiveBuffer(&Packet
.ByteCount
, sizeof(USHORT
));
133 if (KdStatus
!= KDP_PACKET_RECEIVED
)
135 /* Didn't receive ByteCount. */
139 /* Step 4 - Read PacketId */
140 KdStatus
= KdpReceiveBuffer(&Packet
.PacketId
, sizeof(ULONG
));
141 if (KdStatus
!= KDP_PACKET_RECEIVED
)
143 /* Didn't receive PacketId. */
148 if (Packet.PacketId != ExpectedPacketId)
155 /* Step 5 - Read Checksum */
156 KdStatus
= KdpReceiveBuffer(&Packet
.Checksum
, sizeof(ULONG
));
157 if (KdStatus
!= KDP_PACKET_RECEIVED
)
159 /* Didn't receive Checksum. */
163 /* Step 6 - Handle control packets */
164 if (Packet
.PacketLeader
== CONTROL_PACKET_LEADER
)
166 switch (Packet
.PacketType
)
168 case PACKET_TYPE_KD_ACKNOWLEDGE
:
169 /* Are we waiting for an ACK packet? */
170 if (PacketType
== PACKET_TYPE_KD_ACKNOWLEDGE
&&
171 Packet
.PacketId
== (CurrentPacketId
& ~SYNC_PACKET_ID
))
173 /* Remote acknowledges the last packet */
174 CurrentPacketId
^= 1;
175 return KDP_PACKET_RECEIVED
;
177 /* That's not what we were waiting for, start over. */
180 case PACKET_TYPE_KD_RESET
:
181 KDDBGPRINT("KdReceivePacket - got a reset packet\n");
182 KdpSendControlPacket(PACKET_TYPE_KD_RESET
, 0);
183 CurrentPacketId
= INITIAL_PACKET_ID
;
184 RemotePacketId
= INITIAL_PACKET_ID
;
187 case PACKET_TYPE_KD_RESEND
:
188 KDDBGPRINT("KdReceivePacket - got PACKET_TYPE_KD_RESEND\n");
189 /* Remote wants us to resend the last packet */
190 return KDP_PACKET_RESEND
;
193 KDDBGPRINT("KdReceivePacket - got unknown control packet\n");
194 return KDP_PACKET_RESEND
;
198 /* Did we wait for an ack packet? */
199 if (PacketType
== PACKET_TYPE_KD_ACKNOWLEDGE
)
201 /* We received something different */
202 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
203 CurrentPacketId
^= 1;
204 return KDP_PACKET_RECEIVED
;
207 /* Get size of the message header */
208 MessageHeader
->Length
= MessageHeader
->MaximumLength
;
210 /* Packet smaller than expected or too big? */
211 if (Packet
.ByteCount
< MessageHeader
->Length
||
212 Packet
.ByteCount
> PACKET_MAX_SIZE
)
214 KDDBGPRINT("KdReceivePacket - too few data (%d) for type %d\n",
215 Packet
.ByteCount
, MessageHeader
->Length
);
216 MessageHeader
->Length
= Packet
.ByteCount
;
217 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
221 //KDDBGPRINT("KdReceivePacket - got normal PacketType, Buffer = %p\n", MessageHeader->Buffer);
223 /* Receive the message header data */
224 KdStatus
= KdpReceiveBuffer(MessageHeader
->Buffer
,
225 MessageHeader
->Length
);
226 if (KdStatus
!= KDP_PACKET_RECEIVED
)
228 /* Didn't receive data. Packet needs to be resent. */
229 KDDBGPRINT("KdReceivePacket - Didn't receive message header data.\n");
230 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
234 //KDDBGPRINT("KdReceivePacket - got normal PacketType 3\n");
236 /* Calculate checksum for the header data */
237 Checksum
= KdpCalculateChecksum(MessageHeader
->Buffer
,
238 MessageHeader
->Length
);
240 /* Calculate the length of the message data */
241 *DataLength
= Packet
.ByteCount
- MessageHeader
->Length
;
243 /* Shall we receive messsage data? */
246 /* Set the length of the message data */
247 MessageData
->Length
= (USHORT
)*DataLength
;
249 /* Do we have data? */
250 if (MessageData
->Length
)
252 KDDBGPRINT("KdReceivePacket - got data\n");
254 /* Receive the message data */
255 KdStatus
= KdpReceiveBuffer(MessageData
->Buffer
,
256 MessageData
->Length
);
257 if (KdStatus
!= KDP_PACKET_RECEIVED
)
259 /* Didn't receive data. Start over. */
260 KDDBGPRINT("KdReceivePacket - Didn't receive message data.\n");
261 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
265 /* Add cheksum for message data */
266 Checksum
+= KdpCalculateChecksum(MessageData
->Buffer
,
267 MessageData
->Length
);
271 /* We must receive a PACKET_TRAILING_BYTE now */
272 KdStatus
= KdpReceiveBuffer(&Byte
, sizeof(UCHAR
));
273 if (KdStatus
!= KDP_PACKET_RECEIVED
|| Byte
!= PACKET_TRAILING_BYTE
)
275 KDDBGPRINT("KdReceivePacket - wrong trailing byte (0x%x), status 0x%x\n", Byte
, KdStatus
);
276 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
280 /* Compare checksum */
281 if (Packet
.Checksum
!= Checksum
)
283 KDDBGPRINT("KdReceivePacket - wrong cheksum, got %x, calculated %x\n",
284 Packet
.Checksum
, Checksum
);
285 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
289 /* Acknowledge the received packet */
290 KdpSendControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE
, Packet
.PacketId
);
292 /* Check if the received PacketId is ok */
293 if (Packet
.PacketId
!= RemotePacketId
)
295 /* Continue with next packet */
299 /* Did we get the right packet type? */
300 if (PacketType
== Packet
.PacketType
)
302 /* Yes, return success */
303 //KDDBGPRINT("KdReceivePacket - all ok\n");
305 return KDP_PACKET_RECEIVED
;
308 /* We received something different, ignore it. */
309 KDDBGPRINT("KdReceivePacket - wrong PacketType\n");
312 return KDP_PACKET_RECEIVED
;
319 IN PSTRING MessageHeader
,
320 IN PSTRING MessageData
,
321 IN OUT PKD_CONTEXT KdContext
)
327 /* Initialize a KD_PACKET */
328 Packet
.PacketLeader
= PACKET_LEADER
;
329 Packet
.PacketType
= (USHORT
)PacketType
;
330 Packet
.ByteCount
= MessageHeader
->Length
;
331 Packet
.Checksum
= KdpCalculateChecksum(MessageHeader
->Buffer
,
332 MessageHeader
->Length
);
334 /* If we have message data, add it to the packet */
337 Packet
.ByteCount
+= MessageData
->Length
;
338 Packet
.Checksum
+= KdpCalculateChecksum(MessageData
->Buffer
,
339 MessageData
->Length
);
342 Retries
= KdContext
->KdpDefaultRetries
;
346 /* Set the packet id */
347 Packet
.PacketId
= CurrentPacketId
;
349 /* Send the packet header to the KD port */
350 KdpSendBuffer(&Packet
, sizeof(KD_PACKET
));
352 /* Send the message header */
353 KdpSendBuffer(MessageHeader
->Buffer
, MessageHeader
->Length
);
355 /* If we have meesage data, also send it */
358 KdpSendBuffer(MessageData
->Buffer
, MessageData
->Length
);
361 /* Finalize with a trailing byte */
362 KdpSendByte(PACKET_TRAILING_BYTE
);
364 /* Wait for acknowledge */
365 KdStatus
= KdReceivePacket(PACKET_TYPE_KD_ACKNOWLEDGE
,
371 /* Did we succeed? */
372 if (KdStatus
== KDP_PACKET_RECEIVED
)
374 /* Packet received, we can quit the loop */
375 CurrentPacketId
&= ~SYNC_PACKET_ID
;
378 else if (KdStatus
== KDP_PACKET_TIMEOUT
)
380 /* Timeout, decrement the retry count */
385 * If the retry count reaches zero, bail out
386 * for packet types allowed to timeout.
390 if (PacketType
== PACKET_TYPE_KD_DEBUG_IO
)
396 // else (KdStatus == KDP_PACKET_RESEND) /* Resend the packet */
398 /* Packet timed out, send it again */
399 KDDBGPRINT("KdSendPacket got KdStatus 0x%x\n", KdStatus
);