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

📄 pl010ser.c

📁 EP931X系列的WinCE串口驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
{
    PSER16550_INFO  pSer16550 = &(((PSER_INFO)pHead)->ser16550);
    PAMBA_UART_INFO pSerAMBA  = &(((PSER_INFO)pHead)->serAMBA);
    USHORT        divisor = 0;
    UCHAR         lcr = 0;

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

    if ( divisor )
    {
      
       pSerAMBA->LCR_M = ((divisor & 0xFF00) >> 8);
       pSerAMBA->LCR_L = (divisor & 0xFF);
       OUTB(pSerAMBA, pUART_LCR_M, pSerAMBA->LCR_M);
       OUTB(pSerAMBA, pUART_LCR_L, pSerAMBA->LCR_L);

       // NOTE: Writes to LCR_M or LCR_L *must* be followed by a write to
       // LCR_H - this strobes the data into the 23-bit wide LCR register.
       //
       lcr = INB(pSerAMBA, pUART_LCR_H);
       OUTB(pSerAMBA, pUART_LCR_H, lcr);

       return( TRUE );
    
    } else {
        return( FALSE );
    }

}

//
// @doc OEM
// @func BOOL | SL_SetBaudRate |
//  This routine sets the baud rate of the device.
//
// @rdesc None.
//
BOOL
SL_SetBaudRate(
              PVOID   pHead,    // @parm     PVOID returned by HWInit
              ULONG   BaudRate    // @parm     ULONG representing decimal baud rate.
              )
{
    PSER16550_INFO  pSer16550 = &(((PSER_INFO)pHead)->ser16550);
    PAMBA_UART_INFO pSerAMBA  = &(((PSER_INFO)pHead)->serAMBA);
    BOOL fRet = FALSE;

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

    try {
        // Enter critical section before calling function, since
        // we can't make sys calls inside SetBaudRate
        EnterCriticalSection(&(pSer16550->RegCritSec));

        fRet = SetBaudRate(pHead, BaudRate);

        LeaveCriticalSection(&(pSer16550->RegCritSec));
    }except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
             EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        return( FALSE );
    }

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

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

//
// @doc OEM
// @func BOOL | SL_SetByteSize |
//  This routine sets the WordSize of the device.
//
// @rdesc None.
//
BOOL
SL_SetByteSize(
              PVOID   pHead,        // @parm     PVOID returned by HWInit
              ULONG   ByteSize    // @parm     ULONG ByteSize field from DCB.
              )
{
    PSER16550_INFO  pSer16550 = &(((PSER_INFO)pHead)->ser16550);
    PAMBA_UART_INFO pSerAMBA  = &(((PSER_INFO)pHead)->serAMBA);
    UINT8 lcr = 0;
    BOOL bRet = FALSE;

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

    bRet = TRUE;

    EnterCriticalSection(&(pSer16550->RegCritSec));
    try
    {
        lcr = INB(pSerAMBA, pUART_LCR_H);
        lcr &= AMBA_UART_BSIZE_MASK;
        switch ( ByteSize ) {
        case 5:
            lcr |= AMBA_UARTLCR_H_WLEN_5;
            break;
        case 6:
            lcr |= AMBA_UARTLCR_H_WLEN_6;
            break;
        case 7:
            lcr |= AMBA_UARTLCR_H_WLEN_7;
            break;
        case 8:
            lcr |= AMBA_UARTLCR_H_WLEN_8;
            break;
        default:
            bRet = FALSE;
            break;
        }
        if (bRet) {
            OUTB(pSerAMBA, pUART_LCR_H, lcr);
        }
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        bRet = FALSE;
    }
    LeaveCriticalSection(&(pSer16550->RegCritSec));

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

    return(bRet);
}
//
// @doc OEM
// @func BOOL | SL_SetParity |
//  This routine sets the parity of the device.
//
// @rdesc None.
//
BOOL
SL_SetParity(
            PVOID   pHead,    // @parm     PVOID returned by HWInit
            ULONG   Parity    // @parm     ULONG parity field from DCB.
            )
{
    PSER16550_INFO  pSer16550 = &(((PSER_INFO)pHead)->ser16550);
    PAMBA_UART_INFO pSerAMBA  = &(((PSER_INFO)pHead)->serAMBA);
    UINT8 lcr = 0;
    BOOL bRet = FALSE;

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

    bRet = TRUE;

    EnterCriticalSection(&(pSer16550->RegCritSec));
    try {
        lcr = INB(pSerAMBA, pUART_LCR_H);
        lcr &= AMBA_UART_PARITY_MASK;
        switch ( Parity ) {
        case ODDPARITY:
            lcr |= (AMBA_UARTLCR_H_PEN);
            break;

        case EVENPARITY:
            lcr |= (AMBA_UARTLCR_H_PEN | AMBA_UARTLCR_H_EPS);
            break;

        case MARKPARITY:
            DEBUGMSG(ZONE_WARN, (TEXT("SL_SetParity: MARKPARITY not supported.\r\n")));
            break;

        case SPACEPARITY:
            DEBUGMSG(ZONE_WARN, (TEXT("SL_SetParity: SPACEPARITY not supported.\r\n")));
            break;

        case NOPARITY:
            break;
        default:
            bRet = FALSE;
            break;
        }
        if (bRet)
        {
            OUTB(pSerAMBA, pUART_LCR_H, lcr);
        }
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        bRet = FALSE;
    }
    LeaveCriticalSection(&(pSer16550->RegCritSec));

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

    return(bRet);
}
//
// @doc OEM
// @func VOID | SL_SetStopBits |
//  This routine sets the Stop Bits for the device.
//
// @rdesc None.
//
BOOL
SL_SetStopBits(
              PVOID   pHead,      // @parm     PVOID returned by HWInit
              ULONG   StopBits  // @parm     ULONG StopBits field from DCB.
              )
{
    PSER16550_INFO  pSer16550 = &(((PSER_INFO)pHead)->ser16550);
    PAMBA_UART_INFO pSerAMBA  = &(((PSER_INFO)pHead)->serAMBA);
    UINT8 lcr = 0;
    BOOL bRet = FALSE;

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

    bRet = TRUE;

    EnterCriticalSection(&(pSer16550->RegCritSec));
    lcr = INB(pSerAMBA, pUART_LCR_H);
    lcr &= AMBA_UART_SBIT_MASK;

    try {
        // Note that 1.5 stop bits only works if the word size
        // is 5 bits.  Any other xmit word size will cause the
        // 1.5 stop bit setting to generate 2 stop bits.
        switch ( StopBits ) {
        case ONESTOPBIT :
            break;
        case ONE5STOPBITS :
            DEBUGMSG(ZONE_WARN, (TEXT("SL_SetStopBits: ONE5STOPBITS not supported.\r\n")));
            break;
        case TWOSTOPBITS :
            lcr |= AMBA_UARTLCR_H_STP2;
            break;
        default:
            bRet = FALSE;
            break;
        }

        if (bRet)
        {
            OUTB(pSerAMBA, pUART_LCR_H, lcr);
        }
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        bRet = FALSE;
    }

    LeaveCriticalSection(&(pSer16550->RegCritSec));

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

    return(bRet);
}

//
// @doc OEM
// @func ULONG | SL_GetRxBufferSize | This function returns
// the size of the hardware buffer passed to the interrupt
// initialize function.  It would be used only for devices
// which share a buffer between the MDD/PDD and an ISR.
//
// 
// @rdesc This routine always returns 0 for 16550 UARTS.
// 
ULONG
SL_GetRxBufferSize(
                  PVOID pHead
                  )
{
    return(0);
}

//
// @doc OEM
// @func PVOID | SC_GetRxStart | This routine returns the start of the hardware
// receive buffer.  See SL_GetRxBufferSize.
// 
// @rdesc The return value is a pointer to the start of the device receive buffer.
// 
PVOID
SL_GetRxStart(
             PVOID   pHead // @parm PVOID returned by SC_init.
             )
{
    return(NULL);
}

//
// @doc OEM
// @func ULONG | SL_GetGetInterruptType | This function is called
//   by the MDD whenever an interrupt occurs.  The return code
//   is then checked by the MDD to determine which of the four
//   interrupt handling routines are to be called.
// 
// @rdesc This routine returns a bitmask indicating which interrupts
//   are currently pending.
// 
INTERRUPT_TYPE
SL_GetInterruptType(
                   PVOID pHead      // Pointer to hardware head
                   )
{
    PSER16550_INFO  pSer16550 = &(((PSER_INFO)pHead)->ser16550);
    PAMBA_UART_INFO pSerAMBA  = &(((PSER_INFO)pHead)->serAMBA);
    INTERRUPT_TYPE interrupts;

    DEBUGMSG (0,
              (TEXT("+SL_GetInterruptType 0x%X\r\n"), pHead));
    try {
        pSerAMBA->IIR = INB(pSerAMBA, pUART_IIR);
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        pSerAMBA->IIR = 0; // simulate no interrupt
    }

    if ( !pSerAMBA->IIR ) {
        // No interrupts pending, vector is useless
        interrupts = INTR_NONE;
        DEBUGMSG(ZONE_WARN, (TEXT("SL_GetInterruptType: No Interrupt...\r\n")));
    } else {
        // The interrupt value is valid
// NOTE: Receive errors (e.g., Line Errors) don't generate an interrupt
// On the Integrator.  We need to check for errors at read time.
        pSerAMBA->IIR &= AMBA_UARTIIR_MASK;
        if (pSerAMBA->IIR & AMBA_UARTIIR_RIS)
            interrupts = INTR_RX;
        else if (pSerAMBA->IIR & AMBA_UARTIIR_TIS)
            interrupts = INTR_TX;
        else if (pSerAMBA->IIR & AMBA_UARTIIR_MIS)
            interrupts = INTR_MODEM;
        else if (pSerAMBA->IIR & AMBA_UARTIIR_RTIS)	// Receive Timeout
            interrupts = INTR_RX;
        else
            interrupts = INTR_NONE;
    }

    if (pSer16550->AddTXIntr) {
        interrupts |= INTR_TX;
        pSer16550->AddTXIntr = FALSE;
    }

    DEBUGMSG (ZONE_THREAD,
              (TEXT("-SL_GetInterruptType 0x%X, 0x%X\r\n"),
               pHead, interrupts));

    return(interrupts);
}


// @doc OEM
// @func ULONG | SL_RxIntr | This routine gets several characters from the hardware
//   receive buffer and puts them in a buffer provided via the second argument.
//   It returns the number of bytes lost to overrun.
// 
// @rdesc The return value indicates the number of overruns detected.
//   The actual number of dropped characters may be higher.
//
ULONG
SL_RxIntr(
         PVOID pHead,                // @parm Pointer to hardware head
         PUCHAR pRxBuffer,           // @parm Pointer to receive buffer
         ULONG *pBufflen             // @parm In = max bytes to read, out = bytes read
         )
{
    PSER16550_INFO  pSer16550 = &(((PSER_INFO)pHead)->ser16550);
    PAMBA_UART_INFO pSerAMBA  = &(((PSER_INFO)pHead)->serAMBA);
    ULONG        RetVal    = 0;
    ULONG        TargetRoom    = *pBufflen;
    BOOL        fRXFlag = FALSE;
    BOOL        fReplaceparityErrors = FALSE;
    BOOL        fNull;
    UCHAR       cEvtChar, cRXChar;

    DEBUGMSG (0, (TEXT("+GetBytes - len %d.\r\n"),
                  *pBufflen));
    *pBufflen = 0;

    // LAM - I have local copies of some DCB elements since I don't
    // want to keep dereferencing inside my read loop and there are too
    // many of them to trust the compiler.
    cEvtChar = pSer16550->dcb.EvtChar;
    fNull = pSer16550->dcb.fNull;
    if ( pSer16550->dcb.fErrorChar && pSer16550->dcb.fParity )
        fReplaceparityErrors = TRUE;

    try
    {
        while ( TargetRoom )
        {

            // See if there is another byte to be read
            //
            if (!(INB(pSerAMBA, pUART_FR) & AMBA_UARTFR_RXFE))
            {

⌨️ 快捷键说明

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