www.pudn.com > 2410winceCE_l80t64.rar > Chip.c


//--------------------------------------------------------------------------- 
// 
//  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; 
}