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

📄 bvd_ser_pdd.c

📁 PXA27X_CAYMAN BSP from CAYMAN board
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright ?1999 Intel Corp.  */
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995-1998  Microsoft Corporation

Module Name:  

  bvd_ser_pdd.c

Abstract:  

Notes: 
--*/
#include <windows.h>
#include <types.h>
#include <ceddk.h>
#include <memory.h>
#include <serhw.h>
#include "Bvd1.h" 
#include "bvd_ser16550.h" 
#include "bvd_ser_pdd.h"
#include "bvd1bd.h"     
#include <nkintr.h>
#include <oalintr.h>
#include <devload.h>
#undef ZONE_INIT
#include <serdbg.h>

// #define DBGMSG
#define DBGMSG NKDbgPrintfW

#include "bvd_serbaud.h"

//-----------------------------------------------------------------
// EXTERNAL FUNCTIONS
//-----------------------------------------------------------------
//Set the Sandgate's BCR (Board Control Register)
extern BOOL set_BCRVal(unsigned my_bcrSetBits, unsigned my_bcrClrBits, BOOL inpowerhandler);

void XSC1_EnableIRTranceiver(PSER_PDD_INFO pHWHead,BOOL bHighSpeed);
//void usWait(unsigned usVal);
//#define IRTransceiverLatchDelay() (usWait(1))  // needs to be > 200 ns


#ifdef USE_NEW_SERIAL_MODEL


// Miscellaneous internal routines.
// ****************************************************************
//
//      @doc INTERNAL
//
//      @func VOID              | XSC1_SerPDDInternalMapRegisterAddresses |
//              This routine maps the ASIC registers. It's an artifact of this
//              implementation.
//
//      @rdesc BOOL.
//
BOOL XSC1_SerPDDInternalMapRegisterAddresses(PSER_PDD_INFO pHWHead)
{
    PUCHAR  pVMem;
    ULONG   err = 0;
    
    
    //Map the harware registers.
    pVMem = (PUCHAR)VirtualAlloc(0,PAGE_SIZE*5,MEM_RESERVE,PAGE_NOACCESS);
    
	if (pVMem)
    {
        DEBUGMSG(ZONE_INIT,(TEXT("VirtualAlloc Succeeded\r\n")));
        
        //Map the UART space
        if (!VirtualCopy((LPVOID)pVMem,(LPVOID)pHWHead->dwIOBase,PAGE_SIZE,PAGE_READWRITE | PAGE_NOCACHE))
        {
            err = GetLastError();
            DEBUGMSG(ZONE_ERROR,(TEXT("Virtual Copy: Serial SPACE FAILED\r\n")));
			return(FALSE);
        }
        pHWHead->pBaseAddress= (PULONG) pVMem;
        pVMem+=PAGE_SIZE;
        
        //Map the GPIO space
        if (!VirtualCopy((LPVOID)pVMem,(LPVOID)GPIO_BASE_U_VIRTUAL,PAGE_SIZE,PAGE_READWRITE | PAGE_NOCACHE))
        {
            err = GetLastError();
            DEBUGMSG(ZONE_ERROR,(TEXT("Virtual Copy: GPIO SPACE FAILED\r\n")));
			return(FALSE);
        }
        //pHWHead->pGPIOReg=(volatile GPIO_REGS *)pVMem;
		pHWHead->pGPIOReg=(volatile XLLP_GPIO_T *)pVMem;
        pVMem+=PAGE_SIZE;
        
        //Map the IRQ space
        if (!VirtualCopy((LPVOID)pVMem,(LPVOID)INTC_BASE_U_VIRTUAL,PAGE_SIZE,PAGE_READWRITE | PAGE_NOCACHE))
        {
            err = GetLastError();
            DEBUGMSG(ZONE_ERROR,(TEXT("Virtual Copy: IRQ SPACE FAILED\r\n")));
			return(FALSE);
        }
        //pHWHead->pINTCReg=(volatile INTC_REGS *)pVMem;
		pHWHead->pINTCReg=(volatile XLLP_INTC_T *)pVMem;
        pVMem+=PAGE_SIZE;

		//Map the Clock Manager space
        if (!VirtualCopy((LPVOID)pVMem,(LPVOID)CLK_BASE_U_VIRTUAL,PAGE_SIZE,PAGE_READWRITE | PAGE_NOCACHE))
        {
            err = GetLastError();
            DEBUGMSG(ZONE_ERROR,(TEXT("Virtual Copy: Clock Manager SPACE FAILED\r\n")));
			return(FALSE);
        }
		pHWHead->pClkMgrReg = (volatile XLLP_CLKMGR_T *)pVMem;
        pVMem+=PAGE_SIZE;

    }
    else
    {
        DEBUGMSG(ZONE_ERROR,(TEXT("Virtual Alloc: FAILED\r\n")));
		return(FALSE);
    }
    
	DEBUGMSG(ZONE_INIT,(TEXT("VirtualCopy Succeeded, pVMem:%x\r\n"),pVMem));
	return(TRUE); 
}

// ****************************************************************
//
//      @doc INTERNAL
//
//      @func VOID  | XSC1_SerPDDSetOutputMode |
//              This routine selects normal serial or IR mode. 
//              It's an artifact of this implementation.
//
//      @rdesc None.
//        
//     NOTE : The caller should have set pHWHead->fIRMode.  It is not
//     set here, since power on/off may need to temporarily disable the 
//     intefaces without actually overwriting the current recorded mode.
//

static void XSC1_SerPDDSetOutputMode(PSER_PDD_INFO pHWHead,BOOL UseIR,BOOL Use9Pin)
{    
    // Here the interface is set to either IR mode
    // or normal serial. Note that it is possible for both BOOLs to
    // be false (i.e. power down), but never for both to be TRUE.
    DEBUGMSG(ZONE_FUNCTION,(TEXT("+XSC1_SerPDDSetOutputMode\r\n")));
    
	//Using this routine to enable/disable IR settings only
	if (UseIR)  //IR mode
    {   
     HW_XSC1_Enable_Uart_IR(pHWHead,0);
    }
	else if (!UseIR)  //IR mode
    {   
     HW_XSC1_Enable_Uart_IR(pHWHead,1);
    }

}


/*++
*******************************************************************************
Routine:

    XSC1_SerPDDGetRegistryData

Description:

    Take the registry path provided to COM_Init and use it to find this 
    requested comm port's DeviceArrayIndex, te IOPort Base Address, and the
   Interrupt number.
   
Arguments:

    LPCTSTR regKeyPath  the registry path passed in to COM_Init.

Return Value:

    -1 if there is an error.

*******************************************************************************
--*/
BOOL XSC1_SerPDDGetRegistryData(PSER_PDD_INFO pHWHead, LPCTSTR regKeyPath)
{
#define GCI_BUFFER_SIZE 256   

    LONG    regError;
    HANDLE  hKey;
    DWORD   dwDataSize = GCI_BUFFER_SIZE;
    
    DEBUGMSG(ZONE_FUNCTION,(TEXT("XSC1_SerPDDGetRegistryData() Try to open %s\r\n"),regKeyPath));

    hKey = OpenDeviceKey((LPCTSTR)regKeyPath);
    if ( !hKey ) {
        DEBUGMSG (ZONE_ERROR, (TEXT("Failed to open %s\r\n"),regKeyPath));
        return(FALSE); 
    }

    // Okay, we're finally ready to try and load our registry data.
    dwDataSize = XSC1_REG_DEVINDEX_VAL_LEN;
    regError = RegQueryValueEx(hKey,XSC1_REG_DEVINDEX_VAL_NAME,NULL,NULL,(LPBYTE)(&pHWHead->dwDevIndex),&dwDataSize);
    if (regError == ERROR_SUCCESS)
    {
        dwDataSize = XSC1_REG_IRQ_VAL_LEN;
        regError = RegQueryValueEx(hKey,XSC1_REG_IRQ_VAL_NAME,NULL,NULL,(LPBYTE)(&pHWHead->dwIRQ),&dwDataSize);
    }
    if (regError == ERROR_SUCCESS)
    {
        dwDataSize = XSC1_REG_IOBASE_VAL_LEN;
        regError = RegQueryValueEx(hKey,XSC1_REG_IOBASE_VAL_NAME,NULL,NULL,(LPBYTE)(&pHWHead->dwIOBase),&dwDataSize);
    }

    if (regError == ERROR_SUCCESS)
    {
        dwDataSize = XSC1_REG_IOLEN_VAL_LEN;
        regError = RegQueryValueEx(hKey,XSC1_REG_IOLEN_VAL_NAME,NULL,NULL,(LPBYTE)(&pHWHead->dwIOLen),&dwDataSize);
    }
    RegCloseKey (hKey);
    if (regError != ERROR_SUCCESS)
    {
        DEBUGMSG(ZONE_ERROR,(TEXT("Failed to get serial registry values, Error 0x%X\r\n"),regError));
        return(FALSE);
    }
    DEBUGMSG(ZONE_INIT,(TEXT("XSC1_SerPDDGetRegistryData - Index 0x%x, Base 0x%x, Len 0x%x, Irq 0x%x\r\n"),
                        pHWHead->dwDevIndex,pHWHead->dwIOBase,pHWHead->dwIOLen,pHWHead->dwIRQ));
    return(TRUE); 
}


/*
 @doc OEM 
 @func PVOID | XSC1_SerPDDInit_ | Initializes device identified by argument.
 *  This routine sets information controlled by the user
 *  such as Line control and baud rate. It can also initialize events and
 *  interrupts, thereby indirectly managing initializing hardware buffers.
 *  Exported only to driver, called only once per process.
 *
 *  NOTE: This routine is called for both normal serial and IR initialization.
 *  Right now, contains initialization code for normal serial serial only.
 *  Code for IR initialization to be added later.
 *
 *  @rdesc The return value is a PVOID to be passed back into the HW
 *         dependent layer when HW functions are called.
 
 // MDD 3.0 change:
 // Using the pHWObj to retrieve values from instead of using the registry
 */
PVOID XSC1_SerPDDInit_(
              BOOL    bIR,        // @parm called for IR or not (normal serial)?
              ULONG   Identifier, // @parm Device identifier.
              PVOID   pMddHead,   // @parm First argument to mdd callbacks.
              PHWOBJ  pHWObj      // @parm Used to retrieve values from instead of using the registry
             )
{
    PSER_PDD_INFO pHWHead;
	
    DEBUGMSG(ZONE_FUNCTION,(TEXT("+XSC1_SerPDDInit_(%s,pMddHead)\r\n"),(LPCTSTR)Identifier));
    
    // Allocate for our main data structure and one of it's fields.
    pHWHead = (PSER_PDD_INFO)LocalAlloc(LMEM_ZEROINIT | LMEM_FIXED,sizeof(SER_PDD_INFO));
    
    if (pHWHead)
    {
        if (!XSC1_SerPDDGetRegistryData(pHWHead,(LPCTSTR)Identifier))
        {
            DEBUGMSG(ZONE_ERROR,(TEXT("XSC1_SerPDDInit_ - Unable to read registry data. Failing Init !!!\r\n")));
			VirtualFree(pHWHead->pBaseAddress,0,MEM_RELEASE);
            LocalFree(pHWHead);
            DEBUGMSG(1,(TEXT("*****XSC1_SerPDDInit Exiting. ERROR: SerPDDGetRegistryData\r\n")));
            return(NULL);
		}
        else
        {
            if (!XSC1_SerPDDInternalMapRegisterAddresses(pHWHead))
			{
             DEBUGMSG(ZONE_ERROR,(TEXT("XSC1_SerPDDInit_ - Unable to map register addresses. Failing Init !!!\r\n")));
			 VirtualFree(pHWHead->pBaseAddress,0,MEM_RELEASE);
             LocalFree(pHWHead);
             DEBUGMSG(1,(TEXT("*****XSC1_SerPDDInit Exiting. ERROR: SerPDDInternalMapRegisterAddresses\r\n")));
             return(NULL);
			}
            
            DEBUGMSG(ZONE_INIT,(TEXT("XSC1_SerPDDInit_ - IRQ %d = SYSINTR %d\r\n"),
                                pHWHead->dwIRQ, pHWObj->dwIntID));

            pHWHead->pMddHead                               = pMddHead;
            pHWHead->pHWObj                                 = pHWObj;
            pHWHead->cOpenCount                             = 0;
            pHWHead->CommProp.wPacketLength                 = 0xffff;
            pHWHead->CommProp.wPacketVersion                = 0xffff;
            pHWHead->CommProp.dwServiceMask                 = SP_SERIALCOMM;
            pHWHead->CommProp.dwReserved1                   = 0;
            pHWHead->CommProp.dwMaxTxQueue                  = 1; //64  
            pHWHead->CommProp.dwMaxRxQueue                  = 1; //64 
            pHWHead->CommProp.dwMaxBaud                     = BAUD_115200;
            pHWHead->CommProp.dwProvSubType                 = PST_RS232;
            pHWHead->CommProp.dwProvCapabilities    =        //Verify
            PCF_DTRDSR | PCF_RLSD | PCF_RTSCTS |
            PCF_SETXCHAR |
            //  PCF_INTTIMEOUTS |
            PCF_PARITY_CHECK |
            PCF_SPECIALCHARS 
            //  PCF_TOTALTIMEOUTS |
            //  PCF_XONXOFF;
            ;

            pHWHead->CommProp.dwSettableBaud                =
            BAUD_075   | BAUD_150    | BAUD_300   | BAUD_600   |
            BAUD_1200  | BAUD_1800   | BAUD_2400  | BAUD_4800  |
            BAUD_7200  | BAUD_9600   | BAUD_14400 | BAUD_19200 | 
            BAUD_38400 | BAUD_115200 | BAUD_57600 | BAUD_USER  ;

            pHWHead->CommProp.dwSettableParams              =
            SP_BAUD | SP_DATABITS | SP_HANDSHAKING | SP_PARITY | 
            SP_PARITY_CHECK | SP_RLSD | SP_STOPBITS;

            pHWHead->CommProp.wSettableData                 =
            DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8;;

            pHWHead->CommProp.wSettableStopParity   =
            STOPBITS_10 | STOPBITS_20 |
            PARITY_NONE | PARITY_ODD | PARITY_EVEN | PARITY_SPACE |
            PARITY_MARK;

            pHWHead->fIRMode=bIR;   // Select wired by default
			
			//Debug serial on FFUART is disabled if product serial on FFUART is enabled

			//Init the uart
            HW_XSC1_Init(pHWHead,pHWHead->pBaseAddress,1,pHWHead->dwIOBase,pHWHead->pGPIOReg,
				              pHWHead->pClkMgrReg, EvaluateEventFlag,
							  pMddHead,(PLOOKUP_TBL)&LS_BaudTable);

			/*
			switch (pHWHead->dwIOBase)
			{ 
			  // mask irq
			  case FFUART_BASE_U_VIRTUAL:
				 //Unmask the interrupt
				 INTC_FFUART_INT_EN(pHWHead->pINTCReg->icmr); 
				 //Select IRQ
				 INTC_FFUART_INT_DIS(pHWHead->pINTCReg->iclr); 
				 break;
         
			  case BTUART_BASE_U_VIRTUAL:
				 //Unmask the interrupt
				 INTC_BTUART_INT_EN(pHWHead->pINTCReg->icmr); 
				 //Select IRQ
				 INTC_BTUART_INT_DIS(pHWHead->pINTCReg->iclr); 
				 break;

			  case STUART_BASE_U_VIRTUAL:
				 //Unmask the interrupt
				 INTC_STUART_INT_EN(pHWHead->pINTCReg->icmr); 
				 //Select IRQ
				 INTC_STUART_INT_DIS(pHWHead->pINTCReg->iclr); 
				 break;
			}
			*/

			//Configuring for IR mode depending upon whether bIR is enabled or not.
			if (bIR)
			 XSC1_SerPDDSetOutputMode(pHWHead,bIR,!bIR);
//			DEBUGMSG(1,(TEXT("***** XSC1_SerPDDInit - Exiting Successfully\r\n")));
            return(pHWHead);
        }
    }
    if (pHWHead->pBaseAddress)
    {
        VirtualFree(pHWHead->pBaseAddress,0,MEM_RELEASE);
    }
    LocalFree(pHWHead);
    DEBUGMSG(ZONE_ERROR,(TEXT("XSC1_SerPDDInit - Exiting with ERROR\r\n")));

    return(NULL);
}

