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

📄 vchip8950.c

📁 EP9315开发板的Wince6.0的BSP包文件
💻 C
📖 第 1 页 / 共 5 页
字号:
//**********************************************************************
//                                                                      
// Filename: Vchip8950.c
//                                                                      
// Description: Routines for the Vchip ethernet controller used for 
//              the Windows CE debug ethernet services, and bootloaders.
//
// 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 2005, All Rights Reserved                       
//                                                                      
//**********************************************************************


// Note : The Odo SMC implementation sometimes encounters read errors if we
// optimize this routine.  So for now I'm just going to turn of all 
// optimizations.
#pragma optimize("", off)

#include "ndis4cs8950.h"
#include "csphy.h"
#include "csv8950.h"
#include "csDma.h"


/***************************************************************************/
/* Definitions defined by User Begin */

//DWORD Vchip_IP_ADDRESS=0x00000000;    
//DWORD Vchip_SUBNET_MASK=0x00000000;   
//WORD  Vchip_MAC_ADDRESS[3]={0x0000, 0x0000, 0x0000}; 


/* Whether dump the frame contents when Rx and TX? */
/* If Vchip_DUMP_FRAMES is defined, the contects of Tx and Rx frames will be
   dumped to the screen. */
//#define Vchip_DUMP_FRAMES

/* End user definitions */
/***************************************************************************/
#include <ceddk.h>

//
// Set the Initialization timeout for the mac to be 5 seconds.
//
//#define MAC_INITIALIZATION_TIMEOUT          50000
#define MAC_INITIALIZATION_TIMEOUT          5000000



#define ReadByte( bOffset ) (*(volatile UCHAR *)(OpReg_BASE+bOffset))
#define WriteByte( bOffset, Value ) (*(volatile UCHAR *)(OpReg_BASE+bOffset) = Value)
#define ReadWord( wOffset ) (*(volatile USHORT *)(OpReg_BASE+wOffset))
#define WriteWord( wOffset, Value ) (*(volatile USHORT *)(OpReg_BASE+wOffset) = Value)
#define ReadDWord( dwOffset ) (*(volatile ULONG *)(OpReg_BASE+dwOffset))
#define WriteDWord( dwOffset, Value ) (*(volatile ULONG *)(OpReg_BASE+dwOffset) = Value)



// These flags are set by the ISR routine when the current Frame being sent has completed
//  transmission with or without error.  They are cleared by the SendFrame() routine before transmission
//  begins and are polled until being set by the ISR.  Note that only 1 Frame will be in the send queue 
//  at any given time.

// Means that the current set of frames to be transmitted have been processed,
//  either with or without error
static BOOL TX_COMPLETED;

// Means that there was an error when trying to send the current frame
static BOOL TX_STATUS;


static BOOL VchipInit( PCHIP pChip );
static void VchipChangeLookAhead( PCHIP pChip );

static BOOL StartupQueues( PCHIP pChip );
static void ShutdownQueues( PCHIP pChip );
static void ResetQueues( PCHIP pChip );

static BOOL StartupPHY( PCHIP pChip );
static BOOL ReadPHY( PCHIP pChip, WORD Address, WORD Register, WORD *pValue );
static BOOL WritePHY( PCHIP pChip, WORD Address, WORD Register, WORD Value );
static BOOL FindMediaType( PCHIP pChip );
static BOOL SetAdvertisement( PCHIP pChip );
static BOOL FindTechMatch( PCHIP pChip );


void ProcessTxStatusQueue( PCHIP pChip );
static void VpsSendError( PCHIP pChip, DWORD SendID, WORD Errors );
static void TransmitComplete( PCHIP pChip, WORD Status, PTXREQ pTxReq );
static void RestartTransmit( PCHIP pChip, WORD StartIndex );

static void VpsSendComplete( PCHIP pChip, DWORD SendID );

static WORD ProcessRxStatusQueue( PCHIP pChip );
static void VpsRecvError( PCHIP pChip, WORD Errors );
static BOOL VpsRecvComplete(PCHIP pChip, WORD TotalLength, WORD FragCount,PFRAG pFrag);

static BYTE CalculateHashIndex( BYTE  *pMulticastAddr );
static BOOL   GetMACAddrFromEEPROM(WORD *MAC_ADDRESS);

/* For debug purpose */
static void DumpRegisters(void);
static BOOL StartupRxPacketQue( PCHIP pChip );
WORD GetTheIndexOfAFreePakcet( PCHIP pChip);
WORD AddAFreePakcetToQ(PCHIP pChip, WORD index);

/******************************************************************************
*
* VchipStartup()
*
* This is called to initialze the ethernet low level driver.  The base address of
* the ethernet hardware is passed into the routine.  The routine will return 
* TRUE for a successful initialization.
******************************************************************************/
BOOL   VchipStartup(PCHIP pChip)
{
    BOOL                    Result;
    PCD                     pData;
    MAXFL                   MaxFL;
    LARGE_INTEGER           liStart, liCurrent;
    BOOL                    b;


    pData    = pChip->pData;


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


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


    /* Startup the PHY */
    //Result = StartupPHY( pChip );

    // if ( Result != TRUE )
    // {
    //    DbgPrint("CS8950.dll: PHY can not be started!\n");
    //    return Result;
    // }
    //
    // Stop the transmit and recieve queues.
    //
    WriteDWord( OpReg_BMCTL,  BMCTL_TxDis | BMCTL_RxDis);

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

    //
    // Change the Self Control register.
    // Program the MDC divisor to be 39 (0x27) so MDIO speed is 2.5 Mhz.
    //
    if(Result)
    {
        WriteDWord
        (
            OpReg_SelfCTL,   
            (0x27<<SelfCTL_MDCDIV_Shift)
        );


        //
        // Startup the PHY 
        //
        Result = StartupPHY( pChip );
    }

    //************************************************************************
    //
    // 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.
    //
    //************************************************************************
    if(Result)
    {
        WriteDWord
        (
            OpReg_SelfCTL,   
            (0x27 << SelfCTL_MDCDIV_Shift) | SelfCTL_PSPRS
        );

    }

    //
    // Reset the Transmit state machine.
    //
    if(Result)
    {
        WriteDWord( OpReg_BMCTL,  BMCTL_TxChRes );

        b = QueryPerformanceCounter(&liStart);
        ASSERT(b);
    
        //
        // Wait until the transmit state machine wakes up from the reset.
        // 
        for(;;)
        {
            b = QueryPerformanceCounter(&liCurrent);
            ASSERT(b);
            if((liCurrent.QuadPart - liStart.QuadPart) > MAC_INITIALIZATION_TIMEOUT)
            {
                DEBUGMSG
                (
                    ZONE_ERROR,
                    (
                        TEXT("CS8950: Transmit State machine never resets.\n")
                    )
                );

                Result = FALSE;
                break;
            }
            if(!(ReadDWord( OpReg_BMCTL) & BMCTL_TxChRes))
            {
                break;
            }
        }
    }
    
    //
    // Reset the Recieve state machine.
    //
    if(Result)
    {
        WriteDWord( OpReg_BMCTL,  BMCTL_RxChRes );

        b = QueryPerformanceCounter(&liStart);
        ASSERT(b);
    
        //
        // Wait until the transmit state machine wakes up from the reset.
        // 
        for(;;)
        {
            b = QueryPerformanceCounter(&liCurrent);
            ASSERT(b);
            if((liCurrent.QuadPart - liStart.QuadPart) > MAC_INITIALIZATION_TIMEOUT)
            {
                DEBUGMSG
                (
                    ZONE_ERROR,
                    (
                        TEXT("CS8950: Recieve State machine never resets.\n")
                    )
                );
                Result = FALSE;
                break;
            }
            if(!(ReadDWord( OpReg_BMCTL) & BMCTL_RxChRes))
            {
                break;
            }
        }
    }


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

    /* Startup the queue for the received packets */
    if(Result)
    {
        Result = StartupRxPacketQue( pChip );
    }

    /* Initialize the chip */
    if(Result)
    {
        Result = VchipInit( pChip );
    }


    if(Result)
    {
        WriteByte(OpReg_AFP, AFP_IAPrimary );
        WriteWord(OpReg_IndAd, pChip->Config.EthernetAddr.Part[0]);
        WriteWord(OpReg_IndAd+2, pChip->Config.EthernetAddr.Part[1]);
        WriteWord(OpReg_IndAd+4, pChip->Config.EthernetAddr.Part[2]);

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


        /* Flush the multicast hash table */
        VchipMulticastDeleteAll( pChip );
    }

    // DumpRegisters(); 

    return Result;
}



/******************************************************************************
*
* VchipEnableInterrupts()
*
******************************************************************************/
void   VchipEnableInterrupts(PCHIP pChip){
   /* Enable interrupts at the chip */
    
   WriteDWord( OpReg_FERMask, FERMask_Interrupt );
  
}


/******************************************************************************
*
* VchipDisableInterrupts()
*
******************************************************************************/
void   VchipDisableInterrupts(PCHIP pChip)
{
    /* Disable interrupts at the chip */
    WriteDWord( OpReg_FERMask, 0L );
  
}


/******************************************************************************
*
* 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 ) 
    {   
        DEBUGMSG
        (
            ZONE_ERROR,
            (
                TEXT("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 ) 
    {   
        DEBUGMSG
        (
            ZONE_ERROR,
            (
                TEXT("Second PHY read failed!")
            )
        );
        return FALSE;
    }


    /* 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 ) 
    {       
        DEBUGMSG
        (
            ZONE_ERROR,
            (
                TEXT("First PHY write failed, Address = 0x%x, Register = 0x%x, Value = 0x%x.\r\n"),
                (ULONG)Address,
                (ULONG)Register,
                (ULONG)Value
            )

⌨️ 快捷键说明

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