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 = &eth8xxMiniportBlock;
 
    /* 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(&ETH8XXChar,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,
                       &ETH8XXChar,
                   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 + -
显示快捷键?