📄 card.c
字号:
The 32-bit CRC value.
Note:
This is adapted from the comments in the assembly language
version in _GENREQ.ASM of the DWB NE1000/2000 driver.
--*/
{
ULONG Crc, Carry;
UINT i, j;
UCHAR CurByte;
DEBUGMSG(ZONE_FUNCTION, (TEXT("+CELAN:CardComputeCrc\r\n")));
Crc = 0xffffffff;
for (i = 0; i < Length; i++) {
CurByte = Buffer[i];
for (j = 0; j < 8; j++) {
Carry = ((Crc & 0x80000000) ? 1 : 0) ^ (CurByte & 0x01);
Crc <<= 1;
CurByte >>= 1;
if (Carry) {
Crc = (Crc ^ 0x04c11db6) | Carry;
}
}
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("-CELAN:CardComputeCrc\r\n")));
return Crc;
}
VOID
CardGetMulticastBit(
IN UCHAR Address[CELAN_LENGTH_OF_ADDRESS],
OUT UCHAR * Byte,
OUT UCHAR * Value
)
/*++
Routine Description:
For a given multicast address, returns the byte and bit in
the card multicast registers that it hashes to. Calls
CardComputeCrc() to determine the CRC value.
Arguments:
Address - the address
Byte - the byte that it hashes to
Value - will have a 1 in the relevant bit
Return Value:
None.
--*/
{
ULONG Crc;
UINT BitNumber;
DEBUGMSG(ZONE_FUNCTION, (TEXT("91C94:+CardGetMulticastBit\r\n")));
//
// First compute the CRC.
//
Crc = CardComputeCrc(Address, CELAN_LENGTH_OF_ADDRESS);
//
// The bit number is now in the 6 most significant bits of CRC.
//
BitNumber = (UINT)((Crc >> 26) & 0x3f);
*Byte = (UCHAR)(BitNumber / 8);
*Value = (UCHAR)((UCHAR)1 << (BitNumber % 8));
DEBUGMSG(ZONE_FUNCTION, (TEXT("91C94:-CardGetMulticastBit\r\n")));
}
VOID
CardFillMulticastRegs(
IN PCELAN_ADAPTER Adapter
)
/*++
Routine Description:
Erases and refills the card multicast registers. Used when
an address has been deleted and all bits must be recomputed.
Arguments:
Adapter - pointer to the adapter block
Return Value:
None.
--*/
{
UINT i;
UCHAR Byte, Bit;
DEBUGMSG(ZONE_FUNCTION, (TEXT("91C94:+CardFillMulticastRegs\r\n")));
//
// First turn all bits off.
//
for (i=0; i<8; i++) {
Adapter->NicMulticastRegs[i] = 0;
}
//
// Now turn on the bit for each address in the multicast list.
//
for ( ; i > 0; ) {
i--;
CardGetMulticastBit(Adapter->Addresses[i], &Byte, &Bit);
Adapter->NicMulticastRegs[Byte] |= Bit;
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("91C94:-CardFillMulticastRegs\r\n")));
}
BOOLEAN
SyncCardCopyMulticastRegs(
IN PVOID SynchronizeContext
)
/*++
Routine Description:
Sets the eight bytes in the card multicast registers.
Arguments:
SynchronizeContext - pointer to the adapter block
Return Value:
None.
--*/
{
PCELAN_ADAPTER Adapter = ((PCELAN_ADAPTER)SynchronizeContext);
UINT i;
DEBUGMSG(ZONE_FUNCTION, (TEXT("91C94:+CardCopyMulticastRegs\r\n")));
SelectBank(BANK3);
for (i=0; i<8; i+=2) {
WriteWord(MULTICAST1+i, Adapter->NicMulticastRegs[i] |
Adapter->NicMulticastRegs[i+1]<<8 );
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("Multicast bits\r\n")));
for (i=0; i<8; i++) {
DEBUGMSG(ZONE_FUNCTION, (TEXT("%02x "),Adapter->NicMulticastRegs[i]));
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("\r\n")));
PrintRegs;
DEBUGMSG(ZONE_FUNCTION, (TEXT("91C94:-CardCopyMulticastRegs\r\n")));
return FALSE;
}
//++
//
// VOID
// CardStart(
// IN PCELAN_ADAPTER Adapter
// )
//
//
// Routine Description:
//
// Starts the card.
//
// Arguments:
//
// Adapter - pointer to the adapter block
//
// Return Value:
//
// None.
//
//--
#pragma NDIS_PAGEABLE_FUNCTION(CardStart)
VOID CardStart(IN PCELAN_ADAPTER Adapter)
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("+CELAN:CardStart\r\n")));
// Initialize trasmit control register
DEBUGMSG(ZONE_INIT, (TEXT("91C94:CardStart\r\n")));
SelectBank(BANK0);
WriteWord(TCR,TCR_PAD_ENABLE|TCR_ENABLE);
//
// Set Receive Mode
//
DEBUGMSG(ZONE_INIT, (TEXT("91C94:Init Receive config register\r\n")));
SelectBank(BANK0);
WriteWord(RCR,Adapter->NicReceiveConfig);
LAN91C111Init();
RETAILMSG(1,(TEXT("CELAN : Initialze LAN91C111 Done\r\n")));
// PrintRegs;
DEBUGMSG(ZONE_FUNCTION, (TEXT("-CELAN:CardStart\r\n")));
}
#pragma NDIS_PAGEABLE_FUNCTION(CardBlockInterrupts)
VOID CardBlockInterrupts(IN PCELAN_ADAPTER Adapter)
{
WORD Bank;
DEBUGMSG(ZONE_INTR,(TEXT("CardBlockInterrupt INT_REG : %04x\r\n"),Adapter->NicInterruptMask));
Bank = ReadWord(BANK_SELECT);
SelectBank(BANK2);
WriteWord(INT_REG,0);
WRITE_PHY(19,0xFFFF);
DEBUGMSG(ZONE_INTR,(TEXT("Set Link detect interrupt to Phy regs.\r\n")));
SelectBank(Bank);
}
#pragma NDIS_PAGEABLE_FUNCTION(CardUnblockInterrupts)
VOID CardUnblockInterrupts(IN PCELAN_ADAPTER Adapter)
{
WORD Bank;
DEBUGMSG(ZONE_INTR,(TEXT("CardUnblockInterrupt INT_REG : %04x\r\n"),Adapter->NicInterruptMask));
Bank = ReadWord(BANK_SELECT);
SelectBank(BANK2);
WriteWord(INT_REG,Adapter->NicInterruptMask);
WRITE_PHY(19,0x3FC0);
DEBUGMSG(ZONE_INTR,(TEXT("Set Link detect interrupt to Phy regs.\r\n")));
SelectBank(Bank);
}
#pragma NDIS_PAGEABLE_FUNCTION(CardGetInterruptStatus)
VOID CardGetInterruptStatus(
IN PCELAN_ADAPTER Adapter,
OUT PUCHAR pInterruptStatus
)
{
SelectBank(BANK2);
*pInterruptStatus = (UCHAR)ReadWord(INT_REG);
}
BOOLEAN
SyncCardSetReceiveConfig(
IN PVOID SynchronizeContext
)
/*++
Routine Description:
Sets the value of the "receive configuration" NIC register to
the value of Adapter->NicReceiveConfig.
Arguments:
SynchronizeContext - pointer to the adapter block
Return Value:
None.
--*/
{
PCELAN_ADAPTER Adapter = ((PCELAN_ADAPTER)SynchronizeContext);
DEBUGMSG(ZONE_FUNCTION, (TEXT("91C94:+SyncCardSetReceiveConfig\r\n")));
SelectBank(BANK0);
WriteWord(RCR,Adapter->NicReceiveConfig);
DEBUGMSG(ZONE_FUNCTION, (TEXT("91C94:-SyncCardSetReceiveConfig\r\n")));
return FALSE;
}
BOOLEAN
SyncCardSetAllMulticast(
IN PVOID SynchronizeContext
)
/*++
Routine Description:
Turns on all the bits in the multicast register. Used when
the card must receive all multicast packets.
Arguments:
SynchronizeContext - pointer to the adapter block
Return Value:
None.
--*/
{
PCELAN_ADAPTER Adapter = ((PCELAN_ADAPTER)SynchronizeContext);
UINT i;
DEBUGMSG(ZONE_FUNCTION, (TEXT("91C94:+CardSetAllMulticast\r\n")));
SelectBank(BANK3);
for (i=0; i<8; i+=2) {
WriteWord(MULTICAST1+i, 0xffff);
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("91C94:-CardSetAllMulticast\r\n")));
return FALSE;
}
void LAN91C111Init()
{
unsigned short capability;
unsigned long AutoNegotiationTimeOver;
WriteWord(0x0e,0x3301);
WriteWord(0x00,0xB0B1);
WriteWord(0x0e,0x3303);
RETAILMSG(1,(TEXT("+Product Ethernet Driver Initialize\r\n")));
PHYDiag();
RETAILMSG(1,(TEXT("Try Auto Negotiation.......\r\n")));
WriteWord(0x0e,0x3300);
WriteWord(0x00,0x0081);
WriteWord(0x0a,0x0800);
AutoNegotiationTimeOver = 0;
capability =0;
WRITE_PHY(0,0x1000);
while ( !(READ_PHY(1)&0x0020)) {
if( AutoNegotiationTimeOver == 0x8000 ) {
RETAILMSG(1,(TEXT("time out.\r\n")));
WRITE_PHY(19,0x3FC0);
capability = 1;
break;
}
WRITE_PHY(0,0x1000);
AutoNegotiationTimeOver++;
}
if ( capability !=1 )
RETAILMSG(1,(TEXT("completed.\r\n")));
if (!(capability))
capability = READ_PHY(5);
WRITE_PHY(0,0x0000);
if( capability & 0x0200) {
RETAILMSG(1,(TEXT("100Base-T4 capable.\r\n")));
RETAILMSG(1,(TEXT("We will not support 100Base-T4.\r\n")));
}
if( capability & 0x0100) {
RETAILMSG(1,(TEXT("100Base-TX Full Duplex capable.\r\n")));
WRITE_PHY(0,0x3100);
WriteWord(0x0e,0x3300);
WriteWord(0x00,0x8881);
WriteWord(0x0a,0x38C0);
}
else if( capability & 0x0080) {
RETAILMSG(1,(TEXT("100Base-TX Half Duplex capable.\r\n")));
WRITE_PHY(0,0x3000);
WriteWord(0x0e,0x3300);
WriteWord(0x00,0x0081);
WriteWord(0x0a,0x28C0);
}
else if( capability & 0x0040) {
RETAILMSG(1,(TEXT("10Base-T Full Duplex capable.\r\n")));
WRITE_PHY(0,0x1100);
WriteWord(0x0e,0x3300);
WriteWord(0x00,0x8881);
WriteWord(0x0a,0x18C0);
}
else if( capability & 0x0020) {
RETAILMSG(1,(TEXT("10Base-T Half Duplex capable.\r\n")));
WRITE_PHY(0,0x1000);
WriteWord(0x0e,0x3300);
WriteWord(0x00,0x0081);
WriteWord(0x0a,0x08C0);
}
else {
RETAILMSG(1,(TEXT("Wait for partner in the state of AutoNegotiaton.\r\n")));
READ_PHY(18);
}
}
void PHYDiag()
{
//Reset Phy module.
WRITE_PHY(0,0x8000);
while ((READ_PHY(0)&0x8000));
RETAILMSG(1,(TEXT("LAN91C111 diagnostic testing...\r\n")));
if( (0x16 == READ_PHY(2)) && (0xF840 == READ_PHY(3))) {
RETAILMSG(1,(TEXT("completed.\r\n")));
} else {
RETAILMSG(1,(TEXT("failed.\r\n")));
while(1);
}
}
void WRITE_PHY(unsigned char address, unsigned short data)
{
int i;
unsigned char adr;
unsigned short dat;
adr = address;
dat = data;
for ( i=0; i<32; i++) SendData1();
//start bits
SendData0();
SendData1();
//write command
SendData0();
SendData1();
//PHY address
for ( i=0; i<5; i++) SendData0();
//PHY reg.
for ( i=0; i<5; i++) {
if(adr & (0x10>>i))
SendData1();
else
SendData0();
}
// TA
SendData1();
SendData0();
//write data
for ( i=0; i<16; i++) {
if(dat & (0x8000>>i))
SendData1();
else
SendData0();
}
}
unsigned short READ_PHY(unsigned char address)
{
unsigned short ret,temp;
int i;
unsigned char adr;
adr = address;
for ( i=0; i<32; i++) SendData1();
//start bits
SendData0();
SendData1();
//read command
SendData1();
SendData0();
//PHY address
for ( i=0; i<5; i++) SendData0();
//PHY reg.
for ( i=0; i<5; i++) {
if(adr & (0x10>>i))
SendData1();
else
SendData0();
}
// TA Z0h
SendDataZ();
SendData0();
// Read data
temp=0;
ret=0;
for ( i=0; i<16; i++) {
WriteWord(0x08,0x3330);
temp = ReadWord(0x08);
temp = (temp & 0x0002)>>1;
ret |= (temp <<(15-i));
WriteWord(0x08,0x3334);
}
return ret;
}
void SendData0()
{
WriteWord(0x0e,0x3303);
WriteWord(0x08,0x3338);
WriteWord(0x08,0x333C);
WriteWord(0x08,0x3338);
}
void SendData1()
{
WriteWord(0x0e,0x3303);
WriteWord(0x08,0x3339);
WriteWord(0x08,0x333D);
WriteWord(0x08,0x3339);
}
void SendDataZ()
{
WriteWord(0x0e,0x3303);
WriteWord(0x08,0x3330);
WriteWord(0x08,0x3334);
WriteWord(0x08,0x3330);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -