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.

2781 lines
116 KiB

  1. /***************************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. RNDISMP.C
  5. Abstract:
  6. Remote NDIS Miniport driver. Sits on top of Remote NDIS bus specific
  7. layers.
  8. Environment:
  9. kernel mode only
  10. Notes:
  11. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  12. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  13. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  14. PURPOSE.
  15. Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
  16. Revision History:
  17. 5/6/99 : created
  18. Author:
  19. Tom Green
  20. ****************************************************************************/
  21. #include "precomp.h"
  22. //
  23. // miniport driver block list (miniport layer may support several microports)
  24. //
  25. DRIVER_BLOCK RndismpMiniportBlockListHead = {0};
  26. UINT RndismpNumMicroports = 0;
  27. NDIS_SPIN_LOCK RndismpGlobalLock;
  28. ULONG RndisForceReset = FALSE;
  29. #ifdef TESTING
  30. UCHAR OffloadBuffer[sizeof(NDIS_TASK_OFFLOAD_HEADER) +
  31. sizeof(NDIS_TASK_OFFLOAD) +
  32. sizeof(NDIS_TASK_TCP_IP_CHECKSUM)];
  33. PUCHAR pOffloadBuffer = OffloadBuffer;
  34. ULONG OffloadSize = sizeof(OffloadBuffer);
  35. #endif
  36. #ifdef RAW_ENCAP
  37. ULONG gRawEncap = TRUE;
  38. #else
  39. ULONG gRawEncap = FALSE;
  40. #endif
  41. //
  42. // A list of NDIS versions we cycle through, trying to register the
  43. // highest version we can with NDIS. This is so that we can run on
  44. // earlier platforms.
  45. //
  46. // To support a newer version, add an entry at the TOP of the list.
  47. //
  48. struct _RNDISMP_NDIS_VERSION_TABLE
  49. {
  50. UCHAR MajorVersion;
  51. UCHAR MinorVersion;
  52. ULONG CharsSize;
  53. } RndismpNdisVersionTable[] =
  54. {
  55. #ifdef NDIS51_MINIPORT
  56. {5, 1, sizeof(NDIS51_MINIPORT_CHARACTERISTICS)},
  57. #endif
  58. {5, 0, sizeof(NDIS50_MINIPORT_CHARACTERISTICS)}
  59. };
  60. ULONG RndismpNdisVersions = sizeof(RndismpNdisVersionTable) /
  61. sizeof(struct _RNDISMP_NDIS_VERSION_TABLE);
  62. /****************************************************************************/
  63. /* DriverEntry */
  64. /****************************************************************************/
  65. /* */
  66. /* Routine Description: */
  67. /* */
  68. /* Driver entry routine. Never called, Microport driver entry is used */
  69. /* */
  70. /****************************************************************************/
  71. NTSTATUS
  72. DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
  73. {
  74. // this is never called. Driver entry in Microport is entry.
  75. TRACE1(("DriverEntry\n"));
  76. return NDIS_STATUS_SUCCESS;
  77. } // DriverEntry
  78. /****************************************************************************/
  79. /* RndisMInitializeWrapper */
  80. /****************************************************************************/
  81. /* */
  82. /* Routine Description: */
  83. /* */
  84. /* RndisMInitializeWrapper is called from the microport to init driver */
  85. /* */
  86. /* Arguments: */
  87. /* */
  88. /* pNdisWrapperHandle - Pass NDIS wrapper handle back to microport */
  89. /* MicroportContext - Microport "Global" context */
  90. /* DriverObject - Driver object */
  91. /* RegistryPath - Registry path */
  92. /* pCharacteristics - Characteristics of RNDIS microport */
  93. /* */
  94. /* Return Value: */
  95. /* */
  96. /* NDIS_STATUS_SUCCESS */
  97. /* NDIS_STATUS_PENDING */
  98. /* */
  99. /****************************************************************************/
  100. NDIS_STATUS
  101. RndisMInitializeWrapper(OUT PNDIS_HANDLE pNdisWrapperHandle,
  102. IN PVOID MicroportContext,
  103. IN PVOID DriverObject,
  104. IN PVOID RegistryPath,
  105. IN PRNDIS_MICROPORT_CHARACTERISTICS pCharacteristics)
  106. {
  107. // Receives the status of the NdisMRegisterMiniport operation.
  108. NDIS_STATUS Status;
  109. // Characteristics table for this driver
  110. NDIS_MINIPORT_CHARACTERISTICS RndismpChar;
  111. // Pointer to the global information for this driver
  112. PDRIVER_BLOCK NewDriver;
  113. // Handle for referring to the wrapper about this driver.
  114. NDIS_HANDLE NdisWrapperHandle;
  115. ULONG i;
  116. TRACE3(("RndisMInitializeWrapper\n"));
  117. // allocate the driver block object, exit if error occurs
  118. Status = MemAlloc(&NewDriver, sizeof(DRIVER_BLOCK));
  119. if(Status != NDIS_STATUS_SUCCESS)
  120. {
  121. TRACE2(("Block Allocate Memory failed (%08X)\n", Status));
  122. return Status;
  123. }
  124. // Initialize the wrapper.
  125. NdisMInitializeWrapper(&NdisWrapperHandle,
  126. (PDRIVER_OBJECT)DriverObject,
  127. RegistryPath,
  128. NULL);
  129. // Save the global information about this driver.
  130. NewDriver->NdisWrapperHandle = NdisWrapperHandle;
  131. NewDriver->AdapterList = (PRNDISMP_ADAPTER) NULL;
  132. NewDriver->DriverObject = DriverObject;
  133. NewDriver->Signature = BLOCK_SIGNATURE;
  134. // get handlers passed in from microport
  135. NewDriver->RmInitializeHandler = pCharacteristics->RmInitializeHandler;
  136. NewDriver->RmInitCompleteNotifyHandler = pCharacteristics->RmInitCompleteNotifyHandler;
  137. NewDriver->RmHaltHandler = pCharacteristics->RmHaltHandler;
  138. NewDriver->RmShutdownHandler = pCharacteristics->RmShutdownHandler;
  139. NewDriver->RmUnloadHandler = pCharacteristics->RmUnloadHandler;
  140. NewDriver->RmSendMessageHandler = pCharacteristics->RmSendMessageHandler;
  141. NewDriver->RmReturnMessageHandler = pCharacteristics->RmReturnMessageHandler;
  142. // save microport "Global" context
  143. NewDriver->MicroportContext = MicroportContext;
  144. // pass the microport the wrapper handle
  145. *pNdisWrapperHandle = (NDIS_HANDLE) NdisWrapperHandle;
  146. // initialize the Miniport characteristics for the call to NdisMRegisterMiniport.
  147. NdisZeroMemory(&RndismpChar, sizeof(RndismpChar));
  148. RndismpChar.HaltHandler = RndismpHalt;
  149. RndismpChar.InitializeHandler = RndismpInitialize;
  150. RndismpChar.QueryInformationHandler = RndismpQueryInformation;
  151. RndismpChar.ReconfigureHandler = RndismpReconfigure;
  152. RndismpChar.ResetHandler = RndismpReset;
  153. RndismpChar.SendPacketsHandler = RndismpMultipleSend;
  154. RndismpChar.SetInformationHandler = RndismpSetInformation;
  155. RndismpChar.ReturnPacketHandler = RndismpReturnPacket;
  156. RndismpChar.CheckForHangHandler = RndismpCheckForHang;
  157. RndismpChar.DisableInterruptHandler = NULL;
  158. RndismpChar.EnableInterruptHandler = NULL;
  159. RndismpChar.HandleInterruptHandler = NULL;
  160. RndismpChar.ISRHandler = NULL;
  161. RndismpChar.SendHandler = NULL;
  162. RndismpChar.TransferDataHandler = NULL;
  163. #if CO_RNDIS
  164. RndismpChar.CoSendPacketsHandler = RndismpCoSendPackets;
  165. RndismpChar.CoCreateVcHandler = RndismpCoCreateVc;
  166. RndismpChar.CoDeleteVcHandler = RndismpCoDeleteVc;
  167. RndismpChar.CoActivateVcHandler = RndismpCoActivateVc;
  168. RndismpChar.CoDeactivateVcHandler = RndismpCoDeactivateVc;
  169. RndismpChar.CoRequestHandler = RndismpCoRequest;
  170. #endif // CO_RNDIS
  171. #ifdef NDIS51_MINIPORT
  172. RndismpChar.PnPEventNotifyHandler = RndismpPnPEventNotify;
  173. RndismpChar.AdapterShutdownHandler = RndismpShutdownHandler;
  174. #endif
  175. for (i = 0; i < RndismpNdisVersions; i++)
  176. {
  177. RndismpChar.MajorNdisVersion = RndismpNdisVersionTable[i].MajorVersion;
  178. RndismpChar.MinorNdisVersion = RndismpNdisVersionTable[i].MinorVersion;
  179. Status = NdisMRegisterMiniport(NdisWrapperHandle,
  180. &RndismpChar,
  181. RndismpNdisVersionTable[i].CharsSize);
  182. if (Status == NDIS_STATUS_SUCCESS)
  183. {
  184. TRACE1(("InitializeWrapper: successfully registered as a %d.%d miniport\n",
  185. RndismpNdisVersionTable[i].MajorVersion,
  186. RndismpNdisVersionTable[i].MinorVersion));
  187. NewDriver->MajorNdisVersion = RndismpNdisVersionTable[i].MajorVersion;
  188. NewDriver->MinorNdisVersion = RndismpNdisVersionTable[i].MinorVersion;
  189. break;
  190. }
  191. }
  192. if(Status != NDIS_STATUS_SUCCESS)
  193. {
  194. Status = STATUS_UNSUCCESSFUL;
  195. // free up memory allocated for block
  196. MemFree(NewDriver, sizeof(DRIVER_BLOCK));
  197. }
  198. else
  199. {
  200. // everything went fine, so add the driver block to the list
  201. AddDriverBlock(&RndismpMiniportBlockListHead, NewDriver);
  202. #ifndef BUILD_WIN9X
  203. // if we are running on a platform < NDIS 5.1, attempt to support
  204. // surprise removal.
  205. HookPnpDispatchRoutine(NewDriver);
  206. #endif
  207. #ifndef BUILD_WIN9X
  208. // Not supported on Win98 Gold:
  209. NdisMRegisterUnloadHandler(NdisWrapperHandle, RndismpUnload);
  210. #endif
  211. }
  212. return (NDIS_STATUS) Status;
  213. } // RndisMInitializeWrapper
  214. /****************************************************************************/
  215. /* RndismpUnload */
  216. /****************************************************************************/
  217. /* */
  218. /* Routine Description: */
  219. /* */
  220. /* Called by NDIS when this driver is unloaded. */
  221. /* */
  222. /* Arguments: */
  223. /* */
  224. /* pDriverObject - Pointer to driver object. */
  225. /* */
  226. /* Return: */
  227. /* */
  228. /* VOID */
  229. /* */
  230. /****************************************************************************/
  231. VOID
  232. RndismpUnload(IN PDRIVER_OBJECT pDriverObject)
  233. {
  234. PDRIVER_BLOCK DriverBlock;
  235. // Find our Driver block for this driver object.
  236. DriverBlock = DriverObjectToDriverBlock(&RndismpMiniportBlockListHead, pDriverObject);
  237. TRACE1(("RndismpUnload: DriverObj %x, DriverBlock %x\n", pDriverObject, DriverBlock));
  238. if (DriverBlock)
  239. {
  240. if (DriverBlock->RmUnloadHandler)
  241. {
  242. (DriverBlock->RmUnloadHandler)(DriverBlock->MicroportContext);
  243. }
  244. RemoveDriverBlock(&RndismpMiniportBlockListHead, DriverBlock);
  245. MemFree(DriverBlock, sizeof(*DriverBlock));
  246. }
  247. TRACE1(("RndismpUnload: Done\n"));
  248. }
  249. #ifndef BUILD_WIN9X
  250. /****************************************************************************/
  251. /* DllInitialize */
  252. /****************************************************************************/
  253. /* */
  254. /* Routine Description: */
  255. /* */
  256. /* Called by the system when this driver is loaded. */
  257. /* */
  258. /* Arguments: */
  259. /* */
  260. /* pRegistryPath - Pointer to registry path for this service. */
  261. /* */
  262. /* Return: */
  263. /* */
  264. /* NTSTATUS - success always */
  265. /* */
  266. /****************************************************************************/
  267. NTSTATUS
  268. DllInitialize(IN PUNICODE_STRING pRegistryPath)
  269. {
  270. #if DBG
  271. DbgPrint("RNDISMP: RndismpDebugFlags set to %x, &RndismpDebugFlags is %p\n",
  272. RndismpDebugFlags, &RndismpDebugFlags);
  273. #endif
  274. TRACE1(("DllInitialize\n"));
  275. #ifdef TESTING
  276. {
  277. PNDIS_TASK_OFFLOAD_HEADER pOffloadHdr = (PNDIS_TASK_OFFLOAD_HEADER)pOffloadBuffer;
  278. PNDIS_TASK_OFFLOAD pTask;
  279. PNDIS_TASK_TCP_IP_CHECKSUM pChksum;
  280. pOffloadHdr->Version = NDIS_TASK_OFFLOAD_VERSION;
  281. pOffloadHdr->Size = sizeof(NDIS_TASK_OFFLOAD_HEADER);
  282. pOffloadHdr->EncapsulationFormat.Encapsulation = IEEE_802_3_Encapsulation;
  283. pOffloadHdr->EncapsulationFormat.EncapsulationHeaderSize = 0; // ?
  284. pOffloadHdr->EncapsulationFormat.Flags.FixedHeaderSize = 0;
  285. pOffloadHdr->OffsetFirstTask = sizeof(NDIS_TASK_OFFLOAD_HEADER);
  286. pTask = (PNDIS_TASK_OFFLOAD)(pOffloadHdr + 1);
  287. pTask->Version = NDIS_TASK_OFFLOAD_VERSION;
  288. pTask->Size = sizeof(NDIS_TASK_OFFLOAD);
  289. pTask->Task = TcpIpChecksumNdisTask;
  290. pTask->OffsetNextTask = 0;
  291. pTask->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
  292. pChksum = (PNDIS_TASK_TCP_IP_CHECKSUM)&pTask->TaskBuffer[0];
  293. *(PULONG)pChksum = 0;
  294. pChksum->V4Transmit.TcpChecksum = 1;
  295. pChksum->V4Transmit.UdpChecksum = 1;
  296. }
  297. #endif
  298. return STATUS_SUCCESS;
  299. }
  300. #endif // !BUILD_WIN9X
  301. /****************************************************************************/
  302. /* DllUnload */
  303. /****************************************************************************/
  304. /* */
  305. /* Routine Description: */
  306. /* */
  307. /* Called by the system when this driver is unloaded. */
  308. /* */
  309. /* Arguments: */
  310. /* */
  311. /* None */
  312. /* */
  313. /* Return: */
  314. /* */
  315. /* NTSTATUS - success always */
  316. /* */
  317. /****************************************************************************/
  318. NTSTATUS
  319. DllUnload(VOID)
  320. {
  321. #if DBG
  322. DbgPrint("RNDISMP: DllUnload called!\n");
  323. #endif
  324. return STATUS_SUCCESS;
  325. }
  326. /****************************************************************************/
  327. /* RndismpHalt */
  328. /****************************************************************************/
  329. /* */
  330. /* Routine Description: */
  331. /* */
  332. /* Stop the adapter and release resources */
  333. /* */
  334. /* Arguments: */
  335. /* */
  336. /* MiniportAdapterContext - a context version of our Adapter pointer */
  337. /* */
  338. /* Return: */
  339. /* */
  340. /* VOID */
  341. /* */
  342. /****************************************************************************/
  343. VOID
  344. RndismpHalt(IN NDIS_HANDLE MiniportAdapterContext)
  345. {
  346. #ifdef BUILD_WIN9X
  347. //
  348. // On Win98/SE, we would have intercepted the config mgr handler.
  349. // Put it back the way it was.
  350. //
  351. UnHookNtKernCMHandler((PRNDISMP_ADAPTER)MiniportAdapterContext);
  352. #endif
  353. RndismpInternalHalt(MiniportAdapterContext, TRUE);
  354. }
  355. /****************************************************************************/
  356. /* RndismpInternalHalt */
  357. /****************************************************************************/
  358. /* */
  359. /* Routine Description: */
  360. /* */
  361. /* Internal Halt routine. This is usually called from the MiniportHalt */
  362. /* entry point, but it may also be called when we are notified of surprise */
  363. /* removal by NDIS. Do all work atmost once. */
  364. /* */
  365. /* Arguments: */
  366. /* */
  367. /* MiniportAdapterContext - a context version of our Adapter pointer */
  368. /* bCalledFromHalt - Is this called from the MiniportHalt entry point? */
  369. /* */
  370. /* Return: */
  371. /* */
  372. /* VOID */
  373. /* */
  374. /****************************************************************************/
  375. VOID
  376. RndismpInternalHalt(IN NDIS_HANDLE MiniportAdapterContext,
  377. IN BOOLEAN bCalledFromHalt)
  378. {
  379. PRNDISMP_ADAPTER Adapter;
  380. PDRIVER_BLOCK DriverBlock;
  381. PRNDISMP_MESSAGE_FRAME pMsgFrame;
  382. BOOLEAN bWokenUp;
  383. UINT Count, LoopCount;
  384. // get adapter context
  385. Adapter = PRNDISMP_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
  386. CHECK_VALID_ADAPTER(Adapter);
  387. TRACE1(("RndismpInternalHalt: Adapter %x, Halting %d, CalledFromHalt %d\n", Adapter, Adapter->Halting, bCalledFromHalt));
  388. FlushPendingMessages(Adapter);
  389. if (!Adapter->Halting)
  390. {
  391. pMsgFrame = BuildRndisMessageCommon(Adapter,
  392. NULL,
  393. REMOTE_NDIS_HALT_MSG,
  394. 0,
  395. NULL,
  396. 0);
  397. if(pMsgFrame)
  398. {
  399. RNDISMP_ACQUIRE_ADAPTER_LOCK(Adapter);
  400. Adapter->Halting = TRUE;
  401. NdisInitializeEvent(&Adapter->HaltWaitEvent);
  402. RNDISMP_RELEASE_ADAPTER_LOCK(Adapter);
  403. // send the message to the microport
  404. RNDISMP_SEND_TO_MICROPORT(Adapter, pMsgFrame, FALSE, CompleteSendHalt);
  405. // wait for the -Send- to complete
  406. bWokenUp = NdisWaitEvent(&Adapter->HaltWaitEvent, MINIPORT_HALT_TIMEOUT);
  407. }
  408. else
  409. {
  410. ASSERT(FALSE);
  411. // Consider allocating the Halt message during Init time.
  412. }
  413. //
  414. // Wait for any outstanding receives to finish before halting
  415. // the microport.
  416. //
  417. LoopCount = 0;
  418. while ((Count = NdisPacketPoolUsage(Adapter->ReceivePacketPool)) != 0)
  419. {
  420. TRACE1(("RndismpInternalHalt: Adapter %p, Pkt pool %x has "
  421. "%d outstanding\n",
  422. Adapter, Adapter->ReceivePacketPool, Count));
  423. NdisMSleep(200);
  424. if (LoopCount++ > 30)
  425. {
  426. TRACE1(("RndismpInternalHalt: Adapter %p, cant reclaim packet pool %x\n",
  427. Adapter, Adapter->ReceivePacketPool));
  428. break;
  429. }
  430. }
  431. //
  432. // Wait for send-messages pending at the microport to finish.
  433. // Since we have set Halting to TRUE, no -new- messages will
  434. // be sent down, however there may be running threads that
  435. // have gone past the check for Halting - allow those
  436. // threads to finish now.
  437. //
  438. LoopCount = 0;
  439. while (Adapter->CurPendedMessages)
  440. {
  441. TRACE1(("RndismpInternalHalt: Adapter %p, %d msgs at microport\n",
  442. Adapter, Adapter->CurPendedMessages));
  443. NdisMSleep(200);
  444. if (LoopCount++ > 30)
  445. {
  446. TRACE1(("RndismpInternalHalt: Adapter %p, %d messages not send-completed!\n",
  447. Adapter, Adapter->CurPendedMessages));
  448. break;
  449. }
  450. }
  451. // cancel our keep alive timer
  452. NdisCancelTimer(&Adapter->KeepAliveTimer, &Adapter->TimerCancelled);
  453. // call the microport halt handler
  454. Adapter->RmHaltHandler(Adapter->MicroportAdapterContext);
  455. }
  456. if (bCalledFromHalt)
  457. {
  458. // free lists associated with OID support
  459. FreeOIDLists(Adapter);
  460. // free the adapter spinlock
  461. NdisFreeSpinLock(&Adapter->Lock);
  462. // save driver block pointer
  463. DriverBlock = Adapter->DriverBlock;
  464. // remove adapter from list
  465. RemoveAdapter(Adapter);
  466. // Free the Adapter and associated memory resources
  467. FreeAdapter(Adapter);
  468. }
  469. } // RndismpInternalHalt
  470. /****************************************************************************/
  471. /* RndismpReconfigure */
  472. /****************************************************************************/
  473. /* */
  474. /* Routine Description: */
  475. /* */
  476. /* NDIS calls this when the device is pulled. Note: only on WinMe! */
  477. /* */
  478. /* Arguments: */
  479. /* */
  480. /* MiniportAdapterContext - a context version of our Adapter pointer */
  481. /* */
  482. /* Return: */
  483. /* */
  484. /* VOID */
  485. /* */
  486. /****************************************************************************/
  487. NDIS_STATUS
  488. RndismpReconfigure(OUT PNDIS_STATUS pStatus,
  489. IN NDIS_HANDLE MiniportAdapterContext,
  490. IN NDIS_HANDLE ConfigContext)
  491. {
  492. PRNDISMP_ADAPTER pAdapter;
  493. // get adapter context
  494. pAdapter = PRNDISMP_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
  495. CHECK_VALID_ADAPTER(pAdapter);
  496. TRACE1(("Reconfig: Adapter %x\n", pAdapter));
  497. RndismpInternalHalt(pAdapter, FALSE);
  498. *pStatus = NDIS_STATUS_SUCCESS;
  499. return (NDIS_STATUS_SUCCESS);
  500. }
  501. /****************************************************************************/
  502. /* RndismpReset */
  503. /****************************************************************************/
  504. /* */
  505. /* Routine Description: */
  506. /* */
  507. /* The RndismpReset request instructs the Miniport to issue a hardware */
  508. /* reset to the network adapter. The driver also resets its software */
  509. /* state. See the description of NdisMReset for a detailed description */
  510. /* of this request. */
  511. /* */
  512. /* Arguments: */
  513. /* */
  514. /* AddressingReset - Does the adapter need the addressing information */
  515. /* reloaded. */
  516. /* MiniportAdapterContext - a context version of our Adapter pointer */
  517. /* */
  518. /* Return: */
  519. /* */
  520. /* NDIS_STATUS */
  521. /* */
  522. /****************************************************************************/
  523. NDIS_STATUS
  524. RndismpReset(OUT PBOOLEAN AddressingReset,
  525. IN NDIS_HANDLE MiniportAdapterContext)
  526. {
  527. PRNDISMP_ADAPTER Adapter;
  528. PRNDISMP_MESSAGE_FRAME pMsgFrame;
  529. NDIS_STATUS Status;
  530. // get adapter context
  531. Adapter = PRNDISMP_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
  532. CHECK_VALID_ADAPTER(Adapter);
  533. ASSERT(Adapter->ResetPending == FALSE);
  534. TRACE1(("RndismpReset: Adapter %x\n", Adapter));
  535. Adapter->ResetPending = TRUE;
  536. FlushPendingMessages(Adapter);
  537. pMsgFrame = BuildRndisMessageCommon(Adapter,
  538. NULL,
  539. REMOTE_NDIS_RESET_MSG,
  540. 0,
  541. NULL,
  542. 0);
  543. if (pMsgFrame)
  544. {
  545. RNDISMP_ACQUIRE_ADAPTER_LOCK(Adapter);
  546. Adapter->NeedReset = FALSE;
  547. //
  548. // Fix water mark so that the reset gets sent down.
  549. //
  550. Adapter->HiWatPendedMessages = RNDISMP_PENDED_SEND_HIWAT + 1;
  551. RNDISMP_RELEASE_ADAPTER_LOCK(Adapter);
  552. // send the message to the microport
  553. RNDISMP_SEND_TO_MICROPORT(Adapter, pMsgFrame, FALSE, CompleteSendReset);
  554. Status = NDIS_STATUS_PENDING;
  555. RNDISMP_ACQUIRE_ADAPTER_LOCK(Adapter);
  556. Adapter->HiWatPendedMessages--;
  557. RNDISMP_RELEASE_ADAPTER_LOCK(Adapter);
  558. }
  559. else
  560. {
  561. CompleteMiniportReset(Adapter, NDIS_STATUS_RESOURCES, FALSE);
  562. Status = NDIS_STATUS_PENDING;
  563. }
  564. return Status;
  565. } // RndismpReset
  566. /****************************************************************************/
  567. /* RndismpCheckForHang */
  568. /****************************************************************************/
  569. /* */
  570. /* Routine Description: */
  571. /* */
  572. /* Check and see if device is "hung" */
  573. /* */
  574. /* Arguments: */
  575. /* */
  576. /* MiniportAdapterContext - a context version of our Adapter pointer */
  577. /* */
  578. /* Return: */
  579. /* */
  580. /* BOOLEAN */
  581. /* */
  582. /****************************************************************************/
  583. BOOLEAN
  584. RndismpCheckForHang(IN NDIS_HANDLE MiniportAdapterContext)
  585. {
  586. PRNDISMP_ADAPTER Adapter;
  587. BOOLEAN bReturnHung;
  588. PRNDISMP_MESSAGE_FRAME pMsgFrame;
  589. PLIST_ENTRY pEnt;
  590. Adapter = PRNDISMP_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
  591. TRACE2(("RndismpCheckForHang: Adapter %x\n", Adapter));
  592. CHECK_VALID_ADAPTER(Adapter);
  593. RNDISMP_ACQUIRE_ADAPTER_LOCK(Adapter);
  594. bReturnHung = (Adapter->NeedReset && !Adapter->ResetPending);
  595. #if THROTTLE_MESSAGES
  596. // Try to grow the pending send window, if we can.
  597. //
  598. if (!Adapter->SendInProgress)
  599. {
  600. if (Adapter->CurPendedMessages == 0)
  601. {
  602. Adapter->HiWatPendedMessages = RNDISMP_PENDED_SEND_HIWAT;
  603. Adapter->LoWatPendedMessages = RNDISMP_PENDED_SEND_LOWAT;
  604. }
  605. }
  606. if (!bReturnHung && !Adapter->ResetPending)
  607. {
  608. //
  609. // Check if the microport isn't completing messages.
  610. //
  611. if (!IsListEmpty(&Adapter->PendingAtMicroportList))
  612. {
  613. pEnt = Adapter->PendingAtMicroportList.Flink;
  614. pMsgFrame = CONTAINING_RECORD(pEnt, RNDISMP_MESSAGE_FRAME, PendLink);
  615. if (pMsgFrame->TicksOnQueue > 4)
  616. {
  617. TRACE1(("CheckForHang: Adapter %x, Msg %x has timed out!\n",
  618. Adapter, pMsgFrame));
  619. bReturnHung = TRUE;
  620. }
  621. else
  622. {
  623. pMsgFrame->TicksOnQueue++;
  624. }
  625. }
  626. }
  627. #endif // THROTTLE_MESSAGES
  628. if (RndisForceReset)
  629. {
  630. RndisForceReset = FALSE;
  631. Adapter->NeedReset = TRUE;
  632. Adapter->ResetPending = FALSE;
  633. bReturnHung = TRUE;
  634. }
  635. RNDISMP_RELEASE_ADAPTER_LOCK(Adapter);
  636. return (bReturnHung);
  637. } // RndismpCheckForHang
  638. /****************************************************************************/
  639. /* RndismpInitialize */
  640. /****************************************************************************/
  641. /* */
  642. /* Routine Description: */
  643. /* */
  644. /* RndismpInitialize starts an adapter and registers resources with the */
  645. /* wrapper. */
  646. /* */
  647. /* Arguments: */
  648. /* */
  649. /* OpenErrorStatus - Extra status bytes for opening token ring adapters. */
  650. /* SelectedMediumIndex - Index of the media type chosen by the driver. */
  651. /* MediumArray - Array of media types for the driver to chose from. */
  652. /* MediumArraySize - Number of entries in the array. */
  653. /* MiniportAdapterHandle - Handle for passing to the wrapper when */
  654. /* referring to this adapter. */
  655. /* ConfigurationHandle - A handle to pass to NdisOpenConfiguration. */
  656. /* */
  657. /* Return Value: */
  658. /* */
  659. /* NDIS_STATUS_SUCCESS */
  660. /* NDIS_STATUS_PENDING */
  661. /* */
  662. /****************************************************************************/
  663. NDIS_STATUS
  664. RndismpInitialize(OUT PNDIS_STATUS OpenErrorStatus,
  665. OUT PUINT SelectedMediumIndex,
  666. IN PNDIS_MEDIUM MediumArray,
  667. IN UINT MediumArraySize,
  668. IN NDIS_HANDLE MiniportAdapterHandle,
  669. IN NDIS_HANDLE ConfigurationHandle)
  670. {
  671. ULONG Index;
  672. NDIS_STATUS Status;
  673. PRNDISMP_ADAPTER Adapter;
  674. NDIS_INTERFACE_TYPE IfType;
  675. PDEVICE_OBJECT Pdo, Fdo, Ndo;
  676. PDRIVER_BLOCK DriverBlock;
  677. PRNDIS_INITIALIZE_COMPLETE pInitCompleteMessage;
  678. PRNDISMP_MESSAGE_FRAME pMsgFrame = NULL;
  679. PRNDISMP_MESSAGE_FRAME pPendingMsgFrame;
  680. PRNDISMP_REQUEST_CONTEXT pReqContext = NULL;
  681. RNDIS_REQUEST_ID RequestId;
  682. ULONG PacketAlignmentFactor;
  683. NDIS_EVENT Event;
  684. BOOLEAN bWokenUp;
  685. BOOLEAN bLinkedAdapter;
  686. BOOLEAN bMicroportInitialized;
  687. TRACE2(("RndismpInitialize\n"));
  688. Adapter = NULL;
  689. Status = NDIS_STATUS_SUCCESS;
  690. bLinkedAdapter = FALSE;
  691. bMicroportInitialized = FALSE;
  692. do
  693. {
  694. // allocate the adapter object, exit if error occurs
  695. Status = MemAlloc(&Adapter, sizeof(RNDISMP_ADAPTER));
  696. if (Status != NDIS_STATUS_SUCCESS)
  697. {
  698. TRACE2(("Adapter Allocate Memory failed (%08X)\n", Status));
  699. break;
  700. }
  701. // allocate space for list of driver-supported OIDs
  702. Status = MemAlloc(&Adapter->DriverOIDList,
  703. RndismpSupportedOidsNum*sizeof(NDIS_OID));
  704. if (Status != NDIS_STATUS_SUCCESS)
  705. {
  706. break;
  707. }
  708. RNDISMP_MOVE_MEM(Adapter->DriverOIDList, RndismpSupportedOids, RndismpSupportedOidsNum*sizeof(NDIS_OID));
  709. Adapter->NumDriverOIDs = RndismpSupportedOidsNum;
  710. Adapter->MiniportAdapterHandle = MiniportAdapterHandle;
  711. InitializeListHead(&Adapter->PendingFrameList);
  712. Adapter->Initing = TRUE;
  713. Adapter->MacOptions = RNDIS_DRIVER_MAC_OPTIONS;
  714. Adapter->RequestId = 1;
  715. #if THROTTLE_MESSAGES
  716. Adapter->HiWatPendedMessages = RNDISMP_PENDED_SEND_HIWAT;
  717. Adapter->LoWatPendedMessages = RNDISMP_PENDED_SEND_LOWAT;
  718. Adapter->CurPendedMessages = 0;
  719. Adapter->SendInProgress = FALSE;
  720. InitializeListHead(&Adapter->WaitingMessageList);
  721. #endif
  722. InitializeListHead(&Adapter->PendingAtMicroportList);
  723. Adapter->IndicatingReceives = FALSE;
  724. InitializeListHead(&Adapter->PendingRcvMessageList);
  725. NdisInitializeTimer(&Adapter->IndicateTimer, IndicateTimeout, (PVOID)Adapter);
  726. Adapter->SendProcessInProgress = FALSE;
  727. InitializeListHead(&Adapter->PendingSendProcessList);
  728. NdisInitializeTimer(&Adapter->SendProcessTimer, SendProcessTimeout, (PVOID)Adapter);
  729. TRACE2(("Adapter structure pointer is (%08X)\n", Adapter));
  730. NdisAllocateSpinLock(&Adapter->Lock);
  731. // get PDO to pass to microport
  732. NdisMGetDeviceProperty(MiniportAdapterHandle,
  733. &Pdo,
  734. &Fdo,
  735. &Ndo,
  736. NULL,
  737. NULL);
  738. #if NEW_NDIS_API_IN_MILLENNIUM
  739. {
  740. NDIS_STRING UnicodeString;
  741. Status = NdisMQueryAdapterInstanceName(&UnicodeString,
  742. Adapter->MiniportAdapterHandle);
  743. if (Status == NDIS_STATUS_SUCCESS)
  744. {
  745. TRACE1(("Init: NDIS returned len %d [%ws]\n",
  746. UnicodeString.Length, UnicodeString.Buffer));
  747. NdisFreeString(UnicodeString);
  748. }
  749. }
  750. #endif
  751. Adapter->pDeviceObject = Fdo;
  752. Adapter->pPhysDeviceObject = Pdo;
  753. Status = GetDeviceFriendlyName(Pdo,
  754. &Adapter->FriendlyNameAnsi,
  755. &Adapter->FriendlyNameUnicode);
  756. if (Status == NDIS_STATUS_SUCCESS)
  757. {
  758. TRACE1(("Init: Pdo %x, Ndo %x: Adapter %x: [%s]\n",
  759. Pdo, Ndo, Adapter, Adapter->FriendlyNameAnsi.Buffer));
  760. }
  761. else
  762. {
  763. Status = NDIS_STATUS_SUCCESS;
  764. }
  765. // Determine the platform we are running on. Ideally we would
  766. // like to do this from DriverEntry, but the NDIS API isn't
  767. // available until MiniportInit time.
  768. {
  769. NDIS_STATUS NdisStatus;
  770. PNDIS_CONFIGURATION_PARAMETER pParameter;
  771. NDIS_STRING VersionKey = NDIS_STRING_CONST("Environment");
  772. NdisReadConfiguration(
  773. &NdisStatus,
  774. &pParameter,
  775. ConfigurationHandle,
  776. &VersionKey,
  777. NdisParameterInteger);
  778. if ((NdisStatus == NDIS_STATUS_SUCCESS) &&
  779. ((pParameter->ParameterType == NdisParameterInteger) ||
  780. (pParameter->ParameterType == NdisParameterHexInteger)))
  781. {
  782. Adapter->bRunningOnWin9x =
  783. (pParameter->ParameterData.IntegerData == NdisEnvironmentWindows);
  784. TRACE1(("Init: Adapter %p, running on %s\n",
  785. Adapter,
  786. ((Adapter->bRunningOnWin9x)? "Win9X": "NT")));
  787. }
  788. else
  789. {
  790. TRACE1(("Init: ReadConfig: NdisStatus %x\n", NdisStatus));
  791. #if DBG
  792. if (NdisStatus == NDIS_STATUS_SUCCESS)
  793. {
  794. TRACE1(("Init: ReadConfig: parametertype %x\n",
  795. pParameter->ParameterType));
  796. }
  797. #endif // DBG
  798. Adapter->bRunningOnWin9x = TRUE;
  799. }
  800. }
  801. // find the driver block associated with this adapter
  802. DriverBlock = DeviceObjectToDriverBlock(&RndismpMiniportBlockListHead, Fdo);
  803. if (DriverBlock == NULL)
  804. {
  805. TRACE1(("Init: Can't find driver block for FDO %x!\n", Fdo));
  806. Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
  807. break;
  808. }
  809. // save the associated driver block in the adapter
  810. Adapter->DriverBlock = DriverBlock;
  811. Adapter->Signature = ADAPTER_SIGNATURE;
  812. // get handlers passed in from microport
  813. Adapter->RmInitializeHandler = DriverBlock->RmInitializeHandler;
  814. Adapter->RmInitCompleteNotifyHandler = DriverBlock->RmInitCompleteNotifyHandler;
  815. Adapter->RmHaltHandler = DriverBlock->RmHaltHandler;
  816. Adapter->RmShutdownHandler = DriverBlock->RmShutdownHandler;
  817. Adapter->RmSendMessageHandler = DriverBlock->RmSendMessageHandler;
  818. Adapter->RmReturnMessageHandler = DriverBlock->RmReturnMessageHandler;
  819. // call microport initialize handler
  820. //
  821. // Microport returns context
  822. // Pass in Miniport context
  823. // Pass in NDIS adapter handle
  824. // Pass in NDIS configuration handle
  825. // Pass in PDO for this adapter
  826. Status = Adapter->RmInitializeHandler(&Adapter->MicroportAdapterContext,
  827. &Adapter->MaxReceiveSize,
  828. (NDIS_HANDLE) Adapter,
  829. (NDIS_HANDLE) MiniportAdapterHandle,
  830. (NDIS_HANDLE) ConfigurationHandle,
  831. Ndo);
  832. if (Status != NDIS_STATUS_SUCCESS)
  833. {
  834. TRACE2(("Microport initialize handler failed (%08X)\n", Status));
  835. break;
  836. }
  837. bMicroportInitialized = TRUE;
  838. // everything looks good, so finish up
  839. Status = AllocateTransportResources(Adapter);
  840. if (Status != NDIS_STATUS_SUCCESS)
  841. {
  842. Status = NDIS_STATUS_RESOURCES;
  843. break;
  844. }
  845. // allocate space to receive a copy of the Initialize complete message in
  846. Status = MemAlloc(&Adapter->pInitCompleteMessage, sizeof(RNDIS_INITIALIZE_COMPLETE));
  847. if (Status != NDIS_STATUS_SUCCESS)
  848. {
  849. Status = NDIS_STATUS_RESOURCES;
  850. break;
  851. }
  852. // now we send down a RNDIS initialize message to the device
  853. pMsgFrame = BuildRndisMessageCommon(Adapter,
  854. NULL,
  855. REMOTE_NDIS_INITIALIZE_MSG,
  856. 0,
  857. (PVOID) NULL,
  858. 0);
  859. if (pMsgFrame == NULL)
  860. {
  861. Status = NDIS_STATUS_RESOURCES;
  862. break;
  863. }
  864. RequestId = pMsgFrame->RequestId;
  865. pReqContext = AllocateRequestContext(Adapter);
  866. if (pReqContext == NULL)
  867. {
  868. Status = NDIS_STATUS_RESOURCES;
  869. break;
  870. }
  871. pReqContext->pNdisRequest = NULL;
  872. NdisInitializeEvent(&Event);
  873. pReqContext->pEvent = &Event;
  874. pMsgFrame->pVc = NULL;
  875. pMsgFrame->pReqContext = pReqContext;
  876. RNDISMP_ASSERT_AT_PASSIVE();
  877. // Keep the message frame around until send-completion.
  878. ReferenceMsgFrame(pMsgFrame);
  879. // send the message to the microport.
  880. RNDISMP_SEND_TO_MICROPORT(Adapter, pMsgFrame, TRUE, CompleteSendInit);
  881. RNDISMP_ASSERT_AT_PASSIVE();
  882. // wait for message to complete
  883. bWokenUp = NdisWaitEvent(&Event, MINIPORT_INIT_TIMEOUT);
  884. // remove the message from the pending queue - it may or may not be there.
  885. RNDISMP_LOOKUP_PENDING_MESSAGE(pPendingMsgFrame, Adapter, RequestId);
  886. DereferenceMsgFrame(pMsgFrame);
  887. if (!bWokenUp)
  888. {
  889. // Failed to receive an Init complete within a reasonable time.
  890. TRACE1(("Init: Adapter %x, failed to receive Init complete\n", Adapter));
  891. Status = NDIS_STATUS_DEVICE_FAILED;
  892. break;
  893. }
  894. //
  895. // the init complete message from the device is now
  896. // copied over to our local structure
  897. //
  898. pInitCompleteMessage = Adapter->pInitCompleteMessage;
  899. if (pInitCompleteMessage->Status != NDIS_STATUS_SUCCESS)
  900. {
  901. Status = pInitCompleteMessage->Status;
  902. break;
  903. }
  904. // make sure this is a supported device.
  905. if (!(pInitCompleteMessage->DeviceFlags & (RNDIS_DF_CONNECTIONLESS | RNDIS_DF_RAW_DATA)) ||
  906. (pInitCompleteMessage->Medium != RNdisMedium802_3))
  907. {
  908. TRACE1(("Init: Complete: unknown DeviceFlags %x or Medium %d\n",
  909. pInitCompleteMessage->DeviceFlags,
  910. pInitCompleteMessage->Medium));
  911. Status = NDIS_STATUS_NOT_SUPPORTED;
  912. break;
  913. }
  914. if ((pInitCompleteMessage->DeviceFlags & RNDIS_DF_RAW_DATA)
  915. || (gRawEncap))
  916. {
  917. Adapter->MultipleSendFunc = DoMultipleSendRaw;
  918. } else
  919. {
  920. Adapter->MultipleSendFunc = DoMultipleSend;
  921. }
  922. Adapter->Medium = RNDIS_TO_NDIS_MEDIUM(pInitCompleteMessage->Medium);
  923. // get device parameters.
  924. Adapter->MaxPacketsPerMessage = pInitCompleteMessage->MaxPacketsPerMessage;
  925. if (Adapter->MaxPacketsPerMessage == 0)
  926. {
  927. Adapter->MaxPacketsPerMessage = 1;
  928. }
  929. #if HACK
  930. if (Adapter->MaxPacketsPerMessage > 1)
  931. {
  932. Adapter->MaxPacketsPerMessage = 2;
  933. }
  934. #endif // HACK
  935. Adapter->bMultiPacketSupported = (Adapter->MaxPacketsPerMessage > 1);
  936. Adapter->MaxTransferSize = pInitCompleteMessage->MaxTransferSize;
  937. PacketAlignmentFactor = pInitCompleteMessage->PacketAlignmentFactor;
  938. if (PacketAlignmentFactor > 7)
  939. {
  940. PacketAlignmentFactor = 7;
  941. }
  942. Adapter->AlignmentIncr = (1 << PacketAlignmentFactor);
  943. Adapter->AlignmentMask = ~((1 << PacketAlignmentFactor) - 1);
  944. #if DBG
  945. DbgPrint("RNDISMP: InitComp: Adapter %x, Version %d.%d, MaxPkt %d, AlignIncr %d, AlignMask %x, MaxXferSize %d\n",
  946. Adapter,
  947. pInitCompleteMessage->MajorVersion,
  948. pInitCompleteMessage->MinorVersion,
  949. Adapter->MaxPacketsPerMessage,
  950. Adapter->AlignmentIncr,
  951. Adapter->AlignmentMask,
  952. Adapter->MaxTransferSize);
  953. #endif // DBG
  954. // Get the medium type.
  955. for (Index = 0; Index < MediumArraySize; Index++)
  956. {
  957. if (MediumArray[Index] == Adapter->Medium)
  958. {
  959. break;
  960. }
  961. }
  962. if (Index == MediumArraySize)
  963. {
  964. TRACE1(("InitComp: Adapter %x, device returned unsupported medium %d\n",
  965. Adapter, pInitCompleteMessage->Medium));
  966. Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
  967. break;
  968. }
  969. *SelectedMediumIndex = Index;
  970. Adapter->DeviceFlags = pInitCompleteMessage->DeviceFlags;
  971. // call NdisMSetAttributesEx in order to let NDIS know
  972. // what kind of driver and features we support
  973. // interface type
  974. IfType = NdisInterfaceInternal;
  975. if (Adapter->bRunningOnWin9x)
  976. {
  977. //
  978. // NOTE! The 0x80000000 bit is set to let NDIS know
  979. // (Millennium only!) that our reconfig handler should
  980. // be called when the device is surprise-removed.
  981. //
  982. NdisMSetAttributesEx(Adapter->MiniportAdapterHandle,
  983. (NDIS_HANDLE) Adapter,
  984. 4,
  985. (ULONG) NDIS_ATTRIBUTE_DESERIALIZE | 0x80000000,
  986. IfType);
  987. }
  988. else
  989. {
  990. ULONG AttrFlags;
  991. AttrFlags = NDIS_ATTRIBUTE_DESERIALIZE |
  992. NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK;
  993. if (Adapter->DeviceFlags & RNDIS_DF_CONNECTIONLESS)
  994. {
  995. AttrFlags |= NDIS_ATTRIBUTE_NOT_CO_NDIS;
  996. }
  997. NdisMSetAttributesEx(Adapter->MiniportAdapterHandle,
  998. (NDIS_HANDLE) Adapter,
  999. 4,
  1000. AttrFlags,
  1001. IfType);
  1002. }
  1003. // Tell the microport that the device completed Init
  1004. // successfully:
  1005. if (Adapter->RmInitCompleteNotifyHandler)
  1006. {
  1007. Status = Adapter->RmInitCompleteNotifyHandler(
  1008. Adapter->MicroportAdapterContext,
  1009. Adapter->DeviceFlags,
  1010. &Adapter->MaxTransferSize);
  1011. if (Status != NDIS_STATUS_SUCCESS)
  1012. {
  1013. break;
  1014. }
  1015. }
  1016. // get the list of supported OIDs from the device
  1017. pMsgFrame = BuildRndisMessageCommon(Adapter,
  1018. NULL,
  1019. REMOTE_NDIS_QUERY_MSG,
  1020. OID_GEN_SUPPORTED_LIST,
  1021. (PVOID) NULL,
  1022. 0);
  1023. if (pMsgFrame == NULL)
  1024. {
  1025. Status = NDIS_STATUS_RESOURCES;
  1026. break;
  1027. }
  1028. //
  1029. // The message frame will be deref'ed once when we receive
  1030. // a reply to the query, and once below, when this thread
  1031. // is done with the frame. Make sure that it doesn't go away
  1032. // until this thread is done with it.
  1033. //
  1034. ReferenceMsgFrame(pMsgFrame);
  1035. // link us on to the list of adapters for this driver block
  1036. AddAdapter(Adapter);
  1037. bLinkedAdapter = TRUE;
  1038. pReqContext->pNdisRequest = NULL;
  1039. pReqContext->Oid = OID_GEN_SUPPORTED_LIST;
  1040. pReqContext->CompletionStatus = NDIS_STATUS_SUCCESS;
  1041. pReqContext->bInternal = TRUE;
  1042. NdisInitializeEvent(&Event);
  1043. pReqContext->pEvent = &Event;
  1044. pMsgFrame->pVc = NULL;
  1045. pMsgFrame->pReqContext = pReqContext;
  1046. RequestId = pMsgFrame->RequestId;
  1047. // send the message to the microport.
  1048. RNDISMP_SEND_TO_MICROPORT(Adapter, pMsgFrame, TRUE, NULL);
  1049. RNDISMP_ASSERT_AT_PASSIVE();
  1050. bWokenUp = NdisWaitEvent(&Event, MINIPORT_INIT_TIMEOUT);
  1051. // remove the message from the pending queue - it may or may not be there.
  1052. RNDISMP_LOOKUP_PENDING_MESSAGE(pPendingMsgFrame, Adapter, RequestId);
  1053. DereferenceMsgFrame(pMsgFrame);
  1054. if (!bWokenUp || (Adapter->DriverOIDList == NULL))
  1055. {
  1056. // Failed to receive a response within a reasonable time,
  1057. // or the device failed this query.
  1058. //
  1059. TRACE1(("Init: Adapter %x, failed to receive response to OID_GEN_SUPPORTED_LIST\n", Adapter));
  1060. Status = NDIS_STATUS_DEVICE_FAILED;
  1061. ASSERT(FALSE);
  1062. break;
  1063. }
  1064. // Successfully queried the supported OID list.
  1065. #ifdef BUILD_WIN9X
  1066. //
  1067. // Attempt to support surprise removal of this device (Win98/SE)
  1068. // by intercepting config mgr messages forwarded by NDIS.
  1069. //
  1070. HookNtKernCMHandler(Adapter);
  1071. #endif // BUILD_WIN9X
  1072. if (Adapter->bRunningOnWin9x)
  1073. {
  1074. //
  1075. // Query and cache the values of certain OIDs that NDIS queries
  1076. // us for, so that when we get those queries, we can complete
  1077. // them immediately (synchronously). This is to work around
  1078. // a problem where NDIS (98/SE only) times out too soon on
  1079. // internally generated queries.
  1080. //
  1081. Status = SyncQueryDevice(Adapter,
  1082. OID_GEN_MAXIMUM_FRAME_SIZE,
  1083. (PUCHAR)&Adapter->MaximumFrameSize,
  1084. sizeof(Adapter->MaximumFrameSize));
  1085. if (Status != NDIS_STATUS_SUCCESS)
  1086. {
  1087. TRACE1(("Init: Adapter %x, failed to query MAXIMUM_FRAME_SIZE\n", Adapter));
  1088. Status = NDIS_STATUS_DEVICE_FAILED;
  1089. break;
  1090. }
  1091. Status = SyncQueryDevice(Adapter,
  1092. OID_GEN_MAC_OPTIONS,
  1093. (PUCHAR)&Adapter->MacOptions,
  1094. sizeof(Adapter->MacOptions));
  1095. if (Status != NDIS_STATUS_SUCCESS)
  1096. {
  1097. TRACE1(("Init: Adapter %x, failed to query MAC_OPTIONS\n", Adapter));
  1098. Status = NDIS_STATUS_DEVICE_FAILED;
  1099. break;
  1100. }
  1101. Status = SyncQueryDevice(Adapter,
  1102. OID_802_3_MAXIMUM_LIST_SIZE,
  1103. (PUCHAR)&Adapter->MaxMulticastListSize,
  1104. sizeof(Adapter->MaxMulticastListSize));
  1105. if (Status != NDIS_STATUS_SUCCESS)
  1106. {
  1107. TRACE1(("Init: Adapter %x, failed to query MAX_LIST_SIZE\n", Adapter));
  1108. Status = NDIS_STATUS_DEVICE_FAILED;
  1109. break;
  1110. }
  1111. Status = SyncQueryDevice(Adapter,
  1112. OID_802_3_CURRENT_ADDRESS,
  1113. (PUCHAR)Adapter->MacAddress,
  1114. ETH_LENGTH_OF_ADDRESS);
  1115. if (Status != NDIS_STATUS_SUCCESS)
  1116. {
  1117. TRACE1(("Init: Adapter %x, failed to query CURRENT_ADDR\n", Adapter));
  1118. Status = NDIS_STATUS_DEVICE_FAILED;
  1119. break;
  1120. }
  1121. TRACE1(("Init: Adapter %p, OID caching done!\n", Adapter));
  1122. }
  1123. // send any registry parameters down to the device, if it supports them.
  1124. if (GetOIDSupport(Adapter, OID_GEN_RNDIS_CONFIG_PARAMETER) == DEVICE_SUPPORTED_OID)
  1125. {
  1126. Status = ReadAndSetRegistryParameters(Adapter, ConfigurationHandle);
  1127. if (Status != NDIS_STATUS_SUCCESS)
  1128. {
  1129. break;
  1130. }
  1131. }
  1132. // register a shutdown handler
  1133. NdisMRegisterAdapterShutdownHandler(Adapter->MiniportAdapterHandle,
  1134. (PVOID) Adapter,
  1135. RndismpShutdownHandler);
  1136. Adapter->TimerCancelled = FALSE;
  1137. Adapter->Initing = FALSE;
  1138. // initialize "KeepAlive" timer
  1139. NdisInitializeTimer(&Adapter->KeepAliveTimer,
  1140. KeepAliveTimerHandler,
  1141. (PVOID) Adapter);
  1142. NdisSetTimer(&Adapter->KeepAliveTimer, KEEP_ALIVE_TIMER / 2);
  1143. Status = NDIS_STATUS_SUCCESS;
  1144. }
  1145. while (FALSE);
  1146. if (Adapter)
  1147. {
  1148. if (Adapter->pInitCompleteMessage)
  1149. {
  1150. MemFree(Adapter->pInitCompleteMessage, sizeof(*Adapter->pInitCompleteMessage));
  1151. }
  1152. }
  1153. if (Status != NDIS_STATUS_SUCCESS)
  1154. {
  1155. TRACE1(("Failed to init adapter %x, status %x\n", Adapter, Status));
  1156. if (bMicroportInitialized)
  1157. {
  1158. ASSERT(Adapter);
  1159. Adapter->RmHaltHandler(Adapter->MicroportAdapterContext);
  1160. }
  1161. if (Adapter)
  1162. {
  1163. if (bLinkedAdapter)
  1164. {
  1165. RemoveAdapter(Adapter);
  1166. }
  1167. FreeAdapter(Adapter);
  1168. }
  1169. }
  1170. return Status;
  1171. } // RndismpInitialize
  1172. /****************************************************************************/
  1173. /* RndisMSendComplete */
  1174. /****************************************************************************/
  1175. /* */
  1176. /* Routine Description: */
  1177. /* */
  1178. /* Called by microport to indicate a message miniport sent is completed */
  1179. /* by microport */
  1180. /* */
  1181. /* Arguments: */
  1182. /* */
  1183. /* MiniportAdapterContext - a context version of our Adapter pointer */
  1184. /* RndisMessageHandle - context used by miniport */
  1185. /* SendStatus - indicate status of send message */
  1186. /* */
  1187. /* Return: */
  1188. /* */
  1189. /* VOID */
  1190. /* */
  1191. /****************************************************************************/
  1192. VOID
  1193. RndisMSendComplete(IN NDIS_HANDLE MiniportAdapterContext,
  1194. IN NDIS_HANDLE RndisMessageHandle,
  1195. IN NDIS_STATUS SendStatus)
  1196. {
  1197. PRNDISMP_ADAPTER Adapter;
  1198. PRNDISMP_MESSAGE_FRAME pMsgFrame;
  1199. // get adapter context
  1200. Adapter = PRNDISMP_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
  1201. CHECK_VALID_ADAPTER(Adapter);
  1202. pMsgFrame = MESSAGE_FRAME_FROM_HANDLE(RndisMessageHandle);
  1203. CHECK_VALID_FRAME(pMsgFrame);
  1204. ASSERT(pMsgFrame->pAdapter == Adapter);
  1205. TRACE2(("RndisMSendComplete: Adapter %x, MsgFrame %x, MDL %x\n", Adapter, pMsgFrame, pMsgFrame->pMessageMdl));
  1206. if ((SendStatus != NDIS_STATUS_SUCCESS) &&
  1207. (SendStatus != NDIS_STATUS_RESOURCES))
  1208. {
  1209. RNDISMP_INCR_STAT(Adapter, MicroportSendError);
  1210. TRACE0(("RndisMSendComplete: Adapter %x, MsgFrame %x, MDL %x, ERROR %x\n",
  1211. Adapter,
  1212. pMsgFrame,
  1213. pMsgFrame->pMessageMdl,
  1214. SendStatus));
  1215. }
  1216. #if THROTTLE_MESSAGES
  1217. RNDISMP_ACQUIRE_ADAPTER_LOCK(Adapter);
  1218. Adapter->CurPendedMessages--;
  1219. RemoveEntryList(&pMsgFrame->PendLink);
  1220. if (SendStatus == NDIS_STATUS_RESOURCES)
  1221. {
  1222. RNDISMP_INCR_STAT(Adapter, SendMsgLowRes);
  1223. }
  1224. if ((SendStatus != NDIS_STATUS_RESOURCES) ||
  1225. (Adapter->CurPendedMessages < 2))
  1226. {
  1227. if (Adapter->CurPendedMessages == Adapter->LoWatPendedMessages)
  1228. {
  1229. RNDISMP_RELEASE_ADAPTER_LOCK(Adapter);
  1230. QueueMessageToMicroport(Adapter, NULL, FALSE);
  1231. }
  1232. else
  1233. {
  1234. RNDISMP_RELEASE_ADAPTER_LOCK(Adapter);
  1235. }
  1236. if (SendStatus == NDIS_STATUS_RESOURCES)
  1237. {
  1238. TRACE1(("RndisMSendComplete: Adapter %x, got resources\n", Adapter));
  1239. SendStatus = NDIS_STATUS_SUCCESS;
  1240. }
  1241. if (pMsgFrame->pCallback)
  1242. {
  1243. (*pMsgFrame->pCallback)(pMsgFrame, SendStatus);
  1244. }
  1245. else
  1246. {
  1247. //
  1248. // Do nothing. The sender will take care of freeing
  1249. // this.
  1250. //
  1251. }
  1252. }
  1253. else
  1254. {
  1255. //
  1256. // The microport is out of send resources. Requeue this
  1257. // and adjust water marks.
  1258. //
  1259. InsertHeadList(&Adapter->WaitingMessageList, &pMsgFrame->PendLink);
  1260. Adapter->HiWatPendedMessages = Adapter->CurPendedMessages;
  1261. Adapter->LoWatPendedMessages = Adapter->CurPendedMessages / 2;
  1262. TRACE1(("RndisMSendComplete: Adapter %x, new Hiwat %d, Lowat %d\n",
  1263. Adapter, Adapter->HiWatPendedMessages, Adapter->LoWatPendedMessages));
  1264. RNDISMP_RELEASE_ADAPTER_LOCK(Adapter);
  1265. }
  1266. #else
  1267. if (pMsgFrame->pCallback)
  1268. {
  1269. (*pMsgFrame->pCallback)(pMsgFrame, SendStatus);
  1270. }
  1271. else
  1272. {
  1273. //
  1274. // Do nothing. The sender will take care of freeing
  1275. // this.
  1276. //
  1277. }
  1278. #endif // THROTTLE_MESSAGES
  1279. } // RndisMSendComplete
  1280. /****************************************************************************/
  1281. /* InitCompletionMessage */
  1282. /****************************************************************************/
  1283. /* */
  1284. /* Routine Description: */
  1285. /* */
  1286. /* Completion message from microport in response to init message miniport */
  1287. /* sent. The init message was sent from the adapter init routine which is */
  1288. /* waiting for this event to unblock */
  1289. /* */
  1290. /* Arguments: */
  1291. /* */
  1292. /* pAdapter - Pointer to our adapter structure */
  1293. /* pMessage - Pointer to RNDIS message */
  1294. /* pMdl - Pointer to MDL received from microport */
  1295. /* TotalLength - length of complete message */
  1296. /* MicroportMessageContext - context for message from micorport */
  1297. /* ReceiveStatus - used by microport to indicate it is low on resource */
  1298. /* bMessageCopied - is this a copy of the original message? */
  1299. /* */
  1300. /* Return: */
  1301. /* */
  1302. /* BOOLEAN - should the message be returned to the microport? */
  1303. /* */
  1304. /****************************************************************************/
  1305. BOOLEAN
  1306. InitCompletionMessage(IN PRNDISMP_ADAPTER pAdapter,
  1307. IN PRNDIS_MESSAGE pMessage,
  1308. IN PMDL pMdl,
  1309. IN ULONG TotalLength,
  1310. IN NDIS_HANDLE MicroportMessageContext,
  1311. IN NDIS_STATUS ReceiveStatus,
  1312. IN BOOLEAN bMessageCopied)
  1313. {
  1314. PRNDIS_INITIALIZE_COMPLETE pInitCompleteMessage;
  1315. PRNDISMP_MESSAGE_FRAME pMsgFrame;
  1316. PRNDISMP_REQUEST_CONTEXT pReqContext;
  1317. BOOLEAN bDiscardMsg = TRUE;
  1318. TRACE2(("InitCompletionMessage\n"));
  1319. do
  1320. {
  1321. if (pMessage->MessageLength < RNDISMP_MIN_MESSAGE_LENGTH(InitializeComplete))
  1322. {
  1323. TRACE1(("InitCompletion: Message length (%d) too short, expect at least (%d)\n",
  1324. pMessage->MessageLength,
  1325. RNDISMP_MIN_MESSAGE_LENGTH(InitializeComplete)));
  1326. break;
  1327. }
  1328. if (pAdapter->pInitCompleteMessage == NULL)
  1329. {
  1330. TRACE1(("InitCompletion: multiple InitComplete from device, ignored\n"));
  1331. break;
  1332. }
  1333. pInitCompleteMessage = RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(pMessage);
  1334. // get request frame from request ID in message
  1335. RNDISMP_LOOKUP_PENDING_MESSAGE(pMsgFrame, pAdapter, pInitCompleteMessage->RequestId);
  1336. if (pMsgFrame == NULL)
  1337. {
  1338. // invalid request ID or aborted request.
  1339. TRACE1(("Invalid request ID %d in Init Complete\n",
  1340. pInitCompleteMessage->RequestId));
  1341. break;
  1342. }
  1343. pReqContext = pMsgFrame->pReqContext;
  1344. RNDISMP_MOVE_MEM(pAdapter->pInitCompleteMessage,
  1345. pInitCompleteMessage,
  1346. sizeof(*pInitCompleteMessage));
  1347. // signal the adapter init routine we are done
  1348. NdisSetEvent(pReqContext->pEvent);
  1349. }
  1350. while (FALSE);
  1351. return (bDiscardMsg);
  1352. } // InitCompletionMessage
  1353. /****************************************************************************/
  1354. /* HaltMessage */
  1355. /****************************************************************************/
  1356. /* */
  1357. /* Routine Description: */
  1358. /* */
  1359. /* Process a HALT message from the device. */
  1360. /* */
  1361. /* Arguments: */
  1362. /* */
  1363. /* pAdapter - Pointer to our Adapter structure */
  1364. /* pMessage - pointer to RNDIS message */
  1365. /* pMdl - Pointer to MDL from microport */
  1366. /* TotalLength - length of complete message */
  1367. /* MicroportMessageContext - context for message from microport */
  1368. /* ReceiveStatus - used by microport to indicate it is low on resource */
  1369. /* bMessageCopied - is this a copy of the original message? */
  1370. /* */
  1371. /* Return: */
  1372. /* */
  1373. /* BOOLEAN - should the message be returned to the microport? */
  1374. /* */
  1375. /****************************************************************************/
  1376. BOOLEAN
  1377. HaltMessage(IN PRNDISMP_ADAPTER pAdapter,
  1378. IN PRNDIS_MESSAGE pMessage,
  1379. IN PMDL pMdl,
  1380. IN ULONG TotalLength,
  1381. IN NDIS_HANDLE MicroportMessageContext,
  1382. IN NDIS_STATUS ReceiveStatus,
  1383. IN BOOLEAN bMessageCopied)
  1384. {
  1385. TRACE1(("HaltMessage: Adapter %x\n", pAdapter));
  1386. #ifndef BUILD_WIN9X
  1387. // Not supported on Win98 Gold:
  1388. NdisMRemoveMiniport(pAdapter->MiniportAdapterHandle);
  1389. #endif
  1390. return TRUE;
  1391. } // HaltMessage
  1392. /****************************************************************************/
  1393. /* ResetCompletionMessage */
  1394. /****************************************************************************/
  1395. /* */
  1396. /* Routine Description: */
  1397. /* */
  1398. /* Completion message from microport in response to reset message miniport */
  1399. /* sent. Indicate this completion message to the upper layers since */
  1400. /* the miniport reset routine indicated STATUS_PENDING to the upper layers */
  1401. /* */
  1402. /* Arguments: */
  1403. /* */
  1404. /* pAdapter - Pointer to our Adapter structure */
  1405. /* pMessage - pointer to RNDIS message */
  1406. /* pMdl - Pointer to MDL from microport */
  1407. /* TotalLength - length of complete message */
  1408. /* MicroportMessageContext - context for message from microport */
  1409. /* ReceiveStatus - used by microport to indicate it is low on resource */
  1410. /* bMessageCopied - is this a copy of the original message? */
  1411. /* */
  1412. /* Return: */
  1413. /* */
  1414. /* BOOLEAN - should the message be returned to the microport? */
  1415. /* */
  1416. /****************************************************************************/
  1417. BOOLEAN
  1418. ResetCompletionMessage(IN PRNDISMP_ADAPTER pAdapter,
  1419. IN PRNDIS_MESSAGE pMessage,
  1420. IN PMDL pMdl,
  1421. IN ULONG TotalLength,
  1422. IN NDIS_HANDLE MicroportMessageContext,
  1423. IN NDIS_STATUS ReceiveStatus,
  1424. IN BOOLEAN bMessageCopied)
  1425. {
  1426. PRNDIS_RESET_COMPLETE pResetMessage;
  1427. BOOLEAN AddressingReset;
  1428. NDIS_STATUS Status;
  1429. TRACE2(("ResetCompletionMessage\n"));
  1430. pResetMessage = RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(pMessage);
  1431. // save these parameters to call to upper layers
  1432. Status = pResetMessage->Status;
  1433. AddressingReset = (BOOLEAN)pResetMessage->AddressingReset;
  1434. CompleteMiniportReset(pAdapter, Status, AddressingReset);
  1435. return TRUE;
  1436. } // ResetCompletionMessage
  1437. /****************************************************************************/
  1438. /* KeepAliveCompletionMessage */
  1439. /****************************************************************************/
  1440. /* */
  1441. /* Routine Description: */
  1442. /* */
  1443. /* Completion message for a keep alive request send down by miniport */
  1444. /* */
  1445. /* Arguments: */
  1446. /* */
  1447. /* pAdapter - Pointer to our Adapter structure */
  1448. /* pMessage - pointer to RNDIS message */
  1449. /* pMdl - Pointer to MDL from microport */
  1450. /* TotalLength - length of complete message */
  1451. /* MicroportMessageContext - context for message from microport */
  1452. /* ReceiveStatus - used by microport to indicate it is low on resource */
  1453. /* bMessageCopied - is this a copy of the original message? */
  1454. /* */
  1455. /* Return: */
  1456. /* */
  1457. /* BOOLEAN - should the message be returned to the microport? */
  1458. /* */
  1459. /****************************************************************************/
  1460. BOOLEAN
  1461. KeepAliveCompletionMessage(IN PRNDISMP_ADAPTER pAdapter,
  1462. IN PRNDIS_MESSAGE pMessage,
  1463. IN PMDL pMdl,
  1464. IN ULONG TotalLength,
  1465. IN NDIS_HANDLE MicroportMessageContext,
  1466. IN NDIS_STATUS ReceiveStatus,
  1467. IN BOOLEAN bMessageCopied)
  1468. {
  1469. PRNDIS_KEEPALIVE_COMPLETE pKeepaliveComplete;
  1470. NDIS_STATUS Status;
  1471. pKeepaliveComplete = RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(pMessage);
  1472. // save off status
  1473. Status = pKeepaliveComplete->Status;
  1474. TRACE2(("KeepAliveCompletionMessage (%d) on adapter %p\n",
  1475. pKeepaliveComplete->RequestId, pAdapter));
  1476. // grab the spinlock
  1477. NdisAcquireSpinLock(&pAdapter->Lock);
  1478. if (pKeepaliveComplete->RequestId != pAdapter->KeepAliveMessagePendingId)
  1479. {
  1480. TRACE0(("KeepAliveCompletion: Adapter %x, expected ID %x, got %x\n",
  1481. pAdapter,
  1482. pAdapter->KeepAliveMessagePendingId,
  1483. pKeepaliveComplete->RequestId));
  1484. //
  1485. // TBD - should we set NeedReset?
  1486. }
  1487. pAdapter->KeepAliveMessagePending = FALSE;
  1488. // if there are problems, tell the check for hang handler we need a reset
  1489. if (Status != NDIS_STATUS_SUCCESS)
  1490. {
  1491. TRACE0(("KeepAliveCompletion: Adapter %x, err status %x from device\n",
  1492. pAdapter, Status));
  1493. // indicate later from check for hang handler
  1494. pAdapter->NeedReset = TRUE;
  1495. }
  1496. // release spinlock
  1497. NdisReleaseSpinLock(&pAdapter->Lock);
  1498. return TRUE;
  1499. } // KeepAliveCompletionMessage
  1500. /****************************************************************************/
  1501. /* KeepAliveMessage */
  1502. /****************************************************************************/
  1503. /* */
  1504. /* Routine Description: */
  1505. /* */
  1506. /* Process a keepalive message sent by the device. Send back a completion. */
  1507. /* */
  1508. /* Arguments: */
  1509. /* */
  1510. /* pAdapter - Pointer to our Adapter structure */
  1511. /* pMessage - pointer to RNDIS message */
  1512. /* pMdl - Pointer to MDL from microport */
  1513. /* TotalLength - length of complete message */
  1514. /* MicroportMessageContext - context for message from microport */
  1515. /* ReceiveStatus - used by microport to indicate it is low on resource */
  1516. /* bMessageCopied - is this a copy of the original message? */
  1517. /* */
  1518. /* Return: */
  1519. /* */
  1520. /* BOOLEAN - should the message be returned to the microport? */
  1521. /* */
  1522. /****************************************************************************/
  1523. BOOLEAN
  1524. KeepAliveMessage(IN PRNDISMP_ADAPTER pAdapter,
  1525. IN PRNDIS_MESSAGE pMessage,
  1526. IN PMDL pMdl,
  1527. IN ULONG TotalLength,
  1528. IN NDIS_HANDLE MicroportMessageContext,
  1529. IN NDIS_STATUS ReceiveStatus,
  1530. IN BOOLEAN bMessageCopied)
  1531. {
  1532. PRNDIS_KEEPALIVE_REQUEST pKeepalive;
  1533. PRNDISMP_MESSAGE_FRAME pMsgFrame;
  1534. TRACE2(("KeepAliveMessage\n"));
  1535. pKeepalive = RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(pMessage);
  1536. //
  1537. // Send a response if we can.
  1538. //
  1539. pMsgFrame = BuildRndisMessageCommon(pAdapter,
  1540. NULL,
  1541. REMOTE_NDIS_KEEPALIVE_CMPLT,
  1542. 0,
  1543. &pKeepalive->RequestId,
  1544. sizeof(pKeepalive->RequestId));
  1545. if (pMsgFrame != NULL)
  1546. {
  1547. // send the message to the microport.
  1548. RNDISMP_SEND_TO_MICROPORT(pAdapter, pMsgFrame, FALSE, NULL);
  1549. }
  1550. else
  1551. {
  1552. TRACE1(("KeepAlive: Adapter %x: failed to alloc response!\n", pAdapter));
  1553. }
  1554. return TRUE;
  1555. } // KeepAliveMessage
  1556. /****************************************************************************/
  1557. /* RndismpShutdownHandler */
  1558. /****************************************************************************/
  1559. /* */
  1560. /* Routine Description: */
  1561. /* */
  1562. /* Removes an adapter instance that was previously initialized. Since the */
  1563. /* system is shutting down there is no need to release resources, just */
  1564. /* shutdown receive. */
  1565. /* */
  1566. /* Arguments: */
  1567. /* */
  1568. /* MiniportAdapterContext - a context version of our Adapter pointer */
  1569. /* */
  1570. /* Return: */
  1571. /* */
  1572. /* VOID */
  1573. /* */
  1574. /****************************************************************************/
  1575. VOID
  1576. RndismpShutdownHandler(IN NDIS_HANDLE MiniportAdapterContext)
  1577. {
  1578. PRNDISMP_ADAPTER Adapter;
  1579. // get adapter context
  1580. Adapter = PRNDISMP_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
  1581. TRACE1(("RndismpShutdownHandler\n"));
  1582. } // RndismpShutdownHandler
  1583. //
  1584. // Interrupt routines, stubbed up for now, we don't need them
  1585. //
  1586. /****************************************************************************/
  1587. /* RndismpDisableInterrupt */
  1588. /****************************************************************************/
  1589. /* */
  1590. /* Routine Description: */
  1591. /* */
  1592. /* */
  1593. /* Arguments: */
  1594. /* */
  1595. /* MiniportAdapterContext - a context version of our Adapter pointer */
  1596. /* */
  1597. /* Return: */
  1598. /* */
  1599. /* VOID */
  1600. /* */
  1601. /****************************************************************************/
  1602. VOID
  1603. RndismpDisableInterrupt(IN NDIS_HANDLE MiniportAdapterContext)
  1604. {
  1605. // NOP
  1606. } // RndismpDisableInterrupt
  1607. /****************************************************************************/
  1608. /* RndismpEnableInterrupt */
  1609. /****************************************************************************/
  1610. /* */
  1611. /* Routine Description: */
  1612. /* */
  1613. /* */
  1614. /* Arguments: */
  1615. /* */
  1616. /* MiniportAdapterContext - a context version of our Adapter pointer */
  1617. /* */
  1618. /* Return: */
  1619. /* */
  1620. /* VOID */
  1621. /* */
  1622. /****************************************************************************/
  1623. VOID
  1624. RndismpEnableInterrupt(IN NDIS_HANDLE MiniportAdapterContext)
  1625. {
  1626. // NOP
  1627. } // RndismpEnableInterrupt
  1628. /****************************************************************************/
  1629. /* RndismpHandleInterrupt */
  1630. /****************************************************************************/
  1631. /* */
  1632. /* Routine Description: */
  1633. /* */
  1634. /* */
  1635. /* Arguments: */
  1636. /* */
  1637. /* MiniportAdapterContext - a context version of our Adapter pointer */
  1638. /* */
  1639. /* Return: */
  1640. /* */
  1641. /* VOID */
  1642. /* */
  1643. /****************************************************************************/
  1644. VOID
  1645. RndismpHandleInterrupt(IN NDIS_HANDLE MiniportAdapterContext)
  1646. {
  1647. // NOP
  1648. } // RndismpHandleInterrupt
  1649. /****************************************************************************/
  1650. /* RndismpIsr */
  1651. /****************************************************************************/
  1652. /* */
  1653. /* Routine Description: */
  1654. /* */
  1655. /* This is the interrupt handler which is registered with the operating */
  1656. /* system. If several are pending (i.e. transmit complete and receive), */
  1657. /* handle them all. Block new interrupts until all pending interrupts */
  1658. /* are handled. */
  1659. /* */
  1660. /* Arguments: */
  1661. /* */
  1662. /* InterruptRecognized - Boolean value which returns TRUE if the */
  1663. /* ISR recognizes the interrupt as coming from this adapter. */
  1664. /* */
  1665. /* QueueDpc - TRUE if a DPC should be queued. */
  1666. /* */
  1667. /* Context - pointer to the adapter object */
  1668. /* */
  1669. /* Return: */
  1670. /* */
  1671. /* VOID */
  1672. /* */
  1673. /****************************************************************************/
  1674. VOID
  1675. RndismpIsr(OUT PBOOLEAN InterruptRecognized,
  1676. OUT PBOOLEAN QueueDpc,
  1677. IN PVOID Context)
  1678. {
  1679. ASSERT(FALSE); // don't expect to be called here.
  1680. } // RndismpIsr
  1681. /****************************************************************************/
  1682. /* CompleteSendInit */
  1683. /****************************************************************************/
  1684. /* */
  1685. /* Routine Description: */
  1686. /* */
  1687. /* Utility function to handle completion of sending of an INIT message. */
  1688. /* We simply free up the message frame. */
  1689. /* */
  1690. /* Arguments: */
  1691. /* */
  1692. /* pMsgFrame - Frame structure describing the INIT message */
  1693. /* SendStatus - outcome of sending this message. */
  1694. /* */
  1695. /* Return: */
  1696. /* */
  1697. /* VOID */
  1698. /* */
  1699. /****************************************************************************/
  1700. VOID
  1701. CompleteSendInit(IN PRNDISMP_MESSAGE_FRAME pMsgFrame,
  1702. IN NDIS_STATUS SendStatus)
  1703. {
  1704. PRNDISMP_ADAPTER pAdapter;
  1705. pAdapter = pMsgFrame->pAdapter;
  1706. TRACE1(("CompleteSendInit: Adapter %x, SendStatus %x\n", pAdapter, SendStatus));
  1707. DereferenceMsgFrame(pMsgFrame);
  1708. } // CompleteSendInit
  1709. /****************************************************************************/
  1710. /* CompleteSendHalt */
  1711. /****************************************************************************/
  1712. /* */
  1713. /* Routine Description: */
  1714. /* */
  1715. /* Utility function to handle completion of sending of a HALT message. */
  1716. /* We simply wake up the thread waiting for this. */
  1717. /* */
  1718. /* Arguments: */
  1719. /* */
  1720. /* pMsgFrame - Frame structure describing the HALT message */
  1721. /* SendStatus - outcome of sending this message. */
  1722. /* */
  1723. /* Return: */
  1724. /* */
  1725. /* VOID */
  1726. /* */
  1727. /****************************************************************************/
  1728. VOID
  1729. CompleteSendHalt(IN PRNDISMP_MESSAGE_FRAME pMsgFrame,
  1730. IN NDIS_STATUS SendStatus)
  1731. {
  1732. PRNDISMP_ADAPTER pAdapter;
  1733. pAdapter = pMsgFrame->pAdapter;
  1734. TRACE1(("CompleteSendHalt: Adapter %x, SendStatus %x\n", pAdapter, SendStatus));
  1735. ASSERT(pAdapter->Halting);
  1736. DereferenceMsgFrame(pMsgFrame);
  1737. NdisSetEvent(&pAdapter->HaltWaitEvent);
  1738. } // CompleteSendHalt
  1739. /****************************************************************************/
  1740. /* CompleteSendReset */
  1741. /****************************************************************************/
  1742. /* */
  1743. /* Routine Description: */
  1744. /* */
  1745. /* Callback routine to handle send-completion of a reset message by the */
  1746. /* microport. */
  1747. /* */
  1748. /* Arguments: */
  1749. /* */
  1750. /* pMsgFrame - Pointer to message frame for the Reset. */
  1751. /* SendStatus - Status of send */
  1752. /* */
  1753. /* Return: */
  1754. /* */
  1755. /* VOID */
  1756. /* */
  1757. /****************************************************************************/
  1758. VOID
  1759. CompleteSendReset(IN PRNDISMP_MESSAGE_FRAME pMsgFrame,
  1760. IN NDIS_STATUS SendStatus)
  1761. {
  1762. PRNDISMP_ADAPTER pAdapter;
  1763. pAdapter = pMsgFrame->pAdapter;
  1764. TRACE1(("CompleteSendReset: Adapter %x, SendStatus %x\n",
  1765. pAdapter, SendStatus));
  1766. DereferenceMsgFrame(pMsgFrame);
  1767. if (SendStatus != NDIS_STATUS_SUCCESS)
  1768. {
  1769. CompleteMiniportReset(pAdapter, SendStatus, FALSE);
  1770. }
  1771. }
  1772. /****************************************************************************/
  1773. /* CompleteMiniportReset */
  1774. /****************************************************************************/
  1775. /* */
  1776. /* Routine Description: */
  1777. /* */
  1778. /* Utility function to complete a pending NDIS Reset. We complete any */
  1779. /* pending requests/sets before indicating reset complete to NDIS. */
  1780. /* */
  1781. /* Arguments: */
  1782. /* */
  1783. /* pAdapter - Pointer to our adapter structure */
  1784. /* ResetStatus - to be used for completing reset */
  1785. /* AddressingReset - Do we need filters to be resent to us? */
  1786. /* */
  1787. /* Return: */
  1788. /* */
  1789. /* VOID */
  1790. /* */
  1791. /****************************************************************************/
  1792. VOID
  1793. CompleteMiniportReset(IN PRNDISMP_ADAPTER pAdapter,
  1794. IN NDIS_STATUS ResetStatus,
  1795. IN BOOLEAN AddressingReset)
  1796. {
  1797. LIST_ENTRY PendingRequests;
  1798. PLIST_ENTRY pEntry, pNext;
  1799. PRNDISMP_MESSAGE_FRAME pMsgFrame;
  1800. do
  1801. {
  1802. if (!pAdapter->ResetPending)
  1803. {
  1804. break;
  1805. }
  1806. pAdapter->ResetPending = FALSE;
  1807. //
  1808. // Take out all pending requests/sets queued on the adapter.
  1809. //
  1810. InitializeListHead(&PendingRequests);
  1811. RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
  1812. for (pEntry = pAdapter->PendingFrameList.Flink;
  1813. pEntry != &pAdapter->PendingFrameList;
  1814. pEntry = pNext)
  1815. {
  1816. pNext = pEntry->Flink;
  1817. pMsgFrame = CONTAINING_RECORD(pEntry, RNDISMP_MESSAGE_FRAME, Link);
  1818. if (pMsgFrame->NdisMessageType == REMOTE_NDIS_QUERY_MSG ||
  1819. pMsgFrame->NdisMessageType == REMOTE_NDIS_SET_MSG)
  1820. {
  1821. RemoveEntryList(pEntry);
  1822. InsertTailList(&PendingRequests, pEntry);
  1823. TRACE0(("RNDISMP: ResetComplete: taking out MsgFrame %x, msg type %x\n",
  1824. pMsgFrame, pMsgFrame->NdisMessageType));
  1825. }
  1826. }
  1827. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  1828. //
  1829. // Complete all these requests.
  1830. //
  1831. for (pEntry = PendingRequests.Flink;
  1832. pEntry != &PendingRequests;
  1833. pEntry = pNext)
  1834. {
  1835. pNext = pEntry->Flink;
  1836. pMsgFrame = CONTAINING_RECORD(pEntry, RNDISMP_MESSAGE_FRAME, Link);
  1837. TRACE0(("RNDISMP: ResetComplete: completing MsgFrame %x, msg type %x\n",
  1838. pMsgFrame, pMsgFrame->NdisMessageType));
  1839. ASSERT(pMsgFrame->pReqContext != NULL);
  1840. if (pMsgFrame->pReqContext->pNdisRequest != NULL)
  1841. {
  1842. //
  1843. // This request came down thru our MiniportCoRequest handler.
  1844. //
  1845. NdisMCoRequestComplete(NDIS_STATUS_REQUEST_ABORTED,
  1846. pAdapter->MiniportAdapterHandle,
  1847. pMsgFrame->pReqContext->pNdisRequest);
  1848. }
  1849. else
  1850. {
  1851. //
  1852. // This request came thru our connectionless query/set handler.
  1853. //
  1854. if (pMsgFrame->NdisMessageType == REMOTE_NDIS_QUERY_MSG)
  1855. {
  1856. NdisMQueryInformationComplete(pAdapter->MiniportAdapterHandle,
  1857. NDIS_STATUS_REQUEST_ABORTED);
  1858. }
  1859. else
  1860. {
  1861. ASSERT(pMsgFrame->NdisMessageType == REMOTE_NDIS_SET_MSG);
  1862. NdisMSetInformationComplete(pAdapter->MiniportAdapterHandle,
  1863. NDIS_STATUS_REQUEST_ABORTED);
  1864. }
  1865. }
  1866. FreeRequestContext(pAdapter, pMsgFrame->pReqContext);
  1867. pMsgFrame->pReqContext = (PRNDISMP_REQUEST_CONTEXT)UlongToPtr(0xabababab);
  1868. DereferenceMsgFrame(pMsgFrame);
  1869. }
  1870. TRACE0(("Completing reset on Adapter %x, Status %x, AddressingReset %d\n",
  1871. pAdapter, ResetStatus, AddressingReset));
  1872. RNDISMP_INCR_STAT(pAdapter, Resets);
  1873. //
  1874. // Complete the reset now.
  1875. //
  1876. NdisMResetComplete(pAdapter->MiniportAdapterHandle,
  1877. ResetStatus,
  1878. AddressingReset);
  1879. }
  1880. while (FALSE);
  1881. }
  1882. /****************************************************************************/
  1883. /* ReadAndSetRegistryParameters */
  1884. /****************************************************************************/
  1885. /* */
  1886. /* Routine Description: */
  1887. /* */
  1888. /* This is called when initializing a device, to read and send any */
  1889. /* registry parameters applicable to this device. */
  1890. /* */
  1891. /* We go through the entire list of configurable parameters by walking */
  1892. /* subkeys under the "ndi\Params" key. Each subkey represents one */
  1893. /* parameter. Using information about this parameter (specifically, its */
  1894. /* name and type), we query its value, and send a SetRequest to the */
  1895. /* device. */
  1896. /* */
  1897. /* Arguments: */
  1898. /* */
  1899. /* pAdapter - Pointer to adapter structure for the device */
  1900. /* ConfigurationContext - NDIS handle to access registry for this device */
  1901. /* */
  1902. /* Return: */
  1903. /* */
  1904. /* NDIS_STATUS */
  1905. /* */
  1906. /****************************************************************************/
  1907. NDIS_STATUS
  1908. ReadAndSetRegistryParameters(IN PRNDISMP_ADAPTER pAdapter,
  1909. IN NDIS_HANDLE ConfigurationContext)
  1910. {
  1911. NDIS_STATUS Status;
  1912. NDIS_HANDLE ConfigHandle;
  1913. NDIS_STRING NdiKeyName = NDIS_STRING_CONST("Ndi");
  1914. NDIS_HANDLE NdiKeyHandle = NULL;
  1915. Status = NDIS_STATUS_SUCCESS;
  1916. ConfigHandle = NULL;
  1917. do
  1918. {
  1919. NdisOpenConfiguration(&Status,
  1920. &ConfigHandle,
  1921. ConfigurationContext);
  1922. if (Status != NDIS_STATUS_SUCCESS)
  1923. {
  1924. break;
  1925. }
  1926. NdisOpenConfigurationKeyByName(
  1927. &Status,
  1928. ConfigHandle,
  1929. &NdiKeyName,
  1930. &NdiKeyHandle);
  1931. if (Status == NDIS_STATUS_SUCCESS)
  1932. {
  1933. NDIS_STRING ParamsKeyName = NDIS_STRING_CONST("Params");
  1934. NDIS_HANDLE ParamsKeyHandle = NULL;
  1935. NdisOpenConfigurationKeyByName(
  1936. &Status,
  1937. NdiKeyHandle,
  1938. &ParamsKeyName,
  1939. &ParamsKeyHandle);
  1940. if (Status == NDIS_STATUS_SUCCESS)
  1941. {
  1942. ULONG i;
  1943. BOOLEAN bDone = FALSE;
  1944. //
  1945. // Iterate through all subkeys under ndi\Params:
  1946. //
  1947. for (i = 0; !bDone; i++)
  1948. {
  1949. NDIS_STRING ParamSubKeyName;
  1950. NDIS_HANDLE ParamSubKeyHandle;
  1951. NDIS_STRING ParamTypeName = NDIS_STRING_CONST("type");
  1952. PNDIS_CONFIGURATION_PARAMETER pConfigParameter;
  1953. ParamSubKeyName.Length =
  1954. ParamSubKeyName.MaximumLength = 0;
  1955. ParamSubKeyName.Buffer = NULL;
  1956. NdisOpenConfigurationKeyByIndex(
  1957. &Status,
  1958. ParamsKeyHandle,
  1959. i,
  1960. &ParamSubKeyName,
  1961. &ParamSubKeyHandle);
  1962. if (Status != NDIS_STATUS_SUCCESS)
  1963. {
  1964. //
  1965. // Done with parameters. Cook return value.
  1966. //
  1967. Status = NDIS_STATUS_SUCCESS;
  1968. break;
  1969. }
  1970. //
  1971. // Got the handle to a subkey under ndi\Params,
  1972. // now read the type information for this parameter.
  1973. //
  1974. #ifndef BUILD_WIN9X
  1975. TRACE3(("ReadAndSetRegParams: subkey %d under ndi\\params: %ws\n",
  1976. i, ParamSubKeyName.Buffer));
  1977. #else
  1978. //
  1979. // Handle Win98Gold behavior.
  1980. //
  1981. if (ParamSubKeyName.Buffer == NULL)
  1982. {
  1983. PNDIS_STRING pNdisString;
  1984. pNdisString = *(PNDIS_STRING *)&ParamSubKeyName;
  1985. ParamSubKeyName = *pNdisString;
  1986. }
  1987. TRACE2(("ReadAndSetRegParams: subkey %d under ndi\\params: %ws\n",
  1988. i, ParamSubKeyName.Buffer));
  1989. #endif
  1990. //
  1991. // We have a parameter name now, in ParamSubKeyName.
  1992. // Get its type information.
  1993. //
  1994. NdisReadConfiguration(
  1995. &Status,
  1996. &pConfigParameter,
  1997. ParamSubKeyHandle,
  1998. &ParamTypeName,
  1999. NdisParameterString);
  2000. if (Status == NDIS_STATUS_SUCCESS)
  2001. {
  2002. TRACE2(("ReadAndSetRegParams: Adapter %p, type is %ws\n",
  2003. pAdapter,
  2004. pConfigParameter->ParameterData.StringData.Buffer));
  2005. //
  2006. // Send off a Set Request for this
  2007. // parameter to the device.
  2008. //
  2009. Status = SendConfiguredParameter(
  2010. pAdapter,
  2011. ConfigHandle,
  2012. &ParamSubKeyName,
  2013. &pConfigParameter->ParameterData.StringData);
  2014. if (Status != NDIS_STATUS_SUCCESS)
  2015. {
  2016. TRACE0(("ReadAndSetRegParams: Adapter %p, failed %x\n",
  2017. pAdapter, Status));
  2018. bDone = TRUE;
  2019. }
  2020. else
  2021. {
  2022. NDIS_STRING NetworkAddressName =
  2023. NDIS_STRING_CONST("NetworkAddress");
  2024. //
  2025. // Special case for the "NetworkAddress"
  2026. // parameter - if we just set this successfully,
  2027. // make note of the fact.
  2028. //
  2029. if (NdisEqualString(&ParamSubKeyName,
  2030. &NetworkAddressName,
  2031. TRUE))
  2032. {
  2033. TRACE1(("ReadAndSetRegParams: Adapter %p,"
  2034. " supports MAC address overwrite\n",
  2035. pAdapter));
  2036. pAdapter->MacOptions |=
  2037. NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE;
  2038. }
  2039. }
  2040. }
  2041. //
  2042. // Done with this subkey under ndi\Params.
  2043. //
  2044. NdisCloseConfiguration(ParamSubKeyHandle);
  2045. } // for each subkey under ndi\Params
  2046. //
  2047. // Done with "ndi\Params"
  2048. //
  2049. NdisCloseConfiguration(ParamsKeyHandle);
  2050. }
  2051. //
  2052. // Done with "ndi"
  2053. //
  2054. NdisCloseConfiguration(NdiKeyHandle);
  2055. }
  2056. //
  2057. // Done with configuration section for this device.
  2058. //
  2059. NdisCloseConfiguration(ConfigHandle);
  2060. }
  2061. while (FALSE);
  2062. return (Status);
  2063. }
  2064. /****************************************************************************/
  2065. /* SendConfiguredParameter */
  2066. /****************************************************************************/
  2067. /* */
  2068. /* Routine Description: */
  2069. /* */
  2070. /* Read the value of the specified config parameter, format a SetRequest, */
  2071. /* send it to the device, and wait for a response. */
  2072. /* */
  2073. /* Arguments: */
  2074. /* */
  2075. /* pAdapter - Pointer to adapter structure for the device */
  2076. /* ConfigHandle - handle to configuration section for this device */
  2077. /* pParameterName - parameter key name */
  2078. /* pParameterType - parameter type */
  2079. /* */
  2080. /* Return: */
  2081. /* */
  2082. /* NDIS_STATUS */
  2083. /* */
  2084. /****************************************************************************/
  2085. NDIS_STATUS
  2086. SendConfiguredParameter(IN PRNDISMP_ADAPTER pAdapter,
  2087. IN NDIS_HANDLE ConfigHandle,
  2088. IN PNDIS_STRING pParameterName,
  2089. IN PNDIS_STRING pParameterType)
  2090. {
  2091. PRNDISMP_MESSAGE_FRAME pMsgFrame = NULL;
  2092. PRNDISMP_MESSAGE_FRAME pPendingMsgFrame = NULL;
  2093. PRNDISMP_REQUEST_CONTEXT pReqContext = NULL;
  2094. NDIS_PARAMETER_TYPE NdisParameterType;
  2095. PNDIS_CONFIGURATION_PARAMETER pConfigParameter;
  2096. ULONG ParameterValueLength;
  2097. PUCHAR pParameterValue;
  2098. UINT32 ParameterType;
  2099. NDIS_EVENT Event;
  2100. UINT BytesRead;
  2101. BOOLEAN bWokenUp;
  2102. RNDIS_REQUEST_ID RequestId;
  2103. PRNDIS_CONFIG_PARAMETER_INFO pRndisConfigInfo = NULL;
  2104. ULONG RndisConfigInfoLength;
  2105. PUCHAR pConfigInfoBuf;
  2106. NDIS_STATUS Status;
  2107. struct {
  2108. NDIS_STRING TypeName;
  2109. NDIS_PARAMETER_TYPE NdisType;
  2110. } StringToNdisType[] =
  2111. {
  2112. {NDIS_STRING_CONST("int"), NdisParameterInteger},
  2113. {NDIS_STRING_CONST("long"), NdisParameterInteger},
  2114. {NDIS_STRING_CONST("word"), NdisParameterInteger},
  2115. {NDIS_STRING_CONST("dword"), NdisParameterInteger},
  2116. {NDIS_STRING_CONST("edit"), NdisParameterString},
  2117. {NDIS_STRING_CONST("enum"), NdisParameterString}
  2118. };
  2119. ULONG NumTypes = sizeof(StringToNdisType);
  2120. ULONG i;
  2121. do
  2122. {
  2123. //
  2124. // Determine the parameter type.
  2125. //
  2126. for (i = 0; i < NumTypes; i++)
  2127. {
  2128. if (NdisEqualString(&StringToNdisType[i].TypeName,
  2129. pParameterType,
  2130. TRUE))
  2131. {
  2132. NdisParameterType = StringToNdisType[i].NdisType;
  2133. break;
  2134. }
  2135. }
  2136. if (i == NumTypes)
  2137. {
  2138. TRACE1(("SendConfiguredParam: Adapter %p, Param %ws, invalid type %ws\n",
  2139. pAdapter,
  2140. pParameterName->Buffer,
  2141. pParameterType->Buffer));
  2142. Status = NDIS_STATUS_INVALID_DATA;
  2143. break;
  2144. }
  2145. NdisReadConfiguration(
  2146. &Status,
  2147. &pConfigParameter,
  2148. ConfigHandle,
  2149. pParameterName,
  2150. NdisParameterType
  2151. );
  2152. if (Status != NDIS_STATUS_SUCCESS)
  2153. {
  2154. //
  2155. // It is okay for a parameter to not be configured.
  2156. //
  2157. Status = NDIS_STATUS_SUCCESS;
  2158. break;
  2159. }
  2160. if (NdisParameterType == NdisParameterInteger)
  2161. {
  2162. ParameterValueLength = sizeof(UINT32);
  2163. pParameterValue = (PUCHAR)&pConfigParameter->ParameterData.IntegerData;
  2164. ParameterType = RNDIS_CONFIG_PARAM_TYPE_INTEGER;
  2165. }
  2166. else
  2167. {
  2168. ASSERT(NdisParameterType == NdisParameterString);
  2169. ParameterValueLength = pConfigParameter->ParameterData.StringData.Length;
  2170. pParameterValue = (PUCHAR)pConfigParameter->ParameterData.StringData.Buffer;
  2171. ParameterType = RNDIS_CONFIG_PARAM_TYPE_STRING;
  2172. }
  2173. RndisConfigInfoLength = sizeof(RNDIS_CONFIG_PARAMETER_INFO) +
  2174. pParameterName->Length +
  2175. ParameterValueLength;
  2176. Status = MemAlloc(&pRndisConfigInfo, RndisConfigInfoLength);
  2177. if (Status != NDIS_STATUS_SUCCESS)
  2178. {
  2179. break;
  2180. }
  2181. pRndisConfigInfo->ParameterNameOffset = sizeof(RNDIS_CONFIG_PARAMETER_INFO);
  2182. pRndisConfigInfo->ParameterNameLength = pParameterName->Length;
  2183. pRndisConfigInfo->ParameterType = ParameterType;
  2184. pRndisConfigInfo->ParameterValueOffset =
  2185. pRndisConfigInfo->ParameterNameOffset +
  2186. pRndisConfigInfo->ParameterNameLength;
  2187. pRndisConfigInfo->ParameterValueLength = ParameterValueLength;
  2188. //
  2189. // Copy in the parameter name.
  2190. //
  2191. pConfigInfoBuf = (PUCHAR)pRndisConfigInfo +
  2192. pRndisConfigInfo->ParameterNameOffset;
  2193. RNDISMP_MOVE_MEM(pConfigInfoBuf, pParameterName->Buffer, pParameterName->Length);
  2194. //
  2195. // Copy in the parameter value.
  2196. //
  2197. pConfigInfoBuf = (PUCHAR)pRndisConfigInfo +
  2198. pRndisConfigInfo->ParameterValueOffset;
  2199. RNDISMP_MOVE_MEM(pConfigInfoBuf, pParameterValue, ParameterValueLength);
  2200. //
  2201. // Build a Set Request
  2202. //
  2203. pMsgFrame = BuildRndisMessageCommon(pAdapter,
  2204. NULL,
  2205. REMOTE_NDIS_SET_MSG,
  2206. OID_GEN_RNDIS_CONFIG_PARAMETER,
  2207. pRndisConfigInfo,
  2208. RndisConfigInfoLength);
  2209. if (pMsgFrame == NULL)
  2210. {
  2211. Status = NDIS_STATUS_RESOURCES;
  2212. break;
  2213. }
  2214. #if DBG
  2215. {
  2216. PMDL pTmpMdl = pMsgFrame->pMessageMdl;
  2217. ULONG Length;
  2218. PUCHAR pBuf;
  2219. ULONG OldDebugFlags = RndismpDebugFlags;
  2220. Length = RNDISMP_GET_MDL_LENGTH(pTmpMdl);
  2221. pBuf = RNDISMP_GET_MDL_ADDRESS(pTmpMdl);
  2222. if (pBuf != NULL)
  2223. {
  2224. RndismpDebugFlags |= DBG_DUMP;
  2225. TRACEDUMP(("SetRequest (OID_GEN_RNDIS_CONFIG_PARAMETER):"
  2226. " Adapter %p, Param %ws\n", pAdapter, pParameterName->Buffer), pBuf, Length);
  2227. }
  2228. RndismpDebugFlags = OldDebugFlags;
  2229. }
  2230. #endif
  2231. pReqContext = AllocateRequestContext(pAdapter);
  2232. if (pReqContext == NULL)
  2233. {
  2234. Status = NDIS_STATUS_RESOURCES;
  2235. break;
  2236. }
  2237. // Fill up the request context.
  2238. pReqContext->pNdisRequest = NULL;
  2239. pReqContext->Oid = OID_GEN_RNDIS_CONFIG_PARAMETER;
  2240. NdisInitializeEvent(&Event);
  2241. pReqContext->pEvent = &Event;
  2242. pReqContext->bInternal = TRUE;
  2243. pReqContext->pBytesRead = &BytesRead;
  2244. pReqContext->InformationBufferLength = RndisConfigInfoLength;
  2245. pMsgFrame->pVc = NULL;
  2246. pMsgFrame->pReqContext = pReqContext;
  2247. // save off the request Id.
  2248. RequestId = pMsgFrame->RequestId;
  2249. // send the message to the microport.
  2250. RNDISMP_SEND_TO_MICROPORT(pAdapter, pMsgFrame, TRUE, NULL);
  2251. RNDISMP_ASSERT_AT_PASSIVE();
  2252. bWokenUp = NdisWaitEvent(&Event, MINIPORT_INIT_TIMEOUT);
  2253. // remove the message from the pending queue - it may or may not be there.
  2254. RNDISMP_LOOKUP_PENDING_MESSAGE(pPendingMsgFrame, pAdapter, RequestId);
  2255. if (!bWokenUp)
  2256. {
  2257. TRACE1(("No response to set parameter, Adapter %x\n", pAdapter));
  2258. Status = NDIS_STATUS_DEVICE_FAILED;
  2259. }
  2260. else
  2261. {
  2262. Status = pReqContext->CompletionStatus;
  2263. TRACE1(("Got response to set config param, Status %x, %d bytes read\n",
  2264. Status, BytesRead));
  2265. }
  2266. }
  2267. while (FALSE);
  2268. if (pRndisConfigInfo)
  2269. {
  2270. MemFree(pRndisConfigInfo, RndisConfigInfoLength);
  2271. }
  2272. if (pMsgFrame)
  2273. {
  2274. DereferenceMsgFrame(pMsgFrame);
  2275. }
  2276. if (pReqContext)
  2277. {
  2278. FreeRequestContext(pAdapter, pReqContext);
  2279. }
  2280. return (Status);
  2281. }
  2282. #ifdef NDIS51_MINIPORT
  2283. /****************************************************************************/
  2284. /* RndismpPnPEventNotify */
  2285. /****************************************************************************/
  2286. /* */
  2287. /* Routine Description: */
  2288. /* */
  2289. /* Entry point called by NDIS to notify us of PnP events affecting our */
  2290. /* device. The main event of importance to us is surprise removal. */
  2291. /* */
  2292. /* Arguments: */
  2293. /* */
  2294. /* pAdapter - Pointer to adapter structure */
  2295. /* */
  2296. /* Return: */
  2297. /* */
  2298. /* NDIS_STATUS */
  2299. /* */
  2300. /****************************************************************************/
  2301. VOID
  2302. RndismpPnPEventNotify(IN NDIS_HANDLE MiniportAdapterContext,
  2303. IN NDIS_DEVICE_PNP_EVENT EventCode,
  2304. IN PVOID InformationBuffer,
  2305. IN ULONG InformationBufferLength)
  2306. {
  2307. PRNDISMP_ADAPTER pAdapter;
  2308. // get adapter context
  2309. pAdapter = PRNDISMP_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
  2310. CHECK_VALID_ADAPTER(pAdapter);
  2311. TRACE3(("PnPEventNotify: Adapter %x\n", pAdapter));
  2312. switch (EventCode)
  2313. {
  2314. case NdisDevicePnPEventSurpriseRemoved:
  2315. TRACE1(("PnPEventNotify: Adapter %p, surprise remove\n", pAdapter));
  2316. RndismpInternalHalt(pAdapter, FALSE);
  2317. break;
  2318. default:
  2319. break;
  2320. }
  2321. } // RndismpPnPEventNotify
  2322. #endif // NDIS51_MINIPORT