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.

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