eth8xxc.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 1,543 行 · 第 1/4 页
C
1,543 行
/* Copyright (c) 1998 Motorola Inc. All rights reserved. */
/*++
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:
eth8xx.c
Abstract:
This is the main file for the Motorola MPC8xx Ethernet device driver
for Windows CE.
Functions:
DllEntry()
DriverEntry()
eth8xxInitialize()
eth8xxRegisterAdapter()
eth8xxShutdown()
eth8xxHalt()
eth8xxReset()
eth8xxQueryInformation()
eth8xxSetInformation()
eth8xxSetPacketFilter()
eth8xxSetMulticastAddressList()
eth8xxSend()
Environment:
This driver conforms to the NDIS 4.0 miniport interface and is
intended for use only with Windows CE. Even though a complete
NDIS 4.0 interface is provided, only the functions actually
required by the Windows CE NDIS wrapper are currently implemented.
In addition to this driver, the following kernel modules must
also be included to provide a fully functional TCP/IP protocol
stack:
- NDIS
- TCPSTK
- ARP and/or DHCP
This device driver has no known conflicts with the Microsoft-supplied
NE2000 device driver for PCMCIA Ethernet cards. However, the level of
support provided by Windows CE for multiple Ethernet interfaces is
unclear and untested at this time.
Notes:
This device driver is loaded automatically when the Windows CE
kernel boots using the following process:
1. the [HKEY_LOCAL_MACHINE\Init] key is used to launch
device.exe (the device manager module)
2. device.exe loads NDIS.DLL (if it is in the kernel image)
3. NDIS.DLL loads all other members of the NDIS group
(including the ETH8XX driver)
4. all instances of the ETH8XX driver defined in the
registry are then initialized via a call to DriverEntry()
(currently only ETH8XX1 is defined in the registry)
Once the driver has been loaded, the following initialization
steps are performed:
1. NdisMInitializeWrapper() is called to obtain a handle
to an NDIS wrapper object
2. the characteristics of the new driver are then defined
prior to calling NdisMRegisterMiniport()
3. if NdisMRegisterMiniport() is successful, the NDIS
wrapper will then call the "InitializeHandler" function
(currently defined to be eth8xxInitialize())
4. eth8xxInitialize() starts out by allocating the memory
for an "adapter" object
5. the adapter object is then initialized using both
registry keys and hardware configuration information
6. the required number of buffer descriptors and buffers are
allocated (from CPM dualported RAM and external RAM,
respectively)
7. the buffer descriptor linked list pointers are initialized
along with the appropriate status flags
8. the CPM (specifically SCC1 for MPC821) is configured to
operate in the Ethernet mode
9. the Ethernet interface and send/receive interrupts are
both enabled
10. the necessary interrupt and shutdown handlers are
registered with NDIS
11. eth8xxInitialize() exits and returns control to NDIS
At this point, the Ethernet interface is fully functional and NDIS
will start by broadcasting a "gratuitous" ARP packet. This ensures
that there are no IP address conflicts and also updates the ARP
caches of any host with a stale entry.
This driver is modelled after the Microsoft-supplied NE2000 driver.
However, this driver differs significantly from the NE2000 driver
in many ways. First of all, the NE2000 driver is for a PCMCIA card
while the MPC8xx Ethernet interface is integrated into the MPC8xx
core. In particular, the InstallDriver() function is not implemented
since it is only used to detect and install device drivers for
PCMCIA cards. Furthermore, the Ethernet hardware in the MPC8xx core
is totally different from that of an NE2000-compatible device and
requires different data structures, initialization procedures, and
interrupt handling procedures. One final key difference is that the
MPC8xx Ethernet controller is a bus-master DMA device that supports
multipacket send and receives while an NE2000-compatible device must
instead use programmed I/O.
The necessary registry entries for the ETH8XX driver are defined
in the PLATFORM.REG file and will be automatically included in the
kernel build if "SET ETH8XX=1" is defined in the build environment
(this is typically done through either <PROJECT>.BAT or SETENV.BAT).
To generate debugging output, include "-DETHDBG=1 -DDEBUG=1" in the
CDEFINES macro within the sources file. Next, enable the appropriate
debug flags using the last element in dpCurSettings below. The ETHDBG
define allows the use of an in-memory debug buffer for tracing
timing-critical sections of the driver (such as the interrupt
handling routines). This debug buffer may be examined using the
MPC8BUG debugger. The DEBUG define, on the other hand, enables the
use of the DEBUGMSG() macro to produce messages on the debug serial
port. Note, however, that using debugging output, especially within
the interrupt handling routine, can cause serious problems and
possible failure of the device driver (suspect non-reentrancy and/or
timing critical problems).
--*/
#include <windows.h>
#include <nkintr.h>
#include <ndis.h>
//#include <platform.h>
//#include <oalintr.h>
#include "eth8xx.h"
/* Optional debugging definitions. */
#if ETHDBG
/* Default debug mode. */
ULONG eth8xxDebugFlag = 1;
/* Debug tracing definitions. */
PUCHAR eth8xxLogBuffer;
UINT eth8xxLogLoc = 0;
VOID eth8xxLog(UCHAR c)
{
if (eth8xxLogLoc < ETH8XX_LOG_SIZE)
eth8xxLogBuffer[eth8xxLogLoc++] = c;
}
#endif
#ifdef DEBUG
DBGPARAM dpCurSettings = {
TEXT("ETH8XX"),
{
TEXT("Errors"), /* ZONE_ERROR */
TEXT("Warnings"), /* ZONE_WARN */
TEXT("Functions"), /* ZONE_FUNCTION */
TEXT("Init"), /* ZONE_INIT */
TEXT("Interrupts"), /* ZONE_INTR */
TEXT("Receives"), /* ZONE_RCV */
TEXT("Transmits"), /* ZONE_XMIT */
TEXT("Undefined"),
TEXT("Undefined"),
TEXT("Undefined"),
TEXT("Undefined"),
TEXT("Undefined"),
TEXT("Undefined"),
TEXT("Undefined"),
TEXT("Undefined"),
TEXT("Undefined")
},
/* Initial debug zones. */
// 0x0001 /* ZONE_ERROR */
// | 0x0008 /* ZONE_INIT */
0
};
#endif /* DEBUG */
/* This constant is used for places where NdisAllocateMemory is
* called and the HighestAcceptableAddress does not matter.
*/
NDIS_PHYSICAL_ADDRESS HighestAcceptableMax =
NDIS_PHYSICAL_ADDRESS_CONST(-1, -1);
/* The global Miniport driver block. */
DRIVER_BLOCK eth8xxMiniportBlock = { 0, (PETH8XX_ADAPTER)NULL };
/* List of supported OIDs for this driver
* (this is the mandatory set for NDIS 4.0).
*/
STATIC UINT eth8xxSupportedOids[] = {
/* general operational characteristics */
OID_GEN_SUPPORTED_LIST,
OID_GEN_HARDWARE_STATUS,
OID_GEN_MEDIA_SUPPORTED,
OID_GEN_MEDIA_IN_USE,
OID_GEN_MAXIMUM_LOOKAHEAD,
OID_GEN_MAXIMUM_FRAME_SIZE,
OID_GEN_MAXIMUM_TOTAL_SIZE,
OID_GEN_MAC_OPTIONS,
OID_GEN_PROTOCOL_OPTIONS,
OID_GEN_LINK_SPEED,
OID_GEN_TRANSMIT_BUFFER_SPACE,
OID_GEN_RECEIVE_BUFFER_SPACE,
OID_GEN_TRANSMIT_BLOCK_SIZE,
OID_GEN_RECEIVE_BLOCK_SIZE,
OID_GEN_VENDOR_DESCRIPTION,
OID_GEN_VENDOR_ID,
OID_GEN_DRIVER_VERSION,
OID_GEN_CURRENT_PACKET_FILTER,
OID_GEN_CURRENT_LOOKAHEAD,
/* mandatory general statistics */
OID_GEN_XMIT_OK,
OID_GEN_RCV_OK,
OID_GEN_XMIT_ERROR,
OID_GEN_RCV_ERROR,
OID_GEN_RCV_NO_BUFFER,
/* 802.3 operational characteristics */
OID_802_3_PERMANENT_ADDRESS,
OID_802_3_CURRENT_ADDRESS,
OID_802_3_MULTICAST_LIST,
OID_802_3_MAXIMUM_LIST_SIZE,
/* mandatory 802.3 statistics */
OID_802_3_RCV_ERROR_ALIGNMENT,
OID_802_3_XMIT_ONE_COLLISION,
OID_802_3_XMIT_MORE_COLLISIONS
};
CRITICAL_SECTION v_UpdateTxBufList;
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath);
/*----------------------------------------------------------------------*/
BOOL __stdcall DllEntry(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved)
/*++
Description:
Standard Windows DLL entrypoint. Since Windows CE NDIS miniports
are implemented as DLLs, a DLL entrypoint is needed.
Arguments:
hDLL - a handle to the DLL instance
dwReason - either DLL_PROCESS_ATTACH or DLL_PROCESS_DETACH
lpReserved - Windows-specific parameter
Return Value:
TRUE - calls to this "do-nothing" routine are always successful
--*/
{
DEBUGMSG(ZONE_FUNCTION | ZONE_INIT,
(TEXT("+ETH8XX: DllEntry\r\n")));
switch (dwReason) {
case DLL_PROCESS_ATTACH:
DEBUGREGISTER(hDLL);
DEBUGMSG(ZONE_INIT, (TEXT(" ETH8XX: DLL_PROCESS_ATTACH\r\n")));
break;
case DLL_PROCESS_DETACH:
DEBUGMSG(ZONE_INIT, (TEXT(" ETH8XX: DLL_PROCESS_DETACH\r\n")));
break;
default:
DEBUGMSG(ZONE_INIT | ZONE_WARN,
(TEXT(" ETH8XX: DllEntry() called with new parameter %d\r\n"),
dwReason));
break;
}
DEBUGMSG(ZONE_FUNCTION | ZONE_INIT,
(TEXT("-ETH8XX: DllEntry\r\n")));
return(TRUE);
}
/*----------------------------------------------------------------------*/
#pragma NDIS_INIT_FUNCTION(DriverEntry)
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
/*++
Description:
This is the primary initialization routine for the ETH8XX
driver. It is responsible for the intializing the NDIS
wrapper and registering the miniport driver. It then calls
a system and architecture specific routine that will init-
ialize and register each adapter (currently only ETH8XX1).
Arguments:
DriverObject - pointer to driver object created by the system
RegistryPath - path to registry entries for this driver
Return Value:
STATUS_SUCCESS if miniport driver successfully registered
STATUS_UNSUCCESSFUL otherwise
--*/
{
NDIS_STATUS Status; /* NDIS return code. */
NDIS_MINIPORT_CHARACTERISTICS ETH8XXChar; /* Characteristics table. */
PDRIVER_BLOCK NewDriver;
NDIS_HANDLE NdisWrapperHandle;
NTSTATUS InitStatus; /* Driver init status. */
DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
(TEXT("+ETH8XX: DriverEntry\r\n")));
NewDriver = ð8xxMiniportBlock;
/* Notify NDIS that a new miniport driver is initializing.
* Initialize the wrapper and get the wrapper handle. This
* NDIS function must be called before any other NDIS calls.
*/
NdisMInitializeWrapper(&NdisWrapperHandle,
DriverObject,
RegistryPath,
NULL);
/* Save the global information about this driver. */
NewDriver->NdisWrapperHandle = NdisWrapperHandle;
NewDriver->AdapterQueue = (PETH8XX_ADAPTER)NULL;
/* Initialize the Miniport characteristics for the call to
* NdisMRegisterMiniport. These are the functions that are
* called by NDIS on behalf of the protocol stacks (see
* ndis.h). The initial memset() is just to ensure that all
* function pointers are initialized to NULL just in case
* we miss something later on.
*/
memset(Ð8XXChar,0,sizeof(ETH8XXChar));
ETH8XXChar.MajorNdisVersion = ETH8XX_NDIS_MAJOR_VERSION;
ETH8XXChar.MinorNdisVersion = ETH8XX_NDIS_MINOR_VERSION;
ETH8XXChar.CheckForHangHandler = NULL;
ETH8XXChar.DisableInterruptHandler = eth8xxDisableInterrupt;
ETH8XXChar.EnableInterruptHandler = eth8xxEnableInterrupt;
ETH8XXChar.HaltHandler = eth8xxHalt;
ETH8XXChar.HandleInterruptHandler = eth8xxHandleInterrupt;
ETH8XXChar.InitializeHandler = eth8xxInitialize;
ETH8XXChar.ISRHandler = eth8xxIsr;
ETH8XXChar.QueryInformationHandler = eth8xxQueryInformation;
ETH8XXChar.ReconfigureHandler = NULL;
ETH8XXChar.ResetHandler = eth8xxReset;
ETH8XXChar.SendHandler = eth8xxSend;
ETH8XXChar.SetInformationHandler = eth8xxSetInformation;
ETH8XXChar.TransferDataHandler = eth8xxTransferData;
ETH8XXChar.ReturnPacketHandler = NULL;
ETH8XXChar.SendPacketsHandler = NULL;
ETH8XXChar.AllocateCompleteHandler = NULL;
/* Register our NDIS 4.0 miniport device driver. */
Status = NdisMRegisterMiniport(NdisWrapperHandle,
Ð8XXChar,
sizeof(ETH8XXChar));
if (Status != NDIS_STATUS_SUCCESS)
{
DEBUGMSG(ZONE_INIT | ZONE_ERROR,
(TEXT("*ETH8XX: NdisMRegisterMiniport FAILED\r\n")));
/* Terminate the wrapper. */
NdisTerminateWrapper(eth8xxMiniportBlock.NdisWrapperHandle, NULL);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?