⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cs8900a.c

📁 IMX开发板
💻 C
📖 第 1 页 / 共 3 页
字号:
//-----------------------------------------------------------------------------
//
//  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.
//
//-----------------------------------------------------------------------------
//
//  Copyright (C) 2004, Motorola Inc. All Rights Reserved
//
//------------------------------------------------------------------------------
//
// Copyright (C) 2004, Freescale Semiconductor, Inc. All Rights Reserved.
// THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
// AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
//
//------------------------------------------------------------------------------

//-----------------------------------------------------------------------------
//
//  File:  cs8900a.c
//
//  Implementation of CS8900 Driver
//
//  This file implements NDIS interface for CS8900.
//
//-----------------------------------------------------------------------------

#include "cs8900a.h"

//-----------------------------------------------------------------------------
// External Functions
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// External Variables
//-----------------------------------------------------------------------------
PBSP_CS8900_REG g_pCS8900Reg = NULL;
//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------

// For multicast support
#define     MAX_MULTICAST_LIST      8

//-----------------------------------------------------------------------------
// Types
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
// Global var of CS89000A Ndis Handler
NDIS_HANDLE  gCs8900aNdisHandle;

CRITICAL_SECTION gCS8900RegCs;
CRITICAL_SECTION gCS8900BufCs;

//-----------------------------------------------------------------------------
// Local Variables
//-----------------------------------------------------------------------------
// This constant is used for places where NdisAllocateMemory
// needs to be called and the HighestAcceptableAddress does
// not matter.
static NDIS_PHYSICAL_ADDRESS HighestAcceptableMax = NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);

//
// List of supported OID for this driver.
static NDIS_OID Cs8900aSupportedOids[] = {
    OID_GEN_VENDOR_DRIVER_VERSION,
    OID_GEN_SUPPORTED_LIST,
    OID_GEN_HARDWARE_STATUS,
    OID_GEN_MEDIA_SUPPORTED,
    OID_GEN_MEDIA_IN_USE,
    OID_GEN_MEDIA_CONNECT_STATUS,
    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,
    OID_GEN_XMIT_OK,
    OID_GEN_RCV_OK,
    OID_GEN_XMIT_ERROR,
    OID_GEN_RCV_ERROR,
    OID_GEN_RCV_NO_BUFFER,
    OID_802_3_PERMANENT_ADDRESS,
    OID_802_3_CURRENT_ADDRESS,
    OID_802_3_MULTICAST_LIST,
    OID_802_3_MAXIMUM_LIST_SIZE,
    OID_802_3_RCV_ERROR_ALIGNMENT,
    OID_802_3_XMIT_ONE_COLLISION,
    OID_802_3_XMIT_MORE_COLLISIONS,
    OID_GEN_MAXIMUM_SEND_PACKETS,
    OID_GEN_RCV_CRC_ERROR,
    OID_GEN_TRANSMIT_QUEUE_LENGTH,
    OID_802_3_XMIT_MAX_COLLISIONS,
    OID_802_3_RCV_OVERRUN,
    OID_802_3_XMIT_UNDERRUN
};

//------------------------------------------------------------------------------
// Local Functions
//------------------------------------------------------------------------------

static void EnablePBCInterrupt()
{
    PHYSICAL_ADDRESS phyAddr_pbc;
	PCSP_PBC_REGS g_pPBC;
	
	phyAddr_pbc.QuadPart = BSP_BASE_REG_PA_PBC_BASE;
    g_pPBC = (PCSP_PBC_REGS) MmMapIoSpace(phyAddr_pbc, sizeof(CSP_PBC_REGS), FALSE);

    // check if Map Virtual Address failed
    if (g_pPBC == NULL)
    {
        DEBUGMSG(ZONE_ERROR,
            (TEXT("%s: PBC MmMapIoSpace failed!\r\n"), __WFUNCTION__));
    }
	else
	{
        DEBUGMSG(ZONE_ERROR,
            (TEXT("%s: PBC MmMapIoSpace Sucess!\r\n"), __WFUNCTION__));
		
		OUTREG16(&g_pPBC->INT_MASK_SET, (1U << PBC_INT_ENET_LSH));
	}
}

