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

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