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)
11 /* GLOBALS ********************************************************************/
13 PFNDBGPRNT KdpDbgPrint
= NULL
;
14 ULONG CurrentPacketId
= INITIAL_PACKET_ID
| SYNC_PACKET_ID
;
15 ULONG RemotePacketId
= INITIAL_PACKET_ID
;
18 /* PRIVATE FUNCTIONS **********************************************************/
20 /******************************************************************************
21 * \name KdpCalculateChecksum
22 * \brief Calculates the checksum for the packet data.
23 * \param Buffer Pointer to the packet data.
24 * \param Length Length of data in bytes.
25 * \return The calculated checksum.
26 * \sa http://www.vista-xp.co.uk/forums/technical-reference-library/2540-basics-debugging.html
34 PUCHAR ByteBuffer
= Buffer
;
39 Checksum
+= (ULONG
)*ByteBuffer
++;
48 IN ULONG PacketId OPTIONAL
)
52 Packet
.PacketLeader
= CONTROL_PACKET_LEADER
;
53 Packet
.PacketId
= PacketId
;
56 Packet
.PacketType
= PacketType
;
58 KdpSendBuffer(&Packet
, sizeof(KD_PACKET
));
62 /* PUBLIC FUNCTIONS ***********************************************************/
64 /******************************************************************************
65 * \name KdReceivePacket
66 * \brief Receive a packet from the KD port.
67 * \param [in] PacketType Describes the type of the packet to receive.
68 * This can be one of the PACKET_TYPE_ constants.
69 * \param [out] MessageHeader Pointer to a STRING structure for the header.
70 * \param [out] MessageData Pointer to a STRING structure for the data.
71 * \return KdPacketReceived if successful, KdPacketTimedOut if the receive
72 * timed out, KdPacketNeedsResend to signal that the last packet needs
74 * \note If PacketType is PACKET_TYPE_KD_POLL_BREAKIN, the function doesn't
75 * wait for any data, but returns KdPacketTimedOut instantly if no breakin
76 * packet byte is received.
77 * \sa http://www.nynaeve.net/?p=169
83 OUT PSTRING MessageHeader
,
84 OUT PSTRING MessageData
,
85 OUT PULONG DataLength
,
86 IN OUT PKD_CONTEXT KdContext
)
93 /* Special handling for breakin packet */
94 if(PacketType
== PACKET_TYPE_KD_POLL_BREAKIN
)
96 return KdpPollBreakIn();
101 /* Step 1 - Read PacketLeader */
102 KdStatus
= KdpReceivePacketLeader(&Packet
.PacketLeader
);
103 if (KdStatus
!= KDP_PACKET_RECEIVED
)
105 /* Check if we got a breakin */
106 if (KdStatus
== KDP_PACKET_RESEND
)
108 KdContext
->KdpControlCPending
= TRUE
;
113 /* Step 2 - Read PacketType */
114 KdStatus
= KdpReceiveBuffer(&Packet
.PacketType
, sizeof(USHORT
));
115 if (KdStatus
!= KDP_PACKET_RECEIVED
)
117 /* Didn't receive a PacketType. */
121 /* Check if we got a resend packet */
122 if (Packet
.PacketLeader
== CONTROL_PACKET_LEADER
&&
123 Packet
.PacketType
== PACKET_TYPE_KD_RESEND
)
125 return KDP_PACKET_RESEND
;
128 /* Step 3 - Read ByteCount */
129 KdStatus
= KdpReceiveBuffer(&Packet
.ByteCount
, sizeof(USHORT
));
130 if (KdStatus
!= KDP_PACKET_RECEIVED
)
132 /* Didn't receive ByteCount. */
136 /* Step 4 - Read PacketId */
137 KdStatus
= KdpReceiveBuffer(&Packet
.PacketId
, sizeof(ULONG
));
138 if (KdStatus
!= KDP_PACKET_RECEIVED
)
140 /* Didn't receive PacketId. */
145 if (Packet.PacketId != ExpectedPacketId)
152 /* Step 5 - Read Checksum */
153 KdStatus
= KdpReceiveBuffer(&Packet
.Checksum
, sizeof(ULONG
));
154 if (KdStatus
!= KDP_PACKET_RECEIVED
)
156 /* Didn't receive Checksum. */
160 /* Step 6 - Handle control packets */
161 if (Packet
.PacketLeader
== CONTROL_PACKET_LEADER
)
163 switch (Packet
.PacketType
)
165 case PACKET_TYPE_KD_ACKNOWLEDGE
:
166 /* Are we waiting for an ACK packet? */
167 if (PacketType
== PACKET_TYPE_KD_ACKNOWLEDGE
&&
168 Packet
.PacketId
== (CurrentPacketId
& ~SYNC_PACKET_ID
))
170 /* Remote acknowledges the last packet */
171 CurrentPacketId
^= 1;
172 return KDP_PACKET_RECEIVED
;
174 /* That's not what we were waiting for, start over. */
177 case PACKET_TYPE_KD_RESET
:
178 KDDBGPRINT("KdReceivePacket - got a reset packet\n");
179 KdpSendControlPacket(PACKET_TYPE_KD_RESET
, 0);
180 CurrentPacketId
= INITIAL_PACKET_ID
;
181 RemotePacketId
= INITIAL_PACKET_ID
;
184 case PACKET_TYPE_KD_RESEND
:
185 KDDBGPRINT("KdReceivePacket - got PACKET_TYPE_KD_RESEND\n");
186 /* Remote wants us to resend the last packet */
187 return KDP_PACKET_RESEND
;
190 KDDBGPRINT("KdReceivePacket - got unknown control packet\n");
191 return KDP_PACKET_RESEND
;
195 /* Did we wait for an ack packet? */
196 if (PacketType
== PACKET_TYPE_KD_ACKNOWLEDGE
)
198 /* We received something different */
199 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
200 CurrentPacketId
^= 1;
201 return KDP_PACKET_RECEIVED
;
204 /* Get size of the message header */
205 MessageHeader
->Length
= MessageHeader
->MaximumLength
;
207 /* Packet smaller than expected or too big? */
208 if (Packet
.ByteCount
< MessageHeader
->Length
||
209 Packet
.ByteCount
> PACKET_MAX_SIZE
)
211 KDDBGPRINT("KdReceivePacket - too few data (%d) for type %d\n",
212 Packet
.ByteCount
, MessageHeader
->Length
);
213 MessageHeader
->Length
= Packet
.ByteCount
;
214 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
218 //KDDBGPRINT("KdReceivePacket - got normal PacketType, Buffer = %p\n", MessageHeader->Buffer);
220 /* Receive the message header data */
221 KdStatus
= KdpReceiveBuffer(MessageHeader
->Buffer
,
222 MessageHeader
->Length
);
223 if (KdStatus
!= KDP_PACKET_RECEIVED
)
225 /* Didn't receive data. Packet needs to be resent. */
226 KDDBGPRINT("KdReceivePacket - Didn't receive message header data.\n");
227 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
231 //KDDBGPRINT("KdReceivePacket - got normal PacketType 3\n");
233 /* Calculate checksum for the header data */
234 Checksum
= KdpCalculateChecksum(MessageHeader
->Buffer
,
235 MessageHeader
->Length
);
237 /* Calculate the length of the message data */
238 *DataLength
= Packet
.ByteCount
- MessageHeader
->Length
;
240 /* Shall we receive messsage data? */
243 /* Set the length of the message data */
244 MessageData
->Length
= (USHORT
)*DataLength
;
246 /* Do we have data? */
247 if (MessageData
->Length
)
249 KDDBGPRINT("KdReceivePacket - got data\n");
251 /* Receive the message data */
252 KdStatus
= KdpReceiveBuffer(MessageData
->Buffer
,
253 MessageData
->Length
);
254 if (KdStatus
!= KDP_PACKET_RECEIVED
)
256 /* Didn't receive data. Start over. */
257 KDDBGPRINT("KdReceivePacket - Didn't receive message data.\n");
258 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
262 /* Add cheksum for message data */
263 Checksum
+= KdpCalculateChecksum(MessageData
->Buffer
,
264 MessageData
->Length
);
268 /* We must receive a PACKET_TRAILING_BYTE now */
269 KdStatus
= KdpReceiveBuffer(&Byte
, sizeof(UCHAR
));
270 if (KdStatus
!= KDP_PACKET_RECEIVED
|| Byte
!= PACKET_TRAILING_BYTE
)
272 KDDBGPRINT("KdReceivePacket - wrong trailing byte (0x%x), status 0x%x\n", Byte
, KdStatus
);
273 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
277 /* Compare checksum */
278 if (Packet
.Checksum
!= Checksum
)
280 KDDBGPRINT("KdReceivePacket - wrong cheksum, got %x, calculated %x\n",
281 Packet
.Checksum
, Checksum
);
282 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
286 /* Acknowledge the received packet */
287 KdpSendControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE
, Packet
.PacketId
);
289 /* Check if the received PacketId is ok */
290 if (Packet
.PacketId
!= RemotePacketId
)
292 /* Continue with next packet */
296 /* Did we get the right packet type? */
297 if (PacketType
== Packet
.PacketType
)
299 /* Yes, return success */
300 //KDDBGPRINT("KdReceivePacket - all ok\n");
302 return KDP_PACKET_RECEIVED
;
305 /* We received something different, ignore it. */
306 KDDBGPRINT("KdReceivePacket - wrong PacketType\n");
309 return KDP_PACKET_RECEIVED
;
316 IN PSTRING MessageHeader
,
317 IN PSTRING MessageData
,
318 IN OUT PKD_CONTEXT KdContext
)
324 /* Initialize a KD_PACKET */
325 Packet
.PacketLeader
= PACKET_LEADER
;
326 Packet
.PacketType
= (USHORT
)PacketType
;
327 Packet
.ByteCount
= MessageHeader
->Length
;
328 Packet
.Checksum
= KdpCalculateChecksum(MessageHeader
->Buffer
,
329 MessageHeader
->Length
);
331 /* If we have message data, add it to the packet */
334 Packet
.ByteCount
+= MessageData
->Length
;
335 Packet
.Checksum
+= KdpCalculateChecksum(MessageData
->Buffer
,
336 MessageData
->Length
);
339 Retries
= KdContext
->KdpDefaultRetries
;
343 /* Set the packet id */
344 Packet
.PacketId
= CurrentPacketId
;
346 /* Send the packet header to the KD port */
347 KdpSendBuffer(&Packet
, sizeof(KD_PACKET
));
349 /* Send the message header */
350 KdpSendBuffer(MessageHeader
->Buffer
, MessageHeader
->Length
);
352 /* If we have meesage data, also send it */
355 KdpSendBuffer(MessageData
->Buffer
, MessageData
->Length
);
358 /* Finalize with a trailing byte */
359 KdpSendByte(PACKET_TRAILING_BYTE
);
361 /* Wait for acknowledge */
362 KdStatus
= KdReceivePacket(PACKET_TYPE_KD_ACKNOWLEDGE
,
368 /* Did we succeed? */
369 if (KdStatus
== KDP_PACKET_RECEIVED
)
371 /* Packet received, we can quit the loop */
372 CurrentPacketId
&= ~SYNC_PACKET_ID
;
375 else if (KdStatus
== KDP_PACKET_TIMEOUT
)
377 /* Timeout, decrement the retry count */
382 * If the retry count reaches zero, bail out
383 * for packet types allowed to timeout.
387 if (PacketType
== PACKET_TYPE_KD_DEBUG_IO
)
393 // else (KdStatus == KDP_PACKET_RESEND) /* Resend the packet */
395 /* Packet timed out, send it again */
396 KDDBGPRINT("KdSendPacket got KdStatus 0x%x\n", KdStatus
);