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

📄 hwctxt.cpp

📁 S3C2440 base Wince USB_gadget driver
💻 CPP
📖 第 1 页 / 共 2 页
字号:

#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 + -