www.pudn.com > 2410winceCE_l80t64.rar > Chip.c, change:2007-07-13,size:24223b
//---------------------------------------------------------------------------
//
// Copyright (C) 1996-2003. Unpublished Work of Cirrus Logic Inc.
// All Rights Reserved.
//
// THIS WORK IS AN UNPUBLISHED WORK AND CONTAINS CONFIDENTIAL,
// PROPRIETARY AND TRADE SECRET INFORMATION OF CRYSTAL SEMICONDUCTOR.
// ACCESS TO THIS WORK IS RESTRICTED TO (I) CRYSTAL SEMICONDUCTOR EMPLOYEES
// WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF THEIR
// ASSIGNMENTS AND (II) ENTITIES OTHER THAN CRYSTAL SEMICONDUCTOR WHO
// HAVE ENTERED INTO APPROPRIATE LICENSE AGREEMENTS. NO PART OF THIS
// WORK MAY BE USED, PRACTICED, PERFORMED, COPIED, DISTRIBUTED, REVISED,
// MODIFIED, TRANSLATED, ABRIDGED, CONDENSED, EXPANDED, COLLECTED,
// COMPILED,LINKED,RECAST, TRANSFORMED, ADAPTED IN ANY FORM OR BY ANY
// MEANS,MANUAL, MECHANICAL, CHEMICAL, ELECTRICAL, ELECTRONIC, OPTICAL,
// BIOLOGICAL, OR OTHERWISE WITHOUT THE PRIOR WRITTEN PERMISSION AND
// CONSENT OF CRYSTAL SEMICONDUCTOR . ANY USE OR EXPLOITATION OF THIS WORK
// WITHOUT THE PRIOR WRITTEN CONSENT OF CRYSTAL SEMICONDUCTOR COULD
// SUBJECT THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
//
//---------------------------------------------------------------------------
/* chip.c - CS8900A VChip Initialization */
#include "cs8900a.h"
#include "cshrd.h"
/* Vchip Global variables. WARNING: In some environments, these variables */
/* will be truncated from the data segment after initialization time! */
#define MAX_CHIPS 4 // should I be using CHIP_COUNT in vchip.h ????
DWORD IOBaseList[MAX_CHIPS] = {0,0,0,0};
extern int EEPROM_NOT_FOUND;
/******************************************************************************
*
* VchipGetConfig()
*
******************************************************************************/
WORD VchipGetConfig( PCHIP pChip)
{
PORT IOBase;
WORD Result;
WORD SelfStatus;
WORD AdapterConfig;
DWORD step;
//
// The steps count down inorder to produce "tighter" code.
//
for (step=8,Result=SUCCESS; step && Result==SUCCESS; step--) {
switch (step) {
case 8:
IOBase=pChip->Config.IOBase;
/* Read the self status register */
SelfStatus = ReadPacketPage( pChip, IOBase, CRYSTAL_SELF_STATUS_REGISTER );
Result = GetConfigFromEEPROM( pChip );
break;
case 7:
/* Read the Ethernet address from the EEPROM */
Result = ReadEEPROM( pChip, EE_ADDRESS_OEM_IA_W1,
&pChip->Config.EthernetAddr.Part[0] );
break;
case 6:
Result = ReadEEPROM( pChip, EE_ADDRESS_OEM_IA_W2,
&pChip->Config.EthernetAddr.Part[1] );
break;
case 5:
Result = ReadEEPROM( pChip, EE_ADDRESS_OEM_IA_W3,
&pChip->Config.EthernetAddr.Part[2] );
break;
case 4:
Result = ReadEEPROM( pChip, EE_ADDRESS_VRHC, &AdapterConfig );
break;
case 3:
/* Get media type from the adapter configuration */
pChip->Config.RequestedMediaType = ((AdapterConfig&EE_MEDIA_MASK)>>
EE_MEDIA_SHIFT);
break;
case 2:
/* Read auto-negotiation control from the EEPROM */
//Result = ReadEEPROM( pChip, EE_ADDRESS_CTL, &AutoNegControl );
break;
case 1:
Result=AddIOBase(IOBase);
break;
} /* endswitch */
} /* endfor */
pChip->Config.RequestedDuplexMode = DUPLEX_HALF;
pChip->Config.MediaSpeed = 10;
pChip->Config.BusType = BUS_ISA;
pChip->Config.BusSlot = (WORD)UNSPECIFIED;
pChip->Config.MaxTxCount = CRYSTAL_TRANSMIT_PACKET_MAXIMUM;
pChip->Config.Flags = 0;
pChip->Config.CurrentDuplexMode = DUPLEX_NONE;
pChip->Config.DetectedMediaType = MEDIA_NONE;
return CHIP_SUCCESS;
}
/******************************************************************************
*
* GetConfigFromEEPROM()
*
******************************************************************************/
WORD GetConfigFromEEPROM( PCHIP pChip )
{
WORD Result;
WORD ISAConfig;
WORD MemBase;
/* Read the ISA configuration from the EEPROM */
Result = ReadEEPROM( pChip, EE_ADDRESS_FLAGS, &ISAConfig );
if ( Result != SUCCESS ) return FAILURE;
/* If memory mode is enabled */
if ( ISAConfig & EE_MEM_FLAG )
{
/* Read the memory base address from the EEPROM */
Result = ReadEEPROM( pChip, EE_ADDRESS_MEM_BASE, &MemBase );
if ( Result != SUCCESS ) return FAILURE;
MemBase &= EE_MEMORY_MASK; /* Clear unused bits */
pChip->Config.MemoryBase = (((DWORD)MemBase)<Config.MemorySize = CRYSTAL_MEMORY_SIZE;
}
else /* Memory mode is disabled */
{
pChip->Config.MemoryBase = (DWORD)UNSPECIFIED;
pChip->Config.MemorySize = (WORD)UNSPECIFIED;
}
/* If a boot ROM is installed */
if ( ISAConfig & EE_BOOT_PROM_FLAG )
{
/* Read the ROM base address from the EEPROM */
Result = ReadEEPROM( pChip, EE_ADDRESS_BOOT_BASE, &MemBase );
if ( Result != SUCCESS ) return FAILURE;
MemBase &= EE_MEMORY_MASK; /* Clear unused bits */
pChip->Config.ROMBase = (((DWORD)MemBase)<Config.ROMSize = CRYSTAL_ROM_SIZE;
}
else /* A boot ROM is not installed */
{
pChip->Config.ROMBase = (DWORD)UNSPECIFIED;
pChip->Config.ROMSize = (WORD)UNSPECIFIED;
}
/* Get the interrupt line from the ISA configuration */
pChip->Config.IntLine = ISAConfig & EE_INTERRUPT_MASK;
//@drsa 11-3-97 3.21 add cs8900 support
if (pChip->Config.ChipType == CS8900_PROD_ID_LOW) {
// Map EEPROM IRQ value to IRQ
if (pChip->Config.IntLine == 3)
pChip->Config.IntLine = 5;
else
pChip->Config.IntLine += 10;
}
pChip->Config.DMALine = (ISAConfig & EE_DMA_MASK) >> EE_DMA_ADJUST;
// Map EEPROM DMA value to DMA channel
if (pChip->Config.DMALine == 3)
pChip->Config.DMALine = (BYTE)UNSPECIFIED;
else
pChip->Config.DMALine += 5;
return SUCCESS;
}
/******************************************************************************
*
* FindNextChip()
*
* If next chip is found, then its IOBase is returned.
* If next chip is not found, then zero is returned.
*
******************************************************************************/
PORT FindNextChip( PCHIP pChip, PORT StartingIOBase )
{
PORT IOBase;
WORD Value;
/* Scan the IO space for our chip */
#if ( defined(SHx_PROCESSOR))
for ( IOBase=StartingIOBase; IOBasepData;
IOBase = pChip->Config.IOBase;
/* Initialize configuration flags to zero */
pData->ConfigFlags = 0;
/* Read adpater configuration from the EEPROM */
Result = ReadEEPROM( pChip, EE_ADDRESS_VRHC, &AdapterConfig );
if ( Result != SUCCESS )
{
return Result;
}
/* Get polarity of DC/DC converter enable pin from AdapterConfig */
if ( AdapterConfig & EE_DCDC_POLARITY )
pData->ConfigFlags |= CFGFLG_DCDC_POLARITY;
/* Get available Hardware configuration (CFGFLG_MEDIA_CAP) */
pData->ConfigFlags |= (AdapterConfig & EE_CKT_MASK) << 4;
/* Read the ISA configuration from the EEPROM */
Result = ReadEEPROM( pChip, EE_ADDRESS_FLAGS, &ISAConfig );
if ( Result != SUCCESS )
{
return Result;
}
/* Get I/O-channel-ready from ISA configuration */
if ( ISAConfig & EE_IOCHRDY_ENBL )
pData->ConfigFlags |= CFGFLG_IOCHRDY;
Result = VchipReset( pChip ); //@drsa
if ( Result != CHIP_SUCCESS ) //@drsa
{ //@drsa
return Result; //@drsa
} //@drsa
// @kml 6/30/99
// /* Check to make sure the chip is functioning */
// Result = CrystalTestInternalLoopBack( pChip );
// if ( Result != CHIP_SUCCESS )
// {
// return Result;
// }
//
// Result = VchipReset( pChip );
// if ( Result != CHIP_SUCCESS )
// {
// return Result;
// }
// @kml 6/30/99 Wait for the LinkOK bit in Line Control Reg.
VominiDelay(100);
DetectMedia( pChip );
while ( pChip->Config.DetectedMediaType == MEDIA_PENDING )
{
if (pChip->Config.CurrentDuplexMode == DUPLEX_PENDING) {
// @kml Auto Config Duplex mode
VominiDelay( 2500 );
} else {
// @kml 6/30/99 quick init time when in Force Full or Half Duplex mode
VominiDelay( 100 );
}
DetectMedia( pChip );
}
if ( pChip->Config.DetectedMediaType != MEDIA_NONE )
{
if ( pChip->Config.DetectedMediaType != MEDIA_BASE_T )
{
Result = VchipReset( pChip ); //@rosa avoids pending receives
if ( Result != CHIP_SUCCESS ) //@rosa
{ //@rosa
return Result; //@rosa
} //@rosa
}
/* Initialize the chip */
Result = VchipInit( pChip );
if ( Result != CHIP_SUCCESS )
{
return Result;
}
}
/* Must start Timer routine to detect cable Status */
Result = VominiStartTimer( pChip, VchipDetectMediaDaemon, 2500,
&pData->DetectMediaTimer, NULL );
if ( Result != CHIP_SUCCESS )
{
return Result;
}
return CHIP_SUCCESS;
}
/******************************************************************************
*
* VchipInit()
*
* Note: This driver does not support memory mode.
*
******************************************************************************/
WORD VchipInit( PCHIP pChip )
{
PCD pData;
PORT IOBase;
WORD BusControl;
WORD SelfControl;
//@drs 11-3-97 3.21 add cs8900 support
WORD IntLine;
pData = pChip->pData;
IOBase = pChip->Config.IOBase;
if (( pChip->Config.DetectedMediaType == MEDIA_PENDING ) ||
( pChip->Config.DetectedMediaType == MEDIA_NONE ))
return CHIP_SUCCESS;
pData->TransmitBidPending = FALSE;
pData->TransmitInProgress = FALSE;
pData->TransmitThresholdCount = 0;
pData->TransmitStarted = FALSE;
pData->StartTX = FALSE;
pData->TransmitCommand = CRYSTAL_TCR_TX_START_381_BYTES;
pData->CurrentReceiveConfiguration = CRYSTAL_DEFAULT_RX_CONFIG_VALUE;
InitQueues( pChip );
/* Put Ethernet address into the Individual Address register */
WritePacketPage( pChip, IOBase, CRYSTAL_INDIVIDUAL_ADDRESS,
pChip->Config.EthernetAddr.Part[0] );
WritePacketPage( pChip, IOBase, CRYSTAL_INDIVIDUAL_ADDRESS+2,
pChip->Config.EthernetAddr.Part[1] );
WritePacketPage( pChip, IOBase, CRYSTAL_INDIVIDUAL_ADDRESS+4,
pChip->Config.EthernetAddr.Part[2] );
/* If IOCHRDY is enabled then clear the bit in the BusControl register */
BusControl = ReadPacketPage( pChip, IOBase, CRYSTAL_BUS_CONTROL_REGISTER );
if ( pData->ConfigFlags & CFGFLG_IOCHRDY )
WritePacketPage( pChip, IOBase, CRYSTAL_BUS_CONTROL_REGISTER,
(WORD)(BusControl & ~CRYSTAL_BCR_IO_CHANNEL_READY_ON) );
else
WritePacketPage( pChip, IOBase, CRYSTAL_BUS_CONTROL_REGISTER,
(WORD)(BusControl | CRYSTAL_BCR_IO_CHANNEL_READY_ON) );
/* Set the Line Control register to match the media type */
if ( pChip->Config.DetectedMediaType == MEDIA_BASE_T )
WritePacketPage( pChip, IOBase, CRYSTAL_LINE_CONTROL_REGISTER,
CRYSTAL_LCR_DEFAULT_VALUE );
else
WritePacketPage( pChip, IOBase, CRYSTAL_LINE_CONTROL_REGISTER,
CRYSTAL_LCR_AUI_ONLY );
/* Set the BSTATUS/HC1 pin to be used as HC1 */
/* HC1 is used to enable the DC/DC converter */
SelfControl = CRYSTAL_SCR_HCO_1_ENABLE;
/* If the media type is 10Base2 */
if ( pChip->Config.DetectedMediaType == MEDIA_BASE_2 )
{
/* Enable the DC/DC converter */
/* If the DC/DC converter has a low enable */
if ( (pData->ConfigFlags & CFGFLG_DCDC_POLARITY) == 0 )
/* Set the HCB1 bit, which causes the HC1 pin to go low */
SelfControl |= CRYSTAL_SCR_HCO_1;
else
SelfControl &= ~CRYSTAL_SCR_HCO_1;
}
else /* Media type is 10BaseT or AUI */
{
/* Disable the DC/DC converter */
/* If the DC/DC converter has a high enable */
if ( (pData->ConfigFlags & CFGFLG_DCDC_POLARITY) != 0 )
/* Set the HCB1 bit, which causes the HC1 pin to go low */
SelfControl |= CRYSTAL_SCR_HCO_1;
else
SelfControl &= ~CRYSTAL_SCR_HCO_1;
}
WritePacketPage( pChip, IOBase, CRYSTAL_SELF_CONTROL_REGISTER, SelfControl );
/* Initialize the config and control registers */
WritePacketPage( pChip, IOBase, CRYSTAL_RX_CONFIG_REGISTER,
CRYSTAL_DEFAULT_RX_CONFIG_VALUE );
WritePacketPage( pChip, IOBase, CRYSTAL_RX_CONTROL_REGISTER,
CRYSTAL_RCR_DEFAULT_VALUE );
WritePacketPage( pChip, IOBase, CRYSTAL_TX_CONFIG_REGISTER,
CRYSTAL_TCR_DEFAULT_VALUE );
WritePacketPage( pChip, IOBase, CRYSTAL_BUFFER_CONFIG_REGISTER,
CRYSTAL_BCR_DEFAULT_VALUE);
/* Setup initial filtering criteria */
VchipChangeFiltering( pChip );
//@drs 11-3-97 3.21 add cs8900 support
IntLine = pChip->Config.IntLine;
#if ( defined(ARM_PROCESSOR) || defined(SHx_PROCESSOR))
/* The INTRQ pin number is independent from pChip->Config.IntLine.
Write the INTRQ pin number which is connected to Processor to CS8900's register.*/
WritePacketPage( pChip, IOBase, CRYSTAL_ISA_INTERRUPT_NUMBER, CS8900_INTERRUPT_REQUEST_PIN_NUM );
#else
IntLine = (IntLine != 5) ? (IntLine - 10) : 3;
WritePacketPage( pChip, IOBase, CRYSTAL_ISA_INTERRUPT_NUMBER, IntLine );
#endif
/* Enable reception and transmission of frames */
WritePacketPage( pChip, IOBase, CRYSTAL_LINE_CONTROL_REGISTER,
(WORD)(ReadPacketPage( pChip, IOBase,CRYSTAL_LINE_CONTROL_REGISTER) |
CRYSTAL_LCR_SERIAL_RX_ON | CRYSTAL_LCR_SERIAL_TX_ON) );
/* Enable interrupt at the chip */
VchipEnableInterrupts( pChip );
return CHIP_SUCCESS;
}
/******************************************************************************
*
* InitQueues()
*
******************************************************************************/
void InitQueues( PCHIP pChip )
{
PCD pData = pChip->pData;
pData->TransmitQueue.Head = pData->TransmitQueue.Tail = NULL;
}
/******************************************************************************
*
* VchipReset()
*
******************************************************************************/
WORD VchipReset( PCHIP pChip )
{
PCD pData;
PORT IOBase;
BYTE Byte;
int x;
pData = pChip->pData;
IOBase = pChip->Config.IOBase;
/* We are now resetting the chip */
/* A spurious interrupt is generated by the chip when it is reset. */
/* This variable informs the interrupt handler to ignore this interrupt. */
pData->Resetting = TRUE;
/* Issue a reset command to the chip */
WritePacketPage( pChip, IOBase, CRYSTAL_SELF_CONTROL_REGISTER,
CRYSTAL_SCR_POWER_ON_RESET );
/* Delay for 20 milliseconds */
VominiDelay( 20 );
/* Transition SBHE to switch chip from 8-bit to 16-bit */
NdisRawReadPortUchar( (PORT)(IOBase+CRYSTAL_ADDRESS_PORT), &Byte );
NdisRawReadPortUchar( (PORT)(IOBase+CRYSTAL_ADDRESS_PORT+1), &Byte );
NdisRawReadPortUchar( (PORT)(IOBase+CRYSTAL_ADDRESS_PORT), &Byte );
NdisRawReadPortUchar( (PORT)(IOBase+CRYSTAL_ADDRESS_PORT+1), &Byte );
/* Wait until the EEPROM is not busy */
for ( x=0; xResetting = FALSE;
return CHIP_SUCCESS;
}
/******************************************************************************
*
* VchipShutdown()
*
******************************************************************************/
void VchipShutdown( PCHIP pChip )
{
PCD pData;
PORT IOBase;
WORD SelfStatus;
pData = pChip->pData;
IOBase = pChip->Config.IOBase;
VominiStopTimer( pChip, pData->DetectMediaTimer );
VchipReset( pChip );
/* Read the self status register */
SelfStatus = ReadPacketPage( pChip, IOBase, CRYSTAL_SELF_STATUS_REGISTER );
DeleteIOBase( pChip->Config.IOBase );
}
/******************************************************************************
*
* VchipTest()
*
******************************************************************************/
void VchipTest( PCHIP pChip )
{
PORT IOBase;
WORD BuffConfig;
IOBase = pChip->Config.IOBase;
/* Generate a software initiated interrupt */
BuffConfig = ReadPacketPage( pChip, IOBase, CRYSTAL_BUFFER_CONFIG_REGISTER );
BuffConfig |= CRYSTAL_BCR_GENERATE_SW_INTERRUPT;
WritePacketPage( pChip, IOBase, CRYSTAL_BUFFER_CONFIG_REGISTER, BuffConfig );
}
/******************************************************************************
*
* ReadEEPROM()
*
******************************************************************************/
WORD ReadEEPROM( PCHIP pChip, WORD Offset, WORD *pValue )
{
PORT IOBase;
int x;
IOBase = pChip->Config.IOBase;
/* Ensure that the EEPROM is not busy */
for ( x=0; xConfig.ChipType = Result & PRODUCT_ID_MASK;
pChip->Config.ChipRev = Result & REVISION_ID_MASK;
/* Read the self status register */
SelfStatus = ReadPacketPage( pChip, IOBase, CRYSTAL_SELF_STATUS_REGISTER );
/* @kml 05/08/00 If the EEPROM is not present or the EEPROM is not OK,
then sofeware reset the chip. */
pChip->Config.IOBase = IOBase;
if ( !(SelfStatus & CRYSTAL_SSR_EEPROM_PRESENT) ||
!(SelfStatus & CRYSTAL_SSR_EEPROM_OK) )
{
EEPROM_NOT_FOUND=TRUE;
VchipReset( pChip );
}
pChip->Config.IOSize = CRYSTAL_IO_SIZE;
return NDIS_STATUS_SUCCESS;
}