📄 bvd_ser_pdd.c
字号:
/* 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 + -