Rev 19 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
19 | f9daq | 1 | //------------------------------------------------------------------------- |
2 | // WINNT driver for PCIVME interface from ARW Elektronik, Germany --------- |
||
3 | // functions for a fast fifo (first in first out) implementation |
||
4 | // |
||
5 | // (c) 1999-2004 ARW Elektronik |
||
6 | // |
||
7 | // this source code is published under GPL (Open Source). You can use, redistrubute and |
||
8 | // modify it unless this header is not modified or deleted. No warranty is given that |
||
9 | // this software will work like expected. |
||
10 | // This product is not authorized for use as critical component in life support systems |
||
11 | // wihout the express written approval of ARW Elektronik Germany. |
||
12 | // |
||
13 | // Please announce changes and hints to ARW Elektronik |
||
14 | // |
||
15 | // $Log: pcivme_fifo.c,v $ |
||
16 | // Revision 1.3 2004/07/24 07:07:26 klaus |
||
17 | // Update copyright to 2004 |
||
18 | // |
||
19 | // Revision 1.2 2003/11/15 19:12:50 klaus |
||
20 | // Update copyright to 2003 |
||
21 | // |
||
22 | // Revision 1.1.1.1 2003/11/14 23:16:33 klaus |
||
23 | // First put into repository |
||
24 | // |
||
25 | // Revision 1.3 2002/10/27 16:17:48 klaus |
||
26 | // Typing bug fixed caused at log addition |
||
27 | // |
||
28 | // Revision 1.2 2002/10/27 16:11:02 klaus |
||
29 | // Added CVS log into header |
||
30 | // |
||
31 | // what who when |
||
32 | // started AR 06.10.1999 |
||
33 | // first release 1.0 AR 17.10.1999 |
||
34 | // |
||
35 | |||
36 | //------------------------------------------------------------------------- |
||
37 | // INCLUDES |
||
38 | // |
||
39 | #include <ntddk.h> |
||
40 | #include <pcivme_fifo.h> |
||
41 | |||
42 | //------------------------------------------------------------------------ |
||
43 | // DEFINES |
||
44 | // |
||
45 | |||
46 | //------------------------------------------------------------------------ |
||
47 | // TYPEDEFS |
||
48 | // |
||
49 | typedef struct |
||
50 | { |
||
51 | USHORT wLevel; // actual Number of Elements |
||
52 | UCHAR *pbBegin; // points to begin of the buffer |
||
53 | UCHAR *pbEnd; // points to the (end of the buffer + 1) |
||
54 | UCHAR *pbWrite; // next write here |
||
55 | UCHAR *pbRead; // next read (if any) here |
||
56 | KSPIN_LOCK Lock; // to guard access to the fifo |
||
57 | BOOLEAN bOverflow; // indicates a overflow to that FIFO |
||
58 | } FIFO_MANAGER; |
||
59 | |||
60 | |||
61 | //------------------------------------------------------------------------ |
||
62 | // FUNCTIONS |
||
63 | // |
||
64 | |||
65 | // the global functions to manage the fifo |
||
66 | // first: init the fifo and allocate nonpaged memory |
||
67 | NTSTATUS InitializeFIFO(USHORT CountOfElements, PVOID *pHandle) |
||
68 | { |
||
69 | ULONG allocSize; |
||
70 | register FIFO_MANAGER *fifo_manager; |
||
71 | |||
72 | *pHandle = NULL; |
||
73 | allocSize = sizeof(FIFO_MANAGER) + sizeof(UCHAR) * CountOfElements + 16; // cause alignment |
||
74 | |||
75 | *pHandle = ExAllocatePool(NonPagedPool, allocSize); |
||
76 | if(*pHandle == NULL) return STATUS_NO_MEMORY; |
||
77 | |||
78 | RtlZeroMemory(*pHandle, allocSize); |
||
79 | |||
80 | fifo_manager = (FIFO_MANAGER *)*pHandle; |
||
81 | |||
82 | // init the fifo_manager |
||
83 | KeInitializeSpinLock(&fifo_manager->Lock); |
||
84 | fifo_manager->wLevel = 0; |
||
85 | fifo_manager->bOverflow = FALSE; |
||
86 | fifo_manager->pbBegin = (UCHAR *)(((ULONG)(fifo_manager + 1) + 8) & ~7); //align |
||
87 | fifo_manager->pbEnd = (UCHAR *)((ULONG)fifo_manager->pbBegin + sizeof(UCHAR) * CountOfElements); |
||
88 | fifo_manager->pbWrite = |
||
89 | fifo_manager->pbRead = fifo_manager->pbBegin; |
||
90 | |||
91 | // KdPrint(("fifo_manager: 0x%08x, begin: 0x%08x, end: 0x%08x\n", |
||
92 | // fifo_manager, fifo_manager->pbBegin, fifo_manager->pbEnd)); |
||
93 | |||
94 | return STATUS_SUCCESS; |
||
95 | } |
||
96 | |||
97 | // second: push elements to the FIFO |
||
98 | int PushElement(PVOID Handle, UCHAR bElement) |
||
99 | { |
||
100 | register FIFO_MANAGER *fifo_manager = (FIFO_MANAGER *)Handle; |
||
101 | KIRQL oldIrql; |
||
102 | |||
103 | KeAcquireSpinLock(&fifo_manager->Lock, &oldIrql); |
||
104 | if ((fifo_manager->wLevel) && (fifo_manager->pbWrite == fifo_manager->pbRead)) |
||
105 | { |
||
106 | KeReleaseSpinLock(&fifo_manager->Lock, oldIrql); |
||
107 | return fifo_manager->wLevel; |
||
108 | } |
||
109 | |||
110 | *(fifo_manager->pbWrite)++ = bElement; |
||
111 | |||
112 | // wrap around |
||
113 | if (fifo_manager->pbWrite >= fifo_manager->pbEnd) |
||
114 | fifo_manager->pbWrite = fifo_manager->pbBegin; |
||
115 | |||
116 | // check for overflow - indicate - and reset pointer to same before |
||
117 | if (fifo_manager->pbWrite == fifo_manager->pbRead) |
||
118 | { |
||
119 | fifo_manager->bOverflow = TRUE; |
||
120 | fifo_manager->pbWrite--; |
||
121 | if (fifo_manager->pbWrite < fifo_manager->pbBegin) |
||
122 | fifo_manager->pbWrite = fifo_manager->pbEnd - 1; |
||
123 | } |
||
124 | else |
||
125 | (fifo_manager->wLevel)++; |
||
126 | |||
127 | KeReleaseSpinLock(&fifo_manager->Lock, oldIrql); |
||
128 | |||
129 | return fifo_manager->wLevel; |
||
130 | } |
||
131 | |||
132 | // third: pull elements from the FIFO |
||
133 | int PullElement(PVOID Handle, UCHAR *pbElement) |
||
134 | { |
||
135 | register FIFO_MANAGER *fifo_manager = (FIFO_MANAGER *)Handle; |
||
136 | KIRQL oldIrql; |
||
137 | |||
138 | if (!(fifo_manager->wLevel)) return 0; |
||
139 | |||
140 | KeAcquireSpinLock(&fifo_manager->Lock, &oldIrql); |
||
141 | |||
142 | if (fifo_manager->wLevel) |
||
143 | { |
||
144 | *pbElement = *(fifo_manager->pbRead)++; |
||
145 | (fifo_manager->wLevel)--; |
||
146 | } |
||
147 | else |
||
148 | *pbElement = 0; // the caller tries to get more than available? |
||
149 | |||
150 | // wrap around |
||
151 | if (fifo_manager->pbRead >= fifo_manager->pbEnd) |
||
152 | fifo_manager->pbRead = fifo_manager->pbBegin; |
||
153 | |||
154 | KeReleaseSpinLock(&fifo_manager->Lock, oldIrql); |
||
155 | |||
156 | return fifo_manager->wLevel; |
||
157 | } |
||
158 | |||
159 | // test how many elements are in the FIFO |
||
160 | int NumberOfElements(PVOID Handle) |
||
161 | { |
||
162 | register FIFO_MANAGER *fifo_manager = (FIFO_MANAGER *)Handle; |
||
163 | |||
164 | return fifo_manager->wLevel; |
||
165 | } |
||
166 | |||
167 | // check and clear the overflow flag |
||
168 | BOOLEAN CheckAndClearOverflow(PVOID Handle) |
||
169 | { |
||
170 | register FIFO_MANAGER *fifo_manager = (FIFO_MANAGER *)Handle; |
||
171 | KIRQL oldIrql; |
||
172 | BOOLEAN helper; |
||
173 | |||
174 | KeAcquireSpinLock(&fifo_manager->Lock, &oldIrql); |
||
175 | helper = fifo_manager->bOverflow; |
||
176 | fifo_manager->bOverflow = FALSE; |
||
177 | KeReleaseSpinLock(&fifo_manager->Lock, oldIrql); |
||
178 | |||
179 | return helper; |
||
180 | } |
||
181 | |||
182 | // close the FIFO and free the allocated memory |
||
183 | void DestroyFIFO(PVOID Handle) |
||
184 | { |
||
185 | if (Handle != NULL) ExFreePool(Handle); |
||
186 | } |
||
187 | |||
188 |