Subversion Repositories f9daq

Rev

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

  1. /*
  2.    cc32lib_NT.c -- a simple access library for the PCICC32 PCI to CAMAC Interface
  3.                    from ARW Elektronik - the WINNT parts
  4.  
  5.    (c) 2000 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.    derived from the previous WIN95 library                              AR   30.07.2000
  16.    added buffer, UNTIL_NOT_Q and AUTOREAD functionality                 AR   17.03.2001
  17. */
  18.  
  19. /*--- INCLUDES -----------------------------------------------------------------------------------*/
  20. #include <windows.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <errno.h>
  25. #include <winioctl.h>
  26.  
  27. #include "pcicc32.h"  /* PCI common ioctl commands and structures between driver and library  */
  28. #include "libcc32_NT.h"          /* shared header bewteen applictaion and library                        */
  29.  
  30. /*--- DEFINES ------------------------------------------------------------------------------------*/
  31. #define DEFDEVICENAME "\\\\.\\PCICC32:\\CC32_xx"
  32.  
  33. /*--- EXTERNALS ----------------------------------------------------------------------------------*/
  34.  
  35. /*--- TYPEDEFS -----------------------------------------------------------------------------------*/
  36. typedef struct
  37. {
  38.         HANDLE nHandle;                     /* the handle of this device */
  39.         int    nModuleNumber;               /* the number of the module */
  40.         unsigned short wLastAccessWidth;    /* the last parametrized data access width */
  41.         unsigned short wLastAttributes;     /* the last Attributes to this channel */
  42.         unsigned long  dwLastAccessAddress; /* the last access address to speed up */
  43. } CC32_DEVICE_NT;
  44.  
  45. /*--- FUNCTIONS -----------------------------------------------------------------------*/
  46.  
  47. //--------------------------------------------------------------------------------------
  48. // get the PCIADA status from the PCI side of the interface
  49. //
  50. static int getStatus(HANDLE nHandle, DWORD dwInterface, char *nTimeout, char *nLAM)
  51. {
  52.         PCICC32_STATUS status;
  53.         DWORD DIOC_count;             // count of returned bytes of DeviceIoControl
  54.         DWORD result;
  55.  
  56.         if (nHandle == (HANDLE)-1) return -1;
  57.  
  58.         *nTimeout = *nLAM = 0;
  59.  
  60.         // attach a window into the CC32 space ----------------
  61.         result = DeviceIoControl(nHandle, PCICC32_GET_STATUS,
  62.                                                 &dwInterface, sizeof(dwInterface),
  63.                                                 &status,      sizeof(status), &DIOC_count, NULL);
  64.  
  65.     if (!result)
  66.                 return GetLastError();
  67.         else
  68.         {
  69.                 *nTimeout = (char)status.bTimeout;
  70.                 *nLAM     = (char)status.bInterrupt;
  71.  
  72.                 return 0;
  73.         }
  74. }
  75.  
  76. //--------------------------------------------------------------------------------------
  77. // clear the PCIADA status
  78. //
  79. static int clearStatus(HANDLE nHandle, DWORD dwInterface)
  80. {
  81.         DWORD DIOC_count;             // count of returned bytes of DeviceIoControl
  82.         DWORD result;
  83.  
  84.         if (nHandle == (HANDLE)-1) return -1;
  85.  
  86.         // attach a window into the CC32 space ----------------
  87.         result = DeviceIoControl(nHandle, PCICC32_CLEAR_STATUS,
  88.                                                 &dwInterface, sizeof(dwInterface),
  89.                                                 NULL,      0, &DIOC_count, NULL);
  90.  
  91.     if (!result)
  92.                 return GetLastError();
  93.         else
  94.                 return 0;
  95. }
  96.  
  97. //-------------------------------------------------------------------------
  98. // set the future access parameters - override the current
  99. //
  100. static int setAccessParameter(HANDLE hHandle, USHORT wAccessType, USHORT wBlockTransfer)
  101. {
  102.         DWORD result;
  103.         DWORD   DIOC_count;     // count of returned bytes of DeviceIoControl
  104.     PCICC32_ACCESS_COMMAND access_parameter;
  105.  
  106.         access_parameter.wAccessType            = wAccessType;
  107.         access_parameter.wBlockTransfer         = wBlockTransfer;
  108.  
  109.         result = DeviceIoControl(hHandle, PCICC32_SET_ACCESS_PARA,
  110.                                         &access_parameter, (DWORD)sizeof(access_parameter), NULL,
  111.                                                    0, &DIOC_count, NULL);      
  112.         if (!result)
  113.                 return GetLastError();
  114.         else
  115.                 return 0;
  116. }
  117.  
  118. //-------------------------------------------------------------------------
  119. // create a DeviceName out of cszDeviceName and nIfcNum
  120. //
  121. static char *DeviceName(int nIfcNum)
  122. {
  123.         static char buffer[255];
  124.         char *ptr = buffer;
  125.  
  126.         strncpy(buffer, DEFDEVICENAME, strlen(DEFDEVICENAME));
  127.  
  128.         while (*ptr) ptr++;
  129.        
  130.         do
  131.         {
  132.                 ptr--;
  133.         } while (*ptr != '_');  // step back until '-'
  134.  
  135.         ptr++;
  136.        
  137.         if (nIfcNum >= 10)      // add the interface number
  138.         {
  139.                 *ptr++   = '1';
  140.                 nIfcNum -= 10;
  141.         }
  142.  
  143.         *ptr++ = '0' + nIfcNum;
  144.         *ptr = 0;
  145.  
  146.         // a little help for the users
  147.     return buffer;
  148. }
  149.  
  150. //-------------------------------------------------------------------------
  151. // open my path to the interface
  152. //
  153. static HANDLE openPath(char *name)
  154. {
  155.     return (HANDLE)CreateFile(
  156.                      name,
  157.                      GENERIC_READ | GENERIC_WRITE,
  158.                      0,
  159.                      NULL,
  160.                      OPEN_EXISTING,
  161.                      FILE_ATTRIBUTE_NORMAL,
  162.                      NULL
  163.                      );
  164. }
  165.  
  166. //--------------------------------------------------------------------------------------
  167. // open the device
  168. //
  169. int cc32_open_NT(char *cszPath, int nModuleNumber, void **handle)
  170. {
  171.         CC32_DEVICE_NT *dev;
  172.         int error = 0;
  173.        
  174.         *handle = (void *)0;
  175.        
  176.         dev = (CC32_DEVICE_NT *)malloc(sizeof(CC32_DEVICE_NT));
  177.         if (!dev) return errno;
  178.        
  179.         dev->nModuleNumber = nModuleNumber;
  180.         dev->nHandle = INVALID_HANDLE_VALUE;
  181.         dev->wLastAccessWidth    = 0xffff;         /* invalidate for future use */
  182.  
  183.         // start the driver ------------------
  184.         dev->nHandle = openPath(DeviceName(nModuleNumber));
  185.        
  186.         if (dev->nHandle == INVALID_HANDLE_VALUE)
  187.                 error = GetLastError();
  188.         else
  189.         {
  190.                 SetFilePointer(dev->nHandle, 0, NULL, FILE_BEGIN);
  191.                 dev->dwLastAccessAddress = 0;
  192.                 dev->wLastAttributes = 0;
  193.                 dev->wLastAccessWidth = 0;
  194.         }
  195.  
  196.         if (error)
  197.         {
  198.                 free(dev);
  199.                 return error;
  200.         }
  201.  
  202.         *handle = (void *)dev;
  203.        
  204.         return NO_ERROR;
  205. }
  206.  
  207. //--------------------------------------------------------------------------------------
  208. // close the device
  209. //
  210. int cc32_close_NT(void *handle)
  211. {
  212.         CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
  213.         int error = NO_ERROR;
  214.        
  215.         if (dev)
  216.         {
  217.                 if (dev->nHandle != INVALID_HANDLE_VALUE)
  218.                         CloseHandle(dev->nHandle);
  219.        
  220.                 free(dev);
  221.         }
  222.         else
  223.                 error = ERROR_INVALID_FUNCTION;
  224.                
  225.         return error;
  226. }
  227.  
  228. //--------------------------------------------------------------------------------------
  229. // read a word
  230. //
  231. unsigned short cc32_read_word_NT(void *handle, unsigned int N, unsigned int A, unsigned int F)
  232. {
  233.         register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
  234.         unsigned long  adr = NAF(N,A,F);
  235.         unsigned short buffer;
  236.         unsigned long  bytesRead;
  237.  
  238.         // cache the data access width
  239.         if (dev->wLastAccessWidth != WORD_ACCESS)
  240.         {
  241.                 dev->wLastAccessWidth = WORD_ACCESS;
  242.                 setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);
  243.         }
  244.  
  245.         // cache the address
  246.         if (dev->dwLastAccessAddress != adr)
  247.         {
  248.           SetFilePointer(dev->nHandle, adr, NULL, FILE_BEGIN);
  249.           dev->dwLastAccessAddress = adr;
  250.         }
  251.  
  252.         ReadFile(dev->nHandle, &buffer, WORD_ACCESS, &bytesRead, NULL);
  253.  
  254.         return buffer;
  255. }
  256.  
  257. //--------------------------------------------------------------------------------------
  258. // read a long
  259. //
  260. unsigned long cc32_read_long_all_NT(void *handle, unsigned int N, unsigned int A, unsigned int F)
  261. {
  262.         register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
  263.         unsigned long  adr = NAF(N,A,F);
  264.         unsigned long  buffer;
  265.         unsigned long  bytesRead;
  266.  
  267.         // cache the data access width
  268.         if (dev->wLastAccessWidth != LONG_ACCESS)
  269.         {
  270.                 dev->wLastAccessWidth = LONG_ACCESS;
  271.                 setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);
  272.         }
  273.  
  274.         // cache the address
  275.         if (dev->dwLastAccessAddress != adr)
  276.         {
  277.           SetFilePointer(dev->nHandle, adr, NULL, FILE_BEGIN);
  278.           dev->dwLastAccessAddress = adr;
  279.         }
  280.  
  281.         ReadFile(dev->nHandle, &buffer, LONG_ACCESS, &bytesRead, NULL);
  282.  
  283.         return buffer;
  284. }
  285.  
  286. //--------------------------------------------------------------------------------------
  287. // read a long and get Q and X
  288. //
  289. unsigned long cc32_read_long_NT(void *handle, unsigned int N, unsigned int A, unsigned int F, char *Q, char *X)
  290. {
  291.         unsigned long erg = cc32_read_long_all_NT(handle, N, A, F);
  292.        
  293.         *Q = (erg & 0x80000000) ? 1 : 0;
  294.         *X = (erg & 0x40000000) ? 1 : 0;
  295.  
  296.         return erg & 0x00FFFFFF;
  297. }
  298.  
  299. //--------------------------------------------------------------------------------------
  300. // write a word
  301. //
  302. void cc32_write_word_NT(void *handle, unsigned int N, unsigned int A, unsigned int F, unsigned short uwData)
  303. {
  304.         register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
  305.         unsigned long adr = NAF(N,A,F);
  306.         DWORD bytesWritten;
  307.        
  308.         // cache the data access width
  309.         if (dev->wLastAccessWidth != WORD_ACCESS)
  310.         {
  311.                 dev->wLastAccessWidth = WORD_ACCESS;
  312.                 setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);
  313.         }
  314.  
  315.         // cache the address
  316.         if (dev->dwLastAccessAddress != adr)
  317.         {
  318.           SetFilePointer(dev->nHandle, adr, NULL, FILE_BEGIN);
  319.           dev->dwLastAccessAddress = adr;
  320.         }
  321.  
  322.         WriteFile(dev->nHandle, &uwData, WORD_ACCESS, &bytesWritten, NULL);
  323. }
  324.  
  325. //--------------------------------------------------------------------------------------
  326. // write a long
  327. //
  328. void cc32_write_long_NT(void *handle, unsigned int N, unsigned int A, unsigned int F, unsigned long ulData)
  329. {
  330.         register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
  331.         unsigned long adr = NAF(N,A,F);
  332.         DWORD bytesWritten;
  333.        
  334.         // cache the data access width
  335.         if (dev->wLastAccessWidth != LONG_ACCESS)
  336.         {
  337.                 dev->wLastAccessWidth = LONG_ACCESS;
  338.                 setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);
  339.         }
  340.  
  341.         // cache the address
  342.         if (dev->dwLastAccessAddress != adr)
  343.         {
  344.           SetFilePointer(dev->nHandle, adr, NULL, FILE_BEGIN);
  345.           dev->dwLastAccessAddress = adr;
  346.         }
  347.  
  348.         WriteFile(dev->nHandle, &ulData, LONG_ACCESS, &bytesWritten, NULL);
  349. }
  350.  
  351. //--------------------------------------------------------------------------------------
  352. // clear the PCIADA status
  353. //
  354. int cc32_poll_error_NT(void *handle, char *nTimeout, char *nLam)
  355. {
  356.         CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
  357.         int error;
  358.        
  359.     if ((error = getStatus(dev->nHandle, dev->nModuleNumber, nTimeout, nLam)))
  360.                 return error;
  361.                
  362.         if (*nTimeout)  /* clear error */
  363.         {
  364.                 if ((error = clearStatus(dev->nHandle, dev->nModuleNumber)))
  365.                         return error;  
  366.         }
  367.        
  368.         return NO_ERROR;
  369. }
  370.  
  371. //--------------------------------------------------------------------------------------
  372. // read 'len' words or 'UNTIL_NOT_Q' from a address made out of N,A,F
  373. //
  374. int cc32_read_word_buffer_NT(void * handle, unsigned int N, unsigned int A, unsigned int F,
  375.                                                                                                                                 unsigned short *pwBuffer, unsigned long *pdwLen)
  376. {
  377.         register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
  378.         unsigned long  adr = NAF(N,A,F);
  379.         unsigned long dwLen;
  380.  
  381.         // cache the data access width
  382.         if (dev->wLastAccessWidth != WORD_ACCESS)
  383.         {
  384.                 dev->wLastAccessWidth = WORD_ACCESS;
  385.                 setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);
  386.         }
  387.  
  388.         // cache the address
  389.         if (dev->dwLastAccessAddress != adr)
  390.         {
  391.           SetFilePointer(dev->nHandle, adr, NULL, FILE_BEGIN);
  392.           dev->dwLastAccessAddress = adr;
  393.         }
  394.  
  395.         *pdwLen <<= 1;  // make bytes
  396.         dwLen = *pdwLen;
  397.         if (!ReadFile(dev->nHandle, pwBuffer, dwLen, pdwLen, NULL))
  398.                 return GetLastError();
  399.  
  400.         *pdwLen >>= 1;  // make words
  401.         return 0;
  402. }
  403.  
  404. //--------------------------------------------------------------------------------------
  405. // read 'len' longs or 'UNTIL_NOT_Q' from a address made out of N,A,F, mask 24 bits out
  406. //
  407. int cc32_read_long_buffer_NT(void * handle, unsigned int N, unsigned int A, unsigned int F,
  408.                                                                                                                                 unsigned long *pdwBuffer, unsigned long *pdwLen)
  409. {
  410.         register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
  411.         unsigned long  adr = NAF(N,A,F);
  412.         unsigned long *pdwPtr = pdwBuffer;
  413.         unsigned long *pdwEnd = pdwBuffer;
  414.         unsigned long dwLen;
  415.  
  416.         // cache the data access width
  417.         if (dev->wLastAccessWidth != LONG_ACCESS)
  418.         {
  419.                 dev->wLastAccessWidth = LONG_ACCESS;
  420.                 setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);
  421.         }
  422.  
  423.         // cache the address
  424.         if (dev->dwLastAccessAddress != adr)
  425.         {
  426.           SetFilePointer(dev->nHandle, adr, NULL, FILE_BEGIN);
  427.           dev->dwLastAccessAddress = adr;
  428.         }
  429.  
  430.         *pdwLen <<= 2;   // make bytes
  431.         dwLen = *pdwLen;
  432.         if (!ReadFile(dev->nHandle, pdwBuffer, dwLen, pdwLen, NULL))
  433.                 return GetLastError();
  434.  
  435.         pdwEnd += *pdwLen;
  436.         while (pdwEnd < pdwPtr)
  437.                 *pdwPtr++ &= 0x00FFFFFF;  // mask Q and X bits
  438.  
  439.         *pdwLen >>= 2;   // make longs
  440.         return 0;
  441. }
  442.  
  443. //--------------------------------------------------------------------------------------
  444. // read 'len' longs or 'UNTIL_NOT_Q' from a address made out of N,A,F, without interpretation
  445. //
  446. int cc32_read_long_all_buffer_NT(void * handle, unsigned int N, unsigned int A, unsigned int F,
  447.                                                                                                                                 unsigned long *pdwBuffer, unsigned long *pdwLen)
  448. {
  449.         register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
  450.         unsigned long  adr = NAF(N,A,F);
  451.         unsigned long dwLen;
  452.  
  453.         // cache the data access width
  454.         if (dev->wLastAccessWidth != LONG_ACCESS)
  455.         {
  456.                 dev->wLastAccessWidth = LONG_ACCESS;
  457.                 setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);
  458.         }
  459.  
  460.         // cache the address
  461.         if (dev->dwLastAccessAddress != adr)
  462.         {
  463.           SetFilePointer(dev->nHandle, adr, NULL, FILE_BEGIN);
  464.           dev->dwLastAccessAddress = adr;
  465.         }
  466.  
  467.         *pdwLen <<= 2;   // make bytes
  468.         dwLen = *pdwLen;
  469.         if (!ReadFile(dev->nHandle, pdwBuffer, dwLen, pdwLen, NULL))
  470.                 return GetLastError();
  471.  
  472.         *pdwLen >>= 2;   // make longs
  473.         return 0;
  474. }
  475.  
  476. //--------------------------------------------------------------------------------------
  477. // switch UNTIL_NOT_Q or AUTOREAD on or off
  478. //
  479. int cc32_access_switch_NT(void *handle, unsigned short uwSwitch)
  480. {
  481.         register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
  482.  
  483.         dev->wLastAttributes  = uwSwitch;
  484.         return setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);
  485. }
  486.  
  487. //--------------------------------------------------------------------------------------
  488. // switch interrupts on
  489. //
  490. int cc32_enable_interrupt_NT(void *handle)
  491. {
  492.         register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
  493.         DWORD result;
  494.         DWORD   DIOC_count;     // count of returned bytes of DeviceIoControl
  495.         PCICC32_IRQ_CONTROL irqCntrl;
  496.  
  497.         irqCntrl.dwInterface = 0;  // don't bother at WINNT
  498.         irqCntrl.wEnable     = 1;  // enable it
  499.  
  500.         result = DeviceIoControl(dev->nHandle, PCICC32_CONTROL_INTERRUPTS,
  501.                                         &irqCntrl, sizeof(irqCntrl), NULL, 0, &DIOC_count, NULL);        
  502.  
  503.         if (!result)
  504.                 return GetLastError();
  505.         else
  506.                 return NO_ERROR;
  507. }
  508.  
  509. //--------------------------------------------------------------------------------------
  510. // switch interrupts off
  511. //
  512. int cc32_disable_interrupt_NT(void *handle)
  513. {
  514.         register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
  515.         DWORD result;
  516.         DWORD   DIOC_count;     // count of returned bytes of DeviceIoControl
  517.         PCICC32_IRQ_CONTROL irqCntrl;
  518.  
  519.         irqCntrl.dwInterface = 0;  // don't bother at WINNT
  520.         irqCntrl.wEnable     = 0;  // disable it
  521.  
  522.         result = DeviceIoControl(dev->nHandle, PCICC32_CONTROL_INTERRUPTS,
  523.                                         &irqCntrl, sizeof(irqCntrl), NULL, 0, &DIOC_count, NULL);        
  524.  
  525.         if (!result)
  526.                 return GetLastError();
  527.         else
  528.                 return NO_ERROR;
  529. }
  530.  
  531. //--------------------------------------------------------------------------------------
  532. // wait blocking for the next interrupt
  533. //
  534. int cc32_get_interrupt_NT(void *handle, unsigned long *dwStatus)
  535. {
  536.         register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
  537.         DWORD result;
  538.         DWORD   DIOC_count;     // count of returned bytes of DeviceIoControl
  539.         PCICC32_IRQ_RESPONSE response;
  540.         int nError;
  541.         OVERLAPPED sOverlapped;
  542.  
  543.         sOverlapped.hEvent    = NULL;
  544.         result = DeviceIoControl(dev->nHandle, PCICC32_INSTALL_IRQ_BLOCK,
  545.                                         NULL, 0, &response, sizeof(response), &DIOC_count, NULL);
  546.        
  547.         *dwStatus = response.dwInterruptFlags;
  548.  
  549.         if (!result)
  550.         {
  551.                 nError = GetLastError();
  552.  
  553.                 // a real error
  554.                 if ((nError != ERROR_IO_PENDING) && (nError != ERROR_SUCCESS))
  555.                         return nError;
  556.  
  557.                 // my IO is pending - wait for it
  558.                 if (nError == ERROR_IO_PENDING)
  559.                 {
  560.                         result = GetOverlappedResult(dev->nHandle, &sOverlapped, &DIOC_count, TRUE);
  561.                        
  562.                         *dwStatus = response.dwInterruptFlags;
  563.  
  564.                         if (!result)
  565.                         {
  566.                                 nError = GetLastError();   // if it was cancelled
  567.                                 if (nError == ERROR_OPERATION_ABORTED)
  568.                                         return NO_ERROR;       // accept it as 'normal'
  569.                                 else
  570.                                         return nError;
  571.                         }
  572.                 }
  573.         }
  574.  
  575.         return NO_ERROR;
  576. }
  577.  
  578.  
  579.