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