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.

1399 lines
57 KiB

  1. /***************************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. UTIL.C
  5. Abstract:
  6. Utility routines for Remote NDIS Miniport driver
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  11. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  12. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  13. PURPOSE.
  14. Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
  15. Revision History:
  16. 5/17/99 : created
  17. Author:
  18. Tom Green
  19. ****************************************************************************/
  20. #include "precomp.h"
  21. ULONG MsgFrameAllocs = 0;
  22. /****************************************************************************/
  23. /* MemAlloc */
  24. /****************************************************************************/
  25. /* */
  26. /* Routine Description: */
  27. /* */
  28. /* Allocate memory */
  29. /* */
  30. /* Arguments: */
  31. /* */
  32. /* Buffer - pointer to buffer pointer */
  33. /* Length - length of buffer to allocate */
  34. /* */
  35. /* Return: */
  36. /* */
  37. /* NDIS_STATUS */
  38. /* */
  39. /****************************************************************************/
  40. NDIS_STATUS
  41. MemAlloc(OUT PVOID *Buffer, IN UINT Length)
  42. {
  43. NDIS_STATUS Status;
  44. TRACE3(("MemAlloc\n"));
  45. ASSERT(Length != 0);
  46. Status = NdisAllocateMemoryWithTag(Buffer,
  47. Length,
  48. RNDISMP_TAG_GEN_ALLOC);
  49. // zero out allocation
  50. if(Status == NDIS_STATUS_SUCCESS)
  51. NdisZeroMemory(*Buffer, Length);
  52. return Status;
  53. } // MemAlloc
  54. /****************************************************************************/
  55. /* MemFree */
  56. /****************************************************************************/
  57. /* */
  58. /* Routine Description: */
  59. /* */
  60. /* Free memory */
  61. /* */
  62. /* Arguments: */
  63. /* */
  64. /* Buffer - pointer to buffer */
  65. /* Length - length of buffer to allocate */
  66. /* */
  67. /* Return: */
  68. /* */
  69. /* VOID */
  70. /* */
  71. /****************************************************************************/
  72. VOID
  73. MemFree(IN PVOID Buffer, IN UINT Length)
  74. {
  75. TRACE3(("MemFree\n"));
  76. NdisFreeMemory(Buffer, Length, 0);
  77. } // MemFree
  78. /****************************************************************************/
  79. /* AddAdapter */
  80. /****************************************************************************/
  81. /* */
  82. /* Routine Description: */
  83. /* */
  84. /* Add an adapter to the list of adapters associated with this driver */
  85. /* */
  86. /* Arguments: */
  87. /* */
  88. /* pAdapter - Adapter object, contains pointer to associated driver block */
  89. /* */
  90. /* Return: */
  91. /* */
  92. /* VOID */
  93. /* */
  94. /****************************************************************************/
  95. VOID
  96. AddAdapter(IN PRNDISMP_ADAPTER pAdapter)
  97. {
  98. PDRIVER_BLOCK DriverBlock = pAdapter->DriverBlock;
  99. TRACE3(("AddpAdapter\n"));
  100. CHECK_VALID_ADAPTER(pAdapter);
  101. // grab the global spinlock
  102. NdisAcquireSpinLock(&RndismpGlobalLock);
  103. pAdapter->NextAdapter = DriverBlock->AdapterList;
  104. DriverBlock->AdapterList = pAdapter;
  105. // keep track of number of adapters associated with this driver block
  106. DriverBlock->NumberAdapters++;
  107. // release global spinlock
  108. NdisReleaseSpinLock(&RndismpGlobalLock);
  109. } // AddAdapter
  110. /****************************************************************************/
  111. /* RemoveAdapter */
  112. /****************************************************************************/
  113. /* */
  114. /* Routine Description: */
  115. /* */
  116. /* Remove an adapter from the list of adapters associated with this driver */
  117. /* */
  118. /* Arguments: */
  119. /* */
  120. /* pAdapter - Adapter object, contains pointer to associated driver block */
  121. /* */
  122. /* Return: */
  123. /* */
  124. /* VOID */
  125. /* */
  126. /****************************************************************************/
  127. VOID
  128. RemoveAdapter(IN PRNDISMP_ADAPTER pAdapter)
  129. {
  130. PDRIVER_BLOCK DriverBlock = pAdapter->DriverBlock;
  131. TRACE3(("RemoveAdapter\n"));
  132. CHECK_VALID_ADAPTER(pAdapter);
  133. // remove the adapter from the driver block list of adapters.
  134. // grab the global spinlock
  135. NdisAcquireSpinLock(&RndismpGlobalLock);
  136. // see if it is the first one
  137. if (DriverBlock->AdapterList == pAdapter)
  138. {
  139. DriverBlock->AdapterList = pAdapter->NextAdapter;
  140. }
  141. // not the first one, so walk the list
  142. else
  143. {
  144. PRNDISMP_ADAPTER * ppAdapter = &DriverBlock->AdapterList;
  145. while (*ppAdapter != pAdapter)
  146. {
  147. ASSERT(*ppAdapter != NULL);
  148. ppAdapter = &((*ppAdapter)->NextAdapter);
  149. }
  150. *ppAdapter = pAdapter->NextAdapter;
  151. }
  152. // removing this adapter
  153. DriverBlock->NumberAdapters--;
  154. // release global spinlock
  155. NdisReleaseSpinLock(&RndismpGlobalLock);
  156. } // RemoveAdapter
  157. /****************************************************************************/
  158. /* DeviceObjectToAdapter */
  159. /****************************************************************************/
  160. /* */
  161. /* Routine Description: */
  162. /* */
  163. /* Given a pointer to an FDO, return the corresponding Adapter structure, */
  164. /* if it exists, and the driver block. */
  165. /* */
  166. /* Arguments: */
  167. /* */
  168. /* pDeviceObject - pointer to the device object to search for. */
  169. /* ppAdapter - place to return pointer to the adapter structure. */
  170. /* ppDriverBlock - place to return pointer to driver block. */
  171. /* */
  172. /* Return: */
  173. /* */
  174. /* VOID */
  175. /* */
  176. /****************************************************************************/
  177. VOID
  178. DeviceObjectToAdapterAndDriverBlock(IN PDEVICE_OBJECT pDeviceObject,
  179. OUT PRNDISMP_ADAPTER * ppAdapter,
  180. OUT PDRIVER_BLOCK * ppDriverBlock)
  181. {
  182. PDRIVER_BLOCK pDriverBlock;
  183. PRNDISMP_ADAPTER pAdapter;
  184. pAdapter = NULL;
  185. pDriverBlock = DeviceObjectToDriverBlock(&RndismpMiniportBlockListHead, pDeviceObject);
  186. if (pDriverBlock != NULL)
  187. {
  188. NdisAcquireSpinLock(&RndismpGlobalLock);
  189. for (pAdapter = pDriverBlock->AdapterList;
  190. pAdapter != NULL;
  191. pAdapter = pAdapter->NextAdapter)
  192. {
  193. if (pAdapter->pDeviceObject == pDeviceObject)
  194. {
  195. break;
  196. }
  197. }
  198. NdisReleaseSpinLock(&RndismpGlobalLock);
  199. }
  200. *ppAdapter = pAdapter;
  201. *ppDriverBlock = pDriverBlock;
  202. } // DeviceObjectToAdapter
  203. /****************************************************************************/
  204. /* AddDriverBlock */
  205. /****************************************************************************/
  206. /* */
  207. /* Routine Description: */
  208. /* */
  209. /* Add driver block to list of drivers (microports) associated with this */
  210. /* driver */
  211. /* */
  212. /* Arguments: */
  213. /* */
  214. /* Head - head of list */
  215. /* Item - driver block to add to list */
  216. /* */
  217. /* Return: */
  218. /* */
  219. /* VOID */
  220. /* */
  221. /****************************************************************************/
  222. VOID
  223. AddDriverBlock(IN PDRIVER_BLOCK Head, IN PDRIVER_BLOCK Item)
  224. {
  225. TRACE3(("AddDriverBlock\n"));
  226. CHECK_VALID_BLOCK(Item);
  227. // first time through, so allocate global spinlock
  228. if(!RndismpNumMicroports)
  229. NdisAllocateSpinLock(&RndismpGlobalLock);
  230. // grab the global spinlock
  231. NdisAcquireSpinLock(&RndismpGlobalLock);
  232. // Link the driver block on the global list of driver blocks
  233. Item->NextDriverBlock = Head->NextDriverBlock;
  234. Head->NextDriverBlock = Item;
  235. // keep track of how many microports we support so we can free
  236. // global resources
  237. RndismpNumMicroports++;
  238. // release global spinlock
  239. NdisReleaseSpinLock(&RndismpGlobalLock);
  240. } // AddDriverBlock
  241. /****************************************************************************/
  242. /* RemoveDriverBlock */
  243. /****************************************************************************/
  244. /* */
  245. /* Routine Description: */
  246. /* */
  247. /* Remove driver block from list of drivers (microports) associated with */
  248. /* this driver */
  249. /* */
  250. /* Arguments: */
  251. /* */
  252. /* Head - head of list */
  253. /* Item - driver block to remove from list */
  254. /* */
  255. /* Return: */
  256. /* */
  257. /* VOID */
  258. /* */
  259. /****************************************************************************/
  260. VOID
  261. RemoveDriverBlock(IN PDRIVER_BLOCK BlockHead, IN PDRIVER_BLOCK Item)
  262. {
  263. UINT NumMicroports;
  264. PDRIVER_BLOCK Head = BlockHead;
  265. TRACE1(("RemoveDriverBlock\n"));
  266. CHECK_VALID_BLOCK(Item);
  267. // grab the global spinlock
  268. NdisAcquireSpinLock(&RndismpGlobalLock);
  269. // Remove the driver block from the global list of driver blocks
  270. while(Head->NextDriverBlock != Item)
  271. {
  272. Head = Head->NextDriverBlock;
  273. // make sure this is valid
  274. if(!Head)
  275. break;
  276. }
  277. if(Head)
  278. Head->NextDriverBlock = Head->NextDriverBlock->NextDriverBlock;
  279. // keep track of how many microports we support so we can free
  280. // global resources
  281. RndismpNumMicroports--;
  282. NumMicroports = RndismpNumMicroports;
  283. // release global spinlock
  284. NdisReleaseSpinLock(&RndismpGlobalLock);
  285. // see if we need to free global spinlock
  286. if(!RndismpNumMicroports)
  287. NdisFreeSpinLock(&RndismpGlobalLock);
  288. ASSERT(Head);
  289. } // RemoveDriverBlock
  290. /****************************************************************************/
  291. /* DeviceObjectToDriverBlock */
  292. /****************************************************************************/
  293. /* */
  294. /* Routine Description: */
  295. /* */
  296. /* Get driver block pointer associated with the PDO passed in */
  297. /* */
  298. /* Arguments: */
  299. /* */
  300. /* Head - head of driver block list */
  301. /* DeviceObject - device object we want to get associated driver block for */
  302. /* */
  303. /* Return: */
  304. /* */
  305. /* PDRIVER_BLOCK */
  306. /* */
  307. /****************************************************************************/
  308. PDRIVER_BLOCK
  309. DeviceObjectToDriverBlock(IN PDRIVER_BLOCK Head,
  310. IN PDEVICE_OBJECT DeviceObject)
  311. {
  312. PDRIVER_OBJECT DriverObject;
  313. TRACE3(("DeviceObjectToDriverBlock\n"));
  314. // grab the global spinlock
  315. NdisAcquireSpinLock(&RndismpGlobalLock);
  316. // get the driver object for this adapter
  317. DriverObject = DeviceObjectToDriverObject(DeviceObject);
  318. Head = Head->NextDriverBlock;
  319. // walk the list of driver blocks to find a match with driver object
  320. while(Head->DriverObject != DriverObject)
  321. {
  322. Head = Head->NextDriverBlock;
  323. // break out if we are at the end of the list
  324. if(!Head)
  325. break;
  326. }
  327. // release global spinlock
  328. NdisReleaseSpinLock(&RndismpGlobalLock);
  329. CHECK_VALID_BLOCK(Head);
  330. return Head;
  331. } // DeviceObjectToDriverBlock
  332. /****************************************************************************/
  333. /* DriverObjectToDriverBlock */
  334. /****************************************************************************/
  335. /* */
  336. /* Routine Description: */
  337. /* */
  338. /* Get driver block pointer associated with the Driver Object passed in */
  339. /* */
  340. /* Arguments: */
  341. /* */
  342. /* Head - head of driver block list */
  343. /* DriverObject - Driver object we want to get associated driver block for */
  344. /* */
  345. /* Return: */
  346. /* */
  347. /* PDRIVER_BLOCK */
  348. /* */
  349. /****************************************************************************/
  350. PDRIVER_BLOCK
  351. DriverObjectToDriverBlock(IN PDRIVER_BLOCK Head,
  352. IN PDRIVER_OBJECT DriverObject)
  353. {
  354. TRACE3(("DriverObjectToDriverBlock\n"));
  355. // grab the global spinlock
  356. NdisAcquireSpinLock(&RndismpGlobalLock);
  357. Head = Head->NextDriverBlock;
  358. // walk the list of driver blocks to find a match with driver object
  359. while(Head->DriverObject != DriverObject)
  360. {
  361. Head = Head->NextDriverBlock;
  362. // break out if we are at the end of the list
  363. if(!Head)
  364. break;
  365. }
  366. // release global spinlock
  367. NdisReleaseSpinLock(&RndismpGlobalLock);
  368. CHECK_VALID_BLOCK(Head);
  369. return Head;
  370. } // DriverObjectToDriverBlock
  371. /****************************************************************************/
  372. /* AllocateMsgFrame */
  373. /****************************************************************************/
  374. /* */
  375. /* Routine Description: */
  376. /* */
  377. /* Allocate a frame that holds context about a message we are about to */
  378. /* send. */
  379. /* */
  380. /* Arguments: */
  381. /* */
  382. /* pAdapter - Adapter object */
  383. /* */
  384. /* Return: */
  385. /* */
  386. /* PRNDISMP_MESSAGE_FRAME */
  387. /* */
  388. /****************************************************************************/
  389. PRNDISMP_MESSAGE_FRAME
  390. AllocateMsgFrame(IN PRNDISMP_ADAPTER pAdapter)
  391. {
  392. PRNDISMP_MESSAGE_FRAME pMsgFrame;
  393. #ifndef DONT_USE_LOOKASIDE_LIST
  394. pMsgFrame = (PRNDISMP_MESSAGE_FRAME)
  395. NdisAllocateFromNPagedLookasideList(&pAdapter->MsgFramePool);
  396. #else
  397. {
  398. NDIS_STATUS Status;
  399. Status = MemAlloc(&pMsgFrame, sizeof(RNDISMP_MESSAGE_FRAME));
  400. if (Status != NDIS_STATUS_SUCCESS)
  401. {
  402. pMsgFrame = NULL;
  403. }
  404. }
  405. #endif // DONT_USE_LOOKASIDE_LIST
  406. if (pMsgFrame)
  407. {
  408. NdisZeroMemory(pMsgFrame, sizeof(*pMsgFrame));
  409. pMsgFrame->pAdapter = pAdapter;
  410. pMsgFrame->RequestId = NdisInterlockedIncrement(&pAdapter->RequestId);
  411. pMsgFrame->Signature = FRAME_SIGNATURE;
  412. pMsgFrame->RefCount = 1;
  413. NdisInterlockedIncrement(&MsgFrameAllocs);
  414. }
  415. #if DBG
  416. else
  417. {
  418. TRACE1(("AllocateMsgFrame: pAdapter %x, MsgFramePool at %x, alloc failed, count %d\n",
  419. pAdapter, &pAdapter->MsgFramePool, MsgFrameAllocs));
  420. DbgBreakPoint();
  421. }
  422. #endif // DBG
  423. return (pMsgFrame);
  424. }
  425. /****************************************************************************/
  426. /* DereferenceMsgFrame */
  427. /****************************************************************************/
  428. /* */
  429. /* Routine Description: */
  430. /* */
  431. /* Free a message frame and any associated resources. */
  432. /* */
  433. /* Arguments: */
  434. /* */
  435. /* Frame - pointer to frame */
  436. /* */
  437. /* Return: */
  438. /* */
  439. /* VOID */
  440. /* */
  441. /****************************************************************************/
  442. VOID
  443. DereferenceMsgFrame(IN PRNDISMP_MESSAGE_FRAME pMsgFrame)
  444. {
  445. PRNDISMP_ADAPTER pAdapter;
  446. PMDL pMdl;
  447. PUCHAR pMessage;
  448. CHECK_VALID_FRAME(pMsgFrame);
  449. if (NdisInterlockedDecrement(&pMsgFrame->RefCount) == 0)
  450. {
  451. //
  452. // Mess up the contents slightly to catch bugs resulting from
  453. // improper reuse of this frame after it is freed.
  454. //
  455. pMsgFrame->Signature++;
  456. pMdl = pMsgFrame->pMessageMdl;
  457. pMsgFrame->pMessageMdl = NULL;
  458. if (pMdl)
  459. {
  460. pMessage = MmGetMdlVirtualAddress(pMdl);
  461. }
  462. else
  463. {
  464. pMessage = NULL;
  465. }
  466. if (pMessage)
  467. {
  468. MemFree(pMessage, -1);
  469. IoFreeMdl(pMdl);
  470. }
  471. pAdapter = pMsgFrame->pAdapter;
  472. #ifndef DONT_USE_LOOKASIDE_LIST
  473. NdisFreeToNPagedLookasideList(&pAdapter->MsgFramePool, pMsgFrame);
  474. #else
  475. MemFree(pMsgFrame, sizeof(RNDISMP_MESSAGE_FRAME));
  476. #endif
  477. NdisInterlockedDecrement(&MsgFrameAllocs);
  478. }
  479. } // DereferenceMsgFrame
  480. /****************************************************************************/
  481. /* ReferenceMsgFrame */
  482. /****************************************************************************/
  483. /* */
  484. /* Routine Description: */
  485. /* */
  486. /* Add a ref count to a message frame */
  487. /* */
  488. /* Arguments: */
  489. /* */
  490. /* Frame - pointer to frame */
  491. /* */
  492. /* Return: */
  493. /* */
  494. /* VOID */
  495. /* */
  496. /****************************************************************************/
  497. VOID
  498. ReferenceMsgFrame(IN PRNDISMP_MESSAGE_FRAME pMsgFrame)
  499. {
  500. NdisInterlockedIncrement(&pMsgFrame->RefCount);
  501. }
  502. /****************************************************************************/
  503. /* KeepAliveTimerHandler */
  504. /****************************************************************************/
  505. /* */
  506. /* Routine Description: */
  507. /* */
  508. /* Timer that keeps tabs on messages coming up from the device and */
  509. /* sends a "KeepAlive" message if the device has been inactive too long */
  510. /* */
  511. /* Arguments: */
  512. /* */
  513. /* SystemSpecific1 - Don't care */
  514. /* Context - pAdapter object */
  515. /* SystemSpecific2 - Don't care */
  516. /* SystemSpecific3 - Don't care */
  517. /* */
  518. /* Return: */
  519. /* */
  520. /* PNDIS_PACKET */
  521. /* */
  522. /****************************************************************************/
  523. VOID
  524. KeepAliveTimerHandler(IN PVOID SystemSpecific1,
  525. IN PVOID Context,
  526. IN PVOID SystemSpecific2,
  527. IN PVOID SystemSpecific3)
  528. {
  529. PRNDISMP_ADAPTER pAdapter;
  530. PRNDISMP_MESSAGE_FRAME pMsgFrame;
  531. ULONG CurrentTime;
  532. // get adapter context
  533. pAdapter = PRNDISMP_ADAPTER_FROM_CONTEXT_HANDLE(Context);
  534. TRACE2(("KeepAliveTimerHandler\n"));
  535. do
  536. {
  537. // get current tick (in milliseconds)
  538. NdisGetSystemUpTime(&CurrentTime);
  539. // check and see if too much time has elapsed since we
  540. // got the last message from the device
  541. RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
  542. if (((CurrentTime - pAdapter->LastMessageFromDevice) > KEEP_ALIVE_TIMER))
  543. {
  544. // see if we have a keep alive message pending, so let's bong this
  545. if (pAdapter->KeepAliveMessagePending)
  546. {
  547. TRACE1(("KeepAliveTimer: Adapter %x, message pending\n", pAdapter));
  548. // indicate later from check for hang handler
  549. pAdapter->NeedReset = TRUE;
  550. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  551. RNDISMP_INCR_STAT(pAdapter, KeepAliveTimeout);
  552. break;
  553. }
  554. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  555. // too much time has elapsed, send down a keep alive message
  556. pMsgFrame = BuildRndisMessageCommon(pAdapter,
  557. NULL,
  558. REMOTE_NDIS_KEEPALIVE_MSG,
  559. 0,
  560. NULL,
  561. 0);
  562. if (pMsgFrame)
  563. {
  564. RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
  565. pAdapter->KeepAliveMessagePending = TRUE;
  566. pAdapter->KeepAliveMessagePendingId = pMsgFrame->RequestId;
  567. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  568. // send the message to the microport
  569. RNDISMP_SEND_TO_MICROPORT(pAdapter, pMsgFrame, FALSE, CompleteSendKeepAlive);
  570. }
  571. }
  572. else
  573. {
  574. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  575. }
  576. }
  577. while (FALSE);
  578. // see if the timer was cancelled somewhere
  579. if (!pAdapter->TimerCancelled)
  580. {
  581. // restart timer
  582. NdisSetTimer(&pAdapter->KeepAliveTimer, KEEP_ALIVE_TIMER / 2);
  583. }
  584. } // KeepAliveTimerHandler
  585. /****************************************************************************/
  586. /* CompleteSendKeepAlive */
  587. /****************************************************************************/
  588. /* */
  589. /* Routine Description: */
  590. /* */
  591. /* Callback routine to handle completion of send by the microport, for */
  592. /* a keepalive message. */
  593. /* */
  594. /* Arguments: */
  595. /* */
  596. /* pMsgFrame - Pointer to message frame describing the message */
  597. /* SendStatus - Status returned by microport */
  598. /* */
  599. /* Return: */
  600. /* */
  601. /* VOID */
  602. /* */
  603. /****************************************************************************/
  604. VOID
  605. CompleteSendKeepAlive(IN PRNDISMP_MESSAGE_FRAME pMsgFrame,
  606. IN NDIS_STATUS SendStatus)
  607. {
  608. PRNDISMP_ADAPTER pAdapter;
  609. pAdapter = pMsgFrame->pAdapter;
  610. DereferenceMsgFrame(pMsgFrame);
  611. if (SendStatus != NDIS_STATUS_SUCCESS)
  612. {
  613. TRACE1(("KeepAlive send failure %x on Adapter %x\n",
  614. SendStatus, pAdapter));
  615. RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
  616. pAdapter->KeepAliveMessagePending = FALSE;
  617. pAdapter->NeedReset = FALSE;
  618. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  619. }
  620. } // CompleteSendKeepAlive
  621. /****************************************************************************/
  622. /* BuildRndisMessageCommon */
  623. /****************************************************************************/
  624. /* */
  625. /* Routine Description: */
  626. /* */
  627. /* Allocate resources for meesage and frame and build RNDIS message */
  628. /* */
  629. /* Arguments: */
  630. /* */
  631. /* pAdapter - adapter object */
  632. /* pVc - optionally, VC on which this message is sent. */
  633. /* NdisMessageType - RNDIS message type */
  634. /* Oid - the NDIS_OID to process. */
  635. /* InformationBuffer - Holds the data to be set. */
  636. /* InformationBufferLength - The length of InformationBuffer. */
  637. /* */
  638. /* Return: */
  639. /* */
  640. /* PRNDISMP_MESSAGE_FRAME */
  641. /* */
  642. /****************************************************************************/
  643. PRNDISMP_MESSAGE_FRAME
  644. BuildRndisMessageCommon(IN PRNDISMP_ADAPTER pAdapter,
  645. IN PRNDISMP_VC pVc OPTIONAL,
  646. IN UINT NdisMessageType,
  647. IN NDIS_OID Oid,
  648. IN PVOID InformationBuffer,
  649. IN ULONG InformationBufferLength)
  650. {
  651. PRNDIS_MESSAGE pMessage;
  652. UINT MessageSize;
  653. PRNDISMP_MESSAGE_FRAME pMsgFrame;
  654. TRACE2(("BuildRndisMessageCommon\n"));
  655. pMsgFrame = NULL;
  656. switch(NdisMessageType)
  657. {
  658. case REMOTE_NDIS_INITIALIZE_MSG:
  659. {
  660. PRNDIS_INITIALIZE_REQUEST pInitRequest;
  661. MessageSize = RNDIS_MESSAGE_SIZE(RNDIS_INITIALIZE_REQUEST);
  662. // get a message and request frame
  663. pMsgFrame = AllocateMessageAndFrame(pAdapter,
  664. MessageSize);
  665. if (pMsgFrame == NULL)
  666. {
  667. break;
  668. }
  669. pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame);
  670. pMessage->NdisMessageType = NdisMessageType;
  671. pMsgFrame->NdisMessageType = NdisMessageType;
  672. TRACE1(("RNDISMP: Init Req message %x, Type %d, Length %d, MaxRcv %d\n",
  673. pMessage, pMessage->NdisMessageType, pMessage->MessageLength, pAdapter->MaxReceiveSize));
  674. pInitRequest = &pMessage->Message.InitializeRequest;
  675. pInitRequest->RequestId = pMsgFrame->RequestId;
  676. pInitRequest->MajorVersion = RNDIS_MAJOR_VERSION;
  677. pInitRequest->MinorVersion = RNDIS_MINOR_VERSION;
  678. pInitRequest->MaxTransferSize = pAdapter->MaxReceiveSize;
  679. break;
  680. }
  681. case REMOTE_NDIS_HALT_MSG:
  682. {
  683. PRNDIS_HALT_REQUEST pHaltRequest;
  684. MessageSize = RNDIS_MESSAGE_SIZE(RNDIS_HALT_REQUEST);
  685. // get a message and request frame
  686. pMsgFrame = AllocateMessageAndFrame(pAdapter,
  687. MessageSize);
  688. if (pMsgFrame == NULL)
  689. {
  690. break;
  691. }
  692. pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame);
  693. pMessage->NdisMessageType = NdisMessageType;
  694. pMsgFrame->NdisMessageType = NdisMessageType;
  695. pHaltRequest = &pMessage->Message.HaltRequest;
  696. pHaltRequest->RequestId = pMsgFrame->RequestId;
  697. break;
  698. }
  699. case REMOTE_NDIS_QUERY_MSG:
  700. {
  701. PRNDIS_QUERY_REQUEST pQueryRequest;
  702. MessageSize = RNDIS_MESSAGE_SIZE(RNDIS_QUERY_REQUEST) + InformationBufferLength;
  703. // get a message and request frame
  704. pMsgFrame = AllocateMessageAndFrame(pAdapter,
  705. MessageSize);
  706. if (pMsgFrame == NULL)
  707. {
  708. break;
  709. }
  710. pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame);
  711. pMessage->NdisMessageType = NdisMessageType;
  712. pMsgFrame->NdisMessageType = NdisMessageType;
  713. pQueryRequest = &pMessage->Message.QueryRequest;
  714. pQueryRequest->RequestId = pMsgFrame->RequestId;
  715. pQueryRequest->Oid = Oid;
  716. pQueryRequest->InformationBufferLength = InformationBufferLength;
  717. pQueryRequest->InformationBufferOffset = sizeof(RNDIS_QUERY_REQUEST);
  718. if (pVc == NULL)
  719. {
  720. pQueryRequest->DeviceVcHandle = NULL_DEVICE_CONTEXT;
  721. }
  722. else
  723. {
  724. pQueryRequest->DeviceVcHandle = pVc->DeviceVcContext;
  725. }
  726. TRACE2(("Query OID %x, Len %d, RequestId %08X\n",
  727. Oid, InformationBufferLength, pQueryRequest->RequestId));
  728. // copy information buffer
  729. RNDISMP_MOVE_MEM(RNDISMP_GET_INFO_BUFFER_FROM_QUERY_MSG(pQueryRequest),
  730. InformationBuffer,
  731. InformationBufferLength);
  732. break;
  733. }
  734. case REMOTE_NDIS_SET_MSG:
  735. {
  736. PRNDIS_SET_REQUEST pSetRequest;
  737. MessageSize = RNDIS_MESSAGE_SIZE(RNDIS_SET_REQUEST) + InformationBufferLength;
  738. // get a message and request frame
  739. pMsgFrame = AllocateMessageAndFrame(pAdapter,
  740. MessageSize);
  741. if (pMsgFrame == NULL)
  742. {
  743. break;
  744. }
  745. pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame);
  746. pMessage->NdisMessageType = NdisMessageType;
  747. pMsgFrame->NdisMessageType = NdisMessageType;
  748. pSetRequest = &pMessage->Message.SetRequest;
  749. pSetRequest->RequestId = pMsgFrame->RequestId;
  750. pSetRequest->Oid = Oid;
  751. pSetRequest->InformationBufferLength = InformationBufferLength;
  752. pSetRequest->InformationBufferOffset = sizeof(RNDIS_SET_REQUEST);
  753. if (pVc == NULL)
  754. {
  755. pSetRequest->DeviceVcHandle = NULL_DEVICE_CONTEXT;
  756. }
  757. else
  758. {
  759. pSetRequest->DeviceVcHandle = pVc->DeviceVcContext;
  760. }
  761. // copy information buffer
  762. RNDISMP_MOVE_MEM(RNDISMP_GET_INFO_BUFFER_FROM_QUERY_MSG(pSetRequest),
  763. InformationBuffer,
  764. InformationBufferLength);
  765. break;
  766. }
  767. case REMOTE_NDIS_RESET_MSG:
  768. {
  769. PRNDIS_RESET_REQUEST pResetRequest;
  770. MessageSize = RNDIS_MESSAGE_SIZE(RNDIS_RESET_REQUEST);
  771. // get a message and request frame
  772. pMsgFrame = AllocateMessageAndFrame(pAdapter,
  773. MessageSize);
  774. if (pMsgFrame == NULL)
  775. {
  776. break;
  777. }
  778. pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame);
  779. pMessage->NdisMessageType = NdisMessageType;
  780. pMsgFrame->NdisMessageType = NdisMessageType;
  781. pResetRequest = &pMessage->Message.ResetRequest;
  782. pResetRequest->Reserved = 0;
  783. break;
  784. }
  785. case REMOTE_NDIS_KEEPALIVE_MSG:
  786. {
  787. PRNDIS_KEEPALIVE_REQUEST pKeepAliveRequest;
  788. MessageSize = RNDIS_MESSAGE_SIZE(RNDIS_KEEPALIVE_REQUEST);
  789. // get a message and request frame
  790. pMsgFrame = AllocateMessageAndFrame(pAdapter,
  791. MessageSize);
  792. if (pMsgFrame == NULL)
  793. {
  794. break;
  795. }
  796. pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame);
  797. pMessage->NdisMessageType = NdisMessageType;
  798. pMsgFrame->NdisMessageType = NdisMessageType;
  799. pKeepAliveRequest = &pMessage->Message.KeepaliveRequest;
  800. pKeepAliveRequest->RequestId = pMsgFrame->RequestId;
  801. break;
  802. }
  803. case REMOTE_NDIS_KEEPALIVE_CMPLT:
  804. {
  805. PRNDIS_KEEPALIVE_COMPLETE pKeepAliveComplete;
  806. MessageSize = RNDIS_MESSAGE_SIZE(RNDIS_KEEPALIVE_COMPLETE);
  807. // get a message and request frame
  808. pMsgFrame = AllocateMessageAndFrame(pAdapter,
  809. MessageSize);
  810. if (pMsgFrame == NULL)
  811. {
  812. break;
  813. }
  814. pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame);
  815. pMessage->NdisMessageType = NdisMessageType;
  816. pMsgFrame->NdisMessageType = NdisMessageType;
  817. pKeepAliveComplete = &pMessage->Message.KeepaliveComplete;
  818. pKeepAliveComplete->RequestId = *(RNDIS_REQUEST_ID *)InformationBuffer;
  819. pKeepAliveComplete->Status = NDIS_STATUS_SUCCESS;
  820. break;
  821. }
  822. default:
  823. TRACE2(("Invalid NdisMessageType (%08X)\n", NdisMessageType));
  824. ASSERT(FALSE);
  825. break;
  826. }
  827. return pMsgFrame;
  828. } // BuildRndisMessageCommon
  829. /****************************************************************************/
  830. /* AllocateMessageAndFrame */
  831. /****************************************************************************/
  832. /* */
  833. /* Routine Description: */
  834. /* */
  835. /* Allocate a message and frame for an RNDIS message */
  836. /* */
  837. /* Arguments: */
  838. /* */
  839. /* pAdapter - pAdapter object */
  840. /* MessageSize - size of RNDIS message */
  841. /* */
  842. /* Return: */
  843. /* */
  844. /* PRNDISMP_MESSAGE_FRAME */
  845. /* */
  846. /****************************************************************************/
  847. PRNDISMP_MESSAGE_FRAME
  848. AllocateMessageAndFrame(IN PRNDISMP_ADAPTER pAdapter,
  849. IN UINT MessageSize)
  850. {
  851. PRNDIS_MESSAGE pMessage = NULL;
  852. PRNDISMP_MESSAGE_FRAME pMsgFrame = NULL;
  853. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  854. PMDL pMdl = NULL;
  855. TRACE3(("AllocateMessageAndFrame\n"));
  856. do
  857. {
  858. // allocate a buffer for RNDIS message
  859. Status = MemAlloc(&pMessage, MessageSize);
  860. // see if we got our buffer
  861. if (Status != NDIS_STATUS_SUCCESS)
  862. {
  863. break;
  864. }
  865. // allocate an MDL to describe this message.
  866. pMdl = IoAllocateMdl(
  867. pMessage,
  868. MessageSize,
  869. FALSE,
  870. FALSE,
  871. NULL);
  872. if (pMdl == NULL)
  873. {
  874. Status = NDIS_STATUS_RESOURCES;
  875. break;
  876. }
  877. MmBuildMdlForNonPagedPool(pMdl);
  878. // got the message buffer, now allocate a frame
  879. pMsgFrame = AllocateMsgFrame(pAdapter);
  880. if (pMsgFrame == NULL)
  881. {
  882. Status = NDIS_STATUS_RESOURCES;
  883. break;
  884. }
  885. // got everything, so fill in some frame things
  886. pMsgFrame->pMessageMdl = pMdl;
  887. pMessage->MessageLength = MessageSize;
  888. }
  889. while (FALSE);
  890. if (Status != NDIS_STATUS_SUCCESS)
  891. {
  892. if (pMdl)
  893. {
  894. IoFreeMdl(pMdl);
  895. }
  896. if (pMessage)
  897. {
  898. MemFree(pMessage, MessageSize);
  899. }
  900. }
  901. return pMsgFrame;
  902. } // AllocateMessageAndFrame
  903. /****************************************************************************/
  904. /* FreeAdapter */
  905. /****************************************************************************/
  906. /* */
  907. /* Routine Description: */
  908. /* */
  909. /* Free all memory allocations to do with an Adapter structure */
  910. /* */
  911. /* Arguments: */
  912. /* */
  913. /* pAdapter - pointer to the adapter to be freed. */
  914. /* */
  915. /* Return: */
  916. /* */
  917. /* VOID */
  918. /****************************************************************************/
  919. VOID
  920. FreeAdapter(IN PRNDISMP_ADAPTER Adapter)
  921. {
  922. // free up transport resources
  923. FreeTransportResources(Adapter);
  924. if (Adapter->DriverOIDList)
  925. {
  926. MemFree(Adapter->DriverOIDList, RndismpSupportedOidsNum*sizeof(NDIS_OID));
  927. }
  928. if (Adapter->FriendlyNameAnsi.Buffer)
  929. {
  930. MemFree(Adapter->FriendlyNameAnsi.Buffer, Adapter->FriendlyNameAnsi.MaximumLength);
  931. }
  932. if (Adapter->FriendlyNameUnicode.Buffer)
  933. {
  934. MemFree(Adapter->FriendlyNameUnicode.Buffer, Adapter->FriendlyNameUnicode.MaximumLength);
  935. }
  936. #if DBG
  937. if (Adapter->pSendLogBuffer)
  938. {
  939. MemFree(Adapter->pSendLogBuffer, Adapter->LogBufferSize);
  940. Adapter->pSendLogBuffer = NULL;
  941. }
  942. #endif // DBG
  943. MemFree(Adapter, sizeof(RNDISMP_ADAPTER));
  944. }
  945. /****************************************************************************/
  946. /* AllocateVc */
  947. /****************************************************************************/
  948. /* */
  949. /* Routine Description: */
  950. /* */
  951. /* Allocate a VC structure */
  952. /* */
  953. /* Arguments: */
  954. /* */
  955. /* pAdapter - adapter object */
  956. /* */
  957. /* Return: */
  958. /* */
  959. /* PRNDISMP_VC */
  960. /* */
  961. /****************************************************************************/
  962. PRNDISMP_VC
  963. AllocateVc(IN PRNDISMP_ADAPTER pAdapter)
  964. {
  965. PRNDISMP_VC pVc;
  966. NDIS_STATUS Status;
  967. Status = MemAlloc(&pVc, sizeof(RNDISMP_VC));
  968. if (Status == NDIS_STATUS_SUCCESS)
  969. {
  970. pVc->pAdapter = pAdapter;
  971. pVc->VcState = RNDISMP_VC_ALLOCATED;
  972. pVc->CallState = RNDISMP_CALL_IDLE;
  973. pVc->RefCount = 0;
  974. RNDISMP_INIT_LOCK(&pVc->Lock);
  975. EnterVcIntoHashTable(pAdapter, pVc);
  976. }
  977. else
  978. {
  979. pVc = NULL;
  980. }
  981. return pVc;
  982. }
  983. /****************************************************************************/
  984. /* DeallocateVc */
  985. /****************************************************************************/
  986. /* */
  987. /* Routine Description: */
  988. /* */
  989. /* Deallocate a VC structure. */
  990. /* */
  991. /* Arguments: */
  992. /* */
  993. /* pVc - Pointer to VC being deallocated. */
  994. /* */
  995. /* Return: */
  996. /* */
  997. /* VOID */
  998. /* */
  999. /****************************************************************************/
  1000. VOID
  1001. DeallocateVc(IN PRNDISMP_VC pVc)
  1002. {
  1003. ASSERT(pVc->RefCount == 0);
  1004. ASSERT(pVc->VcState == RNDISMP_VC_ALLOCATED);
  1005. RemoveVcFromHashTable(pVc->pAdapter, pVc);
  1006. MemFree(pVc, sizeof(RNDISMP_VC));
  1007. }
  1008. /****************************************************************************/
  1009. /* LookupVcId */
  1010. /****************************************************************************/
  1011. /* */
  1012. /* Routine Description: */
  1013. /* */
  1014. /* Search for a VC structure that matches a given VC Id. */
  1015. /* If we find the VC, we reference it and return it. */
  1016. /* */
  1017. /* Arguments: */
  1018. /* */
  1019. /* Adapter - adapter object */
  1020. /* VcId - Id to search for */
  1021. /* */
  1022. /* Notes: */
  1023. /* */
  1024. /* This routine is called with the adapter lock held! */
  1025. /* */
  1026. /* Return: */
  1027. /* */
  1028. /* PRNDISMP_VC - pointer to VC, if one exists */
  1029. /* */
  1030. /****************************************************************************/
  1031. PRNDISMP_VC
  1032. LookupVcId(IN PRNDISMP_ADAPTER pAdapter,
  1033. IN UINT32 VcId)
  1034. {
  1035. PLIST_ENTRY pVcEnt;
  1036. PRNDISMP_VC pVc;
  1037. ULONG VcIdHash;
  1038. PRNDISMP_VC_HASH_TABLE pVcHashTable;
  1039. BOOLEAN bFound = FALSE;
  1040. VcIdHash = RNDISMP_HASH_VCID(VcId);
  1041. pVcHashTable = pAdapter->pVcHashTable;
  1042. do
  1043. {
  1044. if (pVcHashTable == NULL)
  1045. {
  1046. pVc = NULL;
  1047. break;
  1048. }
  1049. for (pVcEnt = pVcHashTable->HashEntry[VcIdHash].Flink;
  1050. pVcEnt != &pVcHashTable->HashEntry[VcIdHash];
  1051. pVcEnt = pVcEnt->Flink)
  1052. {
  1053. pVc = CONTAINING_RECORD(pVcEnt, RNDISMP_VC, VcList);
  1054. if (pVc->VcId == VcId)
  1055. {
  1056. bFound = TRUE;
  1057. RNDISMP_REF_VC(pVc);
  1058. break;
  1059. }
  1060. }
  1061. if (!bFound)
  1062. {
  1063. pVc = NULL;
  1064. }
  1065. }
  1066. while (FALSE);
  1067. return pVc;
  1068. }
  1069. /****************************************************************************/
  1070. /* EnterVcIntoHashTable */
  1071. /****************************************************************************/
  1072. /* */
  1073. /* Routine Description: */
  1074. /* */
  1075. /* Link a VC into the hash table after assigning it a VC Id. */
  1076. /* */
  1077. /* Arguments: */
  1078. /* */
  1079. /* pAdapter - adapter object */
  1080. /* pVc - VC to link to the above adapter */
  1081. /* */
  1082. /* Return: */
  1083. /* */
  1084. /* VOID */
  1085. /* */
  1086. /****************************************************************************/
  1087. VOID
  1088. EnterVcIntoHashTable(IN PRNDISMP_ADAPTER pAdapter,
  1089. IN PRNDISMP_VC pVc)
  1090. {
  1091. PRNDISMP_VC pExistingVc;
  1092. PRNDISMP_VC_HASH_TABLE pVcHashTable;
  1093. UINT32 VcId;
  1094. ULONG VcIdHash;
  1095. RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
  1096. //
  1097. // We pick the next sequentially higher Vc Id value for this VC,
  1098. // but check to see if it is already in use...
  1099. //
  1100. do
  1101. {
  1102. pAdapter->LastVcId++;
  1103. // Never allocate the value 0.
  1104. if (pAdapter->LastVcId == 0)
  1105. {
  1106. pAdapter->LastVcId++;
  1107. }
  1108. VcId = pAdapter->LastVcId;
  1109. pExistingVc = LookupVcId(pAdapter, VcId);
  1110. }
  1111. while (pExistingVc != NULL);
  1112. pVcHashTable = pAdapter->pVcHashTable;
  1113. pVc->VcId = VcId;
  1114. VcIdHash = RNDISMP_HASH_VCID(VcId);
  1115. InsertTailList(&pVcHashTable->HashEntry[VcIdHash], &pVc->VcList);
  1116. pVcHashTable->NumEntries++;
  1117. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  1118. }
  1119. /****************************************************************************/
  1120. /* RemoveVcFromHashTable */
  1121. /****************************************************************************/
  1122. /* */
  1123. /* Routine Description: */
  1124. /* */
  1125. /* Unlink a VC from the adapter hash table. */
  1126. /* */
  1127. /* Arguments: */
  1128. /* */
  1129. /* pAdapter - adapter object */
  1130. /* pVc - VC to be unlinked. */
  1131. /* */
  1132. /* Return: */
  1133. /* */
  1134. /* VOID */
  1135. /* */
  1136. /****************************************************************************/
  1137. VOID
  1138. RemoveVcFromHashTable(IN PRNDISMP_ADAPTER pAdapter,
  1139. IN PRNDISMP_VC pVc)
  1140. {
  1141. RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
  1142. RemoveEntryList(&pVc->VcList);
  1143. pAdapter->pVcHashTable->NumEntries--;
  1144. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  1145. }