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

📄 xrser16550.c

📁 wince 5.0下 实现PCI8串口卡驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
// @func BOOL | XRSL_SetByteSize |
//  This routine sets the WordSize of the device.
//
// @rdesc None.
//
BOOL
XRSL_SetByteSize(
              PVOID   pHead,        // @parm     PVOID returned by HWInit
              ULONG   ByteSize    // @parm     ULONG ByteSize field from DCB.
              )
{
    PSER16550_INFO    pHWHead = (PSER16550_INFO)pHead;
    UINT8 lcr;
    BOOL bRet;

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

    bRet = TRUE;

    EnterCriticalSection(&(pHWHead->RegCritSec));
    try {
        lcr = INB(pHWHead, pLCR);
        lcr &= ~SERIAL_DATA_MASK;
        switch ( ByteSize ) {
        case 5:
            lcr |= SERIAL_5_DATA;
            break;
        case 6:
            lcr |= SERIAL_6_DATA;
            break;
        case 7:
            lcr |= SERIAL_7_DATA;
            break;
        case 8:
            lcr |= SERIAL_8_DATA;
            break;
        default:
            bRet = FALSE;
            break;
        }
        if (bRet) {
            OUTB(pHWHead, pLCR, lcr);
        }
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        bRet = FALSE;
    }
    LeaveCriticalSection(&(pHWHead->RegCritSec));

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

    return(bRet);
}
//
// @doc OEM
// @func BOOL | XRSL_SetParity |
//  This routine sets the parity of the device.
//
// @rdesc None.
//
BOOL
XRSL_SetParity(
            PVOID   pHead,    // @parm     PVOID returned by HWInit
            ULONG   Parity    // @parm     ULONG parity field from DCB.
            )
{
    PSER16550_INFO    pHWHead = (PSER16550_INFO)pHead;
    UINT8 lcr;
    BOOL bRet;

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

    bRet = TRUE;

    EnterCriticalSection(&(pHWHead->RegCritSec));
    try {
        lcr = INB(pHWHead, pLCR);
        lcr &= ~SERIAL_PARITY_MASK;
        switch ( Parity ) {
        case ODDPARITY:
            lcr |= SERIAL_ODD_PARITY;
            break;

        case EVENPARITY:
            lcr |= SERIAL_EVEN_PARITY;
            break;

        case MARKPARITY:
            lcr |= SERIAL_MARK_PARITY;
            break;

        case SPACEPARITY:
            lcr |= SERIAL_SPACE_PARITY;
            break;

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

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

    return(bRet);
}
//
// @doc OEM
// @func VOID | XRSL_SetStopBits |
//  This routine sets the Stop Bits for the device.
//
// @rdesc None.
//
BOOL
XRSL_SetStopBits(
              PVOID   pHead,      // @parm     PVOID returned by HWInit
              ULONG   StopBits  // @parm     ULONG StopBits field from DCB.
              )
{
    PSER16550_INFO    pHWHead = (PSER16550_INFO)pHead;
    UINT8 lcr;
    BOOL bRet;

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

    bRet = TRUE;

    EnterCriticalSection(&(pHWHead->RegCritSec));
    lcr = INB(pHWHead, pLCR);
    lcr &= ~SERIAL_STOP_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 :
            lcr |= SERIAL_1_STOP ;
            break;
        case ONE5STOPBITS :
            lcr |= SERIAL_1_5_STOP ;
            break;
        case TWOSTOPBITS :
            lcr |= SERIAL_2_STOP ;
            break;
        default:
            bRet = FALSE;
            break;
        }

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

    LeaveCriticalSection(&(pHWHead->RegCritSec));

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

    return(bRet);
}

//
// @doc OEM
// @func ULONG | XRSL_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
XRSL_GetRxBufferSize(
                  PVOID pHead
                  )
{
    return(0);
}

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

//
// @doc OEM
// @func ULONG | XRSL_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
XRSL_GetInterruptType(
                   PVOID pHead      // Pointer to hardware head
                   )
{
    PSER16550_INFO    pHWHead = (PSER16550_INFO)pHead;
    INTERRUPT_TYPE interrupts=INTR_NONE;
	BOOL bContinue;

    DEBUGMSG (0,
              (TEXT("+XRSL_GetInterruptType 0x%X\r\n"), pHead));
    do {
        bContinue = FALSE;
        if (pHWHead->bSuspendResume) {
            pHWHead->bSuspendResume = FALSE;
            pHWHead->EventCallback( pHWHead->pMddHead, EV_POWER );
        }
        if (pHWHead->pIsrInfoVirt!=NULL) { 
            if ( pHWHead->pReceiveBuffer && GetRcvDataSize(pHWHead->pReceiveBuffer)>0) {
                pHWHead->IIR=pHWHead->pReceiveBuffer->bBuffer[pHWHead->pReceiveBuffer->dwFIFO_Out].bIntFlag;
            }
            else
                pHWHead->IIR=SERIAL_IIR_INT_INVALID;
        }
        else
        try {
            pHWHead->IIR = INB(pHWHead, pIIR_FCR);
        }
        except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
                EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
            pHWHead->IIR = SERIAL_IIR_INT_INVALID; // simulate no interrupt
        }
        DEBUGMSG (ZONE_THREAD,
                  (TEXT("+XRSL_GetInterruptType IIR=%x\r\n"),pHWHead->IIR ));
        if ( pHWHead->IIR & SERIAL_IIR_INT_INVALID ) {
            // No interrupts pending, vector is useless
            interrupts = INTR_NONE;
        } else {

            // The interrupt value is valid
            switch ( pHWHead->IIR & SERIAL_IIR_INT_MASK ) {
            case SERIAL_IIR_RLS:
                if (pHWHead->pIsrInfoVirt) {
                    pHWHead->LSR=pHWHead->pReceiveBuffer->bBuffer[pHWHead->pReceiveBuffer->dwFIFO_Out].bIntData;
                    pHWHead->pReceiveBuffer->dwFIFO_Out=IncRcvIndex(pHWHead->pReceiveBuffer,pHWHead->pReceiveBuffer->dwFIFO_Out);
                    ProcessLSR (pHWHead);
                    bContinue=TRUE;
                }
                else
                    interrupts |= INTR_LINE;
                break;
            case SERIAL_IIR_CTI:
            case SERIAL_IIR_CTI_2:
            case SERIAL_IIR_RDA:
                interrupts = INTR_RX;
                break;

            case SERIAL_IIR_THRE :
                interrupts = INTR_TX;
                if (pHWHead->pIsrInfoVirt) {
                    pHWHead->pReceiveBuffer->dwFIFO_Out=IncRcvIndex(pHWHead->pReceiveBuffer,pHWHead->pReceiveBuffer->dwFIFO_Out);
                }
                break;
            case SERIAL_IIR_MS :
                if (pHWHead->pIsrInfoVirt) {
                    pHWHead->MSR=pHWHead->pReceiveBuffer->bBuffer[pHWHead->pReceiveBuffer->dwFIFO_Out].bIntData;
                    pHWHead->pReceiveBuffer->dwFIFO_Out=IncRcvIndex(pHWHead->pReceiveBuffer,pHWHead->pReceiveBuffer->dwFIFO_Out);
                    ProcessMSR (pHWHead);
                    bContinue=TRUE;
                }
                else
                    interrupts = INTR_MODEM;
                break;

            default:
                if (pHWHead->pIsrInfoVirt) {
                    pHWHead->pReceiveBuffer->dwFIFO_Out=IncRcvIndex(pHWHead->pReceiveBuffer,pHWHead->pReceiveBuffer->dwFIFO_Out);
                }
                interrupts = INTR_NONE;
                break;
            }
        }
        if (pHWHead->pIsrInfoVirt) {
            if (pHWHead->pReceiveBuffer && GetRcvDataSize(pHWHead->pReceiveBuffer)>0) { //Data available.
                interrupts |= INTR_RX;
            };
        }
        if (pHWHead->AddTXIntr) {
            interrupts |= INTR_TX;
            pHWHead->AddTXIntr = FALSE;
        }
    }while (bContinue && interrupts == INTR_NONE);
    DEBUGMSG (ZONE_THREAD,
              (TEXT("-XRSL_GetInterruptType 0x%X, 0x%X\r\n"),
               pHead, interrupts));

    return(interrupts);
}


