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

📄 ser_card.c

📁 wince下的串口驱动源码
💻 C
📖 第 1 页 / 共 3 页
字号:
// @func BOOL | SC_PostInit | This routine does nothing, because
//          we do our init/postinit processing from SC_Open
//
BOOL
SC_PostInit(
         PVOID   pHead // @parm PVOID returned by SC_init.
         )
{
#ifdef DEBUG
    PSER_CARD_INFO  pHWHead = (PSER_CARD_INFO)pHead;
    DEBUGMSG (ZONE_FUNCTION, (TEXT("SC_POSTINIT\r\n") ));
#endif

    return (TRUE);
}
//
// @doc OEM
// @func ULONG | SC_Close | This routine closes the device identified
// by pHead.
// 
// @rdesc The return value is 0 if successful, -1 if failed.
//
ULONG
SC_Close(
        PVOID   pHead   // @parm PVOID returned by SC_Init.
        )
{
    PSER_CARD_INFO  pHWHead = (PSER_CARD_INFO)pHead;
    ULONG  uTries;
    ULONG retval = 0;

    DEBUGMSG (ZONE_FUNCTION, (TEXT("+SC_CLOSE\r\n") ));
    if ( pHWHead->cOpenCount ) {
        pHWHead->cOpenCount--;

        if ( ! pHWHead->cOpenCount ) {
            // while we are still transmitting, sleep.
            uTries = 0;

			// If this close is not cause by PowerCycle . We will do follows.
			// otherwise the IO port disappeareed after PCMCIA power cycle.
			if (pHWHead->fPowerCycle!=TRUE ) {
				while ( ((pHWHead->ser16550.IER = READ_PORT_UCHAR(pHWHead->ser16550.pIER)) 
					& SERIAL_IER_THR) &&  // indicates TX in progress
                    (uTries++ < 100) &&                            // safety net
                    !(pHWHead->ser16550.LSR & SERIAL_LSR_TEMT)     // indicates FIFO not yet empty
					) {
					DEBUGMSG (ZONE_CLOSE, 
						(TEXT("SerClose, TX in progress, IER 0x%X, LSR 0x%X\r\n"),
						*pHWHead->ser16550.pIER, pHWHead->ser16550.LSR));
					Sleep(10);
				}
				// Note: We can not call SL_Close when PCMCIA close the driver after power cycle.
				// because SL_Close access IO to mask all the interrupt. Of cause this moment 
				// IO space disappeared.
				// It is OK that we do not call SL_Close here. Only thing is wrong is OpenCount..
				// But we always call SL_Init & SL_Open  or SL_Close & SL_Deinit togather. And
				// SL_Deinit does not checking OpenCound So OpenCound will be initial to zero in SL_Init.
	            SL_Close( pHWHead );
			};
				

            // NOTE : To save power, SL_Init was postponed and called
            // from SC_Open.  To maintain symmetry, I then need to call
            // SL_Deinit here, otherwise we leak handles and perhaps
            // do other bad things.
            SL_Deinit( pHWHead );


            // Free up all PCMCIA objects/handles by deregistering
            CallCardServices(CardDeregisterClient) (pHWHead->hCardClient);
        } else {
            // If someone else still has device open, we don't do anything.
            DEBUGMSG (ZONE_CLOSE|ZONE_ERROR, (TEXT("SC_CLOSE : Open Count > 1, do nothing\r\n")) );
        }
    } else {
        DEBUGMSG (ZONE_CLOSE|ZONE_ERROR, (TEXT("SC_CLOSE : Open Count == 0, not performing close\r\n")) );
        retval = (ULONG)-1;
    }

    DEBUGMSG (ZONE_FUNCTION, (TEXT("+SC_CLOSE\r\n") ));
    return (retval);
}

//
// @doc OEM
// @func	VOID | SC_GetCommProperties | Retrieves Comm Properties.
// 
// @rdesc	None.
//
VOID
SC_GetCommProperties(
                    PVOID   pHead,      // @parm PVOID returned by SC_Init. 
                    LPCOMMPROP  pCommProp   // @parm Pointer to receive COMMPROP structure. 
                    )
{
    PSER_CARD_INFO  pHWHead = (PSER_CARD_INFO)pHead;

    memcpy(pCommProp, &pHWHead->CommProp, sizeof(COMMPROP));
    return;
}

//
// @doc OEM
// @func BOOL | SC_SetBaudRate |
//  This routine sets the baud rate of the device.
// 
// @rdesc None.
//
BOOL
SC_SetBaudRate(
              PVOID   pHead,  // @parm     PVOID returned by SC_Init
              ULONG   BaudRate    // @parm     ULONG representing decimal baud rate.
              )
{
    PSER_CARD_INFO  pHWHead = (PSER_CARD_INFO)pHead;

    // If we are running in IR mode, try to set the IR baud
    // first, since it supports a subset of the rates supported
    // by the UART.  If we fail setting the IR rate, then
    // return an error and leave the UART alone.
    if ( pHWHead->fIRMode ) {
        if ( ! SC_SetIRBaudRate( pHWHead, (UINT16)BaudRate ) ) {
            DEBUGMSG (ZONE_ERROR,
                      (TEXT("Unsupported IR BaudRate\r\n")));
            // We should return an error, but vtbl doesn't expect one
            return (FALSE); 
        }
    }

    // Now set buadrate on the UART
    SL_SetBaudRate( pHead, BaudRate );    

    return ( TRUE );

}

//
// @doc OEM
// @func BOOL | SC_PowerOff |
//   Called by driver to turn off power to serial port.
// 
// @rdesc TRUE if success, FALSE if fail.
//
BOOL
SC_PowerOff(
           PVOID   pHead       // @parm	PVOID returned by SC_Init.
           )
{
    return (TRUE);
}

//
// @doc OEM
// @func BOOL | SC_PowerOn |
//   Called by driver to turn on power to serial port.
// 
// @rdesc TRUE if success, FALSE if fail.
//
BOOL
SC_PowerOn(
          PVOID   pHead       // @parm	PVOID returned by SC_Init.
          )
{
    PSER_CARD_INFO  pHWHead = (PSER_CARD_INFO)pHead;
	pHWHead->fPowerCycle=TRUE; 
    return (TRUE);
}

//
// @doc OEM
// @func BOOL | SC_EnableIR | This routine enables the ir.
// 
// @rdesc Returns FALSE since IR not supported on PCMCIA.
//
BOOL
SC_EnableIR(
           PVOID   pHead, // @parm PVOID returned by SC_init.
           ULONG   BaudRate  // @parm BaudRate
           )
{
    return (FALSE);
}

//
// @doc OEM
// @func BOOL | SC_DisableIR | This routine disables the ir.
// 
// @rdesc Returns TRUE if successful, FALSE if failed.
//
BOOL
SC_DisableIR(
            PVOID   pHead // @parm PVOID returned by SC_init.
            )
{
    return (TRUE);
}

//
// @doc OEM
// @func BOOL | SC_Deinit | This routine disables the ir.
// 
// @rdesc Returns TRUE if successful, FALSE if failure.
//
BOOL
SC_Deinit(
         PVOID   pHead // @parm PVOID returned by SC_init.
         )
{
    PSER_CARD_INFO  pHWHead = (PSER_CARD_INFO)pHead;

    if ( !pHWHead )
        return (FALSE);

    // Make sure device is closed before doing DeInit
    if ( pHWHead->cOpenCount )
        SC_Close( pHead );

    // Free the HWObj
    LocalFree(pHWHead->pHWObj);

    LocalFree(pHWHead);
    return (TRUE);
}

//
// @doc OEM
// @func BOOL | SC_DisableIR | This routine disables the ir.
// 
// @rdesc Returns TRUE if successful, FALSEotherwise.
//
BOOL
SC_Open(
       PVOID   pHead // @parm PVOID returned by SC_init.
       )
{
    PSER_CARD_INFO  pHWHead = (PSER_CARD_INFO)pHead;
    STATUS status;

    DEBUGMSG (ZONE_FUNCTION, (TEXT("+SC_OPEN\r\n") ));

    // Lets do the rest of the card initialization
    if ( ! InitPCMCIACard( pHWHead, pHWHead->pMddHead ) ) {
        DEBUGMSG (ZONE_OPEN|ZONE_ERROR, (TEXT("SC_OPEN - Failed to init card\r\n")));
        return (FALSE);
    }

    // Some PCMCIA cards require an additional delay upon reset. We
    // read this value from the registry on card init and sleep here.
    DEBUGMSG (ZONE_INIT,(TEXT("SC_OPEN - Sleep %d ms\r\n"),
                         pHWHead->ResetDelay));
    Sleep(pHWHead->ResetDelay);

    // Init 16550 info.  Note that we do both SL_INIT and SL_OPEN
    // This is an unfortunate side effect of PCMCIA.  As soon as
    // I do a CardRequestConfig, I start drawing power.  So we postpone
    // that till here (in the open).  But, SL_INIT needs our card
    // address space in his init routine, and we don't get the address
    // till after the request config.  So till we come up with a better
    // idea for power enable/disable on PCMCIA, we will have to couple
    // SL_INIT and SL_OPEN.  
    SL_Init( pHWHead, pHWHead->pCardIOWin, (UINT8)pHWHead->IO_Granularity,
             EvaluateEventFlag, pHWHead->pMddHead, NULL);
    DEBUGMSG (ZONE_INIT, (TEXT("SC_OPEN - Init 16550 data\r\n")));

    // SL_Init sets up pointers to all the UART registers,
    // but some cards don't have a scratch register.  So we need to override
    // the scratch pointer just in case someone tries to use this register.
    if ( pHWHead->NoScratchPad )
        pHWHead->ser16550.pScratch = &pHWHead->FakeScratchPad;

    // Make sure the card is responding correctly.  Some cards have had
    // problems where all registers read back as 0.  This can cause us to
    // infinite loop handling serial interrupts (0 indicates interrupt in
    // the ISR).  So we will write to the scratch register and make sure
    // we can read the value back.
    if ( !pHWHead->NoScratchPad ) {
    #define SCRATCH_PATTERN 0xC6        
        WRITE_PORT_UCHAR(pHWHead->ser16550.pScratch, SCRATCH_PATTERN);
        // Stick something else on bus, otherwise
        // even if no UART is there we may read back the C6
        WRITE_PORT_UCHAR(pHWHead->ser16550.pIER, 0x0);
        // And now see if the scratch register was really there.
        if ( SCRATCH_PATTERN != READ_PORT_UCHAR(pHWHead->ser16550.pScratch) ) {
            // Card is not responding.  Return error for the open.
            DEBUGMSG (ZONE_OPEN|ZONE_ERROR, (TEXT("SC_OPEN - ERROR : UART not responding\r\n")));       

            // Free up all PCMCIA objects/handles by deregistering
            CallCardServices(CardDeregisterClient) (pHWHead->hCardClient);

            return (FALSE);
        }
    }

    pHWHead->ser16550.ChipID = CHIP_ID_16550;

    // Register to receive PCMCIA interrupts for this card
    status = CallCardServices(CardRequestIRQ)( pHWHead->hCardClient,
                                               pHWHead->hCardSock,
                                               (CARD_ISR)SerialEventHandler,
                                               (UINT32)pHWHead->pMddHead );

    DEBUGMSG (ZONE_INIT, (TEXT("RequestIRQ returned 0x%X\r\n"),
                          status ));

    // Now that interrupts are hooked, we can actually finish
    // initing the UART and open it for use.
    SL_PostInit( pHWHead );
    SL_Open( pHWHead );

    DEBUGMSG (ZONE_INIT, (TEXT("SC_OPEN - Selecting Non IR Mode\r\n")));
    pHWHead->fIRMode  = FALSE;   // Select wired by default
    SC_SetIRMode(pHWHead, pHWHead->fIRMode );  

	if (!(pHWHead->cOpenCount)) { // If it it first open. Clean the flag
		pHWHead->fPowerCycle  = FALSE;
	}

    // OK, the device is open, so increment the counter.
    pHWHead->cOpenCount++;

    DEBUGMSG (ZONE_FUNCTION, (TEXT("-SC_OPEN\r\n") ));

    return (TRUE);
}

const
HW_VTBL SerCardIoVTbl = {
    SC_Init,
    SC_PostInit,
    SC_Deinit,
    SC_Open,
    SC_Close,
    SL_GetInterruptType,
    SL_RxIntr,
    SL_TxIntrEx,
    SL_ModemIntr,
    SL_LineIntr,
    SL_GetRxBufferSize,
    SC_PowerOff,
    SC_PowerOn,
    SL_ClearDTR,
    SL_SetDTR,
    SL_ClearRTS,
    SL_SetRTS,
    SC_EnableIR,
    SC_DisableIR,
    SL_ClearBreak,
    SL_SetBreak,
    SL_XmitComChar,
    SL_GetStatus,
    SL_Reset,
    SL_GetModemStatus,
    SC_GetCommProperties,
    SL_PurgeComm,
    SL_SetDCB,
    SL_SetCommTimeouts,
    SL_Ioctl};

⌨️ 快捷键说明

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