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.

362 lines
10 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 sends the flag byte at the
  120. // end always. This means that 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 =
  129. AsyncInfo->ExtendedACCM[0] = 0xFFFFFFFF;
  130. DbgTracef(-1,("ASYNC: PPP framing detected\n"));
  131. }
  132. else {
  133. //
  134. // Read again!
  135. //
  136. DbgTracef(-1,("ASYNC: No framing detected yet\n"));
  137. DbgTracef(-1,("ASYNC: Got %.2x %.2x %.2x %.2x %.2x %.2x\n",
  138. frameStart[0],
  139. frameStart[1],
  140. frameStart[2],
  141. frameStart[3],
  142. frameStart[4],
  143. frameStart[5]));
  144. break;
  145. }
  146. //
  147. // set framing mode active
  148. //
  149. pInfo->PortState = PORT_FRAMING;
  150. //
  151. // Send off the worker thread to start reading frames
  152. // off this port - we want to be at passive level otherwise
  153. // it don't work.
  154. //
  155. ExInitializeWorkItem(&(pInfo->WorkItem),
  156. (PWORKER_THREAD_ROUTINE)AsyncStartReads,
  157. pInfo);
  158. ExQueueWorkItem(&(pInfo->WorkItem), DelayedWorkQueue);
  159. return(STATUS_MORE_PROCESSING_REQUIRED);
  160. case STATUS_TIMEOUT:
  161. DbgTracef(-1,("---ASYNC: detect Status %x%0.8x on read\n", status));
  162. break;
  163. case STATUS_CANCELLED:
  164. case STATUS_PORT_DISCONNECTED:
  165. default:
  166. return(STATUS_MORE_PROCESSING_REQUIRED);
  167. }
  168. //
  169. // Wipe out rest of this buffer
  170. //
  171. SerialFlushReads(pInfo);
  172. KeClearEvent(&pInfo->DetectEvent);
  173. //
  174. // Here we are at the end of processing this IRP so we go
  175. // ahead and post another read from the serial port.
  176. //
  177. // this is done on a worker since we run out of stack otherwise
  178. //
  179. ExInitializeWorkItem(&(pInfo->WorkItem),
  180. (PWORKER_THREAD_ROUTINE) AsyncDetectRead,
  181. pInfo);
  182. ExQueueWorkItem(&(pInfo->WorkItem), DelayedWorkQueue);
  183. // We return STATUS_MORE_PROCESSING_REQUIRED so that the
  184. // IoCompletionRoutine will stop working on the IRP.
  185. //
  186. return(STATUS_MORE_PROCESSING_REQUIRED);
  187. }
  188. NTSTATUS
  189. AsyncDetectRead(
  190. IN PASYNC_INFO pInfo)
  191. /*++
  192. --*/
  193. {
  194. NTSTATUS status;
  195. PIRP irp;
  196. PDEVICE_OBJECT deviceObject=pInfo->DeviceObject;
  197. PFILE_OBJECT fileObject=pInfo->FileObject;
  198. PIO_STACK_LOCATION irpSp;
  199. PASYNC_FRAME pFrame;
  200. PASYNC_ADAPTER pAdapter=pInfo->Adapter;
  201. DbgTracef(-1,("Entering AsyncDetectRead\n"));
  202. do {
  203. if (pInfo->PortState == PORT_CLOSING ||
  204. pInfo->PortState == PORT_CLOSED) {
  205. status = STATUS_SUCCESS;
  206. break;
  207. }
  208. // get ptr to first frame in list...
  209. pFrame=pInfo->AsyncFrame;
  210. irp =
  211. IoAllocateIrp(pInfo->DeviceObject->StackSize, (BOOLEAN)FALSE);
  212. // Setup this irp with defaults
  213. AsyncSetupIrp(pFrame, irp);
  214. irp->AssociatedIrp.SystemBuffer =
  215. irp->UserBuffer =
  216. pFrame->Frame + PPP_PADDING;
  217. //
  218. // Get a pointer to the stack location for the first driver. This will be
  219. // used to pass the original function codes and parameters.
  220. //
  221. irpSp = IoGetNextIrpStackLocation(irp);
  222. irpSp->MajorFunction = IRP_MJ_READ;
  223. irpSp->FileObject = fileObject;
  224. if (fileObject->Flags & FO_WRITE_THROUGH) {
  225. irpSp->Flags = SL_WRITE_THROUGH;
  226. }
  227. //
  228. // If this write operation is to be performed without any caching, set the
  229. // appropriate flag in the IRP so no caching is performed.
  230. //
  231. irp->Flags |= IRP_READ_OPERATION;
  232. if (fileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) {
  233. irp->Flags |= IRP_NOCACHE;
  234. }
  235. //
  236. // Copy the caller's parameters to the service-specific portion of the
  237. // IRP.
  238. //
  239. irpSp->Parameters.Read.Length = 6; // from frame...
  240. irpSp->Parameters.Read.Key = 0; // we don't use a key
  241. irpSp->Parameters.Read.ByteOffset = fileObject->CurrentByteOffset;
  242. IoSetCompletionRoutine(
  243. irp, // irp to use
  244. AsyncDetectCompletionRoutine, // routine to call when irp is done
  245. pInfo, // context to pass routine
  246. TRUE, // call on success
  247. TRUE, // call on error
  248. TRUE); // call on cancel
  249. //
  250. // We DO NOT insert the packet at the head of the IRP list for the thread.
  251. // because we do NOT really have an IoCompletionRoutine that does
  252. // anything with the thread.
  253. //
  254. //
  255. // Now simply invoke the driver at its dispatch entry with the IRP.
  256. //
  257. status = IoCallDriver(deviceObject, irp);
  258. } while (FALSE);
  259. KeSetEvent(&pInfo->DetectEvent,
  260. 1,
  261. FALSE);
  262. return(status);
  263. }