//-----------------------------------------------------------------------------
//
// Function: DllEntry
//
//  This function is entry point of the dll.
//
// Parameters:
//      hInstDll
//          [in] .
//      Op
//          [in] .
//      lpvReserved
//          [in] .
//
// Returns:
//    This function always returns TRUE.
//
//-----------------------------------------------------------------------------
BOOL WINAPI DllEntry( HANDLE hInstDll, DWORD  Op, LPVOID lpvReserved )
{
    switch(Op)
    {
        case DLL_PROCESS_ATTACH:
            DEBUGMSG(ZONE_INIT, (TEXT("CS8900A: DLL Process Attach.\r\n")));

            // Disables the DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications
            DisableThreadLibraryCalls((HMODULE) hInstDll);
            break;

        case DLL_PROCESS_DETACH:
            DEBUGMSG(ZONE_INIT, (TEXT("CS8900A: DLL Process Detach.\r\n")));
            break;

        default:
            break;
    }

    return TRUE;
}

//------------------------------------------------------------------------------
//
// Function: DriverEntry
//
// This function is the main entry of driver. It initializes and registers Miniport driver to NDIS.
//
// Parameters:
//      DriverObject
//          [in] pointer to driver object created byt the system.
//
//      RegistryPath
//          [in] Driver Registry path.
//
// Returns:
//      Returns STATUS_SUCCESS if initialization is success. Return STATUS_UNSUCCESSFUL if not.
//
//------------------------------------------------------------------------------
#pragma NDIS_INIT_FUNCTION(DriverEntry)
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
    NDIS_STATUS Status;
    NDIS_MINIPORT_CHARACTERISTICS cs8900aChar; // Characteristics table for this driver.

    DEBUGMSG(ZONE_INIT, (TEXT("CS8900A: +DriverEntry(0x%.8X, 0x%.8X)\r\n"), DriverObject, RegistryPath));

    // Notifies NDIS for new miniport driver
    NdisMInitializeWrapper(&gCs8900aNdisHandle, DriverObject, RegistryPath, NULL);

    // Fill-in adapter characterictics before calling NdisMRegisterMiniport
    memset(&cs8900aChar,0,sizeof(cs8900aChar));
    cs8900aChar.MajorNdisVersion = CS8900A_NDIS_MAJOR_VERSION;
    cs8900aChar.MinorNdisVersion = CS8900A_NDIS_MINOR_VERSION;
    cs8900aChar.CheckForHangHandler = Cs8900aCheckForHang;
    cs8900aChar.DisableInterruptHandler = Cs8900aDisableInterrupt;
    cs8900aChar.EnableInterruptHandler = Cs8900aEnableInterrupt;
    cs8900aChar.HaltHandler = Cs8900aHalt;
    cs8900aChar.HandleInterruptHandler = Cs8900aHandleInterrupt;
    cs8900aChar.InitializeHandler = Cs8900aInitialize;
    cs8900aChar.ISRHandler = NULL;
    cs8900aChar.QueryInformationHandler = Cs8900aQueryInformation;
    cs8900aChar.ReconfigureHandler = NULL;
    cs8900aChar.ResetHandler = Cs8900aReset;
    cs8900aChar.SendHandler = Cs8900aSend;
    cs8900aChar.SetInformationHandler = Cs8900aSetInformation;
    cs8900aChar.TransferDataHandler = Cs8900aTransferData;

    // Now register Miniport
    Status = NdisMRegisterMiniport(gCs8900aNdisHandle, &cs8900aChar, sizeof(cs8900aChar));

    if (Status != NDIS_STATUS_SUCCESS)
    {
        DEBUGMSG(ZONE_ERROR, (TEXT("CS8900A: NdisMRegisterMiniport failure [0x%.8X].\r\n"), Status));
        NdisTerminateWrapper(gCs8900aNdisHandle, NULL);
    }

    DEBUGMSG(ZONE_INIT, (TEXT("CS8900A: -DriverEntry [0x%.8X]\r\n"), Status));
    return (Status);
}

//------------------------------------------------------------------------------
//
// Function: Cs8900aInitialize
//
// This function finds and initializes the adapter.
//
// Parameters:
//      OpenErrorStatus
//          [out] Extra status bytes for opening token ring adapters.
//
//      SelectedMediumIndex
//          [out] Pointer to index of the media type chosen by the driver.
//
//      MediumArray
//          [in] Array of media types for the driver to chose from.
//
//      MediumArraySize
//          [in] Number of entries in the array.
//
//      MiniportAdapterHandle
//          [in] Pointer to index of the media type chosen by the driver.
//
//      ConfigurationHandle
//          [in] Handle to pass to NdisOpenConfiguration.
//
// Returns:
//      Returns NDIS_STATUS_SUCCESS if initialization is success. 
//      Return NDIS_STATUS_FAILURE or NDIS_STATUS_UNSUPPORTED_MEDIA if not.
//
//------------------------------------------------------------------------------
#pragma NDIS_PAGEABLE_FUNCTION(Cs8900aInitialize)
static NDIS_STATUS Cs8900aInitialize(
    OUT PNDIS_STATUS OpenErrorStatus,
    OUT PUINT SelectedMediumIndex,
    IN PNDIS_MEDIUM MediumArray,
    IN UINT MediumArraySize,
    IN NDIS_HANDLE MiniportAdapterHandle,
    IN NDIS_HANDLE WrapperConfigurationContext)
{


    // Pointer to our newly allocated adapter.
    pCs8900_t pEthernet= NULL;

    // The handle for reading from the registry.
    NDIS_HANDLE ConfigHandle = NULL;
    
    UINT32 i;
    NDIS_STATUS Status=NDIS_STATUS_SUCCESS, MACStatus;
    WORD result;
    PNDIS_CONFIGURATION_PARAMETER Value;
    USHORT TmpVal;
    NDIS_STRING MACAddrString[3]= { NDIS_STRING_CONST("MACAddress1"),
                                    NDIS_STRING_CONST("MACAddress2"), 
                                    NDIS_STRING_CONST("MACAddress3")};

    PHYSICAL_ADDRESS phyAddr;
	WORD InterruptEvent;

    DEBUGMSG(ZONE_INIT, (TEXT("CS8900A: +Cs8900aInitialize\r\n")));
	InitializeCriticalSection (&gCS8900RegCs);
	InitializeCriticalSection (&gCS8900BufCs);
        
    do {

        // Search for medium type (802.3) in the given array.
        for (i = 0;i < MediumArraySize; i++) {
            if (MediumArray[i] == NdisMedium802_3) {
                *SelectedMediumIndex = i;
                break;
            }// endif 
        }// endfor
        if (i == MediumArraySize) {
            DEBUGMSG(ZONE_INIT|ZONE_ERROR, (TEXT("CS8900A:No supported media\r\n")));
            Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
            break;
        }

        *SelectedMediumIndex = i;
        DEBUGMSG(ZONE_INIT, (TEXT("CS8900A: Search for media success. \r\n")));
        // Allocate memory for the adapter block now.
        Status = NdisAllocateMemory( (PVOID *)&pEthernet, sizeof(cs8900_t), 0, HighestAcceptableMax);

        if (Status != NDIS_STATUS_SUCCESS)
        {
            DEBUGMSG(ZONE_INIT|ZONE_ERROR, (TEXT("CS8900a: NdisAllocateMemory(cs8900_t) failed\n")));
            break;
        }
        DEBUGMSG(ZONE_INIT, (TEXT("CS8900A: Allocate memory for the adapter block success. \r\n")));        
        // Clear out the pEthernet block, which sets all default values to FALSE,
        // or NULL.

        NdisZeroMemory (pEthernet, sizeof(cs8900_t));
        pEthernet->ndisAdapterHandle = MiniportAdapterHandle;
        pEthernet->LookAheadSize = (WORD)(-1);
        pEthernet->CurrentState = NdisHardwareStatusNotReady;
        pEthernet->HeadPacket = pEthernet->TailPacket = NULL; // initialize then to point to NULL
        pEthernet->TransmitInProgress = FALSE;
        pEthernet->StartTX = FALSE;
        pEthernet->TransmitBidPending = FALSE;
        pEthernet->FramesXmitGood = 0;
        pEthernet->FramesRcvGood = 0;
        pEthernet->FramesXmitBad = 0;
        pEthernet->FramesXmitOneCollision = 0;
        pEthernet->FramesXmitManyCollisions = 0; 
        pEthernet->FrameAlignmentErrors = 0;       
        pEthernet->RcvCRCErrors = 0;
        pEthernet->MissedPackets = 0;
        pEthernet->RcvErrors = 0;
        pEthernet->XmitMaxCollisions = 0;
        pEthernet->RcvOverrun = 0;
        pEthernet->XmitUnderrun = 0;
        pEthernet->RcvExtraDataErrors = 0;
        pEthernet->RcvShortDataErrors = 0; // for receive packet shorter than 64bytes
        pEthernet->TxMaxCount = 1; // now only support 1, may consider to support multiple packets later
        DEBUGMSG(ZONE_INIT, (TEXT("CS8900A: NdisZeroMemory success. \r\n")));
        
        NdisMSetAttributes(
              MiniportAdapterHandle,
              (NDIS_HANDLE)pEthernet,
              FALSE,              // No DMA involved
              NdisInterfaceIsa);  // ISA bus standard

        DEBUGMSG(ZONE_INIT, (TEXT("CS8900A: NdisMSetAttributes completed \r\n")));
        
        // Open the configuration space.
        NdisOpenConfiguration(&Status, &ConfigHandle, WrapperConfigurationContext);
        if (Status != NDIS_STATUS_SUCCESS)
        {
            DEBUGMSG(ZONE_INIT, (TEXT("CS8900A: NdisOpenconfiguration failed 0x%x\n"), Status));
            break;
        }
        DEBUGMSG(ZONE_INIT, (TEXT("CS8900A: NdisOpenconfiguration success. \r\n")));
        
        // read in the MAC address in registry
        for(i=0; i<3; i++)
        {
            NdisReadConfiguration(&MACStatus, &Value, ConfigHandle, &MACAddrString[i], NdisParameterHexInteger );
            if (MACStatus == NDIS_STATUS_SUCCESS) 
            {
                TmpVal=(USHORT)Value->ParameterData.IntegerData;
                pEthernet->CurrentAddress[i*2] = (UCHAR)((TmpVal & 0xff00) >> 8);
                pEthernet->CurrentAddress[(i*2)+1] = (UCHAR)(TmpVal & 0x00ff);

            }
            else
            {
                // assigned all to 0, use MAC settings in EPROM or hardcoded
                pEthernet->CurrentAddress[0] = 0;
                pEthernet->CurrentAddress[1] = 0;
                pEthernet->CurrentAddress[2] = 0;
                pEthernet->CurrentAddress[3] = 0;
                pEthernet->CurrentAddress[4] = 0;
                pEthernet->CurrentAddress[5] = 0;
                pEthernet->CurrentAddress[6] = 0;
                break;
            }
        }

        phyAddr.QuadPart = BSP_BASE_REG_PA_CS8900A_IOBASE;
        // virtual mapping
        g_pCS8900Reg = (PBSP_CS8900_REG)MmMapIoSpace(phyAddr, sizeof(BSP_CS8900_REG), FALSE);
                
        if(g_pCS8900Reg != NULL) 
        {
            DEBUGMSG(ZONE_INIT, (TEXT("CS8900A: MmMapIoSpace pass. \r\n")));
            // detect for the presence of the CS8900 chip
            result=CheckForChip(pEthernet);
            if(result != TRUE) 
            {
                DEBUGMSG(ZONE_ERROR, (TEXT("CS8900A: CS8900 Chip not found!\r\n")));
                Status = NDIS_STATUS_FAILURE;
                break;
            }

        }
        else 
        {
            DEBUGMSG(ZONE_ERROR,(TEXT("CS8900A: MmMapIoSpace failed to alloc memory :%d \r\n"),CS8900_IOSPACE_OPERATION_SIZE));
            Status = NDIS_STATUS_FAILURE;
            break;
        }
        // Register for a Shutdown function
        
        NdisMRegisterAdapterShutdownHandler(MiniportAdapterHandle, pEthernet, Cs8900aShutdown);
        pEthernet->CurrentState = NdisHardwareStatusInitializing;
        // Initialize CS8900 chip
        result = InitializeChip(pEthernet);

        if(result == TRUE)
        {
            InterruptChip(pEthernet, TRUE);
            pEthernet->intLine = BSP_CS8900_IRQ;
            Status = NdisMRegisterInterrupt((PNDIS_MINIPORT_INTERRUPT)&(pEthernet->interruptObj),
                                            MiniportAdapterHandle, 

⌨️ 快捷键说明

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