Subversion Repositories f9daq

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  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.  
  189.