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

📄 s3c6400otgdevice.cpp

📁 Samsung公司S3C6400芯片的BSP源码包
💻 CPP
📖 第 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 <S3C6400.h>
#include <DrvLib.h>
#include "s3c6400otgdevice.h"
#include <Bsp.h>
#define WCE600	// by dodan26

static volatile BSP_ARGS *v_gBspArgs;
#define CARD_INSERTED 1
#define CARD_REMOVED 2
#define UDC_REG_PRIORITY_VAL _T("Priority256")
//#define _CHANDOLP

enum EP0_STATE {
    EP0_STATE_IDLE = 0,
    EP0_STATE_IN_DATA_PHASE,
    EP0_STATE_OUT_DATA_PHASE
};

typedef enum
{
	USB_HIGH, USB_FULL, USB_LOW
} USB_SPEED;

#define IN_TRANSFER  1
#define OUT_TRANSFER 2




#define EP0_STALL_BITS (EP0_SEND_STALL | EP0_SENT_STALL)

typedef struct EP_STATUS {
	DWORD                   	dwEndpointNumber;
	DWORD                   	dwDirectionAssigned;
	DWORD                   	dwPacketSizeAssigned;
	BOOL                    	fInitialized;
	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    0x40    // USB2.0

#define ENDPOINT_COUNT  16
#define EP_VALID(x)     ((x) < ENDPOINT_COUNT)


#define DEFAULT_PRIORITY 120

// GOTGCTL
#define B_SESSION_VALID				(0x1<<19)
#define A_SESSION_VALID			(0x1<<18)

// GRX STATUS
#define PKTSTS						(0xF<<17)
#define GLOBAL_OUT_NAK				(0x1<<17)
#define OUT_PKT_RECEIVED			(0x2<<17)
#define OUT_TRF_COMPLETED			(0x3<<17)
#define SETUP_TRANS_COMPLETED		(0x4<<17)
#define SETUP_PKT_RECEIVED			(0x6<<17)

#define SETUPPHASEDONE				(0x1<<3)	//Setup Phase Done Interrupt
#define XFERCOPMPL					(0x1<<0) 	//Transfer Complete Interrupt

// DIEPCTL0/DOEPCTL0 device control IN/OUT endpoint 0 control register
#define DEPCTL_SNAK					(0x1<<27)
#define DEPCTL_CNAK					(0x1<<26)

//DIEPINT
#define IN_TKN_RECEIVED				(0x1<<4)
#define TIMEOUT_CONDITION			(0x1<<3)

#define IN_EP						0
#define OUT_EP						1

// DCTL
#define SOFT_DISCONNECT				(0x1<<1)
#define CLEAR_GOUTNAK				(0x1<<10)
#define SET_GOUTNAK				(0x1<<9)
#define CLEAR_GNPINNAK				(0x1<<8)
#define SET_GNINNAK					(0x1<<7)

extern "C"
{
	void RxData512(unsigned char *bufPt, volatile ULONG *FifoPt);
	void TxData512(unsigned char *bufPt, volatile ULONG *FifoPt);
}
extern BOOL USBCurrentDriver(PUFN_CLIENT_INFO pDriverList);

typedef struct CTRL_PDD_CONTEXT {
	volatile OTG_PHY_REG * 			pOTGPhyregs;
	volatile S3C6400_SYSCON_REG *		pSYSCONregs;
	PVOID             		pvMddContext;
	DWORD             		dwSig;
	HANDLE            		hIST;
	HANDLE            		hevInterrupt;
	BOOL              		fRunning;
	CRITICAL_SECTION 	csRegisterAccess;
	BOOL              		fSpeedReported;
	BOOL              		fRestartIST;
	BOOL              		fExitIST;
	BOOL              		attachedState;
	BOOL              		sendDataEnd;
	EP0_STATE         		Ep0State;

	// new value in 6400 otg
	USB_SPEED			eSpeed;
	DWORD				dwEp0MaxPktSize;
	// 6400 flag
	BOOL				fSetUpPhaseDone;
	DWORD				CntValue;
	DWORD				dwDetectedSpeed;


	// registry
	DWORD             	dwSysIntr;
	DWORD             	dwIrq;
	DWORD             	dwISTPriority;

	USB_DEVICE_REQUEST 	udr;
	EP_STATUS         		rgEpStatus[ENDPOINT_COUNT];

	PFN_UFN_MDD_NOTIFY    	pfnNotify;
	HANDLE                  		hBusAccess;
	CEDEVICE_POWER_STATE   	cpsCurrent;

} *PCTRLR_PDD_CONTEXT;

#define SC6400_SIG '6400' // "S3C6400" signature

#define IS_VALID_SC6400_CONTEXT(ptr) \
    ( (ptr != NULL) && (ptr->dwSig == SC6400_SIG) )


#ifdef DEBUG

#define ZONE_POWER           DEBUGZONE(8)

UFN_GENERATE_DPCURSETTINGS(UFN_DEFAULT_DPCURSETTINGS_NAME,
    _T("Power"), _T(""), _T(""), _T(""),
    DBG_ERROR | DBG_INIT);
// Caution: Turning on more debug zones can cause STALLs due
// to corrupted setup packets.

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

#else
#define ValidateContext(ptr)
#endif

volatile BYTE *g_pUDCBase;

static BYTE USBClassInfo;
#define USB_RNDIS  	0
#define USB_Serial 	1
#define USB_MSF    	2

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

#define DRIVER_USB_KEY TEXT("Drivers\\USB\\FunctionDrivers")
#define DRIVER_USB_VALUE TEXT("DefaultClientDriver")

#define DRIVER_USB_MSF_CARD_KEY TEXT("Drivers\\USB\\FunctionDrivers\\Mass_Storage_Class")
#define DRIVER_USB_MSF_CARD_VALUE  TEXT("DeviceName")

#define DRIVER_USB_MSF_MMC_KEY TEXT("Drivers\\SDCARD\\ClientDrivers\\Class\\MMC_Class")
#define DRIVER_USB_MSF_MMC_VALUE  TEXT("Index")

#define DRIVER_USB_MSF_SD_KEY TEXT("Drivers\\SDCARD\\ClientDrivers\\Class\\SDMemory_Class")
#define DRIVER_USB_MSF_SD_VALUE  TEXT("Index")

#define DRIVER_USB_MSF_SDHC_KEY TEXT("Drivers\\SDCARD\\ClientDrivers\\Class\\SDMemory_Class\\High_Capacity")
#define DRIVER_USB_MSF_SDHC_VALUE  TEXT("Index")

#define DRIVER_USB_MSF_FLASH_KEY TEXT("Drivers\\BuiltIn\\NANDFLASH")
#define DRIVER_USB_MSF_FLASH_VALUE  TEXT("Index")

HANDLE g_SdCardDetectThread;

BOOL HW_USBClocks(
	PCTRLR_PDD_CONTEXT      pContext,
	CEDEVICE_POWER_STATE    cpsNew);

static DWORD SDCARD_DetectIST();

DWORD bSDMMCMSF = FALSE;
#define HIGH 1
#define FULL  0
#define POWER_THREAD_PRIORITY 101

static void Delay(UINT32 count)
{
	volatile int i, j = 0;
	volatile static int loop = S3C6400_FCLK/100000;
	
	for(;count > 0;count--)
		for(i=0;i < loop; i++) { j++; }
}

// Read a register.
inline
DWORD
ReadReg(
	PCTRLR_PDD_CONTEXT pContext,
	DWORD dwOffset
	)
{
	DEBUGCHK(IS_VALID_SC6400_CONTEXT(pContext));
	volatile ULONG *pbReg = CTRLR_BASE_REG_ADDR(dwOffset);
	DWORD bValue = (DWORD) *pbReg;
	return bValue;
}


// Write a register.
inline
VOID
WriteReg(
	 PCTRLR_PDD_CONTEXT pContext,
	 DWORD dwOffset,
	 DWORD bValue
	 )
{
	DEBUGCHK(IS_VALID_SC6400_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
DWORD
SetClearReg(
	PCTRLR_PDD_CONTEXT pContext,
	DWORD dwOffset,
	DWORD dwMask,
	BOOL  bSet
	)
{
	DEBUGCHK(IS_VALID_SC6400_CONTEXT(pContext));
	volatile ULONG *pbReg = CTRLR_BASE_REG_ADDR(dwOffset);
	volatile DWORD bValue = (DWORD) *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
int
SetClearSpecificReg(
	PCTRLR_PDD_CONTEXT pContext,
	DWORD dwEndpoint,
	DWORD dwOffset,
	int dwMask,
	BOOL  bSet
	)
{
	DEBUGCHK(IS_VALID_SC6400_CONTEXT(pContext));
	int bValue = 0;

	EnterCriticalSection(&pContext->csRegisterAccess);
	// Write the EP number to the index reg
	// Now Write the Register associated with this Endpoint for a given offset
	bValue = SetClearReg(pContext, dwOffset+ (dwEndpoint*0x20), dwMask, bSet);
	LeaveCriticalSection(&pContext->csRegisterAccess);

	return bValue;
}

#define SET   TRUE
#define CLEAR FALSE


// Read an indexed register.
inline
DWORD
ReadEPSpecificReg(
	PCTRLR_PDD_CONTEXT pContext,
	DWORD dwEndpoint,
	DWORD regOffset
	)
{
	DEBUGCHK(IS_VALID_SC6400_CONTEXT(pContext));
	EnterCriticalSection(&pContext->csRegisterAccess);
	DWORD bValue = ReadReg(pContext, regOffset + (dwEndpoint*0x20));
	LeaveCriticalSection(&pContext->csRegisterAccess);
	return bValue;
}

inline
VOID
WriteEPSpecificReg(
	PCTRLR_PDD_CONTEXT pContext,
	DWORD dwEndpoint,
	DWORD regOffset,
	int  bValue
	)
{
	DEBUGCHK(IS_VALID_SC6400_CONTEXT(pContext));
	EnterCriticalSection(&pContext->csRegisterAccess);
	WriteReg(pContext, regOffset + (dwEndpoint*0x20), bValue);
	LeaveCriticalSection(&pContext->csRegisterAccess);
}


/*++

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);  break;
		case  1: pulDataReg = CTRLR_BASE_REG_ADDR(EP1_FIFO);  break;
		case  2: pulDataReg = CTRLR_BASE_REG_ADDR(EP2_FIFO);  break;
		case  3: pulDataReg = CTRLR_BASE_REG_ADDR(EP3_FIFO);  break;
		case  4: pulDataReg = CTRLR_BASE_REG_ADDR(EP4_FIFO);  break;
		case  5: pulDataReg = CTRLR_BASE_REG_ADDR(EP5_FIFO);  break;
		case  6: pulDataReg = CTRLR_BASE_REG_ADDR(EP6_FIFO);  break;
		case  7: pulDataReg = CTRLR_BASE_REG_ADDR(EP7_FIFO);  break;
		case  8: pulDataReg = CTRLR_BASE_REG_ADDR(EP8_FIFO);  break;
		case  9: pulDataReg = CTRLR_BASE_REG_ADDR(EP9_FIFO);  break;
		case  10: pulDataReg = CTRLR_BASE_REG_ADDR(EP10_FIFO);  break;
		case  11: pulDataReg = CTRLR_BASE_REG_ADDR(EP11_FIFO);  break;
		case  12: pulDataReg = CTRLR_BASE_REG_ADDR(EP12_FIFO);  break;
		case  13: pulDataReg = CTRLR_BASE_REG_ADDR(EP13_FIFO);  break;
		case  14: pulDataReg = CTRLR_BASE_REG_ADDR(EP14_FIFO);  break;
		case  15: pulDataReg = CTRLR_BASE_REG_ADDR(EP15_FIFO);  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
EnableDisableEndpointInterrupt(
	PCTRLR_PDD_CONTEXT  	pContext,
	DWORD               			dwEndpoint,
	DWORD					dwDirection,
	BOOL                			fEnable
	)
{
	// TODO: Make new cs or rename this one
	EnterCriticalSection(&pContext->csRegisterAccess);
	// Disable the Endpoint Interrupt
	volatile DWORD bEpIntReg = ReadReg(pContext, DAINTMSK);
	DWORD bIrqEnBit = EpToIrqStatBit(dwEndpoint);

	if (dwEndpoint == 0)
	{
		bIrqEnBit |= bIrqEnBit <<ENDPOINT_COUNT;
	}
	else
	{
		if (dwDirection== USB_OUT_TRANSFER)
		{
			bIrqEnBit = bIrqEnBit << ENDPOINT_COUNT;
		}
		else if (dwDirection== USB_IN_TRANSFER)
		{
			bIrqEnBit = bIrqEnBit;
		}
		else
		{
			RETAILMSG(1,(TEXT("[UFNPDD] EnableDisableEndpointInterrupt Direction Error!!! \r\n")));
		}
	}
	if (fEnable)
	{
		bEpIntReg |= bIrqEnBit;
	}
	else
	{
		bEpIntReg &= ~bIrqEnBit;
	}
	WriteReg(pContext, DAINTMSK, bEpIntReg);
	LeaveCriticalSection(&pContext->csRegisterAccess);
}

static
inline
VOID
EnableEndpointInterrupt(
	PCTRLR_PDD_CONTEXT  	pContext,
	DWORD               			dwEndpoint,
	DWORD					dwDirection
	)
{
	SETFNAME();
	FUNCTION_ENTER_MSG();
	EnableDisableEndpointInterrupt(pContext, dwEndpoint, dwDirection, TRUE);
	FUNCTION_LEAVE_MSG();
}

static
inline
VOID
DisableEndpointInterrupt(
	PCTRLR_PDD_CONTEXT  	pContext,
	DWORD               			dwEndpoint,
	DWORD					dwDirection

⌨️ 快捷键说明

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