|
|
/*++
Copyright (c) 1990-1995 Microsoft Corporation
Module Name:
Miniport.c
Abstract:
This file contains the procedures that makeup most of the NDIS 3.1 Miniport interface.
Author:
Tony Bell (TonyBe) June 06, 1995
Environment:
Kernel Mode
Revision History:
TonyBe 06/06/95 Created
--*/
#include "wan.h"
#define __FILE_SIG__ MINIPORT_FILESIG
//
// Local function prototypes
//
//
// End local function prototypes
//
VOID MPHalt( IN NDIS_HANDLE MiniportAdapterContext ) /*++
Routine Name:
MPHalt
Routine Description:
This routine free's all resources for the adapter.
Arguments:
MiniportAdapterContext - AdapterContext that is given to the wrapper in NdisMSetAttributes call. Is our MiniportCB.
Return Values:
None
--*/ { PMINIPORTCB MiniportCB = (PMINIPORTCB)MiniportAdapterContext;
NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MPHalt: Enter")); NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MiniportCB: 0x%x", MiniportCB));
//
// Make sure that there are no ProtocolCB's
// running over this miniport! If so we
// need to do a linedown to them.
//
NdisAcquireSpinLock(&MiniportCB->Lock);
MiniportCB->Flags |= HALT_IN_PROGRESS;
while (!IsListEmpty(&MiniportCB->ProtocolCBList)) { PLIST_ENTRY le; PPROTOCOLCB ProtocolCB; PBUNDLECB BundleCB; ProtocolState OldState;
le = MiniportCB->ProtocolCBList.Flink;
ProtocolCB =(PPROTOCOLCB) CONTAINING_RECORD(le, PROTOCOLCB, MiniportLinkage);
NdisReleaseSpinLock(&MiniportCB->Lock);
BundleCB = ProtocolCB->BundleCB;
AcquireBundleLock(BundleCB);
OldState = ProtocolCB->State;
ProtocolCB->State = PROTOCOL_UNROUTING; BundleCB->SendMask &= ~ProtocolCB->SendMaskBit; //
// Flush the protocol packet queues. This could cause us
// to complete frames to ndis out of order. Ndis should
// handle this.
//
FlushProtocolPacketQueue(ProtocolCB); //
// If the protocols refcount goes to zero
// we need to do a linedown and cleanup
//
if ((--ProtocolCB->RefCount == 0) && (OldState == PROTOCOL_ROUTED)) {
DoLineDownToProtocol(ProtocolCB);
//
// Returns with bundlecb->lock released
//
RemoveProtocolCBFromBundle(ProtocolCB);
ReleaseBundleLock(BundleCB);
NdisWanFreeProtocolCB(ProtocolCB);
} else {
ReleaseBundleLock(BundleCB);
NdisWanWaitForSyncEvent(&MiniportCB->HaltEvent);
NdisWanClearSyncEvent(&MiniportCB->HaltEvent); }
NdisAcquireSpinLock(&MiniportCB->Lock); }
NdisReleaseSpinLock(&MiniportCB->Lock);
DEREF_MINIPORTCB(MiniportCB);
NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MPHalt: Exit")); }
NDIS_STATUS MPInitialize( OUT PNDIS_STATUS OpenErrorStatus, OUT PUINT SelectedMediumIndex, IN PNDIS_MEDIUM MediumArray, IN UINT MediumArraySize, IN NDIS_HANDLE MiniportAdapterHandle, IN NDIS_HANDLE WrapperConfigurationContext ) /*++
Routine Name:
MPInitialize
Routine Description:
This routine is called after NdisWan registers itself as a Miniport driver. It is responsible for installing NdisWan as a Miniport driver, creating adapter control blocks for each adapter NdisWan exposes (should only be 1), and initializing all adapter specific variables
Arguments:
OpenErrorStatus - Returns information about the error if this function returns NDIS_STATUS_OPEN_ERROR. Used for TokenRing.
SelectedMediumIndex - An index into the MediumArray that specifies the medium type of this driver. Should be WAN or 802.3
MediumArray - An array of medium types supported by the NDIS library
MediumArraySize - Size of the medium array
MiniportAdapterHandle - Handle assigned by the NDIS library that defines this miniport driver. Used as handle in subsequent calls to the NDIS library.
WrapperConfigurationContext - Handle used to read configuration information from the registry
Return Values:
NDIS_STATUS_ADAPTER_NOT_FOUND NDIS_STATUS_FAILURE NDIS_STATUS_NOT_ACCEPTED NDIS_STATUS_OPEN_ERROR NDIS_STATUS_RESOURCES NDIS_STATUS_UNSUPPORTED_MEDIA
--*/ { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; PMINIPORTCB MiniportCB; UINT Index; NDIS_HANDLE ConfigHandle; ULONG NetworkAddressLength; #ifdef NT
LARGE_INTEGER TickCount, SystemTime; #endif
NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MPInitialize: Enter"));
//
// We have to be type 802.3 to the ndis wrapper, but the
// wrapper will expose us to the transports as type wan.
//
for (Index = 0; Index < MediumArraySize; Index++) {
if (MediumArray[Index] == NdisMedium802_3) { break; } }
//
// We don't have a match so we are screwed
//
if (Index == MediumArraySize) { return (NDIS_STATUS_UNSUPPORTED_MEDIA); }
*SelectedMediumIndex = Index;
//
// Allocate and initialize miniport adapter structure
//
#ifdef MINIPORT_NAME
MiniportCB = NdisWanAllocateMiniportCB(&((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->MiniportName); #else
MiniportCB = NdisWanAllocateMiniportCB(NULL); #endif
if (MiniportCB == NULL) { NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_MINIPORT, ("Error Creating MiniportCB!")); return (NDIS_STATUS_FAILURE); }
#ifndef MY_DEVICE_OBJECT
if (NdisWanCB.pDeviceObject == NULL) { PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1]; NDIS_STRING SymbolicName = NDIS_STRING_CONST("\\DosDevices\\NdisWan"); NDIS_STRING Name = NDIS_STRING_CONST("\\Device\\NdisWan"); ULONG i; NTSTATUS retStatus;
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) { DispatchTable[i] = NdisWanIrpStub; } DispatchTable[IRP_MJ_CREATE] = NdisWanCreate; DispatchTable[IRP_MJ_DEVICE_CONTROL] = NdisWanIoctl; DispatchTable[IRP_MJ_CLEANUP] = NdisWanCleanup;
retStatus = NdisMRegisterDevice(NdisWanCB.NdisWrapperHandle, &Name, &SymbolicName, DispatchTable, &NdisWanCB.pDeviceObject, &NdisWanCB.DeviceHandle);
if (retStatus == STATUS_SUCCESS) { NdisWanCB.pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; } else { NdisWanCB.pDeviceObject = NULL; } } #endif
NdisMSetAttributesEx(MiniportAdapterHandle, MiniportCB, (UINT)-1, //
// KyleB says that the following two defines are redundant if
// the miniport is deserialized.
//
// NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT |
// NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER |
NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT | NDIS_ATTRIBUTE_DESERIALIZE | NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND, NdisInterfaceInternal);
MiniportCB->MediumType = MediumArray[Index]; MiniportCB->RefCount = 0; MiniportCB->MiniportHandle = MiniportAdapterHandle;
//
// Read per miniport instance data
//
NdisOpenConfiguration(&Status, &ConfigHandle, WrapperConfigurationContext);
if (Status == NDIS_STATUS_SUCCESS) { NdisReadNetworkAddress(&Status, (PVOID*)&(MiniportCB->NetworkAddress), &NetworkAddressLength, ConfigHandle);
NdisCloseConfiguration(ConfigHandle);
if (Status != NDIS_STATUS_SUCCESS || NetworkAddressLength != ETH_LENGTH_OF_ADDRESS) {
goto BuildAddress; }
} else {
BuildAddress:
#ifdef NT
KeQueryTickCount(&TickCount); KeQuerySystemTime(&SystemTime);
MiniportCB->NetworkAddress[0] = (UCHAR)((TickCount.LowPart >> 16) ^ (SystemTime.LowPart >> 16)) & 0xFE;
MiniportCB->NetworkAddress[1] = (UCHAR)((TickCount.LowPart >> 8) ^ (SystemTime.LowPart >> 8));
//
// The following 4 bytes will be filled in at lineup time
//
MiniportCB->NetworkAddress[2] = ' '; MiniportCB->NetworkAddress[3] = 'R'; MiniportCB->NetworkAddress[4] = 'A'; MiniportCB->NetworkAddress[5] = 'S'; #endif
}
//
// Register our connection manager address family for this
// miniport
//
{
CO_ADDRESS_FAMILY CoAddressFamily; NDIS_CALL_MANAGER_CHARACTERISTICS CmCharacteristics;
NdisZeroMemory(&CmCharacteristics, sizeof(NDIS_CALL_MANAGER_CHARACTERISTICS));
CoAddressFamily.AddressFamily = CO_ADDRESS_FAMILY_PPP; CoAddressFamily.MajorVersion = NDISWAN_MAJOR_VERSION; CoAddressFamily.MinorVersion = NDISWAN_MINOR_VERSION;
CmCharacteristics.MajorVersion = NDISWAN_MAJOR_VERSION; CmCharacteristics.MinorVersion = NDISWAN_MINOR_VERSION;
CmCharacteristics.CmCreateVcHandler = CmCreateVc; CmCharacteristics.CmDeleteVcHandler = CmDeleteVc;
CmCharacteristics.CmOpenAfHandler = CmOpenAf; CmCharacteristics.CmCloseAfHandler = CmCloseAf; CmCharacteristics.CmRegisterSapHandler = CmRegisterSap; CmCharacteristics.CmDeregisterSapHandler = CmDeregisterSap; CmCharacteristics.CmMakeCallHandler = CmMakeCall; CmCharacteristics.CmCloseCallHandler = CmCloseCall; CmCharacteristics.CmIncomingCallCompleteHandler = CmIncomingCallComplete; CmCharacteristics.CmAddPartyHandler = NULL; CmCharacteristics.CmDropPartyHandler = NULL; CmCharacteristics.CmActivateVcCompleteHandler = CmActivateVcComplete; CmCharacteristics.CmDeactivateVcCompleteHandler = CmDeactivateVcComplete; CmCharacteristics.CmModifyCallQoSHandler = CmModifyCallQoS; CmCharacteristics.CmRequestHandler = CmRequest; CmCharacteristics.CmRequestCompleteHandler = ProtoCoRequestComplete;
NdisMCmRegisterAddressFamily(MiniportCB->MiniportHandle, &CoAddressFamily, &CmCharacteristics, sizeof(NDIS_CALL_MANAGER_CHARACTERISTICS)); }
NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MPInitialize: Exit"));
REF_MINIPORTCB(MiniportCB);
return (NDIS_STATUS_SUCCESS); }
#if 0
NDIS_STATUS MPQueryInformation( IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_OID Oid, IN PVOID InformationBuffer, IN ULONG InformationBufferLength, OUT PULONG BytesWritten, OUT PULONG BytesNeeded ) /*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/ { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; PMINIPORTCB MiniportCB = (PMINIPORTCB)MiniportAdapterContext; NDIS_REQUEST NdisRequest;
NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MPQueryInformation: Enter Oid: 0x%x", Oid));
NdisWanInterlockedInc(&MiniportCB->RefCount);
NdisRequest.RequestType = NdisRequestQueryInformation;
NdisRequest.DATA.QUERY_INFORMATION.Oid = Oid;
NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer;
NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = InformationBufferLength;
NdisRequest.DATA.QUERY_INFORMATION.BytesWritten = *BytesWritten;
NdisRequest.DATA.QUERY_INFORMATION.BytesNeeded = *BytesNeeded;
Status = NdisWanOidProc(MiniportCB, &NdisRequest);
*BytesWritten = NdisRequest.DATA.QUERY_INFORMATION.BytesWritten; *BytesNeeded = NdisRequest.DATA.QUERY_INFORMATION.BytesNeeded;
NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MPQueryInformation: Exit Status: %x", Status));
NdisWanInterlockedDec(&MiniportCB->RefCount);
return (Status); } #endif
NDIS_STATUS MPReconfigure( OUT PNDIS_STATUS OpenErrorStatus, IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_HANDLE WrapperConfigurationContext ) /*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/ { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; PMINIPORTCB MiniportCB = (PMINIPORTCB)MiniportAdapterContext;
NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MPReconfigure: Enter"));
NdisWanInterlockedInc(&MiniportCB->RefCount);
NdisWanInterlockedDec(&MiniportCB->RefCount);
NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MPReconfigure: Exit")); return (Status); }
NDIS_STATUS MPReset( OUT PBOOLEAN AddressingReset, IN NDIS_HANDLE MiniportAdapterContext ) /*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/ { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; PMINIPORTCB MiniportCB = (PMINIPORTCB)MiniportAdapterContext;
NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MPReset: Enter"));
*AddressingReset = FALSE;
NdisWanInterlockedInc(&MiniportCB->RefCount);
NdisAcquireSpinLock(&MiniportCB->Lock);
MiniportCB->Flags &= ~ASK_FOR_RESET;
NdisReleaseSpinLock(&MiniportCB->Lock);
NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MPReset: Exit"));
NdisWanInterlockedDec(&MiniportCB->RefCount);
return (Status); }
#if 0
NDIS_STATUS MPSetInformation( IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_OID Oid, IN PVOID InformationBuffer, IN ULONG InformationBufferLength, OUT PULONG BytesWritten, OUT PULONG BytesNeeded ) /*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/ { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; PMINIPORTCB MiniportCB = (PMINIPORTCB)MiniportAdapterContext; NDIS_REQUEST NdisRequest;
NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MPSetInformation: Enter Oid: 0x%x", Oid));
NdisWanInterlockedInc(&MiniportCB->RefCount);
NdisRequest.RequestType = NdisRequestSetInformation;
NdisRequest.DATA.SET_INFORMATION.Oid = Oid;
NdisRequest.DATA.SET_INFORMATION.InformationBuffer = InformationBuffer;
NdisRequest.DATA.SET_INFORMATION.InformationBufferLength = InformationBufferLength;
NdisRequest.DATA.SET_INFORMATION.BytesRead = *BytesWritten;
NdisRequest.DATA.SET_INFORMATION.BytesNeeded = *BytesNeeded;
Status = NdisWanOidProc(MiniportCB, &NdisRequest);
*BytesWritten = NdisRequest.DATA.SET_INFORMATION.BytesRead; *BytesNeeded = NdisRequest.DATA.SET_INFORMATION.BytesNeeded;
NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MPSetInformation: Exit"));
NdisWanInterlockedDec(&MiniportCB->RefCount);
return (Status); } #endif
VOID MPReturnPacket( IN NDIS_HANDLE MiniportAdapterContext, IN PNDIS_PACKET Packet ) { PNDISWAN_PROTOCOL_RESERVED pres; PMINIPORTCB MiniportCB; PNDIS_BUFFER NdisBuffer; PRECV_DESC RecvDesc;
NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("MPReturnPacket: Enter Packet %p", Packet));
pres = PPROTOCOL_RESERVED_FROM_NDIS(Packet);
MiniportCB = (PMINIPORTCB)MiniportAdapterContext;
RecvDesc = pres->RecvDesc;
REMOVE_DBG_RECV(PacketTypeNdis, MiniportCB, Packet);
NdisWanFreeRecvDesc(RecvDesc);
NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("MPReturnPacket: Exit")); }
VOID MPSendPackets( IN NDIS_HANDLE MiniportAdapterContext, IN PPNDIS_PACKET PacketArray, IN UINT NumberOfPackets ) { ULONG i; PMINIPORTCB MiniportCB = (PMINIPORTCB)MiniportAdapterContext;
NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("MPSendPackets: Enter"));
for (i = 0; i < NumberOfPackets; i++) { PNDIS_PACKET NdisPacket = PacketArray[i];
PMINIPORT_RESERVED_FROM_NDIS(NdisPacket)->CmVcCB = NULL;
NdisWanQueueSend(MiniportCB, NdisPacket); }
NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("MPSendPackets: Exit")); }
NDIS_STATUS MPCoCreateVc( IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_HANDLE NdisVcHandle, OUT PNDIS_HANDLE MiniportVcContext ) { NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MPCoCreateVc: Enter"));
NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MPCoCreateVc: Exit"));
return (NDIS_STATUS_SUCCESS); }
NDIS_STATUS MPCoDeleteVc( IN NDIS_HANDLE MiniportVcContext ) { NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MPCoDeleteVc: Enter"));
NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MPCoDeleteVc: Exit")); return (NDIS_STATUS_SUCCESS); }
NDIS_STATUS MPCoActivateVc( IN NDIS_HANDLE MiniportVcContext, IN OUT PCO_CALL_PARAMETERS CallParameters ) { NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MPCoActivateVc: Enter"));
NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MPCoActivateVc: Exit")); return (NDIS_STATUS_SUCCESS); }
NDIS_STATUS MPCoDeactivateVc( IN NDIS_HANDLE MiniportVcContext ) { NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MPCoDeactivateVc: Enter"));
NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MPCoDeactivateVc: Exit")); return (NDIS_STATUS_SUCCESS); }
VOID MPCoSendPackets( IN NDIS_HANDLE MiniportVcContext, IN PPNDIS_PACKET PacketArray, IN UINT NumberOfPackets ) { ULONG i; PCM_VCCB CmVcCB = (PCM_VCCB)MiniportVcContext; PCM_AFSAPCB AfSapCB = CmVcCB->AfSapCB; PMINIPORTCB MiniportCB = AfSapCB->MiniportCB;
NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("MPCoSendPackets: Enter"));
if (CmVcCB->State != CMVC_ACTIVE) {
for (i = 0; i < NumberOfPackets; i++) { PNDIS_PACKET NdisPacket = PacketArray[i];
NdisMCoSendComplete(NDIS_STATUS_FAILURE, CmVcCB->NdisVcHandle, NdisPacket); }
return; }
for (i = 0; i < NumberOfPackets; i++) { PNDIS_PACKET NdisPacket = PacketArray[i];
REF_CMVCCB(CmVcCB);
PMINIPORT_RESERVED_FROM_NDIS(NdisPacket)->CmVcCB = CmVcCB;
NdisWanQueueSend(MiniportCB, NdisPacket); }
NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("MPCoSendPackets: Exit")); }
NDIS_STATUS MPCoRequest( IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_HANDLE MiniportVcContext OPTIONAL, IN OUT PNDIS_REQUEST NdisRequest ) { NDIS_STATUS Status; PCM_VCCB CmVcCB;
NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MPCoRequest: Enter Oid: 0x%x", NdisRequest->DATA.QUERY_INFORMATION.Oid));
CmVcCB = (PCM_VCCB)MiniportVcContext;
Status = NdisWanCoOidProc((PMINIPORTCB)MiniportAdapterContext, CmVcCB, NdisRequest);
NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("MPCoRequest: Exit Status: 0x%x", Status));
return (Status); }
|