⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cs8950.c

📁 wince.net板级支持包BSP for EP9315
💻 C
📖 第 1 页 / 共 4 页
字号:
    /* Get the index of the buffer that contains the frame data */
    Index = (WORD)(pCD->pRxStatNext->BufIndx & RxStat_BufIndx_Mask);
    memcpy(pbData, pCD->RxBuff[Index].pBuff, *pwLength);


    /* Mark the buffer as now available */
    pRxDecDW= (DWORD *)(pCD->pRxDesc+Index);
    RxDecDW1=*pRxDecDW++;
    RxDecDW2=*pRxDecDW;
    (pCD->pRxDesc+Index)->BufLength = RXBUFFSIZE;

    pCD->pRxStatNext->RxStat  = 0x0;
    pCD->pRxStatNext->BufIndx = 0x0;
    pCD->pRxStatNext->FrameLength = 0x0;

    /* Increment to the next receive status entry (with wrap-around) */
    pCD->pRxStatNext++;
    if ( pCD->pRxStatNext == pCD->pRxStatLimit )
    {
        pCD->pRxStatNext = pCD->pRxStat;
    }        


    /* Enqueue the number of receive descriptors processed to the chip */
    WriteDWord( OpReg_RxDEQ, 1 );

    /* Enqueue the number of receive status entries processed to the chip */
    WriteDWord( OpReg_RxSEQ, 1 );


    //
    // Need to perform a dummy read to clear the interrupt status if there are no
    // more interrupt packets.
    //
    Status = pCD->pRxStatNext->RxStat;
    if (!(Status & RxStat_RxFP))  
    {
        Status = ReadDWord(OpReg_IntStsC);
    }
   
    Global_RxTotalCnt++;


    //   EdbgOutputDebugString("\nCS8950  CS8950GetFrame(): Global_RxTotalCnt=%d\n",Global_RxTotalCnt);
 
   //RxWorkaround();

    /* Frame Length == 0 means the received frame with error*/
    if ( *pwLength == 0 ) 
    {
        EdbgOutputDebugString("\n CS8950GetFrame(): Length = 0\r\n");
        return FALSE; 
    }
    
    //
    // Lets send the frame out again as a broadcast packet.
    //
#if 0
    memcpy(tempFrame, pbData,*pwLength);
    tempFrame[0] = 0x00;
    tempFrame[1] = 0x06;
    tempFrame[2] = 0x5B;
    tempFrame[3] = 0xd3;
    tempFrame[4] = 0xFC;
    tempFrame[5] = 0x98;

    tempFrame[6]  = 0x00;
    tempFrame[7]  = 0x00;
    tempFrame[8]  = 0x00;
    tempFrame[9]  = 0x00;
    tempFrame[10] = 0x00;
    tempFrame[11] = 0x00;

    CS8950SendFrame
    ( 
        tempFrame, 
        *pwLength
    );
#endif // 0
    

    return TRUE;
}

//****************************************************************************
// CS8950EnableInts
//****************************************************************************
// Public function that enables ethernet interrupts.
// 
//
void  CS8950EnableInts(void)
{
    EdbgOutputDebugString("CS8950EnableInts\r\n");
    WriteDWord(OpReg_IntEn, IntEn_RxEOFiE );
    WriteDWord(OpReg_FERMask, GIntMask_Interrupt);
}

//****************************************************************************
// CS8950DisableInts
//****************************************************************************
// Public function that disables ethernet interrupts.
// 
//
void  CS8950DisableInts(void)
{
    EdbgOutputDebugString("CS8950DisableInts\r\n");
    WriteDWord(OpReg_IntEn, 0);
    WriteDWord(OpReg_FERMask, 0 );
}

//****************************************************************************
// CS8950GetPendingInterrupts
//****************************************************************************
// Public function that return INTR_TYPE_RX if there are pending ethernet 
// receive interrupts.
// 
//
DWORD   CS8950GetPendingInterrupts(void)
{
    PCD    pCD;
    pCD    = (PCD)pChip->pData;


    if (pCD->pRxStatNext->RxStat & RxStat_RxFP)  
    {
        EdbgOutputDebugString("R");
        return INTR_TYPE_RX;
    }        
    EdbgOutputDebugString("n");
    return 0;
}

//****************************************************************************
// CS8950ReadEEPROM
//****************************************************************************
// Public function to read the pseudo EEPROM
// 
//
BOOL CS8950ReadEEPROM
(
    UINT16 EEPROMAddress, 
    UINT16 *pwVal
)
{
    *pwVal = gusMacAddr[EEPROMAddress];
    return TRUE;
}

//****************************************************************************
// CS8950WriteEEPROM 
//****************************************************************************
// Public function to write the psuedo EEPROM.
// 
//
BOOL  CS8950WriteEEPROM 
( 
    UINT16 EEPROMAddress, 
    UINT16 Data 
)
{
    gusMacAddr[EEPROMAddress] = Data;
    return TRUE;
}



