ReactOS 0.4.16-dev-320-g3bd9ddc
rw.c File Reference
#include "serial.h"
#include <debug.h>
Include dependency graph for rw.c:

Go to the source code of this file.

Functions

static PVOID SerialGetUserBuffer (IN PIRP Irp)
 
static VOID ReadBytes (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, PWORKITEM_DATA WorkItemData)
 
static VOID NTAPI SerialReadWorkItem (IN PDEVICE_OBJECT DeviceObject, IN PVOID pWorkItemData)
 
NTSTATUS NTAPI SerialRead (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
NTSTATUS NTAPI SerialWrite (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 

Variables

static IO_WORKITEM_ROUTINE SerialReadWorkItem
 

Function Documentation

◆ ReadBytes()

static VOID ReadBytes ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp,
PWORKITEM_DATA  WorkItemData 
)
static

Definition at line 28 of file rw.c.

32{
33 PSERIAL_DEVICE_EXTENSION DeviceExtension;
36 UCHAR ReceivedByte;
37 KTIMER TotalTimeoutTimer;
38 KIRQL Irql;
40 PVOID ObjectsArray[2];
43
45 ASSERT(WorkItemData);
46
47 DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
50
51 INFO_(SERIAL, "UseIntervalTimeout = %s, IntervalTimeout = %lu\n",
52 WorkItemData->UseIntervalTimeout ? "YES" : "NO",
53 WorkItemData->UseIntervalTimeout ? WorkItemData->IntervalTimeout.QuadPart : 0);
54 INFO_(SERIAL, "UseTotalTimeout = %s\n",
55 WorkItemData->UseTotalTimeout ? "YES" : "NO");
56
57 ObjectCount = 1;
58 ObjectsArray[0] = &DeviceExtension->InputBufferNotEmpty;
59 if (WorkItemData->UseTotalTimeout)
60 {
61 KeInitializeTimer(&TotalTimeoutTimer);
62 KeSetTimer(&TotalTimeoutTimer, WorkItemData->TotalTimeoutTime, NULL);
63 ObjectsArray[ObjectCount] = &TotalTimeoutTimer;
65 }
66
67 /* while buffer is not fully filled */
68 while (TRUE)
69 {
70 /* read already received bytes from buffer */
71 KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
72 while (!IsCircularBufferEmpty(&DeviceExtension->InputBuffer)
73 && Length > 0)
74 {
75 PopCircularBufferEntry(&DeviceExtension->InputBuffer, &ReceivedByte);
76 INFO_(SERIAL, "Reading byte from buffer: 0x%02x\n", ReceivedByte);
77
78 Buffer[Information++] = ReceivedByte;
79 Length--;
80 }
81 KeClearEvent(&DeviceExtension->InputBufferNotEmpty);
82 KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
83
84 if (Length == 0)
85 {
86 INFO_(SERIAL, "All bytes read\n");
87 break;
88 }
89
90 if (WorkItemData->DontWait
91 && !(WorkItemData->ReadAtLeastOneByte && Information == 0))
92 {
93 INFO_(SERIAL, "Buffer empty. Don't wait more bytes\n");
94 break;
95 }
96
99 ObjectsArray,
100 WaitAny,
101 Executive,
103 FALSE,
104 (WorkItemData->UseIntervalTimeout && Information > 0) ? &WorkItemData->IntervalTimeout : NULL,
105 NULL);
106
107 if (Status == STATUS_TIMEOUT /* interval timeout */
108 || Status == STATUS_WAIT_1) /* total timeout */
109 {
110 TRACE_(SERIAL, "Timeout when reading bytes. Status = 0x%08lx\n", Status);
111 break;
112 }
113 }
114
115 /* stop total timeout timer */
116 if (WorkItemData->UseTotalTimeout)
117 KeCancelTimer(&TotalTimeoutTimer);
118
119 Irp->IoStatus.Information = Information;
120 if (Information == 0)
121 Irp->IoStatus.Status = STATUS_TIMEOUT;
122 else
123 Irp->IoStatus.Status = STATUS_SUCCESS;
124}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN IsCircularBufferEmpty(IN PCIRCULAR_BUFFER pBuffer)
NTSTATUS PopCircularBufferEntry(IN PCIRCULAR_BUFFER pBuffer, OUT PUCHAR Entry)
Definition: bufpool.h:45
LONG ObjectCount
Definition: comsup.c:7
_In_ PIRP Irp
Definition: csq.h:116
_Out_ PKIRQL Irql
Definition: csq.h:179
#define STATUS_TIMEOUT
Definition: d3dkmdt.h:49
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define TRACE_(x)
Definition: compat.h:76
static PVOID SerialGetUserBuffer(IN PIRP Irp)
Definition: rw.c:17
struct _SERIAL_DEVICE_EXTENSION * PSERIAL_DEVICE_EXTENSION
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
Status
Definition: gdiplustypes.h:25
#define ASSERT(a)
Definition: mode.c:44
#define KernelMode
Definition: asm.h:34
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ WaitAny
NTSTATUS NTAPI KeWaitForMultipleObjects(IN ULONG Count, IN PVOID Object[], IN WAIT_TYPE WaitType, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL, OUT PKWAIT_BLOCK WaitBlockArray OPTIONAL)
Definition: wait.c:586
#define STATUS_WAIT_1
Definition: ntstatus.h:71
#define INFO_(ch,...)
Definition: debug.h:159
#define STATUS_SUCCESS
Definition: shellext.h:65
struct _IO_STACK_LOCATION::@3979::@3983 Read
union _IO_STACK_LOCATION::@1580 Parameters
KSPIN_LOCK InputBufferLock
Definition: serial.h:76
KEVENT InputBufferNotEmpty
Definition: serial.h:74
CIRCULAR_BUFFER InputBuffer
Definition: serial.h:75
LARGE_INTEGER TotalTimeoutTime
Definition: serial.h:95
LARGE_INTEGER IntervalTimeout
Definition: serial.h:94
BOOLEAN ReadAtLeastOneByte
Definition: serial.h:97
BOOLEAN UseTotalTimeout
Definition: serial.h:93
BOOLEAN UseIntervalTimeout
Definition: serial.h:92
BOOLEAN DontWait
Definition: serial.h:96
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:281
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
uint32_t ULONG_PTR
Definition: typedefs.h:65
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049
@ Executive
Definition: ketypes.h:415
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by SerialRead(), and SerialReadWorkItem().

◆ SerialGetUserBuffer()

static PVOID SerialGetUserBuffer ( IN PIRP  Irp)
static

Definition at line 17 of file rw.c.

18{
19 ASSERT(Irp);
20
21 if (Irp->MdlAddress)
22 return Irp->MdlAddress;
23 else
24 return Irp->AssociatedIrp.SystemBuffer;
25}

Referenced by ReadBytes(), SerialRead(), and SerialWrite().

◆ SerialRead()

NTSTATUS NTAPI SerialRead ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 148 of file rw.c.

151{
153 PSERIAL_DEVICE_EXTENSION DeviceExtension;
156 PWORKITEM_DATA WorkItemData;
159
160 TRACE_(SERIAL, "IRP_MJ_READ\n");
161
163 Length = Stack->Parameters.Read.Length;
165 DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
166
167 if (Stack->Parameters.Read.ByteOffset.QuadPart != 0 || Buffer == NULL)
168 {
170 goto ByeBye;
171 }
172
173 if (Length == 0)
174 {
176 goto ByeBye;
177 }
178
179 /* Allocate memory for parameters */
181 if (!WorkItemData)
182 {
184 goto ByeBye;
185 }
186 RtlZeroMemory(WorkItemData, sizeof(WORKITEM_DATA));
187 WorkItemData->Irp = Irp;
188
189 /* Calculate time outs */
190 if (DeviceExtension->SerialTimeOuts.ReadIntervalTimeout == INFINITE &&
192 DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant > 0 &&
194 {
195 /* read at least one byte, and at most bytes already received */
196 WorkItemData->DontWait = TRUE;
197 WorkItemData->ReadAtLeastOneByte = TRUE;
198 }
199 else if (DeviceExtension->SerialTimeOuts.ReadIntervalTimeout == INFINITE &&
200 DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant == 0 &&
201 DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier == 0)
202 {
203 /* read only bytes that are already in buffer */
204 WorkItemData->DontWait = TRUE;
205 }
206 else
207 {
208 /* use timeouts */
209 if (DeviceExtension->SerialTimeOuts.ReadIntervalTimeout != 0)
210 {
211 WorkItemData->UseIntervalTimeout = TRUE;
212 WorkItemData->IntervalTimeout.QuadPart = DeviceExtension->SerialTimeOuts.ReadIntervalTimeout;
213 }
214 if (DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier != 0 ||
215 DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant != 0)
216 {
217 ULONG TotalTimeout;
218 LARGE_INTEGER SystemTime;
219
220 WorkItemData->UseTotalTimeout = TRUE;
221 TotalTimeout = DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant +
223 KeQuerySystemTime(&SystemTime);
224 WorkItemData->TotalTimeoutTime.QuadPart = SystemTime.QuadPart +
225 TotalTimeout * 10000;
226 }
227 }
228
229 /* Pend IRP */
231 if (WorkItem)
232 {
233 WorkItemData->IoWorkItem = WorkItem;
236 return STATUS_PENDING;
237 }
238
239 /* Insufficient resources, we can't pend the Irp */
240 INFO_(SERIAL, "Insufficient resources\n");
241 Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort));
242 if (!NT_SUCCESS(Status))
243 {
244 ExFreePoolWithTag(WorkItemData, SERIAL_TAG);
245 goto ByeBye;
246 }
247 ReadBytes(DeviceObject, Irp, WorkItemData);
248 Status = Irp->IoStatus.Status;
249
250 IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort));
251
252ByeBye:
253 Irp->IoStatus.Status = Status;
255 return Status;
256}
#define ULongToPtr(ul)
Definition: basetsd.h:92
#define STATUS_PENDING
Definition: d3dkmdt.h:43
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
static VOID ReadBytes(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, PWORKITEM_DATA WorkItemData)
Definition: rw.c:28
static IO_WORKITEM_ROUTINE SerialReadWorkItem
Definition: rw.c:14
#define SERIAL_TAG
Definition: serial.h:100
#define INFINITE
Definition: serial.h:102
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define PagedPool
Definition: env_spec_w32.h:308
VOID NTAPI IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context)
Definition: iowork.c:40
PIO_WORKITEM NTAPI IoAllocateWorkItem(IN PDEVICE_OBJECT DeviceObject)
Definition: iowork.c:75
IoMarkIrpPending(Irp)
if(dx< 0)
Definition: linetemp.h:194
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define IoCompleteRequest
Definition: irp.c:1240
IO_REMOVE_LOCK RemoveLock
Definition: serial.h:53
SERIAL_TIMEOUTS SerialTimeOuts
Definition: serial.h:72
ULONG ReadTotalTimeoutConstant
Definition: ntddser.h:305
ULONG ReadTotalTimeoutMultiplier
Definition: ntddser.h:304
ULONG ReadIntervalTimeout
Definition: ntddser.h:303
PIRP Irp
Definition: serial.h:89
PIO_WORKITEM IoWorkItem
Definition: serial.h:90
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:115
@ DelayedWorkQueue
Definition: extypes.h:190
#define IoAcquireRemoveLock(RemoveLock, Tag)
#define IoReleaseRemoveLock(_RemoveLock, _Tag)
Definition: iofuncs.h:2764
#define IO_NO_INCREMENT
Definition: iotypes.h:598

◆ SerialReadWorkItem()

static VOID NTAPI SerialReadWorkItem ( IN PDEVICE_OBJECT  DeviceObject,
IN PVOID  pWorkItemData 
)
static

Definition at line 127 of file rw.c.

130{
131 PWORKITEM_DATA WorkItemData;
132 PIRP Irp;
133
134 TRACE_(SERIAL, "SerialReadWorkItem() called\n");
135
136 WorkItemData = (PWORKITEM_DATA)pWorkItemData;
137 Irp = WorkItemData->Irp;
138
139 ReadBytes(DeviceObject, Irp, WorkItemData);
140
142
143 IoFreeWorkItem(WorkItemData->IoWorkItem);
144 ExFreePoolWithTag(pWorkItemData, SERIAL_TAG);
145}
struct _WORKITEM_DATA * PWORKITEM_DATA
VOID NTAPI IoFreeWorkItem(IN PIO_WORKITEM IoWorkItem)
Definition: iowork.c:64

◆ SerialWrite()

NTSTATUS NTAPI SerialWrite ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 259 of file rw.c.

262{
264 PSERIAL_DEVICE_EXTENSION DeviceExtension;
268 KIRQL Irql;
270
271 TRACE_(SERIAL, "IRP_MJ_WRITE\n");
272
273 /* FIXME: pend operation if possible */
274 /* FIXME: use write timeouts */
275
277 Length = Stack->Parameters.Write.Length;
279 DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
280
281 if (Stack->Parameters.Write.ByteOffset.QuadPart != 0 || Buffer == NULL)
282 {
284 goto ByeBye;
285 }
286
287 Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort));
288 if (!NT_SUCCESS(Status))
289 goto ByeBye;
290
291 /* push bytes into output buffer */
292 KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql);
293 while (Information < Length)
294 {
296 if (!NT_SUCCESS(Status))
297 {
299 {
300 KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql);
301 SerialSendByte(NULL, DeviceExtension, NULL, NULL);
302 KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql);
303 continue;
304 }
305 else
306 {
307 WARN_(SERIAL, "Buffer overrun on COM%lu\n", DeviceExtension->ComPort);
308 DeviceExtension->SerialPerfStats.BufferOverrunErrorCount++;
309 break;
310 }
311 }
312 Information++;
313 }
314 KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql);
315 IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort));
316
317 /* send bytes */
318 SerialSendByte(NULL, DeviceExtension, NULL, NULL);
319
320ByeBye:
321 Irp->IoStatus.Information = Information;
322 Irp->IoStatus.Status = Status;
324 return Status;
325}
NTSTATUS PushCircularBufferEntry(IN PCIRCULAR_BUFFER pBuffer, IN UCHAR Entry)
VOID NTAPI SerialSendByte(IN PKDPC Dpc, IN PVOID pDeviceExtension, IN PVOID Unused1, IN PVOID Unused2)
Definition: misc.c:67
#define WARN_(ch,...)
Definition: debug.h:157
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
ULONG BufferOverrunErrorCount
Definition: ntddser.h:298
KSPIN_LOCK OutputBufferLock
Definition: serial.h:78
CIRCULAR_BUFFER OutputBuffer
Definition: serial.h:77
SERIALPERF_STATS SerialPerfStats
Definition: serial.h:71

Variable Documentation

◆ SerialReadWorkItem

IO_WORKITEM_ROUTINE SerialReadWorkItem
static

Definition at line 14 of file rw.c.

Referenced by SerialRead().