⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 edbgprot.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 4 页
字号:

    // establish connection with desktop
    if (!(pClient->State & KITL_CLIENT_REGISTERED) && !ExchangeConfig (pClient))
        return FALSE;

    if (dwUserDataLen > KITL_MAX_DATA_SIZE) {
        KITL_DEBUGMSG(ZONE_WARNING,("!KITLSend: Buffer too large\n"));
        return FALSE;
    }

    // check if the data overlapped with buffer pool, reject if it does
    if ((pUserData < pClient->pTxBufferPool + pClient->WindowSize * KITL_MTU)
        && (pUserData + dwUserDataLen > pClient->pTxBufferPool)) {
        KITLOutputDebugString ("!KITLSend: Data to be send overlapped with buffer pools\r\n");
        return FALSE;
    }

    // Check for re-entrancy -- e.g. if kernel debug zones are turned on
    if (pClient->ServiceId == KITL_SVC_DBGMSG ) {
        if (((hCurThread == hDbgMsgThread) || (hCurThread == hIntrThread) || (hCurThread == hTimerThread))
            && (KITLGlobalState & KITL_ST_MULTITHREADED)) {
            if (!(KITLDebugZone & KITL_ZONE_NOSERIAL)) {
                KITL_DBGMSG_INFO *pDbgMsg = (KITL_DBGMSG_INFO *)pUserData;
                KITLOutputDebugString("!KITLSend(DBGMSG): Reentrant call, hTh:%X\n",hCurThread);
                KITLOutputDebugString("%s\n",pUserData + pDbgMsg->dwLen);
            }
            return TRUE;
        }
        else
            hDbgMsgThread = hCurThread;
    }

    // Determine whether we can make system calls or not. There are three cases where we cannot:
    //     o  During system init, until KITLInitializeInterrupt is called
    //     o  When we are called from within a system call
    //     o  When we are called from the debugger
    if (KITLGlobalState & KITL_ST_MULTITHREADED) {
        // If we're in a sys call, can't block on anything (but won't be preempted)
        if (InSysCall() || IsInPwrHdlr ()) {
            KITL_DEBUGMSG(ZONE_WARNING,("KITLSend(%u): InSysCall or InPowerHandler, use polling\n",Id));
            fUseSysCalls = FALSE;
            fRestoreClientState = TRUE;
            PrevSyscallState = pClient->State & KITL_USE_SYSCALLS;
            pClient->State &= ~KITL_USE_SYSCALLS;
                    
            KITLGlobalState &= ~KITL_ST_MULTITHREADED;
            fRestoreGlobalState = TRUE;

            // The protocol state machine can't handle us stepping in at some arbitrary point
            // and mucking with state, so if someone owns the CS, just bail and print to the
            // debug serial port.
            if (pClient->ClientCS.OwnerThread || KITLKCallcs.OwnerThread) {
                KITL_DEBUGMSG(ZONE_WARNING,("!KITLSend(%u): In syscall with ClientCS owned (KCallcs = 0x%x)",Id, KITLKCallcs.OwnerThread));
                if ((pClient->ServiceId == KITL_SVC_DBGMSG) && !(KITLDebugZone & KITL_ZONE_NOSERIAL)) {
                    KITL_DBGMSG_INFO *pDbgMsg = (KITL_DBGMSG_INFO *)pUserData;
                    KITLOutputDebugString("%s",pUserData + pDbgMsg->dwLen);
                }
                fRet = FALSE;
                goto KITLSend_exit;
            }
        }
        else if (pClient->State & KITL_USE_SYSCALLS) {
            // Normal case
            fUseSysCalls = TRUE;
        }
        else {
            // This client cannot use system calls, and guarantees that scheduling is disabled while
            // it is called into the KITL functions. Currently, this only applies to KDBG client.
            if (Id != KITL_SVC_KDBG) {
                KITL_DEBUGMSG(ZONE_WARNING,("!KITLSend(%u): KITL_USE_SYSCALLS for client turned off\n",Id)); 
            }

            fUseSysCalls = FALSE;
            KITLGlobalState &= ~KITL_ST_MULTITHREADED;
            fRestoreGlobalState = TRUE;
        }
    }
    else {
        // Single threaded and non preemptible
        fUseSysCalls = FALSE;
    }

    if (fUseSysCalls)        
        EnterCriticalSection(&pClient->ClientCS);

    KITL_DEBUGMSG(ZONE_SEND,("+KITLSend(%u), Len: %u, Seq: %u, AckExpected: %u, SC:%u\n",
                             Id, dwUserDataLen,pClient->TxSeqNum, pClient->AckExpected,fUseSysCalls));
    // If Tx window full, block
#ifdef DEBUG
    if (SEQ_DELTA(pClient->AckExpected, pClient->TxSeqNum) >= pClient->WindowSize) {
        KITL_DEBUGMSG(ZONE_WARNING,("KITLSend(%u): Tx window full (AckExpected: %u, Seq: %u) SC:%u\n",
                                    Id,pClient->AckExpected,pClient->TxSeqNum,fUseSysCalls));
    }
#endif
    while ( SEQ_DELTA(pClient->AckExpected, pClient->TxSeqNum) >= pClient->WindowSize) {
        if (fUseSysCalls) {
            SC_EventModify(pClient->evTxFull, EVENT_RESET);
            LeaveCriticalSection(&pClient->ClientCS);
            // Some platforms don't have interrupts
            if (KITLGlobalState & KITL_ST_INT_ENABLED) {
        WaitAgain:
                if (SC_WaitForMultiple (1,&pClient->evTxFull,0,KITL_TIMEOUT_INTERVAL_MS) != WAIT_OBJECT_0) {
                    KITLOutputDebugString("0x%x: KITLSend(%u): Timed out waiting for ack (AckExpected: %u, TxSeq: %u)\n", hCurThread, Id,
                                          pClient->AckExpected,pClient->TxSeqNum);
                    // For default services, don't give up
                    if (IS_DFLT_SVC(Id))
                        goto WaitAgain;
                    fRet = FALSE;
                    goto KITLSend_exit;
                }
                if (!(pClient->State & KITL_CLIENT_REGISTERED)) {
                    // client de-registered, return FALSE
                    KITL_DEBUGMSG(ZONE_WARNING,("KITLSend(%u): Client de-registered while sending\n", Id));
                    fRet = FALSE;
                    goto KITLSend_exit;
                }
            }
            else {
                if (!KITLPollData(TRUE, NULL, NULL)) {
                    fRet = FALSE;
                    goto KITLSend_exit;
                }
                // Give retransmit thread chance to run
                if (SEQ_DELTA(pClient->AckExpected, pClient->TxSeqNum) >= pClient->WindowSize)
                    SC_Sleep(1);
            }
            EnterCriticalSection(&pClient->ClientCS);
        } else {
            // we're InSysCall or in KD, Poll until window closes
            KITLPollResponse (FALSE, ChkAck, TranAck, pClient);
        }
    }
    
    // Format frame into Tx buffer (leave space for transport headers)
    dwPacketIndex = pClient->TxSeqNum % pClient->WindowSize;
    pFrame = pClient->pTxBufferPool + (dwPacketIndex * KITL_MTU);
    pHdr = (PKITL_HDR) (pFrame + Kitl.FrmHdrSize);
    pHdr->Id = KITL_ID;
    pHdr->Service = pClient->ServiceId;
    pHdr->Flags = KITL_FL_FROM_DEV;
    pHdr->Cmd = KITL_CMD_SVC_DATA;
    pHdr->SeqNum = pClient->TxSeqNum;
    SEQ_INC(pClient->TxSeqNum);

    pData = (UCHAR *)KITLDATA(pHdr);
    
    // Copy user data into buffer
    memcpy(pData, pUserData, dwUserDataLen);

    pClient->TxFrameLen[dwPacketIndex] = (USHORT)(dwUserDataLen + sizeof(KITL_HDR));

    if (KITLDebugZone & ZONE_FRAMEDUMP)
        KITLDecodeFrame(">>KITLSend", pHdr, pClient->TxFrameLen[dwPacketIndex]);
    
    if (!(fRet = KitlSendFrame (pFrame, pClient->TxFrameLen[dwPacketIndex])))
        KITLOutputDebugString("!KITLSend: Error in KitlSendFrame\n");
    else {
        if (!fUseSysCalls)
            fRet = KITLPollResponse (FALSE, ChkAck, TranAck, pClient);
        else {
            // Start retransmit timer
            TimerStart(pClient, dwPacketIndex, KITL_RETRANSMIT_INTERVAL_MS, TRUE);
            // If we're in stop and wait mode, wait for ack here. Also need to do this
            // if our interrupt isn't enabled.
            if ((pClient->CfgFlags & KITL_CFGFL_STOP_AND_WAIT) ||
                !(KITLGlobalState & KITL_ST_INT_ENABLED)) {
                SC_EventModify(pClient->evTxFull, EVENT_RESET);
                LeaveCriticalSection(&pClient->ClientCS);

                if (KITLGlobalState & KITL_ST_INT_ENABLED) {
                    while (SC_WaitForMultiple (1,&pClient->evTxFull, 0, KITL_TIMEOUT_INTERVAL_MS) == WAIT_TIMEOUT) {
                        KITL_DEBUGMSG(ZONE_WARNING,("KITLSend: Id: %u Timed out waiting for ack (AckExpected: %u, TxSeq: %u)\n",Id,
                                                    pClient->AckExpected,pClient->TxSeqNum));
                    }
                    if (!(pClient->State & KITL_CLIENT_REGISTERED)) {
                        // client de-registered, return FALSE
                        KITL_DEBUGMSG(ZONE_WARNING,("KITLSend(%u): Client de-registered while sending\n", Id));
                        fRet = FALSE;
                        goto KITLSend_exit;
                    }
                    
                }
                else {
                    fRet = KITLPollResponse (TRUE, ChkAck, TranAck, pClient);
                }
                EnterCriticalSection(&pClient->ClientCS);
            }
            if (!fRet) 
                TimerStop(pClient, dwPacketIndex, TRUE);
        }
    }
    if (!fRet) {
        // Restore state
        pClient->TxSeqNum = SEQ_SUB1(pClient->TxSeqNum);
        pClient->TxFrameLen[dwPacketIndex] = 0;
    }

    if (fUseSysCalls)
        LeaveCriticalSection(&pClient->ClientCS);
