Source code of Windows XP (NT5)
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.

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