Subversion Repositories f9daq

Rev

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

  1. //-------------------------------------------------------------------------------------------
  2. // pcivme_ni.c - shared library for ARW pcivme interface (libpcivme.so)
  3. //
  4. // Copyright (C) 2002-2004 ARW Elektronik Germany
  5. //
  6. // this source code is published under LGPL (Open Source). You can use, redistrubute and
  7. // modify it unless this header  is  not modified or deleted. No warranty is given that
  8. // this software will work like expected.
  9. // This product is not authorized for use as critical component in life support systems
  10. // wihout the express written approval of ARW Elektronik Germany.
  11. //
  12. // Please announce changes and hints to ARW Elektronik
  13. //
  14. // $Log: pcivme_ni.c,v $
  15. // Revision 1.8  2004/08/13 19:23:45  klaus
  16. // conversion to kernel-version 2.6, released version 3.0
  17. //
  18. // Revision 1.7  2002/10/20 18:07:18  klaus
  19. // changed error handling
  20. //
  21. // Revision 1.6  2002/10/18 21:56:28  klaus
  22. // completed functional features, untested
  23. //
  24. // Revision 1.5  2002/10/18 21:56:28  klaus
  25. // completed functional features, untested
  26. //
  27. // Revision 1.4  2002/10/17 21:16:03  klaus
  28. // filled function bodies
  29. //
  30. // Revision 1.3  2002/10/17 21:16:03  klaus
  31. // filled function bodies
  32. //
  33. // Revision 1.2  2002/10/17 19:05:03  klaus
  34. // VME access is working through test to lib to driver
  35. //
  36. // Revision 1.1  2002/10/12 22:04:30  klaus
  37. // first work done
  38. //
  39.  
  40. //-------------------------------------------------------------------------------------------
  41. // INCLUDES
  42. //
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46. #include <unistd.h>
  47. #include <linux/types.h>
  48. #include <sys/ioctl.h>
  49. #include <errno.h>
  50. #include <ctype.h>
  51. #include <sys/types.h>
  52. #include <sys/stat.h>
  53. #include <fcntl.h>
  54.  
  55. #include <../driver/pcivme.h>
  56. #include <../driver/vic.h>
  57. #include <pcivme_ni.h>
  58.  
  59. //-------------------------------------------------------------------------------------------
  60. // DEFINES
  61. //
  62. #define LOCAL_STRING_LEN 40
  63.  
  64. //-------------------------------------------------------------------------------------------
  65. // TYPEDEFS
  66. //
  67.  
  68. // storage for path specific data
  69. typedef struct
  70. {
  71.     int nFileNo;              // file number to f
  72.     __u8 cAddressModifier;    // associated VME address modifier
  73.     __u8 cAccessWidth;        // current access width
  74.     int  nLastError;          // != 0 if a previous error occurred
  75. } VMEMM_DEVICE;
  76.  
  77. //-------------------------------------------------------------------------------------------
  78. // FUNCTIONS
  79. //
  80.  
  81. // construct a device file name
  82. static char *szDeviceName(const char *cszBaseName, int nVMEMM)
  83. {
  84.   static char path[LOCAL_STRING_LEN];
  85.   int i = LOCAL_STRING_LEN - 1;
  86.  
  87.   path[0] = 0;
  88.  
  89.   memset(path, 0, LOCAL_STRING_LEN);
  90.  
  91.   if (strlen(cszBaseName) >= (LOCAL_STRING_LEN - 3))
  92.       return "";
  93.  
  94.   if (nVMEMM > 15)
  95.       return "";
  96.  
  97.   strncpy(path, cszBaseName, LOCAL_STRING_LEN - 3);
  98.  
  99.   while ((i--) && (path[i] != '_'));  // search for '_'
  100.  
  101.   if (i)
  102.   {
  103.       i++; // go after '_'
  104.       if (nVMEMM >= 10)
  105.       {
  106.           path[i] = '1';
  107.           nVMEMM -= 10;
  108.           i++;
  109.       }
  110.       path[i] = '0' + nVMEMM;
  111.       i++;
  112.       path[i] = 0; // trailing 0
  113.   }
  114.   else
  115.       return "";
  116.  
  117.   return path;
  118. }
  119.  
  120. static int initHardware(VMEMM_DEVICE *dev)
  121. {
  122.     PCIVME_INIT_COMMAND init;
  123.  
  124.     init.sVie[0].bDestination = STOP;
  125.     init.sVie[0].bAccessType  =
  126.     init.sVie[0].dwValue      =
  127.     init.sVie[0].wOffset      = 0;
  128.  
  129.     if (ioctl(dev->nFileNo, PCIVME_INIT_HARDWARE, &init) < 0)
  130.     {
  131.         dev->nLastError = errno;
  132.         printf("initHardware:err=%d %s\n" , errno,  strerror(errno) );
  133.         return errno;
  134.     }
  135.  
  136.     return 0;
  137. }
  138.  
  139. static int deInitHardware(VMEMM_DEVICE *dev)
  140. {
  141.     PCIVME_INIT_COMMAND deinit;
  142.  
  143.     deinit.sVie[0].bDestination = STOP;
  144.     deinit.sVie[0].bAccessType  =
  145.     deinit.sVie[0].dwValue      =
  146.     deinit.sVie[0].wOffset      = 0;
  147.  
  148.     if (ioctl(dev->nFileNo, PCIVME_DEINIT_HARDWARE, &deinit) < 0)
  149.     {
  150.         dev->nLastError = errno;
  151.         printf("deInitHardware:err=%d %s\n" , errno,  strerror(errno) );
  152.         return errno;
  153.     }
  154.  
  155.     return 0;
  156. }
  157.  
  158. int VMEopen(const char *cszDeviceName, unsigned char ubAddressModifier, int *pnHandle)
  159. {
  160.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)NULL;
  161.     int error;
  162.  
  163.     *pnHandle = 0;
  164.  
  165.     dev = (VMEMM_DEVICE *)malloc(sizeof(*dev));
  166.     if (!dev)
  167.         return errno;
  168.  
  169.     dev->nFileNo = open(cszDeviceName, O_RDWR);
  170.     printf("VMEopen: dev->nFileNo %d size=%d %s\n" , dev->nFileNo,sizeof(*dev),  cszDeviceName );
  171.     if (dev->nFileNo == -1)
  172.     {
  173.         error = errno;
  174.         printf("VMEopen:err=%d %s\n" , error,  strerror(error) );
  175.         free(dev);
  176.         return error;
  177.     }
  178.  
  179.     dev->cAddressModifier = ubAddressModifier;
  180.     *pnHandle             = (int)dev;
  181.  
  182.     error = initHardware(dev);
  183.     if (error)
  184.         return error;
  185.  
  186.     dev->nLastError = 0;
  187.  
  188.     return setAccessProperties(*pnHandle, dev->cAddressModifier, BYTE_ACCESS); // set access properties to default
  189. }
  190.  
  191. int VMEinit(const char *cszDeviceName, unsigned short nVMEMM, unsigned char ubAddressModifier, int *pnHandle)
  192. {
  193.     char *szLocalDeviceName = szDeviceName(cszDeviceName, nVMEMM);
  194.  
  195.     return VMEopen(szLocalDeviceName, ubAddressModifier, pnHandle);
  196. }
  197.  
  198. int setAccessProperties(int nHandle, unsigned char bModifier, unsigned char bAccessType)
  199. {
  200.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
  201.  
  202.     PCIVME_ACCESS_COMMAND access_command;
  203.                
  204.     access_command.bAccessType =
  205.     access_command.bIncrement  = bAccessType;  // increment and accessType are the same
  206.     access_command.bModifier   = bModifier;
  207.  
  208.     if (ioctl(dev->nFileNo, PCIVME_SET_ACCESS_PARA, &access_command) < 0)
  209.     {
  210.         dev->nLastError = errno;
  211.         printf("setAccessProperties:err=%d %s\n" , errno,  strerror(errno) );
  212.         return errno;
  213.     }
  214.  
  215.     dev->cAddressModifier = bModifier;
  216.     dev->cAccessWidth     = bAccessType;
  217.  
  218.     return 0;
  219. }
  220.  
  221. int VMEread(int nHandle, unsigned long ulAddress, unsigned char ubAccessWidth, unsigned long ulElementCount, void *pvBuffer)
  222. {
  223.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
  224.     size_t count      = (size_t)(ulElementCount * ubAccessWidth);
  225.     ssize_t result;
  226.     int error;
  227.     long pos;
  228.  
  229. //    printf("VMEread:  AW 0x%0x 0x%0x  , AM 0x%0x \n", dev->cAccessWidth, ubAccessWidth, dev->cAddressModifier);
  230.     if (dev->cAccessWidth != ubAccessWidth)
  231.     {
  232.         if ((error = setAccessProperties(nHandle, dev->cAddressModifier, ubAccessWidth)))
  233.             return error;
  234.     }
  235.     pos = lseek(dev->nFileNo, ulAddress, SEEK_SET);
  236.    
  237.     if ( pos < 0){
  238.         printf("VMEread: pos=0x%08lx dev->nFileNo=%d ADDR=0x%08lx %s\n",pos, dev->nFileNo, ulAddress, strerror(errno));
  239.         switch (errno){
  240.           case EBADF:printf("errno =EBADF\n");break;
  241.           case EINVAL:printf("errno =EINVAL\n");break;
  242.           case EOVERFLOW:printf("errno =EOVERFLOW\n");break;
  243.           case ESPIPE:printf("errno =ESPIPE\n");break;
  244.           case ENXIO:printf("errno =ENXIO\n");break;
  245.         }
  246.         //return errno;
  247.     }
  248.  
  249.    
  250.     result = read(dev->nFileNo, pvBuffer, count);
  251. //    printf("VMEread: read %d dev->nFileNo=%d err=%d %s\n",count, dev->nFileNo, errno, strerror(errno));
  252.     if (result != count)
  253.     {
  254.         if (result < 0)
  255.         {
  256.             dev->nLastError = errno;
  257.             return errno;
  258.         }
  259.         else
  260.             return EFAULT;
  261.     }
  262.  
  263.     return 0;
  264. }
  265.  
  266. int VMEwrite(int nHandle, unsigned long ulAddress, unsigned char ubAccessWidth, unsigned long ulElementCount, void *pvBuffer)
  267. {
  268.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
  269.     size_t count      = (size_t)(ulElementCount * ubAccessWidth);
  270.     ssize_t result;
  271.     int error;
  272.     long pos;
  273.  
  274. //    printf("VMEwrite:  AW 0x%0x 0x%0x  , AM 0x%0x \n", dev->cAccessWidth, ubAccessWidth, dev->cAddressModifier);
  275.     if (dev->cAccessWidth != ubAccessWidth)
  276.     {
  277.         if ((error = setAccessProperties(nHandle, dev->cAddressModifier, ubAccessWidth)))
  278.             return error;
  279.     }
  280.  
  281.     pos = lseek(dev->nFileNo, ulAddress, SEEK_SET);
  282.     if (pos < 0){
  283.         printf("VMEwrite: pos=0x%08lx  dev->nFileNo=%d ADDR=0x%08lx %s\n",pos, dev->nFileNo, ulAddress, strerror(errno));
  284.         switch (errno){
  285.           case EBADF:printf("errno =EBADF\n");break;
  286.           case EINVAL:printf("errno =EINVAL\n");break;
  287.           case EOVERFLOW:printf("errno =EOVERFLOW\n");break;
  288.           case ESPIPE:printf("errno =ESPIPE\n");break;
  289.           case ENXIO:printf("errno =ENXIO\n");break;
  290.         }
  291.         //return errno;
  292.     }
  293.     result = write(dev->nFileNo, pvBuffer, count);
  294. //    printf("VMEwrite: write %d dev->nFileNo=%d err=%d %s\n",count, dev->nFileNo,errno, strerror(errno));
  295.     if (result != count)
  296.     {
  297.         if (result < 0)
  298.         {
  299.             dev->nLastError = errno;
  300.            
  301.             return errno;
  302.         }
  303.         else
  304.             return EFAULT;
  305.     }
  306.  
  307.     return 0;
  308. }
  309.  
  310. int VMEaccessVIC(int nHandle, unsigned char ubAccessMode, unsigned short uwAddress, unsigned char *ubContent)
  311. {
  312.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
  313.     PCIVME_VIC68A_ACTION vic68a_action;
  314.  
  315.     vic68a_action.bAccessMode      = ubAccessMode;
  316.     vic68a_action.bContent         = *ubContent;  
  317.     vic68a_action.wRegisterAddress = uwAddress;
  318.  
  319.     if (ioctl(dev->nFileNo, PCIVME_ACCESS_VIC68A, &vic68a_action) < 0)
  320.     {
  321.         dev->nLastError = errno;
  322.         return errno;
  323.     }
  324.  
  325.     *ubContent = vic68a_action.bContent;
  326.  
  327.     return 0;
  328. }
  329.  
  330. int VMEreset(int nHandle)
  331. {
  332.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
  333.     PCIVME_RESET_COMMAND reset_command;
  334.     int i = 10;
  335.  
  336.     reset_command.bCommand = GLOBAL_RESET_CMD;
  337.     reset_command.bResult  = 0xff;  
  338.  
  339.     if (ioctl(dev->nFileNo, PCIVME_RESET, &reset_command) < 0)
  340.     {
  341.         dev->nLastError = errno;
  342.         return errno;
  343.     }
  344.  
  345.     do
  346.     {
  347.         usleep(100);
  348.         reset_command.bCommand = POLL_RESET_CMD;
  349.         reset_command.bResult  = 0xff;  
  350.    
  351.         if (ioctl(dev->nFileNo, PCIVME_RESET, &reset_command) < 0)
  352.         {
  353.             dev->nLastError = errno;
  354.             return errno;
  355.         }
  356.     } while ((reset_command.bResult) && (i--));
  357.  
  358.     if (!i)
  359.         return ETIME;
  360.  
  361.     dev->nLastError = 0;
  362.  
  363.     return 0;
  364. }
  365.  
  366. int VMETAS(int nHandle, unsigned long ulAddress, unsigned char *ubResult)
  367. {
  368.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
  369.     PCIVME_TAS_STRUCT tas;
  370.  
  371.     tas.bContent  = *ubResult;
  372.     tas.bModifier = dev->cAddressModifier;  
  373.     tas.dwAddress = ulAddress;
  374.  
  375.     if (ioctl(dev->nFileNo, PCIVME_TAS, &tas) < 0)
  376.     {
  377.         dev->nLastError = errno;
  378.         return errno;
  379.     }
  380.  
  381.     *ubResult = tas.bContent;
  382.  
  383.     return 0;
  384. }
  385.  
  386. int VMEinterrupt(int nHandle, unsigned char *ubVector)
  387. {
  388.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
  389.         PCIVME_VECTOR_LEVEL ubLocalVector;
  390.  
  391.     if (ioctl(dev->nFileNo, PCIVME_READ_VECTOR_POLL, &ubLocalVector) < 0)
  392.     {
  393.         dev->nLastError = errno;
  394.         return errno;
  395.     }
  396.  
  397.     *ubVector = (__u8)ubLocalVector.dwStatusID;
  398.  
  399.     return 0;
  400. }
  401.  
  402. int VMEsysfailGet(int nHandle, BOOLEAN *bResult)
  403. {
  404.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
  405.         PCIVME_VIC68A_ACTION sAction;    // structure to access vic chip
  406.  
  407.         sAction.wRegisterAddress = EGICR;
  408.         sAction.bAccessMode      = VIC68A_READ;
  409.         sAction.bContent         = 0;
  410.  
  411.     if (ioctl(dev->nFileNo, PCIVME_ACCESS_VIC68A, &sAction) < 0)
  412.     {
  413.         dev->nLastError = errno;
  414.         return errno;
  415.     }
  416.  
  417.         *bResult = (sAction.bContent & 0x08) ? FALSE : TRUE;
  418.  
  419.     return 0;
  420. }
  421.  
  422. int VMEsysfailSet(int nHandle, BOOLEAN bForce)
  423. {
  424.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
  425.         PCIVME_VIC68A_ACTION sAction;    // structure to access vic chip
  426.  
  427.         sAction.wRegisterAddress = ICR7;
  428.         sAction.bAccessMode      = (bForce == TRUE) ? VIC68A_AND : VIC68A_OR;
  429.         sAction.bContent         = (bForce == TRUE) ? 0x3F               : 0x80;
  430.  
  431.     if (ioctl(dev->nFileNo, PCIVME_ACCESS_VIC68A, &sAction) < 0)
  432.     {
  433.         dev->nLastError = errno;
  434.         return errno;
  435.     }
  436.  
  437.     return 0;
  438. }
  439.  
  440. int VMEerror(int nHandle)
  441. {
  442.     __u8 ubVector;
  443.  
  444.     VMEinterrupt(nHandle, &ubVector);
  445.  
  446.     if (ubVector == 7)
  447.         return EFAULT;  // it's a bus error
  448.     else
  449.         return 0;
  450. }
  451.  
  452. int VMEclose(int nHandle)
  453. {
  454.     int error = 0;
  455.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
  456.  
  457.     if (dev != (VMEMM_DEVICE *)NULL)
  458.     {
  459.         deInitHardware(dev);
  460.  
  461.         if (dev->nFileNo != -1)
  462.             close(dev->nFileNo);
  463.         else
  464.             error = -EINVAL;
  465.  
  466.         free(dev);
  467.     }
  468.  
  469.     return error;
  470. }
  471.  
  472. int VMEcontrolInterrupt(int nHandle, BOOLEAN *bEnable)
  473. {
  474.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
  475.         PCIVME_IRQ_CONTROL  control;
  476.  
  477.     control.bEnable = *bEnable;
  478.  
  479.     if (ioctl(dev->nFileNo, PCIVME_CONTROL_INTERRUPTS, &control) < 0)
  480.     {
  481.         dev->nLastError = errno;
  482.         return errno;
  483.     }
  484.  
  485.     // status of interrupt enable before set
  486.     *bEnable = control.bEnable;
  487.  
  488.     return 0;
  489. }
  490.  
  491. int GetLastError(int nHandle)
  492. {
  493.     VMEMM_DEVICE *dev  = (VMEMM_DEVICE *)nHandle;
  494.     int nLocalError;
  495.  
  496.     nLocalError = dev->nLastError;
  497.     dev->nLastError = 0;
  498.  
  499.     return nLocalError;
  500. }
  501.  
  502.  
  503.