/*
 @doc OEM
 @func ULONG | XSC1_SerPDDClose | This routine closes the device identified by the PVOID returned by SerPDDInit.
 *  Not exported to users, only to driver.
 *
 @rdesc The return value is 0.
 */
static ULONG XSC1_SerPDDClose(PVOID   pHead)
{
    PSER_PDD_INFO   pHWHead = (PSER_PDD_INFO)pHead;
    ULONG  uTries;

    DEBUGMSG(ZONE_FUNCTION,(TEXT("+XSC1_SerPDDClose\r\n")));

    if (pHWHead->cOpenCount)
    {
        DEBUGMSG(ZONE_CLOSE,(TEXT("XSC1_SerPDDClose, closing device\r\n")));
        
        pHWHead->cOpenCount--;
        
        // while we are still transmitting, sleep.
        uTries = 0;
        
        while (HW_XSC1_TransmitterBusy(pHWHead) &&  (uTries++ < 100))
        {
            DEBUGMSG (ZONE_CLOSE,(TEXT("XSC1_SerPDDClose, TX in progress, \r\n")));
            Sleep(10);
        }

        // When the device is closed, we power it down.
        DEBUGMSG (ZONE_CLOSE,(TEXT("XSC1_SerPDDClose - Powering down UART\r\n")));
        
        //If using IR mode, then returning to normal serial mode before closing
        pHWHead->fIRMode  = FALSE;  
        XSC1_SerPDDSetOutputMode(pHWHead,FALSE,FALSE);

        DEBUGMSG(ZONE_CLOSE,(TEXT("XSC1_SerPDDClose - Calling HW_XSC1_Close\r\n")));
        HW_XSC1_Close(pHWHead);
        
        switch (pHWHead->dwIOBase)
        {  
         // mask irq
         
         case FFUART_BASE_U_VIRTUAL:
         // mask the FFUART interrupt in ICReg
         // For Merlin Active Sync, we don't disable the interrupt
#ifdef USE_TALISKER
         INTC_FFUART_INT_DIS(pHWHead->pINTCReg->icmr); 
         DEBUGMSG(ZONE_CLOSE,(TEXT("************XSC1_SerPDDClose - Masking FFUART\r\n")));
#endif
         break;

		 case BTUART_BASE_U_VIRTUAL:
         // mask the BTUART interrupt in ICReg
         // For Merlin Active Sync, we don't disable the interrupt
#ifdef USE_TALISKER
         INTC_BTUART_INT_DIS(pHWHead->pINTCReg->icmr); 
         DEBUGMSG(ZONE_CLOSE,(TEXT("************XSC1_SerPDDClose - Masking BTUART\r\n")));
#endif
         break;
             
         case STUART_BASE_U_VIRTUAL:
         //mask the STUART interrupt in ICReg
		 // For Merlin Active Sync, we don't disable the interrupt
#ifdef USE_TALISKER
         INTC_STUART_INT_DIS(pHWHead->pINTCReg->icmr); 
         DEBUGMSG(ZONE_CLOSE,(TEXT("************XSC1_SerPDDClose - Masking STUART\r\n")));
#endif
         break;
        }
    }
    DEBUGMSG(ZONE_FUNCTION,(TEXT("-XSC1_SerPDDClose\r\n")));
    return(0);
}

/*
 @doc OEM 
 @func PVOID | XSC1_SerPDDDeinit | Deinitializes device identified by argument.
 *  This routine frees any memory allocated by XSC1_SerPDDInit_.
 *
 */
static BOOL XSC1_SerPDDDeinit(PVOID   pHead)
{
    PSER_PDD_INFO pHWHead = (PSER_PDD_INFO)pHead;

    DEBUGMSG(ZONE_FUNCTION,(TEXT("XSC1_SerPDDDeinit\r\n")));
    if (!pHWHead)
        return(FALSE);
    
    // Make sure device is closed before doing DeInit
    if (pHWHead->cOpenCount)
        XSC1_SerPDDClose(pHead);
    if (pHWHead->pBaseAddress)
        VirtualFree(pHWHead->pBaseAddress,0,MEM_RELEASE);
    

⌨️ 快捷键说明

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