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