📄 card.c
字号:
//
// Copyright (c) Renesas Technology Corp. 1999-2003 All Rights Reserved.
//
// LAN91C111 network hardware driver
//
//----------------------------------------------------------------------------
//
// FILE : CARD.C
// CREATED : 1998. 8.21 (for NE2000 driver)
// MODIFIED : 2003.08.06
// AUTHOR : Renesas Technology Corp.
// HARDWARE : RENESAS HS7751RSTC01H (S1-E, ITS-DS5)
// TARGET OS : Microsoft(R) Windows(R) CE .NET 4.2
// FUNCTION : Card-specific driver functions
// HISTORY :
// 1999.04.26
// - Released as SMSC LAN91C94 driver for PFM-DS6x by modifying
// NE2000 driver in PB2.12 reference drivers.
// (Detailed history for PFM-DS6x are omitted.)
// 2002.05.21
// - Modified for HS7751RSTC01H. Target device is changed to
// LAN91C111.
// 2002.09.05
// - Header style is changed and file informations are added.
// - Unreferenced header file inclusions are removed.
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995-1998 Microsoft Corporation. All rights reserved.
--*/
#include "precomp.h"
#include "smc91c94.h"
PBYTE EtherNetBase;
extern PVOID RegisterBase;
extern WORD MAC0,MAC1,MAC2;
void LAN91C111Init();
void PHYDiag();
void WRITE_PHY(unsigned char address, unsigned short data);
unsigned short READ_PHY(unsigned char address);
void SendData0();
void SendData1();
void SendDataZ();
//#ifdef DEBUG
void printregs(void)
{
WORD BankReg = ReadWord(BANK_SELECT);
DEBUGMSG(1, (TEXT("SMSC91C94 Registers\r\n")));
DEBUGMSG(1, (TEXT(" BANK0\r\n")));
SelectBank(BANK0);
DEBUGMSG(1, (TEXT(" TCR : 0x%04X\r\n"),ReadWord(TCR)));
DEBUGMSG(1, (TEXT(" EPH_STATUS : 0x%04X\r\n"),ReadWord(EPH_STATUS)));
DEBUGMSG(1, (TEXT(" RCR : 0x%04X\r\n"),ReadWord(RCR)));
DEBUGMSG(1, (TEXT(" COUNTER : 0x%04X\r\n"),ReadWord(COUNTER)));
DEBUGMSG(1, (TEXT(" MIR : 0x%04X\r\n"),ReadWord(MIR)));
DEBUGMSG(1, (TEXT(" MCR : 0x%04X\r\n"),ReadWord(MCR)));
DEBUGMSG(1, (TEXT(" BANK1\r\n")));
SelectBank(BANK1);
DEBUGMSG(1, (TEXT(" CONFIG : 0x%04X\r\n"),ReadWord(CONFIG)));
DEBUGMSG(1, (TEXT(" BASE : 0x%04X\r\n"),ReadWord(BASE)));
DEBUGMSG(1, (TEXT(" ADDR0 : 0x%04X\r\n"),ReadWord(ADDR0)));
DEBUGMSG(1, (TEXT(" ADDR1 : 0x%04X\r\n"),ReadWord(ADDR1)));
DEBUGMSG(1, (TEXT(" ADDR2 : 0x%04X\r\n"),ReadWord(ADDR2)));
DEBUGMSG(1, (TEXT(" GENERAL : 0x%04X\r\n"),ReadWord(GENERAL)));
DEBUGMSG(1, (TEXT(" CONTROL : 0x%04X\r\n"),ReadWord(CONTROL)));
DEBUGMSG(1, (TEXT(" BANK2\r\n")));
SelectBank(BANK2);
DEBUGMSG(1, (TEXT(" MMU_CMD : 0x%04X\r\n"),ReadWord(MMU_CMD)));
DEBUGMSG(1, (TEXT(" PNR_ARR : 0x%04X\r\n"),ReadWord(PNR_ARR)));
DEBUGMSG(1, (TEXT(" FIFO_PORTS : 0x%04X\r\n"),ReadWord(FIFO_PORTS)));
DEBUGMSG(1, (TEXT(" POINTER : 0x%04X\r\n"),ReadWord(POINTER)));
DEBUGMSG(1, (TEXT(" DATA_1 : 0x%04X\r\n"),ReadWord(DATA_1)));
DEBUGMSG(1, (TEXT(" DATA_2 : 0x%04X\r\n"),ReadWord(DATA_2)));
DEBUGMSG(1, (TEXT(" INTERRUPT : 0x%04X\r\n"),ReadWord(INT_REG)));
DEBUGMSG(1, (TEXT(" BANK3\r\n")));
SelectBank(BANK3);
DEBUGMSG(1, (TEXT(" MULTICAST1 : 0x%04X\r\n"),ReadWord(MULTICAST1)));
DEBUGMSG(1, (TEXT(" MULTICAST2 : 0x%04X\r\n"),ReadWord(MULTICAST2)));
DEBUGMSG(1, (TEXT(" MULTICAST3 : 0x%04X\r\n"),ReadWord(MULTICAST3)));
DEBUGMSG(1, (TEXT(" MULTICAST4 : 0x%04X\r\n"),ReadWord(MULTICAST4)));
DEBUGMSG(1, (TEXT(" MGMT : 0x%04X\r\n"),ReadWord(MGMT)));
DEBUGMSG(1, (TEXT(" REVISION : 0x%04X\r\n"),ReadWord(REVISION)));
DEBUGMSG(1, (TEXT(" ERCV : 0x%04X\r\n"),ReadWord(ERCV)));
DEBUGMSG(1, (TEXT(" Bank select : 0x%04X\r\n"),BankReg));
WriteWord(BANK_SELECT,BankReg);
}
#define PrintRegs printregs()
//#else
//#define PrintRegs
//#endif DEBUG
BOOLEAN
CardSlotTest(
IN PCELAN_ADAPTER Adapter
);
BOOLEAN
CardRamTest(
IN PCELAN_ADAPTER Adapter
);
#pragma NDIS_PAGEABLE_FUNCTION(CardCheckParameters)
BOOLEAN CardCheckParameters(
IN PCELAN_ADAPTER Adapter
)
/*++
Routine Description:
Checks that the I/O base address is correct.
Arguments:
Adapter - pointer to the adapter block.
Return Value:
TRUE, if IoBaseAddress appears correct.
--*/
{
return TRUE;
}
#pragma NDIS_PAGEABLE_FUNCTION(CardRamTest)
BOOLEAN
CardRamTest(
IN PCELAN_ADAPTER Adapter
)
/*++
Routine Description:
Finds out how much RAM the adapter has. It starts at 1K and checks thru
60K. It will set Adapter->RamSize to the appropriate value iff this
function returns TRUE.
Arguments:
Adapter - pointer to the adapter block.
Return Value:
TRUE, if all goes well, else FALSE.
--*/
{
return(TRUE);
}
#pragma NDIS_PAGEABLE_FUNCTION(CardInitialize)
BOOLEAN
CardInitialize(
IN PCELAN_ADAPTER Adapter
)
/*++
Routine Description:
Initializes the card into a running state.
Arguments:
Adapter - pointer to the adapter block.
Return Value:
TRUE, if all goes well, else FALSE.
--*/
{
DEBUGMSG(ZONE_INIT, (TEXT("91C94:CardInitialize - Entered.\r\n")));
// VirtualAlloc Register Area for HS7751RSTC01H LAN Controller Base Address
EtherNetBase = (PBYTE)VirtualAlloc(0,0x20,MEM_RESERVE,PAGE_NOACCESS);
DEBUGMSG(ZONE_INIT, (TEXT("91C94:VirtualAlloc at 0x%x.\r\n"),EtherNetBase));
if(!VirtualCopy((PVOID)EtherNetBase,(PVOID)RegisterBase,0x20,PAGE_READWRITE|PAGE_NOCACHE)) {
DEBUGMSG(ZONE_INIT, (TEXT("91C94:VirtualCopy failed.\r\n")));
RETAILMSG(1,(TEXT("91C94:VirtualCopy failed.\r\n")));
}
// Reset the 91C94
SelectBank(BANK0);
WriteWord(RCR,RCR_SOFTRESET);
Sleep(10);
WriteWord(RCR,0);
Sleep(10);
// Initialize the control register
SelectBank(BANK1);
WriteWord(CONTROL,0x0020);
// Reset MMU
SelectBank(BANK2);
WriteWord(MMU_CMD,MC_RESET);
{
int i;
for (i=0;i<10000;i++) {
if(!(ReadWord(MMU_CMD)&MC_BUSY)) {
break;
}
}
if (i==10000) {
DEBUGMSG(ZONE_INIT, (TEXT("91C94:MMU reset failed.\r\n")));
RETAILMSG(1, (TEXT("91C94:MMU reset failed.\r\n")));
return(FALSE);
}
}
DEBUGMSG(ZONE_INIT, (TEXT("91C94:CardInitialize - Finished.\r\n")));
RETAILMSG(1, (TEXT("91C94:CardInitialize - Finished.\r\n")));
return(TRUE);
}
#pragma NDIS_PAGEABLE_FUNCTION(CardReadEthernetAddress)
BOOLEAN CardReadEthernetAddress(
IN PCELAN_ADAPTER Adapter
)
/*++
Routine Description:
Reads in the Ethernet address from the LAN91C94.
Arguments:
Adapter - pointer to the adapter block.
Return Value:
The address is stored in Adapter->PermanentAddress, and StationAddress if it
is currently zero.
--*/
{
// Read MAC address registers
SelectBank(BANK1);
Adapter->PermanentAddress[0] = ReadWord(ADDR0) & 0xFF;
Adapter->PermanentAddress[1] = ReadWord(ADDR0) >> 8;
Adapter->PermanentAddress[2] = ReadWord(ADDR1) & 0xFF;
Adapter->PermanentAddress[3] = ReadWord(ADDR1) >> 8;
Adapter->PermanentAddress[4] = ReadWord(ADDR2) & 0xFF;
Adapter->PermanentAddress[5] = ReadWord(ADDR2) >> 8;
#if 1 // for ROM
if(
((Adapter->PermanentAddress[0] == 0) &&
(Adapter->PermanentAddress[1] == 0) &&
(Adapter->PermanentAddress[2] == 0) &&
(Adapter->PermanentAddress[3] == 0) &&
(Adapter->PermanentAddress[4] == 0) &&
(Adapter->PermanentAddress[5] == 0) )
||
((Adapter->PermanentAddress[0] == 0xff) &&
(Adapter->PermanentAddress[1] == 0xff) &&
(Adapter->PermanentAddress[2] == 0xff) &&
(Adapter->PermanentAddress[3] == 0xff) &&
(Adapter->PermanentAddress[4] == 0xff) &&
(Adapter->PermanentAddress[5] == 0xff) ) )
{
if (Adapter->PermanentAddress[0] == 0xff)
RETAILMSG(1, (TEXT("CELAN: !!Warning!! EEPROM doesn't have MAC address. \r\n")));
if ( (MAC0 == 0) && (MAC1 == 0) && (MAC2 == 0) )
{
RETAILMSG(1, (TEXT("CELAN: !!ERROR!! MAC address is not specified. \r\n")));
return FALSE; // Registry not set
}
else
{
// We do not have EEPROM, so let's set MAC address by software
// MAC address is specified in the registry
#define SWAPB(Word) ((Word<<8)&0xff00 | (Word>>8)&0x00ff)
SelectBank(BANK1);
WriteWord(ADDR0,SWAPB(MAC0));
WriteWord(ADDR1,SWAPB(MAC1));
WriteWord(ADDR2,SWAPB(MAC2));
}
}
// IP address save again
Adapter->PermanentAddress[0] = ReadWord(ADDR0) & 0xFF;
Adapter->PermanentAddress[1] = ReadWord(ADDR0) >> 8;
Adapter->PermanentAddress[2] = ReadWord(ADDR1) & 0xFF;
Adapter->PermanentAddress[3] = ReadWord(ADDR1) >> 8;
Adapter->PermanentAddress[4] = ReadWord(ADDR2) & 0xFF;
Adapter->PermanentAddress[5] = ReadWord(ADDR2) >> 8;
#endif // for ROM
RETAILMSG(1,
(TEXT("CELAN: PermanentAddress [ %02x-%02x-%02x-%02x-%02x-%02x ]\r\n"),
Adapter->PermanentAddress[0],
Adapter->PermanentAddress[1],
Adapter->PermanentAddress[2],
Adapter->PermanentAddress[3],
Adapter->PermanentAddress[4],
Adapter->PermanentAddress[5]));
//
// Use the burned in address as the station address, unless the
// registry specified an override value.
//
if ((Adapter->StationAddress[0] == 0x00) &&
(Adapter->StationAddress[1] == 0x00) &&
(Adapter->StationAddress[2] == 0x00) &&
(Adapter->StationAddress[3] == 0x00) &&
(Adapter->StationAddress[4] == 0x00) &&
(Adapter->StationAddress[5] == 0x00)
)
{
Adapter->StationAddress[0] = Adapter->PermanentAddress[0];
Adapter->StationAddress[1] = Adapter->PermanentAddress[1];
Adapter->StationAddress[2] = Adapter->PermanentAddress[2];
Adapter->StationAddress[3] = Adapter->PermanentAddress[3];
Adapter->StationAddress[4] = Adapter->PermanentAddress[4];
Adapter->StationAddress[5] = Adapter->PermanentAddress[5];
}
return(TRUE);
}
BOOLEAN
CardSetup(
IN PCELAN_ADAPTER Adapter
)
/*++
Routine Description:
Sets up the card.
Arguments:
Adapter - pointer to the adapter block, which must be initialized.
Return Value:
TRUE if successful.
--*/
{
UINT i;
UINT Filter;
USHORT Tmp;
DEBUGMSG(ZONE_FUNCTION, (TEXT("+CELAN:CardSetup\r\n")));
//
// Write to and read from RCR to make sure it is there.
//
DEBUGMSG(ZONE_INIT, (TEXT("91C94:Reset 91C94\r\n")));
SelectBank(BANK0);
WriteWord(RCR,RCR_SOFTRESET);
Sleep(10);
Tmp = ReadWord(RCR);
if ((Tmp & RCR_SOFTRESET) != RCR_SOFTRESET) {
DEBUGMSG(ZONE_INIT,
(TEXT("91C94:CardSetup - Tmp = 0x%x, Expected 0x%x\r\n"),
Tmp, (RCR_SOFTRESET)));
return(FALSE);
}
WriteWord(RCR,0);
Sleep(10);
// Initialize the control register
DEBUGMSG(ZONE_INIT, (TEXT("91C94:Init Control register\r\n")));
SelectBank(BANK1);
WriteWord(CONTROL,0x0920);
//
// Set Loopback Mode
//
// DEBUGMSG(ZONE_INIT, (TEXT("91C94:Set loopbacke mode\r\n")));
// SelectBank(BANK0);
// WriteWord(TCR,TCR_LOOP);
//
// Clear all pending interrupts
//
DEBUGMSG(ZONE_INIT, (TEXT("91C94:Cleare current pending interrupt\r\n")));
SelectBank(BANK2);
WriteWord(INT_REG,ReadWord(INT_REG));
//
// Set Interrupt Mask Register
//
DEBUGMSG(ZONE_INIT, (TEXT("91C94:Set interrupt mask reg %02x\r\n"),Adapter->NicInterruptMask));
SelectBank(BANK2);
WriteWord(INT_REG,Adapter->NicInterruptMask);
#if 0 // Station Address setting is in CardInitialize
//
// Set Station Address
//
DEBUGMSG(ZONE_INIT, (TEXT("91C94:Set station address regs\r\n")));
SelectBank(BANK1);
WriteWord(ADDR0,Adapter->StationAddress[0] |
Adapter->StationAddress[1]<<8);
WriteWord(ADDR1,Adapter->StationAddress[2] |
Adapter->StationAddress[3]<<8);
WriteWord(ADDR2,Adapter->StationAddress[4] |
Adapter->StationAddress[5]<<8);
#endif //#if 0
Filter = Adapter->PacketFilter;
//
// Write out the multicast addresses
//
SelectBank(BANK3);
for (i = 0; i < 8; i+=2)
{
WriteWord(MULTICAST1+i,
(USHORT)((Filter & NDIS_PACKET_TYPE_ALL_MULTICAST) ?
0xffff : Adapter->NicMulticastRegs[i]
| Adapter->NicMulticastRegs[i+1]<<8));
}
PrintRegs;
DEBUGMSG(ZONE_FUNCTION, (TEXT("-CELAN:CardSetup\r\n")));
//
// ... but it is still in loopback mode.
//
return(TRUE);
}
VOID CardStop(
IN PCELAN_ADAPTER Adapter
)
/*++
Routine Description:
Stops the card.
Arguments:
Adapter - pointer to the adapter block
Return Value:
None.
--*/
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("+CELAN:CardStop\r\n")));
SelectBank(BANK0);
WriteWord(RCR,0);
DEBUGMSG(ZONE_FUNCTION, (TEXT("-CELAN:CardStop\r\n")));
}
BOOLEAN CardReset(
IN PCELAN_ADAPTER Adapter
)
/*++
Routine Description:
Resets the card.
Arguments:
Adapter - pointer to the adapter block
Return Value:
TRUE if everything is OK.
--*/
{
WORD Tmp;
DEBUGMSG(ZONE_FUNCTION, (TEXT("+CELAN:CardReset\r\n")));
//
// Stop the chip
//
CardStop(Adapter);
//
// Write to and read from RCR to make sure it is there.
//
DEBUGMSG(ZONE_INIT, (TEXT("91C94:Reset 91C94\r\n")));
SelectBank(BANK0);
WriteWord(RCR,RCR_SOFTRESET);
Sleep(10);
Tmp = ReadWord(RCR);
if ((Tmp & RCR_SOFTRESET) != RCR_SOFTRESET) {
DEBUGMSG(ZONE_ERROR,
(TEXT("91C94:CardSetup - Tmp = 0x%x, Expected 0x%x\r\n"),
Tmp, (RCR_SOFTRESET)));
return(FALSE);
}
WriteWord(RCR,0);
Sleep(10);
//
// Restart the chip
//
CardStart(Adapter);
DEBUGMSG(ZONE_FUNCTION, (TEXT("-CELAN:CardReset\r\n")));
return TRUE;
}
ULONG
CardComputeCrc(
IN PUCHAR Buffer,
IN UINT Length
)
/*++
Routine Description:
Runs the AUTODIN II CRC algorithm on buffer Buffer of
length Length.
Arguments:
Buffer - the input buffer
Length - the length of Buffer
Return Value:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -