📄 halether.c
字号:
*
* 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()
{
#ifdef IMGSHAREETH
ProcessVMiniSend();
#endif
return (pfnEDbgGetPendingInts());
}
/* 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 both the SMC9000 and NE2000 drivers.
*
* 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
{
#ifdef IMGSHAREETH
BOOL bStatus;
BOOL bTaken;
UINT16 wOriginalLength;
ProcessVMiniSend();
//
// ne2000 ether library has a minor problem of returning incorrect
// Ethernet packet size if we give it buffer > max Ether MTU.
// So, pass in only ether MTU if the incoming buffer is greater
// than ether MTU.
//
if (*pwLength >= 1514)
wOriginalLength = 1514;
else
wOriginalLength = *pwLength;
while (1)
{
*pwLength = wOriginalLength;
bStatus = pfnEDbgGetFrame(pData, pwLength);
if (bStatus)
{
VBridgeKIndicateOneRxBuffer(pData, *pwLength, FALSE, &bTaken);
if (!bTaken)
return bStatus;
}
else
break;
}
return (FALSE);
#else
return (pfnEDbgGetFrame(pData, pwLength));
#endif
}
/* 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;
while ( retries++ < 4 ) {
if ( !pfnEDbgSendFrame(pData, dwLength) )
{
#ifdef IMGSHAREETH
ProcessVMiniSend();
#endif
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.
*
* 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 ( ! (pBootArgs->ucEshellFlags & EDBG_FL_DBGMSG) ) {
return (FALSE);
}
memcpy(pPeerAddr, &pBootArgs->DbgHostAddr,sizeof(EDBG_ADDR));
*ppBufferPool = (UCHAR *)EDBG_PHYSICAL_MEMORY_START;
break;
case EDBG_SVC_PPSH:
if ( ! (pBootArgs->ucEshellFlags & EDBG_FL_PPSH) ) {
return (FALSE);
}
memcpy(pPeerAddr, &pBootArgs->CeshHostAddr,sizeof(EDBG_ADDR));
*ppBufferPool = (UCHAR *)EDBG_PHYSICAL_MEMORY_START + EDBG_DFLT_BUFFER_POOL_SIZE;
break;
case EDBG_SVC_KDBG:
if ( ! (pBootArgs->ucEshellFlags & EDBG_FL_KDBG) ) {
return (FALSE);
}
memcpy(pPeerAddr, &pBootArgs->KdbgHostAddr,sizeof(EDBG_ADDR));
*ppBufferPool = (UCHAR *)EDBG_PHYSICAL_MEMORY_START + 2*EDBG_DFLT_BUFFER_POOL_SIZE;
break;
default:
return (FALSE);
}
return (TRUE);
}
/* OEMEthGetSecs
*
* Return a count of seconds from some arbitrary time (the absolute value is not important,
* so long as it increments appropriately). Read this value from the RTC values in CMOS. Note
* that reading the CMOS requires multiple register operations, so this function must be called
* only when scheduling is disabled.
*/
static DWORD dwLastTime; // For making sure we aren't running backward
extern BOOL fRTCInit;
extern BOOL Bare_GetRealTime(LPSYSTEMTIME lpst);
extern volatile DWORD CurMSec;
DWORD
OEMEthGetSecs()
{
SYSTEMTIME st;
DWORD dwRet;
static DWORD dwBias;
if (!fRTCInit) {
Bare_GetRealTime( &st );
dwRet = ((60UL * (60UL * (24UL * (31UL * st.wMonth + st.wDay) + st.wHour) + st.wMinute)) + st.wSecond);
dwBias = dwRet;
} else {
dwRet = (CurMSec/1000) + dwBias;
}
if (dwRet < dwLastTime) {
EdbgOutputDebugString("! Time went backwards (or wrapped): cur: %u, last %u\n",
dwRet,dwLastTime);
}
dwLastTime = dwRet;
return (dwRet);
}
#ifdef IMGSHAREETH
//
// These functions are only needed if vmini is in.
// i.e. if IMGSHAREETH is set.
//
////////////////////////////////////////////////////////////////////////////////
// OEMEthSetFilter()
//
// Description:
//
// This function is used by VMINI to inform the underlying ethernet
// library on the filtering mode it requires.
//
// Arguments:
//
// pdwRequestedFilter :: The requested filter.
// Identical constants have been added in
// that mimics NDIS_PACKET_TYPE_XXX constants.
//
// Return Value:
//
// TRUE :: if we can set the filter.
// FALSE :: otherwise..
//
//
// Note:
//
// As a minimum to get vmini to work, we need to support
// PACKET_TYPE_DIRECTED
// PACKET_TYPE_BROADCAST
//
//
BOOL
OEMEthCurrentPacketFilter(PDWORD pdwRequestedFilter)
{
if (pfnCurrentPacketFilter)
{
EdbgOutputDebugString(
"OEMEthCurrentPacketFilter set to [0x%x]\r\n",
*pdwRequestedFilter);
//
// Note that we can't do it immediately here, since we are called
// by user mode code.
// So what we do is to set the flag here for the kernel mode code
// to pick up.
//
dwFilter = *pdwRequestedFilter;
bNewFilter = TRUE;
return TRUE;
}
else
{
//
// Eth driver does not yet support filter setting
// So if it is PACKET_TYPE_DIRECTED, PACKET_TYPE_MULTICAST,
// PACKET_TYPE_BROADCAST, we just indicate that we are ok with it.
// Since EDBG will run in this mode anyway..
//
DWORD dwInherentlySupported =
PACKET_TYPE_MULTICAST |
PACKET_TYPE_DIRECTED |
PACKET_TYPE_BROADCAST;
if (*pdwRequestedFilter == dwInherentlySupported)
return TRUE;
else
return FALSE;
}
} // OEMEthCurrentPacketFilter()
////////////////////////////////////////////////////////////////////////////////
// OEMEthMulticastList()
//
// Description:
//
// This function is used by VMINI to inform the underlying ethernet
// library on multicast addresses that winsock app is interested in.
//
// Arguments:
//
// pucMulticastAddressList :: Pointer to an array of multicast addresses.
// dwNoOfAddresses :: Number of addresses passed in to us.
//
// Return Value:
//
// TRUE :: if we can set the underlying edbg ethernet libary to start
// filtering on these multicast addresses.
//
// FALSE :: otherwise.
//
BOOL
OEMEthMulticastList(PUCHAR pucMulticastAddressList, DWORD dwNoOfAddresses)
{
//
// This platform does not support multicast yet..
//
DWORD i;
BOOL bReturnValue;
EdbgOutputDebugString(
"OEMEthMulticastList():: No of Entries [%d]\r\n",
dwNoOfAddresses);
//
// We can check how many entries an adapter that are attached to
// can support.
// To make things simple, we just assume we can support minimum that
// vmini thinks we support (i.e. 8).
//
if (dwNoOfAddresses > 8)
{
//
// This should never happen, since VMINI is known to support
// 8 entries only...
//
EdbgOutputDebugString(
"Multicast list requeste [%d] > 8 !!!\r\n",
dwNoOfAddresses);
return FALSE;
}
//
// 8 entries, 6 bytes each..
//
memset(
ucMultiAddr,
0x00,
8 * 6);
//
// 6 bytes per entry..
//
memcpy(
ucMultiAddr,
pucMulticastAddressList,
dwNoOfAddresses * 6);
for (i = 0 ; i < dwNoOfAddresses ; i++)
{
EdbgOutputDebugString(
"[%d] : %x - %x - %x - %x - %x - %x\r\n",
i,
pucMulticastAddressList[6*i+0],
pucMulticastAddressList[6*i+1],
pucMulticastAddressList[6*i+2],
pucMulticastAddressList[6*i+3],
pucMulticastAddressList[6*i+4],
pucMulticastAddressList[6*i+5]);
}
if (pfnMulticastList)
{
//
// We are in KernelIOCTL call, some h/w requires the
// setting of the MULTICAST addresses in interrupt service routine.
// So we will do it later, and mark it so the ISR will know about it..
// Note:
// Order is important here. Don't set bNewMulticast to true until
// all the entries and the dwNoOfEntry are properly set up.
// This is because we can be switched out in the middle of
/// KernelIOCTL!!
//
dwNoOfEntry = dwNoOfAddresses;
bNewMulticast = TRUE;
bReturnValue = TRUE;
}
else
bReturnValue = FALSE;
EdbgOutputDebugString(
"OEMEthMulticastList returning [%d]\r\n",
bReturnValue);
return bReturnValue;
} // OEMEthMulticastList()
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -