Leaked source code of windows server 2003
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.

3992 lines
124 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Module Name:
  3. miniport.c
  4. Abstract:
  5. This module contains all the Miniport interface processing routines.
  6. Author:
  7. Hakan Berk - Microsoft, Inc. (hakanb@microsoft.com) Feb-2000
  8. Environment:
  9. Windows 2000 kernel mode Miniport driver or equivalent.
  10. Revision History:
  11. ---------------------------------------------------------------------------*/
  12. #include <ntddk.h>
  13. #include <ntddndis.h>
  14. #include <ndis.h>
  15. #include <ndiswan.h>
  16. #include <ndistapi.h>
  17. #include <ntverp.h>
  18. #include "debug.h"
  19. #include "timer.h"
  20. #include "bpool.h"
  21. #include "ppool.h"
  22. #include "util.h"
  23. #include "packet.h"
  24. #include "protocol.h"
  25. #include "miniport.h"
  26. #include "tapi.h"
  27. #include "fsm.h"
  28. //
  29. // This is our global adapter context
  30. //
  31. ADAPTER* gl_pAdapter = NULL;
  32. //
  33. // Lock that controls access to gl_pAdapter.
  34. // This lock is necesarry for requests submitted from the bindings as
  35. // they will not know if the adapter is halted or not.
  36. //
  37. NDIS_SPIN_LOCK gl_lockAdapter;
  38. //
  39. // We need a flag to indicate if lock is allocated or not
  40. //
  41. BOOLEAN gl_fLockAllocated = FALSE;
  42. //
  43. // The timer queue that handles the scheduled timer events.
  44. //
  45. TIMERQ gl_TimerQ;
  46. //
  47. // This is used to create a unique identifier in packets
  48. //
  49. ULONG gl_UniqueCounter = 0;
  50. VOID
  51. CreateUniqueValue(
  52. IN HDRV_CALL hdCall,
  53. OUT CHAR* pUniqueValue,
  54. OUT USHORT* pSize
  55. )
  56. {
  57. CHAR* pBuf = pUniqueValue;
  58. ULONG usUniqueValue = InterlockedIncrement( &gl_UniqueCounter );
  59. NdisMoveMemory( pBuf, (CHAR*) &hdCall, sizeof( HDRV_CALL ) );
  60. pBuf += sizeof( HDRV_CALL );
  61. NdisMoveMemory( pBuf, (CHAR*) &usUniqueValue, sizeof( ULONG ) );
  62. *pSize = sizeof( HDRV_CALL ) + sizeof( ULONG );
  63. }
  64. HDRV_CALL
  65. RetrieveHdCallFromUniqueValue(
  66. IN CHAR* pUniqueValue,
  67. IN USHORT Size
  68. )
  69. {
  70. if ( Size != sizeof( HDRV_CALL ) + sizeof( ULONG ) )
  71. return (HDRV_CALL) NULL;
  72. return ( * (UNALIGNED HDRV_CALL*) pUniqueValue );
  73. }
  74. ////////////////////////////////////
  75. //
  76. // Local function prototypes
  77. //
  78. ////////////////////////////////////
  79. VOID
  80. ReferenceAdapter(
  81. IN ADAPTER* pAdapter,
  82. IN BOOLEAN fAcquireLock
  83. );
  84. VOID DereferenceAdapter(
  85. IN ADAPTER* pAdapter
  86. );
  87. ADAPTER* AllocAdapter();
  88. VOID FreeAdapter(
  89. ADAPTER* pAdapter
  90. );
  91. NDIS_STATUS MpInitialize(
  92. OUT PNDIS_STATUS OpenErrorStatus,
  93. OUT PUINT SelectedMediumIndex,
  94. IN PNDIS_MEDIUM MediumArray,
  95. IN UINT MediumArraySize,
  96. IN NDIS_HANDLE MiniportAdapterHandle,
  97. IN NDIS_HANDLE WrapperConfigurationContext
  98. );
  99. VOID MpHalt(
  100. IN NDIS_HANDLE MiniportAdapterContext
  101. );
  102. NDIS_STATUS MpReset(
  103. OUT PBOOLEAN AddressingReset,
  104. IN NDIS_HANDLE MiniportAdapterContext
  105. );
  106. NDIS_STATUS MpWanSend(
  107. IN NDIS_HANDLE MiniportAdapterContext,
  108. IN NDIS_HANDLE NdisLinkHandle,
  109. IN PNDIS_WAN_PACKET WanPacket
  110. );
  111. NDIS_STATUS MpQueryInformation(
  112. IN NDIS_HANDLE MiniportAdapterContext,
  113. IN NDIS_OID Oid,
  114. IN PVOID InformationBuffer,
  115. IN ULONG InformationBufferLength,
  116. OUT PULONG BytesWritten,
  117. OUT PULONG BytesNeeded
  118. );
  119. NDIS_STATUS MpSetInformation(
  120. IN NDIS_HANDLE MiniportAdapterContext,
  121. IN NDIS_OID Oid,
  122. IN PVOID InformationBuffer,
  123. IN ULONG InformationBufferLength,
  124. OUT PULONG BytesWritten,
  125. OUT PULONG BytesNeeded
  126. );
  127. ////////////////////////////////////
  128. //
  129. // Interface functions definitions
  130. //
  131. ////////////////////////////////////
  132. NDIS_STATUS
  133. MpRegisterMiniport(
  134. IN PDRIVER_OBJECT pDriverObject,
  135. IN PUNICODE_STRING pRegistryPath,
  136. OUT NDIS_HANDLE* pNdisWrapperHandle
  137. )
  138. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  139. Functional Description:
  140. This function will be called from DriverEntry() to register the miniport
  141. and create an instance of the adapter.
  142. Parameters:
  143. DriverObject _ Pointer to driver object created by the system.
  144. RegistryPath _ Pointer to registery path name used to read registry
  145. parameters.
  146. Return Values:
  147. NDIS_STATUS_SUCCESFUL: Miniport registered succesfully.
  148. NDIS_STATUS_FAILURE: Miniport failed to register succesfully.
  149. ---------------------------------------------------------------------------*/
  150. {
  151. NDIS_HANDLE NdisWrapperHandle;
  152. NDIS_STATUS status;
  153. NDIS_MINIPORT_CHARACTERISTICS nmc;
  154. TRACE( TL_I, TM_Mp, ("+MpRegisterMiniport") );
  155. NdisMInitializeWrapper( &NdisWrapperHandle,
  156. pDriverObject,
  157. pRegistryPath,
  158. NULL );
  159. //
  160. // Fill in the miniport characteristics
  161. //
  162. NdisZeroMemory( &nmc, sizeof( NDIS_MINIPORT_CHARACTERISTICS ) );
  163. nmc.MajorNdisVersion = MP_NDIS_MajorVersion;
  164. nmc.MinorNdisVersion = MP_NDIS_MinorVersion;
  165. nmc.Reserved = NDIS_USE_WAN_WRAPPER;
  166. nmc.InitializeHandler = MpInitialize;
  167. nmc.ResetHandler = MpReset;
  168. nmc.HaltHandler = MpHalt;
  169. nmc.QueryInformationHandler = MpQueryInformation;
  170. nmc.SetInformationHandler = MpSetInformation;
  171. nmc.WanSendHandler = MpWanSend;
  172. // no CheckForHangHandler
  173. // no DisableInterruptHandler
  174. // no EnableInterruptHandler
  175. // no HandleInterruptHandler
  176. // no ISRHandler
  177. // no SendHandler (see WanSendHandler)
  178. // no TransferDataHandler
  179. // no WanTransferDataHandler
  180. // no ReturnPacketHandler
  181. // no SendPacketsHandler (see WanSendHandler)
  182. // no AllocateCompleteHandler
  183. // no CoActivateVcHandler
  184. // no CoDeactivateVcHandler
  185. // no CoSendPacketsHandler
  186. // no CoRequestHandler
  187. //
  188. // Set the characteristics registering the miniport
  189. //
  190. status = NdisMRegisterMiniport( NdisWrapperHandle,
  191. &nmc,
  192. sizeof( NDIS_MINIPORT_CHARACTERISTICS ) );
  193. //
  194. // If registeration of miniport was not successful,
  195. // undo the initialization of wrapper
  196. //
  197. if ( status != NDIS_STATUS_SUCCESS )
  198. {
  199. NdisTerminateWrapper( NdisWrapperHandle, NULL );
  200. }
  201. else
  202. {
  203. *pNdisWrapperHandle = NdisWrapperHandle;
  204. }
  205. TRACE( TL_I, TM_Mp, ("-MpRegisterMiniport=$%x",status) );
  206. return status;
  207. }
  208. ////////////////////////////////////
  209. //
  210. // Local function definitions
  211. //
  212. ////////////////////////////////////
  213. VOID
  214. ReferenceAdapter(
  215. IN ADAPTER* pAdapter,
  216. IN BOOLEAN fAcquireLock
  217. )
  218. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  219. Functional Description:
  220. This function will increment the reference count on the adapter object.
  221. CAUTION: If fAcquireLock is set, this function will acquire the lock for the
  222. call, otherwise it will assume the caller owns the lock.
  223. Parameters:
  224. pAdapter _ A pointer to our call information structure.
  225. fAcquireLock _ Indicates if the caller already has the lock or not.
  226. Caller must set this flag to FALSE if it has the lock,
  227. otherwise it must be supplied as TRUE.
  228. Return Values:
  229. None
  230. ---------------------------------------------------------------------------*/
  231. {
  232. LONG lRef;
  233. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  234. TRACE( TL_V, TM_Mp, ("+ReferenceAdapter") );
  235. if ( fAcquireLock )
  236. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  237. lRef = ++pAdapter->lRef;
  238. if ( fAcquireLock )
  239. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  240. TRACE( TL_V, TM_Mp, ("-ReferenceAdapter=$%d",lRef) );
  241. }
  242. VOID
  243. DereferenceAdapter(
  244. IN ADAPTER* pAdapter
  245. )
  246. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  247. Functional Description:
  248. This function will decrement the reference count on the adapter object
  249. If the ref count drops to 0 (which means the adapter has been halted),
  250. it will set fire pAdapter->eventAdapterHalted.
  251. Parameters:
  252. pAdapter _ A pointer ot our call information structure.
  253. Return Values:
  254. None
  255. ---------------------------------------------------------------------------*/
  256. {
  257. LONG lRef;
  258. BOOLEAN fSignalAdapterHaltedEvent = FALSE;
  259. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  260. TRACE( TL_V, TM_Mp, ("+DereferenceAdapter") );
  261. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  262. lRef = --pAdapter->lRef;
  263. if ( lRef == 0 )
  264. {
  265. pAdapter->ulMpFlags &= ~MPBF_MiniportInitialized;
  266. pAdapter->ulMpFlags &= ~MPBF_MiniportHaltPending;
  267. pAdapter->ulMpFlags |= MPBF_MiniportHalted;
  268. fSignalAdapterHaltedEvent = TRUE;
  269. }
  270. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  271. //
  272. // Signal the halting of the adapter if we need to
  273. //
  274. if ( fSignalAdapterHaltedEvent )
  275. NdisSetEvent( &pAdapter->eventAdapterHalted );
  276. TRACE( TL_V, TM_Mp, ("-DereferenceAdapter=$%x",lRef) );
  277. }
  278. ADAPTER*
  279. AllocAdapter()
  280. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  281. Functional Description:
  282. This function will allocate the resources for the adapter object and return
  283. a pointer to it.
  284. Parameters:
  285. None
  286. Return Values:
  287. pAdapter: A pointer to the newly allocated adapter object.
  288. NULL: Resources were not available to create the adapter.
  289. ---------------------------------------------------------------------------*/
  290. {
  291. ADAPTER* pAdapter = NULL;
  292. TRACE( TL_N, TM_Mp, ("+AllocAdapter") );
  293. if ( ALLOC_ADAPTER( &pAdapter ) != NDIS_STATUS_SUCCESS )
  294. {
  295. TRACE( TL_A, TM_Mp, ("AllocAdapter: Could not allocate context") );
  296. TRACE( TL_N, TM_Mp, ("-AllocAdapter") );
  297. return NULL;
  298. }
  299. //
  300. // Clear the memory
  301. //
  302. NdisZeroMemory( pAdapter, sizeof( ADAPTER ) );
  303. //
  304. // Initialize adapter tag
  305. //
  306. pAdapter->tagAdapter = MTAG_ADAPTER;
  307. //
  308. // Allocate the lock that controls access to the adapter
  309. //
  310. NdisAllocateSpinLock( &pAdapter->lockAdapter );
  311. //
  312. // Initialize the state
  313. //
  314. pAdapter->ulMpFlags = MPBF_MiniportIdle;
  315. TRACE( TL_N, TM_Mp, ("-AllocAdapter") );
  316. return pAdapter;
  317. }
  318. NDIS_STATUS
  319. ReadRegistrySettings(
  320. IN OUT ADAPTER* pAdapter,
  321. IN NDIS_HANDLE WrapperConfigurationContext
  322. )
  323. {
  324. NDIS_STATUS status = NDIS_STATUS_FAILURE;
  325. NDIS_HANDLE hCfg = 0;
  326. NDIS_CONFIGURATION_PARAMETER* pncp = 0;
  327. BOOLEAN fMaxLinesDefinedInRegistry = FALSE;
  328. TRACE( TL_N, TM_Mp, ("+ReadRegistrySettings") );
  329. do
  330. {
  331. //
  332. // Open the Ndis configuration, it will be closed at the end of the
  333. // while loop before we exit it.
  334. //
  335. NdisOpenConfiguration( &status,
  336. &hCfg,
  337. WrapperConfigurationContext );
  338. if ( status != NDIS_STATUS_SUCCESS )
  339. {
  340. TRACE( TL_A, TM_Mp, ("ReadRegistrySettings: NdisOpenConfiguration() failed") );
  341. break;
  342. }
  343. //
  344. // Read fClientRole value from the registry only in the debug builds
  345. //
  346. {
  347. #if DBG
  348. NDIS_STRING nstr = NDIS_STRING_CONST( "fClientRole" );
  349. NdisReadConfiguration( &status,
  350. &pncp,
  351. hCfg,
  352. &nstr,
  353. NdisParameterInteger );
  354. if (status == NDIS_STATUS_SUCCESS)
  355. {
  356. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Read fClientRole from registry") );
  357. pAdapter->fClientRole = ( pncp->ParameterData.IntegerData > 0 ) ? TRUE : FALSE;
  358. }
  359. else
  360. #endif
  361. {
  362. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Could not read fClientRole from registry, using default value") );
  363. pAdapter->fClientRole = TRUE;
  364. status = NDIS_STATUS_SUCCESS;
  365. }
  366. }
  367. #if DBG
  368. //
  369. // Read ServiceName and ServiceNameLength values from the registry.
  370. // These are server side only values.
  371. //
  372. {
  373. NDIS_STRING nstr = NDIS_STRING_CONST( "ServiceName" );
  374. NdisReadConfiguration( &status,
  375. &pncp,
  376. hCfg,
  377. &nstr,
  378. NdisParameterString );
  379. if (status == NDIS_STATUS_SUCCESS)
  380. {
  381. ANSI_STRING AnsiString;
  382. NdisZeroMemory( &AnsiString, sizeof( ANSI_STRING ) );
  383. status = RtlUnicodeStringToAnsiString( &AnsiString, &pncp->ParameterData.StringData, TRUE );
  384. if ( status == STATUS_SUCCESS )
  385. {
  386. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Read ServiceName from registry") );
  387. pAdapter->nServiceNameLength = ( MAX_SERVICE_NAME_LENGTH < AnsiString.Length ) ?
  388. MAX_SERVICE_NAME_LENGTH : AnsiString.Length;
  389. NdisMoveMemory( pAdapter->ServiceName, AnsiString.Buffer, pAdapter->nServiceNameLength ) ;
  390. RtlFreeAnsiString( &AnsiString );
  391. }
  392. }
  393. if ( status != NDIS_STATUS_SUCCESS )
  394. {
  395. PWSTR wszKeyName = L"ComputerName";
  396. PWSTR wszPath = L"ComputerName\\ComputerName";
  397. RTL_QUERY_REGISTRY_TABLE QueryTable[2];
  398. UNICODE_STRING UnicodeStr;
  399. WCHAR wszName[ MAX_COMPUTERNAME_LENGTH + 1];
  400. NdisZeroMemory( QueryTable, 2 * sizeof( RTL_QUERY_REGISTRY_TABLE ) );
  401. QueryTable[0].QueryRoutine = NULL;
  402. QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
  403. QueryTable[0].Name = wszKeyName;
  404. QueryTable[0].EntryContext = (PVOID) &UnicodeStr;
  405. NdisZeroMemory( &UnicodeStr, sizeof( UNICODE_STRING ) );
  406. UnicodeStr.Length = 0;
  407. UnicodeStr.MaximumLength = MAX_COMPUTERNAME_LENGTH + 1;
  408. UnicodeStr.Buffer = wszName;
  409. status = RtlQueryRegistryValues( RTL_REGISTRY_CONTROL,
  410. wszPath,
  411. QueryTable,
  412. NULL,
  413. NULL );
  414. if ( status == STATUS_SUCCESS )
  415. {
  416. ANSI_STRING AnsiString;
  417. NdisZeroMemory( &AnsiString, sizeof( ANSI_STRING ) );
  418. status = RtlUnicodeStringToAnsiString( &AnsiString, &UnicodeStr, TRUE );
  419. if ( status == STATUS_SUCCESS )
  420. {
  421. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Using Machine Name as ServiceName") );
  422. NdisMoveMemory( pAdapter->ServiceName, AnsiString.Buffer, AnsiString.Length );
  423. NdisMoveMemory( pAdapter->ServiceName + AnsiString.Length,
  424. SERVICE_NAME_EXTENSION,
  425. sizeof( SERVICE_NAME_EXTENSION ) );
  426. //
  427. // -1 is to ignore the terminating NULL character
  428. //
  429. pAdapter->nServiceNameLength = AnsiString.Length + sizeof( SERVICE_NAME_EXTENSION ) - 1;
  430. RtlFreeAnsiString( &AnsiString );
  431. status = NDIS_STATUS_SUCCESS;
  432. }
  433. }
  434. }
  435. if ( status != NDIS_STATUS_SUCCESS )
  436. {
  437. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Using default hardcoded service name") );
  438. NdisMoveMemory( pAdapter->ServiceName, "MS-RAS PPPoE", sizeof( "MS-RAS PPPoE" ) );
  439. pAdapter->nServiceNameLength = ( sizeof( "MS-RAS PPPoE" ) / sizeof( CHAR ) ) - 1;
  440. status = NDIS_STATUS_SUCCESS;
  441. }
  442. //
  443. // Future: Convert service name to UTF-8
  444. // It turns out that we can not do this conversion from a kernel module,
  445. // so the value read from the registry must be in UTF-8 format itself.
  446. //
  447. }
  448. //
  449. // Read AC-Name and AC-NameLength values from the registry.
  450. // These are server side only values.
  451. //
  452. {
  453. NDIS_STRING nstr = NDIS_STRING_CONST( "ACName" );
  454. NdisReadConfiguration( &status,
  455. &pncp,
  456. hCfg,
  457. &nstr,
  458. NdisParameterString );
  459. if (status == NDIS_STATUS_SUCCESS)
  460. {
  461. ANSI_STRING AnsiString;
  462. NdisZeroMemory( &AnsiString, sizeof( ANSI_STRING ) );
  463. status = RtlUnicodeStringToAnsiString( &AnsiString, &pncp->ParameterData.StringData, TRUE );
  464. if ( status == STATUS_SUCCESS )
  465. {
  466. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Read AC-Name from registry") );
  467. pAdapter->nACNameLength = ( MAX_AC_NAME_LENGTH < AnsiString.Length ) ?
  468. MAX_AC_NAME_LENGTH : AnsiString.Length;
  469. NdisMoveMemory( pAdapter->ACName, AnsiString.Buffer, pAdapter->nACNameLength ) ;
  470. RtlFreeAnsiString( &AnsiString );
  471. }
  472. }
  473. if ( status != NDIS_STATUS_SUCCESS )
  474. {
  475. PWSTR wszKeyName = L"ComputerName";
  476. PWSTR wszPath = L"ComputerName\\ComputerName";
  477. RTL_QUERY_REGISTRY_TABLE QueryTable[2];
  478. UNICODE_STRING UnicodeStr;
  479. WCHAR wszName[ MAX_COMPUTERNAME_LENGTH + 1];
  480. NdisZeroMemory( QueryTable, 2 * sizeof( RTL_QUERY_REGISTRY_TABLE ) );
  481. QueryTable[0].QueryRoutine = NULL;
  482. QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
  483. QueryTable[0].Name = wszKeyName;
  484. QueryTable[0].EntryContext = (PVOID) &UnicodeStr;
  485. NdisZeroMemory( &UnicodeStr, sizeof( UNICODE_STRING ) );
  486. UnicodeStr.Length = 0;
  487. UnicodeStr.MaximumLength = MAX_COMPUTERNAME_LENGTH + 1;
  488. UnicodeStr.Buffer = wszName;
  489. status = RtlQueryRegistryValues( RTL_REGISTRY_CONTROL,
  490. wszPath,
  491. QueryTable,
  492. NULL,
  493. NULL );
  494. if ( status == STATUS_SUCCESS )
  495. {
  496. ANSI_STRING AnsiString;
  497. NdisZeroMemory( &AnsiString, sizeof( ANSI_STRING ) );
  498. status = RtlUnicodeStringToAnsiString( &AnsiString, &UnicodeStr, TRUE );
  499. if ( status == STATUS_SUCCESS )
  500. {
  501. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Using Machine Name as AC-Name") );
  502. NdisMoveMemory( pAdapter->ACName, AnsiString.Buffer, AnsiString.Length );
  503. pAdapter->nACNameLength = AnsiString.Length;
  504. RtlFreeAnsiString( &AnsiString );
  505. status = NDIS_STATUS_SUCCESS;
  506. }
  507. }
  508. }
  509. if ( status != NDIS_STATUS_SUCCESS )
  510. {
  511. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Using default hardcoded value for AC-Name") );
  512. NdisMoveMemory( pAdapter->ACName, "MS-RAS Access Concentrator", sizeof( "MS-RAS Access Concentrator" ) );
  513. pAdapter->nACNameLength = ( sizeof( "MS-RAS Access Concentrator" ) / sizeof( CHAR ) ) - 1;
  514. status = NDIS_STATUS_SUCCESS;
  515. }
  516. //
  517. // Future: Convert AC name to UTF-8
  518. // It turns out that we can not do this conversion from a kernel module,
  519. // so the value read from the registry must be in UTF-8 format itself.
  520. //
  521. }
  522. //
  523. // Read nClientQuota value
  524. // These is a server side only value.
  525. //
  526. {
  527. NDIS_STRING nstr = NDIS_STRING_CONST( "ClientQuota" );
  528. NdisReadConfiguration( &status,
  529. &pncp,
  530. hCfg,
  531. &nstr,
  532. NdisParameterInteger );
  533. if (status == NDIS_STATUS_SUCCESS)
  534. {
  535. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Read ClientQuota from registry") );
  536. pAdapter->nClientQuota = (UINT) pncp->ParameterData.IntegerData;
  537. }
  538. else
  539. #endif
  540. {
  541. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Could not read ClientQuota from registry, using default value") );
  542. pAdapter->nClientQuota = 3;
  543. status = NDIS_STATUS_SUCCESS;
  544. }
  545. #if DBG
  546. }
  547. //
  548. // Read MaxLines value
  549. //
  550. {
  551. NDIS_STRING nstr = NDIS_STRING_CONST( "MaxLines" );
  552. NdisReadConfiguration( &status,
  553. &pncp,
  554. hCfg,
  555. &nstr,
  556. NdisParameterInteger );
  557. if (status == NDIS_STATUS_SUCCESS)
  558. {
  559. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Read MaxLines from registry") );
  560. pAdapter->nMaxLines = (UINT) pncp->ParameterData.IntegerData;
  561. fMaxLinesDefinedInRegistry = TRUE;
  562. }
  563. else
  564. #endif
  565. {
  566. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Could not read MaxLines from registry, using default value") );
  567. pAdapter->nMaxLines = 1;
  568. status = NDIS_STATUS_SUCCESS;
  569. }
  570. #if DBG
  571. }
  572. //
  573. // Read CallsPerLine value
  574. //
  575. {
  576. NDIS_STRING nstr = NDIS_STRING_CONST( "CallsPerLine" );
  577. NdisReadConfiguration( &status,
  578. &pncp,
  579. hCfg,
  580. &nstr,
  581. NdisParameterInteger );
  582. if (status == NDIS_STATUS_SUCCESS)
  583. {
  584. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Read CallsPerLine from registry") );
  585. pAdapter->nCallsPerLine = (UINT) pncp->ParameterData.IntegerData;
  586. }
  587. else
  588. #endif
  589. {
  590. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Could not read CallsPerLine from registry, using default value") );
  591. pAdapter->nCallsPerLine = 1;
  592. status = NDIS_STATUS_SUCCESS;
  593. }
  594. #if DBG
  595. }
  596. #endif
  597. //
  598. // Read WanEndPoints if MaxLines was not defined in registry
  599. //
  600. if ( !fMaxLinesDefinedInRegistry )
  601. {
  602. NDIS_STRING nstr = NDIS_STRING_CONST( "WanEndPoints" );
  603. NdisReadConfiguration( &status,
  604. &pncp,
  605. hCfg,
  606. &nstr,
  607. NdisParameterInteger );
  608. if (status == NDIS_STATUS_SUCCESS)
  609. {
  610. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Read WanEndPoints from registry") );
  611. pAdapter->nMaxLines = 1;
  612. pAdapter->nCallsPerLine = (UINT) pncp->ParameterData.IntegerData;
  613. }
  614. status = NDIS_STATUS_SUCCESS;
  615. }
  616. //
  617. // Read MaxTimeouts value
  618. //
  619. {
  620. NDIS_STRING nstr = NDIS_STRING_CONST( "MaxTimeouts" );
  621. NdisReadConfiguration( &status,
  622. &pncp,
  623. hCfg,
  624. &nstr,
  625. NdisParameterInteger );
  626. if (status == NDIS_STATUS_SUCCESS)
  627. {
  628. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Read MaxTimeouts from registry") );
  629. pAdapter->nMaxTimeouts = (UINT) pncp->ParameterData.IntegerData;
  630. }
  631. else
  632. {
  633. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Could not read MaxTimeouts from registry, using default value") );
  634. pAdapter->nMaxTimeouts = 3;
  635. status = NDIS_STATUS_SUCCESS;
  636. }
  637. }
  638. //
  639. // Read SendTimeout value
  640. //
  641. {
  642. NDIS_STRING nstr = NDIS_STRING_CONST( "SendTimeout" );
  643. NdisReadConfiguration( &status,
  644. &pncp,
  645. hCfg,
  646. &nstr,
  647. NdisParameterInteger );
  648. if (status == NDIS_STATUS_SUCCESS)
  649. {
  650. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Read SendTimeout from registry") );
  651. pAdapter->ulSendTimeout = (ULONG) pncp->ParameterData.IntegerData;
  652. }
  653. else
  654. {
  655. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Could not read SendTimeout from registry, using default value") );
  656. pAdapter->ulSendTimeout = 5000;
  657. status = NDIS_STATUS_SUCCESS;
  658. }
  659. }
  660. //
  661. // Read RecvTimeout value
  662. //
  663. {
  664. NDIS_STRING nstr = NDIS_STRING_CONST( "RecvTimeout" );
  665. NdisReadConfiguration( &status,
  666. &pncp,
  667. hCfg,
  668. &nstr,
  669. NdisParameterInteger );
  670. if (status == NDIS_STATUS_SUCCESS)
  671. {
  672. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Read RecvTimeout from registry") );
  673. pAdapter->ulRecvTimeout = (ULONG) pncp->ParameterData.IntegerData;
  674. }
  675. else
  676. {
  677. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Could not read RecvTimeout from registry, using default value") );
  678. pAdapter->ulRecvTimeout = 5000;
  679. status = NDIS_STATUS_SUCCESS;
  680. }
  681. }
  682. //
  683. // Read fAcceptAnyService value from the registry
  684. //
  685. {
  686. NDIS_STRING nstr = NDIS_STRING_CONST( "fAcceptAnyService" );
  687. NdisReadConfiguration( &status,
  688. &pncp,
  689. hCfg,
  690. &nstr,
  691. NdisParameterInteger );
  692. if (status == NDIS_STATUS_SUCCESS)
  693. {
  694. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Read fAcceptAnyService from registry") );
  695. pAdapter->fAcceptAnyService = ( pncp->ParameterData.IntegerData > 0 ) ? TRUE : FALSE;
  696. }
  697. else
  698. {
  699. TRACE( TL_N, TM_Mp, ("ReadRegistrySettings: Could not read fAcceptAnyService from registry, using default value") );
  700. pAdapter->fAcceptAnyService = TRUE;
  701. status = NDIS_STATUS_SUCCESS;
  702. }
  703. }
  704. //
  705. // Close the Ndis configuration
  706. //
  707. NdisCloseConfiguration( hCfg );
  708. } while ( FALSE );
  709. TRACE( TL_N, TM_Mp, ("-ReadRegistrySettings=$%x",status) );
  710. return status;
  711. }
  712. NDIS_STATUS
  713. InitializeAdapter(
  714. IN ADAPTER* pAdapter,
  715. IN NDIS_HANDLE MiniportAdapterHandle,
  716. IN NDIS_HANDLE WrapperConfigurationContext
  717. )
  718. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  719. Functional Description:
  720. This function will initialize the contents of the adapter object.
  721. It will be called from inside MpInitialize() and it will read the necesarry
  722. values from the registry to initialize the adapter context.
  723. Parameters:
  724. pAdapter _ A pointer to our adapter information structure.
  725. Return Values:
  726. None
  727. ---------------------------------------------------------------------------*/
  728. {
  729. NDIS_STATUS status = NDIS_STATUS_SUCCESS;
  730. NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress = NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
  731. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  732. TRACE( TL_N, TM_Mp, ("+InitializeAdapter") );
  733. //
  734. // Initialize and reset the adapter halted event
  735. //
  736. NdisInitializeEvent( &pAdapter->eventAdapterHalted );
  737. NdisResetEvent( &pAdapter->eventAdapterHalted );
  738. //
  739. // Set the state
  740. //
  741. pAdapter->ulMpFlags = MPBF_MiniportInitialized;
  742. //
  743. // Set NDIS's corresponding handle
  744. //
  745. pAdapter->MiniportAdapterHandle = MiniportAdapterHandle;
  746. //
  747. // Read values from registry
  748. //
  749. status = ReadRegistrySettings( pAdapter, WrapperConfigurationContext );
  750. pAdapter->nMaxSendPackets = 1;
  751. //
  752. // Initialize the NdisWanInfo structure
  753. //
  754. pAdapter->NdisWanInfo.MaxFrameSize = PACKET_PPP_PAYLOAD_MAX_LENGTH;
  755. pAdapter->NdisWanInfo.MaxTransmit = 1;
  756. pAdapter->NdisWanInfo.HeaderPadding = PPPOE_PACKET_HEADER_LENGTH;
  757. pAdapter->NdisWanInfo.TailPadding = 0;
  758. pAdapter->NdisWanInfo.Endpoints = pAdapter->nCallsPerLine * pAdapter->nMaxLines;
  759. pAdapter->NdisWanInfo.MemoryFlags = 0;
  760. pAdapter->NdisWanInfo.HighestAcceptableAddress = HighestAcceptableAddress;
  761. pAdapter->NdisWanInfo.FramingBits = PPP_FRAMING |
  762. // PPP_COMPRESS_ADDRESS_CONTROL |
  763. // PPP_COMPRESS_PROTOCOL_FIELD |
  764. TAPI_PROVIDER;
  765. pAdapter->NdisWanInfo.DesiredACCM = 0;
  766. TRACE( TL_N, TM_Mp, ("-InitializeAdapter=$%x",status) );
  767. return status;
  768. }
  769. VOID
  770. FreeAdapter(
  771. ADAPTER* pAdapter
  772. )
  773. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  774. Functional Description:
  775. This function will deallocate the resources for the adapter object.
  776. Parameters:
  777. pAdapter _ A pointer to our adapter information structure.
  778. Return Values:
  779. None
  780. ---------------------------------------------------------------------------*/
  781. {
  782. ASSERT( VALIDATE_ADAPTER( pAdapter ) );
  783. TRACE( TL_N, TM_Mp, ("+FreeAdapter") );
  784. NdisFreeSpinLock( &pAdapter->lockAdapter );
  785. FREE_ADAPTER( pAdapter );
  786. TRACE( TL_N, TM_Mp, ("-FreeAdapter") );
  787. }
  788. NDIS_STATUS
  789. MpInitialize(
  790. OUT PNDIS_STATUS OpenErrorStatus,
  791. OUT PUINT SelectedMediumIndex,
  792. IN PNDIS_MEDIUM MediumArray,
  793. IN UINT MediumArraySize,
  794. IN NDIS_HANDLE MiniportAdapterHandle,
  795. IN NDIS_HANDLE WrapperConfigurationContext
  796. )
  797. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  798. Functional Description:
  799. The MiniportInitialize request is called to have the Miniport driver
  800. initialize the adapter.
  801. No other request will be outstanding on the Miniport when this routine
  802. is called. No other request will be submitted to the Miniport until
  803. the operation is completed.
  804. The wrapper will supply an array containing a list of the media types
  805. that it supports. The Miniport driver reads this array and returns
  806. the index of the media type that the wrapper should treat her as.
  807. If the Miniport driver is impersonating a media type that is different
  808. from the true media type, this must be done completely transparently to
  809. the wrapper.
  810. If the Miniport driver cannot find a media type supported by both it
  811. and the wrapper, it returns NDIS_STATUS_UNSUPPORTED_MEDIA.
  812. The status value NDIS_STATUS_OPEN_ERROR has a special meaning. It
  813. indicates that the OpenErrorStatus parameter has returned a valid status
  814. which the wrapper can examine to obtain more information about the error.
  815. This routine is called with interrupts enabled, and a call to MiniportISR
  816. will occur if the adapter generates any interrupts. During this routine
  817. MiniportDisableInterrupt and MiniportEnableInterrupt will not be called,
  818. so it is the responsibility of the Miniport driver to acknowledge and
  819. clear any interrupts generated.
  820. This routine will be called from the context of MpRegisterMiniport().
  821. Parameters:
  822. OpenErrorStatus _ Returns more information about the reason for the
  823. failure. Currently, the only values defined match those
  824. specified as Open Error Codes in Appendix B of the IBM
  825. Local Area Network Technical Reference.
  826. SelectedMediumIndex _ Returns the index in MediumArray of the medium type
  827. that the Miniport driver wishes to be viewed as.
  828. Note that even though the NDIS interface may complete
  829. this request asynchronously, it must return this
  830. index on completion of this function.
  831. MediumArray _ An array of medium types which the wrapper supports.
  832. MediumArraySize _ The number of elements in MediumArray.
  833. MiniportAdapterHandle _ A handle identifying the Miniport. The Miniport
  834. driver must supply this handle in future requests
  835. that refer to the Miniport.
  836. WrapperConfigurationContext _ The handle used for calls to NdisOpenConfiguration.
  837. Return Values:
  838. NDIS_STATUS_ADAPTER_NOT_FOUND
  839. NDIS_STATUS_FAILURE
  840. NDIS_STATUS_NOT_ACCEPTED
  841. NDIS_STATUS_OPEN_ERROR
  842. NDIS_STATUS_RESOURCES
  843. NDIS_STATUS_SUCCESS
  844. NDIS_STATUS_UNSUPPORTED_MEDIA
  845. ---------------------------------------------------------------------------*/
  846. {
  847. NDIS_STATUS status = NDIS_STATUS_SUCCESS;
  848. ADAPTER* pAdapter = NULL;
  849. UINT i;
  850. TRACE( TL_I, TM_Mp, ("+MpInitialize") );
  851. do
  852. {
  853. //
  854. // Select the medium
  855. //
  856. for (i=0; i<MediumArraySize; i++)
  857. {
  858. if ( MediumArray[i] == NdisMediumWan )
  859. break;
  860. }
  861. //
  862. // Check if we have found a medium supported
  863. //
  864. if ( i < MediumArraySize )
  865. {
  866. *SelectedMediumIndex = i;
  867. }
  868. else
  869. {
  870. TRACE( TL_A, TM_Mp, ("MpInitialize: Unsupported Media") );
  871. status = NDIS_STATUS_UNSUPPORTED_MEDIA;
  872. break;
  873. }
  874. //
  875. // Allocate the adapter block
  876. //
  877. pAdapter = AllocAdapter();
  878. if ( pAdapter == NULL )
  879. {
  880. TRACE( TL_A, TM_Mp, ("MpInitialize: Resources unavailable") );
  881. status = NDIS_STATUS_FAILURE;
  882. break;
  883. }
  884. //
  885. // Initialize the adapter
  886. //
  887. status = InitializeAdapter( pAdapter,
  888. MiniportAdapterHandle,
  889. WrapperConfigurationContext );
  890. if ( status != NDIS_STATUS_SUCCESS )
  891. {
  892. TRACE( TL_A, TM_Mp, ("MpInitialize: InitializeAdapter() failed") );
  893. break;
  894. }
  895. //
  896. // Inform NDIS about our miniport adapter context
  897. //
  898. NdisMSetAttributesEx(MiniportAdapterHandle,
  899. pAdapter,
  900. 0,
  901. NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT |
  902. NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT |
  903. NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND |
  904. NDIS_ATTRIBUTE_DESERIALIZE,
  905. NdisInterfaceInternal );
  906. //
  907. // Do the global initialization
  908. //
  909. gl_pAdapter = pAdapter;
  910. //
  911. // Allocate the packet pools
  912. //
  913. PacketPoolInit();
  914. //
  915. // Do one-time only initialization of global members
  916. //
  917. if ( !gl_fLockAllocated )
  918. {
  919. //
  920. // Allocate the spin lock
  921. //
  922. NdisAllocateSpinLock( &gl_lockAdapter );
  923. //
  924. // Initialize the timer queue
  925. //
  926. TimerQInitialize( &gl_TimerQ );
  927. //
  928. // Finally set lock allocated flag, and start giving access
  929. // to the adapter context for requests from the protocol
  930. //
  931. gl_fLockAllocated = TRUE;
  932. }
  933. //
  934. // Reference the adapter for initialization.
  935. // This reference will be removed in MpHalt().
  936. //
  937. ReferenceAdapter( pAdapter, TRUE );
  938. } while ( FALSE );
  939. if ( status != NDIS_STATUS_SUCCESS )
  940. {
  941. if ( pAdapter != NULL )
  942. {
  943. FreeAdapter( pAdapter );
  944. }
  945. }
  946. TRACE( TL_I, TM_Mp, ("-MpInitialize=$%x",status) );
  947. return status;
  948. }
  949. VOID
  950. MpHalt(
  951. IN NDIS_HANDLE MiniportAdapterContext
  952. )
  953. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  954. Functional Description:
  955. The MiniportHalt request is used to halt the adapter such that it is
  956. no longer functioning. The Miniport driver should stop the adapter
  957. and deregister all of its resources before returning from this routine.
  958. It is not necessary for the Miniport to complete all outstanding
  959. requests and no other requests will be submitted to the Miniport
  960. until the operation is completed.
  961. Interrupts are enabled during the call to this routine.
  962. Parameters:
  963. MiniportAdapterContext _ The adapter handle passed to NdisMSetAttributes
  964. during MiniportInitialize.
  965. Return Values:
  966. None.
  967. ---------------------------------------------------------------------------*/
  968. {
  969. ADAPTER* pAdapter = MiniportAdapterContext;
  970. TRACE( TL_I, TM_Mp, ("+MpHalt") );
  971. //
  972. // Make sure adapter context is a valid one
  973. //
  974. if ( !VALIDATE_ADAPTER( pAdapter ) )
  975. {
  976. TRACE( TL_I, TM_Mp, ("-MpHalt") );
  977. return;
  978. }
  979. //
  980. // Lock the adapter and set halt pending bit
  981. //
  982. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  983. pAdapter->ulMpFlags |= MPBF_MiniportHaltPending;
  984. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  985. //
  986. // Shutdown the tapi provider
  987. //
  988. {
  989. NDIS_TAPI_PROVIDER_SHUTDOWN DummyRequest;
  990. NdisZeroMemory( &DummyRequest, sizeof( NDIS_TAPI_PROVIDER_SHUTDOWN ) );
  991. TpProviderShutdown( pAdapter, &DummyRequest, FALSE);
  992. }
  993. //
  994. // Remove the reference added in MpInitialize()
  995. //
  996. DereferenceAdapter( pAdapter );
  997. //
  998. // Wait for all references to be removed
  999. //
  1000. NdisWaitEvent( &pAdapter->eventAdapterHalted, 0 );
  1001. //
  1002. // All references have been removed, now wait for all packets owned by NDIS
  1003. // to be returned.
  1004. //
  1005. // Note that no synchronization is necesarry for reading the value of NumPacketsOwnedByNdis
  1006. // at this point since it can only be incremented when there is at least 1 reference on the
  1007. // binding - at this point ref count is 0 -, and because it can not be incremented, it can
  1008. // only reach 0 once.
  1009. //
  1010. while ( pAdapter->NumPacketsOwnedByNdiswan )
  1011. {
  1012. NdisMSleep( 10000 );
  1013. }
  1014. //
  1015. // Do deallocation of global resources first
  1016. //
  1017. NdisAcquireSpinLock( &gl_lockAdapter );
  1018. gl_pAdapter = NULL;
  1019. PacketPoolUninit();
  1020. NdisReleaseSpinLock( &gl_lockAdapter );
  1021. //
  1022. // Now we can clean up the adapter context
  1023. //
  1024. FreeAdapter( pAdapter );
  1025. TRACE( TL_I, TM_Mp, ("-MpHalt") );
  1026. }
  1027. NDIS_STATUS
  1028. MpReset(
  1029. OUT PBOOLEAN AddressingReset,
  1030. IN NDIS_HANDLE MiniportAdapterContext
  1031. )
  1032. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1033. Functional Description:
  1034. The MiniportReset request instructs the Miniport driver to issue a
  1035. hardware reset to the network adapter. The Miniport driver also
  1036. resets its software state.
  1037. The MiniportReset request may also reset the parameters of the adapter.
  1038. If a hardware reset of the adapter resets the current station address
  1039. to a value other than what it is currently configured to, the Miniport
  1040. driver automatically restores the current station address following the
  1041. reset. Any multicast or functional addressing masks reset by the
  1042. hardware do not have to be reprogrammed by the Miniport.
  1043. NOTE: This is change from the NDIS 3.0 driver specification. If the
  1044. multicast or functional addressing information, the packet filter, the
  1045. lookahead size, and so on, needs to be restored, the Miniport indicates
  1046. this with setting the flag AddressingReset to TRUE.
  1047. It is not necessary for the Miniport to complete all outstanding requests
  1048. and no other requests will be submitted to the Miniport until the
  1049. operation is completed. Also, the Miniport does not have to signal
  1050. the beginning and ending of the reset with NdisMIndicateStatus.
  1051. NOTE: These are different than the NDIS 3.0 driver specification.
  1052. The Miniport driver must complete the original request, if the orginal
  1053. call to MiniportReset return NDIS_STATUS_PENDING, by calling
  1054. NdisMResetComplete.
  1055. If the underlying hardware does not provide a reset function under
  1056. software control, then this request completes abnormally with
  1057. NDIS_STATUS_NOT_RESETTABLE. If the underlying hardware attempts a
  1058. reset and finds recoverable errors, the request completes successfully
  1059. with NDIS_STATUS_SOFT_ERRORS. If the underlying hardware resets and,
  1060. in the process, finds nonrecoverable errors, the request completes
  1061. successfully with the status NDIS_STATUS_HARD_ERRORS. If the
  1062. underlying hardware reset is accomplished without any errors,
  1063. the request completes successfully with the status NDIS_STATUS_SUCCESS.
  1064. Interrupts are in any state during this call.
  1065. Parameters:
  1066. MiniportAdapterContext _ The adapter handle passed to NdisMSetAttributes
  1067. during MiniportInitialize.
  1068. AddressingReset _ The Miniport indicates if the wrapper needs to call
  1069. MiniportSetInformation to restore the addressing
  1070. information to the current values by setting this
  1071. value to TRUE.
  1072. Return Values:
  1073. NDIS_STATUS_HARD_ERRORS
  1074. NDIS_STATUS_NOT_ACCEPTED
  1075. NDIS_STATUS_NOT_RESETTABLE
  1076. NDIS_STATUS_PENDING
  1077. NDIS_STATUS_SOFT_ERRORS
  1078. NDIS_STATUS_SUCCESS
  1079. ---------------------------------------------------------------------------*/
  1080. {
  1081. TRACE( TL_I, TM_Mp, ("+MpReset") );
  1082. TRACE( TL_I, TM_Mp, ("-MpReset") );
  1083. return NDIS_STATUS_NOT_RESETTABLE;
  1084. }
  1085. NDIS_STATUS
  1086. MpWanSend(
  1087. IN NDIS_HANDLE MiniportAdapterContext,
  1088. IN NDIS_HANDLE NdisLinkHandle,
  1089. IN PNDIS_WAN_PACKET WanPacket
  1090. )
  1091. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1092. Functional Description:
  1093. The Ndis(M)WanSend instructs a WAN driver to transmit a packet through the
  1094. adapter onto the medium.
  1095. Ownership of both the packet descriptor and the packet data is transferred
  1096. to the WAN driver until the request is completed, either synchronously or
  1097. asynchronously. If the WAN driver returns a status other than
  1098. NDIS_STATUS_PENDING, then the request is complete, and ownership of the
  1099. packet immediately reverts to the protocol. If the WAN driver returns
  1100. NDIS_STATUS_PENDING, then the WAN driver must later indicate completion
  1101. of the request by calling Ndis(M)WanSendComplete.
  1102. The WAN driver should NOT return a status of NDIS_STATUS_RESOURCES to
  1103. indicate that there are not enough resources available to process the
  1104. transmit. Instead, the miniport should queue the send for a later time
  1105. or lower the MaxTransmits value.
  1106. The WAN miniport can NOT call NdisMSendResourcesAvailable.
  1107. The packet passed in Ndis(M)WanSend will contain simple HDLC PPP framing
  1108. if PPP framing is set. For SLIP or RAS framing, the packet contains only
  1109. the data portion with no framing whatsoever.
  1110. A WAN driver must NOT provide software loopback or promiscuous mode
  1111. loopback. Both of these are fully provided for in the WAN wrapper.
  1112. NOTE: The MacReservedx section as well as the WanPacketQueue section of
  1113. the NDIS_WAN_PACKET is fully available for use by the WAN driver.
  1114. Interrupts are in any state during this routine.
  1115. Parameters:
  1116. MacBindingHandle _ The handle to be passed to NdisMWanSendComplete().
  1117. NdisLinkHandle _ The Miniport link handle passed to NDIS_LINE_UP
  1118. WanPacket _ A pointer to the NDIS_WAN_PACKET strucutre. The structure
  1119. contains a pointer to a contiguous buffer with guaranteed
  1120. padding at the beginning and end. The driver may manipulate
  1121. the buffer in any way.
  1122. typedef struct _NDIS_WAN_PACKET
  1123. {
  1124. LIST_ENTRY WanPacketQueue;
  1125. PUCHAR CurrentBuffer;
  1126. ULONG CurrentLength;
  1127. PUCHAR StartBuffer;
  1128. PUCHAR EndBuffer;
  1129. PVOID ProtocolReserved1;
  1130. PVOID ProtocolReserved2;
  1131. PVOID ProtocolReserved3;
  1132. PVOID ProtocolReserved4;
  1133. PVOID MacReserved1; // Link
  1134. PVOID MacReserved2; // MacBindingHandle
  1135. PVOID MacReserved3;
  1136. PVOID MacReserved4;
  1137. } NDIS_WAN_PACKET, *PNDIS_WAN_PACKET;
  1138. The available header padding is simply CurrentBuffer-StartBuffer.
  1139. The available tail padding is EndBuffer-(CurrentBuffer+CurrentLength).
  1140. Return Values:
  1141. NDIS_STATUS_INVALID_DATA
  1142. NDIS_STATUS_INVALID_LENGTH
  1143. NDIS_STATUS_INVALID_OID
  1144. NDIS_STATUS_NOT_ACCEPTED
  1145. NDIS_STATUS_NOT_SUPPORTED
  1146. NDIS_STATUS_PENDING
  1147. NDIS_STATUS_SUCCESS
  1148. NDIS_STATUS_FAILURE
  1149. ---------------------------------------------------------------------------*/
  1150. {
  1151. ADAPTER* pAdapter = MiniportAdapterContext;
  1152. NDIS_STATUS status = NDIS_STATUS_FAILURE;
  1153. CALL* pCall = NULL;
  1154. BINDING* pBinding = NULL;
  1155. PPPOE_PACKET* pPacket = NULL;
  1156. BOOLEAN fTapiProvReferenced = FALSE;
  1157. TRACE( TL_V, TM_Mp, ("+MpWanSend($%x,$%x,$%x)",MiniportAdapterContext,NdisLinkHandle,WanPacket) );
  1158. do
  1159. {
  1160. //
  1161. // Make sure adapter context is a valid one
  1162. //
  1163. if ( !VALIDATE_ADAPTER( pAdapter ) )
  1164. {
  1165. TRACE( TL_A, TM_Tp, ("MpWanSend($%x,$%x,$%x): Invalid adapter handle supplied",
  1166. MiniportAdapterContext,
  1167. NdisLinkHandle,
  1168. WanPacket) );
  1169. break;
  1170. }
  1171. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  1172. //
  1173. // Make sure the handle table will not be freed as long as we need it
  1174. // in this function
  1175. //
  1176. if ( !( pAdapter->TapiProv.ulTpFlags & TPBF_TapiProvShutdownPending ) &&
  1177. ( pAdapter->TapiProv.ulTpFlags & TPBF_TapiProvInitialized ) )
  1178. {
  1179. fTapiProvReferenced = TRUE;
  1180. ReferenceTapiProv( pAdapter, FALSE );
  1181. }
  1182. else
  1183. {
  1184. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  1185. TRACE( TL_A, TM_Tp, ("MpWanSend($%x,$%x,$%x): Tapi provider not initialized, or shutting down",
  1186. MiniportAdapterContext,
  1187. NdisLinkHandle,
  1188. WanPacket) );
  1189. break;
  1190. }
  1191. //
  1192. // Map the handle to the pointer for the call context
  1193. //
  1194. pCall = RetrieveFromHandleTable( pAdapter->TapiProv.hCallTable, NdisLinkHandle );
  1195. if ( pCall == NULL )
  1196. {
  1197. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  1198. TRACE( TL_A, TM_Tp, ("MpWanSend($%x,$%x,$%x): Invalid call handle supplied",
  1199. MiniportAdapterContext,
  1200. NdisLinkHandle,
  1201. WanPacket) );
  1202. break;
  1203. }
  1204. NdisAcquireSpinLock( &pCall->lockCall );
  1205. if ( pCall->pBinding == NULL )
  1206. {
  1207. NdisReleaseSpinLock( &pCall->lockCall );
  1208. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  1209. TRACE( TL_A, TM_Tp, ("MpWanSend($%x,$%x,$%x): Binding not found",
  1210. MiniportAdapterContext,
  1211. NdisLinkHandle,
  1212. WanPacket) );
  1213. break;
  1214. }
  1215. status = PacketInitializePAYLOADToSend( &pPacket,
  1216. pCall->SrcAddr,
  1217. pCall->DestAddr,
  1218. pCall->usSessionId,
  1219. WanPacket,
  1220. pCall->pLine->pAdapter );
  1221. if ( status != NDIS_STATUS_SUCCESS )
  1222. {
  1223. NdisReleaseSpinLock( &pCall->lockCall );
  1224. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  1225. TRACE( TL_N, TM_Tp, ("MpWanSend($%x,$%x,$%x): Could not init payload packet to send",
  1226. MiniportAdapterContext,
  1227. NdisLinkHandle,
  1228. WanPacket) );
  1229. break;
  1230. }
  1231. pBinding = pCall->pBinding;
  1232. ReferenceBinding( pBinding, TRUE );
  1233. //
  1234. // Reference the packet so that if PrSend() pends,
  1235. // packet still exists around
  1236. //
  1237. ReferencePacket( pPacket );
  1238. //
  1239. // Release the locks to send the packet
  1240. //
  1241. NdisReleaseSpinLock( &pCall->lockCall );
  1242. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  1243. //
  1244. // Packet is ready, so send it
  1245. //
  1246. status = PrSend( pBinding, pPacket );
  1247. //
  1248. // Since the result of send will always be completed by a call to NdisMWanSendComplete(),
  1249. // we have to return NDIS_STATUS_PENDING from this function.
  1250. //
  1251. status = NDIS_STATUS_PENDING;
  1252. //
  1253. // We can free the packet as we have a reference on the packet
  1254. //
  1255. PacketFree( pPacket );
  1256. } while ( FALSE );
  1257. //
  1258. // If a reference is added on the tapi provider, remove it
  1259. //
  1260. if ( fTapiProvReferenced )
  1261. {
  1262. DereferenceTapiProv( pAdapter );
  1263. }
  1264. TRACE( TL_V, TM_Mp, ("-MpWanSend($%x,$%x,$%x)=$%x",MiniportAdapterContext,NdisLinkHandle,WanPacket,status) );
  1265. return status;
  1266. }
  1267. typedef struct
  1268. _SUPPORTED_OIDS
  1269. {
  1270. NDIS_OID ndisOid;
  1271. CHAR szOidName[64];
  1272. }
  1273. SUPPORTED_OIDS;
  1274. SUPPORTED_OIDS
  1275. SupportedOidsArray[] = {
  1276. { OID_GEN_CURRENT_LOOKAHEAD, "OID_GEN_CURRENT_LOOKAHEAD" },
  1277. { OID_GEN_DRIVER_VERSION, "OID_GEN_DRIVER_VERSION" },
  1278. { OID_GEN_HARDWARE_STATUS, "OID_GEN_HARDWARE_STATUS" },
  1279. { OID_GEN_LINK_SPEED, "OID_GEN_LINK_SPEED" },
  1280. { OID_GEN_MAC_OPTIONS, "OID_GEN_MAC_OPTIONS" },
  1281. { OID_GEN_MAXIMUM_LOOKAHEAD, "OID_GEN_MAXIMUM_LOOKAHEAD" },
  1282. { OID_GEN_MAXIMUM_FRAME_SIZE, "OID_GEN_MAXIMUM_FRAME_SIZE" },
  1283. { OID_GEN_MAXIMUM_TOTAL_SIZE, "OID_GEN_MAXIMUM_TOTAL_SIZE" },
  1284. { OID_GEN_MEDIA_SUPPORTED, "OID_GEN_MEDIA_SUPPORTED" },
  1285. { OID_GEN_MEDIA_IN_USE, "OID_GEN_MEDIA_IN_USE" },
  1286. { OID_GEN_RCV_ERROR, "OID_GEN_RCV_ERROR" },
  1287. { OID_GEN_RCV_OK, "OID_GEN_RCV_OK" },
  1288. { OID_GEN_RECEIVE_BLOCK_SIZE, "OID_GEN_RECEIVE_BLOCK_SIZE" },
  1289. { OID_GEN_RECEIVE_BUFFER_SPACE, "OID_GEN_RECEIVE_BUFFER_SPACE" },
  1290. { OID_GEN_SUPPORTED_LIST, "OID_GEN_SUPPORTED_LIST" },
  1291. { OID_GEN_TRANSMIT_BLOCK_SIZE, "OID_GEN_TRANSMIT_BLOCK_SIZE" },
  1292. { OID_GEN_TRANSMIT_BUFFER_SPACE, "OID_GEN_TRANSMIT_BUFFER_SPACE" },
  1293. { OID_GEN_VENDOR_DESCRIPTION, "OID_GEN_VENDOR_DESCRIPTION" },
  1294. { OID_GEN_VENDOR_ID, "OID_GEN_VENDOR_ID" },
  1295. { OID_GEN_XMIT_ERROR, "OID_GEN_XMIT_ERROR" },
  1296. { OID_GEN_XMIT_OK, "OID_GEN_XMIT_OK" },
  1297. { OID_PNP_CAPABILITIES, "OID_PNP_CAPABILITIES" },
  1298. { OID_PNP_SET_POWER, "OID_PNP_SET_POWER" },
  1299. { OID_PNP_QUERY_POWER, "OID_PNP_QUERY_POWER" },
  1300. { OID_PNP_ENABLE_WAKE_UP, "OID_PNP_ENABLE_WAKE_UP" },
  1301. { OID_TAPI_CLOSE, "OID_TAPI_CLOSE" },
  1302. { OID_TAPI_DROP, "OID_TAPI_DROP" },
  1303. { OID_TAPI_GET_ADDRESS_CAPS, "OID_TAPI_GET_ADDRESS_CAPS" },
  1304. { OID_TAPI_GET_ADDRESS_STATUS, "OID_TAPI_GET_ADDRESS_STATUS" },
  1305. { OID_TAPI_GET_CALL_INFO, "OID_TAPI_GET_CALL_INFO" },
  1306. { OID_TAPI_GET_CALL_STATUS, "OID_TAPI_GET_CALL_STATUS" },
  1307. { OID_TAPI_GET_DEV_CAPS, "OID_TAPI_GET_DEV_CAPS" },
  1308. { OID_TAPI_GET_EXTENSION_ID, "OID_TAPI_GET_EXTENSION_ID" },
  1309. { OID_TAPI_MAKE_CALL, "OID_TAPI_MAKE_CALL" },
  1310. { OID_TAPI_CLOSE_CALL, "OID_TAPI_CLOSE_CALL" },
  1311. { OID_TAPI_NEGOTIATE_EXT_VERSION, "OID_TAPI_NEGOTIATE_EXT_VERSION"},
  1312. { OID_TAPI_OPEN, "OID_TAPI_OPEN" },
  1313. { OID_TAPI_ANSWER, "OID_TAPI_ANSWER" },
  1314. { OID_TAPI_PROVIDER_INITIALIZE, "OID_TAPI_PROVIDER_INITIALIZE" },
  1315. { OID_TAPI_PROVIDER_SHUTDOWN, "OID_TAPI_PROVIDER_SHUTDOWN" },
  1316. { OID_TAPI_SET_STATUS_MESSAGES, "OID_TAPI_SET_STATUS_MESSAGES" },
  1317. { OID_TAPI_SET_DEFAULT_MEDIA_DETECTION, "OID_TAPI_SET_DEFAULT_MEDIA_DETECTION" },
  1318. { OID_WAN_CURRENT_ADDRESS, "OID_WAN_CURRENT_ADDRESS" },
  1319. { OID_WAN_GET_BRIDGE_INFO, "OID_WAN_GET_BRIDGE_INFO" },
  1320. { OID_WAN_GET_COMP_INFO, "OID_WAN_GET_COMP_INFO" },
  1321. { OID_WAN_GET_INFO, "OID_WAN_GET_INFO" },
  1322. { OID_WAN_GET_LINK_INFO, "OID_WAN_GET_LINK_INFO" },
  1323. { OID_WAN_GET_STATS_INFO, "OID_WAN_GET_STATS_INFO" },
  1324. { OID_WAN_HEADER_FORMAT, "OID_WAN_HEADER_FORMAT" },
  1325. { OID_WAN_LINE_COUNT, "OID_WAN_LINE_COUNT" },
  1326. { OID_WAN_MEDIUM_SUBTYPE, "OID_WAN_MEDIUM_SUBTYPE" },
  1327. { OID_WAN_PERMANENT_ADDRESS, "OID_WAN_PERMANENT_ADDRESS" },
  1328. { OID_WAN_PROTOCOL_TYPE, "OID_WAN_PERMANENT_ADDRESS" },
  1329. { OID_WAN_QUALITY_OF_SERVICE, "OID_WAN_QUALITY_OF_SERVICE" },
  1330. { OID_WAN_SET_BRIDGE_INFO, "OID_WAN_SET_BRIDGE_INFO" },
  1331. { OID_WAN_SET_COMP_INFO, "OID_WAN_SET_COMP_INFO" },
  1332. { OID_WAN_SET_LINK_INFO, "OID_WAN_SET_LINK_INFO" },
  1333. { (NDIS_OID) 0, "UNKNOWN OID" }
  1334. };
  1335. CHAR* GetOidName(
  1336. NDIS_OID Oid
  1337. )
  1338. {
  1339. //
  1340. // Calculate the number of oids we support.
  1341. // (Subtract one for unknown oid)
  1342. //
  1343. UINT nNumOids = ( sizeof( SupportedOidsArray ) / sizeof( SUPPORTED_OIDS ) ) - 1;
  1344. UINT i;
  1345. for ( i = 0; i < nNumOids; i++ )
  1346. {
  1347. if ( Oid == SupportedOidsArray[i].ndisOid )
  1348. break;
  1349. }
  1350. return SupportedOidsArray[i].szOidName;
  1351. }
  1352. #define ENFORCE_SAFE_TOTAL_SIZE(mainStruct, embeddedStruct) \
  1353. ((mainStruct*) InformationBuffer)->embeddedStruct.ulTotalSize = InformationBufferLength - FIELD_OFFSET(mainStruct, embeddedStruct)
  1354. #define RETRIEVE_NEEDED_AND_USED_LENGTH(mainStruct, embeddedStruct) \
  1355. { \
  1356. NeededLength = ((mainStruct*) InformationBuffer)->embeddedStruct.ulNeededSize + FIELD_OFFSET(mainStruct, embeddedStruct); \
  1357. UsedLength = ((mainStruct*) InformationBuffer)->embeddedStruct.ulUsedSize + FIELD_OFFSET(mainStruct, embeddedStruct); \
  1358. }
  1359. NDIS_STATUS
  1360. MpQueryInformation(
  1361. IN NDIS_HANDLE MiniportAdapterContext,
  1362. IN NDIS_OID Oid,
  1363. IN PVOID InformationBuffer,
  1364. IN ULONG InformationBufferLength,
  1365. OUT PULONG BytesWritten,
  1366. OUT PULONG BytesNeeded
  1367. )
  1368. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1369. Functional Description:
  1370. The MiniportQueryInformation request allows the inspection of the
  1371. Miniport driver's capabilities and current status.
  1372. If the Miniport does not complete the call immediately (by returning
  1373. NDIS_STATUS_PENDING), it must call NdisMQueryInformationComplete to
  1374. complete the call. The Miniport controls the buffers pointed to by
  1375. InformationBuffer, BytesWritten, and BytesNeeded until the request
  1376. completes.
  1377. No other requests of the following kind will be submitted to the Miniport
  1378. driver until this request has been completed:
  1379. 1. MiniportQueryInformation()
  1380. 2. MiniportSetInformation()
  1381. 3. MiniportHalt()
  1382. Note that the wrapper will intercept all queries of the following OIDs:
  1383. OID_GEN_CURRENT_PACKET_FILTER,
  1384. OID_GEN_PROTOCOL_OPTIONS,
  1385. OID_802_5_CURRENT_FUNCTIONAL,
  1386. OID_802_3_MULTICAST_LIST,
  1387. OID_FDDI_LONG_MULTICAST_LIST,
  1388. OID_FDDI_SHORT_MULTICAST_LIST.
  1389. Interrupts are in any state during this call.
  1390. Parameters:
  1391. MiniportAdapterContext _ The adapter handle passed to NdisMSetAttributes
  1392. during MiniportInitialize.
  1393. Oid _ The OID. (See section 7.4 of the NDIS 3.0 specification for a
  1394. complete description of OIDs.)
  1395. InformationBuffer _ The buffer that will receive the information.
  1396. (See section 7.4 of the NDIS 3.0 specification
  1397. for a description of the length required for each
  1398. OID.)
  1399. InformationBufferLength _ The length in bytes of InformationBuffer.
  1400. BytesWritten _ Returns the number of bytes written into
  1401. InformationBuffer.
  1402. BytesNeeded _ This parameter returns the number of additional bytes
  1403. needed to satisfy the OID.
  1404. Return Values:
  1405. NDIS_STATUS_INVALID_DATA
  1406. NDIS_STATUS_INVALID_LENGTH
  1407. NDIS_STATUS_INVALID_OID
  1408. NDIS_STATUS_NOT_ACCEPTED
  1409. NDIS_STATUS_NOT_SUPPORTED
  1410. NDIS_STATUS_PENDING
  1411. NDIS_STATUS_RESOURCES
  1412. NDIS_STATUS_FAILURE
  1413. NDIS_STATUS_SUCCESS
  1414. ---------------------------------------------------------------------------*/
  1415. {
  1416. ADAPTER* pAdapter = (ADAPTER*) MiniportAdapterContext;
  1417. NDIS_STATUS status = NDIS_STATUS_FAILURE;
  1418. ULONG GenericUlong;
  1419. PVOID SourceBuffer = NULL;
  1420. ULONG NeededLength = 0;
  1421. ULONG UsedLength = 0;
  1422. //
  1423. // This can be any string that represents PPPoE as a MAC address, but
  1424. // it must be up to 6 chars long.
  1425. //
  1426. UCHAR PPPoEWanAddress[6] = { '3', 'P', 'o', 'E', '0', '0' };
  1427. TRACE( TL_I, TM_Mp, ("+MpQueryInformation($%x):%s",(ULONG) Oid, GetOidName( Oid ) ) );
  1428. //
  1429. // Make sure adapter context is a valid one
  1430. //
  1431. if ( !VALIDATE_ADAPTER( pAdapter ) )
  1432. return status;
  1433. switch ( Oid )
  1434. {
  1435. case OID_GEN_MAXIMUM_LOOKAHEAD:
  1436. {
  1437. NeededLength = sizeof( GenericUlong );
  1438. GenericUlong = pAdapter->NdisWanInfo.MaxFrameSize;
  1439. SourceBuffer = &GenericUlong;
  1440. status = NDIS_STATUS_SUCCESS;
  1441. break;
  1442. }
  1443. case OID_GEN_MAC_OPTIONS:
  1444. {
  1445. NeededLength = sizeof( GenericUlong );
  1446. GenericUlong = NDIS_MAC_OPTION_TRANSFERS_NOT_PEND;
  1447. SourceBuffer = &GenericUlong;
  1448. status = NDIS_STATUS_SUCCESS;
  1449. break;
  1450. }
  1451. case OID_GEN_SUPPORTED_LIST:
  1452. {
  1453. //
  1454. // Calculate the number of oids we support.
  1455. // (Subtract one for unknown oid)
  1456. //
  1457. UINT nNumOids = ( sizeof( SupportedOidsArray ) / sizeof( SUPPORTED_OIDS ) ) - 1;
  1458. NeededLength = nNumOids * sizeof( NDIS_OID );
  1459. if ( InformationBufferLength >= NeededLength )
  1460. {
  1461. NDIS_OID* NdisOidArray = (NDIS_OID*) InformationBuffer;
  1462. UINT i;
  1463. for ( i = 0; i < nNumOids; i++ )
  1464. {
  1465. NdisOidArray[i] = SupportedOidsArray[i].ndisOid;
  1466. }
  1467. status = NDIS_STATUS_SUCCESS;
  1468. }
  1469. break;
  1470. }
  1471. case OID_GEN_RCV_ERROR:
  1472. case OID_GEN_RCV_OK:
  1473. case OID_GEN_XMIT_ERROR:
  1474. case OID_GEN_XMIT_OK:
  1475. case OID_GEN_CURRENT_LOOKAHEAD:
  1476. case OID_GEN_DRIVER_VERSION:
  1477. case OID_GEN_HARDWARE_STATUS:
  1478. case OID_GEN_LINK_SPEED:
  1479. case OID_GEN_MAXIMUM_FRAME_SIZE:
  1480. case OID_GEN_MAXIMUM_TOTAL_SIZE:
  1481. case OID_GEN_MEDIA_SUPPORTED:
  1482. case OID_GEN_MEDIA_IN_USE:
  1483. case OID_GEN_RECEIVE_BLOCK_SIZE:
  1484. case OID_GEN_RECEIVE_BUFFER_SPACE:
  1485. case OID_GEN_TRANSMIT_BLOCK_SIZE:
  1486. case OID_GEN_TRANSMIT_BUFFER_SPACE:
  1487. case OID_GEN_VENDOR_DESCRIPTION:
  1488. case OID_GEN_VENDOR_ID:
  1489. {
  1490. status = NDIS_STATUS_NOT_SUPPORTED;
  1491. break;
  1492. }
  1493. case OID_TAPI_GET_ADDRESS_CAPS:
  1494. {
  1495. NeededLength = sizeof( NDIS_TAPI_GET_ADDRESS_CAPS );
  1496. if ( InformationBufferLength < NeededLength )
  1497. {
  1498. break;
  1499. }
  1500. ENFORCE_SAFE_TOTAL_SIZE(
  1501. NDIS_TAPI_GET_ADDRESS_CAPS,
  1502. LineAddressCaps
  1503. );
  1504. status = TpGetAddressCaps( pAdapter,
  1505. (PNDIS_TAPI_GET_ADDRESS_CAPS) InformationBuffer );
  1506. RETRIEVE_NEEDED_AND_USED_LENGTH(
  1507. NDIS_TAPI_GET_ADDRESS_CAPS,
  1508. LineAddressCaps
  1509. );
  1510. break;
  1511. }
  1512. case OID_TAPI_GET_CALL_INFO:
  1513. {
  1514. NeededLength = sizeof( NDIS_TAPI_GET_CALL_INFO );
  1515. if ( InformationBufferLength < NeededLength )
  1516. {
  1517. break;
  1518. }
  1519. ENFORCE_SAFE_TOTAL_SIZE(
  1520. NDIS_TAPI_GET_CALL_INFO,
  1521. LineCallInfo
  1522. );
  1523. status = TpGetCallInfo( pAdapter,
  1524. (PNDIS_TAPI_GET_CALL_INFO) InformationBuffer );
  1525. RETRIEVE_NEEDED_AND_USED_LENGTH(
  1526. NDIS_TAPI_GET_CALL_INFO,
  1527. LineCallInfo
  1528. );
  1529. break;
  1530. }
  1531. case OID_TAPI_GET_CALL_STATUS:
  1532. {
  1533. NeededLength = sizeof( NDIS_TAPI_GET_CALL_STATUS );
  1534. if ( InformationBufferLength < NeededLength )
  1535. {
  1536. break;
  1537. }
  1538. ENFORCE_SAFE_TOTAL_SIZE(
  1539. NDIS_TAPI_GET_CALL_STATUS,
  1540. LineCallStatus
  1541. );
  1542. status = TpGetCallStatus( pAdapter,
  1543. (PNDIS_TAPI_GET_CALL_STATUS) InformationBuffer );
  1544. RETRIEVE_NEEDED_AND_USED_LENGTH(
  1545. NDIS_TAPI_GET_CALL_STATUS,
  1546. LineCallStatus
  1547. );
  1548. break;
  1549. }
  1550. case OID_TAPI_GET_DEV_CAPS:
  1551. {
  1552. NeededLength = sizeof( NDIS_TAPI_GET_DEV_CAPS );
  1553. if ( InformationBufferLength < NeededLength )
  1554. {
  1555. break;
  1556. }
  1557. ENFORCE_SAFE_TOTAL_SIZE(
  1558. NDIS_TAPI_GET_DEV_CAPS,
  1559. LineDevCaps
  1560. );
  1561. status = TpGetDevCaps( pAdapter,
  1562. (PNDIS_TAPI_GET_DEV_CAPS) InformationBuffer );
  1563. RETRIEVE_NEEDED_AND_USED_LENGTH(
  1564. NDIS_TAPI_GET_DEV_CAPS,
  1565. LineDevCaps
  1566. );
  1567. break;
  1568. }
  1569. case OID_TAPI_GET_ID:
  1570. {
  1571. NeededLength = sizeof( NDIS_TAPI_GET_ID );
  1572. if ( InformationBufferLength < NeededLength )
  1573. {
  1574. break;
  1575. }
  1576. ENFORCE_SAFE_TOTAL_SIZE(
  1577. NDIS_TAPI_GET_ID,
  1578. DeviceID
  1579. );
  1580. status = TpGetId( pAdapter,
  1581. (PNDIS_TAPI_GET_ID) InformationBuffer,
  1582. InformationBufferLength );
  1583. RETRIEVE_NEEDED_AND_USED_LENGTH(
  1584. NDIS_TAPI_GET_ID,
  1585. DeviceID
  1586. );
  1587. break;
  1588. }
  1589. case OID_TAPI_GET_ADDRESS_STATUS:
  1590. {
  1591. NeededLength = sizeof( NDIS_TAPI_GET_ADDRESS_STATUS );
  1592. if ( InformationBufferLength < NeededLength )
  1593. {
  1594. break;
  1595. }
  1596. ENFORCE_SAFE_TOTAL_SIZE(
  1597. NDIS_TAPI_GET_ADDRESS_STATUS,
  1598. LineAddressStatus
  1599. );
  1600. status = TpGetAddressStatus( pAdapter,
  1601. (PNDIS_TAPI_GET_ADDRESS_STATUS) InformationBuffer );
  1602. RETRIEVE_NEEDED_AND_USED_LENGTH(
  1603. NDIS_TAPI_GET_ADDRESS_STATUS,
  1604. LineAddressStatus
  1605. );
  1606. break;
  1607. }
  1608. case OID_TAPI_GET_EXTENSION_ID:
  1609. {
  1610. NeededLength = sizeof( NDIS_TAPI_GET_EXTENSION_ID );
  1611. if ( InformationBufferLength < NeededLength )
  1612. {
  1613. break;
  1614. }
  1615. status = TpGetExtensionId( pAdapter,
  1616. (PNDIS_TAPI_GET_EXTENSION_ID) InformationBuffer );
  1617. break;
  1618. }
  1619. case OID_TAPI_MAKE_CALL:
  1620. {
  1621. NeededLength = sizeof( NDIS_TAPI_MAKE_CALL );
  1622. if ( InformationBufferLength < NeededLength )
  1623. {
  1624. break;
  1625. }
  1626. ENFORCE_SAFE_TOTAL_SIZE(
  1627. NDIS_TAPI_MAKE_CALL,
  1628. LineCallParams
  1629. );
  1630. status = TpMakeCall( pAdapter,
  1631. (PNDIS_TAPI_MAKE_CALL) InformationBuffer,
  1632. InformationBufferLength );
  1633. break;
  1634. }
  1635. case OID_TAPI_NEGOTIATE_EXT_VERSION:
  1636. {
  1637. NeededLength = sizeof( NDIS_TAPI_NEGOTIATE_EXT_VERSION );
  1638. if ( InformationBufferLength < NeededLength )
  1639. {
  1640. break;
  1641. }
  1642. status = TpNegotiateExtVersion( pAdapter,
  1643. (PNDIS_TAPI_NEGOTIATE_EXT_VERSION) InformationBuffer );
  1644. break;
  1645. }
  1646. case OID_TAPI_OPEN:
  1647. {
  1648. NeededLength = sizeof( NDIS_TAPI_OPEN );
  1649. if ( InformationBufferLength < NeededLength )
  1650. {
  1651. break;
  1652. }
  1653. status = TpOpenLine( pAdapter,
  1654. (PNDIS_TAPI_OPEN) InformationBuffer );
  1655. break;
  1656. }
  1657. case OID_TAPI_PROVIDER_INITIALIZE:
  1658. {
  1659. NeededLength = sizeof( NDIS_TAPI_PROVIDER_INITIALIZE );
  1660. if ( InformationBufferLength < NeededLength )
  1661. {
  1662. break;
  1663. }
  1664. status = TpProviderInitialize( pAdapter,
  1665. (PNDIS_TAPI_PROVIDER_INITIALIZE) InformationBuffer );
  1666. break;
  1667. }
  1668. case OID_WAN_GET_INFO:
  1669. {
  1670. NeededLength = sizeof( NDIS_WAN_INFO );
  1671. if ( InformationBufferLength < NeededLength )
  1672. {
  1673. break;
  1674. }
  1675. status = MpWanGetInfo( pAdapter,
  1676. (PNDIS_WAN_INFO) InformationBuffer );
  1677. break;
  1678. }
  1679. case OID_WAN_MEDIUM_SUBTYPE:
  1680. {
  1681. NeededLength = sizeof( GenericUlong );
  1682. GenericUlong = NdisWanMediumPppoe;
  1683. SourceBuffer = &GenericUlong;
  1684. status = NDIS_STATUS_SUCCESS;
  1685. break;
  1686. }
  1687. case OID_WAN_CURRENT_ADDRESS:
  1688. case OID_WAN_PERMANENT_ADDRESS:
  1689. {
  1690. NeededLength = sizeof( PPPoEWanAddress );
  1691. SourceBuffer = PPPoEWanAddress;
  1692. status = NDIS_STATUS_SUCCESS;
  1693. break;
  1694. }
  1695. case OID_WAN_GET_LINK_INFO:
  1696. {
  1697. NeededLength = sizeof( NDIS_WAN_GET_LINK_INFO );
  1698. if ( InformationBufferLength < NeededLength )
  1699. {
  1700. break;
  1701. }
  1702. status = MpWanGetLinkInfo( pAdapter,
  1703. (PNDIS_WAN_GET_LINK_INFO) InformationBuffer );
  1704. break;
  1705. }
  1706. case OID_WAN_GET_BRIDGE_INFO:
  1707. case OID_WAN_GET_STATS_INFO:
  1708. case OID_WAN_HEADER_FORMAT:
  1709. case OID_WAN_LINE_COUNT:
  1710. case OID_WAN_PROTOCOL_TYPE:
  1711. case OID_WAN_QUALITY_OF_SERVICE:
  1712. case OID_WAN_SET_BRIDGE_INFO:
  1713. case OID_WAN_SET_COMP_INFO:
  1714. case OID_WAN_SET_LINK_INFO:
  1715. case OID_WAN_GET_COMP_INFO:
  1716. {
  1717. status = NDIS_STATUS_NOT_SUPPORTED;
  1718. break;
  1719. }
  1720. case OID_PNP_CAPABILITIES:
  1721. {
  1722. NDIS_PNP_CAPABILITIES UNALIGNED * pPnpCaps = (NDIS_PNP_CAPABILITIES UNALIGNED *) InformationBuffer;
  1723. NeededLength = sizeof( NDIS_PNP_CAPABILITIES );
  1724. if ( InformationBufferLength < NeededLength )
  1725. {
  1726. break;
  1727. }
  1728. pPnpCaps->Flags = 0;
  1729. pPnpCaps->WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
  1730. pPnpCaps->WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
  1731. pPnpCaps->WakeUpCapabilities.MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
  1732. status = NDIS_STATUS_SUCCESS;
  1733. break;
  1734. }
  1735. case OID_PNP_QUERY_POWER:
  1736. case OID_PNP_ENABLE_WAKE_UP:
  1737. {
  1738. NeededLength = 0;
  1739. status = NDIS_STATUS_SUCCESS;
  1740. break;
  1741. }
  1742. default:
  1743. {
  1744. //
  1745. // Unknown OID
  1746. //
  1747. status = NDIS_STATUS_INVALID_OID;
  1748. break;
  1749. }
  1750. }
  1751. if ( status != NDIS_STATUS_NOT_SUPPORTED &&
  1752. status != NDIS_STATUS_INVALID_OID )
  1753. {
  1754. if ( InformationBufferLength >= NeededLength )
  1755. {
  1756. if ( status == NDIS_STATUS_SUCCESS )
  1757. {
  1758. if ( SourceBuffer )
  1759. {
  1760. NdisMoveMemory( InformationBuffer, SourceBuffer, NeededLength );
  1761. }
  1762. *BytesWritten = NeededLength;
  1763. }
  1764. else if ( status == NDIS_STATUS_INVALID_LENGTH )
  1765. {
  1766. *BytesWritten = 0;
  1767. *BytesNeeded = NeededLength;
  1768. }
  1769. }
  1770. else
  1771. {
  1772. *BytesWritten = 0;
  1773. *BytesNeeded = NeededLength;
  1774. status = NDIS_STATUS_INVALID_LENGTH;
  1775. }
  1776. }
  1777. TRACE( TL_I, TM_Mp, ("-MpQueryInformation()=$%x",status) );
  1778. return status;
  1779. }
  1780. NDIS_STATUS
  1781. MpSetInformation(
  1782. IN NDIS_HANDLE MiniportAdapterContext,
  1783. IN NDIS_OID Oid,
  1784. IN PVOID InformationBuffer,
  1785. IN ULONG InformationBufferLength,
  1786. OUT PULONG BytesWritten,
  1787. OUT PULONG BytesNeeded
  1788. )
  1789. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1790. Functional Description:
  1791. The MiniportSetInformation request allows for control of the Miniport
  1792. by changing information maintained by the Miniport driver.
  1793. Any of the settable NDIS Global Oids may be used. (see section 7.4 of
  1794. the NDIS 3.0 specification for a complete description of the NDIS Oids.)
  1795. If the Miniport does not complete the call immediately (by returning
  1796. NDIS_STATUS_PENDING), it must call NdisMSetInformationComplete to
  1797. complete the call. The Miniport controls the buffers pointed to by
  1798. InformationBuffer, BytesRead, and BytesNeeded until the request completes.
  1799. Interrupts are in any state during the call, and no other requests will
  1800. be submitted to the Miniport until this request is completed.
  1801. Parameters:
  1802. MiniportAdapterContext _ The adapter handle passed to NdisMSetAttributes
  1803. during MiniportInitialize.
  1804. Oid _ The OID. (See section 7.4 of the NDIS 3.0 specification for
  1805. a complete description of OIDs.)
  1806. InformationBuffer _ The buffer that will receive the information.
  1807. (See section 7.4 of the NDIS 3.0 specification for
  1808. a description of the length required for each OID.)
  1809. InformationBufferLength _ The length in bytes of InformationBuffer.
  1810. BytesRead_ Returns the number of bytes read from InformationBuffer.
  1811. BytesNeeded _ This parameter returns the number of additional bytes
  1812. expected to satisfy the OID.
  1813. Return Values:
  1814. NDIS_STATUS_INVALID_DATA
  1815. NDIS_STATUS_INVALID_LENGTH
  1816. NDIS_STATUS_INVALID_OID
  1817. NDIS_STATUS_NOT_ACCEPTED
  1818. NDIS_STATUS_NOT_SUPPORTED
  1819. NDIS_STATUS_PENDING
  1820. NDIS_STATUS_RESOURCES
  1821. NDIS_STATUS_SUCCESS
  1822. ---------------------------------------------------------------------------*/
  1823. {
  1824. ADAPTER* pAdapter = MiniportAdapterContext;
  1825. NDIS_STATUS status = NDIS_STATUS_FAILURE;
  1826. PVOID SourceBuffer = NULL;
  1827. ULONG NeededLength = 0;
  1828. ULONG GenericUlong;
  1829. TRACE( TL_I, TM_Mp, ("+MpSetInformation($%x):%s",(ULONG) Oid, GetOidName( Oid ) ) );
  1830. //
  1831. // Make sure adapter context is a valid one
  1832. //
  1833. if ( !VALIDATE_ADAPTER( pAdapter ) )
  1834. return status;
  1835. switch ( Oid )
  1836. {
  1837. case OID_TAPI_ANSWER:
  1838. {
  1839. NeededLength = sizeof( NDIS_TAPI_ANSWER );
  1840. if ( InformationBufferLength < NeededLength )
  1841. {
  1842. break;
  1843. }
  1844. status = TpAnswerCall( pAdapter,
  1845. (PNDIS_TAPI_ANSWER) InformationBuffer );
  1846. break;
  1847. }
  1848. case OID_TAPI_CLOSE:
  1849. {
  1850. NeededLength = sizeof( NDIS_TAPI_CLOSE );
  1851. if ( InformationBufferLength < NeededLength )
  1852. {
  1853. break;
  1854. }
  1855. status = TpCloseLine( pAdapter,
  1856. (PNDIS_TAPI_CLOSE) InformationBuffer,
  1857. TRUE);
  1858. break;
  1859. }
  1860. case OID_TAPI_CLOSE_CALL:
  1861. {
  1862. NeededLength = sizeof( NDIS_TAPI_CLOSE_CALL );
  1863. if ( InformationBufferLength < NeededLength )
  1864. {
  1865. break;
  1866. }
  1867. status = TpCloseCall( pAdapter,
  1868. (PNDIS_TAPI_CLOSE_CALL) InformationBuffer,
  1869. TRUE );
  1870. break;
  1871. }
  1872. case OID_TAPI_DROP:
  1873. {
  1874. NeededLength = sizeof( NDIS_TAPI_DROP );
  1875. if ( InformationBufferLength < NeededLength )
  1876. {
  1877. break;
  1878. }
  1879. status = TpDropCall( pAdapter,
  1880. (PNDIS_TAPI_DROP) InformationBuffer,
  1881. 0 );
  1882. break;
  1883. }
  1884. case OID_TAPI_PROVIDER_SHUTDOWN:
  1885. {
  1886. NeededLength = sizeof( NDIS_TAPI_PROVIDER_SHUTDOWN );
  1887. if ( InformationBufferLength < NeededLength )
  1888. {
  1889. break;
  1890. }
  1891. status = TpProviderShutdown( pAdapter,
  1892. (PNDIS_TAPI_PROVIDER_SHUTDOWN) InformationBuffer,
  1893. TRUE );
  1894. break;
  1895. }
  1896. case OID_TAPI_SET_DEFAULT_MEDIA_DETECTION:
  1897. {
  1898. NeededLength = sizeof( NDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION );
  1899. if ( InformationBufferLength < NeededLength )
  1900. {
  1901. break;
  1902. }
  1903. status = TpSetDefaultMediaDetection( pAdapter,
  1904. (PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION) InformationBuffer );
  1905. break;
  1906. }
  1907. case OID_TAPI_SET_STATUS_MESSAGES:
  1908. {
  1909. NeededLength = sizeof( NDIS_TAPI_SET_STATUS_MESSAGES );
  1910. if ( InformationBufferLength < NeededLength )
  1911. {
  1912. break;
  1913. }
  1914. status = TpSetStatusMessages( pAdapter,
  1915. (PNDIS_TAPI_SET_STATUS_MESSAGES) InformationBuffer );
  1916. break;
  1917. }
  1918. case OID_WAN_SET_LINK_INFO:
  1919. {
  1920. NeededLength = sizeof( NDIS_WAN_SET_LINK_INFO );
  1921. if ( InformationBufferLength < NeededLength )
  1922. {
  1923. break;
  1924. }
  1925. status = MpWanSetLinkInfo( pAdapter,
  1926. (PNDIS_WAN_SET_LINK_INFO) InformationBuffer );
  1927. break;
  1928. }
  1929. case OID_PNP_SET_POWER:
  1930. case OID_PNP_ENABLE_WAKE_UP:
  1931. {
  1932. NeededLength = 0;
  1933. status = NDIS_STATUS_SUCCESS;
  1934. break;
  1935. }
  1936. default:
  1937. {
  1938. //
  1939. // Unknown OID
  1940. //
  1941. status = NDIS_STATUS_INVALID_OID;
  1942. break;
  1943. }
  1944. }
  1945. if ( status != NDIS_STATUS_NOT_SUPPORTED &&
  1946. status != NDIS_STATUS_INVALID_OID )
  1947. {
  1948. if ( InformationBufferLength >= NeededLength )
  1949. {
  1950. if ( SourceBuffer )
  1951. NdisMoveMemory( InformationBuffer, SourceBuffer, NeededLength );
  1952. *BytesWritten = NeededLength;
  1953. }
  1954. else
  1955. {
  1956. *BytesWritten = 0;
  1957. *BytesNeeded = NeededLength;
  1958. status = NDIS_STATUS_INVALID_LENGTH;
  1959. }
  1960. }
  1961. TRACE( TL_I, TM_Mp, ("-MpSetInformation()=$%x",status) );
  1962. return status;
  1963. }
  1964. VOID
  1965. MpNotifyBindingRemoval(
  1966. BINDING* pBinding
  1967. )
  1968. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1969. Functional Description:
  1970. This function will be called by the protocol module to notify the miniport
  1971. about the removal of a binding.
  1972. Miniport identifies and drops the calls over the binding..
  1973. Parameters:
  1974. pBinding _ A pointer to our binding information structure.
  1975. Return Values:
  1976. None
  1977. ---------------------------------------------------------------------------*/
  1978. {
  1979. ADAPTER* pAdapter = NULL;
  1980. ASSERT( VALIDATE_BINDING( pBinding ) );
  1981. TRACE( TL_N, TM_Mp, ("+MpNotifyBindingRemoval($%x)",pBinding) );
  1982. if ( !gl_fLockAllocated )
  1983. {
  1984. TRACE( TL_A, TM_Mp, ("MpNotifyBindingRemoval($%x): Global lock not allocated yet",pBinding) );
  1985. TRACE( TL_N, TM_Mp, ("-MpNotifyBindingRemoval($%x)",pBinding) );
  1986. return;
  1987. }
  1988. NdisAcquireSpinLock( &gl_lockAdapter );
  1989. if ( gl_pAdapter &&
  1990. !( gl_pAdapter->ulMpFlags & MPBF_MiniportHaltPending ) &&
  1991. ( gl_pAdapter->ulMpFlags & MPBF_MiniportInitialized ) )
  1992. {
  1993. pAdapter = gl_pAdapter;
  1994. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  1995. if ( !( pAdapter->TapiProv.ulTpFlags & TPBF_TapiProvShutdownPending ) &&
  1996. ( pAdapter->TapiProv.ulTpFlags & TPBF_TapiProvInitialized ) )
  1997. {
  1998. ReferenceTapiProv( pAdapter, FALSE );
  1999. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  2000. }
  2001. else
  2002. {
  2003. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  2004. pAdapter = NULL;
  2005. }
  2006. }
  2007. NdisReleaseSpinLock( &gl_lockAdapter );
  2008. if ( pAdapter == NULL )
  2009. {
  2010. TRACE( TL_A, TM_Mp, ("MpNotifyBindingRemoval($%x): Tapi provider not initialized or no adapters found",pBinding) );
  2011. TRACE( TL_N, TM_Mp, ("-MpNotifyBindingRemoval($%x)",pBinding) );
  2012. return;
  2013. }
  2014. //
  2015. // Complete any queued received packets in case PrReceiveComplete()
  2016. // is not called
  2017. //
  2018. PrReceiveComplete( pBinding );
  2019. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  2020. do
  2021. {
  2022. HANDLE_TABLE hCallTable = NULL;
  2023. UINT hCallTableSize = 0;
  2024. UINT i = 0;
  2025. CALL* pCall;
  2026. HDRV_CALL hdCall;
  2027. //
  2028. // Traverse the call handle table and drop calls over
  2029. // the removed binding
  2030. //
  2031. hCallTableSize = pAdapter->nMaxLines * pAdapter->nCallsPerLine;
  2032. hCallTable = pAdapter->TapiProv.hCallTable;
  2033. for ( i = 0; i < hCallTableSize; i++ )
  2034. {
  2035. NDIS_TAPI_DROP DummyRequest;
  2036. BOOLEAN fDropCall = FALSE;
  2037. pCall = RetrieveFromHandleTableByIndex( hCallTable, (USHORT) i );
  2038. if ( pCall == NULL )
  2039. continue;
  2040. NdisAcquireSpinLock( &pCall->lockCall );
  2041. if ( pCall->pBinding == pBinding )
  2042. {
  2043. //
  2044. // This call is over the removed binding,
  2045. // so it should be dropped
  2046. //
  2047. ReferenceCall( pCall, FALSE );
  2048. fDropCall = TRUE;
  2049. }
  2050. NdisReleaseSpinLock( &pCall->lockCall );
  2051. if ( !fDropCall )
  2052. {
  2053. pCall = NULL;
  2054. continue;
  2055. }
  2056. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  2057. //
  2058. // Initialize the request, and drop the call
  2059. //
  2060. DummyRequest.hdCall = pCall->hdCall;
  2061. TpDropCall( pAdapter, &DummyRequest, LINEDISCONNECTMODE_UNREACHABLE );
  2062. //
  2063. // Remove the reference added above
  2064. //
  2065. DereferenceCall( pCall );
  2066. //
  2067. // Re-acquire the adapter's lock
  2068. //
  2069. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  2070. }
  2071. } while ( FALSE );
  2072. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  2073. //
  2074. // Remove the reference added above
  2075. //
  2076. DereferenceTapiProv( pAdapter );
  2077. TRACE( TL_N, TM_Mp, ("-MpNotifyBindingRemoval($%x)",pBinding) );
  2078. }
  2079. CALL*
  2080. MpMapPacketWithSessionIdToCall(
  2081. IN ADAPTER* pAdapter,
  2082. IN PPPOE_PACKET* pPacket
  2083. )
  2084. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2085. Functional Description:
  2086. This function will be called to map an in session packet to a call in
  2087. call handle table.
  2088. If such a call is identified, it will be referenced and a pointer to
  2089. it will be returned. It is the caller's responsibility to remove the
  2090. added reference.
  2091. Parameters:
  2092. pAdapter _ A pointer to our adapter information structure.
  2093. pPacket _ A PPPoE packet received over the wire.
  2094. Return Values:
  2095. A pointer to the call context that the packet must be dispatched to.
  2096. NULL if no such calls could be identified.
  2097. ---------------------------------------------------------------------------*/
  2098. {
  2099. CALL* pCall = NULL;
  2100. CALL* pReturnCall = NULL;
  2101. TRACE( TL_V, TM_Mp, ("+MpMapPacketWithSessionIdToCall($%x)",pPacket) );
  2102. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  2103. if ( pAdapter->fClientRole )
  2104. {
  2105. HANDLE_TABLE hCallTable = NULL;
  2106. UINT hCallTableSize = 0;
  2107. UINT i = 0;
  2108. CHAR* pSrcAddr = PacketGetSrcAddr( pPacket );
  2109. CHAR* pDestAddr = PacketGetDestAddr( pPacket );
  2110. USHORT usSessionId = PacketGetSessionId( pPacket );
  2111. //
  2112. // Miniport acting as a client:
  2113. // Our algorithm is to search for the call handle table
  2114. // to find the matching call
  2115. //
  2116. hCallTableSize = pAdapter->nMaxLines * pAdapter->nCallsPerLine;
  2117. hCallTable = pAdapter->TapiProv.hCallTable;
  2118. for ( i = 0; i < hCallTableSize ; i++ )
  2119. {
  2120. pCall = RetrieveFromHandleTableByIndex( hCallTable, (USHORT) i );
  2121. if ( pCall == NULL )
  2122. continue;
  2123. if ( ( pCall->usSessionId == usSessionId ) &&
  2124. ( NdisEqualMemory( pCall->SrcAddr, pDestAddr, 6 * sizeof( CHAR ) ) ) &&
  2125. ( NdisEqualMemory( pCall->DestAddr, pSrcAddr, 6 * sizeof( CHAR ) ) ) )
  2126. {
  2127. //
  2128. // The packet is intended for this call
  2129. //
  2130. ReferenceCall( pCall, TRUE );
  2131. pReturnCall = pCall;
  2132. break;
  2133. }
  2134. }
  2135. }
  2136. else
  2137. {
  2138. HANDLE_TABLE hCallTable = NULL;
  2139. CHAR* pSrcAddr = PacketGetSrcAddr( pPacket );
  2140. CHAR* pDestAddr = PacketGetDestAddr( pPacket );
  2141. USHORT usSessionId = PacketGetSessionId( pPacket );
  2142. //
  2143. // Miniport acting as a server:
  2144. // Our algorithm is to use the session id directly as the index
  2145. // to the call handle table
  2146. //
  2147. hCallTable = pAdapter->TapiProv.hCallTable;
  2148. pCall = RetrieveFromHandleTableBySessionId( hCallTable, usSessionId );
  2149. if ( pCall )
  2150. {
  2151. if ( ( pCall->usSessionId == usSessionId ) &&
  2152. ( NdisEqualMemory( pCall->SrcAddr, pDestAddr, 6 * sizeof( CHAR ) ) ) &&
  2153. ( NdisEqualMemory( pCall->DestAddr, pSrcAddr, 6 * sizeof( CHAR ) ) ) )
  2154. {
  2155. ReferenceCall( pCall, TRUE );
  2156. pReturnCall = pCall;
  2157. }
  2158. }
  2159. }
  2160. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  2161. TRACE( TL_V, TM_Mp, ("-MpMapPacketWithSessionIdToCall($%x)=$%x",pPacket,pReturnCall) );
  2162. return pReturnCall;
  2163. }
  2164. CALL*
  2165. MpMapPacketWithoutSessionIdToCall(
  2166. IN ADAPTER* pAdapter,
  2167. IN PPPOE_PACKET* pPacket
  2168. )
  2169. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2170. Functional Description:
  2171. This function will be called to map an out of session packet to a call that
  2172. is in connecting state.
  2173. If such a call is identified, it will be referenced and a pointer to
  2174. it will be returned. It is the caller's responsibility to remove the
  2175. added reference.
  2176. This function will only be called for PADO or PADS packets.
  2177. We use the HostUnique tags to save the handle to the call, and
  2178. use them to map the returned packet back to the related call. This provides a
  2179. very efficient mapping for these control packets.
  2180. Our HostUnique tags are prepared in this way. We append hdCall,
  2181. which is unique for a call, to a uniquely generated ULONG value to come up with
  2182. a longer unique value. And when we receive the packet we decode the unique value to reach
  2183. hdCall and use that to retrieve the call pointer.
  2184. Parameters:
  2185. pAdapter _ A pointer to our adapter information structure.
  2186. pPacket _ A PPPoE packet received over the wire.
  2187. Return Values:
  2188. A pointer to the call context that the packet must be dispatched to.
  2189. NULL if no such calls could be identified.
  2190. ---------------------------------------------------------------------------*/
  2191. {
  2192. USHORT usCode = PacketGetCode( pPacket );
  2193. CHAR* pUniqueValue = NULL;
  2194. USHORT UniqueValueSize = 0;
  2195. HDRV_CALL hdCall = (HDRV_CALL) NULL;
  2196. CALL* pCall = NULL;
  2197. TRACE( TL_N, TM_Mp, ("+MpMapPacketWithoutSessionIdToCall($%x)",pPacket) );
  2198. PacketRetrieveHostUniqueTag( pPacket,
  2199. &UniqueValueSize,
  2200. &pUniqueValue );
  2201. if ( pUniqueValue == NULL )
  2202. {
  2203. TRACE( TL_A, TM_Mp, ("MpMapPacketWithoutSessionIdToCall($%x): Could not retrieve HostUnique tag",pPacket) );
  2204. TRACE( TL_N, TM_Mp, ("-MpMapPacketWithoutSessionIdToCall($%x)",pPacket) );
  2205. return NULL;
  2206. }
  2207. //
  2208. // Decode the unique value and retrieve the call handle
  2209. //
  2210. hdCall = RetrieveHdCallFromUniqueValue( pUniqueValue, UniqueValueSize );
  2211. if ( hdCall == (HDRV_CALL) NULL )
  2212. {
  2213. TRACE( TL_A, TM_Mp, ("MpMapPacketWithoutSessionIdToCall($%x): Could not retrieve call handle from unique value",pPacket) );
  2214. TRACE( TL_N, TM_Mp, ("-MpMapPacketWithoutSessionIdToCall($%x)",pPacket) );
  2215. return NULL;
  2216. }
  2217. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  2218. //
  2219. // Retrieve the call pointer using the call handle
  2220. //
  2221. pCall = RetrieveFromHandleTable( pAdapter->TapiProv.hCallTable,
  2222. (NDIS_HANDLE) hdCall );
  2223. if ( pCall )
  2224. {
  2225. if ( !( pCall->ulClFlags & CLBF_CallDropped ||
  2226. pCall->ulClFlags & CLBF_CallClosePending ) )
  2227. {
  2228. ReferenceCall( pCall, TRUE );
  2229. }
  2230. else
  2231. {
  2232. pCall = NULL;
  2233. }
  2234. }
  2235. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  2236. TRACE( TL_N, TM_Mp, ("-MpMapPacketWithoutSessionIdToCall($%x)=$%x",pPacket,pCall) );
  2237. return pCall;
  2238. }
  2239. BOOLEAN
  2240. MpVerifyServiceName(
  2241. IN ADAPTER* pAdapter,
  2242. IN PPPOE_PACKET* pPacket,
  2243. IN BOOLEAN fAcceptEmptyServiceNameTag
  2244. )
  2245. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2246. Functional Description:
  2247. This function will be called to verify that a requested service name is
  2248. supported by our server.
  2249. CAUTION: Do not attempt to lock anything inside this function, and make sure
  2250. not to call any function that may do it because it must be lock free
  2251. (caller might be holding locks).
  2252. Parameters:
  2253. pAdapter _ Pointer to the adapter structure that received the packet.
  2254. pPacket _ A PADI or PADR packet received.
  2255. fAcceptEmptyServiceNameTag _ An empty service name tag is valid in a PADI
  2256. packet but not in a PADR packet. This flag
  2257. indicates this behavior.
  2258. Return Values:
  2259. None
  2260. ---------------------------------------------------------------------------*/
  2261. {
  2262. BOOLEAN fRet = FALSE;
  2263. USHORT tagServiceNameLength = 0;
  2264. CHAR* tagServiceNameValue = NULL;
  2265. TRACE( TL_V, TM_Mp, ("+MpVerifyServiceName($%x)",pPacket) );
  2266. RetrieveTag( pPacket,
  2267. tagServiceName,
  2268. &tagServiceNameLength,
  2269. &tagServiceNameValue,
  2270. 0,
  2271. NULL,
  2272. FALSE );
  2273. do
  2274. {
  2275. if ( fAcceptEmptyServiceNameTag )
  2276. {
  2277. if ( tagServiceNameLength == 0 && tagServiceNameValue != NULL )
  2278. {
  2279. fRet = TRUE;
  2280. break;
  2281. }
  2282. }
  2283. if ( tagServiceNameLength == pAdapter->nServiceNameLength &&
  2284. NdisEqualMemory( tagServiceNameValue, pAdapter->ServiceName, tagServiceNameLength) )
  2285. {
  2286. fRet = TRUE;
  2287. }
  2288. } while ( FALSE );
  2289. TRACE( TL_V, TM_Mp, ("-MpVerifyServiceName($%x)=$%x",pPacket,fRet) );
  2290. return fRet;
  2291. }
  2292. VOID
  2293. MpReplyToPADI(
  2294. IN ADAPTER* pAdapter,
  2295. IN BINDING* pBinding,
  2296. IN PPPOE_PACKET* pPADI
  2297. )
  2298. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2299. Functional Description:
  2300. This function will be called when a PADI packet is received.
  2301. It will look at the services we offer and reply to the PADI packet with a
  2302. PADO packet informing the client of our services.
  2303. Parameters:
  2304. pAdapter _ Pointer to the adapter structure that received the packet.
  2305. pBinding _ Pointer to the binding that the packet is received over.
  2306. pPacket _ A received PADI packet.
  2307. Return Values:
  2308. None
  2309. ---------------------------------------------------------------------------*/
  2310. {
  2311. TRACE( TL_N, TM_Mp, ("+MpReplyToPADI") );
  2312. //
  2313. // Verify the requested service name and
  2314. //
  2315. if ( MpVerifyServiceName( pAdapter, pPADI, TRUE ) )
  2316. {
  2317. NDIS_STATUS status;
  2318. PPPOE_PACKET* pPADO = NULL;
  2319. status = PacketInitializePADOToSend( pPADI,
  2320. &pPADO,
  2321. pBinding->LocalAddress,
  2322. pAdapter->nServiceNameLength,
  2323. pAdapter->ServiceName,
  2324. pAdapter->nACNameLength,
  2325. pAdapter->ACName,
  2326. TRUE );
  2327. if ( status == NDIS_STATUS_SUCCESS )
  2328. {
  2329. //
  2330. // Insert the empty generic service name tag
  2331. //
  2332. status = PacketInsertTag( pPADO,
  2333. tagServiceName,
  2334. 0,
  2335. NULL,
  2336. NULL );
  2337. if ( status == NDIS_STATUS_SUCCESS )
  2338. {
  2339. UINT i;
  2340. ReferencePacket( pPADO );
  2341. ReferenceBinding( pBinding, TRUE );
  2342. PrSend( pBinding, pPADO );
  2343. PacketFree( pPADO );
  2344. }
  2345. }
  2346. }
  2347. TRACE( TL_N, TM_Mp, ("-MpReplyToPADI") );
  2348. }
  2349. BOOLEAN
  2350. MpCheckClientQuota(
  2351. IN ADAPTER* pAdapter,
  2352. IN PPPOE_PACKET* pPacket
  2353. )
  2354. {
  2355. BOOLEAN fRet = FALSE;
  2356. HANDLE_TABLE hCallTable = NULL;
  2357. UINT hCallTableSize = 0;
  2358. CALL* pCall;
  2359. CHAR *pSrcAddr = NULL;
  2360. UINT nNumCurrentConn = 0;
  2361. UINT i;
  2362. TRACE( TL_N, TM_Mp, ("+MpCheckClientQuota") );
  2363. pSrcAddr = PacketGetSrcAddr( pPacket );
  2364. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  2365. hCallTableSize = pAdapter->nMaxLines * pAdapter->nCallsPerLine;
  2366. hCallTable = pAdapter->TapiProv.hCallTable;
  2367. for ( i = 0; i < hCallTableSize; i++ )
  2368. {
  2369. pCall = RetrieveFromHandleTableByIndex( hCallTable, (USHORT) i );
  2370. if ( pCall == NULL )
  2371. continue;
  2372. if ( NdisEqualMemory( pCall->DestAddr, pSrcAddr, 6 * sizeof( CHAR ) ) )
  2373. {
  2374. nNumCurrentConn++;
  2375. continue;
  2376. }
  2377. }
  2378. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  2379. if ( nNumCurrentConn < pAdapter->nClientQuota )
  2380. {
  2381. fRet = TRUE;
  2382. }
  2383. TRACE( TL_N, TM_Mp, ("-MpCheckClientQuota=$%d",(UINT) fRet) );
  2384. return fRet;
  2385. }
  2386. VOID
  2387. MpSendPADSWithError(
  2388. IN BINDING* pBinding,
  2389. IN PPPOE_PACKET* pPADR,
  2390. IN ULONG ulErrorCode
  2391. )
  2392. {
  2393. NDIS_STATUS status;
  2394. PPPOE_PACKET* pPADS = NULL;
  2395. TRACE( TL_N, TM_Mp, ("+MpSendPADSWithError") );
  2396. status = PacketInitializePADSToSend( pPADR,
  2397. &pPADS,
  2398. (USHORT) 0 );
  2399. if ( status == NDIS_STATUS_SUCCESS )
  2400. {
  2401. switch (ulErrorCode)
  2402. {
  2403. case PPPOE_ERROR_SERVICE_NOT_SUPPORTED:
  2404. status = PacketInsertTag( pPADS,
  2405. tagServiceNameError,
  2406. PPPOE_ERROR_SERVICE_NOT_SUPPORTED_MSG_SIZE,
  2407. PPPOE_ERROR_SERVICE_NOT_SUPPORTED_MSG,
  2408. NULL );
  2409. break;
  2410. case PPPOE_ERROR_INVALID_AC_COOKIE_TAG:
  2411. status = PacketInsertTag( pPADS,
  2412. tagGenericError,
  2413. PPPOE_ERROR_INVALID_AC_COOKIE_TAG_MSG_SIZE,
  2414. PPPOE_ERROR_INVALID_AC_COOKIE_TAG_MSG,
  2415. NULL );
  2416. break;
  2417. case PPPOE_ERROR_CLIENT_QUOTA_EXCEEDED:
  2418. status = PacketInsertTag( pPADS,
  2419. tagACSystemError,
  2420. PPPOE_ERROR_CLIENT_QUOTA_EXCEEDED_MSG_SIZE,
  2421. PPPOE_ERROR_CLIENT_QUOTA_EXCEEDED_MSG,
  2422. NULL );
  2423. break;
  2424. }
  2425. }
  2426. if ( status == NDIS_STATUS_SUCCESS )
  2427. {
  2428. ReferencePacket( pPADS );
  2429. ReferenceBinding( pBinding, TRUE );
  2430. PrSend( pBinding, pPADS );
  2431. }
  2432. if ( pPADS )
  2433. {
  2434. PacketFree( pPADS );
  2435. }
  2436. TRACE( TL_N, TM_Mp, ("-MpSendPADSWithError") );
  2437. }
  2438. VOID
  2439. MpRecvCtrlPacket(
  2440. IN BINDING* pBinding,
  2441. IN PPPOE_PACKET* pPacket
  2442. )
  2443. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2444. Functional Description:
  2445. This function will be called by MpRecvPacket() when the packet received
  2446. is a control packet.
  2447. Caller (MpRecPacket()) will make sure that in the context of this function
  2448. gl_pAdapter, gl_pAdapter->TapiProv.hCallTable and gl_pAdapter->TapiProv.hLineTable
  2449. are valid. It will also reference and dereference TapiProv correctly.
  2450. This function will identify the call the packet is for and dispatch the
  2451. packet to it.
  2452. Parameters:
  2453. pBinding _ Pointer to the binding structure that packet was received over.
  2454. pPacket _ A PPPoE packet received over the wire.
  2455. Return Values:
  2456. None
  2457. ---------------------------------------------------------------------------*/
  2458. {
  2459. ADAPTER* pAdapter = NULL;
  2460. BOOLEAN fIndicateReceive = FALSE;
  2461. USHORT usCode;
  2462. CALL* pCall = NULL;
  2463. TRACE( TL_N, TM_Mp, ("+MpRecvCtrlPacket($%x)",pPacket) );
  2464. pAdapter = gl_pAdapter;
  2465. usCode = PacketGetCode( pPacket );
  2466. switch( usCode )
  2467. {
  2468. case PACKET_CODE_PADI:
  2469. //
  2470. // Ignore the received PADI packets unless we act as a server and we have open lines.
  2471. //
  2472. if ( !pAdapter->fClientRole && ( pAdapter->TapiProv.nActiveLines > 0 ) )
  2473. {
  2474. TRACE( TL_N, TM_Mp, ("MpRecvCtrlPacket($%x): PADI received",pPacket) );
  2475. MpReplyToPADI( pAdapter, pBinding, pPacket );
  2476. }
  2477. break;
  2478. case PACKET_CODE_PADR:
  2479. //
  2480. // Ignore the received PADR packets unless we act as a server.
  2481. //
  2482. if ( !pAdapter->fClientRole )
  2483. {
  2484. ULONG ulErrorCode = PPPOE_NO_ERROR;
  2485. TRACE( TL_N, TM_Mp, ("MpRecvCtrlPacket($%x): PADR received",pPacket) );
  2486. //
  2487. // Verify the requested service name and validate the AC Cookie
  2488. // tag, and if they look OK, then start receiving the call.
  2489. //
  2490. if ( !MpVerifyServiceName( pAdapter, pPacket, TRUE ) )
  2491. {
  2492. ulErrorCode = PPPOE_ERROR_SERVICE_NOT_SUPPORTED;
  2493. }
  2494. else if ( !PacketValidateACCookieTagInPADR( pPacket ) )
  2495. {
  2496. ulErrorCode = PPPOE_ERROR_INVALID_AC_COOKIE_TAG;
  2497. }
  2498. else if ( !MpCheckClientQuota( pAdapter, pPacket ) )
  2499. {
  2500. ulErrorCode = PPPOE_ERROR_CLIENT_QUOTA_EXCEEDED;
  2501. }
  2502. if ( ulErrorCode == PPPOE_NO_ERROR )
  2503. {
  2504. TpReceiveCall( pAdapter, pBinding, pPacket );
  2505. }
  2506. else
  2507. {
  2508. MpSendPADSWithError( pBinding, pPacket, ulErrorCode );
  2509. }
  2510. }
  2511. break;
  2512. case PACKET_CODE_PADO:
  2513. if ( pAdapter->fClientRole )
  2514. {
  2515. TRACE( TL_N, TM_Mp, ("MpRecvCtrlPacket($%x): PADO received",pPacket) );
  2516. //
  2517. // Retrieve the call handle from the PADO packet
  2518. //
  2519. pCall = MpMapPacketWithoutSessionIdToCall( pAdapter, pPacket );
  2520. if ( pCall )
  2521. {
  2522. //
  2523. // Dispatch the packet to related call
  2524. //
  2525. FsmRun( pCall, pBinding, pPacket, NULL );
  2526. //
  2527. // Remove the reference added in MpMapPacketWithoutSessionIdToCall()
  2528. //
  2529. DereferenceCall( pCall );
  2530. }
  2531. }
  2532. break;
  2533. case PACKET_CODE_PADS:
  2534. if ( pAdapter->fClientRole )
  2535. {
  2536. TRACE( TL_N, TM_Mp, ("MpRecvCtrlPacket($%x): PADS received",pPacket) );
  2537. //
  2538. // Retrieve the call handle from the PADS packet
  2539. //
  2540. pCall = MpMapPacketWithoutSessionIdToCall( pAdapter, pPacket );
  2541. if ( pCall )
  2542. {
  2543. //
  2544. // For PADS packet, we must make sure that no other calls
  2545. // between the same 2 machines already have the same session id.
  2546. //
  2547. {
  2548. HANDLE_TABLE hCallTable = NULL;
  2549. UINT hCallTableSize = 0;
  2550. UINT i = 0;
  2551. USHORT usSessionId = PacketGetSessionId( pPacket );
  2552. CHAR* pSrcAddr = PacketGetSrcAddr( pPacket );
  2553. CHAR* pDestAddr = PacketGetDestAddr( pPacket );
  2554. BOOLEAN fDuplicateFound = FALSE;
  2555. CALL* pTempCall = NULL;
  2556. TRACE( TL_N, TM_Mp, ("MpRecvCtrlPacket($%x): Checking for duplicate session",pPacket) );
  2557. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  2558. hCallTableSize = pAdapter->nMaxLines * pAdapter->nCallsPerLine;
  2559. hCallTable = pAdapter->TapiProv.hCallTable;
  2560. for ( i = 0; i < hCallTableSize ; i++ )
  2561. {
  2562. pTempCall = RetrieveFromHandleTableByIndex( hCallTable, (USHORT) i );
  2563. if ( pTempCall == NULL )
  2564. continue;
  2565. if ( ( pTempCall->usSessionId == usSessionId ) &&
  2566. ( NdisEqualMemory( pTempCall->SrcAddr, pSrcAddr, 6 * sizeof( CHAR ) ) ) &&
  2567. ( NdisEqualMemory( pTempCall->DestAddr, pDestAddr, 6 * sizeof( CHAR ) ) ) )
  2568. {
  2569. //
  2570. // Another call has been detected between the 2 machines with the same
  2571. // session id, so do not accept this session
  2572. //
  2573. fDuplicateFound = TRUE;
  2574. break;
  2575. }
  2576. }
  2577. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  2578. if ( fDuplicateFound )
  2579. {
  2580. //
  2581. // We have found another session with the same machine that has the
  2582. // same session id, so we can not accept this new session.
  2583. //
  2584. // Remove the reference added in MpMapPacketWithoutSessionId() and
  2585. // drop the packet
  2586. //
  2587. TRACE( TL_A, TM_Mp, ("MpRecvCtrlPacket($%x): Packet dropped - Duplicate session found",pPacket) );
  2588. DereferenceCall( pCall );
  2589. break;
  2590. }
  2591. }
  2592. TRACE( TL_N, TM_Mp, ("MpRecvCtrlPacket($%x): No duplicate sessions found",pPacket) );
  2593. //
  2594. // Dispatch the packet to related call
  2595. //
  2596. FsmRun( pCall, pBinding, pPacket, NULL );
  2597. //
  2598. // Remove the reference added in MpMapPacketWithoutSessionIdToCall()
  2599. //
  2600. DereferenceCall( pCall );
  2601. } // if ( pCall ) ...
  2602. } // if ( fClientRole ) ...
  2603. break;
  2604. case PACKET_CODE_PADT:
  2605. TRACE( TL_N, TM_Mp, ("MpRecvCtrlPacket($%x): PADT received",pPacket) );
  2606. //
  2607. // PADT packet must have a session id.
  2608. // Identify the session and drop the call.
  2609. //
  2610. pCall = MpMapPacketWithSessionIdToCall( pAdapter, pPacket );
  2611. if ( pCall )
  2612. {
  2613. NDIS_TAPI_DROP DummyRequest;
  2614. TRACE( TL_N, TM_Mp, ("MpRecvCtrlPacket($%x): Call being dropped - PADT received",pPacket) );
  2615. //
  2616. // Initialize the request, and drop the call
  2617. //
  2618. DummyRequest.hdCall = pCall->hdCall;
  2619. TpDropCall( pAdapter, &DummyRequest, LINEDISCONNECTMODE_NORMAL );
  2620. //
  2621. // Remove the reference added in MpMapPacketWithSessionIdToCall()
  2622. //
  2623. DereferenceCall( pCall );
  2624. }
  2625. break;
  2626. default:
  2627. break;
  2628. }
  2629. TRACE( TL_N, TM_Mp, ("-MpRecvCtrlPacket($%x)",pPacket) );
  2630. }
  2631. VOID
  2632. MpRecvPacket(
  2633. IN BINDING* pBinding,
  2634. IN PPPOE_PACKET* pPacket
  2635. )
  2636. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2637. Functional Description:
  2638. This function will be called by the protocol module to notify the miniport
  2639. when a packet is received.
  2640. If packet is a control packet, it will call MpRecvCtrlPacket(), otherwise
  2641. it will identify the call and notify NDISWAN about the packet received.
  2642. Parameters:
  2643. pBinding _ Pointer to the binding structure that packet was received over.
  2644. pPacket _ A PPPoE packet received over the wire.
  2645. Return Values:
  2646. None
  2647. ---------------------------------------------------------------------------*/
  2648. {
  2649. ADAPTER* pAdapter = NULL;
  2650. CALL* pCall = NULL;
  2651. TRACE( TL_V, TM_Mp, ("+MpReceivePacket($%x)",pPacket) );
  2652. if ( !gl_fLockAllocated )
  2653. {
  2654. TRACE( TL_V, TM_Mp, ("-MpReceivePacket($%x): Lock not allocated",pPacket) );
  2655. return;
  2656. }
  2657. NdisAcquireSpinLock( &gl_lockAdapter );
  2658. if ( gl_pAdapter &&
  2659. !( gl_pAdapter->ulMpFlags & MPBF_MiniportHaltPending ) &&
  2660. ( gl_pAdapter->ulMpFlags & MPBF_MiniportInitialized ) )
  2661. {
  2662. pAdapter = gl_pAdapter;
  2663. NdisAcquireSpinLock( &pAdapter->lockAdapter );
  2664. if ( !( pAdapter->TapiProv.ulTpFlags & TPBF_TapiProvShutdownPending ) &&
  2665. ( pAdapter->TapiProv.ulTpFlags & TPBF_TapiProvInitialized ) )
  2666. {
  2667. ReferenceTapiProv( pAdapter, FALSE );
  2668. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  2669. }
  2670. else
  2671. {
  2672. NdisReleaseSpinLock( &pAdapter->lockAdapter );
  2673. pAdapter = NULL;
  2674. }
  2675. }
  2676. NdisReleaseSpinLock( &gl_lockAdapter );
  2677. if ( pAdapter == NULL )
  2678. {
  2679. TRACE( TL_V, TM_Mp, ("-MpReceivePacket($%x): Adapter not found",pPacket) );
  2680. return;
  2681. }
  2682. if ( PacketGetCode( pPacket ) == PACKET_CODE_PAYLOAD )
  2683. {
  2684. //
  2685. // Payload packet is received
  2686. //
  2687. pCall = MpMapPacketWithSessionIdToCall( pAdapter, pPacket );
  2688. if ( pCall )
  2689. {
  2690. NdisAcquireSpinLock( &pCall->lockCall );
  2691. //
  2692. // Make sure call is not dropped, closed or closing, and receive window is still open
  2693. //
  2694. if ( !( pCall->ulClFlags & ( CLBF_CallDropped | CLBF_CallClosePending | CLBF_CallClosed ) ) &&
  2695. ( pCall->nReceivedPackets < MAX_RECEIVED_PACKETS ) )
  2696. {
  2697. //
  2698. // Reference the packet. It will be dereferenced when indicated to NDISWAN, or
  2699. // when the queue is destroyed because the call is getting cleaned up.
  2700. //
  2701. ReferencePacket( pPacket );
  2702. //
  2703. // Insert into the receive queue and bump up the received packet count
  2704. //
  2705. InsertTailList( &pCall->linkReceivedPackets, &pPacket->linkPackets );
  2706. pCall->nReceivedPackets++;
  2707. //
  2708. // Try to schedule an IndicateReceivedPackets handler
  2709. //
  2710. MpScheduleIndicateReceivedPacketsHandler( pCall );
  2711. }
  2712. NdisReleaseSpinLock( &pCall->lockCall );
  2713. //
  2714. // Remove the reference added by MpMapPacketWithSessionIdToCall()
  2715. //
  2716. DereferenceCall( pCall );
  2717. }
  2718. }
  2719. else
  2720. {
  2721. //
  2722. // Control packet is received, process it
  2723. //
  2724. MpRecvCtrlPacket( pBinding, pPacket );
  2725. }
  2726. //
  2727. // Remove the reference added above
  2728. //
  2729. DereferenceTapiProv( pAdapter );
  2730. TRACE( TL_V, TM_Mp, ("-MpReceivePacket($%x)",pPacket) );
  2731. }
  2732. VOID
  2733. MpIndicateReceivedPackets(
  2734. IN TIMERQITEM* pTqi,
  2735. IN VOID* pContext,
  2736. IN TIMERQEVENT event
  2737. )
  2738. {
  2739. ULONG ulPacketsToIndicate = MAX_INDICATE_RECEIVED_PACKETS;
  2740. CALL* pCall = (CALL*) pContext;
  2741. PPPOE_PACKET* pPacket = NULL;
  2742. LIST_ENTRY* pLink = NULL;
  2743. ASSERT( VALIDATE_CALL( pCall ) );
  2744. NdisAcquireSpinLock( &pCall->lockCall );
  2745. while ( ulPacketsToIndicate > 0 &&
  2746. pCall->stateCall == CL_stateSessionUp &&
  2747. pCall->nReceivedPackets > 0)
  2748. {
  2749. ulPacketsToIndicate--;
  2750. pLink = RemoveHeadList( &pCall->linkReceivedPackets );
  2751. pCall->nReceivedPackets--;
  2752. NdisReleaseSpinLock( &pCall->lockCall );
  2753. {
  2754. NDIS_STATUS status;
  2755. CHAR* pPayload = NULL;
  2756. USHORT usSize = 0;
  2757. pPacket = (PPPOE_PACKET*) CONTAINING_RECORD( pLink, PPPOE_PACKET, linkPackets );
  2758. PacketRetrievePayload( pPacket,
  2759. &pPayload,
  2760. &usSize );
  2761. //
  2762. // Future: Make sure the size of the packet is less than the max of what NDISWAN expects
  2763. //
  2764. // if ( usSize > pCall->NdisWanLinkInfo.MaxRecvFrameSize )
  2765. // {
  2766. // TRACE( TL_A, TM_Mp, ("MpReceivePacket($%x): PAYLOAD too large to be indicated to NDISWAN",pPacket) );
  2767. // }
  2768. // else
  2769. TRACE( TL_V, TM_Mp, ("MpReceivePacket($%x): PAYLOAD is being indicated to NDISWAN",pPacket) );
  2770. NdisMWanIndicateReceive( &status,
  2771. pCall->pLine->pAdapter->MiniportAdapterHandle,
  2772. pCall->NdisLinkContext,
  2773. pPayload,
  2774. (UINT) usSize );
  2775. DereferencePacket( pPacket );
  2776. }
  2777. NdisAcquireSpinLock( &pCall->lockCall );
  2778. }
  2779. //
  2780. // Check if there are more packets to indicate
  2781. //
  2782. if ( pCall->stateCall == CL_stateSessionUp &&
  2783. pCall->nReceivedPackets > 0)
  2784. {
  2785. //
  2786. // More packets to indicate, so schedule another timer manually.
  2787. // We can not use MpScheduleIndicateReceivedPacketsHandler() function here
  2788. // because of performance reasons, so we do it manually.
  2789. //
  2790. // Since we are scheduling another handler, we do not dereference and reference
  2791. // the call context.
  2792. //
  2793. TimerQInitializeItem( &pCall->timerReceivedPackets );
  2794. TimerQScheduleItem( &gl_TimerQ,
  2795. &pCall->timerReceivedPackets,
  2796. (ULONG) RECEIVED_PACKETS_TIMEOUT,
  2797. MpIndicateReceivedPackets,
  2798. (PVOID) pCall );
  2799. NdisReleaseSpinLock( &pCall->lockCall );
  2800. }
  2801. else
  2802. {
  2803. //
  2804. // We are done, so let's remove the reference on the call context, and
  2805. // reset the CLBF_CallReceivePacketHandlerScheduled flag
  2806. //
  2807. pCall->ulClFlags &= ~CLBF_CallReceivePacketHandlerScheduled;
  2808. NdisReleaseSpinLock( &pCall->lockCall );
  2809. DereferenceCall( pCall );
  2810. }
  2811. }
  2812. VOID
  2813. MpScheduleIndicateReceivedPacketsHandler(
  2814. CALL* pCall
  2815. )
  2816. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2817. Functional Description:
  2818. This function will be called to schedule MpIndicateReceivedPackets() handler.
  2819. It will check if we are allowed to schedule it first, and if we are, then it
  2820. will schedule it and reference the call context.
  2821. CAUTION :Caller MUST be holding pCall->lockCall.
  2822. Parameters:
  2823. pCall _ Pointer to our call context.
  2824. Return Values:
  2825. NONE
  2826. ---------------------------------------------------------------------------*/
  2827. {
  2828. if ( !( pCall->ulClFlags & CLBF_CallReceivePacketHandlerScheduled ) &&
  2829. pCall->stateCall == CL_stateSessionUp &&
  2830. pCall->nReceivedPackets > 0 )
  2831. {
  2832. pCall->ulClFlags |= CLBF_CallReceivePacketHandlerScheduled;
  2833. TimerQInitializeItem( &pCall->timerReceivedPackets );
  2834. TimerQScheduleItem( &gl_TimerQ,
  2835. &pCall->timerReceivedPackets,
  2836. (ULONG) RECEIVED_PACKETS_TIMEOUT,
  2837. MpIndicateReceivedPackets,
  2838. (PVOID) pCall );
  2839. ReferenceCall( pCall, FALSE );
  2840. }
  2841. }
  2842. NDIS_STATUS
  2843. MpWanGetInfo(
  2844. IN ADAPTER* pAdapter,
  2845. IN PNDIS_WAN_INFO pWanInfo
  2846. )
  2847. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2848. Functional Description:
  2849. This function will be called when miniport receives an OID_WAN_GET_INFO
  2850. query from NDISWAN. It will acquire the necesarry information and return it
  2851. back to NDISWAN.
  2852. All the info is initialized when the adapter is initialized except for
  2853. MaxFrameSize which depends on the active bindings. That's why we query
  2854. the protocol to get the current MaxFrameSize, and pass it back.
  2855. Parameters:
  2856. pAdapter _ Pointer to our adapter context.
  2857. pWanInfo _ Pointer to the NDIS_WAN_INFO structure to be filled in.
  2858. Return Values:
  2859. NDIS_STATUS_SUCCESS
  2860. ---------------------------------------------------------------------------*/
  2861. {
  2862. NDIS_STATUS status = NDIS_STATUS_SUCCESS;
  2863. TRACE( TL_N, TM_Mp, ("+MpWanGetInfo") );
  2864. //
  2865. // Retrieve the current MaxFrameSize from protocol
  2866. //
  2867. pAdapter->NdisWanInfo.MaxFrameSize = PrQueryMaxFrameSize();
  2868. //
  2869. // Pass data back to NDISWAN
  2870. //
  2871. *pWanInfo = pAdapter->NdisWanInfo;
  2872. TRACE( TL_N, TM_Mp, ("-MpWanGetInfo()=$%x",status) );
  2873. return status;
  2874. }
  2875. NDIS_STATUS
  2876. MpWanGetLinkInfo(
  2877. IN ADAPTER* pAdapter,
  2878. IN PNDIS_WAN_GET_LINK_INFO pWanLinkInfo
  2879. )
  2880. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2881. Functional Description:
  2882. This function will be called when miniport receives an OID_WAN_GET_LINK_INFO
  2883. query from NDISWAN. It will acquire the necesarry information and return it
  2884. back to NDISWAN.
  2885. All the info is initialized in TpCallStateChangeHandler() when TAPI is signaled
  2886. to LINECALLSTATE_CONNECTED state.
  2887. Parameters:
  2888. pAdapter _ Pointer to our adapter context.
  2889. pWanLinkInfo _ Pointer to the NDIS_WAN_GET_LINK_INFO structure to be filled in.
  2890. Return Values:
  2891. NDIS_STATUS_FAILURE
  2892. NDIS_STATUS_SUCCESS
  2893. ---------------------------------------------------------------------------*/
  2894. {
  2895. NDIS_STATUS status = NDIS_STATUS_FAILURE;
  2896. CALL* pCall = NULL;
  2897. TRACE( TL_N, TM_Mp, ("+MpWanGetLinkInfo") );
  2898. pCall = RetrieveFromHandleTable( pAdapter->TapiProv.hCallTable,
  2899. pWanLinkInfo->NdisLinkHandle );
  2900. if ( pCall )
  2901. {
  2902. *pWanLinkInfo = pCall->NdisWanLinkInfo;
  2903. status = NDIS_STATUS_SUCCESS;
  2904. }
  2905. TRACE( TL_N, TM_Mp, ("-MpWanGetLinkInfo()=$%x",status) );
  2906. return status;
  2907. }
  2908. NDIS_STATUS
  2909. MpWanSetLinkInfo(
  2910. IN ADAPTER* pAdapter,
  2911. IN PNDIS_WAN_SET_LINK_INFO pWanLinkInfo
  2912. )
  2913. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2914. Functional Description:
  2915. This function will be called when miniport receives an OID_WAN_SET_LINK_INFO
  2916. request from NDISWAN. It will do some checks on the passed in params, and if
  2917. the values are acceptiable it will copy them onto the call context.
  2918. Parameters:
  2919. pAdapter _ Pointer to our adapter context.
  2920. pWanLinkInfo _ Pointer to the NDIS_WAN_SET_LINK_INFO structure.
  2921. Return Values:
  2922. NDIS_STATUS_FAILURE
  2923. NDIS_STATUS_SUCCESS
  2924. ---------------------------------------------------------------------------*/
  2925. {
  2926. NDIS_STATUS status = NDIS_STATUS_FAILURE;
  2927. CALL* pCall = NULL;
  2928. TRACE( TL_N, TM_Mp, ("+MpWanSetLinkInfo") );
  2929. pCall = RetrieveFromHandleTable( pAdapter->TapiProv.hCallTable,
  2930. pWanLinkInfo->NdisLinkHandle );
  2931. if ( pCall )
  2932. {
  2933. do
  2934. {
  2935. if ( pWanLinkInfo->MaxSendFrameSize > pCall->ulMaxFrameSize )
  2936. {
  2937. TRACE( TL_A, TM_Mp, ("MpWanSetLinkInfo: Requested MaxSendFrameSize is larger than NIC's") );
  2938. }
  2939. if ( pWanLinkInfo->MaxRecvFrameSize < pCall->ulMaxFrameSize )
  2940. {
  2941. TRACE( TL_A, TM_Mp, ("MpWanSetLinkInfo: Requested MaxRecvFrameSize is smaller than NIC's") );
  2942. }
  2943. if ( pWanLinkInfo->HeaderPadding != pAdapter->NdisWanInfo.HeaderPadding )
  2944. {
  2945. TRACE( TL_A, TM_Mp, ("MpWanSetLinkInfo: Requested HeaderPadding is different than what we asked for") );
  2946. }
  2947. if ( pWanLinkInfo->SendFramingBits & ~pAdapter->NdisWanInfo.FramingBits )
  2948. {
  2949. TRACE( TL_A, TM_Mp, ("MpWanSetLinkInfo: Unknown send framing bits requested") );
  2950. break;
  2951. }
  2952. if ( pWanLinkInfo->RecvFramingBits & ~pAdapter->NdisWanInfo.FramingBits )
  2953. {
  2954. TRACE( TL_A, TM_Mp, ("MpWanSetLinkInfo: Unknown recv framing bits requested") );
  2955. break;
  2956. }
  2957. //
  2958. // Ignore FrameSize if the values are 0.
  2959. //
  2960. if(pWanLinkInfo->MaxSendFrameSize != 0)
  2961. {
  2962. pCall->NdisWanLinkInfo.MaxSendFrameSize = pWanLinkInfo->MaxSendFrameSize;
  2963. }
  2964. if(pWanLinkInfo->MaxRecvFrameSize != 0)
  2965. {
  2966. pCall->NdisWanLinkInfo.MaxRecvFrameSize = pWanLinkInfo->MaxRecvFrameSize;
  2967. }
  2968. RtlCopyMemory(&pCall->NdisWanLinkInfo.HeaderPadding,
  2969. &pWanLinkInfo->HeaderPadding,
  2970. sizeof(NDIS_WAN_GET_LINK_INFO) -
  2971. FIELD_OFFSET(NDIS_WAN_GET_LINK_INFO, HeaderPadding));
  2972. // pCall->NdisWanLinkInfo = * ( (PNDIS_WAN_GET_LINK_INFO) pWanLinkInfo );
  2973. status = NDIS_STATUS_SUCCESS;
  2974. } while ( FALSE );
  2975. }
  2976. TRACE( TL_N, TM_Mp, ("-MpWanSetLinkInfo()=$%x",status) );
  2977. return status;
  2978. }