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

📄 cs8950.c

📁 wince.net板级支持包BSP for EP9315
💻 C
📖 第 1 页 / 共 4 页
字号:
//**********************************************************************
//                                                                      
// Filename: cs8950.c
//                                                                      
// Description: Eboot and ethernet debug code for the CS8950
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Use of this source code is subject to the terms of the Cirrus end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to 
// use this source code. For a copy of the EULA, please see the 
// EULA.RTF on your install media.
//
// Copyright(c) Cirrus Logic Corporation 2002, All Rights Reserved                       
//                                                                      
//**********************************************************************
#include <windows.h>
#include <halether.h>
#include <hwdefs.h>
#include <debugtimer.h>
#include <cs8950sw.h>
#include "cs8950hw.h"
#include "csvchip.h"
#include "csstruct.h"
#include "csv8950.h"
#include "csphy.h"
#include "csv8950.h"


#pragma optimize("", off)
//
//
//
BOOL ReadPHY( PCHIP pChip, WORD Address, WORD Register, WORD *pValue );
static WORD VchipInit( PCHIP pChip );
static WORD VchipReset( PCHIP pChip );
static WORD StartupQueues( PCHIP pChip );
static void InitializeRxQueues( PCHIP pChip );
static void ResetQueues( PCHIP pChip );
static WORD StartupPHY( PCHIP pChip );
static int  ProcessTxStatusQueue( PCHIP pChip );
static void VpsSendError( PCHIP pChip,  WORD Errors );
static void VchipSend(PCHIP pChip,  WORD TotalLength, BYTE *pBuff);
static void VpsRecvError( PCHIP pChip, WORD Errors );
static void DumpRegisters(void);
static void RxWorkaround(void);
static int GetMACAddress(USHORT *MacAddr);

BOOL WritePHY( PCHIP pChip, WORD Address, WORD Register, WORD Value );
void VchipChangeFiltering(unsigned int uiFilteringOpts);
ULONG AvaliableRecieveBuffers(void);

CHIP Chip;
CHIP *pChip;
static CD gCD;
static DWORD Global_TxTotal     =0;
static DWORD Global_TxOkCnt     = 0;
static DWORD Global_TxNotOkCnt  = 0;
static DWORD Global_RxTotalCnt  = 0;
static DWORD Global_RxNotOkCnt  = 0;
static BOOL  Global_TxInProcess =FALSE;
static DWORD gdwEthernetBase = 0;
static USHORT gusMacAddr [3] = {0,0,0};



typedef struct
{
    RxDesc_t        RxDesc[RXDESCCOUNT];
    RxStat_t        RxStat[RXSTATCOUNT];
    TxDesc_t        TxDesc[TXDESCCOUNT];
    TxStat_t        TxStat[TXSTATCOUNT];
    unsigned char   RxBuff[RXBUFFCOUNT][RXBUFFSIZE];
    unsigned char   TxBuff[TXBUFFCOUNT][TXBUFFSIZE];
} CS9850_BUFFER;

CS9850_BUFFER *pCS8950Buffer   = 0 ;
ULONG         ulPhysicalOffset = 0;
#ifdef ASSERT
#undef ASSERT
#endif

#ifdef DEBUG
#define ASSERT(myassert)    if(!myassert) {EdbgOutputDebugString("ASSERTION FAILED: File = %s, Line = %d \r\n",__FILE__, __LINE__);}
#else  // DEBUG
#define ASSERT(myassert)
#endif // DEBUG


//
//  Once we get the memory map down, we need to fill in these  functions.
//
#define CONVERT_TO_PHYSICAL(address)        ((ULONG)address + ulPhysicalOffset)

#define UNSPECIFIED (-1)

//****************************************************************************
// CS8950Disable
//****************************************************************************
// Disables the Transmit and recieve so the MAC does overflow the buffers.
// 
//
void CS8950Disable()
{
    WriteDWord(OpReg_BMCTL, BMCTL_TxDis | BMCTL_RxDis);
}

