Subversion Repositories f9daq

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
21 f9daq 1
/*
2
   cc32lib_NT.c -- a simple access library for the PCICC32 PCI to CAMAC Interface
3
                   from ARW Elektronik - the WINNT parts
4
 
5
   (c) 2000 ARW Elektronik
6
 
7
   this source code is published under GPL (Open Source). You can use, redistrubute and
8
   modify it unless this header   is not modified or deleted. No warranty is given that
9
   this software will work like expected.
10
   This product is not authorized for use as critical component in life support systems
11
   wihout the express written approval of ARW Elektronik Germany.
12
 
13
   Please announce changes and hints to ARW Elektronik
14
 
15
   derived from the previous WIN95 library                              AR   30.07.2000
16
   added buffer, UNTIL_NOT_Q and AUTOREAD functionality                 AR   17.03.2001
17
*/
18
 
19
/*--- INCLUDES -----------------------------------------------------------------------------------*/
20
#include <windows.h>
21
#include <stdio.h>
22
#include <stdlib.h>
23
#include <string.h>
24
#include <errno.h>
25
#include <winioctl.h>
26
 
27
#include "pcicc32.h"  /* PCI common ioctl commands and structures between driver and library  */
28
#include "libcc32_NT.h"          /* shared header bewteen applictaion and library                        */
29
 
30
/*--- DEFINES ------------------------------------------------------------------------------------*/
31
#define DEFDEVICENAME "\\\\.\\PCICC32:\\CC32_xx"
32
 
33
/*--- EXTERNALS ----------------------------------------------------------------------------------*/
34
 
35
/*--- TYPEDEFS -----------------------------------------------------------------------------------*/
36
typedef struct
37
{
38
        HANDLE nHandle;                     /* the handle of this device */
39
        int    nModuleNumber;               /* the number of the module */
40
        unsigned short wLastAccessWidth;    /* the last parametrized data access width */
41
        unsigned short wLastAttributes;     /* the last Attributes to this channel */
42
        unsigned long  dwLastAccessAddress; /* the last access address to speed up */
43
} CC32_DEVICE_NT;
44
 
45
/*--- FUNCTIONS -----------------------------------------------------------------------*/
46
 
47
//--------------------------------------------------------------------------------------
48
// get the PCIADA status from the PCI side of the interface
49
//
50
static int getStatus(HANDLE nHandle, DWORD dwInterface, char *nTimeout, char *nLAM)
51
{
52
        PCICC32_STATUS status;
53
        DWORD DIOC_count;             // count of returned bytes of DeviceIoControl
54
        DWORD result;
55
 
56
        if (nHandle == (HANDLE)-1) return -1;
57
 
58
        *nTimeout = *nLAM = 0;
59
 
60
        // attach a window into the CC32 space ----------------
61
        result = DeviceIoControl(nHandle, PCICC32_GET_STATUS,
62
                                                &dwInterface, sizeof(dwInterface),
63
                                                &status,      sizeof(status), &DIOC_count, NULL);
64
 
65
    if (!result)
66
                return GetLastError();
67
        else
68
        {
69
                *nTimeout = (char)status.bTimeout;
70
                *nLAM     = (char)status.bInterrupt;
71
 
72
                return 0;
73
        }
74
}
75
 
76
//--------------------------------------------------------------------------------------
77
// clear the PCIADA status
78
//
79
static int clearStatus(HANDLE nHandle, DWORD dwInterface)
80
{
81
        DWORD DIOC_count;             // count of returned bytes of DeviceIoControl
82
        DWORD result;
83
 
84
        if (nHandle == (HANDLE)-1) return -1;
85
 
86
        // attach a window into the CC32 space ----------------
87
        result = DeviceIoControl(nHandle, PCICC32_CLEAR_STATUS,
88
                                                &dwInterface, sizeof(dwInterface),
89
                                                NULL,      0, &DIOC_count, NULL);
90
 
91
    if (!result)
92
                return GetLastError();
93
        else
94
                return 0;
95
}
96
 
