Modified: trunk/reactos/drivers/dd/serial/devctrl.c
Modified: trunk/reactos/drivers/dd/serial/legacy.c
Modified: trunk/reactos/drivers/dd/serial/misc.c
Modified: trunk/reactos/drivers/dd/serial/pnp.c
Modified: trunk/reactos/drivers/dd/serial/rw.c
Modified: trunk/reactos/drivers/dd/serial/serial.c
Modified: trunk/reactos/drivers/dd/serial/serial.h
--- trunk/reactos/drivers/dd/serial/devctrl.c 2005-04-02 11:40:58 UTC (rev 14439)
+++ trunk/reactos/drivers/dd/serial/devctrl.c 2005-04-02 14:16:47 UTC (rev 14440)
@@ -7,7 +7,6 @@
*
* PROGRAMMERS: HervÚ Poussineau (poussine@freesurf.fr)
*/
-/* FIXME: call IoAcquireRemoveLock/IoReleaseRemoveLock around each I/O operation */
#define NDEBUG
#include "serial.h"
@@ -219,22 +218,30 @@
pCommProp->ServiceMask = SERIAL_SP_SERIALCOMM;
pCommProp->MaxTxQueue = pCommProp->CurrentTxQueue = DeviceExtension->OutputBuffer.Length - 1;
pCommProp->MaxRxQueue = pCommProp->CurrentRxQueue = DeviceExtension->InputBuffer.Length - 1;
- pCommProp->MaxBaud = SERIAL_BAUD_115200;
pCommProp->ProvSubType = 1; // PST_RS232;
- /* FIXME: ProvCapabilities may be related to Uart type */
pCommProp->ProvCapabilities = SERIAL_PCF_DTRDSR | SERIAL_PCF_INTTIMEOUTS | SERIAL_PCF_PARITY_CHECK
| SERIAL_PCF_RTSCTS | SERIAL_PCF_SETXCHAR | SERIAL_PCF_SPECIALCHARS | SERIAL_PCF_TOTALTIMEOUTS
| SERIAL_PCF_XONXOFF;
- /* FIXME: SettableParams may be related to Uart type */
pCommProp->SettableParams = SERIAL_SP_BAUD | SERIAL_SP_DATABITS | SERIAL_SP_HANDSHAKING
| SERIAL_SP_PARITY | SERIAL_SP_PARITY_CHECK | SERIAL_SP_STOPBITS;
- /* FIXME: SettableBaud may be related to Uart type */
+
+ /* SettableBaud is related to Uart type */
pCommProp->SettableBaud = SERIAL_BAUD_075 | SERIAL_BAUD_110 | SERIAL_BAUD_134_5
| SERIAL_BAUD_150 | SERIAL_BAUD_300 | SERIAL_BAUD_600 | SERIAL_BAUD_1200
| SERIAL_BAUD_1800 | SERIAL_BAUD_2400 | SERIAL_BAUD_4800 | SERIAL_BAUD_7200
- | SERIAL_BAUD_9600 | SERIAL_BAUD_14400 | SERIAL_BAUD_19200 | SERIAL_BAUD_38400
- | SERIAL_BAUD_56K | SERIAL_BAUD_57600 | SERIAL_BAUD_115200 | SERIAL_BAUD_128K
- | SERIAL_BAUD_USER;
+ | SERIAL_BAUD_9600 | SERIAL_BAUD_USER;
+ pCommProp->MaxBaud = SERIAL_BAUD_9600;
+ if (DeviceExtension->UartType >= Uart16450)
+ {
+ pCommProp->SettableBaud |= SERIAL_BAUD_14400 | SERIAL_BAUD_19200 | SERIAL_BAUD_38400;
+ pCommProp->MaxBaud = SERIAL_BAUD_38400;
+ }
+ if (DeviceExtension->UartType >= Uart16550)
+ {
+ pCommProp->SettableBaud |= SERIAL_BAUD_56K | SERIAL_BAUD_57600 | SERIAL_BAUD_115200 | SERIAL_BAUD_128K;
+ pCommProp->MaxBaud = SERIAL_BAUD_115200;
+ }
+
pCommProp->SettableData = SERIAL_DATABITS_5 | SERIAL_DATABITS_6 | SERIAL_DATABITS_7 | SERIAL_DATABITS_8;
pCommProp->SettableStopParity = SERIAL_STOPBITS_10 | SERIAL_STOPBITS_15 | SERIAL_STOPBITS_20
| SERIAL_PARITY_NONE | SERIAL_PARITY_ODD | SERIAL_PARITY_EVEN | SERIAL_PARITY_MARK | SERIAL_PARITY_SPACE;
@@ -264,8 +271,8 @@
- DeviceExtension->OutputBuffer.ReadPosition) % DeviceExtension->OutputBuffer.Length;
KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql);
- pSerialStatus->EofReceived = FALSE; /* FIXME */
- pSerialStatus->WaitForImmediate = FALSE; /* FIXME */
+ pSerialStatus->EofReceived = FALSE; /* always FALSE */
+ pSerialStatus->WaitForImmediate = FALSE; /* always FALSE */
return STATUS_SUCCESS;
}
@@ -286,8 +293,6 @@
DPRINT("Serial: IRP_MJ_DEVICE_CONTROL dispatch\n");
- /* FIXME: pend operation if possible */
-
Stack = IoGetCurrentIrpStackLocation(Irp);
LengthIn = Stack->Parameters.DeviceIoControl.InputBufferLength;
LengthOut = Stack->Parameters.DeviceIoControl.OutputBufferLength;
@@ -315,9 +320,13 @@
DPRINT("Serial: IOCTL_SERIAL_CLR_DTR\n");
/* FIXME: If the handshake flow control of the device is configured to
* automatically use DTR, return STATUS_INVALID_PARAMETER */
- DeviceExtension->MCR &= ~SR_MCR_DTR;
- WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
- Status = STATUS_SUCCESS;
+ Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
+ if (NT_SUCCESS(Status))
+ {
+ DeviceExtension->MCR &= ~SR_MCR_DTR;
+ WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
+ IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
+ }
break;
}
case IOCTL_SERIAL_CLR_RTS:
@@ -325,9 +334,13 @@
DPRINT("Serial: IOCTL_SERIAL_CLR_RTS\n");
/* FIXME: If the handshake flow control of the device is configured to
* automatically use RTS, return STATUS_INVALID_PARAMETER */
- DeviceExtension->MCR &= ~SR_MCR_RTS;
- WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
- Status = STATUS_SUCCESS;
+ Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
+ if (NT_SUCCESS(Status))
+ {
+ DeviceExtension->MCR &= ~SR_MCR_RTS;
+ WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
+ IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
+ }
break;
}
case IOCTL_SERIAL_CONFIG_SIZE:
@@ -546,14 +559,20 @@
DeviceExtension->InputBuffer.ReadPosition = DeviceExtension->InputBuffer.WritePosition = 0;
DeviceExtension->OutputBuffer.ReadPosition = DeviceExtension->OutputBuffer.WritePosition = 0;
/* Clear receive/transmit buffers */
- if (DeviceExtension->UartType >= Uart16550)
+ if (DeviceExtension->UartType >= Uart16550A)
{
- WRITE_PORT_UCHAR(SER_FCR(ComPortBase),
- SR_FCR_CLEAR_RCVR | SR_FCR_CLEAR_XMIT);
+ /* 16550 UARTs also have FIFO queues, but they are unusable due to a bug */
+ Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
+ if (NT_SUCCESS(Status))
+ {
+ WRITE_PORT_UCHAR(SER_FCR(ComPortBase), SR_FCR_CLEAR_RCVR | SR_FCR_CLEAR_XMIT);
+ IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
+ }
}
+ else
+ Status = STATUS_SUCCESS;
KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql2);
KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql1);
- Status = STATUS_SUCCESS;
break;
}
case IOCTL_SERIAL_RESET_DEVICE:
@@ -604,10 +623,16 @@
DPRINT("Serial: IOCTL_SERIAL_SET_DTR\n");
if (!(DeviceExtension->MCR & SR_MCR_DTR))
{
- DeviceExtension->MCR |= SR_MCR_DTR;
- WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
+ Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
+ if (NT_SUCCESS(Status))
+ {
+ DeviceExtension->MCR |= SR_MCR_DTR;
+ WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
+ IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
+ }
}
- Status = STATUS_SUCCESS;
+ else
+ Status = STATUS_SUCCESS;
break;
}
case IOCTL_SERIAL_SET_FIFO_CONTROL:
@@ -617,8 +642,12 @@
Status = STATUS_INVALID_PARAMETER;
else
{
- WRITE_PORT_UCHAR(SER_FCR(ComPortBase), (UCHAR)((*(PULONG)BufferIn) & 0xff));
- Status = STATUS_SUCCESS;
+ Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
+ if (NT_SUCCESS(Status))
+ {
+ WRITE_PORT_UCHAR(SER_FCR(ComPortBase), (UCHAR)((*(PULONG)BufferIn) & 0xff));
+ IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
+ }
}
break;
}
@@ -648,10 +677,14 @@
Status = STATUS_INVALID_PARAMETER;
else
{
- pMCR = (PULONG)BufferIn;
- DeviceExtension->MCR = (UCHAR)(*pMCR & 0xff);
- WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
- Status = STATUS_SUCCESS;
+ Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
+ if (NT_SUCCESS(Status))
+ {
+ pMCR = (PULONG)BufferIn;
+ DeviceExtension->MCR = (UCHAR)(*pMCR & 0xff);
+ WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
+ IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
+ }
}
break;
}
@@ -688,10 +721,16 @@
DPRINT("Serial: IOCTL_SERIAL_SET_RTS\n");
if (!(DeviceExtension->MCR & SR_MCR_RTS))
{
- DeviceExtension->MCR |= SR_MCR_RTS;
- WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
+ Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
+ if (NT_SUCCESS(Status))
+ {
+ DeviceExtension->MCR |= SR_MCR_RTS;
+ WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
+ IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
+ }
}
- Status = STATUS_SUCCESS;
+ else
+ Status = STATUS_SUCCESS;
break;
}
case IOCTL_SERIAL_SET_TIMEOUTS:
--- trunk/reactos/drivers/dd/serial/legacy.c 2005-04-02 11:40:58 UTC (rev 14439)
+++ trunk/reactos/drivers/dd/serial/legacy.c 2005-04-02 14:16:47 UTC (rev 14440)
@@ -96,8 +96,8 @@
if (!ResourceList)
return STATUS_INSUFFICIENT_RESOURCES;
ResourceList->Count = 1;
- ResourceList->List[0].InterfaceType = Isa;
- ResourceList->List[0].BusNumber = -1; /* FIXME */
+ ResourceList->List[0].InterfaceType = InterfaceTypeUndefined;
+ ResourceList->List[0].BusNumber = -1; /* unknown */
ResourceList->List[0].PartialResourceList.Version = 1;
ResourceList->List[0].PartialResourceList.Revision = 1;
ResourceList->List[0].PartialResourceList.Count = 2;
@@ -137,7 +137,7 @@
{
Status = IoReportDetectedDevice(
DriverObject,
- ResourceList->List[0].InterfaceType, ResourceList->List[0].BusNumber, -1/*FIXME*/,
+ ResourceList->List[0].InterfaceType, ResourceList->List[0].BusNumber, -1 /* unknown */,
ResourceList, NULL,
TRUE,
&Pdo);
--- trunk/reactos/drivers/dd/serial/misc.c 2005-04-02 11:40:58 UTC (rev 14439)
+++ trunk/reactos/drivers/dd/serial/misc.c 2005-04-02 14:16:47 UTC (rev 14440)
@@ -105,9 +105,6 @@
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)pDeviceExtension;
ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
- DPRINT1("Serial: sending bytes (if any) on COM%lu\n",
- DeviceExtension->ComPort);
-
KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql);
while (!IsCircularBufferEmpty(&DeviceExtension->OutputBuffer)
&& READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_TBE)
--- trunk/reactos/drivers/dd/serial/pnp.c 2005-04-02 11:40:58 UTC (rev 14439)
+++ trunk/reactos/drivers/dd/serial/pnp.c 2005-04-02 14:16:47 UTC (rev 14440)
@@ -80,7 +80,7 @@
KeInitializeSpinLock(&DeviceExtension->OutputBufferLock);
KeInitializeDpc(&DeviceExtension->ReceivedByteDpc, SerialReceiveByte, DeviceExtension);
KeInitializeDpc(&DeviceExtension->SendByteDpc, SerialSendByte, DeviceExtension);
- //Fdo->Flags |= DO_POWER_PAGEABLE (or DO_POWER_INRUSH?)
+ Fdo->Flags |= DO_POWER_PAGABLE;
Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
if (!NT_SUCCESS(Status))
{
@@ -126,8 +126,8 @@
* not called with a NULL Pdo. Block this call (blocks
* unfortunately all the other PnP serial ports devices).
*/
- //return SerialAddDeviceInternal(DriverObject, Pdo, UartUnknown, NULL);
- return STATUS_UNSUCCESSFUL;
+ return SerialAddDeviceInternal(DriverObject, Pdo, UartUnknown, NULL);
+ //return STATUS_UNSUCCESSFUL;
}
NTSTATUS STDCALL
@@ -230,8 +230,9 @@
}
/* Clear receive/transmit buffers */
- if (DeviceExtension->UartType >= Uart16550)
+ if (DeviceExtension->UartType >= Uart16550A)
{
+ /* 16550 UARTs also have FIFO queues, but they are unusable due to a bug */
WRITE_PORT_UCHAR(SER_FCR(ComPortBase),
SR_FCR_CLEAR_RCVR | SR_FCR_CLEAR_XMIT);
}
@@ -307,6 +308,69 @@
{
DPRINT("Serial: IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
+ /* FIXME: first HACK: PnP manager can send multiple
+ * IRP_MN_START_DEVICE for one device
+ */
+ if (((PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->PnpState != dsStopped)
+ {
+ DPRINT1("Serial: device already started. Ignoring this irp!\n");
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ /* FIXME: AllocatedResources MUST never be NULL ;
+ * that's the second HACK because resource arbitration
+ * doesn't exist in ReactOS yet...
+ */
+ if (Stack->Parameters.StartDevice.AllocatedResources == NULL)
+ {
+ ULONG ResourceListSize;
+ PCM_RESOURCE_LIST ResourceList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
+ KIRQL Dirql;
+ ULONG ComPortBase;
+ ULONG Irq;
+
+ DPRINT1("Serial: no allocated resources for this device! Creating fake list\n");
+ /* These values are resources of the ONLY serial
+ * port that will be managed by this driver
+ * (default is COM2) */
+ ComPortBase = 0x2f8;
+ Irq = 3;
+
+ /* Create resource list */
+ ResourceListSize = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
+ ResourceList = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(PagedPool, ResourceListSize, SERIAL_TAG);
+ if (!ResourceList)
+ return STATUS_INSUFFICIENT_RESOURCES;
+ ResourceList->Count = 1;
+ ResourceList->List[0].InterfaceType = Isa;
+ ResourceList->List[0].BusNumber = -1; /* FIXME */
+ ResourceList->List[0].PartialResourceList.Version = 1;
+ ResourceList->List[0].PartialResourceList.Revision = 1;
+ ResourceList->List[0].PartialResourceList.Count = 2;
+ ResourceDescriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[0];
+ ResourceDescriptor->Type = CmResourceTypePort;
+ ResourceDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
+ ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ ResourceDescriptor->u.Port.Start.u.HighPart = 0;
+ ResourceDescriptor->u.Port.Start.u.LowPart = ComPortBase;
+ ResourceDescriptor->u.Port.Length = 8;
+
+ ResourceDescriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[1];
+ ResourceDescriptor->Type = CmResourceTypeInterrupt;
+ ResourceDescriptor->ShareDisposition = CmResourceShareShared;
+ ResourceDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+ ResourceDescriptor->u.Interrupt.Vector = HalGetInterruptVector(
+ Internal, 0, 0, Irq,
+ &Dirql,
+ &ResourceDescriptor->u.Interrupt.Affinity);
+ ResourceDescriptor->u.Interrupt.Level = (ULONG)Dirql;
+
+ Stack->Parameters.StartDevice.AllocatedResources =
+ Stack->Parameters.StartDevice.AllocatedResourcesTranslated =
+ ResourceList;
+ }
+
/* Call lower driver */
Status = ForwardIrpAndWait(DeviceObject, Irp);
if (NT_SUCCESS(Status))
--- trunk/reactos/drivers/dd/serial/rw.c 2005-04-02 11:40:58 UTC (rev 14439)
+++ trunk/reactos/drivers/dd/serial/rw.c 2005-04-02 14:16:47 UTC (rev 14440)
@@ -15,11 +15,124 @@
static PVOID
SerialGetUserBuffer(IN PIRP Irp)
{
- ASSERT(Irp);
-
- return Irp->AssociatedIrp.SystemBuffer;
+ ASSERT(Irp);
+
+ return Irp->AssociatedIrp.SystemBuffer;
}
+static VOID
+ReadBytes(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ PWORKITEM_DATA WorkItemData)
+{
+ PSERIAL_DEVICE_EXTENSION DeviceExtension;
+ PUCHAR ComPortBase;
+ ULONG Length;
+ PUCHAR Buffer;
+ ULONG Information = 0;
+ LARGE_INTEGER SystemTime, ByteTimeoutTime;
+ UCHAR ReceivedByte;
+ BOOLEAN IsByteReceived;
+ //KIRQL Irql;
+
+ DPRINT("Serial: ReadBytes() called\n");
+
+ DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+ ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
+ Length = IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length;
+ Buffer = SerialGetUserBuffer(Irp);
+
+ /* FIXME: remove disabling interrupts */
+ WRITE_PORT_UCHAR(SER_IER(ComPortBase), DeviceExtension->IER & ~1);
+ while (Length > 0)
+ {
+ /* Calculate dead line to receive the next byte */
+ KeQuerySystemTime(&SystemTime);
+ ByteTimeoutTime.QuadPart = SystemTime.QuadPart +
+ WorkItemData->IntervalTimeout * 10000;
+
+ IsByteReceived = FALSE;
+ while (TRUE)
+ {
+#if 1
+ if ((READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_DR) != 0)
+ {
+ ReceivedByte = READ_PORT_UCHAR(ComPortBase);
+ DPRINT("Serial: received byte 0x%02x (%c)\n", ReceivedByte, ReceivedByte);
+ IsByteReceived = TRUE;
+ break;
+ }
+ else if (WorkItemData->DontWait &&
+ !(WorkItemData->ReadAtLeastOneByte && Information == 0))
+ {
+ DPRINT("Serial: read buffer empty\n");
+ break;
+ }
+#else
+ KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
+ if (!IsCircularBufferEmpty(&DeviceExtension->InputBuffer))
+ {
+ CHECKPOINT1;
+ PopCircularBufferEntry(&DeviceExtension->InputBuffer, &ReceivedByte);
+ KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
+ DPRINT("Serial: reading byte from buffer 0x%02x (%c)\n", ReceivedByte, ReceivedByte);
+ IsByteReceived = TRUE;
+ break;
+ }
+ else if (WorkItemData->DontWait &&
+ !(WorkItemData->ReadAtLeastOneByte && Information == 0))
+ {
+ DPRINT("Serial: read buffer empty\n");
+ break;
+ }
+ KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
+#endif
+ if (IsByteReceived) break;
+ KeQuerySystemTime(&SystemTime);
+ if (WorkItemData->UseIntervalTimeout && Information > 0)
+ {
+ if (SystemTime.QuadPart >= ByteTimeoutTime.QuadPart)
+ break;
+ }
+ if (WorkItemData->UseTotalTimeout)
+ {
+ if (SystemTime.QuadPart >= WorkItemData->TotalTimeoutTime.QuadPart)
+ break;
+ }
+ }
+ if (!IsByteReceived) break;
+ Buffer[Information++] = ReceivedByte;
+ Length--;
+ }
+ /* FIXME: remove enabling interrupts */
+ WRITE_PORT_UCHAR(SER_IER(ComPortBase), DeviceExtension->IER);
+
+ Irp->IoStatus.Information = Information;
+ if (Information == 0)
+ Irp->IoStatus.Status = STATUS_TIMEOUT;
+ else
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+}
+
+static VOID STDCALL
+SerialReadWorkItem(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID pWorkItemData /* real type PWORKITEM_DATA */)
+{
+ PWORKITEM_DATA WorkItemData;
+ PIRP Irp;
+
+ DPRINT("Serial: SerialReadWorkItem() called\n");
+
+ WorkItemData = (PWORKITEM_DATA)pWorkItemData;
+ Irp = WorkItemData->Irp;
+
+ ReadBytes(DeviceObject, Irp, WorkItemData);
+ ExFreePoolWithTag(pWorkItemData, SERIAL_TAG);
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+}
+
NTSTATUS STDCALL
SerialRead(
IN PDEVICE_OBJECT DeviceObject,
@@ -28,12 +141,10 @@
PIO_STACK_LOCATION Stack;
PSERIAL_DEVICE_EXTENSION DeviceExtension;
ULONG Length;
- ULONG Information = 0;
PUCHAR Buffer;
- PUCHAR ComPortBase;
- UCHAR ReceivedByte;
- KIRQL Irql;
- NTSTATUS Status = STATUS_SUCCESS;
+ PWORKITEM_DATA WorkItemData;
+ PIO_WORKITEM WorkItem;
+ NTSTATUS Status;
DPRINT("Serial: IRP_MJ_READ\n");
@@ -43,7 +154,6 @@
Length = Stack->Parameters.Read.Length;
Buffer = SerialGetUserBuffer(Irp);
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
- ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
if (Stack->Parameters.Read.ByteOffset.QuadPart != 0 || Buffer == NULL)
{
@@ -57,136 +167,79 @@
goto ByeBye;
}
- Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
- if (!NT_SUCCESS(Status))
+ /* Allocate memory for parameters */
+ WorkItemData = ExAllocatePoolWithTag(PagedPool, sizeof(WORKITEM_DATA), SERIAL_TAG);
+ if (!WorkItemData)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
goto ByeBye;
+ }
+ RtlZeroMemory(WorkItemData, sizeof(WORKITEM_DATA));
+ WorkItemData->Irp = Irp;
- KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
- while (Length-- > 0)
+ /* Calculate time outs */
+ if (DeviceExtension->SerialTimeOuts.ReadIntervalTimeout == INFINITE &&
+ DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier == INFINITE &&
+ DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant > 0 &&
+ DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant < INFINITE)
{
- Status = PopCircularBufferEntry(&DeviceExtension->InputBuffer, &ReceivedByte);
- if (!NT_SUCCESS(Status))
- break;
- DPRINT("Serial: read from buffer 0x%x (%c)\n", ReceivedByte, ReceivedByte);
- Buffer[Information++] = ReceivedByte;
+ /* read at least one byte, and at most bytes already received */
+ WorkItemData->DontWait = TRUE;
+ WorkItemData->ReadAtLeastOneByte = TRUE;
}
- KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
- if (Length > 0 &&
- !(DeviceExtension->SerialTimeOuts.ReadIntervalTimeout == INFINITE &&
- DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant == 0 &&
- DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier == 0))
+ else if (DeviceExtension->SerialTimeOuts.ReadIntervalTimeout == INFINITE &&
+ DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant == 0 &&
+ DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier == 0)
{
- ULONG IntervalTimeout = 0;
- ULONG TotalTimeout = 0;
- BOOLEAN UseIntervalTimeout = FALSE;
- BOOLEAN UseTotalTimeout = FALSE;
- ULONG ThisByteTimeout;
- BOOLEAN IsByteReceived;
- ULONG i;
- /* Extract timeouts informations */
- if (DeviceExtension->SerialTimeOuts.ReadIntervalTimeout == INFINITE &&
- DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier == INFINITE &&
- DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant > 0 &&
- DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant < INFINITE)
- {
- if (Information > 0)
+ /* read only bytes that are already in buffer */
+ WorkItemData->DontWait = TRUE;
+ }
+ else
+ {
+ /* use timeouts */
+ if (DeviceExtension->SerialTimeOuts.ReadIntervalTimeout != 0)
{
- /* don't read mode bytes */
- Length = 0;
- }
- else
- {
- /* read only one byte */
- UseTotalTimeout = TRUE;
- TotalTimeout = DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant;
- Length = 1;
- }
+ WorkItemData->UseIntervalTimeout = TRUE;
+ WorkItemData->IntervalTimeout = DeviceExtension->SerialTimeOuts.ReadIntervalTimeout;
}
- else
+ if (DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier != 0 ||
+ DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant != 0)
{
- if (DeviceExtension->SerialTimeOuts.ReadIntervalTimeout != 0)
- {
- UseIntervalTimeout = TRUE;
- IntervalTimeout = DeviceExtension->SerialTimeOuts.ReadIntervalTimeout;
- }
- if (DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant != 0 ||
- DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier != 0)
- {
- UseTotalTimeout = TRUE;
- TotalTimeout = DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant +
- DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier * Length;
- }
+ ULONG TotalTimeout;
+ LARGE_INTEGER SystemTime;
+
+ WorkItemData->UseTotalTimeout = TRUE;
+ TotalTimeout = DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant +
+ DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier * Length;
+ KeQuerySystemTime(&SystemTime);
+ WorkItemData->TotalTimeoutTime.QuadPart = SystemTime.QuadPart +
+ TotalTimeout * 10000;
}
- DPRINT("Serial: UseIntervalTimeout = %ws, IntervalTimeout = %lu\n",
- UseIntervalTimeout ? L"YES" : L"NO",
- UseIntervalTimeout ? IntervalTimeout : 0);
- DPRINT("Serial: UseTotalTimeout = %ws, TotalTimeout = %lu\n",
- UseTotalTimeout ? L"YES" : L"NO",
- UseTotalTimeout ? TotalTimeout : 0);
-
- /* FIXME: it should be better to use input buffer instead of
- * disabling interrupts, and try to directly read for port! */
-
- /* FIXME: NtQueryPerformanceCounter gives a more accurate
- * timer, but it is not available on all computers. First try
- * NtQueryPerformanceCounter, and current method if it is not
- * implemented. */
-
- /* FIXME: remove disabling interrupts */
- WRITE_PORT_UCHAR(SER_IER(ComPortBase), DeviceExtension->IER & ~1);
- while (Length > 0)
- {
- ThisByteTimeout = IntervalTimeout;
- IsByteReceived = FALSE;
- while (TRUE)
- {
- for (i = 0; i < 1000; i++)
- {
-#if 1
- if ((READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_DR) != 0)
- {
- ReceivedByte = READ_PORT_UCHAR(ComPortBase);
- DPRINT("Serial: received byte 0x%02x (%c)\n", ReceivedByte, ReceivedByte);
- IsByteReceived = TRUE;
- break;
- }
-#else
- KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
- if (!IsCircularBufferEmpty(&DeviceExtension->InputBuffer))
- {
- PopCircularBufferEntry(&DeviceExtension->InputBuffer, &ReceivedByte);
- KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
- DPRINT("Serial: reading byte from buffer 0x%02x (%c)\n", ReceivedByte, ReceivedByte);
- IsByteReceived = TRUE;
- break;
- }
- KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
-#endif
- KeStallExecutionProcessor(1);
- }
- if (IsByteReceived) break;
- if (UseIntervalTimeout)
- {
- if (ThisByteTimeout == 0) break; else ThisByteTimeout--;
- }
- if (UseTotalTimeout)
- {
- if (TotalTimeout == 0) break; else TotalTimeout--;
- }
- }
- if (!IsByteReceived) break;
- Buffer[Information++] = ReceivedByte;
- Length--;
- }
- /* FIXME: remove enabling interrupts */
- WRITE_PORT_UCHAR(SER_IER(ComPortBase), DeviceExtension->IER);
}
- Status = STATUS_SUCCESS;
+ /* Pend IRP */
+ WorkItem = IoAllocateWorkItem(DeviceObject);
+ if (WorkItem)
+ {
+ IoQueueWorkItem(WorkItem, SerialReadWorkItem, DelayedWorkQueue, WorkItemData);
+ IoMarkIrpPending(Irp);
+ return STATUS_PENDING;
+ }
+
+ /* insufficient resources, we can't pend the Irp */
+ CHECKPOINT;
+ Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePoolWithTag(WorkItemData, SERIAL_TAG);
+ goto ByeBye;
+ }
+ ReadBytes(DeviceObject, Irp, WorkItemData);
+ Status = Irp->IoStatus.Status;
+
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
ByeBye:
- Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
--- trunk/reactos/drivers/dd/serial/serial.c 2005-04-02 11:40:58 UTC (rev 14439)
+++ trunk/reactos/drivers/dd/serial/serial.c 2005-04-02 14:16:47 UTC (rev 14440)
@@ -7,7 +7,6 @@
*
* PROGRAMMERS: HervÚ Poussineau (poussine@freesurf.fr)
*/
-/* FIXME: call IoAcquireRemoveLock/IoReleaseRemoveLock around each I/O operation */
//#define NDEBUG
#include "serial.h"
--- trunk/reactos/drivers/dd/serial/serial.h 2005-04-02 11:40:58 UTC (rev 14439)
+++ trunk/reactos/drivers/dd/serial/serial.h 2005-04-02 14:16:47 UTC (rev 14440)
@@ -20,7 +20,7 @@
#define STDCALL
#define DPRINT1 DbgPrint("(%s:%d) ", __FILE__, __LINE__), DbgPrint
- #define CHECKPOINT1 DbgPrint("(%s:%d)\n")
+ #define CHECKPOINT1 DbgPrint("(%s:%d)\n", __FILE__, __LINE__)
#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24))
@@ -102,6 +102,18 @@
UCHAR MSR; /* Base+6, Modem Status Register */
} SERIAL_DEVICE_EXTENSION, *PSERIAL_DEVICE_EXTENSION;
+typedef struct _WORKITEM_DATA
+{
+ PIRP Irp;
+
+ BOOLEAN UseIntervalTimeout;
+ BOOLEAN UseTotalTimeout;
+ ULONG IntervalTimeout;
+ LARGE_INTEGER TotalTimeoutTime;
+ BOOLEAN DontWait;
+ BOOLEAN ReadAtLeastOneByte;
+} WORKITEM_DATA, *PWORKITEM_DATA;
+
#define SERIAL_TAG TAG('S', 'e', 'r', 'l')
#define INFINITE ((ULONG)-1)