ReactOS 0.4.15-dev-7711-g5627da4
misc.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: Serial port driver
4 * FILE: drivers/dd/serial/misc.c
5 * PURPOSE: Miscellaneous operations
6 *
7 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
8 */
9/* FIXME: call IoAcquireRemoveLock/IoReleaseRemoveLock around each I/O operation */
10
11#include "serial.h"
12
13#include <debug.h>
14
15
19 IN PIRP Irp)
20{
21 PDEVICE_OBJECT LowerDevice = ((PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
22
23 ASSERT(LowerDevice);
24
26 return IoCallDriver(LowerDevice, Irp);
27}
28
31 IN PKDPC Dpc,
32 IN PVOID pDeviceExtension, // real type PSERIAL_DEVICE_EXTENSION
33 IN PVOID Unused1,
34 IN PVOID Unused2)
35{
36 PSERIAL_DEVICE_EXTENSION DeviceExtension;
37 PUCHAR ComPortBase;
38 UCHAR Byte;
39 KIRQL Irql;
40 UCHAR IER;
42
43 DeviceExtension = (PSERIAL_DEVICE_EXTENSION)pDeviceExtension;
44 ComPortBase = ULongToPtr(DeviceExtension->BaseAddress);
45
46 KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
47 while (READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_DATA_RECEIVED)
48 {
49 Byte = READ_PORT_UCHAR(SER_RBR(ComPortBase));
50 INFO_(SERIAL, "Byte received on COM%lu: 0x%02x\n",
51 DeviceExtension->ComPort, Byte);
52 Status = PushCircularBufferEntry(&DeviceExtension->InputBuffer, Byte);
53 if (NT_SUCCESS(Status))
54 DeviceExtension->SerialPerfStats.ReceivedCount++;
55 else
57 }
58 KeSetEvent(&DeviceExtension->InputBufferNotEmpty, 0, FALSE);
59 KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
60
61 /* allow new interrupts */
62 IER = READ_PORT_UCHAR(SER_IER(ComPortBase));
64}
65
68 IN PKDPC Dpc,
69 IN PVOID pDeviceExtension, // real type PSERIAL_DEVICE_EXTENSION
70 IN PVOID Unused1,
71 IN PVOID Unused2)
72{
73 PSERIAL_DEVICE_EXTENSION DeviceExtension;
74 PUCHAR ComPortBase;
75 UCHAR Byte;
76 KIRQL Irql;
77 UCHAR IER;
79
80 DeviceExtension = (PSERIAL_DEVICE_EXTENSION)pDeviceExtension;
81 ComPortBase = ULongToPtr(DeviceExtension->BaseAddress);
82
83 KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql);
84 while (!IsCircularBufferEmpty(&DeviceExtension->OutputBuffer)
85 && READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_THR_EMPTY)
86 {
87 Status = PopCircularBufferEntry(&DeviceExtension->OutputBuffer, &Byte);
88 if (!NT_SUCCESS(Status))
89 break;
90 WRITE_PORT_UCHAR(SER_THR(ComPortBase), Byte);
91 INFO_(SERIAL, "Byte sent to COM%lu: 0x%02x\n",
92 DeviceExtension->ComPort, Byte);
93 DeviceExtension->SerialPerfStats.TransmittedCount++;
94 }
95 if (!IsCircularBufferEmpty(&DeviceExtension->OutputBuffer))
96 {
97 /* allow new interrupts */
98 IER = READ_PORT_UCHAR(SER_IER(ComPortBase));
99 WRITE_PORT_UCHAR(SER_IER(ComPortBase), IER | SR_IER_THR_EMPTY);
100 }
101 KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql);
102}
103
106 IN PKDPC Dpc,
107 IN PVOID pDeviceExtension, // real type PSERIAL_DEVICE_EXTENSION
108 IN PVOID pIrp, // real type PIRP
110{
112}
113
118{
120 PSERIAL_DEVICE_EXTENSION DeviceExtension;
121 PUCHAR ComPortBase;
122 UCHAR Iir;
123 ULONG Events = 0;
124 BOOLEAN ret = FALSE;
125
126 /* FIXME: sometimes, produce SERIAL_EV_RXFLAG event */
127
129 DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
130 ComPortBase = ULongToPtr(DeviceExtension->BaseAddress);
131
132 Iir = READ_PORT_UCHAR(SER_IIR(ComPortBase));
133 if (Iir == 0xff)
134 return TRUE;
135 Iir &= SR_IIR_ID_MASK;
136 if ((Iir & SR_IIR_SELF) != 0) { return FALSE; }
137
138 switch (Iir)
139 {
141 {
142 UCHAR MSR, IER;
143 TRACE_(SERIAL, "SR_IIR_MSR_CHANGE\n");
144
145 MSR = READ_PORT_UCHAR(SER_MSR(ComPortBase));
146 if (MSR & SR_MSR_CTS_CHANGED)
147 {
148 if (MSR & SR_MSR_CTS)
149 KeInsertQueueDpc(&DeviceExtension->SendByteDpc, NULL, NULL);
150 else
151 {
152 ; /* FIXME: stop transmission */
153 }
155 }
156 if (MSR & SR_MSR_DSR_CHANGED)
157 {
158 if (MSR & SR_MSR_DSR)
159 KeInsertQueueDpc(&DeviceExtension->ReceivedByteDpc, NULL, NULL);
160 else
161 {
162 ; /* FIXME: stop reception */
163 }
165 }
166 if (MSR & SR_MSR_RI_CHANGED)
167 {
168 INFO_(SERIAL, "SR_MSR_RI_CHANGED changed: now %d\n", MSR & SI_MSR_RI);
170 }
171 if (MSR & SR_MSR_DCD_CHANGED)
172 {
173 INFO_(SERIAL, "SR_MSR_DCD_CHANGED changed: now %d\n", MSR & SR_MSR_DCD);
175 }
176 IER = READ_PORT_UCHAR(SER_IER(ComPortBase));
177 WRITE_PORT_UCHAR(SER_IER(ComPortBase), IER | SR_IER_MSR_CHANGE);
178
179 ret = TRUE;
180 goto done;
181 }
182 case SR_IIR_THR_EMPTY:
183 {
184 TRACE_(SERIAL, "SR_IIR_THR_EMPTY\n");
185
186 KeInsertQueueDpc(&DeviceExtension->SendByteDpc, NULL, NULL);
188
189 ret = TRUE;
190 goto done;
191 }
193 {
194 ULONG AlreadyReceivedBytes, Limit;
195 TRACE_(SERIAL, "SR_IIR_DATA_RECEIVED\n");
196
197 KeInsertQueueDpc(&DeviceExtension->ReceivedByteDpc, NULL, NULL);
199
200 /* Check if buffer will be 80% full */
201 AlreadyReceivedBytes = GetNumberOfElementsInCircularBuffer(
202 &DeviceExtension->InputBuffer) * 5;
203 Limit = DeviceExtension->InputBuffer.Length * 4;
204 if (AlreadyReceivedBytes < Limit && AlreadyReceivedBytes + 1 >= Limit)
205 {
206 /* Buffer is full at 80% */
208 }
209
210 ret = TRUE;
211 goto done;
212 }
213 case SR_IIR_ERROR:
214 {
215 UCHAR LSR;
216 TRACE_(SERIAL, "SR_IIR_ERROR\n");
217
218 LSR = READ_PORT_UCHAR(SER_LSR(ComPortBase));
219 if (LSR & SR_LSR_OVERRUN_ERROR)
220 {
223 }
224 if (LSR & SR_LSR_PARITY_ERROR)
225 {
228 }
229 if (LSR & SR_LSR_FRAMING_ERROR)
230 {
233 }
234 if (LSR & SR_LSR_BREAK_INT)
235 {
238 }
239
240 ret = TRUE;
241 goto done;
242 }
243 }
244
245done:
246 if (!ret)
247 return FALSE;
248 if (DeviceExtension->WaitOnMaskIrp && (Events & DeviceExtension->WaitMask))
249 {
250 /* Finish pending IRP */
251 PULONG pEvents = (PULONG)DeviceExtension->WaitOnMaskIrp->AssociatedIrp.SystemBuffer;
252
253 DeviceExtension->WaitOnMaskIrp->IoStatus.Status = STATUS_SUCCESS;
254 DeviceExtension->WaitOnMaskIrp->IoStatus.Information = sizeof(ULONG);
255 *pEvents = Events;
256 KeInsertQueueDpc(&DeviceExtension->CompleteIrpDpc, DeviceExtension->WaitOnMaskIrp, NULL);
257
258 /* We are now ready to handle another IRP, even if this one is not completed */
259 DeviceExtension->WaitOnMaskIrp = NULL;
260 return TRUE;
261 }
262 return TRUE;
263}
unsigned char BOOLEAN
#define InterlockedIncrement
Definition: armddk.h:53
LONG NTSTATUS
Definition: precomp.h:26
HANDLE Events[3]
Definition: schedsvc.c:40
#define ULongToPtr(ul)
Definition: basetsd.h:92
NTSTATUS PushCircularBufferEntry(IN PCIRCULAR_BUFFER pBuffer, IN UCHAR Entry)
BOOLEAN IsCircularBufferEmpty(IN PCIRCULAR_BUFFER pBuffer)
NTSTATUS PopCircularBufferEntry(IN PCIRCULAR_BUFFER pBuffer, OUT PUCHAR Entry)
ULONG GetNumberOfElementsInCircularBuffer(IN PCIRCULAR_BUFFER pBuffer)
_In_ PIRP Irp
Definition: csq.h:116
_Out_ PKIRQL Irql
Definition: csq.h:179
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define TRACE_(x)
Definition: compat.h:76
unsigned char Byte
Definition: zlib.h:37
BOOLEAN NTAPI KeInsertQueueDpc(IN PKDPC Dpc, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: dpc.c:725
VOID NTAPI SerialReceiveByte(IN PKDPC Dpc, IN PVOID pDeviceExtension, IN PVOID Unused1, IN PVOID Unused2)
Definition: misc.c:30
VOID NTAPI SerialSendByte(IN PKDPC Dpc, IN PVOID pDeviceExtension, IN PVOID Unused1, IN PVOID Unused2)
Definition: misc.c:67
VOID NTAPI SerialCompleteIrp(IN PKDPC Dpc, IN PVOID pDeviceExtension, IN PVOID pIrp, IN PVOID Unused)
Definition: misc.c:105
#define SR_MSR_RI_CHANGED
Definition: serial.h:164
#define SR_IIR_DATA_RECEIVED
Definition: serial.h:125
#define SER_MSR(x)
Definition: serial.h:161
#define SI_MSR_RI
Definition: serial.h:168
#define SR_MSR_DCD
Definition: serial.h:169
#define SR_IIR_MSR_CHANGE
Definition: serial.h:123
#define SR_MSR_DCD_CHANGED
Definition: serial.h:165
#define SR_LSR_OVERRUN_ERROR
Definition: serial.h:154
#define SR_LSR_BREAK_INT
Definition: serial.h:157
#define SR_IER_THR_EMPTY
Definition: serial.h:114
struct _SERIAL_DEVICE_EXTENSION * PSERIAL_DEVICE_EXTENSION
#define SR_MSR_DSR
Definition: serial.h:167
#define SR_LSR_PARITY_ERROR
Definition: serial.h:155
#define SR_MSR_DSR_CHANGED
Definition: serial.h:163
#define SER_IIR(x)
Definition: serial.h:120
#define SR_LSR_THR_EMPTY
Definition: serial.h:158
#define SR_MSR_CTS_CHANGED
Definition: serial.h:162
#define SER_IER(x)
Definition: serial.h:112
#define SR_MSR_CTS
Definition: serial.h:166
#define SR_LSR_FRAMING_ERROR
Definition: serial.h:156
#define SR_IIR_SELF
Definition: serial.h:121
#define SER_RBR(x)
Definition: serial.h:109
#define SER_LSR(x)
Definition: serial.h:152
#define SR_IER_DATA_RECEIVED
Definition: serial.h:113
#define SR_IIR_ERROR
Definition: serial.h:126
#define SR_IIR_ID_MASK
Definition: serial.h:122
#define SR_LSR_DATA_RECEIVED
Definition: serial.h:153
#define SR_IIR_THR_EMPTY
Definition: serial.h:124
#define SER_THR(x)
Definition: serial.h:110
KSERVICE_ROUTINE SerialInterruptService
Definition: serial.h:268
#define SR_IER_MSR_CHANGE
Definition: serial.h:116
UCHAR KIRQL
Definition: env_spec_w32.h:591
struct _DEVICE_OBJECT * PDEVICE_OBJECT
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
FxIrp * pIrp
Status
Definition: gdiplustypes.h:25
DRIVER_DISPATCH ForwardIrpAndForget
Definition: i8042prt.h:341
#define Unused(x)
Definition: atlwin.h:28
#define ASSERT(a)
Definition: mode.c:44
#define SERIAL_EV_TXEMPTY
Definition: serial.c:101
#define SERIAL_EV_RING
Definition: serial.c:107
#define SERIAL_EV_RX80FULL
Definition: serial.c:109
#define SERIAL_EV_BREAK
Definition: serial.c:105
#define SERIAL_EV_RXCHAR
Definition: serial.c:99
#define SERIAL_EV_DSR
Definition: serial.c:103
#define SERIAL_EV_RLSD
Definition: serial.c:104
#define SERIAL_EV_ERR
Definition: serial.c:106
#define SERIAL_EV_CTS
Definition: serial.c:102
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
#define IoCompleteRequest
Definition: irp.c:1240
#define IoCallDriver
Definition: irp.c:1225
#define READ_PORT_UCHAR(p)
Definition: pc98vid.h:22
#define WRITE_PORT_UCHAR(p, d)
Definition: pc98vid.h:21
#define INFO_(ch,...)
Definition: debug.h:159
#define STATUS_SUCCESS
Definition: shellext.h:65
ULONG Length
Definition: serial.h:43
IO_STATUS_BLOCK IoStatus
Definition: ketypes.h:699
ULONG ParityErrorCount
Definition: ntddser.h:299
ULONG FrameErrorCount
Definition: ntddser.h:296
ULONG SerialOverrunErrorCount
Definition: ntddser.h:297
ULONG TransmittedCount
Definition: ntddser.h:295
ULONG ReceivedCount
Definition: ntddser.h:294
ULONG BufferOverrunErrorCount
Definition: ntddser.h:298
KSPIN_LOCK OutputBufferLock
Definition: serial.h:78
KSPIN_LOCK InputBufferLock
Definition: serial.h:76
KEVENT InputBufferNotEmpty
Definition: serial.h:74
ULONG BreakInterruptErrorCount
Definition: serial.h:70
CIRCULAR_BUFFER InputBuffer
Definition: serial.h:75
CIRCULAR_BUFFER OutputBuffer
Definition: serial.h:77
SERIALPERF_STATS SerialPerfStats
Definition: serial.h:71
uint32_t * PULONG
Definition: typedefs.h:59
#define NTAPI
Definition: typedefs.h:36
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
int ret
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_INTERRUPT_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFINTERRUPT * Interrupt
Definition: wdfinterrupt.h:379
_In_ PKSERVICE_ROUTINE _In_opt_ PVOID ServiceContext
Definition: iofuncs.h:801
#define IO_NO_INCREMENT
Definition: iotypes.h:598
_In_ LONG _In_ LONG Limit
Definition: kefuncs.h:304
unsigned char UCHAR
Definition: xmlstorage.h:181