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.

309 lines
7.1 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. send.c
  5. Abstract:
  6. NOTE: ZZZ There is a potential priority inversion problem when
  7. allocating the packet. For nt it looks like we need to raise
  8. the irql to dpc when we start the allocation.
  9. Author:
  10. Thomas J. Dimitri 8-May-1992
  11. Environment:
  12. Kernel Mode - Or whatever is the equivalent on OS/2 and DOS.
  13. Revision History:
  14. Ray Patch (raypa) 04/13/94 Modified for new WAN wrapper.
  15. --*/
  16. #include "asyncall.h"
  17. #include "globals.h"
  18. //
  19. // Forward references.
  20. //
  21. extern
  22. NTSTATUS
  23. AsyncWriteCompletionRoutine(
  24. IN PDEVICE_OBJECT DeviceObject,
  25. IN PIRP Irp,
  26. IN PNDIS_WAN_PACKET WanPacket);
  27. //=============================================================================
  28. // Function:
  29. //
  30. // AsyncSend()
  31. //
  32. // Description:
  33. //
  34. // This function is the main entry point for transmitting data to the serial
  35. // driver. When entered, we get the MAC binding handle (a pointer to our
  36. // private data structure) and the WAN packet which we are going to send.
  37. // We don't bother queuing the frame, we simple allocate an IRP and ship
  38. // it to the serial driver and let him worry about it.
  39. //
  40. // In Parameters:
  41. //
  42. // NdisLinkContext - Pointer to the ASYNC_INFO structure.
  43. //
  44. // Packet - WAN packet containing the data to be framed and shipped.
  45. //
  46. // Out Parameters:
  47. //
  48. // None.
  49. //
  50. // Return status:
  51. //
  52. // NDIS_STATUS_SUCCESS.
  53. //=============================================================================
  54. NDIS_STATUS
  55. MpSend(
  56. IN NDIS_HANDLE MacBindingHandle,
  57. IN NDIS_HANDLE NdisLinkHandle,
  58. IN PNDIS_WAN_PACKET Packet)
  59. {
  60. PASYNC_INFO AsyncInfo;
  61. NDIS_STATUS Status;
  62. DbgTracef(1,("AS\n"));
  63. //
  64. // Get the open handle for this MAC binding.
  65. //
  66. AsyncInfo = (PASYNC_INFO) NdisLinkHandle;
  67. //
  68. // First make sure this link is still up.
  69. //
  70. if (AsyncInfo->PortState == PORT_FRAMING &&
  71. (AsyncInfo->GetLinkInfo.SendFramingBits &
  72. (PPP_FRAMING | SLIP_FRAMING)) != 0)
  73. {
  74. //
  75. // Now we can send this frame.
  76. //
  77. Status = AsyncSendPacket(
  78. NdisLinkHandle,
  79. Packet);
  80. // For all Status values (PENDING, SUCCESS, and ERROR) the callback from Write will
  81. // do a sendcomplete indication so we always return PENDING.
  82. //
  83. Status = STATUS_PENDING ;
  84. }
  85. else
  86. {
  87. DbgTracef(-2,("AsyncSend: Link not found, dropping packet!\n"));
  88. Status = NDIS_STATUS_SUCCESS;
  89. }
  90. return Status;
  91. }
  92. //=============================================================================
  93. // Function:
  94. //
  95. // AsyncSendPacket()
  96. //
  97. // Description:
  98. // This function is called from AsyncSend() to send an IRP to the serial
  99. // driver. If this IRP pends, the the I/O complete routine will be called
  100. // later to complete the request.
  101. //
  102. // In Parameters:
  103. //
  104. // Packet - WAN packet containing the data to be framed and shipped.
  105. //
  106. // Out Parameters:
  107. //
  108. // None.
  109. //
  110. // Return status:
  111. //
  112. // NDIS_STATUS_SUCCESS.
  113. //=============================================================================
  114. NTSTATUS
  115. AsyncSendPacket(
  116. IN PASYNC_INFO AsyncInfo,
  117. IN PNDIS_WAN_PACKET WanPacket)
  118. {
  119. NTSTATUS Status;
  120. PIRP irp;
  121. PIO_STACK_LOCATION irpSp;
  122. PFILE_OBJECT FileObject;
  123. PDEVICE_OBJECT DeviceObject;
  124. PASYNC_ADAPTER Adapter;
  125. UCHAR irpStackSize;
  126. //
  127. // Initialize locals.
  128. //
  129. FileObject = AsyncInfo->FileObject;
  130. DeviceObject = AsyncInfo->DeviceObject;
  131. Adapter = AsyncInfo->Adapter;
  132. irpStackSize = (UCHAR) Adapter->IrpStackSize;
  133. //
  134. // Get irp from irp pool.
  135. //
  136. irp = IoAllocateIrp(DeviceObject->StackSize, (BOOLEAN)FALSE);
  137. //
  138. // The IO subsystem may be out of irps.
  139. //
  140. if (irp == NULL) {
  141. return(NDIS_STATUS_RESOURCES);
  142. }
  143. //
  144. // Tuck pointer to AsyncInfo for completion use
  145. //
  146. WanPacket->MacReserved1 = AsyncInfo;
  147. irp->Tail.Overlay.OriginalFileObject = FileObject;
  148. irp->RequestorMode = KernelMode;
  149. irp->PendingReturned = FALSE;
  150. //
  151. // Fill in the service independent parameters in the IRP.
  152. //
  153. irp->UserEvent = NULL;
  154. //
  155. // 8 byte align (also use end of packet for IOSB).
  156. //
  157. irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
  158. irp->Overlay.AsynchronousParameters.UserApcContext = NULL;
  159. //
  160. // Get a pointer to the stack location for the first driver. This will be
  161. // used to pass the original function codes and parameters.
  162. //
  163. irpSp = IoGetNextIrpStackLocation(irp);
  164. irpSp->MajorFunction = IRP_MJ_WRITE;
  165. irpSp->FileObject = FileObject;
  166. if (FileObject->Flags & FO_WRITE_THROUGH) {
  167. irpSp->Flags = SL_WRITE_THROUGH;
  168. }
  169. //
  170. // If this write operation is to be performed without any caching, set the
  171. // appropriate flag in the IRP so no caching is performed.
  172. //
  173. if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) {
  174. irp->Flags |= (IRP_NOCACHE | IRP_WRITE_OPERATION);
  175. } else {
  176. irp->Flags |= IRP_WRITE_OPERATION;
  177. }
  178. //
  179. // Assemble a RAS, PPP, SLIP frame type.
  180. //
  181. if (AsyncInfo->GetLinkInfo.SendFramingBits & PPP_FRAMING) {
  182. AssemblePPPFrame(WanPacket);
  183. } else
  184. if (AsyncInfo->GetLinkInfo.SendFramingBits & SLIP_FRAMING) {
  185. AssembleSLIPFrame(WanPacket);
  186. }
  187. irp->AssociatedIrp.SystemBuffer =
  188. WanPacket->CurrentBuffer;
  189. DbgTracef(0, ("Writing out %.2x %.2x %.2x %.2x %.2x\n",
  190. WanPacket->CurrentBuffer[0],
  191. WanPacket->CurrentBuffer[1],
  192. WanPacket->CurrentBuffer[2],
  193. WanPacket->CurrentBuffer[3],
  194. WanPacket->CurrentBuffer[4]));
  195. //
  196. // Copy the caller's parameters to the service-specific portion of the IRP.
  197. //
  198. irpSp->Parameters.Write.Length = WanPacket->CurrentLength;
  199. irpSp->Parameters.Write.Key = 0;
  200. irpSp->Parameters.Write.ByteOffset = FileObject->CurrentByteOffset;
  201. //
  202. // Setup IRP for callback.
  203. //
  204. IoSetCompletionRoutine(
  205. irp, // irp to use
  206. AsyncWriteCompletionRoutine, // routine to call when irp is done
  207. WanPacket, // context to pass routine
  208. TRUE, // call on success
  209. TRUE, // call on error
  210. TRUE); // call on cancel
  211. //
  212. // We DO NOT insert the packet at the head of the IRP list for the thread.
  213. // because we do NOT really have an IoCompletionRoutine that does
  214. // anything with the thread or needs to be in that thread's context.
  215. //
  216. GlobalXmitWentOut++;
  217. AsyncInfo->In++;
  218. //
  219. // Now simply invoke the driver at its dispatch entry with the IRP.
  220. //
  221. Status = IoCallDriver(DeviceObject, irp);
  222. // According to TonyE, the status for the serial driver should
  223. // always be STATUS_PENDING. DigiBoard usually STATUS_SUCCESS.
  224. return Status;
  225. }