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.

361 lines
9.7 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. detect.c
  5. Abstract:
  6. Author:
  7. Thomas J. Dimitri (TommyD) 08-May-1992
  8. Environment:
  9. Kernel Mode - Or whatever is the equivalent on OS/2 and DOS.
  10. Revision History:
  11. --*/
  12. #include "asyncall.h"
  13. VOID
  14. SerialFlushReads(
  15. PASYNC_INFO pInfo);
  16. NTSTATUS
  17. AsyncDetectCompletionRoutine(
  18. IN PDEVICE_OBJECT DeviceObject,
  19. IN PIRP Irp,
  20. IN PASYNC_INFO pInfo)
  21. /*++
  22. This is the IO Completion routine for ReadFrame.
  23. --*/
  24. {
  25. NTSTATUS status;
  26. PASYNC_FRAME pFrame;
  27. PUCHAR frameStart;
  28. DbgTracef(-1,("Entering AsyncDetectCompletionRoutine\n"));
  29. status = Irp->IoStatus.Status;
  30. pInfo->BytesRead = (ULONG)Irp->IoStatus.Information;
  31. IoFreeIrp(Irp);
  32. pFrame=pInfo->AsyncFrame;
  33. DbgTracef(2,("DET PortState = %u for Info 0x%.8x\n", pInfo->PortState, pInfo));
  34. //
  35. // check if this port is closing down or already closed
  36. //
  37. if (pInfo->PortState == PORT_CLOSING ||
  38. pInfo->PortState == PORT_CLOSED) {
  39. if (pInfo->PortState == PORT_CLOSED) {
  40. DbgTracef(-2,("ASYNC: Port closed - but still reading on it!\n"));
  41. }
  42. //
  43. // Acknowledge that the port is closed
  44. //
  45. KeSetEvent(
  46. &pInfo->ClosingEvent, // Event
  47. 1, // Priority
  48. (BOOLEAN)FALSE); // Wait (does not follow)
  49. //
  50. // Ok, if this happens, we are shutting down. Stop
  51. // posting reads. Don't make it try to deallocate the irp!
  52. //
  53. return(STATUS_MORE_PROCESSING_REQUIRED);
  54. }
  55. //
  56. // If the port is close and we are still posting reads, something
  57. // is seriously wrong here!
  58. //
  59. if (pInfo->PortState == PORT_CLOSED) {
  60. DbgTracef(-2, ("ASYNC: !!Whoa, I'm reading bytes on a dead port!!\n"));
  61. }
  62. //
  63. // Send off a irp to check comm status
  64. //
  65. AsyncCheckCommStatus(pInfo);
  66. switch (status) {
  67. case STATUS_SUCCESS:
  68. //
  69. // Look at the first byte and see if we can
  70. // detect the framing.
  71. //
  72. frameStart=pFrame->Frame + PPP_PADDING;
  73. //
  74. // NOTE: New RAS framing clients come in with 0x02 not 0x01
  75. //
  76. if (frameStart[0] == SYN && (frameStart[1]==0x01 || frameStart[1] == 0x02)) {
  77. ULONG bytesWanted;
  78. PUCHAR frameStart2;
  79. pInfo->SetLinkInfo.SendFramingBits =
  80. pInfo->SetLinkInfo.RecvFramingBits = RAS_FRAMING;
  81. DbgTracef(-1,("ASYNC: RAS framing detected\n"));
  82. frameStart2=pFrame->Frame+10;
  83. //
  84. // Adjust buffer for old RAS read
  85. //
  86. ASYNC_MOVE_MEMORY(
  87. frameStart2,
  88. frameStart,
  89. 6);
  90. frameStart=frameStart2;
  91. bytesWanted=(frameStart[2]*256)+(frameStart[3]);
  92. if (bytesWanted > (ULONG)(max( pInfo->Adapter->MaxFrameSize, DEFAULT_EXPANDED_PPP_MAX_FRAME_SIZE ))) {
  93. DbgTracef(-1,("---ASYNC: Frame too large -- size: %d!\n", bytesWanted));
  94. //
  95. // set frame start to non-SYN character
  96. //
  97. *frameStart = 0;
  98. pInfo->BytesRead=0;
  99. pInfo->BytesWanted=6;
  100. //
  101. // break added to fix problem where frame has length
  102. // greater than max frame size. This will send us back
  103. // to detect the next frame! Added 10/31/95 by TonyBe.
  104. //
  105. break;
  106. }
  107. // if this is the first we posted, post another to get
  108. // rest of frame.
  109. if (pInfo->BytesRead == 6) {
  110. pInfo->BytesRead=6;
  111. pInfo->BytesWanted=bytesWanted +
  112. // SYN+SOH+LEN+ETX+CRC
  113. 1 + 1 + 2 + 1 + 2 -
  114. 6;
  115. DbgTracef(2,("---Posting second read for %d bytes\n",pInfo->BytesWanted));
  116. }
  117. } else
  118. //
  119. // It turns out that NetManage send the flag byte at the
  120. // end always. This means taht their first frame is wrong.
  121. // Anyway, this throws off the detect routine. So, we
  122. // will be robust and accept frames without the FLAG_BYTE.
  123. //
  124. if ((frameStart[0] == PPP_FLAG_BYTE && frameStart[1]==0xFF) ||
  125. (frameStart[0] == 0xFF && frameStart[1]==PPP_ESC_BYTE)) {
  126. pInfo->SetLinkInfo.SendFramingBits =
  127. pInfo->SetLinkInfo.RecvFramingBits = PPP_FRAMING;
  128. pInfo->SetLinkInfo.SendACCM=0xFFFFFFFF;
  129. DbgTracef(-1,("ASYNC: PPP framing detected\n"));
  130. }
  131. else {
  132. //
  133. // Read again!
  134. //
  135. DbgTracef(-1,("ASYNC: No framing detected yet\n"));
  136. DbgTracef(-1,("ASYNC: Got %.2x %.2x %.2x %.2x %.2x %.2x\n",
  137. frameStart[0],
  138. frameStart[1],
  139. frameStart[2],
  140. frameStart[3],
  141. frameStart[4],
  142. frameStart[5]));
  143. break;
  144. }
  145. //
  146. // set framing mode active
  147. //
  148. pInfo->PortState = PORT_FRAMING;
  149. //
  150. // Send off the worker thread to start reading frames
  151. // off this port - we want to be at passive level otherwise
  152. // it don't work.
  153. //
  154. ExInitializeWorkItem(&(pInfo->WorkItem),
  155. (PWORKER_THREAD_ROUTINE)AsyncStartReads,
  156. pInfo);
  157. ExQueueWorkItem(&(pInfo->WorkItem), DelayedWorkQueue);
  158. return(STATUS_MORE_PROCESSING_REQUIRED);
  159. case STATUS_TIMEOUT:
  160. DbgTracef(-1,("---ASYNC: detect Status %x%0.8x on read\n", status));
  161. break;
  162. case STATUS_CANCELLED:
  163. case STATUS_PORT_DISCONNECTED:
  164. default:
  165. return(STATUS_MORE_PROCESSING_REQUIRED);
  166. }
  167. //
  168. // Wipe out rest of this buffer
  169. //
  170. SerialFlushReads(pInfo);
  171. KeClearEvent(&pInfo->DetectEvent);
  172. //
  173. // Here we are at the end of processing this IRP so we go
  174. // ahead and post another read from the serial port.
  175. //
  176. // this is done on a worker since we run out of stack otherwise
  177. //
  178. ExInitializeWorkItem(&(pInfo->WorkItem),
  179. (PWORKER_THREAD_ROUTINE) AsyncDetectRead,
  180. pInfo);
  181. ExQueueWorkItem(&(pInfo->WorkItem), DelayedWorkQueue);
  182. // We return STATUS_MORE_PROCESSING_REQUIRED so that the
  183. // IoCompletionRoutine will stop working on the IRP.
  184. //
  185. return(STATUS_MORE_PROCESSING_REQUIRED);
  186. }
  187. NTSTATUS
  188. AsyncDetectRead(
  189. IN PASYNC_INFO pInfo)
  190. /*++
  191. --*/
  192. {
  193. NTSTATUS status;
  194. PIRP irp;
  195. PDEVICE_OBJECT deviceObject=pInfo->DeviceObject;
  196. PFILE_OBJECT fileObject=pInfo->FileObject;
  197. PIO_STACK_LOCATION irpSp;
  198. PASYNC_FRAME pFrame;
  199. PASYNC_ADAPTER pAdapter=pInfo->Adapter;
  200. DbgTracef(-1,("Entering AsyncDetectRead\n"));
  201. do {
  202. if (pInfo->PortState == PORT_CLOSING ||
  203. pInfo->PortState == PORT_CLOSED) {
  204. status = STATUS_SUCCESS;
  205. break;
  206. }
  207. // get ptr to first frame in list...
  208. pFrame=pInfo->AsyncFrame;
  209. irp =
  210. IoAllocateIrp(pInfo->DeviceObject->StackSize, (BOOLEAN)FALSE);
  211. // Setup this irp with defaults
  212. AsyncSetupIrp(pFrame, irp);
  213. irp->AssociatedIrp.SystemBuffer =
  214. irp->UserBuffer =
  215. pFrame->Frame + PPP_PADDING;
  216. //
  217. // Get a pointer to the stack location for the first driver. This will be
  218. // used to pass the original function codes and parameters.
  219. //
  220. irpSp = IoGetNextIrpStackLocation(irp);
  221. irpSp->MajorFunction = IRP_MJ_READ;
  222. irpSp->FileObject = fileObject;
  223. if (fileObject->Flags & FO_WRITE_THROUGH) {
  224. irpSp->Flags = SL_WRITE_THROUGH;
  225. }
  226. //
  227. // If this write operation is to be performed without any caching, set the
  228. // appropriate flag in the IRP so no caching is performed.
  229. //
  230. irp->Flags |= IRP_READ_OPERATION;
  231. if (fileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) {
  232. irp->Flags |= IRP_NOCACHE;
  233. }
  234. //
  235. // Copy the caller's parameters to the service-specific portion of the
  236. // IRP.
  237. //
  238. irpSp->Parameters.Read.Length = 6; // from frame...
  239. irpSp->Parameters.Read.Key = 0; // we don't use a key
  240. irpSp->Parameters.Read.ByteOffset = fileObject->CurrentByteOffset;
  241. IoSetCompletionRoutine(
  242. irp, // irp to use
  243. AsyncDetectCompletionRoutine, // routine to call when irp is done
  244. pInfo, // context to pass routine
  245. TRUE, // call on success
  246. TRUE, // call on error
  247. TRUE); // call on cancel
  248. //
  249. // We DO NOT insert the packet at the head of the IRP list for the thread.
  250. // because we do NOT really have an IoCompletionRoutine that does
  251. // anything with the thread.
  252. //
  253. //
  254. // Now simply invoke the driver at its dispatch entry with the IRP.
  255. //
  256. status = IoCallDriver(deviceObject, irp);
  257. } while (FALSE);
  258. KeSetEvent(&pInfo->DetectEvent,
  259. 1,
  260. FALSE);
  261. return(status);
  262. }