Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

872 lines
23 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. kdcomio.c
  5. Abstract:
  6. This module implements the I/O comunications for the portable kernel
  7. debugger.
  8. Author:
  9. David N. Cutler 27-July-1990
  10. Revision History:
  11. --*/
  12. #include "kdcomp.h"
  13. ULONG
  14. KdpComputeChecksum (
  15. IN PUCHAR Buffer,
  16. IN ULONG Length
  17. );
  18. ULONG
  19. KdpReceiveString (
  20. OUT PCHAR Destination,
  21. IN ULONG Length
  22. );
  23. VOID
  24. KdpSendString (
  25. IN PCHAR Source,
  26. IN ULONG Length
  27. );
  28. VOID
  29. KdpSendControlPacket (
  30. IN USHORT PacketType,
  31. IN ULONG PacketId OPTIONAL
  32. );
  33. #ifdef ALLOC_PRAGMA
  34. #pragma alloc_text(PAGEKD, KdpComputeChecksum)
  35. #pragma alloc_text(PAGEKD, KdCompReceivePacketLeader)
  36. #pragma alloc_text(PAGEKD, KdpReceiveString)
  37. #pragma alloc_text(PAGEKD, KdpSendString)
  38. #pragma alloc_text(PAGEKD, KdpSendControlPacket)
  39. #pragma alloc_text(PAGEKD, KdReceivePacket)
  40. #pragma alloc_text(PAGEKD, KdSendPacket)
  41. #endif
  42. ULONG KdCompPacketIdExpected = 0;
  43. ULONG KdCompNextPacketIdToSend = 0;
  44. //
  45. // KdpRetryCount controls the number of retries before we give
  46. // up and assume kernel debugger is not present.
  47. // KdpNumberRetries is the number of retries left. Initially,
  48. // it is set to 5 such that booting NT without debugger won't be
  49. // delayed to long.
  50. //
  51. ULONG KdCompNumberRetries = 5;
  52. ULONG KdCompRetryCount = 5;
  53. ULONG
  54. KdpComputeChecksum (
  55. IN PUCHAR Buffer,
  56. IN ULONG Length
  57. )
  58. /*++
  59. Routine Description:
  60. This routine computes the checksum for the string passed in.
  61. Arguments:
  62. Buffer - Supplies a pointer to the string.
  63. Length - Supplies the length of the string.
  64. Return Value:
  65. A ULONG is return as the checksum for the input string.
  66. --*/
  67. {
  68. ULONG Checksum = 0;
  69. while (Length > 0) {
  70. Checksum = Checksum + (ULONG)*Buffer++;
  71. Length--;
  72. }
  73. return Checksum;
  74. }
  75. USHORT
  76. KdCompReceivePacketLeader (
  77. IN ULONG PacketType,
  78. OUT PULONG PacketLeader,
  79. IN OUT PKD_CONTEXT KdContext
  80. )
  81. /*++
  82. Routine Description:
  83. This routine waits for a packet header leader.
  84. Arguments:
  85. PacketType - supplies the type of packet we are expecting.
  86. PacketLeader - supplies a pointer to a ulong variable to receive
  87. packet leader bytes.
  88. Return Value:
  89. KDP_PACKET_RESEND - if resend is required.
  90. KDP_PAKCET_TIMEOUT - if timeout.
  91. KDP_PACKET_RECEIVED - if packet received.
  92. --*/
  93. {
  94. UCHAR Input, PreviousByte = 0;
  95. ULONG PacketId = 0;
  96. ULONG Index;
  97. ULONG ReturnCode;
  98. BOOLEAN BreakinDetected = FALSE;
  99. //
  100. // NOTE - With all the interrupts being off, it is very hard
  101. // to implement the actual timeout code. (Maybe, by reading the CMOS.)
  102. // Here we use a loop count to wait about 3 seconds. The CpGetByte
  103. // will return with error code = CP_GET_NODATA if it cannot find data
  104. // byte within 1 second. Kernel debugger's timeout period is 5 seconds.
  105. //
  106. Index = 0;
  107. do {
  108. ReturnCode = KdCompGetByte(&Input);
  109. if (ReturnCode == CP_GET_NODATA) {
  110. if (BreakinDetected) {
  111. KdContext->KdpControlCPending = TRUE;
  112. return KDP_PACKET_RESEND;
  113. } else {
  114. return KDP_PACKET_TIMEOUT;
  115. }
  116. } else if (ReturnCode == CP_GET_ERROR) {
  117. Index = 0;
  118. continue;
  119. } else { // if (ReturnCode == CP_GET_SUCCESS)
  120. if ( Input == PACKET_LEADER_BYTE ||
  121. Input == CONTROL_PACKET_LEADER_BYTE ) {
  122. if ( Index == 0 ) {
  123. PreviousByte = Input;
  124. Index++;
  125. } else if (Input == PreviousByte ) {
  126. Index++;
  127. } else {
  128. PreviousByte = Input;
  129. Index = 1;
  130. }
  131. } else {
  132. //
  133. // If we detect breakin character, we need to verify it
  134. // validity. (It is possible that we missed a packet leader
  135. // and the breakin character is simply a data byte in the
  136. // packet.)
  137. // Since kernel debugger send out breakin character ONLY
  138. // when it is waiting for State Change packet. The breakin
  139. // character should not be followed by any other character
  140. // except packet leader byte.
  141. //
  142. if ( Input == BREAKIN_PACKET_BYTE ) {
  143. BreakinDetected = TRUE;
  144. } else {
  145. //
  146. // The following statement is ABSOLUTELY necessary.
  147. //
  148. BreakinDetected = FALSE;
  149. }
  150. Index = 0;
  151. }
  152. }
  153. } while ( Index < 4 );
  154. if (BreakinDetected) {
  155. KdContext->KdpControlCPending = TRUE;
  156. }
  157. //
  158. // return the packet leader and FALSE to indicate no resend is needed.
  159. //
  160. if ( Input == PACKET_LEADER_BYTE ) {
  161. *PacketLeader = PACKET_LEADER;
  162. } else {
  163. *PacketLeader = CONTROL_PACKET_LEADER;
  164. }
  165. *KdDebuggerNotPresent = FALSE;
  166. SharedUserData->KdDebuggerEnabled |= 0x00000002;
  167. return KDP_PACKET_RECEIVED;
  168. }
  169. ULONG
  170. KdpReceiveString (
  171. OUT PCHAR Destination,
  172. IN ULONG Length
  173. )
  174. /*++
  175. Routine Description:
  176. This routine reads a string from the kernel debugger port.
  177. Arguments:
  178. Destination - Supplies a pointer to the input string.
  179. Length - Supplies the length of the string to be read.
  180. Return Value:
  181. CP_GET_SUCCESS is returned if string is successfully read from the
  182. kernel debugger line.
  183. CP_GET_ERROR is returned if error encountered during reading.
  184. CP_GET_NODATA is returned if timeout.
  185. --*/
  186. {
  187. UCHAR Input;
  188. ULONG ReturnCode;
  189. //
  190. // Read bytes until either a error is encountered or the entire string
  191. // has been read.
  192. //
  193. while (Length > 0) {
  194. ReturnCode = KdCompGetByte(&Input);
  195. if (ReturnCode != CP_GET_SUCCESS) {
  196. return ReturnCode;
  197. } else {
  198. *Destination++ = Input;
  199. Length -= 1;
  200. }
  201. }
  202. return CP_GET_SUCCESS;
  203. }
  204. VOID
  205. KdpSendString (
  206. IN PCHAR Source,
  207. IN ULONG Length
  208. )
  209. /*++
  210. Routine Description:
  211. This routine writes a string to the kernel debugger port.
  212. Arguments:
  213. Source - Supplies a pointer to the output string.
  214. Length - Supplies the length of the string to be written.
  215. Return Value:
  216. None.
  217. --*/
  218. {
  219. UCHAR Output;
  220. //
  221. // Write bytes to the kernel debugger port.
  222. //
  223. while (Length > 0) {
  224. Output = *Source++;
  225. KdCompPutByte(Output);
  226. Length -= 1;
  227. }
  228. return;
  229. }
  230. VOID
  231. KdpSendControlPacket (
  232. IN USHORT PacketType,
  233. IN ULONG PacketId OPTIONAL
  234. )
  235. /*++
  236. Routine Description:
  237. This routine sends a control packet to the host machine that is running the
  238. kernel debugger and waits for an ACK.
  239. Arguments:
  240. PacketType - Supplies the type of packet to send.
  241. PacketId - Supplies packet id, optionally.
  242. Return Value:
  243. None.
  244. --*/
  245. {
  246. KD_PACKET PacketHeader;
  247. //
  248. // Initialize and send the packet header.
  249. //
  250. PacketHeader.PacketLeader = CONTROL_PACKET_LEADER;
  251. if (ARGUMENT_PRESENT( (PVOID)(ULONG_PTR) PacketId )) {
  252. PacketHeader.PacketId = PacketId;
  253. }
  254. PacketHeader.ByteCount = 0;
  255. PacketHeader.Checksum = 0;
  256. PacketHeader.PacketType = PacketType;
  257. KdpSendString((PCHAR)&PacketHeader, sizeof(KD_PACKET));
  258. return;
  259. }
  260. ULONG
  261. KdReceivePacket (
  262. IN ULONG PacketType,
  263. OUT PSTRING MessageHeader,
  264. OUT PSTRING MessageData,
  265. OUT PULONG DataLength,
  266. IN OUT PKD_CONTEXT KdContext
  267. )
  268. /*++
  269. Routine Description:
  270. This routine receives a packet from the host machine that is running
  271. the kernel debugger UI. This routine is ALWAYS called after packet being
  272. sent by caller. It first waits for ACK packet for the packet sent and
  273. then waits for the packet desired.
  274. N.B. If caller is KdPrintString, the parameter PacketType is
  275. PACKET_TYPE_KD_ACKNOWLEDGE. In this case, this routine will return
  276. right after the ack packet is received.
  277. Arguments:
  278. PacketType - Supplies the type of packet that is excepted.
  279. MessageHeader - Supplies a pointer to a string descriptor for the input
  280. message.
  281. MessageData - Supplies a pointer to a string descriptor for the input data.
  282. DataLength - Supplies pointer to ULONG to receive length of recv. data.
  283. KdContext - Supplies a pointer to the kernel debugger context.
  284. Return Value:
  285. KDP_PACKET_RESEND - if resend is required.
  286. KDP_PAKCET_TIMEOUT - if timeout.
  287. KDP_PACKET_RECEIVED - if packet received.
  288. --*/
  289. {
  290. UCHAR Input;
  291. ULONG MessageLength;
  292. KD_PACKET PacketHeader;
  293. ULONG ReturnCode;
  294. ULONG Checksum;
  295. ULONG Status;
  296. //
  297. // Just check for breakin packet and return
  298. //
  299. if (PacketType == PACKET_TYPE_KD_POLL_BREAKIN) {
  300. Status = KdCompPollByte(&Input);
  301. return ((Status == CP_GET_SUCCESS) && (Input == BREAKIN_PACKET_BYTE)) ?
  302. KDP_PACKET_RECEIVED: KDP_PACKET_TIMEOUT;
  303. }
  304. WaitForPacketLeader:
  305. //
  306. // Read Packet Leader
  307. //
  308. ReturnCode = KdCompReceivePacketLeader(PacketType, &PacketHeader.PacketLeader, KdContext);
  309. //
  310. // If we can successfully read packet leader, it has high possibility that
  311. // kernel debugger is alive. So reset count.
  312. //
  313. if (ReturnCode != KDP_PACKET_TIMEOUT) {
  314. KdCompNumberRetries = KdCompRetryCount;
  315. }
  316. if (ReturnCode != KDP_PACKET_RECEIVED) {
  317. return ReturnCode;
  318. }
  319. //
  320. // Read packet type.
  321. //
  322. ReturnCode = KdpReceiveString((PCHAR)&PacketHeader.PacketType,
  323. sizeof(PacketHeader.PacketType));
  324. if (ReturnCode == CP_GET_NODATA) {
  325. return KDP_PACKET_TIMEOUT;
  326. } else if (ReturnCode == CP_GET_ERROR) {
  327. if (PacketHeader.PacketLeader == CONTROL_PACKET_LEADER) {
  328. //
  329. // If read error and it is for a control packet, simply
  330. // preptend that we have not seen this packet. Hopefully
  331. // we will receive the packet we desire which automatically acks
  332. // the packet we just sent.
  333. //
  334. goto WaitForPacketLeader;
  335. } else {
  336. //
  337. // if read error while reading data packet, we have to ask
  338. // kernel debugger to resend us the packet.
  339. //
  340. goto SendResendPacket;
  341. }
  342. }
  343. //
  344. // if the packet we received is a resend request, we return true and
  345. // let caller resend the packet.
  346. //
  347. if ( PacketHeader.PacketLeader == CONTROL_PACKET_LEADER &&
  348. PacketHeader.PacketType == PACKET_TYPE_KD_RESEND ) {
  349. return KDP_PACKET_RESEND;
  350. }
  351. //
  352. // Read data length.
  353. //
  354. ReturnCode = KdpReceiveString((PCHAR)&PacketHeader.ByteCount,
  355. sizeof(PacketHeader.ByteCount));
  356. if (ReturnCode == CP_GET_NODATA) {
  357. return KDP_PACKET_TIMEOUT;
  358. } else if (ReturnCode == CP_GET_ERROR) {
  359. if (PacketHeader.PacketLeader == CONTROL_PACKET_LEADER) {
  360. goto WaitForPacketLeader;
  361. } else {
  362. goto SendResendPacket;
  363. }
  364. }
  365. //
  366. // Read Packet Id.
  367. //
  368. ReturnCode = KdpReceiveString((PCHAR)&PacketHeader.PacketId,
  369. sizeof(PacketHeader.PacketId));
  370. if (ReturnCode == CP_GET_NODATA) {
  371. return KDP_PACKET_TIMEOUT;
  372. } else if (ReturnCode == CP_GET_ERROR) {
  373. if (PacketHeader.PacketLeader == CONTROL_PACKET_LEADER) {
  374. goto WaitForPacketLeader;
  375. } else {
  376. goto SendResendPacket;
  377. }
  378. }
  379. //
  380. // Read packet checksum.
  381. //
  382. ReturnCode = KdpReceiveString((PCHAR)&PacketHeader.Checksum,
  383. sizeof(PacketHeader.Checksum));
  384. if (ReturnCode == CP_GET_NODATA) {
  385. return KDP_PACKET_TIMEOUT;
  386. } else if (ReturnCode == CP_GET_ERROR) {
  387. if (PacketHeader.PacketLeader == CONTROL_PACKET_LEADER) {
  388. goto WaitForPacketLeader;
  389. } else {
  390. goto SendResendPacket;
  391. }
  392. }
  393. //
  394. // A complete packet header is received. Check its validity and
  395. // perform appropriate action depending on packet type.
  396. //
  397. if (PacketHeader.PacketLeader == CONTROL_PACKET_LEADER ) {
  398. if (PacketHeader.PacketType == PACKET_TYPE_KD_ACKNOWLEDGE ) {
  399. //
  400. // If we received an expected ACK packet and we are not
  401. // waiting for any new packet, update outgoing packet id
  402. // and return. If we are NOT waiting for ACK packet
  403. // we will keep on waiting. If the ACK packet
  404. // is not for the packet we send, ignore it and keep on waiting.
  405. //
  406. if (PacketHeader.PacketId !=
  407. (KdCompNextPacketIdToSend & ~SYNC_PACKET_ID)) {
  408. goto WaitForPacketLeader;
  409. } else if (PacketType == PACKET_TYPE_KD_ACKNOWLEDGE) {
  410. KdCompNextPacketIdToSend ^= 1;
  411. return KDP_PACKET_RECEIVED;
  412. } else {
  413. goto WaitForPacketLeader;
  414. }
  415. } else if (PacketHeader.PacketType == PACKET_TYPE_KD_RESET) {
  416. //
  417. // if we received Reset packet, reset the packet control variables
  418. // and resend earlier packet.
  419. //
  420. KdCompNextPacketIdToSend = INITIAL_PACKET_ID;
  421. KdCompPacketIdExpected = INITIAL_PACKET_ID;
  422. KdpSendControlPacket(PACKET_TYPE_KD_RESET, 0L);
  423. return KDP_PACKET_RESEND;
  424. } else if (PacketHeader.PacketType == PACKET_TYPE_KD_RESEND) {
  425. return KDP_PACKET_RESEND;
  426. } else {
  427. //
  428. // Invalid packet header, ignore it.
  429. //
  430. goto WaitForPacketLeader;
  431. }
  432. //
  433. // The packet header is for data packet (not control packet).
  434. //
  435. } else if (PacketType == PACKET_TYPE_KD_ACKNOWLEDGE) {
  436. //
  437. // if we are waiting for ACK packet ONLY
  438. // and we receive a data packet header, check if the packet id
  439. // is what we expected. If yes, assume the acknowledge is lost (but
  440. // sent), ask sender to resend and return with PACKET_RECEIVED.
  441. //
  442. if (PacketHeader.PacketId == KdCompPacketIdExpected) {
  443. KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0L);
  444. KdCompNextPacketIdToSend ^= 1;
  445. return KDP_PACKET_RECEIVED;
  446. } else {
  447. KdpSendControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE,
  448. PacketHeader.PacketId
  449. );
  450. goto WaitForPacketLeader;
  451. }
  452. }
  453. //
  454. // we are waiting for data packet and we received the packet header
  455. // for data packet. Perform the following checkings to make sure
  456. // it is the packet we are waiting for.
  457. //
  458. //
  459. // Check ByteCount received is valid
  460. //
  461. MessageLength = MessageHeader->MaximumLength;
  462. if ((PacketHeader.ByteCount > (USHORT)PACKET_MAX_SIZE) ||
  463. (PacketHeader.ByteCount < (USHORT)MessageLength)) {
  464. goto SendResendPacket;
  465. }
  466. *DataLength = PacketHeader.ByteCount - MessageLength;
  467. //
  468. // Read the message header.
  469. //
  470. ReturnCode = KdpReceiveString(MessageHeader->Buffer, MessageLength);
  471. if (ReturnCode != CP_GET_SUCCESS) {
  472. goto SendResendPacket;
  473. }
  474. MessageHeader->Length = (USHORT)MessageLength;
  475. //
  476. // Read the message data.
  477. //
  478. ReturnCode = KdpReceiveString(MessageData->Buffer, *DataLength);
  479. if (ReturnCode != CP_GET_SUCCESS) {
  480. goto SendResendPacket;
  481. }
  482. MessageData->Length = (USHORT)*DataLength;
  483. //
  484. // Read packet trailing byte
  485. //
  486. ReturnCode = KdCompGetByte(&Input);
  487. if (ReturnCode != CP_GET_SUCCESS || Input != PACKET_TRAILING_BYTE) {
  488. goto SendResendPacket;
  489. }
  490. //
  491. // Check PacketType is what we are waiting for.
  492. //
  493. if (PacketType != PacketHeader.PacketType) {
  494. KdpSendControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE,
  495. PacketHeader.PacketId
  496. );
  497. goto WaitForPacketLeader;
  498. }
  499. //
  500. // Check PacketId is valid.
  501. //
  502. if (PacketHeader.PacketId == INITIAL_PACKET_ID ||
  503. PacketHeader.PacketId == (INITIAL_PACKET_ID ^ 1)) {
  504. if (PacketHeader.PacketId != KdCompPacketIdExpected) {
  505. KdpSendControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE,
  506. PacketHeader.PacketId
  507. );
  508. goto WaitForPacketLeader;
  509. }
  510. } else {
  511. goto SendResendPacket;
  512. }
  513. //
  514. // Check checksum is valid.
  515. //
  516. Checksum = KdpComputeChecksum(
  517. MessageHeader->Buffer,
  518. MessageHeader->Length
  519. );
  520. Checksum += KdpComputeChecksum(
  521. MessageData->Buffer,
  522. MessageData->Length
  523. );
  524. if (Checksum != PacketHeader.Checksum) {
  525. goto SendResendPacket;
  526. }
  527. //
  528. // Send Acknowledge byte and the Id of the packet received.
  529. // Then, update the ExpectId for next incoming packet.
  530. //
  531. KdpSendControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE,
  532. PacketHeader.PacketId
  533. );
  534. //
  535. // We have successfully received the packet so update the
  536. // packet control variables and return sucess.
  537. //
  538. KdCompPacketIdExpected ^= 1;
  539. return KDP_PACKET_RECEIVED;
  540. SendResendPacket:
  541. KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0L);
  542. goto WaitForPacketLeader;
  543. }
  544. VOID
  545. KdSendPacket (
  546. IN ULONG PacketType,
  547. IN PSTRING MessageHeader,
  548. IN PSTRING MessageData OPTIONAL,
  549. IN OUT PKD_CONTEXT KdContext
  550. )
  551. /*++
  552. Routine Description:
  553. This routine sends a packet to the host machine that is running the
  554. kernel debugger and waits for an ACK.
  555. Arguments:
  556. PacketType - Supplies the type of packet to send.
  557. MessageHeader - Supplies a pointer to a string descriptor that describes
  558. the message information.
  559. MessageData - Supplies a pointer to a string descriptor that describes
  560. the optional message data.
  561. KdContext - Supplies a pointer to the kernel debugger context.
  562. Return Value:
  563. None.
  564. --*/
  565. {
  566. KD_PACKET PacketHeader;
  567. ULONG MessageDataLength;
  568. ULONG ReturnCode;
  569. PDBGKD_DEBUG_IO DebugIo;
  570. PDBGKD_WAIT_STATE_CHANGE64 StateChange;
  571. if ( ARGUMENT_PRESENT(MessageData) ) {
  572. MessageDataLength = MessageData->Length;
  573. PacketHeader.Checksum = KdpComputeChecksum(
  574. MessageData->Buffer,
  575. MessageData->Length
  576. );
  577. } else {
  578. MessageDataLength = 0;
  579. PacketHeader.Checksum = 0;
  580. }
  581. PacketHeader.Checksum += KdpComputeChecksum (
  582. MessageHeader->Buffer,
  583. MessageHeader->Length
  584. );
  585. //
  586. // Initialize and send the packet header.
  587. //
  588. PacketHeader.PacketLeader = PACKET_LEADER;
  589. PacketHeader.ByteCount = (USHORT)(MessageHeader->Length + MessageDataLength);
  590. PacketHeader.PacketType = (USHORT)PacketType;
  591. KdCompNumberRetries = KdCompRetryCount;
  592. do {
  593. if (KdCompNumberRetries == 0) {
  594. //
  595. // If the packet is not for reporting exception, we give up
  596. // and declare debugger not present.
  597. //
  598. if (PacketType == PACKET_TYPE_KD_DEBUG_IO) {
  599. DebugIo = (PDBGKD_DEBUG_IO)MessageHeader->Buffer;
  600. if (DebugIo->ApiNumber == DbgKdPrintStringApi) {
  601. *KdDebuggerNotPresent = TRUE;
  602. SharedUserData->KdDebuggerEnabled &= ~0x00000002;
  603. KdCompNextPacketIdToSend = INITIAL_PACKET_ID | SYNC_PACKET_ID;
  604. KdCompPacketIdExpected = INITIAL_PACKET_ID;
  605. return;
  606. }
  607. } else if (PacketType == PACKET_TYPE_KD_STATE_CHANGE64) {
  608. StateChange = (PDBGKD_WAIT_STATE_CHANGE64)MessageHeader->Buffer;
  609. if (StateChange->NewState == DbgKdLoadSymbolsStateChange) {
  610. *KdDebuggerNotPresent = TRUE;
  611. SharedUserData->KdDebuggerEnabled &= ~0x00000002;
  612. KdCompNextPacketIdToSend = INITIAL_PACKET_ID | SYNC_PACKET_ID;
  613. KdCompPacketIdExpected = INITIAL_PACKET_ID;
  614. return;
  615. }
  616. } else if (PacketType == PACKET_TYPE_KD_FILE_IO) {
  617. PDBGKD_FILE_IO FileIo;
  618. FileIo = (PDBGKD_FILE_IO)MessageHeader->Buffer;
  619. if (FileIo->ApiNumber == DbgKdCreateFileApi) {
  620. *KdDebuggerNotPresent = TRUE;
  621. SharedUserData->KdDebuggerEnabled &= ~0x00000002;
  622. KdCompNextPacketIdToSend = INITIAL_PACKET_ID | SYNC_PACKET_ID;
  623. KdCompPacketIdExpected = INITIAL_PACKET_ID;
  624. return;
  625. }
  626. }
  627. }
  628. //
  629. // Setting PacketId has to be in the do loop in case Packet Id was
  630. // reset.
  631. //
  632. PacketHeader.PacketId = KdCompNextPacketIdToSend;
  633. KdpSendString((PCHAR)&PacketHeader, sizeof(KD_PACKET));
  634. //
  635. // Output message header.
  636. //
  637. KdpSendString(MessageHeader->Buffer, MessageHeader->Length);
  638. //
  639. // Output message data.
  640. //
  641. if ( MessageDataLength ) {
  642. KdpSendString(MessageData->Buffer, MessageData->Length);
  643. }
  644. //
  645. // Output a packet trailing byte
  646. //
  647. KdCompPutByte(PACKET_TRAILING_BYTE);
  648. //
  649. // Wait for the Ack Packet
  650. //
  651. ReturnCode = KdReceivePacket(
  652. PACKET_TYPE_KD_ACKNOWLEDGE,
  653. NULL,
  654. NULL,
  655. NULL,
  656. KdContext
  657. );
  658. if (ReturnCode == KDP_PACKET_TIMEOUT) {
  659. KdCompNumberRetries--;
  660. }
  661. } while (ReturnCode != KDP_PACKET_RECEIVED);
  662. //
  663. // Reset Sync bit in packet id. The packet we sent may have Sync bit set
  664. //
  665. KdCompNextPacketIdToSend &= ~SYNC_PACKET_ID;
  666. //
  667. // Since we are able to talk to debugger, the retrycount is set to
  668. // maximum value.
  669. //
  670. KdCompRetryCount = KdContext->KdpDefaultRetries;
  671. }