hwcom.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 1,737 行 · 第 1/4 页
C
1,737 行
/*----------------------------------------------------------------------*/
#pragma NDIS_PAGEABLE_FUNCTION(HW_Setup)
BOOLEAN HW_Setup(IN PETH8XX_ADAPTER Adapter)
/*++
Description:
Sets up the CPM for Ethernet mode. The following sequence of
operations must be performed in order to configure and initialize
the Ethernet interface for MPC821ADS:
1. allocate buffer descriptors from the dual-ported RAM
2. allocate data buffers from external RAM
3. configure the buffer descriptors
4. configure the parallel port pins needed for Ethernet mode
5. configure SCC1 for Ethernet mode
6. configure the SCC1 common protocol RAM
7. configure the Ethernet protocol RAM
8. initialize the CPM to load the Ethernet parameters
9. configure Ethernet interrupts/events (CPM and SIU
interrupt configuration is currently handled in the OAL)
10. enable Ethernet interrupts/events
In addition to the above CPM configuration, the Ethernet transceiver
on the ADS board must also be enabled along with the transmit enable
(TENA) pin (currently mapped to parallel port B pin #19). Both of
these operations are performed by calling HW_Toggle_Eth_If() after
successfully calling this function. Only after all of these steps
have been successfully completed can the Ethernet interface be used.
Arguments:
Adapter - pointer to the NDIS miniport adapter block
Return Value:
TRUE - if successfully configured and enabled
FALSE - if error occurred
--*/
{
DEBUGMSG(ZONE_FUNCTION | ZONE_INIT, (TEXT("+ETH8XX: HW_Setup\r\n")));
/* Assign all the necessary parallel port bits. */
HW_Setup_Par_Ports(Adapter);
/* Setup the serial interface registers in the CPM. */
HW_Setup_Serial_If(Adapter);
/* Configure the common protocol area in the param section of the CPM. */
HW_Setup_Common_Protocol_Area(Adapter);
/* Configure the protocol specific area in the CPM. */
HW_Setup_Eth_Protocol_Area(Adapter);
if (!HW_Handshake_CPM_Init(Adapter))
{
return(FALSE);
}
/* Clear pending events. */
HW_Clear_Init_Events(Adapter);
/* Setup the interrupt events. */
HW_Configure_Interrupts(Adapter);
DEBUGMSG(ZONE_FUNCTION | ZONE_INIT, (TEXT("-ETH8XX: HW_Setup\r\n")));
return(TRUE);
}
/*----------------------------------------------------------------------*/
BOOLEAN HW_Reset(IN PETH8XX_ADAPTER Adapter)
/*++
Description:
Resets the Ethernet interface by performing the following steps:
1. issue GRACEFUL STOP TRANSMIT command
2. clear the ENT and ENR bits in the GSMR
3. disable interrupts
4. disable TENA and BCSR1
5. reset transmit data structures
6. reset receive data structures
7. enable TENA and BCSR1
8. enable interrupts
9. issue INIT TX AND RX PARAMETERS command
10. set the ENT and ENR bits in the GSMR
Arguments:
Adapter - pointer to the NDIS miniport adapter block
Return Value:
TRUE if reset was successful
FALSE otherwise
--*/
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("+ETH8XX: HW_Reset\r\n")));
IF_LOG( eth8xxLog('1'); )
/* Stop the SCC port. */
if (!HW_Stop(Adapter))
{
return(FALSE);
}
IF_LOG( eth8xxLog('2'); )
DEBUGMSG(ZONE_FUNCTION, (TEXT("-ETH8XX: HW_Reset\r\n")));
/* Restart the SCC channel. */
return(HW_Start(Adapter));
}
/*----------------------------------------------------------------------*/
VOID HW_Get_Interrupt_Status(IN PETH8XX_ADAPTER Adapter,
OUT PUCHAR InterruptStatus)
/*++
Description:
Reads the Ethernet interrupt event (SCCE) register from
the CPM to report all events.
Arguments:
Adapter - pointer to NDIS miniport adapter block.
InterruptStatus - Returns the value of SCCE.
Return Value:
None (see InterruptStatus)
--*/
{
UINT16 Event;
DEBUGMSG(ZONE_FUNCTION, (TEXT("+ETH8XX: HW_Get_Interrupt_Status\r\n")));
Event = ADS_IMMR->scc_regs[SCC_ETH_PARM].scc_scce;
/* Note that event register is only 16-bits wide. */
*InterruptStatus = (UCHAR)(Event & 0xFF);
DEBUGMSG(ZONE_FUNCTION, (TEXT("-ETH8XX: HW_Get_Interrupt_Status\r\n")));
}
/*----------------------------------------------------------------------*/
VOID HW_Ack_Interrupt_Status(IN PETH8XX_ADAPTER Adapter,
IN UCHAR InterruptStatus)
/*++
Description:
Clears the interrupt event (SCCE) register on the CPM.
Arguments:
Adapter - pointer to NDIS miniport adapter block.
InterruptStatus - the SCCE bits to be cleared
Return Value:
None
--*/
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("+ETH8XX: HW_Ack_Interrupt_Status\r\n")));
/* Write a "1" to clear an event bit. */
ADS_IMMR->scc_regs[SCC_ETH_PARM].scc_scce = (UINT16) InterruptStatus;
DEBUGMSG(ZONE_FUNCTION, (TEXT("-ETH8XX: HW_Ack_Interrupt_Status\r\n")));
}
/*----------------------------------------------------------------------*/
VOID HW_Block_Interrupts(IN PETH8XX_ADAPTER Adapter)
/*++
Description:
Blocks all Ethernet events/interrupts from the CPM by
clearing the interrupt mask (SCCM) register.
Arguments:
Adapter - pointer to NDIS miniport adapter block.
Return Value:
--*/
{
DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
(TEXT("+ETH8XX: HW_Block_Interrupts\r\n")));
ADS_IMMR->scc_regs[SCC_ETH_PARM].scc_sccm = (UINT16) 0x0000;
DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
(TEXT("-ETH8XX: HW_Block_Interrupts\r\n")));
}
/*----------------------------------------------------------------------*/
VOID HW_Unblock_Interrupts(IN PETH8XX_ADAPTER Adapter)
/*++
Description:
Unblocks all interrupts from the CPM by setting the
interrupt mask (IMR) register.
Arguments:
Adapter - pointer to NDIS miniport adapter block.
Return Value:
None
--*/
{
DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
(TEXT("+ETH8XX: HW_Unblock_Interrupts\r\n")));
/* Setup subscribed events. Note that we don't want RXB, i.e. we
* only want to deal with entire frames.
*/
ADS_IMMR->scc_regs[SCC_ETH_PARM].scc_sccm = ETH_TXB_EVENT
| ETH_BSY_EVENT
| ETH_RXF_EVENT
| ETH_TXE_EVENT
| ETH_GRA_EVENT
;
/* Nothing else to do here, assumed that the OAL does the rest. */
DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
(TEXT("-ETH8XX: HW_Unblock_Interrupts\r\n")));
}
/*----------------------------------------------------------------------*/
BOOLEAN HW_Copy_Down_Packet(IN PETH8XX_ADAPTER Adapter,
IN PNDIS_PACKET Packet,
IN RXTX_ELEMENT *TxElement)
/*++
Description:
Copies the Packet down to a transmit buffer identified by
XmitBufferNum, also fills in the buffer descriptor Length
field to be the length of the packet.
Arguments:
Adapter - pointer to NDIS miniport adapter block.
Packet - the packet to copy down
TxElement - the transmit element to update
Return Value:
TRUE - if the transfer completed with no problems.
FALSE - otherwise
--*/
{
PUCHAR CurBufAddress; /* Source NDIS buffer pointer. */
PUCHAR XmitBufAddress; /* Destination virtual RAM address. */
UINT CurBufLen; /* Length of the current NDIS buffer. */
PNDIS_BUFFER CurBuffer; /* Current NDIS buffer being copied. */
UINT PacketLength; /* Length of the entire packet. */
UINT i; /* Simple loop counter. */
DEBUGMSG(ZONE_FUNCTION | ZONE_XMIT,
(TEXT("+ETH8XX: HW_Copy_Down_Packet\r\n")));
/* Get the packet information. */
NdisQueryPacket(Packet, NULL, NULL, &CurBuffer, &PacketLength);
DEBUGMSG(ZONE_XMIT,
(TEXT(" ETH8XX: HW_Copy_Down_Packet size: 0x%X.\r\n"), PacketLength));
/* Skip zero-length packets. */
if (PacketLength == 0)
{
return(TRUE);
}
/* Get the starting buffer address. */
XmitBufAddress = TxElement->pBuffer;
/* Get address and length of the first buffer in the packet. */
NdisQueryBuffer(CurBuffer, (PVOID *)&CurBufAddress, &CurBufLen);
/* Eliminate 0 length buffers. */
while (CurBuffer && (CurBufLen == 0))
{
NdisGetNextBuffer(CurBuffer, &CurBuffer);
if (CurBuffer)
{
NdisQueryBuffer(CurBuffer, (PVOID *)&CurBufAddress, &CurBufLen);
}
}
/* Return if we did not actually get a buffer. */
if (!CurBuffer)
{
DEBUGMSG(ZONE_ERROR,
(TEXT("*ETH8XX: We would have panicked ! size: 0x%X.\r\n"),
CurBufLen));
return(FALSE);
}
/* Copy the data now. */
do
{
for (i = 0; i < CurBufLen; i++)
{
*XmitBufAddress++ = *CurBufAddress++;
}
/* Move to the next buffer. */
NdisGetNextBuffer(CurBuffer, &CurBuffer);
if (CurBuffer)
{
NdisQueryBuffer(CurBuffer, (PVOID *)&CurBufAddress, &CurBufLen);
}
/* Get address and length of the next buffer. */
while (CurBuffer && (CurBufLen == 0))
{
NdisGetNextBuffer(CurBuffer, &CurBuffer);
if (CurBuffer)
{
NdisQueryBuffer(CurBuffer, (PVOID *)&CurBufAddress, &CurBufLen);
}
}
} while (CurBuffer);
/* Update the CPM Buffer Descriptor. */
TxElement->pBufferDescriptor->bd_status |= (ETH_TX_PAD
| ETH_TX_LAST
| ETH_TX_INTR
| ETH_TX_CRC
);
TxElement->pBufferDescriptor->bd_length = PacketLength;
DEBUGMSG(ZONE_FUNCTION | ZONE_XMIT,
(TEXT("-ETH8XX: HW_Copy_Down_Packet\r\n")));
return(TRUE);
}
/*----------------------------------------------------------------------*/
BOOLEAN HW_Copy_Up_Packet(IN PETH8XX_ADAPTER Adapter,
IN PUCHAR TargetBuffer,
IN PUCHAR SourceBuffer,
IN UINT BufferLength)
/*++
Description:
Copies data from the data buffer to memory.
Arguments:
Adapter - pointer to the adapter block
TargetBuffer - the target address
SourceBuffer - the source address (on the Ethernet controller)
BufferLength - the number of bytes to copy
Return Value:
TRUE if the transfer completed with no problems.
--*/
{
DEBUGMSG(ZONE_FUNCTION | ZONE_RCV,
(TEXT("+ETH8XX: HW_Copy_Up_Packet\r\n")));
NdisMoveMemory(TargetBuffer, SourceBuffer, BufferLength);
DEBUGMSG(ZONE_FUNCTION | ZONE_RCV,
(TEXT("-ETH8XX: HW_Copy_Up_Packet\r\n")));
return TRUE;
}
/*----------------------------------------------------------------------*/
BOOLEAN HW_Start(IN PETH8XX_ADAPTER Adapter)
/*++
Description:
Re-enables Ethernet mode after a prior call to HW_Stop().
Arguments:
Adapter - pointer to the NDIS miniport adapter block
Return Value:
None
--*/
{
BOOLEAN rc;
DEBUGMSG(ZONE_FUNCTION | ZONE_INIT, (TEXT("+ETH8XX: HW_Start\r\n")));
if (Adapter->Status != ENABLED)
{
/* Issue INIT TX AND RX PARAMETERS command. */
rc = HW_Handshake_CPM_Init(Adapter);
if (rc)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?