📄 ucbreg.c
字号:
#pragma optimize("", off)
/*++
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-2000 Microsoft Corporation. All rights reserved.
Module Name:
ucbreg.c
Abstract:
This module contains routines for manipulating the touch/audio board
registers. The FPGA uses a serial interface to actually communicate
with the board, and indicates completions either by an interrupt, or
a polled bit.
Functions:
TchAudAndReg
TchAudOrReg
TchAudWriteReg
TchAudReadReg
Notes:
Revision History:
Glenn Davis 4/1/97
--*/
#include <windows.h>
#include <p2.h>
#include <p2debug.h>
#include <tchaud.h>
#include <drv_glob.h>
/*
* Timeout value for poll loop waiting for completion of register operation.
*/
#define TCHAUD_REG_TIMEOUT 500 /* ms */
#define TCHAUD_SEM_TIMEOUT (TCHAUD_REG_TIMEOUT*2)
/*
* Macro to handle wrap when comparing timestamps
*/
#define ELAPSED_TICKS(start,end) (((start) <= (end))? ((end) - (start)) : (0xffffffff - (start) + (end) + 1))
/*
* Routines to provide synchronization for accessing the touch/audio asic
* registers. We use a mutex to prevent contention between the touch and
* audio drivers, and a flag in driver globals to prevent contention with
* the touch ISR. If the touch ISR sees the flag set, it will not attempt
* to access the UCB registers (it will wait until the 5ms pen timer goes off
* and try again).
*/
void
TchAudLock(HANDLE hMutex, PULONG pSem)
{
DWORD StartTime = GetTickCount(), CurTime;
WaitForSingleObject(hMutex, TCHAUD_SEM_TIMEOUT);
// Now, synchronize with ISR. Busy wait OK, since ISR will always preeempt.
while (InterlockedTestExchange(pSem, 0, 1) != 0) {
Sleep(0); // Force reschedule
CurTime = GetTickCount();
if (ELAPSED_TICKS(StartTime,CurTime) > TCHAUD_SEM_TIMEOUT) {
RETAILMSG(1,(TEXT("!TchAudLock: Timed out waiting for semaphore!!!\r\n")));
break;
}
}
}
void
TchAudUnlock(HANDLE hMutex, PULONG pSem)
{
*pSem = 0;
ReleaseMutex(hMutex);
}
/*
* Routines for accessing the Touch/audio ASIC registers. To read or write
* one of the ASIC registers, first specify the register and operation,
* and then wait for completion, which is indicated by the regIntr bit in the
* ucbStr register. We poll for this event in WaitForRegCompletion.
*/
static BOOL
WaitForRegCompletion(
volatile PTCHAUD_ASIC_REGISTERS pTchAudRegs,
BOOL bInPowerHandler)
{
DWORD StartTime;
if (!bInPowerHandler)
StartTime = GetTickCount();
while (1)
{
if (pTchAudRegs->ucbStr & intrMaskRegIntrMask) {
// Clear regIntr interrupt.
pTchAudRegs->ucbStr = intrMaskRegIntrMask;
return TRUE;
}
if (!bInPowerHandler) {
DWORD CurTime = GetTickCount();
if (ELAPSED_TICKS(StartTime,CurTime) > TCHAUD_REG_TIMEOUT) {
RETAILMSG(1,(TEXT("!TchAud: Timed out waiting for UCB reg completion\n\r")));
return FALSE;
}
}
}
return FALSE;
}
typedef enum {OP_READ, OP_WRITE,OP_AND,OP_OR} REGOP;
/*
* Routine to perform read write and modify operations on ASIC registers.
*/
static BOOL
TchAudRegOp(
USHORT Reg, // UCB register number
USHORT Val, // Value for modify operations
USHORT *pRetval, // for OP_READ only
REGOP op,
volatile PTCHAUD_ASIC_REGISTERS pTchAudRegs,
BOOL bInPowerHandler)
{
BOOL bRet;
USHORT TchAudIntrMask;
// Make sure regIntr is masked so we don't generate interrupts
// when we write to the ASIC.
TchAudIntrMask = pTchAudRegs->intrMask;
pTchAudRegs->intrMask = (USHORT)(TchAudIntrMask & ~intrMaskRegIntrMask);
// Clear regIntr interrupt just as a precaution.
pTchAudRegs->ucbStr = intrMaskRegIntrMask;
if (op != OP_WRITE) {
// Read register
pTchAudRegs->ucbCntr = (USHORT)(Reg & ~ucbCntrWriteBit);
pTchAudRegs->ucbRegister = 0;
if (WaitForRegCompletion(pTchAudRegs, bInPowerHandler) == FALSE) {
bRet = FALSE;
goto RegOpsDone;
}
if (op == OP_READ) {
*pRetval = pTchAudRegs->ucbRegister;
bRet = TRUE;
goto RegOpsDone;
}
if (op == OP_AND)
Val &= pTchAudRegs->ucbRegister;
else // OR
Val |= pTchAudRegs->ucbRegister;
}
// Write to register
// RETAILMSG(1,(TEXT("TchAudRegOp: Writing val 0x%X to reg %u, thread: 0x%X\r\n"),Val,Reg,GetCurrentThread()));
pTchAudRegs->ucbCntr = (USHORT)(Reg | ucbCntrWriteBit);
pTchAudRegs->ucbRegister = Val;
bRet = WaitForRegCompletion(pTchAudRegs, bInPowerHandler);
RegOpsDone:
//
// Restore intrMask register to original value.
//
pTchAudRegs->intrMask = TchAudIntrMask;
return bRet;
}
BOOL
TchAudReadReg(
USHORT Reg,
USHORT *pVal,
PTCHAUD_ASIC_REGISTERS pTchAudRegs,
BOOL bInPowerHandler)
{
return TchAudRegOp(Reg,0,pVal,OP_READ, pTchAudRegs, bInPowerHandler);
}
BOOL
TchAudWriteReg(
USHORT Reg,
USHORT Val,
PTCHAUD_ASIC_REGISTERS pTchAudRegs,
BOOL bInPowerHandler)
{
return TchAudRegOp(Reg,Val,NULL,OP_WRITE, pTchAudRegs, bInPowerHandler);
}
BOOL
TchAudAndReg(
USHORT Reg,
USHORT Val,
PTCHAUD_ASIC_REGISTERS pTchAudRegs,
BOOL bInPowerHandler)
{
return TchAudRegOp(Reg,Val,NULL,OP_AND, pTchAudRegs, bInPowerHandler);
}
BOOL
TchAudOrReg(
USHORT Reg,
USHORT Val,
PTCHAUD_ASIC_REGISTERS pTchAudRegs,
BOOL bInPowerHandler)
{
return TchAudRegOp(Reg,Val,NULL,OP_OR, pTchAudRegs, bInPowerHandler);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -