halether.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 325 行
C
325 行
/*
Copyright(c) 1998,1999 SIC/Hitachi,Ltd.
Module Name:
halether.c
Revision History:
26th April 1999 Released
*/
#include <windows.h>
#include <nkintr.h>
#include <ethdbg.h>
#include <halether.h>
#include "platform.h"
#include "drv_glob.h"
#include "oalintr.h"
#define pDriverGlobals ((PDRIVER_GLOBALS) DRIVER_GLOBALS_PHYSICAL_MEMORY_START)
static BOOL ReadEEPROMData(DWORD *pdwIP, DWORD *pdwSubnetMask);
#define PF_ETHER_BASE ETHERNET_BASE
// The kernel exports...
#ifdef AddrCurMSec
// Some kernels export a pointer to the CurMSec variable.
static volatile DWORD * pCurMSec = (volatile DWORD *) AddrCurMSec;
#else
extern volatile DWORD CurMSec;
static volatile DWORD * pCurMSec = &CurMSec;
#endif
/* OEMEthInit
*
* Initialization routine - called from EdbgInit() to perform platform specific
* HW init. The Odo platform uses a debug board based on the SMC 91C94 Ethernet
* controller.
*
* Return Value:
* Return TRUE if init is successful, FALSE if error.
*/
BOOL
OEMEthInit(
EDBG_ADAPTER *pAdapter) // OUT - Pointer to adapter info structure. Filled in with address
// and SYSINTR info.
{
// First, reset the 91C94
// WRITE_REGISTER_USHORT( SMC_HARD_RESET_REG, 1 );
// WRITE_REGISTER_USHORT( SMC_HARD_RESET_REG, 0 );
// SMCInit will time out and return error if the debug Ethernet board is not present.
// Otherwise, the HW will be initialized and our address and subnet mask will be filled
// in (read from the on chip serial EEPROMs).
if (SMCInit((BYTE *) PF_ETHER_BASE,1,pAdapter->Addr.wMAC)) {
EdbgOutputDebugString("EDBG_PHYSICAL_MEMORY_START = %Xh:\r\n", EDBG_PHYSICAL_MEMORY_START);
// 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.
// SMCSetOptions(OPT_BROADCAST_FILTERING);
// Read the IP address and subnet mask from the unused range 0x23-0x26 of the serial EEPROM.
// This is stored by eboot, which gets it either from DHCP or user input.
if (!ReadEEPROMData(&pAdapter->Addr.dwIP, &pDriverGlobals->eth.SubnetMask)) {
EdbgOutputDebugString("!OEMEthInit: Error reading IP config from SMC EEPROM\n");
goto ErrRet;
}
EdbgOutputDebugString("Read IP config from EEPROM:\r\n");
EdbgOutputDebugString(" IP Address: %s,", inet_ntoa(pAdapter->Addr.dwIP));
EdbgOutputDebugString(" netmask: %s\r\n", inet_ntoa(pDriverGlobals->eth.SubnetMask));
// Copy our address into driver globals (new versions of eboot (2.0+) will do this for us,
// so we won't even need to read the EEPROM data, but leave this in to work with old versions).
memcpy(&pDriverGlobals->eth.PlatformAddr, &pAdapter->Addr, sizeof(EDBG_ADDR));
// Fill in our SYSINTR value for the EDBG subsystem
pAdapter->SysIntrVal = SYSINTR_ETHER;
// Fill in our DHCP IP lease time for the EDBG subsystem
pAdapter->DHCPLeaseTime = pDriverGlobals->eth.DHCPLeaseTime;
pAdapter->EdbgFlags = pDriverGlobals->eth.EdbgFlags;
#if 0 // (SH_PLATFORM == PLATFORM_BIGSUR)
// For BigSur platform, somehow bits 1,2 of CONFIG register become 11.
// These bits should be 00 to use INTR0.
SelectBank(BANK1);
WriteWord(CONFIG, (0xFFF9 & ReadWord(CONFIG)) );
#endif // (SH_PLATFORM == PLATFORM_BIGSUR)
// Fill in our SYSINTR value for the EDBG subsystem
// To use polling mode, put 0 as int.id
#if (SH_PLATFORM == PLATFORM_BIGSUR)
pAdapter->SysIntrVal = 0; // SYSINTR_ETHER;
#else // (SH_PLATFORM == PLATFORM_BIGSUR)
pAdapter->SysIntrVal = SYSINTR_ETHER;
#endif // (SH_PLATFORM == PLATFORM_BIGSUR)
return TRUE;
}
ErrRet:
pDriverGlobals->eth.etherEnabled = 0;
pDriverGlobals->eth.etherFlags = 0;
return FALSE;
}
// Read IP address and netmask from serial EEPROM on the SMC board (stored from the
// last time we got this info from user or DHCP).
static BOOL
ReadEEPROMData(DWORD *pdwIP, DWORD *pdwSubnetMask)
{
UINT16 wIPH, wIPL, wSMH, wSML;
if (!SMCReadEEPROM(0x23,&wIPL) ||
!SMCReadEEPROM(0x24,&wIPH) ||
!SMCReadEEPROM(0x25,&wSML) ||
!SMCReadEEPROM(0x26,&wSMH))
return FALSE;
*pdwIP = ((ULONG)wIPH << 16) | wIPL;
*pdwSubnetMask = ((ULONG)wSMH << 16) | wSML;
return TRUE;
}
/* OEMEthEnableInts
*
* Turn on HW interrupts.
*/
void
OEMEthEnableInts()
{
SMCEnableInts();
}
/* OEMEthDisableInts
*
* Disable HW interrupts.
*/
void
OEMEthDisableInts()
{
SMCDisableInts();
}
/* OEMEthISR
*
* ISR routine, called by EDBG IST when Ethernet controller interrupts. Also
* called in polling mode, to check for received data.
*
* Return Value:
* Return bitmask indicating which interrupts are pending. Currently, the ones
* that EDBG cares about are the following (others should be handled internally):
* INTR_TYPE_RX -- Receive interrupt. IST will call into GetFrame to read data.
*/
DWORD
OEMEthISR()
{
return SMCGetPendingInterrupts();
}
/* OEMEthGetFrame
*
* Check to see if a frame has been received, and if so copy to buffer. An optimization
* which may be performed in the Ethernet driver is to filter out all received broadcast
* packets except for ARPs. This is done in the SMC9000 driver.
*
* Return Value:
* Return TRUE if frame has been received, FALSE if not.
*/
BOOL
OEMEthGetFrame(
BYTE *pData, // OUT - Receives frame data
UINT16 *pwLength) // IN - Length of Rx buffer
// OUT - Number of bytes received
{
return SMCGetFrame(pData, pwLength);
}
/* OEMEthSendFrame
*
* Send Ethernet frame.
*
* Return Value:
* TRUE if frame successfully sent, FALSE otherwise.
*/
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 (!SMCSendFrame(pData, dwLength))
return TRUE;
else
EdbgOutputDebugString("!OEMEthSendFrame failure, retry %u\n",retries);
}
return FALSE;
}
/* OEMEthQueryClientInfo
*
* Return address information for default ethernet services, plus a buffer pool to use
* for formatting and receiving EDBG packets (single buffer pool specified, divided in
* two for Rx and Tx buffers). By specifying a smaller window size, less memory can be
* used (but the protocol will be less efficient...). The amount of memory required per
* client is (2*WindowSize*1500) bytes.
*
* For Odo, we reserve 3 buffer pools worth of memory in the bib file, based on the IMGEBOOT
* flag being set.
*
* Return Value:
* If client can be configured, return TRUE and fill in addressing and buffer info. Otherwise
* return FALSE. For Odo, configure clients based on the flags set by Eshell (received in the
* JUMPIMG command by eboot, and placed in the uninitalized driver globals section).
*/
BOOL
OEMEthQueryClientInfo(
UCHAR Service, // IN - Service ID (one of EDBG_SVC defs from ethdbg.h).
EDBG_ADDR *pPeerAddr, // OUT -Filled in with the peer Ether/IP address and UDP port number.
PUCHAR pWindowSize, // OUT -Filled in with the client window size.
PUCHAR *ppBufferPool) // OUT -Filled in with the packet buffer pool address.
{
// We use the default window size (8) for all services
*pWindowSize = EDBG_WINDOW_SIZE;
switch (Service)
{
// Check the flag in driver globals (set by eboot when it receives the JUMPIMG command)
case EDBG_SVC_DBGMSG:
if (! (pDriverGlobals->eth.etherFlags & EDBG_FL_DBGMSG)) {
return FALSE;
}
memcpy(pPeerAddr, &pDriverGlobals->eth.DbgHostAddr,sizeof(EDBG_ADDR));
*ppBufferPool = (UCHAR *)EDBG_PHYSICAL_MEMORY_START;
break;
case EDBG_SVC_PPSH:
if (! (pDriverGlobals->eth.etherFlags & EDBG_FL_PPSH)) {
return FALSE;
}
memcpy(pPeerAddr, &pDriverGlobals->eth.PpshHostAddr,sizeof(EDBG_ADDR));
*ppBufferPool = (UCHAR *)EDBG_PHYSICAL_MEMORY_START + EDBG_DFLT_BUFFER_POOL_SIZE;
break;
case EDBG_SVC_KDBG:
if (! (pDriverGlobals->eth.etherFlags & EDBG_FL_KDBG)) {
return FALSE;
}
memcpy(pPeerAddr, &pDriverGlobals->eth.KdbgHostAddr,sizeof(EDBG_ADDR));
*ppBufferPool = (UCHAR *)EDBG_PHYSICAL_MEMORY_START + 2*EDBG_DFLT_BUFFER_POOL_SIZE;
break;
default:
return FALSE;
}
return TRUE;
}
BOOL
ether_KFileTimeToSystemTime(
const FILETIME *lpft,
LPSYSTEMTIME lpst
)
{
DWORD dwBase;
ULONG Minutes;
ULONG Seconds;
//
// Take 32-bits of the 64 that we care about. New counter rate is 78125/sec.
//
dwBase = ((lpft->dwHighDateTime << 25) & 0xFE000000) |
((lpft->dwLowDateTime >> 7) & 0x01FFFFFF);
Seconds = dwBase / 78125;
lpst->wSecond = (WORD)(Seconds % 60);
Minutes = Seconds / 60;
lpst->wMinute = (WORD)(Minutes % 60);
lpst->wHour = (WORD)(Minutes / 60);
//
// Okay to wrap on day. Don't care about milliseconds.
//
lpst->wMilliseconds = 0;
lpst->wYear = 1998;
lpst->wMonth = 1;
lpst->wDay = 1;
// RETAILMSG(1, (TEXT("eKFTTST : %d:%d:%d\r\n"), lpst->wHour, lpst->wMinute, lpst->wSecond));
return(TRUE);
}
/* OEMEthGetSecs
*
* Return a count of seconds from some arbitrary time (the absolute value is not important,
* so long as it increments appropriately).
*/
#define FAKE_ITER 20000 // MUST BE >= 1000
DWORD OEMEthGetSecs( void ) {
static DWORD dwFakeMSec = FAKE_ITER;
static BOOL fRTCStarted = FALSE;
if (!fRTCStarted) {
if (0 == *pCurMSec) {
return ++dwFakeMSec / FAKE_ITER;
}
fRTCStarted = TRUE;
dwFakeMSec /= (FAKE_ITER/1000); // serve as the base to keep time continuous
}
return (dwFakeMSec + *pCurMSec) / 1000;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?