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

📄 xrser16550.c

📁 wince 5.0下 实现PCI8串口卡驱动
💻 C
📖 第 1 页 / 共 5 页
字号:

//
// @doc OEM 
// @func PVOID | XRSL_Init | Initializes 16550 device head.  
//
VOID
XRSL_Init(
       PVOID   pHead, // @parm points to device head
       PUCHAR  pRegBase, // Pointer to 16550 register base
       UINT8   RegStride, // Stride amongst the 16550 registers
       EVENT_FUNC EventCallback, // This callback exists in MDD
       PVOID   pMddHead,   // This is the first parm to callback
       PLOOKUP_TBL   pBaudTable  // BaudRate Table
       )
{
    PSER16550_INFO   pHWHead   = (PSER16550_INFO)pHead;

    DEBUGMSG (ZONE_CLOSE,(TEXT("+XRSL_INIT, 0x%X\r\n"), pHWHead));

    // Set up pointers to 16550 registers
    pHWHead->pData    = pRegBase + (RegStride * RECEIVE_BUFFER_REGISTER);
    pHWHead->pIER     = pRegBase + (RegStride * INTERRUPT_ENABLE_REGISTER);
    pHWHead->pIIR_FCR = pRegBase + (RegStride * INTERRUPT_IDENT_REGISTER);
    pHWHead->pLCR     = pRegBase + (RegStride * LINE_CONTROL_REGISTER);
    pHWHead->pMCR     = pRegBase + (RegStride * MODEM_CONTROL_REGISTER);
    pHWHead->pLSR     = pRegBase + (RegStride * LINE_STATUS_REGISTER);
    pHWHead->pMSR     = pRegBase + (RegStride * MODEM_STATUS_REGISTER);
    pHWHead->pScratch = pRegBase + (RegStride * SCRATCH_REGISTER);

    // Store info for callback function
    pHWHead->EventCallback = EventCallback;
    pHWHead->pMddHead = pMddHead;

    // Now set up remaining fields
    if ( pBaudTable != NULL )
        pHWHead->pBaudTable = (LOOKUP_TBL *) pBaudTable;
    else
        pHWHead->pBaudTable = (LOOKUP_TBL *) &LS_BaudTable;
    pHWHead->FlushDone      = CreateEvent(0, FALSE, FALSE, NULL);

    pHWHead->OpenCount = 0;

    // Don't allow any interrupts till PostInit.
    OUTB(pHWHead, pIER, (UCHAR)0);

    InitializeCriticalSection(&(pHWHead->TransmitCritSec));
    InitializeCriticalSection(&(pHWHead->RegCritSec));
	pHWHead->PowerDown = FALSE;
    pHWHead->bSuspendResume = FALSE;
    InstallSoftwareISR(pHWHead,pHWHead->pVirtualStaticAddr,RegStride);
	
    // Clear any interrupts which may be pending.  Normally only
    // happens if we were warm reset.
    ClearPendingInts( pHWHead );

    DEBUGMSG (ZONE_CLOSE,(TEXT("-XRSL_INIT, 0x%X\r\n"), pHWHead));
}

//
// @doc OEM
// @func void | XRSL_PostInit | This routine takes care of final initialization.
//
// @rdesc None.
//
BOOL
XRSL_PostInit(
           PVOID   pHead // @parm PVOID returned by HWinit.
           )
{
    PSER16550_INFO   pHWHead   = (PSER16550_INFO)pHead;

    DEBUGMSG (ZONE_INIT,(TEXT("+XRSL_PostInit, 0x%X\r\n"), pHWHead));
    
    // Since we are just a library which might get used for 
    // builtin ports which init at boot, or by PCMCIA ports
    // which init at Open, we can't do anything too fancy.
    // Lets just make sure we cancel any pending interrupts so
    // that if we are being used with an edge triggered PIC, he
    // will see an edge after the MDD hooks the interrupt.
    ClearPendingInts( pHWHead );
    
    DEBUGMSG (ZONE_INIT,(TEXT("-XRSL_PostInit, 0x%X\r\n"), pHWHead));
    return(TRUE);
}

//
// @doc OEM 
// @func PVOID | XRSL_Deinit | De-initializes 16550 device head.  
//
VOID
XRSL_Deinit(
         PVOID   pHead // @parm points to device head
         )
{
    PSER16550_INFO   pHWHead   = (PSER16550_INFO)pHead;

    DEBUGMSG (ZONE_CLOSE,(TEXT("+XRSL_DEINIT, 0x%X\r\n"), pHWHead));
    UninstallSoftwareISR( pHWHead);
    DeleteCriticalSection(&(pHWHead->TransmitCritSec));
    DeleteCriticalSection(&(pHWHead->RegCritSec));

    // Free the flushdone event
    if ( pHWHead->FlushDone )
        CloseHandle( pHWHead->FlushDone );

    DEBUGMSG (ZONE_CLOSE,(TEXT("-XRSL_DEINIT, 0x%X\r\n"), pHWHead));
}

//
// @doc OEM
// @func void | XRSL_ClearDtr | This routine clears DTR.
//
// @rdesc None.
//
VOID
XRSL_ClearDTR(
           PVOID   pHead // @parm PVOID returned by HWinit.
           )
{
    PSER16550_INFO   pHWHead   = (PSER16550_INFO)pHead;

    DEBUGMSG (ZONE_FUNCTION, (TEXT("+XRSL_ClearDTR, 0x%X\r\n"), pHead));
    EnterCriticalSection(&(pHWHead->RegCritSec));
    try {
        unsigned char byte;

        byte = INB((PSER16550_INFO)pHead, pMCR);
        OUTB((PSER16550_INFO)pHead, pMCR, byte & ~SERIAL_MCR_DTR);
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        // Just exit
    }
    LeaveCriticalSection(&(pHWHead->RegCritSec));

    DEBUGMSG (ZONE_FUNCTION, (TEXT("-XRSL_ClearDTR, 0x%X\r\n"), pHead));
}

//
// @doc OEM
// @func VOID | XRSL_SetDTR | This routine sets DTR.
// 
// @rdesc None.
//
VOID
XRSL_SetDTR(
         PVOID   pHead // @parm PVOID returned by HWinit.
         )
{    
    PSER16550_INFO   pHWHead   = (PSER16550_INFO)pHead;

    DEBUGMSG (ZONE_FUNCTION, (TEXT("+XRSL_SetDTR, 0x%X\r\n"), pHead));
    EnterCriticalSection(&(pHWHead->RegCritSec));
    try {
        unsigned char byte;

        byte = INB((PSER16550_INFO)pHead, pMCR);
        OUTB((PSER16550_INFO)pHead, pMCR, byte | SERIAL_MCR_DTR);
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        // Just exit
    }
    LeaveCriticalSection(&(pHWHead->RegCritSec));

    DEBUGMSG (ZONE_FUNCTION, (TEXT("-XRSL_SetDTR, 0x%X\r\n"), pHead));
}

//
// @doc OEM
// @func VOID | XRSL_ClearRTS | This routine clears RTS.
// 
// @rdesc None.
// 
VOID
XRSL_ClearRTS(
           PVOID   pHead // @parm PVOID returned by HWinit.
           )
{
    PSER16550_INFO   pHWHead   = (PSER16550_INFO)pHead;

    DEBUGMSG (ZONE_FUNCTION, (TEXT("+XRSL_ClearRTS, 0x%X\r\n"), pHead));
    EnterCriticalSection(&(pHWHead->RegCritSec));
    try {
        unsigned char byte;

        byte = INB((PSER16550_INFO)pHead, pMCR);
        OUTB((PSER16550_INFO)pHead, pMCR, byte & ~SERIAL_MCR_RTS);
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        // Just exit
    }
    LeaveCriticalSection(&(pHWHead->RegCritSec));

    DEBUGMSG (ZONE_FUNCTION, (TEXT("-XRSL_ClearRTS, 0x%X\r\n"), pHead));
}

//
// @doc OEM
// @func VOID | XRSL_SetRTS | This routine sets RTS.
// 
// @rdesc None.
//
VOID
XRSL_SetRTS(
         PVOID   pHead // @parm PVOID returned by HWinit.
         )
{
    PSER16550_INFO   pHWHead   = (PSER16550_INFO)pHead;

    DEBUGMSG (ZONE_FUNCTION, (TEXT("+XRSL_SetRTS, 0x%X\r\n"), pHead));

    EnterCriticalSection(&(pHWHead->RegCritSec));
    try {
        unsigned char byte;

        byte = INB((PSER16550_INFO)pHead, pMCR);
        OUTB((PSER16550_INFO)pHead, pMCR, byte | SERIAL_MCR_RTS);
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        // Just exit
    }
    LeaveCriticalSection(&(pHWHead->RegCritSec));

    DEBUGMSG (ZONE_FUNCTION, (TEXT("-XRSL_SetRTS, 0x%X\r\n"), pHead));
}

//
// @doc OEM
// @func VOID | XRSL_ClearBreak | This routine clears break.
// 
// @rdesc None.
// 
VOID
XRSL_ClearBreak(
             PVOID   pHead // @parm PVOID returned by HWinit.
             )
{
    PSER16550_INFO   pHWHead   = (PSER16550_INFO)pHead;

    DEBUGMSG (ZONE_FUNCTION, (TEXT("+XRSL_ClearBreak, 0x%X\r\n"), pHead));

    EnterCriticalSection(&(pHWHead->RegCritSec));
    try {
        unsigned char byte;

        byte = INB((PSER16550_INFO)pHead, pLCR);
        OUTB((PSER16550_INFO)pHead, pLCR, byte & ~SERIAL_LCR_BREAK);
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        // Just exit
    }
    LeaveCriticalSection(&(pHWHead->RegCritSec));

    DEBUGMSG (ZONE_FUNCTION, (TEXT("-XRSL_ClearBreak, 0x%X\r\n"), pHead));
}

//
// @doc OEM
// @func VOID | XRSL_SetBreak | This routine sets break.
// 
// @rdesc None.
//
VOID
XRSL_SetBreak(
           PVOID   pHead // @parm PVOID returned by HWinit.
           )
{
    PSER16550_INFO   pHWHead   = (PSER16550_INFO)pHead;

    DEBUGMSG (ZONE_FUNCTION, (TEXT("+XRSL_SetBreak, 0x%X\r\n"), pHead));

    EnterCriticalSection(&(pHWHead->RegCritSec));
    try {
        unsigned char byte;

        byte = INB((PSER16550_INFO)pHead, pLCR);
        OUTB((PSER16550_INFO)pHead, pLCR, byte | SERIAL_LCR_BREAK);
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        // Just exit
    }
    LeaveCriticalSection(&(pHWHead->RegCritSec));

    DEBUGMSG (ZONE_FUNCTION, (TEXT("-XRSL_SetBreak, 0x%X\r\n"), pHead));
}

//
// SetBaudRate
//
// Internal function.  The only real reason for splitting this out
// is so that we can call it from PowerOn and still allow XRSL_SetBaud
// to do debug messages, acquire critical sections, etc.
//
BOOL
SetBaudRate(
           PVOID   pHead,
           ULONG   BaudRate
           )
{
    PSER16550_INFO    pHWHead = (PSER16550_INFO)pHead;
    USHORT        divisor;
    UCHAR        lcr;	

    // **** Warning ***** Make no system calls, called in power context
    divisor = DivisorOfRate(pHead, BaudRate);

    if ( divisor ) {
       InterruptMask(pHWHead->dwSysIntr,TRUE);
       lcr = INB(pHWHead, pLCR);
       OUTB(pHWHead, pLCR, lcr | SERIAL_LCR_DLAB);
       OUTB(pHWHead, pData, divisor & 0xff); //pData is DivLatch Lo
       OUTB(pHWHead, pIER, (divisor >> 8) & 0xff); //pIER is DivLatch Hi
       OUTB(pHWHead, pLCR, lcr);
       InterruptMask(pHWHead->dwSysIntr,FALSE);
       return( TRUE );
    
    } else {
        return( FALSE );
    }

}

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

    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("+XRSL_SetbaudRate 0x%X, x%X\r\n"), pHead, BaudRate));

    try {
        // Enter critical section before calling function, since
        // we can't make sys calls inside SetBaudRate
        EnterCriticalSection(&(pHWHead->RegCritSec));
        fRet = SetBaudRate(pHead, BaudRate);
        LeaveCriticalSection(&(pHWHead->RegCritSec));
    }except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
             EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        return( FALSE );
    }

    if ( fRet ) {
        pHWHead->dcb.BaudRate = BaudRate;

        DEBUGMSG (ZONE_FUNCTION,
                  (TEXT("-XRSL_SetbaudRate 0x%X (%d Baud)\r\n"),
                   pHead, BaudRate));
        return( TRUE );
    } else {
        DEBUGMSG (ZONE_FUNCTION | ZONE_ERROR,
                  (TEXT("-XRSL_SetbaudRate - Error setting %d, failing to %d\r\n"),
                   BaudRate, pHWHead->dcb.BaudRate) );
        return( FALSE );
    }
}

//
// @doc OEM

⌨️ 快捷键说明

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