// @doc OEM
// @func ULONG | XRSL_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
XRSL_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   pHWHead    = (PSER16550_INFO)pHead;
    ULONG        RetVal    = 0;
    ULONG        TargetRoom    = *pBufflen;
    BOOL        fRXFlag = FALSE;
    BOOL        fReplaceparityErrors = FALSE;
    BOOL        fNull;
    UCHAR       cEvtChar, cRXChar;
	ULONG *pRxBuf;
    *pBufflen = 0;

	pRxBuf = (ULONG*)pRxBuffer;

    // 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 = pHWHead->dcb.EvtChar;
    fNull = pHWHead->dcb.fNull;
    if ( pHWHead->dcb.fErrorChar && pHWHead->dcb.fParity )
        fReplaceparityErrors = TRUE;

    try {
        while ( TargetRoom ) {
            // See if there is another byte to be read
            if (pHWHead->pIsrInfoVirt && pHWHead->pReceiveBuffer) { // Soft FIFO
                if (GetRcvDataSize(pHWHead->pReceiveBuffer)>0 ) {
                    UCHAR uIntFlag = pHWHead->pReceiveBuffer->bBuffer[pHWHead->pReceiveBuffer->dwFIFO_Out].bIntFlag & SERIAL_IIR_INT_MASK;
                    if ( uIntFlag==SERIAL_IIR_CTI || uIntFlag==SERIAL_IIR_CTI_2 || uIntFlag==SERIAL_IIR_RDA ) {
                        cRXChar = pHWHead->pReceiveBuffer->bBuffer[pHWHead->pReceiveBuffer->dwFIFO_Out].bIntData;
                        pHWHead->pReceiveBuffer->dwFIFO_Out=IncRcvIndex(pHWHead->pReceiveBuffer,pHWHead->pReceiveBuffer->dwFIFO_Out);
                    }
                    else
                        break;
                }

⌨️ 快捷键说明

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