Subversion Repositories f9daq

Rev

Rev 11 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
9 f9daq 1
//-------------------------------------------------------------------------------------------
2
// pcivme_ni.c - shared library for ARW pcivme interface (libpcivme.so)
3
//
4
// Copyright (C) 2002-2004 ARW Elektronik Germany
5
//
6
// this source code is published under LGPL (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
// $Log: pcivme_ni.c,v $
15
// Revision 1.8  2004/08/13 19:23:45  klaus
16
// conversion to kernel-version 2.6, released version 3.0
17
//
18
// Revision 1.7  2002/10/20 18:07:18  klaus
19
// changed error handling
20
//
21
// Revision 1.6  2002/10/18 21:56:28  klaus
22
// completed functional features, untested
23
//
24
// Revision 1.5  2002/10/18 21:56:28  klaus
25
// completed functional features, untested
26
//
27
// Revision 1.4  2002/10/17 21:16:03  klaus
28
// filled function bodies
29
//
30
// Revision 1.3  2002/10/17 21:16:03  klaus
31
// filled function bodies
32
//
33
// Revision 1.2  2002/10/17 19:05:03  klaus
34
// VME access is working through test to lib to driver
35
//
36
// Revision 1.1  2002/10/12 22:04:30  klaus
37
// first work done
38
//
39
 
40
//-------------------------------------------------------------------------------------------
41
// INCLUDES
42
//
43
#include <stdio.h>
44
#include <stdlib.h>
45
#include <string.h>
46
#include <unistd.h>
47
#include <linux/types.h>
48
#include <sys/ioctl.h>
49
#include <errno.h>
50
#include <ctype.h>
51
#include <sys/types.h>
52
#include <sys/stat.h>
53
#include <fcntl.h>
54
 
55
#include <../driver/pcivme.h>
56
#include <../driver/vic.h>
57
#include <pcivme_ni.h>
58
 
59
//-------------------------------------------------------------------------------------------
60
// DEFINES
61
//
62
#define LOCAL_STRING_LEN 40
63
 
64
//-------------------------------------------------------------------------------------------
65
// TYPEDEFS
66
//
67
 
68
// storage for path specific data
69
typedef struct
70
{
71
    int nFileNo;              // file number to f
72
    __u8 cAddressModifier;    // associated VME address modifier
73
    __u8 cAccessWidth;        // current access width
74
    int  nLastError;          // != 0 if a previous error occurred
75
} VMEMM_DEVICE;
76
 
77
//-------------------------------------------------------------------------------------------
78
// FUNCTIONS
79
//
80
 
81
// construct a device file name
82
static char *szDeviceName(const char *cszBaseName, int nVMEMM)
83
{
84
  static char path[LOCAL_STRING_LEN];
85
  int i = LOCAL_STRING_LEN - 1;
86
 
87
  path[0] = 0;
88
 
89
  memset(path, 0, LOCAL_STRING_LEN);
90
 
91
  if (strlen(cszBaseName) >= (LOCAL_STRING_LEN - 3))
92
      return "";
93
 
94
  if (nVMEMM > 15)
95
      return "";
96
 
97
  strncpy(path, cszBaseName, LOCAL_STRING_LEN - 3);
98
 
99
  while ((i--) && (path[i] != '_'));  // search for '_'
100
 
101
  if (i)
102
  {
103
      i++; // go after '_'
104
      if (nVMEMM >= 10)
105
      {
106
          path[i] = '1';
107
          nVMEMM -= 10;
108
          i++;
109
      }
110
      path[i] = '0' + nVMEMM;
111
      i++;
112
      path[i] = 0; // trailing 0
113
  }
114
  else
115
      return "";
116
 
117
  return path;
118
}
119
 
120
static int initHardware(VMEMM_DEVICE *dev)
121
{
122
    PCIVME_INIT_COMMAND init;
123
 
124
    init.sVie[0].bDestination = STOP;
125
    init.sVie[0].bAccessType  =
126
    init.sVie[0].dwValue      =
127
    init.sVie[0].wOffset      = 0;
128
 
129
    if (ioctl(dev->nFileNo, PCIVME_INIT_HARDWARE, &init) < 0)
130
    {
131
        dev->nLastError = errno;
132
        return errno;
133
    }
134
 
135
    return 0;
136
}
137
 
138
static int deInitHardware(VMEMM_DEVICE *dev)
139
{
140
    PCIVME_INIT_COMMAND deinit;
141
 
142
    deinit.sVie[0].bDestination = STOP;
143
    deinit.sVie[0].bAccessType  =
144
    deinit.sVie[0].dwValue      =
145
    deinit.sVie[0].wOffset      = 0;
146
 
147
    if (ioctl(dev->nFileNo, PCIVME_DEINIT_HARDWARE, &deinit) < 0)
148
    {
149
        dev->nLastError = errno;
150
        return errno;
151
    }
152
 
153
    return 0;
154
}
155
 
156
int VMEopen(const char *cszDeviceName, unsigned char ubAddressModifier, int *pnHandle)
157
{
158
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)NULL;
159
    int error;