//****************************************************************************
// CS8950DMAInit
//****************************************************************************
// Initializes the DMA buffer for the CS8950.
// 
// dwPhysicalAddr - Physical address
// dwVirtualAddr  - Virtual address.
// dwSize         - size of the buffer.
//
// return         - TRUE  Success
//                  FALSE Failure
//
BOOL CS8950DMAInit(DWORD dwPhysicalAddr, DWORD dwVirtualAddr, DWORD dwSize)
{
    BOOL    bReturn = FALSE;
    EdbgOutputDebugString
    (
        "CS8950DMAInit:  dwPhysicalAddr = 0x%x, dwVirtualAddr= 0x%x "
        "dwSize = 0x%x\r\n",
        dwPhysicalAddr,
        dwVirtualAddr,
        dwSize
    );
    
    if(dwSize > sizeof(CS9850_BUFFER))
    {
        pCS8950Buffer       = (CS9850_BUFFER *) dwVirtualAddr;
        ulPhysicalOffset    = dwPhysicalAddr - dwVirtualAddr;
        bReturn = TRUE;
    }
    else
    {
        EdbgOutputDebugString
        (
            "CS8950DMAInit: CS8950 DMA buffer to Small\r\n"
        );
    }

    return bReturn;
}



volatile int bStop = 1;

//****************************************************************************
// CS8950Init
//****************************************************************************
// This is called to initialze and test the Ethernet Mac hardware.
// This is a library exported function.
//
// pbBaseAddress - Pointer to the CS8950 base address.
// dwMultiplier  - Not used.
// MacAddr       - Value of the MAC address.
//
// return         - TRUE  Success
//                  FALSE Failure
BOOL CS8950Init
(
    BYTE            *pbBaseAddress,
    DWORD           dwMultiplier, 
    USHORT          MacAddr[3] 
) 
{
    
    WORD  Result;
    MAXFL MaxFL;
    DWORD dwCount;    

    EdbgOutputDebugString
    (
        "CS8950Init:  pbBaseAddress = 0x%x\r\n",
        pbBaseAddress
    );


    pChip=&Chip;

    pChip->pData=&gCD;

    gdwEthernetBase = (ULONG)pbBaseAddress;


    EdbgOutputDebugString
    (
        "CS8950Init:  pChip = 0x%x, pChip->pData = 0x%x\r\n",
        (ULONG)pChip,
        (ULONG)pChip->pData
    );
    

    //
    // Check to make sure that CS8950DmaInit has been called.
    //
    if(!pCS8950Buffer)
    {
        return FALSE;
    }

    //
    // Lets get the mac address.  If the MAC address has not been initialized,
    // There is not any point in continuing.
    //
    GetMACAddress(MacAddr);
    if(MacAddr[0] == 0 && MacAddr[1] == 0 && MacAddr[2] == 0)
        return FALSE;

    
    //
    // Stop the transmit and recieve queues.
    //
    WriteDWord( OpReg_BMCTL,  BMCTL_TxDis | BMCTL_RxDis);


    //
    // Perform a reset
    //
    Result = VchipReset( pChip );
    if ( Result != MAC_SUCCESSFUL )
    {
        return FALSE;
    } 

    //
    // Change the Self Control register.
    // Program the MDC divisor to be 7 which is 12.5 Mhz.
    //
    WriteDWord
    (
        OpReg_SelfCTL,   
        (7<<SelfCTL_MDCDIV_Shift)
    );

    //
    // Startup the PHY 
    //
    Result = StartupPHY( pChip );
    if ( Result != MAC_SUCCESSFUL )
    {
        return FALSE;
    }

    //************************************************************************
    //
    // After Communicating with the Phy we must turn on Preamble suppress bit.
    // In order to communicate with the Phy using MDII commands we must send 
    // the preamble.  
    //
    // In order to send ethernet frames from the MAC the Preamble suppress 
    // bit  must be on.
    //
    //************************************************************************
    WriteDWord
    (
        OpReg_SelfCTL,   
        (7 << SelfCTL_MDCDIV_Shift) | SelfCTL_PSPRS
    );


    //
    // Reset the Transmit state machine.
    //
    WriteDWord( OpReg_BMCTL,  BMCTL_TxChRes );
    for( dwCount = 0;;dwCount ++)
    {
        DelayInuSec(1);
        if(dwCount >0x10000)
        {
            EdbgOutputDebugString
            (
                "CS8950: Transmit State machine never resets.\n"
            );            
        }
        if(!(ReadDWord( OpReg_BMCTL) & BMCTL_TxChRes))
        {
            break;
        }
    }
    
    //
    // Reset the Recieve state machine.
    //
    WriteDWord( OpReg_BMCTL,  BMCTL_RxChRes );
    for( dwCount = 0;;dwCount ++)
    {
        DelayInuSec(1);
        if(dwCount >0x10000)
        {
            EdbgOutputDebugString
            (
                "CS8950: Receive State machine never resets.\n"
            );            
        }
        if(!(ReadDWord( OpReg_BMCTL) & BMCTL_RxChRes))
        {
            break;
        }
    }


    /* Startup the transmit and receive queues */
    Result = StartupQueues( pChip );
    if ( Result != MAC_SUCCESSFUL )
    {
        return FALSE;
    }

    /* Initialize the chip */
    Result = VchipInit( pChip );
    if ( Result != MAC_SUCCESSFUL )
    {
        return FALSE;
    }


    WriteByte(OpReg_AFP, AFP_IAPrimary );

    /* Set Individual MAC Address (override) */
    WriteByte(OpReg_IndAd + 0, *(((BYTE *)MacAddr) + 0));
    WriteByte(OpReg_IndAd + 1, *(((BYTE *)MacAddr) + 1));
    WriteByte(OpReg_IndAd + 2, *(((BYTE *)MacAddr) + 2));
    WriteByte(OpReg_IndAd + 3, *(((BYTE *)MacAddr) + 3));
    WriteByte(OpReg_IndAd + 4, *(((BYTE *)MacAddr) + 4));
    WriteByte(OpReg_IndAd + 5, *(((BYTE *)MacAddr) + 5));

    /* Set Max Frame Length and Transmit Start Threshold */
    MaxFL.Word.TxStartThresh  = TXSTARTMAX;
    MaxFL.Word.MaxFrameLength = MAXFRAMELENGTH;
    WriteDWord( OpReg_MaxFL, MaxFL.DWord );
 
    return TRUE;
}

