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 + -
显示快捷键?