|
|
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
D:\nt\private\ntos\tdi\rawwan\core\utils.c
Abstract:
Revision History:
Who When What -------- -------- ---------------------------------------------- arvindm 05-07-97 Created
Notes:
--*/
#include <precomp.h>
#define _FILENUMBER 'LITU'
RWAN_STATUS RWanInitGlobals( IN PDRIVER_OBJECT pDriverObject ) /*++
Routine Description:
Initialize global data structures.
Arguments:
pDriverObject - Points to our driver object, from DriverEntry.
Return Value:
RWAN_STATUS_SUCCESS if initialized successfully, else an appropriate error code.
--*/ { RWAN_STATUS RWanStatus;
pRWanGlobal = &RWanGlobals;
RWAN_ZERO_MEM(pRWanGlobal, sizeof(RWanGlobals));
RWAN_SET_SIGNATURE(pRWanGlobal, nlg); RWAN_INIT_LIST(&pRWanGlobal->AfInfoList); RWAN_INIT_LIST(&pRWanGlobal->ProtocolList); RWAN_INIT_LIST(&pRWanGlobal->AdapterList); RWAN_INIT_GLOBAL_LOCK(); RWAN_INIT_ADDRESS_LIST_LOCK(); RWAN_INIT_CONN_TABLE_LOCK();
RWAN_INIT_EVENT_STRUCT(&pRWanGlobal->Event);
pRWanGlobal->MaxConnections = RWanMaxTdiConnections;
#ifdef NT
pRWanGlobal->pDriverObject = pDriverObject; RWAN_INIT_LIST(&pRWanGlobal->DeviceObjList); #endif // NT
RWanStatus = RWanInitReceive();
if (RWanStatus == RWAN_STATUS_SUCCESS) { RWanStatus = RWanInitSend();
if (RWanStatus != RWAN_STATUS_SUCCESS) { RWanShutdownReceive(); } }
return (RWanStatus); }
VOID RWanDeinitGlobals( VOID ) /*++
Routine Description:
The flip of RWanInitGlobals.
Arguments:
None
Return Value:
None
--*/ { RWAN_FREE_EVENT_STRUCT(&pRWanGlobal->Event); RWAN_FREE_GLOBAL_LOCK();
if (pRWanGlobal->pConnTable != NULL) { RWAN_FREE_MEM(pRWanGlobal->pConnTable); pRWanGlobal->pConnTable = NULL; }
RWanShutdownReceive(); RWanShutdownSend(); }
PRWAN_TDI_PROTOCOL RWanGetProtocolFromNumber( IN UINT Protocol ) /*++
Routine Description:
Return the TDI Protocol info block that represents the given TDI protocol number.
Arguments:
Protocol - The TDI protocol number
Return Value:
Pointer to TDI Protocol block if found, else NULL.
--*/ { PLIST_ENTRY pAfInfoEntry; PRWAN_NDIS_AF_INFO pAfInfo;
PLIST_ENTRY pProtocolEntry; PRWAN_TDI_PROTOCOL pProtocol; BOOLEAN bFound = FALSE;
RWAN_ACQUIRE_GLOBAL_LOCK();
for (pAfInfoEntry = pRWanGlobal->AfInfoList.Flink; pAfInfoEntry != &(pRWanGlobal->AfInfoList); pAfInfoEntry = pAfInfoEntry->Flink) { pAfInfo = CONTAINING_RECORD(pAfInfoEntry, RWAN_NDIS_AF_INFO, AfInfoLink);
for (pProtocolEntry = pAfInfo->TdiProtocolList.Flink; pProtocolEntry != &(pAfInfo->TdiProtocolList); pProtocolEntry = pProtocolEntry->Flink) {
pProtocol = CONTAINING_RECORD(pProtocolEntry, RWAN_TDI_PROTOCOL, AfInfoLink);
if (pProtocol->TdiProtocol == Protocol) { bFound = TRUE; break; } }
if (bFound) { break; } }
RWAN_RELEASE_GLOBAL_LOCK();
if (!bFound) { pProtocol = NULL; }
return (pProtocol); }
TA_ADDRESS * RWanGetValidAddressFromList( IN TRANSPORT_ADDRESS UNALIGNED *pAddrList, IN PRWAN_TDI_PROTOCOL pProtocol ) /*++
Routine Description:
Go through the given transport address list, and return the first valid protocol address that we find.
Valid address: one that matches the address type and length for the specified TDI protocol.
Arguments:
pAddrList - Points to list of addresses pProtocol - Points to TDI Protocol block
Return Value:
Pointer to the first valid address in the list if found, else NULL.
--*/ { INT i; TA_ADDRESS * pAddr;
pAddr = (TA_ADDRESS *)pAddrList->Address;
for (i = 0; i < pAddrList->TAAddressCount; i++) { if ((pAddr->AddressType == pProtocol->SockAddressFamily) && (pAddr->AddressLength >= pProtocol->MaxAddrLength)) { return (pAddr); }
pAddr = (TA_ADDRESS *) ((PUCHAR)(pAddr->Address) + pAddr->AddressLength); }
return (NULL); }
PRWAN_TDI_CONNECTION RWanAllocateConnObject( VOID ) /*++
Routine Description:
Allocate a TDI Connection object.
Arguments:
None
Return Value:
Pointer to allocated Connection Object, or NULL.
--*/ { PRWAN_TDI_CONNECTION pConnObject;
RWAN_ALLOC_MEM(pConnObject, RWAN_TDI_CONNECTION, sizeof(RWAN_TDI_CONNECTION));
if (pConnObject != NULL) { RWAN_ZERO_MEM(pConnObject, sizeof(RWAN_TDI_CONNECTION));
RWAN_SET_SIGNATURE(pConnObject, ntc);
RWAN_INIT_LOCK(&(pConnObject->Lock)); #if DBG
pConnObject->ntcd_sig = ' gbD'; #endif
}
return (pConnObject); }
VOID RWanReferenceConnObject( IN PRWAN_TDI_CONNECTION pConnObject ) /*++
Routine Description:
Add a reference to the specified Connection Object.
Arguments:
pConnObject - Pointer to the TDI Connection Object.
Locks on Entry:
pConnObject
Locks on Exit:
pConnObject
Return Value:
None
--*/ { RWAN_STRUCT_ASSERT(pConnObject, ntc); pConnObject->RefCount++; }
INT RWanDereferenceConnObject( IN PRWAN_TDI_CONNECTION pConnObject ) /*++
Routine Description:
Dereference the specified Connection Object. If the reference count goes down to 0, free it.
Arguments:
pConnObject - Pointer to the TDI Connection Object.
Locks on Entry:
pConnObject
Locks on Exit:
pConnObject, iff it hasn't been freed.
Return Value:
INT - The resulting reference count.
--*/ { INT RefCount; RWAN_DELETE_NOTIFY DeleteNotify;
RWAN_STRUCT_ASSERT(pConnObject, ntc);
RefCount = --pConnObject->RefCount;
if (RefCount == 0) { DeleteNotify = pConnObject->DeleteNotify;
RWAN_RELEASE_CONN_LOCK(pConnObject);
RWANDEBUGP(DL_EXTRA_LOUD, DC_UTIL, ("Derefed away: pConnObj x%x, Notify x%x\n", pConnObject, DeleteNotify.pDeleteRtn));
if (DeleteNotify.pDeleteRtn) { (*DeleteNotify.pDeleteRtn)(DeleteNotify.DeleteContext, TDI_SUCCESS, 0); }
RWAN_FREE_MEM(pConnObject); }
return (RefCount); }
PRWAN_TDI_ADDRESS RWanAllocateAddressObject( IN TA_ADDRESS * pTransportAddress ) /*++
Routine Description:
Allocate a TDI Address object.
Arguments:
pTransportAddress - Points to transport address for which this Address Object is our context.
Return Value:
Pointer to allocated Address Object, or NULL.
--*/ { PRWAN_TDI_ADDRESS pAddrObject; ULONG Size; NDIS_STATUS Status;
Size = sizeof(RWAN_TDI_ADDRESS) + pTransportAddress->AddressLength;
RWAN_ALLOC_MEM(pAddrObject, RWAN_TDI_ADDRESS, Size);
if (pAddrObject != NULL) { RWAN_ZERO_MEM(pAddrObject, Size);
RWAN_SET_SIGNATURE(pAddrObject, nta);
RWAN_INIT_LOCK(&(pAddrObject->Lock));
Status = NDIS_STATUS_SUCCESS;
try { pAddrObject->AddressType = pTransportAddress->AddressType; pAddrObject->AddressLength = pTransportAddress->AddressLength; pAddrObject->pAddress = (PVOID)((PUCHAR)pAddrObject + sizeof(RWAN_TDI_ADDRESS));
RWAN_COPY_MEM(pAddrObject->pAddress, pTransportAddress->Address, pTransportAddress->AddressLength); } except (EXCEPTION_EXECUTE_HANDLER) { Status = NDIS_STATUS_FAILURE; }
if (Status != NDIS_STATUS_SUCCESS) { RWAN_FREE_MEM(pAddrObject); pAddrObject = NULL; } else { RWAN_INIT_LIST(&pAddrObject->IdleConnList); RWAN_INIT_LIST(&pAddrObject->ListenConnList); RWAN_INIT_LIST(&pAddrObject->ActiveConnList); RWAN_INIT_LIST(&pAddrObject->SapList);
RWAN_INIT_EVENT_STRUCT(&pAddrObject->Event); }
}
return (pAddrObject); }
VOID RWanReferenceAddressObject( IN PRWAN_TDI_ADDRESS pAddrObject ) /*++
Routine Description:
Add a reference to the specified Address Object.
Arguments:
pAddrObject - Pointer to the TDI Address Object.
Locks on Entry:
pAddrObject
Locks on Exit:
pAddrObject
Return Value:
None
--*/ { RWAN_STRUCT_ASSERT(pAddrObject, nta); pAddrObject->RefCount++; }
INT RWanDereferenceAddressObject( IN PRWAN_TDI_ADDRESS pAddrObject ) /*++
Routine Description:
Dereference the specified Address Object. If the reference count goes down to 0, free it.
Arguments:
pAddrObject - Pointer to the TDI Address Object.
Locks on Entry:
pAddrObject
Locks on Exit:
pAddrObject, iff it hasn't been freed.
Return Value:
INT - The resulting reference count.
--*/ { INT RefCount; RWAN_DELETE_NOTIFY DeleteNotify;
RWAN_STRUCT_ASSERT(pAddrObject, nta);
RefCount = --pAddrObject->RefCount;
if (RefCount == 0) { RWAN_ASSERT(RWAN_IS_LIST_EMPTY(&pAddrObject->IdleConnList)); RWAN_ASSERT(RWAN_IS_LIST_EMPTY(&pAddrObject->ActiveConnList)); RWAN_ASSERT(RWAN_IS_LIST_EMPTY(&pAddrObject->ListenConnList)); RWAN_ASSERT(RWAN_IS_LIST_EMPTY(&pAddrObject->SapList));
DeleteNotify = pAddrObject->DeleteNotify;
RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
RWANDEBUGP(DL_EXTRA_LOUD, DC_UTIL, ("Derefed away: pAddrObj x%x, Notify x%x\n", pAddrObject, DeleteNotify.pDeleteRtn));
if (DeleteNotify.pDeleteRtn) { (*DeleteNotify.pDeleteRtn)(DeleteNotify.DeleteContext, (UINT)TDI_ADDR_DELETED, 0); }
RWAN_FREE_MEM(pAddrObject); }
return (RefCount); }
PRWAN_NDIS_AF RWanAllocateAf( VOID ) /*++
Routine Description:
Allocate an NDIS AF block.
Arguments:
None
Return Value:
Pointer to allocated NDIS AF Block, or NULL.
--*/ { PRWAN_NDIS_AF pAf;
RWAN_ALLOC_MEM(pAf, RWAN_NDIS_AF, sizeof(RWAN_NDIS_AF));
if (pAf != NULL) { RWAN_ZERO_MEM(pAf, sizeof(RWAN_NDIS_AF));
RWAN_SET_SIGNATURE(pAf, naf);
RWAN_INIT_LOCK(&(pAf->Lock)); RWAN_INIT_LIST(&(pAf->NdisVcList)); RWAN_INIT_LIST(&(pAf->NdisSapList)); }
RWANDEBUGP(DL_WARN, DC_WILDCARD, ("Allocated AF x%x\n", pAf));
return (pAf); }
VOID RWanReferenceAf( IN PRWAN_NDIS_AF pAf ) /*++
Routine Description:
Add a reference to the specified NDIS AF Block.
Arguments:
pAf - Pointer to the NDIS AF Block.
Locks on Entry:
pAf
Locks on Exit:
pAf
Return Value:
None
--*/ { RWAN_STRUCT_ASSERT(pAf, naf); pAf->RefCount++; }
INT RWanDereferenceAf( IN PRWAN_NDIS_AF pAf ) /*++
Routine Description:
Dereference the specified NDIS AF Block. If the reference count goes down to 0, free it. Some additional work if freeing this: unlink from the adapter, and check if the adapter is unbinding.
Arguments:
pAf - Pointer to the NDIS AF Block.
Locks on Entry:
pAf
Locks on Exit:
pAf, iff it hasn't been freed.
Return Value:
INT - The resulting reference count.
--*/ { INT RefCount; RWAN_DELETE_NOTIFY DeleteNotify; PRWAN_NDIS_ADAPTER pAdapter;
RWAN_STRUCT_ASSERT(pAf, naf);
RefCount = --pAf->RefCount;
if (RefCount == 0) { DeleteNotify = pAf->DeleteNotify;
pAdapter = pAf->pAdapter;
RWAN_RELEASE_AF_LOCK(pAf);
RWAN_ACQUIRE_GLOBAL_LOCK();
//
// Unlink from list of AF opens for this NDIS AF
//
RWAN_DELETE_FROM_LIST(&(pAf->AfInfoLink));
RWAN_RELEASE_GLOBAL_LOCK();
RWAN_ACQUIRE_ADAPTER_LOCK(pAdapter);
//
// Unlink from list of AF opens on this adapter.
//
if (RWAN_IS_BIT_SET(pAf->Flags, RWANF_AF_IN_ADAPTER_LIST)) { RWAN_DELETE_FROM_LIST(&(pAf->AfLink)); }
//
// See if we just deleted the last AF on this adapter, and
// we are in the process of unbinding from this adapter.
//
if (RWAN_IS_LIST_EMPTY(&pAdapter->AfList) && RWAN_IS_BIT_SET(pAdapter->Flags, RWANF_AD_UNBIND_PENDING)) { RWanCloseAdapter(pAdapter); //
// Adapter lock is released within the above.
//
} else { RWAN_RELEASE_ADAPTER_LOCK(pAdapter); }
RWANDEBUGP(DL_EXTRA_LOUD, DC_UTIL, ("Derefed away: pAf x%x, Notify x%x\n", pAf, DeleteNotify.pDeleteRtn));
if (DeleteNotify.pDeleteRtn) { (*DeleteNotify.pDeleteRtn)(DeleteNotify.DeleteContext, TDI_SUCCESS, 0); }
RWAN_FREE_MEM(pAf); }
return (RefCount); }
#if 0
VOID RWanReferenceAdapter( IN PRWAN_NDIS_ADAPTER pAdapter ) /*++
Routine Description:
Add a reference to the specified NDIS ADAPTER Block.
Arguments:
pAdapter - Pointer to the NDIS ADAPTER Block.
Locks on Entry:
pAdapter
Locks on Exit:
pAdapter
Return Value:
None
--*/ { RWAN_STRUCT_ASSERT(pAdapter, nad); pAdapter->RefCount++; }
INT RWanDereferenceAdapter( IN PRWAN_NDIS_ADAPTER pAdapter ) /*++
Routine Description:
Dereference the specified NDIS ADAPTER Block. If the reference count goes down to 0, free it.
Arguments:
pAdapter - Pointer to the NDIS ADAPTER Block.
Locks on Entry:
pAdapter
Locks on Exit:
pAdapter, iff it hasn't been freed.
Return Value:
INT - The resulting reference count.
--*/ { INT RefCount; RWAN_DELETE_NOTIFY DeleteNotify;
RWAN_STRUCT_ASSERT(pAdapter, nad);
RefCount = --pAdapter->RefCount;
if (RefCount == 0) { DeleteNotify = pAdapter->DeleteNotify;
RWAN_RELEASE_ADAPTER_LOCK(pAdapter);
if (DeleteNotify.pDeleteRtn) { (*DeleteNotify.pDeleteRtn)(DeleteNotify.DeleteContext, TDI_SUCCESS, 0); }
RWAN_FREE_MEM(pAdapter); }
return (RefCount); }
#endif // 0
TDI_STATUS RWanNdisToTdiStatus( IN NDIS_STATUS Status ) /*++
Routine Description:
Convert an NDIS Status code to an equivalent TDI code. TBD: RWanNdisToTdiStatus: support more NDIS status codes.
Arguments:
Status - NDIS status code.
Return Value:
TDI status.
--*/ { TDI_STATUS TdiStatus;
switch (Status) { case NDIS_STATUS_SUCCESS: TdiStatus = TDI_SUCCESS; break; case NDIS_STATUS_RESOURCES: case NDIS_STATUS_VC_NOT_ACTIVATED: case NDIS_STATUS_VC_NOT_AVAILABLE: TdiStatus = TDI_NO_RESOURCES; break;
case NDIS_STATUS_SAP_IN_USE: TdiStatus = TDI_ADDR_IN_USE; break;
default: TdiStatus = TDI_NOT_ACCEPTED; break; }
return (TdiStatus); }
|