Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

392 lines
8.4 KiB

#include <ndis.h>
#include "82595.h"
#include "eprohw.h"
#include "eprosw.h"
#include "epro.h"
#include "eprodbg.h"
VOID EProEERead(
PEPRO_ADAPTER adapter,
USHORT address,
PUSHORT data)
/*++
Routine Description:
This function reads the 16-bit register at address (address % 64)
from the EPro's eeprom (there are only 64 words of registers
on the eeprom)
IMPORTANT NOTE - for PnP accesses to the EPro's eeprom (registers
0x10 and higher), you must use the EProEEReverseRead since for some
reason the EPro stores PnP data in the reverse bit-order (except for
the low byte of word 10, which is in the normal bit order) -- see
the 82595 docs and PnP docs for an explanation.
Arguments:
data - the where the result is written to
Return Value:
none
--*/
{
UCHAR result;
UCHAR opcode;
// siwtch to bank2
EPRO_SWITCH_BANK_2(adapter);
// Get the value from the register, so we can flip the eecs bit
EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, &result);
// turn the eecs bit on.. (1)
result |= I82595_EECS_MASK;
EPRO_WR_PORT_UCHAR(adapter, I82595_EEPROM_REG, result);
// Write the read opcode to the eeprom (2)
opcode = I82595_EEPROM_READ;
EProEEShiftOutBits(adapter, opcode, 3);
// Write the address to read to the eeprom
EProEEShiftOutBits(adapter, address, 6);
// Read the result
EProEEShiftInBits(adapter, data, 16);
EProEECleanup(adapter);
EPRO_SWITCH_BANK_0(adapter);
}
VOID EProEEWrite(
PEPRO_ADAPTER adapter,
USHORT address,
USHORT data)
{
UCHAR result;
// siwtch to bank2
EPRO_SWITCH_BANK_2(adapter);
EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, &result);
result &= ~(I82595_EEDI_MASK | I82595_EEDO_MASK | I82595_EESK_MASK);
result |= I82595_EECS_MASK;
EPRO_WR_PORT_UCHAR(adapter, I82595_EEPROM_REG, result);
// write the read opcode and register number
EProEEShiftOutBits(adapter, I82595_EEPROM_EWEN, 5);
EProEEShiftOutBits(adapter, address, 4);
EProEEStandBy(adapter);
EProEEShiftOutBits(adapter, I82595_EEPROM_ERASE, 3);
EProEEShiftOutBits(adapter, address, 6);
if (EProEEWaitCmdDone(adapter) == FALSE) {
EPRO_DPRINTF_INIT(("Failed EEPROM erase!\n"));
return;
}
EProEEStandBy(adapter);
EProEEShiftOutBits(adapter, I82595_EEPROM_WRITE, 3);
EProEEShiftOutBits(adapter, address, 6);
EProEEShiftOutBits(adapter, data, 16);
if (EProEEWaitCmdDone(adapter) == FALSE) {
EPRO_DPRINTF_INIT(("Failed EEPROM write!\n"));
return;
}
EProEEStandBy(adapter);
EProEEShiftOutBits(adapter, I82595_EEPROM_EWDS, 5);
EProEEShiftOutBits(adapter, address, 4);
EProEECleanup(adapter);
// siwtch to bank0
EPRO_SWITCH_BANK_0(adapter);
}
VOID EProEECleanup(PEPRO_ADAPTER adapter)
{
UCHAR result;
EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, &result);
result &= ~(I82595_EECS_MASK | I82595_EEDI_MASK);
EPRO_WR_PORT_UCHAR(adapter, I82595_EEPROM_REG, result);
EProEERaiseClock(adapter, &result);
EProEELowerClock(adapter, &result);
}
VOID EProEEUpdateChecksum(PEPRO_ADAPTER adapter)
{
USHORT chkSum = 0, result, i;
for (i=0;i<0x3f;i++) {
EProEERead(adapter, i, &result);
chkSum+=result;
}
chkSum = (USHORT)0xBABA - chkSum;
EProEEWrite(adapter, 0x3f, chkSum);
}
VOID EProEEStandBy(
PEPRO_ADAPTER adapter)
{
UCHAR result;
EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, &result);
result &= ~(I82595_EECS_MASK | I82595_EESK_MASK);
EPRO_WR_PORT_UCHAR(adapter, I82595_EEPROM_REG, result);
NdisStallExecution(100);
result |= I82595_EECS_MASK;
EPRO_WR_PORT_UCHAR(adapter, I82595_EEPROM_REG, result);
}
BOOLEAN EProEEWaitCmdDone(
PEPRO_ADAPTER adapter)
{
USHORT i;
UCHAR result;
EProEEStandBy(adapter);
for (i=0; i<200;i++) {
EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, &result);
if (result & I82595_EEDO_MASK) {
return(TRUE);
}
NdisStallExecution(100);
}
return(FALSE);
}
VOID EProEEReverseRead(
PEPRO_ADAPTER adapter,
USHORT address,
PUSHORT data)
{
UCHAR result, opcode;
UINT i;
// siwtch to bank2
EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_CMD_BANK2);
// Get the value from the register, so we can flip the eecs bit
EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, &result);
// turn the eecs bit on.. (1)
result |= I82595_EECS_MASK;
EPRO_WR_PORT_UCHAR(adapter, I82595_EEPROM_REG, result);
// Write the read opcode to the eeprom (2)
opcode = I82595_EEPROM_READ;
EProEEShiftOutBits(adapter, opcode, 3);
// Write the address to read to the eeprom
EProEEShiftOutBits(adapter, address, 6);
// Read the result
EProEEReverseShiftInBits(adapter, data, 16);
// Turn off EEPROM
EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, &result);
result &= (~I82595_EECS_MASK);
EPRO_WR_PORT_UCHAR(adapter, I82595_EEPROM_REG, result);
EPRO_SWITCH_BANK_0(adapter);
}
VOID EProEEShiftOutBits(
PEPRO_ADAPTER adapter,
USHORT data,
SHORT count)
/*++
Routine Description:
This function shifts count bits OUT TO THE EEPROM through it's serial
interface
Arguments:
adapter - pointer to our adapter structure
data - the word to shift out from (MSB first)
count - the number of bits to shift out...
Return Value:
none
--*/
{
UCHAR result;
USHORT mask;
mask = 0x1 << (count - 1);
EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, &result);
result &= ~(I82595_EEDO_MASK | I82595_EEDI_MASK);
do
{
result &= ~I82595_EEDI_MASK;
if (data & mask)
{
result |= I82595_EEDI_MASK;
}
EPRO_WR_PORT_UCHAR(adapter, I82595_EEPROM_REG, result);
NdisStallExecution(100);
EProEERaiseClock(adapter, &result);
EProEELowerClock(adapter, &result);
mask = mask >> 1;
} while(mask);
result &= ~I82595_EEDI_MASK;
EPRO_WR_PORT_UCHAR(adapter, I82595_EEPROM_REG, result);
}
VOID EProEEShiftInBits(
PEPRO_ADAPTER adapter,
PUSHORT data,
SHORT count)
/*++
Routine Description:
This routine is analagous to shift-out-bits, except reads bits from
the eeprom... Note that for PNP accesses to the EPro
(pnp for the EPro lives in registers 0x10 and higher) you must use
a different function since PnP data is written in reverse bit order
for some reason
Arguments:
adapter - pointer to our adapter structure
data - the word to read into
count - how many bits to read
Return Value:
none
--*/
{
UCHAR result;
USHORT i;
EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, &result);
result &= ~(I82595_EEDO_MASK | I82595_EEDI_MASK);
*data = 0;
for (i=0;i<16;i++)
{
*data = *data << 1;
EProEERaiseClock(adapter, &result); // 4.1
EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, &result); // 4.2
result &= ~I82595_EEDI_MASK;
if (result & I82595_EEDO_MASK) {
*data |= 1;
}
EProEELowerClock(adapter, &result);
}
}
void EProEEReverseShiftInBits(PEPRO_ADAPTER adapter, PUSHORT data, SHORT count)
{
UCHAR result;
SHORT count1;
*data = 0;
for (count1=0;count1<=count;count1++) {
EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, &result); // 4.2
result &= I82595_EEDO_MASK; // turn off everything but the EEDO bit
// according to docs we get MSB out first...
// this is a REVERSE read - get LSB first
*data |= ((result >> I82595_EEDO_OFFSET) << count1);
}
}
VOID EProEERaiseClock(
PEPRO_ADAPTER adapter,
PUCHAR result)
/*++
Routine Description:
This routine raises the "clock" bit in the eeprom access register --
basically since the eeprom is a serial device you raise then lower the
clock between bits...
Arguments:
adapter - pointer to the adapter structure
Return Value:
none
--*/
{
// UCHAR result;
// turn EESK bit high
*result = *result | I82595_EESK_MASK;
EPRO_WR_PORT_UCHAR(adapter, I82595_EEPROM_REG, *result);
NdisStallExecution(EPRO_SK_STALL_TIME);
}
VOID EProEELowerClock(
PEPRO_ADAPTER adapter,
PUCHAR result)
/*++
Routine Description:
Analagous to EProEERaiseClock...
Arguments:
adapter - pointer to our adapter structure.
Return Value:
none
--*/
{
// UCHAR result;
// EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, result);
// turn EESK bit low...
*result = *result & ~I82595_EESK_MASK;
EPRO_WR_PORT_UCHAR(adapter, I82595_EEPROM_REG, *result);
NdisStallExecution(EPRO_SK_STALL_TIME);
}