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.

270 lines
8.6 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. serial.c
  5. Abstract: Functions to talk to the serial port.
  6. Environment:
  7. Kernel mode
  8. Author:
  9. Michael Tsang (MikeTs) 23-Mar-2000
  10. Revision History:
  11. --*/
  12. #include "pch.h"
  13. #ifdef ALLOC_PRAGMA
  14. #pragma alloc_text(PAGE, SerialSyncSendIoctl)
  15. #pragma alloc_text(PAGE, SerialSyncReadWritePort)
  16. #endif /* ALLOC_PRAGMA */
  17. /*****************************************************************************
  18. *
  19. * @doc INTERNAL
  20. *
  21. * @func NTSTATUS | SerialSyncSendIoctl |
  22. * Performs a synchronous ioctl request to the serial port.
  23. *
  24. * @parm IN ULONG | IoctlCode | ioctl code.
  25. * @parm IN PDEVICE_OBJECT | DevObj | Points to the device object.
  26. * @parm IN PVOID | InBuffer OPTIONAL | Points to the input buffer.
  27. * @parm IN ULONG | InBufferLen | Specifies the size of the input buffer.
  28. * @parm OUT PVOID | OutBuffer OPTIONAL | Points to the output buffer.
  29. * @parm IN ULONG | OutBufferLen | Specifies the size of the output buffer.
  30. * @parm IN BOOLEAN | fInternal | If TRUE, an internal ioctl is sent.
  31. * @parm OUT PIO_STATUS_BLOCK | Iosb | Points to the io status block.
  32. *
  33. * @rvalue SUCCESS | returns STATUS_SUCCESS
  34. * @rvalue FAILURE | returns NT status code
  35. *
  36. *****************************************************************************/
  37. NTSTATUS INTERNAL
  38. SerialSyncSendIoctl(
  39. IN ULONG IoctlCode,
  40. IN PDEVICE_OBJECT DevObj,
  41. IN PVOID InBuffer OPTIONAL,
  42. IN ULONG InBufferLen,
  43. OUT PVOID OutBuffer OPTIONAL,
  44. IN ULONG OutBufferLen,
  45. IN BOOLEAN fInternal,
  46. OUT PIO_STATUS_BLOCK Iosb
  47. )
  48. {
  49. PROCNAME("SerialSyncSendIoctl")
  50. NTSTATUS status = STATUS_SUCCESS;
  51. KEVENT event;
  52. PIRP irp;
  53. PAGED_CODE();
  54. ENTER(3, ("(Ioctl=%s,DevObj=%p,InBuff=%p,InLen=%d,OutBuff=%p,OutLen=%d,fInternal=%x,Iosb=%p)\n",
  55. LookupName(IoctlCode,
  56. fInternal? SerialInternalIoctlNames: SerialIoctlNames),
  57. DevObj, InBuffer, InBufferLen, OutBuffer, OutBufferLen,
  58. fInternal, Iosb));
  59. KeInitializeEvent(&event, NotificationEvent, FALSE);
  60. irp = IoBuildDeviceIoControlRequest(IoctlCode,
  61. DevObj,
  62. InBuffer,
  63. InBufferLen,
  64. OutBuffer,
  65. OutBufferLen,
  66. fInternal,
  67. &event,
  68. Iosb);
  69. if (irp != NULL)
  70. {
  71. status = IoCallDriver(DevObj, irp);
  72. if (status == STATUS_PENDING)
  73. {
  74. status = KeWaitForSingleObject(&event,
  75. Executive,
  76. KernelMode,
  77. FALSE,
  78. NULL);
  79. }
  80. if (status == STATUS_SUCCESS)
  81. {
  82. status = Iosb->Status;
  83. }
  84. }
  85. else
  86. {
  87. ERRPRINT(("failed to build ioctl irp (status=%x)\n", status));
  88. status = STATUS_INSUFFICIENT_RESOURCES;
  89. }
  90. EXIT(3, ("=%x\n", status));
  91. return status;
  92. } //SerialSyncSendIoctl
  93. /*****************************************************************************
  94. *
  95. * @doc INTERNAL
  96. *
  97. * @func NTSTATUS | SerialAsyncReadWritePort |
  98. * Read/Write data from/to the Serial Port asynchornously.
  99. *
  100. * @parm IN BOOLEAN | fRead | If TRUE, the access is a Read.
  101. * @parm IN PDEVICE_EXTENSION | DevExt | Points to the device extension.
  102. * @parm IN PIRP | Irp | Points to an I/O Request Packet.
  103. * @parm IN PUCHAR | Buffer | Points to the data buffer.
  104. * @parm IN ULONG | BuffLen | Specifies the data buffer length.
  105. * @parm IN PIO_COMPLETION_ROUTINE | CompletionRoutine |
  106. * Points to the completion callback routine.
  107. * @parm IN PVOID | Context | Callback context.
  108. *
  109. * @rvalue SUCCESS | returns STATUS_SUCCESS
  110. * @rvalue FAILURE | returns NT status code
  111. *
  112. *****************************************************************************/
  113. NTSTATUS INTERNAL
  114. SerialAsyncReadWritePort(
  115. IN BOOLEAN fRead,
  116. IN PDEVICE_EXTENSION DevExt,
  117. IN PIRP Irp,
  118. IN PUCHAR Buffer,
  119. IN ULONG BuffLen,
  120. IN PIO_COMPLETION_ROUTINE CompletionRoutine,
  121. IN PVOID Context
  122. )
  123. {
  124. PROCNAME("SerialAsyncReadWritePort")
  125. NTSTATUS status;
  126. PIO_STACK_LOCATION irpsp;
  127. ENTER(2, ("(fRead=%x,DevExt=%p,Irp=%p,Buff=%p,BuffLen=%d,pfnCompletion=%p,Context=%p)\n",
  128. fRead, DevExt, Irp, Buffer, BuffLen, CompletionRoutine,
  129. Context));
  130. ASSERT(Buffer != NULL);
  131. ASSERT(BuffLen > 0);
  132. Irp->AssociatedIrp.SystemBuffer = Buffer;
  133. irpsp = IoGetNextIrpStackLocation(Irp);
  134. RtlZeroMemory(irpsp, sizeof(*irpsp));
  135. irpsp->Parameters.Read.Length = BuffLen;
  136. irpsp->Parameters.Read.ByteOffset.QuadPart = 0;
  137. irpsp->MajorFunction = fRead? IRP_MJ_READ: IRP_MJ_WRITE;
  138. IoSetCompletionRoutine(Irp,
  139. CompletionRoutine,
  140. Context,
  141. TRUE,
  142. TRUE,
  143. TRUE);
  144. status = IoCallDriver(DevExt->SerialDevObj, Irp);
  145. EXIT(2, ("=%x\n", status));
  146. return status;
  147. } //SerialAsyncReadWritePort
  148. /*****************************************************************************
  149. *
  150. * @doc INTERNAL
  151. *
  152. * @func NTSTATUS | SerialSyncReadWritePort |
  153. * Read/Write data from/to the Serial Port.
  154. *
  155. * @parm IN BOOLEAN | fRead | If TRUE, the access is a Read.
  156. * @parm IN PDEVICE_EXTENSION | DevExt | Points to the device extension.
  157. * @parm IN PUCHAR | Buffer | Points to the data buffer.
  158. * @parm IN ULONG | BuffLen | Specifies the data buffer length.
  159. * @parm IN PLARGE_INTEGER | Timeout | Points to an optional timeout value
  160. * @parm OUT PULONG | BytesAccessed | Optionally returns number of bytes
  161. * accessed.
  162. *
  163. * @rvalue SUCCESS | returns STATUS_SUCCESS
  164. * @rvalue FAILURE | returns NT status code
  165. *
  166. *****************************************************************************/
  167. NTSTATUS INTERNAL
  168. SerialSyncReadWritePort(
  169. IN BOOLEAN fRead,
  170. IN PDEVICE_EXTENSION DevExt,
  171. IN PUCHAR Buffer,
  172. IN ULONG BuffLen,
  173. IN PLARGE_INTEGER Timeout OPTIONAL,
  174. OUT PULONG BytesAccessed OPTIONAL
  175. )
  176. {
  177. PROCNAME("SerialSyncReadWritePort")
  178. NTSTATUS status;
  179. KEVENT event;
  180. PIRP irp;
  181. LARGE_INTEGER StartingOffset = RtlConvertLongToLargeInteger(0);
  182. IO_STATUS_BLOCK iosb;
  183. PAGED_CODE();
  184. ENTER(2, ("(fRead=%x,DevExt=%p,Buff=%p,BuffLen=%d,pTimeout=%p,pBytesAccessed=%p)\n",
  185. fRead, DevExt, Buffer, BuffLen, Timeout, BytesAccessed));
  186. ASSERT(Buffer != NULL);
  187. ASSERT(BuffLen > 0);
  188. if (BytesAccessed != NULL)
  189. {
  190. *BytesAccessed = 0;
  191. }
  192. KeInitializeEvent(&event, NotificationEvent, FALSE);
  193. irp = IoBuildSynchronousFsdRequest(fRead? IRP_MJ_READ: IRP_MJ_WRITE,
  194. DevExt->SerialDevObj,
  195. Buffer,
  196. BuffLen,
  197. &StartingOffset,
  198. &event,
  199. &iosb);
  200. if (irp != NULL)
  201. {
  202. ENTER(2, (".IoCallDriver(DevObj=%p,Irp=%p)\n",
  203. DevExt->SerialDevObj, irp));
  204. status = IoCallDriver(DevExt->SerialDevObj, irp);
  205. EXIT(2, (".IoCallDriver=%x\n", status));
  206. if (status == STATUS_PENDING)
  207. {
  208. status = KeWaitForSingleObject(&event,
  209. Executive,
  210. KernelMode,
  211. FALSE,
  212. Timeout);
  213. }
  214. if (status == STATUS_SUCCESS)
  215. {
  216. status = iosb.Status;
  217. if (BytesAccessed != NULL)
  218. {
  219. *BytesAccessed = (ULONG)iosb.Information;
  220. }
  221. }
  222. else
  223. {
  224. ERRPRINT(("failed accessing com port (status=%x)\n",
  225. status));
  226. }
  227. }
  228. else
  229. {
  230. ERRPRINT(("failed to allocate synchronous IRP\n"));
  231. status = STATUS_INSUFFICIENT_RESOURCES;
  232. }
  233. EXIT(2, ("=%x (BytesAccessed=%d)\n", status, iosb.Information));
  234. return status;
  235. } //SerialSyncReadWritePort