📄 ncfwapi.c
字号:
// See if the physical endpoint requires service
if (IrqStat0 & (1<<PhysEp))
{ // This physical endpoint has interrupted:
// - Service the endpoint's transfer requirements
// - Candidacy level may change depending on results of the transfer
ASSERT(Endpoint->Priv.PhysEp == PhysEp);
ASSERT(Endpoint->Transfer != NULL);
// Call endpoint's transfer handler
// - USB packets will be received (OUT) or transmitted (IN)
Endpoint->Priv.PioPacketHandler(Endpoint);
EndpointActivity++;
}
#if _NCVIRTUALENDPOINTS
else if (Endpoint->Priv.SwapCandidate < SwapCandidate_NoBytesTransferred)
{ // Endpoint does NOT require service, AND it currently has low chance of being re-assigned
// - Increase this endpoint's chances for re-assignment
Endpoint->Priv.SwapCandidate = SwapCandidate_NoBytesTransferred;
}
if (Endpoint->Transfer->TransferFlags & (1<<NC_TRANSFER_FLAG_ENDPOINT_LOCK))
{ // Locked endpoints stay locked, regardless of previous results!
Endpoint->Priv.SwapCandidate = SwapCandidate_Locked;
// No further processing
continue;
}
if (Endpoint->Priv.SwapCandidate < SwapCandidate_TransferComplete)
{ // Transfer did not complete, however endpoint may need to be relocked
if (Endpoint->Transfer->TransferFlags & (1<<NC_TRANSFER_FLAG_TRANSFER_LOCK))
{ // Client requested this transfer to remain assigned for the life of the transfer
Endpoint->Priv.SwapCandidate = SwapCandidate_Locked;
}
else if (Endpoint->Priv.FrameCount < Endpoint->Ex.VirtualEp_MinLockTime)
{ // Number of USB frames since this transfer started and locked is within a threshold
// - Relock the endpoint so it cannot be reassigned (at least for now)
// to prevent unproductive re-assignment thrashing
// - Increment Frame Count: Next interrupt, endpoint may get reassigned!
Endpoint->Priv.SwapCandidate = SwapCandidate_Locked;
Endpoint->Priv.FrameCount += FramesSinceLastInterrupt;
}
}
#endif // _NCVIRTUALENDPOINTS
}
#if _NCVIRTUALENDPOINTS
#pragma message (_NC_MESSAGE"Virtualized endpoints support supported. (Up to 30 endpoints.)")
// This implementation supports NET2272 virtualized endpoints. Virtualized endpoints
// allows your USB device to have as many as 30 (15 IN plus 15 OUT) Bulk or Interrupt
// endpoints. A significant amount of virtualization support firmware may be eliminated
// if the three physical endpoints (EPA, EPB, EPC) plus Endpoint Zero is sufficient
// for your device. This Virtualized Endpoint Interrupt section plus the following
// routines may be removed:
// - FindNextNakingVirtualEp()
// - ReassignBestEndpoint()
// - SaveTransfer()
// - RestartTransfer()
// Recommendation: Discard unused sections *after* debugging!!
IrqStat0 = NETCHIP_READ(IRQSTAT0) & NETCHIP_READ(IRQENB0);
if (IrqStat0 & (1<<VIRTUALIZED_ENDPOINT_INTERRUPT))
{ // At least one virtualized endpoint is requesting service (Host has sent a token)
// - NET2272 virtualization logic is NAKing tokens on virtualized endpoints
Endpoint = FindNextNakingVirtualEp();
if (Endpoint != NULL)
{ // A virtualized transfer needs service. It must be assigned to a physical endpoint
// - Find the best physical endpoint to assign this transfer to:
if (ReassignBestEndpoint(Endpoint) == NCSTATUS_SUCCESS)
{ // Successfully re-assigned a transfer from one of the chip's physical endpoints
// - Start (or restart) this transfer on the same physical endpoint
RestartTransfer(Endpoint);
}
}
EndpointActivity++;
}
#endif
if (EndpointActivity == 0)
{ // No data transfers
// - Check for less time-critical events
// Check for changes in these USB conditions:
if (NETCHIP_READ(IRQSTAT1) & (
(1<<ROOT_PORT_RESET_INTERRUPT) | // Root Port Reset
(1<<RESUME_INTERRUPT) | // Chip wakeup
(1<<SUSPEND_REQUEST_CHANGE_INTERRUPT) | // Host is suspending or resuming
(1<<VBUS_INTERRUPT) | // VBUS went FALSE or TRUE
0))
{ // Handle changes in USB conditions
NcDev_UsbState(PrivDeviceObject);
// Tip: The NET2272 may now be suspended. If the chip's I/O Wakeup Enable
// is TRUE, then care must be taken to NOT access the chip, or it will wakeup!
}
else if (PrivDeviceObject->UsbPowerState == NC_USB_POWER_ON)
{ // The chip is connected and running
// - Check for USB Setup Requests
NcDev_ControlHandler(PrivDeviceObject);
}
}
// Histo tip: Be careful about accessing the chip in this HISTO(). If it is
// suspended and its I/O Wakeup Enable is TRUE, a register access will wake it!
HISTO(DEFAULT_HISTORY, ")Int", 0, 0, 0);
ASSERT(NcDebug_InterruptContext);
NCDEBUG(NcDebug_InterruptContext = FALSE;)
/*
// Debugging tip: If this interrupt handler loops forever unproductively, it
// usually means:
// - An interrupt is enabled but not handled: Disable or write a handler for
// the interrupt.
// - An interrupt is enabled and handled, but the interrupting bit is not
// cleared: The NetChip #IRQ pin remains asserted as long as an interrupt
// bit is enabled and set. (For instance, if VBUS Interrupt is set, the
// chip's #IRQ remains asserted as long as VBUS Interrupt Enable is set. The
// #IRQ pin deasserts when VBUS Interrupt is cleared OR VBUS Interrupt Enable
// is cleared.)
// - The chip's #IRQ pin is stuck low. Note that the #IRQ pin may be shared
// by other chips; it may be another chip that is asserting its interrupt
// pin. Also, there should be a pull-up resister on the interrupt line.
//
// The following code fragment can help expose problematic interrupts:
IrqStat0 = NETCHIP_READ(IRQSTAT0);
IrqEnb0 = NETCHIP_READ(IRQENB0);
IrqStat1 = NETCHIP_READ(IRQSTAT1);
IrqEnb1 = NETCHIP_READ(IRQENB1);
NCPRINTF(VOLUME_MINIMUM, ("NcDev_InterruptHandler(): Unhandled interrupt... \n"));
if (IrqStat0 & IrqEnb0)
{
NCPRINTF(VOLUME_MINIMUM, ("IRQSTAT0(%2.2x) AND IRQENB0(%2.2x): %2.2x\n",
IrqStat0, IrqEnb0, (IrqStat0 & IrqEnb0)));
}
else if (IrqStat0 & IrqEnb0)
{
NCPRINTF(VOLUME_MINIMUM, ("IRQSTAT1(%2.2x) AND IRQENB1(%2.2x): %2.2x\n",
IrqStat1, IrqEnb1, (IrqStat1 & IrqEnb1)));
}
else
{ // Unknown *and* unhandled interrupt
// - We should never *ever* get here!
// - (It can occur if Suspend Request Interrupt Enable is accidentally
// set when writing 1 to Suspend Request Interrupt)
NCPRINTF(VOLUME_MINIMUM, (" - <Unknown source>\n"));
}
*/
}
///////////////////////////////////////////////////////////////////////////////
void
NcResetDataEp(
PNC_DEVICE_OBJECT DeviceObject
)
{ // Reset all endpoints (except endpoint zero)
// - Effectively undoes the API Endpoint Create function for all data endpoints
// - Calls client's Completion Handler (with error) on endpoints with Pending transfers
// - Calls client's Endpoint Event handler
// - Deprograms all endpoints and endpoint state information
// - Expected to be called on initialization, USB reset and de-configuration
NCBYTE EpIndex;
HISTO(DEFAULT_HISTORY, "DsEp", DeviceObject->ConfigurationEndpointCount, 0, 0);
NETCHIP_WRITE(IRQENB0, NETCHIP_READ(IRQENB0) & ~(
(1<<ENDPOINT_A_INTERRUPT_ENABLE) |
(1<<ENDPOINT_B_INTERRUPT_ENABLE) |
(1<<ENDPOINT_C_INTERRUPT_ENABLE) |
(1<<VIRTUALIZED_ENDPOINT_INTERRUPT_ENABLE) |
0));
for (EpIndex = 1; EpIndex <= DeviceObject->ConfigurationEndpointCount; EpIndex++)
{ // For all logical endpoints in the configuration (Except Endpoint Zero!)
// call the client's endpoint closing function. (This allows the client
// to do per-endpoint shutdown, such as freeing endpoint transfer buffers.)
// Call client's endpoint closing function for this endpoint
// - Client can free this endpoint's buffers, etc.
PNC_ENDPOINT_OBJECT Endpoint = &LogicalEndpoints[EpIndex];
if (Endpoint->CompletionStatus == NCSTATUS_PENDING)
{ // This endpoint's transfer did not complete
// - To slightly improve performance, call the endpoint event handler
// rather than the transfer object's completion handler. That way,
// the completion handler can process transfers faster.
Endpoint->EventCode = NC_ENDPOINT_EVENT_SURPRISE_CANCEL_TRANSFER;
ASSERT(Endpoint->EndpointEventHandler != NULL);
Endpoint->EndpointEventHandler(Endpoint);
}
// Close the endpoint
Endpoint->EventCode = NC_ENDPOINT_EVENT_SURPRISE_CLOSE;
ASSERT(Endpoint->EndpointEventHandler != NULL);
Endpoint->EndpointEventHandler(Endpoint);
}
// Clear all endpoint structures except Endpoint Zero
memset(&LogicalEndpoints[1], 0x00, (NCAPI_MAX_ENDPOINT_COUNT - 1)*(sizeof(LogicalEndpoints[0])));
DeviceObject->ConfigurationEndpointCount = 0;
for (EpIndex = 1; EpIndex < NCAPI_MAX_ENDPOINT_COUNT; EpIndex++)
{ // Set starting values for all possible logical endpoints (not including Endpoint Zero):
// - Client may optionally override these handlers
LogicalEndpoints[EpIndex].EndpointEventHandler = (NCSTATUS(*)(PNC_ENDPOINT_OBJECT))DoNothing_MoreProcessingRequired;
}
for (EpIndex = FIRST_PHYSICAL_ENDPOINT; EpIndex < PHYSICAL_ENDPOINT_COUNT; EpIndex++)
{ // Virtualize and disable interrupts for all physical endpoints (except Endpoint Zero)
NETCHIP_WRITE(PAGESEL, EpIndex);
NETCHIP_WRITE(EP_CFG, 0);
NETCHIP_WRITE(EP_IRQENB, 0);
// Map physical endpoint to a logical transfer structure
LogicalEndpoints[EpIndex].Transfer = &LogicalEndpoints[EpIndex].DefaultTransferObject;
PhysicalEndpoints[EpIndex] = &LogicalEndpoints[EpIndex];
PhysicalEndpoints[EpIndex]->Priv.PhysEp = (BYTE)EpIndex;
NC_VIRT_EP(PhysicalEndpoints[EpIndex]->Priv.SwapCandidate = SwapCandidate_TransferComplete;)
}
NETCHIP_WRITE(USBCTL1, NETCHIP_READ(USBCTL1) & ~(1<<VIRTUAL_ENDPOINT_ENABLE));
}
///////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
NCSTATUS
NcApi_OneTimeInit(
PNC_DEVICE_OBJECT DeviceObject
)
{ // One-time initialization of the NetChip API and the NetChip device (NET2272)
// - The caller passes a Device Object to this routine. The Device Object is a
// structure created by the client. It specifies virtually everything about
// the device to the API. It references USB descriptors, dynamic variables
// as well as evnet handlers:
// - USB Descriptors: Before calling here, the client should specify USB descriptors
// and strings in the Device Object.
// - Event Handlers: This routine populates event handlers in the Device Object
// with its own default routines. If the client wants to replace any handler,
// it should do so *after* this routine returns.
// - Other Device Object entries, such as the current configuration, will be updated
// dynamically by NcApi. (For instance soon after connecting to a High-Speed
// USB host, the Device Object's current configuration will reference the client's
// High-Speed configuration.)
// - This routine should NOT be called from an interrupt context.
//XXXXXXXXXXXXXXXXXXXX Add PRINTF regarding 8/16 bit mode
//XXXXXXXXXXXXXXXXXXXX Add PRINTF regarding Virtualization On/Off
NCBYTE StringIndex;
ASSERT(!NcDebug_InterruptContext)
ASSERT(DeviceObject->ConfigurationEndpointCount == 0);
// Copy a private pointer to the client's Device Object
// - This private pointer is for INTERNAL USE ONLY by the device and API software.
PrivDeviceObject = DeviceObject;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -