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.

2005 lines
53 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. mp_main.c
  5. Abstract:
  6. This module contains NDIS miniport handlers
  7. Revision History:
  8. Who When What
  9. -------- -------- ----------------------------------------------
  10. DChen 11-01-99 created
  11. Notes:
  12. --*/
  13. #include "precomp.h"
  14. #if DBG
  15. #define _FILENUMBER "NIAM"
  16. #endif
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(INIT, DriverEntry)
  19. #endif
  20. //
  21. // Global data for LBFO
  22. //
  23. #if LBFO
  24. LIST_ENTRY g_AdapterList;
  25. NDIS_SPIN_LOCK g_Lock;
  26. #endif
  27. NDIS_STATUS DriverEntry(
  28. IN PDRIVER_OBJECT DriverObject,
  29. IN PUNICODE_STRING RegistryPath
  30. )
  31. /*++
  32. Routine Description:
  33. Arguments:
  34. DriverObject - pointer to the driver object
  35. RegistryPath - pointer to the driver registry path
  36. Return Value:
  37. NDIS_STATUS - the value returned by NdisMRegisterMiniport
  38. --*/
  39. {
  40. NDIS_STATUS Status;
  41. NDIS_HANDLE NdisWrapperHandle;
  42. NDIS_MINIPORT_CHARACTERISTICS MPChar;
  43. DBGPRINT(MP_TRACE, ("====> DriverEntry\n"));
  44. //
  45. // Notify the NDIS wrapper about this driver, get a NDIS wrapper handle back
  46. //
  47. NdisMInitializeWrapper(
  48. &NdisWrapperHandle,
  49. DriverObject,
  50. RegistryPath,
  51. NULL);
  52. if (NdisWrapperHandle == NULL)
  53. {
  54. Status = NDIS_STATUS_FAILURE;
  55. DBGPRINT_S(Status, ("<==== DriverEntry failed to InitWrapper, Status=%x\n", Status));
  56. return Status;
  57. }
  58. #if LBFO
  59. //
  60. // Init the global data
  61. //
  62. InitializeListHead(&g_AdapterList);
  63. NdisAllocateSpinLock(&g_Lock);
  64. //
  65. // For regular miniports, there is NO need to have an Unload handler
  66. // For a LBFO miniport, register an Unload handler for global data cleanup
  67. // The unload handler has a more global scope, whereas the scope of the
  68. // MiniportHalt function is restricted to a particular miniport instance.
  69. //
  70. NdisMRegisterUnloadHandler(NdisWrapperHandle, MPUnload);
  71. #endif
  72. //
  73. // Fill in the Miniport characteristics structure with the version numbers
  74. // and the entry points for driver-supplied MiniportXxx
  75. //
  76. NdisZeroMemory(&MPChar, sizeof(MPChar));
  77. MPChar.MajorNdisVersion = MP_NDIS_MAJOR_VERSION;
  78. MPChar.MinorNdisVersion = MP_NDIS_MINOR_VERSION;
  79. MPChar.CheckForHangHandler = MPCheckForHang;
  80. MPChar.DisableInterruptHandler = NULL;
  81. MPChar.EnableInterruptHandler = NULL;
  82. MPChar.HaltHandler = MPHalt;
  83. MPChar.InitializeHandler = MPInitialize;
  84. MPChar.QueryInformationHandler = MPQueryInformation;
  85. //MPChar.ReconfigureHandler = NULL;
  86. MPChar.ResetHandler = MPReset;
  87. MPChar.ReturnPacketHandler = MPReturnPacket;
  88. MPChar.SendPacketsHandler = MpSendPacketsHandler;
  89. MPChar.SetInformationHandler = MPSetInformation;
  90. MPChar.AllocateCompleteHandler = MPAllocateComplete;
  91. MPChar.HandleInterruptHandler = MPHandleInterrupt;
  92. MPChar.ISRHandler = MPIsr;
  93. #ifdef NDIS51_MINIPORT
  94. MPChar.CancelSendPacketsHandler = MPCancelSendPackets;
  95. MPChar.PnPEventNotifyHandler = MPPnPEventNotify;
  96. MPChar.AdapterShutdownHandler = MPShutdown;
  97. #endif
  98. DBGPRINT(MP_LOUD, ("Calling NdisMRegisterMiniport...\n"));
  99. Status = NdisMRegisterMiniport(
  100. NdisWrapperHandle,
  101. &MPChar,
  102. sizeof(NDIS_MINIPORT_CHARACTERISTICS));
  103. if (Status != NDIS_STATUS_SUCCESS)
  104. {
  105. NdisTerminateWrapper(NdisWrapperHandle, NULL);
  106. }
  107. DBGPRINT_S(Status, ("<==== DriverEntry, Status=%x\n", Status));
  108. return Status;
  109. }
  110. NDIS_STATUS MPInitialize(
  111. OUT PNDIS_STATUS OpenErrorStatus,
  112. OUT PUINT SelectedMediumIndex,
  113. IN PNDIS_MEDIUM MediumArray,
  114. IN UINT MediumArraySize,
  115. IN NDIS_HANDLE MiniportAdapterHandle,
  116. IN NDIS_HANDLE WrapperConfigurationContext
  117. )
  118. /*++
  119. Routine Description:
  120. MiniportInitialize handler
  121. Arguments:
  122. OpenErrorStatus Not used
  123. SelectedMediumIndex Place-holder for what media we are using
  124. MediumArray Array of ndis media passed down to us to pick from
  125. MediumArraySize Size of the array
  126. MiniportAdapterHandle The handle NDIS uses to refer to us
  127. WrapperConfigurationContext For use by NdisOpenConfiguration
  128. Return Value:
  129. NDIS_STATUS_SUCCESS unless something goes wrong
  130. --*/
  131. {
  132. NDIS_STATUS Status;
  133. PMP_ADAPTER Adapter = NULL;
  134. UINT index;
  135. #if DBG
  136. LARGE_INTEGER TS, TD, TE;
  137. #endif
  138. DBGPRINT(MP_TRACE, ("====> MPInitialize\n"));
  139. #if DBG
  140. NdisGetCurrentSystemTime(&TS);
  141. #endif
  142. do
  143. {
  144. //
  145. // Find the media type we support
  146. //
  147. for (index = 0; index < MediumArraySize; ++index)
  148. {
  149. if (MediumArray[index] == NIC_MEDIA_TYPE)
  150. {
  151. break;
  152. }
  153. }
  154. if (index == MediumArraySize)
  155. {
  156. DBGPRINT(MP_ERROR, ("Expected media (%x) is not in MediumArray.\n", NIC_MEDIA_TYPE));
  157. Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
  158. break;
  159. }
  160. *SelectedMediumIndex = index;
  161. //
  162. // Allocate MP_ADAPTER structure
  163. //
  164. Status = MpAllocAdapterBlock(&Adapter);
  165. if (Status != NDIS_STATUS_SUCCESS)
  166. {
  167. break;
  168. }
  169. Adapter->AdapterHandle = MiniportAdapterHandle;
  170. //
  171. // Read the registry parameters
  172. //
  173. Status = NICReadRegParameters(
  174. Adapter,
  175. WrapperConfigurationContext);
  176. if (Status != NDIS_STATUS_SUCCESS)
  177. {
  178. break;
  179. }
  180. //
  181. // Inform NDIS of the attributes of our adapter.
  182. // This has to be done before calling NdisMRegisterXxx or NdisXxxx function
  183. // that depends on the information supplied to NdisMSetAttributesEx
  184. // e.g. NdisMAllocateMapRegisters
  185. // If this is NDIS51 miniport, it should use safe APIs. But if this is NDIS
  186. // 5.0, the driver claim to use safe APIs by setting NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS
  187. //
  188. NdisMSetAttributesEx(
  189. MiniportAdapterHandle,
  190. (NDIS_HANDLE) Adapter,
  191. 0,
  192. #ifdef NDIS51_MINIPORT
  193. NDIS_ATTRIBUTE_DESERIALIZE |
  194. NDIS_ATTRIBUTE_BUS_MASTER,
  195. #else
  196. NDIS_ATTRIBUTE_DESERIALIZE |
  197. NDIS_ATTRIBUTE_BUS_MASTER |
  198. NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS,
  199. #endif
  200. NIC_INTERFACE_TYPE);
  201. //
  202. // Find the physical adapter
  203. //
  204. Status = MpFindAdapter(Adapter, WrapperConfigurationContext);
  205. if (Status != NDIS_STATUS_SUCCESS)
  206. {
  207. break;
  208. }
  209. //
  210. // Map bus-relative IO range to system IO space
  211. //
  212. Status = NdisMRegisterIoPortRange(
  213. (PVOID *)&Adapter->PortOffset,
  214. Adapter->AdapterHandle,
  215. Adapter->IoBaseAddress,
  216. Adapter->IoRange);
  217. if (Status != NDIS_STATUS_SUCCESS)
  218. {
  219. DBGPRINT(MP_ERROR, ("NdisMRegisterioPortRange failed\n"));
  220. NdisWriteErrorLogEntry(
  221. Adapter->AdapterHandle,
  222. NDIS_ERROR_CODE_BAD_IO_BASE_ADDRESS,
  223. 0);
  224. break;
  225. }
  226. //
  227. // Read additional info from NIC such as MAC address
  228. //
  229. Status = NICReadAdapterInfo(Adapter);
  230. if (Status != NDIS_STATUS_SUCCESS)
  231. {
  232. break;
  233. }
  234. //
  235. // Allocate all other memory blocks including shared memory
  236. //
  237. Status = NICAllocAdapterMemory(Adapter);
  238. if (Status != NDIS_STATUS_SUCCESS)
  239. {
  240. break;
  241. }
  242. //
  243. // Init send data structures
  244. //
  245. NICInitSend(Adapter);
  246. //
  247. // Init receive data structures
  248. //
  249. Status = NICInitRecv(Adapter);
  250. if (Status != NDIS_STATUS_SUCCESS)
  251. {
  252. break;
  253. }
  254. // Map bus-relative registers to virtual system-space
  255. Status = NdisMMapIoSpace(
  256. (PVOID *) &(Adapter->CSRAddress),
  257. Adapter->AdapterHandle,
  258. Adapter->MemPhysAddress,
  259. NIC_MAP_IOSPACE_LENGTH);
  260. if (Status != NDIS_STATUS_SUCCESS)
  261. {
  262. DBGPRINT(MP_ERROR, ("NdisMMapIoSpace failed\n"));
  263. NdisWriteErrorLogEntry(
  264. Adapter->AdapterHandle,
  265. NDIS_ERROR_CODE_RESOURCE_CONFLICT,
  266. 1,
  267. ERRLOG_MAP_IO_SPACE);
  268. break;
  269. }
  270. DBGPRINT(MP_INFO, ("CSRAddress="PTR_FORMAT"\n", Adapter->CSRAddress));
  271. //
  272. // Disable interrupts here which is as soon as possible
  273. //
  274. NICDisableInterrupt(Adapter);
  275. //
  276. // Register the interrupt
  277. //
  278. Status = NdisMRegisterInterrupt(
  279. &Adapter->Interrupt,
  280. Adapter->AdapterHandle,
  281. Adapter->InterruptLevel,
  282. Adapter->InterruptLevel,
  283. TRUE, // RequestISR
  284. TRUE, // SharedInterrupt
  285. NIC_INTERRUPT_MODE);
  286. if (Status != NDIS_STATUS_SUCCESS)
  287. {
  288. DBGPRINT(MP_ERROR, ("NdisMRegisterInterrupt failed\n"));
  289. NdisWriteErrorLogEntry(
  290. Adapter->AdapterHandle,
  291. NDIS_ERROR_CODE_INTERRUPT_CONNECT,
  292. 0);
  293. break;
  294. }
  295. MP_SET_FLAG(Adapter, fMP_ADAPTER_INTERRUPT_IN_USE);
  296. //
  297. // Test our adapter hardware
  298. //
  299. Status = NICSelfTest(Adapter);
  300. if (Status != NDIS_STATUS_SUCCESS)
  301. {
  302. break;
  303. }
  304. //
  305. // Init the hardware and set up everything
  306. //
  307. Status = NICInitializeAdapter(Adapter);
  308. if (Status != NDIS_STATUS_SUCCESS)
  309. {
  310. break;
  311. }
  312. #ifdef NDIS50_MINIPORT
  313. //
  314. // Register a shutdown handler for NDIS50 or earlier miniports
  315. // For NDIS51 miniports, set AdapterShutdownHandler as shown above
  316. //
  317. NdisMRegisterAdapterShutdownHandler(
  318. Adapter->AdapterHandle,
  319. (PVOID) Adapter,
  320. (ADAPTER_SHUTDOWN_HANDLER) MPShutdown);
  321. #endif
  322. //
  323. // Enable the interrupt
  324. //
  325. NICEnableInterrupt(Adapter);
  326. //
  327. // Minimize init-time
  328. //
  329. NdisMInitializeTimer(
  330. &Adapter->LinkDetectionTimer,
  331. Adapter->AdapterHandle,
  332. MpLinkDetectionDpc,
  333. Adapter);
  334. //
  335. // Set the link detection flag
  336. //
  337. MP_SET_FLAG(Adapter, fMP_ADAPTER_LINK_DETECTION);
  338. //
  339. // Increment the reference count so halt handler will wait
  340. //
  341. MP_INC_REF(Adapter);
  342. NdisMSetTimer(&Adapter->LinkDetectionTimer, NIC_LINK_DETECTION_DELAY);
  343. #if LBFO
  344. //
  345. // Add this adapter to the global miniport list
  346. //
  347. MpAddAdapterToList(Adapter);
  348. #endif
  349. } while (FALSE);
  350. if (Adapter && Status != NDIS_STATUS_SUCCESS)
  351. {
  352. //
  353. // Undo everything if it failed
  354. //
  355. MP_DEC_REF(Adapter);
  356. MpFreeAdapter(Adapter);
  357. }
  358. #if DBG
  359. NdisGetCurrentSystemTime(&TE);
  360. TD.QuadPart = TE.QuadPart - TS.QuadPart;
  361. TD.QuadPart /= 10000; // Convert to ms
  362. DBGPRINT(MP_WARN, ("Init time = %d ms\n", TD.LowPart));
  363. #endif
  364. DBGPRINT_S(Status, ("<==== MPInitialize, Status=%x\n", Status));
  365. //
  366. // Ndis doesn't check OpenErrorStatus.
  367. //
  368. *OpenErrorStatus = Status;
  369. return Status;
  370. }
  371. BOOLEAN MPCheckForHang(
  372. IN NDIS_HANDLE MiniportAdapterContext
  373. )
  374. /*++
  375. Routine Description:
  376. MiniportCheckForHang handler
  377. Arguments:
  378. MiniportAdapterContext Pointer to our adapter
  379. Return Value:
  380. TRUE This NIC needs a reset
  381. FALSE Everything is fine
  382. Note:
  383. CheckForHang handler is called in the context of a timer DPC.
  384. take advantage of this fact when acquiring/releasing spinlocks
  385. --*/
  386. {
  387. PMP_ADAPTER Adapter = (PMP_ADAPTER) MiniportAdapterContext;
  388. NDIS_MEDIA_STATE CurrMediaState;
  389. NDIS_STATUS Status;
  390. PMP_TCB pMpTcb;
  391. //
  392. // Just skip this part if the adapter is doing link detection
  393. //
  394. if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_LINK_DETECTION))
  395. {
  396. return(FALSE);
  397. }
  398. //
  399. // any nonrecoverable hardware error?
  400. //
  401. if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_NON_RECOVER_ERROR))
  402. {
  403. DBGPRINT(MP_WARN, ("Non recoverable error - remove\n"));
  404. return (TRUE);
  405. }
  406. //
  407. // hardware failure?
  408. //
  409. if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_HARDWARE_ERROR))
  410. {
  411. DBGPRINT(MP_WARN, ("hardware error - reset\n"));
  412. return(TRUE);
  413. }
  414. //
  415. // Is send stuck?
  416. //
  417. NdisDprAcquireSpinLock(&Adapter->SendLock);
  418. if (Adapter->nBusySend > 0)
  419. {
  420. pMpTcb = Adapter->CurrSendHead;
  421. pMpTcb->Count++;
  422. if (pMpTcb->Count > NIC_SEND_HANG_THRESHOLD)
  423. {
  424. NdisDprReleaseSpinLock(&Adapter->SendLock);
  425. DBGPRINT(MP_WARN, ("Send stuck - reset\n"));
  426. return(TRUE);
  427. }
  428. }
  429. NdisDprReleaseSpinLock(&Adapter->SendLock);
  430. NdisDprAcquireSpinLock(&Adapter->RcvLock);
  431. //
  432. // Update the RFD shrink count
  433. //
  434. if (Adapter->CurrNumRfd > Adapter->NumRfd)
  435. {
  436. Adapter->RfdShrinkCount++;
  437. }
  438. NdisDprReleaseSpinLock(&Adapter->RcvLock);
  439. NdisDprAcquireSpinLock(&Adapter->Lock);
  440. CurrMediaState = NICGetMediaState(Adapter);
  441. if (CurrMediaState != Adapter->MediaState)
  442. {
  443. DBGPRINT(MP_WARN, ("Media state changed to %s\n",
  444. ((CurrMediaState == NdisMediaStateConnected)?
  445. "Connected": "Disconnected")));
  446. Adapter->MediaState = CurrMediaState;
  447. Status = (CurrMediaState == NdisMediaStateConnected) ?
  448. NDIS_STATUS_MEDIA_CONNECT : NDIS_STATUS_MEDIA_DISCONNECT;
  449. if (Status == NDIS_STATUS_MEDIA_CONNECT)
  450. {
  451. MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_NO_CABLE);
  452. }
  453. else
  454. {
  455. MP_SET_FLAG(Adapter, fMP_ADAPTER_NO_CABLE);
  456. }
  457. NdisDprReleaseSpinLock(&Adapter->Lock);
  458. // Indicate the media event
  459. NdisMIndicateStatus(Adapter->AdapterHandle, Status, (PVOID)0, 0);
  460. NdisMIndicateStatusComplete(Adapter->AdapterHandle);
  461. }
  462. else
  463. {
  464. NdisDprReleaseSpinLock(&Adapter->Lock);
  465. }
  466. return(FALSE);
  467. }
  468. VOID MPHalt(
  469. IN NDIS_HANDLE MiniportAdapterContext)
  470. /*++
  471. Routine Description:
  472. MiniportHalt handler
  473. Arguments:
  474. MiniportAdapterContext Pointer to our adapter
  475. Return Value:
  476. None
  477. --*/
  478. {
  479. LONG Count;
  480. PMP_ADAPTER Adapter = (PMP_ADAPTER) MiniportAdapterContext;
  481. MP_SET_FLAG(Adapter, fMP_ADAPTER_HALT_IN_PROGRESS);
  482. DBGPRINT(MP_TRACE, ("====> MPHalt\n"));
  483. //
  484. // Call Shutdown handler to disable interrupt and turn the hardware off
  485. // by issuing a full reset
  486. //
  487. MPShutdown(MiniportAdapterContext);
  488. //
  489. // Deregister interrupt as early as possible
  490. //
  491. if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_INTERRUPT_IN_USE))
  492. {
  493. NdisMDeregisterInterrupt(&Adapter->Interrupt);
  494. MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_INTERRUPT_IN_USE);
  495. }
  496. #if LBFO
  497. MpRemoveAdapterFromList(Adapter);
  498. //
  499. // For a regualr miniport, no send packets and OID requests should be outstanding
  500. // when Halt handler is called. But for a LBFO miniport in secondary mode,
  501. // some packets from primary miniport may be still around
  502. //
  503. NdisAcquireSpinLock(&Adapter->SendLock);
  504. //
  505. // Free the packets on SendWaitList
  506. //
  507. MpFreeQueuedSendPackets(Adapter);
  508. //
  509. // Free the packets being actively sent & stopped
  510. //
  511. MpFreeBusySendPackets(Adapter);
  512. NdisReleaseSpinLock(&Adapter->SendLock);
  513. #endif
  514. //
  515. // Decrement the ref count which was incremented in MPInitialize
  516. //
  517. Count = MP_DEC_REF(Adapter);
  518. //
  519. // Possible non-zero ref counts mean one or more of the following conditions:
  520. // 1) Pending async shared memory allocation;
  521. // 2) DPC's are not finished (e.g. link detection)
  522. //
  523. if (Count)
  524. {
  525. DBGPRINT(MP_WARN, ("RefCount=%d --- waiting!\n", MP_GET_REF(Adapter)));
  526. while (TRUE)
  527. {
  528. if (NdisWaitEvent(&Adapter->ExitEvent, 2000))
  529. {
  530. break;
  531. }
  532. DBGPRINT(MP_WARN, ("RefCount=%d --- rewaiting!\n", MP_GET_REF(Adapter)));
  533. }
  534. }
  535. NdisAcquireSpinLock(&Adapter->RcvLock);
  536. //
  537. // wait for all the received packets to return
  538. //
  539. MP_DEC_RCV_REF(Adapter);
  540. Count = MP_GET_RCV_REF(Adapter);
  541. NdisReleaseSpinLock(&Adapter->RcvLock);
  542. if (Count)
  543. {
  544. DBGPRINT(MP_WARN, ("RcvRefCount=%d --- waiting!\n", Count));
  545. while (TRUE)
  546. {
  547. if (NdisWaitEvent(&Adapter->AllPacketsReturnedEvent, 2000))
  548. {
  549. break;
  550. }
  551. DBGPRINT(MP_WARN, ("RcvRefCount=%d --- rewaiting!\n", MP_GET_RCV_REF(Adapter)));
  552. }
  553. }
  554. #ifdef NDIS50_MINIPORT
  555. //
  556. // Deregister shutdown handler as it's being halted
  557. //
  558. NdisMDeregisterAdapterShutdownHandler(Adapter->AdapterHandle);
  559. #endif
  560. //
  561. // Reset the PHY chip. We do this so that after a warm boot, the PHY will
  562. // be in a known state, with auto-negotiation enabled.
  563. //
  564. ResetPhy(Adapter);
  565. //
  566. // Free the entire adapter object, including the shared memory structures.
  567. //
  568. MpFreeAdapter(Adapter);
  569. DBGPRINT(MP_TRACE, ("<==== MPHalt\n"));
  570. }
  571. NDIS_STATUS MPReset(
  572. OUT PBOOLEAN AddressingReset,
  573. IN NDIS_HANDLE MiniportAdapterContext)
  574. /*++
  575. Routine Description:
  576. MiniportReset handler
  577. Arguments:
  578. AddressingReset To let NDIS know whether we need help from it with our reset
  579. MiniportAdapterContext Pointer to our adapter
  580. Return Value:
  581. NDIS_STATUS_SUCCESS
  582. NDIS_STATUS_PENDING
  583. NDIS_STATUS_RESET_IN_PROGRESS
  584. NDIS_STATUS_HARD_ERRORS
  585. Note:
  586. ResetHandler is called at DPC. take advantage of this fact when acquiring or releasing
  587. spinlocks
  588. --*/
  589. {
  590. NDIS_STATUS Status;
  591. PMP_ADAPTER Adapter = (PMP_ADAPTER) MiniportAdapterContext;
  592. DBGPRINT(MP_TRACE, ("====> MPReset\n"));
  593. *AddressingReset = TRUE;
  594. NdisDprAcquireSpinLock(&Adapter->Lock);
  595. NdisDprAcquireSpinLock(&Adapter->SendLock);
  596. NdisDprAcquireSpinLock(&Adapter->RcvLock);
  597. do
  598. {
  599. ASSERT(!MP_TEST_FLAG(Adapter, fMP_ADAPTER_HALT_IN_PROGRESS));
  600. //
  601. // Is this adapter already doing a reset?
  602. //
  603. if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_RESET_IN_PROGRESS))
  604. {
  605. Status = NDIS_STATUS_RESET_IN_PROGRESS;
  606. MP_EXIT;
  607. }
  608. MP_SET_FLAG(Adapter, fMP_ADAPTER_RESET_IN_PROGRESS);
  609. //
  610. // Is this adapter doing link detection?
  611. //
  612. if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_LINK_DETECTION))
  613. {
  614. DBGPRINT(MP_WARN, ("Reset is pended...\n"));
  615. Adapter->bResetPending = TRUE;
  616. Status = NDIS_STATUS_PENDING;
  617. MP_EXIT;
  618. }
  619. //
  620. // Is this adapter going to be removed
  621. //
  622. if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_NON_RECOVER_ERROR))
  623. {
  624. Status = NDIS_STATUS_HARD_ERRORS;
  625. if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_REMOVE_IN_PROGRESS))
  626. {
  627. MP_EXIT;
  628. }
  629. // This is an unrecoverable hardware failure.
  630. // We need to tell NDIS to remove this miniport
  631. MP_SET_FLAG(Adapter, fMP_ADAPTER_REMOVE_IN_PROGRESS);
  632. MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_RESET_IN_PROGRESS);
  633. NdisDprReleaseSpinLock(&Adapter->RcvLock);
  634. NdisDprReleaseSpinLock(&Adapter->SendLock);
  635. NdisDprReleaseSpinLock(&Adapter->Lock);
  636. NdisWriteErrorLogEntry(
  637. Adapter->AdapterHandle,
  638. NDIS_ERROR_CODE_HARDWARE_FAILURE,
  639. 1,
  640. ERRLOG_REMOVE_MINIPORT);
  641. NdisMRemoveMiniport(Adapter->AdapterHandle);
  642. DBGPRINT_S(Status, ("<==== MPReset, Status=%x\n", Status));
  643. return Status;
  644. }
  645. //
  646. // Disable the interrupt and issue a reset to the NIC
  647. //
  648. NICDisableInterrupt(Adapter);
  649. NICIssueSelectiveReset(Adapter);
  650. //
  651. // release all the locks and then acquire back the send lock
  652. // we are going to clean up the send queues
  653. // which may involve calling Ndis APIs
  654. // release all the locks before grabbing the send lock to
  655. // avoid deadlocks
  656. //
  657. NdisDprReleaseSpinLock(&Adapter->RcvLock);
  658. NdisDprReleaseSpinLock(&Adapter->SendLock);
  659. NdisDprReleaseSpinLock(&Adapter->Lock);
  660. NdisDprAcquireSpinLock(&Adapter->SendLock);
  661. //
  662. // This is a deserialized miniport, we need to free all the send packets
  663. // Free the packets on SendWaitList
  664. //
  665. MpFreeQueuedSendPackets(Adapter);
  666. //
  667. // Free the packets being actively sent & stopped
  668. //
  669. MpFreeBusySendPackets(Adapter);
  670. #if DBG
  671. if (MP_GET_REF(Adapter) > 1)
  672. {
  673. DBGPRINT(MP_WARN, ("RefCount=%d\n", MP_GET_REF(Adapter)));
  674. }
  675. #endif
  676. NdisZeroMemory(Adapter->MpTcbMem, Adapter->MpTcbMemSize);
  677. //
  678. // Re-initialize the send structures
  679. //
  680. NICInitSend(Adapter);
  681. NdisDprReleaseSpinLock(&Adapter->SendLock);
  682. //
  683. // get all the locks again in the right order
  684. //
  685. NdisDprAcquireSpinLock(&Adapter->Lock);
  686. NdisDprAcquireSpinLock(&Adapter->SendLock);
  687. NdisDprAcquireSpinLock(&Adapter->RcvLock);
  688. //
  689. // Reset the RFD list and re-start RU
  690. //
  691. NICResetRecv(Adapter);
  692. Status = NICStartRecv(Adapter);
  693. if (Status != NDIS_STATUS_SUCCESS)
  694. {
  695. // Are we having failures in a few consecutive resets?
  696. if (Adapter->HwErrCount < NIC_HARDWARE_ERROR_THRESHOLD)
  697. {
  698. // It's not over the threshold yet, let it to continue
  699. Adapter->HwErrCount++;
  700. }
  701. else
  702. {
  703. // This is an unrecoverable hardware failure.
  704. // We need to tell NDIS to remove this miniport
  705. MP_SET_FLAG(Adapter, fMP_ADAPTER_REMOVE_IN_PROGRESS);
  706. MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_RESET_IN_PROGRESS);
  707. NdisDprReleaseSpinLock(&Adapter->RcvLock);
  708. NdisDprReleaseSpinLock(&Adapter->SendLock);
  709. NdisDprReleaseSpinLock(&Adapter->Lock);
  710. NdisWriteErrorLogEntry(
  711. Adapter->AdapterHandle,
  712. NDIS_ERROR_CODE_HARDWARE_FAILURE,
  713. 1,
  714. ERRLOG_REMOVE_MINIPORT);
  715. NdisMRemoveMiniport(Adapter->AdapterHandle);
  716. DBGPRINT_S(Status, ("<==== MPReset, Status=%x\n", Status));
  717. return(Status);
  718. }
  719. break;
  720. }
  721. Adapter->HwErrCount = 0;
  722. MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_HARDWARE_ERROR);
  723. NICEnableInterrupt(Adapter);
  724. } while (FALSE);
  725. MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_RESET_IN_PROGRESS);
  726. exit:
  727. NdisDprReleaseSpinLock(&Adapter->RcvLock);
  728. NdisDprReleaseSpinLock(&Adapter->SendLock);
  729. NdisDprReleaseSpinLock(&Adapter->Lock);
  730. DBGPRINT_S(Status, ("<==== MPReset, Status=%x\n", Status));
  731. return(Status);
  732. }
  733. VOID MPReturnPacket(
  734. IN NDIS_HANDLE MiniportAdapterContext,
  735. IN PNDIS_PACKET Packet
  736. )
  737. /*++
  738. Routine Description:
  739. MiniportReturnPacket handler
  740. Arguments:
  741. MiniportAdapterContext Pointer to our adapter
  742. Packet Pointer to a packet being returned to the miniport
  743. Return Value:
  744. None
  745. Note:
  746. ReturnPacketHandler is called at DPC. take advantage of this fact when acquiring or releasing
  747. spinlocks
  748. --*/
  749. {
  750. PMP_ADAPTER Adapter = (PMP_ADAPTER)MiniportAdapterContext;
  751. PMP_RFD pMpRfd = MP_GET_PACKET_RFD(Packet);
  752. ULONG Count;
  753. DBGPRINT(MP_TRACE, ("====> MPReturnPacket\n"));
  754. ASSERT(pMpRfd);
  755. ASSERT(MP_TEST_FLAG(pMpRfd, fMP_RFD_RECV_PEND));
  756. MP_CLEAR_FLAG(pMpRfd, fMP_RFD_RECV_PEND);
  757. NdisDprAcquireSpinLock(&Adapter->RcvLock);
  758. RemoveEntryList((PLIST_ENTRY)pMpRfd);
  759. // Decrement the Power Mgmt Ref.
  760. Adapter->PoMgmt.OutstandingRecv --;
  761. //
  762. // If we have set power pending, then complete it
  763. //
  764. if (((Adapter->bSetPending == TRUE)
  765. && (Adapter->SetRequest.Oid == OID_PNP_SET_POWER))
  766. && (Adapter->PoMgmt.OutstandingRecv == 0))
  767. {
  768. MpSetPowerLowComplete(Adapter);
  769. }
  770. if (Adapter->RfdShrinkCount < NIC_RFD_SHRINK_THRESHOLD)
  771. {
  772. NICReturnRFD(Adapter, pMpRfd);
  773. }
  774. else
  775. {
  776. ASSERT(Adapter->CurrNumRfd > Adapter->NumRfd);
  777. Adapter->RfdShrinkCount = 0;
  778. NICFreeRfd(Adapter, pMpRfd);
  779. Adapter->CurrNumRfd--;
  780. DBGPRINT(MP_TRACE, ("Shrink... CurrNumRfd = %d\n", Adapter->CurrNumRfd));
  781. }
  782. //
  783. // note that we get the ref count here, but check
  784. // to see if it is zero and signal the event -after-
  785. // releasign the SpinLock. otherwise, we may let the Halthandler
  786. // continue while we are holding a lock.
  787. //
  788. MP_DEC_RCV_REF(Adapter);
  789. Count = MP_GET_RCV_REF(Adapter);
  790. NdisDprReleaseSpinLock(&Adapter->RcvLock);
  791. if (Count == 0)
  792. NdisSetEvent(&Adapter->AllPacketsReturnedEvent);
  793. DBGPRINT(MP_TRACE, ("<==== MPReturnPacket\n"));
  794. }
  795. VOID MPSendPackets(
  796. IN NDIS_HANDLE MiniportAdapterContext,
  797. IN PPNDIS_PACKET PacketArray,
  798. IN UINT NumberOfPackets)
  799. /*++
  800. Routine Description:
  801. MiniportSendPackets handler
  802. Arguments:
  803. MiniportAdapterContext Pointer to our adapter
  804. PacketArray Set of packets to send
  805. NumberOfPackets Self-explanatory
  806. Return Value:
  807. None
  808. --*/
  809. {
  810. PMP_ADAPTER Adapter;
  811. NDIS_STATUS Status;
  812. UINT PacketCount;
  813. #if LBFO
  814. PMP_ADAPTER ThisAdapter;
  815. #endif
  816. DBGPRINT(MP_TRACE, ("====> MPSendPackets\n"));
  817. Adapter = (PMP_ADAPTER)MiniportAdapterContext;
  818. #if LBFO
  819. NdisAcquireSpinLock(&Adapter->LockLBFO);
  820. // Any secondary adapters?
  821. if (Adapter->NumSecondary)
  822. {
  823. // In this sample driver, we do very simple load balancing ...
  824. // Walk through the secondary miniport list, send the packets on a secondary
  825. // miniport if it's ready
  826. // If none of the secondary miniports is ready, we'll use the primary miniport
  827. ThisAdapter = Adapter->NextSecondary;
  828. while (ThisAdapter)
  829. {
  830. if (MP_IS_NOT_READY(ThisAdapter))
  831. {
  832. ThisAdapter = ThisAdapter->NextSecondary;
  833. continue;
  834. }
  835. //
  836. // Found a good secondary miniport to send packets on
  837. // Need to put a ref on this adapter so it won't go away
  838. //
  839. MP_LBFO_INC_REF(ThisAdapter);
  840. NdisReleaseSpinLock(&Adapter->LockLBFO);
  841. NdisAcquireSpinLock(&ThisAdapter->SendLock);
  842. //
  843. // Send these packets
  844. //
  845. for (PacketCount=0;PacketCount < NumberOfPackets; PacketCount++)
  846. {
  847. MpSendPacket(ThisAdapter, PacketArray[PacketCount], FALSE);
  848. }
  849. NdisReleaseSpinLock(&ThisAdapter->SendLock);
  850. //
  851. // Done with this adapter for now, deref it
  852. //
  853. MP_LBFO_DEC_REF(ThisAdapter);
  854. //
  855. // Sent all the packets on a secondary miniport, return
  856. //
  857. return;
  858. }
  859. }
  860. NdisReleaseSpinLock(&Adapter->LockLBFO);
  861. #endif
  862. NdisAcquireSpinLock(&Adapter->SendLock);
  863. // Is this adapter ready for sending?
  864. if (MP_IS_NOT_READY(Adapter))
  865. {
  866. //
  867. // there is link
  868. //
  869. if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_LINK_DETECTION))
  870. {
  871. for (PacketCount = 0; PacketCount < NumberOfPackets; PacketCount++)
  872. {
  873. InsertTailQueue(&Adapter->SendWaitQueue,
  874. MP_GET_PACKET_MR(PacketArray[PacketCount]));
  875. Adapter->nWaitSend++;
  876. DBGPRINT(MP_WARN, ("MpSendPackets: link detection - queue packet "PTR_FORMAT"\n",
  877. PacketArray[PacketCount]));
  878. }
  879. NdisReleaseSpinLock(&Adapter->SendLock);
  880. return;
  881. }
  882. //
  883. // Adapter is not ready and there is not link
  884. //
  885. Status = MP_GET_STATUS_FROM_FLAGS(Adapter);
  886. NdisReleaseSpinLock(&Adapter->SendLock);
  887. for (PacketCount = 0; PacketCount < NumberOfPackets; PacketCount++)
  888. {
  889. NdisMSendComplete(
  890. MP_GET_ADAPTER_HANDLE(Adapter),
  891. PacketArray[PacketCount],
  892. Status);
  893. }
  894. return;
  895. }
  896. //
  897. // Adapter is ready, send these packets
  898. //
  899. for (PacketCount = 0; PacketCount < NumberOfPackets; PacketCount++)
  900. {
  901. //
  902. // queue is not empty or tcb is not available
  903. //
  904. if (!IsQueueEmpty(&Adapter->SendWaitQueue) ||
  905. !MP_TCB_RESOURCES_AVAIABLE(Adapter))
  906. {
  907. InsertTailQueue(&Adapter->SendWaitQueue, MP_GET_PACKET_MR(PacketArray[PacketCount]));
  908. Adapter->nWaitSend++;
  909. }
  910. else
  911. {
  912. MpSendPacket(Adapter, PacketArray[PacketCount], FALSE);
  913. }
  914. }
  915. NdisReleaseSpinLock(&Adapter->SendLock);
  916. DBGPRINT(MP_TRACE, ("<==== MPSendPackets\n"));
  917. return;
  918. }
  919. VOID MPShutdown(
  920. IN NDIS_HANDLE MiniportAdapterContext)
  921. /*++
  922. Routine Description:
  923. MiniportShutdown handler
  924. Arguments:
  925. MiniportAdapterContext Pointer to our adapter
  926. Return Value:
  927. None
  928. --*/
  929. {
  930. PMP_ADAPTER Adapter = (PMP_ADAPTER)MiniportAdapterContext;
  931. DBGPRINT(MP_TRACE, ("====> MPShutdown\n"));
  932. //
  933. // Disable interrupt and issue a full reset
  934. //
  935. NICDisableInterrupt(Adapter);
  936. NICIssueFullReset(Adapter);
  937. DBGPRINT(MP_TRACE, ("<==== MPShutdown\n"));
  938. }
  939. VOID MPAllocateComplete(
  940. IN NDIS_HANDLE MiniportAdapterContext,
  941. IN PVOID VirtualAddress,
  942. IN PNDIS_PHYSICAL_ADDRESS PhysicalAddress,
  943. IN ULONG Length,
  944. IN PVOID Context)
  945. /*++
  946. Routine Description:
  947. MiniportAllocateComplete handler
  948. This handler is needed because we make calls to NdisMAllocateSharedMemoryAsync
  949. Arguments:
  950. MiniportAdapterContext Pointer to our adapter
  951. VirtualAddress Pointer to the allocated memory block
  952. PhysicalAddress Physical address of the memory block
  953. Length Length of the memory block
  954. Context Context in NdisMAllocateSharedMemoryAsync
  955. Return Value:
  956. None
  957. --*/
  958. {
  959. ULONG ErrorValue;
  960. PMP_ADAPTER Adapter = (PMP_ADAPTER)MiniportAdapterContext;
  961. PMP_RFD pMpRfd = (PMP_RFD)Context;
  962. #if !DBG
  963. UNREFERENCED_PARAMETER(Length);
  964. #endif
  965. DBGPRINT(MP_TRACE, ("==== MPAllocateComplete\n"));
  966. ASSERT(pMpRfd);
  967. ASSERT(MP_TEST_FLAG(pMpRfd, fMP_RFD_ALLOC_PEND));
  968. MP_CLEAR_FLAG(pMpRfd, fMP_RFD_ALLOC_PEND);
  969. NdisAcquireSpinLock(&Adapter->RcvLock);
  970. //
  971. // Is allocation successful?
  972. //
  973. if (VirtualAddress)
  974. {
  975. ASSERT(Length == Adapter->HwRfdSize);
  976. pMpRfd->OriginalHwRfd = (PHW_RFD)VirtualAddress;
  977. pMpRfd->OriginalHwRfdPa = *PhysicalAddress;
  978. //
  979. // First get a HwRfd at 8 byte boundary from OriginalHwRfd
  980. //
  981. pMpRfd->HwRfd = (PHW_RFD)DATA_ALIGN(pMpRfd->OriginalHwRfd);
  982. //
  983. // Then shift HwRfd so that the data(after ethernet header) is at 8 bytes boundary
  984. //
  985. pMpRfd->HwRfd = (PHW_RFD)((PUCHAR)pMpRfd->HwRfd + HWRFD_SHIFT_OFFSET);
  986. //
  987. // Update physical address as well
  988. //
  989. pMpRfd->HwRfdPa.QuadPart = pMpRfd->OriginalHwRfdPa.QuadPart + BYTES_SHIFT(pMpRfd->HwRfd, pMpRfd->OriginalHwRfd);
  990. ErrorValue = NICAllocRfd(Adapter, pMpRfd);
  991. if (ErrorValue == 0)
  992. {
  993. // Add this RFD to the RecvList
  994. Adapter->CurrNumRfd++;
  995. NICReturnRFD(Adapter, pMpRfd);
  996. ASSERT(Adapter->CurrNumRfd <= Adapter->MaxNumRfd);
  997. DBGPRINT(MP_TRACE, ("CurrNumRfd=%d\n", Adapter->CurrNumRfd));
  998. }
  999. else
  1000. {
  1001. NdisFreeToNPagedLookasideList(&Adapter->RecvLookaside, pMpRfd);
  1002. }
  1003. }
  1004. else
  1005. {
  1006. NdisFreeToNPagedLookasideList(&Adapter->RecvLookaside, pMpRfd);
  1007. }
  1008. Adapter->bAllocNewRfd = FALSE;
  1009. MP_DEC_REF(Adapter);
  1010. if (MP_GET_REF(Adapter) == 0)
  1011. {
  1012. NdisSetEvent(&Adapter->ExitEvent);
  1013. }
  1014. NdisReleaseSpinLock(&Adapter->RcvLock);
  1015. }
  1016. VOID MPIsr(
  1017. OUT PBOOLEAN InterruptRecognized,
  1018. OUT PBOOLEAN QueueMiniportHandleInterrupt,
  1019. IN NDIS_HANDLE MiniportAdapterContext)
  1020. /*++
  1021. Routine Description:
  1022. MiniportIsr handler
  1023. Arguments:
  1024. InterruptRecognized TRUE on return if the interrupt comes from this NIC
  1025. QueueMiniportHandleInterrupt TRUE on return if MiniportHandleInterrupt should be called
  1026. MiniportAdapterContext Pointer to our adapter
  1027. Return Value:
  1028. None
  1029. --*/
  1030. {
  1031. PMP_ADAPTER Adapter = (PMP_ADAPTER)MiniportAdapterContext;
  1032. USHORT IntStatus;
  1033. DBGPRINT(MP_LOUD, ("====> MPIsr\n"));
  1034. do
  1035. {
  1036. //
  1037. // If the adapter is in low power state, then it should not
  1038. // recognize any interrupt
  1039. //
  1040. if (Adapter->CurrentPowerState > NdisDeviceStateD0)
  1041. {
  1042. *InterruptRecognized = FALSE;
  1043. *QueueMiniportHandleInterrupt = FALSE;
  1044. break;
  1045. }
  1046. //
  1047. // We process the interrupt if it's not disabled and it's active
  1048. //
  1049. if (!NIC_INTERRUPT_DISABLED(Adapter) && NIC_INTERRUPT_ACTIVE(Adapter))
  1050. {
  1051. *InterruptRecognized = TRUE;
  1052. *QueueMiniportHandleInterrupt = TRUE;
  1053. //
  1054. // Disable the interrupt (will be re-enabled in MPHandleInterrupt
  1055. //
  1056. NICDisableInterrupt(Adapter);
  1057. //
  1058. // Acknowledge the interrupt(s) and get the interrupt status
  1059. //
  1060. NIC_ACK_INTERRUPT(Adapter, IntStatus);
  1061. }
  1062. else
  1063. {
  1064. *InterruptRecognized = FALSE;
  1065. *QueueMiniportHandleInterrupt = FALSE;
  1066. }
  1067. }
  1068. while (FALSE);
  1069. DBGPRINT(MP_LOUD, ("<==== MPIsr\n"));
  1070. }
  1071. VOID MPHandleInterrupt(
  1072. IN NDIS_HANDLE MiniportAdapterContext
  1073. )
  1074. /*++
  1075. Routine Description:
  1076. MiniportHandleInterrupt handler
  1077. Arguments:
  1078. MiniportAdapterContext Pointer to our adapter
  1079. Return Value:
  1080. None
  1081. --*/
  1082. {
  1083. PMP_ADAPTER Adapter = (PMP_ADAPTER)MiniportAdapterContext;
  1084. NdisDprAcquireSpinLock(&Adapter->RcvLock);
  1085. MpHandleRecvInterrupt(Adapter);
  1086. NdisDprReleaseSpinLock(&Adapter->RcvLock);
  1087. //
  1088. // Handle send interrupt
  1089. //
  1090. NdisDprAcquireSpinLock(&Adapter->SendLock);
  1091. MpHandleSendInterrupt(Adapter);
  1092. NdisDprReleaseSpinLock(&Adapter->SendLock);
  1093. //
  1094. // Start the receive unit if it had stopped
  1095. //
  1096. NdisDprAcquireSpinLock(&Adapter->RcvLock);
  1097. NICStartRecv(Adapter);
  1098. NdisDprReleaseSpinLock(&Adapter->RcvLock);
  1099. //
  1100. // Re-enable the interrupt (disabled in MPIsr)
  1101. //
  1102. NdisMSynchronizeWithInterrupt(
  1103. &Adapter->Interrupt,
  1104. (PVOID)NICEnableInterrupt,
  1105. Adapter);
  1106. }
  1107. #ifdef NDIS51_MINIPORT
  1108. VOID MPCancelSendPackets(
  1109. IN NDIS_HANDLE MiniportAdapterContext,
  1110. IN PVOID CancelId)
  1111. /*++
  1112. Routine Description:
  1113. MiniportCancelSendpackets handler - NDIS51 and later
  1114. Arguments:
  1115. MiniportAdapterContext Pointer to our adapter
  1116. CancelId All the packets with this Id should be cancelled
  1117. Return Value:
  1118. None
  1119. --*/
  1120. {
  1121. PQUEUE_ENTRY pEntry, pPrevEntry, pNextEntry;
  1122. PNDIS_PACKET Packet;
  1123. PVOID PacketId;
  1124. PMP_ADAPTER Adapter = (PMP_ADAPTER)MiniportAdapterContext;
  1125. DBGPRINT(MP_TRACE, ("====> MPCancelSendPackets\n"));
  1126. pPrevEntry = NULL;
  1127. NdisAcquireSpinLock(&Adapter->SendLock);
  1128. //
  1129. // Walk through the send wait queue and complete the sends with matching Id
  1130. //
  1131. pEntry = Adapter->SendWaitQueue.Head;
  1132. while (pEntry)
  1133. {
  1134. Packet = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
  1135. PacketId = NdisGetPacketCancelId(Packet);
  1136. if (PacketId == CancelId)
  1137. {
  1138. Adapter->nWaitSend--;
  1139. //
  1140. // This packet has the right CancelId
  1141. //
  1142. pNextEntry = pEntry->Next;
  1143. if (pPrevEntry == NULL)
  1144. {
  1145. Adapter->SendWaitQueue.Head = pNextEntry;
  1146. if (pNextEntry == NULL)
  1147. {
  1148. Adapter->SendWaitQueue.Tail = NULL;
  1149. }
  1150. }
  1151. else
  1152. {
  1153. pPrevEntry->Next = pNextEntry;
  1154. if (pNextEntry == NULL)
  1155. {
  1156. Adapter->SendWaitQueue.Tail = pPrevEntry;
  1157. }
  1158. }
  1159. pEntry = pEntry->Next;
  1160. // Put this packet on SendCancelQueue
  1161. InsertTailQueue(&Adapter->SendCancelQueue, MP_GET_PACKET_MR(Packet));
  1162. Adapter->nCancelSend++;
  1163. }
  1164. else
  1165. {
  1166. // This packet doesn't have the right CancelId
  1167. pPrevEntry = pEntry;
  1168. pEntry = pEntry->Next;
  1169. }
  1170. }
  1171. //
  1172. // Get the packets from SendCancelQueue and complete them if any
  1173. //
  1174. while (!IsQueueEmpty(&Adapter->SendCancelQueue))
  1175. {
  1176. pEntry = RemoveHeadQueue(&Adapter->SendCancelQueue);
  1177. NdisReleaseSpinLock(&Adapter->SendLock);
  1178. ASSERT(pEntry);
  1179. Packet = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
  1180. NdisMSendComplete(
  1181. MP_GET_ADAPTER_HANDLE(Adapter),
  1182. Packet,
  1183. NDIS_STATUS_REQUEST_ABORTED);
  1184. NdisAcquireSpinLock(&Adapter->SendLock);
  1185. }
  1186. NdisReleaseSpinLock(&Adapter->SendLock);
  1187. DBGPRINT(MP_TRACE, ("<==== MPCancelSendPackets\n"));
  1188. }
  1189. VOID MPPnPEventNotify(
  1190. IN NDIS_HANDLE MiniportAdapterContext,
  1191. IN NDIS_DEVICE_PNP_EVENT PnPEvent,
  1192. IN PVOID InformationBuffer,
  1193. IN ULONG InformationBufferLength
  1194. )
  1195. /*++
  1196. Routine Description:
  1197. MiniportPnPEventNotify handler - NDIS51 and later
  1198. Arguments:
  1199. MiniportAdapterContext Pointer to our adapter
  1200. PnPEvent Self-explanatory
  1201. InformationBuffer Self-explanatory
  1202. InformationBufferLength Self-explanatory
  1203. Return Value:
  1204. None
  1205. --*/
  1206. {
  1207. PMP_ADAPTER Adapter = (PMP_ADAPTER)MiniportAdapterContext;
  1208. //
  1209. // Turn off the warings.
  1210. //
  1211. UNREFERENCED_PARAMETER(InformationBuffer);
  1212. UNREFERENCED_PARAMETER(InformationBufferLength);
  1213. UNREFERENCED_PARAMETER(Adapter);
  1214. DBGPRINT(MP_TRACE, ("====> MPPnPEventNotify\n"));
  1215. switch (PnPEvent)
  1216. {
  1217. case NdisDevicePnPEventQueryRemoved:
  1218. DBGPRINT(MP_WARN, ("MPPnPEventNotify: NdisDevicePnPEventQueryRemoved\n"));
  1219. break;
  1220. case NdisDevicePnPEventRemoved:
  1221. DBGPRINT(MP_WARN, ("MPPnPEventNotify: NdisDevicePnPEventRemoved\n"));
  1222. break;
  1223. case NdisDevicePnPEventSurpriseRemoved:
  1224. DBGPRINT(MP_WARN, ("MPPnPEventNotify: NdisDevicePnPEventSurpriseRemoved\n"));
  1225. break;
  1226. case NdisDevicePnPEventQueryStopped:
  1227. DBGPRINT(MP_WARN, ("MPPnPEventNotify: NdisDevicePnPEventQueryStopped\n"));
  1228. break;
  1229. case NdisDevicePnPEventStopped:
  1230. DBGPRINT(MP_WARN, ("MPPnPEventNotify: NdisDevicePnPEventStopped\n"));
  1231. break;
  1232. case NdisDevicePnPEventPowerProfileChanged:
  1233. DBGPRINT(MP_WARN, ("MPPnPEventNotify: NdisDevicePnPEventPowerProfileChanged\n"));
  1234. break;
  1235. default:
  1236. DBGPRINT(MP_ERROR, ("MPPnPEventNotify: unknown PnP event %x \n", PnPEvent));
  1237. break;
  1238. }
  1239. DBGPRINT(MP_TRACE, ("<==== MPPnPEventNotify\n"));
  1240. }
  1241. #endif
  1242. #if LBFO
  1243. VOID MPUnload(
  1244. IN PDRIVER_OBJECT DriverObject
  1245. )
  1246. /*++
  1247. Routine Description:
  1248. The Unload handler
  1249. This handler is registered through NdisMRegisterUnloadHandler
  1250. Arguments:
  1251. DriverObject Not used
  1252. Return Value:
  1253. None
  1254. --*/
  1255. {
  1256. ASSERT(IsListEmpty(&g_AdapterList));
  1257. NdisFreeSpinLock(&g_Lock);
  1258. }
  1259. VOID MpAddAdapterToList(
  1260. IN PMP_ADAPTER Adapter
  1261. )
  1262. /*++
  1263. Routine Description:
  1264. This function adds a new adapter to the global adapter list
  1265. 1. Not part of bundle (primary) if BundleId string is empty
  1266. 2. Primary if no adapter with the same BundleId
  1267. 3. Secondary if there is already one adapter with the same BundleId
  1268. Arguments:
  1269. MiniportAdapterContext Pointer to our adapter
  1270. Return Value:
  1271. None
  1272. --*/
  1273. {
  1274. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1275. PMP_ADAPTER ThisAdapter;
  1276. PMP_ADAPTER PrimaryAdapter = NULL;
  1277. DBGPRINT(MP_WARN, ("Add adapter "PTR_FORMAT" ...", Adapter));
  1278. //
  1279. // Set the primary adapter to itself by default
  1280. //
  1281. Adapter->PrimaryAdapter = Adapter;
  1282. //
  1283. // Is this adapter part of a bundle? Just insert it in the list if not
  1284. //
  1285. if (Adapter->BundleId.Length == 0)
  1286. {
  1287. DBGPRINT_RAW(MP_WARN, ("not in a bundle\n"));
  1288. NdisInterlockedInsertTailList(&g_AdapterList, &Adapter->List, &g_Lock);
  1289. return;
  1290. }
  1291. NdisAllocateSpinLock(&Adapter->LockLBFO);
  1292. do
  1293. {
  1294. NdisAcquireSpinLock(&g_Lock);
  1295. //
  1296. // Search for the primary adapter if it exists.
  1297. // Skip searching if the list is empty
  1298. //
  1299. if (IsListEmpty(&g_AdapterList))
  1300. {
  1301. DBGPRINT_RAW(MP_WARN, ("Primary\n"));
  1302. break;
  1303. }
  1304. ThisAdapter = (PMP_ADAPTER)GetListHeadEntry(&g_AdapterList);
  1305. while ((PLIST_ENTRY)ThisAdapter != &g_AdapterList)
  1306. {
  1307. if (!MP_TEST_FLAG(ThisAdapter, fMP_ADAPTER_SECONDARY) &&
  1308. ThisAdapter->BundleId.Length == Adapter->BundleId.Length)
  1309. {
  1310. if (NdisEqualMemory(ThisAdapter->BundleId.Buffer,
  1311. Adapter->BundleId.Buffer, Adapter->BundleId.Length))
  1312. {
  1313. PrimaryAdapter = ThisAdapter;
  1314. break;
  1315. }
  1316. }
  1317. ThisAdapter = (PMP_ADAPTER)GetListFLink((PLIST_ENTRY)ThisAdapter);
  1318. }
  1319. //
  1320. // Does a primary adapter exist? If not, this adapter will be primary.
  1321. //
  1322. if (PrimaryAdapter == NULL)
  1323. {
  1324. DBGPRINT_RAW(MP_WARN, ("Primary\n"));
  1325. break;
  1326. }
  1327. //
  1328. // Found the primary adapter, so set this adapter as secondary
  1329. // Put a ref on the primary adapter so it won't go away while
  1330. // we are calling NdisMSetMiniportSecondary.
  1331. //
  1332. MP_LBFO_INC_REF(PrimaryAdapter);
  1333. NdisReleaseSpinLock(&g_Lock);
  1334. //
  1335. // We found the primary adapter with the same BundleIdentifier string
  1336. // Set this adapter as scondary
  1337. //
  1338. Status = NdisMSetMiniportSecondary(
  1339. Adapter->AdapterHandle,
  1340. PrimaryAdapter->AdapterHandle);
  1341. ASSERT(Status == NDIS_STATUS_SUCCESS);
  1342. NdisAcquireSpinLock(&g_Lock);
  1343. if (Status == NDIS_STATUS_SUCCESS)
  1344. {
  1345. MP_SET_FLAG(Adapter, fMP_ADAPTER_SECONDARY);
  1346. Adapter->PrimaryAdapter = PrimaryAdapter;
  1347. DBGPRINT_RAW(MP_WARN, ("Secondary, use primary adapter "PTR_FORMAT"\n",
  1348. PrimaryAdapter));
  1349. //
  1350. // Add this to the end of primary's secondary miniport list
  1351. //
  1352. NdisAcquireSpinLock(&PrimaryAdapter->LockLBFO);
  1353. PrimaryAdapter->NumSecondary++;
  1354. ThisAdapter = PrimaryAdapter;
  1355. while (ThisAdapter->NextSecondary)
  1356. {
  1357. ThisAdapter = ThisAdapter->NextSecondary;
  1358. }
  1359. ThisAdapter->NextSecondary = Adapter;
  1360. NdisReleaseSpinLock(&PrimaryAdapter->LockLBFO);
  1361. }
  1362. MP_LBFO_DEC_REF(PrimaryAdapter);
  1363. } while (FALSE);
  1364. InsertTailList(&g_AdapterList, &Adapter->List);
  1365. NdisReleaseSpinLock(&g_Lock);
  1366. return;
  1367. }
  1368. VOID MpRemoveAdapterFromList(
  1369. IN PMP_ADAPTER Adapter
  1370. )
  1371. /*++
  1372. Routine Description:
  1373. This function removes the adapter from the global adapter list
  1374. 1. Not part of bundle (primary) if BundleId string is empty
  1375. 2. Secondary - Remove it from primary's secondary adapter list
  1376. 3. Primary - If a secondary adapter exists, promote the secondary
  1377. Arguments:
  1378. MiniportAdapterContext Pointer to our adapter
  1379. Return Value:
  1380. None
  1381. --*/
  1382. {
  1383. PMP_ADAPTER PrimaryAdapter;
  1384. PMP_ADAPTER ThisAdapter;
  1385. DBGPRINT(MP_WARN, ("Remove adapter "PTR_FORMAT" ...", Adapter));
  1386. ASSERT(!IsListEmpty(&g_AdapterList));
  1387. //
  1388. // Is this adapter part of a bundle? Just remove it if not
  1389. //
  1390. if (Adapter->BundleId.Length == 0)
  1391. {
  1392. DBGPRINT_RAW(MP_WARN, ("not in a bundle\n"));
  1393. NdisAcquireSpinLock(&g_Lock);
  1394. RemoveEntryList(&Adapter->List);
  1395. NdisReleaseSpinLock(&g_Lock);
  1396. return;
  1397. }
  1398. NdisAcquireSpinLock(&g_Lock);
  1399. //
  1400. // Check to see if it's secondary adapter, need to remove it from primary
  1401. // adapter's secondary list so the primary adapter won't pass more packets
  1402. // to this adapter
  1403. //
  1404. if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_SECONDARY))
  1405. {
  1406. //
  1407. // This is a secondary adapter
  1408. //
  1409. PrimaryAdapter = Adapter->PrimaryAdapter;
  1410. DBGPRINT_RAW(MP_WARN, ("Secondary, primary adapter = "PTR_FORMAT"\n",
  1411. PrimaryAdapter));
  1412. NdisAcquireSpinLock(&PrimaryAdapter->LockLBFO);
  1413. //
  1414. // Remove it from the primary's secondary miniport list
  1415. //
  1416. ThisAdapter = PrimaryAdapter;
  1417. while (ThisAdapter)
  1418. {
  1419. if (ThisAdapter->NextSecondary == Adapter)
  1420. {
  1421. ThisAdapter->NextSecondary = Adapter->NextSecondary;
  1422. PrimaryAdapter->NumSecondary--;
  1423. break;
  1424. }
  1425. ThisAdapter = ThisAdapter->NextSecondary;
  1426. }
  1427. NdisReleaseSpinLock(&PrimaryAdapter->LockLBFO);
  1428. //
  1429. // Remove this adapter from the list
  1430. //
  1431. RemoveEntryList(&Adapter->List);
  1432. }
  1433. //
  1434. // Need to wait for the ref count to be zero ...
  1435. // For a primary adapter, non-zero ref count means one or more adapters are
  1436. // trying to become this adapter's secondary adapters
  1437. // For a secondary adapter, non-zero ref count means the primary is actively
  1438. // sending some packets on this adapter
  1439. //
  1440. while (TRUE)
  1441. {
  1442. if (MP_LBFO_GET_REF(Adapter) == 0)
  1443. {
  1444. break;
  1445. }
  1446. NdisReleaseSpinLock(&g_Lock);
  1447. NdisMSleep(100);
  1448. NdisAcquireSpinLock(&g_Lock);
  1449. }
  1450. if (!MP_TEST_FLAG(Adapter, fMP_ADAPTER_SECONDARY))
  1451. {
  1452. //
  1453. // Remove this adapter from the list
  1454. //
  1455. RemoveEntryList(&Adapter->List);
  1456. DBGPRINT_RAW(MP_WARN, ("Primary\n"));
  1457. if (Adapter->NumSecondary > 0)
  1458. {
  1459. //
  1460. // Promote a secondary adapter
  1461. //
  1462. MpPromoteSecondary(Adapter);
  1463. }
  1464. }
  1465. NdisReleaseSpinLock(&g_Lock);
  1466. NdisFreeSpinLock(&Adapter->LockLBFO);
  1467. }
  1468. VOID MpPromoteSecondary(
  1469. IN PMP_ADAPTER Adapter)
  1470. /*++
  1471. Routine Description:
  1472. This function promotes a secondary miniport and sets up this new primary's
  1473. secondary adapter list
  1474. Arguments:
  1475. MiniportAdapterContext Pointer to our adapter
  1476. Return Value:
  1477. None
  1478. --*/
  1479. {
  1480. NDIS_STATUS Status;
  1481. PMP_ADAPTER ThisAdapter;
  1482. PMP_ADAPTER PromoteAdapter = NULL;
  1483. //
  1484. // Promote a secondary adapter
  1485. //
  1486. ThisAdapter = Adapter->NextSecondary;
  1487. while (ThisAdapter)
  1488. {
  1489. DBGPRINT(MP_WARN, ("Promote adapter "PTR_FORMAT"\n", ThisAdapter));
  1490. Status = NdisMPromoteMiniport(ThisAdapter->AdapterHandle);
  1491. ASSERT(Status == NDIS_STATUS_SUCCESS);
  1492. if (Status == NDIS_STATUS_SUCCESS)
  1493. {
  1494. PromoteAdapter = ThisAdapter;
  1495. MP_CLEAR_FLAG(PromoteAdapter, fMP_ADAPTER_SECONDARY);
  1496. break;
  1497. }
  1498. ThisAdapter = ThisAdapter->NextSecondary;
  1499. }
  1500. if (PromoteAdapter)
  1501. {
  1502. //
  1503. // Remove the new primary from old primary's secondary miniport list
  1504. //
  1505. NdisAcquireSpinLock(&Adapter->LockLBFO);
  1506. ThisAdapter = Adapter;
  1507. while (ThisAdapter)
  1508. {
  1509. if (ThisAdapter->NextSecondary == PromoteAdapter)
  1510. {
  1511. ThisAdapter->NextSecondary = PromoteAdapter->NextSecondary;
  1512. Adapter->NumSecondary--;
  1513. break;
  1514. }
  1515. ThisAdapter = ThisAdapter->NextSecondary;
  1516. }
  1517. NdisReleaseSpinLock(&Adapter->LockLBFO);
  1518. //
  1519. // Set all adapters in the bundle to use the new primary
  1520. //
  1521. PromoteAdapter->PrimaryAdapter = PromoteAdapter;
  1522. while (ThisAdapter)
  1523. {
  1524. ThisAdapter->PrimaryAdapter = PromoteAdapter;
  1525. ThisAdapter = ThisAdapter->NextSecondary;
  1526. }
  1527. //
  1528. // Set the new primary's secondary miniport list
  1529. //
  1530. NdisAcquireSpinLock(&PromoteAdapter->LockLBFO);
  1531. PromoteAdapter->NextSecondary = Adapter->NextSecondary;
  1532. PromoteAdapter->NumSecondary = Adapter->NumSecondary;
  1533. NdisReleaseSpinLock(&PromoteAdapter->LockLBFO);
  1534. }
  1535. else
  1536. {
  1537. //
  1538. // This shouldn't happen!
  1539. // Set each secondary's primary to point to itself
  1540. //
  1541. DBGPRINT(MP_ERROR, ("Failed to promote any seconday adapter\n"));
  1542. ASSERT(FALSE);
  1543. ThisAdapter = Adapter->NextSecondary;
  1544. while (ThisAdapter)
  1545. {
  1546. ThisAdapter->PrimaryAdapter = ThisAdapter;
  1547. ThisAdapter = ThisAdapter->NextSecondary;
  1548. }
  1549. }
  1550. }
  1551. #endif