|
|
/****************************************************************************
** COPYRIGHT (C) 1994-1997 INTEL CORPORATION ** ** DEVELOPED FOR MICROSOFT BY INTEL CORP., HILLSBORO, OREGON ** ** HTTP://WWW.INTEL.COM/ **
** THIS FILE IS PART OF THE INTEL ETHEREXPRESS PRO/100B(TM) AND ** ** ETHEREXPRESS PRO/100+(TM) NDIS 5.0 MINIPORT SAMPLE DRIVER ** ****************************************************************************/
/****************************************************************************
Module Name: eeprom.c
This driver runs on the following hardware: - 82558 based PCI 10/100Mb ethernet adapters (aka Intel EtherExpress(TM) PRO Adapters)
Environment: Kernel Mode - Or whatever is the equivalent on WinNT
Revision History - JCB 8/14/97 Example Driver Created - Dchen 11-01-99 Modified for the new sample driver *****************************************************************************/
#include "precomp.h"
#pragma hdrstop
#pragma warning (disable: 4244 4514)
#define EEPROM_MAX_SIZE 256
//*****************************************************************************
//
// I/O based Read EEPROM Routines
//
//*****************************************************************************
//-----------------------------------------------------------------------------
// Procedure: EEpromAddressSize
//
// Description: determines the number of bits in an address for the eeprom
// acceptable values are 64, 128, and 256
//
// Arguments:
// Size -- size of the eeprom
//
// Returns:
// bits in an address for that size eeprom
//-----------------------------------------------------------------------------
USHORT GetEEpromAddressSize( IN USHORT Size) { switch (Size) { case 64: return 6; case 128: return 7; case 256: return 8; }
return 0; }
//-----------------------------------------------------------------------------
// Procedure: GetEEpromSize
//
// Description: This routine determines the size of the EEPROM.
//
// Arguments:
// Reg - EEPROM word to read.
//
// Returns:
// Size of the EEPROM, or zero if error.
//-----------------------------------------------------------------------------
USHORT GetEEpromSize( IN PUCHAR CSRBaseIoAddress) { USHORT x, data; USHORT size = 1;
// select EEPROM, reset bits, set EECS
x = READ_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG));
x &= ~(EEDI | EEDO | EESK); x |= EECS; WRITE_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG), x);
// write the read opcode
ShiftOutBits(EEPROM_READ_OPCODE, 3, CSRBaseIoAddress);
// experiment to discover the size of the eeprom. request register zero
// and wait for the eeprom to tell us it has accepted the entire address.
x = READ_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG)); do { size *= 2; // each bit of address doubles eeprom size
x |= EEDO; // set bit to detect "dummy zero"
x &= ~EEDI; // address consists of all zeros
WRITE_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG), x); NdisStallExecution(100); RaiseClock(&x, CSRBaseIoAddress); LowerClock(&x, CSRBaseIoAddress);
// check for "dummy zero"
x = READ_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG)); if (size > EEPROM_MAX_SIZE) { size = 0; break; } } while (x & EEDO);
// Now read the data (16 bits) in from the selected EEPROM word
data = ShiftInBits(CSRBaseIoAddress);
EEpromCleanup(CSRBaseIoAddress); return size; }
//-----------------------------------------------------------------------------
// Procedure: ReadEEprom
//
// Description: This routine serially reads one word out of the EEPROM.
//
// Arguments:
// Reg - EEPROM word to read.
//
// Returns:
// Contents of EEPROM word (Reg).
//-----------------------------------------------------------------------------
USHORT ReadEEprom( IN PUCHAR CSRBaseIoAddress, IN USHORT Reg, IN USHORT AddressSize) { USHORT x; USHORT data;
// select EEPROM, reset bits, set EECS
x = READ_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG));
x &= ~(EEDI | EEDO | EESK); x |= EECS; WRITE_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG), x);
// write the read opcode and register number in that order
// The opcode is 3bits in length, reg is 6 bits long
ShiftOutBits(EEPROM_READ_OPCODE, 3, CSRBaseIoAddress); ShiftOutBits(Reg, AddressSize, CSRBaseIoAddress);
// Now read the data (16 bits) in from the selected EEPROM word
data = ShiftInBits(CSRBaseIoAddress);
EEpromCleanup(CSRBaseIoAddress); return data; }
//-----------------------------------------------------------------------------
// Procedure: ShiftOutBits
//
// Description: This routine shifts data bits out to the EEPROM.
//
// Arguments:
// data - data to send to the EEPROM.
// count - number of data bits to shift out.
//
// Returns: (none)
//-----------------------------------------------------------------------------
VOID ShiftOutBits( IN USHORT data, IN USHORT count, IN PUCHAR CSRBaseIoAddress) { USHORT x,mask;
mask = 0x01 << (count - 1); x = READ_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG));
x &= ~(EEDO | EEDI);
do { x &= ~EEDI; if(data & mask) x |= EEDI;
WRITE_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG), x); NdisStallExecution(100); RaiseClock(&x, CSRBaseIoAddress); LowerClock(&x, CSRBaseIoAddress); mask = mask >> 1; } while(mask);
x &= ~EEDI; WRITE_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG), x); }
//-----------------------------------------------------------------------------
// Procedure: ShiftInBits
//
// Description: This routine shifts data bits in from the EEPROM.
//
// Arguments:
//
// Returns:
// The contents of that particular EEPROM word
//-----------------------------------------------------------------------------
USHORT ShiftInBits( IN PUCHAR CSRBaseIoAddress) { USHORT x,d,i; x = READ_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG));
x &= ~( EEDO | EEDI); d = 0;
for(i=0; i<16; i++) { d = d << 1; RaiseClock(&x, CSRBaseIoAddress);
x = READ_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG));
x &= ~(EEDI); if(x & EEDO) d |= 1;
LowerClock(&x, CSRBaseIoAddress); }
return d; }
//-----------------------------------------------------------------------------
// Procedure: RaiseClock
//
// Description: This routine raises the EEPOM's clock input (EESK)
//
// Arguments:
// x - Ptr to the EEPROM control register's current value
//
// Returns: (none)
//-----------------------------------------------------------------------------
VOID RaiseClock( IN OUT USHORT *x, IN PUCHAR CSRBaseIoAddress) { *x = *x | EESK; WRITE_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG), *x); NdisStallExecution(100); }
//-----------------------------------------------------------------------------
// Procedure: LowerClock
//
// Description: This routine lower's the EEPOM's clock input (EESK)
//
// Arguments:
// x - Ptr to the EEPROM control register's current value
//
// Returns: (none)
//-----------------------------------------------------------------------------
VOID LowerClock( IN OUT USHORT *x, IN PUCHAR CSRBaseIoAddress) { *x = *x & ~EESK; WRITE_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG), *x); NdisStallExecution(100); }
//-----------------------------------------------------------------------------
// Procedure: EEpromCleanup
//
// Description: This routine returns the EEPROM to an idle state
//
// Arguments:
//
// Returns: (none)
//-----------------------------------------------------------------------------
VOID EEpromCleanup( IN PUCHAR CSRBaseIoAddress) { USHORT x; x = READ_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG));
x &= ~(EECS | EEDI); WRITE_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG), x);
RaiseClock(&x, CSRBaseIoAddress); LowerClock(&x, CSRBaseIoAddress); }
|