You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
306 lines
9.0 KiB
306 lines
9.0 KiB
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
llcmain.c
|
|
|
|
Abstract:
|
|
|
|
This module implements data link object for NDIS 3.0.
|
|
Data link driver provides 802.2 LLC Class I and II services
|
|
and also interface to send and receive direct network data.
|
|
This module may later be used as general packet router
|
|
for the protocol modules => smaller system overhead, when
|
|
the NDIS packet header is checked only once. LLC interface
|
|
is also much easier to use than NDIS.
|
|
|
|
Its main tasks are:
|
|
- implement simple and realiable LLC Class II
|
|
connection-oriented services for the other drivers
|
|
- provide network independent interface 802.2 interface
|
|
- remove the system overhead of the packet and indication
|
|
routing to all protocol modules
|
|
- provide transmit packet queueing for the protocol drivers
|
|
- provide 802.2 compatible connect, disconnect and close
|
|
services, that calls back, when the transmit queue is
|
|
empty.
|
|
|
|
The services provides the module are somewhat extended
|
|
802.2 services, because the protocol engine is a IBM version
|
|
of ISO-HDLC ABM. LlcDisconnet and LlcConnect primitives
|
|
implements both Request and Confirm of Connect/Disconnect
|
|
|
|
Data link driver does not make any buffering for the data.
|
|
All data buffer except the LLC header and lan header with the
|
|
I-frames must be provided by the calling protocol driver.
|
|
|
|
|
|
*********************** SPINLOCK RULES *************************
|
|
|
|
DataLink driver uses extensively several spin locks to make it
|
|
as re-entrant as possible with multiple processors and to
|
|
minimize unnecessary spin locking calls.
|
|
The main problem with multiple spin locks are the dead locks.
|
|
The spin locks must always be acquired the same order (and
|
|
released in a reverse order):
|
|
|
|
This is the order used with DataLink spin locks:
|
|
|
|
1. Adapter->ObjectDataBase
|
|
Protects objects from close/delete. This is always locked in
|
|
the receive indication routine.
|
|
|
|
2. Link->SpinLock
|
|
Protects the link. This lock is needed to prevent to upper
|
|
protocol to call the link station, when we are changing it state.
|
|
SendSpinLock cannot protect it, because it must be switched off,
|
|
when the pending commands are executed. (But could we keep
|
|
SendSpinLock locked, when the transmit commands are completed).
|
|
There will occure a dead lock in any way, if the upper protocol
|
|
is waiting the last transmit to complete before it disconnects
|
|
a link station.
|
|
|
|
|
|
3. Adapter->SendSpinLock // protects queues and packet pools
|
|
|
|
---
|
|
Timer spin locks is used only by timer servives:
|
|
4. TimerSpinLock // protects the timer queues
|
|
|
|
****************************************************************
|
|
|
|
Contents:
|
|
LlcInitialize
|
|
LlcTerminate
|
|
|
|
Author:
|
|
|
|
Antti Saarenheimo (o-anttis) 17-MAY-1991
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
//
|
|
// This define enables the private DLC function prototypes
|
|
// We don't want to export our data types to the dlc layer.
|
|
// MIPS compiler doesn't accept hiding of the internal data
|
|
// structures by a PVOID in the function prototype.
|
|
// i386 will check the type defines
|
|
//
|
|
|
|
#ifndef i386
|
|
|
|
#define LLC_PUBLIC_NDIS_PROTOTYPES
|
|
|
|
#endif
|
|
|
|
#include <llc.h>
|
|
#include "dbgmsg.h"
|
|
|
|
//
|
|
// These are the defaults defined in the IBM LAN Architecture reference,
|
|
// this may be set by a DLC application, if it want to change the defaults.
|
|
//
|
|
|
|
DLC_LINK_PARAMETERS DefaultParameters = {
|
|
3, // T1 600 milliseconds (3 * 5 * 40)
|
|
2, // T2 80 milliseconds (2 * 1 * 40)
|
|
10, // Ti 25 seconds ((10 - 5) * 125 * 4)
|
|
127, // TW: maximum transmit window size
|
|
127, // RW: The maximum receive window size
|
|
20, // Nw: number of LPDUs acknowledged, before Ww is incr.)
|
|
5, // N2: Number of retires allowed (both Polls and I LPDSs)
|
|
0, // lowest proirity by default
|
|
600 // default for info field length by default
|
|
};
|
|
|
|
KMUTEX NdisAccessMutex;
|
|
KSEMAPHORE OpenAdapterSemaphore;
|
|
|
|
#define LLC_PROTOCOL_NAME L"DLC"
|
|
|
|
#ifdef NDIS40
|
|
extern ULONG gWaitForAdapter;
|
|
#endif // NDIS40
|
|
|
|
|
|
DLC_STATUS
|
|
LlcInitialize(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The routines initializes the protocol module and
|
|
does the minimal stuff, that must be done in the
|
|
serialized initialization routine.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
NDIS_STATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
NDIS_STATUS Status;
|
|
NDIS_PROTOCOL_CHARACTERISTICS LlcChars;
|
|
|
|
ASSUME_IRQL(PASSIVE_LEVEL);
|
|
|
|
//
|
|
// We must build a MDL for the XID information used
|
|
// when the link level takes care of XID handling.
|
|
//
|
|
|
|
pXidMdl = IoAllocateMdl(&Ieee802Xid,
|
|
sizeof(Ieee802Xid),
|
|
FALSE,
|
|
FALSE,
|
|
NULL
|
|
);
|
|
if (pXidMdl == NULL) {
|
|
return DLC_STATUS_NO_MEMORY;
|
|
}
|
|
|
|
#ifdef NDIS40
|
|
//
|
|
// Event to signal all adapters have been bound - OK for LlcOpenAdapter
|
|
// to bind.
|
|
//
|
|
|
|
NdisInitializeEvent(&PnPBindsComplete);
|
|
NdisResetEvent(&PnPBindsComplete);
|
|
#endif // NDIS40
|
|
|
|
#if LLC_DBG
|
|
|
|
ALLOCATE_SPIN_LOCK(&MemCheckLock);
|
|
|
|
#endif
|
|
|
|
MmBuildMdlForNonPagedPool(pXidMdl);
|
|
LlcInitializeTimerSystem();
|
|
|
|
NdisZeroMemory(&LlcChars, sizeof(LlcChars));
|
|
NdisInitUnicodeString(&LlcChars.Name, LLC_PROTOCOL_NAME);
|
|
|
|
#ifdef NDIS40
|
|
LlcChars.MajorNdisVersion = 4;
|
|
LlcChars.MinorNdisVersion = 0;
|
|
LlcChars.OpenAdapterCompleteHandler = LlcNdisOpenAdapterComplete;
|
|
LlcChars.CloseAdapterCompleteHandler = LlcNdisCloseComplete;
|
|
LlcChars.SendCompleteHandler = LlcNdisSendComplete;
|
|
LlcChars.TransferDataCompleteHandler = LlcNdisTransferDataComplete;
|
|
LlcChars.ResetCompleteHandler = LlcNdisResetComplete;
|
|
LlcChars.RequestCompleteHandler = LlcNdisRequestComplete;
|
|
LlcChars.ReceiveHandler = LlcNdisReceiveIndication;
|
|
LlcChars.ReceiveCompleteHandler = LlcNdisReceiveComplete;
|
|
LlcChars.StatusHandler = NdisStatusHandler;
|
|
LlcChars.StatusCompleteHandler = LlcNdisReceiveComplete;
|
|
// DLC supports bind/unbind/pnp, but not unload.
|
|
LlcChars.UnloadHandler = NULL;
|
|
LlcChars.PnPEventHandler = LlcPnPEventHandler;
|
|
LlcChars.BindAdapterHandler = LlcBindAdapterHandler;
|
|
LlcChars.UnbindAdapterHandler = LlcUnbindAdapterHandler;
|
|
|
|
//
|
|
// Need to get value for waiting on uninitialized adapters.
|
|
//
|
|
|
|
if (!NT_SUCCESS(GetAdapterWaitTimeout(&gWaitForAdapter)))
|
|
{
|
|
ASSERT(FALSE);
|
|
gWaitForAdapter = 15; // Default.
|
|
}
|
|
|
|
DEBUGMSG(DBG_WARN, (TEXT("WaitForAdapter delay = %d sec\n"), gWaitForAdapter));
|
|
|
|
#else // NDIS40
|
|
LlcChars.MajorNdisVersion = 3;
|
|
LlcChars.MinorNdisVersion = 0;
|
|
LlcChars.OpenAdapterCompleteHandler = LlcNdisOpenAdapterComplete;
|
|
LlcChars.CloseAdapterCompleteHandler = LlcNdisCloseComplete;
|
|
LlcChars.SendCompleteHandler = LlcNdisSendComplete;
|
|
LlcChars.TransferDataCompleteHandler = LlcNdisTransferDataComplete;
|
|
LlcChars.ResetCompleteHandler = LlcNdisResetComplete;
|
|
LlcChars.RequestCompleteHandler = LlcNdisRequestComplete;
|
|
LlcChars.ReceiveHandler = LlcNdisReceiveIndication;
|
|
LlcChars.ReceiveCompleteHandler = LlcNdisReceiveComplete;
|
|
LlcChars.StatusHandler = NdisStatusHandler;
|
|
LlcChars.StatusCompleteHandler = LlcNdisReceiveComplete;
|
|
#endif // !NDIS40
|
|
|
|
NdisRegisterProtocol(&Status,
|
|
&LlcProtocolHandle,
|
|
&LlcChars,
|
|
sizeof(LlcChars));
|
|
|
|
KeInitializeSpinLock(&LlcSpinLock);
|
|
|
|
ASSUME_IRQL(PASSIVE_LEVEL);
|
|
|
|
KeInitializeMutex(&NdisAccessMutex, 1);
|
|
|
|
//
|
|
// We use the OpenAdapterSemaphore in the LlcOpenAdapter function. We really
|
|
// want a mutex, but a mutex causes us problems on a checked build if we
|
|
// make a call into NTOS. In either case, we just need a mechanism to ensure
|
|
// only one thread is creating the ADAPTER_CONTEXT & opening the adapter at
|
|
// NDIS level
|
|
//
|
|
|
|
KeInitializeSemaphore(&OpenAdapterSemaphore, 1, 1);
|
|
|
|
if (Status != STATUS_SUCCESS) {
|
|
IoFreeMdl(pXidMdl);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
LlcTerminate(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The routines terminates the LLC protocol module and frees its global
|
|
resources. This assumes all adapter bindings to be closed.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
NDIS_STATUS Status;
|
|
|
|
ASSUME_IRQL(PASSIVE_LEVEL);
|
|
|
|
DEBUGMSG(DBG_INIT, (TEXT("+LlcTerminate()\n")));
|
|
|
|
LlcTerminateTimerSystem();
|
|
#ifdef NDIS40
|
|
CloseAllAdapters();
|
|
#endif // NDIS40
|
|
NdisDeregisterProtocol(&Status, LlcProtocolHandle);
|
|
IoFreeMdl(pXidMdl);
|
|
}
|
|
|