mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
Correct timeout issues when reading
Pend read IRPs Lots of small issues svn path=/trunk/; revision=14440
This commit is contained in:
parent
11fe38608b
commit
ce4cbf5e57
7 changed files with 341 additions and 177 deletions
|
@ -7,7 +7,6 @@
|
||||||
*
|
*
|
||||||
* PROGRAMMERS: Hervé Poussineau (poussine@freesurf.fr)
|
* PROGRAMMERS: Hervé Poussineau (poussine@freesurf.fr)
|
||||||
*/
|
*/
|
||||||
/* FIXME: call IoAcquireRemoveLock/IoReleaseRemoveLock around each I/O operation */
|
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
|
@ -219,22 +218,30 @@ SerialGetCommProp(
|
||||||
pCommProp->ServiceMask = SERIAL_SP_SERIALCOMM;
|
pCommProp->ServiceMask = SERIAL_SP_SERIALCOMM;
|
||||||
pCommProp->MaxTxQueue = pCommProp->CurrentTxQueue = DeviceExtension->OutputBuffer.Length - 1;
|
pCommProp->MaxTxQueue = pCommProp->CurrentTxQueue = DeviceExtension->OutputBuffer.Length - 1;
|
||||||
pCommProp->MaxRxQueue = pCommProp->CurrentRxQueue = DeviceExtension->InputBuffer.Length - 1;
|
pCommProp->MaxRxQueue = pCommProp->CurrentRxQueue = DeviceExtension->InputBuffer.Length - 1;
|
||||||
pCommProp->MaxBaud = SERIAL_BAUD_115200;
|
|
||||||
pCommProp->ProvSubType = 1; // PST_RS232;
|
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
|
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_RTSCTS | SERIAL_PCF_SETXCHAR | SERIAL_PCF_SPECIALCHARS | SERIAL_PCF_TOTALTIMEOUTS
|
||||||
| SERIAL_PCF_XONXOFF;
|
| SERIAL_PCF_XONXOFF;
|
||||||
/* FIXME: SettableParams may be related to Uart type */
|
|
||||||
pCommProp->SettableParams = SERIAL_SP_BAUD | SERIAL_SP_DATABITS | SERIAL_SP_HANDSHAKING
|
pCommProp->SettableParams = SERIAL_SP_BAUD | SERIAL_SP_DATABITS | SERIAL_SP_HANDSHAKING
|
||||||
| SERIAL_SP_PARITY | SERIAL_SP_PARITY_CHECK | SERIAL_SP_STOPBITS;
|
| 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
|
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_150 | SERIAL_BAUD_300 | SERIAL_BAUD_600 | SERIAL_BAUD_1200
|
||||||
| SERIAL_BAUD_1800 | SERIAL_BAUD_2400 | SERIAL_BAUD_4800 | SERIAL_BAUD_7200
|
| 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_9600 | SERIAL_BAUD_USER;
|
||||||
| SERIAL_BAUD_56K | SERIAL_BAUD_57600 | SERIAL_BAUD_115200 | SERIAL_BAUD_128K
|
pCommProp->MaxBaud = SERIAL_BAUD_9600;
|
||||||
| SERIAL_BAUD_USER;
|
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->SettableData = SERIAL_DATABITS_5 | SERIAL_DATABITS_6 | SERIAL_DATABITS_7 | SERIAL_DATABITS_8;
|
||||||
pCommProp->SettableStopParity = SERIAL_STOPBITS_10 | SERIAL_STOPBITS_15 | SERIAL_STOPBITS_20
|
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;
|
| SERIAL_PARITY_NONE | SERIAL_PARITY_ODD | SERIAL_PARITY_EVEN | SERIAL_PARITY_MARK | SERIAL_PARITY_SPACE;
|
||||||
|
@ -264,8 +271,8 @@ SerialGetCommStatus(
|
||||||
- DeviceExtension->OutputBuffer.ReadPosition) % DeviceExtension->OutputBuffer.Length;
|
- DeviceExtension->OutputBuffer.ReadPosition) % DeviceExtension->OutputBuffer.Length;
|
||||||
KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql);
|
KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql);
|
||||||
|
|
||||||
pSerialStatus->EofReceived = FALSE; /* FIXME */
|
pSerialStatus->EofReceived = FALSE; /* always FALSE */
|
||||||
pSerialStatus->WaitForImmediate = FALSE; /* FIXME */
|
pSerialStatus->WaitForImmediate = FALSE; /* always FALSE */
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -286,8 +293,6 @@ SerialDeviceControl(
|
||||||
|
|
||||||
DPRINT("Serial: IRP_MJ_DEVICE_CONTROL dispatch\n");
|
DPRINT("Serial: IRP_MJ_DEVICE_CONTROL dispatch\n");
|
||||||
|
|
||||||
/* FIXME: pend operation if possible */
|
|
||||||
|
|
||||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
LengthIn = Stack->Parameters.DeviceIoControl.InputBufferLength;
|
LengthIn = Stack->Parameters.DeviceIoControl.InputBufferLength;
|
||||||
LengthOut = Stack->Parameters.DeviceIoControl.OutputBufferLength;
|
LengthOut = Stack->Parameters.DeviceIoControl.OutputBufferLength;
|
||||||
|
@ -315,9 +320,13 @@ SerialDeviceControl(
|
||||||
DPRINT("Serial: IOCTL_SERIAL_CLR_DTR\n");
|
DPRINT("Serial: IOCTL_SERIAL_CLR_DTR\n");
|
||||||
/* FIXME: If the handshake flow control of the device is configured to
|
/* FIXME: If the handshake flow control of the device is configured to
|
||||||
* automatically use DTR, return STATUS_INVALID_PARAMETER */
|
* automatically use DTR, return STATUS_INVALID_PARAMETER */
|
||||||
DeviceExtension->MCR &= ~SR_MCR_DTR;
|
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
|
||||||
WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
|
if (NT_SUCCESS(Status))
|
||||||
Status = STATUS_SUCCESS;
|
{
|
||||||
|
DeviceExtension->MCR &= ~SR_MCR_DTR;
|
||||||
|
WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
|
||||||
|
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IOCTL_SERIAL_CLR_RTS:
|
case IOCTL_SERIAL_CLR_RTS:
|
||||||
|
@ -325,9 +334,13 @@ SerialDeviceControl(
|
||||||
DPRINT("Serial: IOCTL_SERIAL_CLR_RTS\n");
|
DPRINT("Serial: IOCTL_SERIAL_CLR_RTS\n");
|
||||||
/* FIXME: If the handshake flow control of the device is configured to
|
/* FIXME: If the handshake flow control of the device is configured to
|
||||||
* automatically use RTS, return STATUS_INVALID_PARAMETER */
|
* automatically use RTS, return STATUS_INVALID_PARAMETER */
|
||||||
DeviceExtension->MCR &= ~SR_MCR_RTS;
|
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
|
||||||
WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
|
if (NT_SUCCESS(Status))
|
||||||
Status = STATUS_SUCCESS;
|
{
|
||||||
|
DeviceExtension->MCR &= ~SR_MCR_RTS;
|
||||||
|
WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
|
||||||
|
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IOCTL_SERIAL_CONFIG_SIZE:
|
case IOCTL_SERIAL_CONFIG_SIZE:
|
||||||
|
@ -546,14 +559,20 @@ SerialDeviceControl(
|
||||||
DeviceExtension->InputBuffer.ReadPosition = DeviceExtension->InputBuffer.WritePosition = 0;
|
DeviceExtension->InputBuffer.ReadPosition = DeviceExtension->InputBuffer.WritePosition = 0;
|
||||||
DeviceExtension->OutputBuffer.ReadPosition = DeviceExtension->OutputBuffer.WritePosition = 0;
|
DeviceExtension->OutputBuffer.ReadPosition = DeviceExtension->OutputBuffer.WritePosition = 0;
|
||||||
/* Clear receive/transmit buffers */
|
/* Clear receive/transmit buffers */
|
||||||
if (DeviceExtension->UartType >= Uart16550)
|
if (DeviceExtension->UartType >= Uart16550A)
|
||||||
{
|
{
|
||||||
WRITE_PORT_UCHAR(SER_FCR(ComPortBase),
|
/* 16550 UARTs also have FIFO queues, but they are unusable due to a bug */
|
||||||
SR_FCR_CLEAR_RCVR | SR_FCR_CLEAR_XMIT);
|
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->OutputBufferLock, Irql2);
|
||||||
KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql1);
|
KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql1);
|
||||||
Status = STATUS_SUCCESS;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IOCTL_SERIAL_RESET_DEVICE:
|
case IOCTL_SERIAL_RESET_DEVICE:
|
||||||
|
@ -604,10 +623,16 @@ SerialDeviceControl(
|
||||||
DPRINT("Serial: IOCTL_SERIAL_SET_DTR\n");
|
DPRINT("Serial: IOCTL_SERIAL_SET_DTR\n");
|
||||||
if (!(DeviceExtension->MCR & SR_MCR_DTR))
|
if (!(DeviceExtension->MCR & SR_MCR_DTR))
|
||||||
{
|
{
|
||||||
DeviceExtension->MCR |= SR_MCR_DTR;
|
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
|
||||||
WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case IOCTL_SERIAL_SET_FIFO_CONTROL:
|
case IOCTL_SERIAL_SET_FIFO_CONTROL:
|
||||||
|
@ -617,8 +642,12 @@ SerialDeviceControl(
|
||||||
Status = STATUS_INVALID_PARAMETER;
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WRITE_PORT_UCHAR(SER_FCR(ComPortBase), (UCHAR)((*(PULONG)BufferIn) & 0xff));
|
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
|
||||||
Status = STATUS_SUCCESS;
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
WRITE_PORT_UCHAR(SER_FCR(ComPortBase), (UCHAR)((*(PULONG)BufferIn) & 0xff));
|
||||||
|
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -648,10 +677,14 @@ SerialDeviceControl(
|
||||||
Status = STATUS_INVALID_PARAMETER;
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pMCR = (PULONG)BufferIn;
|
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
|
||||||
DeviceExtension->MCR = (UCHAR)(*pMCR & 0xff);
|
if (NT_SUCCESS(Status))
|
||||||
WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
|
{
|
||||||
Status = STATUS_SUCCESS;
|
pMCR = (PULONG)BufferIn;
|
||||||
|
DeviceExtension->MCR = (UCHAR)(*pMCR & 0xff);
|
||||||
|
WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
|
||||||
|
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -688,10 +721,16 @@ SerialDeviceControl(
|
||||||
DPRINT("Serial: IOCTL_SERIAL_SET_RTS\n");
|
DPRINT("Serial: IOCTL_SERIAL_SET_RTS\n");
|
||||||
if (!(DeviceExtension->MCR & SR_MCR_RTS))
|
if (!(DeviceExtension->MCR & SR_MCR_RTS))
|
||||||
{
|
{
|
||||||
DeviceExtension->MCR |= SR_MCR_RTS;
|
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
|
||||||
WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case IOCTL_SERIAL_SET_TIMEOUTS:
|
case IOCTL_SERIAL_SET_TIMEOUTS:
|
||||||
|
|
|
@ -96,8 +96,8 @@ DetectLegacyDevice(
|
||||||
if (!ResourceList)
|
if (!ResourceList)
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
ResourceList->Count = 1;
|
ResourceList->Count = 1;
|
||||||
ResourceList->List[0].InterfaceType = Isa;
|
ResourceList->List[0].InterfaceType = InterfaceTypeUndefined;
|
||||||
ResourceList->List[0].BusNumber = -1; /* FIXME */
|
ResourceList->List[0].BusNumber = -1; /* unknown */
|
||||||
ResourceList->List[0].PartialResourceList.Version = 1;
|
ResourceList->List[0].PartialResourceList.Version = 1;
|
||||||
ResourceList->List[0].PartialResourceList.Revision = 1;
|
ResourceList->List[0].PartialResourceList.Revision = 1;
|
||||||
ResourceList->List[0].PartialResourceList.Count = 2;
|
ResourceList->List[0].PartialResourceList.Count = 2;
|
||||||
|
@ -137,7 +137,7 @@ DetectLegacyDevice(
|
||||||
{
|
{
|
||||||
Status = IoReportDetectedDevice(
|
Status = IoReportDetectedDevice(
|
||||||
DriverObject,
|
DriverObject,
|
||||||
ResourceList->List[0].InterfaceType, ResourceList->List[0].BusNumber, -1/*FIXME*/,
|
ResourceList->List[0].InterfaceType, ResourceList->List[0].BusNumber, -1 /* unknown */,
|
||||||
ResourceList, NULL,
|
ResourceList, NULL,
|
||||||
TRUE,
|
TRUE,
|
||||||
&Pdo);
|
&Pdo);
|
||||||
|
|
|
@ -105,9 +105,6 @@ SerialSendByte(
|
||||||
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)pDeviceExtension;
|
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)pDeviceExtension;
|
||||||
ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
|
ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
|
||||||
|
|
||||||
DPRINT1("Serial: sending bytes (if any) on COM%lu\n",
|
|
||||||
DeviceExtension->ComPort);
|
|
||||||
|
|
||||||
KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql);
|
KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql);
|
||||||
while (!IsCircularBufferEmpty(&DeviceExtension->OutputBuffer)
|
while (!IsCircularBufferEmpty(&DeviceExtension->OutputBuffer)
|
||||||
&& READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_TBE)
|
&& READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_TBE)
|
||||||
|
|
|
@ -80,7 +80,7 @@ SerialAddDeviceInternal(
|
||||||
KeInitializeSpinLock(&DeviceExtension->OutputBufferLock);
|
KeInitializeSpinLock(&DeviceExtension->OutputBufferLock);
|
||||||
KeInitializeDpc(&DeviceExtension->ReceivedByteDpc, SerialReceiveByte, DeviceExtension);
|
KeInitializeDpc(&DeviceExtension->ReceivedByteDpc, SerialReceiveByte, DeviceExtension);
|
||||||
KeInitializeDpc(&DeviceExtension->SendByteDpc, SerialSendByte, 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);
|
Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -126,8 +126,8 @@ SerialAddDevice(
|
||||||
* not called with a NULL Pdo. Block this call (blocks
|
* not called with a NULL Pdo. Block this call (blocks
|
||||||
* unfortunately all the other PnP serial ports devices).
|
* unfortunately all the other PnP serial ports devices).
|
||||||
*/
|
*/
|
||||||
//return SerialAddDeviceInternal(DriverObject, Pdo, UartUnknown, NULL);
|
return SerialAddDeviceInternal(DriverObject, Pdo, UartUnknown, NULL);
|
||||||
return STATUS_UNSUCCESSFUL;
|
//return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS STDCALL
|
||||||
|
@ -230,8 +230,9 @@ SerialPnpStartDevice(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear receive/transmit buffers */
|
/* 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),
|
WRITE_PORT_UCHAR(SER_FCR(ComPortBase),
|
||||||
SR_FCR_CLEAR_RCVR | SR_FCR_CLEAR_XMIT);
|
SR_FCR_CLEAR_RCVR | SR_FCR_CLEAR_XMIT);
|
||||||
}
|
}
|
||||||
|
@ -307,6 +308,69 @@ SerialPnp(
|
||||||
{
|
{
|
||||||
DPRINT("Serial: IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
|
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 */
|
/* Call lower driver */
|
||||||
Status = ForwardIrpAndWait(DeviceObject, Irp);
|
Status = ForwardIrpAndWait(DeviceObject, Irp);
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
|
|
|
@ -15,9 +15,122 @@
|
||||||
static PVOID
|
static PVOID
|
||||||
SerialGetUserBuffer(IN PIRP Irp)
|
SerialGetUserBuffer(IN PIRP Irp)
|
||||||
{
|
{
|
||||||
ASSERT(Irp);
|
ASSERT(Irp);
|
||||||
|
|
||||||
return Irp->AssociatedIrp.SystemBuffer;
|
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
|
NTSTATUS STDCALL
|
||||||
|
@ -28,12 +141,10 @@ SerialRead(
|
||||||
PIO_STACK_LOCATION Stack;
|
PIO_STACK_LOCATION Stack;
|
||||||
PSERIAL_DEVICE_EXTENSION DeviceExtension;
|
PSERIAL_DEVICE_EXTENSION DeviceExtension;
|
||||||
ULONG Length;
|
ULONG Length;
|
||||||
ULONG Information = 0;
|
|
||||||
PUCHAR Buffer;
|
PUCHAR Buffer;
|
||||||
PUCHAR ComPortBase;
|
PWORKITEM_DATA WorkItemData;
|
||||||
UCHAR ReceivedByte;
|
PIO_WORKITEM WorkItem;
|
||||||
KIRQL Irql;
|
NTSTATUS Status;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
|
||||||
|
|
||||||
DPRINT("Serial: IRP_MJ_READ\n");
|
DPRINT("Serial: IRP_MJ_READ\n");
|
||||||
|
|
||||||
|
@ -43,7 +154,6 @@ SerialRead(
|
||||||
Length = Stack->Parameters.Read.Length;
|
Length = Stack->Parameters.Read.Length;
|
||||||
Buffer = SerialGetUserBuffer(Irp);
|
Buffer = SerialGetUserBuffer(Irp);
|
||||||
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
|
|
||||||
|
|
||||||
if (Stack->Parameters.Read.ByteOffset.QuadPart != 0 || Buffer == NULL)
|
if (Stack->Parameters.Read.ByteOffset.QuadPart != 0 || Buffer == NULL)
|
||||||
{
|
{
|
||||||
|
@ -57,136 +167,79 @@ SerialRead(
|
||||||
goto ByeBye;
|
goto ByeBye;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
/* Calculate time outs */
|
||||||
|
if (DeviceExtension->SerialTimeOuts.ReadIntervalTimeout == INFINITE &&
|
||||||
|
DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier == INFINITE &&
|
||||||
|
DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant > 0 &&
|
||||||
|
DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant < INFINITE)
|
||||||
|
{
|
||||||
|
/* read at least one byte, and at most bytes already received */
|
||||||
|
WorkItemData->DontWait = TRUE;
|
||||||
|
WorkItemData->ReadAtLeastOneByte = TRUE;
|
||||||
|
}
|
||||||
|
else if (DeviceExtension->SerialTimeOuts.ReadIntervalTimeout == INFINITE &&
|
||||||
|
DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant == 0 &&
|
||||||
|
DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier == 0)
|
||||||
|
{
|
||||||
|
/* read only bytes that are already in buffer */
|
||||||
|
WorkItemData->DontWait = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* use timeouts */
|
||||||
|
if (DeviceExtension->SerialTimeOuts.ReadIntervalTimeout != 0)
|
||||||
|
{
|
||||||
|
WorkItemData->UseIntervalTimeout = TRUE;
|
||||||
|
WorkItemData->IntervalTimeout = DeviceExtension->SerialTimeOuts.ReadIntervalTimeout;
|
||||||
|
}
|
||||||
|
if (DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier != 0 ||
|
||||||
|
DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant != 0)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ExFreePoolWithTag(WorkItemData, SERIAL_TAG);
|
||||||
goto ByeBye;
|
goto ByeBye;
|
||||||
|
|
||||||
KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
|
|
||||||
while (Length-- > 0)
|
|
||||||
{
|
|
||||||
Status = PopCircularBufferEntry(&DeviceExtension->InputBuffer, &ReceivedByte);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
break;
|
|
||||||
DPRINT("Serial: read from buffer 0x%x (%c)\n", ReceivedByte, ReceivedByte);
|
|
||||||
Buffer[Information++] = ReceivedByte;
|
|
||||||
}
|
}
|
||||||
KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
|
ReadBytes(DeviceObject, Irp, WorkItemData);
|
||||||
if (Length > 0 &&
|
Status = Irp->IoStatus.Status;
|
||||||
!(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)
|
|
||||||
{
|
|
||||||
/* don't read mode bytes */
|
|
||||||
Length = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* read only one byte */
|
|
||||||
UseTotalTimeout = TRUE;
|
|
||||||
TotalTimeout = DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant;
|
|
||||||
Length = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
|
|
||||||
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
|
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
|
||||||
|
|
||||||
ByeBye:
|
ByeBye:
|
||||||
Irp->IoStatus.Information = Information;
|
|
||||||
Irp->IoStatus.Status = Status;
|
Irp->IoStatus.Status = Status;
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
return Status;
|
return Status;
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
*
|
*
|
||||||
* PROGRAMMERS: Hervé Poussineau (poussine@freesurf.fr)
|
* PROGRAMMERS: Hervé Poussineau (poussine@freesurf.fr)
|
||||||
*/
|
*/
|
||||||
/* FIXME: call IoAcquireRemoveLock/IoReleaseRemoveLock around each I/O operation */
|
|
||||||
|
|
||||||
//#define NDEBUG
|
//#define NDEBUG
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#define STDCALL
|
#define STDCALL
|
||||||
|
|
||||||
#define DPRINT1 DbgPrint("(%s:%d) ", __FILE__, __LINE__), DbgPrint
|
#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))
|
#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24))
|
||||||
|
|
||||||
|
@ -102,6 +102,18 @@ typedef struct _SERIAL_DEVICE_EXTENSION
|
||||||
UCHAR MSR; /* Base+6, Modem Status Register */
|
UCHAR MSR; /* Base+6, Modem Status Register */
|
||||||
} SERIAL_DEVICE_EXTENSION, *PSERIAL_DEVICE_EXTENSION;
|
} 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 SERIAL_TAG TAG('S', 'e', 'r', 'l')
|
||||||
|
|
||||||
#define INFINITE ((ULONG)-1)
|
#define INFINITE ((ULONG)-1)
|
||||||
|
|
Loading…
Reference in a new issue