Subversion Repositories f9daq

Rev

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