V-Q

Section: Misc. Reference Manual Pages
Index
 

V-Q 1.3

 

V-Q V1.3 - VMEbus access from a QNX VMEbus PC

 

Running under the operating system QNX V4.23

 

Distributed by ÄLVSJÖ DATA AB, Älvsjö, Sweden

This manual has been written by Carsten Emde <ce@ceag.ch>.

 

Copyright

This manual and the digitally encoded software included with V-Q 1.3 is Copyright © 1997,1998 by Carsten Emde, CE Computer Experts AG, CH-5706 Boniswil. World-wide distribution rights are owned by ÄLVSJÖ DATA AB, Älvsjö, Sweden. All rights reserved. The software is intended to be used on a single computer system. Any reproduction of the software on tape, disk or any other medium except for backup purposes or as part of a run-time redistribution license is prohibited. Reproduction of the documentation, in part or whole, by any means, electrical, mechanical, magnetic, optical, chemical, manual or otherwise is also prohibited. Distribution of the software and/or documentation, in part or as a whole, to any other party or any other system may constitute copyright infringements and misappropriation of trade secrets and confidential processes that are the property of Carsten Emde, ÄLVSJÖ DATA AB and/or other parties.

Alpha is a trademark of Digital Equipment Corp.
Eurocom is a registered trademark of Eltec Elektronik GmbH.
PowerPC and MC68000 etc. are trademarks of Motorola, Inc.
QNX is a registered trademark of QNX Software Systems Ltd.
Universe is a trademark of Tundra Semiconductor Corporation.

The information contained in this manual is believed to be accurate as of the date of publication; neither ÄLVSJÖ DATA AB nor CE Computer Experts AG, however, will be liable for any damages, including directly or consequentially, from use of the software or reliance on the accuracy of this documentation. The information contained herein is subject to change without notice.

Due to the nature of a highly integrated chip such as the Tundra Universe, not all of the intended and documented functionality could be achieved in the final product. A current version of Tundra's Errata Sheet for the Universe chip was available when the v-q driver was developed, and all of the recommended solutions have been considered. In some cases, however, there were no appropriate solutions; ÄLVSJÖ DATA AB and CE Computer Experts AG reject any responsibility for such chip-related problems. The current version of the Errata Sheet may be obtained via Internet at the URL http://www.tundra.com.

 

0. Version and release history

VersionEditionRelease typeModuleChanges

1.01Initial
1.12Internal(all)Usage text is now also available via the standard use utility
1.13Internalv-qProvided options to specify data size and addressing mode, several minor fixes
1.14BetadumpProvided options to specify data size
1.15Betav-qAdded option -n to force non-privileged VMEbus access, fixed an incorrect setting of the default access permission
1.16Releasev-qMinor additions and corrections
1.27Betav-q, VMEslaveAdded I/O control mode to manage slave access, provided test program VMEslave
1.28Beta(all)Added I/O control mode to manage master access, provided test program VMEbench, added -x option to VMEdev, changed default transfer size in dump
1.29Betav-q, VMEbenchOptimized memory mapping in v-q's file manager mode, removed -x option, fixed a close() problem (could occur, if more than one process was using the same device), fixed a data size problem, optimized VMEbench
1.210Betav-qFixed a nasty bug (introduced in edition 9) that caused v-q to refuse command line data and address size settings
1.311Internalv-q, VMEirqAdded VMEbus IRQ handler and generator, provided test program VMEirq
1.312Releasev-q, dumpuniFixed a bug that prevented v-q and dumpuni from working with Tundra's Universe II, added benchmark results obtained from Universe II

 

1. Introduction

Traditional VMEbus boards are often equipped with members of the Motorola 68xxx processor family the bus interface of which was kept in mind when the VMEbus was designed. Accessing the VMEbus from such boards was, therefore, straight-forward. This was even facilitated when the VIC chip became available which allowed to standardize software intended to provide board-to-board communication via the VMEbus. More recently, other processors such as Intel 80x86 chips (e.g. Eltec's Eurocom-128), Alpha and others are used on VMEbus boards. Nonetheless, the new PowerPC family from Motorola is available on VMEbus boards. Since the internal bus (PCI) of these processors cannot be connected to the VIC chip, another bus interface circuit was required. One of the commonly used solutions is the Universe chip from Tundra Semiconductor Corporation. In PCI parlance, such an interface chip is called a bridge; it has to perform a number of tasks, e.g.  

VMEbus


    address size adjustment
    data size adjustment
    read/modify/write
    system controller function
    interrupt acknowledge
    bus arbitration

 

PCI bus


    address phase
    data transfer
    termination
    parity
    retry
    read/modify/write
    interrupt handling

These tasks are achieved by a PCI master, a PCI slave and a PCI interrupt interface to the PCI bus, and a VME master, a VME slave and a VME interrupt interface to the VMEbus. In order to use the Tundra Universe bridge, a wide variety of register settings must be done; in addition, the specific properties of the two very different bus architectures must be considered. Instead of re-inventing the wheel of Tundra Universe programming every time by every company, the required functionality is better integrated into a single software tool. This is the purpose of ÄLVSJÖ DATA's V-Q driver package for QNX described in this manual.

 

1.1 Principle of operation of the v-q driver

Although the v-q driver is a single binary program, it contains two functionally very different parts: i) a file manager that allows accessing a particular VMEbus memory range as if it were a local file and ii) an I/O control interface. The latter provides functions to obtain a pointer to VMEbus memory, to open and close a slave memory window (local memory that may be accessed from a VMEbus board), to install VMEbus interrupt handlers and to assert VMEbus interrupts. Accessing VMEbus memory from the PCI system is, thus, possible via the file manager (standard file manager functions) and via the I/O control interface (obtaining a pointer to VMEbus memory). These two modes, however, have a number of very specific advantages and disadvantages that should be taken into consideration before selecting one of them:

File manager modeI/O control mode

Can be used by every programRestricted to dedicated programs
Ideal for testing purposesIdeal as part of an integrated system
May serve an unlimited number of simultaneous tasksLimited to a maximum of 3 simultaneous tasks
Less fastFast

Irrespective of whether the v-q driver runs in file manager or in I/O control mode, it installs a virtual file in the system device directory (/dev) immediately after being invoked. The name of this device reflects the mode of operation as shown in the following table.

Device file nameProvided functionality

/dev/vme<base>Random VMEbus access (comparable to a RAM disk) starting at address <base>
/dev/vmeirq<level>Installation of VMEbus IRQ handlers, level <level>
/dev/vmeioctlVMEbus slave window, VMEbus master window, generation of VMEbus IRQs

 

1.2 Distinguishing product features

The v-q driver has a number of unique features. The following list is intended as an aid to compare the v-q driver to other products.

Unlimited number of VMEbus memory windows in file manager mode.
Unlimited number of concurrent links.
Every interrupt vector of every level may be used simultaneously.
Optimized for memory access speed.
Optimized for minimum interrupt latency.
Everything combined in a single program of less than 40 kByte.
Exhaustive documentation.
Example source code for every single function is part of the delivery.

 

2. Installation

The installation disk contains the standard QNX archive v-q.tar.F that is installed by typing

#  install

as usual. After installation, the driver /bin/v-q, the utilities /bin/dump and /bin/dumpuni, and the example source environments of VMEaccess, VMEbench, VMEirq and VMEslave will appear on the system disk. To test the correct installation of the driver and the utilities, they may be started using the standard use utility or with the -? command line option both of which will produce a short usage message on screen:

# use v-q
Function: 1. Create device '/dev/vme<base>' to access VMEbus
             window at <base> via Tundra Universe bridge.
             Default window size <length> is 65,536 Byte.
          2. Option '-i': Create device '/dev/vmeioctl' to manage
             Tundra Universe bridge via special I/O control commands.
          3. Option '-l<lvl>': Create device '/dev/vmeirq<lvl>' to
             manage VMEbus IRQ handlers for level <lvl>.
Options:
    -1       force 8-bit access (D8)
    -2       force 16-bit access (D16)
    -4       force 32-bit access (D32)
    -s       force short addressing mode (A16)
    -t       force standard addressing mode (A24)
    -e       force extended addressing mode (A32)
    -n       non-privileged access (default supervisor)
    -p       access VMEbus by pointer
    -i       I/O control mode (may only be combined with -v or -vv)
    -l<lvl>  IRQ handler mode (may only be combined with -v or -vv)
    -v       verbose
    -vv      even more verbose

# use dump
dump [-1|-1o|-2|-4|-b] <path>
Options:
    -1   use 8-bit access
    -1o  use 8-bit access (odd addresses only)
    -2   use 16-bit access
    -4   use 32-bit access
    -b   access blocks of 256 Bytes at once (default)

# use dumpuni
Function: Display Tundra Universe registers
Options:
    (none)

 

3. Using the v-q driver in file manager mode

Every time the v-q VMEbus driver is started in file manager mode (not in I/O control mode, i.e. without specifying the -i option), a device named /dev/vme<base> is created where <base> stands for the base address of the VMEbus address window that can be accessed through this device.  

3.1. VMEbus base address

The requested VMEbus base address must be passed to the driver in the mandatory command line argument. If, for example, a 64-kByte static RAM PC card is located at the base address 0xfe800000, the command

# v-q 0xfe800000 &

will create the device /dev/vmefe800000. Immediately after submitting this command, any program can access the static RAM on the PC Card using standard file I/O. If, for example, the first 256 Byte of this memory region need to be inspected, the provided dump utility can be used for this purpose:

# dump /dev/vmefe800000
  Addr     0 1  2 3  4 5  6 7  8 9  A B  C D  E F 0 2 4 6 8 A C E
