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.

1569 lines
42 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. mp_nic.c
  5. Abstract:
  6. This module contains miniport send/receive routines
  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 'CINM'
  16. #endif
  17. __inline VOID MP_FREE_SEND_PACKET(
  18. IN PMP_ADAPTER Adapter,
  19. IN PMP_TCB pMpTcb
  20. )
  21. /*++
  22. Routine Description:
  23. Recycle a MP_TCB and complete the packet if necessary
  24. Assumption: Send spinlock has been acquired
  25. Arguments:
  26. Adapter Pointer to our adapter
  27. pMpTcb Pointer to MP_TCB
  28. Return Value:
  29. None
  30. --*/
  31. {
  32. PNDIS_PACKET Packet;
  33. PNDIS_BUFFER CurrBuffer;
  34. ASSERT(MP_TEST_FLAG(pMpTcb, fMP_TCB_IN_USE));
  35. Packet = pMpTcb->Packet;
  36. pMpTcb->Packet = NULL;
  37. pMpTcb->Count = 0;
  38. if (pMpTcb->MpTxBuf)
  39. {
  40. ASSERT(MP_TEST_FLAG(pMpTcb, fMP_TCB_USE_LOCAL_BUF));
  41. PushEntryList(&Adapter->SendBufList, &pMpTcb->MpTxBuf->SList);
  42. pMpTcb->MpTxBuf = NULL;
  43. }
  44. #ifndef NDIS51_MINIPORT
  45. else if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_MAP_REGISTER))
  46. {
  47. //
  48. // Complete physical mapping for each buffer in this packet
  49. //
  50. ASSERT(Packet);
  51. CurrBuffer = pMpTcb->FirstBuffer;
  52. while (CurrBuffer)
  53. {
  54. NdisMCompleteBufferPhysicalMapping(
  55. Adapter->AdapterHandle,
  56. CurrBuffer,
  57. Adapter->CurrMapRegHead);
  58. Adapter->CurrMapRegHead++;
  59. if (Adapter->CurrMapRegHead == (ULONG)Adapter->NumTbd)
  60. Adapter->CurrMapRegHead = 0;
  61. //
  62. // Get the next buffer
  63. //
  64. NdisGetNextBuffer(CurrBuffer, &CurrBuffer);
  65. }
  66. }
  67. #endif
  68. MP_CLEAR_FLAGS(pMpTcb);
  69. Adapter->CurrSendHead = Adapter->CurrSendHead->Next;
  70. Adapter->nBusySend--;
  71. ASSERT(Adapter->nBusySend >= 0);
  72. if (Packet)
  73. {
  74. NdisReleaseSpinLock(&Adapter->SendLock);
  75. DBGPRINT(MP_TRACE, ("Calling NdisMSendComplete, Pkt= "PTR_FORMAT"\n", Packet));
  76. NdisMSendComplete(
  77. MP_GET_ADAPTER_HANDLE(Adapter),
  78. Packet,
  79. NDIS_STATUS_SUCCESS);
  80. NdisAcquireSpinLock(&Adapter->SendLock);
  81. }
  82. }
  83. NDIS_STATUS MpSendPacket(
  84. IN PMP_ADAPTER Adapter,
  85. IN PNDIS_PACKET Packet,
  86. IN BOOLEAN bFromQueue
  87. )
  88. /*++
  89. Routine Description:
  90. Do the work to send a packet
  91. Assumption: Send spinlock has been acquired
  92. Arguments:
  93. Adapter Pointer to our adapter
  94. Packet The packet
  95. bFromQueue TRUE if it's taken from the send wait queue
  96. Return Value:
  97. NDIS_STATUS_SUCCESS
  98. NDIS_STATUS_PENDING Put into the send wait queue
  99. NDIS_STATUS_HARD_ERRORS
  100. --*/
  101. {
  102. NDIS_STATUS Status = NDIS_STATUS_PENDING;
  103. PMP_TCB pMpTcb = NULL;
  104. PMP_TXBUF pMpTxBuf = NULL;
  105. ULONG BytesCopied;
  106. // Mimiced frag list if map registers are used, on the local stack as it's not so big
  107. MP_FRAG_LIST FragList;
  108. // Pointer to either the scatter gather or the local mimiced frag list
  109. PMP_FRAG_LIST pFragList;
  110. DBGPRINT(MP_TRACE, ("--> MpSendPacket, Pkt= "PTR_FORMAT"\n", Packet));
  111. pMpTcb = Adapter->CurrSendTail;
  112. ASSERT(!MP_TEST_FLAG(pMpTcb, fMP_TCB_IN_USE));
  113. NdisQueryPacket(
  114. Packet,
  115. (PUINT)&pMpTcb->PhysBufCount,
  116. (PUINT)&pMpTcb->BufferCount,
  117. &pMpTcb->FirstBuffer,
  118. (PUINT)&pMpTcb->PacketLength);
  119. ASSERT(pMpTcb->PhysBufCount);
  120. ASSERT(pMpTcb->FirstBuffer);
  121. ASSERT(pMpTcb->PacketLength);
  122. //
  123. // Check to see if we need to coalesce
  124. //
  125. if (pMpTcb->PacketLength < NIC_MIN_PACKET_SIZE ||
  126. pMpTcb->PhysBufCount > NIC_MAX_PHYS_BUF_COUNT)
  127. {
  128. //
  129. // A local MP_TXBUF available (for local data copying)?
  130. //
  131. if (IsSListEmpty(&Adapter->SendBufList))
  132. {
  133. Adapter->nWaitSend++;
  134. if (bFromQueue)
  135. {
  136. InsertHeadQueue(&Adapter->SendWaitQueue, MP_GET_PACKET_MR(Packet));
  137. }
  138. else
  139. {
  140. InsertTailQueue(&Adapter->SendWaitQueue, MP_GET_PACKET_MR(Packet));
  141. }
  142. DBGPRINT(MP_TRACE, ("<-- MpSendPacket - queued, no buf\n"));
  143. return Status;
  144. }
  145. pMpTxBuf = (PMP_TXBUF) PopEntryList(&Adapter->SendBufList);
  146. ASSERT(pMpTxBuf);
  147. //
  148. // Copy the buffers in this packet, enough to give the first buffer as they are linked
  149. //
  150. BytesCopied = MpCopyPacket(pMpTcb->FirstBuffer, pMpTxBuf);
  151. //
  152. // MpCopyPacket may return 0 if system resources are low or exhausted
  153. //
  154. if (BytesCopied == 0)
  155. {
  156. PushEntryList(&Adapter->SendBufList, &pMpTxBuf->SList);
  157. DBGPRINT(MP_ERROR, ("Calling NdisMSendComplete with NDIS_STATUS_RESOURCES, Pkt= "PTR_FORMAT"\n", Packet));
  158. NdisReleaseSpinLock(&Adapter->SendLock);
  159. NdisMSendComplete(
  160. MP_GET_ADAPTER_HANDLE(Adapter),
  161. Packet,
  162. NDIS_STATUS_RESOURCES);
  163. NdisAcquireSpinLock(&Adapter->SendLock);
  164. return NDIS_STATUS_RESOURCES;
  165. }
  166. pMpTcb->MpTxBuf = pMpTxBuf;
  167. //
  168. // Set up the frag list, only one fragment after it's coalesced
  169. //
  170. pFragList = &FragList;
  171. pFragList->NumberOfElements = 1;
  172. pFragList->Elements[0].Address = pMpTxBuf->BufferPa;
  173. pFragList->Elements[0].Length = (BytesCopied >= NIC_MIN_PACKET_SIZE) ?
  174. BytesCopied : NIC_MIN_PACKET_SIZE;
  175. MP_SET_FLAG(pMpTcb, fMP_TCB_USE_LOCAL_BUF);
  176. //
  177. // Even the driver uses its local buffer, it has to wait the send complete interrupt to
  178. // complete the packet. Otherwise, the driver may run into the following situation:
  179. // before send complete interrupt happens, its halt handler is called and the halt handler
  180. // deregisters the interrupt, so no send complete interrupt can happen, and the send
  181. // complete interrupt handle routine will never be called to free some resources used
  182. // by this send.
  183. }
  184. else
  185. {
  186. #ifdef NDIS51_MINIPORT
  187. ASSERT(MP_TEST_FLAG(Adapter, fMP_ADAPTER_SCATTER_GATHER));
  188. //
  189. // In scatter/gather case, use the frag list pointer saved
  190. // in the packet info field
  191. //
  192. pFragList = (PMP_FRAG_LIST) NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
  193. ScatterGatherListPacketInfo);
  194. #else
  195. if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_SCATTER_GATHER))
  196. {
  197. //
  198. // In scatter/gather case, use the frag list pointer saved
  199. // in the packet info field
  200. //
  201. pFragList = (PMP_FRAG_LIST) NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
  202. ScatterGatherListPacketInfo);
  203. }
  204. else
  205. {
  206. //
  207. // In the map register case, use the local frag list structure
  208. //
  209. pFragList = &FragList;
  210. //
  211. // Do the physical mapping to get all the fragment physical addresses
  212. //
  213. MpStartPacketPhysicalMapping(
  214. Adapter,
  215. pMpTcb->FirstBuffer,
  216. pFragList);
  217. }
  218. #endif
  219. }
  220. pMpTcb->Packet = Packet;
  221. MP_SET_FLAG(pMpTcb, fMP_TCB_IN_USE);
  222. //
  223. // Call the NIC specific send handler, it only needs to deal with the frag list
  224. //
  225. Status = NICSendPacket(Adapter, pMpTcb, pFragList);
  226. Adapter->nBusySend++;
  227. ASSERT(Adapter->nBusySend <= Adapter->NumTcb);
  228. Adapter->CurrSendTail = Adapter->CurrSendTail->Next;
  229. DBGPRINT(MP_TRACE, ("<-- MpSendPacket\n"));
  230. return Status;
  231. }
  232. ULONG MpCopyPacket(
  233. IN PNDIS_BUFFER CurrBuffer,
  234. IN PMP_TXBUF pMpTxBuf
  235. )
  236. /*++
  237. Routine Description:
  238. Copy the packet data to a local buffer
  239. Either the packet is too small or it has too many fragments
  240. Assumption: Send spinlock has been acquired
  241. Arguments:
  242. CurrBuffer Pointer to the first NDIS_BUFFER
  243. pMpTxBuf Pointer to the local buffer (MP_TXBUF)
  244. Return Value:
  245. Bytes copied
  246. --*/
  247. {
  248. UINT CurrLength;
  249. PUCHAR pSrc;
  250. PUCHAR pDest;
  251. UINT BytesCopied = 0;
  252. DBGPRINT(MP_TRACE, ("--> MpCopyPacket\n"));
  253. pDest = pMpTxBuf->pBuffer;
  254. while ((CurrBuffer) && (BytesCopied < pMpTxBuf->BufferSize))
  255. {
  256. //
  257. // Support for the following API with NormalPagePrioirty was added for
  258. // NDIS 5.0 and 5.1 miniports in Windows XP
  259. //
  260. #if !BUILD_W2K
  261. NdisQueryBufferSafe( CurrBuffer, &pSrc, &CurrLength, NormalPagePriority );
  262. #else
  263. NdisQueryBuffer( CurrBuffer, &pSrc, &CurrLength);
  264. #endif
  265. if (pSrc == NULL)
  266. {
  267. return 0;
  268. }
  269. if (pMpTxBuf->BufferSize - BytesCopied < CurrLength)
  270. {
  271. CurrLength = pMpTxBuf->BufferSize - BytesCopied;
  272. }
  273. if (CurrLength)
  274. {
  275. //
  276. // Copy the data.
  277. //
  278. NdisMoveMemory(pDest, pSrc, CurrLength);
  279. BytesCopied += CurrLength;
  280. pDest += CurrLength;
  281. }
  282. NdisGetNextBuffer( CurrBuffer, &CurrBuffer);
  283. }
  284. //
  285. // Zero out the padding bytes
  286. //
  287. if (BytesCopied < NIC_MIN_PACKET_SIZE)
  288. {
  289. NdisZeroMemory(pDest, NIC_MIN_PACKET_SIZE - BytesCopied);
  290. }
  291. NdisAdjustBufferLength(pMpTxBuf->NdisBuffer, BytesCopied);
  292. NdisFlushBuffer(pMpTxBuf->NdisBuffer, TRUE);
  293. ASSERT(BytesCopied <= pMpTxBuf->BufferSize);
  294. DBGPRINT(MP_TRACE, ("<-- MpCopyPacket\n"));
  295. return BytesCopied;
  296. }
  297. #ifndef NDIS51_MINIPORT
  298. VOID MpStartPacketPhysicalMapping(
  299. IN PMP_ADAPTER Adapter,
  300. IN PNDIS_BUFFER CurrBuffer,
  301. OUT PMP_FRAG_LIST pFragList
  302. )
  303. /*++
  304. Routine Description:
  305. Call NdisMStartBufferPhysicalMapping on each NDIS buffer
  306. Get the physical address for each fragment and save them in the fragment list
  307. We use the same fragment list as the scatter gather so the driver writers only need
  308. to deal one type.
  309. Assumption: spinlock has been acquired
  310. Arguments:
  311. Adapter Pointer to our adapter
  312. CurrBuffer Pointer to the first NDIS_BUFFER
  313. pFragList The pointer to the frag list to be filled
  314. Return Value:
  315. None
  316. --*/
  317. {
  318. NDIS_PHYSICAL_ADDRESS_UNIT PhysAddrUnits[NIC_MAX_PHYS_BUF_COUNT];
  319. UINT ArraySize, i;
  320. ULONG ElementIndex = 0;
  321. DBGPRINT(MP_TRACE, ("--> MpStartPacketPhysicalMapping\n"));
  322. while (CurrBuffer)
  323. {
  324. NdisMStartBufferPhysicalMapping(
  325. Adapter->AdapterHandle,
  326. CurrBuffer,
  327. Adapter->CurrMapRegTail,
  328. TRUE,
  329. PhysAddrUnits,
  330. &ArraySize);
  331. Adapter->CurrMapRegTail++;
  332. if (Adapter->CurrMapRegTail == (ULONG)Adapter->NumTbd)
  333. {
  334. Adapter->CurrMapRegTail = 0;
  335. }
  336. for (i = 0; i < ArraySize; i++)
  337. {
  338. pFragList->Elements[ElementIndex].Address = PhysAddrUnits[i].PhysicalAddress;
  339. pFragList->Elements[ElementIndex].Length = PhysAddrUnits[i].Length;
  340. ElementIndex++;
  341. }
  342. //
  343. // Flush the current buffer because it could be cached
  344. //
  345. NdisFlushBuffer(CurrBuffer, TRUE);
  346. //
  347. // point to the next buffer
  348. //
  349. NdisGetNextBuffer(CurrBuffer, &CurrBuffer);
  350. }
  351. pFragList->NumberOfElements = ElementIndex;
  352. ASSERT(pFragList->NumberOfElements);
  353. DBGPRINT(MP_TRACE, ("<-- MpStartPacketPhysicalMapping\n"));
  354. }
  355. #endif
  356. NDIS_STATUS NICSendPacket(
  357. IN PMP_ADAPTER Adapter,
  358. IN PMP_TCB pMpTcb,
  359. IN PMP_FRAG_LIST pFragList
  360. )
  361. /*++
  362. Routine Description:
  363. NIC specific send handler
  364. Assumption: Send spinlock has been acquired
  365. Arguments:
  366. Adapter Pointer to our adapter
  367. pMpTcb Pointer to MP_TCB
  368. pFragList The pointer to the frag list to be filled
  369. Return Value:
  370. NDIS_STATUS_SUCCESS
  371. NDIS_STATUS_HARD_ERRORS
  372. --*/
  373. {
  374. NDIS_STATUS Status;
  375. ULONG index;
  376. UCHAR TbdCount = 0;
  377. PHW_TCB pHwTcb = pMpTcb->HwTcb;
  378. PTBD_STRUC pHwTbd = pMpTcb->HwTbd;
  379. DBGPRINT(MP_TRACE, ("--> NICSendPacket\n"));
  380. for (index = 0; index < pFragList->NumberOfElements; index++)
  381. {
  382. if (pFragList->Elements[index].Length)
  383. {
  384. pHwTbd->TbdBufferAddress = NdisGetPhysicalAddressLow(pFragList->Elements[index].Address);
  385. pHwTbd->TbdCount = pFragList->Elements[index].Length;
  386. pHwTbd++;
  387. TbdCount++;
  388. }
  389. }
  390. pHwTcb->TxCbHeader.CbStatus = 0;
  391. pHwTcb->TxCbHeader.CbCommand = CB_S_BIT | CB_TRANSMIT | CB_TX_SF_BIT;
  392. pHwTcb->TxCbTbdPointer = pMpTcb->HwTbdPhys;
  393. pHwTcb->TxCbTbdNumber = TbdCount;
  394. pHwTcb->TxCbCount = 0;
  395. pHwTcb->TxCbThreshold = (UCHAR) Adapter->AiThreshold;
  396. Status = NICStartSend(Adapter, pMpTcb);
  397. DBGPRINT(MP_TRACE, ("<-- NICSendPacket\n"));
  398. return Status;
  399. }
  400. NDIS_STATUS NICStartSend(
  401. IN PMP_ADAPTER Adapter,
  402. IN PMP_TCB pMpTcb
  403. )
  404. /*++
  405. Routine Description:
  406. Issue a send command to the NIC
  407. Assumption: Send spinlock has been acquired
  408. Arguments:
  409. Adapter Pointer to our adapter
  410. pMpTcb Pointer to MP_TCB
  411. Return Value:
  412. NDIS_STATUS_SUCCESS
  413. NDIS_STATUS_HARD_ERRORS
  414. --*/
  415. {
  416. NDIS_STATUS Status;
  417. DBGPRINT(MP_TRACE, ("--> NICStartSend\n"));
  418. //
  419. // If the transmit unit is idle (very first transmit) then we must
  420. // setup the general pointer and issue a full CU-start
  421. //
  422. if (Adapter->TransmitIdle)
  423. {
  424. DBGPRINT(MP_INFO, ("CU is idle -- First TCB added to Active List\n"));
  425. //
  426. // Wait for the SCB to clear before we set the general pointer
  427. //
  428. if (!WaitScb(Adapter))
  429. {
  430. Status = NDIS_STATUS_HARD_ERRORS;
  431. MP_EXIT;
  432. }
  433. //
  434. // Don't try to start the transmitter if the command unit is not
  435. // idle ((not idle) == (Cu-Suspended or Cu-Active)).
  436. //
  437. if ((Adapter->CSRAddress->ScbStatus & SCB_CUS_MASK) != SCB_CUS_IDLE)
  438. {
  439. DBGPRINT(MP_ERROR, ("Adapter = "PTR_FORMAT", CU Not IDLE\n", Adapter));
  440. MP_SET_HARDWARE_ERROR(Adapter);
  441. NdisStallExecution(25);
  442. }
  443. Adapter->CSRAddress->ScbGeneralPointer = pMpTcb->HwTcbPhys;
  444. Status = D100IssueScbCommand(Adapter, SCB_CUC_START, FALSE);
  445. Adapter->TransmitIdle = FALSE;
  446. Adapter->ResumeWait = TRUE;
  447. }
  448. else
  449. {
  450. //
  451. // If the command unit has already been started, then append this
  452. // TCB onto the end of the transmit chain, and issue a CU-Resume.
  453. //
  454. DBGPRINT(MP_LOUD, ("adding TCB to Active chain\n"));
  455. //
  456. // Clear the suspend bit on the previous packet.
  457. //
  458. pMpTcb->PrevHwTcb->TxCbHeader.CbCommand &= ~CB_S_BIT;
  459. //
  460. // Issue a CU-Resume command to the device. We only need to do a
  461. // WaitScb if the last command was NOT a RESUME.
  462. //
  463. Status = D100IssueScbCommand(Adapter, SCB_CUC_RESUME, Adapter->ResumeWait);
  464. }
  465. exit:
  466. DBGPRINT(MP_TRACE, ("<-- NICStartSend\n"));
  467. return Status;
  468. }
  469. NDIS_STATUS MpHandleSendInterrupt(
  470. IN PMP_ADAPTER Adapter
  471. )
  472. /*++
  473. Routine Description:
  474. Interrupt handler for sending processing
  475. Re-claim the send resources, complete sends and get more to send from the send wait queue
  476. Assumption: Send spinlock has been acquired
  477. Arguments:
  478. Adapter Pointer to our adapter
  479. Return Value:
  480. NDIS_STATUS_SUCCESS
  481. NDIS_STATUS_HARD_ERRORS
  482. NDIS_STATUS_PENDING
  483. --*/
  484. {
  485. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  486. PMP_TCB pMpTcb;
  487. #if DBG
  488. LONG i;
  489. #endif
  490. DBGPRINT(MP_TRACE, ("---> MpHandleSendInterrupt\n"));
  491. //
  492. // Any packets being sent? Any packet waiting in the send queue?
  493. //
  494. if (Adapter->nBusySend == 0 &&
  495. IsQueueEmpty(&Adapter->SendWaitQueue))
  496. {
  497. ASSERT(Adapter->CurrSendHead == Adapter->CurrSendTail);
  498. DBGPRINT(MP_TRACE, ("<--- MpHandleSendInterrupt\n"));
  499. return Status;
  500. }
  501. //
  502. // Check the first TCB on the send list
  503. //
  504. while (Adapter->nBusySend > 0)
  505. {
  506. #if DBG
  507. pMpTcb = Adapter->CurrSendHead;
  508. for (i = 0; i < Adapter->nBusySend; i++)
  509. {
  510. pMpTcb = pMpTcb->Next;
  511. }
  512. if (pMpTcb != Adapter->CurrSendTail)
  513. {
  514. DBGPRINT(MP_ERROR, ("nBusySend= %d\n", Adapter->nBusySend));
  515. DBGPRINT(MP_ERROR, ("CurrSendhead= "PTR_FORMAT"\n", Adapter->CurrSendHead));
  516. DBGPRINT(MP_ERROR, ("CurrSendTail= "PTR_FORMAT"\n", Adapter->CurrSendTail));
  517. ASSERT(FALSE);
  518. }
  519. #endif
  520. pMpTcb = Adapter->CurrSendHead;
  521. //
  522. // Is this TCB completed?
  523. //
  524. if (pMpTcb->HwTcb->TxCbHeader.CbStatus & CB_STATUS_COMPLETE)
  525. {
  526. //
  527. // Check if this is a multicast hw workaround packet
  528. //
  529. if ((pMpTcb->HwTcb->TxCbHeader.CbCommand & CB_CMD_MASK) != CB_MULTICAST)
  530. {
  531. MP_FREE_SEND_PACKET_FUN(Adapter, pMpTcb);
  532. }
  533. else
  534. {
  535. }
  536. }
  537. else
  538. {
  539. break;
  540. }
  541. }
  542. //
  543. // If we queued any transmits because we didn't have any TCBs earlier,
  544. // dequeue and send those packets now, as long as we have free TCBs.
  545. //
  546. if (MP_IS_READY(Adapter))
  547. {
  548. while (!IsQueueEmpty(&Adapter->SendWaitQueue) &&
  549. MP_TCB_RESOURCES_AVAIABLE(Adapter))
  550. {
  551. PNDIS_PACKET Packet;
  552. PQUEUE_ENTRY pEntry;
  553. #if OFFLOAD
  554. if (MP_TEST_FLAG(Adapter, fMP_SHARED_MEM_IN_USE))
  555. {
  556. break;
  557. }
  558. #endif
  559. pEntry = RemoveHeadQueue(&Adapter->SendWaitQueue);
  560. ASSERT(pEntry);
  561. Adapter->nWaitSend--;
  562. Packet = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
  563. DBGPRINT(MP_INFO, ("MpHandleSendInterrupt - send a queued packet\n"));
  564. Status = MpSendPacketFun(Adapter, Packet, TRUE);
  565. if (Status != NDIS_STATUS_SUCCESS)
  566. {
  567. break;
  568. }
  569. }
  570. }
  571. DBGPRINT(MP_TRACE, ("<--- MpHandleSendInterrupt\n"));
  572. return Status;
  573. }
  574. VOID MpHandleRecvInterrupt(
  575. IN PMP_ADAPTER Adapter
  576. )
  577. /*++
  578. Routine Description:
  579. Interrupt handler for receive processing
  580. Put the received packets into an array and call NdisMIndicateReceivePacket
  581. If we run low on RFDs, allocate another one
  582. Assumption: Rcv spinlock has been acquired
  583. Arguments:
  584. Adapter Pointer to our adapter
  585. Return Value:
  586. None
  587. --*/
  588. {
  589. PMP_RFD pMpRfd;
  590. PHW_RFD pHwRfd;
  591. PNDIS_PACKET PacketArray[NIC_DEF_RFDS];
  592. PNDIS_PACKET PacketFreeArray[NIC_DEF_RFDS];
  593. UINT PacketArrayCount;
  594. UINT PacketFreeCount;
  595. UINT Index;
  596. UINT LoopIndex = 0;
  597. UINT LoopCount = NIC_MAX_RFDS / NIC_DEF_RFDS + 1; // avoid staying here too long
  598. BOOLEAN bContinue = TRUE;
  599. BOOLEAN bAllocNewRfd = FALSE;
  600. USHORT PacketStatus;
  601. DBGPRINT(MP_TRACE, ("---> MpHandleRecvInterrupt\n"));
  602. ASSERT(Adapter->nReadyRecv >= NIC_MIN_RFDS);
  603. while (LoopIndex++ < LoopCount && bContinue)
  604. {
  605. PacketArrayCount = 0;
  606. PacketFreeCount = 0;
  607. //
  608. // Process up to the array size RFD's
  609. //
  610. while (PacketArrayCount < NIC_DEF_RFDS)
  611. {
  612. if (IsListEmpty(&Adapter->RecvList))
  613. {
  614. ASSERT(Adapter->nReadyRecv == 0);
  615. bContinue = FALSE;
  616. break;
  617. }
  618. //
  619. // Get the next MP_RFD to process
  620. //
  621. pMpRfd = (PMP_RFD)GetListHeadEntry(&Adapter->RecvList);
  622. //
  623. // Get the associated HW_RFD
  624. //
  625. pHwRfd = pMpRfd->HwRfd;
  626. //
  627. // Is this packet completed?
  628. //
  629. PacketStatus = NIC_RFD_GET_STATUS(pHwRfd);
  630. if (!NIC_RFD_STATUS_COMPLETED(PacketStatus))
  631. {
  632. bContinue = FALSE;
  633. break;
  634. }
  635. //
  636. // HW specific - check if actual count field has been updated
  637. //
  638. if (!NIC_RFD_VALID_ACTUALCOUNT(pHwRfd))
  639. {
  640. bContinue = FALSE;
  641. break;
  642. }
  643. //
  644. // Remove the RFD from the head of the List
  645. //
  646. RemoveEntryList((PLIST_ENTRY)pMpRfd);
  647. Adapter->nReadyRecv--;
  648. ASSERT(Adapter->nReadyRecv >= 0);
  649. ASSERT(MP_TEST_FLAG(pMpRfd, fMP_RFD_RECV_READY));
  650. MP_CLEAR_FLAG(pMpRfd, fMP_RFD_RECV_READY);
  651. //
  652. // A good packet? drop it if not.
  653. //
  654. if (!NIC_RFD_STATUS_SUCCESS(PacketStatus))
  655. {
  656. DBGPRINT(MP_WARN, ("Receive failure = %x\n", PacketStatus));
  657. NICReturnRFD(Adapter, pMpRfd);
  658. continue;
  659. }
  660. //
  661. // Do not receive any packets until a filter has been set
  662. //
  663. if (!Adapter->PacketFilter)
  664. {
  665. NICReturnRFD(Adapter, pMpRfd);
  666. continue;
  667. }
  668. //
  669. // Do not receive any packets until we are at D0
  670. //
  671. if (Adapter->CurrentPowerState != NdisDeviceStateD0)
  672. {
  673. NICReturnRFD(Adapter, pMpRfd);
  674. continue;
  675. }
  676. pMpRfd->PacketSize = NIC_RFD_GET_PACKET_SIZE(pHwRfd);
  677. NdisAdjustBufferLength(pMpRfd->NdisBuffer, pMpRfd->PacketSize);
  678. NdisFlushBuffer(pMpRfd->NdisBuffer, FALSE);
  679. // we don't mess up the buffer chain, no need to make this call in this case
  680. // NdisRecalculatePacketCounts(pMpRfd->ReceivePacket);
  681. //
  682. // set the status on the packet, either resources or success
  683. //
  684. if (Adapter->nReadyRecv >= MIN_NUM_RFD)
  685. {
  686. // NDIS_STATUS_SUCCESS
  687. NDIS_SET_PACKET_STATUS(pMpRfd->NdisPacket, NDIS_STATUS_SUCCESS);
  688. MP_SET_FLAG(pMpRfd, fMP_RFD_RECV_PEND);
  689. InsertTailList(&Adapter->RecvPendList, (PLIST_ENTRY)pMpRfd);
  690. MP_INC_RCV_REF(Adapter);
  691. }
  692. else
  693. {
  694. //
  695. // NDIS_STATUS_RESOURCES
  696. //
  697. NDIS_SET_PACKET_STATUS(pMpRfd->NdisPacket, NDIS_STATUS_RESOURCES);
  698. MP_SET_FLAG(pMpRfd, fMP_RFD_RESOURCES);
  699. PacketFreeArray[PacketFreeCount] = pMpRfd->NdisPacket;
  700. PacketFreeCount++;
  701. //
  702. // Reset the RFD shrink count - don't attempt to shrink RFD
  703. //
  704. Adapter->RfdShrinkCount = 0;
  705. //
  706. // Remember to allocate a new RFD later
  707. //
  708. bAllocNewRfd = TRUE;
  709. }
  710. PacketArray[PacketArrayCount] = pMpRfd->NdisPacket;
  711. PacketArrayCount++;
  712. }
  713. //
  714. // if we didn't process any receives, just return from here
  715. //
  716. if (PacketArrayCount == 0)
  717. {
  718. break;
  719. }
  720. //
  721. // Update the number of outstanding Recvs
  722. //
  723. Adapter->PoMgmt.OutstandingRecv += PacketArrayCount;
  724. NdisDprReleaseSpinLock(&Adapter->RcvLock);
  725. NdisDprAcquireSpinLock(&Adapter->Lock);
  726. //
  727. // if we have a Recv interrupt and have reported a media disconnect status
  728. // time to indicate the new status
  729. //
  730. if (NdisMediaStateDisconnected == Adapter->MediaState)
  731. {
  732. DBGPRINT(MP_WARN, ("Media state changed to Connected\n"));
  733. MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_NO_CABLE);
  734. Adapter->MediaState = NdisMediaStateConnected;
  735. NdisDprReleaseSpinLock(&Adapter->Lock);
  736. //
  737. // Indicate the media event
  738. //
  739. NdisMIndicateStatus(Adapter->AdapterHandle, NDIS_STATUS_MEDIA_CONNECT, (PVOID)0, 0);
  740. NdisMIndicateStatusComplete(Adapter->AdapterHandle);
  741. }
  742. else
  743. {
  744. NdisDprReleaseSpinLock(&Adapter->Lock);
  745. }
  746. NdisMIndicateReceivePacket(
  747. Adapter->AdapterHandle,
  748. PacketArray,
  749. PacketArrayCount);
  750. NdisDprAcquireSpinLock(&Adapter->RcvLock);
  751. //
  752. // NDIS won't take ownership for the packets with NDIS_STATUS_RESOURCES.
  753. // For other packets, NDIS always takes the ownership and gives them back
  754. // by calling MPReturnPackets
  755. //
  756. for (Index = 0; Index < PacketFreeCount; Index++)
  757. {
  758. //
  759. // Get the MP_RFD saved in this packet, in NICAllocRfd
  760. //
  761. pMpRfd = MP_GET_PACKET_RFD(PacketFreeArray[Index]);
  762. ASSERT(MP_TEST_FLAG(pMpRfd, fMP_RFD_RESOURCES));
  763. MP_CLEAR_FLAG(pMpRfd, fMP_RFD_RESOURCES);
  764. //
  765. // Decrement the number of outstanding Recvs
  766. //
  767. Adapter->PoMgmt.OutstandingRecv --;
  768. NICReturnRFD(Adapter, pMpRfd);
  769. }
  770. //
  771. //If we have set power pending, then complete it
  772. //
  773. if (((Adapter->bSetPending == TRUE)
  774. && (Adapter->SetRequest.Oid == OID_PNP_SET_POWER))
  775. && (Adapter->PoMgmt.OutstandingRecv == 0))
  776. {
  777. MpSetPowerLowComplete(Adapter);
  778. }
  779. }
  780. //
  781. // If we ran low on RFD's, we need to allocate a new RFD
  782. //
  783. if (bAllocNewRfd)
  784. {
  785. //
  786. // Allocate one more RFD only if no pending new RFD allocation AND
  787. // it doesn't exceed the max RFD limit
  788. //
  789. if (!Adapter->bAllocNewRfd && Adapter->CurrNumRfd < Adapter->MaxNumRfd)
  790. {
  791. PMP_RFD TempMpRfd;
  792. NDIS_STATUS TempStatus;
  793. TempMpRfd = NdisAllocateFromNPagedLookasideList(&Adapter->RecvLookaside);
  794. if (TempMpRfd)
  795. {
  796. MP_INC_REF(Adapter);
  797. Adapter->bAllocNewRfd = TRUE;
  798. MP_SET_FLAG(TempMpRfd, fMP_RFD_ALLOC_PEND);
  799. //
  800. // Allocate the shared memory for this RFD.
  801. //
  802. TempStatus = NdisMAllocateSharedMemoryAsync(
  803. Adapter->AdapterHandle,
  804. Adapter->HwRfdSize,
  805. FALSE,
  806. TempMpRfd);
  807. //
  808. // The return value will be either NDIS_STATUS_PENDING or NDIS_STATUS_FAILURE
  809. //
  810. if (TempStatus == NDIS_STATUS_FAILURE)
  811. {
  812. MP_CLEAR_FLAGS(TempMpRfd);
  813. NdisFreeToNPagedLookasideList(&Adapter->RecvLookaside, TempMpRfd);
  814. Adapter->bAllocNewRfd = FALSE;
  815. MP_DEC_REF(Adapter);
  816. }
  817. }
  818. }
  819. }
  820. ASSERT(Adapter->nReadyRecv >= NIC_MIN_RFDS);
  821. DBGPRINT(MP_TRACE, ("<--- MpHandleRecvInterrupt\n"));
  822. }
  823. VOID NICReturnRFD(
  824. IN PMP_ADAPTER Adapter,
  825. IN PMP_RFD pMpRfd
  826. )
  827. /*++
  828. Routine Description:
  829. Recycle a RFD and put it back onto the receive list
  830. Assumption: Rcv spinlock has been acquired
  831. Arguments:
  832. Adapter Pointer to our adapter
  833. pMpRfd Pointer to the RFD
  834. Return Value:
  835. None
  836. --*/
  837. {
  838. PMP_RFD pLastMpRfd;
  839. PHW_RFD pHwRfd = pMpRfd->HwRfd;
  840. ASSERT(pMpRfd->Flags == 0);
  841. MP_SET_FLAG(pMpRfd, fMP_RFD_RECV_READY);
  842. //
  843. // HW_SPECIFIC_START
  844. //
  845. pHwRfd->RfdCbHeader.CbStatus = 0;
  846. pHwRfd->RfdActualCount = 0;
  847. pHwRfd->RfdCbHeader.CbCommand = (RFD_EL_BIT);
  848. pHwRfd->RfdCbHeader.CbLinkPointer = DRIVER_NULL;
  849. //
  850. // We don't use any of the OOB data besides status
  851. // Otherwise, we need to clean up OOB data
  852. // NdisZeroMemory(NDIS_OOB_DATA_FROM_PACKET(pMpRfd->NdisPacket),14);
  853. //
  854. // Append this RFD to the RFD chain
  855. if (!IsListEmpty(&Adapter->RecvList))
  856. {
  857. pLastMpRfd = (PMP_RFD)GetListTailEntry(&Adapter->RecvList);
  858. // Link it onto the end of the chain dynamically
  859. pHwRfd = pLastMpRfd->HwRfd;
  860. pHwRfd->RfdCbHeader.CbLinkPointer = pMpRfd->HwRfdPhys;
  861. pHwRfd->RfdCbHeader.CbCommand = 0;
  862. }
  863. //
  864. // HW_SPECIFIC_END
  865. //
  866. //
  867. // The processing on this RFD is done, so put it back on the tail of
  868. // our list
  869. //
  870. InsertTailList(&Adapter->RecvList, (PLIST_ENTRY)pMpRfd);
  871. Adapter->nReadyRecv++;
  872. ASSERT(Adapter->nReadyRecv <= Adapter->CurrNumRfd);
  873. }
  874. NDIS_STATUS NICStartRecv(
  875. IN PMP_ADAPTER Adapter
  876. )
  877. /*++
  878. Routine Description:
  879. Start the receive unit if it's not in a ready state
  880. Assumption: Rcv spinlock has been acquired
  881. Arguments:
  882. Adapter Pointer to our adapter
  883. Return Value:
  884. NDIS_STATUS_SUCCESS
  885. NDIS_STATUS_HARD_ERRROS
  886. --*/
  887. {
  888. PMP_RFD pMpRfd;
  889. NDIS_STATUS Status;
  890. DBGPRINT(MP_TRACE, ("---> NICStartRecv\n"));
  891. //
  892. // If the receiver is ready, then don't try to restart.
  893. //
  894. if (NIC_IS_RECV_READY(Adapter))
  895. {
  896. DBGPRINT(MP_LOUD, ("Receive unit already active\n"));
  897. return NDIS_STATUS_SUCCESS;
  898. }
  899. DBGPRINT(MP_LOUD, ("Re-start receive unit...\n"));
  900. ASSERT(!IsListEmpty(&Adapter->RecvList));
  901. //
  902. // Get the MP_RFD head
  903. //
  904. pMpRfd = (PMP_RFD)GetListHeadEntry(&Adapter->RecvList);
  905. //
  906. // If more packets are received, clean up RFD chain again
  907. //
  908. if (NIC_RFD_GET_STATUS(pMpRfd->HwRfd))
  909. {
  910. MpHandleRecvInterrupt(Adapter);
  911. ASSERT(!IsListEmpty(&Adapter->RecvList));
  912. //
  913. // Get the new MP_RFD head
  914. //
  915. pMpRfd = (PMP_RFD)GetListHeadEntry(&Adapter->RecvList);
  916. }
  917. //
  918. // Wait for the SCB to clear before we set the general pointer
  919. //
  920. if (!WaitScb(Adapter))
  921. {
  922. Status = NDIS_STATUS_HARD_ERRORS;
  923. MP_EXIT;
  924. }
  925. if (Adapter->CurrentPowerState > NdisDeviceStateD0)
  926. {
  927. Status = NDIS_STATUS_HARD_ERRORS;
  928. MP_EXIT;
  929. }
  930. //
  931. // Set the SCB General Pointer to point the current Rfd
  932. //
  933. Adapter->CSRAddress->ScbGeneralPointer = pMpRfd->HwRfdPhys;
  934. //
  935. // Issue the SCB RU start command
  936. //
  937. Status = D100IssueScbCommand(Adapter, SCB_RUC_START, FALSE);
  938. if (Status == NDIS_STATUS_SUCCESS)
  939. {
  940. // wait for the command to be accepted
  941. if (!WaitScb(Adapter))
  942. {
  943. Status = NDIS_STATUS_HARD_ERRORS;
  944. }
  945. }
  946. exit:
  947. DBGPRINT_S(Status, ("<--- NICStartRecv, Status=%x\n", Status));
  948. return Status;
  949. }
  950. VOID MpFreeQueuedSendPackets(
  951. IN PMP_ADAPTER Adapter
  952. )
  953. /*++
  954. Routine Description:
  955. Free and complete the pended sends on SendWaitQueue
  956. Assumption: spinlock has been acquired
  957. Arguments:
  958. Adapter Pointer to our adapter
  959. Return Value:
  960. None
  961. --*/
  962. {
  963. PQUEUE_ENTRY pEntry;
  964. PNDIS_PACKET Packet;
  965. NDIS_STATUS Status = MP_GET_STATUS_FROM_FLAGS(Adapter);
  966. DBGPRINT(MP_TRACE, ("--> MpFreeQueuedSendPackets\n"));
  967. while (!IsQueueEmpty(&Adapter->SendWaitQueue))
  968. {
  969. pEntry = RemoveHeadQueue(&Adapter->SendWaitQueue);
  970. Adapter->nWaitSend--;
  971. NdisReleaseSpinLock(&Adapter->SendLock);
  972. ASSERT(pEntry);
  973. Packet = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
  974. NdisMSendComplete(
  975. MP_GET_ADAPTER_HANDLE(Adapter),
  976. Packet,
  977. Status);
  978. NdisAcquireSpinLock(&Adapter->SendLock);
  979. }
  980. DBGPRINT(MP_TRACE, ("<-- MpFreeQueuedSendPackets\n"));
  981. }
  982. void MpFreeBusySendPackets(
  983. IN PMP_ADAPTER Adapter
  984. )
  985. /*++
  986. Routine Description:
  987. Free and complete the stopped active sends
  988. Assumption: Send spinlock has been acquired
  989. Arguments:
  990. Adapter Pointer to our adapter
  991. Return Value:
  992. None
  993. --*/
  994. {
  995. PMP_TCB pMpTcb;
  996. DBGPRINT(MP_TRACE, ("--> MpFreeBusySendPackets\n"));
  997. //
  998. // Any packets being sent? Check the first TCB on the send list
  999. //
  1000. while (Adapter->nBusySend > 0)
  1001. {
  1002. pMpTcb = Adapter->CurrSendHead;
  1003. //
  1004. // Is this TCB completed?
  1005. //
  1006. if ((pMpTcb->HwTcb->TxCbHeader.CbCommand & CB_CMD_MASK) != CB_MULTICAST)
  1007. {
  1008. MP_FREE_SEND_PACKET_FUN(Adapter, pMpTcb);
  1009. }
  1010. else
  1011. {
  1012. break;
  1013. }
  1014. }
  1015. DBGPRINT(MP_TRACE, ("<-- MpFreeBusySendPackets\n"));
  1016. }
  1017. VOID NICResetRecv(
  1018. IN PMP_ADAPTER Adapter
  1019. )
  1020. /*++
  1021. Routine Description:
  1022. Reset the receive list
  1023. Assumption: Rcv spinlock has been acquired
  1024. Arguments:
  1025. Adapter Pointer to our adapter
  1026. Return Value:
  1027. None
  1028. --*/
  1029. {
  1030. PMP_RFD pMpRfd;
  1031. PHW_RFD pHwRfd;
  1032. LONG RfdCount;
  1033. DBGPRINT(MP_TRACE, ("--> NICResetRecv\n"));
  1034. ASSERT(!IsListEmpty(&Adapter->RecvList));
  1035. //
  1036. // Get the MP_RFD head
  1037. //
  1038. pMpRfd = (PMP_RFD)GetListHeadEntry(&Adapter->RecvList);
  1039. for (RfdCount = 0; RfdCount < Adapter->nReadyRecv; RfdCount++)
  1040. {
  1041. pHwRfd = pMpRfd->HwRfd;
  1042. pHwRfd->RfdCbHeader.CbStatus = 0;
  1043. pMpRfd = (PMP_RFD)GetListFLink(&pMpRfd->List);
  1044. }
  1045. DBGPRINT(MP_TRACE, ("<-- NICResetRecv\n"));
  1046. }
  1047. VOID MpLinkDetectionDpc(
  1048. IN PVOID SystemSpecific1,
  1049. IN PVOID FunctionContext,
  1050. IN PVOID SystemSpecific2,
  1051. IN PVOID SystemSpecific3
  1052. )
  1053. /*++
  1054. Routine Description:
  1055. Timer function for postponed link negotiation
  1056. Arguments:
  1057. SystemSpecific1 Not used
  1058. FunctionContext Pointer to our adapter
  1059. SystemSpecific2 Not used
  1060. SystemSpecific3 Not used
  1061. Return Value:
  1062. None
  1063. --*/
  1064. {
  1065. PMP_ADAPTER Adapter = (PMP_ADAPTER)FunctionContext;
  1066. NDIS_STATUS Status;
  1067. NDIS_MEDIA_STATE CurrMediaState;
  1068. NDIS_STATUS IndicateStatus;
  1069. UNREFERENCED_PARAMETER(SystemSpecific1);
  1070. UNREFERENCED_PARAMETER(SystemSpecific2);
  1071. UNREFERENCED_PARAMETER(SystemSpecific3);
  1072. //
  1073. // Handle the link negotiation.
  1074. //
  1075. if (Adapter->bLinkDetectionWait)
  1076. {
  1077. Status = ScanAndSetupPhy(Adapter);
  1078. }
  1079. else
  1080. {
  1081. Status = PhyDetect(Adapter);
  1082. }
  1083. if (Status == NDIS_STATUS_PENDING)
  1084. {
  1085. // Wait for 100 ms
  1086. Adapter->bLinkDetectionWait = TRUE;
  1087. NdisMSetTimer(&Adapter->LinkDetectionTimer, NIC_LINK_DETECTION_DELAY);
  1088. return;
  1089. }
  1090. //
  1091. // Reset some variables for link detection
  1092. //
  1093. Adapter->bLinkDetectionWait = FALSE;
  1094. DBGPRINT(MP_WARN, ("MpLinkDetectionDpc - negotiation done\n"));
  1095. NdisDprAcquireSpinLock(&Adapter->Lock);
  1096. MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_LINK_DETECTION);
  1097. NdisDprReleaseSpinLock(&Adapter->Lock);
  1098. //
  1099. // Any OID query request?
  1100. //
  1101. if (Adapter->bQueryPending)
  1102. {
  1103. switch(Adapter->QueryRequest.Oid)
  1104. {
  1105. case OID_GEN_LINK_SPEED:
  1106. *((PULONG) Adapter->QueryRequest.InformationBuffer) = Adapter->usLinkSpeed * 10000;
  1107. *((PULONG) Adapter->QueryRequest.BytesWritten) = sizeof(ULONG);
  1108. break;
  1109. case OID_GEN_MEDIA_CONNECT_STATUS:
  1110. default:
  1111. ASSERT(Adapter->QueryRequest.Oid == OID_GEN_MEDIA_CONNECT_STATUS);
  1112. CurrMediaState = NICGetMediaState(Adapter);
  1113. NdisMoveMemory(Adapter->QueryRequest.InformationBuffer,
  1114. &CurrMediaState,
  1115. sizeof(NDIS_MEDIA_STATE));
  1116. NdisDprAcquireSpinLock(&Adapter->Lock);
  1117. if (Adapter->MediaState != CurrMediaState)
  1118. {
  1119. Adapter->MediaState = CurrMediaState;
  1120. DBGPRINT(MP_WARN, ("Media state changed to %s\n",
  1121. ((CurrMediaState == NdisMediaStateConnected)?
  1122. "Connected": "Disconnected")));
  1123. IndicateStatus = (CurrMediaState == NdisMediaStateConnected) ?
  1124. NDIS_STATUS_MEDIA_CONNECT : NDIS_STATUS_MEDIA_DISCONNECT;
  1125. if (IndicateStatus == NDIS_STATUS_MEDIA_CONNECT)
  1126. {
  1127. MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_NO_CABLE);
  1128. }
  1129. else
  1130. {
  1131. MP_SET_FLAG(Adapter, fMP_ADAPTER_NO_CABLE);
  1132. }
  1133. NdisDprReleaseSpinLock(&Adapter->Lock);
  1134. // Indicate the media event
  1135. NdisMIndicateStatus(Adapter->AdapterHandle, IndicateStatus, (PVOID)0, 0);
  1136. NdisMIndicateStatusComplete(Adapter->AdapterHandle);
  1137. }
  1138. else
  1139. {
  1140. NdisDprReleaseSpinLock(&Adapter->Lock);
  1141. }
  1142. *((PULONG) Adapter->QueryRequest.BytesWritten) = sizeof(NDIS_MEDIA_STATE);
  1143. }
  1144. Adapter->bQueryPending = FALSE;
  1145. NdisMQueryInformationComplete(Adapter->AdapterHandle, NDIS_STATUS_SUCCESS);
  1146. }
  1147. //
  1148. // Any OID set request?
  1149. //
  1150. if (Adapter->bSetPending)
  1151. {
  1152. ULONG PacketFilter;
  1153. if (Adapter->SetRequest.Oid == OID_GEN_CURRENT_PACKET_FILTER)
  1154. {
  1155. NdisMoveMemory(&PacketFilter, Adapter->SetRequest.InformationBuffer, sizeof(ULONG));
  1156. NdisDprAcquireSpinLock(&Adapter->Lock);
  1157. Status = NICSetPacketFilter(
  1158. Adapter,
  1159. PacketFilter);
  1160. NdisDprReleaseSpinLock(&Adapter->Lock);
  1161. if (Status == NDIS_STATUS_SUCCESS)
  1162. {
  1163. Adapter->PacketFilter = PacketFilter;
  1164. }
  1165. Adapter->bSetPending = FALSE;
  1166. NdisMSetInformationComplete(Adapter->AdapterHandle, Status);
  1167. }
  1168. }
  1169. NdisDprAcquireSpinLock(&Adapter->Lock);
  1170. //
  1171. // Any pendingf reset?
  1172. //
  1173. if (Adapter->bResetPending)
  1174. {
  1175. // The link detection may have held some requests and caused reset.
  1176. // Complete the reset with NOT_READY status
  1177. Adapter->bResetPending = FALSE;
  1178. MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_RESET_IN_PROGRESS);
  1179. NdisDprReleaseSpinLock(&Adapter->Lock);
  1180. NdisMResetComplete(
  1181. Adapter->AdapterHandle,
  1182. NDIS_STATUS_ADAPTER_NOT_READY,
  1183. FALSE);
  1184. }
  1185. else
  1186. {
  1187. NdisDprReleaseSpinLock(&Adapter->Lock);
  1188. }
  1189. NdisDprAcquireSpinLock(&Adapter->RcvLock);
  1190. //
  1191. // Start the NIC receive unit
  1192. //
  1193. Status = NICStartRecv(Adapter);
  1194. if (Status != NDIS_STATUS_SUCCESS)
  1195. {
  1196. MP_SET_HARDWARE_ERROR(Adapter);
  1197. }
  1198. NdisDprReleaseSpinLock(&Adapter->RcvLock);
  1199. NdisDprAcquireSpinLock(&Adapter->SendLock);
  1200. //
  1201. // Send packets which have been queued while link detection was going on.
  1202. //
  1203. if (MP_IS_READY(Adapter))
  1204. {
  1205. while (!IsQueueEmpty(&Adapter->SendWaitQueue) &&
  1206. MP_TCB_RESOURCES_AVAIABLE(Adapter))
  1207. {
  1208. PNDIS_PACKET Packet;
  1209. PQUEUE_ENTRY pEntry;
  1210. #if OFFLOAD
  1211. if (MP_TEST_FLAG(Adapter, fMP_SHARED_MEM_IN_USE))
  1212. {
  1213. break;
  1214. }
  1215. #endif
  1216. pEntry = RemoveHeadQueue(&Adapter->SendWaitQueue);
  1217. ASSERT(pEntry);
  1218. Adapter->nWaitSend--;
  1219. Packet = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
  1220. DBGPRINT(MP_INFO, ("MpLinkDetectionDpc - send a queued packet\n"));
  1221. Status = MpSendPacketFun(Adapter, Packet, TRUE);
  1222. if (Status != NDIS_STATUS_SUCCESS)
  1223. {
  1224. break;
  1225. }
  1226. }
  1227. }
  1228. MP_DEC_REF(Adapter);
  1229. if (MP_GET_REF(Adapter) == 0)
  1230. {
  1231. NdisSetEvent(&Adapter->ExitEvent);
  1232. }
  1233. NdisDprReleaseSpinLock(&Adapter->SendLock);
  1234. }