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

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