📄 sc2450pdd.cpp
字号:
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
EnableDisableEndpointInterrupt(pContext, dwEndpoint, FALSE);
FUNCTION_LEAVE_MSG();
}
/*++
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, EIR, bIntBit);
FUNCTION_LEAVE_MSG();
} // _ClearInterrupt
// Reset an endpoint
VOID
ResetEndpoint(
PCTRLR_PDD_CONTEXT pContext,
EP_STATUS *peps
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
ValidateContext(pContext);
PREFAST_DEBUGCHK(peps);
RETAILMSG(DBG, (_T(" ResetEndpoint \r\n")));
// 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;
//0816
WORD bEDR;
if(dwEndpoint == 0 ) {
// Clear all EP0 Status bits
WriteReg(pContext, EP0SR, (EP0SHT | EP0TST |EP0RSR));
WriteReg(pContext, EP0CR, 0x0000);
}
else if(dwEndpoint < ENDPOINT_COUNT) {
// Clear all EP Status bits
WriteIndexedReg(pContext, dwEndpoint, ESR, (OSD | DTCZ | SPT | FFS | FSC | TPS));
// Clear all EP Control bits
bEDR = ReadIndexedReg(pContext, dwEndpoint, EDR);
if(bEDR & (0x1 << dwEndpoint)) { // Tx
WriteIndexedReg(pContext, dwEndpoint, ECR, 0x0000); // Single Buffer Mode
}
else
{
WriteIndexedReg(pContext, dwEndpoint, ECR, 0x0080); // Dual Buffer Mode
}
// Clear and disable endpoint interrupt
WriteReg(pContext, EIR, EpToIrqStatBit(peps->dwEndpointNumber));
DisableEndpointInterrupt(pContext, peps->dwEndpointNumber);
}
else {
DEBUGCHK(FALSE);
}
FUNCTION_LEAVE_MSG();
}
// Reset the device and EP0.
VOID
ResetDevice(
PCTRLR_PDD_CONTEXT pContext
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DEBUGCHK(IS_VALID_SC2450_CONTEXT(pContext));
RETAILMSG(DBG, (_T(" ResetDevice \r\n")));
// Reset System Control Register
WriteReg(pContext, SCR, 0x0020);
// Reset System Status Register
WriteReg(pContext, SSR, (VBUSOFF | VBUSON | TBM | SDE | HFRM | HFSUSP | HFRES ) );
// Disable endpoint interrupts - write Zeros to Disable
WriteReg(pContext, EIER, EP_INTERRUPT_DISABLE_ALL);
// End point Interrupt Status - Write a '1' to Clear
WriteReg(pContext, EIR, CLEAR_ALL_EP_INTRS);
// 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
VOID
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;
WORD bEpIrqStat;
SETFNAME();
FUNCTION_ENTER_MSG();
bEpIrqStat = ReadIndexedReg(pContext, dwEndpoint, ESR);
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);
DWORD dwCurrentPermissions = GetCurrentPermissions();
SetProcPermissions(pTransfer->dwCallerPermissions);
__try {
volatile ULONG *pulFifoReg = _GetDataRegister(dwEndpoint);
DEBUGCHK(pulFifoReg != NULL);
PBYTE pbBuffer = (PBYTE)pTransfer->pvBuffer + pTransfer->cbTransferred;
DWORD cbBuffer = pTransfer->cbBuffer - pTransfer->cbTransferred;
DWORD cbFifoWord = ReadIndexedReg(pContext, dwEndpoint, BRCR);
WORD ReadData = 0 ;
DWORD cbFifo;
if(dwEndpoint ==0){
if (bEpIrqStat & EP0LWO)
cbFifo = cbFifoWord*2-1;
else
cbFifo = cbFifoWord*2;
}
else {
if (bEpIrqStat & LWO)
cbFifo = cbFifoWord*2-1;
else
cbFifo = cbFifoWord*2;
}
DEBUGCHK(cbFifo <= peps->dwPacketSizeAssigned);
// Read from the FIFO
const DWORD cbRead = min(cbFifo, cbBuffer);
DWORD cbToRead;
for (cbToRead = 0; cbToRead < cbRead; cbToRead+=2) {
ReadData= (WORD)*pulFifoReg;
*pbBuffer = (BYTE)ReadData;
*(pbBuffer+1) = (BYTE)(ReadData>>8);
pbBuffer +=2;
}
pTransfer->cbTransferred += cbRead;
if ( (cbRead < peps->dwPacketSizeAssigned) ||
(pTransfer->cbTransferred == pTransfer->cbBuffer) ) {
// Short packet or filled buffer. Complete transfer.
fCompleted = TRUE;
dwStatus = UFN_NO_ERROR;
}
if (dwEndpoint == 0) {
SetClearReg(pContext, EP0SR, EP0RSR, SET);
if (fCompleted) {
pContext->Ep0State = EP0_STATE_IDLE;
}
}
else {
if((peps->dwEndpointType == USB_ENDPOINT_TYPE_BULK) && (!fCompleted)){
if(bEpIrqStat & PSIF) {
pbBuffer = (PBYTE)pTransfer->pvBuffer + pTransfer->cbTransferred;
cbBuffer = pTransfer->cbBuffer - pTransfer->cbTransferred;
cbFifoWord = ReadIndexedReg(pContext, dwEndpoint, BRCR);
ReadData = 0 ;
if (bEpIrqStat & LWO)
cbFifo = cbFifoWord*2-1;
else
cbFifo = cbFifoWord*2;
// Read from the FIFO
const DWORD cbRead = min(cbFifo, cbBuffer);
for (cbToRead = 0; cbToRead < cbRead; cbToRead+=2) {
ReadData= (WORD)*pulFifoReg;
*pbBuffer = (BYTE)ReadData;
*(pbBuffer+1) = (BYTE)(ReadData>>8);
pbBuffer +=2;
}
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 {
RETAILMSG(DBG, (_T("Now_NO One Packet, bEpIrqStat : 0x%08x \r\n"),bEpIrqStat));
}
}
}
}
__except(EXCEPTION_EXECUTE_HANDLER) {
RETAILMSG(DBG, (_T("%s Exception!\r\n"), pszFname));
fCompleted = TRUE;
dwStatus = UFN_CLIENT_BUFFER_ERROR;
}
SetProcPermissions(dwCurrentPermissions);
if (fCompleted) {
RETAILMSG(DBG, (_T("%s RxDone Ep%x BufferSize=%u, Xfrd=%u\r\n"),
pszFname, dwEndpoint,pTransfer->cbBuffer, pTransfer->cbTransferred));
}
}
else
SetClearIndexedReg(pContext,dwEndpoint,ESR,RPS,SET);
*pfCompleted = fCompleted;
*pdwStatus = dwStatus;
FUNCTION_LEAVE_MSG();
}
// Write data to an endpoint.
static
VOID
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();
#if 1
BOOL fCompleted = FALSE;
PSTransfer pTransfer = peps->pTransfer;
DWORD dwStatus = ERROR_GEN_FAILURE;
DEBUGCHK(peps->fInitialized);
DWORD dwEndpoint = peps->dwEndpointNumber;
pTransfer = peps->pTransfer;
if (pTransfer) {
ValidateTransferDirection(pContext, peps, pTransfer);
DEBUGCHK(pTransfer->dwFlags == USB_IN_TRANSFER);
DEBUGCHK(pTransfer->dwUsbError == UFN_NOT_COMPLETE_ERROR);
DWORD dwCurrentPermissions = GetCurrentPermissions();
SetProcPermissions(pTransfer->dwCallerPermissions);
// Transfer is ready
__try {
PBYTE pbBuffer = (PBYTE) pTransfer->pvBuffer + pTransfer->cbTransferred;
DWORD cbBuffer = pTransfer->cbBuffer - pTransfer->cbTransferred;
volatile ULONG *pulFifoReg = _GetDataRegister(dwEndpoint);
DWORD cbWritten = 0;
WORD WriteData = 0;
// Min of input byte count and supported size
DWORD cbToWrite = min(cbBuffer, peps->dwPacketSizeAssigned);
if (dwEndpoint == 0) {
WriteIndexedReg(pContext, 0, BWCR, cbToWrite);
for (cbWritten = 0; cbWritten < cbToWrite; cbWritten+=2) {
WriteData=((*(pbBuffer+1))<<8) | *pbBuffer;
*pulFifoReg = WriteData;
pbBuffer +=2;
}
/* 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;
// We have to consider 16bit buffer interface
if (pTransfer->cbTransferred == pTransfer->cbBuffer
&& pTransfer->pvPddData == 0) {
dwStatus = UFN_NO_ERROR;
fCompleted = TRUE;
pContext->Ep0State = EP0_STATE_IDLE;
}
}
else {
// 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);
}
// If Packet was completed in a previous interrupt cycle,
// the data length to be txed will be zero, and
// zero length data packet should not be transmitted
if( cbToWrite != 0) WriteIndexedReg(pContext, dwEndpoint, BWCR, cbToWrite);;
for (cbWritten = 0; cbWritten < cbToWrite; cbWritten+=2) {
WriteData=((*(pbBuffer+1))<<8) | *pbBuffer;
*pulFifoReg = WriteData;
pbBuffer +=2;
}
// We have to consider 16bit buffer interface
if (pTransfer->cbTransferred == pTransfer->cbBuffer
|| cbWritten == 0) {
dwStatus = UFN_NO_ERROR;
fCompleted = TRUE;
}
// 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
pTransfer->cbTransferred += cbToWrite;
}
}
__except(EXCEPTION_EXECUTE_HANDLER) {
RETAILMSG(DBG, (_T("%s Exception!\r\n"), pszFname));
fCompleted = TRUE;
dwStatus = UFN_CLIENT_BUFFER_ERROR;
}
SetProcPermissions(dwCurrentPermissions);
}
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.
RETAILMSG(DBG, (_T("%s Not Transfer \r\n"),
pszFname));
goto EXIT;
}
if (fCompleted) {
// Disable transfer interrupts until another transfer is issued.
if (peps->dwEndpointNumber != 0) {
DisableEndpointInterrupt(pContext, peps->dwEndpointNumber);
}
RETAILMSG(DBG, (_T("%s Tx Done Ep%x Status %u\r\n"), pszFname,
dwEndpoint, dwStatus));
CompleteTransfer(pContext, peps, dwStatus);
}
else {
RETAILMSG(DBG, (_T("%s Tx EP%x BufferSize=%u, Xfrd=%u\r\n"),
pszFname, dwEndpoint, pTransfer->cbBuffer, pTransfer->cbTransferred));
}
EXIT:
FUNCTION_LEAVE_MSG();
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -