ReactOS  0.4.15-dev-4920-g5fa8403
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 
29 VOID NTAPI
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
56  DeviceExtension->SerialPerfStats.BufferOverrunErrorCount++;
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 
66 VOID NTAPI
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));
100  }
101  KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql);
102 }
103 
104 VOID NTAPI
106  IN PKDPC Dpc,
107  IN PVOID pDeviceExtension, // real type PSERIAL_DEVICE_EXTENSION
108  IN PVOID pIrp, // real type PIRP
109  IN PVOID Unused)
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  {
140  case SR_IIR_MSR_CHANGE:
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));
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));
220  {
223  }
224  if (LSR & SR_LSR_PARITY_ERROR)
225  {
228  }
230  {
233  }
234  if (LSR & SR_LSR_BREAK_INT)
235  {
238  }
239 
240  ret = TRUE;
241  goto done;
242  }
243  }
244 
245 done:
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 }
_Must_inspect_result_ typedef _In_ PVOID Unused
Definition: iotypes.h:1166
#define IN
Definition: typedefs.h:39
#define ULongToPtr(ul)
Definition: basetsd.h:92
CIRCULAR_BUFFER OutputBuffer
Definition: serial.h:77
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:107
#define SERIAL_EV_RING
Definition: serial.c:107
#define INFO_(ch,...)
Definition: debug.h:159
#define SER_RBR(x)
Definition: serial.h:109
#define READ_PORT_UCHAR(p)
Definition: pc98vid.h:22
#define TRUE
Definition: types.h:120
struct _DEVICE_OBJECT * PDEVICE_OBJECT
#define SR_IER_MSR_CHANGE
Definition: serial.h:116
ULONG BufferOverrunErrorCount
Definition: ntddser.h:298
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_INTERRUPT_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFINTERRUPT * Interrupt
Definition: wdfinterrupt.h:372
VOID NTAPI SerialCompleteIrp(IN PKDPC Dpc, IN PVOID pDeviceExtension, IN PVOID pIrp, IN PVOID Unused)
Definition: misc.c:105
unsigned char * PUCHAR
Definition: retypes.h:3
BOOLEAN NTAPI KeInsertQueueDpc(IN PKDPC Dpc, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: dpc.c:725
LONG NTSTATUS
Definition: precomp.h:26
#define SERIAL_EV_DSR
Definition: serial.c:103
ULONG GetNumberOfElementsInCircularBuffer(IN PCIRCULAR_BUFFER pBuffer)
VOID NTAPI KeAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL OldIrql)
Definition: spinlock.c:50
#define SR_MSR_DCD_CHANGED
Definition: serial.h:165
#define SR_IER_THR_EMPTY
Definition: serial.h:114
KSPIN_LOCK InputBufferLock
Definition: serial.h:76
IO_STATUS_BLOCK IoStatus
FxIrp * pIrp
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
_Out_ PKIRQL Irql
Definition: csq.h:179
#define SERIAL_EV_TXEMPTY
Definition: serial.c:101
#define SERIAL_EV_RX80FULL
Definition: serial.c:109
#define SERIAL_EV_RLSD
Definition: serial.c:104
#define SERIAL_EV_ERR
Definition: serial.c:106
#define SER_MSR(x)
Definition: serial.h:161
KEVENT InputBufferNotEmpty
Definition: serial.h:74
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define SR_LSR_DATA_RECEIVED
Definition: serial.h:153
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
KSPIN_LOCK OutputBufferLock
Definition: serial.h:78
#define SR_MSR_DSR_CHANGED
Definition: serial.h:163
#define SR_MSR_RI_CHANGED
Definition: serial.h:164
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define SR_IER_DATA_RECEIVED
Definition: serial.h:113
#define FALSE
Definition: types.h:117
#define SR_LSR_PARITY_ERROR
Definition: serial.h:155
_In_ PIRP Irp
Definition: csq.h:116
SERIALPERF_STATS SerialPerfStats
Definition: serial.h:71
BOOLEAN IsCircularBufferEmpty(IN PCIRCULAR_BUFFER pBuffer)
#define SR_MSR_DCD
Definition: serial.h:169
#define IER
Definition: serial_port.h:62
#define SR_MSR_CTS_CHANGED
Definition: serial.h:162
unsigned char BOOLEAN
#define IoCompleteRequest
Definition: irp.c:1240
#define LSR
Definition: serial_port.h:67
ULONG SerialOverrunErrorCount
Definition: ntddser.h:297
#define SER_THR(x)
Definition: serial.h:110
#define SR_IIR_ID_MASK
Definition: serial.h:122
HANDLE Events[3]
Definition: schedsvc.c:40
Status
Definition: gdiplustypes.h:24
#define TRACE_(x)
Definition: compat.h:76
ULONG BreakInterruptErrorCount
Definition: serial.h:70
#define SERIAL_EV_CTS
Definition: serial.c:102
#define MSR
Definition: serial_port.h:68
#define SR_LSR_OVERRUN_ERROR
Definition: serial.h:154
#define SR_LSR_THR_EMPTY
Definition: serial.h:158
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define SER_IIR(x)
Definition: serial.h:120
#define SI_MSR_RI
Definition: serial.h:168
NTSTATUS PushCircularBufferEntry(IN PCIRCULAR_BUFFER pBuffer, IN UCHAR Entry)
_In_ PKSERVICE_ROUTINE _In_opt_ PVOID ServiceContext
Definition: iofuncs.h:800
ULONG Length
Definition: serial.h:43
unsigned char UCHAR
Definition: xmlstorage.h:181
#define SERIAL_EV_BREAK
Definition: serial.c:105
int ret
#define SR_LSR_FRAMING_ERROR
Definition: serial.h:156
VOID NTAPI SerialReceiveByte(IN PKDPC Dpc, IN PVOID pDeviceExtension, IN PVOID Unused1, IN PVOID Unused2)
Definition: misc.c:30
Definition: ketypes.h:687
#define WRITE_PORT_UCHAR(p, d)
Definition: pc98vid.h:21
BOOLEAN NTAPI SerialInterruptService(IN PKINTERRUPT Interrupt, IN OUT PVOID ServiceContext)
Definition: misc.c:115
#define SR_IIR_MSR_CHANGE
Definition: serial.h:123
#define SR_MSR_CTS
Definition: serial.h:166
#define SER_LSR(x)
Definition: serial.h:152
#define SR_IIR_DATA_RECEIVED
Definition: serial.h:125
NTSTATUS PopCircularBufferEntry(IN PCIRCULAR_BUFFER pBuffer, OUT PUCHAR Entry)
#define InterlockedIncrement
Definition: armddk.h:53
#define SR_LSR_BREAK_INT
Definition: serial.h:157
struct _SERIAL_DEVICE_EXTENSION * PSERIAL_DEVICE_EXTENSION
ULONG TransmittedCount
Definition: ntddser.h:295
unsigned int * PULONG
Definition: retypes.h:1
NTSTATUS NTAPI ForwardIrpAndForget(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: misc.c:18
#define NULL
Definition: types.h:112
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define SER_IER(x)
Definition: serial.h:112
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
ULONG FrameErrorCount
Definition: ntddser.h:296
unsigned char Byte
Definition: zlib.h:37
VOID NTAPI SerialSendByte(IN PKDPC Dpc, IN PVOID pDeviceExtension, IN PVOID Unused1, IN PVOID Unused2)
Definition: misc.c:67
#define SR_IIR_THR_EMPTY
Definition: serial.h:124
CIRCULAR_BUFFER InputBuffer
Definition: serial.h:75
#define OUT
Definition: typedefs.h:40
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define SR_IIR_ERROR
Definition: serial.h:126
#define SERIAL_EV_RXCHAR
Definition: serial.c:99
#define STATUS_SUCCESS
Definition: shellext.h:65
ULONG ParityErrorCount
Definition: ntddser.h:299
signed int * PLONG
Definition: retypes.h:5
_In_ LONG _In_ LONG Limit
Definition: kefuncs.h:317
ULONG ReceivedCount
Definition: ntddser.h:294
#define SR_MSR_DSR
Definition: serial.h:167
#define SR_IIR_SELF
Definition: serial.h:121