- 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
This commit is contained in:
Hervé Poussineau 2005-03-22 22:10:44 +00:00
parent c75445a9d4
commit 64574d47b1
4 changed files with 108 additions and 16 deletions

View file

@ -8,7 +8,7 @@
* PROGRAMMERS: Hervé Poussineau (poussine@freesurf.fr) * PROGRAMMERS: Hervé Poussineau (poussine@freesurf.fr)
*/ */
//#define NDEBUG #define NDEBUG
#include "serial.h" #include "serial.h"
NTSTATUS NTSTATUS
@ -16,7 +16,8 @@ InitializeCircularBuffer(
IN PCIRCULAR_BUFFER pBuffer, IN PCIRCULAR_BUFFER pBuffer,
IN ULONG BufferSize) 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) if (!pBuffer->Buffer)
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
pBuffer->Length = BufferSize; pBuffer->Length = BufferSize;
@ -28,6 +29,7 @@ NTSTATUS
FreeCircularBuffer( FreeCircularBuffer(
IN PCIRCULAR_BUFFER pBuffer) IN PCIRCULAR_BUFFER pBuffer)
{ {
DPRINT("Serial: FreeCircularBuffer(pBuffer %p)\n", pBuffer);
ExFreePoolWithTag(pBuffer->Buffer, SERIAL_TAG); ExFreePoolWithTag(pBuffer->Buffer, SERIAL_TAG);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -36,6 +38,7 @@ BOOLEAN
IsCircularBufferEmpty( IsCircularBufferEmpty(
IN PCIRCULAR_BUFFER pBuffer) IN PCIRCULAR_BUFFER pBuffer)
{ {
DPRINT("Serial: IsCircularBufferEmpty(pBuffer %p)\n", pBuffer);
return (pBuffer->ReadPosition == pBuffer->WritePosition); return (pBuffer->ReadPosition == pBuffer->WritePosition);
} }
@ -44,6 +47,7 @@ PushCircularBufferEntry(
IN PCIRCULAR_BUFFER pBuffer, IN PCIRCULAR_BUFFER pBuffer,
IN UCHAR Entry) IN UCHAR Entry)
{ {
DPRINT("Serial: PushCircularBufferEntry(pBuffer %p, Entry 0x%x)\n", pBuffer, Entry);
ASSERT(pBuffer->Length); ASSERT(pBuffer->Length);
ULONG NextPosition = (pBuffer->WritePosition + 1) % pBuffer->Length; ULONG NextPosition = (pBuffer->WritePosition + 1) % pBuffer->Length;
if (NextPosition == pBuffer->ReadPosition) if (NextPosition == pBuffer->ReadPosition)
@ -58,6 +62,7 @@ PopCircularBufferEntry(
IN PCIRCULAR_BUFFER pBuffer, IN PCIRCULAR_BUFFER pBuffer,
OUT PUCHAR Entry) OUT PUCHAR Entry)
{ {
DPRINT("Serial: PopCircularBufferEntry(pBuffer %p)\n", pBuffer);
ASSERT(pBuffer->Length); ASSERT(pBuffer->Length);
if (IsCircularBufferEmpty(pBuffer)) if (IsCircularBufferEmpty(pBuffer))
return STATUS_ARRAY_BOUNDS_EXCEEDED; return STATUS_ARRAY_BOUNDS_EXCEEDED;
@ -65,3 +70,27 @@ PopCircularBufferEntry(
pBuffer->ReadPosition = (pBuffer->ReadPosition + 1) % pBuffer->Length; pBuffer->ReadPosition = (pBuffer->ReadPosition + 1) % pBuffer->Length;
return STATUS_SUCCESS; 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;
}

View file

@ -60,16 +60,13 @@ SerialSetBaudRate(
{ {
UCHAR Lcr; UCHAR Lcr;
DPRINT("Serial: SerialSetBaudRate(COM%lu, %lu Bauds)\n", DeviceExtension->ComPort, BaudRate); 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 */ /* Set Bit 7 of LCR to expose baud registers */
Lcr = READ_PORT_UCHAR(SER_LCR(ComPortBase)); Lcr = READ_PORT_UCHAR(SER_LCR(ComPortBase));
Lcr |= SR_LCR_DLAB; WRITE_PORT_UCHAR(SER_LCR(ComPortBase), Lcr | SR_LCR_DLAB);
WRITE_PORT_UCHAR(SER_LCR(ComPortBase), Lcr);
/* Write the baud rate */ /* Write the baud rate */
WRITE_PORT_UCHAR(SER_DLL(ComPortBase), divisor & 0xff); WRITE_PORT_UCHAR(SER_DLL(ComPortBase), divisor & 0xff);
WRITE_PORT_UCHAR(SER_DLM(ComPortBase), divisor >> 8); WRITE_PORT_UCHAR(SER_DLM(ComPortBase), divisor >> 8);
/* Switch back to normal registers */ /* Switch back to normal registers */
Lcr ^= SR_LCR_DLAB;
WRITE_PORT_UCHAR(SER_LCR(ComPortBase), Lcr); WRITE_PORT_UCHAR(SER_LCR(ComPortBase), Lcr);
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort); IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
@ -77,7 +74,7 @@ SerialSetBaudRate(
} }
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
DeviceExtension->BaudRate = NewBaudRate; DeviceExtension->BaudRate = BaudRate;
return Status; return Status;
} }
@ -213,6 +210,25 @@ SerialGetCommProp(
return STATUS_SUCCESS; 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 NTSTATUS STDCALL
SerialDeviceControl( SerialDeviceControl(
IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_OBJECT DeviceObject,
@ -289,6 +305,8 @@ SerialDeviceControl(
case IOCTL_SERIAL_GET_BAUD_RATE: case IOCTL_SERIAL_GET_BAUD_RATE:
{ {
DPRINT("Serial: IOCTL_SERIAL_GET_BAUD_RATE\n"); 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)) if (LengthOut < sizeof(SERIAL_BAUD_RATE))
Status = STATUS_BUFFER_TOO_SMALL; Status = STATUS_BUFFER_TOO_SMALL;
else if (Buffer == NULL) else if (Buffer == NULL)
@ -309,9 +327,22 @@ SerialDeviceControl(
} }
case IOCTL_SERIAL_GET_COMMSTATUS: case IOCTL_SERIAL_GET_COMMSTATUS:
{ {
/* FIXME */ DPRINT("Serial: IOCTL_SERIAL_GET_COMMSTATUS\n");
DPRINT1("Serial: IOCTL_SERIAL_GET_COMMSTATUS not implemented.\n"); if (LengthOut < sizeof(SERIAL_STATUS))
Status = STATUS_NOT_IMPLEMENTED; {
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; break;
} }
case IOCTL_SERIAL_GET_DTRRTS: case IOCTL_SERIAL_GET_DTRRTS:
@ -466,9 +497,18 @@ SerialDeviceControl(
} }
case IOCTL_SERIAL_PURGE: case IOCTL_SERIAL_PURGE:
{ {
/* FIXME */ DPRINT("Serial: IOCTL_SERIAL_PURGE\n");
DPRINT1("Serial: IOCTL_SERIAL_PURGE not implemented.\n"); /* FIXME: lock input and output queues */
Status = STATUS_NOT_IMPLEMENTED; 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; break;
} }
case IOCTL_SERIAL_RESET_DEVICE: case IOCTL_SERIAL_RESET_DEVICE:
@ -572,9 +612,26 @@ SerialDeviceControl(
} }
case IOCTL_SERIAL_SET_QUEUE_SIZE: case IOCTL_SERIAL_SET_QUEUE_SIZE:
{ {
/* FIXME */ if (LengthIn < sizeof(SERIAL_QUEUE_SIZE ))
DPRINT1("Serial: IOCTL_SERIAL_SET_QUEUE_SIZE not implemented.\n"); return STATUS_BUFFER_TOO_SMALL;
Status = STATUS_NOT_IMPLEMENTED; 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; break;
} }
case IOCTL_SERIAL_SET_RTS: case IOCTL_SERIAL_SET_RTS:

View file

@ -83,6 +83,7 @@ SerialAddDeviceInternal(
DPRINT("Serial: IoAttachDeviceToDeviceStackSafe() failed with status 0x%08x\n", Status); DPRINT("Serial: IoAttachDeviceToDeviceStackSafe() failed with status 0x%08x\n", Status);
goto ByeBye; goto ByeBye;
} }
Fdo->Flags |= DO_BUFFERED_IO;
Fdo->Flags &= ~DO_DEVICE_INITIALIZING; Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
if (pFdo) if (pFdo)
{ {

View file

@ -178,6 +178,11 @@ PopCircularBufferEntry(
IN PCIRCULAR_BUFFER pBuffer, IN PCIRCULAR_BUFFER pBuffer,
OUT PUCHAR Entry); OUT PUCHAR Entry);
NTSTATUS
IncreaseCircularBufferSize(
IN PCIRCULAR_BUFFER pBuffer,
IN ULONG NewBufferSize);
/************************************ cleanup.c */ /************************************ cleanup.c */
NTSTATUS STDCALL NTSTATUS STDCALL