2061 lines
46 KiB
C
2061 lines
46 KiB
C
/*++
|
||
|
||
Copyright (c) 1990 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
init.c
|
||
|
||
Abstract:
|
||
|
||
This file controls all the loading and unloading of the driver. It controls
|
||
the initial bindings and the teardown in the event it is told to unload.
|
||
|
||
Author:
|
||
|
||
Sean Selitrennikoff (seanse) 3-93
|
||
|
||
Environment:
|
||
|
||
Kernel Mode.
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include <ntddk.h>
|
||
#include <ndis.h>
|
||
#include "lsl.h"
|
||
#include "lslmlid.h"
|
||
#include "frames.h"
|
||
#include "mlid.h"
|
||
#include "ndismlid.h"
|
||
|
||
#define UNICODE_STRING_CONST(x) {sizeof(L##x)-2, sizeof(L##x), L##x}
|
||
|
||
|
||
//
|
||
// PLEASE NOTE: The ordering of the strings in the arrays is important.
|
||
// Code depends on the indicies of the strings. Each dependency is
|
||
// listed with the array that it depends on.
|
||
//
|
||
|
||
//
|
||
// All the string names of the counters that must be kept by a MLID.
|
||
// - ndismlid.c
|
||
// - lslmlid.c
|
||
//
|
||
static
|
||
MEON_STRING
|
||
NdisMlidGenericStatStrings[] = {
|
||
"MTotalTxPacketCount",
|
||
"MTotalRxPacketCount",
|
||
"MNoECBAvailableCount",
|
||
"MPacketTxTooBigCount",
|
||
"MPacketTxTooSmallCount",
|
||
"MPacketRxTooBigCount",
|
||
"MTotalTxMiscCount",
|
||
"MTotalRxMiscCount",
|
||
"MTotalTxOKByteCount",
|
||
"MTotalRxOKByteCount",
|
||
"MTotalGroupAddrTxCount",
|
||
"MTotalGroupAddrRxCount",
|
||
"MAdapterResetCount",
|
||
"MAdapterOprTimeStamp",
|
||
"MQDepth"
|
||
};
|
||
|
||
//
|
||
// The type of each of the above stat, where 0 == UINT32 and 1 == UINT64
|
||
// - No Dependencies
|
||
//
|
||
static
|
||
UINT32
|
||
NdisMlidGenericStatTypes[] = {
|
||
0, // TotalTxPacketCount
|
||
0, // TotalRxPacketCount
|
||
0, // NoECBAvailableCount
|
||
0, // PacketTxTooBigCount
|
||
0, // PacketRxTooSmallCount
|
||
0, // PacketRxTooBigCount
|
||
0, // TotalTxMiscCount
|
||
0, // TotalRxMiscCount
|
||
1, // TotalTxOKByteCount
|
||
1, // TotalRxOKByteCount
|
||
0, // TotalGroupAddrTxCount
|
||
0, // TotalGroupAddrRxCount
|
||
0, // AdapterResetCount
|
||
0, // AdapterOprTimeStamp
|
||
0 // QDepth
|
||
};
|
||
|
||
|
||
//
|
||
// String names for counters kept by Token Ring MLIDs
|
||
// - ndismlid.c: TRN_LastRingID
|
||
//
|
||
static
|
||
MEON_STRING
|
||
NdisMlidTokenRingStatStrings[] = {
|
||
"TRN_ACErrorCounter",
|
||
"TRN_AbortDelimiterCounter",
|
||
"TRN_BurstErrorCounter",
|
||
"TRN_FrameCopiedErrorCounter",
|
||
"TRN_FrequencyErrorCounter",
|
||
"TRN_InternalErrorCounter",
|
||
"TRN_LastRingStatus",
|
||
"TRN_LineErrorCounter",
|
||
"TRN_LostFrameCounter",
|
||
"TRN_TokenErrorCounter",
|
||
"TRN_UpstreamNodeAddress",
|
||
"TRN_LastRingID",
|
||
"TRN_LastBeaconType"
|
||
};
|
||
|
||
|
||
//
|
||
// The type of each of the above stat, where 0 == UINT32 and 1 == UINT64
|
||
// - ndismlid.c: TRN_LastRingID
|
||
//
|
||
static
|
||
UINT32
|
||
NdisMlidTokenRingStatTypes[] = {
|
||
0, // TRN_ACErrorCounter
|
||
0, // TRN_AbortDelimiterCounter
|
||
0, // TRN_BurstErrorCounter
|
||
0, // TRN_FrameCopiedErrorCounter
|
||
0, // TRN_FrequencyErrorCounter
|
||
0, // TRN_InternalErrorCounter
|
||
0, // TRN_LastRingStatus
|
||
0, // TRN_LineErrorCounter
|
||
0, // TRN_LostFrameCounter
|
||
0, // TRN_TokenErrorCounter
|
||
1, // TRN_UpstreamNodeAddress
|
||
0, // TRN_LastRingID
|
||
0 // TRN_LastBeaconType
|
||
};
|
||
|
||
//
|
||
// String names for counters kept by Ethernet MLIDs
|
||
// - No Dependencies
|
||
//
|
||
static
|
||
MEON_STRING
|
||
NdisMlidEthernetStatStrings[] = {
|
||
"ETH_TxOKSingleCollisionsCount",
|
||
"ETH_TxOKMultipleCollisionsCount",
|
||
"ETH_TxOKButDeferred",
|
||
"ETH_TxAbortLateCollision",
|
||
"ETH_TxAbortExcessCollision",
|
||
"ETH_TxAbortCarrierSense",
|
||
"ETH_TxAbortExcessiveDeferral",
|
||
"ETH_RxAbortFrameAlignment"
|
||
};
|
||
|
||
|
||
//
|
||
// The type of each of the above stats, where 0 == UINT32 and 1 == UINT64
|
||
// - No Dependencies
|
||
//
|
||
static
|
||
UINT32
|
||
NdisMlidEthernetStatTypes[] = {
|
||
0, // ETH_TxOKSingleCollisionsCount
|
||
0, // ETH_TxOKMultipleCollisionsCount
|
||
0, // ETH_TxOKButDeferred
|
||
0, // ETH_TxAbortLateCollision
|
||
0, // ETH_TxAbortExcessCollision
|
||
0, // ETH_TxAbortCarrierSense
|
||
0, // ETH_TxAbortExcessiveDeferral
|
||
0 // ETH_RxAbortFrameAlignment
|
||
};
|
||
|
||
//
|
||
// String names for counter kept by FDDI MLIDs
|
||
// - No Dependencies
|
||
//
|
||
static
|
||
MEON_STRING
|
||
NdisMlidFddiStatStrings[] = {
|
||
"FDI_ConfigurationState",
|
||
"FDI_UpstreamNode",
|
||
"FDI_DownstreamNode",
|
||
"FDI_FrameErrorCount",
|
||
"FDI_FrameLostCount",
|
||
"FDI_RingManagementCount",
|
||
"FDI_LCTFailureCount",
|
||
"FDI_LemRejectCount",
|
||
"FDI_LemCount",
|
||
"FDI_LConnectionState"
|
||
};
|
||
|
||
|
||
//
|
||
// The type of each of the above stats, where 0 == UINT32 and 1 == UINT64
|
||
// - No Dependencies
|
||
//
|
||
static
|
||
UINT32
|
||
NdisMlidFddiStatTypes[] = {
|
||
0, // FDI_ConfigurationState
|
||
1, // FDI_UpstreamNode
|
||
1, // FDI_DownstreamNode
|
||
0, // FDI_FrameErrorCount
|
||
0, // FDI_FrameLostCount
|
||
0, // FDI_RingManagementCount
|
||
0, // FDI_LCTFailureCount
|
||
0, // FDI_LemRejectCount
|
||
0, // FDI_LemCount
|
||
0 // FDI_LConnectionState
|
||
};
|
||
|
||
|
||
//
|
||
// Holds the string names of all frame types
|
||
// - No Dependencies
|
||
//
|
||
static
|
||
MEON_STRING
|
||
NdisMlidFrameTypeStrings[] = {
|
||
"VIRTUAL_LAN",
|
||
"LOCALTALK",
|
||
"ETHERNET_II",
|
||
"ETHERNET_802.2",
|
||
"TOKEN-RING",
|
||
"ETHERNET_802.3"
|
||
"802.4",
|
||
"Reserved",
|
||
"GNET",
|
||
"PRONET-10",
|
||
"ETHERNET_SNAP",
|
||
"TOKEN-RING_SNAP",
|
||
"LANPAC_II",
|
||
"ISDN",
|
||
"NOVELL_RX-NET",
|
||
"IBM_PCN2_802.2",
|
||
"IBM_PCN2_SNAP",
|
||
"OMNINET/4",
|
||
"3270_COAXA",
|
||
"IP"
|
||
"FDDI_802.2",
|
||
"IVDLAN_802.9",
|
||
"DATACO_OSI",
|
||
"FDDI_SNAP"
|
||
};
|
||
|
||
//
|
||
// Handle for this "protocol" for NDIS
|
||
//
|
||
NDIS_HANDLE NdisMlidProtocolHandle = NULL;
|
||
|
||
//
|
||
// Spin lock for accessing MLID list
|
||
//
|
||
NDIS_SPIN_LOCK NdisMlidSpinLock;
|
||
|
||
//
|
||
// Array of MLIDs
|
||
//
|
||
extern PMLID_BOARDS MlidBoards = NULL;
|
||
|
||
//
|
||
// Number of MLIDs in use
|
||
//
|
||
extern UINT32 CountMlidBoards = 0;
|
||
|
||
//
|
||
// Size of the MLID array
|
||
//
|
||
extern UINT32 AllocatedMlidBoards = 0;
|
||
|
||
|
||
|
||
|
||
|
||
NTSTATUS
|
||
NdisMlidRegisterProtocol(
|
||
IN UNICODE_STRING *NameString
|
||
);
|
||
|
||
VOID
|
||
NdisMlidDeregisterProtocol(
|
||
VOID
|
||
);
|
||
|
||
NTSTATUS
|
||
NdisMlidInitializeMlids(
|
||
VOID
|
||
);
|
||
|
||
VOID
|
||
NdisMlidUnloadMlids(
|
||
IN PDRIVER_OBJECT DriverObject
|
||
);
|
||
|
||
VOID
|
||
NdisMlidUnloadMlid(
|
||
IN PMLID_STRUCT Mlid
|
||
);
|
||
|
||
PMLID_STRUCT
|
||
NdisMlidOpenMlid(
|
||
PVOID OdiRegistryPtr,
|
||
PVOID NdisRegistryPtr,
|
||
);
|
||
|
||
|
||
NTSTATUS
|
||
DriverEntry(
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN PUNICODE_STRING RegistryPath
|
||
)
|
||
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the entry point for the driver.
|
||
|
||
Arguments:
|
||
|
||
DriverObject - The driver object for this driver in the NT system.
|
||
|
||
RegistryPath - Path in the registry to it's parameters.
|
||
|
||
Return Value:
|
||
|
||
Indicates the success or failure of the initialization.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
UNICODE_STRING NameString = UNICODE_STRING_CONST("\\Device\\NdisMlid");
|
||
|
||
//
|
||
// Fill in unload handler
|
||
//
|
||
|
||
DriverObject->DriverUnload = NdisMlidUnloadMlids;
|
||
|
||
//
|
||
// make ourselves known to the NDIS wrapper.
|
||
//
|
||
|
||
Status = NdisMlidRegisterProtocol(&NameString);
|
||
|
||
if (!NT_SUCCESS (Status)) {
|
||
|
||
#if DBG
|
||
DbgPrint("NdisMlidInitialize: RegisterProtocol failed!\n");
|
||
#endif
|
||
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
|
||
}
|
||
|
||
NdisAllocateSpinLock(&NdisMlidSpinLock);
|
||
|
||
//
|
||
// Now Initialize all the boards according to registry
|
||
//
|
||
|
||
Status = NdisMlidInitializeMlids();
|
||
|
||
if (!(NT_SUCCESS(Status))) {
|
||
|
||
NdisFreeSpinLock(&NdisMlidSpinLock);
|
||
|
||
NdisMlidDeregisterProtocol();
|
||
|
||
return(Status);
|
||
|
||
}
|
||
|
||
return(STATUS_SUCCESS);
|
||
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
NdisMlidRegisterProtocol(
|
||
IN UNICODE_STRING *NameString
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine introduces this driver as a transport to the NDIS interface.
|
||
|
||
Arguments:
|
||
|
||
NameString - Name of this device.
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS - Success.
|
||
STATUS_INSUFFICIENT_RESOURCES - Failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
NDIS_STATUS NdisStatus;
|
||
PNDIS_PROTOCOL_CHARACTERISTICS ProtChars; // Used temporarily to register
|
||
|
||
ProtChars = ExAllocatePool(NonPagedPool,
|
||
sizeof(NDIS_PROTOCOL_CHARACTERISTICS) + NameString->Length
|
||
);
|
||
|
||
//
|
||
// Set up the characteristics of this protocol
|
||
//
|
||
|
||
ProtChars->MajorNdisVersion = 3;
|
||
ProtChars->MinorNdisVersion = 0;
|
||
|
||
ProtChars->Name.Length = NameString->Length;
|
||
ProtChars->Name.Buffer = (PVOID)(ProtChars + 1);
|
||
|
||
ProtChars->OpenAdapterCompleteHandler = NdisMlidOpenAdapterComplete;
|
||
ProtChars->CloseAdapterCompleteHandler = NdisMlidCloseAdapterComplete;
|
||
ProtChars->ResetCompleteHandler = NdisMlidResetComplete;
|
||
ProtChars->RequestCompleteHandler = NdisMlidRequestComplete;
|
||
ProtChars->SendCompleteHandler = NdisMlidSendComplete;
|
||
ProtChars->TransferDataCompleteHandler = NdisMlidTransferDataComplete;
|
||
ProtChars->ReceiveHandler = NdisMlidReceive;
|
||
ProtChars->ReceiveCompleteHandler = NdisMlidReceiveComplete;
|
||
ProtChars->StatusHandler = NdisMlidStatus;
|
||
ProtChars->StatusCompleteHandler = NdisMlidStatusComplete;
|
||
|
||
NdisRegisterProtocol (
|
||
&NdisStatus,
|
||
&NdisMlidProtocolHandle,
|
||
ProtChars,
|
||
(UINT)sizeof(NDIS_PROTOCOL_CHARACTERISTICS) + NameString->Length
|
||
);
|
||
|
||
ExFreePool(ProtChars);
|
||
|
||
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
||
|
||
#if DBG
|
||
DbgPrint("NdisMlidInitialize: NdisRegisterProtocol failed: %s\n", NdisStatus);
|
||
#endif
|
||
|
||
return (NTSTATUS)NdisStatus;
|
||
|
||
}
|
||
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
|
||
VOID
|
||
NdisMlidDeregisterProtocol(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine removes this transport to the NDIS interface.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
NDIS_STATUS NdisStatus;
|
||
|
||
if (NdisMlidProtocolHandle != (NDIS_HANDLE)NULL) {
|
||
|
||
NdisDeregisterProtocol (
|
||
&NdisStatus,
|
||
NdisMlidProtocolHandle
|
||
);
|
||
|
||
NdisMlidProtocolHandle = (NDIS_HANDLE)NULL;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
NdisMlidUnloadMlids(
|
||
IN PDRIVER_OBJECT DriverObject
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine shuts down all the MLIDs and unloads itself.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
UINT32 i;
|
||
|
||
NdisAcquireSpinLock(&NdisMlidSpinLock);
|
||
|
||
//
|
||
// For each MLID
|
||
//
|
||
|
||
for (i = 0; i < AllocatedMlidBoards; i++) {
|
||
|
||
//
|
||
// If MLID was opened
|
||
//
|
||
|
||
if (MlidBoards[i].Mlid != NULL) {
|
||
|
||
//
|
||
// Unload MLID
|
||
//
|
||
|
||
NdisMlidUnloadMlid(MlidBoards[i].Mlid);
|
||
MlidBoards[i].Mlid = NULL;
|
||
|
||
CountMlidBoards--;
|
||
|
||
if (CountMlidBoards == 0) {
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
NdisReleaseSpinLock(&NdisMlidSpinLock);
|
||
|
||
NdisFreeSpinLock(&NdisMlidSpinLock);
|
||
|
||
NdisMlidDeregisterProtocol();
|
||
|
||
ExFreePool(MlidBoards);
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
NdisMlidUnloadMlid(
|
||
IN PMLID_STRUCT Mlid
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine removes this transport to the NDIS interface.
|
||
|
||
NOTE: You must hold the NdisMlidSpinLock when calling this routine!!
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
UINT32 Status;
|
||
NDIS_STATUS NdisStatus;
|
||
PECB SendECB;
|
||
|
||
NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
|
||
|
||
//
|
||
// Set unloading flag
|
||
//
|
||
Mlid->Unloading = TRUE;
|
||
|
||
//
|
||
// Remove all pending ECBs
|
||
//
|
||
|
||
while (Mlid->FirstPendingSend != NULL) {
|
||
|
||
//
|
||
// Remove ECB from queue
|
||
//
|
||
|
||
SendECB = Mlid->FirstPendingSend;
|
||
|
||
Mlid->FirstPendingSend = SendECB->ECB_NextLink;
|
||
|
||
if (SendECB->ECB_NextLink != NULL) {
|
||
|
||
SendECB->ECB_NextLink->ECB_PreviousLink = NULL;
|
||
|
||
}
|
||
|
||
if (Mlid->LastPendingSend == SendECB) {
|
||
|
||
Mlid->LastPendingSend = NULL;
|
||
|
||
}
|
||
|
||
//
|
||
// Cancel the ECB
|
||
//
|
||
|
||
SendECB->ECB_Status = (UINT16)CANCELED;
|
||
|
||
//
|
||
// Give it to LSL
|
||
//
|
||
|
||
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
||
|
||
(*(Mlid->LSLFunctionList->SupportAPIArray[HoldEvent_INDEX]))(
|
||
SendECB
|
||
);
|
||
|
||
NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
|
||
|
||
}
|
||
|
||
//
|
||
// Service all held sends
|
||
//
|
||
|
||
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
||
|
||
(*(Mlid->LSLFunctionList->SupportAPIArray[ServiceEvents_INDEX]))(
|
||
);
|
||
|
||
//
|
||
// Close Ndis Adapter
|
||
//
|
||
|
||
NdisCloseAdapter(&NdisStatus, Mlid->NdisBindingHandle);
|
||
|
||
//
|
||
// If pend, wait
|
||
//
|
||
|
||
if (NdisStatus == NDIS_STATUS_PENDING) {
|
||
|
||
//
|
||
// Wait for close to complete
|
||
//
|
||
|
||
KeWaitForSingleObject(
|
||
&(Mlid->MlidRequestCompleteEvent),
|
||
Executive,
|
||
KernelMode,
|
||
TRUE,
|
||
(PTIME)NULL
|
||
);
|
||
|
||
KeResetEvent(&Mlid->MlidRequestCompleteEvent);
|
||
}
|
||
|
||
//
|
||
// Get status
|
||
//
|
||
|
||
Status = Mlid->RequestStatus;
|
||
|
||
//
|
||
// Deregister with LSL
|
||
//
|
||
|
||
(*(Mlid->LSLFunctionList->SupportAPIArray[DeRegisterMLID_INDEX]))(
|
||
Mlid->ConfigTable.MLIDCFG_BoardNumber
|
||
);
|
||
|
||
NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
|
||
|
||
//
|
||
// Free up resources
|
||
//
|
||
|
||
Mlid->StatsTable->References--;
|
||
|
||
if (Mlid->StatsTable->References == 0) {
|
||
ExFreePool(Mlid->StatsTable);
|
||
}
|
||
|
||
if (Mlid->MulticastAddresses.MAAllocated != 0) {
|
||
|
||
if (Mlid->NdisMlidMedium != NdisMedium802_5) {
|
||
|
||
ExFreePool(Mlid->MulticastAddresses.Addresses);
|
||
|
||
}
|
||
|
||
ExFreePool(Mlid->MulticastAddresses.EnableCounts);
|
||
Mlid->MulticastAddresses.MAAllocated = 0;
|
||
}
|
||
|
||
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
||
|
||
NdisFreeSpinLock(&(Mlid->MlidSpinLock));
|
||
|
||
ExFreePool(Mlid);
|
||
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
NdisMlidInitializeMlids(
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine loads all ODI boards that are supposed to be loaded.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
NDIS_STATUS_SUCCESS if a single load succeeds.
|
||
NDIS_STATUS_FAILURE is no boards get loaded.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOLEAN LoadedADriver = FALSE;
|
||
PMLID_STRUCT Mlid;
|
||
|
||
PVOID OdiRegistryPtr;
|
||
PVOID NdisRegistryPtr;
|
||
|
||
UINT32 i;
|
||
|
||
|
||
//
|
||
// Find first ODI driver that is supposed to be loaded
|
||
//*\\ here - Config
|
||
|
||
//
|
||
// Find corresponding NDIS MAC Info
|
||
//*\\ here - Config
|
||
|
||
while (TRUE) {
|
||
|
||
//
|
||
// Open this MLID
|
||
//
|
||
Mlid = NdisMlidOpenMlid(OdiRegistryPtr, NdisRegistryPtr);
|
||
|
||
if (Mlid != NULL) {
|
||
|
||
//
|
||
// Do we have space in global array for this MLID
|
||
//
|
||
|
||
if (CountMlidBoards == AllocatedMlidBoards) {
|
||
|
||
//
|
||
// Allocate more space
|
||
//
|
||
|
||
Mlid = (PMLID_STRUCT)ExAllocatePool(
|
||
NonPagedPool,
|
||
sizeof(MLID_STRUCT) * (CountMlidBoards + 1)
|
||
);
|
||
|
||
if (Mlid == NULL) {
|
||
|
||
//
|
||
// No more memory available, unload opened MLID
|
||
//
|
||
|
||
NdisMlidUnloadMlid(Mlid);
|
||
|
||
return(STATUS_INSUFFICIENT_RESOURCES);
|
||
|
||
}
|
||
|
||
//
|
||
// Copy Array
|
||
//
|
||
|
||
RtlCopyMemory(Mlid, MlidBoards, sizeof(MLID_STRUCT) * CountMlidBoards);
|
||
|
||
//
|
||
// Init last cell
|
||
//
|
||
|
||
MlidBoards = Mlid;
|
||
|
||
MlidBoards[CountMlidBoards].Mlid = NULL;
|
||
MlidBoards[CountMlidBoards].BoardNumber = (UINT32)-1;
|
||
|
||
AllocatedMlidBoards++;
|
||
|
||
}
|
||
|
||
//
|
||
// Find an open index
|
||
//
|
||
|
||
for (i=0; i < AllocatedMlidBoards; i++) {
|
||
|
||
if (MlidBoards[i].Mlid == NULL) {
|
||
|
||
//
|
||
// Store into global array all info
|
||
//
|
||
|
||
MlidBoards[i].Mlid = Mlid;
|
||
MlidBoards[i].BoardNumber = Mlid->ConfigTable.MLIDCFG_BoardNumber;
|
||
MlidBoards[i].AdapterName = &(Mlid->AdapterName);
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// Set flag so we know to stay loaded.
|
||
//
|
||
LoadedADriver = TRUE;
|
||
|
||
}
|
||
|
||
//
|
||
// Get next ODI board to be loaded
|
||
//*\\ here - Config
|
||
|
||
//
|
||
// Get corresponding NDIS MAC Info
|
||
//*\\ here - Config
|
||
|
||
}
|
||
|
||
if (LoadedADriver) {
|
||
|
||
return(NDIS_STATUS_SUCCESS);
|
||
|
||
}
|
||
|
||
return(NDIS_STATUS_FAILURE);
|
||
|
||
}
|
||
|
||
|
||
PMLID_STRUCT
|
||
NdisMlidOpenMlid(
|
||
PVOID OdiRegistryPtr,
|
||
PVOID NdisRegistryPtr,
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine will create a binding from an ODI board to an NDIS MAC. If the
|
||
NDIS MAC is not yet open, it will do so.
|
||
|
||
Arguments:
|
||
|
||
OdiRegistryPtr - Pointer into the ODI registry information for this board number.
|
||
|
||
NdisRegistryPtr - Pointer into the corresponding NDIS registry for the ODI board.
|
||
|
||
Return Value:
|
||
|
||
NULL - If error, else a pointer to the MLID structure.
|
||
|
||
--*/
|
||
|
||
{
|
||
PMLID_STRUCT Mlid;
|
||
PNDISMLID_StatsTable StatsTable;
|
||
|
||
UINT32 i;
|
||
UINT32 j;
|
||
|
||
UNICODE_STRING AdapterName;
|
||
|
||
NDIS_STATUS NdisStatus;
|
||
NDIS_STATUS OpenErrorStatus;
|
||
|
||
NDIS_HANDLE NdisBindingHandle;
|
||
|
||
NDIS_MEDIUM MediumArray[] = {NdisMedium802_3, NdisMedium802_5, NdisMediumFddi };
|
||
UINT SelectedMediumIndex;
|
||
|
||
UINT32 TotalFrameSize;
|
||
UINT16 FrameID;
|
||
UINT32 NdisLinkSpeed;
|
||
UINT32 NdisMacOptions;
|
||
|
||
PCM_RESOURCE_LIST Resources;
|
||
|
||
PNDIS_REQUEST NdisMlidRequest;
|
||
|
||
//
|
||
// Allocate memory for this MLID
|
||
//
|
||
|
||
Mlid = (PMLID_STRUCT)ExAllocatePool(NonPagedPool, sizeof(MLID_STRUCT));
|
||
|
||
if (Mlid == NULL) {
|
||
|
||
return(NULL);
|
||
|
||
}
|
||
|
||
RtlZeroMemory(Mlid, sizeof(MLID_STRUCT));
|
||
|
||
//
|
||
// Allocate NDIS_REQUEST for this initialization
|
||
//
|
||
NdisMlidRequest = (PNDIS_REQUEST)ExAllocatePool(NonPagedPool, sizeof(NDIS_REQUEST));
|
||
|
||
if (NdisMlidRequest == NULL) {
|
||
|
||
goto Fail1;
|
||
|
||
}
|
||
|
||
Mlid->SendPacketPool = (NDIS_HANDLE)NULL;
|
||
Mlid->SendBufferPool = (NDIS_HANDLE)NULL;
|
||
Mlid->ReceivePacketPool = (NDIS_HANDLE)NULL;
|
||
Mlid->ReceiveBufferPool = (NDIS_HANDLE)NULL;
|
||
|
||
//
|
||
// Allocate NDIS_PACKET_POOL for sends
|
||
//
|
||
NdisAllocatePacketPool(
|
||
&NdisStatus,
|
||
&(Mlid->SendPacketPool),
|
||
NDISMLID_SENDS_PER_MLID,
|
||
sizeof(MLID_RESERVED)
|
||
);
|
||
|
||
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
||
|
||
goto Fail2;
|
||
|
||
}
|
||
|
||
//
|
||
// Allocate NDIS_BUFFER_POOL for sends
|
||
//
|
||
NdisAllocateBufferPool(
|
||
&NdisStatus,
|
||
&(Mlid->SendBufferPool),
|
||
NDISMLID_SENDS_PER_MLID * NDISMLID_BUFFERS_PER_PACKET
|
||
);
|
||
|
||
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
||
|
||
goto Fail2;
|
||
|
||
}
|
||
|
||
//
|
||
// Set LSLFunctionList here
|
||
//*\\ here - How do I get the LSLFunctionList?
|
||
|
||
//
|
||
// Fail if count of functions is not enough, or if LSL version number is
|
||
// incorrect
|
||
//*\\ here - Implement check of LSLFunctionList.
|
||
|
||
//
|
||
// Open Send stage
|
||
//
|
||
Mlid->StageOpen = TRUE;
|
||
|
||
//
|
||
|
||
// Initialize completion event
|
||
//
|
||
KeInitializeEvent(
|
||
&(Mlid->MlidRequestCompleteEvent),
|
||
NotificationEvent,
|
||
FALSE
|
||
);
|
||
|
||
Mlid->UsingEvent = TRUE;
|
||
|
||
//
|
||
// Get name of NDIS MAC from registry
|
||
//*\\ here - Config
|
||
|
||
|
||
//
|
||
// Call NdisOpenAdapter
|
||
//
|
||
NdisOpenAdapter(
|
||
&NdisStatus,
|
||
&OpenErrorStatus,
|
||
&NdisBindingHandle,
|
||
&SelectedMediumIndex,
|
||
MediumArray,
|
||
3,
|
||
NdisMlidProtocolHandle,
|
||
(NDIS_HANDLE)Mlid,
|
||
(PNDIS_STRING)(&AdapterName),
|
||
0,
|
||
NULL
|
||
);
|
||
|
||
//
|
||
// if (pending), wait
|
||
//
|
||
if (NdisStatus == NDIS_STATUS_PENDING) {
|
||
|
||
|
||
//
|
||
// Wait for open to complete
|
||
//
|
||
|
||
KeWaitForSingleObject(
|
||
&(Mlid->MlidRequestCompleteEvent),
|
||
Executive,
|
||
KernelMode,
|
||
TRUE,
|
||
(PTIME)NULL
|
||
);
|
||
|
||
KeResetEvent(&Mlid->MlidRequestCompleteEvent);
|
||
|
||
//
|
||
// Get status
|
||
//
|
||
|
||
NdisStatus = (NDIS_STATUS)(Mlid->RequestStatus);
|
||
|
||
}
|
||
|
||
//
|
||
// If failure, release resources
|
||
//
|
||
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
||
|
||
goto Fail1;
|
||
|
||
}
|
||
|
||
//
|
||
// Save Media type
|
||
//
|
||
Mlid->NdisMlidMedium = MediumArray[SelectedMediumIndex];
|
||
|
||
//
|
||
// Save Ndis MAC context
|
||
//
|
||
Mlid->NdisBindingHandle = NdisBindingHandle;
|
||
|
||
//
|
||
// Is NDIS MAC not already opened by another MLID?
|
||
//
|
||
for (i=0; i < AllocatedMlidBoards ; i++ ) {
|
||
|
||
if (MlidBoards[i].Mlid != NULL) {
|
||
|
||
//
|
||
// Are the names the same?
|
||
//
|
||
|
||
if (RtlEqualUnicodeString(&AdapterName, MlidBoards[i].AdapterName, TRUE)) {
|
||
|
||
//
|
||
// Store stat table pointer
|
||
//
|
||
|
||
StatsTable = (MlidBoards[i].Mlid)->StatsTable;
|
||
break;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// Did we find an NDIS MAC?
|
||
//
|
||
|
||
if (StatsTable == NULL) {
|
||
|
||
//
|
||
// Allocate memory for the MLID Statistic table
|
||
//
|
||
|
||
StatsTable = (PNDISMLID_StatsTable)ExAllocatePool(NonPagedPool,
|
||
sizeof(NDISMLID_StatsTable)
|
||
);
|
||
|
||
if (StatsTable == NULL) {
|
||
|
||
//
|
||
// Fail
|
||
//
|
||
|
||
goto Fail3;
|
||
|
||
}
|
||
|
||
//
|
||
// Initialize structure
|
||
//
|
||
|
||
RtlZeroMemory(StatsTable, sizeof(NDISMLID_StatsTable));
|
||
|
||
StatsTable->StatsTable.MStatTableMajorVer = 1;
|
||
StatsTable->StatsTable.MStatTableMinorVer = 0;
|
||
|
||
//
|
||
// Setup Generic counters
|
||
//
|
||
for (i = 0; i < NUM_GENERIC_COUNTS; i++) {
|
||
|
||
StatsTable->MLID_GenericCounts[i].StatString = &(NdisMlidGenericStatStrings[i]);
|
||
StatsTable->MLID_GenericCounts[i].StatUseFlag = NdisMlidGenericStatTypes[i];
|
||
StatsTable->MLID_GenericCounts[i].StatCounter = (PVOID)(&StatsTable->GenericCounts[i]);
|
||
|
||
}
|
||
|
||
StatsTable->StatsTable.MNumGenericCounters = NUM_GENERIC_COUNTS;
|
||
StatsTable->StatsTable.MGenericCountsPtr = &(StatsTable->MLID_GenericCounts);
|
||
|
||
//
|
||
// Setup Medium specific counters
|
||
//
|
||
switch (Mlid->NdisMlidMedium) {
|
||
|
||
case NdisMedium802_3:
|
||
|
||
for (i = 0; i < NUM_ETHERNET_COUNTS; i++) {
|
||
|
||
StatsTable->MLID_MediaCounts[i].StatString = &(NdisMlidEthernetStatStrings[i]);
|
||
StatsTable->MLID_MediaCounts[i].StatUseFlag = NdisMlidEthernetStatTypes[i];
|
||
StatsTable->MLID_MediaCounts[i].StatCounter = (PVOID)(&StatsTable->MediaCounts[i]);
|
||
|
||
}
|
||
|
||
StatsTable->StatsTable.MNumMediaCounters = NUM_ETHERNET_COUNTS;
|
||
StatsTable->StatsTable.MMediaCountsPtr = &(StatsTable->MLID_MediaCounts);
|
||
|
||
break;
|
||
|
||
case NdisMedium802_5:
|
||
|
||
for (i = 0; i < NUM_TOKEN_RING_COUNTS; i++) {
|
||
|
||
StatsTable->MLID_MediaCounts[i].StatString = &(NdisMlidTokenRingStatStrings[i]);
|
||
StatsTable->MLID_MediaCounts[i].StatUseFlag = NdisMlidTokenRingStatTypes[i];
|
||
StatsTable->MLID_MediaCounts[i].StatCounter = (PVOID)(&StatsTable->MediaCounts[i]);
|
||
|
||
}
|
||
|
||
StatsTable->StatsTable.MNumMediaCounters = NUM_TOKEN_RING_COUNTS;
|
||
StatsTable->StatsTable.MMediaCountsPtr = &(StatsTable->MLID_MediaCounts);
|
||
|
||
break;
|
||
|
||
case NdisMediumFddi:
|
||
|
||
for (i = 0; i < NUM_FDDI_COUNTS; i++) {
|
||
|
||
StatsTable->MLID_MediaCounts[i].StatString = &(NdisMlidFddiStatStrings[i]);
|
||
StatsTable->MLID_MediaCounts[i].StatUseFlag = NdisMlidFddiStatTypes[i];
|
||
StatsTable->MLID_MediaCounts[i].StatCounter = (PVOID)(&StatsTable->MediaCounts[i]);
|
||
|
||
}
|
||
|
||
StatsTable->StatsTable.MNumMediaCounters = NUM_FDDI_COUNTS;
|
||
StatsTable->StatsTable.MMediaCountsPtr = &(StatsTable->MLID_MediaCounts);
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// Link statistic table
|
||
//
|
||
Mlid->StatsTable = StatsTable;
|
||
|
||
//
|
||
// Increment reference count
|
||
//
|
||
StatsTable->References++;
|
||
|
||
//
|
||
// Get network address
|
||
//
|
||
NdisMlidRequest->RequestType = NdisRequestQueryInformation;
|
||
|
||
switch (Mlid->NdisMlidMedium) {
|
||
|
||
case NdisMedium802_3:
|
||
NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_802_3_CURRENT_ADDRESS;
|
||
break;
|
||
|
||
case NdisMedium802_5:
|
||
NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_802_5_CURRENT_ADDRESS;
|
||
break;
|
||
|
||
case NdisMediumFddi:
|
||
NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_FDDI_LONG_CURRENT_ADDR;
|
||
break;
|
||
|
||
}
|
||
|
||
NdisMlidRequest->DATA.QUERY_INFORMATION.InformationBuffer = (PVOID)&(Mlid->ConfigTable.MLIDCFG_NodeAddress[0]);
|
||
NdisMlidRequest->DATA.QUERY_INFORMATION.InformationBufferLength = 6;
|
||
NdisMlidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
|
||
NdisMlidRequest->DATA.QUERY_INFORMATION.BytesNeeded = 0;
|
||
|
||
|
||
NdisRequest(
|
||
&NdisStatus,
|
||
Mlid->NdisBindingHandle,
|
||
NdisMlidRequest
|
||
);
|
||
|
||
//
|
||
// if (pending), wait
|
||
//
|
||
|
||
if (NdisStatus == NDIS_STATUS_PENDING) {
|
||
|
||
//
|
||
// Wait for request to complete
|
||
//
|
||
|
||
KeWaitForSingleObject(
|
||
&(Mlid->MlidRequestCompleteEvent),
|
||
Executive,
|
||
KernelMode,
|
||
TRUE,
|
||
(PTIME)NULL
|
||
);
|
||
|
||
KeResetEvent(&Mlid->MlidRequestCompleteEvent);
|
||
|
||
//
|
||
// Get status
|
||
//
|
||
NdisStatus = (NDIS_STATUS)Mlid->RequestStatus;
|
||
|
||
}
|
||
|
||
//
|
||
// If failure, release resources and close adapter
|
||
//
|
||
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
||
goto Fail4;
|
||
}
|
||
|
||
|
||
//
|
||
// Get FrameID for this MLID from registry, check that it is one we support.
|
||
//*\\ here - Config
|
||
|
||
|
||
//
|
||
// Get maximum total frame size
|
||
//
|
||
NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE;
|
||
NdisMlidRequest->DATA.QUERY_INFORMATION.InformationBuffer = (PVOID)&(TotalFrameSize);
|
||
NdisMlidRequest->DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(TotalFrameSize);
|
||
NdisMlidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
|
||
NdisMlidRequest->DATA.QUERY_INFORMATION.BytesNeeded = 0;
|
||
|
||
NdisRequest(
|
||
&NdisStatus,
|
||
Mlid->NdisBindingHandle,
|
||
NdisMlidRequest
|
||
);
|
||
|
||
//
|
||
// if (pending), wait
|
||
//
|
||
|
||
if (NdisStatus == NDIS_STATUS_PENDING) {
|
||
|
||
//
|
||
// Wait for request to complete
|
||
//
|
||
|
||
KeWaitForSingleObject(
|
||
&(Mlid->MlidRequestCompleteEvent),
|
||
Executive,
|
||
KernelMode,
|
||
TRUE,
|
||
(PTIME)NULL
|
||
);
|
||
|
||
KeResetEvent(&Mlid->MlidRequestCompleteEvent);
|
||
|
||
//
|
||
// Get status
|
||
//
|
||
NdisStatus = (NDIS_STATUS)Mlid->RequestStatus;
|
||
|
||
}
|
||
|
||
//
|
||
// If failure, release resources and close adapter
|
||
//
|
||
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
||
goto Fail4;
|
||
}
|
||
|
||
|
||
//
|
||
// Get link speed
|
||
//
|
||
NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_GEN_LINK_SPEED;
|
||
NdisMlidRequest->DATA.QUERY_INFORMATION.InformationBuffer = (PVOID)&(NdisLinkSpeed);
|
||
NdisMlidRequest->DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(NdisLinkSpeed);
|
||
NdisMlidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
|
||
NdisMlidRequest->DATA.QUERY_INFORMATION.BytesNeeded = 0;
|
||
|
||
NdisRequest(
|
||
&NdisStatus,
|
||
Mlid->NdisBindingHandle,
|
||
NdisMlidRequest
|
||
);
|
||
|
||
//
|
||
// if (pending), wait
|
||
//
|
||
|
||
if (NdisStatus == NDIS_STATUS_PENDING) {
|
||
|
||
//
|
||
// Wait for request to complete
|
||
//
|
||
|
||
KeWaitForSingleObject(
|
||
&(Mlid->MlidRequestCompleteEvent),
|
||
Executive,
|
||
KernelMode,
|
||
TRUE,
|
||
(PTIME)NULL
|
||
);
|
||
|
||
KeResetEvent(&Mlid->MlidRequestCompleteEvent);
|
||
|
||
//
|
||
// Get status
|
||
//
|
||
NdisStatus = (NDIS_STATUS)Mlid->RequestStatus;
|
||
|
||
}
|
||
|
||
//
|
||
// If failure, release resources and close adapter
|
||
//
|
||
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
||
goto Fail4;
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// Get MAC_OPTIONS
|
||
//
|
||
NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_GEN_MAC_OPTIONS;
|
||
NdisMlidRequest->DATA.QUERY_INFORMATION.InformationBuffer = (PVOID)&(NdisMacOptions);
|
||
NdisMlidRequest->DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(NdisMacOptions);
|
||
NdisMlidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
|
||
NdisMlidRequest->DATA.QUERY_INFORMATION.BytesNeeded = 0;
|
||
|
||
NdisRequest(
|
||
&NdisStatus,
|
||
Mlid->NdisBindingHandle,
|
||
NdisMlidRequest
|
||
);
|
||
|
||
//
|
||
// if (pending), wait
|
||
//
|
||
|
||
if (NdisStatus == NDIS_STATUS_PENDING) {
|
||
|
||
//
|
||
// Wait for request to complete
|
||
//
|
||
|
||
KeWaitForSingleObject(
|
||
&(Mlid->MlidRequestCompleteEvent),
|
||
Executive,
|
||
KernelMode,
|
||
TRUE,
|
||
(PTIME)NULL
|
||
);
|
||
|
||
KeResetEvent(&Mlid->MlidRequestCompleteEvent);
|
||
|
||
//
|
||
// Get status
|
||
//
|
||
NdisStatus = (NDIS_STATUS)Mlid->RequestStatus;
|
||
|
||
}
|
||
|
||
//
|
||
// If failure, release resources and close adapter
|
||
//
|
||
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
||
goto Fail4;
|
||
}
|
||
|
||
|
||
if ((NdisMacOptions & NDIS_MAC_OPTION_RECEIVE_SERIALIZED) &&
|
||
(NdisMacOptions & NDIS_MAC_OPTION_TRANSFERS_NOT_PEND)) {
|
||
|
||
//
|
||
// Allocate NDIS_PACKET_POOL for receives
|
||
//
|
||
|
||
NdisAllocatePacketPool(
|
||
&NdisStatus,
|
||
&(Mlid->ReceivePacketPool),
|
||
1,
|
||
sizeof(MLID_RESERVED)
|
||
);
|
||
|
||
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
||
|
||
goto Fail4;
|
||
|
||
}
|
||
|
||
//
|
||
// Allocate NDIS_BUFFER_POOL for receives
|
||
// NOTE: In this case I added a huge number of NDIS_BUFFERS, since
|
||
// we only have one packet we need to be liberal in our guess of
|
||
// BUFFERs per PACKET.
|
||
//
|
||
NdisAllocateBufferPool(
|
||
&NdisStatus,
|
||
&(Mlid->ReceiveBufferPool),
|
||
NDISMLID_BUFFERS_PER_PACKET + 10
|
||
);
|
||
|
||
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
||
|
||
goto Fail4;
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// Allocate NDIS_PACKET_POOL for receives
|
||
//
|
||
NdisAllocatePacketPool(
|
||
&NdisStatus,
|
||
&(Mlid->ReceivePacketPool),
|
||
NDISMLID_RECEIVES_PER_MLID,
|
||
sizeof(MLID_RESERVED)
|
||
);
|
||
|
||
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
||
|
||
goto Fail4;
|
||
|
||
}
|
||
|
||
//
|
||
// Allocate NDIS_BUFFER_POOL for receives
|
||
//
|
||
NdisAllocateBufferPool(
|
||
&NdisStatus,
|
||
&(Mlid->ReceiveBufferPool),
|
||
NDISMLID_RECEIVES_PER_MLID * NDISMLID_BUFFERS_PER_PACKET + 5
|
||
);
|
||
|
||
if (NdisStatus != NDIS_STATUS_SUCCESS) {
|
||
|
||
goto Fail4;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// Begin Init ConfigTable.
|
||
//
|
||
|
||
|
||
RtlCopyMemory(&(Mlid->ConfigTable.MLIDCFG_Signature[0]),
|
||
"HardwareDriverMLID ",
|
||
26
|
||
);
|
||
|
||
Mlid->ConfigTable.MLIDCFG_MajorVersion = 1;
|
||
Mlid->ConfigTable.MLIDCFG_MinorVersion = 12;
|
||
Mlid->ConfigTable.MLIDCFG_ModeFlags = 0x24C9; // PromiscuousBit |
|
||
// SupFragECB |
|
||
// SupFrameDataSize |
|
||
// RawSend |
|
||
// RealDriver |
|
||
// MulticastBit
|
||
|
||
Mlid->ConfigTable.MLIDCFG_BoardNumber = (UINT16)-1;
|
||
Mlid->ConfigTable.MLIDCFG_BoardInstance = 1; //*\\ Should this change?
|
||
Mlid->ConfigTable.MLIDCFG_MaxFrameSize = TotalFrameSize;
|
||
|
||
switch (FrameID) {
|
||
|
||
case ETHERNET_II_FRAME_ID:
|
||
|
||
Mlid->ConfigTable.MLIDCFG_BestDataSize = TotalFrameSize - sizeof(Ethernet_II_Header);
|
||
Mlid->ConfigTable.MLIDCFG_WorstDataSize = TotalFrameSize - sizeof(Ethernet_II_Header);
|
||
break;
|
||
|
||
case ETHERNET_802_2_FRAME_ID:
|
||
|
||
Mlid->ConfigTable.MLIDCFG_BestDataSize = TotalFrameSize - sizeof(Ethernet_802_2_Header);
|
||
Mlid->ConfigTable.MLIDCFG_WorstDataSize = TotalFrameSize - sizeof(Ethernet_802_2_Header);
|
||
break;
|
||
|
||
case ETHERNET_802_3_FRAME_ID:
|
||
|
||
Mlid->ConfigTable.MLIDCFG_BestDataSize = TotalFrameSize - sizeof(Ethernet_802_3_Header);
|
||
Mlid->ConfigTable.MLIDCFG_WorstDataSize = TotalFrameSize - sizeof(Ethernet_802_3_Header);
|
||
break;
|
||
|
||
case ETHERNET_SNAP_FRAME_ID:
|
||
|
||
Mlid->ConfigTable.MLIDCFG_BestDataSize = TotalFrameSize - sizeof(Ethernet_Snap_Header);
|
||
Mlid->ConfigTable.MLIDCFG_WorstDataSize = TotalFrameSize - sizeof(Ethernet_Snap_Header);
|
||
break;
|
||
|
||
case FDDI_802_2_FRAME_ID:
|
||
|
||
Mlid->ConfigTable.MLIDCFG_BestDataSize = TotalFrameSize - sizeof(Fddi_802_2_Header);
|
||
Mlid->ConfigTable.MLIDCFG_WorstDataSize = TotalFrameSize - sizeof(Fddi_802_2_Header);
|
||
break;
|
||
|
||
case FDDI_SNAP_FRAME_ID:
|
||
|
||
Mlid->ConfigTable.MLIDCFG_BestDataSize = TotalFrameSize - sizeof(Fddi_Snap_Header);
|
||
Mlid->ConfigTable.MLIDCFG_WorstDataSize = TotalFrameSize - sizeof(Fddi_Snap_Header);
|
||
break;
|
||
|
||
case TOKEN_RING_SNAP_FRAME_ID:
|
||
|
||
Mlid->ConfigTable.MLIDCFG_BestDataSize = TotalFrameSize - sizeof(TokenRing_Header) - 8;
|
||
Mlid->ConfigTable.MLIDCFG_WorstDataSize = TotalFrameSize - sizeof(TokenRing_Header) - 26;
|
||
break;
|
||
|
||
case TOKEN_RING_802_2_FRAME_ID:
|
||
|
||
Mlid->ConfigTable.MLIDCFG_BestDataSize = TotalFrameSize - sizeof(TokenRing_Header) - 3;
|
||
Mlid->ConfigTable.MLIDCFG_WorstDataSize = TotalFrameSize - sizeof(TokenRing_Header) - 21;
|
||
break;
|
||
|
||
default:
|
||
|
||
//
|
||
// Invalid frame type. We should have already checked this.
|
||
//
|
||
ASSERT(0);
|
||
|
||
}
|
||
|
||
Mlid->ConfigTable.MLIDCFG_CardName = NULL; //*\\ here
|
||
Mlid->ConfigTable.MLIDCFG_ShortName = NULL; //*\\ here
|
||
Mlid->ConfigTable.MLIDCFG_FrameTypeString = &(NdisMlidFrameTypeStrings[FrameID]);
|
||
Mlid->ConfigTable.MLIDCFG_FrameID = FrameID;
|
||
Mlid->ConfigTable.MLIDCFG_TransportTime = (0x1000 / (NdisLinkSpeed / 10)) + 1;
|
||
Mlid->ConfigTable.MLIDCFG_SourceRouting = (PVOID)NULL;
|
||
Mlid->ConfigTable.MLIDCFG_LookAheadSize = 18;
|
||
|
||
//
|
||
// Convert to KBits/Second.
|
||
//
|
||
NdisLinkSpeed /= 10;
|
||
|
||
//
|
||
// Check if we can store it like this.
|
||
//
|
||
if (NdisLinkSpeed > 0x7FFF) {
|
||
|
||
//
|
||
// Convert to MBits/Second
|
||
//
|
||
|
||
NdisLinkSpeed /= 1000;
|
||
|
||
} else {
|
||
|
||
NdisLinkSpeed |= 0x8000;
|
||
|
||
}
|
||
|
||
Mlid->ConfigTable.MLIDCFG_LineSpeed = NdisLinkSpeed;
|
||
Mlid->ConfigTable.MLIDCFG_DriverMajorVer = 3;
|
||
Mlid->ConfigTable.MLIDCFG_DriverMinorVer = 0;
|
||
Mlid->ConfigTable.MLIDCFG_Flags = 0x600; // Adapter does group address filtering
|
||
Mlid->ConfigTable.MLIDCFG_SendRetries = (Mlid->NdisMlidMedium == NdisMedium802_3) ? 10 : 0;
|
||
Mlid->ConfigTable.MLIDCFG_Slot = 0; //*\\ change for EISA and MCA cards.
|
||
|
||
//
|
||
// Now we grunge through NDIS structures to get IoPort infor, Memory Info, DMA info
|
||
// and interrupt info.
|
||
//
|
||
Resources = ((PNDIS_OPEN_BLOCK)NdisBindingHandle)->AdapterHandle->Resources;
|
||
|
||
//
|
||
// First do port information
|
||
//
|
||
{
|
||
BOOLEAN TooManyPorts = FALSE;
|
||
|
||
for (i = 0; i < Resources->Count; i++) {
|
||
|
||
for (j=0; j < Resources->List[0].PartialResourceList.Count; j++) {
|
||
|
||
if (Resources->List[0].PartialResourceList.PartialDescriptors[j].Type ==
|
||
CmResourceTypePort) {
|
||
|
||
//
|
||
// Found a port
|
||
//
|
||
|
||
if (!TooManyPorts) {
|
||
|
||
TooManyPorts = TRUE;
|
||
|
||
//
|
||
// Store in Port0 holder
|
||
//
|
||
Mlid->ConfigTable.MLIDCFG_IOPort0 = (UINT16)(
|
||
Resources->List[0].PartialResourceList.PartialDescriptors[j].u.Port.Start.LowPart);
|
||
|
||
Mlid->ConfigTable.MLIDCFG_IORange0 = (UINT16)(
|
||
Resources->List[0].PartialResourceList.PartialDescriptors[j].u.Port.Length);
|
||
|
||
} else {
|
||
|
||
//
|
||
// Store in Port1 holder and exit port.
|
||
//
|
||
Mlid->ConfigTable.MLIDCFG_IOPort1 = (UINT16)(
|
||
Resources->List[0].PartialResourceList.PartialDescriptors[j].u.Port.Start.LowPart);
|
||
|
||
Mlid->ConfigTable.MLIDCFG_IORange1 = (UINT16)(
|
||
Resources->List[0].PartialResourceList.PartialDescriptors[j].u.Port.Length);
|
||
|
||
i = Resources->Count;
|
||
break;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// Now do memory information
|
||
//
|
||
{
|
||
BOOLEAN TooManyMemorys = FALSE;
|
||
|
||
for (i = 0; i < Resources->Count; i++) {
|
||
|
||
for (j=0; j < Resources->List[0].PartialResourceList.Count; j++) {
|
||
|
||
if (Resources->List[0].PartialResourceList.PartialDescriptors[j].Type ==
|
||
CmResourceTypeMemory) {
|
||
|
||
//
|
||
// Found memory
|
||
//
|
||
|
||
if (!TooManyMemorys) {
|
||
|
||
TooManyMemorys = TRUE;
|
||
|
||
//
|
||
// Store in Memory0 holder
|
||
//
|
||
Mlid->ConfigTable.MLIDCFG_MemoryAddress0 = (UINT32)(
|
||
Resources->List[0].PartialResourceList.PartialDescriptors[j].u.Memory.Start.LowPart);
|
||
|
||
Mlid->ConfigTable.MLIDCFG_MemorySize0 = (UINT16)(
|
||
Resources->List[0].PartialResourceList.PartialDescriptors[j].u.Memory.Length / 16);
|
||
|
||
} else {
|
||
|
||
//
|
||
// Store in Memory1 holder and exit.
|
||
//
|
||
Mlid->ConfigTable.MLIDCFG_MemoryAddress1 = (UINT32)(
|
||
Resources->List[0].PartialResourceList.PartialDescriptors[j].u.Memory.Start.LowPart);
|
||
|
||
Mlid->ConfigTable.MLIDCFG_MemorySize1 = (UINT16)(
|
||
Resources->List[0].PartialResourceList.PartialDescriptors[j].u.Memory.Length / 16);
|
||
|
||
i = Resources->Count;
|
||
break;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
//
|
||
// Now do interrupts
|
||
//
|
||
{
|
||
BOOLEAN TooManyInterrupts = FALSE;
|
||
|
||
for (i = 0; i < Resources->Count; i++) {
|
||
|
||
for (j=0; j < Resources->List[0].PartialResourceList.Count; j++) {
|
||
|
||
if (Resources->List[0].PartialResourceList.PartialDescriptors[j].Type ==
|
||
CmResourceTypeInterrupt) {
|
||
|
||
//
|
||
// Found interrupt
|
||
//
|
||
|
||
if (!TooManyInterrupts) {
|
||
|
||
TooManyInterrupts = TRUE;
|
||
|
||
//
|
||
// Store in Interrupt0 holder
|
||
//
|
||
Mlid->ConfigTable.MLIDCFG_Interrupt0 = (UINT8)(
|
||
Resources->List[0].PartialResourceList.PartialDescriptors[j].u.Interrupt.Level);
|
||
|
||
if (Resources->List[0].PartialResourceList.PartialDescriptors[j].ShareDisposition ==
|
||
CmResourceShareShared) {
|
||
|
||
Mlid->ConfigTable.MLIDCFG_SharingFlags |= 0x20;
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// Store in Interrupt1 holder and exit.
|
||
//
|
||
Mlid->ConfigTable.MLIDCFG_Interrupt1 = (UINT8)(
|
||
Resources->List[0].PartialResourceList.PartialDescriptors[j].u.Interrupt.Level);
|
||
|
||
if (Resources->List[0].PartialResourceList.PartialDescriptors[j].ShareDisposition ==
|
||
CmResourceShareShared) {
|
||
|
||
Mlid->ConfigTable.MLIDCFG_SharingFlags |= 0x40;
|
||
|
||
}
|
||
|
||
i = Resources->Count;
|
||
break;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// Now do DMA channels
|
||
//
|
||
{
|
||
BOOLEAN TooManyDMAs = FALSE;
|
||
|
||
for (i = 0; i < Resources->Count; i++) {
|
||
|
||
for (j=0; j < Resources->List[0].PartialResourceList.Count; j++) {
|
||
|
||
if (Resources->List[0].PartialResourceList.PartialDescriptors[j].Type ==
|
||
CmResourceTypeDma) {
|
||
|
||
//
|
||
// Found DMA Channel
|
||
//
|
||
|
||
if (!TooManyDMAs) {
|
||
|
||
TooManyDMAs = TRUE;
|
||
|
||
//
|
||
// Store in DMALine0 holder
|
||
//
|
||
Mlid->ConfigTable.MLIDCFG_DMALine0 = (UINT8)(
|
||
Resources->List[0].PartialResourceList.PartialDescriptors[j].u.Dma.Channel);
|
||
|
||
} else {
|
||
|
||
//
|
||
// Store in DMALine1 holder and exit.
|
||
//
|
||
Mlid->ConfigTable.MLIDCFG_DMALine1 = (UINT8)(
|
||
Resources->List[0].PartialResourceList.PartialDescriptors[j].u.Dma.Channel);
|
||
|
||
i = Resources->Count;
|
||
break;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
Mlid->ConfigTable.MLIDCFG_ResourceTag = 0;
|
||
|
||
|
||
//
|
||
// End of initialize ConfigTable.
|
||
//
|
||
|
||
|
||
|
||
|
||
|
||
//
|
||
// Register with LSL
|
||
//
|
||
|
||
(*(Mlid->LSLFunctionList->SupportAPIArray[RegisterMLID_INDEX]))(
|
||
NdisMlidHandlerInfo,
|
||
&(Mlid->ConfigTable),
|
||
&(Mlid->BoardNumber)
|
||
);
|
||
|
||
Mlid->UsingEvent = FALSE;
|
||
|
||
//
|
||
// Setup default packet filters
|
||
//
|
||
|
||
Mlid->RequestStatus = NDIS_STATUS_PENDING;
|
||
|
||
ASSERT(sizeof(TotalFrameSize) == 4);
|
||
|
||
TotalFrameSize = NDIS_PACKET_TYPE_DIRECTED |
|
||
NDIS_PACKET_TYPE_MULTICAST |
|
||
NDIS_PACKET_TYPE_BROADCAST;
|
||
|
||
NdisMlidRequest->DATA.SET_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
|
||
NdisMlidRequest->DATA.SET_INFORMATION.InformationBuffer = (PVOID)&(TotalFrameSize);
|
||
NdisMlidRequest->DATA.SET_INFORMATION.InformationBufferLength = sizeof(TotalFrameSize);
|
||
NdisMlidRequest->DATA.SET_INFORMATION.BytesRead = 0;
|
||
NdisMlidRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
|
||
|
||
NdisRequest(
|
||
&NdisStatus,
|
||
Mlid->NdisBindingHandle,
|
||
NdisMlidRequest
|
||
);
|
||
|
||
if (NdisStatus == NDIS_STATUS_PENDING) {
|
||
|
||
//
|
||
// Get status and Semaphore is release inside RequestCompleteHandler
|
||
//
|
||
NdisStatus = (NDIS_STATUS)Mlid->RequestStatus;
|
||
|
||
} else {
|
||
|
||
ExFreePool(NdisMlidRequest);
|
||
|
||
}
|
||
|
||
//
|
||
// If failure, release resources and close adapter
|
||
//
|
||
if ((NdisStatus != NDIS_STATUS_SUCCESS) &&
|
||
(NdisStatus != NDIS_STATUS_PENDING)) {
|
||
|
||
goto Fail5;
|
||
|
||
}
|
||
|
||
//
|
||
// Time stamp the sucker
|
||
//
|
||
{
|
||
LARGE_INTEGER TimeStamp;
|
||
|
||
KeQuerySystemTime(&TimeStamp);
|
||
(*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[13].StatCounter))) = // MAdapterOprTimeStamp
|
||
TimeStamp.LowPart;
|
||
|
||
}
|
||
|
||
NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
|
||
|
||
if (Mlid->StatsTable->StatisticsOperational == FALSE) {
|
||
|
||
//
|
||
// Start the statistics timer
|
||
//
|
||
Mlid->StatsTable->StatisticsOperational = TRUE;
|
||
|
||
NdisInitializeTimer(&(Mlid->StatsTable->StatisticTimer),
|
||
NdisMlidStatisticTimer,
|
||
Mlid
|
||
);
|
||
|
||
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
||
|
||
NdisSetTimer(&(Mlid->StatsTable->StatisticTimer), 30000);
|
||
|
||
NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
|
||
|
||
}
|
||
|
||
Mlid->NdisPacketFilterValue = NDIS_PACKET_TYPE_DIRECTED |
|
||
NDIS_PACKET_TYPE_MULTICAST |
|
||
NDIS_PACKET_TYPE_BROADCAST;
|
||
|
||
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
|
||
|
||
return(Mlid);
|
||
|
||
Fail5:
|
||
//
|
||
// Deregister with LSL
|
||
//
|
||
(*(Mlid->LSLFunctionList->SupportAPIArray[DeRegisterMLID_INDEX]))(
|
||
Mlid->ConfigTable.MLIDCFG_BoardNumber
|
||
);
|
||
|
||
Fail4:
|
||
//
|
||
// Free Receive packet pool
|
||
//
|
||
if (Mlid->ReceivePacketPool != (NDIS_HANDLE)NULL) {
|
||
NdisFreePacketPool(Mlid->ReceivePacketPool);
|
||
}
|
||
|
||
//
|
||
// Free Receive buffer pool
|
||
//
|
||
if (Mlid->ReceiveBufferPool != (NDIS_HANDLE)NULL) {
|
||
NdisFreeBufferPool(Mlid->ReceiveBufferPool);
|
||
}
|
||
|
||
//
|
||
// Free StatsTable
|
||
//
|
||
StatsTable->References--;
|
||
if (StatsTable->References == 0) {
|
||
ExFreePool(StatsTable);
|
||
}
|
||
|
||
Fail3:
|
||
//
|
||
// Close Adapter
|
||
//
|
||
NdisCloseAdapter(&NdisStatus, Mlid->NdisBindingHandle);
|
||
|
||
//
|
||
// If pend, wait
|
||
//
|
||
|
||
if (NdisStatus == NDIS_STATUS_PENDING) {
|
||
|
||
//
|
||
// Wait for close to complete
|
||
//
|
||
|
||
KeWaitForSingleObject(
|
||
&(Mlid->MlidRequestCompleteEvent),
|
||
Executive,
|
||
KernelMode,
|
||
TRUE,
|
||
(PTIME)NULL
|
||
);
|
||
|
||
KeResetEvent(&Mlid->MlidRequestCompleteEvent);
|
||
|
||
}
|
||
|
||
Fail2:
|
||
|
||
//
|
||
// Free Send packet pool
|
||
//
|
||
if (Mlid->SendPacketPool != (NDIS_HANDLE)NULL) {
|
||
NdisFreePacketPool(Mlid->SendPacketPool);
|
||
}
|
||
|
||
//
|
||
// Free Send buffer pool
|
||
//
|
||
if (Mlid->SendBufferPool != (NDIS_HANDLE)NULL) {
|
||
NdisFreeBufferPool(Mlid->SendBufferPool);
|
||
}
|
||
|
||
//
|
||
// Free NDIS_REQUEST
|
||
//
|
||
if (Mlid->UsingEvent) {
|
||
ExFreePool(NdisMlidRequest);
|
||
}
|
||
|
||
Fail1:
|
||
|
||
//
|
||
// Free Mlid structure
|
||
//
|
||
ExFreePool(Mlid);
|
||
|
||
return(NULL);
|
||
|
||
}
|
||
|