]> rtime.felk.cvut.cz Git - mf6xx.git/blob - src/hudaqlib/resources.c
QEMU mf624.c formatted to make QEMU checkpatch.pl mostly happy.
[mf6xx.git] / src / hudaqlib / resources.c
1 /******************************************************************/\r
2 /**@file resources.c:\r
3  * Desctiption: Humusoft data acquisition Linux library\r
4  implementation.                                   *\r
5  * Dependency: Linux                                              *\r
6  *                Copyright 2006-2008 Jaroslav Fojtik             *\r
7  ******************************************************************/\r
8 #include <stdio.h>\r
9 #include <malloc.h>\r
10 \r
11 #include <sys/mman.h>\r
12 #include <sys/io.h>\r
13 #include <unistd.h>\r
14 #include <fcntl.h>\r
15 #include <string.h>\r
16 #include <byteswap.h>\r
17 #include <inttypes.h>\r
18 #include <time.h>\r
19 \r
20 #include "hudaqlib.h"\r
21 #include "hudaq_internal.h"\r
22 \r
23 \r
24 #ifdef _MSC_VER\r
25         #pragma comment(lib, "setupapi")\r
26 #endif //_MSC_VER\r
27 \r
28 \r
29 int IOPLsUsed = 0;\r
30 \r
31 /** Calltables for all available devices. */\r
32 const CallTable * const AllCTs[] = \r
33 {\r
34 #ifdef MF61X\r
35         &CT612, &CT614,\r
36 #endif\r
37 #ifdef MF62X\r
38         &CT622, &CT624, &CT625,\r
39 #endif\r
40 #ifdef PCI1753\r
41         &CTPCI1753,\r
42 #endif\r
43 #ifdef PCD7004\r
44         &CTPCD7004,\r
45 #endif\r
46 #ifdef PCT7303B\r
47         &CTPCT7303,\r
48 #endif\r
49 };\r
50 \r
51 int OpenDeviceHandle(const char* devicename, int deviceorder, DriverRecord *Rec);\r
52 \r
53 \r
54 static uintptr_t device_mmap_range(int device_fd, uintptr_t mem_start, size_t mem_length, unsigned int mmap_offset)\r
55 {\r
56         size_t pagesize;\r
57         unsigned char *mm;\r
58         unsigned char *ptr;\r
59 \r
60         pagesize = getpagesize();\r
61         //mem_length += (mem_start & (pagesize-1))+pagesize-1;\r
62         //mem_length &= ~(pagesize-1);\r
63         //FIXME mem_length\r
64 \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
67                 perror("mmap()");\r
68                 return 0;\r
69         }\r
70         ptr = mm + (mem_start & (pagesize-1));\r
71 \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
74 \r
75         return  (uintptr_t)ptr;\r
76 }\r
77 \r
78 static void device_unmmap_range(uintptr_t mem_start, size_t mem_length)\r
79 {\r
80         size_t pagesize;\r
81         unsigned char *mm;\r
82 \r
83         pagesize = getpagesize();\r
84         mem_length += (mem_start & (pagesize-1))+pagesize-1;\r
85         mem_length &= ~(pagesize-1);\r
86 \r
87         mm = (mem_start & ~(pagesize-1));\r
88 \r
89         if(munmap(mm, mem_length) != 0) {\r
90                 printf("\nHudaqlib: unmmap failed.");\r
91         }\r
92 }\r
93 \r
94 /* Allocate available resources (?)*/\r
95 int DeviceIoControl(int Operation, DriverRecord *Rec)\r
96 {\r
97         int i, ret;\r
98         int fd;\r
99         char memdev[64];\r
100 \r
101         if(Rec == NULL) {\r
102                 return 0;\r
103         }\r
104         sprintf(memdev, "/dev/uio%d", Rec->UioDevNum);\r
105 \r
106         if(Operation) //Allocate resources\r
107         {\r
108                 fd = open(memdev, O_RDWR | O_SYNC);\r
109                 if (fd < 0) {\r
110                         perror("open()");       \r
111                 }\r
112                 if (fd >= 0)\r
113                 {   \r
114                         for(i = 0; i < Rec->NumPhysMemResources; i ++)\r
115                         {\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
122                         }           \r
123                         close(fd);\r
124                 }\r
125 \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
130                         {\r
131                                 ret = ioperm(Rec->Resources.IOResources[i].Base,\r
132                                                 Rec->Resources.IOResources[i].Length, 1);\r
133                         }\r
134                         else        \r
135                         {\r
136                                 iopl(3);\r
137                                 IOPLsUsed ++;\r
138                         }\r
139                 }\r
140                 return 1;\r
141         }\r
142         else          //free resources\r
143         {\r
144                 for(i = 0; i < Rec->Resources.NumMemResources; i ++)\r
145                 {\r
146                         device_unmmap_range((void *) Rec->Resources.MemResources[i].Base,\r
147                                         Rec->Resources.MemResources[i].Length);\r
148                 }\r
149                 Rec->Resources.NumMemResources = 0;\r
150 \r
151                 for(i = 0; i < Rec->Resources.NumIOResources; i ++)\r
152                 {\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
158                         }\r
159                         else \r
160                         {\r
161                                 if(IOPLsUsed > 0) {\r
162                                         IOPLsUsed --;\r
163                                 }\r
164                                 if(IOPLsUsed <= 0) {\r
165                                          iopl(0);\r
166                                 }\r
167                         }\r
168                 }\r
169                 return 1;\r
170         }\r
171 }\r
172 \r
173 \r
174 \r
175 /*********************************\r
176  *********************************/\r
177 \r
178 HUDAQSTATUS InternalResetDevice(DeviceRecord *DevRecord, int ShareFlag)\r
179 {\r
180         int Iter;\r
181 \r
182         if(DevRecord == NULL) {\r
183                 return HUDAQFAILURE;\r
184         }\r
185 \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
188         {\r
189                 //printf("\nTry to match: %s %s", AllCTs[Iter]->DeviceString, DevRecord->Name);\r
190                 if(!strcmp(AllCTs[Iter]->DeviceString, DevRecord->Name))\r
191                 {\r
192                         if(AllCTs[Iter]->HudaqInit(DevRecord, ShareFlag) > 0) {\r
193                                 return HUDAQSUCCESS;\r
194                         } else {\r
195                                 return HUDAQFAILURE;\r
196                         }\r
197                 }\r
198         }\r
199 \r
200         // unsupported device\r
201         DevRecord->pCT = &CtDummy;\r
202         return HUDAQPARTIAL;\r
203 }\r
204 \r
205 \r
206 /** Opens a given device. */\r
207 HUDAQHANDLE HUDAQAPI HudaqOpenDevice(const char* devicename, int deviceorder, int shareflag)\r
208 {\r
209         DeviceRecord* devrecord;\r
210 \r
211         if (devicename == NULL) {\r
212                 return 0;  /* Invalid device name. */\r
213         }\r
214         /* allocate memory for the device record */\r
215         devrecord = calloc(1, sizeof(DeviceRecord));\r
216         if (devrecord == 0) {\r
217                 return 0;\r
218         }\r
219 \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
224 \r
225         /* open the system device handle */\r
226         if(OpenDeviceHandle(devrecord->Name, devrecord->Order, &devrecord->DrvRes) < 0)\r
227         {\r
228                 free(devrecord);\r
229                 return 0;\r
230         }\r
231 \r
232         /* get the resources */\r
233         if(!DeviceIoControl(1, &(devrecord->DrvRes)))\r
234         {\r
235                 free(devrecord);    \r
236                 return 0; /* DeviceIoControl returns (bool) 'false' if fails.  */\r
237         }\r
238 \r
239         devrecord->pCT = &CtDummy;\r
240         devrecord->DrvRes.DriverData = calloc(1, 1024); //!!!! THIS SHOULD BE SHARED !!!!\r
241         devrecord->DrvRes.DriverDataSize = 1024;\r
242 \r
243         \r
244         switch(InternalResetDevice(devrecord, shareflag))\r
245         {\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
251                                    return(0);\r
252         }\r
253 \r
254         return((HUDAQHANDLE) devrecord);\r
255 }\r
256 \r
257 \r
258 HUDAQSTATUS HUDAQAPI HudaqResetDevice(HUDAQHANDLE handle)\r
259 {\r
260         return InternalResetDevice(HudaqGetDeviceRecord(handle), 0);\r
261 }\r
262 \r
263 \r
264 \r
265 /** Closes a valid handle to a device. */\r
266 void HUDAQAPI HudaqCloseDevice(HUDAQHANDLE handle)\r
267 {\r
268 \r
269         /* typecast handle to device record, check for validity */\r
270         DeviceRecord* devrecord = (DeviceRecord*) handle;\r
271         if (devrecord == 0)\r
272                 return;\r
273 \r
274         devrecord->pCT->HudaqDone(devrecord);\r
275 \r
276         /* free the resources */\r
277         DeviceIoControl(0, &(devrecord->DrvRes));\r
278 \r
279         if(devrecord->DrvRes.DriverData) {\r
280                 free(devrecord->DrvRes.DriverData);\r
281                 devrecord->DrvRes.DriverData = NULL;\r
282         }\r
283 \r
284         /* close the system device handle */\r
285         //  CloseHandle(devrecord->SysHandle);\r
286 \r
287         /* free the device record memory */\r
288         free(devrecord);\r
289 }\r
290 \r
291 \r
292 \r
293 const HudaqResourceInfo* HUDAQAPI HudaqGetDeviceResources(HUDAQHANDLE handle)\r
294 {\r
295         /* typecast handle to device record, check for validity */\r
296         DeviceRecord* devrecord = (DeviceRecord*) handle;\r
297         if (devrecord == 0)\r
298                 return(0);\r
299 \r
300         /* return the pointer to resource structure */\r
301         return(&(devrecord->DrvRes.Resources));\r
302 }\r
303 \r
304 \r
305 /** This procedure returns full device name. */\r
306 const char* HUDAQAPI HudaqGetBoardName(HUDAQHANDLE handle)\r
307 {\r
308         /* typecast handle to device record, check for validity */\r
309         DeviceRecord* devrecord = (DeviceRecord*) handle;\r
310         if (devrecord == 0)\r
311                 return(NULL);\r
312 \r
313         /* Return a pointer to the device name. */\r
314         return(devrecord->Name);\r
315 }\r
316 \r
317 \r
318 /** Entry / Exit code of whole dll. */\r
319 /*\r
320    int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)\r
321    {\r
322    switch(dwReason)\r
323    {\r
324    case DLL_PROCESS_ATTACH:\r
325    break;\r
326 \r
327    case DLL_PROCESS_DETACH:\r
328    if(SaveHandle)   //Is there any handle opened by "GetBoardIOAddress"?\r
329    {\r
330    HudaqCloseDevice(SaveHandle);\r
331    SaveHandle = 0;\r
332    }\r
333    break;\r
334 \r
335    default: ;\r
336 //MessageBox(NULL, "DllMain.", "HUDAQ", MB_OK | MB_APPLMODAL | MB_ICONHAND);\r
337 }\r
338 \r
339 \r
340 return 1;   // Ok\r
341 }\r
342  */\r
343 \r
344 \r
345 /*************************************************/\r
346 /* Return time in ms.                            */\r
347 int timeGetTime(void)\r
348 {\r
349         struct timespec current_time;\r
350         clock_gettime(CLOCK_REALTIME, &current_time);\r
351 \r
352         return current_time.tv_nsec/1000 + current_time.tv_sec*1000;\r
353 }\r