halether.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 977 行 · 第 1/3 页
C
977 行
// Nice utils to blast the TX/RX of the NIC..
{
unsigned char pBootMe[] =
{
0x00, 0xb0, 0xd0, 0x21, 0xaf, 0x45, 0x00, 0xd0, 0xc9, 0x09, 0x78, 0x72, 0x08, 0x00, 0x45, 0x00,
0x00, 0x53, 0x04, 0x00, 0x00, 0x00, 0x40, 0x11, 0x41, 0xe9, 0x9d, 0x38, 0x97, 0x79, 0xff, 0xff,
0xff, 0xff, 0x03, 0xd4, 0x03, 0xd4, 0x00, 0x3f, 0x91, 0xf5, 0x45, 0x44, 0x42, 0x47, 0xff, 0x01,
0x01, 0x00, 0x02, 0x00, 0x00, 0xc0, 0xf0, 0x2a, 0xb0, 0x79, 0x9d, 0x38, 0x97, 0x79, 0x41, 0x4c,
0x54, 0x4f, 0x4f, 0x4e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
0x4c, 0x54, 0x4f, 0x4f, 0x4e, 0x41, 0x34, 0x35, 0x31, 0x37, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00,
0x25
};
pfnEDbgInit((BYTE *) pBootArgs->dwEdbgBaseAddr,1,pAdapter->Addr.wMAC);
{
int i;
BYTE pbData[1536];
USHORT usSize;
for (i = 0 ; i < 10000000 ; i++)
while(1)
{
pfnEDbgSendFrame(pBootMe, sizeof(pBootMe));
usSize = 1536;
pfnEDbgGetFrame(pbData, &usSize);
}
}
return (FALSE);
}
*/
if (!pfnEDbgInit((BYTE *) 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 );
#if IMGSHAREETH
VBridgeInit();
VBridgeKSetLocalMacAddress((char *)wLocalMAC);
#endif
// Create device name based on Ethernet address
CreateDeviceName(&pAdapter->Addr, szDeviceName);
EdbgOutputDebugString("Using device name: %s\n", szDeviceName);
// 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 = MapIrq2SysIntr(pBootArgs->ucEdbgIRQ);
EdbgOutputDebugString("Using interrupt: [%d] and SYSINTR_XXX [%d]\r\n",
pBootArgs->ucEdbgIRQ,
pAdapter->SysIntrVal);
}
else
{
EdbgOutputDebugString("EDBG uses poll mode.\r\n");
pAdapter->SysIntrVal = EDBG_SYSINTR_NOINTR;
}
// Check the boot parameters to see if our IP address has been configured by
// 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;
}
}
}
if (!( pBootArgs->ucLoaderFlags & LDRFL_JUMPIMG )) {
pAdapter->DHCPLeaseTime = DHCPLeaseTime;
pAdapter->EdbgFlags = EdbgFlags;
}
// 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. Note that we cannot turn this option on until DHCP is
// done processing, since some DHCP servers return responses in broadcast frames.
pfnEDbgSetOptions(OPT_BROADCAST_FILTERING);
return (TRUE);
}
/* OEMEthEnableInts
*
* Turn on HW interrupts. Return TRUE if interrupts supported, or FALSE
* to run in polling mode for all clients.
*/
void
OEMEthEnableInts()
{
pfnEDbgEnableInts();
}
/* OEMEthDisableInts
*
* Disable HW interrupts.
*/
void
OEMEthDisableInts()
{
pfnEDbgDisableInts();
}
/* 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()
{
#if IMGSHAREETH
{
PBYTE pVMiniData;
DWORD dwVMiniDataLength;
////////////////////////////////////////////////////////////////////////////
// Handle the filter if we need to..
//
if (bNewFilter && pfnCurrentPacketFilter)
{
bNewFilter = FALSE;
pfnCurrentPacketFilter(dwFilter);
}
////////////////////////////////////////////////////////////////////////////
// Consume all the client packets.
//
while (VBridgeKGetOneTxBuffer(&pVMiniData, &dwVMiniDataLength) == TRUE)
{
pfnEDbgSendFrame (pVMiniData, dwVMiniDataLength);
VBridgeKGetOneTxBufferComplete(pVMiniData);
}
}
#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.
*
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?