ether.c

来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 297 行

C
297
字号
//------------------------------------------------------------------------------
//
//  Module Name:
//      ether.c
//
//  Abstract:
//
//  Functions:
//
//------------------------------------------------------------------------------
#include <windows.h>
#include <halether.h>
#include <ceddk.h>
#include <ethdbg.h>
#include <nkintr.h>
#include <armintboot.h>
#include <platform.h>

#include "eboot.h"

//
// *** Must match config.bib values ***
#define ETHDMA_BUFF_BASE    0x4000      // Ethernet DMA buffer base address.
#define ETHDMA_BUFF_SIZE    0x20000     // Ethernet DMA buffer size.

typedef BOOL (*PFN_EDBG_INIT_DMABUF)(DWORD dwStartAddress, DWORD dwSize);

static PFN_EDBG_INIT             pfnEDbgInit;
static PFN_EDBG_INIT_DMABUF      pfnEDbgInitDMA;
static PFN_EDBG_GET_FRAME        pfnEDbgGetFrame;
static PFN_EDBG_SEND_FRAME       pfnEDbgSendFrame;

typedef struct vendorid
{
    DWORD dwUpperMAC; // first 3 bytes of ethernet address
    char  *szAbbrev;
} VENDORID;

static const VENDORID VendorIds[] =
{
    {0x00006E, "AE" }, // Artisoft
    {0x000094, "AS" }, // ASANTE
    {0x0000E8, "AC" }, // Accton Technology
    {0x004005, "LS" }, // LinkSys
    {0x004033, "AD" }, // Addtron Technology
    {0x004092, "ASP"}, // ASP Computer Products
    {0x00800F, "SMC"}, // SMC
    {0x008048, "CPX"}, // Compex
    {0x0080AD, "CN" }, // CNET Technologies
    {0x0080C8, "DL" }, // D-Link
    {0x00A0D2, "AT" }, // Allied TeleSyn
    {0x00C00D, "ALR"}, // Advanced Logic Research
    {0x00C06D, "BR" }, // Boca Research
    {0x00C0DF, "GE" }, // Kye International GENIUS GE2000 series
    {0x00C0F0, "KS" }, // Kingston
    {0x4854E8, "WB" }  // WinBond Electronics Corp
};

#define NUM_VENDORIDS (sizeof(VendorIds)/sizeof(VENDORID))

BOOL FindDebugNIC(PULONG pBaseAddr, PUCHAR pIRQ, PUCHAR pAdaptType);
int GetPCIConfig(ULONG bus, ULONG device, ULONG function, PCI_COMMON_CONFIG *pConfig);

BOOL
OEMEthGetFrame(
    BYTE *pData,       // OUT - Receives frame data
    UINT16 *pwLength)  // IN  - Length of Rx buffer
                       // OUT - Number of bytes received
{
    if (pfnEDbgGetFrame)
        return(pfnEDbgGetFrame(pData, pwLength));

    return(FALSE);
}

BOOL
OEMEthSendFrame(
    BYTE *pData,     // IN - Data buffer
    DWORD dwLength)  // IN - Length of buffer
{
    int retries = 0;

    // Let's be persistant here
    while (retries++ < 4) {
        if (!pfnEDbgSendFrame(pData, dwLength))
            return TRUE;
        else
            EdbgOutputDebugString("ERROR: OEMEthSendFrame failure, retry %u\r\n", retries);
    }
    return(FALSE);
}

BOOL OEMEthHardwareInit(ETH_HARDWARE_INIT_ARGS *pInitArgs, EDBG_ADDR *pMyAddr)
{
    HARP_BOOT_ARGS *pBootArgs = NULL;


    // Form platform name string...
    strncpy(pInitArgs->szPlatformString, "ARMINT", EDBG_MAX_DEV_NAMELEN);

    //------------------------------------------------------------------
    // This value should agree with DRIVER_GLOBALS_PHYSICAL_MEMORY_START
    // in drv_glob.h PLUS DRIVER_GLOBALS_ZEROINIT_SIZE, 'cause that's
    // where we put the ethernet debug info from Eboot for the OS to read.
    //------------------------------------------------------------------
    pInitArgs->pBootArgs = (HARP_BOOT_ARGS *)(0x00008000 + 0x800);
    pBootArgs = pInitArgs->pBootArgs;
    EdbgOutputDebugString("Boot Args @ 0x%x\r\n", pInitArgs->pBootArgs);

    // Find debug NIC and get base address, IRQ, and NIC type.
    if (!FindDebugNIC(&pBootArgs->dwEdbgBaseAddr, &pBootArgs->ucEdbgIRQ, &pBootArgs->ucEdbgAdapterType))
        return(FALSE);


    // Assign controller-specific callbacks.
    switch (pBootArgs->ucEdbgAdapterType)
    {
        case EDBG_ADAPTER_NE2000:
            pfnEDbgInit           = NE2000Init;
            pfnEDbgGetFrame       = NE2000GetFrame;
            pfnEDbgSendFrame      = NE2000SendFrame;
            break;

        case EDBG_ADAPTER_SMC9000:
            pfnEDbgInit           = SMCInit;
            pfnEDbgGetFrame       = SMCGetFrame;
            pfnEDbgSendFrame      = SMCSendFrame;
            break;

        default:
            EdbgOutputDebugString("ERROR: Unable to find network card.\r\n");
            EdbgOutputDebugString("ERROR: Card Type = %d, Address = 0x%s.\r\n", pBootArgs->ucEdbgAdapterType, pBootArgs->dwEdbgBaseAddr);
            return(FALSE);
    }

    // call driver specific initialization
    if (!pfnEDbgInit((BYTE *)(PHYS_PCI_IO_BASE | pBootArgs->dwEdbgBaseAddr), 1, pMyAddr->wMAC))
    {
        EdbgOutputDebugString("ERROR: Failed to initialize NIC.\r\n");
        return(FALSE);
    }

    return(TRUE);
}


DWORD OEMEthGetSecs(void)
{
    // Returning counter value for Integrator RTC.
    // WARNING: this assumes RTC CLK1HZ signal is
    // set for 1 Hz = 1 tick/second.

    return(*(DWORD *)INTEGRATOR_RTC_BASE);
}


BOOL FindDebugNIC(PULONG pBaseAddr, PUCHAR pIRQ, PUCHAR pAdaptType)
{
    PCI_SLOT_NUMBER     slotNumber;
    PCI_COMMON_CONFIG   pciConfig;
    UCHAR               bus, device, function;
    ULONG               length;

    if (pBaseAddr == NULL || pIRQ == NULL)
        return(FALSE);

    for (bus = 0; bus < PCI_MAX_BUS; bus++)
    {
        for (device = 0; device < PCI_MAX_DEVICES; device++)
        {
            slotNumber.u.bits.DeviceNumber = device;

            for (function = 0; function < PCI_MAX_FUNCTION; function++)
            {
                slotNumber.u.bits.FunctionNumber = function;

                length = GetPCIConfig(bus, device, function, &pciConfig);

                if (length == 0 || pciConfig.VendorID == 0xFFFF) 
                    break;

                if ((pciConfig.BaseClass == PCI_CLASS_NETWORK_CTLR) &&
                    (pciConfig.SubClass  == PCI_SUBCLASS_NET_ETHERNET_CTLR))
                {
                   
// TODO - for the moment, we're assuming only one NIC and if we find it, 
// it's the debug NIC (and an NE2000-compatible at that)...
                    *pIRQ = pciConfig.u.type0.InterruptLine;
                    *pBaseAddr = (pciConfig.u.type0.BaseAddresses[0] & 0xFFFFFFFC);
                    *pAdaptType = EDBG_ADAPTER_NE2000;

                    EdbgOutputDebugString("INFO: Found NIC (IRQ = 0x%x, BaseAddress = 0x%x)\r\n", *pIRQ, *pBaseAddr);
                    return(TRUE);
                }
                
                if (function == 0 && !(pciConfig.HeaderType & 0x80)) 
                    break;
                
            }
            if (length == 0)
                break;
        }

        if (length == 0 && device == 0)
            break;
    }

    EdbgOutputDebugString("INFO: No debug NIC found...\r\n");

    return (FALSE);
}

// Stub LED display routine - called by NE2000 ethdbg driver.
VOID SC_WriteDebugLED(WORD wIndex, DWORD dwPattern)
{
    return;
}

static void itoa10(int i, char *a)
{
    char * p = a;
    int c = 0;
    int n = i;
    char swap;

    //
    // Build the ascii string in reverse digit order
    //
    while (n)
    {
        *p = (char)(n % 10) + '0';
        n /= 10;
        p++;
        c++;
    }

    *p = 0;
    c--;

    //
    // Reverse the string in place to correct order
    //
    for (n = 0; n < c; n++, c--)
    {
        swap = a[n];
        a[n] = a[c];
        a[c] = swap;
    }
}

static DWORD UpperDWFromMAC(EDBG_ADDR *pAddr)
{
    DWORD ret;

    //
    // The WORDs in wMAC field are in net order, so we need to do some
    // serious shifting around.
    // A hex ethernet address of 12 34 56 78 9a bc is stored in wMAC array as
    // wMAC[0] = 3412, wMAC[1] = 7856, wMAC[2] = bc9a.
    // The 4 byte return value should look like 0x00123456
    //
    ret = (pAddr->wMAC[0] & 0x00ff) << 16;
    ret |= pAddr->wMAC[0] & 0xff00;
    ret |= pAddr->wMAC[1] & 0x00ff;
    return ret;
}

void CreateDeviceName(EDBG_ADDR *pMyAddr, char *szBuf,
                             LPSTR szPlatformString)
{
    int i;
    DWORD dwUpperMAC;

    EdbgOutputDebugString("CreateDeviceName\r\n");
    dwUpperMAC = UpperDWFromMAC(pMyAddr);

    EdbgOutputDebugString("UpperDWORD = 0x%X\r\n", dwUpperMAC);
    strcpy(szBuf, szPlatformString);
    szBuf += strlen(szBuf);

    for (i = 0; i < NUM_VENDORIDS; i++)
    {
        if (dwUpperMAC == VendorIds[i].dwUpperMAC)
        {
            strcat(szBuf,VendorIds[i].szAbbrev);
            szBuf += strlen(szBuf);
            break;
        }
    }

    itoa10(((pMyAddr->wMAC[2]>>8) | ((pMyAddr->wMAC[2] & 0x00ff) << 8)),
           szBuf);
}



⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?