test: kdcomio.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# kdcomio.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1990  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     kdcomio.c
    00008
    00009 Abstract:
    00010
    00011     This module implements the I/O comunications for the portable kernel
    00012     debugger.
    00013
    00014 Author:
    00015
    00016     David N. Cutler 27-July-1990
    00017
    00018 Revision History:
    00019
    00020 --*/
    00021
    00022 #include "kdp.h"
    00023
    00024 ULONG
    00025 KdpComputeChecksum (
    00026     IN PUCHAR Buffer,
    00027     IN ULONG Length
    00028     );
    00029
    00030 ULONG
    00031 KdpReceiveString (
    00032     OUT PCHAR Destination,
    00033     IN ULONG Length
    00034     );
    00035
    00036 VOID
    00037 KdpSendString (
    00038     IN PCHAR Source,
    00039     IN ULONG Length
    00040     );
    00041
    00042 VOID
    00043 KdpSendControlPacket (
    00044     IN USHORT PacketType,
    00045     IN ULONG PacketId OPTIONAL
    00046     );
    00047
    00048 #ifdef ALLOC_PRAGMA
    00049 #pragma alloc_text(PAGEKD, KdpComputeChecksum)
    00050 #pragma alloc_text(PAGEKD, KdpReceivePacketLeader)
    00051 #pragma alloc_text(PAGEKD, KdpReceiveString)
    00052 #pragma alloc_text(PAGEKD, KdpSendString)
    00053 #pragma alloc_text(PAGEKD, KdpSendControlPacket)
    00054 #pragma alloc_text(PAGEKD, KdpReceivePacket)
    00055 #pragma alloc_text(PAGEKD, KdpSendPacket)
    00056 #endif
    00057
    00058
    00059 ULONG
    00060 KdpComputeChecksum (
    00061     IN PUCHAR Buffer,
    00062     IN ULONG Length
    00063     )
    00064
    00065 /*++
    00066
    00067 Routine Description:
    00068
    00069     This routine computes the checksum for the string passed in.
    00070
    00071 Arguments:
    00072
    00073     Buffer - Supplies a pointer to the string.
    00074
    00075     Length - Supplies the length of the string.
    00076
    00077 Return Value:
    00078
    00079     A ULONG is return as the checksum for the input string.
    00080
    00081 --*/
    00082
    00083 {
    00084
    00085     ULONG Checksum = 0;
    00086
    00087     while (Length > 0) {
    00088         Checksum = Checksum + (ULONG)*Buffer++;
    00089         Length--;
    00090     }
    00091     return Checksum;
    00092 }
    00093
    00094 USHORT
    00095 KdpReceivePacketLeader (
    00096     IN ULONG PacketType,
    00097     OUT PULONG PacketLeader
    00098     )
    00099
    00100 /*++
    00101
    00102 Routine Description:
    00103
    00104     This routine waits for a packet header leader.
    00105
    00106 Arguments:
    00107
    00108     PacketType - supplies the type of packet we are expecting.
    00109
    00110     PacketLeader - supplies a pointer to a ulong variable to receive
    00111                    packet leader bytes.
    00112
    00113 Return Value:
    00114
    00115     KDP_PACKET_RESEND - if resend is required.
    00116     KDP_PAKCET_TIMEOUT - if timeout.
    00117     KDP_PACKET_RECEIVED - if packet received.
    00118
    00119 --*/
    00120
    00121 {
    00122
    00123     UCHAR Input, PreviousByte = 0;
    00124     ULONG PacketId = 0;
    00125     ULONG Index;
    00126     ULONG ReturnCode;
    00127     BOOLEAN BreakinDetected = FALSE;
    00128
    00129     //
    00130     // NOTE - With all the interrupts being off, it is very hard
    00131     // to implement the actual timeout code. (Maybe, by reading the CMOS.)
    00132     // Here we use a loop count to wait about 3 seconds.  The CpGetByte
    00133     // will return with error code = CP_GET_NODATA if it cannot find data
    00134     // byte within 1 second. Kernel debugger's timeout period is 5 seconds.
    00135     //
    00136
    00137     Index = 0;
    00138     do {
    00139         ReturnCode = KdPortGetByte(&Input);
    00140         if (ReturnCode == CP_GET_NODATA) {
    00141             if (BreakinDetected) {
    00142                 KdpControlCPending = TRUE;
    00143                 return KDP_PACKET_RESEND;
    00144             } else {
    00145                 return KDP_PACKET_TIMEOUT;
    00146             }
    00147         } else if (ReturnCode == CP_GET_ERROR) {
    00148             Index = 0;
    00149             continue;
    00150         } else {                    // if (ReturnCode == CP_GET_SUCCESS)
    00151             if ( Input == PACKET_LEADER_BYTE ||
    00152                  Input == CONTROL_PACKET_LEADER_BYTE ) {
    00153                 if ( Index == 0 ) {
    00154                     PreviousByte = Input;
    00155                     Index++;
    00156                 } else if (Input == PreviousByte ) {
    00157                     Index++;
    00158                 } else {
    00159                     PreviousByte = Input;
    00160                     Index = 1;
    00161                 }
    00162             } else {
    00163
    00164                 //
    00165                 // If we detect breakin character, we need to verify it
    00166                 // validity.  (It is possible that we missed a packet leader
    00167                 // and the breakin character is simply a data byte in the
    00168                 // packet.)
    00169                 // Since kernel debugger send out breakin character ONLY
    00170                 // when it is waiting for State Change packet.  The breakin
    00171                 // character should not be followed by any other character
    00172                 // except packet leader byte.
    00173                 //
    00174
    00175                 if ( Input == BREAKIN_PACKET_BYTE ) {
    00176                     BreakinDetected = TRUE;
    00177                 } else {
    00178
    00179                     //
    00180                     // The following statement is ABSOLUTELY necessary.
    00181                     //
    00182
    00183                     BreakinDetected = FALSE;
    00184                 }
    00185                 Index = 0;
    00186             }
    00187         }
    00188     } while ( Index < 4 );
    00189
    00190     if (BreakinDetected) {
    00191         KdpControlCPending = TRUE;
    00192     }
    00193
    00194     //
    00195     // return the packet leader and FALSE to indicate no resend is needed.
    00196     //
    00197
    00198     if ( Input == PACKET_LEADER_BYTE ) {
    00199         *PacketLeader = PACKET_LEADER;
    00200     } else {
    00201         *PacketLeader = CONTROL_PACKET_LEADER;
    00202     }
    00203
    00204     KdDebuggerNotPresent = FALSE;
    00205     return KDP_PACKET_RECEIVED;
    00206 }
    00207
    00208 ULONG
    00209 KdpReceiveString (
    00210     OUT PCHAR Destination,
    00211     IN ULONG Length
    00212     )
    00213
    00214 /*++
    00215
    00216 Routine Description:
    00217
    00218     This routine reads a string from the kernel debugger port.
    00219
    00220 Arguments:
    00221
    00222     Destination - Supplies a pointer to the input string.
    00223
    00224     Length - Supplies the length of the string to be read.
    00225
    00226 Return Value:
    00227
    00228     CP_GET_SUCCESS is returned if string is successfully read from the
    00229         kernel debugger line.
    00230     CP_GET_ERROR is returned if error encountered during reading.
    00231     CP_GET_NODATA is returned if timeout.
    00232
    00233 --*/
    00234
    00235 {
    00236
    00237     UCHAR Input;
    00238     ULONG ReturnCode;
    00239
    00240     //
    00241     // Read bytes until either a error is encountered or the entire string
    00242     // has been read.
    00243     //
    00244     while (Length > 0) {
    00245         ReturnCode = KdPortGetByte(&Input);
    00246         if (ReturnCode != CP_GET_SUCCESS) {
    00247             return ReturnCode;
    00248         } else {
    00249             *Destination++ = Input;
    00250             Length -= 1;
    00251         }
    00252     }
    00253     return CP_GET_SUCCESS;
    00254 }
    00255
    00256 VOID
    00257 KdpSendString (
    00258     IN PCHAR Source,
    00259     IN ULONG Length
    00260     )
    00261
    00262 /*++
    00263
    00264 Routine Description:
    00265
    00266     This routine writes a string to the kernel debugger port.
    00267
    00268 Arguments:
    00269
    00270     Source - Supplies a pointer to the output string.
    00271
    00272     Length - Supplies the length of the string to be written.
    00273
    00274 Return Value:
    00275
    00276     None.
    00277
    00278 --*/
    00279
    00280 {
    00281
    00282     UCHAR Output;
    00283
    00284     //
    00285     // Write bytes to the kernel debugger port.
    00286     //
    00287
    00288     while (Length > 0) {
    00289         Output = *Source++;
    00290         KdPortPutByte(Output);
    00291         Length -= 1;
    00292     }
    00293     return;
    00294 }
    00295
    00296 VOID
    00297 KdpSendControlPacket (
    00298     IN USHORT PacketType,
    00299     IN ULONG PacketId OPTIONAL
    00300     )
    00301
    00302 /*++
    00303
    00304 Routine Description:
    00305
    00306     This routine sends a control packet to the host machine that is running the
    00307     kernel debugger and waits for an ACK.
    00308
    00309 Arguments:
    00310
    00311     PacketType - Supplies the type of packet to send.
    00312
    00313     PacketId - Supplies packet id, optionally.
    00314
    00315 Return Value:
    00316
    00317     None.
    00318
    00319 --*/
    00320
    00321 {
    00322
    00323     KD_PACKET PacketHeader;
    00324
    00325     //
    00326     // Initialize and send the packet header.
    00327     //
    00328
    00329     PacketHeader.PacketLeader = CONTROL_PACKET_LEADER;
    00330     if (ARGUMENT_PRESENT(PacketId)) {
    00331         PacketHeader.PacketId = PacketId;
    00332     }
    00333     PacketHeader.ByteCount = 0;
    00334     PacketHeader.Checksum = 0;
    00335     PacketHeader.PacketType = PacketType;
    00336     KdpSendString((PCHAR)&PacketHeader, sizeof(KD_PACKET));
    00337
    00338     return;
    00339 }
    00340
    00341 ULONG
    00342 KdpReceivePacket (
    00343     IN ULONG PacketType,
    00344     OUT PSTRING MessageHeader,
    00345     OUT PSTRING MessageData,
    00346     OUT PULONG DataLength
    00347     )
    00348
    00349 /*++
    00350
    00351 Routine Description:
    00352
    00353     This routine receives a packet from the host machine that is running
    00354     the kernel debugger UI.  This routine is ALWAYS called after packet being
    00355     sent by caller.  It first waits for ACK packet for the packet sent and
    00356     then waits for the packet desired.
    00357
    00358     N.B. If caller is KdPrintString, the parameter PacketType is
    00359        PACKET_TYPE_KD_ACKNOWLEDGE.  In this case, this routine will return
    00360        right after the ack packet is received.
    00361
    00362 Arguments:
    00363
    00364     PacketType - Supplies the type of packet that is excepted.
    00365
    00366     MessageHeader - Supplies a pointer to a string descriptor for the input
    00367         message.
    00368
    00369     MessageData - Supplies a pointer to a string descriptor for the input data.
    00370
    00371     DataLength - Supplies pointer to ULONG to receive length of recv. data.
    00372
    00373 Return Value:
    00374
    00375     KDP_PACKET_RESEND - if resend is required.
    00376     KDP_PAKCET_TIMEOUT - if timeout.
    00377     KDP_PACKET_RECEIVED - if packet received.
    00378
    00379 --*/
    00380
    00381 {
    00382
    00383     UCHAR Input;
    00384     ULONG MessageLength;
    00385     KD_PACKET PacketHeader;
    00386     ULONG ReturnCode;
    00387     ULONG Checksum;
    00388
    00389 WaitForPacketLeader:
    00390
    00391     //
    00392     // Read Packet Leader
    00393     //
    00394
    00395     ReturnCode = KdpReceivePacketLeader(PacketType, &PacketHeader.PacketLeader);
    00396
    00397     //
    00398     // If we can successfully read packet leader, it has high possibility that
    00399     // kernel debugger is alive.  So reset count.
    00400     //
    00401
    00402     if (ReturnCode != KDP_PACKET_TIMEOUT) {
    00403         KdpNumberRetries = KdpRetryCount;
    00404     }
    00405     if (ReturnCode != KDP_PACKET_RECEIVED) {
    00406         return ReturnCode;
    00407     }
    00408
    00409     //
    00410     // Read packet type.
    00411     //
    00412
    00413     ReturnCode = KdpReceiveString((PCHAR)&PacketHeader.PacketType,
    00414                                   sizeof(PacketHeader.PacketType));
    00415     if (ReturnCode == CP_GET_NODATA) {
    00416         return KDP_PACKET_TIMEOUT;
    00417     } else if (ReturnCode == CP_GET_ERROR) {
    00418         if (PacketHeader.PacketLeader == CONTROL_PACKET_LEADER) {
    00419
    00420             //
    00421             // If read error and it is for a control packet, simply
    00422             // preptend that we have not seen this packet.  Hopefully
    00423             // we will receive the packet we desire which automatically acks
    00424             // the packet we just sent.
    00425             //
    00426
    00427             goto WaitForPacketLeader;
    00428         } else {
    00429
    00430             //
    00431             // if read error while reading data packet, we have to ask
    00432             // kernel debugger to resend us the packet.
    00433             //
    00434
    00435             goto SendResendPacket;
    00436         }
    00437     }
    00438
    00439     //
    00440     // if the packet we received is a resend request, we return true and
    00441     // let caller resend the packet.
    00442     //
    00443
    00444     if ( PacketHeader.PacketLeader == CONTROL_PACKET_LEADER &&
    00445          PacketHeader.PacketType == PACKET_TYPE_KD_RESEND ) {
    00446         return KDP_PACKET_RESEND;
    00447     }
    00448
    00449     //
    00450     // Read data length.
    00451     //
    00452
    00453     ReturnCode = KdpReceiveString((PCHAR)&PacketHeader.ByteCount,
    00454                                   sizeof(PacketHeader.ByteCount));
    00455     if (ReturnCode == CP_GET_NODATA) {
    00456         return KDP_PACKET_TIMEOUT;
    00457     } else if (ReturnCode == CP_GET_ERROR) {
    00458         if (PacketHeader.PacketLeader == CONTROL_PACKET_LEADER) {
    00459             goto WaitForPacketLeader;
    00460         } else {
    00461             goto SendResendPacket;
    00462         }
    00463     }
    00464
    00465     //
    00466     // Read Packet Id.
    00467     //
    00468
    00469     ReturnCode = KdpReceiveString((PCHAR)&PacketHeader.PacketId,
    00470                                   sizeof(PacketHeader.PacketId));
    00471
    00472     if (ReturnCode == CP_GET_NODATA) {
    00473         return KDP_PACKET_TIMEOUT;
    00474     } else if (ReturnCode == CP_GET_ERROR) {
    00475         if (PacketHeader.PacketLeader == CONTROL_PACKET_LEADER) {
    00476             goto WaitForPacketLeader;
    00477         } else {
    00478             goto SendResendPacket;
    00479         }
    00480     }
    00481
    00482     //
    00483     // Read packet checksum.
    00484     //
    00485
    00486     ReturnCode = KdpReceiveString((PCHAR)&PacketHeader.Checksum,
    00487                                   sizeof(PacketHeader.Checksum));
    00488     if (ReturnCode == CP_GET_NODATA) {
    00489         return KDP_PACKET_TIMEOUT;
    00490     } else if (ReturnCode == CP_GET_ERROR) {
    00491         if (PacketHeader.PacketLeader == CONTROL_PACKET_LEADER) {
    00492             goto WaitForPacketLeader;
    00493         } else {
    00494             goto SendResendPacket;
    00495         }
    00496     }
    00497
    00498     //
    00499     // A complete packet header is received.  Check its validity and
    00500     // perform appropriate action depending on packet type.
    00501     //
    00502
    00503     if (PacketHeader.PacketLeader == CONTROL_PACKET_LEADER ) {
    00504         if (PacketHeader.PacketType == PACKET_TYPE_KD_ACKNOWLEDGE ) {
    00505
    00506             //
    00507             // If we received an expected ACK packet and we are not
    00508             // waiting for any new packet, update outgoing packet id
    00509             // and return.  If we are NOT waiting for ACK packet
    00510             // we will keep on waiting.  If the ACK packet
    00511             // is not for the packet we send, ignore it and keep on waiting.
    00512             //
    00513
    00514             if (PacketHeader.PacketId !=
    00515                 (KdpNextPacketIdToSend & ~SYNC_PACKET_ID))  {
    00516                 goto WaitForPacketLeader;
    00517             } else if (PacketType == PACKET_TYPE_KD_ACKNOWLEDGE) {
    00518                 KdpNextPacketIdToSend ^= 1;
    00519                 return KDP_PACKET_RECEIVED;
    00520             } else {
    00521                 goto WaitForPacketLeader;
    00522             }
    00523         } else if (PacketHeader.PacketType == PACKET_TYPE_KD_RESET) {
    00524
    00525             //
    00526             // if we received Reset packet, reset the packet control variables
    00527             // and resend earlier packet.
    00528             //
    00529
    00530             KdpNextPacketIdToSend = INITIAL_PACKET_ID;
    00531             KdpPacketIdExpected = INITIAL_PACKET_ID;
    00532             KdpSendControlPacket(PACKET_TYPE_KD_RESET, 0L);
    00533             return KDP_PACKET_RESEND;
    00534         } else if (PacketHeader.PacketType == PACKET_TYPE_KD_RESEND) {
    00535             return KDP_PACKET_RESEND;
    00536         } else {
    00537
    00538             //
    00539             // Invalid packet header, ignore it.
    00540             //
    00541
    00542             goto WaitForPacketLeader;
    00543         }
    00544
    00545     //
    00546     // The packet header is for data packet (not control packet).
    00547     //
    00548
    00549     } else if (PacketType == PACKET_TYPE_KD_ACKNOWLEDGE) {
    00550
    00551         //
    00552         // if we are waiting for ACK packet ONLY
    00553         // and we receive a data packet header, check if the packet id
    00554         // is what we expected.  If yes, assume the acknowledge is lost (but
    00555         // sent), ask sender to resend and return with PACKET_RECEIVED.
    00556         //
    00557
    00558         if (PacketHeader.PacketId == KdpPacketIdExpected) {
    00559             KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0L);
    00560             KdpNextPacketIdToSend ^= 1;
    00561             return KDP_PACKET_RECEIVED;
    00562         } else {
    00563             KdpSendControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE,
    00564                                  PacketHeader.PacketId
    00565                                  );
    00566             goto WaitForPacketLeader;
    00567         }
    00568     }
    00569
    00570     //
    00571     // we are waiting for data packet and we received the packet header
    00572     // for data packet. Perform the following checkings to make sure
    00573     // it is the packet we are waiting for.
    00574     //
    00575
    00576     //
    00577     // Check ByteCount received is valid
    00578     //
    00579
    00580     MessageLength = MessageHeader->MaximumLength;
    00581     if ((PacketHeader.ByteCount > (USHORT)PACKET_MAX_SIZE) ||
    00582         (PacketHeader.ByteCount < (USHORT)MessageLength)) {
    00583         goto SendResendPacket;
    00584     }
    00585     *DataLength = PacketHeader.ByteCount - MessageLength;
    00586
    00587     //
    00588     // Read the message header.
    00589     //
    00590
    00591     ReturnCode = KdpReceiveString(MessageHeader->Buffer, MessageLength);
    00592     if (ReturnCode != CP_GET_SUCCESS) {
    00593         goto SendResendPacket;
    00594     }
    00595     MessageHeader->Length = (USHORT)MessageLength;
    00596
    00597     //
    00598     // Read the message data.
    00599     //
    00600
    00601     ReturnCode = KdpReceiveString(MessageData->Buffer, *DataLength);
    00602     if (ReturnCode != CP_GET_SUCCESS) {
    00603         goto SendResendPacket;
    00604     }
    00605     MessageData->Length = (USHORT)*DataLength;
    00606
    00607     //
    00608     // Read packet trailing byte
    00609     //
    00610
    00611     ReturnCode = KdPortGetByte(&Input);
    00612     if (ReturnCode != CP_GET_SUCCESS || Input != PACKET_TRAILING_BYTE) {
    00613         goto SendResendPacket;
    00614     }
    00615
    00616     //
    00617     // Check PacketType is what we are waiting for.
    00618     //
    00619
    00620     if (PacketType != PacketHeader.PacketType) {
    00621         KdpSendControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE,
    00622                              PacketHeader.PacketId
    00623                              );
    00624         goto WaitForPacketLeader;
    00625     }
    00626
    00627     //
    00628     // Check PacketId is valid.
    00629     //
    00630
    00631     if (PacketHeader.PacketId == INITIAL_PACKET_ID ||
    00632         PacketHeader.PacketId == (INITIAL_PACKET_ID ^ 1)) {
    00633         if (PacketHeader.PacketId != KdpPacketIdExpected) {
    00634             KdpSendControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE,
    00635                                  PacketHeader.PacketId
    00636                                  );
    00637             goto WaitForPacketLeader;
    00638         }
    00639     } else {
    00640         goto SendResendPacket;
    00641     }
    00642
    00643     //
    00644     // Check checksum is valid.
    00645     //
    00646
    00647     Checksum = KdpComputeChecksum(
    00648                             MessageHeader->Buffer,
    00649                             MessageHeader->Length
    00650                             );
    00651
    00652     Checksum += KdpComputeChecksum(
    00653                             MessageData->Buffer,
    00654                             MessageData->Length
    00655                             );
    00656     if (Checksum != PacketHeader.Checksum) {
    00657         goto SendResendPacket;
    00658     }
    00659
    00660     //
    00661     // Send Acknowledge byte and the Id of the packet received.
    00662     // Then, update the ExpectId for next incoming packet.
    00663     //
    00664
    00665     KdpSendControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE,
    00666                          PacketHeader.PacketId
    00667                          );
    00668
    00669     //
    00670     // We have successfully received the packet so update the
    00671     // packet control variables and return sucess.
    00672     //
    00673
    00674     KdpPacketIdExpected ^= 1;
    00675     return KDP_PACKET_RECEIVED;
    00676
    00677 SendResendPacket:
    00678     KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0L);
    00679     goto WaitForPacketLeader;
    00680 }
    00681
    00682 VOID
    00683 KdpSendPacket (
    00684     IN ULONG PacketType,
    00685     IN PSTRING MessageHeader,
    00686     IN PSTRING MessageData OPTIONAL
    00687     )
    00688
    00689 /*++
    00690
    00691 Routine Description:
    00692
    00693     This routine sends a packet to the host machine that is running the
    00694     kernel debugger and waits for an ACK.
    00695
    00696 Arguments:
    00697
    00698     PacketType - Supplies the type of packet to send.
    00699
    00700     MessageHeader - Supplies a pointer to a string descriptor that describes
    00701         the message information.
    00702
    00703     MessageData - Supplies a pointer to a string descriptor that describes
    00704         the optional message data.
    00705
    00706 Return Value:
    00707
    00708     None.
    00709
    00710 --*/
    00711
    00712 {
    00713
    00714     KD_PACKET PacketHeader;
    00715     ULONG MessageDataLength;
    00716     ULONG ReturnCode;
    00717     PDBGKD_DEBUG_IO DebugIo;
    00718     PDBGKD_WAIT_STATE_CHANGE StateChange;
    00719
    00720     if ( ARGUMENT_PRESENT(MessageData) ) {
    00721         MessageDataLength = MessageData->Length;
    00722         PacketHeader.Checksum = KdpComputeChecksum(
    00723                                         MessageData->Buffer,
    00724                                         MessageData->Length
    00725                                         );
    00726     } else {
    00727         MessageDataLength = 0;
    00728         PacketHeader.Checksum = 0;
    00729     }
    00730
    00731     PacketHeader.Checksum += KdpComputeChecksum (
    00732                                     MessageHeader->Buffer,
    00733                                     MessageHeader->Length
    00734                                     );
    00735
    00736     //
    00737     // Initialize and send the packet header.
    00738     //
    00739
    00740     PacketHeader.PacketLeader = PACKET_LEADER;
    00741     PacketHeader.ByteCount = (USHORT)(MessageHeader->Length + MessageDataLength);
    00742     PacketHeader.PacketType = (USHORT)PacketType;
    00743     KdpNumberRetries = KdpRetryCount;
    00744     do {
    00745         if (KdpNumberRetries == 0) {
    00746
    00747             //
    00748             // If the packet is not for reporting exception, we give up
    00749             // and declare debugger not present.
    00750             //
    00751
    00752             if (PacketType == PACKET_TYPE_KD_DEBUG_IO) {
    00753                 DebugIo = (PDBGKD_DEBUG_IO)MessageHeader->Buffer;
    00754                 if (DebugIo->ApiNumber == DbgKdPrintStringApi) {
    00755                     KdDebuggerNotPresent = TRUE;
    00756                     KdpNextPacketIdToSend = INITIAL_PACKET_ID | SYNC_PACKET_ID;
    00757                     KdpPacketIdExpected = INITIAL_PACKET_ID;
    00758                     return;
    00759                 }
    00760             } else if (PacketType == PACKET_TYPE_KD_STATE_CHANGE) {
    00761                 StateChange = (PDBGKD_WAIT_STATE_CHANGE)MessageHeader->Buffer;
    00762                 if (StateChange->NewState == DbgKdLoadSymbolsStateChange) {
    00763                     KdDebuggerNotPresent = TRUE;
    00764                     KdpNextPacketIdToSend = INITIAL_PACKET_ID | SYNC_PACKET_ID;
    00765                     KdpPacketIdExpected = INITIAL_PACKET_ID;
    00766                     return;
    00767                 }
    00768             }
    00769         }
    00770
    00771         //
    00772         // Setting PacketId has to be in the do loop in case Packet Id was
    00773         // reset.
    00774         //
    00775
    00776         PacketHeader.PacketId = KdpNextPacketIdToSend;
    00777         KdpSendString((PCHAR)&PacketHeader, sizeof(KD_PACKET));
    00778
    00779         //
    00780         // Output message header.
    00781         //
    00782
    00783         KdpSendString(MessageHeader->Buffer, MessageHeader->Length);
    00784
    00785         //
    00786         // Output message data.
    00787         //
    00788
    00789         if ( MessageDataLength ) {
    00790             KdpSendString(MessageData->Buffer, MessageData->Length);
    00791         }
    00792
    00793         //
    00794         // Output a packet trailing byte
    00795         //
    00796
    00797         KdPortPutByte(PACKET_TRAILING_BYTE);
    00798
    00799         //
    00800         // Wait for the Ack Packet
    00801         //
    00802
    00803         ReturnCode = KdpReceivePacket(
    00804                          PACKET_TYPE_KD_ACKNOWLEDGE,
    00805                          NULL,
    00806                          NULL,
    00807                          NULL
    00808                          );
    00809         if (ReturnCode == KDP_PACKET_TIMEOUT) {
    00810             KdpNumberRetries--;
    00811         }
    00812     } while (ReturnCode != KDP_PACKET_RECEIVED);
    00813
    00814     //
    00815     // Reset Sync bit in packet id.  The packet we sent may have Sync bit set
    00816     //
    00817
    00818     KdpNextPacketIdToSend &= ~SYNC_PACKET_ID;
    00819
    00820     //
    00821     // Since we are able to talk to debugger, the retrycount is set to
    00822     // maximum value.
    00823     //
    00824
    00825     KdpRetryCount = MAXIMUM_RETRIES;
    00826 }