--- /dev/null
+/******************************************************************/\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, ¤t_time);\r
+\r
+ return current_time.tv_nsec/1000 + current_time.tv_sec*1000;\r
+}\r