//****************************************************************************
// GetMACAddress
//****************************************************************************
// 
// 
//
static int GetMACAddress(USHORT *MacAddr)
{
    if(gusMacAddr[0] == 0 && gusMacAddr[1] == 0 && gusMacAddr[2] == 0)
        return FALSE;

    //
    // Currently copy the Mac Address from internal ram.
    //
    MacAddr[0] = gusMacAddr[0];
    MacAddr[1] = gusMacAddr[1];
    MacAddr[2] = gusMacAddr[2];

    return TRUE;
}



/******************************************************************************
*
* PHYAutoNegotiation();
* Purpose: PHY Auto Negotiation to detect the link speed (10/100Mbps) and 
*          duplex (half/full).
* return:  TRUE: successful. FALSE: fail
*
******************************************************************************/
static int PHYAutoNegotiation()
{
    unsigned short   val;
    int              x;
    unsigned short   PhyId;
    unsigned char    b8;
    WORD             Result;
    char            *strDuplex, *strSpeed;

    PhyId = 0x1;

    //
    // Write to Auto-Negotiation Advertisement Register (0x04)
    // Set IEEE_802.3, and advertise 100/10M full/half duplex available
    //
    val = ANAR_SeltField_IEEE8023 | ANAR_10BaseT_HDX_Able | ANAR_10BaseT_FDX_Able | 
          ANAR_100BaseTX_HDX_Able | ANAR_100BaseTX_FDX_Able;
    Result = WritePHY( pChip, PhyId, PHYReg_ANAR, val);
    ASSERT(Result);


    /*write to Basic Mode Control Register (0x00), enable and restart auto negotiation*/
    val = BMCR_Restart_Auto_Neg| BMCR_Auto_Neg_Enable;
    Result = WritePHY( pChip, PhyId, PHYReg_BMCR, val);
      
    for(x = 0; x<MAX_AUTOCONFIGTIME; x++)  /* 02/14/02 @melody Auto_Neg should be compeleted in 5 min.*/
    { 
        /* Check if Auto-Negotiation complete? */
        DelayInMsec(1);
        Result = ReadPHY( pChip, PhyId, PHYReg_BMSR, &val );
        if((val & BMSR_Auto_Neg_Complete) )
        {
            break;
        }
    }

    if(x == MAX_AUTOCONFIGTIME)
    {
        //
        // If this fails set to Half_Duplex 10 Mbit.
        //
        Result = WritePHY( pChip, 0x0, PHYReg_BMCR, 0x0000); 
        EdbgOutputDebugString("CS8950: Error! PHY cannot complete Auto Negotiation.\n"); 
        return FALSE;
    }

    /* if the Link is Full Duplex, then set MAC for Full Duplex too. */  
    Result = ReadPHY( pChip, PhyId, PHYReg_ANLPAR, &val );

    //if((val & ANLPAR_10BaseT_FDX_Able) || (val & ANLPAR_100BaseTX_FDX_Able)) 
    //{
    //    b8 = ReadByte(OpReg_TestCTL); 
    //    b8 |=  TestCTL_MACFDX;
    //    WriteByte(OpReg_TestCTL, b8);
    //}

    Result = ReadPHY( pChip, PhyId, PHYReg_SSR, &val );
    if(val & SSR_Full_Duplex ) 
    {
        b8 = ReadByte(OpReg_TestCTL); 
        b8 |=  TestCTL_MACFDX;
        WriteByte(OpReg_TestCTL, b8);
    }

    //
    // Lets print out the current mode that we are operating in.
    //
    if(val & SSR_Full_Duplex)
    {
        strDuplex = "Full";   
    }
    else
    {
        strDuplex = "Half";   
    }

    if(val & SSR_10_Mbps)
    {
        strSpeed = "10";   
    }
    else
    {
        strSpeed = "100";   
    }

    // 
    // Show the current link mode.
    //
    EdbgOutputDebugString("CS8950: Speed = %s Mbs, Duplex = %s.\n", strSpeed, strDuplex); 

   return TRUE;
}



/******************************************************************************
*
* StartupPHY()
*
******************************************************************************/
static WORD StartupPHY( PCHIP pChip )
{
    PCD     pCD;
    WORD    Result;
 

    pCD = (PCD)pChip->pData;
    /* Disable 2nd PHY */
    //Result = WritePHY( pChip, 0x1f, PHYReg_BMCR, BMCR_Power_Down);
    //ASSERT(Result);


    /* QQQQQQQ Disable SQE in Reg 0x13 */
    Result = WritePHY( pChip, 0x0, 0x13, 0x0000);
    ASSERT(Result);


    /* Set PHY Internal LoopBack */
    /*     Result = WritePHY( pChip, 0x0, PHYReg_BMCR, BMCR_Full_Duplex|BMCR_Loopback);*/
    /*Result = WritePHY( pChip, 0x0, PHYReg_BMCR, BMCR_Auto_Neg_Enable|BMCR_Restart_Auto_Neg);*/
    //     Result = WritePHY( pChip, 0x0, PHYReg_BMCR, BMCR_Full_Duplex); }
    //Result = WritePHY( pChip, 0x0, PHYReg_BMCR, 0x0000); //Half_Duplex
    // @melody 09/10/01   Result = WritePHY( pChip, 0x0, PHYReg_BMCR, 0x0000); //Half_Duplex
    //ASSERT(Result);
    /* @melody 09/10/01  */

    Result =PHYAutoNegotiation();

    ASSERT(Result);

    return MAC_SUCCESSFUL;
}



/******************************************************************************
*
* ReadPHY()
*
******************************************************************************/
BOOL ReadPHY( PCHIP pChip, WORD Address, WORD Register, WORD *pValue )
{
    BYTE Status;
    int  x;

    /* Ensure that the PHY is not busy */
    for ( x=0; x<MAXLOOP; x++ )
    {
        Status=ReadByte( OpReg_MIISts );
        if ( !(Status & MIISts_Busy) ) break;
    }
    if ( x == MAXLOOP ) 
    {   
        EdbgOutputDebugString
        (
            "First PHY read failed, Address =0x%x, Register= 0x%x. \r\n", 
            Address, 
            Register
        );
        return FALSE;
    }

    /* Issue the command to read the register within the PHY */
    WriteWord(OpReg_MIICmd, (WORD)(MIICmd_Opcode_Read |(Address<<5)| Register));

    /* Wait until the command is completed */
    for ( x=0; x<MAXLOOP; x++ )
    {
        Status=ReadByte( OpReg_MIISts);
        if ( !(Status & MIISts_Busy) ) 
            break;
    }
    if ( x == MAXLOOP ) 
    {   
        EdbgOutputDebugString("Second PHY read failed!");
        return MAC_FAILED;
    }


    /* Get the PHY data from the PHY Data register */
    *pValue=ReadWord( OpReg_MIIData );

    return TRUE;
}


/******************************************************************************
*
* WritePHY()
*
******************************************************************************/
BOOL WritePHY( PCHIP pChip, WORD Address, WORD Register, WORD Value )
{
    BYTE Status;
    int  x;


    /* Ensure that the PHY is not busy */
    for ( x=0; x<MAXLOOP; x++ )
    {
        Status=ReadByte( OpReg_MIISts);
        if ( !(Status & MIISts_Busy) ) break;
    }
    if ( x == MAXLOOP ) 
    {       
        EdbgOutputDebugString
        (
            "First PHY write failed, Address = 0x%x, Register = 0x%x, Value = 0x%x.\r\n",
            (ULONG)Address,
            (ULONG)Register,
            (ULONG)Value
        );
        return FALSE;
    }

    /* Put the PHY data into the PHY Data register */
    WriteWord( OpReg_MIIData, Value );

    /* Issue the command to write to the register within the PHY */
    WriteWord( OpReg_MIICmd,(WORD)(MIICmd_Opcode_Write |(Address<<5)| Register));

    /* Wait until the command is completed */
    for ( x=0; x<MAXLOOP; x++ )
    {
        Status=ReadByte( OpReg_MIISts );
        if ( !(Status & MIISts_Busy) ) 
            break;
    }
    if ( x == MAXLOOP ) 
    {       
        EdbgOutputDebugString
        (
            "Second PHY write failed, Address = 0x%x, Register = 0x%x, Value = 0x%x.\r\n",
            (ULONG)Address,
            (ULONG)Register,
            (ULONG)Value
        );
        return FALSE;
    }

    return TRUE;
}


/******************************************************************************
*
* FindPHYType()
*
******************************************************************************/
BOOL FindPHYType( PCHIP pChip )
{
    PCD  pCD;
    WORD PHYAddress;
    BOOL Result;
    union
    {
      WORD  Word[2];
      DWORD DWord;
    } PHYID;

    pCD = (PCD)pChip->pData;

    /* Search for a known type of PHY */
    for ( PHYAddress=0; PHYAddress<32; PHYAddress++ )
    {
        /* Read PHY ID register 1 */
        Result = ReadPHY( pChip, PHYAddress, PHYReg_PHYIDR1, &PHYID.Word[1] );
        if ( Result != TRUE )
        {
            EdbgOutputDebugString("Cannot read PHY ID register 1!\r\n");
            return FALSE;
        }

        /* Read PHY ID register 2 */
        Result = ReadPHY( pChip, PHYAddress, PHYReg_PHYIDR2, &PHYID.Word[0] );
        if ( Result != TRUE )
        {
            EdbgOutputDebugString("Cannot read PHY ID register 2!\r\n");
            return FALSE;
        }

        /* Check if it is a PHY that we know about */
        if ( ((PHYID.DWord & PHYID_OUI_Mask)   == PHYID_OUI_National) &&
           ((PHYID.DWord & PHYID_Model_Mask) == PHYID_Model_DP83840) )
        {
            pCD->PHYType = PHY_TYPE_NATIONAL;
            break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -