Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2669 lines
108 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. #if THROTTLE_MESSAGES
  715. Adapter->HiWatPendedMessages = RNDISMP_PENDED_SEND_HIWAT;
  716. Adapter->LoWatPendedMessages = RNDISMP_PENDED_SEND_LOWAT;
  717. Adapter->CurPendedMessages = 0;
  718. Adapter->SendInProgress = FALSE;
  719. InitializeListHead(&Adapter->WaitingMessageList);
  720. #endif
  721. InitializeListHead(&Adapter->PendingAtMicroportList);
  722. Adapter->IndicatingReceives = FALSE;
  723. InitializeListHead(&Adapter->PendingRcvMessageList);
  724. NdisInitializeTimer(&Adapter->IndicateTimer, IndicateTimeout, (PVOID)Adapter);
  725. Adapter->SendProcessInProgress = FALSE;
  726. InitializeListHead(&Adapter->PendingSendProcessList);
  727. NdisInitializeTimer(&Adapter->SendProcessTimer, SendProcessTimeout, (PVOID)Adapter);
  728. TRACE2(("Adapter structure pointer is (%08X)\n", Adapter));
  729. NdisAllocateSpinLock(&Adapter->Lock);
  730. // get PDO to pass to microport
  731. NdisMGetDeviceProperty(MiniportAdapterHandle,
  732. &Pdo,
  733. &Fdo,
  734. &Ndo,
  735. NULL,
  736. NULL);
  737. #if NEW_NDIS_API_IN_MILLENNIUM
  738. {
  739. NDIS_STRING UnicodeString;
  740. Status = NdisMQueryAdapterInstanceName(&UnicodeString,
  741. Adapter->MiniportAdapterHandle);
  742. if (Status == NDIS_STATUS_SUCCESS)
  743. {
  744. TRACE1(("Init: NDIS returned len %d [%ws]\n",
  745. UnicodeString.Length, UnicodeString.Buffer));
  746. NdisFreeString(UnicodeString);
  747. }
  748. }
  749. #endif
  750. Adapter->pDeviceObject = Fdo;
  751. Adapter->pPhysDeviceObject = Pdo;
  752. Status = GetDeviceFriendlyName(Pdo,
  753. &Adapter->FriendlyNameAnsi,
  754. &Adapter->FriendlyNameUnicode);
  755. if (Status == NDIS_STATUS_SUCCESS)
  756. {
  757. TRACE1(("Init: Pdo %x, Ndo %x: Adapter %x: [%s]\n",
  758. Pdo, Ndo, Adapter, Adapter->FriendlyNameAnsi.Buffer));
  759. }
  760. else
  761. {
  762. Status = NDIS_STATUS_SUCCESS;
  763. }
  764. // Determine the platform we are running on. Ideally we would
  765. // like to do this from DriverEntry, but the NDIS API isn't
  766. // available until MiniportInit time.
  767. {
  768. NDIS_STATUS NdisStatus;
  769. PNDIS_CONFIGURATION_PARAMETER pParameter;
  770. NDIS_STRING VersionKey = NDIS_STRING_CONST("Environment");
  771. NdisReadConfiguration(
  772. &NdisStatus,
  773. &pParameter,
  774. ConfigurationHandle,
  775. &VersionKey,
  776. NdisParameterInteger);
  777. if ((NdisStatus == NDIS_STATUS_SUCCESS) &&
  778. ((pParameter->ParameterType == NdisParameterInteger) ||
  779. (pParameter->ParameterType == NdisParameterHexInteger)))
  780. {
  781. Adapter->bRunningOnWin9x =
  782. (pParameter->ParameterData.IntegerData == NdisEnvironmentWindows);
  783. TRACE1(("Init: Adapter %p, running on %s\n",
  784. Adapter,
  785. ((Adapter->bRunningOnWin9x)? "Win9X": "NT")));
  786. }
  787. else
  788. {
  789. TRACE1(("Init: ReadConfig: NdisStatus %x\n", NdisStatus));
  790. #if DBG
  791. if (NdisStatus == NDIS_STATUS_SUCCESS)
  792. {
  793. TRACE1(("Init: ReadConfig: parametertype %x\n",
  794. pParameter->ParameterType));
  795. }
  796. #endif // DBG
  797. Adapter->bRunningOnWin9x = TRUE;
  798. }
  799. }
  800. // find the driver block associated with this adapter
  801. DriverBlock = DeviceObjectToDriverBlock(&RndismpMiniportBlockListHead, Fdo);
  802. if (DriverBlock == NULL)
  803. {
  804. TRACE1(("Init: Can't find driver block for FDO %x!\n", Fdo));
  805. Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
  806. break;
  807. }
  808. // save the associated driver block in the adapter
  809. Adapter->DriverBlock = DriverBlock;
  810. Adapter->Signature = ADAPTER_SIGNATURE;
  811. // get handlers passed in from microport
  812. Adapter->RmInitializeHandler = DriverBlock->RmInitializeHandler;
  813. Adapter->RmInitCompleteNotifyHandler = DriverBlock->RmInitCompleteNotifyHandler;
  814. Adapter->RmHaltHandler = DriverBlock->RmHaltHandler;
  815. Adapter->RmShutdownHandler = DriverBlock->RmShutdownHandler;
  816. Adapter->RmSendMessageHandler = DriverBlock->RmSendMessageHandler;
  817. Adapter->RmReturnMessageHandler = DriverBlock->RmReturnMessageHandler;
  818. // call microport initialize handler
  819. //
  820. // Microport returns context
  821. // Pass in Miniport context
  822. // Pass in NDIS adapter handle
  823. // Pass in NDIS configuration handle
  824. // Pass in PDO for this adapter
  825. Status = Adapter->RmInitializeHandler(&Adapter->MicroportAdapterContext,
  826. &Adapter->MaxReceiveSize,
  827. (NDIS_HANDLE) Adapter,
  828. (NDIS_HANDLE) MiniportAdapterHandle,
  829. (NDIS_HANDLE) ConfigurationHandle,
  830. Ndo);
  831. if (Status != NDIS_STATUS_SUCCESS)
  832. {
  833. TRACE2(("Microport initialize handler failed (%08X)\n", Status));
  834. break;
  835. }
  836. bMicroportInitialized = TRUE;
  837. // everything looks good, so finish up
  838. Status = AllocateTransportResources(Adapter);
  839. if (Status != NDIS_STATUS_SUCCESS)
  840. {
  841. Status = NDIS_STATUS_RESOURCES;
  842. break;
  843. }
  844. // allocate space to receive a copy of the Initialize complete message in
  845. Status = MemAlloc(&Adapter->pInitCompleteMessage, sizeof(RNDIS_INITIALIZE_COMPLETE));
  846. if (Status != NDIS_STATUS_SUCCESS)
  847. {
  848. Status = NDIS_STATUS_RESOURCES;
  849. break;
  850. }
  851. // now we send down a RNDIS initialize message to the device
  852. pMsgFrame = BuildRndisMessageCommon(Adapter,
  853. NULL,
  854. REMOTE_NDIS_INITIALIZE_MSG,
  855. 0,
  856. (PVOID) NULL,
  857. 0);
  858. if (pMsgFrame == NULL)
  859. {
  860. Status = NDIS_STATUS_RESOURCES;
  861. break;
  862. }
  863. RequestId = pMsgFrame->RequestId;
  864. pReqContext = AllocateRequestContext(Adapter);
  865. if (pReqContext == NULL)
  866. {
  867. Status = NDIS_STATUS_RESOURCES;
  868. break;
  869. }
  870. pReqContext->pNdisRequest = NULL;
  871. NdisInitializeEvent(&Event);
  872. pReqContext->pEvent = &Event;
  873. pMsgFrame->pVc = NULL;
  874. pMsgFrame->pReqContext = pReqContext;
  875. RNDISMP_ASSERT_AT_PASSIVE();
  876. // send the message to the microport.
  877. RNDISMP_SEND_TO_MICROPORT(Adapter, pMsgFrame, TRUE, NULL);
  878. RNDISMP_ASSERT_AT_PASSIVE();
  879. // wait for message to complete
  880. bWokenUp = NdisWaitEvent(&Event, MINIPORT_INIT_TIMEOUT);
  881. // remove the message from the pending queue - it may or may not be there.
  882. RNDISMP_LOOKUP_PENDING_MESSAGE(pPendingMsgFrame, Adapter, RequestId);
  883. DereferenceMsgFrame(pMsgFrame);
  884. if (!bWokenUp)
  885. {
  886. // Failed to receive an Init complete within a reasonable time.
  887. TRACE1(("Init: Adapter %x, failed to receive Init complete\n", Adapter));
  888. Status = NDIS_STATUS_DEVICE_FAILED;
  889. break;
  890. }
  891. //
  892. // the init complete message from the device is now
  893. // copied over to our local structure
  894. //
  895. pInitCompleteMessage = Adapter->pInitCompleteMessage;
  896. if (pInitCompleteMessage->Status != NDIS_STATUS_SUCCESS)
  897. {
  898. Status = pInitCompleteMessage->Status;
  899. break;
  900. }
  901. // make sure this is a supported device.
  902. if (!(pInitCompleteMessage->DeviceFlags & (RNDIS_DF_CONNECTIONLESS | RNDIS_DF_RAW_DATA)) ||
  903. (pInitCompleteMessage->Medium != RNdisMedium802_3))
  904. {
  905. TRACE1(("Init: Complete: unknown DeviceFlags %x or Medium %d\n",
  906. pInitCompleteMessage->DeviceFlags,
  907. pInitCompleteMessage->Medium));
  908. Status = NDIS_STATUS_NOT_SUPPORTED;
  909. break;
  910. }
  911. if ((pInitCompleteMessage->DeviceFlags & RNDIS_DF_RAW_DATA)
  912. || (gRawEncap))
  913. {
  914. Adapter->MultipleSendFunc = DoMultipleSendRaw;
  915. } else
  916. {
  917. Adapter->MultipleSendFunc = DoMultipleSend;
  918. }
  919. Adapter->Medium = RNDIS_TO_NDIS_MEDIUM(pInitCompleteMessage->Medium);
  920. // get device parameters.
  921. Adapter->MaxPacketsPerMessage = pInitCompleteMessage->MaxPacketsPerMessage;
  922. if (Adapter->MaxPacketsPerMessage == 0)
  923. {
  924. Adapter->MaxPacketsPerMessage = 1;
  925. }
  926. #if HACK
  927. if (Adapter->MaxPacketsPerMessage > 1)
  928. {
  929. Adapter->MaxPacketsPerMessage = 2;
  930. }
  931. #endif // HACK
  932. Adapter->bMultiPacketSupported = (Adapter->MaxPacketsPerMessage > 1);
  933. Adapter->MaxTransferSize = pInitCompleteMessage->MaxTransferSize;
  934. PacketAlignmentFactor = pInitCompleteMessage->PacketAlignmentFactor;
  935. if (PacketAlignmentFactor > 7)
  936. {
  937. PacketAlignmentFactor = 7;
  938. }
  939. Adapter->AlignmentIncr = (1 << PacketAlignmentFactor);
  940. Adapter->AlignmentMask = ~((1 << PacketAlignmentFactor) - 1);
  941. #if DBG
  942. DbgPrint("RNDISMP: InitComp: Adapter %x, Version %d.%d, MaxPkt %d, AlignIncr %d, AlignMask %x, MaxXferSize %d\n",
  943. Adapter,
  944. pInitCompleteMessage->MajorVersion,
  945. pInitCompleteMessage->MinorVersion,
  946. Adapter->MaxPacketsPerMessage,
  947. Adapter->AlignmentIncr,
  948. Adapter->AlignmentMask,
  949. Adapter->MaxTransferSize);
  950. #endif // DBG
  951. // Get the medium type.
  952. for (Index = 0; Index < MediumArraySize; Index++)
  953. {
  954. if (MediumArray[Index] == Adapter->Medium)
  955. {
  956. break;
  957. }
  958. }
  959. if (Index == MediumArraySize)
  960. {
  961. TRACE1(("InitComp: Adapter %x, device returned unsupported medium %d\n",
  962. Adapter, pInitCompleteMessage->Medium));
  963. Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
  964. break;
  965. }
  966. *SelectedMediumIndex = Index;
  967. Adapter->DeviceFlags = pInitCompleteMessage->DeviceFlags;
  968. // call NdisMSetAttributesEx in order to let NDIS know
  969. // what kind of driver and features we support
  970. // interface type
  971. IfType = NdisInterfaceInternal;
  972. if (Adapter->bRunningOnWin9x)
  973. {
  974. //
  975. // NOTE! The 0x80000000 bit is set to let NDIS know
  976. // (Millennium only!) that our reconfig handler should
  977. // be called when the device is surprise-removed.
  978. //
  979. NdisMSetAttributesEx(Adapter->MiniportAdapterHandle,
  980. (NDIS_HANDLE) Adapter,
  981. 4,
  982. (ULONG) NDIS_ATTRIBUTE_DESERIALIZE | 0x80000000,
  983. IfType);
  984. }
  985. else
  986. {
  987. ULONG AttrFlags;
  988. AttrFlags = NDIS_ATTRIBUTE_DESERIALIZE |
  989. NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK;
  990. if (Adapter->DeviceFlags & RNDIS_DF_CONNECTIONLESS)
  991. {
  992. AttrFlags |= NDIS_ATTRIBUTE_NOT_CO_NDIS;
  993. }
  994. NdisMSetAttributesEx(Adapter->MiniportAdapterHandle,
  995. (NDIS_HANDLE) Adapter,
  996. 4,
  997. AttrFlags,
  998. IfType);
  999. }
  1000. // Tell the microport that the device completed Init
  1001. // successfully:
  1002. if (Adapter->RmInitCompleteNotifyHandler)
  1003. {
  1004. Status = Adapter->RmInitCompleteNotifyHandler(
  1005. Adapter->MicroportAdapterContext,
  1006. Adapter->DeviceFlags,
  1007. &Adapter->MaxTransferSize);
  1008. if (Status != NDIS_STATUS_SUCCESS)
  1009. {
  1010. break;
  1011. }
  1012. }
  1013. // get the list of supported OIDs from the device
  1014. pMsgFrame = BuildRndisMessageCommon(Adapter,
  1015. NULL,
  1016. REMOTE_NDIS_QUERY_MSG,
  1017. OID_GEN_SUPPORTED_LIST,
  1018. (PVOID) NULL,
  1019. 0);
  1020. if (pMsgFrame == NULL)
  1021. {
  1022. Status = NDIS_STATUS_RESOURCES;
  1023. break;
  1024. }
  1025. // link us on to the list of adapters for this driver block
  1026. AddAdapter(Adapter);
  1027. bLinkedAdapter = TRUE;
  1028. pReqContext->pNdisRequest = NULL;
  1029. pReqContext->Oid = OID_GEN_SUPPORTED_LIST;
  1030. pReqContext->CompletionStatus = NDIS_STATUS_SUCCESS;
  1031. NdisInitializeEvent(&Event);
  1032. pReqContext->pEvent = &Event;
  1033. pMsgFrame->pVc = NULL;
  1034. pMsgFrame->pReqContext = pReqContext;
  1035. // send the message to the microport.
  1036. RNDISMP_SEND_TO_MICROPORT(Adapter, pMsgFrame, TRUE, NULL);
  1037. RNDISMP_ASSERT_AT_PASSIVE();
  1038. bWokenUp = NdisWaitEvent(&Event, MINIPORT_INIT_TIMEOUT);
  1039. // remove the message from the pending queue - it may or may not be there.
  1040. RNDISMP_LOOKUP_PENDING_MESSAGE(pPendingMsgFrame, Adapter, RequestId);
  1041. DereferenceMsgFrame(pMsgFrame);
  1042. if (!bWokenUp || (Adapter->DriverOIDList == NULL))
  1043. {
  1044. // Failed to receive a response within a reasonable time,
  1045. // or the device failed this query.
  1046. //
  1047. TRACE1(("Init: Adapter %x, failed to receive response to OID_GEN_SUPPORTED_LIST\n", Adapter));
  1048. Status = NDIS_STATUS_DEVICE_FAILED;
  1049. ASSERT(FALSE);
  1050. break;
  1051. }
  1052. // Successfully queried the supported OID list.
  1053. #ifdef BUILD_WIN9X
  1054. //
  1055. // Attempt to support surprise removal of this device (Win98/SE)
  1056. // by intercepting config mgr messages forwarded by NDIS.
  1057. //
  1058. HookNtKernCMHandler(Adapter);
  1059. #endif
  1060. // send any registry parameters down to the device, if it supports them.
  1061. if (GetOIDSupport(Adapter, OID_GEN_RNDIS_CONFIG_PARAMETER) == DEVICE_SUPPORTED_OID)
  1062. {
  1063. Status = ReadAndSetRegistryParameters(Adapter, ConfigurationHandle);
  1064. if (Status != NDIS_STATUS_SUCCESS)
  1065. {
  1066. break;
  1067. }
  1068. }
  1069. // register a shutdown handler
  1070. NdisMRegisterAdapterShutdownHandler(Adapter->MiniportAdapterHandle,
  1071. (PVOID) Adapter,
  1072. RndismpShutdownHandler);
  1073. Adapter->TimerCancelled = FALSE;
  1074. Adapter->Initing = FALSE;
  1075. // initialize "KeepAlive" timer
  1076. NdisInitializeTimer(&Adapter->KeepAliveTimer,
  1077. KeepAliveTimerHandler,
  1078. (PVOID) Adapter);
  1079. NdisSetTimer(&Adapter->KeepAliveTimer, KEEP_ALIVE_TIMER / 2);
  1080. Status = NDIS_STATUS_SUCCESS;
  1081. }
  1082. while (FALSE);
  1083. if (Adapter)
  1084. {
  1085. if (Adapter->pInitCompleteMessage)
  1086. {
  1087. MemFree(Adapter->pInitCompleteMessage, sizeof(*Adapter->pInitCompleteMessage));
  1088. }
  1089. }
  1090. if (Status != NDIS_STATUS_SUCCESS)
  1091. {
  1092. TRACE1(("Failed to init adapter %x, status %x\n", Adapter, Status));
  1093. if (bMicroportInitialized)
  1094. {
  1095. ASSERT(Adapter);
  1096. Adapter->RmHaltHandler(Adapter->MicroportAdapterContext);
  1097. }
  1098. if (Adapter)
  1099. {
  1100. if (bLinkedAdapter)
  1101. {
  1102. RemoveAdapter(Adapter);
  1103. }
  1104. FreeAdapter(Adapter);
  1105. }
  1106. }
  1107. return Status;
  1108. } // RndismpInitialize
  1109. /****************************************************************************/
  1110. /* RndisMSendComplete */
  1111. /****************************************************************************/
  1112. /* */
  1113. /* Routine Description: */
  1114. /* */
  1115. /* Called by microport to indicate a message miniport sent is completed */
  1116. /* by microport */
  1117. /* */
  1118. /* Arguments: */
  1119. /* */
  1120. /* MiniportAdapterContext - a context version of our Adapter pointer */
  1121. /* RndisMessageHandle - context used by miniport */
  1122. /* SendStatus - indicate status of send message */
  1123. /* */
  1124. /* Return: */
  1125. /* */
  1126. /* VOID */
  1127. /* */
  1128. /****************************************************************************/
  1129. VOID
  1130. RndisMSendComplete(IN NDIS_HANDLE MiniportAdapterContext,
  1131. IN NDIS_HANDLE RndisMessageHandle,
  1132. IN NDIS_STATUS SendStatus)
  1133. {
  1134. PRNDISMP_ADAPTER Adapter;
  1135. PRNDISMP_MESSAGE_FRAME pMsgFrame;
  1136. // get adapter context
  1137. Adapter = PRNDISMP_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
  1138. CHECK_VALID_ADAPTER(Adapter);
  1139. pMsgFrame = MESSAGE_FRAME_FROM_HANDLE(RndisMessageHandle);
  1140. CHECK_VALID_FRAME(pMsgFrame);
  1141. ASSERT(pMsgFrame->pAdapter == Adapter);
  1142. TRACE2(("RndisMSendComplete: Adapter %x, MsgFrame %x, MDL %x\n", Adapter, pMsgFrame, pMsgFrame->pMessageMdl));
  1143. if ((SendStatus != NDIS_STATUS_SUCCESS) &&
  1144. (SendStatus != NDIS_STATUS_RESOURCES))
  1145. {
  1146. RNDISMP_INCR_STAT(Adapter, MicroportSendError);
  1147. TRACE0(("RndisMSendComplete: Adapter %x, MsgFrame %x, MDL %x, ERROR %x\n",
  1148. Adapter,
  1149. pMsgFrame,
  1150. pMsgFrame->pMessageMdl,
  1151. SendStatus));
  1152. }
  1153. #if THROTTLE_MESSAGES
  1154. RNDISMP_ACQUIRE_ADAPTER_LOCK(Adapter);
  1155. Adapter->CurPendedMessages--;
  1156. RemoveEntryList(&pMsgFrame->PendLink);
  1157. if (SendStatus == NDIS_STATUS_RESOURCES)
  1158. {
  1159. RNDISMP_INCR_STAT(Adapter, SendMsgLowRes);
  1160. }
  1161. if ((SendStatus != NDIS_STATUS_RESOURCES) ||
  1162. (Adapter->CurPendedMessages < 2))
  1163. {
  1164. if (Adapter->CurPendedMessages == Adapter->LoWatPendedMessages)
  1165. {
  1166. RNDISMP_RELEASE_ADAPTER_LOCK(Adapter);
  1167. QueueMessageToMicroport(Adapter, NULL, FALSE);
  1168. }
  1169. else
  1170. {
  1171. RNDISMP_RELEASE_ADAPTER_LOCK(Adapter);
  1172. }
  1173. if (SendStatus == NDIS_STATUS_RESOURCES)
  1174. {
  1175. TRACE1(("RndisMSendComplete: Adapter %x, got resources\n", Adapter));
  1176. SendStatus = NDIS_STATUS_SUCCESS;
  1177. }
  1178. if (pMsgFrame->pCallback)
  1179. {
  1180. (*pMsgFrame->pCallback)(pMsgFrame, SendStatus);
  1181. }
  1182. else
  1183. {
  1184. //
  1185. // Do nothing. The sender will take care of freeing
  1186. // this.
  1187. //
  1188. }
  1189. }
  1190. else
  1191. {
  1192. //
  1193. // The microport is out of send resources. Requeue this
  1194. // and adjust water marks.
  1195. //
  1196. InsertHeadList(&Adapter->WaitingMessageList, &pMsgFrame->PendLink);
  1197. Adapter->HiWatPendedMessages = Adapter->CurPendedMessages;
  1198. Adapter->LoWatPendedMessages = Adapter->CurPendedMessages / 2;
  1199. TRACE1(("RndisMSendComplete: Adapter %x, new Hiwat %d, Lowat %d\n",
  1200. Adapter, Adapter->HiWatPendedMessages, Adapter->LoWatPendedMessages));
  1201. RNDISMP_RELEASE_ADAPTER_LOCK(Adapter);
  1202. }
  1203. #else
  1204. if (pMsgFrame->pCallback)
  1205. {
  1206. (*pMsgFrame->pCallback)(pMsgFrame, SendStatus);
  1207. }
  1208. else
  1209. {
  1210. //
  1211. // Do nothing. The sender will take care of freeing
  1212. // this.
  1213. //
  1214. }
  1215. #endif // THROTTLE_MESSAGES
  1216. } // RndisMSendComplete
  1217. /****************************************************************************/
  1218. /* InitCompletionMessage */
  1219. /****************************************************************************/
  1220. /* */
  1221. /* Routine Description: */
  1222. /* */
  1223. /* Completion message from microport in response to init message miniport */
  1224. /* sent. The init message was sent from the adapter init routine which is */
  1225. /* waiting for this event to unblock */
  1226. /* */
  1227. /* Arguments: */
  1228. /* */
  1229. /* pAdapter - Pointer to our adapter structure */
  1230. /* pMessage - Pointer to RNDIS message */
  1231. /* pMdl - Pointer to MDL received from microport */
  1232. /* TotalLength - length of complete message */
  1233. /* MicroportMessageContext - context for message from micorport */
  1234. /* ReceiveStatus - used by microport to indicate it is low on resource */
  1235. /* bMessageCopied - is this a copy of the original message? */
  1236. /* */
  1237. /* Return: */
  1238. /* */
  1239. /* BOOLEAN - should the message be returned to the microport? */
  1240. /* */
  1241. /****************************************************************************/
  1242. BOOLEAN
  1243. InitCompletionMessage(IN PRNDISMP_ADAPTER pAdapter,
  1244. IN PRNDIS_MESSAGE pMessage,
  1245. IN PMDL pMdl,
  1246. IN ULONG TotalLength,
  1247. IN NDIS_HANDLE MicroportMessageContext,
  1248. IN NDIS_STATUS ReceiveStatus,
  1249. IN BOOLEAN bMessageCopied)
  1250. {
  1251. PRNDIS_INITIALIZE_COMPLETE pInitCompleteMessage;
  1252. PRNDISMP_MESSAGE_FRAME pMsgFrame;
  1253. PRNDISMP_REQUEST_CONTEXT pReqContext;
  1254. BOOLEAN bDiscardMsg = TRUE;
  1255. TRACE2(("InitCompletionMessage\n"));
  1256. do
  1257. {
  1258. if (pMessage->MessageLength < RNDISMP_MIN_MESSAGE_LENGTH(InitializeComplete))
  1259. {
  1260. TRACE1(("InitCompletion: Message length (%d) too short, expect at least (%d)\n",
  1261. pMessage->MessageLength,
  1262. RNDISMP_MIN_MESSAGE_LENGTH(InitializeComplete)));
  1263. break;
  1264. }
  1265. if (pAdapter->pInitCompleteMessage == NULL)
  1266. {
  1267. TRACE1(("InitCompletion: multiple InitComplete from device, ignored\n"));
  1268. break;
  1269. }
  1270. pInitCompleteMessage = RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(pMessage);
  1271. // get request frame from request ID in message
  1272. RNDISMP_LOOKUP_PENDING_MESSAGE(pMsgFrame, pAdapter, pInitCompleteMessage->RequestId);
  1273. if (pMsgFrame == NULL)
  1274. {
  1275. // invalid request ID or aborted request.
  1276. TRACE1(("Invalid request ID %d in Init Complete\n",
  1277. pInitCompleteMessage->RequestId));
  1278. break;
  1279. }
  1280. pReqContext = pMsgFrame->pReqContext;
  1281. RNDISMP_MOVE_MEM(pAdapter->pInitCompleteMessage,
  1282. pInitCompleteMessage,
  1283. sizeof(*pInitCompleteMessage));
  1284. // signal the adapter init routine we are done
  1285. NdisSetEvent(pReqContext->pEvent);
  1286. }
  1287. while (FALSE);
  1288. return (bDiscardMsg);
  1289. } // InitCompletionMessage
  1290. /****************************************************************************/
  1291. /* HaltMessage */
  1292. /****************************************************************************/
  1293. /* */
  1294. /* Routine Description: */
  1295. /* */
  1296. /* Process a HALT message from the device. */
  1297. /* */
  1298. /* Arguments: */
  1299. /* */
  1300. /* pAdapter - Pointer to our Adapter structure */
  1301. /* pMessage - pointer to RNDIS message */
  1302. /* pMdl - Pointer to MDL from microport */
  1303. /* TotalLength - length of complete message */
  1304. /* MicroportMessageContext - context for message from microport */
  1305. /* ReceiveStatus - used by microport to indicate it is low on resource */
  1306. /* bMessageCopied - is this a copy of the original message? */
  1307. /* */
  1308. /* Return: */
  1309. /* */
  1310. /* BOOLEAN - should the message be returned to the microport? */
  1311. /* */
  1312. /****************************************************************************/
  1313. BOOLEAN
  1314. HaltMessage(IN PRNDISMP_ADAPTER pAdapter,
  1315. IN PRNDIS_MESSAGE pMessage,
  1316. IN PMDL pMdl,
  1317. IN ULONG TotalLength,
  1318. IN NDIS_HANDLE MicroportMessageContext,
  1319. IN NDIS_STATUS ReceiveStatus,
  1320. IN BOOLEAN bMessageCopied)
  1321. {
  1322. TRACE1(("HaltMessage: Adapter %x\n", pAdapter));
  1323. #ifndef BUILD_WIN9X
  1324. // Not supported on Win98 Gold:
  1325. NdisMRemoveMiniport(pAdapter->MiniportAdapterHandle);
  1326. #endif
  1327. return TRUE;
  1328. } // HaltMessage
  1329. /****************************************************************************/
  1330. /* ResetCompletionMessage */
  1331. /****************************************************************************/
  1332. /* */
  1333. /* Routine Description: */
  1334. /* */
  1335. /* Completion message from microport in response to reset message miniport */
  1336. /* sent. Indicate this completion message to the upper layers since */
  1337. /* the miniport reset routine indicated STATUS_PENDING to the upper layers */
  1338. /* */
  1339. /* Arguments: */
  1340. /* */
  1341. /* pAdapter - Pointer to our Adapter structure */
  1342. /* pMessage - pointer to RNDIS message */
  1343. /* pMdl - Pointer to MDL from microport */
  1344. /* TotalLength - length of complete message */
  1345. /* MicroportMessageContext - context for message from microport */
  1346. /* ReceiveStatus - used by microport to indicate it is low on resource */
  1347. /* bMessageCopied - is this a copy of the original message? */
  1348. /* */
  1349. /* Return: */
  1350. /* */
  1351. /* BOOLEAN - should the message be returned to the microport? */
  1352. /* */
  1353. /****************************************************************************/
  1354. BOOLEAN
  1355. ResetCompletionMessage(IN PRNDISMP_ADAPTER pAdapter,
  1356. IN PRNDIS_MESSAGE pMessage,
  1357. IN PMDL pMdl,
  1358. IN ULONG TotalLength,
  1359. IN NDIS_HANDLE MicroportMessageContext,
  1360. IN NDIS_STATUS ReceiveStatus,
  1361. IN BOOLEAN bMessageCopied)
  1362. {
  1363. PRNDIS_RESET_COMPLETE pResetMessage;
  1364. BOOLEAN AddressingReset;
  1365. NDIS_STATUS Status;
  1366. TRACE2(("ResetCompletionMessage\n"));
  1367. pResetMessage = RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(pMessage);
  1368. // save these parameters to call to upper layers
  1369. Status = pResetMessage->Status;
  1370. AddressingReset = (BOOLEAN)pResetMessage->AddressingReset;
  1371. CompleteMiniportReset(pAdapter, Status, AddressingReset);
  1372. return TRUE;
  1373. } // ResetCompletionMessage
  1374. /****************************************************************************/
  1375. /* KeepAliveCompletionMessage */
  1376. /****************************************************************************/
  1377. /* */
  1378. /* Routine Description: */
  1379. /* */
  1380. /* Completion message for a keep alive request send down by miniport */
  1381. /* */
  1382. /* Arguments: */
  1383. /* */
  1384. /* pAdapter - Pointer to our Adapter structure */
  1385. /* pMessage - pointer to RNDIS message */
  1386. /* pMdl - Pointer to MDL from microport */
  1387. /* TotalLength - length of complete message */
  1388. /* MicroportMessageContext - context for message from microport */
  1389. /* ReceiveStatus - used by microport to indicate it is low on resource */
  1390. /* bMessageCopied - is this a copy of the original message? */
  1391. /* */
  1392. /* Return: */
  1393. /* */
  1394. /* BOOLEAN - should the message be returned to the microport? */
  1395. /* */
  1396. /****************************************************************************/
  1397. BOOLEAN
  1398. KeepAliveCompletionMessage(IN PRNDISMP_ADAPTER pAdapter,
  1399. IN PRNDIS_MESSAGE pMessage,
  1400. IN PMDL pMdl,
  1401. IN ULONG TotalLength,
  1402. IN NDIS_HANDLE MicroportMessageContext,
  1403. IN NDIS_STATUS ReceiveStatus,
  1404. IN BOOLEAN bMessageCopied)
  1405. {
  1406. PRNDIS_KEEPALIVE_COMPLETE pKeepaliveComplete;
  1407. NDIS_STATUS Status;
  1408. TRACE2(("KeepAliveCompletionMessage\n"));
  1409. pKeepaliveComplete = RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(pMessage);
  1410. // save off status
  1411. Status = pKeepaliveComplete->Status;
  1412. // grab the spinlock
  1413. NdisAcquireSpinLock(&pAdapter->Lock);
  1414. if (pKeepaliveComplete->RequestId != pAdapter->KeepAliveMessagePendingId)
  1415. {
  1416. TRACE0(("KeepAliveCompletion: Adapter %x, expected ID %x, got %x\n",
  1417. pAdapter,
  1418. pAdapter->KeepAliveMessagePendingId,
  1419. pKeepaliveComplete->RequestId));
  1420. //
  1421. // TBD - should we set NeedReset?
  1422. }
  1423. pAdapter->KeepAliveMessagePending = FALSE;
  1424. // if there are problems, tell the check for hang handler we need a reset
  1425. if (Status != NDIS_STATUS_SUCCESS)
  1426. {
  1427. TRACE0(("KeepAliveCompletion: Adapter %x, err status %x from device\n",
  1428. pAdapter, Status));
  1429. // indicate later from check for hang handler
  1430. pAdapter->NeedReset = TRUE;
  1431. }
  1432. // release spinlock
  1433. NdisReleaseSpinLock(&pAdapter->Lock);
  1434. return TRUE;
  1435. } // KeepAliveCompletionMessage
  1436. /****************************************************************************/
  1437. /* KeepAliveMessage */
  1438. /****************************************************************************/
  1439. /* */
  1440. /* Routine Description: */
  1441. /* */
  1442. /* Process a keepalive message sent by the device. Send back a completion. */
  1443. /* */
  1444. /* Arguments: */
  1445. /* */
  1446. /* pAdapter - Pointer to our Adapter structure */
  1447. /* pMessage - pointer to RNDIS message */
  1448. /* pMdl - Pointer to MDL from microport */
  1449. /* TotalLength - length of complete message */
  1450. /* MicroportMessageContext - context for message from microport */
  1451. /* ReceiveStatus - used by microport to indicate it is low on resource */
  1452. /* bMessageCopied - is this a copy of the original message? */
  1453. /* */
  1454. /* Return: */
  1455. /* */
  1456. /* BOOLEAN - should the message be returned to the microport? */
  1457. /* */
  1458. /****************************************************************************/
  1459. BOOLEAN
  1460. KeepAliveMessage(IN PRNDISMP_ADAPTER pAdapter,
  1461. IN PRNDIS_MESSAGE pMessage,
  1462. IN PMDL pMdl,
  1463. IN ULONG TotalLength,
  1464. IN NDIS_HANDLE MicroportMessageContext,
  1465. IN NDIS_STATUS ReceiveStatus,
  1466. IN BOOLEAN bMessageCopied)
  1467. {
  1468. PRNDIS_KEEPALIVE_REQUEST pKeepalive;
  1469. PRNDISMP_MESSAGE_FRAME pMsgFrame;
  1470. TRACE2(("KeepAliveMessage\n"));
  1471. pKeepalive = RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(pMessage);
  1472. //
  1473. // Send a response if we can.
  1474. //
  1475. pMsgFrame = BuildRndisMessageCommon(pAdapter,
  1476. NULL,
  1477. REMOTE_NDIS_KEEPALIVE_CMPLT,
  1478. 0,
  1479. &pKeepalive->RequestId,
  1480. sizeof(pKeepalive->RequestId));
  1481. if (pMsgFrame != NULL)
  1482. {
  1483. // send the message to the microport.
  1484. RNDISMP_SEND_TO_MICROPORT(pAdapter, pMsgFrame, FALSE, NULL);
  1485. }
  1486. else
  1487. {
  1488. TRACE1(("KeepAlive: Adapter %x: failed to alloc response!\n", pAdapter));
  1489. }
  1490. return TRUE;
  1491. } // KeepAliveMessage
  1492. /****************************************************************************/
  1493. /* RndismpShutdownHandler */
  1494. /****************************************************************************/
  1495. /* */
  1496. /* Routine Description: */
  1497. /* */
  1498. /* Removes an adapter instance that was previously initialized. Since the */
  1499. /* system is shutting down there is no need to release resources, just */
  1500. /* shutdown receive. */
  1501. /* */
  1502. /* Arguments: */
  1503. /* */
  1504. /* MiniportAdapterContext - a context version of our Adapter pointer */
  1505. /* */
  1506. /* Return: */
  1507. /* */
  1508. /* VOID */
  1509. /* */
  1510. /****************************************************************************/
  1511. VOID
  1512. RndismpShutdownHandler(IN NDIS_HANDLE MiniportAdapterContext)
  1513. {
  1514. PRNDISMP_ADAPTER Adapter;
  1515. // get adapter context
  1516. Adapter = PRNDISMP_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
  1517. TRACE1(("RndismpShutdownHandler\n"));
  1518. } // RndismpShutdownHandler
  1519. //
  1520. // Interrupt routines, stubbed up for now, we don't need them
  1521. //
  1522. /****************************************************************************/
  1523. /* RndismpDisableInterrupt */
  1524. /****************************************************************************/
  1525. /* */
  1526. /* Routine Description: */
  1527. /* */
  1528. /* */
  1529. /* Arguments: */
  1530. /* */
  1531. /* MiniportAdapterContext - a context version of our Adapter pointer */
  1532. /* */
  1533. /* Return: */
  1534. /* */
  1535. /* VOID */
  1536. /* */
  1537. /****************************************************************************/
  1538. VOID
  1539. RndismpDisableInterrupt(IN NDIS_HANDLE MiniportAdapterContext)
  1540. {
  1541. // NOP
  1542. } // RndismpDisableInterrupt
  1543. /****************************************************************************/
  1544. /* RndismpEnableInterrupt */
  1545. /****************************************************************************/
  1546. /* */
  1547. /* Routine Description: */
  1548. /* */
  1549. /* */
  1550. /* Arguments: */
  1551. /* */
  1552. /* MiniportAdapterContext - a context version of our Adapter pointer */
  1553. /* */
  1554. /* Return: */
  1555. /* */
  1556. /* VOID */
  1557. /* */
  1558. /****************************************************************************/
  1559. VOID
  1560. RndismpEnableInterrupt(IN NDIS_HANDLE MiniportAdapterContext)
  1561. {
  1562. // NOP
  1563. } // RndismpEnableInterrupt
  1564. /****************************************************************************/
  1565. /* RndismpHandleInterrupt */
  1566. /****************************************************************************/
  1567. /* */
  1568. /* Routine Description: */
  1569. /* */
  1570. /* */
  1571. /* Arguments: */
  1572. /* */
  1573. /* MiniportAdapterContext - a context version of our Adapter pointer */
  1574. /* */
  1575. /* Return: */
  1576. /* */
  1577. /* VOID */
  1578. /* */
  1579. /****************************************************************************/
  1580. VOID
  1581. RndismpHandleInterrupt(IN NDIS_HANDLE MiniportAdapterContext)
  1582. {
  1583. // NOP
  1584. } // RndismpHandleInterrupt
  1585. /****************************************************************************/
  1586. /* RndismpIsr */
  1587. /****************************************************************************/
  1588. /* */
  1589. /* Routine Description: */
  1590. /* */
  1591. /* This is the interrupt handler which is registered with the operating */
  1592. /* system. If several are pending (i.e. transmit complete and receive), */
  1593. /* handle them all. Block new interrupts until all pending interrupts */
  1594. /* are handled. */
  1595. /* */
  1596. /* Arguments: */
  1597. /* */
  1598. /* InterruptRecognized - Boolean value which returns TRUE if the */
  1599. /* ISR recognizes the interrupt as coming from this adapter. */
  1600. /* */
  1601. /* QueueDpc - TRUE if a DPC should be queued. */
  1602. /* */
  1603. /* Context - pointer to the adapter object */
  1604. /* */
  1605. /* Return: */
  1606. /* */
  1607. /* VOID */
  1608. /* */
  1609. /****************************************************************************/
  1610. VOID
  1611. RndismpIsr(OUT PBOOLEAN InterruptRecognized,
  1612. OUT PBOOLEAN QueueDpc,
  1613. IN PVOID Context)
  1614. {
  1615. ASSERT(FALSE); // don't expect to be called here.
  1616. } // RndismpIsr
  1617. /****************************************************************************/
  1618. /* CompleteSendHalt */
  1619. /****************************************************************************/
  1620. /* */
  1621. /* Routine Description: */
  1622. /* */
  1623. /* Utility function to handle completion of sending of a HALT message. */
  1624. /* We simply wake up the thread waiting for this. */
  1625. /* */
  1626. /* Arguments: */
  1627. /* */
  1628. /* pMsgFrame - Frame structure describing the HALT message */
  1629. /* SendStatus - outcome of sending this message. */
  1630. /* */
  1631. /* Return: */
  1632. /* */
  1633. /* VOID */
  1634. /* */
  1635. /****************************************************************************/
  1636. VOID
  1637. CompleteSendHalt(IN PRNDISMP_MESSAGE_FRAME pMsgFrame,
  1638. IN NDIS_STATUS SendStatus)
  1639. {
  1640. PRNDISMP_ADAPTER pAdapter;
  1641. pAdapter = pMsgFrame->pAdapter;
  1642. TRACE1(("CompleteSendHalt: Adapter %x, SendStatus %x\n", pAdapter, SendStatus));
  1643. ASSERT(pAdapter->Halting);
  1644. DereferenceMsgFrame(pMsgFrame);
  1645. NdisSetEvent(&pAdapter->HaltWaitEvent);
  1646. } // CompleteSendHalt
  1647. /****************************************************************************/
  1648. /* CompleteSendReset */
  1649. /****************************************************************************/
  1650. /* */
  1651. /* Routine Description: */
  1652. /* */
  1653. /* Callback routine to handle send-completion of a reset message by the */
  1654. /* microport. */
  1655. /* */
  1656. /* Arguments: */
  1657. /* */
  1658. /* pMsgFrame - Pointer to message frame for the Reset. */
  1659. /* SendStatus - Status of send */
  1660. /* */
  1661. /* Return: */
  1662. /* */
  1663. /* VOID */
  1664. /* */
  1665. /****************************************************************************/
  1666. VOID
  1667. CompleteSendReset(IN PRNDISMP_MESSAGE_FRAME pMsgFrame,
  1668. IN NDIS_STATUS SendStatus)
  1669. {
  1670. PRNDISMP_ADAPTER pAdapter;
  1671. pAdapter = pMsgFrame->pAdapter;
  1672. TRACE1(("CompleteSendReset: Adapter %x, SendStatus %x\n",
  1673. pAdapter, SendStatus));
  1674. DereferenceMsgFrame(pMsgFrame);
  1675. if (SendStatus != NDIS_STATUS_SUCCESS)
  1676. {
  1677. CompleteMiniportReset(pAdapter, SendStatus, FALSE);
  1678. }
  1679. }
  1680. /****************************************************************************/
  1681. /* CompleteMiniportReset */
  1682. /****************************************************************************/
  1683. /* */
  1684. /* Routine Description: */
  1685. /* */
  1686. /* Utility function to complete a pending NDIS Reset. We complete any */
  1687. /* pending requests/sets before indicating reset complete to NDIS. */
  1688. /* */
  1689. /* Arguments: */
  1690. /* */
  1691. /* pAdapter - Pointer to our adapter structure */
  1692. /* ResetStatus - to be used for completing reset */
  1693. /* AddressingReset - Do we need filters to be resent to us? */
  1694. /* */
  1695. /* Return: */
  1696. /* */
  1697. /* VOID */
  1698. /* */
  1699. /****************************************************************************/
  1700. VOID
  1701. CompleteMiniportReset(IN PRNDISMP_ADAPTER pAdapter,
  1702. IN NDIS_STATUS ResetStatus,
  1703. IN BOOLEAN AddressingReset)
  1704. {
  1705. LIST_ENTRY PendingRequests;
  1706. PLIST_ENTRY pEntry, pNext;
  1707. PRNDISMP_MESSAGE_FRAME pMsgFrame;
  1708. do
  1709. {
  1710. if (!pAdapter->ResetPending)
  1711. {
  1712. break;
  1713. }
  1714. pAdapter->ResetPending = FALSE;
  1715. //
  1716. // Take out all pending requests/sets queued on the adapter.
  1717. //
  1718. InitializeListHead(&PendingRequests);
  1719. RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
  1720. for (pEntry = pAdapter->PendingFrameList.Flink;
  1721. pEntry != &pAdapter->PendingFrameList;
  1722. pEntry = pNext)
  1723. {
  1724. pNext = pEntry->Flink;
  1725. pMsgFrame = CONTAINING_RECORD(pEntry, RNDISMP_MESSAGE_FRAME, Link);
  1726. if (pMsgFrame->NdisMessageType == REMOTE_NDIS_QUERY_MSG ||
  1727. pMsgFrame->NdisMessageType == REMOTE_NDIS_SET_MSG)
  1728. {
  1729. RemoveEntryList(pEntry);
  1730. InsertTailList(&PendingRequests, pEntry);
  1731. TRACE0(("RNDISMP: ResetComplete: taking out MsgFrame %x, msg type %x\n",
  1732. pMsgFrame, pMsgFrame->NdisMessageType));
  1733. }
  1734. }
  1735. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  1736. //
  1737. // Complete all these requests.
  1738. //
  1739. for (pEntry = PendingRequests.Flink;
  1740. pEntry != &PendingRequests;
  1741. pEntry = pNext)
  1742. {
  1743. pNext = pEntry->Flink;
  1744. pMsgFrame = CONTAINING_RECORD(pEntry, RNDISMP_MESSAGE_FRAME, Link);
  1745. TRACE0(("RNDISMP: ResetComplete: completing MsgFrame %x, msg type %x\n",
  1746. pMsgFrame, pMsgFrame->NdisMessageType));
  1747. ASSERT(pMsgFrame->pReqContext != NULL);
  1748. if (pMsgFrame->pReqContext->pNdisRequest != NULL)
  1749. {
  1750. //
  1751. // This request came down thru our MiniportCoRequest handler.
  1752. //
  1753. NdisMCoRequestComplete(NDIS_STATUS_REQUEST_ABORTED,
  1754. pAdapter->MiniportAdapterHandle,
  1755. pMsgFrame->pReqContext->pNdisRequest);
  1756. }
  1757. else
  1758. {
  1759. //
  1760. // This request came thru our connectionless query/set handler.
  1761. //
  1762. if (pMsgFrame->NdisMessageType == REMOTE_NDIS_QUERY_MSG)
  1763. {
  1764. NdisMQueryInformationComplete(pAdapter->MiniportAdapterHandle,
  1765. NDIS_STATUS_REQUEST_ABORTED);
  1766. }
  1767. else
  1768. {
  1769. ASSERT(pMsgFrame->NdisMessageType == REMOTE_NDIS_SET_MSG);
  1770. NdisMSetInformationComplete(pAdapter->MiniportAdapterHandle,
  1771. NDIS_STATUS_REQUEST_ABORTED);
  1772. }
  1773. }
  1774. FreeRequestContext(pAdapter, pMsgFrame->pReqContext);
  1775. pMsgFrame->pReqContext = (PRNDISMP_REQUEST_CONTEXT)UlongToPtr(0xabababab);
  1776. DereferenceMsgFrame(pMsgFrame);
  1777. }
  1778. TRACE0(("Completing reset on Adapter %x, Status %x, AddressingReset %d\n",
  1779. pAdapter, ResetStatus, AddressingReset));
  1780. RNDISMP_INCR_STAT(pAdapter, Resets);
  1781. //
  1782. // Complete the reset now.
  1783. //
  1784. NdisMResetComplete(pAdapter->MiniportAdapterHandle,
  1785. ResetStatus,
  1786. AddressingReset);
  1787. }
  1788. while (FALSE);
  1789. }
  1790. /****************************************************************************/
  1791. /* ReadAndSetRegistryParameters */
  1792. /****************************************************************************/
  1793. /* */
  1794. /* Routine Description: */
  1795. /* */
  1796. /* This is called when initializing a device, to read and send any */
  1797. /* registry parameters applicable to this device. */
  1798. /* */
  1799. /* We go through the entire list of configurable parameters by walking */
  1800. /* subkeys under the "ndi\Params" key. Each subkey represents one */
  1801. /* parameter. Using information about this parameter (specifically, its */
  1802. /* name and type), we query its value, and send a SetRequest to the */
  1803. /* device. */
  1804. /* */
  1805. /* Arguments: */
  1806. /* */
  1807. /* pAdapter - Pointer to adapter structure for the device */
  1808. /* ConfigurationContext - NDIS handle to access registry for this device */
  1809. /* */
  1810. /* Return: */
  1811. /* */
  1812. /* NDIS_STATUS */
  1813. /* */
  1814. /****************************************************************************/
  1815. NDIS_STATUS
  1816. ReadAndSetRegistryParameters(IN PRNDISMP_ADAPTER pAdapter,
  1817. IN NDIS_HANDLE ConfigurationContext)
  1818. {
  1819. NDIS_STATUS Status;
  1820. NDIS_HANDLE ConfigHandle;
  1821. NDIS_STRING NdiKeyName = NDIS_STRING_CONST("Ndi");
  1822. NDIS_HANDLE NdiKeyHandle = NULL;
  1823. Status = NDIS_STATUS_SUCCESS;
  1824. ConfigHandle = NULL;
  1825. do
  1826. {
  1827. NdisOpenConfiguration(&Status,
  1828. &ConfigHandle,
  1829. ConfigurationContext);
  1830. if (Status != NDIS_STATUS_SUCCESS)
  1831. {
  1832. break;
  1833. }
  1834. NdisOpenConfigurationKeyByName(
  1835. &Status,
  1836. ConfigHandle,
  1837. &NdiKeyName,
  1838. &NdiKeyHandle);
  1839. if (Status == NDIS_STATUS_SUCCESS)
  1840. {
  1841. NDIS_STRING ParamsKeyName = NDIS_STRING_CONST("Params");
  1842. NDIS_HANDLE ParamsKeyHandle = NULL;
  1843. NdisOpenConfigurationKeyByName(
  1844. &Status,
  1845. NdiKeyHandle,
  1846. &ParamsKeyName,
  1847. &ParamsKeyHandle);
  1848. if (Status == NDIS_STATUS_SUCCESS)
  1849. {
  1850. ULONG i;
  1851. BOOLEAN bDone = FALSE;
  1852. //
  1853. // Iterate through all subkeys under ndi\Params:
  1854. //
  1855. for (i = 0; !bDone; i++)
  1856. {
  1857. NDIS_STRING ParamSubKeyName;
  1858. NDIS_HANDLE ParamSubKeyHandle;
  1859. NDIS_STRING ParamTypeName = NDIS_STRING_CONST("type");
  1860. PNDIS_CONFIGURATION_PARAMETER pConfigParameter;
  1861. ParamSubKeyName.Length =
  1862. ParamSubKeyName.MaximumLength = 0;
  1863. ParamSubKeyName.Buffer = NULL;
  1864. NdisOpenConfigurationKeyByIndex(
  1865. &Status,
  1866. ParamsKeyHandle,
  1867. i,
  1868. &ParamSubKeyName,
  1869. &ParamSubKeyHandle);
  1870. if (Status != NDIS_STATUS_SUCCESS)
  1871. {
  1872. //
  1873. // Done with parameters. Cook return value.
  1874. //
  1875. Status = NDIS_STATUS_SUCCESS;
  1876. break;
  1877. }
  1878. //
  1879. // Got the handle to a subkey under ndi\Params,
  1880. // now read the type information for this parameter.
  1881. //
  1882. #ifndef BUILD_WIN9X
  1883. TRACE3(("ReadAndSetRegParams: subkey %d under ndi\\params: %ws\n",
  1884. i, ParamSubKeyName.Buffer));
  1885. #else
  1886. //
  1887. // Handle Win98Gold behavior.
  1888. //
  1889. if (ParamSubKeyName.Buffer == NULL)
  1890. {
  1891. PNDIS_STRING pNdisString;
  1892. pNdisString = *(PNDIS_STRING *)&ParamSubKeyName;
  1893. ParamSubKeyName = *pNdisString;
  1894. }
  1895. TRACE2(("ReadAndSetRegParams: subkey %d under ndi\\params: %ws\n",
  1896. i, ParamSubKeyName.Buffer));
  1897. #endif
  1898. //
  1899. // We have a parameter name now, in ParamSubKeyName.
  1900. // Get its type information.
  1901. //
  1902. NdisReadConfiguration(
  1903. &Status,
  1904. &pConfigParameter,
  1905. ParamSubKeyHandle,
  1906. &ParamTypeName,
  1907. NdisParameterString);
  1908. if (Status == NDIS_STATUS_SUCCESS)
  1909. {
  1910. TRACE2(("ReadAndSetRegParams: Adapter %p, type is %ws\n",
  1911. pAdapter,
  1912. pConfigParameter->ParameterData.StringData.Buffer));
  1913. //
  1914. // Send off a Set Request for this
  1915. // parameter to the device.
  1916. //
  1917. Status = SendConfiguredParameter(
  1918. pAdapter,
  1919. ConfigHandle,
  1920. &ParamSubKeyName,
  1921. &pConfigParameter->ParameterData.StringData);
  1922. if (Status != NDIS_STATUS_SUCCESS)
  1923. {
  1924. TRACE0(("ReadAndSetRegParams: Adapter %p, failed %x\n",
  1925. pAdapter, Status));
  1926. bDone = TRUE;
  1927. }
  1928. else
  1929. {
  1930. NDIS_STRING NetworkAddressName =
  1931. NDIS_STRING_CONST("NetworkAddress");
  1932. //
  1933. // Special case for the "NetworkAddress"
  1934. // parameter - if we just set this successfully,
  1935. // make note of the fact.
  1936. //
  1937. if (NdisEqualString(&ParamSubKeyName,
  1938. &NetworkAddressName,
  1939. TRUE))
  1940. {
  1941. TRACE1(("ReadAndSetRegParams: Adapter %p,"
  1942. " supports MAC address overwrite\n",
  1943. pAdapter));
  1944. pAdapter->MacOptions |=
  1945. NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE;
  1946. }
  1947. }
  1948. }
  1949. //
  1950. // Done with this subkey under ndi\Params.
  1951. //
  1952. NdisCloseConfiguration(ParamSubKeyHandle);
  1953. } // for each subkey under ndi\Params
  1954. //
  1955. // Done with "ndi\Params"
  1956. //
  1957. NdisCloseConfiguration(ParamsKeyHandle);
  1958. }
  1959. //
  1960. // Done with "ndi"
  1961. //
  1962. NdisCloseConfiguration(NdiKeyHandle);
  1963. }
  1964. //
  1965. // Done with configuration section for this device.
  1966. //
  1967. NdisCloseConfiguration(ConfigHandle);
  1968. }
  1969. while (FALSE);
  1970. return (Status);
  1971. }
  1972. /****************************************************************************/
  1973. /* SendConfiguredParameter */
  1974. /****************************************************************************/
  1975. /* */
  1976. /* Routine Description: */
  1977. /* */
  1978. /* Read the value of the specified config parameter, format a SetRequest, */
  1979. /* send it to the device, and wait for a response. */
  1980. /* */
  1981. /* Arguments: */
  1982. /* */
  1983. /* pAdapter - Pointer to adapter structure for the device */
  1984. /* ConfigHandle - handle to configuration section for this device */
  1985. /* pParameterName - parameter key name */
  1986. /* pParameterType - parameter type */
  1987. /* */
  1988. /* Return: */
  1989. /* */
  1990. /* NDIS_STATUS */
  1991. /* */
  1992. /****************************************************************************/
  1993. NDIS_STATUS
  1994. SendConfiguredParameter(IN PRNDISMP_ADAPTER pAdapter,
  1995. IN NDIS_HANDLE ConfigHandle,
  1996. IN PNDIS_STRING pParameterName,
  1997. IN PNDIS_STRING pParameterType)
  1998. {
  1999. PRNDISMP_MESSAGE_FRAME pMsgFrame = NULL;
  2000. PRNDISMP_MESSAGE_FRAME pPendingMsgFrame = NULL;
  2001. PRNDISMP_REQUEST_CONTEXT pReqContext = NULL;
  2002. NDIS_PARAMETER_TYPE NdisParameterType;
  2003. PNDIS_CONFIGURATION_PARAMETER pConfigParameter;
  2004. ULONG ParameterValueLength;
  2005. PUCHAR pParameterValue;
  2006. UINT32 ParameterType;
  2007. NDIS_EVENT Event;
  2008. UINT BytesRead;
  2009. BOOLEAN bWokenUp;
  2010. RNDIS_REQUEST_ID RequestId;
  2011. PRNDIS_CONFIG_PARAMETER_INFO pRndisConfigInfo = NULL;
  2012. ULONG RndisConfigInfoLength;
  2013. PUCHAR pConfigInfoBuf;
  2014. NDIS_STATUS Status;
  2015. struct {
  2016. NDIS_STRING TypeName;
  2017. NDIS_PARAMETER_TYPE NdisType;
  2018. } StringToNdisType[] =
  2019. {
  2020. {NDIS_STRING_CONST("int"), NdisParameterInteger},
  2021. {NDIS_STRING_CONST("long"), NdisParameterInteger},
  2022. {NDIS_STRING_CONST("word"), NdisParameterInteger},
  2023. {NDIS_STRING_CONST("dword"), NdisParameterInteger},
  2024. {NDIS_STRING_CONST("edit"), NdisParameterString},
  2025. {NDIS_STRING_CONST("enum"), NdisParameterString}
  2026. };
  2027. ULONG NumTypes = sizeof(StringToNdisType);
  2028. ULONG i;
  2029. do
  2030. {
  2031. //
  2032. // Determine the parameter type.
  2033. //
  2034. for (i = 0; i < NumTypes; i++)
  2035. {
  2036. if (NdisEqualString(&StringToNdisType[i].TypeName,
  2037. pParameterType,
  2038. TRUE))
  2039. {
  2040. NdisParameterType = StringToNdisType[i].NdisType;
  2041. break;
  2042. }
  2043. }
  2044. if (i == NumTypes)
  2045. {
  2046. TRACE1(("SendConfiguredParam: Adapter %p, Param %ws, invalid type %ws\n",
  2047. pAdapter,
  2048. pParameterName->Buffer,
  2049. pParameterType->Buffer));
  2050. Status = NDIS_STATUS_INVALID_DATA;
  2051. break;
  2052. }
  2053. NdisReadConfiguration(
  2054. &Status,
  2055. &pConfigParameter,
  2056. ConfigHandle,
  2057. pParameterName,
  2058. NdisParameterType
  2059. );
  2060. if (Status != NDIS_STATUS_SUCCESS)
  2061. {
  2062. //
  2063. // It is okay for a parameter to not be configured.
  2064. //
  2065. Status = NDIS_STATUS_SUCCESS;
  2066. break;
  2067. }
  2068. if (NdisParameterType == NdisParameterInteger)
  2069. {
  2070. ParameterValueLength = sizeof(UINT32);
  2071. pParameterValue = (PUCHAR)&pConfigParameter->ParameterData.IntegerData;
  2072. ParameterType = RNDIS_CONFIG_PARAM_TYPE_INTEGER;
  2073. }
  2074. else
  2075. {
  2076. ASSERT(NdisParameterType == NdisParameterString);
  2077. ParameterValueLength = pConfigParameter->ParameterData.StringData.Length;
  2078. pParameterValue = (PUCHAR)pConfigParameter->ParameterData.StringData.Buffer;
  2079. ParameterType = RNDIS_CONFIG_PARAM_TYPE_STRING;
  2080. }
  2081. RndisConfigInfoLength = sizeof(RNDIS_CONFIG_PARAMETER_INFO) +
  2082. pParameterName->Length +
  2083. ParameterValueLength;
  2084. Status = MemAlloc(&pRndisConfigInfo, RndisConfigInfoLength);
  2085. if (Status != NDIS_STATUS_SUCCESS)
  2086. {
  2087. break;
  2088. }
  2089. pRndisConfigInfo->ParameterNameOffset = sizeof(RNDIS_CONFIG_PARAMETER_INFO);
  2090. pRndisConfigInfo->ParameterNameLength = pParameterName->Length;
  2091. pRndisConfigInfo->ParameterType = ParameterType;
  2092. pRndisConfigInfo->ParameterValueOffset =
  2093. pRndisConfigInfo->ParameterNameOffset +
  2094. pRndisConfigInfo->ParameterNameLength;
  2095. pRndisConfigInfo->ParameterValueLength = ParameterValueLength;
  2096. //
  2097. // Copy in the parameter name.
  2098. //
  2099. pConfigInfoBuf = (PUCHAR)pRndisConfigInfo +
  2100. pRndisConfigInfo->ParameterNameOffset;
  2101. RNDISMP_MOVE_MEM(pConfigInfoBuf, pParameterName->Buffer, pParameterName->Length);
  2102. //
  2103. // Copy in the parameter value.
  2104. //
  2105. pConfigInfoBuf = (PUCHAR)pRndisConfigInfo +
  2106. pRndisConfigInfo->ParameterValueOffset;
  2107. RNDISMP_MOVE_MEM(pConfigInfoBuf, pParameterValue, ParameterValueLength);
  2108. //
  2109. // Build a Set Request
  2110. //
  2111. pMsgFrame = BuildRndisMessageCommon(pAdapter,
  2112. NULL,
  2113. REMOTE_NDIS_SET_MSG,
  2114. OID_GEN_RNDIS_CONFIG_PARAMETER,
  2115. pRndisConfigInfo,
  2116. RndisConfigInfoLength);
  2117. if (pMsgFrame == NULL)
  2118. {
  2119. Status = NDIS_STATUS_RESOURCES;
  2120. break;
  2121. }
  2122. #if DBG
  2123. {
  2124. PMDL pTmpMdl = pMsgFrame->pMessageMdl;
  2125. ULONG Length;
  2126. PUCHAR pBuf;
  2127. ULONG OldDebugFlags = RndismpDebugFlags;
  2128. Length = MmGetMdlByteCount(pTmpMdl);
  2129. pBuf = MmGetSystemAddressForMdl(pTmpMdl);
  2130. RndismpDebugFlags |= DBG_DUMP;
  2131. TRACEDUMP(("SetRequest (OID_GEN_RNDIS_CONFIG_PARAMETER):"
  2132. " Adapter %p, Param %ws\n", pAdapter, pParameterName->Buffer), pBuf, Length);
  2133. RndismpDebugFlags = OldDebugFlags;
  2134. }
  2135. #endif
  2136. pReqContext = AllocateRequestContext(pAdapter);
  2137. if (pReqContext == NULL)
  2138. {
  2139. Status = NDIS_STATUS_RESOURCES;
  2140. break;
  2141. }
  2142. // Fill up the request context.
  2143. pReqContext->pNdisRequest = NULL;
  2144. pReqContext->Oid = OID_GEN_RNDIS_CONFIG_PARAMETER;
  2145. NdisInitializeEvent(&Event);
  2146. pReqContext->pEvent = &Event;
  2147. pReqContext->bInternal = TRUE;
  2148. pReqContext->pBytesRead = &BytesRead;
  2149. pReqContext->InformationBufferLength = RndisConfigInfoLength;
  2150. pMsgFrame->pVc = NULL;
  2151. pMsgFrame->pReqContext = pReqContext;
  2152. // save off the request Id.
  2153. RequestId = pMsgFrame->RequestId;
  2154. // send the message to the microport.
  2155. RNDISMP_SEND_TO_MICROPORT(pAdapter, pMsgFrame, TRUE, NULL);
  2156. RNDISMP_ASSERT_AT_PASSIVE();
  2157. bWokenUp = NdisWaitEvent(&Event, MINIPORT_INIT_TIMEOUT);
  2158. // remove the message from the pending queue - it may or may not be there.
  2159. RNDISMP_LOOKUP_PENDING_MESSAGE(pPendingMsgFrame, pAdapter, RequestId);
  2160. if (!bWokenUp)
  2161. {
  2162. TRACE1(("No response to set parameter, Adapter %x\n", pAdapter));
  2163. Status = NDIS_STATUS_DEVICE_FAILED;
  2164. }
  2165. else
  2166. {
  2167. Status = pReqContext->CompletionStatus;
  2168. TRACE1(("Got response to set config param, Status %x, %d bytes read\n",
  2169. Status, BytesRead));
  2170. }
  2171. }
  2172. while (FALSE);
  2173. if (pRndisConfigInfo)
  2174. {
  2175. MemFree(pRndisConfigInfo, RndisConfigInfoLength);
  2176. }
  2177. if (pMsgFrame)
  2178. {
  2179. DereferenceMsgFrame(pMsgFrame);
  2180. }
  2181. if (pReqContext)
  2182. {
  2183. FreeRequestContext(pAdapter, pReqContext);
  2184. }
  2185. return (Status);
  2186. }
  2187. #ifdef NDIS51_MINIPORT
  2188. /****************************************************************************/
  2189. /* RndismpPnPEventNotify */
  2190. /****************************************************************************/
  2191. /* */
  2192. /* Routine Description: */
  2193. /* */
  2194. /* Entry point called by NDIS to notify us of PnP events affecting our */
  2195. /* device. The main event of importance to us is surprise removal. */
  2196. /* */
  2197. /* Arguments: */
  2198. /* */
  2199. /* pAdapter - Pointer to adapter structure */
  2200. /* */
  2201. /* Return: */
  2202. /* */
  2203. /* NDIS_STATUS */
  2204. /* */
  2205. /****************************************************************************/
  2206. VOID
  2207. RndismpPnPEventNotify(IN NDIS_HANDLE MiniportAdapterContext,
  2208. IN NDIS_DEVICE_PNP_EVENT EventCode,
  2209. IN PVOID InformationBuffer,
  2210. IN ULONG InformationBufferLength)
  2211. {
  2212. PRNDISMP_ADAPTER pAdapter;
  2213. // get adapter context
  2214. pAdapter = PRNDISMP_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
  2215. CHECK_VALID_ADAPTER(pAdapter);
  2216. TRACE3(("PnPEventNotify: Adapter %x\n", pAdapter));
  2217. switch (EventCode)
  2218. {
  2219. case NdisDevicePnPEventSurpriseRemoved:
  2220. TRACE1(("PnPEventNotify: Adapter %p, surprise remove\n", pAdapter));
  2221. RndismpInternalHalt(pAdapter, FALSE);
  2222. break;
  2223. default:
  2224. break;
  2225. }
  2226. } // RndismpPnPEventNotify
  2227. #endif // NDIS51_MINIPORT