halether.c

来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 977 行 · 第 1/3 页

C
977
字号
/*++
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-2000 Microsoft Corporation.  All rights reserved.

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 "pc.h"
#include "bootarg.h"
#include "oalintr.h"
#include "rtl8139.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_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 EDBG_PHYSICAL_MEMORY_START (0x801DC000)
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

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))

#define PLATFORM_STRING "CEPC"

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

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;
}

static void
CreateDeviceName(EDBG_ADDR *pMyAddr, char *szBuf)
{
    int i;
    DWORD dwUpperMAC = UpperDWFromMAC(pMyAddr);

    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);
}



/* InitDebugEther
 *
 *   Initialize debug Ether support for platform if requested (flag must be
 *   set in boot parameters area).  Called from OEMInit().
 */
void
InitDebugEther()
{
    BOOT_ARGS *pBootArgs = (BOOT_ARGS *) ((ULONG)(*(PBYTE *)BOOT_ARG_PTR_LOCATION) | 0x80000000);

    // Check for magic number to make sure parameter area is valid.
    if ( (pBootArgs->dwSig == BOOTARG_SIG) && (pBootArgs->ucLoaderFlags & LDRFL_USE_EDBG) ) {
        OEMWriteDebugString(TEXT("Using Debug Ethernet card\n"));

        // Read debug zone mask from boot args
        if ( pBootArgs->dwEdbgDebugZone )
            EdbgDebugZone = pBootArgs->dwEdbgDebugZone;

        // EdbgInit() will call our OEMEthInit routine to initialize debug Ether HW.
        if ( ( (pBootArgs->ucEshellFlags & EDBG_FL_DBGMSG) ||
        	  (pBootArgs->ucEshellFlags & EDBG_FL_PPSH) ||
        	  (pBootArgs->ucEshellFlags & EDBG_FL_KDBG) ) &&
        	EdbgInit() ) {
            // Attempt to configure debug services over ethernet.  SetKernelCommDev will block
            // (calling EdbgRegisterDfltClient) until the desktop application is started, and
            // will set up the necessary kernel hooks to route data to the peer.
            if ( (pBootArgs->ucEshellFlags & EDBG_FL_DBGMSG) && 
                 SetKernelCommDev(KERNEL_SVC_DBGMSG,KERNEL_COMM_ETHER) ) {
                EdbgOutputDebugString("Switched to ethernet for debug messages, host: %s, port: %d\r\n",
                                      inet_ntoa(pBootArgs->DbgHostAddr.dwIP),
                                      ntohs(pBootArgs->DbgHostAddr.wPort));
            }
            if ( (pBootArgs->ucEshellFlags & EDBG_FL_PPSH) &&
                 SetKernelCommDev(KERNEL_SVC_PPSH,KERNEL_COMM_ETHER) ) {
                EdbgOutputDebugString("Switched to ethernet for PPSH, host: %s, port: %d\r\n",
                                      inet_ntoa(pBootArgs->CeshHostAddr.dwIP),
                                      ntohs(pBootArgs->CeshHostAddr.wPort));
            }
            if ( (pBootArgs->ucEshellFlags & EDBG_FL_KDBG) &&
                 SetKernelCommDev(KERNEL_SVC_KDBG,KERNEL_COMM_ETHER) ) {
                EdbgOutputDebugString("Switched to ethernet for KDBG, host: %s, port: %d\r\n",
                                      inet_ntoa(pBootArgs->KdbgHostAddr.dwIP),
                                      ntohs(pBootArgs->KdbgHostAddr.wPort));
            }
        } else
            OEMWriteDebugString(TEXT("EdbgInit failed, not using debug Ethernet services\r\n"));
    }
}


#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)
{
    BOOL fGotIP=FALSE, fGotJumpimg=FALSE;
    EDBG_ADDR EshellHostAddr;
    EDBG_OS_CONFIG_DATA *pCfgData;
    int BootmeCnt=0;
    DWORD dwSubnetMask;
    DWORD dwNextBootme;  // Time at which to send the next BOOTME
    char szDeviceName[EDBG_MAX_DEV_NAMELEN];
    DWORD dwIPState = IPSTATE_NONE;
    int DHCPRetry=0;
    DWORD DHCPLeaseTime;
    DWORD EdbgFlags = 0;

    memset(&EshellHostAddr,0,sizeof(EDBG_ADDR));

    pBootArgs = (BOOT_ARGS *) ((ULONG)(*(PBYTE *)BOOT_ARG_PTR_LOCATION) | 0x80000000);
    
    switch (pBootArgs->ucEdbgAdapterType) {
    case EDBG_ADAPTER_SMC9000:
        pfnEDbgInit           = SMCInit;
        pfnEDbgEnableInts     = SMCEnableInts;     
        pfnEDbgDisableInts    = SMCDisableInts;    
        pfnEDbgGetPendingInts = SMCGetPendingInterrupts; 
        pfnEDbgGetFrame       = SMCGetFrame;       
        pfnEDbgSendFrame      = SMCSendFrame;      
        pfnEDbgReadEEPROM     = SMCReadEEPROM;     
        pfnEDbgWriteEEPROM    = SMCWriteEEPROM;
        pfnEDbgSetOptions     = SMCSetOptions;
//		pfnCurrentPacketFilter= NULL;
//		pfnMulticastList	  = NULL;

        break;

    case EDBG_ADAPTER_NE2000:
        pfnEDbgInit           = NE2000Init;
        pfnEDbgEnableInts     = NE2000EnableInts;     
        pfnEDbgDisableInts    = NE2000DisableInts;    
        pfnEDbgGetPendingInts = NE2000GetPendingInts; 
        pfnEDbgGetFrame       = NE2000GetFrame;       
        pfnEDbgSendFrame      = NE2000SendFrame;      
        pfnEDbgReadEEPROM     = NE2000ReadEEPROM;     
        pfnEDbgWriteEEPROM    = NE2000WriteEEPROM;    
        pfnEDbgSetOptions     = NE2000SetOptions;
//		pfnCurrentPacketFilter= Ne2000CurrentPacketFilter;
//		pfnMulticastList	  = NE2000MulticastList;
        break;

    case EDBG_ADAPTER_OEM:
    {       
        pfnEDbgInit           = RTL8139Init;
        pfnEDbgEnableInts     = RTL8139EnableInts;     
        pfnEDbgDisableInts    = RTL8139DisableInts;    
        pfnEDbgGetPendingInts = RTL8139GetPendingInts; 
        pfnEDbgGetFrame       = RTL8139GetFrame;       
        pfnEDbgSendFrame      = RTL8139SendFrame;      
        pfnEDbgReadEEPROM     = RTL8139ReadEEPROM;     
        pfnEDbgWriteEEPROM    = RTL8139WriteEEPROM;    
        pfnEDbgSetOptions     = RTL8139SetOptions;
//		pfnCurrentPacketFilter= NULL;
//		pfnMulticastList	  = NULL;

        ////////////////////////////////////////////////////////////////////
        //  Okay, for RTL we need to initialize the DMA buffer first..
        //
        if (!RTL8139InitDMABuffer(
                0x80200000,
                0x20000))               
        {
            EdbgOutputDebugString("Failed RTL8139InitDMABuffer()..\r\n");
            return FALSE;
        }
        break;
        
    }

    default:
        EdbgOutputDebugString("Unsupported debug Ethernet parameters - adapter: %u, IRQ:%u\n",
                              pBootArgs->ucEdbgAdapterType, pBootArgs->ucEdbgIRQ);
        return (FALSE);
    }


/*

⌨️ 快捷键说明

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