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

📄 s3c6400otgdevice.cpp

📁 Samsung公司S3C6400芯片的BSP源码包
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	)
{
	SETFNAME();
	FUNCTION_ENTER_MSG();
	EnableDisableEndpointInterrupt(pContext, dwEndpoint, dwDirection, FALSE);
	FUNCTION_LEAVE_MSG();
}


// 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,
	// it is best to clear all IN and OUT bits associated with endpoint.
	DWORD dwEndpoint = peps->dwEndpointNumber;
	if(dwEndpoint == 0)
	{
		WriteEPSpecificReg(pContext, dwEndpoint, DIEPINT, 0x3f);
		WriteEPSpecificReg(pContext, dwEndpoint, DOEPINT, 0x3f);
	}
	else if (dwEndpoint < ENDPOINT_COUNT)
	{
		WriteEPSpecificReg(pContext, dwEndpoint, DIEPINT, 0x3f);
		WriteEPSpecificReg(pContext, dwEndpoint, DOEPINT, 0x3f);
		DisableEndpointInterrupt(pContext, peps->dwEndpointNumber, peps->dwDirectionAssigned);
	}

	FUNCTION_LEAVE_MSG();
}

static
VOID
InitPhyCon(
	PCTRLR_PDD_CONTEXT pContext
	)
{
	pContext->pOTGPhyregs->OPHYPWR = 0x0;
	pContext->pOTGPhyregs->OPHYCLK = 0x20;
	pContext->pOTGPhyregs->ORSTCON = 0x1;
	Delay(100);	
//	Sleep(10);
	pContext->pOTGPhyregs->ORSTCON = 0x0;
	Delay(100);	//10000
//	Sleep(100);
}

static
VOID
InitDevice(
	PCTRLR_PDD_CONTEXT pContext
	)
{
	WriteReg(pContext, GUSBCFG,
					0<<15			// PHY Low Power Clock sel
					|1<<14			// Non-Periodic TxFIFO Rewind Enable
					|0x5<<10		// Turnaround time
					|0<<9|0<<8		// [0:HNP disable, 1:HNP enable][ 0:SRP disable, 1:SRP enable]
					|0<<7			// Ulpi DDR sel
					|0<<6			// 0: high speed utmi+, 1: full speed serial
					|0<<4			// 0: utmi+, 1:ulpi
					|1<<3			// phy i/f  0:8bit, 1:16bit
					|0x7<<0			// HS/FS Timeout*
					);
	WriteReg(pContext, DCFG, 1<<18|0<<0);				// [][1: full speed(30Mhz) 0:high speed]
	WriteReg(pContext, DAINTMSK, (1<<0)<<ENDPOINT_COUNT |(1<<0));		//IN, OUT ep int unmask

	WriteReg(pContext, DOEPMSK, 0);				// Not use OUT EP Interrupt in slave(cpu) mode, but if you use DMA it should be use.
	WriteReg(pContext, DIEPMSK, IN_TKN_RECEIVED | TIMEOUT_CONDITION);	// Tkn Rcvd when TxFIFO Empty, ep timeout

	WriteReg(pContext, GOTGCTL,
					0<<11			// 0:HNP disable, 1:HNP enable
					|0<<9			// 0:No HNP req, 1:HNP req
					|1<<1			// 0:No session req, 1:session req
					);
	WriteReg(pContext, GRXFSIZ, 0x800);						// Rx FIFO Size
	WriteReg(pContext, GNPTXFSIZ, 0x800<<16|0x800<<0);		// Non Periodic Tx FIFO Size
	WriteReg(pContext, GINTMSK, INT_RESUME | INT_IN_EP|INT_SDE|INT_RESET |INT_SUSPEND|INT_RX_FIFO_NOT_EMPTY | INT_OTG);	//gint unmask

	WriteReg(pContext, GAHBCFG, MODE_SLAVE|BURST_SINGLE|GBL_INT_UNMASK);
	WriteReg(pContext, GRSTCTL, (1<<5)|(1<<4));
	while(!((ReadReg(pContext, GRSTCTL) & (0x3<<4)) == 0)); // Wait Until the FIFO Flush bit Cleared
}

void SetSoftDisconnect(
	PCTRLR_PDD_CONTEXT pContext
	)
{
	volatile DWORD dwTemp = ReadReg(pContext, DCTL);
	dwTemp |= SOFT_DISCONNECT;
	WriteReg(pContext, DCTL, dwTemp);
}

void ClearSoftDisconnect(
	PCTRLR_PDD_CONTEXT pContext
	)
{
	volatile DWORD dwTemp = ReadReg(pContext, DCTL);
	dwTemp = dwTemp & ~SOFT_DISCONNECT;
	WriteReg(pContext, DCTL, dwTemp);
}

