halether.c

来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 848 行 · 第 1/2 页

C
848
字号
/*++
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, 1996, 1997  Microsoft Corporation

Module Name:  
    halether.c
    
Abstract:

    Platform specific code for debug ethernet services (debug messages,
    kernel debugger, text shell (CESH)).  These functions are all called
    from ethdbg.lib.  They are non-preemptible, and cannot make any system calls.

Functions:


Notes: 

--*/

//	FOR MIPS ONLY.
//	Not sure yet ethernet support for SH4

#ifdef MIPS



#include <windows.h>
#include <nkintr.h>
#include <oalintr.h>
#include <alt_def.h>
#include "ethernet.h"
#include <oalio.h>
#include <eglobal.h>
#include <vrc5074.h>


// Needed for the Cedar BSP since halether.h can't be updated.
//
BOOL DEC21140InitDMABuffer(DWORD dwStartAddress, DWORD dwSize);
BOOL DEC21140SetMACAddress(USHORT MacAddr[3]);

// No Vmini support in Cedar.
#undef IMGSHAREETH


#ifdef IMGSHAREETH
BOOL    bNewFilter = FALSE;    // User mode --> Kernel mode to set new filter.
DWORD   dwFilter;              //      The filter..
PFN_EDBG_CURRENT_PACKET_FILTER  pfnCurrentPacketFilter;
PFN_EDBG_MULTICAST_LIST                 pfnMulticastList;
#endif // IMGSHAREETH.


/////////////////////////////////////////////////////////////////////////////////
//	Depending on which NIC deteceted, we'll update this table accordingly...
//
typedef	struct _NIC_FTBL
{
	BOOL	(*NIC_Init)					(BYTE *pbBaseAddress, ULONG	dwMemOffset, USHORT MacAddr[3]);
	void	(*NIC_EnableInts)			(void);
	void	(*NIC_DisableInts)			(void);
	DWORD	(*NIC_GetPendingInts)		(void);
	UINT16	(*NIC_GetFrame)				(BYTE *pbData, UINT16 *pwLength);
	UINT16	(*NIC_OtherGetFrame)		(BYTE *pbData, UINT16 *pwLength);
	UINT16	(*NIC_SendFrame)			(BYTE *pbData, DWORD dwLength);
	BOOL	(*NIC_InitDMABuffer)		(DWORD dwStartAddress, DWORD dwSize);
	DWORD	(*NIC_QueryBufferSize)		(void);
	DWORD	(*NIC_QueryDescriptorSize)	(void);
} NIC_FTBL, *PNIC_FTBL;


NIC_FTBL	DEC21140FTbl =
{
	DEC21140Init,
	DEC21140EnableInts,
	NULL,
	DEC21140GetPendingInts,
	NULL,
	DEC21140GetFrame,
	DEC21140SendFrame, 
	DEC21140InitDMABuffer,
	DEC21140QueryBufferSize,
	DEC21140QueryDescriptorSize
};

NIC_FTBL    NE2000FTbl =
{
    NE2000Init,
    NE2000EnableInts,
    NE2000DisableInts,
    NE2000GetPendingInts,
    NE2000GetFrame,
    NULL,
    NE2000SendFrame,
    NULL,               // NE2000 Does not need these functions...
    NULL,
    NULL
};

PNIC_FTBL		NIC_FTbl;
BOOL			bDecChip = FALSE;


/////////////////////////////////////////////////////////////////////////////////
// WARNING --- WARNING --- WARNING ---
// Still one peculiarity unresolved.
// If EdbgOutputDebugString() is called early during the startup, it will cause the
// whole system to freeze.
// Investigation shows that it's frozen in the OEMWriteDebugByte() where it
// loops forever waiting for "tx holding register empty" in the UART.
// 
// Hence all reference to EdbgOutputDebugString() in NE2000.c and hal are redirected
// to local EdbgOutputDebugString which will simply use OutputDebugString() instead
// of checking whether or not it should pump to ethernet (which is what actually
// done in ethdbg.lib).   [Note that if the ethdbg itself uses the function, we
// can't prevent it from here...]
//
// So here we go...
// ALL EdbgOutputDebugString() WILL GO OUT SERIAL !!!
// The target audience will just be those that trouble shooting the HAL, and NE2000 
// library.   No one else should be affected.
// 
// 

static void vOutputFormatString(const UCHAR *sz, va_list vl);

void
localEdbgOutputDebugString(const char *sz, ...)
{
	;
	// Do nothing !!!    
}

void
localDEBUGMSG (const char *sz, ...)
{
	;
	// Do nothing !!!

}


USHORT wLocalMAC[3]; // Global, so that oemioctl handling for IOCTL_HAL_GET_UUID can
                      // return our MAC address as a form of unique ID

// 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)
{
    DWORD dwUpperMAC = UpperDWFromMAC(pMyAddr);

    strcpy(szBuf,PLATFORM_STRING);
    szBuf += strlen(szBuf);
    itoa10(((pMyAddr->wMAC[2]>>8) | ((pMyAddr->wMAC[2] & 0x00ff) << 8)), szBuf);
}


#ifdef IMGSHAREETH

void
ProcessVMiniSend(void)
{
	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)
    {
        NIC_FTbl->NIC_SendFrame(pVMiniData, dwVMiniDataLength);
        VBridgeKGetOneTxBufferComplete(pVMiniData);
    } 

}	//	ProcessVMiniSend()

#endif	// IMGSHAREETH.

/////////////////////////////////////////////////////////////////////////////////
//	OEMEthInit
//  
//  Initialization routine - called from EdbgInit() to perform platform specific
//  HW init.  
//  Return Value:
//	Return TRUE if init is successful, FALSE if error.

