From 64574d47b1ee2ca6a57df3de33c5c947e6c213b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Tue, 22 Mar 2005 22:10:44 +0000 Subject: [PATCH] - Implement IOCTL_SERIAL_GET_COMMSTATUS, IOCTL_SERIAL_PURGE, IOCTL_SET_QUEUE_SIZE - Add a hack in IOCTL_SERIAL_GET_BAUD_RATE to get it working with mode.exe svn path=/trunk/; revision=14273 --- reactos/drivers/dd/serial/circularbuffer.c | 33 ++++++++- reactos/drivers/dd/serial/devctrl.c | 85 ++++++++++++++++++---- reactos/drivers/dd/serial/pnp.c | 1 + reactos/drivers/dd/serial/serial.h | 5 ++ 4 files changed, 108 insertions(+), 16 deletions(-) diff --git a/reactos/drivers/dd/serial/circularbuffer.c b/reactos/drivers/dd/serial/circularbuffer.c index 85b83bab49b..0b533b8db01 100644 --- a/reactos/drivers/dd/serial/circularbuffer.c +++ b/reactos/drivers/dd/serial/circularbuffer.c @@ -8,7 +8,7 @@ * PROGRAMMERS: Hervé Poussineau (poussine@freesurf.fr) */ -//#define NDEBUG +#define NDEBUG #include "serial.h" NTSTATUS @@ -16,7 +16,8 @@ InitializeCircularBuffer( IN PCIRCULAR_BUFFER pBuffer, IN ULONG BufferSize) { - pBuffer->Buffer = ExAllocatePoolWithTag(NonPagedPool, BufferSize * sizeof(UCHAR), SERIAL_TAG); + DPRINT("Serial: InitializeCircularBuffer(pBuffer %p, BufferSize %lu)\n", pBuffer, BufferSize); + pBuffer->Buffer = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, BufferSize * sizeof(UCHAR), SERIAL_TAG); if (!pBuffer->Buffer) return STATUS_INSUFFICIENT_RESOURCES; pBuffer->Length = BufferSize; @@ -28,6 +29,7 @@ NTSTATUS FreeCircularBuffer( IN PCIRCULAR_BUFFER pBuffer) { + DPRINT("Serial: FreeCircularBuffer(pBuffer %p)\n", pBuffer); ExFreePoolWithTag(pBuffer->Buffer, SERIAL_TAG); return STATUS_SUCCESS; } @@ -36,6 +38,7 @@ BOOLEAN IsCircularBufferEmpty( IN PCIRCULAR_BUFFER pBuffer) { + DPRINT("Serial: IsCircularBufferEmpty(pBuffer %p)\n", pBuffer); return (pBuffer->ReadPosition == pBuffer->WritePosition); } @@ -44,6 +47,7 @@ PushCircularBufferEntry( IN PCIRCULAR_BUFFER pBuffer, IN UCHAR Entry) { + DPRINT("Serial: PushCircularBufferEntry(pBuffer %p, Entry 0x%x)\n", pBuffer, Entry); ASSERT(pBuffer->Length); ULONG NextPosition = (pBuffer->WritePosition + 1) % pBuffer->Length; if (NextPosition == pBuffer->ReadPosition) @@ -58,6 +62,7 @@ PopCircularBufferEntry( IN PCIRCULAR_BUFFER pBuffer, OUT PUCHAR Entry) { + DPRINT("Serial: PopCircularBufferEntry(pBuffer %p)\n", pBuffer); ASSERT(pBuffer->Length); if (IsCircularBufferEmpty(pBuffer)) return STATUS_ARRAY_BOUNDS_EXCEEDED; @@ -65,3 +70,27 @@ PopCircularBufferEntry( pBuffer->ReadPosition = (pBuffer->ReadPosition + 1) % pBuffer->Length; return STATUS_SUCCESS; } + +NTSTATUS +IncreaseCircularBufferSize( + IN PCIRCULAR_BUFFER pBuffer, + IN ULONG NewBufferSize) +{ + PUCHAR NewBuffer; + + DPRINT("Serial: IncreaseCircularBufferSize(pBuffer %p, NewBufferSize %lu)\n", pBuffer, NewBufferSize); + ASSERT(pBuffer->Length); + if (pBuffer->Length > NewBufferSize) + return STATUS_INVALID_PARAMETER; + else if (pBuffer->Length == NewBufferSize) + return STATUS_SUCCESS; + + NewBuffer = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, NewBufferSize * sizeof(UCHAR), SERIAL_TAG); + if (!NewBuffer) + return STATUS_INSUFFICIENT_RESOURCES; + RtlCopyMemory(NewBuffer, pBuffer->Buffer, pBuffer->Length * sizeof(UCHAR)); + ExFreePoolWithTag(pBuffer->Buffer, SERIAL_TAG); + pBuffer->Buffer = NewBuffer; + pBuffer->Length = NewBufferSize; + return STATUS_SUCCESS; +} diff --git a/reactos/drivers/dd/serial/devctrl.c b/reactos/drivers/dd/serial/devctrl.c index abaf6f48f58..07b7c119512 100644 --- a/reactos/drivers/dd/serial/devctrl.c +++ b/reactos/drivers/dd/serial/devctrl.c @@ -60,16 +60,13 @@ SerialSetBaudRate( { UCHAR Lcr; DPRINT("Serial: SerialSetBaudRate(COM%lu, %lu Bauds)\n", DeviceExtension->ComPort, BaudRate); - /* FIXME: update DeviceExtension->LowerDevice when modifying LCR? */ /* Set Bit 7 of LCR to expose baud registers */ Lcr = READ_PORT_UCHAR(SER_LCR(ComPortBase)); - Lcr |= SR_LCR_DLAB; - WRITE_PORT_UCHAR(SER_LCR(ComPortBase), Lcr); + WRITE_PORT_UCHAR(SER_LCR(ComPortBase), Lcr | SR_LCR_DLAB); /* Write the baud rate */ WRITE_PORT_UCHAR(SER_DLL(ComPortBase), divisor & 0xff); WRITE_PORT_UCHAR(SER_DLM(ComPortBase), divisor >> 8); /* Switch back to normal registers */ - Lcr ^= SR_LCR_DLAB; WRITE_PORT_UCHAR(SER_LCR(ComPortBase), Lcr); IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort); @@ -77,7 +74,7 @@ SerialSetBaudRate( } if (NT_SUCCESS(Status)) - DeviceExtension->BaudRate = NewBaudRate; + DeviceExtension->BaudRate = BaudRate; return Status; } @@ -213,6 +210,25 @@ SerialGetCommProp( return STATUS_SUCCESS; } +NTSTATUS +SerialGetCommStatus( + OUT PSERIAL_STATUS pSerialStatus, + IN PSERIAL_DEVICE_EXTENSION DeviceExtension) +{ + RtlZeroMemory(pSerialStatus, sizeof(SERIAL_STATUS)); + + pSerialStatus->Errors = 0; /* FIXME */ + pSerialStatus->HoldReasons = 0; /* FIXME */ + pSerialStatus->AmountInInQueue = (DeviceExtension->InputBuffer.WritePosition + DeviceExtension->InputBuffer.Length + - DeviceExtension->InputBuffer.ReadPosition) % DeviceExtension->InputBuffer.Length; + pSerialStatus->AmountInOutQueue = (DeviceExtension->OutputBuffer.WritePosition + DeviceExtension->OutputBuffer.Length + - DeviceExtension->OutputBuffer.ReadPosition) % DeviceExtension->OutputBuffer.Length; + pSerialStatus->EofReceived = FALSE; /* FIXME */ + pSerialStatus->WaitForImmediate = FALSE; /* FIXME */ + + return STATUS_SUCCESS; +} + NTSTATUS STDCALL SerialDeviceControl( IN PDEVICE_OBJECT DeviceObject, @@ -289,6 +305,8 @@ SerialDeviceControl( case IOCTL_SERIAL_GET_BAUD_RATE: { DPRINT("Serial: IOCTL_SERIAL_GET_BAUD_RATE\n"); + /* FIXME: HACK!!! following line MUST NOT be here! */ + Buffer = Irp->UserBuffer; if (LengthOut < sizeof(SERIAL_BAUD_RATE)) Status = STATUS_BUFFER_TOO_SMALL; else if (Buffer == NULL) @@ -309,9 +327,22 @@ SerialDeviceControl( } case IOCTL_SERIAL_GET_COMMSTATUS: { - /* FIXME */ - DPRINT1("Serial: IOCTL_SERIAL_GET_COMMSTATUS not implemented.\n"); - Status = STATUS_NOT_IMPLEMENTED; + DPRINT("Serial: IOCTL_SERIAL_GET_COMMSTATUS\n"); + if (LengthOut < sizeof(SERIAL_STATUS)) + { + DPRINT("Serial: return STATUS_BUFFER_TOO_SMALL\n"); + Status = STATUS_BUFFER_TOO_SMALL; + } + else if (Buffer == NULL) + { + DPRINT("Serial: return STATUS_INVALID_PARAMETER\n"); + Status = STATUS_INVALID_PARAMETER; + } + else + { + Status = SerialGetCommStatus((PSERIAL_STATUS)Buffer, DeviceExtension); + Information = sizeof(SERIAL_STATUS); + } break; } case IOCTL_SERIAL_GET_DTRRTS: @@ -466,9 +497,18 @@ SerialDeviceControl( } case IOCTL_SERIAL_PURGE: { - /* FIXME */ - DPRINT1("Serial: IOCTL_SERIAL_PURGE not implemented.\n"); - Status = STATUS_NOT_IMPLEMENTED; + DPRINT("Serial: IOCTL_SERIAL_PURGE\n"); + /* FIXME: lock input and output queues */ + DeviceExtension->InputBuffer.ReadPosition = DeviceExtension->InputBuffer.WritePosition = 0; + DeviceExtension->OutputBuffer.ReadPosition = DeviceExtension->OutputBuffer.WritePosition = 0; + /* Clear receive/transmit buffers */ + if (DeviceExtension->UartType >= Uart16550) + { + WRITE_PORT_UCHAR(SER_FCR(ComPortBase), + SR_FCR_CLEAR_RCVR | SR_FCR_CLEAR_XMIT); + } + /* FIXME: unlock input and output queues */ + Status = STATUS_SUCCESS; break; } case IOCTL_SERIAL_RESET_DEVICE: @@ -572,9 +612,26 @@ SerialDeviceControl( } case IOCTL_SERIAL_SET_QUEUE_SIZE: { - /* FIXME */ - DPRINT1("Serial: IOCTL_SERIAL_SET_QUEUE_SIZE not implemented.\n"); - Status = STATUS_NOT_IMPLEMENTED; + if (LengthIn < sizeof(SERIAL_QUEUE_SIZE )) + return STATUS_BUFFER_TOO_SMALL; + else if (Buffer == NULL) + return STATUS_INVALID_PARAMETER; + else + { + Status = STATUS_SUCCESS; + if (((PSERIAL_QUEUE_SIZE)Buffer)->InSize > DeviceExtension->InputBuffer.Length) + { + /* FIXME: lock input queue */ + Status = IncreaseCircularBufferSize(&DeviceExtension->InputBuffer, ((PSERIAL_QUEUE_SIZE)Buffer)->InSize); + /* FIXME: unlock input queue */ + } + if (NT_SUCCESS(Status) && ((PSERIAL_QUEUE_SIZE)Buffer)->OutSize > DeviceExtension->OutputBuffer.Length) + { + /* FIXME: lock output queue */ + Status = IncreaseCircularBufferSize(&DeviceExtension->OutputBuffer, ((PSERIAL_QUEUE_SIZE)Buffer)->OutSize); + /* FIXME: unlock output queue */ + } + } break; } case IOCTL_SERIAL_SET_RTS: diff --git a/reactos/drivers/dd/serial/pnp.c b/reactos/drivers/dd/serial/pnp.c index 8708c237085..745552b3b51 100644 --- a/reactos/drivers/dd/serial/pnp.c +++ b/reactos/drivers/dd/serial/pnp.c @@ -83,6 +83,7 @@ SerialAddDeviceInternal( DPRINT("Serial: IoAttachDeviceToDeviceStackSafe() failed with status 0x%08x\n", Status); goto ByeBye; } + Fdo->Flags |= DO_BUFFERED_IO; Fdo->Flags &= ~DO_DEVICE_INITIALIZING; if (pFdo) { diff --git a/reactos/drivers/dd/serial/serial.h b/reactos/drivers/dd/serial/serial.h index e4f1f801eee..d6a3ef1e210 100644 --- a/reactos/drivers/dd/serial/serial.h +++ b/reactos/drivers/dd/serial/serial.h @@ -178,6 +178,11 @@ PopCircularBufferEntry( IN PCIRCULAR_BUFFER pBuffer, OUT PUCHAR Entry); +NTSTATUS +IncreaseCircularBufferSize( + IN PCIRCULAR_BUFFER pBuffer, + IN ULONG NewBufferSize); + /************************************ cleanup.c */ NTSTATUS STDCALL