📄 chip.c
字号:
//-----------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft 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 LICENSE.RTF on
// your install media.
//
//-----------------------------------------------------------------------------
//
// Copyright (C) 2004, Motorola Inc. All Rights Reserved
//
//------------------------------------------------------------------------------
//
// Copyright (C) 2004, Freescale Semiconductor, Inc. All Rights Reserved.
// THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
// AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
//
//------------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
// File: chip.c
//
// Implementation of CS8900 Driver
//
// This file implements the chip specific functions for CS8900
//
//------------------------------------------------------------------------------
#include "cs8900a.h"
//------------------------------------------------------------------------------
// External Functions
//------------------------------------------------------------------------------
extern PBSP_CS8900_REG g_pCS8900Reg;
extern CRITICAL_SECTION gCS8900BufCs;
//------------------------------------------------------------------------------
// External Variables
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Defines
//------------------------------------------------------------------------------
#define MAX_RETRY 100000
#define CRC_POLYNOMIAL_SPECIAL 0xEDB88320
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Global Variables
//------------------------------------------------------------------------------
// Static MAC Address if EEPROM not found, set to :12-13-17-28-2701
static const UINT8 gMACAddr[6] = {0x12, 0x13, 0x17, 0x28, 0x27, 0x01} ;
extern CRITICAL_SECTION gCS8900RegCs;
//------------------------------------------------------------------------------
// Local Variables
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Local Functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//
// Function: ReadCs8900Register
//
// This function reads the contents of the CS8900 register.
//
// Parameters:
// RegisterOffset
// [in] Offset from the base address
//
// Returns:
// Return Value at the address
//
//------------------------------------------------------------------------------
WORD ReadCs8900Register(WORD RegisterOffset)
{
WORD Value;
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +ReadCs8900Register\r\n")));
EnterCriticalSection (&gCS8900RegCs);
NdisRawWritePortUshort( (unsigned long)&(g_pCS8900Reg->CS8900_PAGE_POINTER), RegisterOffset );
NdisRawReadPortUshort( (unsigned long)&(g_pCS8900Reg->CS8900_PAGE_DATA_0), &Value );
LeaveCriticalSection (&gCS8900RegCs);
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +ReadCs8900Register [0x%.8X]\r\n"), Value));
return Value;
}
//------------------------------------------------------------------------------
//
// Function: WriteCs8900Register
//
// This function writes the contents to the CS8900 register.
//
// Parameters:
// RegisterOffset
// [in] Offset from the base address
//
// Value
// [in] Contents to be written
//
// Returns:
// none
//
//------------------------------------------------------------------------------
void WriteCs8900Register(WORD RegisterOffset, WORD Value)
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +WriteCs8900Register\r\n")));
EnterCriticalSection (&gCS8900RegCs);
NdisRawWritePortUshort( (unsigned long)&(g_pCS8900Reg->CS8900_PAGE_POINTER), RegisterOffset );
NdisRawWritePortUshort( (unsigned long)&(g_pCS8900Reg->CS8900_PAGE_DATA_0), Value );
LeaveCriticalSection (&gCS8900RegCs);
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: -WriteCs8900Register\r\n")));
}
//------------------------------------------------------------------------------
//
// Function: CheckForChip
//
// This function checks for the presence of CS8900 chip.
//
// Parameters:
// pEthernet
// [in] pointer to the CS8900 structure.
//
// Returns:
// TRUE indicates success. FALSE indicates failure.
//
//------------------------------------------------------------------------------
WORD CheckForChip(pCs8900_t pEthernet)
{
WORD Value;
UINT32 i;
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +CheckForChip\r\n")));
/* The software reset does not work. The SELF_ST_SI_BUSY is never de-asserted
* and the subsequent for loop executes infinitely.
*/
// Trigger a software reset
// WriteCs8900Register(PKTPG_SELF_CTL, SELF_CTL_RESET);
for (i=MAX_RETRY; i>0; i--)
{
if (!(ReadCs8900Register(PKTPG_SELF_ST) & SELF_ST_SI_BUSY))
break;
}
if (i <= 0)
{
DEBUGMSG(ZONE_INIT, (TEXT("CS8900A Reset0 Timeout.\r\n")));
return FALSE;
}
for (i=MAX_RETRY; i>0; i--)
{
if ((ReadCs8900Register(PKTPG_SELF_ST) & SELF_ST_INIT_DONE))
break;
}
if (i <= 0) {
DEBUGMSG(ZONE_INIT, (TEXT("CS8900A Reset1 Timeout.\r\n")));
return FALSE;
}
// end of chip reset
// Read the address port (packet page pointer)
NdisRawReadPortUshort( (unsigned long)&(g_pCS8900Reg->CS8900_PAGE_POINTER), &Value );
//Add by Paul, Chao, I don't know why read first times will get invalid value, but just do it.
//For safety reason, we read six times and reserve last value
NdisRawReadPortUshort( (unsigned long)&(g_pCS8900Reg->CS8900_PAGE_POINTER), &Value );
NdisRawReadPortUshort( (unsigned long)&(g_pCS8900Reg->CS8900_PAGE_POINTER), &Value );
NdisRawReadPortUshort( (unsigned long)&(g_pCS8900Reg->CS8900_PAGE_POINTER), &Value );
NdisRawReadPortUshort( (unsigned long)&(g_pCS8900Reg->CS8900_PAGE_POINTER), &Value );
NdisRawReadPortUshort( (unsigned long)&(g_pCS8900Reg->CS8900_PAGE_POINTER), &Value );
DEBUGMSG(ZONE_INIT, (TEXT("CS8900:CheckForChip, NdisRawReadPortUshort(CS8900_PAGE_POINTER), Value=0x%x, 0x%x\r\n"), Value, (g_pCS8900Reg->CS8900_PAGE_POINTER)));
if ( (Value & CS8900_PacketPage_Signature_Mask) == CS8900_PacketPage_Signature )
{
// Read the EISA Number and Product ID
Value = ReadCs8900Register(PKTPG_EISA_NUM);
if(Value != EISA_NUM_CRYSTAL)
{
DEBUGMSG(ZONE_INIT, (TEXT("CS8900:EISA Registration Number Wrong! Expect=%x, Read=%x\r\n"), EISA_NUM_CRYSTAL, Value));
return FALSE;
}
Value = ReadCs8900Register(PKTPG_PRODUCT_ID);
pEthernet->ChipRevsion = Value & PROD_REV_MASK;
Value &= PROD_ID_MASK;
if(Value!=PROD_ID_CS8900)
{
DEBUGMSG(ZONE_INIT, (TEXT("CS8900:Product ID Wrong! Expect=%x, Read=%x\r\n"), PROD_ID_CS8900, Value));
return FALSE;
}
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: -CheckForChip\r\n")));
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function: InitializeChip
//
// This function initializes the CS8900 chip.
//
// Parameters:
// pEthernet
// [in] pointer to the CS8900 structure.
//
// Returns:
// TRUE indicates success.
//
//------------------------------------------------------------------------------
WORD InitializeChip(pCs8900_t pEthernet)
{
WORD data;
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +InitializeChip\r\n")));
// Check for EEPROM presence
data = ReadCs8900Register(PKTPG_SELF_ST);
if ((data & SELF_ST_EEPROM_PRES) && (data & SELF_ST_EEPROM_OK))
{
*(UINT16 *)pEthernet->CurrentAddress = cs8900aReadFromEEPROM(pEthernet, EEPROM_IND_ADDR_L);
*(UINT16 *)(&pEthernet->CurrentAddress[2]) = cs8900aReadFromEEPROM(pEthernet, EEPROM_IND_ADDR_M);
*(UINT16 *)(&pEthernet->CurrentAddress[4]) = cs8900aReadFromEEPROM(pEthernet, EEPROM_IND_ADDR_H);
}
else
{
if(pEthernet->CurrentAddress[0] == 0 && pEthernet->CurrentAddress[1] == 0 && pEthernet->CurrentAddress[3] == 0 &&
pEthernet->CurrentAddress[4] == 0 && pEthernet->CurrentAddress[5] == 0 && pEthernet->CurrentAddress[6] == 0 )
{
*(UINT16 *)pEthernet->CurrentAddress = *(UINT16 *)gMACAddr;
*(UINT16 *)(&pEthernet->CurrentAddress[2]) = *(UINT16 *)(&gMACAddr[2]);
*(UINT16 *)(&pEthernet->CurrentAddress[4]) = *(UINT16 *)(&gMACAddr[4]);
}
}
// Compare and write the current MAC address into CS8900 Individual Address register if
// there is difference
data = ReadCs8900Register(PKTPG_IND_ADDR);
if(data!= *(UINT16 *)pEthernet->CurrentAddress)
{
WriteCs8900Register(PKTPG_IND_ADDR, *(UINT16 *)pEthernet->CurrentAddress);
}
data = ReadCs8900Register(PKTPG_IND_ADDR+2);
if(data!= *(UINT16 *)(&pEthernet->CurrentAddress[2]) )
{
WriteCs8900Register(PKTPG_IND_ADDR+2, *(UINT16 *)(&pEthernet->CurrentAddress[2]));
}
data = ReadCs8900Register(PKTPG_IND_ADDR+4);
if(data!= *(UINT16 *)(&pEthernet->CurrentAddress[4]))
{
WriteCs8900Register(PKTPG_IND_ADDR+4, *(UINT16 *)(&pEthernet->CurrentAddress[4]));
}
NdisMoveMemory(&pEthernet->PermanentAddress, &pEthernet->CurrentAddress, (ULONG)ETHER_ADDR_SIZE);
WriteCs8900Register(PKTPG_SELF_CTL, SELF_CTL_HC1E);
WriteCs8900Register(PKTPG_LINE_CTL, LINE_CTL_10BASET);
// Don't use IOCHRDY pin
data = ReadCs8900Register(PKTPG_BUS_CTL);
data |= BUS_CTL_IOCHRDY;
WriteCs8900Register(PKTPG_BUS_CTL, data);
data = RX_CFG_ALL_IE | 0x0800; // enable crc in buffer too
WriteCs8900Register(PKTPG_RX_CFG, data); // pg 53
data = TX_CFG_16_COLL_IE |TX_CFG_JABBER_IE | TX_CFG_OUT_WIN_IE | TX_CFG_TX_OK_IE;
WriteCs8900Register(PKTPG_TX_CFG, data); // pg 56
data = BUF_CFG_RDY4TX_IE | BUF_CFG_TX_UNDR_IE | BUF_CFG_MISOFLO_IE | BUF_CFG_COLOFLO_IE;
WriteCs8900Register(PKTPG_BUF_CFG, data); // pg 59
// set filtering (pg55)
data = ReadCs8900Register(PKTPG_RX_CTL);
//Clear the broadcast, multicast and promiscuous bits
data &= ~(RX_CTL_BCAST_A | RX_CTL_MCAST_A | RX_CTL_PROM_A);
data |= RX_DEFAULT_CONFIGURATION;
pEthernet->PacketFilter = data;
WriteCs8900Register(PKTPG_RX_CTL, data);
// Write the interrupt number to the register
WriteCs8900Register(PKTPG_INT_NUM, (WORD)CS8900_INTERRUPT_NUM);
// Enable reception and transmission of frames
data = ReadCs8900Register(PKTPG_LINE_CTL);
data |= (LCR_RX_ON | LCR_TX_ON);
WriteCs8900Register(PKTPG_LINE_CTL, data);
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: -InitializeChip\r\n")));
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function: cs8900aReadFromEEPROM
//
// This function read the contents of EEPROM.
//
// Parameters:
// pEthernet
// [in] pointer to the CS8900 structure.
//
// EEPROMAddress
// [in] EEPROM address.
//
// Returns:
// TRUE indicates success. FALSE indicates failure.
//
//------------------------------------------------------------------------------
WORD cs8900aReadFromEEPROM (pCs8900_t pEthernet, WORD EEPROMAddress)
{
UINT32 i;
WORD Value;
DEBUGMSG(ZONE_FUNCTION, (TEXT("CS8900A: +cs8900aReadFromEEPROM\r\n")));
if(pEthernet == NULL) {
DEBUGMSG(ZONE_INIT, (TEXT("CS8900: ReadFromEEPROM :: pEthernet NULL. \r\n")));
return FALSE;
}
// Wait for NO BUSY signal
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -