reactos/drivers/serial/serial/circularbuffer.c

114 lines
3.1 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: Serial port driver
* FILE: drivers/dd/serial/circularbuffer.c
* PURPOSE: Operations on a circular buffer
*
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
*/
#include "serial.h"
#include <debug.h>
NTSTATUS
InitializeCircularBuffer(
IN PCIRCULAR_BUFFER pBuffer,
IN ULONG BufferSize)
{
TRACE_(SERIAL, "InitializeCircularBuffer(pBuffer %p, BufferSize %lu)\n", pBuffer, BufferSize);
ASSERT(pBuffer);
pBuffer->Buffer = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, BufferSize * sizeof(UCHAR), SERIAL_TAG);
if (!pBuffer->Buffer)
return STATUS_INSUFFICIENT_RESOURCES;
pBuffer->Length = BufferSize;
pBuffer->ReadPosition = pBuffer->WritePosition = 0;
return STATUS_SUCCESS;
}
NTSTATUS
FreeCircularBuffer(
IN PCIRCULAR_BUFFER pBuffer)
{
TRACE_(SERIAL, "FreeCircularBuffer(pBuffer %p)\n", pBuffer);
ASSERT(pBuffer);
if (pBuffer->Buffer != NULL)
ExFreePoolWithTag(pBuffer->Buffer, SERIAL_TAG);
return STATUS_SUCCESS;
}
BOOLEAN
IsCircularBufferEmpty(
IN PCIRCULAR_BUFFER pBuffer)
{
TRACE_(SERIAL, "IsCircularBufferEmpty(pBuffer %p)\n", pBuffer);
ASSERT(pBuffer);
return (pBuffer->ReadPosition == pBuffer->WritePosition);
}
ULONG
GetNumberOfElementsInCircularBuffer(
IN PCIRCULAR_BUFFER pBuffer)
{
TRACE_(SERIAL, "GetNumberOfElementsInCircularBuffer(pBuffer %p)\n", pBuffer);
ASSERT(pBuffer);
return (pBuffer->WritePosition + pBuffer->Length - pBuffer->ReadPosition) % pBuffer->Length;
}
NTSTATUS
PushCircularBufferEntry(
IN PCIRCULAR_BUFFER pBuffer,
IN UCHAR Entry)
{
ULONG NextPosition;
TRACE_(SERIAL, "PushCircularBufferEntry(pBuffer %p, Entry 0x%x)\n", pBuffer, Entry);
ASSERT(pBuffer);
ASSERT(pBuffer->Length);
NextPosition = (pBuffer->WritePosition + 1) % pBuffer->Length;
if (NextPosition == pBuffer->ReadPosition)
return STATUS_BUFFER_TOO_SMALL;
pBuffer->Buffer[pBuffer->WritePosition] = Entry;
pBuffer->WritePosition = NextPosition;
return STATUS_SUCCESS;
}
NTSTATUS
PopCircularBufferEntry(
IN PCIRCULAR_BUFFER pBuffer,
OUT PUCHAR Entry)
{
TRACE_(SERIAL, "PopCircularBufferEntry(pBuffer %p)\n", pBuffer);
ASSERT(pBuffer);
ASSERT(pBuffer->Length);
if (IsCircularBufferEmpty(pBuffer))
return STATUS_ARRAY_BOUNDS_EXCEEDED;
*Entry = pBuffer->Buffer[pBuffer->ReadPosition];
pBuffer->ReadPosition = (pBuffer->ReadPosition + 1) % pBuffer->Length;
return STATUS_SUCCESS;
}
NTSTATUS
IncreaseCircularBufferSize(
IN PCIRCULAR_BUFFER pBuffer,
IN ULONG NewBufferSize)
{
PUCHAR NewBuffer;
TRACE_(SERIAL, "IncreaseCircularBufferSize(pBuffer %p, NewBufferSize %lu)\n", pBuffer, NewBufferSize);
ASSERT(pBuffer);
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;
}