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

📄 mdd.c

📁 我自己编译的armv4i wince60模拟器的bps源文件,已经验证可以使用,欢迎下载
💻 C
📖 第 1 页 / 共 5 页
字号:
    // Make sure the caller has access permissions
    if ( !(pOpenHead->AccessCode & GENERIC_WRITE) ) {
        DEBUGMSG(ZONE_USR_READ|ZONE_ERROR,
                 (TEXT("SERDMA_Write: Access permission failure x%X\n\r"),
                  pOpenHead->AccessCode));
        SetLastError (ERROR_INVALID_ACCESS);
        return (ULONG)-1;
    }

    if ( pSourceBytes == NULL ) {
        DEBUGMSG (ZONE_WRITE|ZONE_ERROR,
                  (TEXT("SERDMA_Write, bad read pointer\r\n") ));
        SetLastError(ERROR_INVALID_PARAMETER);
        return (ULONG)-1;
    }

    // Construct the DMA packet
    if (NumberOfBytes > sizeof(pTransmitPacketBuffer->u.PacketContents)) {
        DEBUGMSG (ZONE_WRITE|ZONE_ERROR,
                  (TEXT("SERDMA_Write, bad read pointer\r\n") ));
        SetLastError(ERROR_INVALID_PARAMETER);
        return (ULONG)-1;
    }

    pTransmitPacketBuffer = (DMA_PACKET_BUFFER*) 
        InterlockedExchangePointer(g_pPacketBufferCache, NULL);
    if ( pTransmitPacketBuffer == NULL ) {
        // Another thread is using the global PacketBuffer. Allocate a new one here.
        pTransmitPacketBuffer = LocalAlloc(LMEM_FIXED, sizeof(DMA_PACKET_BUFFER));
        if ( pTransmitPacketBuffer == NULL ) {
            SetLastError(ERROR_OUTOFMEMORY);
            return (ULONG)-1;
        }
    }

    pTransmitPacketBuffer->u.PacketLength = (USHORT)NumberOfBytes;
    if (!CeSafeCopyMemory(pTransmitPacketBuffer->u.PacketContents, pSourceBytes, NumberOfBytes)) {
        DEBUGMSG (ZONE_WRITE|ZONE_ERROR,
                  (TEXT("SERDMA_Write, bad read pointer\r\n") ));
        SetLastError(ERROR_INVALID_PARAMETER);
        goto EXIT;
    }

    COM_INC_USAGE_CNT(pOpenHead);

    pHWObj   = pSerialHead->pHWObj;
    pHWHead  = pSerialHead->pHWHead;
    pFuncTbl = pHWObj->pFuncTbl;

    // Transmit the packet
    Len = sizeof(*pTransmitPacketBuffer);
    pFuncTbl->HWTxIntrHandler(pHWHead,
                              (PUCHAR)pTransmitPacketBuffer,
                              &Len);

    // Report the event to WaitCommEvent()
    EvaluateEventFlag(pSerialHead, EV_TXEMPTY);

    COM_DEC_USAGE_CNT(pOpenHead);

    ulRet = NumberOfBytes;

EXIT:
    if (pTransmitPacketBuffer == &g_PacketBuffer) {
        // We're using the global buffer. Release it now.
        g_pPacketBufferCache = &g_PacketBuffer;
    }
    else {
        LocalFree(pTransmitPacketBuffer);
    }
    
    DEBUGMSG (ZONE_WRITE|ZONE_FUNCTION,
              (TEXT("-SERDMA_Write, returning %d\n\r"),ulRet));
    
    return ulRet;
}

ULONG
SERDMA_Seek(
        HANDLE  pHead,
        LONG    Position,
        DWORD   Type
        )
{
    return(ULONG)-1;
}

/*
 @doc EXTERNAL
 @func  BOOL | SERDMA_PowerUp | Turn power on to serial device
 * Exported to users.
 @rdesc This routine returns a status of 1 if unsuccessful and 0 otherwise.
 */
BOOL
SERDMA_PowerUp(
           HANDLE      pHead       /*@parm Handle to device. */
           )
{
    return 0;
}

/*
 @doc EXTERNAL
 @func  BOOL | SERDMA_PowerDown | Turns off power to serial device.
 * Exported to users.
 @rdesc This routine returns a status of 1 if unsuccessful and 0 otherwise.
 */
BOOL
SERDMA_PowerDown(
             HANDLE      pHead       /*@parm Handle to device. */
             )
{
    PHW_INDEP_INFO  pSerialHead = (PHW_INDEP_INFO)pHead;
    PVOID           pHWHead = pSerialHead->pHWHead;

    SL_PowerOff(pHWHead);

    return 0;
}

