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

📄 cs8950.c

📁 ebd9307开发板wince bsp源码,包括cs8900,lcd,nand,serial,touch,usb,gpio,wd等驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
    {
        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;
}


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


static BOOL Check_PHY_ID_Type( PCHIP pChip, WORD PHYAddress)
{
    PCD  pCD;
    BOOL Result;
    union
    {
      WORD  Word[2];
      DWORD DWord;
    } PHYID;

    pCD = (PCD)pChip->pData;

    /* Read PHY ID register 1 */
    Result = ReadPHY( pChip, PHYAddress, PHYReg_PHYIDR1, &PHYID.Word[1] );
    if ( Result != TRUE )
    {
        return FALSE;
	}

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

	 /* Not a Valid PhyID */
	 if (PHYID.DWord == 0xffffffff || PHYID.DWord == 0x0)
	 {
        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;
         DEBUGMSG(ZONE_INIT,(TEXT("Detected National PHY at address: %x\r\n"), PHYAddress) );
	 }
     else if ( ((PHYID.DWord & PHYID_OUI_Mask)   == PHYID_OUI_Crystal) &&
              ((PHYID.DWord & PHYID_Model_Mask) == PHYID_Model_CS8952) )
	 {
         pCD->PHYType = PHY_TYPE_CRYSTAL;
         DEBUGMSG(ZONE_INIT,(TEXT("Detected Crystal PHY at address: %x\r\n"), PHYAddress) );
	 }
     else if ( ((PHYID.DWord & PHYID_OUI_Mask)   == PHYID_OUI_ICS) &&
             ((PHYID.DWord & PHYID_Model_Mask) == PHYID_Model_ICS1890) )
	 {
         pCD->PHYType = PHY_TYPE_ICS;
         DEBUGMSG(ZONE_INIT,(TEXT("Detected ICS1890 PHY at address: %x\r\n"), PHYAddress) );
	 }
     else if ( ((PHYID.DWord & PHYID_OUI_Mask)   == PHYID_OUI_BROADCOM) &&
             ((PHYID.DWord & PHYID_Model_Mask) == PHYID_Model_BCM5201) )
	 {                                                                  
         pCD->PHYType = PHY_TYPE_BROADCOM;                              
         DEBUGMSG(ZONE_INIT,(TEXT("Detected Broadcom PHY at address: %x\r\n"), PHYAddress) );
	 }                                                                  
     else if ( ((PHYID.DWord & PHYID_OUI_Mask)   == PHYID_OUI_MICREL) &&
          ((PHYID.DWord & PHYID_Model_Mask) == PHYID_Model_KS8721BL) )
	 {                                                                  
         pCD->PHYType = PHY_TYPE_MICREL_8721BL;                              
         DEBUGMSG(ZONE_INIT,(TEXT("Detected Micrel KS8721BL PHY at address: %x\r\n"), PHYAddress ));
	 }
     else if (PHYID.DWord == 0x00406212)
	 {
         pCD->PHYType = PHY_TYPE_BROADCOM;
         DEBUGMSG(ZONE_INIT,(TEXT("Detected Broadcom PHY at address: %x\r\n"), PHYAddress) );
	 }
     else if (PHYID.DWord == 0x78100003)
	 {
         pCD->PHYType = PHY_TYPE_LEVEL1; /* clc */
         DEBUGMSG(ZONE_INIT,(TEXT("Detected Level1 PHY at address: %x\r\n"), PHYAddress) );
	 } else
	 {

⌨️ 快捷键说明

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