KITLSend_exit:

    if (pClient->ServiceId == KITL_SVC_DBGMSG)
        hDbgMsgThread = 0;
    
    if (fRestoreClientState)
        pClient->State |= PrevSyscallState;
    
    if (fRestoreGlobalState)
        KITLGlobalState |= KITL_ST_MULTITHREADED;
    
    KITL_DEBUGMSG(ZONE_SEND,("-Send (%u): Ret %u\n", Id, fRet));
    return fRet;
}

/* RetransmitFrame
 *
 *   Retransmit specified frame in Tx buffer, either due to a timeout waiting
 *   for an ack, or a NACK received from the peer.
 *
 * Return Value:
 *   Return TRUE if the timer should be rescheduled, FALSE if not.  We only return
 *   FALSE if the retransmitted frame does not fall in the Tx window.  This can
 *   happen if we get called in a sys call, and so cannot touch the timer structs
 *   (since can't get the CS).
 */
BOOL
RetransmitFrame(KITL_CLIENT *pClient, UCHAR Index, BOOL fUseSysCalls)
{
    UCHAR *pData = pClient->pTxBufferPool + (Index * KITL_MTU);
    DWORD OldProcPerms;
    BOOL  fRet = TRUE;
    KITL_HDR *pHdr;

    pHdr = (KITL_HDR *)(pData + Kitl.FrmHdrSize);

    if (fUseSysCalls && (pClient->State & KITL_USE_SYSCALLS))
        EnterCriticalSection(&pClient->ClientCS);
    
    // Set permissions for accessing client buffer, if necessary
    if (pClient->ProcPerms) {
        SWITCHKEY (OldProcPerms, pClient->ProcPerms);
    }

    if (!SEQ_BETWEEN(pClient->AckExpected, pHdr->SeqNum, pClient->TxSeqNum)) {
        KITL_DEBUGMSG(ZONE_WARNING,("!RetransmitFrame: Frame seq %u not in Tx window (%u,%u)\n",
                                    pHdr->SeqNum, pClient->AckExpected, pClient->TxSeqNum));
        fRet = FALSE; // Don't reschedule timer
    } else {
        if (KITLDebugZone & ZONE_FRAMEDUMP)
            KITLDecodeFrame(">>Retransmit", pHdr, pClient->TxFrameLen[Index]);

        KITL_DEBUGMSG(ZONE_RETRANSMIT,("RetransmitFrame(Id:%u), Seq: %u, Len: %u, Window (%u,%u)\n",pClient->ServiceId,
                                       pHdr->SeqNum, pClient->TxFrameLen[Index], pClient->AckExpected, pClient->TxSeqNum));
        if (!KitlSendRawData (pData, (USHORT) (pClient->TxFrameLen[Index] + Kitl.FrmHdrSize + Kitl.FrmTlrSize))) {
            KITLOutputDebugString("!RetransmitFrame: Error in KitlSendRawData\n");
            // Go ahead and return TRUE so frame will be tried again.
        }
    }
    if (pClient->ProcPerms) {
        SETCURKEY (OldProcPerms);
    }
    if (fUseSysCalls && (pClient->State & KITL_USE_SYSCALLS))
        LeaveCriticalSection(&pClient->ClientCS);
    return fRet;
}



/* SendAckNack
 *
 *   Send an ACK or NACK frame to peer:
 *      ACK:   Acknowledge receipt of all frames up to SeqNum
 *      NACK:  Request retransmission of frame specified by SeqNum
 */
static void
SendAckNack(BOOL IsAck, KITL_CLIENT *pClient, UCHAR SeqNum)
{
    UCHAR *AckNackBuf;
    KITL_HDR *pHdr;

    AckNackBuf = _alloca (Kitl.FrmHdrSize // for transport header
        + sizeof(KITL_HDR)                // for protocol header
        + Kitl.FrmTlrSize);               // for transport tailer

    if (!AckNackBuf) {
        KITLOutputDebugString ("!SendAckNack: Stack overflow\r\n");
        return;
    }
    pHdr = (KITL_HDR *)(AckNackBuf + Kitl.FrmHdrSize);
    pHdr->Id       = KITL_ID;
    pHdr->Service  = pClient->ServiceId;    // must use id of the other side
    pHdr->Flags    = (IsAck? KITL_FL_ACK:KITL_FL_NACK)|KITL_FL_FROM_DEV;
    pHdr->Cmd      = KITL_CMD_SVC_DATA;
    pHdr->SeqNum   = SeqNum;

    if (KITLDebugZone & ZONE_FRAMEDUMP)
        KITLDecodeFrame(">>SendAckNack ", pHdr, sizeof(KITL_HDR));
    if (!KitlSendFrame (AckNackBuf, sizeof(KITL_HDR)))
        KITLOutputDebugString("!KITL: Error in KitlSendFrame for ACK\n");
}


/* 
 * @func  BOOL | KITLRecv | Receive message over debug Ethernet interface.
 * @rdesc Return TRUE if successful, FALSE if error occurrs.
 * @comm  Receive message from peer KITL client.  If no received data
 *        is available for the specified service, block until data is ready, or
 *        timeout occurs.
 *        Note: If the caller does not provide a big enough buffer to hold the data, 
 *        the buffer is filled, and remaining data is tossed.  Don't have to worry 
 *        about this by providing a buffer of KITL_MAX_DATA_SIZE bytes.
 *  @xref  <f KITLRegisterClient> <f KITLSend> 
 */ 
BOOL
KITLRecv(
    UCHAR Id,        // @parm [IN] - KITL client id (returned from <f KITLRegisterClient>)
    UCHAR *pRecvBuf, // @parm [OUT]- Buffer to receive data
    DWORD *pdwLen,   // @parm [IN] - Buffer size. [OUT] - Bytes of data received.
    DWORD Timeout)   // @parm [IN] - Timeout value (0 == don't block, INFINITE == wait forever)
{
    KITL_CLIENT *pClient = KITLClients[Id];
    DWORD dwStartTime;
    DWORD dwBytesToCopy;
    UCHAR PrevSyscallState;
    BOOL  fRestoreClientState = FALSE, fRestoreGlobalState = FALSE;
    BOOL  fUseSysCalls;
    BOOL  fRet = TRUE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -