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.

5351 lines
165 KiB

  1. /*++
  2. Copyright (c) 1990-1995 Microsoft Corporation
  3. Module Name:
  4. miniport.c
  5. Abstract:
  6. NDIS miniport wrapper functions
  7. Author:
  8. Jameel Hyder (JameelH) Re-organization 01-Jun-95
  9. Environment:
  10. Kernel mode, FSD
  11. Revision History:
  12. --*/
  13. #include <precomp.h>
  14. #pragma hdrstop
  15. //
  16. // Define the module number for debug code.
  17. //
  18. #define MODULE_NUMBER MODULE_MINIPORT
  19. NTSTATUS
  20. ndisCompletionRoutine(
  21. IN PDEVICE_OBJECT pdo,
  22. IN PIRP pirp,
  23. IN PVOID Context
  24. )
  25. /*++
  26. Routine Description:
  27. Arguments:
  28. pdo - Pointer to the device object for the miniport.
  29. pirp - Pointer to the device set power state IRP that was completed.
  30. Context - Pointer to an EVENT.
  31. Return Value:
  32. --*/
  33. {
  34. PPOWER_QUERY pQuery = Context;
  35. pQuery->Status = pirp->IoStatus.Status;
  36. SET_EVENT(&pQuery->Event);
  37. return(STATUS_MORE_PROCESSING_REQUIRED);
  38. }
  39. NDIS_STATUS
  40. ndisMInitializeAdapter(
  41. IN PNDIS_M_DRIVER_BLOCK pMiniBlock,
  42. IN PNDIS_WRAPPER_CONFIGURATION_HANDLE pConfigurationHandle,
  43. IN PUNICODE_STRING pExportName,
  44. IN NDIS_HANDLE DeviceContext OPTIONAL
  45. )
  46. {
  47. FILTERDBS FilterDB = {0};
  48. PDEVICE_OBJECT pTmpDevice = NULL;
  49. NTSTATUS NtStatus;
  50. LONG ErrorCode = 1;
  51. PNDIS_MINIPORT_BLOCK Miniport = NULL;
  52. UNICODE_STRING SymbolicLink;
  53. NDIS_STATUS MiniportInitializeStatus = NDIS_STATUS_SUCCESS;
  54. NDIS_STATUS OpenErrorStatus;
  55. NDIS_STATUS NdisStatus;
  56. NDIS_POWER_PROFILE PowerProfile;
  57. ULONG GenericUlong = 0;
  58. PVOID DataBuffer;
  59. PNDIS_MINIPORT_WORK_ITEM WorkItem;
  60. GUID guidLanClass = GUID_NDIS_LAN_CLASS;
  61. UINT SelectedMediumIndex;
  62. UINT PacketFilter = 0x01;
  63. WCHAR SymLnkBuf[128];
  64. ULONG MaximumShortAddresses;
  65. ULONG MaximumLongAddresses;
  66. KIRQL OldIrql;
  67. BOOLEAN DerefDriver = FALSE, FreeBuffer = FALSE;
  68. BOOLEAN Dequeue = FALSE, ExtendedError = FALSE, HaltMiniport = FALSE;
  69. BOOLEAN ClearDeviceClassAssociation = FALSE, WmiDeregister = FALSE;
  70. UCHAR CurrentLongAddress[6];
  71. UCHAR CurrentShortAddress[2];
  72. UCHAR i;
  73. BOOLEAN fRc;
  74. #if ARCNET
  75. BOOLEAN FreeArcnetLookaheadBuffer = FALSE;
  76. #endif
  77. BOOLEAN DeleteSymbolicLink = FALSE;
  78. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  79. ("==>ndisMInitializeAdapter\n"));
  80. do
  81. {
  82. ASSERT (CURRENT_IRQL < DISPATCH_LEVEL);
  83. MiniportReferencePackage();
  84. //
  85. // Initialize device.
  86. //
  87. if (!ndisReferenceDriver((PNDIS_M_DRIVER_BLOCK)pMiniBlock))
  88. {
  89. //
  90. // The driver is closing.
  91. //
  92. break;
  93. }
  94. DerefDriver = TRUE;
  95. pTmpDevice = pConfigurationHandle->DeviceObject;
  96. //
  97. // Initialize the Miniport adapter block in the device object extension
  98. //
  99. // *** NDIS_WRAPPER_CONTEXT has a higher alignment requirement than
  100. // NDIS_MINIPORT_BLOCK, so we put it first in the extension.
  101. //
  102. Miniport = (PNDIS_MINIPORT_BLOCK)((PNDIS_WRAPPER_CONTEXT)pTmpDevice->DeviceExtension + 1);
  103. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  104. ("ndisMInitializeAdapter: Miniport %p, ", Miniport));
  105. DBGPRINT_UNICODE(DBG_COMP_PNP, DBG_LEVEL_INFO, Miniport->pAdapterInstanceName);
  106. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO, ("\n"));
  107. //
  108. // Create symbolic link for the device
  109. //
  110. SymbolicLink.Buffer = SymLnkBuf;
  111. SymbolicLink.Length = 0;
  112. SymbolicLink.MaximumLength = sizeof(SymLnkBuf);
  113. RtlCopyUnicodeString(&SymbolicLink, &ndisDosDevicesStr);
  114. RtlAppendUnicodeStringToString(&SymbolicLink, &Miniport->BaseName);
  115. NtStatus = IoCreateSymbolicLink(&SymbolicLink, pExportName);
  116. if (!NT_SUCCESS(NtStatus))
  117. {
  118. #if DBG
  119. DbgPrint("ndisMInitializeAdapter: IoCreateSymbolicLink failed for Miniport %p, SymbolicLinkName %p, DeviceName %p, Status %lx\n",
  120. Miniport, &SymbolicLink, pExportName, NtStatus);
  121. #endif
  122. if (NtStatus == STATUS_OBJECT_NAME_COLLISION)
  123. {
  124. DeleteSymbolicLink = TRUE;
  125. }
  126. else
  127. {
  128. DeleteSymbolicLink = FALSE;
  129. }
  130. }
  131. else
  132. {
  133. DeleteSymbolicLink = TRUE;
  134. }
  135. Miniport->DeviceContext = DeviceContext;
  136. Miniport->AssignedProcessor = ndisValidProcessors[ndisCurrentProcessor];
  137. ndisCurrentProcessor --;
  138. if (ndisCurrentProcessor > ndisMaximumProcessor)
  139. {
  140. ndisCurrentProcessor = ndisMaximumProcessor;
  141. }
  142. MINIPORT_SET_FLAG(Miniport, fMINIPORT_RESOURCES_AVAILABLE);
  143. //
  144. // Initialize the handlers for the simplex case with the RcvPkt handler set to null-filter case
  145. //
  146. Miniport->PacketIndicateHandler = ndisMDummyIndicatePacket;
  147. Miniport->SavedPacketIndicateHandler = ndisMDummyIndicatePacket;
  148. Miniport->EthRxIndicateHandler = EthFilterDprIndicateReceive;
  149. Miniport->FddiRxIndicateHandler = FddiFilterDprIndicateReceive;
  150. Miniport->TrRxIndicateHandler = TrFilterDprIndicateReceive;
  151. Miniport->EthRxCompleteHandler = EthFilterDprIndicateReceiveComplete;
  152. Miniport->FddiRxCompleteHandler = FddiFilterDprIndicateReceiveComplete;
  153. Miniport->TrRxCompleteHandler = TrFilterDprIndicateReceiveComplete;
  154. Miniport->SendCompleteHandler = NdisMSendComplete;
  155. Miniport->TDCompleteHandler = NdisMTransferDataComplete;
  156. Miniport->ResetCompleteHandler = NdisMResetComplete;
  157. Miniport->StatusHandler = NdisMIndicateStatus;
  158. Miniport->StatusCompleteHandler = NdisMIndicateStatusComplete;
  159. Miniport->SendResourcesHandler = NdisMSendResourcesAvailable;
  160. Miniport->QueryCompleteHandler = NdisMQueryInformationComplete;
  161. Miniport->SetCompleteHandler = NdisMSetInformationComplete;
  162. Miniport->WanSendCompleteHandler = NdisMWanSendComplete;
  163. Miniport->WanRcvHandler = NdisMWanIndicateReceive;
  164. Miniport->WanRcvCompleteHandler = NdisMWanIndicateReceiveComplete;
  165. //
  166. // And optimize Dpc/Isr stuff
  167. //
  168. Miniport->HandleInterruptHandler = Miniport->DriverHandle->MiniportCharacteristics.HandleInterruptHandler;
  169. Miniport->DisableInterruptHandler = Miniport->DriverHandle->MiniportCharacteristics.DisableInterruptHandler;
  170. Miniport->EnableInterruptHandler = Miniport->DriverHandle->MiniportCharacteristics.EnableInterruptHandler;
  171. Miniport->DeferredSendHandler = ndisMStartSends;
  172. //
  173. // Initialize the list for VC instance names
  174. //
  175. InitializeListHead(&Miniport->WmiEnabledVcs);
  176. //
  177. // Set some flags describing the miniport.
  178. //
  179. if (pMiniBlock->MiniportCharacteristics.MajorNdisVersion >= 4)
  180. {
  181. //
  182. // Does this miniport indicate packets?
  183. //
  184. if (pMiniBlock->MiniportCharacteristics.ReturnPacketHandler)
  185. {
  186. Miniport->InfoFlags |= NDIS_MINIPORT_INDICATES_PACKETS;
  187. }
  188. //
  189. // Can this miniport handle multiple sends?
  190. //
  191. if (pMiniBlock->MiniportCharacteristics.SendPacketsHandler)
  192. {
  193. MINIPORT_SET_SEND_FLAG(Miniport, fMINIPORT_SEND_PACKET_ARRAY);
  194. Miniport->DeferredSendHandler = ndisMStartSendPackets;
  195. Miniport->WSendPacketsHandler = pMiniBlock->MiniportCharacteristics.SendPacketsHandler;
  196. }
  197. if (pMiniBlock->MiniportCharacteristics.MajorNdisVersion == 5)
  198. {
  199. //
  200. // This is an NDIS 5.0 miniport.
  201. //
  202. MINIPORT_SET_FLAG(Miniport, fMINIPORT_IS_NDIS_5);
  203. Miniport->InfoFlags |= NDIS_MINIPORT_IS_NDIS_5;
  204. if (pMiniBlock->MiniportCharacteristics.CoSendPacketsHandler != NULL)
  205. {
  206. //
  207. // This is a connection-oriented miniport.
  208. //
  209. MINIPORT_SET_FLAG(Miniport, fMINIPORT_IS_CO);
  210. }
  211. }
  212. }
  213. //
  214. // the refernce is already initalized, so just increment it here
  215. // we do reference the miniport instead of intializing it
  216. // to avoid setting the reference count to 1 if miniport has already
  217. // been refrenced by receiving some power IRPs
  218. //
  219. MINIPORT_INCREMENT_REF(Miniport);
  220. Miniport->CFHangTicks = 1; // Default
  221. //
  222. // Allocate a pool of work items to start with.
  223. //
  224. for (i = 0; i < NUMBER_OF_SINGLE_WORK_ITEMS; i++)
  225. {
  226. WorkItem = &Miniport->WorkItemBuffer[i];
  227. NdisZeroMemory(WorkItem, sizeof(NDIS_MINIPORT_WORK_ITEM));
  228. //
  229. // Place the work item on the free queue.
  230. //
  231. PushEntryList(&Miniport->SingleWorkItems[i], &WorkItem->Link);
  232. }
  233. //
  234. // Enqueue the miniport on the driver block.
  235. //
  236. if (!ndisQueueMiniportOnDriver(Miniport, pMiniBlock))
  237. {
  238. //
  239. // The Driver is closing, undo what we have done.
  240. //
  241. break;
  242. }
  243. Dequeue = TRUE;
  244. //
  245. // Initialize the deferred dpc
  246. //
  247. INITIALIZE_DPC(&Miniport->DeferredDpc, ndisMDeferredDpc, Miniport);
  248. Miniport->LockHandler = XFilterLockHandler;
  249. //
  250. // the miniport's current device state is unspecified.
  251. //
  252. if (Miniport->CurrentDevicePowerState == PowerDeviceUnspecified)
  253. {
  254. Miniport->CurrentDevicePowerState = PowerDeviceD0;
  255. }
  256. ndisQueryPowerCapabilities(Miniport);
  257. //
  258. // Call adapter callback. The current value for "Export"
  259. // is what we tell him to name this device.
  260. //
  261. MINIPORT_SET_FLAG(Miniport, fMINIPORT_IN_INITIALIZE);
  262. MINIPORT_CLEAR_FLAG(Miniport, fMINIPORT_NORMAL_INTERRUPTS);
  263. if (pMiniBlock->Flags & fMINIBLOCK_VERIFYING)
  264. {
  265. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_VERIFYING);
  266. if ((ndisDriverTrackAlloc != NULL) &&
  267. (ndisMiniportTrackAlloc == NULL))
  268. {
  269. ndisMiniportTrackAlloc = Miniport;
  270. }
  271. else
  272. {
  273. //
  274. // tracking memory alocation is allowed
  275. // for one miniport only. otherwise null out the
  276. // global ndisDriverTrackAlloc to avoid confusion
  277. // memory allocations will continue to get tracked
  278. // but the result will not be as useful
  279. //
  280. ndisMiniportTrackAlloc = NULL;
  281. }
  282. }
  283. Miniport->MacOptions = 0;
  284. MiniportInitializeStatus = (pMiniBlock->MiniportCharacteristics.InitializeHandler)(
  285. &OpenErrorStatus,
  286. &SelectedMediumIndex,
  287. ndisMediumArray,
  288. ndisMediumArraySize/sizeof(NDIS_MEDIUM),
  289. (NDIS_HANDLE)(Miniport),
  290. (NDIS_HANDLE)pConfigurationHandle);
  291. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  292. ("ndisMInitializeAdapter: Miniport %p, InitializeHandler returned %lx\n", Miniport,
  293. MiniportInitializeStatus));
  294. MINIPORT_CLEAR_FLAG(Miniport, fMINIPORT_IN_INITIALIZE);
  295. //
  296. // Free the slot information buffer
  297. //
  298. if (pConfigurationHandle->ParametersQueryTable[3].DefaultData != NULL)
  299. {
  300. FREE_POOL(pConfigurationHandle->ParametersQueryTable[3].DefaultData);
  301. }
  302. if (MiniportInitializeStatus == NDIS_STATUS_SUCCESS)
  303. {
  304. HaltMiniport = TRUE;
  305. CHECK_FOR_NORMAL_INTERRUPTS(Miniport);
  306. //
  307. // set up the shutdown handlers for 5.1 miniports
  308. //
  309. if (pMiniBlock->MiniportCharacteristics.AdapterShutdownHandler != NULL)
  310. {
  311. NdisMRegisterAdapterShutdownHandler(
  312. (NDIS_HANDLE)Miniport,
  313. (PVOID)(Miniport->MiniportAdapterContext),
  314. (ADAPTER_SHUTDOWN_HANDLER)(pMiniBlock->MiniportCharacteristics.AdapterShutdownHandler));
  315. }
  316. #if DBG
  317. //
  318. // if the driver verifier is on for the miniport, check to see if it registered an
  319. // AdapterShutdownHandler and complain if it did not
  320. //
  321. NDIS_WARN((((PNDIS_WRAPPER_CONTEXT)Miniport->WrapperContext)->ShutdownHandler == NULL) &&
  322. (Miniport->Interrupt != NULL) &&
  323. (Miniport->BusType != PNPISABus),
  324. Miniport, NDIS_GFLAG_WARN_LEVEL_0,
  325. ("ndisMInitializeAdapter: Miniport %p did not register a Shutdown handler.\n", Miniport));
  326. //
  327. // complain if this is a hardware based device and the driver is asking Ndis to ignore
  328. // stuck send packets or requests
  329. //
  330. NDIS_WARN(MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_HARDWARE_DEVICE) &&
  331. MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IGNORE_REQUEST_QUEUE | fMINIPORT_IGNORE_PACKET_QUEUE),
  332. Miniport, NDIS_GFLAG_WARN_LEVEL_1,
  333. ("ndisMInitializeAdapter: -Hardware Based- Miniport %p improperly sets NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT or NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT attributes.\n", Miniport));
  334. #endif
  335. ASSERT(SelectedMediumIndex < (ndisMediumArraySize/sizeof(NDIS_MEDIUM)));
  336. Miniport->MediaType = ndisMediumArray[SelectedMediumIndex];
  337. if (Miniport->MediaType != NdisMedium802_5)
  338. {
  339. MINIPORT_SET_FLAG(Miniport, fMINIPORT_IGNORE_TOKEN_RING_ERRORS);
  340. }
  341. if (NdisMediumWan == Miniport->MediaType)
  342. {
  343. if (!MINIPORT_TEST_FLAG(Miniport, (fMINIPORT_IS_CO | fMINIPORT_IS_NDIS_5)))
  344. {
  345. Miniport->DeferredSendHandler = ndisMStartWanSends;
  346. }
  347. }
  348. //
  349. // get and save the vendor driver version if we don't have t already
  350. //
  351. if (pMiniBlock->DriverVersion == 0)
  352. {
  353. ndisMDoMiniportOp(Miniport,
  354. TRUE,
  355. OID_GEN_VENDOR_DRIVER_VERSION,
  356. &pMiniBlock->DriverVersion,
  357. sizeof(ULONG),
  358. 0x0,
  359. TRUE);
  360. }
  361. //
  362. // Set Maximumlookahead to 0 as default. For lan media query the real
  363. // stuff.
  364. //
  365. if ((Miniport->MediaType >= 0) &&
  366. (Miniport->MediaType < NdisMediumMax))
  367. {
  368. if ((NdisMediumWan != Miniport->MediaType) &&
  369. ndisMediaTypeCl[Miniport->MediaType])
  370. {
  371. //
  372. // Query maximum lookahead
  373. //
  374. ErrorCode = ndisMDoMiniportOp(Miniport,
  375. TRUE,
  376. OID_GEN_MAXIMUM_LOOKAHEAD,
  377. &GenericUlong,
  378. sizeof(GenericUlong),
  379. 0x1,
  380. TRUE);
  381. if (ErrorCode != 0)
  382. {
  383. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  384. ("ndisMInitializeAdapter: Error querying the OID_GEN_MAXIMUM_LOOKAHEAD\n"));
  385. break;
  386. }
  387. }
  388. }
  389. //
  390. // Now adjust based on media type
  391. //
  392. switch(Miniport->MediaType)
  393. {
  394. case NdisMedium802_3:
  395. Miniport->MaximumLookahead = ((NDIS_M_MAX_LOOKAHEAD - 14) < GenericUlong) ?
  396. NDIS_M_MAX_LOOKAHEAD - 14 : GenericUlong;
  397. break;
  398. case NdisMedium802_5:
  399. Miniport->MaximumLookahead = ((NDIS_M_MAX_LOOKAHEAD - 32) < GenericUlong) ?
  400. (NDIS_M_MAX_LOOKAHEAD - 32) : GenericUlong;
  401. break;
  402. case NdisMediumFddi:
  403. Miniport->MaximumLookahead = ((NDIS_M_MAX_LOOKAHEAD - 16) < GenericUlong) ?
  404. (NDIS_M_MAX_LOOKAHEAD - 16) : GenericUlong;
  405. break;
  406. #if ARCNET
  407. case NdisMediumArcnet878_2:
  408. Miniport->MaximumLookahead = ((NDIS_M_MAX_LOOKAHEAD - 50) < GenericUlong) ?
  409. NDIS_M_MAX_LOOKAHEAD - 50 : GenericUlong;
  410. //
  411. // Assume we will succeed with the lookahead allocation.
  412. //
  413. ExtendedError = FALSE;
  414. //
  415. // allocate a lookahead buffer for arcnet.
  416. //
  417. Miniport->ArcBuf = ALLOC_FROM_POOL(sizeof(NDIS_ARC_BUF), NDIS_TAG_LA_BUF);
  418. if (Miniport->ArcBuf == NULL)
  419. {
  420. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  421. (" Could not allocate arcnet lookahead buffer\n"));
  422. ExtendedError = TRUE;
  423. }
  424. NdisZeroMemory(Miniport->ArcBuf, sizeof(NDIS_ARC_BUF));
  425. Miniport->ArcBuf->ArcnetLookaheadBuffer = ALLOC_FROM_POOL(NDIS_M_MAX_LOOKAHEAD, NDIS_TAG_LA_BUF);
  426. if (Miniport->ArcBuf->ArcnetLookaheadBuffer == NULL)
  427. {
  428. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  429. (" Could not allocate arcnet lookahead buffer\n"));
  430. ExtendedError = TRUE;
  431. }
  432. else
  433. {
  434. FreeArcnetLookaheadBuffer = TRUE;
  435. NdisZeroMemory(Miniport->ArcBuf->ArcnetLookaheadBuffer,
  436. Miniport->MaximumLookahead);
  437. }
  438. break;
  439. #endif
  440. case NdisMediumWan:
  441. Miniport->MaximumLookahead = NDIS_M_MAX_LOOKAHEAD - 14;
  442. break;
  443. case NdisMediumIrda:
  444. case NdisMediumWirelessWan:
  445. case NdisMediumLocalTalk:
  446. Miniport->MaximumLookahead = GenericUlong;
  447. //
  448. // fall through
  449. //
  450. default:
  451. break;
  452. }
  453. //
  454. // Was there an error?
  455. //
  456. if (ExtendedError)
  457. {
  458. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  459. (" Extended error when processing OID_GEN_MAXIMUM_LOOOKAHEAD\n"));
  460. ErrorCode = 1;
  461. break;
  462. }
  463. //
  464. // For lan media query the real
  465. // stuff. We also need to call this for wan drivers.
  466. //
  467. if (((Miniport->MediaType >= 0) &&
  468. (Miniport->MediaType < NdisMediumMax) &&
  469. ndisMediaTypeCl[Miniport->MediaType]) ||
  470. (NdisMediumWan == Miniport->MediaType))
  471. {
  472. //
  473. // Query mac options
  474. //
  475. ErrorCode = ndisMDoMiniportOp(Miniport,
  476. TRUE,
  477. OID_GEN_MAC_OPTIONS,
  478. &GenericUlong,
  479. sizeof(GenericUlong),
  480. 0x3,
  481. TRUE);
  482. if (ErrorCode != 0)
  483. {
  484. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  485. (" Error querying OID_GEN_MAC_OPTIONS\n"));
  486. break;
  487. }
  488. //
  489. // NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE bit in MacOption
  490. // is set by Ndis when/if the driver calls NdisReadNetworkAddress
  491. // so make sure we don't override this
  492. //
  493. Miniport->MacOptions |= (UINT)GenericUlong;
  494. if (Miniport->MacOptions & NDIS_MAC_OPTION_NO_LOOPBACK)
  495. {
  496. MINIPORT_SET_FLAG(Miniport, fMINIPORT_DOES_NOT_DO_LOOPBACK);
  497. }
  498. //
  499. // complain if this is a hardware based device and wants to do loopback itself
  500. //
  501. NDIS_WARN(MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_HARDWARE_DEVICE) &&
  502. !(Miniport->MacOptions & NDIS_MAC_OPTION_NO_LOOPBACK),
  503. Miniport, NDIS_GFLAG_WARN_LEVEL_1,
  504. ("ndisMInitializeAdapter: -Hardware Based- Miniport %p says it does loopback.\n", Miniport));
  505. if ((Miniport->MacOptions & NDISWAN_OPTIONS) == NDISWAN_OPTIONS)
  506. {
  507. Miniport->MaximumLookahead = NDIS_M_MAX_LOOKAHEAD - 14;
  508. }
  509. }
  510. //
  511. // Query media-connect state. By default, it is connected. Avoid doing
  512. // this for NDISWAN miniports which are identified in the following
  513. // convoluted way
  514. // only do it for the media that needs to be polled to indicate the correct
  515. // status. for the rest assume it is connected and let the miniport to
  516. // indicate otherwise. this way miniports can pend this OID till they find
  517. // their media connect status (which can take up to a few seconds) without
  518. // affecting the initialization time
  519. //
  520. MINIPORT_SET_FLAG(Miniport, fMINIPORT_MEDIA_CONNECTED);
  521. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_REQUIRES_MEDIA_POLLING) &&
  522. (NdisMediumWan != Miniport->MediaType) &&
  523. ndisMediaTypeCl[Miniport->MediaType] &&
  524. ((Miniport->MacOptions & NDISWAN_OPTIONS) != NDISWAN_OPTIONS) &&
  525. (pMiniBlock->AssociatedProtocol == NULL) &&
  526. ndisMDoMiniportOp(Miniport,
  527. TRUE,
  528. OID_GEN_MEDIA_CONNECT_STATUS,
  529. &GenericUlong,
  530. sizeof(GenericUlong),
  531. 0,
  532. TRUE) == 0)
  533. {
  534. PNDIS_REQUEST Request;
  535. if (GenericUlong == NdisMediaStateConnected)
  536. {
  537. MINIPORT_SET_FLAG(Miniport, fMINIPORT_MEDIA_CONNECTED);
  538. }
  539. else
  540. {
  541. MINIPORT_CLEAR_FLAG(Miniport, fMINIPORT_MEDIA_CONNECTED);
  542. }
  543. //
  544. // Allocate a request structure to do media queries
  545. //
  546. Request = (PNDIS_REQUEST)ALLOC_FROM_POOL(sizeof(NDIS_REQUEST) + sizeof(ULONG),
  547. NDIS_TAG_Q_REQ);
  548. if (Request == NULL)
  549. {
  550. ErrorCode = 0x01;
  551. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  552. ("ndisMInitializeAdapter: Error querying the OID_GEN_MAXIMUM_LOOKAHEAD\n"));
  553. break;
  554. }
  555. Miniport->MediaRequest = Request;
  556. ZeroMemory(Request, sizeof(NDIS_REQUEST) + sizeof(ULONG));
  557. INITIALIZE_EVENT(&(PNDIS_COREQ_RESERVED_FROM_REQUEST(Request)->Event));
  558. Request->RequestType = NdisRequestQueryInformation;
  559. //
  560. // Copy the buffer that was passed to us into the new buffer.
  561. //
  562. Request->DATA.QUERY_INFORMATION.Oid = OID_GEN_MEDIA_CONNECT_STATUS;
  563. Request->DATA.QUERY_INFORMATION.InformationBuffer = Request + 1;
  564. Request->DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(ULONG);
  565. Miniport->InfoFlags |= NDIS_MINIPORT_SUPPORTS_MEDIA_QUERY;
  566. PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Flags = REQST_COMPLETED;
  567. Miniport->CheckForHangSeconds = NDIS_CFHANG_TIME_SECONDS;
  568. }
  569. else
  570. {
  571. //
  572. // Since we are not polling for media-state, set the tick to 1 and adjust
  573. // timer value back to what we need.
  574. // Clear the Requires Media Polling flag as ndis cannot query the adapter for connectivity
  575. //
  576. Miniport->CheckForHangSeconds = Miniport->CFHangTicks*NDIS_CFHANG_TIME_SECONDS;
  577. Miniport->CFHangTicks = 1;
  578. MINIPORT_CLEAR_FLAG(Miniport, fMINIPORT_REQUIRES_MEDIA_POLLING);
  579. }
  580. Miniport->CFHangCurrentTick = Miniport->CFHangTicks;
  581. if (MINIPORT_TEST_SEND_FLAG(Miniport, fMINIPORT_SEND_PACKET_ARRAY))
  582. {
  583. //
  584. // If this miniport supports SendPacketsHandler then we need to query
  585. // the maximum number of packets that the miniport supports in a single
  586. // call.
  587. //
  588. ErrorCode = ndisMDoMiniportOp(Miniport,
  589. TRUE,
  590. OID_GEN_MAXIMUM_SEND_PACKETS,
  591. &GenericUlong,
  592. sizeof(GenericUlong),
  593. 0x2,
  594. TRUE);
  595. if (ErrorCode != 0)
  596. {
  597. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  598. ("Error querying OID_GEN_MAXIMUM_SEND_PACKETS\n"));
  599. //
  600. // Don't error out. If the miniport did not respond to this, it does
  601. // not limit it, so we use what makes sense to us which is SEND_PACKET_ARRAY
  602. //
  603. }
  604. Miniport->MaxSendPackets = SEND_PACKET_ARRAY;
  605. if (GenericUlong < SEND_PACKET_ARRAY)
  606. {
  607. Miniport->MaxSendPackets = (USHORT)GenericUlong;
  608. }
  609. }
  610. //
  611. // Query the miniport so we can create the right filter package as appropriate
  612. //
  613. switch(Miniport->MediaType)
  614. {
  615. case NdisMedium802_3:
  616. //
  617. // Query maximum MulticastAddress
  618. //
  619. ErrorCode = ndisMDoMiniportOp(Miniport,
  620. TRUE,
  621. OID_802_3_MAXIMUM_LIST_SIZE,
  622. &MaximumLongAddresses,
  623. sizeof(GenericUlong),
  624. 0x7,
  625. TRUE);
  626. if (ErrorCode != 0)
  627. {
  628. ExtendedError = TRUE;
  629. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  630. (" Error querying OID_802_3_MAXIMUM_LIST_SIZE\n"));
  631. break;
  632. }
  633. Miniport->MaximumLongAddresses = MaximumLongAddresses;
  634. ErrorCode = ndisMDoMiniportOp(Miniport,
  635. TRUE,
  636. OID_802_3_CURRENT_ADDRESS,
  637. &CurrentLongAddress,
  638. sizeof(CurrentLongAddress),
  639. 0x9,
  640. TRUE);
  641. if (ErrorCode != 0)
  642. {
  643. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  644. (" Error querying OID_802_3_CURRENT_ADDRESS\n"));
  645. ExtendedError = TRUE;
  646. break;
  647. }
  648. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  649. ("ndisMInitializeAdapter: Miniport %p, Ethernet Address %02X %02X %02X %02X %02X %02X\n",
  650. Miniport,
  651. CurrentLongAddress[0],
  652. CurrentLongAddress[1],
  653. CurrentLongAddress[2],
  654. CurrentLongAddress[3],
  655. CurrentLongAddress[4],
  656. CurrentLongAddress[5]));
  657. ErrorCode = ndisMDoMiniportOp(Miniport,
  658. TRUE,
  659. OID_GEN_PHYSICAL_MEDIUM,
  660. &GenericUlong,
  661. sizeof(GenericUlong),
  662. 0xa,
  663. TRUE);
  664. if (ErrorCode != 0)
  665. {
  666. //
  667. // It is okay for a miniport to not support OID_GEN_PHYSICAL_MEDIUM,
  668. // so we let this go.
  669. //
  670. ErrorCode = 0;
  671. break;
  672. }
  673. Miniport->PhysicalMediumType = GenericUlong;
  674. ndisMNotifyMachineName(Miniport, NULL);
  675. break;
  676. case NdisMedium802_5:
  677. ErrorCode = ndisMDoMiniportOp(Miniport,
  678. TRUE,
  679. OID_802_5_CURRENT_ADDRESS,
  680. &CurrentLongAddress,
  681. sizeof(CurrentLongAddress),
  682. 0xB,
  683. TRUE);
  684. if (ErrorCode != 0)
  685. {
  686. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  687. (" Error querying OID_802_5_CURRENT_ADDRESS\n"));
  688. ExtendedError = TRUE;
  689. }
  690. break;
  691. case NdisMediumFddi:
  692. //
  693. // Query maximum MulticastAddress
  694. //
  695. ErrorCode = ndisMDoMiniportOp(Miniport,
  696. TRUE,
  697. OID_FDDI_LONG_MAX_LIST_SIZE,
  698. &MaximumLongAddresses,
  699. sizeof(GenericUlong),
  700. 0xD,
  701. TRUE);
  702. if (ErrorCode != 0)
  703. {
  704. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  705. (" Error querying OID_FDDI_LONG_MAX_LIST_SIZE\n"));
  706. ExtendedError = TRUE;
  707. break;
  708. }
  709. Miniport->MaximumLongAddresses = MaximumLongAddresses;
  710. //
  711. // Query maximum MulticastAddress
  712. //
  713. ErrorCode = ndisMDoMiniportOp(Miniport,
  714. TRUE,
  715. OID_FDDI_SHORT_MAX_LIST_SIZE,
  716. &MaximumShortAddresses,
  717. sizeof(MaximumShortAddresses),
  718. 0xF,
  719. TRUE);
  720. if (ErrorCode != 0)
  721. {
  722. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  723. (" Error querying OID_FDDI_SHORT_MAX_LIST_SIZE\n"));
  724. ExtendedError = TRUE;
  725. break;
  726. }
  727. Miniport->MaximumShortAddresses = MaximumShortAddresses;
  728. ErrorCode = ndisMDoMiniportOp(Miniport,
  729. TRUE,
  730. OID_FDDI_LONG_CURRENT_ADDR,
  731. &CurrentLongAddress,
  732. sizeof(CurrentLongAddress),
  733. 0x11,
  734. TRUE);
  735. if (ErrorCode != 0)
  736. {
  737. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  738. (" Error querying OID_FDDI_LONG_CURRENT_ADDR\n"));
  739. ExtendedError = TRUE;
  740. break;
  741. }
  742. ErrorCode = ndisMDoMiniportOp(Miniport,
  743. TRUE,
  744. OID_FDDI_SHORT_CURRENT_ADDR,
  745. &CurrentShortAddress,
  746. sizeof(CurrentShortAddress),
  747. 0x13,
  748. TRUE);
  749. if (ErrorCode != 0)
  750. {
  751. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  752. (" Error querying OID_FDDI_SHORT_CURRENT_ADDR\n"));
  753. ExtendedError = TRUE;
  754. break;
  755. }
  756. break;
  757. #if ARCNET
  758. case NdisMediumArcnet878_2:
  759. //
  760. // In case of an encapsulated ethernet binding, we need
  761. // to return the maximum number of multicast addresses
  762. // possible.
  763. //
  764. Miniport->MaximumLongAddresses = NDIS_M_MAX_MULTI_LIST;
  765. //
  766. // Allocate Buffer pools
  767. //
  768. NdisAllocateBufferPool(&NdisStatus,
  769. &Miniport->ArcBuf->ArcnetBufferPool,
  770. ARC_SEND_BUFFERS);
  771. if (NdisStatus != NDIS_STATUS_SUCCESS)
  772. {
  773. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  774. (" Failed to allocate buffer pool for arcnet\n"));
  775. ErrorCode = 0x16;
  776. ExtendedError = TRUE;
  777. break;
  778. }
  779. DataBuffer = ALLOC_FROM_POOL(ARC_HEADER_SIZE * ARC_SEND_BUFFERS, NDIS_TAG_ARC_SEND_BUFFERS);
  780. if (DataBuffer == NULL)
  781. {
  782. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  783. (" Failed to allocate memory for arcnet data buffers\n"));
  784. NdisFreeBufferPool(Miniport->ArcBuf->ArcnetBufferPool);
  785. ErrorCode = 0x18;
  786. ExtendedError = TRUE;
  787. break;
  788. }
  789. ZeroMemory(DataBuffer, ARC_HEADER_SIZE * ARC_SEND_BUFFERS);
  790. for (i = 0; i < ARC_SEND_BUFFERS; i++)
  791. {
  792. PARC_BUFFER_LIST Buffer = &Miniport->ArcBuf->ArcnetBuffers[i];
  793. Buffer->BytesLeft = Buffer->Size = ARC_HEADER_SIZE;
  794. Buffer->Buffer = DataBuffer;
  795. Buffer->Next = NULL; // This implies that it is free
  796. DataBuffer = (((PUCHAR)DataBuffer) + ARC_HEADER_SIZE);
  797. }
  798. Miniport->ArcBuf->NumFree = ARC_SEND_BUFFERS;
  799. //
  800. // Get current address
  801. //
  802. ErrorCode = ndisMDoMiniportOp(Miniport,
  803. TRUE,
  804. OID_ARCNET_CURRENT_ADDRESS,
  805. &CurrentLongAddress[5], // address = 00-00-00-00-00-XX
  806. 1,
  807. 0x15,
  808. TRUE);
  809. if (ErrorCode != 0)
  810. {
  811. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  812. (" Error querying OID_ARCNET_CURRENT_ADDRESS\n"));
  813. FREE_POOL(DataBuffer);
  814. NdisFreeBufferPool(Miniport->ArcBuf->ArcnetBufferPool);
  815. ExtendedError = TRUE;
  816. break;
  817. }
  818. Miniport->ArcnetAddress = CurrentLongAddress[5];
  819. break;
  820. #endif
  821. case NdisMediumWan:
  822. ErrorCode = ndisMDoMiniportOp(Miniport,
  823. TRUE,
  824. OID_WAN_CURRENT_ADDRESS,
  825. &CurrentLongAddress,
  826. sizeof(CurrentLongAddress),
  827. 0x17,
  828. TRUE);
  829. if (ErrorCode != 0)
  830. {
  831. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  832. (" Error querying OID_WAN_CURRENT_ADDRESS\n"));
  833. ExtendedError = TRUE;
  834. break;
  835. }
  836. default:
  837. ErrorCode = 0;
  838. break;
  839. }
  840. if (ErrorCode != 0)
  841. {
  842. break;
  843. }
  844. //
  845. // Now create the filter package, as appropriate. Note that CurrentLongAddress etc.
  846. // are still valid from the abover switch statement
  847. //
  848. switch(Miniport->MediaType)
  849. {
  850. case NdisMedium802_3:
  851. fRc = EthCreateFilter(MaximumLongAddresses,
  852. CurrentLongAddress,
  853. &FilterDB.EthDB);
  854. if (!fRc)
  855. {
  856. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  857. (" Error creating the Ethernet filter database\n"));
  858. ErrorCode = 0x9;
  859. ExtendedError = TRUE;
  860. break;
  861. }
  862. FilterDB.EthDB->Miniport = Miniport;
  863. break;
  864. case NdisMedium802_5:
  865. fRc = TrCreateFilter(CurrentLongAddress,
  866. &FilterDB.TrDB);
  867. if (!fRc)
  868. {
  869. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  870. (" Error creating the Token Ring filter database\n"));
  871. ErrorCode = 0xC;
  872. ExtendedError = TRUE;
  873. break;
  874. }
  875. FilterDB.TrDB->Miniport = Miniport;
  876. break;
  877. case NdisMediumFddi:
  878. fRc = FddiCreateFilter(MaximumLongAddresses,
  879. MaximumShortAddresses,
  880. CurrentLongAddress,
  881. CurrentShortAddress,
  882. &FilterDB.FddiDB);
  883. if (!fRc)
  884. {
  885. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  886. (" Error creating the FDDI filter database\n"));
  887. ErrorCode = 0x15;
  888. ExtendedError = TRUE;
  889. break;
  890. }
  891. FilterDB.FddiDB->Miniport = Miniport;
  892. break;
  893. #if ARCNET
  894. case NdisMediumArcnet878_2:
  895. if (!ArcCreateFilter(Miniport,
  896. CurrentLongAddress[5],
  897. &FilterDB.ArcDB))
  898. {
  899. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  900. (" Error creating the Arcnet filter database\n"));
  901. FREE_POOL(DataBuffer);
  902. NdisFreeBufferPool(Miniport->ArcBuf->ArcnetBufferPool);
  903. ErrorCode = 0x1B;
  904. ExtendedError = TRUE;
  905. break;
  906. }
  907. FilterDB.ArcDB->Miniport = Miniport;
  908. //
  909. // Zero all but the last one.
  910. //
  911. CurrentLongAddress[0] = 0;
  912. CurrentLongAddress[1] = 0;
  913. CurrentLongAddress[2] = 0;
  914. CurrentLongAddress[3] = 0;
  915. CurrentLongAddress[4] = 0;
  916. if (!EthCreateFilter(32,
  917. CurrentLongAddress,
  918. &FilterDB.EthDB))
  919. {
  920. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  921. (" Error creating the Arcnet filter database for encapsulated ethernet\n"));
  922. //
  923. // Delete the arcnet filter.
  924. //
  925. ArcDeleteFilter(FilterDB.ArcDB);
  926. FREE_POOL(DataBuffer);
  927. NdisFreeBufferPool(Miniport->ArcBuf->ArcnetBufferPool);
  928. ErrorCode = 0x1C;
  929. ExtendedError = TRUE;
  930. break;
  931. }
  932. FilterDB.EthDB->Miniport = Miniport;
  933. break;
  934. #endif
  935. default:
  936. fRc = nullCreateFilter(&FilterDB.NullDB);
  937. if (!fRc)
  938. {
  939. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  940. (" Error creating the NULL filter database\n"));
  941. ErrorCode = 0x1E;
  942. ExtendedError = TRUE;
  943. break;
  944. }
  945. FilterDB.NullDB->Miniport = Miniport;
  946. break;
  947. }
  948. //
  949. // If we successfully create the adapter instance name then we
  950. // register with WMI.
  951. //
  952. //
  953. // let 'em know we can handle WMI requests from IRP_MJ_SYSTEM_CONTROL.
  954. //
  955. NtStatus = IoWMIRegistrationControl(Miniport->DeviceObject, WMIREG_ACTION_REGISTER);
  956. if (!NT_SUCCESS(NtStatus))
  957. {
  958. DBGPRINT((DBG_COMP_INIT | DBG_COMP_WMI), DBG_LEVEL_WARN,
  959. (" ndisMInitializeAdapter: Failed to register for WMI support\n"));
  960. ErrorCode = 0x1F;
  961. ExtendedError = TRUE;
  962. }
  963. else
  964. {
  965. WmiDeregister = TRUE;
  966. }
  967. //
  968. // Do we need to log an error?
  969. //
  970. if (ExtendedError)
  971. {
  972. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  973. (" Extended error while initializing the miniport\n"));
  974. NdisWriteErrorLogEntry((NDIS_HANDLE)Miniport,
  975. NDIS_ERROR_CODE_DRIVER_FAILURE,
  976. 2,
  977. 0xFF00FF00,
  978. ErrorCode);
  979. break;
  980. }
  981. //
  982. // force a IRP_MN_QUERY_PNP_DEVICE_STATE PnP Irp so we can set the
  983. // PNP_DEVICE_DONT_DISPLAY_IN_UI bit
  984. //
  985. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_HIDDEN))
  986. {
  987. IoInvalidateDeviceState(Miniport->PhysicalDeviceObject);
  988. }
  989. NtStatus = STATUS_SUCCESS;
  990. //
  991. // Determine PnP/PM capabilities for this adapter.
  992. // But only if the bus drive says it supports PM
  993. // except when dealing with IM drivers!
  994. //
  995. if ((MINIPORT_PNP_TEST_FLAG(Miniport, (fMINIPORT_PM_SUPPORTED | fMINIPORT_NO_HALT_ON_SUSPEND)) ||
  996. (Miniport->DriverHandle->Flags & fMINIBLOCK_INTERMEDIATE_DRIVER)) &&
  997. (Miniport->MediaType >= 0) &&
  998. (Miniport->MediaType < NdisMediumMax))
  999. {
  1000. //
  1001. // Query the miniport for it's pnp capabilities.
  1002. // If it doesn't support any then it won't handle this
  1003. // OID.
  1004. //
  1005. ErrorCode = ndisMDoMiniportOp(Miniport,
  1006. TRUE,
  1007. OID_PNP_CAPABILITIES,
  1008. &Miniport->PMCapabilities,
  1009. sizeof(Miniport->PMCapabilities),
  1010. 0x19,
  1011. FALSE);
  1012. //
  1013. // reserved flags that miniports are not suposed to write to
  1014. // zero it out just in case they do
  1015. //
  1016. Miniport->PMCapabilities.Flags = 0;
  1017. if (0 == ErrorCode)
  1018. {
  1019. SYSTEM_POWER_STATE SystemState;
  1020. DEVICE_POWER_STATE DeviceState;
  1021. BOOLEAN WakeupCapable = TRUE;
  1022. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_PM_SUPPORTED);
  1023. if ((Miniport->PMCapabilities.WakeUpCapabilities.MinLinkChangeWakeUp == NdisDeviceStateUnspecified) &&
  1024. (Miniport->PMCapabilities.WakeUpCapabilities.MinMagicPacketWakeUp == NdisDeviceStateUnspecified) &&
  1025. (Miniport->PMCapabilities.WakeUpCapabilities.MinPatternWakeUp == NdisDeviceStateUnspecified))
  1026. {
  1027. WakeupCapable = FALSE;
  1028. }
  1029. else
  1030. {
  1031. if (Miniport->DeviceCaps.SystemWake <= PowerSystemWorking)
  1032. {
  1033. WakeupCapable = FALSE;
  1034. }
  1035. else
  1036. {
  1037. for (SystemState = PowerSystemSleeping1;
  1038. SystemState <= Miniport->DeviceCaps.SystemWake;
  1039. SystemState++)
  1040. {
  1041. DeviceState = Miniport->DeviceCaps.DeviceState[SystemState];
  1042. if ((DeviceState != PowerDeviceUnspecified) &&
  1043. (DeviceState <= Miniport->PMCapabilities.WakeUpCapabilities.MinPatternWakeUp))
  1044. {
  1045. //
  1046. // check for device state to make sure the device can go to this state
  1047. // any device should be able to go to D0 or D3, so only check for D1 and D2
  1048. //
  1049. if (((DeviceState == PowerDeviceD1) && !Miniport->DeviceCaps.DeviceD1) ||
  1050. ((DeviceState == PowerDeviceD2) && !Miniport->DeviceCaps.DeviceD2))
  1051. {
  1052. //
  1053. // we can't do WOL from this system state. check the next one
  1054. //
  1055. continue;
  1056. }
  1057. else
  1058. {
  1059. //
  1060. // there is at least one system state from which the device can do
  1061. // WOL.
  1062. //
  1063. break;
  1064. }
  1065. }
  1066. }
  1067. if (SystemState > Miniport->DeviceCaps.SystemWake)
  1068. {
  1069. WakeupCapable = FALSE;
  1070. DBGPRINT_RAW(DBG_COMP_PM, DBG_LEVEL_INFO, ("ndisMInitializeAdapter: WOL not possible on this miniport: %p \n", Miniport));
  1071. }
  1072. }
  1073. }
  1074. if (!WakeupCapable)
  1075. {
  1076. //
  1077. // set SystemWake to PowerSystemWorking so everybody knows we can not do
  1078. // WOL on this machine but we may be able to put the device to sleep
  1079. // when it is disconnected for some time.
  1080. // note that at this point we already know the SystemWake is != PowerSystemUnspecified
  1081. //
  1082. Miniport->DeviceCaps.SystemWake = PowerSystemWorking;
  1083. }
  1084. if (!(Miniport->PnPCapabilities & NDIS_DEVICE_DISABLE_PM))
  1085. {
  1086. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_DEVICE_POWER_ENABLE);
  1087. if ((Miniport->PMCapabilities.WakeUpCapabilities.MinLinkChangeWakeUp != NdisDeviceStateUnspecified) &&
  1088. (Miniport->MediaDisconnectTimeOut != (USHORT)(-1)))
  1089. {
  1090. //
  1091. // If the miniport is capable of wake-up for a link change
  1092. // then we need to allocate a timer for timeout.
  1093. //
  1094. Miniport->WakeUpEnable |= NDIS_PNP_WAKE_UP_LINK_CHANGE;
  1095. }
  1096. if (!(Miniport->PnPCapabilities & NDIS_DEVICE_DISABLE_WAKE_UP) &&
  1097. WakeupCapable)
  1098. {
  1099. if ((Miniport->PMCapabilities.WakeUpCapabilities.MinPatternWakeUp != NdisDeviceStateUnspecified) &&
  1100. !(Miniport->PnPCapabilities & NDIS_DEVICE_DISABLE_WAKE_ON_PATTERN_MATCH))
  1101. {
  1102. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_DEVICE_POWER_WAKE_ENABLE);
  1103. //
  1104. // NDIS_DEVICE_WAKE_UP_ENABLE bit is used by tcp/ip to decide whether or not to set a timer
  1105. // to renew DHCP address. set this flag only if packet matching is enabled
  1106. //
  1107. Miniport->PMCapabilities.Flags |= (NDIS_DEVICE_WAKE_UP_ENABLE | NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE);
  1108. }
  1109. //
  1110. // no protocol is going to set the magic packet wake up method. so ndis
  1111. // does it itself (unless specified otherwise in registry)
  1112. //
  1113. if ((Miniport->PMCapabilities.WakeUpCapabilities.MinMagicPacketWakeUp != NdisDeviceStateUnspecified) &&
  1114. !(Miniport->PnPCapabilities & NDIS_DEVICE_DISABLE_WAKE_ON_MAGIC_PACKET))
  1115. {
  1116. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_DEVICE_POWER_WAKE_ENABLE);
  1117. Miniport->PMCapabilities.Flags |= NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE;
  1118. Miniport->WakeUpEnable |= NDIS_PNP_WAKE_UP_MAGIC_PACKET;
  1119. }
  1120. }
  1121. }
  1122. IF_DBG(DBG_COMP_PM, DBG_LEVEL_INFO)
  1123. {
  1124. DbgPrint("ndisMInitializeAdapter: Driver says Miniport %p supports PM\n", Miniport);
  1125. DbgPrint("\tMinMagicPacketWakeUp: %ld\n", Miniport->PMCapabilities.WakeUpCapabilities.MinMagicPacketWakeUp);
  1126. DbgPrint("\tMinPatternWakeUp: %ld\n", Miniport->PMCapabilities.WakeUpCapabilities.MinPatternWakeUp);
  1127. DbgPrint("\tMinLinkChangeWakeUp: %ld\n", Miniport->PMCapabilities.WakeUpCapabilities.MinLinkChangeWakeUp);
  1128. }
  1129. }
  1130. else
  1131. {
  1132. MINIPORT_PNP_CLEAR_FLAG(Miniport, fMINIPORT_PM_SUPPORTED);
  1133. }
  1134. ErrorCode = 0;
  1135. }
  1136. //
  1137. // we initialize this timer anyway, just in case user enables "media disconnect sleep" at run-time
  1138. // when -setting- the timer however, we will check to make sure the media disconnect feature is enabled
  1139. //
  1140. NdisInitializeTimer(&Miniport->MediaDisconnectTimer, ndisMediaDisconnectTimeout, Miniport);
  1141. ErrorCode = 1;
  1142. //
  1143. // Register the device class.
  1144. //
  1145. NtStatus = IoRegisterDeviceInterface(Miniport->PhysicalDeviceObject,
  1146. &guidLanClass,
  1147. &Miniport->BaseName,
  1148. &Miniport->SymbolicLinkName);
  1149. if (!NT_SUCCESS(NtStatus))
  1150. {
  1151. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
  1152. (" ndisMInitializeAdapter: IoRegisterDeviceClassAssociation failed\n"));
  1153. break;
  1154. }
  1155. //
  1156. // setting this flag obviously is not necessary because we are going
  1157. // to clear it right away. but leave it here just in case we end up
  1158. // doing something that can fail the initialization -after- this.
  1159. //
  1160. ClearDeviceClassAssociation = TRUE;
  1161. //
  1162. // Set to not cleanup
  1163. //
  1164. ErrorCode = 0;
  1165. HaltMiniport = FALSE;
  1166. DerefDriver = FreeBuffer = Dequeue = FALSE;
  1167. #if ARCNET
  1168. FreeArcnetLookaheadBuffer = FALSE;
  1169. #endif
  1170. ClearDeviceClassAssociation = FALSE;
  1171. DeleteSymbolicLink = FALSE;
  1172. WmiDeregister = FALSE;
  1173. //
  1174. // Finally mark the device as *NOT* initializing. This is to let
  1175. // layered miniports initialize their device instance *OUTSIDE*
  1176. // of their driver entry. If this flag is on, then NdisOpenAdapter
  1177. // to this device will not work. This is also true of subsequent
  1178. // instances of a driver initializing outside of its DriverEntry
  1179. // as a result of a PnP event.
  1180. //
  1181. Miniport->DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  1182. //
  1183. // Start wake up timer
  1184. //
  1185. NdisMSetPeriodicTimer((PNDIS_MINIPORT_TIMER)(&Miniport->WakeUpDpcTimer),
  1186. Miniport->CheckForHangSeconds*1000);
  1187. //
  1188. // Notify WMI of adapter arrival.
  1189. //
  1190. {
  1191. PWNODE_SINGLE_INSTANCE wnode;
  1192. PUCHAR ptmp;
  1193. NTSTATUS NtStatus;
  1194. ndisSetupWmiNode(Miniport,
  1195. Miniport->pAdapterInstanceName,
  1196. Miniport->MiniportName.Length + sizeof(USHORT),
  1197. (PVOID)&GUID_NDIS_NOTIFY_ADAPTER_ARRIVAL,
  1198. &wnode);
  1199. if (wnode != NULL)
  1200. {
  1201. //
  1202. // Save the number of elements in the first ULONG.
  1203. //
  1204. ptmp = (PUCHAR)wnode + wnode->DataBlockOffset;
  1205. *((PUSHORT)ptmp) = Miniport->MiniportName.Length;
  1206. //
  1207. // Copy the data after the number of elements.
  1208. //
  1209. RtlCopyMemory(ptmp + sizeof(USHORT),
  1210. Miniport->MiniportName.Buffer,
  1211. Miniport->MiniportName.Length);
  1212. //
  1213. // Indicate the event to WMI. WMI will take care of freeing
  1214. // the WMI struct back to pool.
  1215. //
  1216. NtStatus = IoWMIWriteEvent(wnode);
  1217. if (!NT_SUCCESS(NtStatus))
  1218. {
  1219. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  1220. ("ndisMInitializeAdapter: Failed to indicate adapter arrival\n"));
  1221. FREE_POOL(wnode);
  1222. }
  1223. }
  1224. }
  1225. //
  1226. // let the adapter know about the current power source
  1227. //
  1228. PowerProfile = ((BOOLEAN)ndisAcOnLine == TRUE) ?
  1229. NdisPowerProfileAcOnLine :
  1230. NdisPowerProfileBattery;
  1231. ndisNotifyMiniports(Miniport,
  1232. NdisDevicePnPEventPowerProfileChanged,
  1233. &PowerProfile,
  1234. sizeof(NDIS_POWER_PROFILE));
  1235. }
  1236. else
  1237. {
  1238. NdisMDeregisterAdapterShutdownHandler(Miniport);
  1239. ndisLastFailedInitErrorCode = ErrorCode = MiniportInitializeStatus;
  1240. ASSERT(Miniport->Interrupt == NULL);
  1241. ASSERT(Miniport->TimerQueue == NULL);
  1242. ASSERT(Miniport->MapRegisters == NULL);
  1243. if ((Miniport->TimerQueue != NULL) || (Miniport->Interrupt != NULL))
  1244. {
  1245. if (Miniport->Interrupt != NULL)
  1246. {
  1247. BAD_MINIPORT(Miniport, "Unloading without deregistering interrupt");
  1248. }
  1249. else
  1250. {
  1251. BAD_MINIPORT(Miniport, "Unloading without deregistering timer");
  1252. }
  1253. KeBugCheckEx(BUGCODE_ID_DRIVER,
  1254. (ULONG_PTR)Miniport,
  1255. (ULONG_PTR)Miniport->Interrupt,
  1256. (ULONG_PTR)Miniport->TimerQueue,
  1257. 1);
  1258. }
  1259. }
  1260. } while (FALSE);
  1261. ndisMAdjustFilters(Miniport, &FilterDB);
  1262. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  1263. {
  1264. Miniport->SendPacketsHandler = ndisMSendPacketsX;
  1265. }
  1266. else
  1267. {
  1268. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_SG_LIST))
  1269. {
  1270. Miniport->SendPacketsHandler = ndisMSendPacketsSG;
  1271. if (pMiniBlock->MiniportCharacteristics.SendPacketsHandler)
  1272. {
  1273. Miniport->DeferredSendHandler = ndisMStartSendPacketsSG;
  1274. }
  1275. else
  1276. {
  1277. Miniport->DeferredSendHandler = ndisMStartSendsSG;
  1278. }
  1279. }
  1280. else
  1281. {
  1282. Miniport->SendPacketsHandler = ndisMSendPackets;
  1283. }
  1284. }
  1285. ndisMSetIndicatePacketHandler(Miniport);
  1286. Miniport->SavedPacketIndicateHandler = Miniport->PacketIndicateHandler;
  1287. //
  1288. // Perform any necessary cleanup.
  1289. //
  1290. //
  1291. if (WmiDeregister)
  1292. {
  1293. //
  1294. // Deregister with WMI
  1295. //
  1296. IoWMIRegistrationControl(Miniport->DeviceObject, WMIREG_ACTION_DEREGISTER);
  1297. }
  1298. if (HaltMiniport)
  1299. {
  1300. (Miniport->DriverHandle->MiniportCharacteristics.HaltHandler)(Miniport->MiniportAdapterContext);
  1301. ASSERT(Miniport->TimerQueue == NULL);
  1302. ASSERT (Miniport->Interrupt == NULL);
  1303. ASSERT(Miniport->MapRegisters == NULL);
  1304. if ((Miniport->TimerQueue != NULL) || (Miniport->Interrupt != NULL))
  1305. {
  1306. if (Miniport->Interrupt != NULL)
  1307. {
  1308. BAD_MINIPORT(Miniport, "Unloading without deregistering interrupt");
  1309. }
  1310. else
  1311. {
  1312. BAD_MINIPORT(Miniport, "Unloading without deregistering timer");
  1313. }
  1314. KeBugCheckEx(BUGCODE_ID_DRIVER,
  1315. (ULONG_PTR)Miniport,
  1316. (ULONG_PTR)Miniport->TimerQueue,
  1317. (ULONG_PTR)Miniport->Interrupt,
  1318. 2);
  1319. }
  1320. }
  1321. if (FreeBuffer)
  1322. {
  1323. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  1324. (" INIT FAILURE: Freeing the miniport name.\n"));
  1325. }
  1326. #if ARCNET
  1327. if (FreeArcnetLookaheadBuffer)
  1328. {
  1329. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  1330. (" INIT FAILURE: Freeing the arcnet lookahead buffer.\n"));
  1331. FREE_POOL(Miniport->ArcBuf->ArcnetLookaheadBuffer);
  1332. FREE_POOL(Miniport->ArcBuf);
  1333. }
  1334. #endif
  1335. if (Dequeue)
  1336. {
  1337. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  1338. (" INIT FAILURE: Dequeueing the miniport from the driver block.\n"));
  1339. ndisDeQueueMiniportOnDriver(Miniport, pMiniBlock);
  1340. }
  1341. if (ClearDeviceClassAssociation)
  1342. {
  1343. IoSetDeviceInterfaceState(&Miniport->SymbolicLinkName, FALSE);
  1344. }
  1345. if (DeleteSymbolicLink)
  1346. {
  1347. NtStatus = IoDeleteSymbolicLink(&SymbolicLink);
  1348. if (!NT_SUCCESS(NtStatus))
  1349. {
  1350. #if DBG
  1351. DbgPrint("ndisMInitializeAdapter: deleting symbolic link name failed for miniport %p, SymbolicLinkName %p, NtStatus %lx\n",
  1352. Miniport, &SymbolicLink, NtStatus);
  1353. #endif
  1354. }
  1355. }
  1356. if (DerefDriver)
  1357. {
  1358. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  1359. (" INIT FAILURE: Dereferencing the miniport block.\n"));
  1360. ndisDereferenceDriver(pMiniBlock, FALSE);
  1361. }
  1362. if (ErrorCode != 0)
  1363. {
  1364. MiniportDereferencePackage();
  1365. }
  1366. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  1367. ("<==ndisMInitializeAdapter: Miniport %p, Status %lx\n", Miniport, ErrorCode));
  1368. return ErrorCode;
  1369. }
  1370. VOID
  1371. ndisMOpenAdapter(
  1372. OUT PNDIS_STATUS Status,
  1373. IN PNDIS_OPEN_BLOCK Open,
  1374. IN BOOLEAN UsingEncapsulation
  1375. )
  1376. /*++
  1377. Routine Description:
  1378. This routine handles opening a miniport directly from NdisOpenAdapter()
  1379. NOTE: called with Miniport spin lock held.
  1380. NOTE: for serialized drivers called with local lock held
  1381. Arguments:
  1382. Return Value:
  1383. None.
  1384. --*/
  1385. {
  1386. PNDIS_MINIPORT_BLOCK Miniport = Open->MiniportHandle;
  1387. PNDIS_PROTOCOL_BLOCK Protocol = Open->ProtocolHandle;
  1388. PNDIS_MAC_BLOCK FakeMac;
  1389. BOOLEAN FilterOpen;
  1390. BOOLEAN DerefMini = FALSE, DeQueueFromMiniport = FALSE, DeQueueFromProtocol = FALSE;
  1391. BOOLEAN FakeMacAllocated = FALSE;
  1392. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1393. ("==>ndisMOpenAdapter: Protocol %p, Miniport %p, Open %p\n",
  1394. Protocol,
  1395. Miniport,
  1396. Open));
  1397. ASSERT_MINIPORT_LOCKED(Miniport);
  1398. do
  1399. {
  1400. if (!MINIPORT_INCREMENT_REF(Miniport))
  1401. {
  1402. //
  1403. // The adapter is closing.
  1404. //
  1405. *Status = NDIS_STATUS_CLOSING;
  1406. break;
  1407. }
  1408. DerefMini = TRUE;
  1409. //
  1410. // Initialize the open block.
  1411. //
  1412. FakeMac = (PNDIS_MAC_BLOCK)Miniport->FakeMac;
  1413. if (FakeMac == NULL)
  1414. {
  1415. //
  1416. // Allocate a fake MAC block for the characteristics.
  1417. //
  1418. FakeMac = (PNDIS_MAC_BLOCK)ALLOC_FROM_POOL(sizeof(NDIS_MAC_BLOCK), NDIS_TAG_FAKE_MAC);
  1419. if (FakeMac == NULL)
  1420. {
  1421. *Status = NDIS_STATUS_RESOURCES;
  1422. break;
  1423. }
  1424. //
  1425. // Initialize the fake mac block.
  1426. //
  1427. ZeroMemory(FakeMac, sizeof(NDIS_MAC_BLOCK));
  1428. Miniport->FakeMac = (PVOID)FakeMac;
  1429. FakeMacAllocated = TRUE;
  1430. }
  1431. Open->MacHandle = (PVOID)FakeMac;
  1432. Open->MiniportAdapterContext = Miniport->MiniportAdapterContext;
  1433. Open->CurrentLookahead = (USHORT)Miniport->CurrentLookahead;
  1434. INITIALIZE_SPIN_LOCK(&Open->SpinLock);
  1435. DBGPRINT_RAW(DBG_COMP_OPENREF, DBG_LEVEL_INFO, (" =1 0x%x\n", Open));
  1436. Open->References = 1;
  1437. //
  1438. // Add an extra ref-count for connection-oriented miniports
  1439. // This is removed after the protocol is notified of open-afs
  1440. //
  1441. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IS_CO) &&
  1442. (Protocol->ProtocolCharacteristics.CoAfRegisterNotifyHandler != NULL))
  1443. {
  1444. Open->References ++;
  1445. }
  1446. if (UsingEncapsulation)
  1447. {
  1448. MINIPORT_SET_FLAG(Open, fMINIPORT_OPEN_USING_ETH_ENCAPSULATION);
  1449. }
  1450. //
  1451. // Save the handlers with the open block.
  1452. //
  1453. Open->WSendHandler = Miniport->DriverHandle->MiniportCharacteristics.SendHandler;
  1454. Open->WSendPacketsHandler = Miniport->WSendPacketsHandler;
  1455. Open->WTransferDataHandler = Miniport->DriverHandle->MiniportCharacteristics.TransferDataHandler;
  1456. Open->SendCompleteHandler = Protocol->ProtocolCharacteristics.SendCompleteHandler;
  1457. Open->TransferDataCompleteHandler = Protocol->ProtocolCharacteristics.TransferDataCompleteHandler;
  1458. Open->ReceiveHandler = Protocol->ProtocolCharacteristics.ReceiveHandler;
  1459. Open->ReceiveCompleteHandler = Protocol->ProtocolCharacteristics.ReceiveCompleteHandler;
  1460. Open->StatusHandler = Protocol->ProtocolCharacteristics.StatusHandler;
  1461. Open->StatusCompleteHandler = Protocol->ProtocolCharacteristics.StatusCompleteHandler;
  1462. Open->ResetCompleteHandler = Protocol->ProtocolCharacteristics.ResetCompleteHandler;
  1463. Open->RequestCompleteHandler = Protocol->ProtocolCharacteristics.RequestCompleteHandler;
  1464. Open->ResetHandler = ndisMReset;
  1465. Open->ReceivePacketHandler = Protocol->ProtocolCharacteristics.ReceivePacketHandler;
  1466. Open->RequestHandler = ndisMRequest;
  1467. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  1468. {
  1469. Open->RequestHandler = ndisMRequestX;
  1470. }
  1471. //
  1472. // for backward compatibility with macros that use this field
  1473. //
  1474. Open->BindingHandle = (NDIS_HANDLE)Open;
  1475. //
  1476. // for even more speed...
  1477. //
  1478. #if ARCNET
  1479. if (NdisMediumArcnet878_2 == Miniport->MediaType)
  1480. {
  1481. Open->TransferDataHandler = ndisMArcTransferData;
  1482. }
  1483. else
  1484. #endif
  1485. {
  1486. Open->TransferDataHandler = ndisMTransferData;
  1487. }
  1488. //
  1489. // Set the send handler in the open block.
  1490. //
  1491. switch (Miniport->MediaType)
  1492. {
  1493. #if ARCNET
  1494. case NdisMediumArcnet878_2:
  1495. Open->SendHandler = ndisMSend;
  1496. break;
  1497. #endif
  1498. case NdisMediumWan:
  1499. if (!MINIPORT_TEST_FLAG(Miniport, (fMINIPORT_IS_CO | fMINIPORT_IS_NDIS_5)))
  1500. {
  1501. Open->SendHandler = (PVOID)ndisMWanSend;
  1502. }
  1503. break;
  1504. default:
  1505. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  1506. {
  1507. DBGPRINT_RAW(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1508. (" Using ndisMSendX/ndisMSendPacketsX\n"));
  1509. Open->SendHandler = ndisMSendX;
  1510. }
  1511. else
  1512. {
  1513. DBGPRINT_RAW(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1514. (" Using ndisMSend/ndisMSendPackets\n"));
  1515. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_SG_LIST))
  1516. {
  1517. Open->SendHandler = ndisMSendSG;
  1518. }
  1519. else
  1520. {
  1521. Open->SendHandler = ndisMSend;
  1522. }
  1523. }
  1524. break;
  1525. }
  1526. //
  1527. // Set up the send packets handler.
  1528. //
  1529. Open->SendPacketsHandler = Miniport->SendPacketsHandler;
  1530. //
  1531. // For WAN miniports, the send handler is different.
  1532. //
  1533. if ((NdisMediumWan == Miniport->MediaType) &&
  1534. !MINIPORT_TEST_FLAG(Miniport, (fMINIPORT_IS_CO | fMINIPORT_IS_NDIS_5)))
  1535. {
  1536. Open->WanSendHandler = ndisMWanSend;
  1537. }
  1538. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IS_CO))
  1539. {
  1540. //
  1541. // NDIS 5.0 miniport extensions
  1542. //
  1543. Open->MiniportCoRequestHandler = Miniport->DriverHandle->MiniportCharacteristics.CoRequestHandler;
  1544. Open->MiniportCoCreateVcHandler = Miniport->DriverHandle->MiniportCharacteristics.CoCreateVcHandler;
  1545. //
  1546. // initialize Lists
  1547. //
  1548. InitializeListHead(&Open->ActiveVcHead);
  1549. InitializeListHead(&Open->InactiveVcHead);
  1550. //
  1551. // the convential send function is not available for CO miniports
  1552. // since this send function does not specify the Vc to send upon
  1553. // However for components which want to use this let them.
  1554. //
  1555. if ((Open->SendHandler == NULL) && (Open->SendPacketsHandler == NULL))
  1556. {
  1557. Open->SendHandler = ndisMRejectSend;
  1558. Open->SendPacketsHandler = ndisMRejectSendPackets;
  1559. }
  1560. }
  1561. Open->CancelSendPacketsHandler = Miniport->DriverHandle->MiniportCharacteristics.CancelSendPacketsHandler;
  1562. Miniport->SavedSendHandler = (PVOID)Open->SendHandler;
  1563. Miniport->SavedSendPacketsHandler = (PVOID)Open->SendPacketsHandler;
  1564. Miniport->SavedCancelSendPacketsHandler = (PVOID)Open->CancelSendPacketsHandler;
  1565. //
  1566. // insert the open on miniport and protocol queue
  1567. //
  1568. if (ndisQueueOpenOnMiniport(Miniport, Open))
  1569. {
  1570. DeQueueFromMiniport = TRUE;
  1571. }
  1572. else
  1573. {
  1574. *Status = NDIS_STATUS_OPEN_FAILED;
  1575. break;
  1576. }
  1577. if (ndisQueueOpenOnProtocol(Open, Protocol))
  1578. {
  1579. DeQueueFromProtocol = TRUE;
  1580. }
  1581. else
  1582. {
  1583. *Status = NDIS_STATUS_OPEN_FAILED;
  1584. break;
  1585. }
  1586. //
  1587. // Insert the open into the filter package
  1588. //
  1589. switch (Miniport->MediaType)
  1590. {
  1591. #if ARCNET
  1592. case NdisMediumArcnet878_2:
  1593. if (!UsingEncapsulation)
  1594. {
  1595. FilterOpen = ArcNoteFilterOpenAdapter(Miniport->ArcDB,
  1596. Open,
  1597. &Open->FilterHandle);
  1598. break;
  1599. }
  1600. #endif
  1601. //
  1602. // If we're using ethernet encapsulation then
  1603. // we simply fall through to the ethernet stuff.
  1604. //
  1605. case NdisMedium802_3:
  1606. FilterOpen = XNoteFilterOpenAdapter(Miniport->EthDB,
  1607. Open,
  1608. &Open->FilterHandle);
  1609. break;
  1610. case NdisMedium802_5:
  1611. FilterOpen = XNoteFilterOpenAdapter(Miniport->TrDB,
  1612. Open,
  1613. &Open->FilterHandle);
  1614. break;
  1615. case NdisMediumFddi:
  1616. FilterOpen = XNoteFilterOpenAdapter(Miniport->FddiDB,
  1617. Open,
  1618. &Open->FilterHandle);
  1619. break;
  1620. default:
  1621. FilterOpen = XNoteFilterOpenAdapter(Miniport->NullDB,
  1622. Open,
  1623. &Open->FilterHandle);
  1624. break;
  1625. }
  1626. //
  1627. // Check for an open filter failure.
  1628. //
  1629. if (!FilterOpen)
  1630. {
  1631. //
  1632. // Something went wrong, clean up and exit.
  1633. //
  1634. *Status = NDIS_STATUS_OPEN_FAILED;
  1635. break;
  1636. }
  1637. if (FakeMacAllocated)
  1638. {
  1639. FakeMac->MacCharacteristics.TransferDataHandler = ndisMTransferData;
  1640. FakeMac->MacCharacteristics.ResetHandler = ndisMReset;
  1641. FakeMac->MacCharacteristics.RequestHandler = Open->RequestHandler;
  1642. FakeMac->MacCharacteristics.SendHandler = Open->SendHandler;
  1643. }
  1644. *Status = NDIS_STATUS_SUCCESS;
  1645. } while (FALSE);
  1646. //
  1647. // Cleanup failure case
  1648. //
  1649. if (*Status != NDIS_STATUS_SUCCESS)
  1650. {
  1651. if (DeQueueFromMiniport)
  1652. {
  1653. ndisDeQueueOpenOnMiniport(Open, Miniport);
  1654. }
  1655. if (DeQueueFromProtocol)
  1656. {
  1657. ndisDeQueueOpenOnProtocol(Open, Protocol);
  1658. }
  1659. if (DerefMini)
  1660. {
  1661. MINIPORT_DECREMENT_REF(Miniport);
  1662. }
  1663. }
  1664. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1665. ("<==ndisMOpenAdapter: Protocol %p, Miniport %p, Open %p, Status %lx\n",
  1666. Protocol,
  1667. Miniport,
  1668. Open,
  1669. Status));
  1670. }
  1671. BOOLEAN
  1672. NdisIMSwitchToMiniport(
  1673. IN NDIS_HANDLE MiniportAdapterHandle,
  1674. OUT PNDIS_HANDLE SwitchHandle
  1675. )
  1676. /*++
  1677. Routine Description:
  1678. This routine will attempt to synchronously grab the miniport's (specified
  1679. by MiniportAdapterHandle) spin-lock and local lock. If it succeeds
  1680. it will return TRUE, otherwise it will return FALSE.
  1681. Arguments:
  1682. MiniportAdapterHandle - Pointer to the NDIS_MINIPORT_BLOCK whose
  1683. context we should nail down.
  1684. SwitchHandle - Pointer to storage for the current irql.
  1685. This is returned to the caller as a handle,
  1686. need-to-know basis baby.
  1687. Return Value:
  1688. TRUE if we obtain both locks, FALSE otherwise.
  1689. --*/
  1690. {
  1691. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  1692. BOOLEAN LocalLock;
  1693. KIRQL OldIrql;
  1694. RAISE_IRQL_TO_DISPATCH(&OldIrql);
  1695. *((PKIRQL)SwitchHandle) = OldIrql;
  1696. //
  1697. // Did we already acquire the lock with this thread?
  1698. //
  1699. if (CURRENT_THREAD == Miniport->MiniportThread)
  1700. {
  1701. //
  1702. // We've already acquired the lock...
  1703. //
  1704. ASSERT_MINIPORT_LOCKED(Miniport);
  1705. *SwitchHandle = (NDIS_HANDLE)-1;
  1706. LocalLock = TRUE;
  1707. }
  1708. else
  1709. {
  1710. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1711. LOCK_MINIPORT(Miniport, LocalLock);
  1712. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1713. }
  1714. return LocalLock;
  1715. }
  1716. VOID
  1717. NdisIMRevertBack(
  1718. IN NDIS_HANDLE MiniportAdapterHandle,
  1719. IN NDIS_HANDLE SwitchHandle
  1720. )
  1721. /*++
  1722. Routine Description:
  1723. This routine will undo what NdisMLockMiniport did. It will release the
  1724. local lock and free the spin lock.
  1725. Arguments:
  1726. MiniportAdapterHandle - Pointer to the NDIS_MINIPORT_BLOCK whose
  1727. context we are releasing.
  1728. SwitchHandle - This is the original irql from the NdisMLockMiniport
  1729. call.
  1730. Return Value:
  1731. --*/
  1732. {
  1733. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  1734. ASSERT_MINIPORT_LOCKED(Miniport);
  1735. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1736. //
  1737. // Before we unlock the miniport's context we need to pick up any
  1738. // stray workitems for this miniport that may have been generated by
  1739. // the caller.
  1740. //
  1741. NDISM_PROCESS_DEFERRED(Miniport);
  1742. if ((NDIS_HANDLE)-1 != SwitchHandle)
  1743. {
  1744. UNLOCK_MINIPORT(Miniport, TRUE);
  1745. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, (KIRQL)SwitchHandle);
  1746. }
  1747. else
  1748. {
  1749. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1750. }
  1751. }
  1752. NDIS_STATUS
  1753. NdisIMQueueMiniportCallback(
  1754. IN NDIS_HANDLE MiniportAdapterHandle,
  1755. IN W_MINIPORT_CALLBACK CallbackRoutine,
  1756. IN PVOID CallbackContext
  1757. )
  1758. /*++
  1759. Routine Description:
  1760. This routine will attempt to acquire the specified MiniportAdapterHandle's
  1761. miniport lock and local lock and call the callback routine with the context
  1762. information. If it cannot do so then it will queue a workitem to do it
  1763. later.
  1764. Arguments:
  1765. MiniportAdapterHandle - PNDIS_MINIPORT_BLOCK of the miniport whose
  1766. context we are attempting to acquire.
  1767. CallbackRoutine - Pointer to the routine that we are to call.
  1768. CallbackContext - Context information for the callback routine.
  1769. Return Value:
  1770. NDIS_STATUS_SUCCESS - If we were able to do this synchronously.
  1771. NDIS_STATUS_PENDING - If it will be called at a later time.
  1772. NDIS_STATUS_RESOURCES - If the work item could not be queue'd.
  1773. --*/
  1774. {
  1775. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  1776. NDIS_STATUS Status;
  1777. BOOLEAN LocalLock;
  1778. KIRQL OldIrql;
  1779. RAISE_IRQL_TO_DISPATCH(&OldIrql);
  1780. //
  1781. // Did we already acuqire the lock with this thread?
  1782. //
  1783. if (CURRENT_THREAD == Miniport->MiniportThread)
  1784. {
  1785. //
  1786. // We've already acquired the lock...
  1787. //
  1788. ASSERT_MINIPORT_LOCKED(Miniport);
  1789. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1790. LocalLock = TRUE;
  1791. }
  1792. else
  1793. {
  1794. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1795. LOCK_MINIPORT(Miniport, LocalLock);
  1796. }
  1797. if (LocalLock)
  1798. {
  1799. //
  1800. // Call the callback routine.
  1801. //
  1802. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1803. (*CallbackRoutine)(Miniport->MiniportAdapterContext, CallbackContext);
  1804. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1805. NDISM_PROCESS_DEFERRED(Miniport);
  1806. UNLOCK_MINIPORT(Miniport, LocalLock);
  1807. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1808. Status = NDIS_STATUS_SUCCESS;
  1809. }
  1810. else
  1811. {
  1812. //
  1813. // Queue the work item to do this later.
  1814. //
  1815. Status = NDISM_QUEUE_NEW_WORK_ITEM(Miniport,
  1816. NdisWorkItemMiniportCallback,
  1817. CallbackContext,
  1818. CallbackRoutine);
  1819. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1820. Status = (NDIS_STATUS_SUCCESS == Status) ? NDIS_STATUS_PENDING : NDIS_STATUS_RESOURCES;
  1821. }
  1822. LOWER_IRQL(OldIrql, DISPATCH_LEVEL);
  1823. return Status;
  1824. }
  1825. VOID
  1826. FASTCALL
  1827. ndisMDeQueueWorkItem(
  1828. IN PNDIS_MINIPORT_BLOCK Miniport,
  1829. IN NDIS_WORK_ITEM_TYPE WorkItemType,
  1830. OUT PVOID * WorkItemContext OPTIONAL,
  1831. OUT PVOID * WorkItemHandler OPTIONAL
  1832. )
  1833. /*++
  1834. Routine Description:
  1835. This routine will dequeue a workitem of the given type and return any context
  1836. information that is associated with it.
  1837. Arguments:
  1838. Miniport - Pointer to the miniport block.
  1839. WorkItemType - Type of workitem to dequeue.
  1840. WorkItemContext - Pointer to storage space for context information.
  1841. Return Value:
  1842. None.
  1843. --*/
  1844. {
  1845. PSINGLE_LIST_ENTRY Link;
  1846. PNDIS_MINIPORT_WORK_ITEM WorkItem;
  1847. //
  1848. // Grab the first workitem of the given type.
  1849. //
  1850. Link = PopEntryList(&Miniport->WorkQueue[WorkItemType]);
  1851. if (Link != NULL)
  1852. {
  1853. //
  1854. // Get a pointer to the context information.
  1855. //
  1856. WorkItem = CONTAINING_RECORD(Link, NDIS_MINIPORT_WORK_ITEM, Link);
  1857. if (WorkItemContext != NULL)
  1858. {
  1859. *WorkItemContext = WorkItem->WorkItemContext;
  1860. }
  1861. if (ARGUMENT_PRESENT(WorkItemHandler))
  1862. {
  1863. ASSERT(WorkItemType == NdisWorkItemMiniportCallback);
  1864. *WorkItemHandler = *(PVOID *)(WorkItem + 1);
  1865. }
  1866. switch (WorkItemType)
  1867. {
  1868. //
  1869. // Enumerate these if any work-item types are added and they are *not*
  1870. // single work-item types
  1871. //
  1872. case NdisWorkItemMiniportCallback:
  1873. FREE_POOL(WorkItem);
  1874. break;
  1875. case NdisWorkItemResetInProgress:
  1876. PushEntryList(&Miniport->SingleWorkItems[NdisWorkItemResetRequested], Link);
  1877. break;
  1878. case NdisWorkItemResetRequested:
  1879. WorkItem->WorkItemType = NdisWorkItemResetInProgress;
  1880. PushEntryList(&Miniport->WorkQueue[NdisWorkItemResetInProgress], Link);
  1881. break;
  1882. default:
  1883. PushEntryList(&Miniport->SingleWorkItems[WorkItemType], Link);
  1884. break;
  1885. }
  1886. }
  1887. }
  1888. NDIS_STATUS
  1889. FASTCALL
  1890. ndisMQueueWorkItem(
  1891. IN PNDIS_MINIPORT_BLOCK Miniport,
  1892. IN NDIS_WORK_ITEM_TYPE WorkItemType,
  1893. IN PVOID WorkItemContext
  1894. )
  1895. /*++
  1896. Routine Description:
  1897. Arguments:
  1898. Return Value:
  1899. --*/
  1900. {
  1901. NDIS_STATUS Status;
  1902. PSINGLE_LIST_ENTRY Link;
  1903. PNDIS_MINIPORT_WORK_ITEM WorkItem;
  1904. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO,
  1905. ("==>ndisMQueueWorkItem\n"));
  1906. Link = PopEntryList(&Miniport->SingleWorkItems[WorkItemType]);
  1907. if (NULL != Link)
  1908. {
  1909. WorkItem = CONTAINING_RECORD(Link, NDIS_MINIPORT_WORK_ITEM, Link);
  1910. WorkItem->WorkItemType = WorkItemType;
  1911. WorkItem->WorkItemContext = WorkItemContext;
  1912. PushEntryList(&Miniport->WorkQueue[WorkItemType], Link);
  1913. Status = NDIS_STATUS_SUCCESS;
  1914. }
  1915. else
  1916. {
  1917. Status = NDIS_STATUS_NOT_ACCEPTED;
  1918. }
  1919. //
  1920. // If this is an intermediate driver then we may have to fire a timer
  1921. // so the work item gets processed.
  1922. //
  1923. if (((Miniport->Flags & (fMINIPORT_INTERMEDIATE_DRIVER | fMINIPORT_DESERIALIZE)) == fMINIPORT_INTERMEDIATE_DRIVER) &&
  1924. (NDIS_STATUS_SUCCESS == Status))
  1925. {
  1926. NDISM_DEFER_PROCESS_DEFERRED(Miniport);
  1927. }
  1928. else if ((MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE) ||
  1929. MINIPORT_PNP_TEST_FLAG (Miniport, fMINIPORT_PM_HALTED)) &&
  1930. (WorkItemType == NdisWorkItemRequest))
  1931. {
  1932. ndisMDoRequests(Miniport);
  1933. }
  1934. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO,
  1935. ("<==ndisMQueueWorkItem\n"));
  1936. return(Status);
  1937. }
  1938. NDIS_STATUS
  1939. FASTCALL
  1940. ndisMQueueNewWorkItem(
  1941. IN PNDIS_MINIPORT_BLOCK Miniport,
  1942. IN NDIS_WORK_ITEM_TYPE WorkItemType,
  1943. IN PVOID WorkItemContext,
  1944. IN PVOID WorkItemHandler OPTIONAL
  1945. )
  1946. /*++
  1947. Routine Description:
  1948. This routine will queue a workitem in the work queue even if there
  1949. are already work items queue for it.
  1950. Arguments:
  1951. Miniport - Miniport block to queue the workitem to.
  1952. WorkItem - Workitem to place on the queue.
  1953. Return Value:
  1954. --*/
  1955. {
  1956. NDIS_STATUS Status;
  1957. PNDIS_MINIPORT_WORK_ITEM WorkItem;
  1958. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO,
  1959. ("==>ndisMQueueNewWorkItem\n"));
  1960. ASSERT((WorkItemType < NUMBER_OF_WORK_ITEM_TYPES) &&
  1961. (WorkItemType >= NUMBER_OF_SINGLE_WORK_ITEMS));
  1962. do
  1963. {
  1964. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO,
  1965. ("Allocate a workitem from the pool.\n"));
  1966. WorkItem = ALLOC_FROM_POOL(sizeof(NDIS_MINIPORT_WORK_ITEM) + (ARGUMENT_PRESENT(WorkItemHandler) ? sizeof(PVOID) : 0),
  1967. NDIS_TAG_WORK_ITEM);
  1968. if (NULL == WorkItem)
  1969. {
  1970. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_FATAL,
  1971. ("Failed to allocate a workitem from the pool!\n"));
  1972. DBGBREAK(DBG_COMP_WORK_ITEM, DBG_LEVEL_FATAL);
  1973. Status = NDIS_STATUS_FAILURE;
  1974. break;
  1975. }
  1976. WorkItem->WorkItemType = WorkItemType;
  1977. WorkItem->WorkItemContext = WorkItemContext;
  1978. if (ARGUMENT_PRESENT(WorkItemHandler))
  1979. {
  1980. ASSERT(WorkItemType == NdisWorkItemMiniportCallback);
  1981. *(PVOID *)(WorkItem + 1) = WorkItemHandler;
  1982. }
  1983. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO,
  1984. ("WorkItem 0x%x\n", WorkItem));
  1985. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO,
  1986. ("WorkItem Type 0x%x\n", WorkItemType));
  1987. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO,
  1988. ("WorkItem Context 0x%x\n", WorkItemContext));
  1989. PushEntryList(&Miniport->WorkQueue[WorkItemType], &WorkItem->Link);
  1990. Status = NDIS_STATUS_SUCCESS;
  1991. } while (FALSE);
  1992. //
  1993. // If this is an intermediate driver (but not a co-ndis or a
  1994. // deserialized driver) then we may have to fire a timer
  1995. // so the work item gets processed.
  1996. //
  1997. if (((Miniport->Flags & (fMINIPORT_INTERMEDIATE_DRIVER | fMINIPORT_DESERIALIZE)) == fMINIPORT_INTERMEDIATE_DRIVER) &&
  1998. (NDIS_STATUS_SUCCESS == Status))
  1999. {
  2000. NDISM_DEFER_PROCESS_DEFERRED(Miniport);
  2001. }
  2002. DBGPRINT(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO,
  2003. ("<==ndisMQueueNewWorkItem\n"));
  2004. return(Status);
  2005. }
  2006. VOID
  2007. FASTCALL
  2008. ndisMProcessDeferred(
  2009. IN PNDIS_MINIPORT_BLOCK Miniport
  2010. )
  2011. /*++
  2012. Routine Description:
  2013. Processes all outstanding operations.
  2014. CALLED WITH THE LOCK HELD!!
  2015. Arguments:
  2016. Miniport - Miniport to send to.
  2017. Return Value:
  2018. None.
  2019. --*/
  2020. {
  2021. NDIS_STATUS Status;
  2022. BOOLEAN ProcessWorkItems;
  2023. BOOLEAN AddressingReset = FALSE;
  2024. PKDPC Dpc;
  2025. ASSERT_MINIPORT_LOCKED(Miniport);
  2026. DBGPRINT_RAW(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO,
  2027. ("==>ndisMProcessDeferred\n"));
  2028. //
  2029. // DO NOT CHANGE THE ORDER THAT THE WORKITEMS ARE PROCESSED!!!!!
  2030. //
  2031. do
  2032. {
  2033. ProcessWorkItems = FALSE;
  2034. //
  2035. // Are there any sends to process?
  2036. //
  2037. if ((Miniport->WorkQueue[NdisWorkItemSend].Next != NULL) &&
  2038. !MINIPORT_TEST_FLAG(Miniport, (fMINIPORT_RESET_REQUESTED |
  2039. fMINIPORT_RESET_IN_PROGRESS |
  2040. fMINIPORT_PM_HALTING)))
  2041. {
  2042. //
  2043. // Process the sends.
  2044. //
  2045. NDISM_DEQUEUE_WORK_ITEM(Miniport, NdisWorkItemSend, NULL);
  2046. NDISM_START_SENDS(Miniport);
  2047. ProcessWorkItems = TRUE;
  2048. }
  2049. //
  2050. // Is there a reset currently in progress?
  2051. //
  2052. if (Miniport->WorkQueue[NdisWorkItemResetInProgress].Next != NULL)
  2053. {
  2054. if (Miniport->WorkQueue[NdisWorkItemRequest].Next != NULL)
  2055. {
  2056. //
  2057. // We have requests to process that set up the packet
  2058. // filters.
  2059. //
  2060. NDISM_DEQUEUE_WORK_ITEM(Miniport, NdisWorkItemRequest, NULL);
  2061. ndisMDoRequests(Miniport);
  2062. }
  2063. break;
  2064. }
  2065. if (Miniport->WorkQueue[NdisWorkItemReturnPackets].Next != NULL)
  2066. {
  2067. NDISM_DEQUEUE_WORK_ITEM(Miniport, NdisWorkItemReturnPackets, NULL);
  2068. ndisMDeferredReturnPackets(Miniport);
  2069. }
  2070. //
  2071. // If the adapter is halting then get out of here.
  2072. //
  2073. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_PM_HALTING))
  2074. {
  2075. DBGPRINT_RAW(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO,
  2076. (" Miniport is halting\n"));
  2077. break;
  2078. }
  2079. //
  2080. // If a miniport wants a call back do it now...
  2081. //
  2082. if (Miniport->WorkQueue[NdisWorkItemMiniportCallback].Next != NULL)
  2083. {
  2084. W_MINIPORT_CALLBACK CallbackRoutine = NULL;
  2085. PVOID CallbackContext;
  2086. //
  2087. // Get the callback routine and the context information for it.
  2088. //
  2089. NDISM_DEQUEUE_WORK_ITEM_WITH_HANDLER(Miniport,
  2090. NdisWorkItemMiniportCallback,
  2091. &CallbackContext,
  2092. (PVOID *)&CallbackRoutine);
  2093. if (CallbackRoutine != NULL)
  2094. {
  2095. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  2096. //
  2097. // Call the intermediate drivers callback routine.
  2098. //
  2099. (*CallbackRoutine)(Miniport->MiniportAdapterContext, CallbackContext);
  2100. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  2101. }
  2102. ProcessWorkItems = TRUE;
  2103. }
  2104. //
  2105. // Was there a reset requested?
  2106. //
  2107. if (Miniport->WorkQueue[NdisWorkItemResetRequested].Next != NULL)
  2108. {
  2109. DBGPRINT_RAW(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO,
  2110. (" Reset requested\n"));
  2111. //
  2112. // We need to release the work item lock to
  2113. // indicate the status to the bindings
  2114. // and to call down to the miniport driver.
  2115. //
  2116. Status = ndisMProcessResetRequested(Miniport, &AddressingReset);
  2117. if (NDIS_STATUS_PENDING == Status)
  2118. {
  2119. DBGPRINT_RAW(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO,
  2120. (" Reset is pending\n"));
  2121. //
  2122. // The reset is still in progress so we need to stop
  2123. // processing workitems and wait for the completion.
  2124. //
  2125. break;
  2126. }
  2127. else
  2128. {
  2129. //
  2130. // Do step1 of the reset complete.
  2131. //
  2132. ndisMResetCompleteStage1(Miniport,
  2133. Status,
  2134. AddressingReset);
  2135. if (Miniport->WorkQueue[NdisWorkItemRequest].Next == NULL)
  2136. {
  2137. //
  2138. // somehow we did not queue a workitem due to address reset flag
  2139. //
  2140. AddressingReset = FALSE;
  2141. }
  2142. if (!AddressingReset || (Status != NDIS_STATUS_SUCCESS))
  2143. {
  2144. //
  2145. // If there is no addressing reset to be done or
  2146. // the reset failed in some way then we tell the
  2147. // bindings now.
  2148. //
  2149. ndisMResetCompleteStage2(Miniport);
  2150. }
  2151. else
  2152. {
  2153. //
  2154. // We MUST complete the filter requests within
  2155. // the reset in progress workitem. Mainly because
  2156. // we don't want to do any sends at this time.
  2157. //
  2158. ProcessWorkItems = TRUE;
  2159. continue;
  2160. }
  2161. }
  2162. }
  2163. //
  2164. // Process any requests?
  2165. //
  2166. if (Miniport->WorkQueue[NdisWorkItemRequest].Next != NULL)
  2167. {
  2168. //
  2169. // Process the requests.
  2170. //
  2171. NDISM_DEQUEUE_WORK_ITEM(Miniport, NdisWorkItemRequest, NULL);
  2172. ndisMDoRequests(Miniport);
  2173. ProcessWorkItems = TRUE;
  2174. }
  2175. if (Miniport->WorkQueue[NdisWorkItemSend].Next != NULL)
  2176. {
  2177. //
  2178. // Process the sends.
  2179. //
  2180. NDISM_DEQUEUE_WORK_ITEM(Miniport, NdisWorkItemSend, NULL);
  2181. NDISM_START_SENDS(Miniport);
  2182. ProcessWorkItems = TRUE;
  2183. }
  2184. } while (ProcessWorkItems);
  2185. DBGPRINT_RAW(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO,
  2186. ("<==ndisMProcessDeferred\n"));
  2187. }
  2188. VOID
  2189. NdisMIndicateStatus(
  2190. IN NDIS_HANDLE MiniportAdapterHandle,
  2191. IN NDIS_STATUS GeneralStatus,
  2192. IN PVOID StatusBuffer,
  2193. IN UINT StatusBufferSize
  2194. )
  2195. /*++
  2196. Routine Description:
  2197. This function indicates a new status of the media/mini-port.
  2198. Arguments:
  2199. MiniportAdapterHandle - points to the adapter block.
  2200. GeneralStatus - The status to indicate.
  2201. StatusBuffer - Additional information.
  2202. StatusBufferSize - Length of the buffer.
  2203. Return Value:
  2204. None.
  2205. --*/
  2206. {
  2207. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  2208. PNDIS_OPEN_BLOCK Open, NextOpen;
  2209. NDIS_STATUS Status;
  2210. BOOLEAN fTimerCancelled, fSwap = FALSE;
  2211. BOOLEAN fInternal = FALSE;
  2212. PNDIS_GUID pNdisGuid;
  2213. NTSTATUS NtStatus;
  2214. BOOLEAN fMediaConnectStateIndication = FALSE;
  2215. KIRQL OldIrql;
  2216. //
  2217. // Internal indications are media-sense indications. These are detected by
  2218. // a StatusBufferSize of -1 and StatusBuffer of NULL.
  2219. //
  2220. if ((GeneralStatus == NDIS_STATUS_MEDIA_CONNECT) || (GeneralStatus == NDIS_STATUS_MEDIA_DISCONNECT))
  2221. {
  2222. fMediaConnectStateIndication = TRUE;
  2223. fInternal = ((StatusBufferSize == INTERNAL_INDICATION_SIZE) && (StatusBuffer == INTERNAL_INDICATION_BUFFER));
  2224. }
  2225. ASSERT_MINIPORT_LOCKED(Miniport);
  2226. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  2227. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_FILTER_IM) &&
  2228. fMediaConnectStateIndication)
  2229. {
  2230. //
  2231. // if this is a media conenct/disconnect event from an IM filter
  2232. // driver, skip wmi event
  2233. //
  2234. NtStatus = STATUS_UNSUCCESSFUL;
  2235. }
  2236. else
  2237. {
  2238. //
  2239. // Check to see if the status is enabled for WMI event indication.
  2240. //
  2241. NtStatus = ndisWmiGetGuid(&pNdisGuid, Miniport, NULL, GeneralStatus);
  2242. }
  2243. if ((NT_SUCCESS(NtStatus)) &&
  2244. NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_EVENT_ENABLED))
  2245. {
  2246. PWNODE_SINGLE_INSTANCE wnode;
  2247. ULONG DataBlockSize = 0;
  2248. PUCHAR ptmp;
  2249. //
  2250. // If the data item is an array then we need to add in the number of
  2251. // elements.
  2252. //
  2253. if (NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_ARRAY))
  2254. {
  2255. DataBlockSize = StatusBufferSize + sizeof(ULONG);
  2256. }
  2257. else
  2258. {
  2259. DataBlockSize = pNdisGuid->Size;
  2260. }
  2261. //
  2262. // in case of media connect/disconnect status indication, include the
  2263. // NIC's name in the WMI event
  2264. //
  2265. if (fMediaConnectStateIndication)
  2266. {
  2267. DataBlockSize += Miniport->MiniportName.Length + sizeof(WCHAR);
  2268. }
  2269. ndisSetupWmiNode(Miniport,
  2270. Miniport->pAdapterInstanceName,
  2271. DataBlockSize,
  2272. (PVOID)&pNdisGuid->Guid,
  2273. &wnode);
  2274. if (NULL != wnode)
  2275. {
  2276. //
  2277. // Increment ptmp to the start of the data block.
  2278. //
  2279. ptmp = (PUCHAR)wnode + wnode->DataBlockOffset;
  2280. if (NDIS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_ARRAY))
  2281. {
  2282. //
  2283. // If the status is an array but there is no data then complete it with no
  2284. // data and a 0 length
  2285. //
  2286. if ((NULL == StatusBuffer) || (0 == StatusBufferSize))
  2287. {
  2288. *((PULONG)ptmp) = 0;
  2289. ptmp += sizeof(ULONG);
  2290. }
  2291. else
  2292. {
  2293. //
  2294. // Save the number of elements in the first ULONG.
  2295. //
  2296. *((PULONG)ptmp) = StatusBufferSize / pNdisGuid->Size;
  2297. //
  2298. // Copy the data after the number of elements.
  2299. //
  2300. RtlCopyMemory(ptmp + sizeof(ULONG), StatusBuffer, StatusBufferSize);
  2301. ptmp += sizeof(ULONG) + StatusBufferSize;
  2302. }
  2303. }
  2304. else
  2305. {
  2306. //
  2307. // Do we indicate any data up?
  2308. //
  2309. if (0 != pNdisGuid->Size)
  2310. {
  2311. //
  2312. // Copy the data into the buffer.
  2313. //
  2314. RtlCopyMemory(ptmp, StatusBuffer, pNdisGuid->Size);
  2315. ptmp += pNdisGuid->Size;
  2316. }
  2317. }
  2318. if (fMediaConnectStateIndication)
  2319. {
  2320. //
  2321. // for media connect/disconnect status,
  2322. // add the name of the adapter
  2323. //
  2324. RtlCopyMemory(ptmp,
  2325. Miniport->MiniportName.Buffer,
  2326. Miniport->MiniportName.Length);
  2327. }
  2328. //
  2329. // Indicate the event to WMI. WMI will take care of freeing
  2330. // the WMI struct back to pool.
  2331. //
  2332. NtStatus = IoWMIWriteEvent(wnode);
  2333. if (!NT_SUCCESS(NtStatus))
  2334. {
  2335. DBGPRINT(DBG_COMP_WMI, DBG_LEVEL_ERR,
  2336. (" ndisMIndicateStatus: Unable to indicate the WMI event.\n"));
  2337. FREE_POOL(wnode);
  2338. }
  2339. }
  2340. }
  2341. //
  2342. // Process the status code that was indicated.
  2343. //
  2344. switch (GeneralStatus)
  2345. {
  2346. case NDIS_STATUS_RING_STATUS:
  2347. if (StatusBufferSize == sizeof(NDIS_STATUS))
  2348. {
  2349. Status = *((PNDIS_STATUS)StatusBuffer);
  2350. if (Status & (NDIS_RING_LOBE_WIRE_FAULT |
  2351. NDIS_RING_HARD_ERROR |
  2352. NDIS_RING_SIGNAL_LOSS))
  2353. {
  2354. Miniport->TrResetRing = NDIS_MINIPORT_TR_RESET_TIMEOUT;
  2355. }
  2356. else
  2357. {
  2358. Miniport->TrResetRing = 0;
  2359. }
  2360. }
  2361. break;
  2362. case NDIS_STATUS_MEDIA_DISCONNECT:
  2363. Miniport->MediaSenseDisconnectCount ++;
  2364. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2365. ("NdisMIndicateStatus: NDIS_STATUS_MEDIA_DISCONNECT, Miniport %p, Flags: %lx, PnpFlags %lx, DevicePowerState %lx\n",
  2366. Miniport,
  2367. Miniport->Flags,
  2368. Miniport->PnPFlags,
  2369. Miniport->CurrentDevicePowerState));
  2370. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_MEDIA_CONNECTED))
  2371. {
  2372. fSwap = TRUE;
  2373. }
  2374. MINIPORT_CLEAR_FLAG(Miniport, fMINIPORT_MEDIA_CONNECTED);
  2375. if (!fInternal)
  2376. {
  2377. //
  2378. // miniport can do media sense and indicate status
  2379. //
  2380. MINIPORT_CLEAR_FLAG(Miniport, fMINIPORT_REQUIRES_MEDIA_POLLING);
  2381. MINIPORT_SET_FLAG(Miniport, fMINIPORT_SUPPORTS_MEDIA_SENSE);
  2382. //
  2383. // Is this a PM enabled miniport? And is dynamic power policy
  2384. // enabled for the miniport?
  2385. //
  2386. if (fSwap &&
  2387. MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_DEVICE_POWER_ENABLE) &&
  2388. (Miniport->WakeUpEnable & NDIS_PNP_WAKE_UP_LINK_CHANGE) &&
  2389. (Miniport->MediaDisconnectTimeOut != (USHORT)(-1)))
  2390. {
  2391. //
  2392. // Are we already waiting for the disconnect timer to fire?
  2393. //
  2394. if (!MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_MEDIA_DISCONNECT_WAIT))
  2395. {
  2396. //
  2397. // Mark the miniport as disconnecting and fire off the
  2398. // timer.
  2399. //
  2400. MINIPORT_PNP_CLEAR_FLAG(Miniport, fMINIPORT_MEDIA_DISCONNECT_CANCELLED);
  2401. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_MEDIA_DISCONNECT_WAIT);
  2402. NdisSetTimer(&Miniport->MediaDisconnectTimer, Miniport->MediaDisconnectTimeOut * 1000);
  2403. }
  2404. }
  2405. }
  2406. break;
  2407. case NDIS_STATUS_MEDIA_CONNECT:
  2408. Miniport->MediaSenseConnectCount ++;
  2409. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  2410. ("NdisMIndicateStatus: NDIS_STATUS_MEDIA_CONNECT, Miniport %p, Flags: %lx, PnpFlags %lx, DevicePowerState %lx\n",
  2411. Miniport,
  2412. Miniport->Flags,
  2413. Miniport->PnPFlags,
  2414. Miniport->CurrentDevicePowerState));
  2415. if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_MEDIA_CONNECTED))
  2416. {
  2417. fSwap = TRUE;
  2418. }
  2419. MINIPORT_SET_FLAG(Miniport, fMINIPORT_MEDIA_CONNECTED);
  2420. if (!fInternal)
  2421. {
  2422. //
  2423. // miniport can do media sense and can indicate that status to Ndis. Do not poll
  2424. //
  2425. MINIPORT_CLEAR_FLAG(Miniport, fMINIPORT_REQUIRES_MEDIA_POLLING);
  2426. MINIPORT_SET_FLAG(Miniport, fMINIPORT_SUPPORTS_MEDIA_SENSE);
  2427. //
  2428. // if media disconnect timer was set, cancel the timer
  2429. //
  2430. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_MEDIA_DISCONNECT_WAIT))
  2431. {
  2432. //
  2433. // Clear the disconnect wait bit and cancel the timer.
  2434. // IF the timer routine hasn't grabed the lock then we are ok.
  2435. //
  2436. MINIPORT_PNP_CLEAR_FLAG(Miniport, fMINIPORT_MEDIA_DISCONNECT_WAIT);
  2437. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_MEDIA_DISCONNECT_CANCELLED);
  2438. NdisCancelTimer(&Miniport->MediaDisconnectTimer, &fTimerCancelled);
  2439. }
  2440. }
  2441. break;
  2442. default:
  2443. break;
  2444. }
  2445. for (Open = Miniport->OpenQueue;
  2446. (Open != NULL);
  2447. Open = NextOpen)
  2448. {
  2449. if (MINIPORT_TEST_FLAG(Open, fMINIPORT_OPEN_CLOSING))
  2450. {
  2451. NextOpen = Open->MiniportNextOpen;
  2452. continue;
  2453. }
  2454. M_OPEN_INCREMENT_REF_INTERLOCKED(Open);
  2455. if (Open->StatusHandler != NULL)
  2456. {
  2457. Open->Flags |= fMINIPORT_STATUS_RECEIVED;
  2458. if ((NDIS_STATUS_WAN_LINE_UP == GeneralStatus) ||
  2459. (NDIS_STATUS_WAN_LINE_DOWN == GeneralStatus))
  2460. {
  2461. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  2462. }
  2463. else
  2464. {
  2465. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  2466. }
  2467. //
  2468. // Call Protocol to indicate status
  2469. //
  2470. (Open->StatusHandler)(Open->ProtocolBindingContext,
  2471. GeneralStatus,
  2472. StatusBuffer,
  2473. StatusBufferSize);
  2474. if ((NDIS_STATUS_WAN_LINE_UP == GeneralStatus) ||
  2475. (NDIS_STATUS_WAN_LINE_DOWN == GeneralStatus))
  2476. {
  2477. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  2478. }
  2479. else
  2480. {
  2481. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  2482. }
  2483. }
  2484. NextOpen = Open->MiniportNextOpen;
  2485. ndisMDereferenceOpen(Open);
  2486. }
  2487. //
  2488. // If we got a connect/disconnect, swap open handlers
  2489. //
  2490. if (fSwap)
  2491. {
  2492. if (NDIS_STATUS_MEDIA_CONNECT == GeneralStatus)
  2493. {
  2494. MINIPORT_PNP_CLEAR_FLAG(Miniport, fMINIPORT_MEDIA_DISCONNECT_INDICATED);
  2495. ndisMRestoreOpenHandlers(Miniport, fMINIPORT_STATE_MEDIA_DISCONNECTED);
  2496. Miniport->PacketIndicateHandler = Miniport->SavedPacketIndicateHandler;
  2497. }
  2498. else
  2499. {
  2500. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_MEDIA_DISCONNECT_INDICATED);
  2501. ndisMSwapOpenHandlers(Miniport,
  2502. NDIS_STATUS_NO_CABLE,
  2503. fMINIPORT_STATE_MEDIA_DISCONNECTED);
  2504. Miniport->SavedPacketIndicateHandler = Miniport->PacketIndicateHandler;
  2505. Miniport->PacketIndicateHandler = ndisMDummyIndicatePacket;
  2506. }
  2507. }
  2508. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  2509. }
  2510. VOID
  2511. NdisMIndicateStatusComplete(
  2512. IN NDIS_HANDLE MiniportAdapterHandle
  2513. )
  2514. /*++
  2515. Routine Description:
  2516. This function indicates the status is complete.
  2517. Arguments:
  2518. MiniportAdapterHandle - points to the adapter block.
  2519. Return Value:
  2520. None.
  2521. --*/
  2522. {
  2523. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  2524. PNDIS_OPEN_BLOCK Open, NextOpen;
  2525. KIRQL OldIrql;
  2526. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  2527. ASSERT_MINIPORT_LOCKED(Miniport);
  2528. for (Open = Miniport->OpenQueue;
  2529. Open != NULL;
  2530. Open = NextOpen)
  2531. {
  2532. if (MINIPORT_TEST_FLAG(Open, (fMINIPORT_OPEN_CLOSING |
  2533. fMINIPORT_OPEN_UNBINDING)))
  2534. {
  2535. NextOpen = Open->MiniportNextOpen;
  2536. continue;
  2537. }
  2538. M_OPEN_INCREMENT_REF_INTERLOCKED(Open);
  2539. if ((NULL != Open->StatusCompleteHandler) &&
  2540. (Open->Flags & fMINIPORT_STATUS_RECEIVED))
  2541. {
  2542. //
  2543. // Call Protocol to indicate status
  2544. //
  2545. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  2546. (Open->StatusCompleteHandler)(Open->ProtocolBindingContext);
  2547. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  2548. }
  2549. Open->Flags &= ~fMINIPORT_STATUS_RECEIVED;
  2550. NextOpen = Open->MiniportNextOpen;
  2551. ndisMDereferenceOpen(Open);
  2552. }
  2553. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  2554. }
  2555. VOID
  2556. NdisMWanIndicateReceive(
  2557. OUT PNDIS_STATUS Status,
  2558. IN NDIS_HANDLE MiniportAdapterHandle,
  2559. IN NDIS_HANDLE NdisLinkContext,
  2560. IN PUCHAR Packet,
  2561. IN ULONG PacketSize
  2562. )
  2563. /*++
  2564. Routine Description:
  2565. This function indicates the status is complete.
  2566. Arguments:
  2567. MiniportAdapterHandle - points to the adapter block.
  2568. Return Value:
  2569. None.
  2570. --*/
  2571. {
  2572. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  2573. PNDIS_OPEN_BLOCK Open;
  2574. KIRQL OldIrql;
  2575. ASSERT_MINIPORT_LOCKED(Miniport);
  2576. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  2577. for (Open = Miniport->OpenQueue;
  2578. Open != NULL;
  2579. Open = Open->MiniportNextOpen)
  2580. {
  2581. //
  2582. // Call Protocol to indicate packet
  2583. //
  2584. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  2585. *Status = (Open->ProtocolHandle->ProtocolCharacteristics.WanReceiveHandler)(
  2586. NdisLinkContext,
  2587. Packet,
  2588. PacketSize);
  2589. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  2590. }
  2591. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  2592. }
  2593. VOID
  2594. NdisMWanIndicateReceiveComplete(
  2595. IN NDIS_HANDLE MiniportAdapterHandle,
  2596. IN NDIS_HANDLE NdisLinkContext
  2597. )
  2598. /*++
  2599. Routine Description:
  2600. This function indicates the status is complete.
  2601. Arguments:
  2602. MiniportAdapterHandle - points to the adapter block.
  2603. Return Value:
  2604. None.
  2605. --*/
  2606. {
  2607. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  2608. PNDIS_OPEN_BLOCK Open;
  2609. KIRQL OldIrql;
  2610. ASSERT_MINIPORT_LOCKED(Miniport);
  2611. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  2612. for (Open = Miniport->OpenQueue;
  2613. Open != NULL;
  2614. Open = Open->MiniportNextOpen)
  2615. {
  2616. //
  2617. // Call Protocol to indicate status
  2618. //
  2619. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  2620. (Open->ReceiveCompleteHandler)(NdisLinkContext);
  2621. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  2622. }
  2623. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  2624. }
  2625. PNDIS_PACKET
  2626. NdisGetReceivedPacket(
  2627. IN NDIS_HANDLE NdisBindingHandle,
  2628. IN NDIS_HANDLE MacContext
  2629. )
  2630. {
  2631. PNDIS_OPEN_BLOCK OpenBlock = ((PNDIS_OPEN_BLOCK)NdisBindingHandle);
  2632. PNDIS_MINIPORT_BLOCK Miniport;
  2633. PNDIS_PACKET Packet = NULL;
  2634. #ifdef TRACK_RECEIVED_PACKETS
  2635. PETHREAD CurThread = PsGetCurrentThread();
  2636. // ULONG CurThread = KeGetCurrentProcessorNumber();
  2637. #endif
  2638. Miniport = OpenBlock->MiniportHandle;
  2639. DBGPRINT_RAW(DBG_COMP_SEND, DBG_LEVEL_INFO,
  2640. ("NdisGetReceivedPacket - Miniort %p, Context %p\n",
  2641. Miniport, MacContext));
  2642. ASSERT_MINIPORT_LOCKED(Miniport);
  2643. //
  2644. // The following tests whether we came here via a IndicatePacket or IndicateRecieve
  2645. //
  2646. if ((INDICATED_PACKET(Miniport) == (PNDIS_PACKET)MacContext) &&
  2647. (MacContext != NULL))
  2648. {
  2649. Packet = NDIS_GET_ORIGINAL_PACKET((PNDIS_PACKET)MacContext);
  2650. #ifdef TRACK_RECEIVED_PACKETS
  2651. {
  2652. PNDIS_STACK_RESERVED NSR;
  2653. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR)
  2654. NDIS_APPEND_RCV_LOGFILE(Packet, Miniport, CurThread,
  2655. 0xA, CURR_STACK_LOCATION(Packet), NSR->RefCount, NSR->XRefCount, NDIS_GET_PACKET_STATUS(Packet));
  2656. }
  2657. #endif
  2658. }
  2659. return Packet;
  2660. }
  2661. VOID
  2662. NdisReturnPackets(
  2663. IN PNDIS_PACKET * PacketsToReturn,
  2664. IN UINT NumberOfPackets
  2665. )
  2666. /*++
  2667. Routine Description:
  2668. Decrement the refcount for the packet and return back to the miniport if 0.
  2669. We take the Miniport lock here and hence are protected against other receives.
  2670. Arguments:
  2671. PacketsToReturn - Pointer to the set of packets to return to the miniport
  2672. NumberOfPackets - self descriptive
  2673. Return Value:
  2674. None.
  2675. --*/
  2676. {
  2677. UINT i;
  2678. KIRQL OldIrql;
  2679. #ifdef TRACK_RECEIVED_PACKETS
  2680. PETHREAD CurThread = PsGetCurrentThread();
  2681. // ULONG CurThread = KeGetCurrentProcessorNumber();
  2682. #endif
  2683. RAISE_IRQL_TO_DISPATCH(&OldIrql);
  2684. for (i = 0; i < NumberOfPackets; i++)
  2685. {
  2686. PNDIS_MINIPORT_BLOCK Miniport;
  2687. PNDIS_STACK_RESERVED NSR;
  2688. W_RETURN_PACKET_HANDLER Handler;
  2689. PNDIS_PACKET Packet;
  2690. ULONG RefCount;
  2691. BOOLEAN LocalLock;
  2692. Packet = PacketsToReturn[i];
  2693. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR)
  2694. ASSERT (Packet != NULL);
  2695. Miniport = NSR->Miniport;
  2696. ASSERT (Miniport != NULL);
  2697. NDIS_APPEND_RCV_LOGFILE(Packet, Miniport, CurThread,
  2698. 0xB, CURR_STACK_LOCATION(Packet), NSR->RefCount, NSR->XRefCount, NDIS_GET_PACKET_STATUS(Packet));
  2699. ADJUST_PACKET_REFCOUNT(NSR, &RefCount);
  2700. if (RefCount == 0)
  2701. {
  2702. NDIS_APPEND_RCV_LOGFILE(Packet, Miniport, CurThread,
  2703. 0xC, CURR_STACK_LOCATION(Packet), NSR->RefCount, NSR->XRefCount, NDIS_GET_PACKET_STATUS(Packet));
  2704. if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  2705. {
  2706. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  2707. LOCK_MINIPORT(Miniport, LocalLock);
  2708. }
  2709. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE) ||
  2710. LocalLock)
  2711. {
  2712. #ifdef NDIS_TRACK_RETURNED_PACKETS
  2713. if (NSR->RefCount != 0)
  2714. {
  2715. DbgPrint("Packet %p is being returned back to the miniport"
  2716. "but the ref count is not zero.\n", Packet);
  2717. DbgBreakPoint();
  2718. }
  2719. if (Packet->Private.Head == NULL)
  2720. {
  2721. DbgPrint("Packet %p is being returned back to the miniport with NULL Head.\n", Packet);
  2722. DbgBreakPoint();
  2723. }
  2724. #endif
  2725. //
  2726. // Return the packet to the miniport
  2727. //
  2728. Handler = Miniport->DriverHandle->MiniportCharacteristics.ReturnPacketHandler;
  2729. NSR->Miniport = NULL;
  2730. POP_PACKET_STACK(Packet);
  2731. #ifdef NDIS_TRACK_RETURNED_PACKETS
  2732. if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_INTERMEDIATE_DRIVER))
  2733. {
  2734. ULONG SL;
  2735. if ((SL = CURR_STACK_LOCATION(Packet)) != -1)
  2736. {
  2737. DbgPrint("Packet %p is being returned back to the non-IM miniport"
  2738. " with stack location %lx.\n", Packet, SL);
  2739. DbgBreakPoint();
  2740. }
  2741. }
  2742. #endif
  2743. #ifdef TRACK_RECEIVED_PACKETS
  2744. if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE) &&
  2745. (NDIS_GET_PACKET_STATUS(Packet) == NDIS_STATUS_RESOURCES))
  2746. {
  2747. NDIS_STATUS OStatus = (NDIS_STATUS)NDIS_ORIGINAL_STATUS_FROM_PACKET(Packet);
  2748. if (OStatus != NDIS_STATUS_RESOURCES)
  2749. {
  2750. DbgPrint("Packet %p is being returned back to the non-deserialized miniport"
  2751. " with packet status changed from %lx to NDIS_STATUS_RESOURCES.\n", Packet, OStatus);
  2752. DbgBreakPoint();
  2753. }
  2754. }
  2755. #endif
  2756. NDIS_APPEND_RCV_LOGFILE(Packet, Miniport, CurThread,
  2757. 0xD, CURR_STACK_LOCATION(Packet), NSR->RefCount, NSR->XRefCount, NDIS_GET_PACKET_STATUS(Packet));
  2758. (*Handler)(Miniport->MiniportAdapterContext, Packet);
  2759. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_INTERMEDIATE_DRIVER))
  2760. {
  2761. InterlockedDecrement(&Miniport->IndicatedPacketsCount);
  2762. }
  2763. }
  2764. else
  2765. {
  2766. NDIS_APPEND_RCV_LOGFILE(Packet, Miniport, CurThread,
  2767. 0xE, CURR_STACK_LOCATION(Packet), NSR->RefCount, NSR->XRefCount, NDIS_GET_PACKET_STATUS(Packet));
  2768. //
  2769. // Miniport is busy so we need to queue this for later.
  2770. //
  2771. NSR->NextPacket = Miniport->ReturnPacketsQueue;
  2772. Miniport->ReturnPacketsQueue = Packet;
  2773. NDISM_QUEUE_WORK_ITEM(Miniport, NdisWorkItemReturnPackets, NULL);
  2774. }
  2775. if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  2776. {
  2777. UNLOCK_MINIPORT(Miniport, LocalLock);
  2778. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  2779. }
  2780. }
  2781. }
  2782. LOWER_IRQL(OldIrql, DISPATCH_LEVEL);
  2783. }
  2784. VOID
  2785. FASTCALL
  2786. ndisMDeferredReturnPackets(
  2787. IN PNDIS_MINIPORT_BLOCK Miniport
  2788. )
  2789. {
  2790. PNDIS_PACKET Packet, NextPacket;
  2791. PNDIS_STACK_RESERVED NSR;
  2792. W_RETURN_PACKET_HANDLER Handler;
  2793. #ifdef TRACK_RECEIVED_PACKETS
  2794. PETHREAD CurThread = PsGetCurrentThread();
  2795. // ULONG CurThread = KeGetCurrentProcessorNumber();
  2796. #endif
  2797. ASSERT_MINIPORT_LOCKED(Miniport);
  2798. ASSERT(!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE));
  2799. Handler = Miniport->DriverHandle->MiniportCharacteristics.ReturnPacketHandler;
  2800. for (Packet = Miniport->ReturnPacketsQueue;
  2801. Packet != NULL;
  2802. Packet = NextPacket)
  2803. {
  2804. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR)
  2805. NextPacket = NSR->NextPacket;
  2806. NSR->Miniport = NULL;
  2807. POP_PACKET_STACK(Packet);
  2808. #ifdef NDIS_TRACK_RETURNED_PACKETS
  2809. {
  2810. ULONG SL;
  2811. if ((SL = CURR_STACK_LOCATION(Packet)) != -1)
  2812. {
  2813. DbgPrint("Packet %p is being returned back to the non-IM miniport"
  2814. " with stack location %lx.\n", Packet, SL);
  2815. DbgBreakPoint();
  2816. }
  2817. }
  2818. #endif
  2819. #ifdef TRACK_RECEIVED_PACKETS
  2820. if (NDIS_GET_PACKET_STATUS(Packet) == NDIS_STATUS_RESOURCES)
  2821. {
  2822. NDIS_STATUS OStatus = (NDIS_STATUS)NDIS_ORIGINAL_STATUS_FROM_PACKET(Packet);
  2823. if (OStatus != NDIS_STATUS_RESOURCES)
  2824. {
  2825. DbgPrint("Packet %p is being returned back to the non-deserialized miniport"
  2826. " with packet status changed from %lx to NDIS_STATUS_RESOURCES.\n", Packet, OStatus);
  2827. DbgBreakPoint();
  2828. }
  2829. }
  2830. #endif
  2831. NDIS_APPEND_RCV_LOGFILE(Packet, Miniport, CurThread,
  2832. 0xF, CURR_STACK_LOCATION(Packet), NSR->RefCount, NSR->XRefCount, NDIS_GET_PACKET_STATUS(Packet));
  2833. (*Handler)(Miniport->MiniportAdapterContext, Packet);
  2834. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_INTERMEDIATE_DRIVER))
  2835. {
  2836. InterlockedDecrement(&Miniport->IndicatedPacketsCount);
  2837. }
  2838. }
  2839. Miniport->ReturnPacketsQueue = NULL;
  2840. }
  2841. VOID
  2842. FASTCALL
  2843. ndisMAbortRequests(
  2844. IN PNDIS_MINIPORT_BLOCK Miniport
  2845. )
  2846. /*++
  2847. Routine Description:
  2848. this routine will abort any pending requets.
  2849. Arguments:
  2850. Return Value:
  2851. Note:
  2852. called at DPC with Miniport's lock held.
  2853. --*/
  2854. {
  2855. PNDIS_REQUEST Request;
  2856. PNDIS_REQUEST NextRequest;
  2857. DBGPRINT_RAW(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
  2858. ("==>ndisMAbortRequests\n"));
  2859. //
  2860. // Clear the request timeout flag.
  2861. //
  2862. MINIPORT_CLEAR_FLAG(Miniport, fMINIPORT_REQUEST_TIMEOUT);
  2863. //
  2864. // Dequeue any request work items that are queued
  2865. //
  2866. NDISM_DEQUEUE_WORK_ITEM(Miniport, NdisWorkItemRequest, NULL);
  2867. Request = Miniport->PendingRequest;
  2868. Miniport->PendingRequest = NULL;
  2869. //
  2870. // Go through the pending request queue and clear it out.
  2871. //
  2872. for (NOTHING; Request != NULL; Request = NextRequest)
  2873. {
  2874. //
  2875. // Get a pointer to the next request before we kill the
  2876. // current one.
  2877. //
  2878. NextRequest = PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Next;
  2879. PNDIS_RESERVED_FROM_PNDIS_REQUEST(Request)->Next = NULL;
  2880. //
  2881. // Make this request the request in progress.
  2882. //
  2883. MINIPORT_SET_FLAG(Miniport, fMINIPORT_PROCESSING_REQUEST);
  2884. Miniport->PendingRequest = Request;
  2885. if (Request->RequestType == NdisRequestSetInformation)
  2886. {
  2887. ndisMSyncSetInformationComplete(Miniport, NDIS_STATUS_REQUEST_ABORTED);
  2888. }
  2889. else
  2890. {
  2891. ndisMSyncQueryInformationComplete(Miniport, NDIS_STATUS_REQUEST_ABORTED);
  2892. }
  2893. }
  2894. DBGPRINT_RAW(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
  2895. ("<==ndisMAbortRequests\n"));
  2896. }
  2897. VOID
  2898. FASTCALL
  2899. ndisMAbortPackets(
  2900. IN PNDIS_MINIPORT_BLOCK Miniport,
  2901. IN PNDIS_OPEN_BLOCK pOpen OPTIONAL,
  2902. IN PVOID CancelId OPTIONAL
  2903. )
  2904. /*++
  2905. Routine Description:
  2906. Aborts all outstanding packets on a mini-port.
  2907. CALLED WITH THE LOCK HELD!!
  2908. Arguments:
  2909. Miniport - Miniport to abort.
  2910. Return Value:
  2911. None.
  2912. --*/
  2913. {
  2914. PNDIS_OPEN_BLOCK Open;
  2915. PNDIS_PACKET OldFirstPendingPacket, NewFirstPendingPacket;
  2916. LIST_ENTRY SubmittedPackets;
  2917. PLIST_ENTRY List;
  2918. PNDIS_PACKET Packet;
  2919. BOOLEAN LookForFirstPendingPacket = FALSE;
  2920. DBGPRINT_RAW(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO,
  2921. ("==>ndisMAbortPackets\n"));
  2922. if (CancelId == NULL)
  2923. {
  2924. ASSERT_MINIPORT_LOCKED(Miniport);
  2925. }
  2926. //
  2927. // Dequeue any send work items that are queued
  2928. //
  2929. NDISM_DEQUEUE_WORK_ITEM(Miniport, NdisWorkItemSend, NULL);
  2930. OldFirstPendingPacket = Miniport->FirstPendingPacket;
  2931. NewFirstPendingPacket = NULL;
  2932. InitializeListHead(&SubmittedPackets);
  2933. if (CancelId)
  2934. LookForFirstPendingPacket = TRUE;
  2935. //
  2936. // Clear out the packet queues.
  2937. //
  2938. Miniport->FirstPendingPacket = NULL;
  2939. //
  2940. // Go through the list of packets and return them to the bindings
  2941. //
  2942. while (!IsListEmpty(&Miniport->PacketList))
  2943. {
  2944. PNDIS_STACK_RESERVED NSR;
  2945. List = RemoveHeadList(&Miniport->PacketList);
  2946. Packet = CONTAINING_RECORD(List, NDIS_PACKET, WrapperReserved);
  2947. if (LookForFirstPendingPacket)
  2948. {
  2949. if (Packet != OldFirstPendingPacket)
  2950. {
  2951. InsertTailList(&SubmittedPackets, List);
  2952. continue;
  2953. }
  2954. else
  2955. {
  2956. //
  2957. // we passed and saved the packets already submitted
  2958. // to the miniport
  2959. //
  2960. LookForFirstPendingPacket = FALSE;
  2961. }
  2962. }
  2963. //
  2964. // Get the open that the packet came from.
  2965. //
  2966. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR)
  2967. Open = NSR->Open;
  2968. ASSERT(VALID_OPEN(Open));
  2969. if (CancelId)
  2970. {
  2971. if ((Open != pOpen) || (CancelId != NDIS_GET_PACKET_CANCEL_ID(Packet)))
  2972. {
  2973. if (NewFirstPendingPacket == NULL)
  2974. {
  2975. //
  2976. // we found the first pending packet that we are going
  2977. // to put back after we are done
  2978. //
  2979. NewFirstPendingPacket = Packet;
  2980. }
  2981. //
  2982. // put the packet back on the submitted queue
  2983. //
  2984. InsertTailList(&SubmittedPackets, List);
  2985. continue;
  2986. }
  2987. }
  2988. //
  2989. // get rid of packet
  2990. //
  2991. #if ARCNET
  2992. //
  2993. // Now free the arcnet header.
  2994. //
  2995. if ((Miniport->MediaType == NdisMediumArcnet878_2) &&
  2996. MINIPORT_TEST_PACKET_FLAG(Packet, fPACKET_PENDING))
  2997. {
  2998. ndisMFreeArcnetHeader(Miniport, Packet, Open);
  2999. }
  3000. #endif
  3001. //
  3002. // Set this to mark that the packet is complete
  3003. //
  3004. NSR->Open = MAGIC_OPEN_I(7);
  3005. POP_PACKET_STACK(Packet);
  3006. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  3007. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_SG_LIST) &&
  3008. (NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, ScatterGatherListPacketInfo) != NULL))
  3009. {
  3010. ndisMFreeSGList(Miniport, Packet);
  3011. }
  3012. MINIPORT_CLEAR_PACKET_FLAG(Packet, fPACKET_CLEAR_ITEMS);
  3013. (Open->SendCompleteHandler)(Open->ProtocolBindingContext,
  3014. Packet,
  3015. NDIS_STATUS_REQUEST_ABORTED);
  3016. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  3017. ndisMDereferenceOpen(Open);
  3018. }
  3019. Miniport->FirstPendingPacket = NewFirstPendingPacket;
  3020. if (CancelId)
  3021. {
  3022. //
  3023. // we may have some packets that we should put back on miniport
  3024. //
  3025. while (!IsListEmpty(&SubmittedPackets))
  3026. {
  3027. List = RemoveHeadList(&SubmittedPackets);
  3028. InsertTailList(&Miniport->PacketList, List);
  3029. }
  3030. }
  3031. else
  3032. {
  3033. //
  3034. // only reset this flag if we are aborting -all- the packets
  3035. //
  3036. MINIPORT_SET_FLAG(Miniport, fMINIPORT_RESOURCES_AVAILABLE);
  3037. }
  3038. DBGPRINT_RAW(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO,
  3039. ("<==ndisMAbortPackets\n"));
  3040. }
  3041. NDIS_STATUS
  3042. ndisMProcessResetRequested(
  3043. IN PNDIS_MINIPORT_BLOCK Miniport,
  3044. OUT PBOOLEAN pAddressingReset
  3045. )
  3046. /*++
  3047. Routine Description:
  3048. Arguments:
  3049. Return Value:
  3050. Note: called at DPC with miniport spinlock held
  3051. --*/
  3052. {
  3053. NDIS_STATUS Status;
  3054. do
  3055. {
  3056. //
  3057. // Dequeue the reset requested work item. this dequeuing will automatically
  3058. // queue the reset in progress work item.
  3059. //
  3060. NDISM_DEQUEUE_WORK_ITEM(Miniport, NdisWorkItemResetRequested, NULL);
  3061. //
  3062. // if adapter is getting halted, fail the reset request
  3063. //
  3064. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_HALTING))
  3065. {
  3066. MINIPORT_CLEAR_FLAG(Miniport, fMINIPORT_RESET_REQUESTED);
  3067. Status = NDIS_STATUS_NOT_RESETTABLE;
  3068. break;
  3069. }
  3070. //
  3071. // Set the reset in progress bit so that the send path can see it.
  3072. //
  3073. MINIPORT_SET_FLAG(Miniport, fMINIPORT_RESET_IN_PROGRESS);
  3074. MINIPORT_CLEAR_FLAG(Miniport, fMINIPORT_RESET_REQUESTED);
  3075. ndisMSwapOpenHandlers(Miniport,
  3076. NDIS_STATUS_RESET_IN_PROGRESS,
  3077. fMINIPORT_STATE_RESETTING);
  3078. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  3079. NdisMIndicateStatus(Miniport, NDIS_STATUS_RESET_START, NULL, 0);
  3080. NdisMIndicateStatusComplete(Miniport);
  3081. DBGPRINT_RAW(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO,
  3082. (" Calling miniport reset\n"));
  3083. //
  3084. // Call the miniport's reset handler.
  3085. //
  3086. Status = (Miniport->DriverHandle->MiniportCharacteristics.ResetHandler)(pAddressingReset,
  3087. Miniport->MiniportAdapterContext);
  3088. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  3089. }while (FALSE);
  3090. return(Status);
  3091. }
  3092. NDIS_STATUS
  3093. ndisMReset(
  3094. IN NDIS_HANDLE NdisBindingHandle
  3095. )
  3096. /*++
  3097. Routine Description:
  3098. Arguments:
  3099. Return Value:
  3100. --*/
  3101. {
  3102. PNDIS_OPEN_BLOCK Open = (PNDIS_OPEN_BLOCK)NdisBindingHandle;
  3103. PNDIS_MINIPORT_BLOCK Miniport = Open->MiniportHandle;
  3104. NDIS_STATUS Status;
  3105. BOOLEAN FreeLock;
  3106. KIRQL OldIrql;
  3107. DBGPRINT_RAW(DBG_COMP_RESET, DBG_LEVEL_INFO,
  3108. ("==>ndisMReset\n"));
  3109. do
  3110. {
  3111. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  3112. FreeLock = TRUE;
  3113. //
  3114. // if adapter is getting halted, fail the reset request
  3115. //
  3116. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_HALTING))
  3117. {
  3118. Status = NDIS_STATUS_NOT_RESETTABLE;
  3119. break;
  3120. }
  3121. Status = NDIS_STATUS_RESET_IN_PROGRESS;
  3122. //
  3123. // Is there already a reset in progress?
  3124. //
  3125. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  3126. {
  3127. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_RESET_IN_PROGRESS))
  3128. {
  3129. break;
  3130. }
  3131. }
  3132. else
  3133. {
  3134. if (NDISM_QUEUE_WORK_ITEM(Miniport,
  3135. NdisWorkItemResetRequested,
  3136. NdisBindingHandle) != NDIS_STATUS_SUCCESS)
  3137. {
  3138. break;
  3139. }
  3140. }
  3141. Status = NDIS_STATUS_NOT_RESETTABLE;
  3142. if (Miniport->DriverHandle->MiniportCharacteristics.ResetHandler != NULL)
  3143. {
  3144. //
  3145. // Update the open's references.
  3146. //
  3147. M_OPEN_INCREMENT_REF_INTERLOCKED(Open);
  3148. Miniport->ResetOpen = Open;
  3149. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  3150. {
  3151. BOOLEAN AddressingReset = FALSE;
  3152. //
  3153. // Set the reset in progress flag.
  3154. //
  3155. MINIPORT_SET_FLAG(Miniport, fMINIPORT_RESET_IN_PROGRESS | fMINIPORT_CALLING_RESET);
  3156. ndisMSwapOpenHandlers(Miniport,
  3157. NDIS_STATUS_RESET_IN_PROGRESS,
  3158. fMINIPORT_STATE_RESETTING);
  3159. //
  3160. // wait for all the requests to come back.
  3161. // note: this is not the same as waiting for all requests to complete
  3162. // we just make sure the original request call has come back
  3163. //
  3164. do
  3165. {
  3166. if (Miniport->RequestCount == 0)
  3167. {
  3168. break;
  3169. }
  3170. else
  3171. {
  3172. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  3173. NDIS_INTERNAL_STALL(50);
  3174. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  3175. }
  3176. } while (TRUE);
  3177. //
  3178. // ok, we got the permission to reset the adapter
  3179. // make sure it was not turned off while we were waiting
  3180. //
  3181. if (Miniport->CurrentDevicePowerState != PowerDeviceD0)
  3182. {
  3183. Miniport->ResetOpen = NULL;
  3184. //
  3185. // undo the call to ndisMSwapOpenHandlers, leaving the active handlers
  3186. // the fake one.
  3187. //
  3188. Miniport->XState &= ~fMINIPORT_STATE_RESETTING;
  3189. Miniport->FakeStatus = NDIS_STATUS_NOT_SUPPORTED;
  3190. MINIPORT_CLEAR_FLAG(Miniport, fMINIPORT_RESET_IN_PROGRESS | fMINIPORT_CALLING_RESET);
  3191. Status = NDIS_STATUS_NOT_SUPPORTED;
  3192. ndisMDereferenceOpen(Open);
  3193. break;
  3194. }
  3195. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  3196. FreeLock = FALSE;
  3197. NdisMIndicateStatus(Miniport, NDIS_STATUS_RESET_START, NULL, 0);
  3198. NdisMIndicateStatusComplete(Miniport);
  3199. DBGPRINT_RAW(DBG_COMP_WORK_ITEM, DBG_LEVEL_INFO,
  3200. ("Calling miniport reset\n"));
  3201. //
  3202. // Call the miniport's reset handler at DPC
  3203. //
  3204. RAISE_IRQL_TO_DISPATCH(&OldIrql);
  3205. Status = (Miniport->DriverHandle->MiniportCharacteristics.ResetHandler)(
  3206. &AddressingReset,
  3207. Miniport->MiniportAdapterContext);
  3208. LOWER_IRQL(OldIrql, DISPATCH_LEVEL);
  3209. if (NDIS_STATUS_PENDING != Status)
  3210. {
  3211. NdisMResetComplete(Miniport, Status, AddressingReset);
  3212. Status = NDIS_STATUS_PENDING;
  3213. }
  3214. }
  3215. else
  3216. {
  3217. BOOLEAN LocalLock;
  3218. //
  3219. // Set the reset requested flag.
  3220. //
  3221. MINIPORT_SET_FLAG(Miniport, fMINIPORT_RESET_REQUESTED);
  3222. //
  3223. // Grab the local lock.
  3224. //
  3225. LOCK_MINIPORT(Miniport, LocalLock);
  3226. if (LocalLock)
  3227. {
  3228. //
  3229. // If we did not lock down the miniport, then some other routine will
  3230. // do this processing for us. Otherwise we need to do this processing.
  3231. //
  3232. NDISM_PROCESS_DEFERRED(Miniport);
  3233. }
  3234. UNLOCK_MINIPORT(Miniport, LocalLock);
  3235. Status = NDIS_STATUS_PENDING;
  3236. }
  3237. }
  3238. } while (FALSE);
  3239. if (FreeLock)
  3240. {
  3241. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  3242. }
  3243. DBGPRINT_RAW(DBG_COMP_RESET, DBG_LEVEL_INFO,
  3244. ("<==ndisReset\n"));
  3245. return(Status);
  3246. }
  3247. VOID
  3248. NdisMResetComplete(
  3249. IN NDIS_HANDLE MiniportAdapterHandle,
  3250. IN NDIS_STATUS Status,
  3251. IN BOOLEAN AddressingReset
  3252. )
  3253. /*++
  3254. Routine Description:
  3255. This function indicates the completion of a reset.
  3256. Arguments:
  3257. MiniportAdapterHandle - points to the adapter block.
  3258. Status - Status of the reset.
  3259. AddressingReset - Do we have to submit a request to reload the address
  3260. information. This includes packet filter, and multicast/functional addresses.
  3261. Return Value:
  3262. None.
  3263. --*/
  3264. {
  3265. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  3266. KIRQL OldIrql;
  3267. BOOLEAN LocalLock;
  3268. DBGPRINT_RAW(DBG_COMP_RESET, DBG_LEVEL_INFO,
  3269. ("==>NdisMResetComplete\n"));
  3270. ASSERT_MINIPORT_LOCKED(Miniport);
  3271. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  3272. #if 0
  3273. //
  3274. // do not clear the CALLING_RESET flag now. if we do, it will allow
  3275. // ndisMDispatchRequests to send down a request to the miniport that can
  3276. // later on get aborted by Ndis in NdisMResetComplete
  3277. //
  3278. //
  3279. // clear this flag here as well. if reset completed before the original
  3280. // reset call returns, this will allow the RestoreFilter requests to go through
  3281. //
  3282. MINIPORT_CLEAR_FLAG(Miniport, fMINIPORT_CALLING_RESET);
  3283. #endif
  3284. if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_RESET_IN_PROGRESS))
  3285. {
  3286. BAD_MINIPORT(Miniport, "Completing reset when one is not pending");
  3287. KeBugCheckEx(BUGCODE_ID_DRIVER,
  3288. (ULONG_PTR)Miniport,
  3289. (ULONG_PTR)Status,
  3290. (ULONG_PTR)AddressingReset,
  3291. 0);
  3292. }
  3293. //
  3294. // Code that is common for synchronous and async resets.
  3295. //
  3296. ndisMResetCompleteStage1(Miniport, Status, AddressingReset);
  3297. if (Miniport->WorkQueue[NdisWorkItemRequest].Next == NULL)
  3298. {
  3299. //
  3300. // somehow we did not queue a workitem due to address reset flag
  3301. //
  3302. AddressingReset = FALSE;
  3303. }
  3304. if (!AddressingReset || (Status != NDIS_STATUS_SUCCESS))
  3305. {
  3306. //
  3307. // If there is no addressing reset to be done or
  3308. // the reset failed in some way then we tell the
  3309. // bindings now.
  3310. //
  3311. ndisMResetCompleteStage2(Miniport);
  3312. }
  3313. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  3314. DBGPRINT_RAW(DBG_COMP_RESET, DBG_LEVEL_INFO,
  3315. ("<==NdisMResetComplete\n"));
  3316. }
  3317. VOID
  3318. ndisMResetCompleteStage1(
  3319. IN PNDIS_MINIPORT_BLOCK Miniport,
  3320. IN NDIS_STATUS Status,
  3321. IN BOOLEAN AddressingReset
  3322. )
  3323. /*++
  3324. Routine Description:
  3325. Arguments:
  3326. Return Value:
  3327. Note:
  3328. Called at DPC with Miniport's lock held.
  3329. --*/
  3330. {
  3331. if (NDIS_STATUS_NOT_RESETTABLE != Status)
  3332. {
  3333. //
  3334. // Destroy all outstanding packets and requests.
  3335. //
  3336. ndisMAbortPackets(Miniport, NULL, NULL);
  3337. ndisMAbortRequests(Miniport);
  3338. //
  3339. // we can clear this flag now and not any sooner. otherwise we may end up sending
  3340. // a request down on another thread and aborting it ourselves
  3341. //
  3342. MINIPORT_CLEAR_FLAG(Miniport, fMINIPORT_CALLING_RESET);
  3343. //
  3344. // Check if we are going to have to reset theadapter again.
  3345. // This happens when we are doing the reset because of a ring failure.
  3346. //
  3347. if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IGNORE_TOKEN_RING_ERRORS))
  3348. {
  3349. if (Miniport->TrResetRing == 1)
  3350. {
  3351. if (Status == NDIS_STATUS_SUCCESS)
  3352. {
  3353. Miniport->TrResetRing = 0;
  3354. }
  3355. else
  3356. {
  3357. Miniport->TrResetRing = NDIS_MINIPORT_TR_RESET_TIMEOUT;
  3358. }
  3359. }
  3360. }
  3361. //
  3362. // If we need to reset the miniports filter settings then
  3363. // queue the necessary requests & work items.
  3364. //
  3365. if (AddressingReset && (Status == NDIS_STATUS_SUCCESS) &&
  3366. ((Miniport->EthDB != NULL) ||
  3367. (Miniport->TrDB != NULL) ||
  3368. #if ARCNET
  3369. (Miniport->ArcDB != NULL) ||
  3370. #endif
  3371. (Miniport->FddiDB != NULL)))
  3372. {
  3373. ndisMRestoreFilterSettings(Miniport, NULL, TRUE);
  3374. }
  3375. }
  3376. else
  3377. {
  3378. MINIPORT_CLEAR_FLAG(Miniport, fMINIPORT_CALLING_RESET);
  3379. }
  3380. //
  3381. // Save the reset status as it is now.
  3382. //
  3383. Miniport->ResetStatus = Status;
  3384. }
  3385. VOID
  3386. FASTCALL
  3387. ndisMResetCompleteStage2(
  3388. IN PNDIS_MINIPORT_BLOCK Miniport
  3389. )
  3390. /*++
  3391. Routine Description:
  3392. Arguments:
  3393. Return Value:
  3394. Note:
  3395. Called at DPC with Miniport's lock held.
  3396. --*/
  3397. {
  3398. PNDIS_OPEN_BLOCK Open = NULL;
  3399. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  3400. {
  3401. Open = Miniport->ResetOpen;
  3402. Miniport->ResetOpen = NULL;
  3403. }
  3404. else
  3405. {
  3406. ASSERT(Miniport->WorkQueue[NdisWorkItemResetInProgress].Next != NULL);
  3407. NDISM_DEQUEUE_WORK_ITEM(Miniport, NdisWorkItemResetInProgress, &Open);
  3408. }
  3409. MINIPORT_CLEAR_FLAG(Miniport, fMINIPORT_RESET_IN_PROGRESS);
  3410. ndisMRestoreOpenHandlers(Miniport, fMINIPORT_STATE_RESETTING);
  3411. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  3412. NdisMIndicateStatus(Miniport,
  3413. NDIS_STATUS_RESET_END,
  3414. &Miniport->ResetStatus,
  3415. sizeof(Miniport->ResetStatus));
  3416. NdisMIndicateStatusComplete(Miniport);
  3417. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  3418. //
  3419. // If a protocol initiated the reset then notify it of the completion.
  3420. //
  3421. if (NULL != Open)
  3422. {
  3423. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  3424. (Open->ResetCompleteHandler)(Open->ProtocolBindingContext, Miniport->ResetStatus);
  3425. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  3426. ndisMDereferenceOpen(Open);
  3427. }
  3428. //
  3429. // if halt is waiting for this reset to complete, let it know we are done.
  3430. //
  3431. if (Miniport->ResetCompletedEvent)
  3432. SET_EVENT(Miniport->ResetCompletedEvent);
  3433. }
  3434. //
  3435. // The following routines are called in place of the original send, request,
  3436. //
  3437. NDIS_STATUS
  3438. ndisMFakeWanSend(
  3439. IN NDIS_HANDLE NdisBindingHandle,
  3440. IN NDIS_HANDLE NdisLinkHandle,
  3441. IN PVOID Packet
  3442. )
  3443. {
  3444. PNDIS_MINIPORT_BLOCK Miniport = ((PNDIS_OPEN_BLOCK)NdisBindingHandle)->MiniportHandle;
  3445. NDIS_STATUS Status;
  3446. DBGPRINT_RAW(DBG_COMP_SEND, DBG_LEVEL_INFO,
  3447. ("==>ndisMFakeWanSend\n"));
  3448. Status = (Miniport == NULL) ? NDIS_STATUS_FAILURE : Miniport->FakeStatus;
  3449. DBGPRINT_RAW(DBG_COMP_SEND, DBG_LEVEL_INFO,
  3450. ("<==ndisMFakeWanSend\n"));
  3451. return(Status);
  3452. }
  3453. NDIS_STATUS
  3454. ndisMFakeSend(
  3455. IN NDIS_HANDLE NdisBindingHandle,
  3456. IN PNDIS_PACKET Packet
  3457. )
  3458. /*++
  3459. Routine Description:
  3460. Arguments:
  3461. Return Value:
  3462. --*/
  3463. {
  3464. PNDIS_MINIPORT_BLOCK Miniport = ((PNDIS_OPEN_BLOCK)NdisBindingHandle)->MiniportHandle;
  3465. NDIS_STATUS Status;
  3466. DBGPRINT_RAW(DBG_COMP_SEND, DBG_LEVEL_INFO,
  3467. ("==>ndisMFakeSend\n"));
  3468. Status = (Miniport == NULL) ? NDIS_STATUS_FAILURE : Miniport->FakeStatus;
  3469. DBGPRINT_RAW(DBG_COMP_SEND, DBG_LEVEL_INFO,
  3470. ("<==ndisMFakeSend\n"));
  3471. return(Status);
  3472. }
  3473. VOID
  3474. ndisMFakeSendPackets(
  3475. IN NDIS_HANDLE NdisBindingHandle,
  3476. IN PPNDIS_PACKET PacketArray,
  3477. IN UINT NumberOfPackets
  3478. )
  3479. /*++
  3480. Routine Description:
  3481. Arguments:
  3482. Return Value:
  3483. --*/
  3484. {
  3485. PNDIS_OPEN_BLOCK Open = (PNDIS_OPEN_BLOCK)NdisBindingHandle;
  3486. PNDIS_MINIPORT_BLOCK Miniport = Open->MiniportHandle;
  3487. NDIS_STATUS Status;
  3488. UINT c;
  3489. DBGPRINT_RAW(DBG_COMP_SEND, DBG_LEVEL_INFO,
  3490. ("==>ndisMFakeSendPackets\n"));
  3491. Status = (Miniport == NULL) ? NDIS_STATUS_FAILURE :
  3492. ((Miniport->MediaType == NdisMediumArcnet878_2) ?
  3493. NDIS_STATUS_FAILURE : Miniport->FakeStatus);
  3494. for (c = 0; c < NumberOfPackets; c++)
  3495. {
  3496. //
  3497. // For send packets we need to call the completion handler....
  3498. //
  3499. PNDIS_PACKET pPacket = PacketArray[c];
  3500. MINIPORT_CLEAR_PACKET_FLAG(pPacket, fPACKET_CLEAR_ITEMS);
  3501. (Open->SendCompleteHandler)(Open->ProtocolBindingContext, pPacket, Status);
  3502. }
  3503. DBGPRINT_RAW(DBG_COMP_SEND, DBG_LEVEL_INFO,
  3504. ("<==ndisMFakeSendPackets\n"));
  3505. }
  3506. NDIS_STATUS
  3507. ndisMFakeReset(
  3508. IN NDIS_HANDLE NdisBindingHandle
  3509. )
  3510. /*++
  3511. Routine Description:
  3512. Arguments:
  3513. Return Value:
  3514. --*/
  3515. {
  3516. NDIS_STATUS Status;
  3517. DBGPRINT_RAW(DBG_COMP_RESET, DBG_LEVEL_INFO,
  3518. ("==>ndisMFakeReset\n"));
  3519. if (((PNDIS_OPEN_BLOCK)NdisBindingHandle)->MiniportHandle == NULL)
  3520. {
  3521. Status = NDIS_STATUS_FAILURE;
  3522. }
  3523. else
  3524. {
  3525. Status = ((PNDIS_OPEN_BLOCK)NdisBindingHandle)->MiniportHandle->FakeStatus;
  3526. }
  3527. DBGPRINT_RAW(DBG_COMP_RESET, DBG_LEVEL_INFO,
  3528. ("<==ndisMFakeReset\n"));
  3529. return(Status);
  3530. }
  3531. NDIS_STATUS
  3532. ndisMFakeRequest(
  3533. IN NDIS_HANDLE NdisBindingHandle,
  3534. IN PNDIS_REQUEST NdisRequest
  3535. )
  3536. /*++
  3537. Routine Description:
  3538. Arguments:
  3539. Return Value:
  3540. --*/
  3541. {
  3542. NDIS_STATUS Status;
  3543. if (((PNDIS_OPEN_BLOCK)NdisBindingHandle)->MiniportHandle == NULL)
  3544. {
  3545. Status = NDIS_STATUS_FAILURE;
  3546. }
  3547. else
  3548. {
  3549. Status = ((PNDIS_OPEN_BLOCK)NdisBindingHandle)->MiniportHandle->FakeStatus;
  3550. }
  3551. return(Status);
  3552. }
  3553. VOID
  3554. FASTCALL
  3555. ndisMRestoreOpenHandlers(
  3556. IN PNDIS_MINIPORT_BLOCK Miniport,
  3557. IN UCHAR Flags
  3558. )
  3559. /*++
  3560. Routine Description:
  3561. This routine will restore the original open handlers to fake handlers so
  3562. that protocol requests will be processed normally. this routine will check to
  3563. make sure that it can restore the handlers to the original ones because there
  3564. may be more than one reasons to use the fake handlers
  3565. Arguments:
  3566. Miniport - Pointer to the miniport block.
  3567. Flags Flags to -clear-
  3568. Return Value:
  3569. None
  3570. Notes:
  3571. Called with Miniport SpinLock held.
  3572. --*/
  3573. {
  3574. PNDIS_OPEN_BLOCK Open;
  3575. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  3576. ("==>ndisMRestoreOpenHandlers: Miniport %p, Current fake status %lx, Flags %lx\n",
  3577. Miniport,
  3578. Miniport->FakeStatus,
  3579. (ULONG)Flags));
  3580. ASSERT(CURRENT_IRQL == DISPATCH_LEVEL);
  3581. do
  3582. {
  3583. //
  3584. // check to make sure we can restore the handlers
  3585. //
  3586. Miniport->XState &= ~Flags;
  3587. if (Miniport->XState)
  3588. {
  3589. //
  3590. //
  3591. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  3592. ("ndisMRestoreOpenHandlers: Keeping the fake handlers on Miniport %p, State flags %lx\n",
  3593. Miniport, Miniport->XState));
  3594. //
  3595. // if the only reason we are here is because media is disconnected
  3596. // make sure we put back the request handler
  3597. //
  3598. if ((Miniport->XState & fMINIPORT_STATE_MEDIA_DISCONNECTED) == fMINIPORT_STATE_MEDIA_DISCONNECTED)
  3599. {
  3600. for (Open = Miniport->OpenQueue;
  3601. Open != NULL;
  3602. Open = Open->MiniportNextOpen)
  3603. {
  3604. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  3605. {
  3606. Open->RequestHandler = ndisMRequestX;
  3607. }
  3608. else
  3609. {
  3610. Open->RequestHandler = ndisMRequest;
  3611. }
  3612. }
  3613. }
  3614. break;
  3615. }
  3616. for (Open = Miniport->OpenQueue;
  3617. Open != NULL;
  3618. Open = Open->MiniportNextOpen)
  3619. {
  3620. //
  3621. // Restore the handlers.
  3622. //
  3623. Open->SendHandler = (SEND_HANDLER)Miniport->SavedSendHandler;
  3624. Open->SendPacketsHandler = (SEND_PACKETS_HANDLER)Miniport->SavedSendPacketsHandler;
  3625. Open->CancelSendPacketsHandler = (W_CANCEL_SEND_PACKETS_HANDLER)Miniport->SavedCancelSendPacketsHandler;
  3626. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  3627. {
  3628. Open->RequestHandler = ndisMRequestX;
  3629. }
  3630. else
  3631. {
  3632. Open->RequestHandler = ndisMRequest;
  3633. }
  3634. Open->ResetHandler = ndisMReset;
  3635. }
  3636. } while (FALSE);
  3637. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  3638. ("<==ndisMRestoreOpenHandlers: Miniport %p\n", Miniport));
  3639. return;
  3640. }
  3641. VOID
  3642. FASTCALL
  3643. ndisMSwapOpenHandlers(
  3644. IN PNDIS_MINIPORT_BLOCK Miniport,
  3645. IN NDIS_STATUS Status,
  3646. IN UCHAR Flags
  3647. )
  3648. /*++
  3649. Routine Description:
  3650. This routine will swap the miniport handlers to fake handlers so that
  3651. protocol requests will be failed cleanly.
  3652. Arguments:
  3653. Miniport - Pointer to the miniport block.
  3654. Return Value:
  3655. None
  3656. Notes: Called with miniport SpinLock held
  3657. --*/
  3658. {
  3659. PNDIS_OPEN_BLOCK Open;
  3660. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  3661. ("==>ndisMSwapOpenHandlers: Miniport %p, FakeStatus %lx, Flags %lx\n",
  3662. Miniport,
  3663. Status,
  3664. (ULONG)Flags));
  3665. ASSERT(CURRENT_IRQL == DISPATCH_LEVEL);
  3666. Miniport->XState |= Flags;
  3667. //
  3668. // Save the status that should be returned whenever someone
  3669. // calls one of the routines below.
  3670. //
  3671. Miniport->FakeStatus = Status;
  3672. //
  3673. // Swap the handlers for each open queued to the miniport.
  3674. //
  3675. for (Open = Miniport->OpenQueue;
  3676. Open != NULL;
  3677. Open = Open->MiniportNextOpen)
  3678. {
  3679. //
  3680. // Swap the send handler.
  3681. //
  3682. if ((NdisMediumWan == Miniport->MediaType) &&
  3683. !MINIPORT_TEST_FLAG(Miniport, (fMINIPORT_IS_CO | fMINIPORT_IS_NDIS_5)))
  3684. {
  3685. Open->SendHandler = (PVOID)ndisMFakeWanSend;
  3686. }
  3687. else
  3688. {
  3689. Open->SendHandler = (PVOID)ndisMFakeSend;
  3690. }
  3691. //
  3692. // Swap the send packets handler.
  3693. //
  3694. Open->SendPacketsHandler = ndisMFakeSendPackets;
  3695. //
  3696. // Swap the reset handler.
  3697. //
  3698. Open->ResetHandler = ndisMFakeReset;
  3699. //
  3700. // Swap the request handler, but not for media-sense case
  3701. //
  3702. if (NDIS_STATUS_NO_CABLE != Status)
  3703. {
  3704. Open->RequestHandler = ndisMFakeRequest;
  3705. }
  3706. //
  3707. // set the cancel send packets ahndler to null
  3708. //
  3709. Open->CancelSendPacketsHandler = NULL;
  3710. //
  3711. // swap the indicate packet handler
  3712. //
  3713. }
  3714. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  3715. ("<==ndisMSwapOpenHandlers: Miniport %p\n", Miniport));
  3716. }
  3717. VOID
  3718. NdisMSetAttributes(
  3719. IN NDIS_HANDLE MiniportAdapterHandle,
  3720. IN NDIS_HANDLE MiniportAdapterContext,
  3721. IN BOOLEAN BusMaster,
  3722. IN NDIS_INTERFACE_TYPE AdapterType
  3723. )
  3724. /*++
  3725. Routine Description:
  3726. This function sets specific information about an adapter.
  3727. Arguments:
  3728. MiniportAdapterHandle - points to the adapter block.
  3729. MiniportAdapterContext - Context to pass to all Miniport driver functions.
  3730. BusMaster - TRUE if a bus mastering adapter.
  3731. Return Value:
  3732. None.
  3733. --*/
  3734. {
  3735. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  3736. ("==>NdisMSetAttributes: Miniport %p\n", MiniportAdapterHandle));
  3737. NdisMSetAttributesEx(MiniportAdapterHandle,
  3738. MiniportAdapterContext,
  3739. 0,
  3740. BusMaster ? NDIS_ATTRIBUTE_BUS_MASTER : 0,
  3741. AdapterType);
  3742. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  3743. ("<==NdisMSetAttributes: Miniport %p\n", MiniportAdapterHandle));
  3744. }
  3745. VOID
  3746. NdisMSetAttributesEx(
  3747. IN NDIS_HANDLE MiniportAdapterHandle,
  3748. IN NDIS_HANDLE MiniportAdapterContext,
  3749. IN UINT CheckForHangTimeInSeconds OPTIONAL,
  3750. IN ULONG AttributeFlags,
  3751. IN NDIS_INTERFACE_TYPE AdapterType OPTIONAL
  3752. )
  3753. {
  3754. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  3755. PNDIS_OPEN_BLOCK Open;
  3756. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  3757. ("==>NdisMSetAttributesEx: Miniport %p\n", Miniport));
  3758. Miniport->MiniportAdapterContext = MiniportAdapterContext;
  3759. Miniport->MiniportAttributes = AttributeFlags;
  3760. //
  3761. // In the case of a first time initialization this will fail out since there
  3762. // will not be any opens. In the case of a second time initialization (power up)
  3763. // we need to fix up the existing open block's adapter contexts.
  3764. //
  3765. for (Open = Miniport->OpenQueue;
  3766. Open != NULL;
  3767. Open = Open->MiniportNextOpen)
  3768. {
  3769. Open->MiniportAdapterContext = MiniportAdapterContext;
  3770. }
  3771. Miniport->AdapterType = AdapterType;
  3772. //
  3773. // Set the new timeout value in ticks. Each tick is NDIS_CFHANG_TIME_SECONDS long.
  3774. //
  3775. if (CheckForHangTimeInSeconds != 0)
  3776. {
  3777. if (CheckForHangTimeInSeconds < NDIS_CFHANG_TIME_SECONDS)
  3778. {
  3779. CheckForHangTimeInSeconds = NDIS_CFHANG_TIME_SECONDS;
  3780. }
  3781. Miniport->CFHangTicks = (USHORT)(CheckForHangTimeInSeconds/NDIS_CFHANG_TIME_SECONDS);
  3782. }
  3783. //
  3784. // Is this a bus master.
  3785. //
  3786. if (AttributeFlags & NDIS_ATTRIBUTE_BUS_MASTER)
  3787. {
  3788. MINIPORT_SET_FLAG(Miniport, fMINIPORT_BUS_MASTER);
  3789. Miniport->InfoFlags |= NDIS_MINIPORT_BUS_MASTER;
  3790. }
  3791. //
  3792. // Should we ignore the packet queues?
  3793. //
  3794. if (AttributeFlags & NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT)
  3795. {
  3796. MINIPORT_SET_FLAG(Miniport, fMINIPORT_IGNORE_PACKET_QUEUE);
  3797. Miniport->InfoFlags |= NDIS_MINIPORT_IGNORE_PACKET_QUEUE;
  3798. }
  3799. //
  3800. // Should we ignore the request queues?
  3801. //
  3802. if (AttributeFlags & NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT)
  3803. {
  3804. MINIPORT_SET_FLAG(Miniport, fMINIPORT_IGNORE_REQUEST_QUEUE);
  3805. Miniport->InfoFlags |= NDIS_MINIPORT_IGNORE_REQUEST_QUEUE;
  3806. }
  3807. //
  3808. // Should we ignore token ring errors?
  3809. //
  3810. if (AttributeFlags & NDIS_ATTRIBUTE_IGNORE_TOKEN_RING_ERRORS)
  3811. {
  3812. MINIPORT_SET_FLAG(Miniport, fMINIPORT_IGNORE_TOKEN_RING_ERRORS);
  3813. Miniport->InfoFlags |= NDIS_MINIPORT_IGNORE_TOKEN_RING_ERRORS;
  3814. }
  3815. //
  3816. // Is this an intermediate miniport?
  3817. //
  3818. if (AttributeFlags & NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER)
  3819. {
  3820. MINIPORT_SET_FLAG(Miniport, fMINIPORT_INTERMEDIATE_DRIVER);
  3821. Miniport->InfoFlags |= NDIS_MINIPORT_INTERMEDIATE_DRIVER;
  3822. }
  3823. //
  3824. // does the device wants us not to halt it on suspend?
  3825. //
  3826. if (AttributeFlags & NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND)
  3827. {
  3828. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_NO_HALT_ON_SUSPEND);
  3829. Miniport->InfoFlags |= NDIS_MINIPORT_NO_HALT_ON_SUSPEND;
  3830. }
  3831. //
  3832. // fMINIPORT_IS_CO flag is set on miniports -before- initializing the miniport based
  3833. // on existence of some handlers in driver characteristics
  3834. // allow the driver to override this. do this -before- the test for deserialization.
  3835. // if these drivers are deserialized, they have to make it explicit.
  3836. //
  3837. if (AttributeFlags & NDIS_ATTRIBUTE_NOT_CO_NDIS)
  3838. {
  3839. MINIPORT_CLEAR_FLAG(Miniport, fMINIPORT_IS_CO);
  3840. }
  3841. if (((AttributeFlags & NDIS_ATTRIBUTE_DESERIALIZE) ||
  3842. MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IS_CO)))
  3843. {
  3844. MINIPORT_SET_FLAG(Miniport, fMINIPORT_DESERIALIZE);
  3845. Miniport->InfoFlags |= NDIS_MINIPORT_DESERIALIZE;
  3846. NdisInitializeTimer(&Miniport->WakeUpDpcTimer,
  3847. ndisMWakeUpDpcX,
  3848. Miniport);
  3849. //
  3850. // Reset handlers to the de-serialized ones
  3851. //
  3852. Miniport->SendCompleteHandler = ndisMSendCompleteX;
  3853. }
  3854. else
  3855. {
  3856. NdisInitializeTimer(&Miniport->WakeUpDpcTimer,
  3857. ndisMWakeUpDpc,
  3858. Miniport);
  3859. }
  3860. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IS_CO))
  3861. {
  3862. CoReferencePackage();
  3863. }
  3864. if ((Miniport->DriverHandle->MiniportCharacteristics.MajorNdisVersion > 5) ||
  3865. ((Miniport->DriverHandle->MiniportCharacteristics.MajorNdisVersion == 5) &&
  3866. (Miniport->DriverHandle->MiniportCharacteristics.MinorNdisVersion >= 1)) ||
  3867. (AttributeFlags & NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS))
  3868. {
  3869. MINIPORT_SET_SEND_FLAG(Miniport, fMINIPORT_SEND_DO_NOT_MAP_MDLS);
  3870. Miniport->InfoFlags |= NDIS_MINIPORT_USES_SAFE_BUFFER_APIS;
  3871. }
  3872. if (AttributeFlags & NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK)
  3873. {
  3874. Miniport->InfoFlags |= NDIS_MINIPORT_SURPRISE_REMOVE_OK;
  3875. }
  3876. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  3877. ("<==NdisMSetAttributesEx: Miniport %p\n", Miniport));
  3878. }
  3879. NDIS_STATUS
  3880. NdisMSetMiniportSecondary(
  3881. IN NDIS_HANDLE MiniportHandle,
  3882. IN NDIS_HANDLE PrimaryMiniportHandle
  3883. )
  3884. /*++
  3885. Routine Description:
  3886. This associates a miniport with another marking current miniport as secondary
  3887. with the link to primary. The secondary has no bindings and opens blocked.
  3888. Arguments:
  3889. MiniportHandle - Miniport block for this miniport
  3890. PrimaryMiniportHandle - Miniport block for the primary miniport
  3891. Return Value:
  3892. NDIS_STATUS_SUCCESS or NDIS_STATUS_NOT_SUPPORTED
  3893. --*/
  3894. {
  3895. PNDIS_MINIPORT_BLOCK Miniport, PrimaryMiniport;
  3896. PNDIS_OPEN_BLOCK Open;
  3897. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  3898. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  3899. ("==>NdisMSetMiniportSecondary: Miniport %p, PrimaryMiniport %p\n",
  3900. MiniportHandle, PrimaryMiniportHandle));
  3901. Miniport = (PNDIS_MINIPORT_BLOCK)MiniportHandle;
  3902. ASSERT(Miniport != NULL);
  3903. PrimaryMiniport = (PNDIS_MINIPORT_BLOCK)PrimaryMiniportHandle;
  3904. ASSERT(PrimaryMiniport != NULL);
  3905. if ((Miniport->DriverHandle != PrimaryMiniport->DriverHandle) ||
  3906. (Miniport->PrimaryMiniport != Miniport))
  3907. {
  3908. Status = NDIS_STATUS_NOT_SUPPORTED;
  3909. }
  3910. else
  3911. {
  3912. MINIPORT_SET_FLAG(Miniport, fMINIPORT_SECONDARY);
  3913. ndisCloseMiniportBindings(Miniport);
  3914. Miniport->PrimaryMiniport = PrimaryMiniport;
  3915. }
  3916. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  3917. ("<==NdisMSetMiniportSecondary: Miniport %p, PrimaryMiniport %p\n",
  3918. MiniportHandle, PrimaryMiniportHandle));
  3919. return Status;
  3920. }
  3921. NDIS_STATUS
  3922. NdisMPromoteMiniport(
  3923. IN NDIS_HANDLE MiniportHandle
  3924. )
  3925. /*++
  3926. Routine Description:
  3927. This promotes a secondary miniport to a primary. Fails if there already
  3928. is a primary.
  3929. Arguments:
  3930. MiniportHandle - Miniport block for this miniport
  3931. Return Value:
  3932. NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE
  3933. --*/
  3934. {
  3935. PNDIS_MINIPORT_BLOCK Miniport;
  3936. PNDIS_WORK_ITEM WorkItem;
  3937. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  3938. PNDIS_MINIPORT_BLOCK OldPrimaryMiniport;
  3939. PNDIS_M_DRIVER_BLOCK MiniBlock;
  3940. KIRQL OldIrql;
  3941. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  3942. ("==>NdisMPromoteMiniport: Miniport %p\n", MiniportHandle));
  3943. Miniport = (PNDIS_MINIPORT_BLOCK)MiniportHandle;
  3944. ASSERT(Miniport != NULL);
  3945. do
  3946. {
  3947. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  3948. if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_SECONDARY) ||
  3949. (Miniport->PrimaryMiniport == Miniport) ||
  3950. MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_REJECT_REQUESTS))
  3951. {
  3952. Status = NDIS_STATUS_NOT_SUPPORTED;
  3953. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  3954. break;
  3955. }
  3956. WorkItem = ALLOC_FROM_POOL(sizeof(NDIS_WORK_ITEM), NDIS_TAG_WORK_ITEM);
  3957. if (WorkItem == NULL)
  3958. {
  3959. Status = NDIS_STATUS_RESOURCES;
  3960. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  3961. break;
  3962. }
  3963. OldPrimaryMiniport = Miniport->PrimaryMiniport;
  3964. NdisInitializeWorkItem(WorkItem, ndisQueuedCheckAdapterBindings, Miniport);
  3965. MINIPORT_CLEAR_FLAG(Miniport, fMINIPORT_SECONDARY);
  3966. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_QUEUED_BIND_WORKITEM);
  3967. MINIPORT_INCREMENT_REF(Miniport);
  3968. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  3969. //
  3970. // Make all miniports belonging to this cluster point
  3971. // to this new primary (including this primary itself).
  3972. //
  3973. MiniBlock = Miniport->DriverHandle;
  3974. ACQUIRE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, &OldIrql);
  3975. {
  3976. PNDIS_MINIPORT_BLOCK TmpMiniport = NULL;
  3977. for (TmpMiniport = MiniBlock->MiniportQueue;
  3978. TmpMiniport != NULL;
  3979. TmpMiniport = TmpMiniport->NextMiniport)
  3980. {
  3981. if (TmpMiniport->PrimaryMiniport == OldPrimaryMiniport)
  3982. {
  3983. //
  3984. // TmpMiniport was a secondary of the old primary
  3985. // Lets make it point to the new Primary (this miniport)
  3986. //
  3987. TmpMiniport->PrimaryMiniport = Miniport;
  3988. }
  3989. }
  3990. }
  3991. RELEASE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, OldIrql);
  3992. //
  3993. // Queue a work-item to notify protocols and make sure the miniport does not go
  3994. // away while we are waiting
  3995. //
  3996. NdisScheduleWorkItem(WorkItem);
  3997. } while (FALSE);
  3998. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  3999. ("<==NdisMPromoteMiniport: Miniport %p\n", MiniportHandle));
  4000. return Status;
  4001. }
  4002. NDIS_STATUS
  4003. ndisQueueBindWorkitem(
  4004. IN PNDIS_MINIPORT_BLOCK Miniport
  4005. )
  4006. /*++
  4007. Routine Description:
  4008. This routine queues a workitem to handle initiating the bindings
  4009. between a miniport and the protocols.
  4010. Arguments:
  4011. Miniport
  4012. Return Value:
  4013. NDIS_STATUS_SUCCESS if the workitem is successfully queued.
  4014. --*/
  4015. {
  4016. PNDIS_WORK_ITEM WorkItem;
  4017. NDIS_STATUS Status;
  4018. KIRQL OldIrql;
  4019. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  4020. ("==>ndisQueueBindWorkitem: Miniport %p\n", Miniport));
  4021. do
  4022. {
  4023. WorkItem = ALLOC_FROM_POOL(sizeof(NDIS_WORK_ITEM), NDIS_TAG_WORK_ITEM);
  4024. if (WorkItem == NULL)
  4025. {
  4026. Status = NDIS_STATUS_RESOURCES;
  4027. break;
  4028. }
  4029. PnPReferencePackage();
  4030. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  4031. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_REJECT_REQUESTS))
  4032. {
  4033. //
  4034. // miniport is halting or halted. abort
  4035. //
  4036. Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
  4037. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  4038. }
  4039. else
  4040. {
  4041. MINIPORT_PNP_SET_FLAG(Miniport, fMINIPORT_QUEUED_BIND_WORKITEM);
  4042. MINIPORT_INCREMENT_REF(Miniport);
  4043. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  4044. WorkItem->Routine = (NDIS_PROC)ndisQueuedCheckAdapterBindings;
  4045. WorkItem->Context = (PVOID)Miniport;
  4046. INITIALIZE_WORK_ITEM((PWORK_QUEUE_ITEM)WorkItem->WrapperReserved,
  4047. ndisWorkItemHandler,
  4048. WorkItem);
  4049. XQUEUE_WORK_ITEM((PWORK_QUEUE_ITEM)WorkItem->WrapperReserved,
  4050. CriticalWorkQueue);
  4051. Status = NDIS_STATUS_SUCCESS;
  4052. }
  4053. PnPDereferencePackage();
  4054. }while (FALSE);
  4055. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  4056. ("<==ndisQueueBindWorkitem: Miniport %p, Status %lx\n", Miniport, Status));
  4057. return Status;
  4058. }
  4059. VOID
  4060. ndisQueuedCheckAdapterBindings(
  4061. IN PNDIS_WORK_ITEM pWorkItem,
  4062. IN PVOID Context
  4063. )
  4064. /*++
  4065. Routine Description:
  4066. Arguments:
  4067. Return Value:
  4068. --*/
  4069. {
  4070. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)Context;
  4071. NTSTATUS NtStatus;
  4072. KIRQL OldIrql;
  4073. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  4074. ("==>ndisQueuedCheckAdapterBindings: Miniport %p\n", Miniport));
  4075. PnPReferencePackage();
  4076. do
  4077. {
  4078. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  4079. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_REJECT_REQUESTS) ||
  4080. MINIPORT_TEST_FLAG(Miniport, fMINIPORT_SECONDARY) ||
  4081. ((Miniport->PnPDeviceState != NdisPnPDeviceStarted) &&
  4082. (Miniport->PnPDeviceState != NdisPnPDeviceQueryStopped) &&
  4083. (Miniport->PnPDeviceState != NdisPnPDeviceQueryRemoved)))
  4084. {
  4085. MINIPORT_PNP_CLEAR_FLAG(Miniport, fMINIPORT_QUEUED_BIND_WORKITEM);
  4086. if (Miniport->QueuedBindingCompletedEvent)
  4087. {
  4088. SET_EVENT(Miniport->QueuedBindingCompletedEvent);
  4089. }
  4090. }
  4091. else
  4092. {
  4093. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  4094. ndisCheckAdapterBindings(Miniport, NULL);
  4095. //
  4096. // Set the device class association so that people can reference this.
  4097. //
  4098. NtStatus = IoSetDeviceInterfaceState(&Miniport->SymbolicLinkName, TRUE);
  4099. if (!NT_SUCCESS(NtStatus))
  4100. {
  4101. DBGPRINT(DBG_COMP_PNP, DBG_LEVEL_ERR,
  4102. ("ndisQueuedCheckAdapterBindings: IoSetDeviceInterfaceState failed: Miniport %p, Status %lx\n", Miniport, NtStatus));
  4103. }
  4104. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  4105. MINIPORT_PNP_CLEAR_FLAG(Miniport, fMINIPORT_QUEUED_BIND_WORKITEM);
  4106. if (Miniport->QueuedBindingCompletedEvent)
  4107. {
  4108. SET_EVENT(Miniport->QueuedBindingCompletedEvent);
  4109. }
  4110. }
  4111. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  4112. }while (FALSE);
  4113. PnPDereferencePackage();
  4114. MINIPORT_DECREMENT_REF(Miniport);
  4115. FREE_POOL(pWorkItem);
  4116. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  4117. ("<==ndisQueuedCheckAdapterBindings: Miniport %p\n", Miniport));
  4118. }
  4119. BOOLEAN
  4120. ndisIsMiniportStarted(
  4121. IN PNDIS_MINIPORT_BLOCK Miniport
  4122. )
  4123. /*++
  4124. Routine Description:
  4125. this routine checks to make sure the miniport has been initialized by walking
  4126. the miniport queue on the driver
  4127. returns TRUE is the Miniport has been started, otherwise returns FALSE
  4128. Arguments:
  4129. Miniport - Miniport
  4130. Return Value:
  4131. TRUE if started, FALSE otherwise
  4132. --*/
  4133. {
  4134. PNDIS_M_DRIVER_BLOCK MiniBlock;
  4135. PNDIS_MINIPORT_BLOCK TmpMiniport = NULL;
  4136. KIRQL OldIrql;
  4137. DBGPRINT_RAW(DBG_COMP_PNP, DBG_LEVEL_INFO,
  4138. ("==>ndisIsMiniportStarted: Miniport %p\n", Miniport));
  4139. //
  4140. // find the miniport on driver queue
  4141. //
  4142. MiniBlock = Miniport->DriverHandle;
  4143. if (MiniBlock)
  4144. {
  4145. PnPReferencePackage();
  4146. ACQUIRE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, &OldIrql);
  4147. for (TmpMiniport = MiniBlock->MiniportQueue;
  4148. TmpMiniport != NULL;
  4149. TmpMiniport = TmpMiniport->NextMiniport)
  4150. {
  4151. if (TmpMiniport == Miniport)
  4152. {
  4153. break;
  4154. }
  4155. }
  4156. RELEASE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, OldIrql);
  4157. PnPDereferencePackage();
  4158. }
  4159. DBGPRINT_RAW(DBG_COMP_PM, DBG_LEVEL_INFO,
  4160. ("<==ndisIsMiniportStarted: Miniport %p, Started %lx\n", Miniport, (TmpMiniport == Miniport)));
  4161. return (TmpMiniport == Miniport);
  4162. }
  4163. BOOLEAN
  4164. FASTCALL
  4165. ndisQueueOpenOnMiniport(
  4166. IN PNDIS_MINIPORT_BLOCK Miniport,
  4167. IN PNDIS_OPEN_BLOCK Open
  4168. )
  4169. /*++
  4170. Routine Description:
  4171. inserts an open block to the list of opens for a Miniport.
  4172. Arguments:
  4173. OpenP - The open block to be queued.
  4174. Miniport - The Miniport block to queue it on.
  4175. NOTE: called with miniport lock held. for serialized miniports, the local lock is held as well
  4176. Return Value:
  4177. None.
  4178. --*/
  4179. {
  4180. BOOLEAN rc;
  4181. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  4182. ("==>ndisQueueOpenOnMiniport: Miniport %p, Open %p\n", Miniport, Open));
  4183. //
  4184. // we can not reference the package here because this routine can
  4185. // be claled at raised IRQL.
  4186. // make sure the PNP package has been referenced already
  4187. //
  4188. ASSERT(ndisPkgs[NPNP_PKG].ReferenceCount > 0);
  4189. if ((Miniport->PnPDeviceState != NdisPnPDeviceStarted) &&
  4190. (Miniport->PnPDeviceState != NdisPnPDeviceQueryStopped) &&
  4191. (Miniport->PnPDeviceState != NdisPnPDeviceQueryRemoved))
  4192. {
  4193. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  4194. ("ndisQueueOpenOnMiniport: failing open because the miniport is not started, Miniport %p, Open %p\n", Miniport, Open));
  4195. rc = FALSE;
  4196. }
  4197. else
  4198. {
  4199. Open->MiniportNextOpen = Miniport->OpenQueue;
  4200. Miniport->OpenQueue = Open;
  4201. Miniport->NumOpens++;
  4202. ndisUpdateCheckForLoopbackFlag(Miniport);
  4203. rc = TRUE;
  4204. }
  4205. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  4206. ("<==ndisQueueOpenOnMiniport: Miniport %p, Open %p, rc %lx\n", Miniport, Open, rc));
  4207. return rc;
  4208. }
  4209. /*++
  4210. VOID
  4211. ndisMSetIndicatePacketHandler(
  4212. IN PNDIS_MINIPORT_BLOCK Miniport
  4213. )
  4214. this function sets the Miniport's indicate packet handler either during
  4215. initial initialization or after a media re-connect status indication
  4216. can be called at DPC
  4217. --*/
  4218. VOID
  4219. ndisMSetIndicatePacketHandler(
  4220. IN PNDIS_MINIPORT_BLOCK Miniport
  4221. )
  4222. {
  4223. KIRQL OldIrql;
  4224. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  4225. //
  4226. // set the PacketIndicateHandler and SavedPacketIndicateHandler
  4227. //
  4228. switch(Miniport->MediaType)
  4229. {
  4230. case NdisMedium802_3:
  4231. Miniport->SavedPacketIndicateHandler = ethFilterDprIndicateReceivePacket;
  4232. break;
  4233. case NdisMedium802_5:
  4234. Miniport->SavedPacketIndicateHandler = trFilterDprIndicateReceivePacket;
  4235. break;
  4236. case NdisMediumFddi:
  4237. Miniport->SavedPacketIndicateHandler = fddiFilterDprIndicateReceivePacket;
  4238. break;
  4239. #if ARCNET
  4240. case NdisMediumArcnet878_2:
  4241. Miniport->SavedPacketIndicateHandler = ethFilterDprIndicateReceivePacket;
  4242. Miniport->SendPacketsHandler = ndisMFakeSendPackets;
  4243. break;
  4244. #endif
  4245. case NdisMediumWan:
  4246. break;
  4247. case NdisMediumIrda:
  4248. case NdisMediumWirelessWan:
  4249. case NdisMediumLocalTalk:
  4250. //
  4251. // fall through
  4252. //
  4253. default:
  4254. Miniport->SavedPacketIndicateHandler = ndisMIndicatePacket;
  4255. break;
  4256. }
  4257. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_MEDIA_CONNECTED))
  4258. {
  4259. Miniport->PacketIndicateHandler = Miniport->SavedPacketIndicateHandler;
  4260. }
  4261. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  4262. }
  4263. BOOLEAN
  4264. ndisReferenceOpenByHandle(
  4265. PNDIS_OPEN_BLOCK Open,
  4266. BOOLEAN fRef
  4267. )
  4268. {
  4269. KIRQL OldIrql;
  4270. PNDIS_OPEN_BLOCK *ppOpen;
  4271. BOOLEAN rc = FALSE;
  4272. ACQUIRE_SPIN_LOCK(&ndisGlobalOpenListLock, &OldIrql);
  4273. for (ppOpen = &ndisGlobalOpenList; *ppOpen != NULL; ppOpen = &(*ppOpen)->NextGlobalOpen)
  4274. {
  4275. if (*ppOpen == Open)
  4276. {
  4277. ACQUIRE_SPIN_LOCK_DPC(&Open->SpinLock)
  4278. if (fRef)
  4279. {
  4280. if ((!MINIPORT_TEST_FLAG(Open, fMINIPORT_OPEN_CLOSING)) &&
  4281. (Open->References != 0))
  4282. {
  4283. M_OPEN_INCREMENT_REF_INTERLOCKED(Open);
  4284. rc = TRUE;
  4285. }
  4286. }
  4287. else
  4288. {
  4289. rc = TRUE;
  4290. }
  4291. RELEASE_SPIN_LOCK_DPC(&Open->SpinLock);
  4292. break;
  4293. }
  4294. }
  4295. RELEASE_SPIN_LOCK(&ndisGlobalOpenListLock, OldIrql);
  4296. return rc;
  4297. }
  4298. BOOLEAN
  4299. ndisRemoveOpenFromGlobalList(
  4300. IN PNDIS_OPEN_BLOCK Open
  4301. )
  4302. {
  4303. PNDIS_OPEN_BLOCK *ppOpen;
  4304. KIRQL OldIrql;
  4305. BOOLEAN rc = FALSE;
  4306. ACQUIRE_SPIN_LOCK(&ndisGlobalOpenListLock, &OldIrql);
  4307. for (ppOpen = &ndisGlobalOpenList; *ppOpen != NULL; ppOpen = &(*ppOpen)->NextGlobalOpen)
  4308. {
  4309. if (*ppOpen == Open)
  4310. {
  4311. *ppOpen = Open->NextGlobalOpen;
  4312. rc = TRUE;
  4313. break;
  4314. }
  4315. }
  4316. RELEASE_SPIN_LOCK(&ndisGlobalOpenListLock, OldIrql);
  4317. return rc;
  4318. }