Subversion Repositories f9daq

Rev

Rev 13 | Go to most recent revision | Details | Compare with Previous | 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;
11 f9daq 132
        printf("initHardware:err=%d %s\n" , errno,  strerror(errno) );
9 f9daq 133
        return errno;
134
    }
135
 
136
    return 0;
137
}
138
 
139
static int deInitHardware(VMEMM_DEVICE *dev)
140
{
141
    PCIVME_INIT_COMMAND deinit;
142
 
143
    deinit.sVie[0].bDestination = STOP;
144
    deinit.sVie[0].bAccessType  =
145
    deinit.sVie[0].dwValue      =
146
    deinit.sVie[0].wOffset      = 0;
147
 
148
    if (ioctl(dev->nFileNo, PCIVME_DEINIT_HARDWARE, &deinit) < 0)
149
    {
150
        dev->nLastError = errno;
11 f9daq 151
        printf("deInitHardware:err=%d %s\n" , errno,  strerror(errno) );
9 f9daq 152
        return errno;
153
    }
154
 
155
    return 0;
156
}
157
 
158
int VMEopen(const char *cszDeviceName, unsigned char ubAddressModifier, int *pnHandle)
159
{
160
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)NULL;
161
    int error;
162
 
163
    *pnHandle = 0;
164
 
165
    dev = (VMEMM_DEVICE *)malloc(sizeof(*dev));
166
    if (!dev)
167
        return errno;
168
 
169
    dev->nFileNo = open(cszDeviceName, O_RDWR);
14 f9daq 170
    //printf("VMEopen: dev->nFileNo %d size=%d %s\n" , dev->nFileNo,sizeof(*dev),  cszDeviceName );
9 f9daq 171
    if (dev->nFileNo == -1)
172
    {
173
        error = errno;
11 f9daq 174
        printf("VMEopen:err=%d %s\n" , error,  strerror(error) );
9 f9daq 175
        free(dev);
176
        return error;
177
    }
178
 
179
    dev->cAddressModifier = ubAddressModifier;
180
    *pnHandle             = (int)dev;
181
 
182
    error = initHardware(dev);
11 f9daq 183
    if (error)
9 f9daq 184
        return error;
185
 
186
    dev->nLastError = 0;
187
 
188
    return setAccessProperties(*pnHandle, dev->cAddressModifier, BYTE_ACCESS); // set access properties to default
189
}
190
 
191
int VMEinit(const char *cszDeviceName, unsigned short nVMEMM, unsigned char ubAddressModifier, int *pnHandle)
192
{
193
    char *szLocalDeviceName = szDeviceName(cszDeviceName, nVMEMM);
194
 
195
    return VMEopen(szLocalDeviceName, ubAddressModifier, pnHandle);
196
}
197
 
198
int setAccessProperties(int nHandle, unsigned char bModifier, unsigned char bAccessType)
199
{
200
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
201
 
202
    PCIVME_ACCESS_COMMAND access_command;
203
 
204
    access_command.bAccessType =
205
    access_command.bIncrement  = bAccessType;  // increment and accessType are the same
206
    access_command.bModifier   = bModifier;
207
 
208
    if (ioctl(dev->nFileNo, PCIVME_SET_ACCESS_PARA, &access_command) < 0)
209
    {
210
        dev->nLastError = errno;
11 f9daq 211
        printf("setAccessProperties:err=%d %s\n" , errno,  strerror(errno) );
9 f9daq 212
        return errno;
213
    }
214
 
215
    dev->cAddressModifier = bModifier;
216
    dev->cAccessWidth     = bAccessType;
217
 
218
    return 0;
219
}
220
 
221
int VMEread(int nHandle, unsigned long ulAddress, unsigned char ubAccessWidth, unsigned long ulElementCount, void *pvBuffer)
222
{
223
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
224
    size_t count      = (size_t)(ulElementCount * ubAccessWidth);
225
    ssize_t result;
226
    int error;
11 f9daq 227
    long pos;
9 f9daq 228
 
13 f9daq 229
//    printf("VMEread:  AW 0x%0x 0x%0x  , AM 0x%0x \n", dev->cAccessWidth, ubAccessWidth, dev->cAddressModifier);
9 f9daq 230
    if (dev->cAccessWidth != ubAccessWidth)
231
    {
232
        if ((error = setAccessProperties(nHandle, dev->cAddressModifier, ubAccessWidth)))
233
            return error;
234
    }
11 f9daq 235
    pos = lseek(dev->nFileNo, ulAddress, SEEK_SET);
236
 
237
    if ( pos < 0){
238
        printf("VMEread: pos=0x%08lx dev->nFileNo=%d ADDR=0x%08lx %s\n",pos, dev->nFileNo, ulAddress, strerror(errno));
239
        switch (errno){
240
          case EBADF:printf("errno =EBADF\n");break;
241
          case EINVAL:printf("errno =EINVAL\n");break;
242
          case EOVERFLOW:printf("errno =EOVERFLOW\n");break;
243
          case ESPIPE:printf("errno =ESPIPE\n");break;
244
          case ENXIO:printf("errno =ENXIO\n");break;
245
        }
246
        //return errno;
247
    }
9 f9daq 248
 
11 f9daq 249
 
9 f9daq 250
    result = read(dev->nFileNo, pvBuffer, count);
13 f9daq 251
//    printf("VMEread: read %d dev->nFileNo=%d err=%d %s\n",count, dev->nFileNo, errno, strerror(errno));
9 f9daq 252
    if (result != count)
253
    {
254
        if (result < 0)
255
        {
256
            dev->nLastError = errno;
257
            return errno;
258
        }
259
        else
260
            return EFAULT;
261
    }
262
 
263
    return 0;
264
}
265
 
266
int VMEwrite(int nHandle, unsigned long ulAddress, unsigned char ubAccessWidth, unsigned long ulElementCount, void *pvBuffer)
267
{
268
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
269
    size_t count      = (size_t)(ulElementCount * ubAccessWidth);
270
    ssize_t result;
271
    int error;
11 f9daq 272
    long pos;
9 f9daq 273
 
13 f9daq 274
//    printf("VMEwrite:  AW 0x%0x 0x%0x  , AM 0x%0x \n", dev->cAccessWidth, ubAccessWidth, dev->cAddressModifier);
9 f9daq 275
    if (dev->cAccessWidth != ubAccessWidth)
276
    {
277
        if ((error = setAccessProperties(nHandle, dev->cAddressModifier, ubAccessWidth)))
278
            return error;
279
    }
280
 
11 f9daq 281
    pos = lseek(dev->nFileNo, ulAddress, SEEK_SET);
282
    if (pos < 0){
283
        printf("VMEwrite: pos=0x%08lx  dev->nFileNo=%d ADDR=0x%08lx %s\n",pos, dev->nFileNo, ulAddress, strerror(errno));
284
        switch (errno){
285
          case EBADF:printf("errno =EBADF\n");break;
286
          case EINVAL:printf("errno =EINVAL\n");break;
287
          case EOVERFLOW:printf("errno =EOVERFLOW\n");break;
288
          case ESPIPE:printf("errno =ESPIPE\n");break;
289
          case ENXIO:printf("errno =ENXIO\n");break;
290
        }
291
        //return errno;
292
    }
9 f9daq 293
    result = write(dev->nFileNo, pvBuffer, count);
13 f9daq 294
//    printf("VMEwrite: write %d dev->nFileNo=%d err=%d %s\n",count, dev->nFileNo,errno, strerror(errno));
9 f9daq 295
    if (result != count)
296
    {
297
        if (result < 0)
298
        {
299
            dev->nLastError = errno;
11 f9daq 300
 
9 f9daq 301
            return errno;
302
        }
303
        else
304
            return EFAULT;
305
    }
306
 
307
    return 0;
308
}
309
 
310
int VMEaccessVIC(int nHandle, unsigned char ubAccessMode, unsigned short uwAddress, unsigned char *ubContent)
311
{
312
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
313
    PCIVME_VIC68A_ACTION vic68a_action;
314
 
315
    vic68a_action.bAccessMode      = ubAccessMode;
316
    vic68a_action.bContent         = *ubContent;
317
    vic68a_action.wRegisterAddress = uwAddress;
318
 
319
    if (ioctl(dev->nFileNo, PCIVME_ACCESS_VIC68A, &vic68a_action) < 0)
320
    {
321
        dev->nLastError = errno;
322
        return errno;
323
    }
324
 
325
    *ubContent = vic68a_action.bContent;
326
 
327
    return 0;
328
}
329
 
330
int VMEreset(int nHandle)
331
{
332
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
333
    PCIVME_RESET_COMMAND reset_command;
334
    int i = 10;
335
 
336
    reset_command.bCommand = GLOBAL_RESET_CMD;
337
    reset_command.bResult  = 0xff;
338
 
339
    if (ioctl(dev->nFileNo, PCIVME_RESET, &reset_command) < 0)
340
    {
341
        dev->nLastError = errno;
342
        return errno;
343
    }
344
 
345
    do
346
    {
347
        usleep(100);
348
        reset_command.bCommand = POLL_RESET_CMD;
349
        reset_command.bResult  = 0xff;
350
 
351
        if (ioctl(dev->nFileNo, PCIVME_RESET, &reset_command) < 0)
352
        {
353
            dev->nLastError = errno;
354
            return errno;
355
        }
356
    } while ((reset_command.bResult) && (i--));
357
 
358
    if (!i)
359
        return ETIME;
360
 
361
    dev->nLastError = 0;
362
 
363
    return 0;
364
}
365
 
366
int VMETAS(int nHandle, unsigned long ulAddress, unsigned char *ubResult)
367
{
368
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
369
    PCIVME_TAS_STRUCT tas;
370
 
371
    tas.bContent  = *ubResult;
372
    tas.bModifier = dev->cAddressModifier;
373
    tas.dwAddress = ulAddress;
374
 
375
    if (ioctl(dev->nFileNo, PCIVME_TAS, &tas) < 0)
376
    {
377
        dev->nLastError = errno;
378
        return errno;
379
    }
380
 
381
    *ubResult = tas.bContent;
382
 
383
    return 0;
384
}
385
 
386
int VMEinterrupt(int nHandle, unsigned char *ubVector)
387
{
388
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
389
	PCIVME_VECTOR_LEVEL ubLocalVector;
390
 
391
    if (ioctl(dev->nFileNo, PCIVME_READ_VECTOR_POLL, &ubLocalVector) < 0)
392
    {
393
        dev->nLastError = errno;
394
        return errno;
395
    }
396
 
397
    *ubVector = (__u8)ubLocalVector.dwStatusID;
398
 
399
    return 0;
400
}
401
 
402
int VMEsysfailGet(int nHandle, BOOLEAN *bResult)
403
{
404
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
405
	PCIVME_VIC68A_ACTION sAction;    // structure to access vic chip
406
 
407
	sAction.wRegisterAddress = EGICR;
408
	sAction.bAccessMode      = VIC68A_READ;
409
	sAction.bContent         = 0;
410
 
411
    if (ioctl(dev->nFileNo, PCIVME_ACCESS_VIC68A, &sAction) < 0)
412
    {
413
        dev->nLastError = errno;
414
        return errno;
415
    }
416
 
417
	*bResult = (sAction.bContent & 0x08) ? FALSE : TRUE;
418
 
419
    return 0;
420
}
421
 
422
int VMEsysfailSet(int nHandle, BOOLEAN bForce)
423
{
424
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
425
	PCIVME_VIC68A_ACTION sAction;    // structure to access vic chip
426
 
427
	sAction.wRegisterAddress = ICR7;
428
	sAction.bAccessMode      = (bForce == TRUE) ? VIC68A_AND : VIC68A_OR;
429
	sAction.bContent         = (bForce == TRUE) ? 0x3F		 : 0x80;
430
 
431
    if (ioctl(dev->nFileNo, PCIVME_ACCESS_VIC68A, &sAction) < 0)
432
    {
433
        dev->nLastError = errno;
434
        return errno;
435
    }
436
 
437
    return 0;
438
}
439
 
440
int VMEerror(int nHandle)
441
{
442
    __u8 ubVector;
443
 
444
    VMEinterrupt(nHandle, &ubVector);
445
 
446
    if (ubVector == 7)
447
        return EFAULT;  // it's a bus error
448
    else
449
        return 0;
450
}
451
 
452
int VMEclose(int nHandle)
453
{
454
    int error = 0;
455
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
456
 
457
    if (dev != (VMEMM_DEVICE *)NULL)
458
    {
459
        deInitHardware(dev);
460
 
461
        if (dev->nFileNo != -1)
462
            close(dev->nFileNo);
463
        else
464
            error = -EINVAL;
465
 
466
        free(dev);
467
    }
468
 
469
    return error;
470
}
471
 
472
int VMEcontrolInterrupt(int nHandle, BOOLEAN *bEnable)
473
{
474
    VMEMM_DEVICE *dev = (VMEMM_DEVICE *)nHandle;
475
	PCIVME_IRQ_CONTROL  control;
476
 
477
    control.bEnable = *bEnable;
478
 
479
    if (ioctl(dev->nFileNo, PCIVME_CONTROL_INTERRUPTS, &control) < 0)
480
    {
481
        dev->nLastError = errno;
482
        return errno;
483
    }
484
 
485
    // status of interrupt enable before set
486
    *bEnable = control.bEnable;
487
 
488
    return 0;
489
}
490
 
491
int GetLastError(int nHandle)
492
{
493
    VMEMM_DEVICE *dev  = (VMEMM_DEVICE *)nHandle;
494
    int nLocalError;
495
 
496
    nLocalError = dev->nLastError;
497
    dev->nLastError = 0;
498
 
499
    return nLocalError;
500
}
501
 
502