--------  ---- ---- ---- ---- ---- ---- ---- ---- ----------------
00000000  1b00 0090 d823 62f8 9010 2001 4000 4bd0 ....X#bx.. .@.KP
00000010  d422 e2fc 8090 0008 0280 0108 b810 2000 T"b|........8. .
00000020  2100 0090 9e10 2001 de24 231c 2300 0090 !..... .^$#.#...
00000030  1080 0102 c024 6340 1100 0090 e402 2314 ....@$c@....d.#.
00000040  a404 a001 e422 2314 1100 0090 e802 2304 $. .d"#.....h.#.
00000050  a805 2001 1080 00f9 e822 2304 1100 0090 (. ....yh"#.....
00000060  ec02 230c ac05 a001 1080 00f4 ec22 230c l.#.,. ....tl"#.
00000070  1100 0090 d202 2360 9202 6001 1080 00ef ....R.#`..`....o
00000080  d222 2360 1100 0090 d602 2354 9602 e001 R"#`....V.#T..`.
00000090  1080 00ea d622 2354 1f00 0090 9a10 2001 ...jV"#T...... .
000000a0  da23 e31c 2100 0090 1080 00e4 c024 2340 Z#c.!......d@$#@
000000b0  2300 0090 1080 00e1 c024 631c 2b00 0090 #......a@$c.+...
000000c0  2700 0090 a410 2001 e424 e320 e425 631c '...$. .d$c d%c.
000000d0  2d00 0090 c025 a340 1080 00d8 a810 2001 -...@%#@...X(. .
000000e0  1100 0090 1500 0090 c022 231c 9210 2001 ........@"#... .
000000f0  1080 00d2 d222 a340 1100 0090 d602 233c ...RR"#@....V.#<

If the same memory region is required within a program, the following sequence of C language instructions may be used:

#define BUFFERLEN 256
  unsigned char buffer[BUFFERLEN];
  int path;
 
  if ((path = open("/dev/vmefe800000", O_RDWR)) < 0)
    return(errno);
  return(0);
  if (read(path, buffer, sizeof(buffer)) != sizeof(buffer))
    return(errno);
  return(0);

Similarly, of course, data can be written to this memory region. The following code writes the value of 206 to byte offset 16:

#define OFFSET_MODIFY 16
#define NEWVALUE 206
  char c;
  if (lseek(path, OFFSET_MODIFY, SET_SEEK) < 0)
    return(errno);
  c = NEWVALUE;
  if (write(path, &c, sizeof(c)) != sizeof(c))
    return(errno);
  return(0);

Alternatively, the entire memory block can be updated:

  if (lseek(path, 0, SET_SEEK) < 0)
    return(errno);
  buffer[OFFSET_MODIFY] = NEWVALUE;
  if (write(path, buffer, sizeof(buffer)) != sizeof(buffer))
    return(errno);
  return(0);

Several processes of the v-q driver may run simultaneously as long as they specify a different VMEbus base address. If the same address is specified twice, the driver aborts with error EEXIST, and the error message

v-q: driver for the specified VMEbus address already running

is written to the screen.  

3.2. Length of the VMEbus window

The size of the VMEbus window optionally may be specified in a second command line argument; by default, a window size of 65,536 Byte is used. If, for example, the 256-Byte image of a relay board at the VMEbus address 0xffff0000 is to be accessed, the command

# v-q 0xffff0000 256 &

can be used.  

3.3. Verbosity level

Normally, the v-q driver does not produce any screen output. If, however, one of the 'verbose' (-v) or 'very verbose' (-vv) command line options is specified, diagnostic information is provided. This information is normally not required but may be helpful in case the v-q driver does not work as expected. It should be handy whenever the ÄLVSJÖ DATA support group is contacted.  

3.4. Pointer access

Some VMEbus boards can be accessed using any of the three access modes byte, word and longword. If this is the case, the v-q driver internally may use a pointer to the mapped VMEbus memory region instead of a pointer to an intermediately allocated buffer. For this purpose, the -p option is provided. This speeds up the memory access but may not work on a specific VMEbus board that does not implement a particular access data size. As another disadvantage, VMEbus access errors can only be checked at the end of the entire transfer, not between single accesses. It is, therefore, recommended to use the pointer access feature only, if the existence and the reliability of a given VMEbus address range has been tested previously. The options -1, -2 and -4 on the one hand and the -p option on the other hand are mutually exclusive.  

3.5. Error codes

In addition to the possible errors of system file I/O, specific error codes of the v-q driver have been defined. They are returned from the file I/O command in case of a malfunction. These error codes are

Error codeError description

201PCI bus initialization error
202PCI bus read error
203PCI bus write error
204Window error
205Device error
206Argument error
207Assignment error
208Shared memory error
209Memory map error
210VMEbus access error

 

4. Default access in file manager mode

If the v-q driver was started without a command line option to force a particular access data size or addressing mode, the mode of operation is solely derived from the access length specified in the file I/O command and from the absolute VMEbus base address.  

4.1. Data size

The access data size, if not specified explicitly using one of the -1, -2, or -4 command line options, is derived from the access length as given in the following table:

Access length modulo 4Data size

0D32
1D8
2D16
3D8

 

4.2. Address size

The address size, if not specified explicitly using one of the -s, -t, or -e command line options, is determined according to the VMEbus base address:

VMEbus base addressAddress size

0xffff0000 to 0xffffffffA16
0xff000000 to 0xfffeffffA24
0x00000000 to 0xfeffffffA32

 

4.3. Access permission

By default, supervisor access of the VMEbus is used. The command line option -n may be specified to always use non-privileged accesses.

 

5. Using the v-q driver in I/O control mode

Other functionality than file manager behavior is available through the driver's I/O control mode (-i and -l options). If one of these options is specified, none of the above named file manager options except -v and -vv (verbose, very verbose) can be used. The device name in I/O control mode except for IRQ handler installation is always /dev/vmeioctl and cannot be modified. If working in IRQ handler mode, the file name is /dev/vmeirq suffixed by the IRQ level (1 to 7); again, the file name cannot be modified. In both cases, the driver is accessed using the standard QNX call qnx_ioctl(). As of this driver version, eight functions are supported, one common function (QCTL_COMM_GET_VER) and seven functions that are specific to the v-q driver (QCTL_VMEDEV_SLAVE_OPEN, QCTL_VMEDEV_SLAVE_CLOSE, QCTL_VMEDEV_MASTER_OPEN, QCTL_VMEDEV_MASTER_CLOSE, QCTL_VMEDEV_SLAVE_IRQ_OPEN, QCTL_VMEDEV_SLAVE_IRQ_CLOSE, and QCTL_VMEDEV_MASTER_IRQ_ASSERT). The common header file /usr/local/lib/VMEdev/VMEdev.h contains all required definitions.

 

5.1. QCTL_COMM_GET_VER

The standard function

int qnx_ioctl(int path, QCTL_COMM_GET_VER, NULL, 0, NULL, 0);

returns version, release, edition and beta state of the v-q driver, every variable occupying one nibble of the unsigned short return value:

BitsDescription

12..15Release (major number)
8..11Version (minor number)
4..7Edition (independent from release and version)
Bit 0Beta state (0=release, 1=beta)

An example of the QCTL_COMM_GET_VER I/O control call is given in the source code of VMEslave (section 8.4.).

 

5.2. QCTL_VMEDEV_SLAVE_OPEN

The v-q specific function

_qio_vmedev_slave slave;
int qnx_ioctl(int path, QCTL_VMEDEV_SLAVE_OPEN, (void *) &slave, sizeof(slave), NULL, 0);

enables slave access of the local PCI bus from the VMEbus. Before calling this function, appropriate values must be assigned to all elements of the _qio_vmedev_slave structure. The window number windownum can only be 0, 1, 2 or 3, and the access modes addrsize, datatype, privilege, lockrmw (lock PCI bus during read-modify-write cycles) and space should only be assigned to one of the following predefined preprocessor variables that may be included from /usr/local/lib/VMEdev/VMEdev.h:

NameValueStructure element

VMEDEV_SLAVE_ADDRSIZE_A160addrsize
VMEDEV_SLAVE_ADDRSIZE_A241addrsize
VMEDEV_SLAVE_ADDRSIZE_A322addrsize
VMEDEV_SLAVE_ADDRSIZE_USER16addrsize
VMEDEV_SLAVE_ADDRSIZE_USER27addrsize

VMEDEV_SLAVE_DATATYPE_DATA1datatype
VMEDEV_SLAVE_DATATYPE_PROGRAM2datatype
VMEDEV_SLAVE_DATATYPE_BOTH3datatype

VMEDEV_SLAVE_PRIVILEGE_USER1privilege
VMEDEV_SLAVE_PRIVILEGE_SUPERVISOR2privilege
VMEDEV_SLAVE_PRIVILEGE_BOTH3privilege

VMEDEV_SLAVE_LOCKRMW_DISABLE0lockrmw
VMEDEV_SLAVE_LOCKRMW_ENABLE1lockrmw

VMEDEV_SLAVE_SPACE_MEMORY0space
VMEDEV_SLAVE_SPACE_IO1space
VMEDEV_SLAVE_SPACE_CONFIG2space

The transfer data structure has the following format and is used in the two functions QCTL_VMEDEV_SLAVE_OPEN and QCTL_VMEDEV_SLAVE_CLOSE:

typedef struct _qio_vmedev_slave_tag {
  unsigned char  windownum, /* window number (0..3) */
                 addrsize,
                 datatype,
                 privilege,
                 lockrmw,
                 space;
  unsigned short reserved;
  unsigned long  vmeaddr,  /* VMEbus base address */
                 winsize,  /* Window size */
                 pciaddr;  /* PCI base address */
} _qio_vmedev_slave;
The granularity of the specified base addressed may not exceed the specifications of the Universe chip:

Window numberGranularity

1 4 kByte
264 kByte
364 kByte
464 kByte

The QCTL_VMEDEV_SLAVE_OPEN function returns 0, if the slave window could be installed as requested, -1 otherwise. In the latter case, the global variable errno is affected. Possible errors are EBUSY (the specified window number is already open) or EINVAL (one or more of the window specifications are illegal or the Universe chip could not be accessed). An example of the QCTL_VMEDEV_SLAVE_OPEN I/O control call is given in the source code of VMEslave (section 8.4.).

 

5.3. QCTL_VMEDEV_SLAVE_CLOSE

The v-q specific function

_qio_vmedev_slave slave;
int qnx_ioctl(int path, QCTL_VMEDEV_SLAVE_CLOSE, (void *) &slave, sizeof(slave), NULL, 0);

disables slave access of the local PCI bus from the VMEbus. Before calling this function, the window number windownum of the _qio_vmedev_slave structure must be defined; all other structure elements will not be considered. The function returns 0, if the slave window was closed successfully, -1 otherwise. In the latter case, the global variable errno is affected. Possible errors are ENODEV (the specified window is not open) and EINVAL (the Universe chip could not be accessed). An example of the QCTL_VMEDEV_SLAVE_CLOSE I/O control call is given in the source code of VMEslave (section 8.4.).

 

5.4. QCTL_VMEDEV_MASTER_OPEN

The v-q specific function

char *vmeptr;
_qio_vmedev_master master;
int qnx_ioctl(int path, QCTL_VMEDEV_MASTER_OPEN,
  (void *) &master, sizeof(master), (void *) &vmeptr, sizeof(vmeptr));

retrieves a pointer to the specified VME memory range. A total of three windows are available, i.e. this functions may not be called more than three times. Before calling this function, appropriate values must be assigned to all elements of the _qio_vmedev_master structure. The access modes datasize, addrsize, datatype and privilege should only be assigned to one of the following predefined preprocessor variables that may be included from /usr/local/lib/VMEdev/VMEdev.h:

NameValueStructure element

VMEDEV_MASTER_DATASIZE_D80datasize
VMEDEV_MASTER_DATASIZE_D161datasize
VMEDEV_MASTER_DATASIZE_D322datasize
VMEDEV_MASTER_DATASIZE_D643datasize

VMEDEV_MASTER_ADDRSIZE_A160addrsize
VMEDEV_MASTER_ADDRSIZE_A241addrsize
VMEDEV_MASTER_ADDRSIZE_A322addrsize
VMEDEV_MASTER_ADDRSIZE_USER16addrsize
VMEDEV_MASTER_ADDRSIZE_USER27addrsize

VMEDEV_MASTER_DATATYPE_DATA0datatype
VMEDEV_MASTER_DATATYPE_PROGRAM1datatype

VMEDEV_MASTER_PRIVILEGE_USER0privilege
VMEDEV_MASTER_PRIVILEGE_SUPERVISOR1privilege

The transfer data structure has the following format and is used in the two functions QCTL_VMEDEV_MASTER_OPEN and QCTL_VMEDEV_MASTER_CLOSE:

typedef struct _qio_vmedev_master_tag {
  unsigned char  datasize,
                 addrsize,
                 datatype,
                 privilege;
  unsigned long  vmeaddr,  /* VMEbus base address */
                 winsize;  /* Window size */
} _qio_vmedev_master;

The QCTL_VMEDEV_MASTER_OPEN function returns 0, if the slave window could be installed as requested, -1 otherwise. In the latter case, the global variable errno is affected. Possible errors are EBUSY (the available three windows are already in use) or EINVAL (one or more of the window specifications are illegal or the Universe chip could not be accessed). Before the retrieved pointer to physical memory can be used, it must be mapped to the program's memory space using the standard shared memory module /dev/shmem/Physical. This is normally done using the two functions shm_open() and mmap() as shown in the following example:

char *vmeptr_log, *vmeptr_phys;
int shmpath;
if ((shmpath = shm_open("Physical", O_RDWR, 0777)) < 0) {
   printf("Can't access physical memory due to error %d\n%s\n",
     errno, strerror(errno));
   exit(EXIT_FAILURE);
}
if ((vmeptr_log = mmap(NULL, TESTSIZE, PROT_READ|PROT_WRITE,
  MAP_SHARED, shmpath, (long) vmeptr_phys)) < (char*) 0) {
   printf("Can't map physical memory due to error %d\n%s\n",
     errno, strerror(errno));
   exit(EXIT_FAILURE);
}

An example of the QCTL_VMEDEV_MASTER_OPEN I/O control call is given in the source code of VMEbench (section 8.2.).

 

5.5. QCTL_VMEDEV_MASTER_CLOSE

The v-q specific function

int qnx_ioctl(int path, QCTL_VMEDEV_MASTER_CLOSE, NULL, 0, NULL, 0);

disables pointer access from the local PCI system to the VMEbus. The function returns 0, if the pointer was returned successfully, -1 otherwise. In the latter case, the global variable errno is affected. Possible errors are ENODEV (the pointer was never obtained) and EINVAL (the Universe chip could not be accessed). The function QCTL_VMEDEV_MASTER_CLOSE is called implicitly, whenever the /dev/vmeioctl device is closed; it is, however, considered good programming practice to call this function prior to close() (see example VMEbench in section 8.2.).

 

5.6. QCTL_VMEDEV_SLAVE_IRQ_OPEN

The v-q specific function

_qui_vmedev_slave_irq irq;
int qnx_ioctl(int path, QCTL_VMEDEV_SLAVE_IRQ_OPEN, (void *) &irq, sizeof(irq), NULL, 0);

locally installs a VMEbus interrupt handler of specified level and vector. After having submitted this command, the program can use the Receive() function to asynchronously wait for a VMEbus interrupt to arrive. The transfer data structure has the following format and is used in the two functions QCTL_VMEDEV_SLAVE_IRQ_OPEN and QCTL_VMEDEV_SLAVE_IRQ_CLOSE:

typedef struct _qio_vmedev_slave_irq_tag {
  int locirq;
  int map;
  int vector;
  int ident;
} _qio_vmedev_slave_irq;

The variable locirq must contain the number of the local ISA vector that is assigned to the Universe bridge (e.g. vector #10). It may be mapped using PCI interrupt 0 or 1 (usually 0), which can be specified in the map variable. This information can be obtained from the manufacturer of the VMEbus board. The required IRQ vector must be written to vector. The caller will only be informed, if both level (passed as command line option to the v-q driver) and vector exactly match. If the same program wants to install more than one VMEbus interrupt handler, identification information may be written to the variable ident. This value will be returned in the message part of the Receive() function in order to identify the origin of every message received. The QCTL_VMEDEV_SLAVE_IRQ_OPEN function returns 0, if the interrupt handler could be installed successfully, -1 otherwise. In the latter case, the global variable errno is affected. Possible errors are EBUSY (the specified interrupt level/vector combination is already in use), ENODEV (the specified device is not running in the requested I/O control mode), EINVAL (one or more of the interupt specifications are illegal or the Universe chip could not be accessed). The following program section exemplifies the usage of the QCTL_VMEDEV_SLAVE_IRQ_OPEN I/O control call.

/* Variable declaration */
int vmepath, ident;
_qio_vmedev_slave_irq slave_irq;
/* Open v-q device (must have been started with 'v-q -l3 &') */
vmepath = open("/dev/vmeirq3", O_RDONLY);
/* Install interrupt handler */
slave_irq.locirq = 10;
slave_irq.map = 0;
slave_irq.vector = 128;
slave_irq.ident = 12345678;
qnx_ioctl(vmepath, QCTL_VMEDEV_SLAVE_IRQ_OPEN,
    (char *) &slave_irq, sizeof(slave_irq), NULL, 0);
/* Wait until interrupt arrives */
Receive (0, &ident, sizeof(ident));
/* Deinstall interrupt handler */
qnx_ioctl(vmepath, QCTL_VMEDEV_SLAVE_IRQ_CLOSE,
    (char *) &slave_irq, sizeof(slave_irq), NULL, 0);
/* Good bye */
close(vmepath);

A practical example of the QCTL_VMEDEV_SLAVE_IRQ_OPEN I/O control call is given in the source code of VMEirq (section 8.3.).

 

5.7. QCTL_VMEDEV_SLAVE_IRQ_CLOSE

The v-q specific function

_qui_vmedev_slave_irq irq;
int qnx_ioctl(int path, QCTL_VMEDEV_SLAVE_IRQ_CLOSE, (void *) &irq, sizeof(irq), NULL, 0);

disables the interrupt handler previously installed using the QCTL_VMEDEV_SLAVE_IRQ_OPEN I/O control mode. The element vector of the _qui_vmedev_slave_irq transfer structure must be set to the requested vector number, the other elements are not considered. The function QCTL_VMEDEV_SLAVE_IRQ_CLOSE is called implicitly, whenever the /dev/vmeirq<level> device is closed; it is, however, considered good programming practice to call this function prior to close().

 

5.8. QCTL_VMEDEV_MASTER_IRQ_ASSERT

The v-q specific function

_qui_vmedev_master_irq irq;
int qnx_ioctl(int path, QCTL_VMEDEV_MASTER_IRQ_ASSERT, (void *) &irq, sizeof(irq), NULL, 0);

asserts a VMEbus interrupt of specified level and vector. This information must be written to the _qui_vmedev_master_irq structure prior to calling the QCTL_VMEDEV_MASTER_IRQ_ASSERT I/O control mode. The required transfer data structure has the following format:

typedef struct _qio_vmedev_master_irq_tag {
  int level;
  int vector;
} _qio_vmedev_master_irq;

The function immediately returns after the IRQ was asserted. Possible errors are ENODEV (the specified device is not runing in this mode), and EINVAL (one or more of the interupt specifications are illegal or the Universe chip could not be accessed).

 

6. Benchmarks

The following benchmark results have been obtained using the VMEbench utility. PCI master was a 133-MHz Pentium CPU board, VMEbus memory was on-board memory of a 68k-CPU. During the entire test, the 68k-CPU was idle. Window size was 1 MByte, access mode A32/D32.

 

6.1. Universe I

 

6.1.1. File manager mode (no options)

Access data sizeSpeed (Bytes/s)

113420
226784
453504
8103481
16194387
32344595
64563993
128825548
2561087385
5121290956
10241419468
20481495449
40961536819
81921548288
163841549926
32768399769
65536406323

 

6.1.2. File manager mode (internal pointer, -p option)

Access data sizeSpeed (Bytes/s)

115592
230022
462316
8120208
16224326
32396006
64640281
128927590
2561195059
5121395712
10241523916
20481597849
40961636761
81921658060
163841667891
32768701235
65536629145

 

6.1.3. Master access via pointer obtained in I/O control mode

Access data sizeSpeed (Bytes/s)

1417673
2838421
41678859
81679387
161679449
321654393
641667097
1281673548
2561676390
5121677619
10241678540
20481678950
40961679360
81921679360
163841680998
327681677721
655361690828

 

6.2. Universe II

 

6.2.1. File manager mode (no options)

Access data sizeSpeed (Bytes/s)

113755
227429
454823
8106878
16203984
32373331
64638272
128989619
2561371648
5121694412
10241919795
20482048819
40962126643
81922141388
163842139750
32768550502
65536550502

 

6.2.2. File manager mode (internal pointer, -p option)

Access data sizeSpeed (Bytes/s)

114852
228965
459296
8115912
16221161
32403987
64692403
1281074713
2561481420
5121828454
10242070937
20482218803
40962300313
81922344550
163842365849
32768773324
65536734003

 

6.2.3. Master access via pointer obtained in I/O control mode

Access data sizeSpeed (Bytes/s)

1595212
21194382
42389292
82389264
162389590
322337856
642364019
1282378086
2562383872
5122386227
10242386329
20482388787
40962389606
81922390425
163842388787
327682392064
655362398617

 

7. Other utilities

 

7.1. dump

The dump program already mentioned above produces a hex dump of a file. It is not restricted to the /dev/vme<base> device of the v-q driver but can be used in combination with any other file or system device. The provided command line options are used to specify the access size

OptionDescription

-1use 8-bit access
-1ouse 8-bit access (odd addresses only)
-2use 16-bit access
-4use 32-bit access
-baccess blocks of 256 Bytes at once (default)

These options, however, have no effect on the v-q access data size, if one of the -1, -2, -4 driver options has been specified when v-q was started.

 

7.2. dumpuni

The dumpuni program permits inspection of all Tundra Universe registers. This utility is primarily intended for debug and support purposes but may also be helpful for a quick check whether the Tundra Universe chip can be identified correctly using the implemented method. For this purpose, only the first register PCI_ID of the entire register dump

PCI_ID   :000010E3  PCI_CSR  :02000007  PCI_CLASS:06800000
PCI_MISC0:00800000  PCI_BS   :03000000  PCI_MISC1:0003010A
LSI0_CTL :00820000  LSI0_BS  :20000000  LSI0_BD  :22000000
LSI0_TO  :60000000  LSI1_CTL :00800000  LSI1_BS  :00000000
LSI1_BD  :02000000  LSI1_TO  :80000000  LSI2_CTL :00800000
LSI2_BS  :00000000  LSI2_BD  :00000000  LSI2_TO  :00000000
LSI3_CTL :00800000  LSI3_BS  :00000000  LSI3_BD  :00000000
LSI3_TO  :00000000  SCYC_CTL :00000000  SCYC_ADDR:00000000
SCYC_EN  :00000000  SCYC_CMP :00000000  SCYC_SWP :00000000
LMISC    :10000000  SLSI     :00000000  L_CMDERR :70000000
LAERR    :00000000  DCTL     :00000080  DTBC     :00000000
DLA      :00000000  DVA      :00000000  DCPP     :00000000
DGCS     :00000000  D_LLUE   :00000000  LINT_EN  :00000000
LINT_STAT:00004000  LINT_MAP0:00000000  LINT_MAP1:00000000
VINT_EN  :00000000  VINT_STAT:00000000  VINT_MAP0:00000000
VINT_MAP1:00000000  STATID   :FF000000  V1_STATID:00000000
V2_STATID:00000000  V3_STATID:00000000  V4_STATID:00000000
V5_STATID:00000000  V6_STATID:00000000  V7_STATID:00000000
MAST_CTL :80C00000  MISC_CTL :31040000  MISC_STAT:00260000
USER_AM  :40400000  VSI0_CTL :00F00000  VSI0_BS  :00000000
VSI0_BD  :00000000  VSI0_TO  :00000000  VSI1_CTL :00F00000
VSI1_BS  :00000000  VSI1_BD  :00000000  VSI1_TO  :00000000
VSI2_CTL :00F00000  VSI2_BS  :00000000  VSI2_BD  :00000000
VSI2_TO  :00000000  VSI3_CTL :00F00000  VSI3_BS  :00000000
VSI3_BD  :00000000  VSI3_TO  :00000000  VRAI_CTL :00F00000
VRAI_BS  :00000000  VCSR_CTL :00000000  VCSR_TO  :00000000
V_AMERR  :24000000  VAERR    :800026FD  VCSR_CLR :00000000
VCSR_SET :00000000  VCSR_BS  :00000000

must be checked. As in the above example, the two least significant bytes must be 0x10e3 which is Tundra's registered vendor code.

 

8. Example source code environment

 

8.1. VMEaccess

A program skeleton providing minimal functionality to access the VMEbus via the v-q driver is available in the source code environment /usr/local/lib/VMEaccess:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
static void usage(void);

/*
 * V M E a c c e s s
 * An example program to access the VMEbus via the v-q driver
 */
main(int argc, char *argv[])
{
  unsigned char buffer[256];
  char         *filename = NULL;
  int           i, j, vmepath;
  for (i = 1; i < argc; i++) {
    if (argv[i][0] == '-') {
      for (j = 1; j < strlen(argv[i]); j++) {
        switch(argv[i][j]) {
          case '?':
            usage();
            exit(EXIT_SUCCESS);
            break;
          default:
            printf("Option '%c' not recognized\n", argv[i][j]);
            exit(EXIT_FAILURE);
            break;
        }
      }
    } else if (filename == NULL)
      filename = argv[i];
    else {
      printf("No more than one argument accepted\n");
      exit(EXIT_FAILURE);
    }
  }   
  if (filename == NULL) {
     printf("The v-q device, e.g. /dev/vme80000000, must be specified\n");
     exit(EXIT_FAILURE);
  }
  if ((vmepath = open(filename, O_RDONLY)) < 0) {
     printf("Can't open v-q device '%s' due to error %d\n%s\n",
       filename, errno, strerror(errno));
     exit(EXIT_FAILURE);
  }
  
  if (read(vmepath, buffer, sizeof(buffer)) < 1) {
     printf("Can't read from v-q device '%s' due to error %d\n%s\n",
       filename, errno, strerror(errno));
     exit(EXIT_FAILURE);
  }
  
  printf("First byte read from v-q device '%s' is 0x%02x\n",
    filename, buffer[0]);
  close(vmepath);
}

/*
 * u s a g e
 */
#define __USAGE 1
static void usage(void)
{
#ifdef __USAGE
  puts("Syntax:   VMEaccess [<opts>] <path>");
  puts("Function: Exemplify usage of v-q driver (VMEbus master access)");
  puts("Options:");
  puts("    (none)");
#endif
}

 

8.2. VMEbench

The performance of the v-q driver may be tested using the program VMEbench the source code environment of which is located in the directory /usr/local/lib/VMEbench.

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "../VMEdev/VMEdev.h"
#define TESTDURATION 5
#define TESTADDR 0x80000000
#define TESTSIZE 0x10000
static void           usage(void);
static unsigned char  buffer[0x10000];
volatile sig_atomic_t elapsed;

/*
 * a l a r m h a n d l e r
 */
void alarmhandler(/* int signo */)
{
  elapsed = 1;
}

/*
 * V M E b e n c h
 * An example program to benchmark VMEbus accesses via the v-q driver
 */
main(int argc, char *argv[])
{
  char               filename_vq[32], *filename_io = "/dev/vmeioctl";
  char              *shmname = "Physical";
  char              *vmeptr_log, *vmeptr_phys;
  int                i, j, vmepath, shmpath, size, loops, throughput;
  int                accioctl = 0, accstdio = 0;
  _qio_vmedev_master master;
  for (i = 1; i < argc; i++) {
    if (argv[i][0] == '-') {
      for (j = 1; j < strlen(argv[i]); j++) {
        switch(argv[i][j]) {
          case 'i':
            accioctl = 1;
            break;
          case 's':
            accstdio = 1;
            break;
          case '?':
            usage();
            exit(EXIT_SUCCESS);
            break;
          default:
            printf("Option '%c' not recognized\n", argv[i][j]);
            exit(EXIT_FAILURE);
            break;
        }
      }
    } else {
      printf("No arguments accepted\n");
      exit(EXIT_FAILURE);
    }
  }   
  if (accioctl == 0 && accstdio == 0)
    accioctl = accstdio = 1;
  signal(SIGALRM, alarmhandler);
  if (accstdio) {
    printf("Test VMEbus access via standard read/write\n");  
    printf("------------------------------------------\n");  
    sprintf(filename_vq, "/dev/vme%08x", TESTADDR);
    if ((vmepath = open(filename_vq, O_RDONLY)) < 0) {
       printf("Can't open v-q device '%s' due to error %d\n%s\n",
         filename_vq, errno, strerror(errno));
       printf("Please run 'v-q [-x] 0x%08x 0x%08x &'\n", TESTADDR, TESTSIZE);
       exit(EXIT_FAILURE);
    }
    for (size = 1; size <= sizeof(buffer); size <<= 1) {
      elapsed = 0;
      loops = 0;
      if (alarm(TESTDURATION) < 0) {
        printf("No timer available, aborting\n");
        exit(EXIT_FAILURE);
      }
      while (!elapsed) {
        lseek(vmepath, 0, SEEK_SET);
        if (read(vmepath, buffer, size) < 1 && errno != 4) {
          printf("Can't read from v-q device '%s' due to error %d\n%s\n",
            filename_vq, errno, strerror(errno));
           exit(EXIT_FAILURE);
        }
        loops++;
      }
      throughput = (loops * size) / TESTDURATION;
      printf("Access data size %5d Bytes: %7d Bytes read per second\n",
        size, throughput);
      fflush(stdout);
    }
    close(vmepath);
  }
  if (accioctl) {
    if (accstdio)
      printf("\n\n");
    printf("Test VMEbus access via special I/O control\n");  
    printf("------------------------------------------\n");  
    if ((vmepath = open(filename_io, O_RDONLY)) < 0) {
       printf("Can't open v-q device '%s' due to error %d\n%s\n",
         filename_io, errno, strerror(errno));
       printf("Please run 'v-q -i &'\n");
       exit(EXIT_FAILURE);
    }
    master.datasize = VMEDEV_MASTER_DATASIZE_D32;
    master.addrsize = VMEDEV_MASTER_ADDRSIZE_A32;
    master.datatype = VMEDEV_MASTER_DATATYPE_DATA;
    master.privilege = VMEDEV_MASTER_PRIVILEGE_USER;
    master.vmeaddr = TESTADDR;
    master.winsize = TESTSIZE;
   
    vmeptr_phys = 0;
    if (qnx_ioctl(vmepath, QCTL_VMEDEV_MASTER_OPEN,
        (char *) &master, sizeof(master),
        (char *) &vmeptr_phys, sizeof(vmeptr_phys)) < 0) {
       printf("Can't get pointer to VMEbus via '%s' due to error %d\n%s\n",
         filename_io, errno, strerror(errno));
       exit(EXIT_FAILURE);
    }
    if ((shmpath = shm_open(shmname, O_RDWR, 0777)) < 0) {
       printf("Can't access physical memory due to error %d\n%s\n",
         errno, strerror(errno));
       exit(EXIT_FAILURE);
    }
    if ((vmeptr_log = mmap(NULL, TESTSIZE, PROT_READ|PROT_WRITE,
      MAP_SHARED, shmpath, (long) vmeptr_phys)) == (char*) -1) {
       printf("Can't map physical memory due to error %d\n%s\n",
         errno, strerror(errno));
       exit(EXIT_FAILURE);
    }
  
    for (size = 1; size <= sizeof(buffer); size <<= 1) {
      elapsed = 0;
      loops = 0;
      if (alarm(TESTDURATION) < 0) {
        printf("No timer available, aborting\n");
        exit(EXIT_FAILURE);
      }
      switch (size) {
        case 1:
          while (!elapsed) {
            *buffer = *vmeptr_log;
            loops++;
          }
          break;
        case 2:
          while (!elapsed) {
            *((short *) buffer) = *((short *) vmeptr_log);
            loops++;
          }
          break;
        case 4:
          while (!elapsed) {
            *((long *) buffer) = *((long *) vmeptr_log);
            loops++;
          }
          break;
        case 8:
          while (!elapsed) {
            *((long *) buffer) = *((long *) vmeptr_log);
            *((long *) (buffer + 4)) = *((long *) (vmeptr_log + 4));
            loops++;
          }
          break;
        case 16:
          while (!elapsed) {
            *((long *) buffer) = *((long *) vmeptr_log);
            *((long *) (buffer + 4)) = *((long *) (vmeptr_log + 4));
            *((long *) (buffer + 8)) = *((long *) (vmeptr_log + 8));
            *((long *) (buffer + 12)) = *((long *) (vmeptr_log + 12));
            loops++;
          }
          break;
        default:
          while (!elapsed) {
            memcpy(buffer, vmeptr_log, size);
            loops++;
          }
          break;
      }
      throughput = (loops * size) / TESTDURATION;
      printf("Access data size %5d Bytes: %7d Bytes read per second\n",
        size, throughput);
      fflush(stdout);
    }
    qnx_ioctl(vmepath, QCTL_VMEDEV_MASTER_CLOSE, NULL, 0, NULL, 0);
    close(vmepath);
  }
}

/*
 * u s a g e
 */
#define __USAGE 1
static void usage(void)
{
#ifdef __USAGE
  puts("Syntax:   VMEbench [<opts>]");
  puts("Function: Exemplify usage of v-q driver (VMEbus benchmark)");
  puts("Options:");
  puts("   -s    access via standard read/write");
  puts("   -i    access via special I/O control");
#endif
}

 

8.3. VMEirq

The ability to install IRQ handlers is demonstrated in the example program VMEirq the source code environment of which is located in the directory /usr/local/lib/VMEirq. Again, the interface is based on the standard QNX call qnx_ioctl(), and the required data structures and definitions are available in the common header file /usr/local/lib/VMEdev/VMEdev.h.

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/kernel.h>
#include "../VMEdev/VMEdev.h"
#define LEVEL  3 
#define VECTOR 0
#define MYIDENT 3262   /* As good as any number */
static void usage(void);
volatile sig_atomic_t ctrl_c;
void breakhandler(int signum)
{
  ctrl_c = 1;
}
/*
 * V M E i r q
 * An example program to install VMEbus IRQ via the v-q driver
 */
main(int argc, char *argv[])
{
  char filename[32];
  int  i, j, irqhndlpath, irqassertpath, sendpid, ident;
  int  locirq = -2, level = -1, vector = -1, assert = 0;
  _qio_vmedev_slave_irq slave_irq;
  _qio_vmedev_master_irq master_irq;
  for (i = 1; i < argc; i++) {
    if (argv[i][0] == '-') {
      for (j = 1; j < strlen(argv[i]); j++) {
        switch(argv[i][j]) {
          case 'a':
            assert = 1;
            break;
          case '?':
            usage();
            exit(EXIT_SUCCESS);
            break;
          default:
            printf("%s: Option '%c' not recognized\n", argv[0], argv[i][j]);
            exit(EXIT_FAILURE);
            break;
        }
      }
    } else {
      if (locirq == -2) {
        if (!strcmp(argv[i], "none"))
          locirq = -1;
        else
          locirq = atoi(argv[i]);
        if (locirq != -1 && !(locirq > 0 && locirq < 16)) {
          printf("%s: Invalid number (%d) specified for local IRQ\n",
            argv[0], locirq);
          exit(EXIT_FAILURE);
        }
      } else if (level == -1) {
        level = atoi(argv[i]);
        if (level < 1 || level > 7) {
          printf("%s: Invalid number (%d) specified for IRQ level\n",
            argv[0], level);
          exit(EXIT_FAILURE);
        }
      } else if (vector == -1) {
        vector = atoi(argv[i]);
        if (vector < 0 || vector > 255) {
          printf("%s: Invalid number (%d) specified for IRQ vector\n",
            argv[0], vector);
          exit(EXIT_FAILURE);
        }
      } else {
        printf("No more than three arguments accepted\n");
        exit(EXIT_FAILURE);
      }
    }
  }   
  if (locirq == -2)
    locirq = -1;
  if (level == -1)
    level = LEVEL;
  if (vector == -1)
    vector = VECTOR;
  if (assert) {
    if ((irqassertpath = open("/dev/vmeioctl", O_RDONLY)) < 0) {
      printf("Can't open v-q device '/dev/vmeioctl' due to error %d\n%s\n",
        errno, strerror(errno));
      printf("Please run 'v-q -i &'\n");
      exit(EXIT_FAILURE);
    }
    master_irq.level = level;
    master_irq.vector = vector;
    if (qnx_ioctl(irqassertpath, QCTL_VMEDEV_MASTER_IRQ_ASSERT,
      (char *) &master_irq, sizeof(master_irq), NULL, 0) < 0) {
      printf("Can't assert VMEbus IRQ due to error %d\n%s\n",
        errno, strerror(errno));
      exit(EXIT_FAILURE);
    }
    close(irqassertpath);
  } else {
    signal(SIGINT, breakhandler);
    sprintf(filename, "/dev/vmeirq%1d", level);
    if ((irqhndlpath = open(filename, O_RDONLY)) < 0) {
      printf("Can't open v-q device '%s' due to error %d\n%s\n",
        filename, errno, strerror(errno));
      printf("Please run 'v-q -l%d &'\n", level);
      exit(EXIT_FAILURE);
    }
    slave_irq.locirq = locirq;
    slave_irq.map = 0;
    slave_irq.vector = vector;
    slave_irq.ident = MYIDENT;
    if (qnx_ioctl(irqhndlpath, QCTL_VMEDEV_SLAVE_IRQ_OPEN,
      (char *) &slave_irq, sizeof(slave_irq), NULL, 0) < 0) {
      printf("Can't install VMEbus IRQ via '%s' due to error %d\n%s\n",
        filename, errno, strerror(errno));
      exit(EXIT_FAILURE);
    }
    while ((sendpid = Receive(0, &ident, sizeof(ident))) != -1) {
      if (locirq == -1)
        printf("Message from Tundra Universe IRQ handler received\n");
      else {
        if (ident == MYIDENT)
          printf("Message from VMEbus IRQ (level %d, vector %d) received\n",
            level, vector);
        else
          printf("Can't happen\n");
      }
    }
    if (sendpid == -1) {
      if (ctrl_c)
        printf("User abort\n");
      else
        printf("Unknown message received\n");
    }
    qnx_ioctl(irqhndlpath, QCTL_VMEDEV_SLAVE_IRQ_CLOSE,
      (char *) &slave_irq, sizeof(slave_irq), NULL, 0);
    close(irqhndlpath);
  } 
}

/*
 * u s a g e
 */
#define __USAGE 1
static void usage(void)
{
#ifdef __USAGE
  puts("Syntax:   VMEirq <local irq> [<level>] [<vector>] [<opts>]");
  puts("Function: Exemplify usage of v-q driver (VMEbus IRQ)");
  puts("Options:");
  puts("    -a    assert interrupt (default handle)");
#endif
}

 

8.4. VMEslave

Usage of the v-q driver in I/O control mode is demonstrated in the program VMEslave the source code environment of which is located in the directory /usr/local/lib/VMEslave. The interface is based on the standard QNX call qnx_ioctl(); the required data structures and definitions are available in the common header file /usr/local/lib/VMEdev/VMEdev.h.

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/qioctl.h>
#include "VMEdev.h"
static void usage(void);

/*
 * V M E s l a v e
 * An example program to open a VMEbus slave window via the v-q driver
 */
main(int argc, char *argv[])
{
  char             *filename = "/dev/vmeioctl";
  int               i, j, vmepath, retval;
  _qio_vmedev_slave slave;
  for (i = 1; i < argc; i++) {
    if (argv[i][0] == '-') {
      for (j = 1; j < strlen(argv[i]); j++) {
        switch(argv[i][j]) {
          case '?':
            usage();
            exit(EXIT_SUCCESS);
            break;
          default:
            printf("Option '%c' not recognized\n", argv[i][j]);
            exit(EXIT_FAILURE);
            break;
        }
      }
    } else {
      printf("No argument accepted\n");
      exit(EXIT_FAILURE);
    }
  }   
  if ((vmepath = open(filename, O_RDONLY)) < 0) {
    printf("Can't open v-q device '%s' due to error %d\n%s\n",
      filename, errno, strerror(errno));
    exit(EXIT_FAILURE);
  }
  
  if ((retval = qnx_ioctl(vmepath, QCTL_COMM_GET_VER, NULL, 0, NULL, 0)) == -1) { 
    printf("Can't get ioctl version info from v-q device '%s' due to error %d\n%s\n",
      filename, errno, strerror(errno));
    exit(EXIT_FAILURE);
  }
  printf("Version of v-q device '%s' is %d.%d, edition %d%s\n",
    filename, (retval >> 12) & 0x0f, (retval >> 8) & 0x0f,
              (retval >>  4) & 0x0f, (retval & 0x0f) ? " (beta)" : "");
  slave.windownum = 0;
  slave.addrsize  = VMEDEV_SLAVE_ADDRSIZE_A32;
  slave.datatype  = VMEDEV_SLAVE_DATATYPE_DATA;
  slave.privilege = VMEDEV_SLAVE_PRIVILEGE_BOTH;
  slave.lockrmw   = VMEDEV_SLAVE_LOCKRMW_ENABLE;
  slave.space     = VMEDEV_SLAVE_SPACE_MEMORY;
  slave.vmeaddr   = 0x70000000;
  slave.winsize   = 0x00100000;
  slave.pciaddr   = 0;
  /* close the window: it *might* be open */
  qnx_ioctl(vmepath, QCTL_VMEDEV_SLAVE_CLOSE, (void *) &slave, sizeof(slave),
    NULL, 0);
  if (qnx_ioctl(vmepath, QCTL_VMEDEV_SLAVE_OPEN,
    (void *) &slave, sizeof(slave), NULL, 0) < 0) { 
    printf("Can't open VMEbus slave window via v-q device '%s' due to error %d\n%s\n",
      filename, errno, strerror(errno));
    exit(EXIT_FAILURE);
  }
  printf("Enabled PCI slave window at 0x%08x to VMEbus at 0x%08x\n",
    slave.pciaddr, slave.vmeaddr);
  printf("Hit enter to close the window\n");
  getchar();
    
  if (qnx_ioctl(vmepath, QCTL_VMEDEV_SLAVE_CLOSE,
    (void *) &slave, sizeof(slave), NULL, 0) == -1) { 
    printf("Can't close VMEbus slave window via v-q device '%s' due to error %d\n%s\n",
      filename, errno, strerror(errno));
    exit(EXIT_FAILURE);
  }
  printf("PCI slave window closed\n");  
  close(vmepath);
}

/*
 * u s a g e
 */
#define __USAGE 1
static void usage(void)
{
#ifdef __USAGE
  puts("Syntax:   VMEslave [<opts>] <path>");
  puts("Function: Exemplify usage of v-q driver (VMEbus slave window)");
  puts("Options:");
  puts("    (none)");
#endif
}


 

Index

V-Q 1.3
V-Q V1.3 - VMEbus access from a QNX VMEbus PC
Running under the operating system QNX V4.23
Distributed by ÄLVSJÖ DATA AB, Älvsjö, Sweden
Copyright
0. Version and release history
1. Introduction
VMEbus
PCI bus
1.1 Principle of operation of the v-q driver
1.2 Distinguishing product features
2. Installation
3. Using the v-q driver in file manager mode
3.1. VMEbus base address
3.2. Length of the VMEbus window
3.3. Verbosity level
3.4. Pointer access
3.5. Error codes
4. Default access in file manager mode
4.1. Data size
4.2. Address size
4.3. Access permission
5. Using the v-q driver in I/O control mode
5.1. QCTL_COMM_GET_VER
5.2. QCTL_VMEDEV_SLAVE_OPEN
5.3. QCTL_VMEDEV_SLAVE_CLOSE
5.4. QCTL_VMEDEV_MASTER_OPEN
5.5. QCTL_VMEDEV_MASTER_CLOSE
5.6. QCTL_VMEDEV_SLAVE_IRQ_OPEN
5.7. QCTL_VMEDEV_SLAVE_IRQ_CLOSE
5.8. QCTL_VMEDEV_MASTER_IRQ_ASSERT
6. Benchmarks
6.1. Universe I
6.1.1. File manager mode (no options)
6.1.2. File manager mode (internal pointer, -p option)
6.1.3. Master access via pointer obtained in I/O control mode
6.2. Universe II
6.2.1. File manager mode (no options)
6.2.2. File manager mode (internal pointer, -p option)
6.2.3. Master access via pointer obtained in I/O control mode
7. Other utilities
7.1. dump
7.2. dumpuni
8. Example source code environment
8.1. VMEaccess
8.2. VMEbench
8.3. VMEirq
8.4. VMEslave

This document was created by man2html.