Sync with trunk r65656.
[reactos.git] / drivers / serial / serial / circularbuffer.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: Serial port driver
4 * FILE: drivers/dd/serial/circularbuffer.c
5 * PURPOSE: Operations on a circular buffer
6 *
7 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
8 */
9
10 #include "serial.h"
11
12 #include <debug.h>
13
14 NTSTATUS
15 InitializeCircularBuffer(
16 IN PCIRCULAR_BUFFER pBuffer,
17 IN ULONG BufferSize)
18 {
19 TRACE_(SERIAL, "InitializeCircularBuffer(pBuffer %p, BufferSize %lu)\n", pBuffer, BufferSize);
20 ASSERT(pBuffer);
21 pBuffer->Buffer = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, BufferSize * sizeof(UCHAR), SERIAL_TAG);
22 if (!pBuffer->Buffer)
23 return STATUS_INSUFFICIENT_RESOURCES;
24 pBuffer->Length = BufferSize;
25 pBuffer->ReadPosition = pBuffer->WritePosition = 0;
26 return STATUS_SUCCESS;
27 }
28
29 NTSTATUS
30 FreeCircularBuffer(
31 IN PCIRCULAR_BUFFER pBuffer)
32 {
33 TRACE_(SERIAL, "FreeCircularBuffer(pBuffer %p)\n", pBuffer);
34 ASSERT(pBuffer);
35 if (pBuffer->Buffer != NULL)
36 ExFreePoolWithTag(pBuffer->Buffer, SERIAL_TAG);
37 return STATUS_SUCCESS;
38 }
39
40 BOOLEAN
41 IsCircularBufferEmpty(
42 IN PCIRCULAR_BUFFER pBuffer)
43 {
44 TRACE_(SERIAL, "IsCircularBufferEmpty(pBuffer %p)\n", pBuffer);
45 ASSERT(pBuffer);
46 return (pBuffer->ReadPosition == pBuffer->WritePosition);
47 }
48
49 ULONG
50 GetNumberOfElementsInCircularBuffer(
51 IN PCIRCULAR_BUFFER pBuffer)
52 {
53 TRACE_(SERIAL, "GetNumberOfElementsInCircularBuffer(pBuffer %p)\n", pBuffer);
54 ASSERT(pBuffer);
55 return (pBuffer->WritePosition + pBuffer->Length - pBuffer->ReadPosition) % pBuffer->Length;
56 }
57
58 NTSTATUS
59 PushCircularBufferEntry(
60 IN PCIRCULAR_BUFFER pBuffer,
61 IN UCHAR Entry)
62 {
63 ULONG NextPosition;
64 TRACE_(SERIAL, "PushCircularBufferEntry(pBuffer %p, Entry 0x%x)\n", pBuffer, Entry);
65 ASSERT(pBuffer);
66 ASSERT(pBuffer->Length);
67 NextPosition = (pBuffer->WritePosition + 1) % pBuffer->Length;
68 if (NextPosition == pBuffer->ReadPosition)
69 return STATUS_BUFFER_TOO_SMALL;
70 pBuffer->Buffer[pBuffer->WritePosition] = Entry;
71 pBuffer->WritePosition = NextPosition;
72 return STATUS_SUCCESS;
73 }
74
75 NTSTATUS
76 PopCircularBufferEntry(
77 IN PCIRCULAR_BUFFER pBuffer,
78 OUT PUCHAR Entry)
79 {
80 TRACE_(SERIAL, "PopCircularBufferEntry(pBuffer %p)\n", pBuffer);
81 ASSERT(pBuffer);
82 ASSERT(pBuffer->Length);
83 if (IsCircularBufferEmpty(pBuffer))
84 return STATUS_ARRAY_BOUNDS_EXCEEDED;
85 *Entry = pBuffer->Buffer[pBuffer->ReadPosition];
86 pBuffer->ReadPosition = (pBuffer->ReadPosition + 1) % pBuffer->Length;
87 return STATUS_SUCCESS;
88 }
89
90 NTSTATUS
91 IncreaseCircularBufferSize(
92 IN PCIRCULAR_BUFFER pBuffer,
93 IN ULONG NewBufferSize)
94 {
95 PUCHAR NewBuffer;
96
97 TRACE_(SERIAL, "IncreaseCircularBufferSize(pBuffer %p, NewBufferSize %lu)\n", pBuffer, NewBufferSize);
98 ASSERT(pBuffer);
99 ASSERT(pBuffer->Length);
100 if (pBuffer->Length > NewBufferSize)
101 return STATUS_INVALID_PARAMETER;
102 else if (pBuffer->Length == NewBufferSize)
103 return STATUS_SUCCESS;
104
105 NewBuffer = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, NewBufferSize * sizeof(UCHAR), SERIAL_TAG);
106 if (!NewBuffer)
107 return STATUS_INSUFFICIENT_RESOURCES;
108 RtlCopyMemory(NewBuffer, pBuffer->Buffer, pBuffer->Length * sizeof(UCHAR));
109 ExFreePoolWithTag(pBuffer->Buffer, SERIAL_TAG);
110 pBuffer->Buffer = NewBuffer;
111 pBuffer->Length = NewBufferSize;
112 return STATUS_SUCCESS;
113 }