1 /******************************************************************/
\r
2 /**@file resources.c:
\r
3 * Desctiption: Humusoft data acquisition Linux library
\r
5 * Dependency: Linux *
\r
6 * Copyright 2006-2008 Jaroslav Fojtik *
\r
7 ******************************************************************/
\r
11 #include <sys/mman.h>
\r
16 #include <byteswap.h>
\r
17 #include <inttypes.h>
\r
20 #include "hudaqlib.h"
\r
21 #include "hudaq_internal.h"
\r
25 #pragma comment(lib, "setupapi")
\r
31 /** Calltables for all available devices. */
\r
32 const CallTable * const AllCTs[] =
\r
38 &CT622, &CT624, &CT625,
\r
51 int OpenDeviceHandle(const char* devicename, int deviceorder, DriverRecord *Rec);
\r
54 static uintptr_t device_mmap_range(int device_fd, uintptr_t mem_start, size_t mem_length, unsigned int mmap_offset)
\r
60 pagesize = getpagesize();
\r
61 //mem_length += (mem_start & (pagesize-1))+pagesize-1;
\r
62 //mem_length &= ~(pagesize-1);
\r
65 mm = mmap(0, mem_length, PROT_READ | PROT_WRITE, MAP_SHARED, device_fd, mmap_offset * getpagesize());
\r
66 if ((mm == NULL) || (mm == MAP_FAILED)) {
\r
70 ptr = mm + (mem_start & (pagesize-1));
\r
72 //fprintf(stderr,"mmap OK for range 0x%08lx length 0x%08lx -> 0x%08lx\n",
\r
73 // (long)mem_start,(long)mem_length,(long)ptr);
\r
75 return (uintptr_t)ptr;
\r
78 static void device_unmmap_range(uintptr_t mem_start, size_t mem_length)
\r
83 pagesize = getpagesize();
\r
84 mem_length += (mem_start & (pagesize-1))+pagesize-1;
\r
85 mem_length &= ~(pagesize-1);
\r
87 mm = (mem_start & ~(pagesize-1));
\r
89 if(munmap(mm, mem_length) != 0) {
\r
90 printf("\nHudaqlib: unmmap failed.");
\r
94 /* Allocate available resources (?)*/
\r
95 int DeviceIoControl(int Operation, DriverRecord *Rec)
\r
104 sprintf(memdev, "/dev/uio%d", Rec->UioDevNum);
\r
106 if(Operation) //Allocate resources
\r
108 fd = open(memdev, O_RDWR | O_SYNC);
\r
114 for(i = 0; i < Rec->NumPhysMemResources; i ++)
\r
116 Rec->Resources.MemResources[i].Base =
\r
117 device_mmap_range(fd, Rec->PhysMemResources[i].Base,
\r
118 Rec->PhysMemResources[i].Length,
\r
119 Rec->PhysMemResources[i].UioMappingIndex);
\r
120 Rec->Resources.MemResources[i].Length = Rec->PhysMemResources[i].Length;
\r
121 Rec->Resources.NumMemResources++;
\r
126 for(i = 0; i < Rec->Resources.NumIOResources; i ++)
\r
127 { /*baze, delka useku, 1=povoleni 0=zakazani*/
\r
128 //printf("IOPERM %X %X",Rec->Resources.IOResources[i].Base,Rec->Resources.IOResources[i].Length);
\r
129 if(Rec->Resources.IOResources[i].Base + Rec->Resources.IOResources[i].Length <= 0x3FF)
\r
131 ret = ioperm(Rec->Resources.IOResources[i].Base,
\r
132 Rec->Resources.IOResources[i].Length, 1);
\r
142 else //free resources
\r
144 for(i = 0; i < Rec->Resources.NumMemResources; i ++)
\r
146 device_unmmap_range((void *) Rec->Resources.MemResources[i].Base,
\r
147 Rec->Resources.MemResources[i].Length);
\r
149 Rec->Resources.NumMemResources = 0;
\r
151 for(i = 0; i < Rec->Resources.NumIOResources; i ++)
\r
153 /* !!!!!!!!!!! BUG, scan all allocated ranges prevent disabling already used space. !!!!!!!!!!! */
\r
154 if(Rec->Resources.IOResources[i].Base + Rec->Resources.IOResources[i].Length <= 0x3FF)
\r
155 { /*base, IO length, 1=enable 0=disable*/
\r
156 ret = ioperm(Rec->Resources.IOResources[i].Base,
\r
157 Rec->Resources.IOResources[i].Length, 0);
\r
161 if(IOPLsUsed > 0) {
\r
164 if(IOPLsUsed <= 0) {
\r
175 /*********************************
\r
176 *********************************/
\r
178 HUDAQSTATUS InternalResetDevice(DeviceRecord *DevRecord, int ShareFlag)
\r
182 if(DevRecord == NULL) {
\r
183 return HUDAQFAILURE;
\r
186 /* Traverse a list with supported devices. A PCI ID would be much more better. */
\r
187 for(Iter = 0; Iter < (sizeof(AllCTs) / sizeof(CallTable*)); Iter ++)
\r
189 //printf("\nTry to match: %s %s", AllCTs[Iter]->DeviceString, DevRecord->Name);
\r
190 if(!strcmp(AllCTs[Iter]->DeviceString, DevRecord->Name))
\r
192 if(AllCTs[Iter]->HudaqInit(DevRecord, ShareFlag) > 0) {
\r
193 return HUDAQSUCCESS;
\r
195 return HUDAQFAILURE;
\r
200 // unsupported device
\r
201 DevRecord->pCT = &CtDummy;
\r
202 return HUDAQPARTIAL;
\r
206 /** Opens a given device. */
\r
207 HUDAQHANDLE HUDAQAPI HudaqOpenDevice(const char* devicename, int deviceorder, int shareflag)
\r
209 DeviceRecord* devrecord;
\r
211 if (devicename == NULL) {
\r
212 return 0; /* Invalid device name. */
\r
214 /* allocate memory for the device record */
\r
215 devrecord = calloc(1, sizeof(DeviceRecord));
\r
216 if (devrecord == 0) {
\r
220 /* copy device name and order */
\r
221 devrecord->DrvRes.Size = sizeof(DriverRecord);
\r
222 strncpy(devrecord->Name, devicename, sizeof(devrecord->Name) - 1);
\r
223 devrecord->Order = deviceorder;
\r
225 /* open the system device handle */
\r
226 if(OpenDeviceHandle(devrecord->Name, devrecord->Order, &devrecord->DrvRes) < 0)
\r
232 /* get the resources */
\r
233 if(!DeviceIoControl(1, &(devrecord->DrvRes)))
\r
236 return 0; /* DeviceIoControl returns (bool) 'false' if fails. */
\r
239 devrecord->pCT = &CtDummy;
\r
240 devrecord->DrvRes.DriverData = calloc(1, 1024); //!!!! THIS SHOULD BE SHARED !!!!
\r
241 devrecord->DrvRes.DriverDataSize = 1024;
\r
244 switch(InternalResetDevice(devrecord, shareflag))
\r
246 case HUDAQSUCCESS: break; // everything is OK
\r
247 case HUDAQPARTIAL: break; // unknown device, return its resources only
\r
248 case HUDAQFAILURE: // initialisation failed - go on
\r
249 default: // unexpected return code
\r
250 HudaqCloseDevice((HUDAQHANDLE) devrecord);
\r
254 return((HUDAQHANDLE) devrecord);
\r
258 HUDAQSTATUS HUDAQAPI HudaqResetDevice(HUDAQHANDLE handle)
\r
260 return InternalResetDevice(HudaqGetDeviceRecord(handle), 0);
\r
265 /** Closes a valid handle to a device. */
\r
266 void HUDAQAPI HudaqCloseDevice(HUDAQHANDLE handle)
\r
269 /* typecast handle to device record, check for validity */
\r
270 DeviceRecord* devrecord = (DeviceRecord*) handle;
\r
271 if (devrecord == 0)
\r
274 devrecord->pCT->HudaqDone(devrecord);
\r
276 /* free the resources */
\r
277 DeviceIoControl(0, &(devrecord->DrvRes));
\r
279 if(devrecord->DrvRes.DriverData) {
\r
280 free(devrecord->DrvRes.DriverData);
\r
281 devrecord->DrvRes.DriverData = NULL;
\r
284 /* close the system device handle */
\r
285 // CloseHandle(devrecord->SysHandle);
\r
287 /* free the device record memory */
\r
293 const HudaqResourceInfo* HUDAQAPI HudaqGetDeviceResources(HUDAQHANDLE handle)
\r
295 /* typecast handle to device record, check for validity */
\r
296 DeviceRecord* devrecord = (DeviceRecord*) handle;
\r
297 if (devrecord == 0)
\r
300 /* return the pointer to resource structure */
\r
301 return(&(devrecord->DrvRes.Resources));
\r
305 /** This procedure returns full device name. */
\r
306 const char* HUDAQAPI HudaqGetBoardName(HUDAQHANDLE handle)
\r
308 /* typecast handle to device record, check for validity */
\r
309 DeviceRecord* devrecord = (DeviceRecord*) handle;
\r
310 if (devrecord == 0)
\r
313 /* Return a pointer to the device name. */
\r
314 return(devrecord->Name);
\r
318 /** Entry / Exit code of whole dll. */
\r
320 int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
\r
324 case DLL_PROCESS_ATTACH:
\r
327 case DLL_PROCESS_DETACH:
\r
328 if(SaveHandle) //Is there any handle opened by "GetBoardIOAddress"?
\r
330 HudaqCloseDevice(SaveHandle);
\r
336 //MessageBox(NULL, "DllMain.", "HUDAQ", MB_OK | MB_APPLMODAL | MB_ICONHAND);
\r
345 /*************************************************/
\r
346 /* Return time in ms. */
\r
347 int timeGetTime(void)
\r
349 struct timespec current_time;
\r
350 clock_gettime(CLOCK_REALTIME, ¤t_time);
\r
352 return current_time.tv_nsec/1000 + current_time.tv_sec*1000;
\r