97
//-------------------------------------------------------------------------
98
// set the future access parameters - override the current
99
//
100
static int setAccessParameter(HANDLE hHandle, USHORT wAccessType, USHORT wBlockTransfer)
101
{
102
        DWORD result;
103
        DWORD   DIOC_count;     // count of returned bytes of DeviceIoControl
104
    PCICC32_ACCESS_COMMAND access_parameter;
105
 
106
        access_parameter.wAccessType            = wAccessType;
107
        access_parameter.wBlockTransfer         = wBlockTransfer;
108
 
109
        result = DeviceIoControl(hHandle, PCICC32_SET_ACCESS_PARA,
110
                                        &access_parameter, (DWORD)sizeof(access_parameter), NULL,
111
                                                   0, &DIOC_count, NULL);      
112
        if (!result)
113
                return GetLastError();
114
        else
115
                return 0;
116
}
117
 
118
//-------------------------------------------------------------------------
119
// create a DeviceName out of cszDeviceName and nIfcNum
120
//
121
static char *DeviceName(int nIfcNum)
122
{
123
        static char buffer[255];
124
        char *ptr = buffer;
125
 
126
        strncpy(buffer, DEFDEVICENAME, strlen(DEFDEVICENAME));
127
 
128
        while (*ptr) ptr++;
129
 
130
        do
131
        {
132
                ptr--;
133
        } while (*ptr != '_');  // step back until '-'
134
 
135
        ptr++;
136
 
137
        if (nIfcNum >= 10)      // add the interface number
138
        {
139
                *ptr++   = '1';
140
                nIfcNum -= 10;
141
        }
142
 
143
        *ptr++ = '0' + nIfcNum;
144
        *ptr = 0;
145
 
146
        // a little help for the users
147
    return buffer;
148
}
149
 
150
//-------------------------------------------------------------------------
151
// open my path to the interface
152
//
153
static HANDLE openPath(char *name)
154
{
155
    return (HANDLE)CreateFile(
156
                     name,
157
                     GENERIC_READ | GENERIC_WRITE,
158
                     0,
159
                     NULL,
160
                     OPEN_EXISTING,
161
                     FILE_ATTRIBUTE_NORMAL,
162
                     NULL
163
                     );
164
}
165
 
166
//--------------------------------------------------------------------------------------
167
// open the device
168
//
169
int cc32_open_NT(char *cszPath, int nModuleNumber, void **handle)
170
{
171
        CC32_DEVICE_NT *dev;
172
        int error = 0;
173
 
174
        *handle = (void *)0;
175
 
176
        dev = (CC32_DEVICE_NT *)malloc(sizeof(CC32_DEVICE_NT));
177
        if (!dev) return errno;
178
 
179
        dev->nModuleNumber = nModuleNumber;
180
        dev->nHandle = INVALID_HANDLE_VALUE;
181
        dev->wLastAccessWidth    = 0xffff;         /* invalidate for future use */
182
 
183
        // start the driver ------------------
184
        dev->nHandle = openPath(DeviceName(nModuleNumber));
185
 
186
        if (dev->nHandle == INVALID_HANDLE_VALUE)
187
                error = GetLastError();
188
        else
189
        {
190
                SetFilePointer(dev->nHandle, 0, NULL, FILE_BEGIN);
191
                dev->dwLastAccessAddress = 0;
192
                dev->wLastAttributes = 0;
193
                dev->wLastAccessWidth = 0;
194
        }
195
 
196
        if (error)
197
        {
198
                free(dev);
199
                return error;
200
        }
201
 
202
        *handle = (void *)dev;
203
 
204
        return NO_ERROR;
205
}
206
 
207
//--------------------------------------------------------------------------------------
208
// close the device
209
//
210
int cc32_close_NT(void *handle)
211
{
212
        CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
213
        int error = NO_ERROR;
214
 
215
        if (dev)
216
        {
217
                if (dev->nHandle != INVALID_HANDLE_VALUE)
218
                        CloseHandle(dev->nHandle);
219
 
220
                free(dev);
221
        }
222
        else
223
                error = ERROR_INVALID_FUNCTION;
224
 
225
        return error;
226
}
227
 
228
//--------------------------------------------------------------------------------------
229
// read a word
230
//
231
unsigned short cc32_read_word_NT(void *handle, unsigned int N, unsigned int A, unsigned int F)
232
{
233
        register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
234
        unsigned long  adr = NAF(N,A,F);
235
        unsigned short buffer;
236
        unsigned long  bytesRead;
237
 
238
        // cache the data access width
239
        if (dev->wLastAccessWidth != WORD_ACCESS)
240
        {
241
                dev->wLastAccessWidth = WORD_ACCESS;
242
                setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);
243
        }
244
 
245
        // cache the address
246
        if (dev->dwLastAccessAddress != adr)
247
        {
248
          SetFilePointer(dev->nHandle, adr, NULL, FILE_BEGIN);
249
          dev->dwLastAccessAddress = adr;
250
        }
251
 
252
        ReadFile(dev->nHandle, &buffer, WORD_ACCESS, &bytesRead, NULL);
253
 
254
        return buffer;
255
}
256
 
257
//--------------------------------------------------------------------------------------
258
// read a long
259
//
260
unsigned long cc32_read_long_all_NT(void *handle, unsigned int N, unsigned int A, unsigned int F)
261
{
262
        register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
263
        unsigned long  adr = NAF(N,A,F);
264
        unsigned long  buffer;
265
        unsigned long  bytesRead;
266
 
267
        // cache the data access width
268
        if (dev->wLastAccessWidth != LONG_ACCESS)
269
        {
270
                dev->wLastAccessWidth = LONG_ACCESS;
271
                setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);
272
        }
273
 
274
        // cache the address
275
        if (dev->dwLastAccessAddress != adr)
276
        {
277
          SetFilePointer(dev->nHandle, adr, NULL, FILE_BEGIN);
278
          dev->dwLastAccessAddress = adr;
279
        }
280
 
281
        ReadFile(dev->nHandle, &buffer, LONG_ACCESS, &bytesRead, NULL);
282
 
283
        return buffer;
284
}
285
 
286
//--------------------------------------------------------------------------------------
287
// read a long and get Q and X
288
//
289
unsigned long cc32_read_long_NT(void *handle, unsigned int N, unsigned int A, unsigned int F, char *Q, char *X)
290
{
291
        unsigned long erg = cc32_read_long_all_NT(handle, N, A, F);
292
 
293
        *Q = (erg & 0x80000000) ? 1 : 0;
294
        *X = (erg & 0x40000000) ? 1 : 0;
295
 
296
        return erg & 0x00FFFFFF;
297
}
298
 
299
//--------------------------------------------------------------------------------------
300
// write a word
301
//
302
void cc32_write_word_NT(void *handle, unsigned int N, unsigned int A, unsigned int F, unsigned short uwData)
303
{
304
        register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
305
        unsigned long adr = NAF(N,A,F);
306
        DWORD bytesWritten;
307
 
308
        // cache the data access width
309
        if (dev->wLastAccessWidth != WORD_ACCESS)
310
        {
311
                dev->wLastAccessWidth = WORD_ACCESS;
312
                setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);
313
        }
314
 
315
        // cache the address
316
        if (dev->dwLastAccessAddress != adr)
317
        {
318
          SetFilePointer(dev->nHandle, adr, NULL, FILE_BEGIN);
319
          dev->dwLastAccessAddress = adr;
320
        }
321
 
322
        WriteFile(dev->nHandle, &uwData, WORD_ACCESS, &bytesWritten, NULL);
323
}
324
 
325
//--------------------------------------------------------------------------------------
326
// write a long
327
//
328
void cc32_write_long_NT(void *handle, unsigned int N, unsigned int A, unsigned int F, unsigned long ulData)
329
{
330
        register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
331
        unsigned long adr = NAF(N,A,F);
332
        DWORD bytesWritten;
333
 
334
        // cache the data access width
335
        if (dev->wLastAccessWidth != LONG_ACCESS)
336
        {
337
                dev->wLastAccessWidth = LONG_ACCESS;
338
                setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);
339
        }
340
 
341
        // cache the address
342
        if (dev->dwLastAccessAddress != adr)
343
        {
344
          SetFilePointer(dev->nHandle, adr, NULL, FILE_BEGIN);
345
          dev->dwLastAccessAddress = adr;
346
        }
347
 
348
        WriteFile(dev->nHandle, &ulData, LONG_ACCESS, &bytesWritten, NULL);
349
}
350
 
351
//--------------------------------------------------------------------------------------
352
// clear the PCIADA status
353
//
354
int cc32_poll_error_NT(void *handle, char *nTimeout, char *nLam)
355
{
356
        CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
357
        int error;
358
 
359
    if ((error = getStatus(dev->nHandle, dev->nModuleNumber, nTimeout, nLam)))
360
                return error;
361
 
362
        if (*nTimeout)  /* clear error */
363
        {
364
                if ((error = clearStatus(dev->nHandle, dev->nModuleNumber)))
365
                        return error;  
366
        }
367
 
368
        return NO_ERROR;
369
}
370
 
371
//--------------------------------------------------------------------------------------
372
// read 'len' words or 'UNTIL_NOT_Q' from a address made out of N,A,F 
373
//
374
int cc32_read_word_buffer_NT(void * handle, unsigned int N, unsigned int A, unsigned int F,
375
                                                                                                                                unsigned short *pwBuffer, unsigned long *pdwLen)
376
{
377
        register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
378
        unsigned long  adr = NAF(N,A,F);
379
        unsigned long dwLen;
380
 
381
        // cache the data access width
382
        if (dev->wLastAccessWidth != WORD_ACCESS)
383
        {
384
                dev->wLastAccessWidth = WORD_ACCESS;
385
                setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);
386
        }
387
 
388
        // cache the address
389
        if (dev->dwLastAccessAddress != adr)
390
        {
391
          SetFilePointer(dev->nHandle, adr, NULL, FILE_BEGIN);
392
          dev->dwLastAccessAddress = adr;
393
        }
394
 
395
        *pdwLen <<= 1;  // make bytes
396
        dwLen = *pdwLen;
397
        if (!ReadFile(dev->nHandle, pwBuffer, dwLen, pdwLen, NULL))
398
                return GetLastError();
399
 
400
        *pdwLen >>= 1;  // make words
401
        return 0;
402
}
403
 
404
//--------------------------------------------------------------------------------------
405
// read 'len' longs or 'UNTIL_NOT_Q' from a address made out of N,A,F, mask 24 bits out
406
//
407
int cc32_read_long_buffer_NT(void * handle, unsigned int N, unsigned int A, unsigned int F,
408
                                                                                                                                unsigned long *pdwBuffer, unsigned long *pdwLen)
409
{
410
        register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
411
        unsigned long  adr = NAF(N,A,F);
412
        unsigned long *pdwPtr = pdwBuffer;
413
        unsigned long *pdwEnd = pdwBuffer;
414
        unsigned long dwLen;
415
 
416
        // cache the data access width
417
        if (dev->wLastAccessWidth != LONG_ACCESS)
418
        {
419
                dev->wLastAccessWidth = LONG_ACCESS;
420
                setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);
421
        }
422
 
423
        // cache the address
424
        if (dev->dwLastAccessAddress != adr)
425
        {
426
          SetFilePointer(dev->nHandle, adr, NULL, FILE_BEGIN);
427
          dev->dwLastAccessAddress = adr;
428
        }
429
 
430
        *pdwLen <<= 2;   // make bytes
431
        dwLen = *pdwLen;
432
        if (!ReadFile(dev->nHandle, pdwBuffer, dwLen, pdwLen, NULL))
433
                return GetLastError();
434
 
435
        pdwEnd += *pdwLen;
436
        while (pdwEnd < pdwPtr)
437
                *pdwPtr++ &= 0x00FFFFFF;  // mask Q and X bits 
438
 
439
        *pdwLen >>= 2;   // make longs
440
        return 0;
441
}
442
 
443
//--------------------------------------------------------------------------------------
444
// read 'len' longs or 'UNTIL_NOT_Q' from a address made out of N,A,F, without interpretation 
445
//
446
int cc32_read_long_all_buffer_NT(void * handle, unsigned int N, unsigned int A, unsigned int F,
447
                                                                                                                                unsigned long *pdwBuffer, unsigned long *pdwLen)
448
{
449
        register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
450
        unsigned long  adr = NAF(N,A,F);
451
        unsigned long dwLen;
452
 
453
        // cache the data access width
454
        if (dev->wLastAccessWidth != LONG_ACCESS)
455
        {
456
                dev->wLastAccessWidth = LONG_ACCESS;
457
                setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);
458
        }
459
 
460
        // cache the address
461
        if (dev->dwLastAccessAddress != adr)
462
        {
463
          SetFilePointer(dev->nHandle, adr, NULL, FILE_BEGIN);
464
          dev->dwLastAccessAddress = adr;
465
        }
466
 