//****************************************************************************
// CS8950SendFrame
//****************************************************************************
// This is a library exported function to sends an ethernet frame.
// 
// pbData   - Pointer to the ethernet buffer being sent.
// dwLength - Length of the ethernet buffer.
//
// return   -  TRUE  - ERROR
//             FALSE - NO ERROR
//
//           Always return that we sent the frame correctly. 
//           The only other option is to wait until a frame is sent which 
//           would cause the system to stall.
//
UINT16 CS8950SendFrame
( 
    BYTE *pbData, 
    DWORD dwLength 
)
{
    int status;
    PCD  pCD;
     
    pCD = (PCD)pChip->pData;

    /* Verify that the total length is not too big */
/*    if ( dwLength > 1514 )
    {
       //VpsSendError( pChip, TX_ERR_TOO_BIG );
       EdbgOutputDebugString("CS8950SendFrame: Frame to big!!!!\r\n");
       return FALSE; 
    }
*/
    
#if 0    
    if (pCD->TxQueueDepth == TXBUFFCOUNT) {
    
         status=ProcessTxStatusQueue( pChip );

         while (pCD->pTxStatNext->TxStat & TxStat_TxFP) {
             if ( pCD->TxQueueDepth > 0 ) {
               ProcessTxStatusQueue( pChip );
             } else {
               EdbgOutputDebugString(
                   "CS8950SendFrame() Error: TxQueueDepth==0 but Tx status in Q\n");
               break;
             }
         }
    }

    VchipSend(pChip,  (WORD)dwLength, pbData);
    Global_TxTotal++;



    return TRUE;
#endif
//#if 0    
    //
    // Wait for the TxInProcess the previous frame has been transmitted.
    //
    if ( Global_TxInProcess == TRUE) 
    {
        status=ProcessTxStatusQueue( pChip );
        Global_TxInProcess=FALSE;
    }

    VchipSend(pChip,  (WORD)dwLength, pbData);
    Global_TxInProcess=TRUE;
    Global_TxTotal++;

    return FALSE;
//#endif // 0    
}


//****************************************************************************
// CS8950GetFrame
//****************************************************************************
// This is a library exported function to recieve a frame.
//
// pbData   - Pointer to an ethernet buffer being returned.
// pwLength - Size of buffer returned.
// 
// return   - TRUE if Buffer returned
//            FALSE if no buffer received
//
UINT16 CS8950GetFrame( BYTE *pbData, UINT16 *pwLength )
{
    PCD pCD;
    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. */
    }

⌨️ 快捷键说明

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