// Routine to handle the PROCESS_EXITING flag.  Should let free any threads blocked on pOpenHead,
// so they can be killed and the process closed.

BOOL
ProcessExiting(PHW_OPEN_INFO pOpenHead)
{
    PHW_INDEP_INFO  pSerialHead = pOpenHead->pSerialHead;
    PHWOBJ          pHWObj;
    int i;
    BOOL            RetCode = TRUE;

    DEBUGMSG (ZONE_CLOSE|ZONE_FUNCTION, (TEXT("+ProcessExiting\r\n")));

    if ( !pSerialHead ) {
        DEBUGMSG (ZONE_ERROR, (TEXT("!!ProcessExiting: pSerialHead == NULL!!\r\n")));
        SetLastError(ERROR_INVALID_HANDLE);
        return FALSE;
    }
    pHWObj = (PHWOBJ)pSerialHead->pHWObj;

    // Use the OpenCS to make sure we don't collide with an in-progress open.
    EnterCriticalSection(&(pSerialHead->OpenCS));

    if ( pSerialHead->OpenCnt ) {

        DEBUGMSG (1,
                  (TEXT("ProcessClose: (%d handles)\r\n"),
                   pSerialHead->OpenCnt));

        // In multi open case, do we need to restore state later on or something????
        if ( pHWObj && (pHWObj->BindFlags & THREAD_IN_MDD) &&
             pSerialHead->pDispatchThread ) {
            SetThreadPriority(pSerialHead->pDispatchThread,
                              THREAD_PRIORITY_NORMAL);
        }

        // Free up any threads which may be blocked waiting for events.
        // Monitor users count to make sure no one is still in one of
        // the SERDMA_ functions before proceeding (wait up to 2 s).
        for ( i=0; i<20 && pOpenHead->StructUsers; i++ ) {
            DEBUGMSG(ZONE_INIT|ZONE_CLOSE,
                     (TEXT("ProcessExiting: %d users in MDD functions\n\r"),pOpenHead->StructUsers));

            // For any open handle, we must free pending waitcommevents
            EnterCriticalSection(&(pOpenHead->CommEvents.EventCS));
            pOpenHead->CommEvents.fEventMask = 0;
            pOpenHead->CommEvents.fAbort = 1;
            SetEvent(pOpenHead->CommEvents.hCommEvent);
            LeaveCriticalSection(&(pOpenHead->CommEvents.EventCS));

            // And only for the handle with access permissions do we
            // have to worry about read, write, etc being blocked.
            if ( pOpenHead->AccessCode & (GENERIC_READ | GENERIC_WRITE) ) {
                SetEvent(pSerialHead->hReadEvent);
            }

            /* Sleep, let threads finish */
            Sleep(100);
        }
        if ( i==20 )
            DEBUGMSG(ZONE_CLOSE|ZONE_INIT|ZONE_ERROR,
                     (TEXT("ProcessExiting: Waited 2s for serial users to exit, %d left\n\r"),
                      pOpenHead->StructUsers));

    } else {
        DEBUGMSG (ZONE_ERROR, (TEXT("!!Close of non-open serial port\r\n")));
        SetLastError(ERROR_INVALID_HANDLE);
        RetCode = FALSE;
    }

    // OK, other inits/opens can go ahead.
    LeaveCriticalSection(&(pSerialHead->OpenCS));

    DEBUGMSG (ZONE_CLOSE|ZONE_FUNCTION, (TEXT("-ProcessExiting\r\n")));
    return RetCode;
}

/*
 *  @doc INTERNAL
 *      @func           BOOL | ApplyDCB | Apply the current DCB.
 *
 *      This function will apply the current DCB settings to the device.
 *      It will also call to the PDD to set the PDD values.
 */
BOOL
ApplyDCB (PHW_INDEP_INFO pSerialHead, DCB *pDCB, BOOL fOpen)
{
    PHWOBJ          pHWObj      = pSerialHead->pHWObj;

    if ( !pHWObj->pFuncTbl->HWSetDCB(pSerialHead->pHWHead,
                                     pDCB) ) {
        return FALSE;
    }

    if ( !fOpen ) {
        return TRUE;
    }

    // If PDD SetDCB was successful, save the supplied DCB and
    // configure port to match these settings.
    memcpy(&(pSerialHead->DCB), pDCB, sizeof(DCB));

    return TRUE;
}

// ****************************************************************
//
//      @func   VOID | EvaluateEventFlag | Evaluate an event mask.
//
//      @parm PHW_INDEP_INFO    | pHWIHead              | MDD context pointer
//      @parm ULONG                             | fdwEventMask  | Bitmask of events
//
//      @rdesc  No return
//
//      @remark This function is called by the PDD (and internally in the MDD
//                      to evaluate a COMM event.  If the user is waiting for a
//                      COMM event (see WaitCommEvent()) then it will signal the
//                      users thread.
//
VOID
EvaluateEventFlag(PVOID pHead, ULONG fdwEventMask)
{
    PHW_INDEP_INFO  pHWIHead = (PHW_INDEP_INFO)pHead;
    PLIST_ENTRY     pEntry;
    PHW_OPEN_INFO   pOpenHead;
    DWORD           dwTmpEvent, dwOrigEvent;
    BOOL            fRetCode;

    if ( !pHWIHead->OpenCnt ) {
        DEBUGMSG (ZONE_EVENTS|ZONE_ERROR,
                  (TEXT(" EvaluateEventFlag - device was closed\r\n")));
        SetLastError (ERROR_INVALID_HANDLE);
        return;
    }

    DEBUGMSG (ZONE_EVENTS, (TEXT(" CommEvent - Event 0x%X, Global Mask 0x%X\r\n"),
                            fdwEventMask,
                            pHWIHead->fEventMask));

    // Now that we support multiple opens, we must check mask for each open handle
    // To keep this relatively painless, we keep a per-device mask which is the
    // bitwise or of each current open mask.  We can check this first before doing
    // all the linked list work to figure out who to notify
    if ( pHWIHead->fEventMask & fdwEventMask ) {
        pEntry = pHWIHead->OpenList.Flink;
        while ( pEntry != &pHWIHead->OpenList ) {
            pOpenHead = CONTAINING_RECORD( pEntry, HW_OPEN_INFO, llist);
            pEntry = pEntry->Flink;  // advance to next

            EnterCriticalSection(&(pOpenHead->CommEvents.EventCS));
            // Don't do anything unless this event is of interest to the MDD.
            if ( pOpenHead->CommEvents.fEventMask & fdwEventMask ) {
                // Store the event data
                dwOrigEvent = pOpenHead->CommEvents.fEventData;
                do {
                    dwTmpEvent = dwOrigEvent;
                    dwOrigEvent = InterlockedExchange(&(pOpenHead->CommEvents.fEventData),
                                                      dwTmpEvent | fdwEventMask) ;

                } while ( dwTmpEvent != dwOrigEvent );

                // Signal the MDD that new event data is available.
                fRetCode = SetEvent(pOpenHead->CommEvents.hCommEvent);
                DEBUGMSG (ZONE_EVENTS, (TEXT(" CommEvent - Event 0x%X, Handle 0x%X Mask 0x%X (%X)\r\n"),
                                        dwTmpEvent | fdwEventMask,
                                        pOpenHead,
                                        pOpenHead->CommEvents.fEventMask,
                                        fRetCode));

            }
            LeaveCriticalSection(&(pOpenHead->CommEvents.EventCS));
        }
    }
}

/*
 @doc INTERNAL
 @func  BOOL | WaitCommEvent | See Win32 documentation.
 * Exported to users.
 */
BOOL
WINAPI
WaitCommEvent(
             PHW_OPEN_INFO   pOpenHead,      // @parm Handle to device.
             PULONG          pfdwEventMask,  // @parm Pointer to ULONG to receive CommEvents.fEventMask.
             LPOVERLAPPED    Unused          // @parm Pointer to OVERLAPPED not used.
             )
{
    PHW_INDEP_INFO  pHWIHead = pOpenHead->pSerialHead;
    DWORD           dwEventData;

    DEBUGMSG(ZONE_FUNCTION|ZONE_EVENTS,(TEXT("+WaitCommEvent x%X x%X, pMask x%X\n\r"),
                                        pOpenHead, pHWIHead , pfdwEventMask));

    if ( !pHWIHead || !pHWIHead->OpenCnt ) {
        DEBUGMSG (ZONE_ERROR|ZONE_EVENTS, (TEXT("-WaitCommEvent - device not open (x%X, %d) \r\n"),
                                           pHWIHead, (pHWIHead == NULL) ? 0 : pHWIHead->OpenCnt));
        *pfdwEventMask = 0;
        SetLastError(ERROR_INVALID_HANDLE);
        return FALSE;
    }

    // We should return immediately if mask is 0
    if ( !pOpenHead->CommEvents.fEventMask ) {
        DEBUGMSG (ZONE_ERROR|ZONE_EVENTS, (TEXT("-WaitCommEvent - Mask already clear\r\n")));
        *pfdwEventMask = 0;
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    COM_INC_USAGE_CNT(pOpenHead);

    // Abort should only affect us once we start waiting.  Ignore any old aborts
    pOpenHead->CommEvents.fAbort = 0;

⌨️ 快捷键说明

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