PVOID
SerInit(
ULONG Identifier, // @parm Device identifier.
PVOID pMddHead, // @parm First argument to mdd callbacks.
PHWOBJ pHWObj // @parm Pointer to our own HW OBJ for this device
)
{
DEBUGMSG (ZONE_CLOSE,(TEXT("+SerInit, 0x%X\r\n"), Identifier));
CSerialPDD * pSerialPDD = NULL;
if (pHWObj) {
DWORD dwIndex= pHWObj->dwIntID;
pHWObj->dwIntID = 0;
pSerialPDD = CreateSerialObject((LPTSTR)Identifier,pMddHead, pHWObj,dwIndex);
}
if (pSerialPDD==NULL) {
ASSERT(FALSE);
LocalFree(pHWObj);
}
DEBUGMSG (ZONE_CLOSE,(TEXT("-SerInit, 0x%X\r\n"), pSerialPDD));
return pSerialPDD;
}
//=====================================================================================================
CSerialPDD * CreateSerialObject(LPTSTR lpActivePath, PVOID pMdd,PHWOBJ pHwObj, DWORD DeviceArrayIndex)
{
CSerialPDD * pSerialPDD = NULL;
RETAILMSG( TRUE, (TEXT("DEBUG: CreateSerialObject %d\r\n"), DeviceArrayIndex));
switch (DeviceArrayIndex)
{
case 0: ///< UART0
pSerialPDD = new CPdd6410Serial0(lpActivePath,pMdd, pHwObj);
break;
case 1: ///< UART1
pSerialPDD = new CPdd6410Serial1(lpActivePath,pMdd, pHwObj);
break;
case 2: ///< UART2(IrDA)
pSerialPDD = new CPdd6410Serial2(lpActivePath, pMdd, pHwObj);
break;
case 3: ///< UART3(IrDA)
pSerialPDD = new CPdd6410Serial3(lpActivePath, pMdd, pHwObj);
break;
}
if (pSerialPDD && !pSerialPDD->Init())
{
delete pSerialPDD;
pSerialPDD = NULL;
}
return pSerialPDD;
}
//===========================================================================================================
virtual BOOL Init()
{
PHYSICAL_ADDRESS ioPhysicalBase = { S3C6410_BASE_REG_PA_GPIO, 0};
ULONG inIoSpace = 0;
if (TranslateBusAddr(m_hParent,Internal,0, ioPhysicalBase,&inIoSpace,&ioPhysicalBase))
{
// Map it if it is Memeory Mapped IO.
m_pIOPregs = (S3C6410_GPIO_REG *)DrvLib_MapIoSpace(ioPhysicalBase.LowPart , sizeof(S3C6410_GPIO_REG),FALSE);
}
ioPhysicalBase.LowPart = S3C6410_BASE_REG_PA_SYSCON;
ioPhysicalBase.HighPart = 0;
if (TranslateBusAddr(m_hParent,Internal,0, ioPhysicalBase,&inIoSpace,&ioPhysicalBase))
{
m_pSysconRegs = (S3C6410_SYSCON_REG *) DrvLib_MapIoSpace(ioPhysicalBase.LowPart ,sizeof(S3C6410_SYSCON_REG),FALSE);
}
if(m_pSysconRegs)
{
m_pSysconRegs->PCLK_GATE |= (1<<1); // UART0
m_pSysconRegs->SCLK_GATE |= (1<<5); // UART0~3
}
if (m_pIOPregs)
{
DDKISRINFO ddi;
if (GetIsrInfo(&ddi)== ERROR_SUCCESS &&
KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &ddi.dwIrq, sizeof(UINT32), &ddi.dwSysintr, sizeof(UINT32), NULL))
{
//RETAILMSG( TRUE, (TEXT("DEBUG: Serial0 SYSINTR : %d\r\n"), (PBYTE)&ddi.dwSysintr));
RegSetValueEx(DEVLOAD_SYSINTR_VALNAME,REG_DWORD,(PBYTE)&ddi.dwSysintr, sizeof(UINT32));
}
else
{
return FALSE;
}
//gao0129
/*
m_pDTRPort = (volatile ULONG *)&(m_pIOPregs->GPNDAT);
m_pDSRPort = (volatile ULONG *)&(m_pIOPregs->GPNDAT);
m_dwDTRPortNum = 6;
m_dwDSRPortNum = 7;
*/
// CTS0(GPA2), RTS0(GPA3), TXD0(GPA1), RXD0(GPA0)
m_pIOPregs->GPACON &= ~(0xf<<0 | 0xf<<4 | 0xf<<8 | 0xf<<12 ); ///< Clear Bit
m_pIOPregs->GPACON |= (0x2<<0 | 0x2<<4 | 0x2<<8 | 0x2<<12 ); ///< Select UART IP
m_pIOPregs->GPAPUD &= ~(0x3<<0 | 0x3<<2 | 0x3<<4 | 0x3<<6 ); ///< Pull-Up/Down Disable
// DTR0(GPN6), DSR0(GPN7)
// If you want to use COM1 port for ActiveSync, use these statements.
//gao0129
/*
m_pIOPregs->GPNCON &= ~(0x3<<12); ///< DTR0 Clear Bit
m_pIOPregs->GPNCON |= (0x1<<12); ///< Output
m_pIOPregs->GPNPUD &= ~(0x3<<12); ///< Pull-Up/Down Disable
m_pIOPregs->GPNCON &= ~(0x3<<14); ///< DSR0 Clear Bit
m_pIOPregs->GPNCON |= (0x0<<14); ///< Input
m_pIOPregs->GPNPUD &= ~(0x3<<14); ///< Pull-Up/Down Disable
*/
return CPdd6410Uart::Init();
}
return FALSE;
}
//===================================================================================================================
BOOL CPdd6410Uart::Init()
{
if ( CSerialPDD::Init() && IsKeyOpened() && m_XmitFlushDone!=NULL)
{
// IST Setup .
DDKISRINFO ddi;
if (GetIsrInfo(&ddi)!=ERROR_SUCCESS)
{
return FALSE;
}
m_dwSysIntr = ddi.dwSysintr;
if (m_dwSysIntr != MAXDWORD && m_dwSysIntr!=0 )
{
m_hISTEvent= CreateEvent(0,FALSE,FALSE,NULL);
}
if (m_hISTEvent!=NULL)
{
InterruptInitialize(m_dwSysIntr,m_hISTEvent,0,0);
}
else
{
return FALSE;
}
// Get Device Index.
if (!GetRegValue(PC_REG_DEVINDEX_VAL_NAME, (PBYTE)&m_dwDevIndex, PC_REG_DEVINDEX_VAL_LEN))
{
m_dwDevIndex = 0;
}
if (!GetRegValue(PC_REG_SERIALWATERMARK_VAL_NAME,(PBYTE)&m_dwWaterMark,PC_REG_SERIALWATERMARKER_VAL_LEN))
{
m_dwWaterMark = 8;
}
if (!GetRegValue(PC_REG_6410UART_IST_TIMEOUTS_VAL_NAME,(PBYTE)&m_dwISTTimeout, PC_REG_6410UART_IST_TIMEOUTS_VAL_LEN))
{
m_dwISTTimeout = INFINITE;
}
if (!GetRegValue(PC_REG_6410UART_MEM_LENGTH_VAL_NAME, (PBYTE)&m_dwMemLen, PC_REG_6410UART_MEM_LENGTH_VAL_LEN))
{
m_dwMemLen = 0x40;
}
if (!MapHardware() || !CreateHardwareAccess())
{
return FALSE;
}
return TRUE;
}
return FALSE;
}
复制代码
下面的代码是通过物理中断号去向系统请求系统中断(也就是虚拟中断),并用ddi.dwSysintr去改变注册表.
下次GetIsrInfo读到的就是改变后的值了.
DDKISRINFO ddi;
if (GetIsrInfo(&ddi)== ERROR_SUCCESS &&
KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &ddi.dwIrq, sizeof(UINT32), &ddi.dwSysintr, sizeof(UINT32), NULL))
{
//RETAILMSG( TRUE, (TEXT("DEBUG: Serial0 SYSINTR : %d\r\n"), (PBYTE)&ddi.dwSysintr));
RegSetValueEx(DEVLOAD_SYSINTR_VALNAME,REG_DWORD,(PBYTE)&ddi.dwSysintr, sizeof(UINT32));
}
else
{
return FALSE;
}