📄 halether.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
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.
Module Name:
halether.c
Abstract:
Platform specific code for debug ethernet services (debug messages,
kernel debugger, text shell (PPSH)). These functions are all called
from ethdbg.lib. They are non-preemptible, and cannot make any system calls.
Functions:
Notes:
--*/
#include <windows.h>
#include <nkintr.h>
#include <ethdbg.h>
#include <halether.h>
#include <oalintr.h>
#include <kitl.h>
#include <memorymap.h>
#include <drv_glob.h>
#include <debugtimer.h>
#include <cs8950sw.h>
#include <hwdefs.h>
#include <options.h>
#include <eeinfo.h>
#define pDriverGlobals ((PDRIVER_GLOBALS) DRIVER_GLOBALS_VIRTUAL_MEMORY)
//extern HARP_BOOT_ARGS *pBootArgs;
//
// Function pointers to the support library functions of the currently installed
// debug ethernet controller.
//
PFN_EDBG_INIT pfnEDbgInit;
PFN_EDBG_ENABLE_INTS pfnEDbgEnableInts;
PFN_EDBG_DISABLE_INTS pfnEDbgDisableInts;
PFN_EDBG_GET_PENDING_INTS pfnEDbgGetPendingInts;
PFN_EDBG_GET_FRAME pfnEDbgGetFrame;
PFN_EDBG_SEND_FRAME pfnEDbgSendFrame;
PFN_EDBG_READ_EEPROM pfnEDbgReadEEPROM;
PFN_EDBG_WRITE_EEPROM pfnEDbgWriteEEPROM;
PFN_EDBG_SET_OPTIONS pfnEDbgSetOptions;
PFN_EDBG_CURRENT_PACKET_FILTER pfnCurrentPacketFilter;
PFN_EDBG_MULTICAST_LIST pfnMulticastList;
// Buffer for receiving frames into.
UCHAR RcvBuf[1500];
extern DWORD EdbgDebugZone;
USHORT wLocalMAC[3]; // Saved copy of the mac address
// Well known DHCP ports for use with UDP
#define DHCP_SERVER_PORT 0x4300
#define DHCP_CLIENT_PORT 0x4400
//
#define MAX_BOOTME_CNT 20
#define BOOTME_INTERVAL 3
#ifdef IMGSHAREETH
BOOL bNewFilter = FALSE; // User mode --> Kernel mode to set new filter.
DWORD dwFilter; // The filter..
BOOL bNewMulticast = FALSE; // User mode --> Kernel mode for new list
DWORD dwNoOfEntry;
BOOL ucMultiAddr[8][6]; // The new list..
// VMINI assumes 8 multicast list entry..
//
#endif
DWORD OEMRequestSysIntr(
DWORD Irq
);
extern ULONG gulCS8950KitlUsed;
#define IPSTATE_NONE 0
#define IPSTATE_GOTIP 1
#define IPSTATE_ARP 2
#define IPSTATE_ARPED 3
#define IPSTATE_RETRY 4
#define MAX_DHCP_RETRY 3
/* OEMEthInit
*
* Initialization routine - called from EdbgInit() to perform platform specific
* HW init. The CEPC platform uses either an SMC 91C94 Ethernet controller or
* an NE2000 compatible adapter (NSC 8390 ethernet controller).
*
* Return Value:
* Return TRUE if init is successful, FALSE if error.
*/
BOOL
OEMEthInit(EDBG_ADAPTER *pAdapter)
{
PULONG pulEthernetBase;
BOOL bTemp;
DEBUGMSG(1, (TEXT("+OEMEthInit\r\n")));
//
// Store info from bootargs in the adapter object.
//
pAdapter->Addr.dwIP = pDriverGlobals->eth.EdbgAddr.dwIP;
//pAdapter->Addr = pDriverGlobals->eth.EdbgAddr;
pAdapter->DHCPLeaseTime = pDriverGlobals->eth.DHCPLeaseTime;
pAdapter->EdbgFlags = pDriverGlobals->eth.EdbgFlags;
//uiActiveNicNumber = pDriverGlobals->eth.EdbgHardwareType;
//
// Some parameters included in boot args for future use, make sure these aren't set
//
switch(pDriverGlobals->eth.EdbgHardwareType)
{
#if 0
case EDBG_ADAPTER_SMC9000:
pfnEDbgInit = SMCInit;
pfnEDbgEnableInts = SMCEnableInts;
pfnEDbgDisableInts = SMCDisableInts;
pfnEDbgGetPendingInts = SMCGetPendingInterrupts;
pfnEDbgGetFrame = SMCGetFrame;
pfnEDbgSendFrame = SMCSendFrame;
pfnEDbgReadEEPROM = SMCReadEEPROM;
pfnEDbgWriteEEPROM = SMCWriteEEPROM;
pfnEDbgSetOptions = SMCSetOptions;
pfnCurrentPacketFilter= NULL;
pfnMulticastList = NULL;
pulEthernetBase = (ULONG *)0x12345678;
EdbgOutputDebugString("INFO: EDBG using SMC9000 controller.\r\n");
break;
#endif // 0
//
// Ethernet base needs to be passed in from eboot.
// TODO
//
case EDBG_ADAPTER_NE2000:
pfnEDbgInit = NE2000Init;
pfnEDbgEnableInts = NE2000EnableInts;
pfnEDbgDisableInts = NE2000DisableInts;
pfnEDbgGetPendingInts = NE2000GetPendingInts;
pfnEDbgGetFrame = NE2000GetFrame;
pfnEDbgSendFrame = NE2000SendFrame;
pfnEDbgReadEEPROM = NE2000ReadEEPROM;
pfnEDbgWriteEEPROM = NE2000WriteEEPROM;
pfnEDbgSetOptions = NE2000SetOptions;
pfnCurrentPacketFilter= Ne2000CurrentPacketFilter;
pfnMulticastList = NE2000MulticastList;
pulEthernetBase = (ULONG *)(PCMCIACARD_IO + 0x320);
//
// TODO - Change the interrupt later.
//
pAdapter->SysIntrVal = KITL_SYSINTR_NOINTR;
EdbgOutputDebugString("INFO: EDBG using NE2000 controller.\r\n");
break;
//
// Put in the CS8950 ethernet routines.
//
case EDBG_ADAPTER_CS8950:
pfnEDbgInit = CS8950Init;
pfnEDbgEnableInts = CS8950EnableInts;
pfnEDbgDisableInts = CS8950DisableInts;
pfnEDbgGetPendingInts = CS8950GetPendingInterrupts;
pfnEDbgGetFrame = CS8950GetFrame;
pfnEDbgSendFrame = CS8950SendFrame;
pfnEDbgReadEEPROM = CS8950ReadEEPROM;
pfnEDbgWriteEEPROM = CS8950WriteEEPROM;
pfnEDbgSetOptions = NULL;
pfnCurrentPacketFilter= NULL; //CS8950CurrentPacketFilter;
pfnMulticastList = NULL; // CS8950MulticastList;
pulEthernetBase = (ULONG *)ETHERNET_BASE;
pAdapter->SysIntrVal = SYSINTR_ETHER;
gulCS8950KitlUsed = TRUE;
//
// CS8950 DMA's to SDRAM. Need to give the library a physical and virtual
// address to uncached memory.
//
bTemp = CS8950DMAInit
(
CS8950_PHYSICAL_MEMORY,
CS8950_VIRTUAL_MEMORY,
CS8950_MEMORY_SIZE
);
if(!bTemp)
{
EdbgOutputDebugString("ERROR: Failed to Initialize CS8950 DMA buffer.\r\n");
return FALSE;
}
//
// We need to do this since the board does not have a MAC address.
// Lets use the same mac address as eboot.
//
CS8950WriteEEPROM(0, pDriverGlobals->eth.EdbgAddr.wMAC[0]);
CS8950WriteEEPROM(1, pDriverGlobals->eth.EdbgAddr.wMAC[1]);
CS8950WriteEEPROM(2, pDriverGlobals->eth.EdbgAddr.wMAC[2]);
EdbgOutputDebugString("INFO: EDBG using Internal EP931x controller.\r\n");
break;
default:
EdbgOutputDebugString
(
"Unsupported debug Ethernet parameters - adapter: %u\n",
pDriverGlobals->eth.EdbgHardwareType
);
return (FALSE);
}
//
// Initialize the ethernet device.
//
//
if (!pfnEDbgInit((BYTE *) pulEthernetBase,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 );
#ifdef IMGSHAREETH
VBridgeInit();
VBridgeKSetLocalMacAddress((char *)wLocalMAC);
#endif
// 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.
#ifndef IMGSHAREETH
if (pAdapter->Addr.dwIP)
pfnEDbgSetOptions(OPT_BROADCAST_FILTERING);
#endif
DEBUGMSG(1, (TEXT("-OEMEthInit\r\n")));
return (TRUE);
}
/* OEMEthEnableInts
*
* Turn on HW interrupts. Return TRUE if interrupts supported, or FALSE
* to run in polling mode for all clients.
*/
void
OEMEthEnableInts()
{
if(pfnEDbgEnableInts)
{
pfnEDbgEnableInts();
}
}
/* OEMEthDisableInts
*
* Disable HW interrupts.
*/
void
OEMEthDisableInts()
{
if(pfnEDbgDisableInts)
{
pfnEDbgDisableInts();
}
}
#ifdef IMGSHAREETH
/* ProcessVMiniSend()
*
* This routine drains the pending VMINI TX.
*
*/
void
ProcessVMiniSend(void)
{
PBYTE pVMiniData;
DWORD dwVMiniDataLength;
////////////////////////////////////////////////////////////////////////////
// Handle the filter if we need to..
//
if (bNewFilter && pfnCurrentPacketFilter)
{
bNewFilter = FALSE;
pfnCurrentPacketFilter(dwFilter);
}
//
// Handle new multicast list..
//
if (bNewMulticast && pfnMulticastList)
{
bNewMulticast = FALSE;
pfnMulticastList(
(PUCHAR)ucMultiAddr,
dwNoOfEntry);
}
////////////////////////////////////////////////////////////////////////////
// Consume all the client packets.
//
while (VBridgeKGetOneTxBuffer(&pVMiniData, &dwVMiniDataLength) == TRUE)
{
pfnEDbgSendFrame (pVMiniData, dwVMiniDataLength);
VBridgeKGetOneTxBufferComplete(pVMiniData);
}
} // ProcessVMiniSend()
#endif
/* 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()
{
DWORD dwReturnValue = 0;
EdbgOutputDebugString("X");
#ifdef IMGSHAREETH
ProcessVMiniSend();
#endif
if(pfnEDbgGetPendingInts)
{
dwReturnValue = pfnEDbgGetPendingInts();
}
return dwReturnValue;
}
/* 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -