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

📄 mdd.c

📁 SBC2410 WinCE 5.0 BSP.绝大多数驱动已经调通。
💻 C
📖 第 1 页 / 共 5 页
字号:
    }
    return(TRUE);
}

// ****************************************************************
//
//	@doc EXTERNAL
//	@func		HANDLE | COM_INIT | Serial device initialization.
//
//	@parm 		ULONG  | Identifier | Port identifier.  The device loader
//				passes in the registry key that contains information
//				about the active device.
//
//	@remark		This routine is called at device load time in order
//	 			to perform any initialization.	 Typically the init
//				routine does as little as possible, postponing memory
//				allocation and device power-on to Open time.
//
//	 @rdesc		Returns a pointer to the serial head which is passed into 
//	 			the COM_OPEN and COM_DEINIT entry points as a device handle.
//
HANDLE
COM_Init(
        ULONG   Identifier
        )
{
    PVOID           pHWHead     = NULL;
    PHW_INDEP_INFO  pSerialHead = NULL;
    ULONG           HWBufferSize;
    DWORD           DevIndex;
    HKEY            hKey;
    ULONG           kreserved = 0, kvaluetype;
    ULONG           datasize = sizeof(ULONG);

    /*
     *	INTERNAL: this routine initializes the hardware abstraction interface
     *	via HWInit(). It allocates a data structure representing this
     *	instantiation of the device. It also creates an event and initializes
     *	a critical section for receiving as well as registering the logical
     *	interrupt dwIntID with NK via InterruptInitialize. This call
     *	requires that the hardware dependent portion export apis that return
     *	the physical address of the receive buffer and the size of that buffer.
     *	Finally, it creates a buffer to act as an intermediate
     *	buffer when receiving.
     */
    DEBUGMSG (ZONE_INIT | ZONE_FUNCTION, (TEXT("+COM_Init\r\n")));

    // Allocate our control structure.
    pSerialHead  =  (PHW_INDEP_INFO)LocalAlloc(LPTR, sizeof(HW_INDEP_INFO));

    // Check that LocalAlloc did stuff ok too.
    if ( !pSerialHead ) {
        DEBUGMSG(ZONE_INIT | ZONE_ERROR,
                 (TEXT("Error allocating memory for pSerialHead, COM_Init failed\n\r")));
        return(NULL);
    }

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

    // Init CommTimeouts.
    pSerialHead->CommTimeouts.ReadIntervalTimeout = READ_TIMEOUT;
    pSerialHead->CommTimeouts.ReadTotalTimeoutMultiplier =
    READ_TIMEOUT_MULTIPLIER;
    pSerialHead->CommTimeouts.ReadTotalTimeoutConstant =
    READ_TIMEOUT_CONSTANT;
    pSerialHead->CommTimeouts.WriteTotalTimeoutMultiplier=  0;
    pSerialHead->CommTimeouts.WriteTotalTimeoutConstant =   0;

    /* Create tx and rx events and stash in global struct field. Check return.
     */
    pSerialHead->hSerialEvent = CreateEvent(0,FALSE,FALSE,NULL);
    pSerialHead->hKillDispatchThread = CreateEvent(0, FALSE, FALSE, NULL);
    pSerialHead->hTransmitEvent = CreateEvent(0, FALSE, FALSE, NULL);
    pSerialHead->hReadEvent = CreateEvent(0, FALSE, FALSE, NULL);

    if ( !pSerialHead->hSerialEvent || !pSerialHead->hKillDispatchThread ||
         !pSerialHead->hTransmitEvent || !pSerialHead->hReadEvent ) {
        DEBUGMSG(ZONE_ERROR | ZONE_INIT,
                 (TEXT("Error creating event, COM_Init failed\n\r")));
        LocalFree(pSerialHead);
        return(NULL);
    }

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

    /* 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, COM_Init failed\r\n")));
        LocalFree(pSerialHead);
        return(NULL);
    }

    datasize = sizeof(DWORD);

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

    datasize = sizeof(DWORD);
    if ( RegQueryValueEx(hKey, L"Priority256", NULL, &kvaluetype,
                         (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));
    }

    RegCloseKey (hKey);

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

    // Initialize hardware dependent data.
    pSerialHead->pHWObj = GetSerialObject( DevIndex );
    if ( !pSerialHead->pHWObj ) {
        DEBUGMSG(ZONE_ERROR | ZONE_INIT,
                 (TEXT("Error in GetSerialObject, COM_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, COM_Init failed\r\n")));
        COM_Deinit(pSerialHead);
        return(NULL);
    }
    DEBUGMSG (ZONE_INIT,
              (TEXT("Back from hardware init\r\n")));

    // Allocate at least twice the hardware buffer size so we have headroom
    HWBufferSize        = 2 * pSerialHead->pHWObj->pFuncTbl->HWGetRxBufferSize(pHWHead);

    // Init rx buffer and buffer length here.
    pSerialHead->RxBufferInfo.Length =
    HWBufferSize > RX_BUFFER_SIZE ? HWBufferSize:RX_BUFFER_SIZE;

    pSerialHead->RxBufferInfo.RxCharBuffer =
    LocalAlloc(LPTR, pSerialHead->RxBufferInfo.Length);

    if ( !pSerialHead->RxBufferInfo.RxCharBuffer ) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR,
                 (TEXT("Error allocating receive buffer, COM_Init failed\n\r")));
        COM_Deinit(pSerialHead);
        return(NULL);
    }

    DEBUGMSG (ZONE_INIT, (TEXT("RxHead init'ed\r\n")));

    RxResetFifo(pSerialHead);

    InitializeCriticalSection(&(pSerialHead->RxBufferInfo.CS));
    InitializeCriticalSection(&(pSerialHead->TxBufferInfo.CS));
    DEBUGMSG (ZONE_INIT, (TEXT("RxBuffer init'ed with start at %x\r\n"),
                          pSerialHead->RxBufferInfo.RxCharBuffer));

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

    }

    // OK, now that everything is ready on our end, give the PDD
    // one last chance to init interrupts, etc.
    (void) pSerialHead->pHWObj->pFuncTbl->HWPostInit( pHWHead );

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

/*
 @doc EXTERNAL
 @func		HANDLE | COM_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
COM_Open(
        HANDLE  pHead,          // @parm Handle returned by COM_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("+COM_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, COM_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("COM_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("COM_Open: First open : Do Init x%X\n\r"),
                  pOpenHead));

        if ( pSerialHead->pHWObj->BindFlags & THREAD_AT_OPEN ) {
            DEBUGMSG(ZONE_INIT|ZONE_OPEN,
                     (TEXT("COM_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("COM_Open: Failed StartDispatchThread x%X\n\r"),
                          pOpenHead));
                goto OpenFail;
            }
        }

        pSerialHead->RxBytes = 0;
        pSerialHead->TxBytes = 0;
        pSerialHead->TxBytesPending = 0;
        pSerialHead->DroppedBytesMDD = 0;
        pSerialHead->DroppedBytesPDD = 0;

        pSerialHead->DCB.DCBlength  = sizeof(DCB);
        pSerialHead->DCB.BaudRate   = 9600;
        pSerialHead->DCB.fBinary    = TRUE;
        pSerialHead->DCB.fParity    = FALSE;

        pSerialHead->DCB.fOutxCtsFlow = FALSE;
        pSerialHead->DCB.fOutxDsrFlow = FALSE;
//        pSerialHead->DCB.fDtrControl = FALSE; //DTR_CONTROL_ENABLE; -by HMSEO
        pSerialHead->DCB.fDtrControl = DTR_CONTROL_ENABLE; //-by HMSEO
        pSerialHead->DCB.fDsrSensitivity = FALSE;
        pSerialHead->DCB.fTXContinueOnXoff = FALSE;
        pSerialHead->DCB.fOutX      = FALSE;
        pSerialHead->DCB.fInX       = FALSE;
        pSerialHead->DCB.fErrorChar = FALSE; //NOTE: ignored
        pSerialHead->DCB.fNull      = FALSE; //NOTE: ignored
        pSerialHead->DCB.fRtsControl = FALSE; //RTS_CONTROL_ENABLE; -by HMSEO
        pSerialHead->DCB.fAbortOnError = FALSE; //NOTE: ignored

        pSerialHead->DCB.XonLim     = 512;
        pSerialHead->DCB.XoffLim    = 128;

        pSerialHead->DCB.ByteSize   = 8;
        pSerialHead->DCB.Parity     = NOPARITY;
        pSerialHead->DCB.StopBits   = ONESTOPBIT;

        pSerialHead->DCB.XonChar    = X_ON_CHAR;
        pSerialHead->DCB.XoffChar   = X_OFF_CHAR;
        pSerialHead->DCB.ErrorChar  = ERROR_CHAR;
        pSerialHead->DCB.EofChar    = E_OF_CHAR;
        pSerialHead->DCB.EvtChar    = EVENT_CHAR;

⌨️ 快捷键说明

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