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

📄 sc2413pdd.cpp-ori

📁 支持三星原产的S3C2413开发板
💻 CPP-ORI
📖 第 1 页 / 共 5 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
#include <windows.h>
#include <nkintr.h>
#include <ddkreg.h>
#include <s3c2413.h>
#include "sc2413pdd.h"

#define RNDIS	0			// To use RNDIS, set to 1.

#define UDC_REG_PRIORITY_VAL _T("Priority256")

#define EP_STATE_IDLE 0
#define EP0_STATE_IN_DATA_PHASE  1
#define EP0_STATE_END_XFER_PHASE  2
#define EP0_STATE_OUT_DATA_PHASE 3

#define IN_TRANSFER  1
#define OUT_TRANSFER 2


typedef struct EP_STATUS {
	DWORD				   dwEndPointNumber;
	DWORD				   dwDirectionAssigned;
	DWORD				   dwPacketSizeAssigned;
	BOOL					fInitialized;
	DWORD				   dwEpState;
	DWORD				   dwEndpointType;
	PSTransfer			  pTransfer;
	CRITICAL_SECTION		cs;
} *PEP_STATUS;

#define LOCK_ENDPOINT(peps)	 EnterCriticalSection(&peps->cs)
#define UNLOCK_ENDPOINT(peps)   LeaveCriticalSection(&peps->cs)


#define EP_0_PACKET_SIZE	0x8	// Could also be 16 but they recommend 8  


static const EP_STATUS g_rgEpStatus[]  = {
	{ 
		0x0,
	},
	{ 
		0x1,
	},
	{ 
		0x2,
	},
	{ 
		0x3,
	},
	{ 
		0x4,
	}
};


#define ENDPOINT_COUNT  dim(g_rgEpStatus)
#define EP_VALID(x) ((x) < ENDPOINT_COUNT)


#define DEFAULT_PRIORITY 100

typedef struct CTRL_PDD_CONTEXT {
	PVOID			 pvMddContext;
	DWORD			 dwSig;
	HANDLE			hIST;
	HANDLE			hevInterrupt;
	BOOL			  fRunning;
	CRITICAL_SECTION  csIndexedRegisterAccess;
	BOOL			  fSpeedReported;
	BOOL			  fRestartIST;
	BOOL			  fExitIST;
	BOOL			  attachedState;
	BOOL			  sendDataEnd;
	// registry 
	DWORD			 dwIOBase;
	DWORD			 dwSysIntr;
	DWORD			 dwIrq;
	DWORD			 dwIOLen;
	DWORD			 dwISTPriority;

	EP_STATUS		 rgEpStatus[ENDPOINT_COUNT];
	
	PFN_UFN_MDD_NOTIFY	  pfnNotify;
	HANDLE				  hBusAccess;
	CEDEVICE_POWER_STATE	cpsCurrent;
} *PCTRLR_PDD_CONTEXT;

#define SC2413_SIG '2413' // "SC2413" signature

#define IS_VALID_SC2413_CONTEXT(ptr) \
	( (ptr != NULL) && (ptr->dwSig == SC2413_SIG) )

WORD	g_wCurrentState;
#ifdef DEBUG

#define ZONE_POWER		   DEBUGZONE(8)

UFN_GENERATE_DPCURSETTINGS(UFN_DEFAULT_DPCURSETTINGS_NAME, 
	_T("Power"), _T(""), _T(""), _T(""), 
	DBG_ERROR | DBG_INIT); 

// Validate the context.
static
VOID
ValidateContext(
				PCTRLR_PDD_CONTEXT pContext
				)
{
	PREFAST_DEBUGCHK(pContext);
	DEBUGCHK(pContext->dwSig == SC2413_SIG);
	DEBUGCHK(!pContext->hevInterrupt || pContext->hIST);
	DEBUGCHK(VALID_DX(pContext->cpsCurrent));
	DEBUGCHK(pContext->pfnNotify);
}

