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.

755 lines
22 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. dma.c
  5. Abstract:
  6. Author:
  7. Jameel Hyder (jameelh) 02-Apr-1998
  8. Environment:
  9. Kernel mode, FSD
  10. Revision History:
  11. 02-Apr-1998 JameelH Initial version
  12. --*/
  13. #include <precomp.h>
  14. #pragma hdrstop
  15. //
  16. // Define the module number for debug code.
  17. //
  18. #define MODULE_NUMBER MODULE_DMA
  19. NDIS_STATUS
  20. NdisMInitializeScatterGatherDma(
  21. IN NDIS_HANDLE MiniportAdapterHandle,
  22. IN BOOLEAN Dma64BitAddresses,
  23. IN ULONG MaximumPhysicalMapping
  24. )
  25. /*++
  26. Routine Description:
  27. Allocates adapter channel for bus mastering devices.
  28. Arguments:
  29. Return Value:
  30. None.
  31. --*/
  32. {
  33. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  34. DEVICE_DESCRIPTION DeviceDescription;
  35. ULONG MapRegisters, SGMapRegsisters;
  36. NDIS_STATUS Status = NDIS_STATUS_NOT_SUPPORTED;
  37. NTSTATUS NtStatus;
  38. ULONG ScatterGatherListSize;
  39. BOOLEAN DereferenceDmaAdapter = FALSE;
  40. BOOLEAN FreeSGListLookasideList = FALSE;
  41. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  42. ("==>NdisMInitializeScatterGatherDma: Miniport %lx, Dma64BitAddresses %lx, MaximumPhysicalMapping 0x%lx\n",
  43. Miniport, Dma64BitAddresses, MaximumPhysicalMapping));
  44. do
  45. {
  46. if (!MINIPORT_TEST_FLAGS(Miniport, fMINIPORT_IS_NDIS_5 | fMINIPORT_BUS_MASTER))
  47. {
  48. Status = NDIS_STATUS_NOT_SUPPORTED;
  49. break;
  50. }
  51. if (MINIPORT_VERIFY_TEST_FLAG(Miniport, fMINIPORT_VERIFY_FAIL_INIT_SG))
  52. {
  53. Status = NDIS_STATUS_RESOURCES;
  54. break;
  55. }
  56. NdisZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));
  57. DeviceDescription.Master = TRUE;
  58. DeviceDescription.ScatterGather = TRUE;
  59. DeviceDescription.BusNumber = Miniport->BusNumber;
  60. DeviceDescription.DmaChannel = 0;
  61. DeviceDescription.InterfaceType = Miniport->AdapterType;
  62. if (Dma64BitAddresses)
  63. {
  64. DeviceDescription.Dma32BitAddresses = FALSE;
  65. DeviceDescription.Dma64BitAddresses = TRUE;
  66. MINIPORT_SET_FLAG(Miniport, fMINIPORT_64BITS_DMA);
  67. }
  68. else
  69. {
  70. DeviceDescription.Dma32BitAddresses = TRUE;
  71. DeviceDescription.Dma64BitAddresses = FALSE;
  72. }
  73. if (((MaximumPhysicalMapping * 2 - 2) / PAGE_SIZE) + 2 < Miniport->SGMapRegistersNeeded)
  74. {
  75. DeviceDescription.MaximumLength = (Miniport->SGMapRegistersNeeded - 1) << PAGE_SHIFT;
  76. }
  77. else
  78. {
  79. DeviceDescription.MaximumLength = MaximumPhysicalMapping*2;
  80. }
  81. DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION2;
  82. //
  83. // Get the adapter object.
  84. //
  85. Miniport->SystemAdapterObject = IoGetDmaAdapter(Miniport->PhysicalDeviceObject,
  86. &DeviceDescription,
  87. &MapRegisters);
  88. if (Miniport->SystemAdapterObject == NULL)
  89. {
  90. NdisWriteErrorLogEntry((NDIS_HANDLE)Miniport,
  91. NDIS_ERROR_CODE_OUT_OF_RESOURCES,
  92. 1,
  93. 0xFFFFFFFF);
  94. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_ERR,
  95. ("NdisMInitializeScatterGatherDma: Miniport %lx, IoGetDmaAdapter failed\n", Miniport));
  96. Status = NDIS_STATUS_RESOURCES;
  97. break;
  98. }
  99. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  100. ("NdisMInitializeScatterGatherDma: Miniport %lx, MapRegisters 0x%lx\n", Miniport, MapRegisters));
  101. InterlockedIncrement(&Miniport->DmaAdapterRefCount);
  102. DereferenceDmaAdapter = TRUE;
  103. if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  104. {
  105. Miniport->SendCompleteHandler = ndisMSendCompleteSG;
  106. }
  107. Miniport->SGListLookasideList = (PNPAGED_LOOKASIDE_LIST)ALLOC_FROM_POOL(sizeof(NPAGED_LOOKASIDE_LIST), NDIS_TAG_DMA);
  108. if (Miniport->SGListLookasideList == NULL)
  109. {
  110. Status = NDIS_STATUS_RESOURCES;
  111. break;
  112. }
  113. FreeSGListLookasideList = TRUE;
  114. NtStatus = Miniport->SystemAdapterObject->DmaOperations->CalculateScatterGatherList(
  115. Miniport->SystemAdapterObject,
  116. NULL,
  117. 0,
  118. MapRegisters * PAGE_SIZE,
  119. &ScatterGatherListSize,
  120. &SGMapRegsisters);
  121. ASSERT(NT_SUCCESS(NtStatus));
  122. ASSERT(SGMapRegsisters == MapRegisters);
  123. if (!NT_SUCCESS(NtStatus))
  124. {
  125. Status = NDIS_STATUS_RESOURCES;
  126. break;
  127. }
  128. Miniport->ScatterGatherListSize = ScatterGatherListSize;
  129. ExInitializeNPagedLookasideList(Miniport->SGListLookasideList,
  130. NULL,
  131. NULL,
  132. 0,
  133. ScatterGatherListSize,
  134. NDIS_TAG_DMA,
  135. 0);
  136. Status = NDIS_STATUS_SUCCESS;
  137. MINIPORT_SET_FLAG(Miniport, fMINIPORT_SG_LIST);
  138. Miniport->InfoFlags |= NDIS_MINIPORT_SG_LIST;
  139. DereferenceDmaAdapter = FALSE;
  140. FreeSGListLookasideList = FALSE;
  141. }while (FALSE);
  142. if (DereferenceDmaAdapter)
  143. {
  144. ndisDereferenceDmaAdapter(Miniport);
  145. }
  146. if (FreeSGListLookasideList && Miniport->SGListLookasideList)
  147. {
  148. ExDeleteNPagedLookasideList(Miniport->SGListLookasideList);
  149. FREE_POOL(Miniport->SGListLookasideList);
  150. Miniport->SGListLookasideList = NULL;
  151. }
  152. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  153. ("<==NdisMInitializeScatterGatherDma: Miniport %lx, Status %lx\n", Miniport, Status));
  154. return(Status);
  155. }
  156. VOID
  157. FASTCALL
  158. ndisMAllocSGList(
  159. IN PNDIS_MINIPORT_BLOCK Miniport,
  160. IN PNDIS_PACKET Packet
  161. )
  162. /*++
  163. Routine Description:
  164. Arguments:
  165. Return Value:
  166. None.
  167. --*/
  168. {
  169. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  170. PNDIS_BUFFER Buffer;
  171. PVOID pBufferVa;
  172. ULONG PacketLength;
  173. PNDIS_BUFFER pNdisBuffer = NULL;
  174. PVOID SGListBuffer;
  175. KIRQL OldIrql;
  176. NdisQueryPacket(Packet, NULL, NULL, &Buffer, &PacketLength);
  177. pBufferVa = MmGetMdlVirtualAddress(Buffer);
  178. SGListBuffer = ExAllocateFromNPagedLookasideList(Miniport->SGListLookasideList);
  179. //
  180. // Callers of GetScatterGatherList must be at dispatch.
  181. //
  182. RAISE_IRQL_TO_DISPATCH(&OldIrql);
  183. if (SGListBuffer)
  184. {
  185. Packet->Private.Flags = NdisGetPacketFlags(Packet) | NDIS_FLAGS_USES_SG_BUFFER_LIST;
  186. NDIS_DOUBLE_BUFFER_INFO_FROM_PACKET(Packet) = SGListBuffer;
  187. Status = Miniport->SystemAdapterObject->DmaOperations->BuildScatterGatherList(
  188. Miniport->SystemAdapterObject,
  189. Miniport->DeviceObject,
  190. Buffer,
  191. pBufferVa,
  192. PacketLength,
  193. ndisMProcessSGList,
  194. Packet,
  195. TRUE,
  196. SGListBuffer,
  197. Miniport->ScatterGatherListSize);
  198. if (!NT_SUCCESS(Status))
  199. {
  200. NDIS_DOUBLE_BUFFER_INFO_FROM_PACKET(Packet) = NULL;
  201. NdisClearPacketFlags(Packet, NDIS_FLAGS_USES_SG_BUFFER_LIST);
  202. ExFreeToNPagedLookasideList(Miniport->SGListLookasideList, SGListBuffer);
  203. }
  204. }
  205. else
  206. {
  207. Status = NDIS_STATUS_RESOURCES;
  208. }
  209. if (!NT_SUCCESS(Status))
  210. {
  211. Status = Miniport->SystemAdapterObject->DmaOperations->GetScatterGatherList(
  212. Miniport->SystemAdapterObject,
  213. Miniport->DeviceObject,
  214. Buffer,
  215. pBufferVa,
  216. PacketLength,
  217. ndisMProcessSGList,
  218. Packet,
  219. TRUE);
  220. }
  221. LOWER_IRQL(OldIrql, DISPATCH_LEVEL);
  222. if (!NT_SUCCESS(Status))
  223. {
  224. PCHAR NewBuffer;
  225. UINT BytesCopied;
  226. do
  227. {
  228. //
  229. // Allocate a buffer for the packet.
  230. //
  231. NewBuffer = (PUCHAR)ALLOC_FROM_POOL(PacketLength, NDIS_TAG_DOUBLE_BUFFER_PKT);
  232. if (NULL == NewBuffer)
  233. {
  234. Status = NDIS_STATUS_RESOURCES;
  235. break;
  236. }
  237. //
  238. // Allocate an MDL for the buffer
  239. //
  240. NdisAllocateBuffer(&Status, &pNdisBuffer, NULL, (PVOID)NewBuffer, PacketLength);
  241. if (NDIS_STATUS_SUCCESS != Status)
  242. {
  243. break;
  244. }
  245. ndisMCopyFromPacketToBuffer(Packet, // Packet to copy from.
  246. 0, // Offset from beginning of packet.
  247. PacketLength, // Number of bytes to copy.
  248. NewBuffer, // The destination buffer.
  249. &BytesCopied); // The number of bytes copied.
  250. Packet->Private.Flags = NdisGetPacketFlags(Packet) | NDIS_FLAGS_DOUBLE_BUFFERED;
  251. pBufferVa = MmGetMdlVirtualAddress(pNdisBuffer);
  252. NDIS_DOUBLE_BUFFER_INFO_FROM_PACKET(Packet) = pNdisBuffer;
  253. RAISE_IRQL_TO_DISPATCH(&OldIrql);
  254. Status = Miniport->SystemAdapterObject->DmaOperations->GetScatterGatherList(
  255. Miniport->SystemAdapterObject,
  256. Miniport->DeviceObject,
  257. pNdisBuffer,
  258. pBufferVa,
  259. PacketLength,
  260. ndisMProcessSGList,
  261. Packet,
  262. TRUE);
  263. LOWER_IRQL(OldIrql, DISPATCH_LEVEL);
  264. }while (FALSE);
  265. if (!NT_SUCCESS(Status))
  266. {
  267. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  268. ("ndisMAllocSGList: GetScatterGatherList failed %lx\n", Status));
  269. if (pNdisBuffer)
  270. {
  271. NdisFreeBuffer(pNdisBuffer);
  272. }
  273. if (NewBuffer)
  274. {
  275. FREE_POOL(NewBuffer);
  276. }
  277. NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, ScatterGatherListPacketInfo) = NULL;
  278. NDIS_DOUBLE_BUFFER_INFO_FROM_PACKET(Packet) = NULL;
  279. NdisClearPacketFlags(Packet, NDIS_FLAGS_DOUBLE_BUFFERED);
  280. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IS_CO))
  281. {
  282. PNDIS_STACK_RESERVED NSR;
  283. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR);
  284. NdisMCoSendComplete(NDIS_STATUS_FAILURE, NSR->VcPtr, Packet);
  285. }
  286. else
  287. {
  288. ndisMSendCompleteX(Miniport, Packet, NDIS_STATUS_FAILURE);
  289. }
  290. }
  291. }
  292. }
  293. VOID
  294. FASTCALL
  295. ndisMFreeSGList(
  296. IN PNDIS_MINIPORT_BLOCK Miniport,
  297. IN PNDIS_PACKET Packet
  298. )
  299. /*++
  300. Routine Description:
  301. Arguments:
  302. Return Value:
  303. None.
  304. --*/
  305. {
  306. PSCATTER_GATHER_LIST pSGL;
  307. PVOID SGListBuffer;
  308. pSGL = NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, ScatterGatherListPacketInfo);
  309. ASSERT(pSGL != NULL);
  310. NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, ScatterGatherListPacketInfo) = NULL;
  311. ASSERT(CURRENT_IRQL == DISPATCH_LEVEL);
  312. Miniport->SystemAdapterObject->DmaOperations->PutScatterGatherList(Miniport->SystemAdapterObject,
  313. pSGL,
  314. TRUE);
  315. if (NdisGetPacketFlags(Packet) & NDIS_FLAGS_USES_SG_BUFFER_LIST)
  316. {
  317. NdisClearPacketFlags(Packet, NDIS_FLAGS_USES_SG_BUFFER_LIST);
  318. SGListBuffer = NDIS_DOUBLE_BUFFER_INFO_FROM_PACKET(Packet);
  319. NDIS_DOUBLE_BUFFER_INFO_FROM_PACKET(Packet) = NULL;
  320. ASSERT(SGListBuffer != NULL);
  321. ExFreeToNPagedLookasideList(Miniport->SGListLookasideList, SGListBuffer);
  322. }
  323. else if (NdisGetPacketFlags(Packet) & NDIS_FLAGS_DOUBLE_BUFFERED)
  324. {
  325. PNDIS_BUFFER DoubleBuffer;
  326. PVOID Buffer;
  327. NdisClearPacketFlags(Packet, NDIS_FLAGS_DOUBLE_BUFFERED);
  328. DoubleBuffer = NDIS_DOUBLE_BUFFER_INFO_FROM_PACKET(Packet);
  329. NDIS_DOUBLE_BUFFER_INFO_FROM_PACKET(Packet) = NULL;
  330. ASSERT(DoubleBuffer != NULL);
  331. Buffer = MmGetMdlVirtualAddress(DoubleBuffer);
  332. NdisFreeBuffer(DoubleBuffer);
  333. FREE_POOL(Buffer);
  334. }
  335. }
  336. VOID
  337. ndisMProcessSGList(
  338. IN PDEVICE_OBJECT pDO,
  339. IN PIRP pIrp,
  340. IN PSCATTER_GATHER_LIST pSGL,
  341. IN PVOID Context
  342. )
  343. /*++
  344. Routine Description:
  345. Arguments:
  346. Return Value:
  347. None.
  348. --*/
  349. {
  350. PNDIS_PACKET Packet = (PNDIS_PACKET)Context;
  351. PNDIS_CO_VC_PTR_BLOCK VcPtr;
  352. PNDIS_MINIPORT_BLOCK Miniport;
  353. PNDIS_OPEN_BLOCK Open;
  354. PNDIS_STACK_RESERVED NSR;
  355. ASSERT(CURRENT_IRQL == DISPATCH_LEVEL);
  356. NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, ScatterGatherListPacketInfo) = pSGL;
  357. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR);
  358. Open = NSR->Open;
  359. Miniport = Open->MiniportHandle;
  360. //
  361. // Handle Send/SendPacket differently
  362. //
  363. MINIPORT_SET_PACKET_FLAG(Packet, fPACKET_PENDING);
  364. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IS_CO))
  365. {
  366. VcPtr = NSR->VcPtr;
  367. (*VcPtr->WCoSendPacketsHandler)(VcPtr->MiniportContext,
  368. &Packet,
  369. 1);
  370. }
  371. else if (MINIPORT_TEST_SEND_FLAG(Miniport, fMINIPORT_SEND_PACKET_ARRAY))
  372. {
  373. //
  374. // Pass the packet down to the miniport.
  375. //
  376. (Open->WSendPacketsHandler)(Miniport->MiniportAdapterContext,
  377. &Packet,
  378. 1);
  379. }
  380. else
  381. {
  382. ULONG Flags;
  383. NDIS_STATUS Status;
  384. NdisQuerySendFlags(Packet, &Flags);
  385. Status = (Open->WSendHandler)(Open->MiniportAdapterContext, Packet, Flags);
  386. if (Status != NDIS_STATUS_PENDING)
  387. {
  388. ndisMSendCompleteX(Miniport, Packet, Status);
  389. }
  390. }
  391. }
  392. VOID
  393. FASTCALL
  394. ndisMAllocSGListS(
  395. IN PNDIS_MINIPORT_BLOCK Miniport,
  396. IN PNDIS_PACKET Packet
  397. )
  398. /*++
  399. Routine Description:
  400. Allocate SG list for packets sent on a serialized miniport
  401. Arguments:
  402. Miniport
  403. Packet
  404. Return Value:
  405. None.
  406. --*/
  407. {
  408. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  409. PNDIS_BUFFER Buffer;
  410. PVOID pBufferVa;
  411. ULONG PacketLength;
  412. PNDIS_BUFFER pNdisBuffer = NULL;
  413. PVOID SGListBuffer;
  414. KIRQL OldIrql;
  415. NdisQueryPacket(Packet, NULL, NULL, &Buffer, &PacketLength);
  416. pBufferVa = MmGetMdlVirtualAddress(Buffer);
  417. SGListBuffer = ExAllocateFromNPagedLookasideList(Miniport->SGListLookasideList);
  418. //
  419. // Callers of GetScatterGatherList must be at dispatch.
  420. //
  421. RAISE_IRQL_TO_DISPATCH(&OldIrql);
  422. if (SGListBuffer)
  423. {
  424. Packet->Private.Flags = NdisGetPacketFlags(Packet) | NDIS_FLAGS_USES_SG_BUFFER_LIST;
  425. NDIS_DOUBLE_BUFFER_INFO_FROM_PACKET(Packet) = SGListBuffer;
  426. Status = Miniport->SystemAdapterObject->DmaOperations->BuildScatterGatherList(
  427. Miniport->SystemAdapterObject,
  428. Miniport->DeviceObject,
  429. Buffer,
  430. pBufferVa,
  431. PacketLength,
  432. ndisMProcessSGListS,
  433. Packet,
  434. TRUE,
  435. SGListBuffer,
  436. Miniport->ScatterGatherListSize);
  437. if (!NT_SUCCESS(Status))
  438. {
  439. NDIS_DOUBLE_BUFFER_INFO_FROM_PACKET(Packet) = NULL;
  440. NdisClearPacketFlags(Packet, NDIS_FLAGS_USES_SG_BUFFER_LIST);
  441. ExFreeToNPagedLookasideList(Miniport->SGListLookasideList, SGListBuffer);
  442. }
  443. }
  444. else
  445. {
  446. Status = NDIS_STATUS_RESOURCES;
  447. }
  448. if (!NT_SUCCESS(Status))
  449. {
  450. Status = Miniport->SystemAdapterObject->DmaOperations->GetScatterGatherList(
  451. Miniport->SystemAdapterObject,
  452. Miniport->DeviceObject,
  453. Buffer,
  454. pBufferVa,
  455. PacketLength,
  456. ndisMProcessSGListS,
  457. Packet,
  458. TRUE);
  459. }
  460. LOWER_IRQL(OldIrql, DISPATCH_LEVEL);
  461. if (!NT_SUCCESS(Status))
  462. {
  463. PCHAR NewBuffer;
  464. UINT BytesCopied;
  465. //
  466. // probably the packet was too fragmented and we couldn't allocate enough
  467. // map registers. try to double buffer the packet.
  468. //
  469. do
  470. {
  471. //
  472. // Allocate a buffer for the packet.
  473. //
  474. NewBuffer = (PUCHAR)ALLOC_FROM_POOL(PacketLength, NDIS_TAG_DOUBLE_BUFFER_PKT);
  475. if (NULL == NewBuffer)
  476. {
  477. Status = NDIS_STATUS_RESOURCES;
  478. break;
  479. }
  480. //
  481. // Allocate an MDL for the buffer
  482. //
  483. NdisAllocateBuffer(&Status, &pNdisBuffer, NULL, (PVOID)NewBuffer, PacketLength);
  484. if (NDIS_STATUS_SUCCESS != Status)
  485. {
  486. break;
  487. }
  488. ndisMCopyFromPacketToBuffer(Packet, // Packet to copy from.
  489. 0, // Offset from beginning of packet.
  490. PacketLength, // Number of bytes to copy.
  491. NewBuffer, // The destination buffer.
  492. &BytesCopied); // The number of bytes copied.
  493. Packet->Private.Flags = NdisGetPacketFlags(Packet) | NDIS_FLAGS_DOUBLE_BUFFERED;
  494. pBufferVa = MmGetMdlVirtualAddress(pNdisBuffer);
  495. NDIS_DOUBLE_BUFFER_INFO_FROM_PACKET(Packet) = pNdisBuffer;
  496. RAISE_IRQL_TO_DISPATCH(&OldIrql);
  497. Status = Miniport->SystemAdapterObject->DmaOperations->GetScatterGatherList(
  498. Miniport->SystemAdapterObject,
  499. Miniport->DeviceObject,
  500. pNdisBuffer,
  501. pBufferVa,
  502. PacketLength,
  503. ndisMProcessSGListS,
  504. Packet,
  505. TRUE);
  506. LOWER_IRQL(OldIrql, DISPATCH_LEVEL);
  507. }while (FALSE);
  508. if (!NT_SUCCESS(Status))
  509. {
  510. PNDIS_STACK_RESERVED NSR;
  511. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  512. ("ndisMAllocSGList: GetScatterGatherList failed %lx\n", Status));
  513. if (pNdisBuffer)
  514. {
  515. NdisFreeBuffer(pNdisBuffer);
  516. }
  517. if (NewBuffer)
  518. {
  519. FREE_POOL(NewBuffer);
  520. }
  521. NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, ScatterGatherListPacketInfo) = NULL;
  522. NDIS_DOUBLE_BUFFER_INFO_FROM_PACKET(Packet) = NULL;
  523. NdisClearPacketFlags(Packet, NDIS_FLAGS_DOUBLE_BUFFERED);
  524. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  525. //
  526. // complete the send, don't unlink the packet since it was never
  527. // linked to begin with.
  528. //
  529. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR);
  530. NDISM_COMPLETE_SEND_SG(Miniport, Packet, NSR, Status, TRUE, 0, FALSE);
  531. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  532. }
  533. }
  534. }
  535. VOID
  536. ndisMProcessSGListS(
  537. IN PDEVICE_OBJECT pDO,
  538. IN PIRP pIrp,
  539. IN PSCATTER_GATHER_LIST pSGL,
  540. IN PVOID Context
  541. )
  542. /*++
  543. Routine Description:
  544. Arguments:
  545. Return Value:
  546. None.
  547. --*/
  548. {
  549. PNDIS_PACKET Packet = (PNDIS_PACKET)Context;
  550. PNDIS_MINIPORT_BLOCK Miniport;
  551. PNDIS_OPEN_BLOCK Open;
  552. PNDIS_STACK_RESERVED NSR;
  553. BOOLEAN LocalLock;
  554. ASSERT(CURRENT_IRQL == DISPATCH_LEVEL);
  555. NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, ScatterGatherListPacketInfo) = pSGL;
  556. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR);
  557. Open = NSR->Open;
  558. Miniport = Open->MiniportHandle;
  559. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC (Miniport);
  560. //
  561. // queue the packet
  562. //
  563. LINK_PACKET_SG(Miniport, Packet, NSR);
  564. if (Miniport->FirstPendingPacket == NULL)
  565. {
  566. Miniport->FirstPendingPacket = Packet;
  567. }
  568. //
  569. // If we have the local lock and there is no
  570. // packet pending, then fire off a send.
  571. //
  572. LOCK_MINIPORT(Miniport, LocalLock);
  573. NDISM_QUEUE_WORK_ITEM(Miniport, NdisWorkItemSend, NULL);
  574. if (LocalLock)
  575. {
  576. NDISM_PROCESS_DEFERRED(Miniport);
  577. }
  578. UNLOCK_MINIPORT(Miniport, LocalLock);
  579. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  580. }