hwcom.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 1,737 行 · 第 1/4 页
C
1,737 行
{
/* Clear any pending Ethernet interrupt events. */
HW_Clear_Init_Events(Adapter);
/* Re-enable Ethernet interrupts. */
HW_Unblock_Interrupts(Adapter);
/* Enable the Ethernet I/F. */
HW_Toggle_Eth_If(Adapter, TRUE);
}
}
DEBUGMSG(ZONE_FUNCTION | ZONE_INIT, (TEXT("-ETH8XX: HW_Start\r\n")));
return(rc);
}
/*----------------------------------------------------------------------*/
BOOLEAN HW_Stop(IN PETH8XX_ADAPTER Adapter)
/*++
Description:
Stops the Ethernet interface. Note that we explicitly check
for the GRACEFUL STOP TX event in the Event register rather
than waiting for the interrupt. It was discovered through
testing that this interrupt never makes it through to the
eth8xxIsr() interrupt handler. One possible theory is if NDIS
only allocates one thread per adapter. In that case, while the
thread is executing here, there's nothing left to check for
and process adapter-related interrupts. Anyway, a workaround
has been implemented which will wait for the GRACEFUL STOP TX
command to complete before proceeding.
Note: the argument to NdisStallExecution() must not exceed 50
microseconds because all interrupts and other CPU activity are
disabled during the call (see also the Windows NT DDK document-
ation for NdisStallExecution).
Arguments:
Adapter - pointer to the NDIS miniport adapter block
Return Value:
None
--*/
{
volatile ADAPTER_STATUS *chkStatus = &(Adapter->Status);
DEBUGMSG(ZONE_FUNCTION, (TEXT("+ETH8XX: HW_Stop\r\n")));
/* Only stop the transmitter if it is currently enabled. */
if ((*chkStatus == ENABLED) || (*chkStatus == SHUTDOWN))
{
if (ADS_IMMR->scc_regs[SCC_ETH_PARM].scc_scce & ETH_GRA_EVENT)
{
DEBUGMSG(ZONE_ERROR,
(TEXT("HW_Stop: ETH_GRA_EVENT is already set\r\n")));
/* Acknowledge pre-existing GRACEFUL STOP event. */
ADS_IMMR->scc_regs[SCC_ETH_PARM].scc_scce = ETH_GRA_EVENT;
}
/* Issue the GRACEFUL STOP TX command. */
if (!KernelIoControl(OEM_IOCTL_ISSUE_CPM_CMD, (LPVOID)SCC_ETH_CH_NUM,
GRACEFUL_STOP_TX, (LPVOID) NOTUSED, (DWORD) NOTUSED,
(LPDWORD)NOTUSED))
{
/* Failed to stop transmitter. */
DEBUGMSG(ZONE_ERROR,
(TEXT("*ETH8XX: HW_Stop KernelIoControl command failed.\r\n")));
DEBUGMSG(ZONE_XMIT, (TEXT(" ETH8XX: transmitter enabled\r\n")));
Adapter->Status = ENABLED;
} else {
/* Loop until GRACEFUL STOP TX command has completed. */
while (*chkStatus != DISABLED)
{
/* Check for GRACEFUL STOP TX event. */
if (ADS_IMMR->scc_regs[SCC_ETH_PARM].scc_scce & ETH_GRA_EVENT)
{
/* Acknowledge the event. */
ADS_IMMR->scc_regs[SCC_ETH_PARM].scc_scce = ETH_GRA_EVENT;
/* OK to proceed with disabling the adapter. */
Adapter->Status = DISABLED;
} else {
/* Pause 20 microseconds before checking again. */
NdisStallExecution(20);
}
}
/* Disable further Ethernet interrupts. */
HW_Block_Interrupts(Adapter);
/* Disable the Ethernet interface. */
HW_Toggle_Eth_If(Adapter, FALSE);
/* Flush all receive and transmit buffer descriptors. */
HW_Internal_Setup_BDs(Adapter);
}
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("-ETH8XX: HW_Stop\r\n")));
return(Adapter->Status == DISABLED);
}
/*----------------------------------------------------------------------*/
VOID HW_Start_Xmit(IN PETH8XX_ADAPTER Adapter,
IN RXTX_ELEMENT *TxElement)
/*++
Description:
Sets the READY bit in the TX buffer descriptor.
Arguments:
Adapter - pointer to the NDIS miniport adapter block
Return Value:
None
--*/
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("+ETH8XX: HW_Start_Xmit\r\n")));
TxElement->pBufferDescriptor->bd_status |= ETH_TX_READY;
IF_LOG( eth8xxLog('x');)
DEBUGMSG(ZONE_FUNCTION, (TEXT("-ETH8XX: HW_Start_Xmit\r\n")));
}
/*----------------------------------------------------------------------*/
VOID HW_Advance_Element(IN RXTX_ELEMENT *pElement,
IN INT andStatusMask,
IN INT orStatusMask,
IN BD *pFirstBufferDescriptor,
IN PUCHAR pFirstBuffer,
IN BD *pLastBufferDescriptor,
IN UINT bufferSize,
IN BOOLEAN resetDescriptor)
/*++
Description:
Advances the buffer descriptor for both the transmit and receive
queues. For receives, this routine is called after each newly
arrived frame has been indicated and transferred to NDIS via a
call to NdisMEthIndicateReceive(). Note that we must explicitly
clear all of the frame status bits in the buffer descriptor.
Testing has shown that the CPM will set the status bits as
appropriate but it will not clear out any of the bits that may
have been previously set.
Arguments:
pElement - Rx/Tx queue element to be updated
andStatusMask - Boolean mask ANDed with status bits
orStatusMask - Boolean mask ORed with status bits
pFirstBufferDescriptor - address of first buffer descriptor in queue
pFirstBuffer - address of associated buffer
pLastBufferDescriptor - address of last buffer descriptor in queue
bufferSize - size of each buffer in bytes
resetDescriptor - TRUE to prepare descriptor for reuse
Return Value:
None
--*/
{
DEBUGMSG(ZONE_FUNCTION | ZONE_RCV,
(TEXT("+ETH8XX: HW_Advance_Element\r\n")));
if (resetDescriptor)
{
/* Prepare buffer descriptor for next usage. */
pElement->pBufferDescriptor->bd_length = 0;
pElement->pBufferDescriptor->bd_status &= andStatusMask;
pElement->pBufferDescriptor->bd_status |= orStatusMask;
}
/* Wrap around end of buffer descriptor list if necessary. */
if (pElement->pBufferDescriptor == pLastBufferDescriptor)
{
pElement->pBufferDescriptor = pFirstBufferDescriptor;
pElement->pBuffer = pFirstBuffer;
} else {
pElement->pBufferDescriptor++;
pElement->pBuffer += bufferSize;
}
DEBUGMSG(ZONE_FUNCTION | ZONE_RCV,
(TEXT("-ETH8XX: HW_Advance_Element\r\n")));
return;
}
/*----------------------------------------------------------------------*/
BOOLEAN HW_Fill_Multicast_Regs(IN PETH8XX_ADAPTER Adapter)
/*++
Description:
Erases and refills the multicast registers. Used when
an address has been deleted and all bits must be recomputed.
Arguments:
Adapter - pointer to the NDIS miniport adapter block
Return Value:
None
--*/
{
BOOLEAN rc = TRUE; /* return status code. */
UINT i; /* Simple loop counter. */
UINT cur_addr; /* Current address to be added/hashed. */
DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
(TEXT("+ETH8XX: HW_Fill_Multicast_Regs\r\n")));
/* Need to stop Ethernet interface prior to clearing GADDR and IADDR. */
if (HW_Set_All_Multicast(Adapter, FALSE) != NDIS_STATUS_SUCCESS)
{
/* Failed to stop interface and clear multicast registers. */
rc = FALSE;
} else {
/* Execute the SET GROUP ADDRESS for each multicast address. */
for (i = 0; i < Adapter->NbrMulticasts; i++)
{
cur_addr = i * ETH_LENGTH_OF_ADDRESS;
DEBUGMSG(ZONE_INIT,
(TEXT(" ETH8XX: Multicast [ %02x-%02x-%02x-%02x-%02x-%02x ]\r\n"),
Adapter->Addresses[i][cur_addr],
Adapter->Addresses[i][cur_addr + 1],
Adapter->Addresses[i][cur_addr + 2],
Adapter->Addresses[i][cur_addr + 3],
Adapter->Addresses[i][cur_addr + 4],
Adapter->Addresses[i][cur_addr + 5]));
/* Pick out the next address and store it in the CPM. */
ADS_IMMR->pram[SCC_ETH_PARM].enet_scc.taddr_h = (USHORT)
((Adapter->Addresses[i][cur_addr + 5] << 8)
+ Adapter->Addresses[i][cur_addr + 4]);
ADS_IMMR->pram[SCC_ETH_PARM].enet_scc.taddr_m = (USHORT)
((Adapter->Addresses[i][cur_addr + 3] << 8)
+ Adapter->Addresses[i][cur_addr + 2]);
ADS_IMMR->pram[SCC_ETH_PARM].enet_scc.taddr_l = (USHORT)
((Adapter->Addresses[i][cur_addr + 1] << 8)
+ Adapter->Addresses[i][cur_addr]);
/* Execute the CPM "SET GROUP ADDRESS" command. */
if (!KernelIoControl(OEM_IOCTL_ISSUE_CPM_CMD, (LPVOID)SCC_ETH_CH_NUM,
SET_GROUP_ADDRESS, (LPVOID) NOTUSED, (DWORD) NOTUSED,
(LPDWORD)NOTUSED))
{
DEBUGMSG(ZONE_ERROR,
(TEXT("*ETH8XX: Error issuing SET GROUP ADDR\r\n")));
}
}
}
DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
(TEXT("-ETH8XX: HW_Fill_Multicast_Regs\r\n")));
return(rc);
}
/*----------------------------------------------------------------------*/
NDIS_STATUS HW_Set_All_Multicast(IN PETH8XX_ADAPTER Adapter,
IN BOOLEAN On)
/*++
Description:
Turns on/off all the bits in the multicast (Group) address hash
table. Note that the Individual address (IADDR) hash table is
currently unused (see the PSMR register) so we just clear it.
Arguments:
Adapter - pointer to NDIS miniport adapter block
Return Value:
NDIS_STATUS_SUCCESS - Group and Individual hash tables updated
NDIS_STATUS_FAILURE - failed to update Group and Individual hash tables
--*/
{
NDIS_STATUS rc = NDIS_STATUS_FAILURE;
DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
(TEXT("+ETH8XX: HW_Set_All_Multicast\r\n")));
/* Stop the Ethernet interface before updating GADDR and IADDR. */
if (HW_Stop(Adapter))
{
if (On)
{
/* Enable reception of all "Group/Multicast" frames. */
ADS_IMMR->pram[SCC_ETH_PARM].enet_scc.gaddr1 = (SHORT)0xFFFF;
ADS_IMMR->pram[SCC_ETH_PARM].enet_scc.gaddr2 = (SHORT)0xFFFF;
ADS_IMMR->pram[SCC_ETH_PARM].enet_scc.gaddr3 = (SHORT)0xFFFF;
ADS_IMMR->pram[SCC_ETH_PARM].enet_scc.gaddr4 = (SHORT)0xFFFF;
} else {
/* Disable reception of all "Group/Multicast" frames. */
ADS_IMMR->pram[SCC_ETH_PARM].enet_scc.gaddr1 = (SHORT)0x0000;
ADS_IMMR->pram[SCC_ETH_PARM].enet_scc.gaddr2 = (SHORT)0x0000;
ADS_IMMR->pram[SCC_ETH_PARM].enet_scc.gaddr3 = (SHORT)0x0000;
ADS_IMMR->pram[SCC_ETH_PARM].enet_scc.gaddr4 = (SHORT)0x0000;
}
/* Individual address hash table is currently unused. */
ADS_IMMR->pram[SCC_ETH_PARM].enet_scc.iaddr1 = (SHORT)0x0000;
ADS_IMMR->pram[SCC_ETH_PARM].enet_scc.iaddr2 = (SHORT)0x0000;
ADS_IMMR->pram[SCC_ETH_PARM].enet_scc.iaddr3 = (SHORT)0x0000;
ADS_IMMR->pram[SCC_ETH_PARM].enet_scc.iaddr4 = (SHORT)0x0000;
/* Restart the Ethernet interface. */
rc = HW_Start(Adapter) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE;
}
DEBUGMSG(ZONE_INIT|ZONE_FUNCTION,
(TEXT("-ETH8XX: HW_Set_All_Multicast\r\n")));
return(rc);
}
/*----------------------------------------------------------------------*/
VOID HW_Set_Promiscuous(IN PETH8XX_ADAPTER Adapter,
IN BOOLEAN On)
/*++
Description:
Enables or disables promiscuous mode (reception of all packets).
Arguments:
Adapter - pointer to NDIS miniport adapter block
On - Turn mode on (TRUE) or off (FALSE)
Return Value:
None
--*/
{
DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
(TEXT("+ETH8XX: HW_Set_Promiscuous\r\n")));
/* Set the PRO bit in the Protocol-specific Mode Register (PSMR). */
if (On)
{
ADS_IMMR->scc_regs[SCC_ETH_PARM].scc_psmr |= ETH_MODE_PROMISCUOUS;
} else {
ADS_IMMR->scc_regs[SCC_ETH_PARM].scc_psmr &= ~(ETH_MODE_PROMISCUOUS);
}
DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
(TEXT("-ETH8XX: HW_Set_Promiscuous\r\n")));
}
/*----------------------------------------------------------------------*/
VOID HW_Set_Broadcast(IN PETH8XX_ADAPTER Adapter,
IN BOOLEAN On)
/*++
Description:
Enables or disables reception of Ethernet broadcasts.
Arguments:
Adapter - pointer to NDIS miniport adapter block
On - Turn mode on (TRUE) or off (FALSE)
Return Value:
None
--*/
{
DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
(TEXT("+ETH8XX: HW_Set_Broadcast\r\n")));
/* Set the PRO bit in the Protocol-specific Mode Register (PSMR). */
if (On)
{
ADS_IMMR->scc_regs[SCC_ETH_PARM].scc_psmr &= ~(ETH_MODE_REJ_BROADCAST);
} else {
ADS_IMMR->scc_regs[SCC_ETH_PARM].scc_psmr |= ETH_MODE_REJ_BROADCAST;
}
DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
(TEXT("-ETH8XX: HW_Set_Broadcast\r\n")));
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?