#define	NIC_DESCRIPTORS_HEAD		0xA3BE0000
#define NIC_BUFFER_SIZE			0x00200000
 
BOOL
OEMEthInit(
    EDBG_ADAPTER *pAdapter) // OUT - Pointer to adapter info structure. Filled 
                            //       in with address and SYSINTR info.
{
    EDBG_ADDR    MyAddr;                  // Device's IP and MAC addresses.
    DWORD        EtherCardIoAddress = 0;  // I/O Address of Ether 16 NIC.
    DWORD	 EtherCardIrq = 0;
    DWORD	 dwMemOffset = 0;		
    DWORD        dwIP = 0;
    PDEVICE_NETWORK_INFO    pLocalDeviceNetworkInfo = NULL;


    ////////////////////////////////////////////////////////////////////////////
    // Initialize Ether Card.
    // Boston (DDB5476) supports DEC21140 for EDBG.
    //
    EtherCardIoAddress = pDriverGlobals->EtherIoAddr | KSEG1_BASE | PCI_IO_BASE;
    EtherCardIrq       = pDriverGlobals->EtherIntrNumber & CLEAN_UP;


    ////////////////////////////////////////////////////////////////////////////
    // Use IRQ to determine which chip to talk to...
    //

    dwMemOffset = 0;

    if ((pDriverGlobals->EtherIntrNumber & ~CLEAN_UP) == DEC21140_DEBUG)
    {
        bDecChip = TRUE;
        NIC_FTbl = &DEC21140FTbl;		

        // Get the MAC address for Boston (it's stored in system flash).
        //
        pLocalDeviceNetworkInfo =
                         (PDEVICE_NETWORK_INFO) DEVICE_NETWORK_INFO_LOCATION;

        if (pLocalDeviceNetworkInfo->dwSignature == VALID_INFO_SIGNATURE &&
            pLocalDeviceNetworkInfo->dwMACSignature == VALID_MAC_ADDRESS)
        {
            MyAddr.wMAC[0] = pLocalDeviceNetworkInfo->wMAC[0];
            MyAddr.wMAC[1] = pLocalDeviceNetworkInfo->wMAC[1];
            MyAddr.wMAC[2] = pLocalDeviceNetworkInfo->wMAC[2];

            dwIP = pLocalDeviceNetworkInfo->dwIP;

            // Call into the DEC21140 driver and give it the MAC (it'll need it
            // to set up perfect filtering).
            DEC21140SetMACAddress(MyAddr.wMAC);
        }
        else
        {
            EdbgOutputDebugString ("ERROR: No MAC address assigned to the DEC21140...\r\n");
            return(FALSE);
        }

        // Initialize the NIC DMA buffer.
        //
        if (!NIC_FTbl->NIC_InitDMABuffer(NIC_DESCRIPTORS_HEAD, NIC_BUFFER_SIZE))
        {
            EdbgOutputDebugString ("ERROR: Failed to initialize NIC DMA buffer. .\r\n");
            return(FALSE);
        }

        // Initialize the NIC.  Note we're passing NULL for the MAC address.
        // This signals the public DEC21140 driver not to look for the MAC
        // itself, since it doesn't know how to find it on Boston.
        //
        if (!(NIC_FTbl->NIC_Init((PBYTE)EtherCardIoAddress, 0, NULL)))
        {
            EdbgOutputDebugString ("ERROR: Failed to initialize NIC...\r\n");
            return(FALSE);
        }

    }
    else if ((pDriverGlobals->EtherIntrNumber & ~CLEAN_UP) == NE2000_DEBUG)
    {
        bDecChip = FALSE;
        NIC_FTbl = &NE2000FTbl;		

        if (!(NIC_FTbl->NIC_Init((PBYTE)EtherCardIoAddress, 0, MyAddr.wMAC)))
        {
            EdbgOutputDebugString ("ERROR: Failed to initialize NE2000 NIC...\r\n");
            return(FALSE);
        }
    }


    // Here we simply update the pAdapter.
    //
    pAdapter->Addr.wMAC[0] = MyAddr.wMAC[0];
    pAdapter->Addr.wMAC[1] = MyAddr.wMAC[1];
    pAdapter->Addr.wMAC[2] = MyAddr.wMAC[2];
    pAdapter->Addr.dwIP    = dwIP;
    pAdapter->Addr.wPort   = 0;
    
    // Save out local mac address.
    //
    memcpy( (char *)wLocalMAC, pAdapter->Addr.wMAC, sizeof(wLocalMAC) );

    // Use Vmini to share ethernet port, since there's only one on-board NIC.
#ifdef IMGSHAREETH
    VBridgeInit();
    VBridgeKSetLocalMacAddress((char *)wLocalMAC);
#endif	// IMGSHAREETH.

    // Store DHCP lease and EDBG flag information.
    //
    pAdapter->DHCPLeaseTime = pDriverGlobals->DHCPLeaseTime;
    pAdapter->EdbgFlags     = 0;

    // Hardcode the EDBG Ethernet controller interrupt.
    //
    pAdapter->SysIntrVal = SYSINTR_ETHER;	

    return(TRUE);
}



/////////////////////////////////////////////////////////////////////////////////
//	OEMEthEnableInts
//	Turn on HW interrupts.  
void
OEMEthEnableInts()
{
    NIC_FTbl->NIC_EnableInts();
}



/////////////////////////////////////////////////////////////////////////////////
//	OEMEthEnableInts
//	Disable HW interrupts

void
OEMEthDisableInts()
{
    NIC_FTbl->NIC_DisableInts();
}



////////////////////////////////////////////////////////////////////////////////
// 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()
{	
    // Vmini.
#ifdef IMGSHAREETH
        ProcessVMiniSend();
#endif	// IMGSHAREETH.

    return NIC_FTbl->NIC_GetPendingInts();
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?