📄 celan.c
字号:
//
// Copyright (c) Renesas Technology Corp. 1999-2003 All Rights Reserved.
//
// LAN91C111 network hardware driver
//
//----------------------------------------------------------------------------
//
// FILE : CELAN.C
// CREATED : 1998.07.22 ("ne2000.c", for NE2000 driver)
// MODIFIED : 2003.08.06
// AUTHOR : Renesas Technology Corp.
// HARDWARE : RENESAS HS7751RSTC01H (S1-E, ITS-DS5)
// TARGET OS : Microsoft(R) Windows(R) CE .NET 4.2
// FUNCTION : LAN driver main part
// HISTORY :
// 1999.04.26
// - Released as PFM-DS6x SMC91C94 LAN driver by modifying NE2000
// driver in PB2.12 reference drivers.
// (Detailed history for PFM-DS6x are omitted.)
// 2002.05.29
// - Modified for HS7751RSTC01H. Target device is changed to
// LAN91C111.
// 2002.09.05
// - Header style is changed and file informations are added.
/*++
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.
Copyright (c) 1995-1998 Microsoft Corporation. All rights reserved.
--*/
#include "precomp.h"
#include "smc91c94.h"
#include <winreg.h>
#include <devload.h>
//#include <nkintr.h>
#include <oalintr.h>
//
// On debug builds tell the compiler to keep the symbols for
// internal functions, otw throw them out.
//
#if DBG
#define STATIC
#else
#define STATIC static
#endif
//
// Debugging definitions
//
#if DBG
//
// Default debug mode
//
ULONG CelanDebugFlag =
CELAN_DEBUG_LOUD
| CELAN_DEBUG_VERY_LOUD
// | CELAN_DEBUG_LOG
// | CELAN_DEBUG_CHECK_DUP_SENDS
// | CELAN_DEBUG_TRACK_PACKET_LENS
// | CELAN_DEBUG_WORKAROUND1
// | CELAN_DEBUG_CARD_BAD
// | CELAN_DEBUG_CARD_TESTS
;
//
// Debug tracing defintions
//
#define CELAN_LOG_SIZE 256
UCHAR CelanLogBuffer[CELAN_LOG_SIZE]={0};
UINT CelanLogLoc = 0;
extern
VOID
CelanLog(UCHAR c) {
CelanLogBuffer[CelanLogLoc++] = c;
CelanLogBuffer[(CelanLogLoc + 4) % CELAN_LOG_SIZE] = '\0';
if (CelanLogLoc >= CELAN_LOG_SIZE)
CelanLogLoc = 0;
}
#endif
//
// This constant is used for places where NdisAllocateMemory
// needs to be called and the HighestAcceptableAddress does
// not matter.
//
NDIS_PHYSICAL_ADDRESS HighestAcceptableMax =
NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
//
// The global Miniport driver block.
//
DRIVER_BLOCK CelanMiniportBlock={0};
//
// List of supported OID for this driver.
//
STATIC UINT CelanSupportedOids[] = {
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,
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
};
//
// Determines whether failing the initial card test will prevent
// the adapter from being registered.
//
#ifdef CARD_TEST
BOOLEAN InitialCardTest = TRUE;
#else // CARD_TEST
BOOLEAN InitialCardTest = FALSE;
#endif // CARD_TEST
PVOID RegisterBase;
WORD MAC0,MAC1,MAC2;
DWORD EtherIST(PVOID pArg);
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);
#pragma NDIS_INIT_FUNCTION(DriverEntry)
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
This is the primary initialization routine for the CELAN driver.
It is simply responsible for the intializing the wrapper and registering
the Miniport driver. It then calls a system and architecture specific
routine that will initialize and register each adapter.
Arguments:
DriverObject - Pointer to driver object created by the system.
RegistryPath - Path to the parameters for this driver in the registry.
Return Value:
The status of the operation.
--*/
{
//
// Receives the status of the NdisMRegisterMiniport operation.
//
NDIS_STATUS Status;
//
// Characteristics table for this driver.
//
NDIS_MINIPORT_CHARACTERISTICS CELANChar;
//
// Pointer to the global information for this driver
//
PDRIVER_BLOCK NewDriver = &CelanMiniportBlock;
//
// Handle for referring to the wrapper about this driver.
//
NDIS_HANDLE NdisWrapperHandle;
// Handle for the registry key
HKEY hKey;
ULONG datasize, kvaluetype;
DWORD MacValue;
#if NDIS_WIN
// Not compiled
UCHAR pIds[sizeof (EISA_MCA_ADAPTER_IDS) + 3 * sizeof (USHORT)];
((PEISA_MCA_ADAPTER_IDS)pIds)->nEisaAdapters=0;
((PEISA_MCA_ADAPTER_IDS)pIds)->nMcaAdapters=3;
*((PUSHORT)(((PEISA_MCA_ADAPTER_IDS)pIds)->IdArray) + 0)=AE2_ADAPTER_ID;
*((PUSHORT)(((PEISA_MCA_ADAPTER_IDS)pIds)->IdArray) + 1)=UB_ADAPTER_ID;
*((PUSHORT)(((PEISA_MCA_ADAPTER_IDS)pIds)->IdArray) + 2)=NE2_ADAPTER_ID;
(PVOID) DriverObject = (PVOID) pIds;
#endif
DEBUGMSG(ZONE_INIT|ZONE_FUNCTION,
(TEXT("+CELAN:DriverEntry for %s\r\n"),RegistryPath->Buffer));
//
// Initialize the wrapper.
//
NdisMInitializeWrapper(
&NdisWrapperHandle,
DriverObject,
RegistryPath,
NULL
);
DEBUGMSG(ZONE_INIT,(TEXT("Try to open %s\r\n"),(LPCTSTR)RegistryPath->Buffer));
if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE,(LPCTSTR)RegistryPath->Buffer, 0,
KEY_ALL_ACCESS, &hKey) )
{
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("Faild to open HKEY_LOCAL_MACHINE key.\r\n")));
return STATUS_UNSUCCESSFUL;
}
//
// Get 91C94 register base address
//
datasize = sizeof(DWORD);
if ( RegQueryValueEx(hKey, TEXT("RegBase"), NULL, &kvaluetype,
(LPBYTE)&RegisterBase,&datasize) )
{
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("Faild to get RegBase value.\r\n")));
return STATUS_UNSUCCESSFUL;
}
//
// Get MAC address
//
datasize = sizeof(DWORD);
if ( RegQueryValueEx(hKey, TEXT("MAC0"), NULL, &kvaluetype,
(LPBYTE)&MacValue,&datasize) )
{
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("Faild to get MAC0 value.\r\n")));
//return STATUS_UNSUCCESSFUL;
MAC0 = 0; // for ROM
}
else
MAC0 = (WORD)MacValue;
datasize = sizeof(DWORD);
if ( RegQueryValueEx(hKey, TEXT("MAC1"), NULL, &kvaluetype,
(LPBYTE)&MacValue,&datasize) )
{
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("Faild to get MAC1 value.\r\n")));
//return STATUS_UNSUCCESSFUL;
MAC1 = 0; // for ROM
}
else
MAC1 = (WORD)MacValue;
datasize = sizeof(DWORD);
if ( RegQueryValueEx(hKey, TEXT("MAC2"), NULL, &kvaluetype,
(LPBYTE)&MacValue,&datasize) )
{
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("Faild to get MAC2 value.\r\n")));
//return STATUS_UNSUCCESSFUL;
MAC2 = 0; // for ROM
}
else
MAC2 = (WORD)MacValue;
RegCloseKey (hKey);
DEBUGMSG (ZONE_INIT,(TEXT("SMSC91C94 register base address : %x\r\n"),RegisterBase));
//
// Save the global information about this driver.
//
NewDriver->NdisWrapperHandle = NdisWrapperHandle;
NewDriver->AdapterQueue = (PCELAN_ADAPTER)NULL;
//
// Initialize the Miniport characteristics for the call to
// NdisMRegisterMiniport.
//
memset(&CELANChar,0,sizeof(CELANChar));
CELANChar.MajorNdisVersion = CELAN_NDIS_MAJOR_VERSION;
CELANChar.MinorNdisVersion = CELAN_NDIS_MINOR_VERSION;
CELANChar.CheckForHangHandler = NULL;
CELANChar.DisableInterruptHandler = CelanDisableInterrupt;
CELANChar.EnableInterruptHandler = CelanEnableInterrupt;
CELANChar.HaltHandler = CelanHalt;
CELANChar.HandleInterruptHandler = CelanHandleInterrupt;
CELANChar.InitializeHandler = CelanInitialize;
CELANChar.ISRHandler = CelanIsr;
CELANChar.QueryInformationHandler = CelanQueryInformation;
CELANChar.ReconfigureHandler = NULL;
CELANChar.ResetHandler = CelanReset;
CELANChar.SendHandler = CelanSend;
CELANChar.SetInformationHandler = CelanSetInformation;
CELANChar.TransferDataHandler = NULL;
Status = NdisMRegisterMiniport(
NdisWrapperHandle,
&CELANChar,
sizeof(CELANChar)
);
if (Status == NDIS_STATUS_SUCCESS) {
DEBUGMSG(ZONE_INIT|ZONE_FUNCTION,
(TEXT("-CELAN:DriverEntry: Success\r\n")));
return STATUS_SUCCESS;
}
// Terminate the wrapper.
NdisTerminateWrapper (CelanMiniportBlock.NdisWrapperHandle, NULL);
CelanMiniportBlock.NdisWrapperHandle = NULL;
DEBUGMSG(ZONE_INIT|ZONE_FUNCTION,
(TEXT("-CELAN:DriverEntry: Unsuccessful\r\n")));
return STATUS_UNSUCCESSFUL;
}
#pragma NDIS_PAGEABLE_FUNCTION(CelanInitialize)
extern
NDIS_STATUS
CelanInitialize(
OUT PNDIS_STATUS OpenErrorStatus,
OUT PUINT SelectedMediumIndex,
IN PNDIS_MEDIUM MediumArray,
IN UINT MediumArraySize,
IN NDIS_HANDLE MiniportAdapterHandle,
IN NDIS_HANDLE ConfigurationHandle
)
/*++
Routine Description:
CelanInitialize starts an adapter and registers resources with the
wrapper.
Arguments:
OpenErrorStatus - Extra status bytes for opening token ring adapters.
SelectedMediumIndex - Index of the media type chosen by the driver.
MediumArray - Array of media types for the driver to chose from.
MediumArraySize - Number of entries in the array.
MiniportAdapterHandle - Handle for passing to the wrapper when
referring to this adapter.
ConfigurationHandle - A handle to pass to NdisOpenConfiguration.
Return Value:
NDIS_STATUS_SUCCESS
NDIS_STATUS_PENDING
--*/
{
//
// Pointer to our newly allocated adapter.
//
PCELAN_ADAPTER Adapter;
//
// The handle for reading from the registry.
//
NDIS_HANDLE ConfigHandle;
//
// The value read from the registry.
//
PNDIS_CONFIGURATION_PARAMETER ReturnedValue;
//
// String names of all the parameters that will be read.
//
NDIS_STRING IOAddressStr = IOADDRESS;
NDIS_STRING InterruptStr = INTERRUPT;
NDIS_STRING MaxMulticastListStr = MAX_MULTICAST_LIST;
NDIS_STRING NetworkAddressStr = NETWORK_ADDRESS;
NDIS_STRING BusTypeStr = NDIS_STRING_CONST("BusType");
NDIS_STRING CardTypeStr = NDIS_STRING_CONST("CardType");
//
// TRUE if there is a configuration error.
//
BOOLEAN ConfigError = FALSE;
//
// A special value to log concerning the error.
//
ULONG ConfigErrorValue = 0;
//
// The slot number the adapter is located in, used for
// Microchannel adapters.
//
UINT SlotNumber = 0;
//
// TRUE if it is unnecessary to read the Io Base Address
// and Interrupt from the registry. Used for Microchannel
// adapters, which get this information from the slot
// information.
//
BOOLEAN SkipIobaseAndInterrupt = FALSE;
//
// The network address the adapter should use instead of the
// the default burned in address.
//
PVOID NetAddress;
//
// The number of bytes in the address. It should be
// CELAN_LENGTH_OF_ADDRESS
//
ULONG Length;
//
// These are used when calling CelanRegisterAdapter.
//
//
// The physical address of the base I/O port.
//
PVOID IoBaseAddr;
//
// The interrupt number to use.
//
CCHAR InterruptNumber;
//
// The number of multicast address to be supported.
//
UINT MaxMulticastList;
//
// Temporary looping variable.
//
ULONG i;
//
// Status of Ndis calls.
//
NDIS_STATUS Status;
DEBUGMSG(ZONE_FUNCTION, (TEXT("+CELAN:Initialize\r\n")));
//
// Search for the medium type (802.3) in the given array.
//
for (i = 0; i < MediumArraySize; i++){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -