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 + -
显示快捷键?