📄 hwctxt.cpp
字号:
#include <windows.h>
#include <types.h>
#include <ceddk.h>
#include <winbase.h>
#include <memory.h>
#include <string.h>
#include <nkintr.h>
#include <excpt.h>
#include <mmddk.h>
#include <ddkreg.h>
#include "generic.h"
#include "s3c2440a.h"
#include "hwctxt.h"
LPCTSTR pszFname = _T("usbdgadget");
#define FUNCTION_ENTER_MSG(x) RETAILMSG(1, (_T("%s ++ [%x]\r\n"), pszFname, x))
#define FUNCTION_LEAVE_MSG(x) RETAILMSG(1, (_T("%s --[%x]\r\n"), pszFname, x))
#define CTRLR_BASE_REG_ADDR(offset) ((volatile ULONG*)((g_pUDCBase) + (offset)))
UDGContext *g_pUDGContext = NULL;
volatile BYTE *g_pUDCBase = NULL;
int dummy = 0xdeadbeef;
BOOL
UDGContext::CreateUDGContext(DWORD dwIndex)
{
RETAILMSG(MDSMSG, (TEXT("UDGContext::CreatUDGContext()\r\n")));
FUNCTION_ENTER_MSG(dwIndex);
if (g_pUDGContext)
{
FUNCTION_LEAVE_MSG(dwIndex);
return(TRUE);
}
g_pUDGContext = new UDGContext;
if (!g_pUDGContext)
{
return(FALSE);
}
return(g_pUDGContext->Init(dwIndex));
}
UDGContext::UDGContext(VOID)
{
RETAILMSG(MDSMSG, (TEXT("UDGContext::UDGContext()\r\n")));
LOCKINIT_IDXREG;
LOCKINIT_ENDPOINT(FIFO_IN);
LOCKINIT_ENDPOINT(FIFO_OUT);
m_fInitialized = FALSE;
}
UDGContext::~UDGContext(VOID)
{
DELETELOCK_ENDPOINT(FIFO_IN);
DELETELOCK_ENDPOINT(FIFO_OUT);
}
BOOL
UDGContext::MapRegisterSet()
{
DEBUGCHK(g_pUDCBase == NULL);
g_pUDCBase = (volatile BYTE *) ((USED_BASE_REG_VA_UNCACHED) + (USBD_BASE_REG_OFFSET));
if(!g_pUDCBase)
{
return FALSE;
}
else {
RETAILMSG(MDSMSG, (_T("MapRegisterSet() : usb device controller base address=%x\r\n"), g_pUDCBase));
}
// + HLP
volatile S3C2440A_IOPORT_REG *s2440IOP = (S3C2440A_IOPORT_REG *) IOPORT_BASE_REG_VA_UNCACHED;
s2440IOP = (volatile S3C2440A_IOPORT_REG *) VirtualAlloc(0, sizeof(S3C2440A_IOPORT_REG),
MEM_RESERVE, PAGE_NOACCESS);
if(s2440IOP == NULL)
{
RETAILMSG(MDSMSG, (TEXT("UDGContext::MapRegisterSet() - For s2440IOP: VirtualAlloc failed!\r\n")));
}
else
{
if( !VirtualCopy( (PVOID)s2440IOP,
(PVOID)(IOPORT_BASE_REG_VA_UNCACHED),
sizeof(S3C2440A_IOPORT_REG),
PAGE_READWRITE|PAGE_NOCACHE ) )
{
RETAILMSG(MDSMSG,(TEXT("UDGContext::MapRegisterSet() - For s2440IOP: VirtualCopy failed!\r\n")));
}
}
/* s2440IOP->GPGDAT |= (1 << 8);//1); // set high
s2440IOP->GPGCON &= ~(3 << 16);//2); // clear GPG1
s2440IOP->GPGCON |= (/*1///2 << 16);//2); // config as output
s2440IOP->GPGUP &= ~(1 << 8);//1); // pullup disabled
Sleep(1000);
s2440IOP->GPGDAT &= ~(1 << 8);//1); // set low
*/
s2440IOP->GPGDAT |= (1 << 1); // set high
s2440IOP->GPGCON &= ~(3 << 2); // clear GPG1
s2440IOP->GPGCON |= (1 << 2); // config as output
s2440IOP->GPGUP &= ~(1 << 1); // pullup disabled
Sleep(1000);
s2440IOP->GPGDAT &= ~(1 << 1); // set low
VirtualFree((void*)s2440IOP, sizeof(S3C2440A_IOPORT_REG), MEM_RELEASE);
// - HLP
return (TRUE);
}
/*++
Deallocate register space.
Arguments: None.
Return Value: None.
--*/
VOID
UDGContext::UnmapRegisterSet(VOID)
{
// Unmap any memory areas that we may have mapped.
if (g_pUDCBase) {
g_pUDCBase = NULL;
}
}
// Read a register.
inline BYTE
UDGContext::ReadReg(DWORD dwOffset)
{
SetKMode(TRUE);
volatile ULONG *pbReg = CTRLR_BASE_REG_ADDR(dwOffset);
BYTE bValue = (BYTE) *pbReg;
SetKMode(FALSE);
return bValue;
}
// Write a register.
inline VOID
UDGContext::WriteReg(DWORD dwOffset,
BYTE bValue)
{
SetKMode(TRUE);
volatile ULONG *pbReg = CTRLR_BASE_REG_ADDR(dwOffset);
*pbReg = (ULONG) bValue;
SetKMode(FALSE);
}
// Calling with dwMask = 0 and SET reads and writes the contents unchanged.
inline BYTE
UDGContext::SetClearReg(DWORD dwOffset,
BYTE dwMask,
BOOL bSet)
{
SetKMode(TRUE);
volatile ULONG *pbReg = CTRLR_BASE_REG_ADDR(dwOffset);
BYTE bValue = (BYTE) *pbReg;
if (bSet) {
bValue |= dwMask;
}
else {
bValue &= ~dwMask;
}
*pbReg = bValue;
SetKMode(FALSE);
return bValue;
}
// Calling with dwMask = 0 and SET reads and writes the contents unchanged.
inline BYTE
UDGContext::SetClearIndexedReg(DWORD dwEndpoint,
DWORD dwOffset,
BYTE dwMask,
BOOL bSet)
{
SetKMode(TRUE);
LOCK_IDXREG;
BYTE bValue = 0;
// Write the EP number to the index reg
WriteReg(IDXADDR_REG_OFFSET, (BYTE) dwEndpoint);
// Now Write the Register associated with this Endpoint for a given offset
bValue = SetClearReg(dwOffset, dwMask, bSet);
UNLOCK_IDXREG;
SetKMode(FALSE);
return bValue;
}
// Read an indexed register.
inline BYTE
UDGContext::ReadIndexedReg(DWORD dwEndpoint,
DWORD regOffset)
{
SetKMode(TRUE);
LOCK_IDXREG;
// Write the EP number to the index reg
WriteReg(IDXADDR_REG_OFFSET, (BYTE) dwEndpoint);
// Now Read the Register associated with this Endpoint for a given offset
BYTE bValue = ReadReg(regOffset);
UNLOCK_IDXREG;
SetKMode(FALSE);
return bValue;
}
// Write an indexed register.
inline VOID
UDGContext::WriteIndexedReg(DWORD dwIndex,
DWORD regOffset,
BYTE bValue)
{
SetKMode(TRUE);
LOCK_IDXREG;
// Write the EP number to the index reg
WriteReg(IDXADDR_REG_OFFSET, (BYTE) dwIndex);
// Now Write the Register associated with this Endpoint for a given offset
WriteReg(regOffset, bValue);
UNLOCK_IDXREG;
SetKMode(FALSE);
}
/*++
Return the data register of an endpoint.
Arguments: dwEndpoint - the target endpoint
Return Value: The data register of the target endpoint.
--*/
volatile ULONG*
UDGContext::GetDataRegister(DWORD dwEndpoint)
{
volatile ULONG *pulDataReg = NULL;
// find the data register (non-uniform offset)
switch (dwEndpoint) {
case 0: pulDataReg = CTRLR_BASE_REG_ADDR(EP0_FIFO_REG_OFFSET); break;
case 1: pulDataReg = CTRLR_BASE_REG_ADDR(EP1_FIFO_REG_OFFSET); break;
case 2: pulDataReg = CTRLR_BASE_REG_ADDR(EP2_FIFO_REG_OFFSET); break;
case 3: pulDataReg = CTRLR_BASE_REG_ADDR(EP3_FIFO_REG_OFFSET); break;
case 4: pulDataReg = CTRLR_BASE_REG_ADDR(EP4_FIFO_REG_OFFSET); break;
default:
DEBUGCHK(FALSE);
break;
}
return pulDataReg;
}
// Set the address of the device on the USB.
DWORD
UDGContext::SetAddress(BYTE bAddress)
{
SetKMode(TRUE);
// Make sure that the Address Update bit is set (0x80)
WriteReg(SET_ADDRESS_REG_OFFSET, (0x80 | bAddress));
SetKMode(FALSE);
return ERROR_SUCCESS;
}
VOID
UDGContext::PowerUp(PVOID pvContext)
{
RETAILMSG(MDSMSG, (TEXT("UDGContext::PowerUp()\r\n")));
PCTRLR_CONTEXT pContext = (PCTRLR_CONTEXT)pvContext;
DevicePowerNotify(DEVICE_NAME, (_CEDEVICE_POWER_STATE)(pContext->cpsCurrentDx=D0), POWER_NAME);
}
VOID
UDGContext::PowerDown(PVOID pvContext)
{
RETAILMSG(MDSMSG, (TEXT("UDGContext::PowerDown()\r\n")));
PCTRLR_CONTEXT pContext = (PCTRLR_CONTEXT)pvContext;
DevicePowerNotify(DEVICE_NAME, (_CEDEVICE_POWER_STATE)(pContext->cpsCurrentDx=D4), POWER_NAME);
}
DWORD
UDGContext::Init(DWORD dwIndex)
{
RETAILMSG(MDSMSG, (TEXT("UDGContext::Init()\r\n")));
if (m_fInitialized) return (FALSE);
m_pHWContext = NULL;
m_pHWContext = (PCTRLR_CONTEXT) LocalAlloc(LPTR, sizeof(*m_pHWContext));
PCTRLR_CONTEXT pContext = (PCTRLR_CONTEXT) m_pHWContext;
m_dwDriverIndex = dwIndex;
m_fInPowerHandler = FALSE;
HKEY hkDevice = NULL;
DWORD dwRet;
BOOL fIntInitialized = FALSE;
DWORD dwType;
hkDevice = OpenDeviceKey((LPWSTR)m_dwDriverIndex);
if (!hkDevice) {
dwRet = GetLastError();
goto EXIT;
}
pContext->dwIrq = IRQ_UNSPECIFIED;
LOCKINIT_IDXREG;
DWORD dwDataSize;
DWORD dwPriority;
DDKISRINFO dii;
DDKWINDOWINFO dwi;
// read window configuration from the registry
dwi.cbSize = sizeof(dwi);
dwRet = DDKReg_GetWindowInfo(hkDevice, &dwi);
if(dwRet != ERROR_SUCCESS) {
RETAILMSG(MDSMSG, (_T("UDGContext::Init() - DDKReg_GetWindowInfo() failed %d\r\n"),
dwRet));
goto EXIT;
}
else if (dwi.dwNumIoWindows != 1) {
RETAILMSG(MDSMSG, (_T("UDGContext::Init() - %d windows configured, expected 1\r\n"),
dwi.dwNumIoWindows));
dwRet = ERROR_INVALID_DATA;
goto EXIT;
}
else if (dwi.ioWindows[0].dwLen < USBD_REGISTER_SET_SIZE) {
RETAILMSG(MDSMSG, (_T("UDGContext::Init() - ioLen of 0x%x is less than required 0x%x\r\n"),
dwi.ioWindows[0].dwLen, USBD_REGISTER_SET_SIZE));
dwRet = ERROR_INVALID_DATA;
goto EXIT;
}
else if (dwi.ioWindows[0].dwBase == 0) {
RETAILMSG(MDSMSG, (_T("UDGContext::Init() - no ioBase value specified\r\n")));
dwRet = ERROR_INVALID_DATA;
goto EXIT;
}
else {
pContext->dwIOBase = dwi.ioWindows[0].dwBase;
pContext->dwIOLen = dwi.ioWindows[0].dwLen;
}
// get ISR configuration information
dii.cbSize = sizeof(dii);
dwRet = DDKReg_GetIsrInfo(hkDevice, &dii);
if (dwRet != ERROR_SUCCESS) {
RETAILMSG(MDSMSG, (_T("UDGContext::Init() - DDKReg_GetIsrInfo() failed %d\r\n"),
dwRet));
goto EXIT;
}
else if( (dii.dwSysintr == SYSINTR_NOP) && (dii.dwIrq == IRQ_UNSPECIFIED) ) {
RETAILMSG(MDSMSG, (_T("UDGContext::Init() - no IRQ or SYSINTR value specified\r\n")));
dwRet = ERROR_INVALID_DATA;
goto EXIT;
}
else {
if (dii.dwSysintr == SYSINTR_NOP) {
BOOL fSuccess = KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dii.dwIrq,
sizeof(DWORD), &dii.dwSysintr, sizeof(DWORD), NULL);
if (!fSuccess) {
RETAILMSG(MDSMSG, (_T("UDGContext::Init() - IOCTL_HAL_REQUEST_SYSINTR failed!\r\n")));
goto EXIT;
}
pContext->dwIrq = dii.dwIrq;
pContext->dwSysIntr = dii.dwSysintr;
}
else {
pContext->dwSysIntr = dii.dwSysintr;
}
}
RETAILMSG(MDSMSG, (TEXT("UDGContext::Init - dwSysIntr:%d, dwIrq:%d \r\n"), pContext->dwSysIntr, pContext->dwIrq));
//map register space to virtual memory
if( !MapRegisterSet() )
{
RETAILMSG(MDSMSG, (TEXT("UDGContext::Init() - Failed to map config registers\r\n")));
goto EXIT;
}
ResetDevice();
// Read the IST priority
dwDataSize = sizeof(dwPriority);
dwRet = RegQueryValueEx(hkDevice, UDC_REG_PRIORITY_VAL, NULL, &dwType,
(LPBYTE) &dwPriority, &dwDataSize);
if (dwRet != ERROR_SUCCESS) {
dwPriority = DEFAULT_PRIORITY;
}
pContext->dwISTPriority = dwPriority;
//start interrupt thread
if(StartInterruptThread(pContext) != ERROR_SUCCESS)
{
RETAILMSG(MDSMSG, (TEXT("UDG_init() - Failed start interrupt thread \r\n")));
return (FALSE);
}
//power
PowerUp(pContext);
m_fInitialized=TRUE;
EXIT:
if (hkDevice) RegCloseKey(hkDevice);
if (dwRet != ERROR_SUCCESS) {
FreeCtrlrContext(pContext);
}
return(m_fInitialized);
}
VOID
UDGContext::FreeCtrlrContext(PVOID pvContext)
{
PCTRLR_CONTEXT pContext = (PCTRLR_CONTEXT)pvContext;
UnmapRegisterSet();
if (pContext->dwSysIntr) {
KernelIoControl(IOCTL_HAL_DISABLE_WAKE, &pContext->dwSysIntr,
sizeof(pContext->dwSysIntr), NULL, 0, NULL);
}
if (pContext->dwIrq != IRQ_UNSPECIFIED) {
KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &pContext->dwIrq,
sizeof(DWORD), NULL, 0, NULL);
}
LocalFree(pContext);
DELETELOCK_IDXREG;
}
BOOL
UDGContext::Deinit(PVOID pvContext)
{
PCTRLR_CONTEXT pContext = (PCTRLR_CONTEXT)pvContext;
FreeCtrlrContext(pContext);
RETAILMSG(MDSMSG, (TEXT("UDGContext::DeInit()\r\n")));
return TRUE;
}
DWORD
UDGContext::StartInterruptThread(PVOID pvContext)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -