📄 vchip8950.c
字号:
//**********************************************************************
//
// 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 + -