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.

626 lines
14 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. read.c
  5. Abstract:
  6. This module contains the code that is very specific to initialization
  7. and unload operations in the irenum driver
  8. Author:
  9. Brian Lieuallen, 7-13-2000
  10. Environment:
  11. Kernel mode
  12. Revision History :
  13. --*/
  14. #include "internal.h"
  15. #include <ntddmodm.h>
  16. #include "ircomm.h"
  17. VOID
  18. LockedMemoryCopy(
  19. PKSPIN_LOCK Lock,
  20. PVOID Destination,
  21. PVOID Source,
  22. ULONG Length
  23. )
  24. {
  25. KIRQL OldIrql;
  26. KeAcquireSpinLock(
  27. Lock,
  28. &OldIrql
  29. );
  30. RtlCopyMemory(
  31. Destination,
  32. Source,
  33. Length
  34. );
  35. KeReleaseSpinLock(
  36. Lock,
  37. OldIrql
  38. );
  39. return;
  40. }
  41. VOID
  42. LockedZeroMemory(
  43. PKSPIN_LOCK Lock,
  44. PVOID Destination,
  45. ULONG Length
  46. )
  47. {
  48. KIRQL OldIrql;
  49. KeAcquireSpinLock(
  50. Lock,
  51. &OldIrql
  52. );
  53. RtlZeroMemory(
  54. Destination,
  55. Length
  56. );
  57. KeReleaseSpinLock(
  58. Lock,
  59. OldIrql
  60. );
  61. return;
  62. }
  63. NTSTATUS
  64. IrCommDeviceControl(
  65. PDEVICE_OBJECT DeviceObject,
  66. PIRP Irp
  67. )
  68. {
  69. PFDO_DEVICE_EXTENSION DeviceExtension=(PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
  70. PIO_STACK_LOCATION IrpSp=IoGetCurrentIrpStackLocation(Irp);
  71. NTSTATUS Status=STATUS_SUCCESS;
  72. PUCHAR SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
  73. ULONG InputLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
  74. ULONG OutputLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  75. ULONG SizeNeeded;
  76. Irp->IoStatus.Information=0;
  77. D_TRACE(DbgPrint("IRCOMM: IrCommDeviceControl\n");)
  78. if (DeviceExtension->Removing) {
  79. //
  80. // the device has been removed, no more irps
  81. //
  82. Irp->IoStatus.Status=STATUS_DEVICE_REMOVED;
  83. IoCompleteRequest(Irp,IO_NO_INCREMENT);
  84. return STATUS_DEVICE_REMOVED;
  85. }
  86. switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
  87. case IOCTL_SERIAL_SET_TIMEOUTS:
  88. if (InputLength >= sizeof(SERIAL_TIMEOUTS)) {
  89. LockedMemoryCopy(
  90. &DeviceExtension->SpinLock,
  91. &DeviceExtension->TimeOuts,
  92. SystemBuffer,
  93. sizeof(SERIAL_TIMEOUTS)
  94. );
  95. break;
  96. }
  97. Status=STATUS_INVALID_PARAMETER;
  98. break;
  99. case IOCTL_SERIAL_GET_TIMEOUTS:
  100. if (OutputLength >= sizeof(SERIAL_TIMEOUTS) ) {
  101. LockedMemoryCopy(
  102. &DeviceExtension->SpinLock,
  103. SystemBuffer,
  104. &DeviceExtension->TimeOuts,
  105. sizeof(SERIAL_TIMEOUTS)
  106. );
  107. Irp->IoStatus.Information=sizeof(SERIAL_TIMEOUTS);
  108. break;
  109. }
  110. Status=STATUS_INVALID_PARAMETER;
  111. break;
  112. case IOCTL_SERIAL_SET_QUEUE_SIZE:
  113. if (InputLength >= sizeof( SERIAL_QUEUE_SIZE)) {
  114. LockedMemoryCopy(
  115. &DeviceExtension->SpinLock,
  116. &DeviceExtension->QueueSizes,
  117. SystemBuffer,
  118. sizeof( SERIAL_QUEUE_SIZE)
  119. );
  120. break;
  121. }
  122. Status=STATUS_INVALID_PARAMETER;
  123. break;
  124. case IOCTL_SERIAL_GET_HANDFLOW:
  125. SizeNeeded=sizeof(SERIAL_HANDFLOW);
  126. if (OutputLength >= SizeNeeded) {
  127. LockedMemoryCopy(
  128. &DeviceExtension->SpinLock,
  129. SystemBuffer,
  130. &DeviceExtension->HandFlow,
  131. SizeNeeded
  132. );
  133. Irp->IoStatus.Information=SizeNeeded;
  134. break;
  135. }
  136. Status=STATUS_INVALID_PARAMETER;
  137. break;
  138. case IOCTL_SERIAL_SET_HANDFLOW:
  139. SizeNeeded=sizeof(SERIAL_HANDFLOW);
  140. if (InputLength >= SizeNeeded) {
  141. LockedMemoryCopy(
  142. &DeviceExtension->SpinLock,
  143. &DeviceExtension->HandFlow,
  144. SystemBuffer,
  145. SizeNeeded
  146. );
  147. break;
  148. }
  149. Status=STATUS_INVALID_PARAMETER;
  150. break;
  151. case IOCTL_SERIAL_GET_BAUD_RATE:
  152. if (OutputLength >= sizeof(ULONG) ) {
  153. IoMarkIrpPending(Irp);
  154. QueuePacket(&DeviceExtension->Uart.Queue,Irp,FALSE);
  155. return STATUS_PENDING;
  156. }
  157. Status=STATUS_INVALID_PARAMETER;
  158. break;
  159. case IOCTL_SERIAL_SET_BAUD_RATE:
  160. if (InputLength >= sizeof(ULONG) ) {
  161. IoMarkIrpPending(Irp);
  162. QueuePacket(&DeviceExtension->Uart.Queue,Irp,FALSE);
  163. return STATUS_PENDING;
  164. }
  165. Status=STATUS_INVALID_PARAMETER;
  166. break;
  167. case IOCTL_SERIAL_GET_LINE_CONTROL:
  168. if (OutputLength >= sizeof(SERIAL_LINE_CONTROL)) {
  169. IoMarkIrpPending(Irp);
  170. QueuePacket(&DeviceExtension->Uart.Queue,Irp,FALSE);
  171. return STATUS_PENDING;
  172. }
  173. Status=STATUS_INVALID_PARAMETER;
  174. break;
  175. case IOCTL_SERIAL_SET_LINE_CONTROL:
  176. if (InputLength >= sizeof(SERIAL_LINE_CONTROL)) {
  177. IoMarkIrpPending(Irp);
  178. QueuePacket(&DeviceExtension->Uart.Queue,Irp,FALSE);
  179. return STATUS_PENDING;
  180. }
  181. Status=STATUS_INVALID_PARAMETER;
  182. break;
  183. case IOCTL_SERIAL_GET_CHARS:
  184. if (OutputLength >= sizeof(SERIAL_CHARS)) {
  185. LockedMemoryCopy(
  186. &DeviceExtension->SpinLock,
  187. SystemBuffer,
  188. &DeviceExtension->SerialChars,
  189. sizeof(SERIAL_CHARS)
  190. );
  191. Irp->IoStatus.Information=sizeof(SERIAL_CHARS);
  192. break;
  193. }
  194. Status=STATUS_INVALID_PARAMETER;
  195. break;
  196. case IOCTL_SERIAL_SET_CHARS:
  197. SizeNeeded=sizeof(SERIAL_CHARS);
  198. if (InputLength >= SizeNeeded) {
  199. LockedMemoryCopy(
  200. &DeviceExtension->SpinLock,
  201. &DeviceExtension->SerialChars,
  202. SystemBuffer,
  203. SizeNeeded
  204. );
  205. break;
  206. }
  207. Status=STATUS_INVALID_PARAMETER;
  208. break;
  209. case IOCTL_SERIAL_GET_WAIT_MASK:
  210. case IOCTL_SERIAL_SET_WAIT_MASK:
  211. case IOCTL_SERIAL_WAIT_ON_MASK:
  212. IoMarkIrpPending(Irp);
  213. Irp->IoStatus.Information=0;
  214. QueuePacket(&DeviceExtension->Mask.Queue,Irp,FALSE);
  215. return STATUS_PENDING;
  216. case IOCTL_SERIAL_GET_MODEMSTATUS:
  217. if (OutputLength >= sizeof(ULONG)) {
  218. IoMarkIrpPending(Irp);
  219. QueuePacket(&DeviceExtension->Uart.Queue,Irp,FALSE);
  220. return STATUS_PENDING;
  221. }
  222. Status=STATUS_INVALID_PARAMETER;
  223. break;
  224. case IOCTL_SERIAL_PURGE:
  225. if (InputLength >= sizeof(ULONG)) {
  226. if (*(PULONG)SystemBuffer & SERIAL_PURGE_TXABORT) {
  227. //
  228. // we only want to flush the write irps in the queue, not any ioctl's
  229. //
  230. FlushQueuedPackets(&DeviceExtension->Write.Queue,IRP_MJ_WRITE);
  231. AbortSend(DeviceExtension->ConnectionHandle);
  232. }
  233. if (*(PULONG)SystemBuffer & SERIAL_PURGE_RXABORT) {
  234. FlushQueuedPackets(&DeviceExtension->Read.Queue,FLUSH_ALL_IRPS);
  235. ReadPurge(DeviceExtension,READ_PURGE_ABORT_IRP);
  236. }
  237. if (*(PULONG)SystemBuffer & SERIAL_PURGE_TXCLEAR) {
  238. }
  239. if (*(PULONG)SystemBuffer & SERIAL_PURGE_RXCLEAR) {
  240. ReadPurge(DeviceExtension,READ_PURGE_CLEAR_BUFFER);
  241. }
  242. break;
  243. }
  244. Status=STATUS_INVALID_PARAMETER;
  245. break;
  246. case IOCTL_SERIAL_SET_DTR:
  247. case IOCTL_SERIAL_CLR_DTR:
  248. DeviceExtension->Read.DtrState= (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_SET_DTR);
  249. case IOCTL_SERIAL_SET_RTS:
  250. case IOCTL_SERIAL_CLR_RTS: {
  251. IoMarkIrpPending(Irp);
  252. QueuePacket(&DeviceExtension->Uart.Queue,Irp,FALSE);
  253. return STATUS_PENDING;
  254. }
  255. case IOCTL_SERIAL_GET_DTRRTS:
  256. SizeNeeded=sizeof(ULONG);
  257. if (OutputLength >= SizeNeeded) {
  258. IoMarkIrpPending(Irp);
  259. QueuePacket(&DeviceExtension->Uart.Queue,Irp,FALSE);
  260. return STATUS_PENDING;
  261. }
  262. Status=STATUS_INVALID_PARAMETER;
  263. break;
  264. case IOCTL_SERIAL_GET_COMMSTATUS:
  265. SizeNeeded=sizeof(SERIAL_STATUS);
  266. if (OutputLength >= SizeNeeded) {
  267. RtlZeroMemory(
  268. SystemBuffer,
  269. SizeNeeded
  270. );
  271. LockedMemoryCopy(
  272. &DeviceExtension->Read.ReadLock,
  273. &((PSERIAL_STATUS)SystemBuffer)->AmountInInQueue,
  274. &DeviceExtension->Read.BytesInBuffer,
  275. sizeof(DeviceExtension->Read.BytesInBuffer)
  276. );
  277. Irp->IoStatus.Information=SizeNeeded;
  278. break;
  279. }
  280. Status=STATUS_INVALID_PARAMETER;
  281. break;
  282. case IOCTL_SERIAL_GET_STATS: {
  283. PSERIALPERF_STATS Stats=(PSERIALPERF_STATS)SystemBuffer;
  284. SizeNeeded=sizeof(SERIAL_STATUS);
  285. if (OutputLength >= SizeNeeded) {
  286. RtlZeroMemory(
  287. Stats,
  288. OutputLength
  289. );
  290. Stats->TransmittedCount = DeviceExtension->Write.BytesWritten;
  291. Stats->ReceivedCount = DeviceExtension->Read.BytesRead;
  292. Irp->IoStatus.Information=SizeNeeded;
  293. break;
  294. }
  295. Status=STATUS_INVALID_PARAMETER;
  296. break;
  297. }
  298. case IOCTL_SERIAL_CLEAR_STATS:
  299. DeviceExtension->Write.BytesWritten=0;
  300. DeviceExtension->Read.BytesRead=0;
  301. break;
  302. case IOCTL_SERIAL_GET_PROPERTIES: {
  303. PSERIAL_COMMPROP SerialProps=(PSERIAL_COMMPROP)SystemBuffer;
  304. SizeNeeded=FIELD_OFFSET(SERIAL_COMMPROP,ProvChar);
  305. if (OutputLength >= SizeNeeded) {
  306. RtlZeroMemory(
  307. SerialProps,
  308. OutputLength
  309. );
  310. SerialProps->PacketLength=(USHORT)SizeNeeded;
  311. SerialProps->PacketVersion=1;
  312. SerialProps->ServiceMask=SERIAL_SP_SERIALCOMM;
  313. SerialProps->MaxBaud=115200;
  314. SerialProps->ProvSubType=SERIAL_SP_RS232;
  315. SerialProps->ProvCapabilities=SERIAL_PCF_DTRDSR | SERIAL_PCF_RTSCTS | SERIAL_PCF_CD | SERIAL_PCF_TOTALTIMEOUTS | SERIAL_PCF_INTTIMEOUTS;
  316. SerialProps->SettableParams=SERIAL_SP_PARITY | SERIAL_SP_BAUD | SERIAL_SP_DATABITS | SERIAL_SP_STOPBITS | SERIAL_SP_HANDSHAKING | SERIAL_SP_CARRIER_DETECT;
  317. SerialProps->SettableBaud=SERIAL_BAUD_9600 |
  318. SERIAL_BAUD_14400 |
  319. SERIAL_BAUD_19200 |
  320. SERIAL_BAUD_38400 |
  321. SERIAL_BAUD_56K |
  322. SERIAL_BAUD_128K |
  323. SERIAL_BAUD_115200 |
  324. SERIAL_BAUD_57600 |
  325. SERIAL_BAUD_USER;
  326. SerialProps->SettableData=SERIAL_DATABITS_7 | SERIAL_DATABITS_8;
  327. SerialProps->SettableStopParity = SERIAL_STOPBITS_10 | SERIAL_PARITY_NONE | SERIAL_PARITY_EVEN | SERIAL_PARITY_ODD;
  328. Irp->IoStatus.Information=SizeNeeded;
  329. break;
  330. }
  331. Status=STATUS_INVALID_PARAMETER;
  332. break;
  333. }
  334. case IOCTL_SERIAL_CONFIG_SIZE:
  335. SizeNeeded=sizeof(ULONG);
  336. if (OutputLength >= SizeNeeded) {
  337. *(PULONG)SystemBuffer=0;
  338. Irp->IoStatus.Information=SizeNeeded;
  339. break;
  340. }
  341. Status=STATUS_INVALID_PARAMETER;
  342. break;
  343. case IOCTL_MODEM_CHECK_FOR_MODEM:
  344. Status=STATUS_INVALID_DEVICE_REQUEST;
  345. break;
  346. default:
  347. DbgPrint("IRCOMM: unhandled ioctl %d \n",(IrpSp->Parameters.DeviceIoControl.IoControlCode >> 2) & 0x3f);
  348. Status=STATUS_INVALID_DEVICE_REQUEST;
  349. break;
  350. }
  351. IoMarkIrpPending(Irp);
  352. Irp->IoStatus.Status=Status;
  353. #if DBG
  354. if (Status == STATUS_INVALID_PARAMETER) {
  355. D_ERROR(DbgPrint("IRCOMM: ioctl irp %d bad param, in size=%d, out size=%d\n",
  356. IrpSp->Parameters.DeviceIoControl.IoControlCode,
  357. InputLength,
  358. OutputLength
  359. );)
  360. }
  361. #endif
  362. IoCompleteRequest(Irp,IO_NO_INCREMENT);
  363. return STATUS_PENDING;
  364. }
  365. VOID
  366. UartComplete(
  367. PVOID Context,
  368. PIRP Irp
  369. )
  370. {
  371. PFDO_DEVICE_EXTENSION DeviceExtension=(PFDO_DEVICE_EXTENSION)Context;
  372. IoCompleteRequest(Irp,IO_NO_INCREMENT);
  373. StartNextPacket(&DeviceExtension->Uart.Queue);
  374. return;
  375. }
  376. VOID
  377. UartStartRoutine(
  378. PVOID Context,
  379. PIRP Irp
  380. )
  381. {
  382. PFDO_DEVICE_EXTENSION DeviceExtension=(PFDO_DEVICE_EXTENSION)Context;
  383. PIO_STACK_LOCATION IrpSp=IoGetCurrentIrpStackLocation(Irp);
  384. AccessUartState(
  385. DeviceExtension->ConnectionHandle,
  386. Irp,
  387. UartComplete,
  388. DeviceExtension
  389. );
  390. return;
  391. }