Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1404 lines
58 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 = RNDISMP_GET_MDL_ADDRESS(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 %p, message pending: last msg %d, cur %d\n",
  548. pAdapter, pAdapter->LastMessageFromDevice, CurrentTime));
  549. // indicate later from check for hang handler
  550. pAdapter->NeedReset = TRUE;
  551. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  552. RNDISMP_INCR_STAT(pAdapter, KeepAliveTimeout);
  553. break;
  554. }
  555. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  556. // too much time has elapsed, send down a keep alive message
  557. pMsgFrame = BuildRndisMessageCommon(pAdapter,
  558. NULL,
  559. REMOTE_NDIS_KEEPALIVE_MSG,
  560. 0,
  561. NULL,
  562. 0);
  563. if (pMsgFrame)
  564. {
  565. RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
  566. pAdapter->KeepAliveMessagePending = TRUE;
  567. pAdapter->KeepAliveMessagePendingId = pMsgFrame->RequestId;
  568. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  569. TRACE2(("Sending Keepalive(%d) on Adapter %p: last rcv %d, cur %d\n",
  570. pMsgFrame->RequestId, pAdapter, pAdapter->LastMessageFromDevice, CurrentTime ));
  571. // send the message to the microport
  572. RNDISMP_SEND_TO_MICROPORT(pAdapter, pMsgFrame, FALSE, CompleteSendKeepAlive);
  573. }
  574. }
  575. else
  576. {
  577. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  578. }
  579. }
  580. while (FALSE);
  581. // see if the timer was cancelled somewhere
  582. if (!pAdapter->TimerCancelled)
  583. {
  584. // restart timer
  585. NdisSetTimer(&pAdapter->KeepAliveTimer, KEEP_ALIVE_TIMER / 2);
  586. }
  587. } // KeepAliveTimerHandler
  588. /****************************************************************************/
  589. /* CompleteSendKeepAlive */
  590. /****************************************************************************/
  591. /* */
  592. /* Routine Description: */
  593. /* */
  594. /* Callback routine to handle completion of send by the microport, for */
  595. /* a keepalive message. */
  596. /* */
  597. /* Arguments: */
  598. /* */
  599. /* pMsgFrame - Pointer to message frame describing the message */
  600. /* SendStatus - Status returned by microport */
  601. /* */
  602. /* Return: */
  603. /* */
  604. /* VOID */
  605. /* */
  606. /****************************************************************************/
  607. VOID
  608. CompleteSendKeepAlive(IN PRNDISMP_MESSAGE_FRAME pMsgFrame,
  609. IN NDIS_STATUS SendStatus)
  610. {
  611. PRNDISMP_ADAPTER pAdapter;
  612. pAdapter = pMsgFrame->pAdapter;
  613. DereferenceMsgFrame(pMsgFrame);
  614. if (SendStatus != NDIS_STATUS_SUCCESS)
  615. {
  616. TRACE1(("KeepAlive send failure %x on Adapter %x\n",
  617. SendStatus, pAdapter));
  618. RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
  619. pAdapter->KeepAliveMessagePending = FALSE;
  620. pAdapter->NeedReset = FALSE;
  621. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  622. }
  623. } // CompleteSendKeepAlive
  624. /****************************************************************************/
  625. /* BuildRndisMessageCommon */
  626. /****************************************************************************/
  627. /* */
  628. /* Routine Description: */
  629. /* */
  630. /* Allocate resources for meesage and frame and build RNDIS message */
  631. /* */
  632. /* Arguments: */
  633. /* */
  634. /* pAdapter - adapter object */
  635. /* pVc - optionally, VC on which this message is sent. */
  636. /* NdisMessageType - RNDIS message type */
  637. /* Oid - the NDIS_OID to process. */
  638. /* InformationBuffer - Holds the data to be set. */
  639. /* InformationBufferLength - The length of InformationBuffer. */
  640. /* */
  641. /* Return: */
  642. /* */
  643. /* PRNDISMP_MESSAGE_FRAME */
  644. /* */
  645. /****************************************************************************/
  646. PRNDISMP_MESSAGE_FRAME
  647. BuildRndisMessageCommon(IN PRNDISMP_ADAPTER pAdapter,
  648. IN PRNDISMP_VC pVc OPTIONAL,
  649. IN UINT NdisMessageType,
  650. IN NDIS_OID Oid,
  651. IN PVOID InformationBuffer,
  652. IN ULONG InformationBufferLength)
  653. {
  654. PRNDIS_MESSAGE pMessage;
  655. UINT MessageSize;
  656. PRNDISMP_MESSAGE_FRAME pMsgFrame;
  657. TRACE2(("BuildRndisMessageCommon\n"));
  658. pMsgFrame = NULL;
  659. switch(NdisMessageType)
  660. {
  661. case REMOTE_NDIS_INITIALIZE_MSG:
  662. {
  663. PRNDIS_INITIALIZE_REQUEST pInitRequest;
  664. MessageSize = RNDIS_MESSAGE_SIZE(RNDIS_INITIALIZE_REQUEST);
  665. // get a message and request frame
  666. pMsgFrame = AllocateMessageAndFrame(pAdapter,
  667. MessageSize);
  668. if (pMsgFrame == NULL)
  669. {
  670. break;
  671. }
  672. pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame);
  673. pMessage->NdisMessageType = NdisMessageType;
  674. pMsgFrame->NdisMessageType = NdisMessageType;
  675. TRACE1(("RNDISMP: Init Req message %x, Type %d, Length %d, MaxRcv %d\n",
  676. pMessage, pMessage->NdisMessageType, pMessage->MessageLength, pAdapter->MaxReceiveSize));
  677. pInitRequest = &pMessage->Message.InitializeRequest;
  678. pInitRequest->RequestId = pMsgFrame->RequestId;
  679. pInitRequest->MajorVersion = RNDIS_MAJOR_VERSION;
  680. pInitRequest->MinorVersion = RNDIS_MINOR_VERSION;
  681. pInitRequest->MaxTransferSize = pAdapter->MaxReceiveSize;
  682. break;
  683. }
  684. case REMOTE_NDIS_HALT_MSG:
  685. {
  686. PRNDIS_HALT_REQUEST pHaltRequest;
  687. MessageSize = RNDIS_MESSAGE_SIZE(RNDIS_HALT_REQUEST);
  688. // get a message and request frame
  689. pMsgFrame = AllocateMessageAndFrame(pAdapter,
  690. MessageSize);
  691. if (pMsgFrame == NULL)
  692. {
  693. break;
  694. }
  695. pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame);
  696. pMessage->NdisMessageType = NdisMessageType;
  697. pMsgFrame->NdisMessageType = NdisMessageType;
  698. pHaltRequest = &pMessage->Message.HaltRequest;
  699. pHaltRequest->RequestId = pMsgFrame->RequestId;
  700. break;
  701. }
  702. case REMOTE_NDIS_QUERY_MSG:
  703. {
  704. PRNDIS_QUERY_REQUEST pQueryRequest;
  705. MessageSize = RNDIS_MESSAGE_SIZE(RNDIS_QUERY_REQUEST) + InformationBufferLength;
  706. // get a message and request frame
  707. pMsgFrame = AllocateMessageAndFrame(pAdapter,
  708. MessageSize);
  709. if (pMsgFrame == NULL)
  710. {
  711. break;
  712. }
  713. pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame);
  714. pMessage->NdisMessageType = NdisMessageType;
  715. pMsgFrame->NdisMessageType = NdisMessageType;
  716. pQueryRequest = &pMessage->Message.QueryRequest;
  717. pQueryRequest->RequestId = pMsgFrame->RequestId;
  718. pQueryRequest->Oid = Oid;
  719. pQueryRequest->InformationBufferLength = InformationBufferLength;
  720. pQueryRequest->InformationBufferOffset = sizeof(RNDIS_QUERY_REQUEST);
  721. if (pVc == NULL)
  722. {
  723. pQueryRequest->DeviceVcHandle = NULL_DEVICE_CONTEXT;
  724. }
  725. else
  726. {
  727. pQueryRequest->DeviceVcHandle = pVc->DeviceVcContext;
  728. }
  729. TRACE2(("Query OID %x, Len %d, RequestId %08X\n",
  730. Oid, InformationBufferLength, pQueryRequest->RequestId));
  731. // copy information buffer
  732. RNDISMP_MOVE_MEM(RNDISMP_GET_INFO_BUFFER_FROM_QUERY_MSG(pQueryRequest),
  733. InformationBuffer,
  734. InformationBufferLength);
  735. break;
  736. }
  737. case REMOTE_NDIS_SET_MSG:
  738. {
  739. PRNDIS_SET_REQUEST pSetRequest;
  740. MessageSize = RNDIS_MESSAGE_SIZE(RNDIS_SET_REQUEST) + InformationBufferLength;
  741. // get a message and request frame
  742. pMsgFrame = AllocateMessageAndFrame(pAdapter,
  743. MessageSize);
  744. if (pMsgFrame == NULL)
  745. {
  746. break;
  747. }
  748. pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame);
  749. pMessage->NdisMessageType = NdisMessageType;
  750. pMsgFrame->NdisMessageType = NdisMessageType;
  751. pSetRequest = &pMessage->Message.SetRequest;
  752. pSetRequest->RequestId = pMsgFrame->RequestId;
  753. pSetRequest->Oid = Oid;
  754. pSetRequest->InformationBufferLength = InformationBufferLength;
  755. pSetRequest->InformationBufferOffset = sizeof(RNDIS_SET_REQUEST);
  756. if (pVc == NULL)
  757. {
  758. pSetRequest->DeviceVcHandle = NULL_DEVICE_CONTEXT;
  759. }
  760. else
  761. {
  762. pSetRequest->DeviceVcHandle = pVc->DeviceVcContext;
  763. }
  764. // copy information buffer
  765. RNDISMP_MOVE_MEM(RNDISMP_GET_INFO_BUFFER_FROM_QUERY_MSG(pSetRequest),
  766. InformationBuffer,
  767. InformationBufferLength);
  768. break;
  769. }
  770. case REMOTE_NDIS_RESET_MSG:
  771. {
  772. PRNDIS_RESET_REQUEST pResetRequest;
  773. MessageSize = RNDIS_MESSAGE_SIZE(RNDIS_RESET_REQUEST);
  774. // get a message and request frame
  775. pMsgFrame = AllocateMessageAndFrame(pAdapter,
  776. MessageSize);
  777. if (pMsgFrame == NULL)
  778. {
  779. break;
  780. }
  781. pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame);
  782. pMessage->NdisMessageType = NdisMessageType;
  783. pMsgFrame->NdisMessageType = NdisMessageType;
  784. pResetRequest = &pMessage->Message.ResetRequest;
  785. pResetRequest->Reserved = 0;
  786. break;
  787. }
  788. case REMOTE_NDIS_KEEPALIVE_MSG:
  789. {
  790. PRNDIS_KEEPALIVE_REQUEST pKeepAliveRequest;
  791. MessageSize = RNDIS_MESSAGE_SIZE(RNDIS_KEEPALIVE_REQUEST);
  792. // get a message and request frame
  793. pMsgFrame = AllocateMessageAndFrame(pAdapter,
  794. MessageSize);
  795. if (pMsgFrame == NULL)
  796. {
  797. break;
  798. }
  799. pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame);
  800. pMessage->NdisMessageType = NdisMessageType;
  801. pMsgFrame->NdisMessageType = NdisMessageType;
  802. pKeepAliveRequest = &pMessage->Message.KeepaliveRequest;
  803. pKeepAliveRequest->RequestId = pMsgFrame->RequestId;
  804. break;
  805. }
  806. case REMOTE_NDIS_KEEPALIVE_CMPLT:
  807. {
  808. PRNDIS_KEEPALIVE_COMPLETE pKeepAliveComplete;
  809. MessageSize = RNDIS_MESSAGE_SIZE(RNDIS_KEEPALIVE_COMPLETE);
  810. // get a message and request frame
  811. pMsgFrame = AllocateMessageAndFrame(pAdapter,
  812. MessageSize);
  813. if (pMsgFrame == NULL)
  814. {
  815. break;
  816. }
  817. pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame);
  818. pMessage->NdisMessageType = NdisMessageType;
  819. pMsgFrame->NdisMessageType = NdisMessageType;
  820. pKeepAliveComplete = &pMessage->Message.KeepaliveComplete;
  821. pKeepAliveComplete->RequestId = *(RNDIS_REQUEST_ID *)InformationBuffer;
  822. pKeepAliveComplete->Status = NDIS_STATUS_SUCCESS;
  823. break;
  824. }
  825. default:
  826. TRACE2(("Invalid NdisMessageType (%08X)\n", NdisMessageType));
  827. ASSERT(FALSE);
  828. break;
  829. }
  830. return pMsgFrame;
  831. } // BuildRndisMessageCommon
  832. /****************************************************************************/
  833. /* AllocateMessageAndFrame */
  834. /****************************************************************************/
  835. /* */
  836. /* Routine Description: */
  837. /* */
  838. /* Allocate a message and frame for an RNDIS message */
  839. /* */
  840. /* Arguments: */
  841. /* */
  842. /* pAdapter - pAdapter object */
  843. /* MessageSize - size of RNDIS message */
  844. /* */
  845. /* Return: */
  846. /* */
  847. /* PRNDISMP_MESSAGE_FRAME */
  848. /* */
  849. /****************************************************************************/
  850. PRNDISMP_MESSAGE_FRAME
  851. AllocateMessageAndFrame(IN PRNDISMP_ADAPTER pAdapter,
  852. IN UINT MessageSize)
  853. {
  854. PRNDIS_MESSAGE pMessage = NULL;
  855. PRNDISMP_MESSAGE_FRAME pMsgFrame = NULL;
  856. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  857. PMDL pMdl = NULL;
  858. TRACE3(("AllocateMessageAndFrame\n"));
  859. do
  860. {
  861. // allocate a buffer for RNDIS message
  862. Status = MemAlloc(&pMessage, MessageSize);
  863. // see if we got our buffer
  864. if (Status != NDIS_STATUS_SUCCESS)
  865. {
  866. break;
  867. }
  868. // allocate an MDL to describe this message.
  869. pMdl = IoAllocateMdl(
  870. pMessage,
  871. MessageSize,
  872. FALSE,
  873. FALSE,
  874. NULL);
  875. if (pMdl == NULL)
  876. {
  877. Status = NDIS_STATUS_RESOURCES;
  878. break;
  879. }
  880. MmBuildMdlForNonPagedPool(pMdl);
  881. // got the message buffer, now allocate a frame
  882. pMsgFrame = AllocateMsgFrame(pAdapter);
  883. if (pMsgFrame == NULL)
  884. {
  885. Status = NDIS_STATUS_RESOURCES;
  886. break;
  887. }
  888. // got everything, so fill in some frame things
  889. pMsgFrame->pMessageMdl = pMdl;
  890. pMessage->MessageLength = MessageSize;
  891. }
  892. while (FALSE);
  893. if (Status != NDIS_STATUS_SUCCESS)
  894. {
  895. if (pMdl)
  896. {
  897. IoFreeMdl(pMdl);
  898. }
  899. if (pMessage)
  900. {
  901. MemFree(pMessage, MessageSize);
  902. }
  903. }
  904. return pMsgFrame;
  905. } // AllocateMessageAndFrame
  906. /****************************************************************************/
  907. /* FreeAdapter */
  908. /****************************************************************************/
  909. /* */
  910. /* Routine Description: */
  911. /* */
  912. /* Free all memory allocations to do with an Adapter structure */
  913. /* */
  914. /* Arguments: */
  915. /* */
  916. /* pAdapter - pointer to the adapter to be freed. */
  917. /* */
  918. /* Return: */
  919. /* */
  920. /* VOID */
  921. /****************************************************************************/
  922. VOID
  923. FreeAdapter(IN PRNDISMP_ADAPTER Adapter)
  924. {
  925. // free up transport resources
  926. FreeTransportResources(Adapter);
  927. if (Adapter->DriverOIDList)
  928. {
  929. MemFree(Adapter->DriverOIDList, RndismpSupportedOidsNum*sizeof(NDIS_OID));
  930. }
  931. if (Adapter->FriendlyNameAnsi.Buffer)
  932. {
  933. MemFree(Adapter->FriendlyNameAnsi.Buffer, Adapter->FriendlyNameAnsi.MaximumLength);
  934. }
  935. if (Adapter->FriendlyNameUnicode.Buffer)
  936. {
  937. MemFree(Adapter->FriendlyNameUnicode.Buffer, Adapter->FriendlyNameUnicode.MaximumLength);
  938. }
  939. #if DBG
  940. if (Adapter->pSendLogBuffer)
  941. {
  942. MemFree(Adapter->pSendLogBuffer, Adapter->LogBufferSize);
  943. Adapter->pSendLogBuffer = NULL;
  944. }
  945. #endif // DBG
  946. MemFree(Adapter, sizeof(RNDISMP_ADAPTER));
  947. }
  948. /****************************************************************************/
  949. /* AllocateVc */
  950. /****************************************************************************/
  951. /* */
  952. /* Routine Description: */
  953. /* */
  954. /* Allocate a VC structure */
  955. /* */
  956. /* Arguments: */
  957. /* */
  958. /* pAdapter - adapter object */
  959. /* */
  960. /* Return: */
  961. /* */
  962. /* PRNDISMP_VC */
  963. /* */
  964. /****************************************************************************/
  965. PRNDISMP_VC
  966. AllocateVc(IN PRNDISMP_ADAPTER pAdapter)
  967. {
  968. PRNDISMP_VC pVc;
  969. NDIS_STATUS Status;
  970. Status = MemAlloc(&pVc, sizeof(RNDISMP_VC));
  971. if (Status == NDIS_STATUS_SUCCESS)
  972. {
  973. pVc->pAdapter = pAdapter;
  974. pVc->VcState = RNDISMP_VC_ALLOCATED;
  975. pVc->CallState = RNDISMP_CALL_IDLE;
  976. pVc->RefCount = 0;
  977. RNDISMP_INIT_LOCK(&pVc->Lock);
  978. EnterVcIntoHashTable(pAdapter, pVc);
  979. }
  980. else
  981. {
  982. pVc = NULL;
  983. }
  984. return pVc;
  985. }
  986. /****************************************************************************/
  987. /* DeallocateVc */
  988. /****************************************************************************/
  989. /* */
  990. /* Routine Description: */
  991. /* */
  992. /* Deallocate a VC structure. */
  993. /* */
  994. /* Arguments: */
  995. /* */
  996. /* pVc - Pointer to VC being deallocated. */
  997. /* */
  998. /* Return: */
  999. /* */
  1000. /* VOID */
  1001. /* */
  1002. /****************************************************************************/
  1003. VOID
  1004. DeallocateVc(IN PRNDISMP_VC pVc)
  1005. {
  1006. ASSERT(pVc->RefCount == 0);
  1007. ASSERT(pVc->VcState == RNDISMP_VC_ALLOCATED);
  1008. RemoveVcFromHashTable(pVc->pAdapter, pVc);
  1009. MemFree(pVc, sizeof(RNDISMP_VC));
  1010. }
  1011. /****************************************************************************/
  1012. /* LookupVcId */
  1013. /****************************************************************************/
  1014. /* */
  1015. /* Routine Description: */
  1016. /* */
  1017. /* Search for a VC structure that matches a given VC Id. */
  1018. /* If we find the VC, we reference it and return it. */
  1019. /* */
  1020. /* Arguments: */
  1021. /* */
  1022. /* Adapter - adapter object */
  1023. /* VcId - Id to search for */
  1024. /* */
  1025. /* Notes: */
  1026. /* */
  1027. /* This routine is called with the adapter lock held! */
  1028. /* */
  1029. /* Return: */
  1030. /* */
  1031. /* PRNDISMP_VC - pointer to VC, if one exists */
  1032. /* */
  1033. /****************************************************************************/
  1034. PRNDISMP_VC
  1035. LookupVcId(IN PRNDISMP_ADAPTER pAdapter,
  1036. IN UINT32 VcId)
  1037. {
  1038. PLIST_ENTRY pVcEnt;
  1039. PRNDISMP_VC pVc;
  1040. ULONG VcIdHash;
  1041. PRNDISMP_VC_HASH_TABLE pVcHashTable;
  1042. BOOLEAN bFound = FALSE;
  1043. VcIdHash = RNDISMP_HASH_VCID(VcId);
  1044. pVcHashTable = pAdapter->pVcHashTable;
  1045. do
  1046. {
  1047. if (pVcHashTable == NULL)
  1048. {
  1049. pVc = NULL;
  1050. break;
  1051. }
  1052. for (pVcEnt = pVcHashTable->HashEntry[VcIdHash].Flink;
  1053. pVcEnt != &pVcHashTable->HashEntry[VcIdHash];
  1054. pVcEnt = pVcEnt->Flink)
  1055. {
  1056. pVc = CONTAINING_RECORD(pVcEnt, RNDISMP_VC, VcList);
  1057. if (pVc->VcId == VcId)
  1058. {
  1059. bFound = TRUE;
  1060. RNDISMP_REF_VC(pVc);
  1061. break;
  1062. }
  1063. }
  1064. if (!bFound)
  1065. {
  1066. pVc = NULL;
  1067. }
  1068. }
  1069. while (FALSE);
  1070. return pVc;
  1071. }
  1072. /****************************************************************************/
  1073. /* EnterVcIntoHashTable */
  1074. /****************************************************************************/
  1075. /* */
  1076. /* Routine Description: */
  1077. /* */
  1078. /* Link a VC into the hash table after assigning it a VC Id. */
  1079. /* */
  1080. /* Arguments: */
  1081. /* */
  1082. /* pAdapter - adapter object */
  1083. /* pVc - VC to link to the above adapter */
  1084. /* */
  1085. /* Return: */
  1086. /* */
  1087. /* VOID */
  1088. /* */
  1089. /****************************************************************************/
  1090. VOID
  1091. EnterVcIntoHashTable(IN PRNDISMP_ADAPTER pAdapter,
  1092. IN PRNDISMP_VC pVc)
  1093. {
  1094. PRNDISMP_VC pExistingVc;
  1095. PRNDISMP_VC_HASH_TABLE pVcHashTable;
  1096. UINT32 VcId;
  1097. ULONG VcIdHash;
  1098. RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
  1099. //
  1100. // We pick the next sequentially higher Vc Id value for this VC,
  1101. // but check to see if it is already in use...
  1102. //
  1103. do
  1104. {
  1105. pAdapter->LastVcId++;
  1106. // Never allocate the value 0.
  1107. if (pAdapter->LastVcId == 0)
  1108. {
  1109. pAdapter->LastVcId++;
  1110. }
  1111. VcId = pAdapter->LastVcId;
  1112. pExistingVc = LookupVcId(pAdapter, VcId);
  1113. }
  1114. while (pExistingVc != NULL);
  1115. pVcHashTable = pAdapter->pVcHashTable;
  1116. pVc->VcId = VcId;
  1117. VcIdHash = RNDISMP_HASH_VCID(VcId);
  1118. InsertTailList(&pVcHashTable->HashEntry[VcIdHash], &pVc->VcList);
  1119. pVcHashTable->NumEntries++;
  1120. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  1121. }
  1122. /****************************************************************************/
  1123. /* RemoveVcFromHashTable */
  1124. /****************************************************************************/
  1125. /* */
  1126. /* Routine Description: */
  1127. /* */
  1128. /* Unlink a VC from the adapter hash table. */
  1129. /* */
  1130. /* Arguments: */
  1131. /* */
  1132. /* pAdapter - adapter object */
  1133. /* pVc - VC to be unlinked. */
  1134. /* */
  1135. /* Return: */
  1136. /* */
  1137. /* VOID */
  1138. /* */
  1139. /****************************************************************************/
  1140. VOID
  1141. RemoveVcFromHashTable(IN PRNDISMP_ADAPTER pAdapter,
  1142. IN PRNDISMP_VC pVc)
  1143. {
  1144. RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
  1145. RemoveEntryList(&pVc->VcList);
  1146. pAdapter->pVcHashTable->NumEntries--;
  1147. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  1148. }