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.

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