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

📄 bvd_ser16550.c

📁 cayman提供的PXA270 wince下的bsp源码包
💻 C
📖 第 1 页 / 共 5 页
字号:
    }
    LeaveCriticalSection(&(pHWHead->RegCritSec));

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

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

    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("+HW_XSC1_SetStopBits 0x%X, x%X\r\n"), pHead, StopBits));
//	DEBUGMSG (1, (TEXT("??????????????????+HW_XSC1_SetStopBits 0x%X, x%X\r\n"), pHead, StopBits));

    bRet = TRUE;

    EnterCriticalSection(&(pHWHead->RegCritSec));
    lcr = INB(pHWHead, pLCR);
    lcr &= ~SERIAL_STOP_MASK;

    try {

		HW_XSC1_DisableTxRx(pHead);

        // 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);
        }

		HW_XSC1_EnableTxRx(pHead);
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        bRet = FALSE;
    }

    LeaveCriticalSection(&(pHWHead->RegCritSec));

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

    return(bRet);
}

//
// @doc OEM
// @func ULONG | HW_XSC1_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 IRDASEL.
//
// 
// @rdesc This routine always returns 0 for 16550 UARTS.
// 
ULONG
HW_XSC1_GetRxBufferSize(
                  PVOID pHead
                  )
{
    return(0);
}

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

//
// @doc OEM
// @func ULONG | HW_XSC1_GetInterruptType | 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
HW_XSC1_GetInterruptType(
                   PVOID pHead      // Pointer to hardware head
                   )
{
    PSER16550_INFO    pHWHead = (PSER16550_INFO)pHead;
    INTERRUPT_TYPE interrupts = INTR_NONE;
	UINT           blr = 0;

//    DEBUGMSG (0,
//              (TEXT("+HW_XSC1_GetInterruptType 0x%X\r\n"), pHead));
//	DEBUGMSG (1, (TEXT("???????????????????+HW_XSC1_GetInterruptType 0x%X\r\n"), pHead));

    try {
        pHWHead->IIR = INB(pHWHead, pIIR_FCR);
		if (pHWHead->IOBase == BTUART_BASE_U_VIRTUAL)
		{

		}
		
//		DEBUGMSG (1, (TEXT("???????????????????+HW_XSC1_GetInterruptType: IIR %X\r\n"), pHWHead->IIR));
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        pHWHead->IIR = SERIAL_IIR_NO_INTERRUPT_PENDING; // simulate no interrupt
    }

    if ( pHWHead->IIR & SERIAL_IIR_NO_INTERRUPT_PENDING ) {
        // 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 :
            interrupts |= INTR_MODEM;
            break;

        default:
            interrupts = INTR_NONE;
            break;
        }
    }

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

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

    return(interrupts);
}


// @doc OEM
// @func ULONG | HW_XSC1_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
HW_XSC1_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;


    DEBUGMSG (0, (TEXT("+HW_XSC1_RxIntr - len %d.\r\n"),
                  *pBufflen));
//	DEBUGMSG (1, (TEXT("??????????????+HW_XSC1_RxIntr - 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 = 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
            HW_XSC1_ReadLSR( pHWHead );

           #ifdef UART_32_BIT_PERIPHERAL_BUS
		     //To do:
           #else
            if ( pHWHead->LSR & SERIAL_LSR_DR ) {
                
				// Read the byte
                cRXChar = (UCHAR) INB(pHWHead, pTHR_RBR_DLL);

				 DEBUGMSG (ZONE_READ | ZONE_THREAD,
                      (TEXT("HW_XSC1_RxIntrEx - Char Read %c\r\n"),
                       cRXChar));

                // DEBUGMSG (ZONE_READ | ZONE_WARN, (TEXT("Rx: %c\r\n"),cRXChar));
				
                // But we may want to discard it
                if ( pHWHead->dcb.fDsrSensitivity &&
                     (! (pHWHead->MSR & SERIAL_MSR_DSR)) ) {
                    // Do nothing - byte gets discarded
                    DEBUGMSG (ZONE_FLOW,
                              (TEXT("Dropping byte because DSR is low\r\n")));
                } else if (!cRXChar && fNull) {
                    // Do nothing - byte gets discarded
                    DEBUGMSG (ZONE_FLOW| ZONE_WARN,
                              (TEXT("Dropping NULL byte due to fNull\r\n")));
                } else {
                    // Do character replacement if parity error detected.
                    if ( fReplaceparityErrors && (pHWHead->LSR & SERIAL_LSR_PE) ) {
                        cRXChar = pHWHead->dcb.ErrorChar;
                    } else {
                        // See if we need to generate an EV_RXFLAG for the received char.
                        if ( cRXChar == cEvtChar )
                            fRXFlag = TRUE;
                    }

                    // Finally, we can get byte, update status and save.
                    *pRxBuffer++ = cRXChar;
                    (*pBufflen)++;
                    --TargetRoom;
                }
			} else {
                // We read all chars, so we're done
                break;
            }
            #endif
        }
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        // just exit
    }

    // if we saw one (or more) EVT chars, then generate an event
    if ( fRXFlag )
        pHWHead->EventCallback( pHWHead->pMddHead, EV_RXFLAG );

    if ( pHWHead->DroppedBytes )
        DEBUGMSG (ZONE_WARN, (TEXT("Rx drop %d.\r\n"),
                              pHWHead->DroppedBytes));

//	DEBUGMSG (1, (TEXT("-HW_XSC1_RxIntr - rx'ed %d, dropped %d.\r\n"),
//                  *pBufflen,
//                  pHWHead->DroppedBytes));


    RetVal = pHWHead->DroppedBytes;
    pHWHead->DroppedBytes = 0;
    return(RetVal);
}

//
// @doc OEM
// @func ULONG | HW_XSC1_TXIntrEx | This routine is called from the new MDD
//   whenever INTR_TX is returned by HW_XSC1_GetInterruptType
// 
// @rdesc None
//
VOID
HW_XSC1_TxIntrEx(
           PVOID pHead,                // Hardware Head
           PUCHAR pTxBuffer,          // @parm Pointer to receive buffer
           ULONG *pBufflen            // @parm In = max bytes to transmit, out = bytes transmitted
           )
{
    PSER16550_INFO   pHWHead    = (PSER16550_INFO)pHead;
    UCHAR       byteCount;
    ULONG NumberOfBytes = *pBufflen;
	//ULONG ier;

    DEBUGMSG (ZONE_THREAD, (TEXT("Transmit Event\r\n")));

    DEBUGMSG (ZONE_WRITE,
              (TEXT("+HW_XSC1_TxIntrEx 0x%X, Len %d\r\n"), pHead, *pBufflen));

//	DEBUGMSG (1, (TEXT("?????????????????+HW_XSC1_TxIntrEx 0x%X, Len %d\r\n"), pHead, *pBufflen));

	// We may be done sending.  If so, just disable the TX interrupts
    // and return to the MDD.  
    if( ! *pBufflen ) 
	{	
		if (pHWHead->bIr)
		{
		 //Enable rx and disable tx
		 HW_XSC1_Enable_IR_Rx_Tx(pHead, TRUE, FALSE);
        }

		DEBUGMSG (ZONE_WRITE, (TEXT("HW_XSC1_TxIntrEx: Disable INTR_TX.\r\n")));
		//Reflect change in pHWHead->IER
		pHWHead->IER = (IER_NORMAL_INTS|SERIAL_IER_UUE);
		//Uart should be left enabled also
		OUTB(pHWHead, pIER_DLH, (IER_NORMAL_INTS|SERIAL_IER_UUE));

/*		
        //#ifdef A1_Cotulla
		if( (pHWHead->ProcessorStepping == COTULLA_A1_CP15_VAL)  || (pHWHead->ProcessorStepping == SABINAL_A1_CP15_VAL) )
		{
		 //A1 Cotulla: Read IIR right after disabling Tx interrupt.
         pHWHead->IIR = INB(pHWHead, pIIR_FCR);
		}
        //#elif B0_Cotulla
		//else if(pHWHead->ProcessorStepping == COTULLA_B0_CP15_VAL)
		//{
			//B0 Cotulla: No need to read IIR right after disabling Tx interrupt. Fixed in B0 Si.
		//}
        //#endif
*/
		//DEBUGMSG (1, (TEXT("???????????????????-HW_XSC1_TxIntrEx: IER %X\r\n"), pHWHead->IER));
        return;
    }

    *pBufflen = 0;  // In case we don't send anything below.

    // Disable xmit intr.  Most 16550s will keep hammering
    // us with xmit interrupts if we don't turn them off
    // Whoever gets the FlushDone will then need to turn
    // TX Ints back on if needed.
    EnterCriticalSection(&(pHWHead->RegCritSec));
    try {
        // Need to signal FlushDone for XmitComChar
        PulseEvent(pHWHead->FlushDone);

        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 ) {
            //HW_XSC1_ReadMSR( pHWHead );
            // 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) ) {
                ULONG value;
                DEBUGMSG (ZONE_WRITE|ZONE_FLOW,
                          (TEXT("HW_XSC1_TxIntrEx, flowed off via CTS\n") ) );
                pHWHead->CTSFlowOff = TRUE;  // Record flowed off state
                value = INB(pHWHead, pIER_DLH);
                OUTB(pHWHea

⌨️ 快捷键说明

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