467
        *pdwLen <<= 2;   // make bytes
468
        dwLen = *pdwLen;
469
        if (!ReadFile(dev->nHandle, pdwBuffer, dwLen, pdwLen, NULL))
470
                return GetLastError();
471
 
472
        *pdwLen >>= 2;   // make longs
473
        return 0;
474
}
475
 
476
//--------------------------------------------------------------------------------------
477
// switch UNTIL_NOT_Q or AUTOREAD on or off 
478
//
479
int cc32_access_switch_NT(void *handle, unsigned short uwSwitch)
480
{
481
        register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
482
 
483
        dev->wLastAttributes  = uwSwitch;
484
        return setAccessParameter(dev->nHandle, dev->wLastAccessWidth, dev->wLastAttributes);
485
}
486
 
487
//--------------------------------------------------------------------------------------
488
// switch interrupts on
489
//
490
int cc32_enable_interrupt_NT(void *handle)
491
{
492
        register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
493
        DWORD result;
494
        DWORD   DIOC_count;     // count of returned bytes of DeviceIoControl
495
        PCICC32_IRQ_CONTROL irqCntrl;
496
 
497
        irqCntrl.dwInterface = 0;  // don't bother at WINNT
498
        irqCntrl.wEnable     = 1;  // enable it
499
 
500
        result = DeviceIoControl(dev->nHandle, PCICC32_CONTROL_INTERRUPTS,
501
                                        &irqCntrl, sizeof(irqCntrl), NULL, 0, &DIOC_count, NULL);        
502
 
503
        if (!result)
504
                return GetLastError();
505
        else
506
                return NO_ERROR;
507
}
508
 
509
//--------------------------------------------------------------------------------------
510
// switch interrupts off
511
//
512
int cc32_disable_interrupt_NT(void *handle)
513
{
514
        register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
515
        DWORD result;
516
        DWORD   DIOC_count;     // count of returned bytes of DeviceIoControl
517
        PCICC32_IRQ_CONTROL irqCntrl;
518
 
519
        irqCntrl.dwInterface = 0;  // don't bother at WINNT
520
        irqCntrl.wEnable     = 0;  // disable it
521
 
522
        result = DeviceIoControl(dev->nHandle, PCICC32_CONTROL_INTERRUPTS,
523
                                        &irqCntrl, sizeof(irqCntrl), NULL, 0, &DIOC_count, NULL);        
524
 
525
        if (!result)
526
                return GetLastError();
527
        else
528
                return NO_ERROR;
529
}
530
 
531
//--------------------------------------------------------------------------------------
532
// wait blocking for the next interrupt
533
//
534
int cc32_get_interrupt_NT(void *handle, unsigned long *dwStatus)
535
{
536
        register CC32_DEVICE_NT *dev = (CC32_DEVICE_NT *)handle;
537
        DWORD result;
538
        DWORD   DIOC_count;     // count of returned bytes of DeviceIoControl
539
        PCICC32_IRQ_RESPONSE response;
540
        int nError;
541
        OVERLAPPED sOverlapped;
542
 
543
        sOverlapped.hEvent    = NULL;
544
        result = DeviceIoControl(dev->nHandle, PCICC32_INSTALL_IRQ_BLOCK,
545
                                        NULL, 0, &response, sizeof(response), &DIOC_count, NULL);
546
 
547
        *dwStatus = response.dwInterruptFlags;
548
 
549
        if (!result)
550
        {
551
                nError = GetLastError();
552
 
553
                // a real error 
554
                if ((nError != ERROR_IO_PENDING) && (nError != ERROR_SUCCESS))
555
                        return nError;
556
 
557
                // my IO is pending - wait for it
558
                if (nError == ERROR_IO_PENDING)
559
                {
560
                        result = GetOverlappedResult(dev->nHandle, &sOverlapped, &DIOC_count, TRUE);
561
 
562
                        *dwStatus = response.dwInterruptFlags;
563
 
564
                        if (!result)
565
                        {
566
                                nError = GetLastError();   // if it was cancelled
567
                                if (nError == ERROR_OPERATION_ABORTED)
568
                                        return NO_ERROR;       // accept it as 'normal'
569
                                else
570
                                        return nError;
571
                        }
572
                }
573
        }
574
 
575
        return NO_ERROR;
576
}
577
 
578