#else
#define ValidateContext(ptr)
#endif

volatile BYTE *g_pUDCBase;

#define CTRLR_BASE_REG_ADDR(offset) ((volatile ULONG*) ( (g_pUDCBase) + (offset)))


// Read a register.
inline
BYTE
ReadReg(
		PCTRLR_PDD_CONTEXT pContext,
		DWORD dwOffset
		)
{
	DEBUGCHK(IS_VALID_SC2413_CONTEXT(pContext));

	volatile ULONG *pbReg = CTRLR_BASE_REG_ADDR(dwOffset);
	BYTE bValue = (BYTE) *pbReg;
	return bValue;
}


// Write a register.
inline
VOID
WriteReg(
		 PCTRLR_PDD_CONTEXT pContext,
		 DWORD dwOffset,
		 BYTE bValue
		 )
{
	DEBUGCHK(IS_VALID_SC2413_CONTEXT(pContext));

	volatile ULONG *pbReg = CTRLR_BASE_REG_ADDR(dwOffset);
	*pbReg = (ULONG) bValue;
}



// Calling with dwMask = 0 and SET reads and writes the contents unchanged.
inline
BYTE
SetClearReg(
			PCTRLR_PDD_CONTEXT pContext,
			DWORD dwOffset,
			BYTE dwMask,
			BOOL  bSet
			)
{
	DEBUGCHK(IS_VALID_SC2413_CONTEXT(pContext));

	volatile ULONG *pbReg = CTRLR_BASE_REG_ADDR(dwOffset);
	BYTE bValue = (BYTE) *pbReg;

	if (bSet) {
		bValue |= dwMask;
	}
	else {
		bValue &= ~dwMask;
	}

	*pbReg = bValue;

	return bValue;
}
// Calling with dwMask = 0 and SET reads and writes the contents unchanged.
inline
BYTE
SetClearIndexedReg(
				   PCTRLR_PDD_CONTEXT pContext,
				   DWORD dwEndpoint,
				   DWORD dwOffset,
				   BYTE dwMask,
				   BOOL  bSet
				   )
{
	DEBUGCHK(IS_VALID_SC2413_CONTEXT(pContext));
	BYTE bValue = 0;


	EnterCriticalSection(&pContext->csIndexedRegisterAccess);
	// Write the EP number to the index reg
	WriteReg(pContext, IDXADDR_REG_OFFSET, (BYTE) dwEndpoint);	
	// Now Write the Register associated with this Endpoint for a given offset
	bValue = SetClearReg(pContext, dwOffset, dwMask, bSet);
	LeaveCriticalSection(&pContext->csIndexedRegisterAccess);

	return bValue;
}
#define SET   TRUE
#define CLEAR FALSE



// Read an indexed register.
inline
BYTE
ReadIndexedReg(
			   PCTRLR_PDD_CONTEXT pContext,
			   DWORD dwEndpoint,
			   DWORD regOffset
			   )
{
	DEBUGCHK(IS_VALID_SC2413_CONTEXT(pContext));

	EnterCriticalSection(&pContext->csIndexedRegisterAccess);
	// Write the EP number to the index reg
	WriteReg(pContext, IDXADDR_REG_OFFSET, (BYTE) dwEndpoint);
	// Now Read the Register associated with this Endpoint for a given offset
	BYTE bValue = ReadReg(pContext, regOffset);
	LeaveCriticalSection(&pContext->csIndexedRegisterAccess);
	return bValue;
}


// Write an indexed register.
inline
VOID
WriteIndexedReg(
				PCTRLR_PDD_CONTEXT pContext,
				DWORD dwIndex,
				DWORD regOffset,
				BYTE  bValue
				)
{  
	DEBUGCHK(IS_VALID_SC2413_CONTEXT(pContext));

	EnterCriticalSection(&pContext->csIndexedRegisterAccess);
	// Write the EP number to the index reg
	WriteReg(pContext, IDXADDR_REG_OFFSET, (BYTE) dwIndex);	
	// Now Write the Register associated with this Endpoint for a given offset
	WriteReg(pContext, regOffset, bValue);
	LeaveCriticalSection(&pContext->csIndexedRegisterAccess);
}

