]> rtime.felk.cvut.cz Git - mf6xx.git/blobdiff - src/hudaqlib/resources.c
Changed some directory names for easier understanding.
[mf6xx.git] / src / hudaqlib / resources.c
diff --git a/src/hudaqlib/resources.c b/src/hudaqlib/resources.c
new file mode 100644 (file)
index 0000000..ade43bb
--- /dev/null
@@ -0,0 +1,353 @@
+/******************************************************************/\r
+/**@file resources.c:\r
+ * Desctiption: Humusoft data acquisition Linux library\r
+ implementation.                                   *\r
+ * Dependency: Linux                                              *\r
+ *                Copyright 2006-2008 Jaroslav Fojtik             *\r
+ ******************************************************************/\r
+#include <stdio.h>\r
+#include <malloc.h>\r
+\r
+#include <sys/mman.h>\r
+#include <sys/io.h>\r
+#include <unistd.h>\r
+#include <fcntl.h>\r
+#include <string.h>\r
+#include <byteswap.h>\r
+#include <inttypes.h>\r
+#include <time.h>\r
+\r
+#include "hudaqlib.h"\r
+#include "hudaq_internal.h"\r
+\r
+\r
+#ifdef _MSC_VER\r
+       #pragma comment(lib, "setupapi")\r
+#endif //_MSC_VER\r
+\r
+\r
+int IOPLsUsed = 0;\r
+\r
+/** Calltables for all available devices. */\r
+const CallTable * const AllCTs[] = \r
+{\r
+#ifdef MF61X\r
+       &CT612, &CT614,\r
+#endif\r
+#ifdef MF62X\r
+       &CT622, &CT624, &CT625,\r
+#endif\r
+#ifdef PCI1753\r
+       &CTPCI1753,\r
+#endif\r
+#ifdef PCD7004\r
+       &CTPCD7004,\r
+#endif\r
+#ifdef PCT7303B\r
+       &CTPCT7303,\r
+#endif\r
+};\r
+\r
+int OpenDeviceHandle(const char* devicename, int deviceorder, DriverRecord *Rec);\r
+\r
+\r
+static uintptr_t device_mmap_range(int device_fd, uintptr_t mem_start, size_t mem_length, unsigned int mmap_offset)\r
+{\r
+       size_t pagesize;\r
+       unsigned char *mm;\r
+       unsigned char *ptr;\r
+\r
+       pagesize = getpagesize();\r
+       //mem_length += (mem_start & (pagesize-1))+pagesize-1;\r
+       //mem_length &= ~(pagesize-1);\r
+       //FIXME mem_length\r
+\r
+       mm = mmap(0, mem_length, PROT_READ | PROT_WRITE, MAP_SHARED, device_fd, mmap_offset * getpagesize());\r
+       if ((mm == NULL) || (mm == MAP_FAILED)) {\r
+               perror("mmap()");\r
+               return 0;\r
+       }\r
+       ptr = mm + (mem_start & (pagesize-1));\r
+\r
+       //fprintf(stderr,"mmap OK for range 0x%08lx length 0x%08lx -> 0x%08lx\n",\r
+       //            (long)mem_start,(long)mem_length,(long)ptr);\r
+\r
+       return  (uintptr_t)ptr;\r
+}\r
+\r
+static void device_unmmap_range(uintptr_t mem_start, size_t mem_length)\r
+{\r
+       size_t pagesize;\r
+       unsigned char *mm;\r
+\r
+       pagesize = getpagesize();\r
+       mem_length += (mem_start & (pagesize-1))+pagesize-1;\r
+       mem_length &= ~(pagesize-1);\r
+\r
+       mm = (mem_start & ~(pagesize-1));\r
+\r
+       if(munmap(mm, mem_length) != 0) {\r
+               printf("\nHudaqlib: unmmap failed.");\r
+       }\r
+}\r
+\r
+/* Allocate available resources (?)*/\r
+int DeviceIoControl(int Operation, DriverRecord *Rec)\r
+{\r
+       int i, ret;\r
+       int fd;\r
+       char memdev[64];\r
+\r
+       if(Rec == NULL) {\r
+               return 0;\r
+       }\r
+       sprintf(memdev, "/dev/uio%d", Rec->UioDevNum);\r
+\r
+       if(Operation) //Allocate resources\r
+       {\r
+               fd = open(memdev, O_RDWR | O_SYNC);\r
+               if (fd < 0) {\r
+                       perror("open()");       \r
+               }\r
+               if (fd >= 0)\r
+               {   \r
+                       for(i = 0; i < Rec->NumPhysMemResources; i ++)\r
+                       {\r
+                               Rec->Resources.MemResources[i].Base = \r
+                                       device_mmap_range(fd, Rec->PhysMemResources[i].Base, \r
+                                               Rec->PhysMemResources[i].Length, \r
+                                               Rec->PhysMemResources[i].UioMappingIndex);\r
+                               Rec->Resources.MemResources[i].Length = Rec->PhysMemResources[i].Length;\r
+                               Rec->Resources.NumMemResources++;\r
+                       }           \r
+                       close(fd);\r
+               }\r
+\r
+               for(i = 0; i < Rec->Resources.NumIOResources; i ++)\r
+               {       /*baze, delka useku, 1=povoleni 0=zakazani*/\r
+                       //printf("IOPERM %X %X",Rec->Resources.IOResources[i].Base,Rec->Resources.IOResources[i].Length);\r
+                       if(Rec->Resources.IOResources[i].Base + Rec->Resources.IOResources[i].Length <= 0x3FF)\r
+                       {\r
+                               ret = ioperm(Rec->Resources.IOResources[i].Base,\r
+                                               Rec->Resources.IOResources[i].Length, 1);\r
+                       }\r
+                       else        \r
+                       {\r
+                               iopl(3);\r
+                               IOPLsUsed ++;\r
+                       }\r
+               }\r
+               return 1;\r
+       }\r
+       else          //free resources\r
+       {\r
+               for(i = 0; i < Rec->Resources.NumMemResources; i ++)\r
+               {\r
+                       device_unmmap_range((void *) Rec->Resources.MemResources[i].Base,\r
+                                       Rec->Resources.MemResources[i].Length);\r
+               }\r
+               Rec->Resources.NumMemResources = 0;\r
+\r
+               for(i = 0; i < Rec->Resources.NumIOResources; i ++)\r
+               {\r
+                       /* !!!!!!!!!!! BUG, scan all allocated ranges prevent disabling already used space. !!!!!!!!!!! */\r
+                       if(Rec->Resources.IOResources[i].Base + Rec->Resources.IOResources[i].Length <= 0x3FF)\r
+                       {      /*base, IO length, 1=enable 0=disable*/\r
+                               ret = ioperm(Rec->Resources.IOResources[i].Base,\r
+                                               Rec->Resources.IOResources[i].Length, 0);\r
+                       }\r
+                       else \r
+                       {\r
+                               if(IOPLsUsed > 0) {\r
+                                       IOPLsUsed --;\r
+                               }\r
+                               if(IOPLsUsed <= 0) {\r
+                                        iopl(0);\r
+                               }\r
+                       }\r
+               }\r
+               return 1;\r
+       }\r
+}\r
+\r
+\r
+\r
+/*********************************\r
+ *********************************/\r
+\r
+HUDAQSTATUS InternalResetDevice(DeviceRecord *DevRecord, int ShareFlag)\r
+{\r
+       int Iter;\r
+\r
+       if(DevRecord == NULL) {\r
+               return HUDAQFAILURE;\r
+       }\r
+\r
+       /* Traverse a list with supported devices. A PCI ID would be much more better. */\r
+       for(Iter = 0; Iter < (sizeof(AllCTs) / sizeof(CallTable*)); Iter ++)\r
+       {\r
+               //printf("\nTry to match: %s %s", AllCTs[Iter]->DeviceString, DevRecord->Name);\r
+               if(!strcmp(AllCTs[Iter]->DeviceString, DevRecord->Name))\r
+               {\r
+                       if(AllCTs[Iter]->HudaqInit(DevRecord, ShareFlag) > 0) {\r
+                               return HUDAQSUCCESS;\r
+                       } else {\r
+                               return HUDAQFAILURE;\r
+                       }\r
+               }\r
+       }\r
+\r
+       // unsupported device\r
+       DevRecord->pCT = &CtDummy;\r
+       return HUDAQPARTIAL;\r
+}\r
+\r
+\r
+/** Opens a given device. */\r
+HUDAQHANDLE HUDAQAPI HudaqOpenDevice(const char* devicename, int deviceorder, int shareflag)\r
+{\r
+       DeviceRecord* devrecord;\r
+\r
+       if (devicename == NULL) {\r
+               return 0;  /* Invalid device name. */\r
+       }\r
+       /* allocate memory for the device record */\r
+       devrecord = calloc(1, sizeof(DeviceRecord));\r
+       if (devrecord == 0) {\r
+               return 0;\r
+       }\r
+\r
+       /* copy device name and order */\r
+       devrecord->DrvRes.Size = sizeof(DriverRecord);\r
+       strncpy(devrecord->Name, devicename, sizeof(devrecord->Name) - 1);\r
+       devrecord->Order = deviceorder;\r
+\r
+       /* open the system device handle */\r
+       if(OpenDeviceHandle(devrecord->Name, devrecord->Order, &devrecord->DrvRes) < 0)\r
+       {\r
+               free(devrecord);\r
+               return 0;\r
+       }\r
+\r
+       /* get the resources */\r
+       if(!DeviceIoControl(1, &(devrecord->DrvRes)))\r
+       {\r
+               free(devrecord);    \r
+               return 0; /* DeviceIoControl returns (bool) 'false' if fails.  */\r
+       }\r
+\r
+       devrecord->pCT = &CtDummy;\r
+       devrecord->DrvRes.DriverData = calloc(1, 1024); //!!!! THIS SHOULD BE SHARED !!!!\r
+       devrecord->DrvRes.DriverDataSize = 1024;\r
+\r
+       \r
+       switch(InternalResetDevice(devrecord, shareflag))\r
+       {\r
+               case HUDAQSUCCESS: break;  // everything is OK\r
+               case HUDAQPARTIAL: break;  // unknown device, return its resources only\r
+               case HUDAQFAILURE:         // initialisation failed - go on\r
+               default:                   // unexpected return code\r
+                                  HudaqCloseDevice((HUDAQHANDLE) devrecord);\r
+                                  return(0);\r
+       }\r
+\r
+       return((HUDAQHANDLE) devrecord);\r
+}\r
+\r
+\r
+HUDAQSTATUS HUDAQAPI HudaqResetDevice(HUDAQHANDLE handle)\r
+{\r
+       return InternalResetDevice(HudaqGetDeviceRecord(handle), 0);\r
+}\r
+\r
+\r
+\r
+/** Closes a valid handle to a device. */\r
+void HUDAQAPI HudaqCloseDevice(HUDAQHANDLE handle)\r
+{\r
+\r
+       /* typecast handle to device record, check for validity */\r
+       DeviceRecord* devrecord = (DeviceRecord*) handle;\r
+       if (devrecord == 0)\r
+               return;\r
+\r
+       devrecord->pCT->HudaqDone(devrecord);\r
+\r
+       /* free the resources */\r
+       DeviceIoControl(0, &(devrecord->DrvRes));\r
+\r
+       if(devrecord->DrvRes.DriverData) {\r
+               free(devrecord->DrvRes.DriverData);\r
+               devrecord->DrvRes.DriverData = NULL;\r
+       }\r
+\r
+       /* close the system device handle */\r
+       //  CloseHandle(devrecord->SysHandle);\r
+\r
+       /* free the device record memory */\r
+       free(devrecord);\r
+}\r
+\r
+\r
+\r
+const HudaqResourceInfo* HUDAQAPI HudaqGetDeviceResources(HUDAQHANDLE handle)\r
+{\r
+       /* typecast handle to device record, check for validity */\r
+       DeviceRecord* devrecord = (DeviceRecord*) handle;\r
+       if (devrecord == 0)\r
+               return(0);\r
+\r
+       /* return the pointer to resource structure */\r
+       return(&(devrecord->DrvRes.Resources));\r
+}\r
+\r
+\r
+/** This procedure returns full device name. */\r
+const char* HUDAQAPI HudaqGetBoardName(HUDAQHANDLE handle)\r
+{\r
+       /* typecast handle to device record, check for validity */\r
+       DeviceRecord* devrecord = (DeviceRecord*) handle;\r
+       if (devrecord == 0)\r
+               return(NULL);\r
+\r
+       /* Return a pointer to the device name. */\r
+       return(devrecord->Name);\r
+}\r
+\r
+\r
+/** Entry / Exit code of whole dll. */\r
+/*\r
+   int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)\r
+   {\r
+   switch(dwReason)\r
+   {\r
+   case DLL_PROCESS_ATTACH:\r
+   break;\r
+\r
+   case DLL_PROCESS_DETACH:\r
+   if(SaveHandle)   //Is there any handle opened by "GetBoardIOAddress"?\r
+   {\r
+   HudaqCloseDevice(SaveHandle);\r
+   SaveHandle = 0;\r
+   }\r
+   break;\r
+\r
+   default: ;\r
+//MessageBox(NULL, "DllMain.", "HUDAQ", MB_OK | MB_APPLMODAL | MB_ICONHAND);\r
+}\r
+\r
+\r
+return 1;   // Ok\r
+}\r
+ */\r
+\r
+\r
+/*************************************************/\r
+/* Return time in ms.                           */\r
+int timeGetTime(void)\r
+{\r
+       struct timespec current_time;\r
+       clock_gettime(CLOCK_REALTIME, &current_time);\r
+\r
+       return current_time.tv_nsec/1000 + current_time.tv_sec*1000;\r
+}\r