304 lines
8.5 KiB
C
304 lines
8.5 KiB
C
|
/****************************************************************************
|
||
|
** 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);
|
||
|
}
|
||
|
|