/*++

Routine Description:

Return the data register of an endpoint.

Arguments:

dwEndpoint - the target endpoint

Return Value:

The data register of the target endpoint.

--*/
static
volatile ULONG*
_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;
} // _GetDataRegister


// Retrieve the endpoint status structure.
inline
static
PEP_STATUS
GetEpStatus(
			PCTRLR_PDD_CONTEXT pContext,
			DWORD dwEndpoint
			)
{
	ValidateContext(pContext);
	DEBUGCHK(EP_VALID(dwEndpoint));

	PEP_STATUS peps = &pContext->rgEpStatus[dwEndpoint];

	return peps;
}


// Return the irq bit for this endpoint.
inline
static
BYTE
EpToIrqStatBit(
			   DWORD dwEndpoint
			   )
{
	DEBUGCHK(EP_VALID(dwEndpoint));

	return (1<<(BYTE)dwEndpoint);
}

/*++

Routine Description:

Enable the interrupt of an endpoint.

Arguments:

dwEndpoint - the target endpoint

Return Value:

None.

--*/
static
VOID
EnableEndpointInterrupt(
						PCTRLR_PDD_CONTEXT pContext,
						DWORD		dwEndpoint
						)
{	
	SETFNAME();
	FUNCTION_ENTER_MSG();

	// End Point Zero is always enabled (after Run)
	if (dwEndpoint == 0) {
		FUNCTION_LEAVE_MSG();
		return;
	}

	// Enable the Endpoint Interrupt
	BYTE irqEnBit = EpToIrqStatBit(dwEndpoint);
	SetClearReg(pContext, EP_INT_EN_REG_OFFSET, irqEnBit, SET);

	FUNCTION_LEAVE_MSG();		  
} // _EnableEpInterrupt


/*++

Routine Description:

Disable the interrupt of an endpoint.

Arguments:

dwEndpoint - the target endpoint

Return Value:

None.

--*/
static
VOID
DisableEndpointInterrupt(
						 PCTRLR_PDD_CONTEXT pContext,
						 DWORD		dwEndpoint
						 )
{	
	SETFNAME();
	FUNCTION_ENTER_MSG();

	// End Point Zero is always enabled (after Run)
	if (dwEndpoint == 0) {
		FUNCTION_LEAVE_MSG();
		return;
	}

	// Disable the Endpoint Interrupt
	BYTE irqEnBit = EpToIrqStatBit(dwEndpoint);
	SetClearReg(pContext, EP_INT_EN_REG_OFFSET, irqEnBit, CLEAR);

	FUNCTION_LEAVE_MSG();
} // DisableEndpointInterrupt

/*++

Routine Description:

Clear the interrupt status register index of an endpoint.

Arguments:

dwEndpoint - the target endpoint

Return Value:

None.

--*/
static
VOID
ClearEndpointInterrupt(
					   PCTRLR_PDD_CONTEXT pContext,
					   DWORD		dwEndpoint
					   )
{
	SETFNAME();
	FUNCTION_ENTER_MSG();
	
	// Clear the Endpoint Interrupt
	BYTE bIntBit = EpToIrqStatBit(dwEndpoint);
	WriteReg(pContext, EP_INT_REG_OFFSET, bIntBit);

	FUNCTION_LEAVE_MSG();
} // _ClearInterrupt


// Reset an endpoint
static
VOID
ResetEndpoint(
			  PCTRLR_PDD_CONTEXT pContext,
			  EP_STATUS *peps
			  )
{
	SETFNAME();
	FUNCTION_ENTER_MSG();

	ValidateContext(pContext);
	PREFAST_DEBUGCHK(peps);

	// Since Reset can be called before/after an Endpoint has been configured,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -