⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 8390.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * 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 + -