halether.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 960 行 · 第 1/2 页
C
960 行
/*++
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 <drv_glob.h>
#include <platform.h>
#include <oalintr.h>
#ifdef KITL
#include <kitl.h>
#endif
#undef IMGSHAREETH // VMini not in Cedar.
#define pDriverGlobals ((PDRIVER_GLOBALS) DRIVER_GLOBALS_PHYSICAL_MEMORY_START)
extern HARP_BOOT_ARGS *pBootArgs;
//
// 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;
#if IMGSHAREETH
PFN_EDBG_CURRENT_PACKET_FILTER pfnCurrentPacketFilter;
PFN_EDBG_MULTICAST_LIST pfnMulticastList;
#endif
// 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
//
#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 "ARMINT"
#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
ULONG OEMMapIntLogic2SysIntr(ULONG nLogical);
// NOTE: This function only works if i is greater than 0.
// It's only used in this file and we know that
// we never call it with anything less or equal 0.
// It must be modified if you need to extended to
// work on generic integer.
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)
{
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);
}
#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));
DEBUGMSG(1, (TEXT("+OEMEthInit\r\n")));
// Some parameters included in boot args for future use, make sure these aren't set
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;
#ifdef IMGSHAREETH
pfnCurrentPacketFilter= NULL;
pfnMulticastList = NULL;
#endif
EdbgOutputDebugString("INFO: EDBG using SMC9000 controller.\r\n");
break;
case EDBG_ADAPTER_NE2000:
pfnEDbgInit = NE2000Init;
pfnEDbgEnableInts = NE2000EnableInts;
pfnEDbgDisableInts = NE2000DisableInts;
pfnEDbgGetPendingInts = NE2000GetPendingInts;
pfnEDbgGetFrame = NE2000GetFrame;
pfnEDbgSendFrame = NE2000SendFrame;
pfnEDbgReadEEPROM = NE2000ReadEEPROM;
pfnEDbgWriteEEPROM = NE2000WriteEEPROM;
pfnEDbgSetOptions = NE2000SetOptions;
#ifdef IMGSHAREETH
pfnCurrentPacketFilter= Ne2000CurrentPacketFilter;
pfnMulticastList = NE2000MulticastList;
#endif
EdbgOutputDebugString("INFO: EDBG using NE2000 controller.\r\n");
break;
default:
EdbgOutputDebugString("Unsupported debug Ethernet parameters - adapter: %u, IRQ:%u\n",
pBootArgs->ucEdbgAdapterType, pBootArgs->ucEdbgIRQ);
return (FALSE);
}
if (!pfnEDbgInit((BYTE *) (VA_PCI_IO_BASE | 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 );
#ifdef IMGSHAREETH
VBridgeInit();
VBridgeKSetLocalMacAddress((char *)wLocalMAC);
#endif
#ifndef KITL
// Create device name based on Ethernet address
//
CreateDeviceName(&pAdapter->Addr, szDeviceName);
EdbgOutputDebugString("Using device name: %s\n", szDeviceName);
#endif // !KITL.
// 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 = OEMMapIntLogic2SysIntr(pBootArgs->ucEdbgIRQ);
DEBUGMSG(1, (TEXT("INFO: Ethdbg IRQ = 0x%x SYSINTR = 0x%x\r\n"), pBootArgs->ucEdbgIRQ, pAdapter->SysIntrVal));
}
else
#ifndef KITL
pAdapter->SysIntrVal = EDBG_SYSINTR_NOINTR;
#else
pAdapter->SysIntrVal = KITL_SYSINTR_NOINTR;
#endif
// Check the boot parameters to see if our IP address has been configured by
#ifndef KITL
// bootloader, or passed in on loadcepc command line.
//
if ( pBootArgs->EdbgAddr.dwIP != 0 ) {
EdbgOutputDebugString("IP address %s passed in boot args, skipping DHCP\n",inet_ntoa(pBootArgs->EdbgAddr.dwIP));
pAdapter->Addr.dwIP = pBootArgs->EdbgAddr.dwIP;
fGotIP = TRUE;
dwIPState = IPSTATE_GOTIP;
} else {
// Need to get an IP address, either from DHCP or user input
if ( EbootInitDHCP(&pAdapter->Addr) ) {
EdbgOutputDebugString("Error in InitDHCP!\n");
return (FALSE);
}
EdbgOutputDebugString("Wait for DHCP, enter new IP address, or CR to use existing IP: ");
}
if ( pBootArgs->ucLoaderFlags & LDRFL_JUMPIMG ) {
// Already got config from eshell
fGotJumpimg = TRUE;
pAdapter->DHCPLeaseTime = pBootArgs->DHCPLeaseTime;
pAdapter->EdbgFlags = pBootArgs->EdbgFlags;
}
// Loop until we have an IP address and eshell tells us which services are
// configured for Ethernet
while ( !fGotJumpimg ) {
USHORT wLen, wDestPort, wSrcPort, wUDPDataLen, *pwUDPData;
// Once we get our IP address, periodically send BOOTME commands to eshell.
switch (dwIPState) {
case IPSTATE_NONE:
// We haven't gotten an IP address yet. Call into DHCP to see if we
// need to retransmit request, and poll serial port for user input.
EbootDHCPRetransmit(&pAdapter->Addr,NULL,NULL);
if (EbootReadSerialIP(&pAdapter->Addr, &dwSubnetMask)) {
fGotIP = TRUE;
dwIPState = IPSTATE_GOTIP;
EdbgFlags |= EDBG_FLAGS_STATIC_IP;
DHCPLeaseTime = DEFAULT_DHCP_LEASE;
}
break;
case IPSTATE_GOTIP:
// Send a gratuitous ARP (an ARP of our new IP address) to verify that no other
// station is using our IP address.
if (!EbootGratuitousARP(&pAdapter->Addr, RcvBuf)) {
dwIPState = IPSTATE_ARP;
dwNextBootme = OEMEthGetSecs(); // use dwNextBootme for ARP timeout
} else {
EdbgOutputDebugString("EbootGratuitousARP failed\r\n");
}
break;
case IPSTATE_ARP:
if ((OEMEthGetSecs() - dwNextBootme) >= ARP_RESPONSE_WAIT) {
EdbgOutputDebugString("No ARP response in %d seconds, assuming ownership of %s\r\n",
ARP_RESPONSE_WAIT, inet_ntoa(pAdapter->Addr.dwIP));
dwIPState = IPSTATE_ARPED;
dwNextBootme = 0;
}
break;
case IPSTATE_ARPED:
if ((BootmeCnt < MAX_BOOTME_CNT) &&
((BootmeCnt == 0) || (OEMEthGetSecs() >= dwNextBootme))) {
EbootSendBootme(&pAdapter->Addr, 2, 0, PLATFORM_STRING,
szDeviceName, EDBG_CPU_i486, 0);
BootmeCnt++;
dwNextBootme = OEMEthGetSecs() + BOOTME_INTERVAL;
}
break;
case IPSTATE_RETRY:
pAdapter->Addr.dwIP = 0;
EbootInitDHCP(&pAdapter->Addr);
dwIPState = IPSTATE_NONE;
break;
} // switch (dwIPState)
// Get a frame and pass it to the appropriate handler routine
wLen = sizeof(RcvBuf);
if ( pfnEDbgGetFrame(RcvBuf, &wLen) ) {
// Ethernet frame type is in 7th word of buffer
USHORT wFrameType = *(USHORT *)(RcvBuf + 6*sizeof(USHORT));
switch ( ntohs(wFrameType) ) {
case 0x0806:
if (EbootProcessARP(&pAdapter->Addr,RcvBuf) == PROCESS_ARP_RESPONSE) {
switch (dwIPState) {
// Someone has responded to our gratuitous ARP request so they have our IP address.
// We need to retry the DHCP request.
case IPSTATE_ARP:
case IPSTATE_GOTIP:
DHCPRetry++;
if (DHCPRetry > MAX_DHCP_RETRY) {
EdbgOutputDebugString( "Some other station has IP Address: %s !!! Aborting.\r\n", inet_ntoa(pAdapter->Addr.dwIP));
return FALSE;
}
EdbgOutputDebugString( "Some other station has IP Address: %s !!! Retrying.\r\n", inet_ntoa(pAdapter->Addr.dwIP));
dwIPState = IPSTATE_RETRY;
break;
}
}
break;
case 0x0800:
if ( !EbootCheckUDP(&pAdapter->Addr, RcvBuf, &wDestPort, &wSrcPort, &pwUDPData, &wUDPDataLen) ) {
switch (dwIPState) {
case IPSTATE_NONE:
if ( (wDestPort == DHCP_CLIENT_PORT) && (wSrcPort == DHCP_SERVER_PORT) )
EbootProcessDHCP(
&pAdapter->Addr,
&dwSubnetMask,
(BYTE *)pwUDPData,
wUDPDataLen,
&DHCPLeaseTime,
&fGotIP
);
if (fGotIP) {
dwIPState = IPSTATE_GOTIP;
}
break;
case IPSTATE_ARPED:
pCfgData = NULL;
if ( EbootProcessEDBG(&pAdapter->Addr,&EshellHostAddr,RcvBuf,pwUDPData, wUDPDataLen, &fGotJumpimg, &pCfgData) ) {
if ( pCfgData ) {
if ( pCfgData->Flags & EDBG_FL_DBGMSG ) {
EdbgOutputDebugString("Enabling debug messages over Ethernet, IP: %s, port:%u\n",
inet_ntoa(pCfgData->DbgMsgIPAddr),pCfgData->DbgMsgPort);
memcpy(&pBootArgs->DbgHostAddr.wMAC,&EshellHostAddr.wMAC,6);
pBootArgs->DbgHostAddr.dwIP = pCfgData->DbgMsgIPAddr;
pBootArgs->DbgHostAddr.wPort = pCfgData->DbgMsgPort;
}
if ( pCfgData->Flags & EDBG_FL_PPSH ) {
EdbgOutputDebugString("Enabling CESH over Ethernet, IP: %s, port:%u\n",
inet_ntoa(pCfgData->PpshIPAddr),pCfgData->PpshPort);
memcpy(&pBootArgs->CeshHostAddr.wMAC,&EshellHostAddr.wMAC,6);
pBootArgs->CeshHostAddr.dwIP = pCfgData->PpshIPAddr;
pBootArgs->CeshHostAddr.wPort = pCfgData->PpshPort;
}
if ( pCfgData->Flags & EDBG_FL_KDBG ) {
EdbgOutputDebugString("Enabling KDBG over Ethernet, IP: %s, port:%u\n",
inet_ntoa(pCfgData->KdbgIPAddr),pCfgData->KdbgPort);
memcpy(&pBootArgs->KdbgHostAddr.wMAC,&EshellHostAddr.wMAC,6);
pBootArgs->KdbgHostAddr.dwIP = pCfgData->KdbgIPAddr;
pBootArgs->KdbgHostAddr.wPort = pCfgData->KdbgPort;
}
pBootArgs->ucEshellFlags = pCfgData->Flags;
}
}
break;
}
}
break;
default:
break;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?