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

📄 cs8950.c

📁 EP9315开发板的Wince6.0的BSP包文件
💻 C
📖 第 1 页 / 共 5 页
字号:
    volatile DWORD Status; 
    // volatile DWORD BufIndx;
    WORD  Errors;
    WORD  Index;
    DWORD RxDecDW1,RxDecDW2; 
    DWORD *pRxDecDW; 
    static unsigned char tempFrame[1524];
    pCD    = (PCD)pChip->pData;

    // ULONG ulAvaliableBuffers; 
    //ulAvaliableBuffers = AvaliableRecieveBuffers();
    //                         
    //if(ulAvaliableBuffers < 16)
    //{
    //    EdbgOutputDebugString("Avaliable = %d\r\n", ulAvaliableBuffers);
    //}


    //
    // The documentation says that if there is no frame in the frame buffer then
    // return.
    //
    Status=pCD->pRxStatNext->RxStat;
    if (!(Status & RxStat_RxFP))  
    {
        Status = ReadDWord(OpReg_IntStsC);
        return FALSE;
    } 

    //BufIndx=pCD->pRxStatNext->BufIndx;
    //if (!(BufIndx & RxStat_RxFP))  
    //{
        //Status = ReadDWord(OpReg_IntStsC);
    //    return FALSE;
    //} 
    

    /* Get the total length of the frame */
    *pwLength = pCD->pRxStatNext->FrameLength;

      
    /* If the received frame has errors */
    if ( !(Status & RxStat_RxWE) )
    {
       Errors = (WORD)((Status & RxStat_Error_Mask) >> 16);
       VpsRecvError( pChip, Errors );
       *pwLength=0; // 0 means a frame with error. */
    }

    /* 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;
}


/******************************************************************************
*
* CS8950MulticastAddAll()
*
******************************************************************************/

void CS8950MulticastAddAll(void)
{
    DWORD RxControl;

 
    /* Get the current settings of the receiver control register */
    RxControl=ReadDWord( OpReg_RxCTL );

    /* Turn off the receiver while changing the hash table */
    WriteDWord( OpReg_RxCTL, RxControl & ~RxCTL_SerRxON );
    
    /* Set all the bits in the hash table */
    WriteByte( OpReg_AFP, AFP_Hash );
    WriteDWord( OpReg_HashTb , 0xFFFFFFFF );
    WriteDWord( OpReg_HashTb+4, 0xFFFFFFFF );

    /* Turn the receiver back on */
    WriteDWord(OpReg_RxCTL, RxControl );

}

//****************************************************************************
// 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 BOOL PHYAutoNegotiation()
{
    unsigned short   val;
    int              x;
    unsigned short   PhyId;
    unsigned char    b8;
    WORD             Result;
    char            *strDuplex, *strSpeed;


    FindPHYType(pChip);
    PhyId = ((PCD)pChip->pData)->PHYAddress;

    //
    // 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 PHY to Full_Duplex 100 Mbit.
        //
        Result = WritePHY( pChip, 0x0, PHYReg_BMCR, BMCR_Full_Duplex|BMCR_100_MBPS); 

		//set MAC for Full Duplex too.
		b8 = ReadByte(OpReg_TestCTL); 
        b8 |=  TestCTL_MACFDX;
        WriteByte(OpReg_TestCTL, b8);

        EdbgOutputDebugString("EthernetMAC: Error! PHY cannot complete Auto Negotiation. Set to 100MBps Full Duplex.\n"); 
        return FALSE;
    }

	//CS8952 needs 1 second delay.  Otherwise it won't send the 1st frame.
	if ( ((PCD)pChip->pData)->PHYType == PHY_TYPE_CRYSTAL)
	{
       DelayInMsec(1000);
	}

    strDuplex = "Half";   

    /* 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);

        strDuplex = "Full";   
    }

    
    strSpeed = "10";   
    //
    // Lets print out the current mode that we are operating in.
    //
    if((val & ANLPAR_100BaseTX_FDX_Able) || (val & ANLPAR_100BaseTX_HDX_Able))
    {
        strSpeed = "100";   
    }


    // 
    // Show the current link mode.
    //
    EdbgOutputDebugString("EthernetMAC: PhyId=%d PhyType=%d Speed=%s Mbs Duplex=%s.\n",
		                   PhyId, ((PCD)pChip->pData)->PHYType, strSpeed, strDuplex); 


   return TRUE;
}


/******************************************************************************
*
* ReadPHY()
*
******************************************************************************/
static 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;
}

⌨️ 快捷键说明

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