📄 ncvirtep.c
字号:
/******************************************************************************
Copyright (C) 2004, NetChip Technology, Inc. (http://www.netchip.com)
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
NCVIRTEP.C
Virtual endpoint support
XXXXXXXXXXXXXXXXXXXXXXX Comments please!
NetChip support: If you have technical problems, comments or feedback about this product,
please contact us: support@netchip.com. Please write "Firmware API" in the subject.
In the body, please provide the software release code (e.g. RE010203), the application
filename, the NetChip chip you are using, plus any helpful details.
******************************************************************************/
///////////////////////////////////////////////////////////////////////////////
#if _NCVIRTUALENDPOINTS
///////////////////////////////////////////////////////////////////////////////
#include <NcCommon.h> // Collection of common NetChip header files
#include <NcFwApiPriv.h> // Private interface (Apps do not directly reference content)
#include <NcDevice.h> // Useful NET2272 functions, types and macros (for USB transfers, etc.)
///////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void
TxFinalPio(
PNC_ENDPOINT_OBJECT Endpoint
);
///////////////////////////////////////////////////////////////////////////////
void
TxPacketsPio(
PNC_ENDPOINT_OBJECT Endpoint
);
///////////////////////////////////////////////////////////////////////////////
void
RxPacketsPio(
PNC_ENDPOINT_OBJECT Endpoint
);
///////////////////////////////////////////////////////////////////////////////
void
DoNothing_Void(
void * pIgnored
);
///////////////////////////////////////////////////////////////////////////////
// Debug: Section of code is running in a NetChip interrupt context:
// - Set TRUE when the NetChip interrupt handler starts, set FALSE
// before the interrupt handler returns.
// - NetChip API functions are performance-tuned to be called from the
// context of a NetChip interrupt routine. If a call is made to an
// interrupt-sensitive API function from a non-NetChip interrupt context,
// the function should assert to warn the developer. The developer may
// add interrupt protection to the API call, or restructure client code
// to call from an interrupt context.
NCDEBUG(extern BOOL NcDebug_InterruptContext;)
#if _NCSTATISTICS
///////////////////////////////////////////////////////////////////////////////
// Statistics support:
// - After software integration is stable and reliable, statistics for transfer
// operations can help to tune and maximize performance
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#include <stddef.h>
#include <string.h>
///////////////////////////////////////////////////////////////////////////////
typedef struct _NC_PHYS_EP_STATISTICS
{
// Number of times this endpoint was assigned to an IN transfer
// - A single transfer, especially a large transfer, may be released
// and reassigned several times for the life of the transfer
UINT Reassign_In;
// Number of times this endpoint was assigned to an OUT transfer
// - A single transfer, especially a large transfer, may be
// reassigned several times for the life of the transfer
UINT Reassign_Out;
} NC_PHYS_EP_STATISTICS, * PNC_PHYS_EP_STATISTICS;
// Reassignment statistics
extern UINT Reassign_AllLocked; //XXXXXXXXXXXXX???
///////////////////////////////////////////////////////////////////////////////
// Apply statistic counters and macros
#pragma message(_NC_MESSAGE"Compiled with statistic counters (_NCSTATISTICS)")
// Statistics can help to tune and improve software performance for your specific
// application. You may modify statistical gathering as you see fit. Generally,
// statistic gathering should impact the CPU as little as possible. For released
// code, compile-time switches disable statistics gathering.
// Number of virtualized endpoint interrupts that occurred where there was
// no Transfer Object active on the interrupting endpoint.
UINT NoTransferForVirtualInterrupt = 0;
// All endpoints locked:
// - A virtualized interrupt occurred, but it could not be assigned to a physical
// endpoint because all physical endpoints were locked
UINT Reassign_AllLocked = 0;
// Statics for each of the NET2272 physical endpoints:
NC_PHYS_EP_STATISTICS PhysEpStatistics[PHYSICAL_ENDPOINT_COUNT];
///////////////////////////////////////////////////////////////////////////////
void
ShowPhysEpStat(
char * StatisticName,
UINT StatisticStructureOffset
)
{
NCBYTE PhysEp;
UINT Total = 0;
printf("%-25s: ", StatisticName);
for (PhysEp = FIRST_PHYSICAL_ENDPOINT; PhysEp < PHYSICAL_ENDPOINT_COUNT; PhysEp++)
{ // For all physical endpoints...
PBYTE StructBase = (PBYTE)&PhysEpStatistics[PhysEp];
UINT Count = (*(PUINT)(StructBase + StatisticStructureOffset));
printf("%9u ", Count);
Total += Count;
}
printf("%9u\n", Total);
}
///////////////////////////////////////////////////////////////////////////////
extern PCHAR EpDirString[];
///////////////////////////////////////////////////////////////////////////////
// Helpers to make statistical print formatting easier and more flexible
// - Common format for statistical totals and for each endpoint:
// - Reformat as appropriate for changes to statistical printing
// Row header format for endpoints and totals:
// - First few columns of each row follow the following format
// - Tip: For clean column format, the number of spaces for each header
// should be the same
#define NCSTAT_ENDPOINT_ROWHEADER " %2.2u %s %2.2x "
#define NCSTAT_TOTALS_ROWHEADER " --- Totals --- "
// Remaining row format for endpoints and totals
// After the row header, the remainder of the row follows this format:
#define NCSTAT_COMMON "%8I64u %8I64u %8I64u %10I64u %12I64u\n"
///////////////////////////////////////////////////////////////////////////////
void
NcApi_ShowStatistics(
void
)
{ // Show accumulated statistics
NCBYTE LogicalEp;
// Columns of stats
// - In an effort to make adjusting columns easier, columns are managed
// independently of their content. With luck it should be easier to
// re-design statistical output
__int64 StatColumn[10];
__int64 StatTotals[10];
memset(&StatTotals, 0, sizeof(StatTotals));
printf("\n"
"-------- NET2272 Transfer Statistics --------\n");
// Assert: Statistics may get skewed if interrupts occur while printing!
ASSERT(System_InterruptController(NCSYS_INTERRUPT_STATUS) == NCSYS_INTERRUPT_DISABLE);
printf("\n"
" General stats:\n"
" No transfer for virtualized interrupt: %8u\n"
" All endpoints locked (unable to reassign): %8u\n",
NoTransferForVirtualInterrupt,
Reassign_AllLocked
);
// Physical endpoint statistics
printf("\n"
" Physical endpoint stats : ------EPA ------EPB ------EPC ----Total \n");
ShowPhysEpStat(" Reassigned as IN", offsetof(NC_PHYS_EP_STATISTICS, Reassign_In));
ShowPhysEpStat(" Reassigned as OUT", offsetof(NC_PHYS_EP_STATISTICS, Reassign_Out));
// Logical endpoint statistics
printf("\n"
" Logical endpoint stats:\n"
" /-- Reassignment stats --\\\n"
" LogEp UsbEp TakeInst TakeFast TakeSlow Xfrs BytesXfr'd\n");
for (LogicalEp = 0; LogicalEp <= PrivDeviceObject->ConfigurationEndpointCount; LogicalEp++)
{
UINT Column = 0;
// Statistical columns appear in the following order
// - Re-order or re-design as appropriate here:
StatColumn[Column++] = LogicalEndpoints[LogicalEp].Priv.Reassign_Instantly; // TakeInst
StatColumn[Column++] = LogicalEndpoints[LogicalEp].Priv.Reassign_EmptyEp; // TakeFast
StatColumn[Column++] = LogicalEndpoints[LogicalEp].Priv.Reassign_SavedEp; // TakeSlow
StatColumn[Column++] = LogicalEndpoints[LogicalEp].Priv.TotalTransfers; // Xfrs
StatColumn[Column++] = LogicalEndpoints[LogicalEp].Priv.TotalBytesTransferred; // BytesXfr'd
// Accumulate totals for each column
StatTotals[0] += StatColumn[0];
StatTotals[1] += StatColumn[1];
StatTotals[2] += StatColumn[2];
StatTotals[3] += StatColumn[3];
StatTotals[4] += StatColumn[4];
StatTotals[5] += StatColumn[5];
StatTotals[6] += StatColumn[6];
StatTotals[7] += StatColumn[7];
StatTotals[8] += StatColumn[8];
StatTotals[9] += StatColumn[9];
printf(NCSTAT_ENDPOINT_ROWHEADER NCSTAT_COMMON,
LogicalEp,
EpDirString[(LogicalEndpoints[LogicalEp].DirectionIn)? 1: 0],
LogicalEndpoints[LogicalEp].Priv.UsbEp,
// Statistics shown for each endpoint then totaled at the end:
StatColumn[0],
StatColumn[1],
StatColumn[2],
StatColumn[3],
StatColumn[4]
);
}
// Show summary
// - Using same format for totals and endpoints
printf(NCSTAT_TOTALS_ROWHEADER NCSTAT_COMMON,
StatTotals[0],
StatTotals[1],
StatTotals[2],
StatTotals[3],
StatTotals[4]
);
}
///////////////////////////////////////////////////////////////////////////////
#endif // _NCSTATISTICS
///////////////////////////////////////////////////////////////////////////////
PNC_ENDPOINT_OBJECT
FindNextNakingVirtualEp(
void
)
{ // Find the next virtual endpoint requiring service
// - A virtual endpoint requiring service has its corresponding bit set
// in VIRTOUT0, VIRTOUT1, VIRTIN0 or VIRTIN1. A set bit indicates the virtual
// endpoint has responded to the USB host with at least one NAK.
// - Round Robin: Starting with the endpoint index we used the last time we were called,
// read the VIRTXXX register associated each USB endpoint of the configuration, in turn,
// until we find an endpoint with its VIRTXXX bit set.
static NCBYTE VirtEpIndex = 0;
UINT ActiveTransfers = 0;
NCBYTE LogicalEp;
// Assert: At least one virtualized endpoint must be requesting service:
ASSERT(NETCHIP_READ(IRQSTAT0) & (1<<VIRTUALIZED_ENDPOINT_INTERRUPT));
for (LogicalEp = 1; LogicalEp <= PrivDeviceObject->ConfigurationEndpointCount; LogicalEp++)
{ // For all endpoints in the configuration
PNC_ENDPOINT_OBJECT Endpoint;
VirtEpIndex++;
ASSERT(VirtEpIndex > 0);
if (VirtEpIndex > PrivDeviceObject->ConfigurationEndpointCount)
{ // This is the final endpoint in this configuration
// - Round-Robin: Start over from the beginning
VirtEpIndex = 1;
}
Endpoint = &LogicalEndpoints[VirtEpIndex];
if (
(Endpoint->CompletionStatus != NCSTATUS_PENDING) && // No active Transfer Object?
(Endpoint->Priv.Virtualized)) // Endpoint is virtualized?
{ // Virtualized endpoint does not have an active Transfer Object
// - Clear its virtualized service request bit (even if the host is not
// requesting service on the endpoint!)
NETCHIP_WRITE(Endpoint->Priv.NcVirtReg, Endpoint->Priv.NcVirtBitMask);
continue;
}
// This virtualized endpoint has an active Transfer Object
// - Later, if none of the virtualized endpoints has a pending transfer,
// virtualized interrupts can be disabled. This prevents virtualized
// endpoints from interrupting uselessly.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -