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

📄 halether.c

📁 RTL8139 网卡驱动源码 for WinCE.net CEPC
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
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.

Module Name:  
    halether.c
    
Abstract:

    Platform specific code for debug ethernet services (debug messages,
    kernel debugger, text shell (PPSH)).  These functions are all called
    from ethdbg.lib.  They are non-preemptible, and cannot make any system calls.

Functions:


Notes: 

--*/
#include <windows.h>
#include <nkintr.h>
#include <ethdbg.h>
#include <halether.h>
#include <hal.h>
#include <PCIreg.h>
#include "pc.h"
#include "bootarg.h"
#include "oalintr.h"


int __cdecl _inp  (unsigned short);
int __cdecl _outp (unsigned short, int);

//
// Function pointers to the support library functions of the currently installed debug ethernet controller.
//
PFN_EDBG_INIT                   pfnEDbgInit;
PFN_EDBG_INIT_DMABUFFER         pfnEDbgInitDMABuffer;
PFN_EDBG_ENABLE_INTS            pfnEDbgEnableInts;
PFN_EDBG_DISABLE_INTS           pfnEDbgDisableInts;
PFN_EDBG_GET_PENDING_INTS       pfnEDbgGetPendingInts;
PFN_EDBG_GET_FRAME              pfnEDbgGetFrame;
PFN_EDBG_SEND_FRAME             pfnEDbgSendFrame;
PFN_EDBG_READ_EEPROM            pfnEDbgReadEEPROM;
PFN_EDBG_WRITE_EEPROM           pfnEDbgWriteEEPROM;
PFN_EDBG_SET_OPTIONS            pfnEDbgSetOptions;
PFN_EDBG_CURRENT_PACKET_FILTER  pfnCurrentPacketFilter;
PFN_EDBG_MULTICAST_LIST         pfnMulticastList;

#define ETHDMA_BUFFER_BASE	    0x80200000      // MUST MATCH CONFIG.BIB
#define ETHDMA_BUFFER_SIZE	    0x00020000      // 128K DMA Buffer

#define EDBG_PHYSICAL_MEMORY_START (0x801DC000) // MUST MATCH CONFIG.BIB
static BOOT_ARGS *pBootArgs;

// Buffer for receiving frames into.  
UCHAR RcvBuf[1500];
extern DWORD EdbgDebugZone;

USHORT wLocalMAC[3];    // Saved copy of the mac address

// Well known DHCP ports for use with UDP
#define DHCP_SERVER_PORT 0x4300
#define DHCP_CLIENT_PORT 0x4400

// We retry more than Odo since CEPC BIOS's take longer to boot.
#define MAX_BOOTME_CNT   20
#define BOOTME_INTERVAL  3

#define PLATFORM_STRING "CEPC"

typedef struct __VendorId // NIC vendor ID.
{
    USHORT wVenId;      // Vendor Id
    USHORT wDevId;      // Device Id
    ULONG  dwUpperMAC;  // first 3 bytes of ethernet address
    UCHAR  Type;        // NIC type (EDBG_ADAPTER_xxx)
    UCHAR  *szAbbrev;   // Vendor name abbreviation
} VENDORID, *PVENDORID;

static const VENDORID VendorIds[] =
{
//   VenId   DevId     MAC           Type            Name
//  -------------------------------------------------------
    {0x0000, 0x0000, 0x004033, EDBG_ADAPTER_NE2000,  "AD" }, // Addtron Tech (ISA)
    {0x1050, 0x0940, 0x004005, EDBG_ADAPTER_NE2000,  "LS" }, // LinkSys
    {0x1050, 0x0940, 0x002078, EDBG_ADAPTER_NE2000,  "LS" }, // LinkSys
    {0x10EC, 0x8029, 0x00C0F0, EDBG_ADAPTER_NE2000,  "KS" }, // Kingston
    {0x10EC, 0x8129, 0x000000, EDBG_ADAPTER_RTL8139, "RT" }, // RealTek (Lanner)
    {0x10EC, 0x8139, 0x00900B, EDBG_ADAPTER_RTL8139, "RT" }, // RealTek (Lanner)
    {0x10EC, 0x8139, 0x00D0C9, EDBG_ADAPTER_RTL8139, "RT" }, // RealTek (Lanner)
    {0x10EC, 0x8139, 0x00E04C, EDBG_ADAPTER_RTL8139, "RT" }, // RealTek (Advantech)
    {0x100B, 0x0020, 0x00A0CC, EDBG_ADAPTER_DP83815, "NG" }  // Netgear
};
#define NUM_VENDORIDS (sizeof(VendorIds)/sizeof(VENDORID))

#ifdef IMGSHAREETH
BOOL    bNewFilter = FALSE;     //  User mode --> Kernel mode to set new filter.
DWORD   dwFilter;               //  The filter..

BOOL    bNewMulticast = FALSE;  //  User mode --> Kernel mode for new list
DWORD   dwNoOfEntry;
BOOL    ucMultiAddr[8][6];      //  The new list..  
                                //  VMINI assumes 8 multicast list entry..
                                //                          
#endif

static void
itoa10(
    int n,
    char s[]
    )
{
    int i = 0; 

    // Get absolute value of number
    unsigned int val = (unsigned int)((n < 0) ? -n : n);

    // Extract digits in reverse order
    do {
        s[i++] = (val % 10) + '0';
    } while (val /= 10);

    // Add sign if number negative
    if (n < 0) s[i++] = '-';

    s[i--] = '\0';

    // Reverse string
    for (n = 0; n < i; n++, i--) {
        char swap = s[n];
        s[n] = s[i];
        s[i] = 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)
{
    int i;
    DWORD dwUpperMAC = UpperDWFromMAC(pMyAddr);

    // If a device name was passed up by the bootloader, use it.
    //
    if ((pBootArgs->dwVersionSig == BOOT_ARG_VERSION_SIG) &&
        strlen(pBootArgs->szDeviceNameRoot))
        strncpy(szBuf, pBootArgs->szDeviceNameRoot, EDBG_MAX_DEV_NAMELEN);
    else
        strcpy(szBuf, PLATFORM_STRING);
    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);
}


#define IPSTATE_NONE    0
#define IPSTATE_GOTIP   1
#define IPSTATE_ARP     2
#define IPSTATE_ARPED   3
#define IPSTATE_RETRY   4

#define MAX_DHCP_RETRY  3


/* OEMEthInit
 *
 *  Initialization routine - called from EdbgInit() to perform platform specific
 *  HW init.  The CEPC platform uses either an SMC 91C94 Ethernet controller or
 *  an NE2000 compatible adapter (NSC 8390 ethernet controller).
 *
 *  Return Value:
 *    Return TRUE if init is successful, FALSE if error.
 */
BOOL
OEMEthInit(EDBG_ADAPTER *pAdapter)
{
    pBootArgs = (BOOT_ARGS *) ((ULONG)(*(PBYTE *)BOOT_ARG_PTR_LOCATION) | 0x80000000);

    // Some parameters included in boot args for future use, make sure these aren't set
    switch (pBootArgs->ucEdbgAdapterType) {
    case EDBG_ADAPTER_NE2000:
        pfnEDbgInit           = NE2000Init;
        pfnEDbgInitDMABuffer  = NULL;
        pfnEDbgEnableInts     = NE2000EnableInts;     
        pfnEDbgDisableInts    = NE2000DisableInts;    
        pfnEDbgGetPendingInts = NE2000GetPendingInts; 
        pfnEDbgGetFrame       = NE2000GetFrame;       
        pfnEDbgSendFrame      = NE2000SendFrame;      
        pfnEDbgReadEEPROM     = NE2000ReadEEPROM;     
        pfnEDbgWriteEEPROM    = NE2000WriteEEPROM;    
        break;
   

    case EDBG_ADAPTER_RTL8139:
        pfnEDbgInit           = RTL8139Init;
        pfnEDbgInitDMABuffer  = RTL8139InitDMABuffer;
        pfnEDbgEnableInts     = RTL8139EnableInts;     
        pfnEDbgDisableInts    = RTL8139DisableInts;    
        pfnEDbgGetPendingInts = RTL8139GetPendingInts; 
        pfnEDbgGetFrame       = RTL8139GetFrame;       
        pfnEDbgSendFrame      = RTL8139SendFrame;      
        pfnEDbgReadEEPROM     = RTL8139ReadEEPROM;     
        pfnEDbgWriteEEPROM    = RTL8139WriteEEPROM;             
        break;

	case EDBG_USB_RNDIS:
		EdbgOutputDebugString(" RNDIS Edbg!\r\n");
        pfnEDbgInit           = HostMiniInit;
        pfnEDbgEnableInts     = RndisEnableInts;     
        pfnEDbgDisableInts    = RndisDisableInts;    
        pfnEDbgGetPendingInts = RndisGetPendingInts; 
        pfnEDbgGetFrame       = RndisEDbgGetFrame;       
        pfnEDbgSendFrame      = RndisEDbgSendFrame;      
        pfnEDbgReadEEPROM     = NULL;
        pfnEDbgWriteEEPROM    = NULL;
        pfnEDbgSetOptions     = RndisSetOptions;
        pfnCurrentPacketFilter= RndisCurrentPacketFilter;
        pfnMulticastList      = RndisMulticastList;
        break ;

    default:
        EdbgOutputDebugString("Unsupported debug Ethernet parameters - adapter: %u, IRQ:%u\n",
                              pBootArgs->ucEdbgAdapterType, pBootArgs->ucEdbgIRQ);
        return (FALSE);
    }
  
    // Initialize NIC DMA buffer, if required.
    //
    if (pfnEDbgInitDMABuffer)
    {
        if (!pfnEDbgInitDMABuffer(ETHDMA_BUFFER_BASE, ETHDMA_BUFFER_SIZE))
        {
            EdbgOutputDebugString("ERROR: Failed to initialize Ethernet controller DMA buffer.\r\n");
            return FALSE;
        }
    }

    pAdapter->Addr=pBootArgs->EdbgAddr;// Inherit Eth address from Bootloader first.
    if (!pfnEDbgInit((BYTE *) pBootArgs->dwEdbgBaseAddr,1,pAdapter->Addr.wMAC) )
        return (FALSE);

    // Check the MAC address - this can be invalid if the switches are set wrong.
    if ( !pAdapter->Addr.wMAC[0] && !pAdapter->Addr.wMAC[1] && !pAdapter->Addr.wMAC[2] ) {
        EdbgOutputDebugString("Invalid Ethernet address read from the debug ethernet controller, check switch settings\n");
        return (FALSE);
    }

    // Save out local mac address.
    memcpy ((char *)wLocalMAC, pAdapter->Addr.wMAC, sizeof(wLocalMAC));
    
    EdbgOutputDebugString("Debug Ethernet card initialized, MAC Address:%B:%B:%B:%B:%B:%B\r\n",
                          pAdapter->Addr.wMAC[0] & 0x00FF, pAdapter->Addr.wMAC[0] >> 8,
                          pAdapter->Addr.wMAC[1] & 0x00FF, pAdapter->Addr.wMAC[1] >> 8,
                          pAdapter->Addr.wMAC[2] & 0x00FF, pAdapter->Addr.wMAC[2] >> 8  );

#if defined(IMGSHAREETH)
    VBridgeInit();
    VBridgeKSetLocalMacAddress((char *)wLocalMAC);
#endif

    // Fill in our SYSINTR value for the EDBG subsystem. Since we have limited IRQ
    // resources, just run in polled mode unless otherwise configured.
    if ( pBootArgs->ucEdbgIRQ )
        pAdapter->SysIntrVal = OEMTranslateIrq(pBootArgs->ucEdbgIRQ);
    else
        pAdapter->SysIntrVal = EDBG_SYSINTR_NOINTR;

    pAdapter->Addr.dwIP = pBootArgs->EdbgAddr.dwIP;
    pAdapter->DHCPLeaseTime = pBootArgs->DHCPLeaseTime;
    pAdapter->EdbgFlags = pBootArgs->EdbgFlags;

    // Enable filtering of broadcast packets (all except ARP packets) to reduce overhead.  We still have
    // to take an interrupt, but the driver can quickly determine whether a packet may be discarded without
    // having to copy all the data from the chip.   Note that we cannot turn this option on until DHCP is
    // done processing, since some DHCP servers return responses in broadcast frames.

#ifndef IMGSHAREETH
    if (pAdapter->Addr.dwIP)
        pfnEDbgSetOptions(OPT_BROADCAST_FILTERING);
#endif

    return (TRUE);
}

/* OEMEthEnableInts
 *
 *  Turn on HW interrupts.  Return TRUE if interrupts supported, or FALSE
 *  to run in polling mode for all clients.
 */
void
OEMEthEnableInts()
{
    pfnEDbgEnableInts();
}

/* OEMEthDisableInts
 *
 *  Disable HW interrupts.
 */
void
OEMEthDisableInts()
{
    pfnEDbgDisableInts();
}

#ifdef IMGSHAREETH

/* ProcessVMiniSend()
 *
 *      This routine drains the pending VMINI TX.
 * 
 */

void
ProcessVMiniSend(void)
{
    PBYTE   pVMiniData;
    DWORD   dwVMiniDataLength;

    ////////////////////////////////////////////////////////////////////////////
    //  Handle the filter if we need to..
    //
    if (bNewFilter && pfnCurrentPacketFilter)
    {
        bNewFilter = FALSE;     
        pfnCurrentPacketFilter(dwFilter);
    }       

    //
    //  Handle new multicast list..
    //  
    
    if (bNewMulticast && pfnMulticastList)
    {
        bNewMulticast = FALSE;
        pfnMulticastList(
            (PUCHAR)ucMultiAddr,
            dwNoOfEntry);
    }

    ////////////////////////////////////////////////////////////////////////////
    //  Consume all the client packets.
    //
    while (VBridgeKGetOneTxBuffer(&pVMiniData, &dwVMiniDataLength) == TRUE)
    {
        pfnEDbgSendFrame (pVMiniData, dwVMiniDataLength);
        VBridgeKGetOneTxBufferComplete(pVMiniData);
    } 

}   //  ProcessVMiniSend()

#endif

/* OEMEthISR
 *
 *    ISR routine, called by EDBG IST when Ethernet controller interrupts. Also
 *    called in polling mode, to check for received data.

⌨️ 快捷键说明

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