📄 cs8900a.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.
//
//-----------------------------------------------------------------------------
//
// 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 + -