Subversion Repositories f9daq

Rev

Rev 11 | 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.         return errno;
  133.     }
  134.  
  135.     return 0;
  136. }
  137.  
  138. static int deInitHardware(VMEMM_DEVICE *dev)
  139. {
  140.     PCIVME_INIT_COMMAND deinit;
  141.  
  142.     deinit.sVie[0].bDestination = STOP;
  143.     deinit.sVie[0].bAccessType  =
  144.     deinit.sVie[0].dwValue      =
  145.     deinit.sVie[0].wOffset      = 0;
  146.  
  147.     if (ioctl(dev->nFileNo, PCIVME_DEINIT_HARDWARE, &deinit) < 0)
  148.     {
  149.         dev->nLastError = errno;
  150.         return errno;
  151.     }
  152.  
  153.     return 0;
  154. }
  155.  
  156. int VMEopen(const char *cszDeviceName, unsigned char ubAddressModifier, int *pnHandle)
  157. {
  158.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)NULL;
  159.     int error;
  160.  
  161.     *pnHandle = 0;
  162.  
  163.     dev = (VMEMM_DEVICE *)malloc(sizeof(*dev));
  164.     if (!dev)
  165.         return errno;
  166.  
  167.     dev->nFileNo = open(cszDeviceName, O_RDWR);
  168.  
  169.     if (dev->nFileNo == -1)
  170.     {
  171.         error = errno;
  172.         free(dev);
  173.         return error;
  174.     }
  175.  
  176.     dev->cAddressModifier = ubAddressModifier;
  177.     *pnHandle             = (int)dev;
  178.  
  179.     error = initHardware(dev);
  180.     if (error)
  181.         return error;
  182.  
  183.     dev->nLastError = 0;
  184.  
  185.     return setAccessProperties(*pnHandle, dev->cAddressModifier, BYTE_ACCESS); // set access properties to default
  186. }
  187.  
  188. int VMEinit(const char *cszDeviceName, unsigned short nVMEMM, unsigned char ubAddressModifier, int *pnHandle)
  189. {
  190.     char *szLocalDeviceName = szDeviceName(cszDeviceName, nVMEMM);
  191.  
  192.     return VMEopen(szLocalDeviceName, ubAddressModifier, pnHandle);
  193. }
  194.  
  195. int setAccessProperties(int nHandle, unsigned char bModifier, unsigned char bAccessType)
  196. {
  197.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
  198.  
  199.     PCIVME_ACCESS_COMMAND access_command;
  200.                
  201.     access_command.bAccessType =
  202.     access_command.bIncrement  = bAccessType;  // increment and accessType are the same
  203.     access_command.bModifier   = bModifier;
  204.  
  205.     if (ioctl(dev->nFileNo, PCIVME_SET_ACCESS_PARA, &access_command) < 0)
  206.     {
  207.         dev->nLastError = errno;
  208.         return errno;
  209.     }
  210.  
  211.     dev->cAddressModifier = bModifier;
  212.     dev->cAccessWidth     = bAccessType;
  213.  
  214.     return 0;
  215. }
  216.  
  217. int VMEread(int nHandle, unsigned long ulAddress, unsigned char ubAccessWidth, unsigned long ulElementCount, void *pvBuffer)
  218. {
  219.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
  220.     size_t count      = (size_t)(ulElementCount * ubAccessWidth);
  221.     ssize_t result;
  222.     int error;
  223.  
  224.     if (dev->cAccessWidth != ubAccessWidth)
  225.     {
  226.         if ((error = setAccessProperties(nHandle, dev->cAddressModifier, ubAccessWidth)))
  227.             return error;
  228.     }
  229.  
  230.     if (lseek(dev->nFileNo, ulAddress, SEEK_SET) < 0)
  231.         return errno;
  232.  
  233.     result = read(dev->nFileNo, pvBuffer, count);
  234.  
  235.     if (result != count)
  236.     {
  237.         if (result < 0)
  238.         {
  239.             dev->nLastError = errno;
  240.             return errno;
  241.         }
  242.         else
  243.             return EFAULT;
  244.     }
  245.  
  246.     return 0;
  247. }
  248.  
  249. int VMEwrite(int nHandle, unsigned long ulAddress, unsigned char ubAccessWidth, unsigned long ulElementCount, void *pvBuffer)
  250. {
  251.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
  252.     size_t count      = (size_t)(ulElementCount * ubAccessWidth);
  253.     ssize_t result;
  254.     int error;
  255.  
  256.     if (dev->cAccessWidth != ubAccessWidth)
  257.     {
  258.         if ((error = setAccessProperties(nHandle, dev->cAddressModifier, ubAccessWidth)))
  259.             return error;
  260.     }
  261.  
  262.     if (lseek(dev->nFileNo, ulAddress, SEEK_SET) < 0)
  263.         return errno;
  264.  
  265.     result = write(dev->nFileNo, pvBuffer, count);
  266.  
  267.     if (result != count)
  268.     {
  269.         if (result < 0)
  270.         {
  271.             dev->nLastError = errno;
  272.             return errno;
  273.         }
  274.         else
  275.             return EFAULT;
  276.     }
  277.  
  278.     return 0;
  279. }
  280.  
  281. int VMEaccessVIC(int nHandle, unsigned char ubAccessMode, unsigned short uwAddress, unsigned char *ubContent)
  282. {
  283.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
  284.     PCIVME_VIC68A_ACTION vic68a_action;
  285.  
  286.     vic68a_action.bAccessMode      = ubAccessMode;
  287.     vic68a_action.bContent         = *ubContent;  
  288.     vic68a_action.wRegisterAddress = uwAddress;
  289.  
  290.     if (ioctl(dev->nFileNo, PCIVME_ACCESS_VIC68A, &vic68a_action) < 0)
  291.     {
  292.         dev->nLastError = errno;
  293.         return errno;
  294.     }
  295.  
  296.     *ubContent = vic68a_action.bContent;
  297.  
  298.     return 0;
  299. }
  300.  
  301. int VMEreset(int nHandle)
  302. {
  303.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
  304.     PCIVME_RESET_COMMAND reset_command;
  305.     int i = 10;
  306.  
  307.     reset_command.bCommand = GLOBAL_RESET_CMD;
  308.     reset_command.bResult  = 0xff;  
  309.  
  310.     if (ioctl(dev->nFileNo, PCIVME_RESET, &reset_command) < 0)
  311.     {
  312.         dev->nLastError = errno;
  313.         return errno;
  314.     }
  315.  
  316.     do
  317.     {
  318.         usleep(100);
  319.         reset_command.bCommand = POLL_RESET_CMD;
  320.         reset_command.bResult  = 0xff;  
  321.    
  322.         if (ioctl(dev->nFileNo, PCIVME_RESET, &reset_command) < 0)
  323.         {
  324.             dev->nLastError = errno;
  325.             return errno;
  326.         }
  327.     } while ((reset_command.bResult) && (i--));
  328.  
  329.     if (!i)
  330.         return ETIME;
  331.  
  332.     dev->nLastError = 0;
  333.  
  334.     return 0;
  335. }
  336.  
  337. int VMETAS(int nHandle, unsigned long ulAddress, unsigned char *ubResult)
  338. {
  339.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
  340.     PCIVME_TAS_STRUCT tas;
  341.  
  342.     tas.bContent  = *ubResult;
  343.     tas.bModifier = dev->cAddressModifier;  
  344.     tas.dwAddress = ulAddress;
  345.  
  346.     if (ioctl(dev->nFileNo, PCIVME_TAS, &tas) < 0)
  347.     {
  348.         dev->nLastError = errno;
  349.         return errno;
  350.     }
  351.  
  352.     *ubResult = tas.bContent;
  353.  
  354.     return 0;
  355. }
  356.  
  357. int VMEinterrupt(int nHandle, unsigned char *ubVector)
  358. {
  359.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
  360.         PCIVME_VECTOR_LEVEL ubLocalVector;
  361.  
  362.     if (ioctl(dev->nFileNo, PCIVME_READ_VECTOR_POLL, &ubLocalVector) < 0)
  363.     {
  364.         dev->nLastError = errno;
  365.         return errno;
  366.     }
  367.  
  368.     *ubVector = (__u8)ubLocalVector.dwStatusID;
  369.  
  370.     return 0;
  371. }
  372.  
  373. int VMEsysfailGet(int nHandle, BOOLEAN *bResult)
  374. {
  375.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
  376.         PCIVME_VIC68A_ACTION sAction;    // structure to access vic chip
  377.  
  378.         sAction.wRegisterAddress = EGICR;
  379.         sAction.bAccessMode      = VIC68A_READ;
  380.         sAction.bContent         = 0;
  381.  
  382.     if (ioctl(dev->nFileNo, PCIVME_ACCESS_VIC68A, &sAction) < 0)
  383.     {
  384.         dev->nLastError = errno;
  385.         return errno;
  386.     }
  387.  
  388.         *bResult = (sAction.bContent & 0x08) ? FALSE : TRUE;
  389.  
  390.     return 0;
  391. }
  392.  
  393. int VMEsysfailSet(int nHandle, BOOLEAN bForce)
  394. {
  395.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
  396.         PCIVME_VIC68A_ACTION sAction;    // structure to access vic chip
  397.  
  398.         sAction.wRegisterAddress = ICR7;
  399.         sAction.bAccessMode      = (bForce == TRUE) ? VIC68A_AND : VIC68A_OR;
  400.         sAction.bContent         = (bForce == TRUE) ? 0x3F               : 0x80;
  401.  
  402.     if (ioctl(dev->nFileNo, PCIVME_ACCESS_VIC68A, &sAction) < 0)
  403.     {
  404.         dev->nLastError = errno;
  405.         return errno;
  406.     }
  407.  
  408.     return 0;
  409. }
  410.  
  411. int VMEerror(int nHandle)
  412. {
  413.     __u8 ubVector;
  414.  
  415.     VMEinterrupt(nHandle, &ubVector);
  416.  
  417.     if (ubVector == 7)
  418.         return EFAULT;  // it's a bus error
  419.     else
  420.         return 0;
  421. }
  422.  
  423. int VMEclose(int nHandle)
  424. {
  425.     int error = 0;
  426.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
  427.  
  428.     if (dev != (VMEMM_DEVICE *)NULL)
  429.     {
  430.         deInitHardware(dev);
  431.  
  432.         if (dev->nFileNo != -1)
  433.             close(dev->nFileNo);
  434.         else
  435.             error = -EINVAL;
  436.  
  437.         free(dev);
  438.     }
  439.  
  440.     return error;
  441. }
  442.  
  443. int VMEcontrolInterrupt(int nHandle, BOOLEAN *bEnable)
  444. {
  445.     VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
  446.         PCIVME_IRQ_CONTROL  control;
  447.  
  448.     control.bEnable = *bEnable;
  449.  
  450.     if (ioctl(dev->nFileNo, PCIVME_CONTROL_INTERRUPTS, &control) < 0)
  451.     {
  452.         dev->nLastError = errno;
  453.         return errno;
  454.     }
  455.  
  456.     // status of interrupt enable before set
  457.     *bEnable = control.bEnable;
  458.  
  459.     return 0;
  460. }
  461.  
  462. int GetLastError(int nHandle)
  463. {
  464.     VMEMM_DEVICE *dev  = (VMEMM_DEVICE *)nHandle;
  465.     int nLocalError;
  466.  
  467.     nLocalError = dev->nLastError;
  468.     dev->nLastError = 0;
  469.  
  470.     return nLocalError;
  471. }
  472.  
  473.  
  474.