160
 
161
    *pnHandle = 0;
162
 
163
    dev = (VMEMM_DEVICE *)malloc(sizeof(*dev));
164
    if (!dev)
165
        return errno;
166
 
167
    dev->nFileNo = open(cszDeviceName, O_RDWR);
168
 
169
    if (dev->nFileNo == -1)
170
    {
171
        error = errno;
172
        free(dev);
173
        return error;
174
    }
175
 
176
    dev->cAddressModifier = ubAddressModifier;
177
    *pnHandle             = (int)dev;
178
 
179
    error = initHardware(dev);
180
    if (error)
181
        return error;
182
 
183
    dev->nLastError = 0;
184
 
185
    return setAccessProperties(*pnHandle, dev->cAddressModifier, BYTE_ACCESS); // set access properties to default
186
}
187
 
188
int VMEinit(const char *cszDeviceName, unsigned short nVMEMM, unsigned char ubAddressModifier, int *pnHandle)
189
{
190
    char *szLocalDeviceName = szDeviceName(cszDeviceName, nVMEMM);
191
 
192
    return VMEopen(szLocalDeviceName, ubAddressModifier, pnHandle);
193
}
194
 
195
int setAccessProperties(int nHandle, unsigned char bModifier, unsigned char bAccessType)
196
{
197
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
198
 
199
    PCIVME_ACCESS_COMMAND access_command;
200
 
201
    access_command.bAccessType =
202
    access_command.bIncrement  = bAccessType;  // increment and accessType are the same
203
    access_command.bModifier   = bModifier;
204
 
205
    if (ioctl(dev->nFileNo, PCIVME_SET_ACCESS_PARA, &access_command) < 0)
206
    {
207
        dev->nLastError = errno;
208
        return errno;
209
    }
210
 
211
    dev->cAddressModifier = bModifier;
212
    dev->cAccessWidth     = bAccessType;
213
 
214
    return 0;
215
}
216
 
217
int VMEread(int nHandle, unsigned long ulAddress, unsigned char ubAccessWidth, unsigned long ulElementCount, void *pvBuffer)
218
{
219
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
220
    size_t count      = (size_t)(ulElementCount * ubAccessWidth);
221
    ssize_t result;
222
    int error;
223
 
224
    if (dev->cAccessWidth != ubAccessWidth)
225
    {
226
        if ((error = setAccessProperties(nHandle, dev->cAddressModifier, ubAccessWidth)))
227
            return error;
228
    }
229
 
230
    if (lseek(dev->nFileNo, ulAddress, SEEK_SET) < 0)
231
        return errno;
232
 
233
    result = read(dev->nFileNo, pvBuffer, count);
234
 
235
    if (result != count)
236
    {
237
        if (result < 0)
238
        {
239
            dev->nLastError = errno;
240
            return errno;
241
        }
242
        else
243
            return EFAULT;
244
    }
245
 
246
    return 0;
247
}
248
 
249
int VMEwrite(int nHandle, unsigned long ulAddress, unsigned char ubAccessWidth, unsigned long ulElementCount, void *pvBuffer)
250
{
251
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
252
    size_t count      = (size_t)(ulElementCount * ubAccessWidth);
253
    ssize_t result;
254
    int error;
255
 
256
    if (dev->cAccessWidth != ubAccessWidth)
257
    {
258
        if ((error = setAccessProperties(nHandle, dev->cAddressModifier, ubAccessWidth)))
259
            return error;
260
    }
261
 
262
    if (lseek(dev->nFileNo, ulAddress, SEEK_SET) < 0)
263
        return errno;
264
 
265
    result = write(dev->nFileNo, pvBuffer, count);
266
 
267
    if (result != count)
268
    {
269
        if (result < 0)
270
        {
271
            dev->nLastError = errno;
272
            return errno;
273
        }
274
        else
275
            return EFAULT;
276
    }
277
 
278
    return 0;
279
}
280
 
281
int VMEaccessVIC(int nHandle, unsigned char ubAccessMode, unsigned short uwAddress, unsigned char *ubContent)
282
{
283
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
284
    PCIVME_VIC68A_ACTION vic68a_action;
285
 
286
    vic68a_action.bAccessMode      = ubAccessMode;
287
    vic68a_action.bContent         = *ubContent;  
288
    vic68a_action.wRegisterAddress = uwAddress;
289
 
290
    if (ioctl(dev->nFileNo, PCIVME_ACCESS_VIC68A, &vic68a_action) < 0)
291
    {
292
        dev->nLastError = errno;
293
        return errno;
294
    }
295
 
296
    *ubContent = vic68a_action.bContent;
297
 
298
    return 0;
299
}
300
 
301
int VMEreset(int nHandle)
302
{
303
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
304
    PCIVME_RESET_COMMAND reset_command;
305
    int i = 10;
306
 
307
    reset_command.bCommand = GLOBAL_RESET_CMD;
308
    reset_command.bResult  = 0xff;  
309
 
310
    if (ioctl(dev->nFileNo, PCIVME_RESET, &reset_command) < 0)
311
    {
312
        dev->nLastError = errno;
313
        return errno;
314
    }
315
 
316
    do
317
    {
318
        usleep(100);
319
        reset_command.bCommand = POLL_RESET_CMD;
320
        reset_command.bResult  = 0xff;  
321
 
322
        if (ioctl(dev->nFileNo, PCIVME_RESET, &reset_command) < 0)
323
        {
324
            dev->nLastError = errno;
325
            return errno;
326
        }
327
    } while ((reset_command.bResult) && (i--));
328
 
329
    if (!i)
330
        return ETIME;
331
 
332
    dev->nLastError = 0;
333
 
334
    return 0;
335
}
336
 
337
int VMETAS(int nHandle, unsigned long ulAddress, unsigned char *ubResult)
338
{
339
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
340
    PCIVME_TAS_STRUCT tas;
341
 
342
    tas.bContent  = *ubResult;
343
    tas.bModifier = dev->cAddressModifier;  
344
    tas.dwAddress = ulAddress;
345
 
346
    if (ioctl(dev->nFileNo, PCIVME_TAS, &tas) < 0)
347
    {
348
        dev->nLastError = errno;
349
        return errno;
350
    }
351
 
352
    *ubResult = tas.bContent;
353
 
354
    return 0;
355
}
356
 
357
int VMEinterrupt(int nHandle, unsigned char *ubVector)
358
{
359
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
360
        PCIVME_VECTOR_LEVEL ubLocalVector;
361
 
362
    if (ioctl(dev->nFileNo, PCIVME_READ_VECTOR_POLL, &ubLocalVector) < 0)
363
    {
364
        dev->nLastError = errno;
365
        return errno;
366
    }
367
 
368
    *ubVector = (__u8)ubLocalVector.dwStatusID;
369
 
370
    return 0;
371
}
372
 
373
int VMEsysfailGet(int nHandle, BOOLEAN *bResult)
374
{
375
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
376
        PCIVME_VIC68A_ACTION sAction;    // structure to access vic chip
377
 
378
        sAction.wRegisterAddress = EGICR;
379
        sAction.bAccessMode      = VIC68A_READ;
380
        sAction.bContent         = 0;
381
 
382
    if (ioctl(dev->nFileNo, PCIVME_ACCESS_VIC68A, &sAction) < 0)
383
    {
384
        dev->nLastError = errno;
385
        return errno;
386
    }
387
 
388
        *bResult = (sAction.bContent & 0x08) ? FALSE : TRUE;
389
 
390
    return 0;
391
}
392
 
393
int VMEsysfailSet(int nHandle, BOOLEAN bForce)
394
{
395
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
396
        PCIVME_VIC68A_ACTION sAction;    // structure to access vic chip
397
 
398
        sAction.wRegisterAddress = ICR7;
399
        sAction.bAccessMode      = (bForce == TRUE) ? VIC68A_AND : VIC68A_OR;
400
        sAction.bContent         = (bForce == TRUE) ? 0x3F               : 0x80;
401
 
402
    if (ioctl(dev->nFileNo, PCIVME_ACCESS_VIC68A, &sAction) < 0)
403
    {
404
        dev->nLastError = errno;
405
        return errno;
406
    }
407
 
408
    return 0;
409
}
410
 
411
int VMEerror(int nHandle)
412
{
413
    __u8 ubVector;
414
 
415
    VMEinterrupt(nHandle, &ubVector);
416
 
417
    if (ubVector == 7)
418
        return EFAULT;  // it's a bus error
419
    else
420
        return 0;
421
}
422
 
423
int VMEclose(int nHandle)
424
{
425
    int error = 0;
426
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
427
 
428
    if (dev != (VMEMM_DEVICE *)NULL)
429
    {
430
        deInitHardware(dev);
431
 
432
        if (dev->nFileNo != -1)
433
            close(dev->nFileNo);
434
        else
435
            error = -EINVAL;
436
 
437
        free(dev);
438
    }
439
 
440
    return error;
441
}
442
 
443
int VMEcontrolInterrupt(int nHandle, BOOLEAN *bEnable)
444
{
445
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
446
        PCIVME_IRQ_CONTROL  control;
447
 
448
    control.bEnable = *bEnable;
449
 
450
    if (ioctl(dev->nFileNo, PCIVME_CONTROL_INTERRUPTS, &control) < 0)
451
    {
452
        dev->nLastError = errno;
453
        return errno;
454
    }
455
 
456
    // status of interrupt enable before set
457
    *bEnable = control.bEnable;
458
 
459
    return 0;
460
}
461
 
462
int GetLastError(int nHandle)
463
{
464
    VMEMM_DEVICE *dev  = (VMEMM_DEVICE *)nHandle;
465
    int nLocalError;
466
 
467
    nLocalError = dev->nLastError;
468
    dev->nLastError = 0;
469
 
470
    return nLocalError;
471
}
472
 
473