Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmisc.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: Serial port driver 00004 * FILE: drivers/dd/serial/misc.c 00005 * PURPOSE: Misceallenous operations 00006 * 00007 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org) 00008 */ 00009 /* FIXME: call IoAcquireRemoveLock/IoReleaseRemoveLock around each I/O operation */ 00010 00011 #include "serial.h" 00012 00013 static IO_COMPLETION_ROUTINE ForwardIrpAndWaitCompletion; 00014 00015 static NTSTATUS NTAPI 00016 ForwardIrpAndWaitCompletion( 00017 IN PDEVICE_OBJECT DeviceObject, 00018 IN PIRP Irp, 00019 IN PVOID Context) 00020 { 00021 if (Irp->PendingReturned) 00022 KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE); 00023 return STATUS_MORE_PROCESSING_REQUIRED; 00024 } 00025 00026 NTSTATUS 00027 ForwardIrpAndWait( 00028 IN PDEVICE_OBJECT DeviceObject, 00029 IN PIRP Irp) 00030 { 00031 PDEVICE_OBJECT LowerDevice = ((PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice; 00032 KEVENT Event; 00033 NTSTATUS Status; 00034 00035 ASSERT(LowerDevice); 00036 00037 KeInitializeEvent(&Event, NotificationEvent, FALSE); 00038 IoCopyCurrentIrpStackLocationToNext(Irp); 00039 00040 TRACE_(SERIAL, "Calling lower device %p\n", LowerDevice); 00041 IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE); 00042 00043 Status = IoCallDriver(LowerDevice, Irp); 00044 if (Status == STATUS_PENDING) 00045 { 00046 Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); 00047 if (NT_SUCCESS(Status)) 00048 Status = Irp->IoStatus.Status; 00049 } 00050 00051 return Status; 00052 } 00053 00054 NTSTATUS NTAPI 00055 ForwardIrpAndForget( 00056 IN PDEVICE_OBJECT DeviceObject, 00057 IN PIRP Irp) 00058 { 00059 PDEVICE_OBJECT LowerDevice = ((PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice; 00060 00061 ASSERT(LowerDevice); 00062 00063 IoSkipCurrentIrpStackLocation(Irp); 00064 return IoCallDriver(LowerDevice, Irp); 00065 } 00066 00067 VOID NTAPI 00068 SerialReceiveByte( 00069 IN PKDPC Dpc, 00070 IN PVOID pDeviceExtension, // real type PSERIAL_DEVICE_EXTENSION 00071 IN PVOID Unused1, 00072 IN PVOID Unused2) 00073 { 00074 PSERIAL_DEVICE_EXTENSION DeviceExtension; 00075 PUCHAR ComPortBase; 00076 UCHAR Byte; 00077 KIRQL Irql; 00078 UCHAR IER; 00079 NTSTATUS Status; 00080 00081 DeviceExtension = (PSERIAL_DEVICE_EXTENSION)pDeviceExtension; 00082 ComPortBase = ULongToPtr(DeviceExtension->BaseAddress); 00083 00084 KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql); 00085 while (READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_DATA_RECEIVED) 00086 { 00087 Byte = READ_PORT_UCHAR(SER_RBR(ComPortBase)); 00088 INFO_(SERIAL, "Byte received on COM%lu: 0x%02x\n", 00089 DeviceExtension->ComPort, Byte); 00090 Status = PushCircularBufferEntry(&DeviceExtension->InputBuffer, Byte); 00091 if (NT_SUCCESS(Status)) 00092 DeviceExtension->SerialPerfStats.ReceivedCount++; 00093 else 00094 DeviceExtension->SerialPerfStats.BufferOverrunErrorCount++; 00095 } 00096 KeSetEvent(&DeviceExtension->InputBufferNotEmpty, 0, FALSE); 00097 KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql); 00098 00099 /* allow new interrupts */ 00100 IER = READ_PORT_UCHAR(SER_IER(ComPortBase)); 00101 WRITE_PORT_UCHAR(SER_IER(ComPortBase), IER | SR_IER_DATA_RECEIVED); 00102 } 00103 00104 VOID NTAPI 00105 SerialSendByte( 00106 IN PKDPC Dpc, 00107 IN PVOID pDeviceExtension, // real type PSERIAL_DEVICE_EXTENSION 00108 IN PVOID Unused1, 00109 IN PVOID Unused2) 00110 { 00111 PSERIAL_DEVICE_EXTENSION DeviceExtension; 00112 PUCHAR ComPortBase; 00113 UCHAR Byte; 00114 KIRQL Irql; 00115 UCHAR IER; 00116 NTSTATUS Status; 00117 00118 DeviceExtension = (PSERIAL_DEVICE_EXTENSION)pDeviceExtension; 00119 ComPortBase = ULongToPtr(DeviceExtension->BaseAddress); 00120 00121 KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql); 00122 while (!IsCircularBufferEmpty(&DeviceExtension->OutputBuffer) 00123 && READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_THR_EMPTY) 00124 { 00125 Status = PopCircularBufferEntry(&DeviceExtension->OutputBuffer, &Byte); 00126 if (!NT_SUCCESS(Status)) 00127 break; 00128 WRITE_PORT_UCHAR(SER_THR(ComPortBase), Byte); 00129 INFO_(SERIAL, "Byte sent to COM%lu: 0x%02x\n", 00130 DeviceExtension->ComPort, Byte); 00131 DeviceExtension->SerialPerfStats.TransmittedCount++; 00132 } 00133 if (!IsCircularBufferEmpty(&DeviceExtension->OutputBuffer)) 00134 { 00135 /* allow new interrupts */ 00136 IER = READ_PORT_UCHAR(SER_IER(ComPortBase)); 00137 WRITE_PORT_UCHAR(SER_IER(ComPortBase), IER | SR_IER_THR_EMPTY); 00138 } 00139 KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql); 00140 } 00141 00142 VOID NTAPI 00143 SerialCompleteIrp( 00144 IN PKDPC Dpc, 00145 IN PVOID pDeviceExtension, // real type PSERIAL_DEVICE_EXTENSION 00146 IN PVOID pIrp, // real type PIRP 00147 IN PVOID Unused) 00148 { 00149 IoCompleteRequest((PIRP)pIrp, IO_NO_INCREMENT); 00150 } 00151 00152 BOOLEAN NTAPI 00153 SerialInterruptService( 00154 IN PKINTERRUPT Interrupt, 00155 IN OUT PVOID ServiceContext) 00156 { 00157 PDEVICE_OBJECT DeviceObject; 00158 PSERIAL_DEVICE_EXTENSION DeviceExtension; 00159 PUCHAR ComPortBase; 00160 UCHAR Iir; 00161 ULONG Events = 0; 00162 BOOLEAN ret = FALSE; 00163 00164 /* FIXME: sometimes, produce SERIAL_EV_RXFLAG event */ 00165 00166 DeviceObject = (PDEVICE_OBJECT)ServiceContext; 00167 DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 00168 ComPortBase = ULongToPtr(DeviceExtension->BaseAddress); 00169 00170 Iir = READ_PORT_UCHAR(SER_IIR(ComPortBase)); 00171 if (Iir == 0xff) 00172 return TRUE; 00173 Iir &= SR_IIR_ID_MASK; 00174 if ((Iir & SR_IIR_SELF) != 0) { return FALSE; } 00175 00176 switch (Iir) 00177 { 00178 case SR_IIR_MSR_CHANGE: 00179 { 00180 UCHAR MSR, IER; 00181 TRACE_(SERIAL, "SR_IIR_MSR_CHANGE\n"); 00182 00183 MSR = READ_PORT_UCHAR(SER_MSR(ComPortBase)); 00184 if (MSR & SR_MSR_CTS_CHANGED) 00185 { 00186 if (MSR & SR_MSR_CTS) 00187 KeInsertQueueDpc(&DeviceExtension->SendByteDpc, NULL, NULL); 00188 else 00189 { 00190 ; /* FIXME: stop transmission */ 00191 } 00192 Events |= SERIAL_EV_CTS; 00193 } 00194 if (MSR & SR_MSR_DSR_CHANGED) 00195 { 00196 if (MSR & SR_MSR_DSR) 00197 KeInsertQueueDpc(&DeviceExtension->ReceivedByteDpc, NULL, NULL); 00198 else 00199 { 00200 ; /* FIXME: stop reception */ 00201 } 00202 Events |= SERIAL_EV_DSR; 00203 } 00204 if (MSR & SR_MSR_RI_CHANGED) 00205 { 00206 INFO_(SERIAL, "SR_MSR_RI_CHANGED changed: now %d\n", MSR & SI_MSR_RI); 00207 Events |= SERIAL_EV_RING; 00208 } 00209 if (MSR & SR_MSR_DCD_CHANGED) 00210 { 00211 INFO_(SERIAL, "SR_MSR_DCD_CHANGED changed: now %d\n", MSR & SR_MSR_DCD); 00212 Events |= SERIAL_EV_RLSD; 00213 } 00214 IER = READ_PORT_UCHAR(SER_IER(ComPortBase)); 00215 WRITE_PORT_UCHAR(SER_IER(ComPortBase), IER | SR_IER_MSR_CHANGE); 00216 00217 ret = TRUE; 00218 goto done; 00219 } 00220 case SR_IIR_THR_EMPTY: 00221 { 00222 TRACE_(SERIAL, "SR_IIR_THR_EMPTY\n"); 00223 00224 KeInsertQueueDpc(&DeviceExtension->SendByteDpc, NULL, NULL); 00225 Events |= SERIAL_EV_TXEMPTY; 00226 00227 ret = TRUE; 00228 goto done; 00229 } 00230 case SR_IIR_DATA_RECEIVED: 00231 { 00232 ULONG AlreadyReceivedBytes, Limit; 00233 TRACE_(SERIAL, "SR_IIR_DATA_RECEIVED\n"); 00234 00235 KeInsertQueueDpc(&DeviceExtension->ReceivedByteDpc, NULL, NULL); 00236 Events |= SERIAL_EV_RXCHAR; 00237 00238 /* Check if buffer will be 80% full */ 00239 AlreadyReceivedBytes = GetNumberOfElementsInCircularBuffer( 00240 &DeviceExtension->InputBuffer) * 5; 00241 Limit = DeviceExtension->InputBuffer.Length * 4; 00242 if (AlreadyReceivedBytes < Limit && AlreadyReceivedBytes + 1 >= Limit) 00243 { 00244 /* Buffer is full at 80% */ 00245 Events |= SERIAL_EV_RX80FULL; 00246 } 00247 00248 ret = TRUE; 00249 goto done; 00250 } 00251 case SR_IIR_ERROR: 00252 { 00253 UCHAR LSR; 00254 TRACE_(SERIAL, "SR_IIR_ERROR\n"); 00255 00256 LSR = READ_PORT_UCHAR(SER_LSR(ComPortBase)); 00257 if (LSR & SR_LSR_OVERRUN_ERROR) 00258 { 00259 InterlockedIncrement((PLONG)&DeviceExtension->SerialPerfStats.SerialOverrunErrorCount); 00260 Events |= SERIAL_EV_ERR; 00261 } 00262 if (LSR & SR_LSR_PARITY_ERROR) 00263 { 00264 InterlockedIncrement((PLONG)&DeviceExtension->SerialPerfStats.ParityErrorCount); 00265 Events |= SERIAL_EV_ERR; 00266 } 00267 if (LSR & SR_LSR_FRAMING_ERROR) 00268 { 00269 InterlockedIncrement((PLONG)&DeviceExtension->SerialPerfStats.FrameErrorCount); 00270 Events |= SERIAL_EV_ERR; 00271 } 00272 if (LSR & SR_LSR_BREAK_INT) 00273 { 00274 InterlockedIncrement((PLONG)&DeviceExtension->BreakInterruptErrorCount); 00275 Events |= SERIAL_EV_BREAK; 00276 } 00277 00278 ret = TRUE; 00279 goto done; 00280 } 00281 } 00282 00283 done: 00284 if (!ret) 00285 return FALSE; 00286 if (DeviceExtension->WaitOnMaskIrp && (Events & DeviceExtension->WaitMask)) 00287 { 00288 /* Finish pending IRP */ 00289 PULONG pEvents = (PULONG)DeviceExtension->WaitOnMaskIrp->AssociatedIrp.SystemBuffer; 00290 00291 DeviceExtension->WaitOnMaskIrp->IoStatus.Status = STATUS_SUCCESS; 00292 DeviceExtension->WaitOnMaskIrp->IoStatus.Information = sizeof(ULONG); 00293 *pEvents = Events; 00294 KeInsertQueueDpc(&DeviceExtension->CompleteIrpDpc, DeviceExtension->WaitOnMaskIrp, NULL); 00295 00296 /* We are now ready to handle another IRP, even if this one is not completed */ 00297 DeviceExtension->WaitOnMaskIrp = NULL; 00298 return STATUS_SUCCESS; 00299 } 00300 return TRUE; 00301 } Generated on Sat May 26 2012 04:15:48 for ReactOS by
1.7.6.1
|