void MaskUSBSignal(
	PCTRLR_PDD_CONTEXT pContext
	)
{
	volatile DWORD dwRegValue;
	dwRegValue = pContext->pSYSCONregs->OTHERS;
	dwRegValue |= (1<<16);
	pContext->pSYSCONregs->OTHERS = dwRegValue;
}

static
void
SoftResetCore(
	PCTRLR_PDD_CONTEXT pContext
	)
{
	DWORD dwTemp;

	WriteReg(pContext, GRSTCTL, 0x1);
	do
	{
		dwTemp = ReadReg(pContext, GRSTCTL);
	}while(!(dwTemp & (0x1<<31))); //Wait until AHB Master IDLE

}


// Reset the device and EP0.
static
VOID
ResetDevice(
	PCTRLR_PDD_CONTEXT pContext
	)
{
	SETFNAME();
	FUNCTION_ENTER_MSG();

	DEBUGCHK(IS_VALID_SC6400_CONTEXT(pContext));

	MaskUSBSignal(pContext);
	pContext->eSpeed = USB_FULL;
	InitPhyCon(pContext);
	SoftResetCore(pContext);
	InitDevice(pContext);
	// Reset all endpoints
	for (DWORD dwEpIdx = 0; dwEpIdx < ENDPOINT_COUNT; ++dwEpIdx)
	{
		EP_STATUS *peps = GetEpStatus(pContext, dwEpIdx);
		ResetEndpoint(pContext, peps);
	}

	FUNCTION_LEAVE_MSG();
}

static
VOID
CompleteTransfer(
	PCTRLR_PDD_CONTEXT pContext,
	PEP_STATUS peps,
	DWORD dwUsbError
	)
{
	SETFNAME();
	FUNCTION_ENTER_MSG();

	PSTransfer pTransfer = peps->pTransfer;
	peps->pTransfer = NULL;

	pTransfer->dwUsbError = dwUsbError;
	pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_TRANSFER_COMPLETE, (DWORD) pTransfer);

	FUNCTION_LEAVE_MSG();
}

#ifdef DEBUG
static
VOID
ValidateTransferDirection(
                          PCTRLR_PDD_CONTEXT pContext,
                          PEP_STATUS peps,
                          PSTransfer pTransfer
                          )
{
	DEBUGCHK(pContext);
	PREFAST_DEBUGCHK(peps);
	PREFAST_DEBUGCHK(pTransfer);

	if (peps->dwEndpointNumber != 0)
	{
		DEBUGCHK(peps->dwDirectionAssigned == pTransfer->dwFlags);
	}
}
#else
#define ValidateTransferDirection(ptr1, ptr2, ptr3)
#endif


// Read data from an endpoint.
static
BYTE
HandleRx(
		PCTRLR_PDD_CONTEXT       pContext,
		PEP_STATUS peps,
		PBOOL pfCompleted,
		PDWORD pdwStatus
		)
{
	BOOL fCompleted = FALSE;
	DWORD dwStatus = ERROR_GEN_FAILURE;
	DWORD dwEndpoint = peps->dwEndpointNumber;
	BYTE bRet = 0;

	SETFNAME();
	FUNCTION_ENTER_MSG();

	PSTransfer pTransfer = peps->pTransfer;

	pTransfer = peps->pTransfer;

	if (pTransfer)
	{
		DEBUGCHK(pTransfer->dwFlags == USB_OUT_TRANSFER);
		DEBUGCHK(pTransfer->dwUsbError == UFN_NOT_COMPLETE_ERROR);

		ValidateTransferDirection(pContext, peps, pTransfer);

		DEBUGCHK(peps->fInitialized);

#ifndef	WCE600	// by dodan2
		DWORD dwCurrentPermissions = GetCurrentPermissions();
		SetProcPermissions(pTransfer->dwCallerPermissions);
#endif
		__try
		{
			volatile ULONG *pulFifoReg = _GetDataRegister(dwEndpoint);

			DEBUGCHK(pulFifoReg != NULL);

			PBYTE  pbBuffer =  (PBYTE)pTransfer->pvBuffer + pTransfer->cbTransferred;

			DWORD cbBuffer = pTransfer->cbBuffer - pTransfer->cbTransferred;
			DWORD cbFifo = pContext->CntValue;
			pContext->CntValue = 0;
			DEBUGCHK(cbFifo <= peps->dwPacketSizeAssigned);

			// Read from the FIFO
			const DWORD cbRead = min(cbFifo, cbBuffer);
			DWORD cbToRead;
			DWORD ReadData = 0;

			if ((cbRead == 512) && (((DWORD)pbBuffer & 0x3)==0))
			{
				RxData512(pbBuffer, pulFifoReg);
			}
			else
			{
				for(cbToRead = 0; cbToRead < cbRead; cbToRead += 4)
				{
					ReadData = (DWORD)*pulFifoReg;
					*pbBuffer = (BYTE)ReadData;
					*(pbBuffer+1) = (BYTE)(ReadData>>8);
					*(pbBuffer+2) = (BYTE)(ReadData>>16);
					*(pbBuffer+3) = (BYTE)(ReadData>>24);
					pbBuffer += 4;
				}
			}

			DEBUGCHK(cbRead <= pTransfer->cbBuffer - pTransfer->cbTransferred);
			pTransfer->cbTransferred += cbRead;

			if ( (cbRead < peps->dwPacketSizeAssigned) || (pTransfer->cbTransferred == pTransfer->cbBuffer) )
			{
				// Short packet or filled buffer. Complete transfer.
				fCompleted = TRUE;
				dwStatus = UFN_NO_ERROR;
			}
			else
			{
				if (dwEndpoint == 0)
				{
					WriteReg(pContext, DOEPTSIZ0, 1<<19 | pContext->dwEp0MaxPktSize);
					WriteReg(pContext, DOEPCTL0, (1<<31)|(1<<26)|(0<<0));
				}
				else
				{
					WriteEPSpecificReg(pContext, dwEndpoint, DOEPTSIZ, 1<<19 | peps->dwPacketSizeAssigned);
					WriteEPSpecificReg(pContext, dwEndpoint, DOEPCTL, 1<<31|1<<26|2<<18|1<<15 |peps->dwPacketSizeAssigned);
				}
			}

			if (dwEndpoint == 0)
			{
				bRet |= SERVICED_OUT_PKY_RDY;
				if (fCompleted)
				{
					bRet |= DATA_END;
					pContext->Ep0State = EP0_STATE_IDLE;
				}
			}
			else
			{
				DEBUGCHK( (bRet & OUT_PACKET_READY) == 0);
			}
		}
		__except(EXCEPTION_EXECUTE_HANDLER)
		{
			DEBUGMSG(ZONE_ERROR, (_T("%s Exception!\r\n"), pszFname));
			fCompleted = TRUE;
			dwStatus = UFN_CLIENT_BUFFER_ERROR;
		}

#ifndef	WCE600	// by dodan2
		SetProcPermissions(dwCurrentPermissions);
#endif

		DEBUGMSG(ZONE_RECEIVE, (_T("%s Rx Ep%x BufferSize=%u,Xfrd=%u \r\n"),
			pszFname, dwEndpoint, pTransfer->cbBuffer, pTransfer->cbTransferred));

	}


	*pfCompleted = fCompleted;
	*pdwStatus = dwStatus;
	FUNCTION_LEAVE_MSG();

	return bRet;
}


// Write data to an endpoint.
static
BYTE
HandleTx(
		PCTRLR_PDD_CONTEXT       pContext,
		PEP_STATUS peps,
		BOOL fEnableInterrupts
		)
{
	SETFNAME();
	DEBUGCHK(pContext);
	PREFAST_DEBUGCHK(peps);

	// This routine can be entered from both ISTMain and MDD/Client threads so
	// need critical section.

	FUNCTION_ENTER_MSG();

	BYTE bRet = 0;

	BOOL fCompleted = FALSE;
	PSTransfer pTransfer = peps->pTransfer;
	DWORD dwStatus = ERROR_GEN_FAILURE;
	DEBUGCHK(peps->fInitialized);
	DWORD dwEndpoint = peps->dwEndpointNumber;

	pTransfer = peps->pTransfer;
	DWORD WriteData = 0;
	if (pTransfer)
	{
		ValidateTransferDirection(pContext, peps, pTransfer);

		DEBUGCHK(pTransfer->dwFlags == USB_IN_TRANSFER);
		DEBUGCHK(pTransfer->dwUsbError == UFN_NOT_COMPLETE_ERROR);

#ifndef	WCE600	// by dodan2
		DWORD dwCurrentPermissions = GetCurrentPermissions();
		SetProcPermissions(pTransfer->dwCallerPermissions);
#endif

	// Transfer is ready
		__try
		{
			PBYTE pbBuffer = (PBYTE) pTransfer->pvBuffer + pTransfer->cbTransferred;
//			PDWORD  pbBuffer =  (PDWORD)pTransfer->pvBuffer + pTransfer->cbTransferred;

			DWORD cbBuffer = pTransfer->cbBuffer - pTransfer->cbTransferred;

			volatile ULONG *pulFifoReg = _GetDataRegister(dwEndpoint);

			DWORD cbWritten = 0;

			// Min of input byte count and supported size
			volatile DWORD cbToWrite = min(cbBuffer, peps->dwPacketSizeAssigned);

			if (dwEndpoint == 0)
			{
				WriteReg(pContext, DIEPTSIZ0, 1<<19 | cbToWrite);
				WriteReg(pContext, DIEPCTL0, (1<<31)|(1<<26)|(1<<11)|(0<<0));

				if (((DWORD)pbBuffer % 4) != 0) 
					RETAILMSG(1,(TEXT("Tx EP0 Not Alligned %x\r\n"),(DWORD)pbBuffer));

				for (cbWritten = 0; cbWritten <cbToWrite; cbWritten+=4)
				{
					WriteData = ((*(pbBuffer+3))<<24) | ((*(pbBuffer+2))<<16) | ((*(pbBuffer+1))<<8) | *pbBuffer;
					*pulFifoReg = WriteData;
					pbBuffer += 4;
//					(DWORD)*pulFifoReg = (DWORD)*(pbBuffer);
//					pbBuffer += 1;
				}


				/* We can complete on a packet which is full. We need to wait till
				* next time and generate a zero length packet, so only complete
				* if we're at the end and it is not the max packet size.
				*/
				pTransfer->cbTransferred += cbToWrite;
				if ((pTransfer->cbTransferred >= pTransfer->cbBuffer) && (pTransfer->pvPddData == 0))
				{
					dwStatus = UFN_NO_ERROR;
					fCompleted = TRUE;
					pContext->Ep0State = EP0_STATE_IDLE;
				}

			}
			else// if (cbToWrite != 0)
			{
				// Enable Interrupts before writing to the FIFO. This insures
				// That any interrupts generated because of the write will be
				// "latched"

				if (fEnableInterrupts)
				{
					DEBUGCHK(dwEndpoint != 0);
					EnableEndpointInterrupt(pContext, dwEndpoint, peps->dwDirectionAssigned);
				}
				if(cbToWrite !=0)
				{
					WriteEPSpecificReg(pContext, dwEndpoint, DIEPTSIZ, 1<<29 | 1<<19 | cbToWrite);
					WriteEPSpecificReg(pContext, dwEndpoint, DIEPCTL, (1<<31) |(1<<26) |(2<<18)|(1<<15)|(1<<11)|(peps->dwPacketSizeAssigned<<0));
				}
				if (((DWORD)pbBuffer % 4) != 0) 
					RETAILMSG(1,(TEXT("Tx Not Alligned %x\r\n"),(DWORD)pbBuffer));

				if ((cbToWrite == 512) && (((DWORD)pbBuffer & 0x3)==0))				
				{
					TxData512(pbBuffer, pulFifoReg);
					cbWritten += 512;
				}
				else
				{
					for (cbWritten = 0; cbWritten <cbToWrite; cbWritten+=4)
					{
						WriteData = ((*(pbBuffer+3))<<24) | ((*(pbBuffer+2))<<16) | ((*(pbBuffer+1))<<8) | *pbBuffer;
						*pulFifoReg = WriteData;
						pbBuffer += 4;
					}
				}

				// Update the Transfered Count
				pTransfer->cbTransferred += cbToWrite;
				// By Placing the check for packet complete here, before
				// cbTransferred is updated, there is a 1 interrupt cycle delay
				// That is complete is not declared until the data has actually
				// been ACKd (TPC set) by the host
				if ( (pTransfer->cbTransferred >= pTransfer->cbBuffer) || (cbWritten == 0))
				{
					fCompleted = TRUE;
					dwStatus = UFN_NO_ERROR;
				}


			}

		}
		__except(EXCEPTION_EXECUTE_HANDLER)
		{
			DEBUGMSG(ZONE_ERROR, (_T("%s Exception!\r\n"), pszFname));
			fCompleted = TRUE;
			dwStatus = UFN_CLIENT_BUFFER_ERROR;
		}

#ifndef	WCE600	// by dodan2
		SetProcPermissions(dwCurrentPermissions);
#endif
	}
	else
	{
		// It is possible for an interrupt to come in while still in this
		// function for first pass of transfer. If this happens it is possible
		// to complete the transfer and have that interrupt be unnecessary
		// so... just ignore it.
		goto EXIT;
	}

	if (fCompleted)
	{
		// Disable transfer interrupts until another transfer is issued.
		if (peps->dwEndpointNumber != 0)
		{
			DisableEndpointInterrupt(pContext, peps->dwEndpointNumber, peps->dwDirectionAssigned);
		}
		DEBUGMSG(ZONE_SEND, (_T("%s Tx Done  Ep%x  Status %u\r\n"), pszFname, dwEndpoint, dwStatus));
		CompleteTransfer(pContext, peps, dwStatus);
	}
	else
	{
		DEBUGMSG(ZONE_SEND, (_T("%s Tx EP%x BufferSize=%u, Xfrd=%u\r\n"),
			pszFname, dwEndpoint, pTransfer->cbBuffer, pTransfer->cbTransferred));
	}

	EXIT:
	FUNCTION_LEAVE_MSG();

⌨️ 快捷键说明

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