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

📄 serio.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
📖 第 1 页 / 共 4 页
字号:
            if( pHWHead->dcb.fDsrSensitivity && (!(pHWHead->MSR & SERIAL_MSR_DSR)) ){
                // Do nothing - byte gets discarded.
                DEBUGMSG(ZONE_FUNCTION, (TEXT("GetByte DSR Sensitivity!!\r\n")));
            }
            else {
                // Get byte, update status and save.
                    ++pTargetBuffer;
                    (*pByteNumber)++;
                    --TargetRoom;
            }
        }
        else {
            // We read all chars, so we're done
            DEBUGMSG(ZONE_FUNCTION, (TEXT("GetByte DSR OFF!!\r\n")));
            break;
        }
    }

    
    RetVal = pHWHead->DroppedBytes;
    pHWHead->DroppedBytes = 0;
    LeaveCriticalSection(&(pHWHead->CS));

    return RetVal;
}

// *********************************************************************
//
//  @doc OEM
//
//  @func PVOID | HWGetRxStart |
//      This routine returns the start of the hardware receive buffer.
//      Required by NK Interrupt support.
//
//  @parm PVOID | pHead | PDD device context (returned from HWInit())
//
//  @rdesc The return value is a pointer to the start of the device
//      receive buffer.
//
//  @remark This parameter is passed to the InterruptInitialize() call
//      in the HAL.  It was intended for the ISR to handle receive
//      characters in a fast path but is currently unused.
//**********************************************************************
PVOID
HWGetRxStart(PVOID  pHead)
{
    DEBUGMSG(ZONE_FUNCTION, (TEXT("Serial PDD: Enter HWGetRxStart\r\n")));

    return NULL;
}

// ***************************************************************************
//
//  @doc OEM
//
//  @func INTERRUPT_TYPE | HWGetIntrType | Returns the current interrupt type.
//
//  @parm PVOID | pHead | PDD device context (returned from HWInit())
//
//  @rdesc  The interrupt type.
//
//  @remark This is called by the MDD to determine what type of interrupt
//          occured.
//*****************************************************************************
INTERRUPT_TYPE
HWGetIntrType( PVOID   pHead )
{
    PPERP_IO_SER_INFO   pHWHead = (PPERP_IO_SER_INFO)pHead;
    INTERRUPT_TYPE      interrupts = INTR_NONE;
    ULONG               win32status = 0;
    USHORT CMUClkMsk;                                       // @BUGBUG
    USHORT aaa;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("Serial PDD: Enter HWGetIntrType\r\n")));

    CMUClkMsk = REG16(VRCmuRegs.cmuclkmsk);
    InterlockedAndOr16(pVRIO+CMUCLKMSK, 0xFFFF, MSKSIU | MSKSSIU);

    EnterCriticalSection(&(pHWHead->CS));

    pHWHead->IIR = REG8(ASICSiuRegs.siuiid_fc);
    DEBUGMSG(ZONE_FUNCTION, (TEXT("Intr = 0x%x\r\n"), pHWHead->IIR));

    if( pHWHead->IIR & SERIAL_IIR_INT_INVALID ){
        HWReadLSR(pHWHead);

        if( pHWHead->LSR & SERIAL_LSR_DR ){

                interrupts = INTR_RX;
        }
        else {
            // 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:
                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;
                break;

            case SERIAL_IIR_MS :
                pHWHead->MSR = REG8(ASICSiuRegs.siums);
                interrupts = INTR_MODEM;
                break;

            default:
                HWReadLSR( pHWHead );
                
                if( pHWHead->LSR & SERIAL_LSR_DR ){

                    interrupts = INTR_RX;
                }
                else {

                    interrupts = INTR_NONE;
                }
                break;
        }
    }

    if (REG16(VRGiuRegs.giuintstat) & DCDINTR) {

        READ_VALUE16(aaa, VRGiuRegs.giuintalsell);
        aaa ^= DCDINTR;
        WRITE_VALUE16(VRGiuRegs.giuintalsell, aaa);
        REG16(VRGiuRegs.giuintstat) = DCDINTR;
        pHWHead->DCDWakeUp = TRUE;
        interrupts = INTR_MODEM;
    }

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

    // Check for power status.
    if (pHWHead->fPowerOff == 1) {

        pHWHead->fPowerOff = 0;
        win32status |= EV_POWER;
        EvaluateEventFlag(pHWHead->pMddHead, win32status);
    }

//  if (!(CMUClkMsk & (MSKSIU | MSKSSIU))) {
    if (!(CMUClkMsk & MSKSSIU)) {
        
//      DISABLE_BITS16(VRCmuRegs.cmuclkmsk, MSKSIU | MSKSSIU);
        DISABLE_BITS16(VRCmuRegs.cmuclkmsk, MSKSSIU);
    }

    LeaveCriticalSection(&(pHWHead->CS));

    DEBUGMSG(ZONE_FUNCTION, (TEXT("Interrupt = 0x%x\r\n"), interrupts));

    return interrupts;
}

// **********************************************************************
//
//  @doc OEM
//
//  @func VOID | HWClearOtherIntr |
//      This routine clears the status bits assoicated with a
//      modem status interrupt.  On standard UARTS, the MODEM interrupt
//      covers events DCTS, DDSR, RI and DDCD. The PeRP hardware
//      only supports DDSR and DCTS. DDCD and RI are handled by a
//      check in getIntrType.
//
//  @rdesc None.
//**********************************************************************
VOID
HWClearOtherIntr(
    PVOID pHead /*@parm     PVOID returned by HWInit */
    )
{
    PPERP_IO_SER_INFO   pHWHead = (PPERP_IO_SER_INFO)pHead;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("Serial PDD: Enter HWClearOtherIntr\r\n")));

    HWReadMSR( pHWHead );

    // If we are currently flowed off via CTS or DSR, then
    // we better signal the TX thread when one of them changes
    // so that TX can resume sending.

    if ( pHWHead->DSRFlowOff && (pHWHead->MSR & SERIAL_MSR_DSR) ){

        pHWHead->DSRFlowOff = FALSE;

        // DSR is set, so go ahead and resume sending

        ENABLE_BITS8(ASICSiuRegs.siuie, SERIAL_IER_RDA | SERIAL_IER_RLS
                        | SERIAL_IER_MS | SERIAL_IER_THR);

        // Then simulate a TX intr to get things moving
        pHWHead->AddTXIntr = TRUE;
        DEBUGMSG(ZONE_FUNCTION, (TEXT("AddTXIntr = TRUE for DSRFlow\r\n")));
    }

    if ( pHWHead->CTSFlowOff && (pHWHead->MSR & SERIAL_MSR_CTS) ){

        pHWHead->CTSFlowOff = FALSE;

        // CTS is set, so go ahead and resume sending

        ENABLE_BITS8(ASICSiuRegs.siuie, SERIAL_IER_RDA | SERIAL_IER_RLS
                        | SERIAL_IER_MS | SERIAL_IER_THR);

        // Then simulate a TX intr to get things moving
        DEBUGMSG(ZONE_FUNCTION, (TEXT("AddTXIntr = TRUE for CTSFlow\r\n")));
        pHWHead->AddTXIntr = TRUE;
    }
}

// ****************************************************************
//
//  @doc OEM
//
//  @func VOID | HWClearLineIntr |
//      This routine clears the status bits for line events
//      (parity, break, framing, overrun). This applies to most
//      standard UARTS, but since the PeRP hardware doesn't
//      have a corresponding interrupt, we do nothing here.
//
//  @rdesc None.
//******************************************************************
VOID
HWClearLineIntr(
    PVOID pHead /*@parm     PVOID returned by HWInit */
    )
{
    PPERP_IO_SER_INFO   pHWHead = (PPERP_IO_SER_INFO)pHead;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("Serial PDD: Enter HWClearLineIntr\r\n")));

    HWReadLSR( pHWHead );
}

// ****************************************************************************
//
//  @doc OEM
//
//  @func ULONG | HWGetRxBufferSize |
//          This routine returns the maximal number of bytes the hardware
//          buffer can hold, not counting the padding, stop, start bits, etc.
//
//  @rdesc  Returns the number of bytes in the hardware receive queue.
//*****************************************************************************
ULONG
HWGetRxBufferSize(
    PVOID   pHead       /*@parm     PVOID returned by HWInit */
    )
{

    DEBUGMSG(ZONE_FUNCTION, (TEXT("Serial PDD: Enter HWGetRxBufferSize\r\n")));

    return 0;
}

// ************************************************************************
//
//  @doc OEM
//
//  @func VOID | HWTxIntrHandler | This routine handles the tx interrupt.
//
//  @parm PVOID | pHead | PDD device context (returned from HWInit())
//
//  @rdesc  This routine cleas the transmit status bit in the hardware CSR
//          and performs some internal bookkeeping so that HWPutBytes will
//          send data. It is called when the driver detects a transmit
//          interrupt as set by HWGetIntrType.
//**************************************************************************
VOID
HWTxIntrHandler(
    PVOID   pHead
    )
{
    PPERP_IO_SER_INFO pHWHead = (PPERP_IO_SER_INFO)pHead;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("Serial PDD: Enter HWTxIntrHandler\r\n")));

    if ( pHWHead->IrMode ){

        while(TRUE){
            HWReadLSR( pHWHead );
            
            if( pHWHead->LSR & SERIAL_LSR_TEMT ){
            
                break;
            }
        }

        REG8(ASICSiuRegs.siuiid_fc) = SERIAL_FCR_RCVR_RESET;

        REG8(ASICSiuRegs.siuiid_fc) = pHWHead->FCR;

        ENABLE_BITS8(ASICSiuRegs.siuie, SERIAL_IER_RDA);
    
        DISABLE_BITS8(ASICSiuRegs.siumc, SERIAL_MCR_RTS);
    }

    DISABLE_BITS8(ASICSiuRegs.siuie, SERIAL_IER_THR);
    
    // Let the putbytes routine know he can continue
    PulseEvent(pHWHead->FlushDone);
}

// ****************************************************************
//
//  @doc    OEM
//  @func   ULONG | HWPutBytes |
//          Called by driver to write bytes to hardware.
//
//  @rdesc  This function returns 0, or the minimum number of milliseconds
//          before the mdd layer should call again.  This is used if the
//          device does not support indications of modem lines for hardware
//          flow control.  Thus the MDD layer will call again to see if
//          the flow control condition has been removed.  Without much
//          testing I've used 10msecs as the wait period.  Perhaps this
//          value should be tuned.
//**********************************************************************
ULONG
HWPutBytes(
    PVOID   pHead,          /*@parm PVOID returned by HWInit. */
    PUCHAR  pSrc,           /*@parm Pointer to bytes to be sent. */
    ULONG   NumberOfBytes,  /*@parm Number of bytes to be sent. */
    PULONG  pBytesSent      /*@parm Pointer to actual number of bytes put. */
    )
{
    PPERP_IO_SER_INFO   pHWHead        = (PPERP_IO_SER_INFO)pHead;
    UCHAR       byteCount;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("Serial PDD: Enter HWPutBytes\r\n")));
    DEBUGMSG(ZONE_FUNCTION, (TEXT("NumberOfBytes = %d\r\n"), NumberOfBytes));

    *pBytesSent = 0;
    
        pHWHead->CommErrors &= ~CE_TXFULL;
    
    // If CTS flow control is desired, check cts. If clear, don't send,
    // but loop.  When CTS comes back on, the OtherInt routine will
    // detect this and re-enable TX interrupts (causing Flushdone).
    // For finest granularity, we would check this in the loop below,
    // but for speed, I check it here (up to 8 xmit characters before
    // we actually flow off.

    if ( pHWHead->dcb.fOutxCtsFlow ){

        // We don't need to explicitly read the MSR, since we always enable
        // IER_MS, which ensures that we will get an interrupt and read
        // the MSR whenever CTS, DSR, TERI, or DCD change.

        if(! (pHWHead->MSR & SERIAL_MSR_CTS) ){

            DEBUGMSG(ZONE_FUNCTION, (TEXT("CSTFlow = TRUE\r\n")));
            pHWHead->CTSFlowOff = TRUE;  // Record flowed off state

            DISABLE_BITS8(ASICSiuRegs.siuie, SERIAL_IER_THR);

            // We could return a positive value here, which would
            // cause the MDD to periodically check the flow control
            // status.  However, we don't need to since we know that
            // the DCTS interrupt will cause the MDD to call us, and we
            // will subsequently fake a TX interrupt to the MDD, causing
            // him to call back into PutBytes.

            return 0;
            }
    }

    // Same thing applies for DSR
    if ( pHWHead->dcb.fOutxDsrFlow ){

        // We don't need to explicitly read the MSR, since we always enable
        // IER_MS, which ensures that we will get an interrupt and read
        // the MSR whenever CTS, DSR, TERI, or DCD change.

        if(! (pHWHead->MSR & SERIAL_MSR_DSR) ){

            DEBUGMSG(ZONE_FUNCTION, (TEXT("DSRFlow = TRUE\r\n")));
            pHWHead->DSRFlowOff = TRUE;  // Record flowed off state

            DISABLE_BITS8(ASICSiuRegs.siuie, SERIAL_IER_THR);

            // See the comment above above positive return codes.
            

⌨️ 快捷键说明

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