- Update to r53061
[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 NTSTATUS
13 InitializeCircularBuffer(
14 IN PCIRCULAR_BUFFER pBuffer,
15 IN ULONG BufferSize)
16 {
17 TRACE_(SERIAL, "InitializeCircularBuffer(pBuffer %p, BufferSize %lu)\n", pBuffer, BufferSize);
18 ASSERT(pBuffer);
19 pBuffer->Buffer = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, BufferSize * sizeof(UCHAR), SERIAL_TAG);
20 if (!pBuffer->Buffer)
21 return STATUS_INSUFFICIENT_RESOURCES;
22 pBuffer->Length = BufferSize;
23 pBuffer->ReadPosition = pBuffer->WritePosition = 0;
24 return STATUS_SUCCESS;
25 }
26
27 NTSTATUS
28 FreeCircularBuffer(
29 IN PCIRCULAR_BUFFER pBuffer)
30 {
31 TRACE_(SERIAL, "FreeCircularBuffer(pBuffer %p)\n", pBuffer);
32 ASSERT(pBuffer);
33 if (pBuffer->Buffer != NULL)
34 ExFreePoolWithTag(pBuffer->Buffer, SERIAL_TAG);
35 return STATUS_SUCCESS;
36 }
37
38 BOOLEAN
39 IsCircularBufferEmpty(
40 IN PCIRCULAR_BUFFER pBuffer)
41 {
42 TRACE_(SERIAL, "IsCircularBufferEmpty(pBuffer %p)\n", pBuffer);
43 ASSERT(pBuffer);
44 return (pBuffer->ReadPosition == pBuffer->WritePosition);
45 }
46
47 ULONG
48 GetNumberOfElementsInCircularBuffer(
49 IN PCIRCULAR_BUFFER pBuffer)
50 {
51 TRACE_(SERIAL, "GetNumberOfElementsInCircularBuffer(pBuffer %p)\n", pBuffer);
52 ASSERT(pBuffer);
53 return (pBuffer->WritePosition + pBuffer->Length - pBuffer->ReadPosition) % pBuffer->Length;
54 }
55
56 NTSTATUS
57 PushCircularBufferEntry(
58 IN PCIRCULAR_BUFFER pBuffer,
59 IN UCHAR Entry)
60 {
61 ULONG NextPosition;
62 TRACE_(SERIAL, "PushCircularBufferEntry(pBuffer %p, Entry 0x%x)\n", pBuffer, Entry);
63 ASSERT(pBuffer);
64 ASSERT(pBuffer->Length);
65 NextPosition = (pBuffer->WritePosition + 1) % pBuffer->Length;
66 if (NextPosition == pBuffer->ReadPosition)
67 return STATUS_BUFFER_TOO_SMALL;
68 pBuffer->Buffer[pBuffer->WritePosition] = Entry;
69 pBuffer->WritePosition = NextPosition;
70 return STATUS_SUCCESS;
71 }
72
73 NTSTATUS
74 PopCircularBufferEntry(
75 IN PCIRCULAR_BUFFER pBuffer,
76 OUT PUCHAR Entry)
77 {
78 TRACE_(SERIAL, "PopCircularBufferEntry(pBuffer %p)\n", pBuffer);
79 ASSERT(pBuffer);
80 ASSERT(pBuffer->Length);
81 if (IsCircularBufferEmpty(pBuffer))
82 return STATUS_ARRAY_BOUNDS_EXCEEDED;
83 *Entry = pBuffer->Buffer[pBuffer->ReadPosition];
84 pBuffer->ReadPosition = (pBuffer->ReadPosition + 1) % pBuffer->Length;
85 return STATUS_SUCCESS;
86 }
87
88 NTSTATUS
89 IncreaseCircularBufferSize(
90 IN PCIRCULAR_BUFFER pBuffer,
91 IN ULONG NewBufferSize)
92 {
93 PUCHAR NewBuffer;
94
95 TRACE_(SERIAL, "IncreaseCircularBufferSize(pBuffer %p, NewBufferSize %lu)\n", pBuffer, NewBufferSize);
96 ASSERT(pBuffer);
97 ASSERT(pBuffer->Length);
98 if (pBuffer->Length > NewBufferSize)
99 return STATUS_INVALID_PARAMETER;
100 else if (pBuffer->Length == NewBufferSize)
101 return STATUS_SUCCESS;
102
103 NewBuffer = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, NewBufferSize * sizeof(UCHAR), SERIAL_TAG);
104 if (!NewBuffer)
105 return STATUS_INSUFFICIENT_RESOURCES;
106 RtlCopyMemory(NewBuffer, pBuffer->Buffer, pBuffer->Length * sizeof(UCHAR));
107 ExFreePoolWithTag(pBuffer->Buffer, SERIAL_TAG);
108 pBuffer->Buffer = NewBuffer;
109 pBuffer->Length = NewBufferSize;
110 return STATUS_SUCCESS;
111 }