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

📄 mdd.c

📁 我自己编译的armv4i wince60模拟器的bps源文件,已经验证可以使用,欢迎下载
💻 C
📖 第 1 页 / 共 5 页
字号:

    // Initially, open list is empty.
    InitializeListHead( &pSerialHead->OpenList );
    InitializeCriticalSection(&(pSerialHead->OpenCS));
    pSerialHead->pAccessOwner = NULL;
    pSerialHead->fEventMask = 0;

    /* Initialize the critical sections that will guard the parts of
     * the receive and transmit buffers.
     */
    InitializeCriticalSection(&(pSerialHead->ReceiveCritSec1));

    /* Want to use the Identifier to do RegOpenKey and RegQueryValue (?)
     * to get the index to be passed to GetHWObj.
     * The HWObj will also have a flag denoting whether to start the
     * listening thread or provide the callback.
     */
    DEBUGMSG (ZONE_INIT,(TEXT("Try to open %s\r\n"), (LPCTSTR)Identifier));
    hKey = OpenDeviceKey((LPCTSTR)Identifier);
    if ( !hKey ) {
        DEBUGMSG (ZONE_INIT | ZONE_ERROR,
                  (TEXT("Failed to open devkeypath, SERDMA_Init failed\r\n")));
        LocalFree(pSerialHead);
        return(NULL);
    }

    datasize = sizeof(DWORD);

    if ( RegQueryValueEx(hKey, L"DeviceArrayIndex", NULL, NULL,
                         (LPBYTE)&DevIndex, &datasize) ) {
        DEBUGMSG (ZONE_INIT | ZONE_ERROR,
                  (TEXT("Failed to get DeviceArrayIndex value, SERDMA_Init failed\r\n")));
        RegCloseKey (hKey);
        LocalFree(pSerialHead);
        return(NULL);
    }

    datasize = sizeof(DWORD);
    if ( RegQueryValueEx(hKey, L"Priority256", NULL, NULL,
                         (LPBYTE)&pSerialHead->Priority256, &datasize) ) {
        pSerialHead->Priority256 = DEFAULT_CE_THREAD_PRIORITY;
        DEBUGMSG (ZONE_INIT | ZONE_WARN,
                  (TEXT("Failed to get Priority256 value, defaulting to %d\r\n"), pSerialHead->Priority256));
    }

    datasize = sizeof(DWORD);
    if ( RegQueryValueEx(hKey, L"DMAChannel", NULL, NULL,
                         (LPBYTE)&DMAChannelNumber, &datasize) || DMAChannelNumber > 9) {
        DEBUGMSG (ZONE_INIT | ZONE_ERROR,
                  (TEXT("Failed to get DMAChannel value, SERDMA_Init failed\r\n")));
        RegCloseKey (hKey);
        LocalFree(pSerialHead);
        return(NULL);
    }

    RegCloseKey (hKey);

    DEBUGMSG (ZONE_INIT,
              (TEXT("DevIndex %X\r\n"), DevIndex));

    pSerialHead->hKillDispatchThread = CreateEvent(0, FALSE, FALSE, NULL); // auto reset, initially clear
    pSerialHead->hReadEvent = CreateEvent(0, TRUE, FALSE, NULL); // manual reset, initially clear
    pSerialHead->hReceiveBufferEmpty = CreateEvent(0, TRUE, TRUE, NULL); // manual reset, initially set
    wcscpy(ChannelEventName, L"channel0");
    ChannelEventName[7] = '0'+(WCHAR)DMAChannelNumber; // DMAChannelNumber has been validated to be 0...9 already.
    pSerialHead->hReceiveDataReady = CreateEvent(0, FALSE, FALSE, ChannelEventName); // set/reset by the DMA device itself.  The second and third args are ignored.
    if ( !pSerialHead->hKillDispatchThread ||
         !pSerialHead->hReadEvent ||
         !pSerialHead->hReceiveBufferEmpty ||
         !pSerialHead->hReceiveDataReady) {
        DEBUGMSG(ZONE_ERROR | ZONE_INIT,
                 (TEXT("Error creating event, SERDMA_Init failed\n\r")));
        LocalFree(pSerialHead);
        return NULL;
    }

    // Initialize hardware dependent data.
    pSerialHead->pHWObj = GetSerialObject( DevIndex );
    if ( !pSerialHead->pHWObj ) {
        DEBUGMSG(ZONE_ERROR | ZONE_INIT,
                 (TEXT("Error in GetSerialObject, SERDMA_Init failed\n\r")));
        LocalFree(pSerialHead);
        return NULL;
    }

    DEBUGMSG (ZONE_INIT, (TEXT("About to call HWInit(%s,0x%X)\r\n"),
                          Identifier, pSerialHead));
    pHWHead = pSerialHead->pHWObj->pFuncTbl->HWInit(Identifier, pSerialHead, pSerialHead->pHWObj);
    pSerialHead->pHWHead = pHWHead;

    /* Check that HWInit did stuff ok.  From here on out, call Deinit function
     * when things fail.
     */
    if ( !pHWHead ) {
        DEBUGMSG (ZONE_INIT | ZONE_ERROR,
                  (TEXT("Hardware doesn't init correctly, SERDMA_Init failed\r\n")));
        SERDMA_Deinit(pSerialHead);
        return NULL;
    }
    DEBUGMSG (ZONE_INIT,
              (TEXT("Back from hardware init\r\n")));

    if ( pSerialHead->pHWObj->BindFlags & THREAD_AT_INIT ) {
        // Hook the interrupt and start the associated thread.
        if ( ! StartDispatchThread( pSerialHead ) ) {
            // Failed on InterruptInitialize or CreateThread.  Bail.
            SERDMA_Deinit(pSerialHead);
            return NULL;
        }

    }

    // OK, now that everything is ready on our end, give the PDD
    // one last chance to init interrupts, etc.
    // For SERDMA, this opens the file HANDLE to the DMA device
    // instance.
    if (!pSerialHead->pHWObj->pFuncTbl->HWPostInit( pHWHead )) {
        SERDMA_Deinit(pSerialHead);
        return NULL;
    }

    DEBUGMSG (ZONE_INIT | ZONE_FUNCTION, (TEXT("-SERDMA_Init\r\n")));
    return pSerialHead;
}

/*
 @doc EXTERNAL
 @func          HANDLE | SERDMA_Open | Serial port driver initialization.
 *      Description: This routine must be called by the user to open the
 *      serial device. The HANDLE returned must be used by the application in
 *      all subsequent calls to the serial driver. This routine starts the thread
 *      which handles the serial events.
 *      Exported to users.
 *
 @rdesc This routine returns a HANDLE representing the device.
 */
HANDLE
SERDMA_Open(
        HANDLE  pHead,          // @parm Handle returned by SERDMA_Init.
        DWORD   AccessCode,     // @parm access code.
        DWORD   ShareMode       // @parm share mode - Not used in this driver.
        )
{
    PHW_INDEP_INFO  pSerialHead = (PHW_INDEP_INFO)pHead;
    PHW_OPEN_INFO   pOpenHead;
    PHWOBJ          pHWObj      = pSerialHead->pHWObj;

    DEBUGMSG (ZONE_OPEN|ZONE_FUNCTION, (TEXT("+SERDMA_Open handle x%X, access x%X, share x%X\r\n"),
                                        pHead, AccessCode, ShareMode));


    // Return NULL if SerialInit failed.
    if ( !pSerialHead ) {
        DEBUGMSG (ZONE_OPEN|ZONE_ERROR,
                  (TEXT("Open attempted on uninited device!\r\n")));
        SetLastError(ERROR_INVALID_HANDLE);
        return(NULL);
    }

    // Return NULL if opening with access & someone else already has
    if ( (AccessCode & (GENERIC_READ | GENERIC_WRITE)) &&
         pSerialHead->pAccessOwner ) {
        DEBUGMSG (ZONE_OPEN|ZONE_ERROR,
                  (TEXT("Open requested access %x, handle x%X already has x%X!\r\n"),
                   AccessCode, pSerialHead->pAccessOwner,
                   pSerialHead->pAccessOwner->AccessCode));
        SetLastError(ERROR_INVALID_ACCESS);
        return(NULL);
    }
    // OK, lets allocate an open structure
    pOpenHead    =  (PHW_OPEN_INFO)LocalAlloc(LPTR, sizeof(HW_OPEN_INFO));
    if ( !pOpenHead ) {
        DEBUGMSG(ZONE_INIT | ZONE_ERROR,
                 (TEXT("Error allocating memory for pOpenHead, SERDMA_Open failed\n\r")));
        return(NULL);
    }

    // Init the structure
    pOpenHead->pSerialHead = pSerialHead;  // pointer back to our parent
    pOpenHead->StructUsers = 0;
    pOpenHead->AccessCode = AccessCode;
    pOpenHead->ShareMode = ShareMode;
    pOpenHead->CommEvents.hCommEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    pOpenHead->CommEvents.fEventMask = 0;
    pOpenHead->CommEvents.fEventData = 0;
    pOpenHead->CommEvents.fAbort = 0;
        InitializeCriticalSection(&(pOpenHead->CommEvents.EventCS));

    // if we have access permissions, note it in pSerialhead
    if ( AccessCode & (GENERIC_READ | GENERIC_WRITE) ) {
        DEBUGMSG(ZONE_INIT|ZONE_CLOSE,
                 (TEXT("SERDMA_Open: Access permission handle granted x%X\n\r"),
                  pOpenHead));
        pSerialHead->pAccessOwner = pOpenHead;
    }

    // add this open entry to list of open entries.
    // Note that we hold the open CS for the duration of the routine since
    // all of our state info is in flux during this time.  In particular,
    // without the CS is would be possible for an open & close to be going on
    // simultaneously and have bad things happen like spinning a new event
    // thread before the old one was gone, etc.
    EnterCriticalSection(&(pSerialHead->OpenCS));
    InsertHeadList(&pSerialHead->OpenList,
                   &pOpenHead->llist);

    // If port not yet opened, we need to do some init
    if ( ! pSerialHead->OpenCnt ) {
        DEBUGMSG(ZONE_INIT|ZONE_OPEN,
                 (TEXT("SERDMA_Open: First open : Do Init x%X\n\r"),
                  pOpenHead));

        if ( pSerialHead->pHWObj->BindFlags & THREAD_AT_OPEN ) {
            DEBUGMSG(ZONE_INIT|ZONE_OPEN,
                     (TEXT("SERDMA_Open: Starting DispatchThread x%X\n\r"),
                      pOpenHead));
            // Hook the interrupt and start the associated thread.
            if ( ! StartDispatchThread( pSerialHead ) ) {
                // Failed on InterruptInitialize or CreateThread.  Bail.
                DEBUGMSG(ZONE_INIT|ZONE_OPEN,
                         (TEXT("SERDMA_Open: Failed StartDispatchThread x%X\n\r"),
                          pOpenHead));
                goto OpenFail;
            }
        }
        pHWObj->pFuncTbl->HWSetCommTimeouts(pSerialHead->pHWHead,
                                            &(pSerialHead->CommTimeouts));

        if ( !pHWObj->pFuncTbl->HWOpen(pSerialHead->pHWHead) ) {
            DEBUGMSG (ZONE_OPEN|ZONE_ERROR, (TEXT("HW Open failed.\r\n")));
            goto OpenFail;
        }

        pHWObj->pFuncTbl->HWPurgeComm(pSerialHead->pHWHead, PURGE_RXCLEAR);
        if ( pHWObj->BindFlags & THREAD_IN_MDD ) {
            CeSetThreadPriority(pSerialHead->pDispatchThread,
                                pSerialHead->Priority256);
        }
    }

    ++(pSerialHead->OpenCnt);

    // OK, we are finally back in a stable state.  Release the CS.
    LeaveCriticalSection(&(pSerialHead->OpenCS));

    DEBUGMSG (ZONE_OPEN|ZONE_FUNCTION, (TEXT("-SERDMA_Open handle x%X, x%X, Ref x%X\r\n"),
                                        pOpenHead, pOpenHead->pSerialHead, pSerialHead->OpenCnt));

    return pOpenHead;

OpenFail :
    DEBUGMSG (ZONE_OPEN|ZONE_FUNCTION, (TEXT("-SERDMA_Open handle x%X, x%X, Ref x%X\r\n"),
                                        NULL, pOpenHead->pSerialHead, pSerialHead->OpenCnt));

    SetLastError(ERROR_OPEN_FAILED);

    // If this was the handle with access permission, remove pointer
    if ( pOpenHead == pSerialHead->pAccessOwner )
        pSerialHead->pAccessOwner = NULL;

    // Remove the Open entry from the linked list
    RemoveEntryList(&pOpenHead->llist);

    // OK, everything is stable so release the critical section
    LeaveCriticalSection(&(pSerialHead->OpenCS));

    // Free all data allocated in open
    if ( pOpenHead->CommEvents.hCommEvent )
        CloseHandle(pOpenHead->CommEvents.hCommEvent);
        DeleteCriticalSection(&(pOpenHead->CommEvents.EventCS));
    LocalFree( pOpenHead );

    return NULL;
}

// ****************************************************************
//
//      @doc EXTERNAL
//
//      @func BOOL      | SERDMA_Close | close the serial device.
//
//      @parm DWORD | pHead             | Context pointer returned from SERDMA_Open
//
//      @rdesc TRUE if success; FALSE if failure
//
//      @remark This routine is called by the device manager to close the device.
//
//
//
BOOL
SERDMA_Close(PHW_OPEN_INFO pOpenHead)
{
    PHW_INDEP_INFO  pSerialHead = pOpenHead->pSerialHead;
    PHWOBJ          pHWObj;
    int i;
    BOOL            RetCode = TRUE;

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

    if ( !pSerialHead ) {
        DEBUGMSG (ZONE_ERROR, (TEXT("!!SERDMA_Close: 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 ) {
        --(pSerialHead->OpenCnt);

        DEBUGMSG (1, (TEXT("SERDMA_Close: (%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("SERDMA_Close: %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));

⌨️ 快捷键说明

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