ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

misc.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.