Rev 21 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
21 | f9daq | 1 | /* |
2 | cc32lib.c -- a simple access library for the PCICC32 PCI to CAMAC Interface from ARW Elektronik |
||
3 | |||
4 | (c) 2000 ARW Elektronik |
||
5 | |||
6 | this source code is published under GPL (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 | first steps derived from the LINUX pcicc32 library AR 16.03.2000 |
||
15 | added buffer, UNTIL_NOT_Q and AUTOREAD functionality AR 17.03.2001 |
||
16 | corrected fault in setAccessParameter() AR 21.05.2002 |
||
17 | added framework only fro future interrupt handling AR 08.06.2002 |
||
18 | */ |
||
19 | |||
20 | /*--- INCLUDES -----------------------------------------------------------------------------------*/ |
||
21 | #include <windows.h> |
||
22 | #include <stdio.h> |
||
23 | #include <stdlib.h> |
||
24 | #include <string.h> |
||
25 | #include <errno.h> |
||
26 | #include "Vpcic32D.h" /* PCI common ioctl commands and structures between driver and library */ |
||
27 | #include "libcc32_95.h" /* shared header bewteen applictaion and library */ |
||
28 | |||
29 | /*--- DEFINES ------------------------------------------------------------------------------------*/ |
||
30 | #define pwCC32_ADR(adr, N, A, F) (unsigned short *)((N << 10) + (A << 6) + ((F & 0xF) << 2) + adr) |
||
31 | #define plCC32_ADR(adr, N, A, F) (unsigned long *)((N << 10) + (A << 6) + ((F & 0xF) << 2) + adr) |
||
32 | #define WINDOW_SIZE 32768 |
||
33 | |||
34 | /*--- EXTERNALS ----------------------------------------------------------------------------------*/ |
||
35 | |||
36 | /*--- TYPEDEFS -----------------------------------------------------------------------------------*/ |
||
37 | typedef struct |
||
38 | { |
||
39 | HANDLE nHandle; /* the handle of this device */ |
||
40 | int nModuleNumber; /* the number of the module */ |
||
41 | char *base; /* base of range */ |
||
42 | unsigned short wLastAttributes; /* switched attributes like UNTIL_NOT_Q or AUTOREAD */ |
||
43 | } CC32_DEVICE; |
||
44 | |||
45 | /*--- FUNCTIONS -----------------------------------------------------------------------*/ |
||
46 | |||
47 | //-------------------------------------------------------------------------------------- |
||
48 | // a function to get the base address of the CAMAC range |
||
49 | // |
||
50 | static int attachWindow(HANDLE nHandle, DWORD dwInterface, void **base) |
||
51 | { |
||
52 | VPCIC32D_WINDOW window; |
||
53 | DWORD DIOC_count; // count of returned bytes of DeviceIoControl |
||
54 | DWORD result; |
||
55 | |||
56 | *base = NULL; |
||
57 | if (nHandle == (HANDLE)-1) return ERROR_INVALID_HANDLE; |
||
58 | |||
59 | // attach a window into the CC32 space ---------------- |
||
60 | result = DeviceIoControl(nHandle, VPCIC32_ATTACH_CC32, |
||
61 | &dwInterface, sizeof(dwInterface), |
||
62 | &window, sizeof(window), |
||
63 | &DIOC_count, NULL); |
||
64 | |||
65 | if (!result) |
||
66 | return GetLastError(); |
||
67 | else |
||
68 | { |
||
69 | *base = window.pvWindowBase; |
||
70 | return 0; |
||
71 | } |
||
72 | } |
||
73 | |||
74 | //-------------------------------------------------------------------------------------- |
||
75 | // a function to release a attached range |
||
76 | // |
||
77 | static int detachWindow(HANDLE nHandle, DWORD dwInterface) |
||
78 | { |
||
79 | DWORD DIOC_count; // count of returned bytes of DeviceIoControl |
||
80 | DWORD result; |
||
81 | |||
82 | if (nHandle == (HANDLE)-1) return ERROR_INVALID_HANDLE; |
||
83 | |||
84 | // attach a window into the CC32 space ---------------- |
||
85 | result = DeviceIoControl(nHandle, VPCIC32_DETACH_CC32, |
||
86 | &dwInterface, sizeof(dwInterface), |
||
87 | NULL, 0, &DIOC_count, NULL); |
||
88 | if (!result) |
||
89 | return GetLastError(); |
||
90 | else |
||
91 | return 0; |
||
92 | } |
||
93 | |||
94 | //-------------------------------------------------------------------------------------- |
||
95 | // get the PCIADA status from the PCI side of the interface |
||
96 | // |
||
97 | static int getStatus(HANDLE nHandle, DWORD dwInterface, char *nTimeout, char *nLAM) |
||
98 | { |
||
99 | VPCIC32D_STATUS status; |
||
100 | DWORD DIOC_count; // count of returned bytes of DeviceIoControl |
||
101 | DWORD result; |
||
102 | |||
103 | if (nHandle == (HANDLE)-1) return ERROR_INVALID_HANDLE; |
||
104 | |||
105 | *nTimeout = *nLAM = 0; |
||
106 | |||
107 | // attach a window into the CC32 space ---------------- |
||
108 | result = DeviceIoControl(nHandle, VPCIC32_GET_STATUS, |
||
109 | &dwInterface, sizeof(dwInterface), |
||
110 | &status, sizeof(status), &DIOC_count, NULL); |
||
111 | |||
112 | if (!result) |
||
113 | return GetLastError(); |
||
114 | else |
||
115 | { |
||
116 | *nTimeout = (char)status.bTimeout; |
||
117 | *nLAM = (char)status.bInterrupt; |
||
118 | |||
119 | return 0; |
||
120 | } |
||
121 | } |
||
122 | |||
123 | //-------------------------------------------------------------------------------------- |
||
124 | // clear the PCIADA status |
||
125 | // |
||
126 | static int clearStatus(HANDLE nHandle, DWORD dwInterface) |
||
127 | { |
||
128 | DWORD DIOC_count; // count of returned bytes of DeviceIoControl |
||
129 | DWORD result; |
||
130 | |||
131 | if (nHandle == (HANDLE)-1) return ERROR_INVALID_HANDLE; |
||
132 | |||
133 | // attach a window into the CC32 space ---------------- |
||
134 | result = DeviceIoControl(nHandle, VPCIC32_CLEAR_STATUS, |
||
135 | &dwInterface, sizeof(dwInterface), |
||
136 | NULL, 0, &DIOC_count, NULL); |
||
137 | |||
138 | if (!result) |
||
139 | return GetLastError(); |
||
140 | else |
||
141 | return 0; |
||
142 | } |
||
143 | |||
144 | //------------------------------------------------------------------------- |
||
145 | // set the future access parameters - override the current |
||
146 | // |
||
147 | static int setAccessParameter(HANDLE hHandle, DWORD dwInterface, USHORT wBlockTransfer) |
||
148 | { |
||
149 | DWORD result; |
||
150 | DWORD DIOC_count; // count of returned bytes of DeviceIoControl |
||
151 | VPCIC32D_ACCESS_COMMAND access_parameter; |
||
152 | |||
153 | if (hHandle == (HANDLE)-1) return ERROR_INVALID_HANDLE; |
||
154 | |||
155 | access_parameter.dwInterface = dwInterface; |
||
156 | access_parameter.wBlockTransfer = wBlockTransfer; |
||
157 | |||
158 | result = DeviceIoControl(hHandle, VPCIC32_SET_ACCESS_PARA, |
||
159 | &access_parameter, (DWORD)sizeof(access_parameter), NULL, |
||
160 | 0, &DIOC_count, NULL); |
||
161 | if (!result) |
||
162 | return GetLastError(); |
||
163 | else |
||
164 | return 0; |
||
165 | } |
||
166 | |||
167 | //-------------------------------------------------------------------------------------- |
||
168 | // open the device |
||
169 | // |
||
170 | int cc32_open_95(char *cszPath, int nModuleNumber, void **handle) |
||
171 | { |
||
172 | CC32_DEVICE *dev; |
||
173 | int error; |
||
174 | |||
175 | *handle = (void *)-1; |
||
176 | |||
177 | dev = (CC32_DEVICE *)malloc(sizeof(CC32_DEVICE)); |
||
178 | if (!dev) return errno; |
||
179 | |||
180 | dev->base = (char *)0; |
||
181 | dev->nModuleNumber = nModuleNumber; |
||
182 | dev->wLastAttributes = 0; |
||
183 | |||
184 | dev->nHandle = CreateFile(cszPath, |
||
185 | 0, |
||
186 | 0, |
||
187 | NULL, |
||
188 | 0, |
||
189 | FILE_FLAG_DELETE_ON_CLOSE, |
||
190 | NULL); |
||
191 | |||
192 | if (dev->nHandle != INVALID_HANDLE_VALUE) |
||
193 | error = attachWindow(dev->nHandle, nModuleNumber, &dev->base); |
||
194 | else |
||
195 | error = GetLastError(); |
||
196 | |||
197 | if (error) |
||
198 | { |
||
199 | free(dev); |
||
200 | return error; |
||
201 | } |
||
202 | |||
203 | *handle = (void *)dev; |
||
204 | |||
205 | return NO_ERROR; |
||
206 | } |
||
207 | |||
208 | //-------------------------------------------------------------------------------------- |
||
209 | // close the device |
||
210 | // |
||
211 | int cc32_close_95(void *handle) |
||
212 | { |
||
213 | CC32_DEVICE *dev = (CC32_DEVICE *)handle; |
||
214 | int error = NO_ERROR; |
||
215 | |||
216 | if (dev) |
||
217 | { |
||
218 | if (dev->nHandle != INVALID_HANDLE_VALUE) |
||
219 | { |
||
220 | detachWindow(dev->nHandle, dev->nModuleNumber); |
||
221 | CloseHandle(dev->nHandle); |
||
222 | } |
||
223 | |||
224 | free(dev); |
||
225 | } |
||
226 | else |
||
227 | error = ERROR_INVALID_FUNCTION; |
||
228 | |||
229 | return error; |
||
230 | } |
||
231 | |||
232 | //-------------------------------------------------------------------------------------- |
||
233 | // read a word |
||
234 | // |
||
235 | unsigned short cc32_read_word_95(void *handle, unsigned int N, unsigned int A, unsigned int F) |
||
236 | { |
||
237 | CC32_DEVICE *dev = (CC32_DEVICE *)handle; |
||
238 | |||
239 | return *pwCC32_ADR(dev->base, N, A, F); |
||
240 | } |
||
241 | |||
242 | //-------------------------------------------------------------------------------------- |
||
243 | // read a long |
||
244 | // |
||
245 | unsigned long cc32_read_long_all_95(void *handle, unsigned int N, unsigned int A, unsigned int F) |
||
246 | { |
||
247 | CC32_DEVICE *dev = (CC32_DEVICE *)handle; |
||
248 | |||
249 | return *plCC32_ADR(dev->base, N, A, F); |
||
250 | } |
||
251 | |||
252 | //-------------------------------------------------------------------------------------- |
||
253 | // read a long and get Q and X |
||
254 | // |
||
255 | unsigned long cc32_read_long_95(void *handle, unsigned int N, unsigned int A, unsigned int F, char *Q, char *X) |
||
256 | { |
||
257 | CC32_DEVICE *dev = (CC32_DEVICE *)handle; |
||
258 | unsigned long erg = *plCC32_ADR(dev->base, N, A, F); |
||
259 | |||
260 | *Q = (erg & 0x80000000) ? 1 : 0; |
||
261 | *X = (erg & 0x40000000) ? 1 : 0; |
||
262 | |||
263 | return erg & 0x00FFFFFF; |
||
264 | } |
||
265 | |||
266 | //-------------------------------------------------------------------------------------- |
||
267 | // write a word |
||
268 | // |
||
269 | void cc32_write_word_95(void *handle, unsigned int N, unsigned int A, unsigned int F, unsigned short uwData) |
||
270 | { |
||
271 | CC32_DEVICE *dev = (CC32_DEVICE *)handle; |
||
272 | |||
273 | dev->wLastAttributes = 0; |
||
274 | *pwCC32_ADR(dev->base, N, A, F) = uwData; |
||
275 | } |
||
276 | |||
277 | //-------------------------------------------------------------------------------------- |
||
278 | // write a long |
||
279 | // |
||
280 | void cc32_write_long_95(void *handle, unsigned int N, unsigned int A, unsigned int F, unsigned long ulData) |
||
281 | { |
||
282 | CC32_DEVICE *dev = (CC32_DEVICE *)handle; |
||
283 | |||
284 | dev->wLastAttributes = 0; |
||
285 | *plCC32_ADR(dev->base, N, A, F) = ulData; |
||
286 | } |
||
287 | |||
288 | //-------------------------------------------------------------------------------------- |
||
289 | // clear the PCIADA status |
||
290 | // |
||
291 | int cc32_poll_error_95(void *handle, char *nTimeout, char *nLam) |
||
292 | { |
||
293 | CC32_DEVICE *dev = (CC32_DEVICE *)handle; |
||
294 | int error; |
||
295 | |||
296 | if ((error = getStatus(dev->nHandle, dev->nModuleNumber, nTimeout, nLam))) |
||
297 | return error; |
||
298 | |||
299 | if (*nTimeout) /* clear error */ |
||
300 | { |
||
301 | if ((error = clearStatus(dev->nHandle, dev->nModuleNumber))) |
||
302 | return error; |
||
303 | } |
||
304 | |||
305 | return NO_ERROR; |
||
306 | } |
||
307 | |||
308 | //-------------------------------------------------------------------------------------- |
||
309 | // read 'len' words or 'UNTIL_NOT_Q' from a address made out of N,A,F |
||
310 | // |
||
311 | int cc32_read_word_buffer_95(void * handle, unsigned int N, unsigned int A, unsigned int F, |
||
312 | unsigned short *pwBuffer, unsigned long *pdwLen) |
||
313 | { |
||
314 | CC32_DEVICE *dev = (CC32_DEVICE *)handle; |
||
315 | register unsigned long i = 0; |
||
316 | unsigned long dwLen = *pdwLen; |
||
317 | unsigned long *pdwAddress = plCC32_ADR(dev->base, N, A, F); |
||
318 | register unsigned long dwTempBuffer; |
||
319 | |||
320 | if (dev->wLastAttributes & UNTIL_NOT_Q) |
||
321 | { |
||
322 | do |
||
323 | { |
||
324 | dwTempBuffer = *pdwAddress; |
||
325 | *pwBuffer++ = (unsigned short)dwTempBuffer; |
||
326 | } while ((dwTempBuffer & 0x80000000) && (i++ < dwLen)); |
||
327 | } |
||
328 | else |
||
329 | { |
||
330 | while (i++ < dwLen) |
||
331 | *pwBuffer++ = (unsigned short)*pdwAddress; |
||
332 | } |
||
333 | |||
334 | *pdwLen = --i; |
||
335 | return 0; |
||
336 | } |
||
337 | |||
338 | //-------------------------------------------------------------------------------------- |
||
339 | // read 'len' longs or 'UNTIL_NOT_Q' from a address made out of N,A,F, mask 24 bits out |
||
340 | // |
||
341 | int cc32_read_long_buffer_95(void * handle, unsigned int N, unsigned int A, unsigned int F, |
||
342 | unsigned long *pdwBuffer, unsigned long *pdwLen) |
||
343 | { |
||
344 | CC32_DEVICE *dev = (CC32_DEVICE *)handle; |
||
345 | register unsigned long i = 0; |
||
346 | unsigned long dwLen = *pdwLen; |
||
347 | unsigned long *pdwAddress = plCC32_ADR(dev->base, N, A, F); |
||
348 | register unsigned long dwTempBuffer; |
||
349 | |||
350 | if (dev->wLastAttributes & UNTIL_NOT_Q) |
||
351 | { |
||
352 | do |
||
353 | { |
||
354 | dwTempBuffer = *pdwAddress; |
||
355 | *pdwBuffer++ = dwTempBuffer & 0x00FFFFFF; |
||
356 | } while ((dwTempBuffer & 0x80000000) && (i++ < dwLen)); |
||
357 | } |
||
358 | else |
||
359 | { |
||
360 | while (i++ < dwLen) |
||
361 | *pdwBuffer++ = *pdwAddress & 0x00FFFFFF; |
||
362 | } |
||
363 | |||
364 | *pdwLen = --i; |
||
365 | return 0; |
||
366 | } |
||
367 | |||
368 | //-------------------------------------------------------------------------------------- |
||
369 | // read 'len' longs or 'UNTIL_NOT_Q' from a address made out of N,A,F, without interpretation |
||
370 | // |
||
371 | int cc32_read_long_all_buffer_95(void * handle, unsigned int N, unsigned int A, unsigned int F, |
||
372 | unsigned long *pdwBuffer, unsigned long *pdwLen) |
||
373 | { |
||
374 | CC32_DEVICE *dev = (CC32_DEVICE *)handle; |
||
375 | register unsigned long i = 0; |
||
376 | unsigned long dwLen = *pdwLen; |
||
377 | unsigned long *pdwAddress = plCC32_ADR(dev->base, N, A, F); |
||
378 | register unsigned long dwTempBuffer; |
||
379 | |||
380 | if (dev->wLastAttributes & UNTIL_NOT_Q) |
||
381 | { |
||
382 | do |
||
383 | { |
||
384 | dwTempBuffer = *pdwAddress; |
||
385 | *pdwBuffer++ = dwTempBuffer; |
||
386 | } while ((dwTempBuffer & 0x80000000) && (i++ < dwLen)); |
||
387 | } |
||
388 | else |
||
389 | { |
||
390 | while (i++ < dwLen) |
||
391 | *pdwBuffer++ = *pdwAddress; |
||
392 | } |
||
393 | |||
394 | *pdwLen = --i; |
||
395 | return 0; |
||
396 | } |
||
397 | |||
398 | //-------------------------------------------------------------------------------------- |
||
399 | // switch UNTIL_NOT_Q or AUTOREAD on or off |
||
400 | // |
||
401 | int cc32_access_switch_95(void *handle, unsigned short uwSwitch) |
||
402 | { |
||
403 | CC32_DEVICE *dev = (CC32_DEVICE *)handle; |
||
404 | |||
405 | dev->wLastAttributes = uwSwitch; |
||
406 | return setAccessParameter(dev->nHandle, dev->nModuleNumber, dev->wLastAttributes); |
||
407 | } |
||
408 | |||
409 | //-------------------------------------------------------------------------------------- |
||
410 | // switch interrupts on |
||
411 | // |
||
412 | int cc32_enable_interrupt_95(void *handle) |
||
413 | { |
||
414 | return ERROR_INVALID_FUNCTION; |
||
415 | } |
||
416 | |||
417 | //-------------------------------------------------------------------------------------- |
||
418 | // switch interrupts off |
||
419 | // |
||
420 | int cc32_disable_interrupt_95(void *handle) |
||
421 | { |
||
422 | return ERROR_INVALID_FUNCTION; |
||
423 | } |
||
424 | |||
425 | //-------------------------------------------------------------------------------------- |
||
426 | // wait blocking for the next interrupt |
||
427 | // |
||
428 | int cc32_get_interrupt_95(void *handle, unsigned long *dwStatus) |
||
429 | { |
||
430 | return ERROR_INVALID_FUNCTION; |
||
431 | } |