📄 8390.c
字号:
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Novell Eagle 2000 driver
* FILE: ne2000/8390.c
* PURPOSE: DP8390 NIC specific routines
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 27/08-2000 Created
*/
#include <roscfg.h>
#include <ne2000.h>
#include <debug.h>
/* Null-terminated array of ports to probe. This is "semi-risky" (Don Becker). */
ULONG ProbeAddressList[] = { 0x280, 0x300, 0x320, 0x340, 0x360, 0x380, 0 };
static BOOLEAN ProbeAddressForNIC(
ULONG address)
/*
* FUNCTION: Probes an address for a NIC
* ARGUMENTS:
* address = Base address to probe
* RETURNS:
* TRUE if an NIC is found at the address
* FALSE otherwise
* NOTES:
* If the adapter responds correctly to a
* stop command we assume it is present
*/
{
UCHAR Tmp;
NDIS_DbgPrint(MID_TRACE, ("Probing address 0x%x\n", address));
/* Disable interrupts */
NdisRawWritePortUchar(address + PG0_IMR, 0);
/* Stop the NIC */
NdisRawWritePortUchar(address + PG0_CR, CR_STP | CR_RD2);
/* Pause for 1.6ms */
NdisStallExecution(1600);
/* Read NIC response */
NdisRawReadPortUchar(address + PG0_CR, &Tmp);
if ((Tmp == (CR_RD2 | CR_STP)) || (Tmp == (CR_RD2 | CR_STP | CR_STA)))
return TRUE;
else
return FALSE;
}
BOOLEAN NICCheck(
PNIC_ADAPTER Adapter)
/*
* FUNCTION: Tests for a NIC
* ARGUMENTS:
* Adapter = Pointer to adapter information
* RETURNS:
* TRUE if NIC is believed to be present, FALSE if not
*/
{
int i;
NDIS_DbgPrint(MAX_TRACE, ("Called\n"));
/* first try the supplied value */
if(ProbeAddressForNIC(Adapter->IoBaseAddress))
{
NDIS_DbgPrint(MID_TRACE, ("Found adapter at 0x%x\n", Adapter->IoBaseAddress));
return TRUE;
}
/* ok, no dice, time to probe */
for(i = 0; ProbeAddressList[i]; i++)
{
if(ProbeAddressForNIC(ProbeAddressList[i]))
{
NDIS_DbgPrint(MID_TRACE, ("Found adapter at address 0x%x\n", ProbeAddressList[i]));
Adapter->IoBaseAddress = ProbeAddressList[i];
return TRUE;
}
}
NDIS_DbgPrint(MIN_TRACE,("Adapter NOT found!\n"));
return FALSE;
}
static BOOLEAN NICTestAddress(
PNIC_ADAPTER Adapter,
ULONG Address)
/*
* FUNCTION: Tests if an address is writable
* ARGUMENTS:
* Adapter = Pointer to adapter information
* RETURNS:
* TRUE if the address is writable, FALSE if not
*/
{
USHORT Data;
USHORT Tmp;
/* Read one word */
NICReadDataAlign(Adapter, &Data, Address, 0x02);
/* Alter it */
Data ^= 0xFFFF;
/* Write it back */
NICWriteDataAlign(Adapter, Address, &Data, 0x02);
/* Check if it has changed on the NIC */
NICReadDataAlign(Adapter, &Tmp, Address, 0x02);
return (Data == Tmp);
}
static BOOLEAN NICTestRAM(
PNIC_ADAPTER Adapter)
/*
* FUNCTION: Finds out how much RAM a NIC has
* ARGUMENTS:
* Adapter = Pointer to adapter information
* RETURNS:
* TRUE if the RAM size was found, FALSE if not
* NOTES:
* Start at 1KB and test for every 1KB up to 64KB
*/
{
ULONG Base;
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
/* Locate RAM base address */
for (Base = 0x0400; Base < 0x10000; Base += 0x0400) {
if (NICTestAddress(Adapter, Base))
break;
}
if (Base == 0x10000) {
/* No RAM on this board */
NDIS_DbgPrint(MIN_TRACE, ("No RAM found on board.\n"));
return FALSE;
}
Adapter->RamBase = (PUCHAR)Base;
/* Find RAM size */
for (; Base < 0x10000; Base += 0x0400) {
if (!NICTestAddress(Adapter, Base))
break;
}
Adapter->RamSize = (UINT)(Base - (ULONG_PTR)Adapter->RamBase);
NDIS_DbgPrint(MID_TRACE, ("RAM is at (0x%X). Size is (0x%X).\n",
Adapter->RamBase, Adapter->RamSize));
return TRUE;
}
static VOID NICSetPhysicalAddress(
PNIC_ADAPTER Adapter)
/*
* FUNCTION: Initializes the physical address on the NIC
* ARGUMENTS:
* Adapter = Pointer to adapter information
* NOTES:
* The physical address is taken from Adapter.
* The NIC is stopped by this operation
*/
{
UINT i;
/* Select page 1 */
NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE1);
/* Initialize PAR - Physical Address Registers */
for (i = 0; i < 0x06; i++)
NdisRawWritePortUchar(Adapter->IOBase + PG1_PAR + i, Adapter->StationAddress[i]);
/* Go back to page 0 */
NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0);
}
static VOID NICSetMulticastAddressMask(
PNIC_ADAPTER Adapter)
/*
* FUNCTION: Initializes the multicast address mask on the NIC
* ARGUMENTS:
* Adapter = Pointer to adapter information
* NOTES:
* The multicast address mask is taken from Adapter.
* The NIC is stopped by this operation
*/
{
UINT i;
/* Select page 1 */
NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE1);
/* Initialize MAR - Multicast Address Registers */
for (i = 0; i < 0x08; i++)
NdisRawWritePortUchar(Adapter->IOBase + PG1_MAR + i, Adapter->MulticastAddressMask[i]);
/* Go back to page 0 */
NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0);
}
static BOOLEAN NICReadSAPROM(
PNIC_ADAPTER Adapter)
/*
* FUNCTION: Reads the Station Address PROM data from the NIC
* ARGUMENTS:
* Adapter = Pointer to adapter information
* RETURNS:
* TRUE if a the NIC is an NE2000
* NOTES:
* This routine also determines if the NIC can support word mode transfers
* and if it does initializes the NIC for word mode.
* The station address in the adapter structure is initialized with
* the address from the SAPROM
*/
{
UINT i;
UCHAR Buffer[32];
UCHAR WordLength;
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
/* Read Station Address PROM (SAPROM) which is 16 bytes at remote DMA address 0.
Some cards double the data read which we must compensate for */
/* Initialize RBCR0 and RBCR1 - Remote Byte Count Registers */
NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, 0x20);
NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, 0x00);
/* Initialize RSAR0 and RSAR1 - Remote Start Address Registers */
NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR0, 0x00);
NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR1, 0x00);
/* Select page 0, read and start the NIC */
NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD0 | CR_PAGE0);
/* Read one byte at a time */
WordLength = 2; /* Assume a word is two bytes */
for (i = 0; i < 32; i += 2) {
NdisRawReadPortUchar(Adapter->IOBase + NIC_DATA, &Buffer[i]);
NdisRawReadPortUchar(Adapter->IOBase + NIC_DATA, &Buffer[i + 1]);
if (Buffer[i] != Buffer[i + 1])
WordLength = 1; /* A word is one byte long */
}
/* If WordLength is 2 the data read before was doubled. We must compensate for this */
if (WordLength == 2) {
NDIS_DbgPrint(MAX_TRACE,("NE2000 or compatible network adapter found.\n"));
Adapter->WordMode = TRUE;
/* Move the SAPROM data to the adapter object */
for (i = 0; i < 16; i++)
Adapter->SAPROM[i] = Buffer[i * 2];
/* Copy the station address */
NdisMoveMemory(
(PVOID)&Adapter->StationAddress,
(PVOID)&Adapter->SAPROM,
DRIVER_LENGTH_OF_ADDRESS);
/* Initialize DCR - Data Configuration Register (word mode/4 words FIFO) */
NdisRawWritePortUchar(Adapter->IOBase + PG0_DCR, DCR_WTS | DCR_LS | DCR_FT10);
return TRUE;
} else {
NDIS_DbgPrint(MAX_TRACE, ("NE1000 or compatible network adapter found.\n"));
Adapter->WordMode = FALSE;
return FALSE;
}
}
NDIS_STATUS NICInitialize(
PNIC_ADAPTER Adapter)
/*
* FUNCTION: Initializes a NIC
* ARGUMENTS:
* Adapter = Pointer to adapter information
* RETURNS:
* Status of NIC initialization
* NOTES:
* The NIC is put into loopback mode
*/
{
UCHAR Tmp;
NDIS_DbgPrint(MID_TRACE, ("Called.\n"));
/* Reset the NIC */
NdisRawReadPortUchar(Adapter->IOBase + NIC_RESET, &Tmp);
/* Wait for 1.6ms */
NdisStallExecution(1600);
/* Write the value back */
NdisRawWritePortUchar(Adapter->IOBase + NIC_RESET, Tmp);
/* Select page 0 and stop NIC */
NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0);
/* Initialize DCR - Data Configuration Register (byte mode/8 bytes FIFO) */
NdisRawWritePortUchar(Adapter->IOBase + PG0_DCR, DCR_LS | DCR_FT10);
/* Clear RBCR0 and RBCR1 - Remote Byte Count Registers */
NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, 0x00);
NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, 0x00);
/* Initialize RCR - Receive Configuration Register (monitor mode) */
NdisRawWritePortUchar(Adapter->IOBase + PG0_RCR, RCR_MON);
/* Enter loopback mode (internal NIC module loopback) */
NdisRawWritePortUchar(Adapter->IOBase + PG0_TCR, TCR_LOOP);
/* Read the Station Address PROM */
if (!NICReadSAPROM(Adapter))
return NDIS_STATUS_ADAPTER_NOT_FOUND;
NDIS_DbgPrint(MID_TRACE, ("Station address is (%02X %02X %02X %02X %02X %02X).\n",
Adapter->StationAddress[0], Adapter->StationAddress[1],
Adapter->StationAddress[2], Adapter->StationAddress[3],
Adapter->StationAddress[4], Adapter->StationAddress[5]));
/* Select page 0 and start NIC */
NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2 | CR_PAGE0);
/* Clear ISR - Interrupt Status Register */
NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, 0xFF);
/* Find NIC RAM size */
NICTestRAM(Adapter);
return NDIS_STATUS_SUCCESS;
}
NDIS_STATUS NICSetup(
PNIC_ADAPTER Adapter)
/*
* FUNCTION: Sets up a NIC
* ARGUMENTS:
* Adapter = Pointer to adapter information
* RETURNS:
* Status of operation
* NOTES:
* The NIC is put into loopback mode
*/
{
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
if (Adapter->WordMode ) {
/* Initialize DCR - Data Configuration Register (word mode/4 words FIFO) */
NdisRawWritePortUchar(Adapter->IOBase + PG0_DCR, DCR_WTS | DCR_LS | DCR_FT10);
} else {
/* Initialize DCR - Data Configuration Register (byte mode/8 bytes FIFO) */
NdisRawWritePortUchar(Adapter->IOBase + PG0_DCR, DCR_LS | DCR_FT10);
}
/* Clear RBCR0 and RBCR1 - Remote Byte Count Registers */
NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, 0x00);
NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, 0x00);
/* Initialize RCR - Receive Configuration Register (monitor mode) */
NdisRawWritePortUchar(Adapter->IOBase + PG0_RCR, RCR_MON);
/* Enter loopback mode (internal NIC module loopback) */
NdisRawWritePortUchar(Adapter->IOBase + PG0_TCR, TCR_LOOP);
/* Set boundary page */
NdisRawWritePortUchar(Adapter->IOBase + PG0_BNRY, Adapter->NextPacket);
/* Set start page */
NdisRawWritePortUchar(Adapter->IOBase + PG0_PSTART, Adapter->PageStart);
/* Set stop page */
NdisRawWritePortUchar(Adapter->IOBase + PG0_PSTOP, Adapter->PageStop);
/* Program our address on the NIC */
NICSetPhysicalAddress(Adapter);
/* Program the multicast address mask on the NIC */
NICSetMulticastAddressMask(Adapter);
/* Select page 1 and stop NIC */
NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE1);
/* Initialize current page register */
NdisRawWritePortUchar(Adapter->IOBase + PG1_CURR, Adapter->PageStart + 1);
/* Select page 0 and stop NIC */
NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0);
/* Clear ISR - Interrupt Status Register */
NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, 0xFF);
/* Initialize IMR - Interrupt Mask Register */
NdisRawWritePortUchar(Adapter->IOBase + PG0_IMR, Adapter->InterruptMask);
/* Select page 0 and start NIC */
NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2 | CR_PAGE0);
Adapter->CurrentPage = Adapter->PageStart + 1;
Adapter->NextPacket = Adapter->PageStart + 1;
Adapter->BufferOverflow = FALSE;
Adapter->ReceiveError = FALSE;
Adapter->TransmitError = FALSE;
NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
return NDIS_STATUS_SUCCESS;
}
NDIS_STATUS NICStart(
PNIC_ADAPTER Adapter)
/*
* FUNCTION: Starts a NIC
* ARGUMENTS:
* Adapter = Pointer to adapter information
* RETURNS:
* Status of operation
*/
{
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
/* Take NIC out of loopback mode */
NdisRawWritePortUchar(Adapter->IOBase + PG0_TCR, 0x00);
/* Initialize RCR - Receive Configuration Register (accept all) */
NdisRawWritePortUchar(Adapter->IOBase + PG0_RCR, RCR_AB | RCR_AM | RCR_PRO);
return NDIS_STATUS_SUCCESS;
}
NDIS_STATUS NICStop(
PNIC_ADAPTER Adapter)
/*
* FUNCTION: Stops a NIC
* ARGUMENTS:
* Adapter = Pointer to adapter information
* RETURNS:
* Status of operation
*/
{
UCHAR Tmp;
UINT i;
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
/* Select page 0 and stop NIC */
NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0);
/* Clear Remote Byte Count Register so ISR_RST will be set */
NdisRawWritePortUchar( Adapter->IOBase + PG0_RBCR0, 0x00);
NdisRawWritePortUchar( Adapter->IOBase + PG0_RBCR0, 0x00);
/* Wait for ISR_RST to be set, but timeout after 2ms */
for (i = 0; i < 4; i++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -