Subject: Re: Reading and writing from/to VME device

From: Didier Kryn <[email-masked]>
Date: Tue, 27 Mar 2007 11:09:41 +0200

Hi Konstantin,
    I am new to this board, and, by chance I am just starting this week 
my first test wit the VME on this board (I have however more than 20 
years of VME experience). Your whole logic is mainly OK.  My driver uses 
slightly different device names but it seems very similar and the API 
uses the same structures. I just noticed three things which bother me:
    1) You declare outWinCfg and use later in the code outWinCfgADC. I 
guess the compiler will complain, unless I missed something. I guess 
this is not the file you actually compiled.
    2) Why do you specify MAP_SHARED in the mmap() call ? I sort of 
understood that the philosophy of this driver was all against sharing. 
Maybe it works, but I wouldn't try it the first time.
    3) I think it is an error to declare your data pointer as a u_char 
*. If you configure your interface for D16, you must perform D16 access. 
For example, you might do the following:

unsigned short *rdPtr;
...
rdPtr = (unsigned short *)mmap(...);
    for(i=0;i<0x50;i++){
       printf("# Read at VME address %x = %x\n", i*sizeof(*rdPtr), 
rdPtr[i] );
    }

I like using sizeof() instead of 2 because it remains valid if you 
convert your code for D32.
If you want to perform D8 access, you should configure your window 
accordingly. Beware that there are 2 kinds of D8 transfers, which make 
them more complicated and, for that reason mostly abandonned. IIRC, the 
VITA standard for CR/CSR defines 1byte data words at even addresses so 
as to transfer them as D16. Therefore you should transfer them as short 
and then mask the high order byte. I don't know what the high order byte 
will be in case of successfull transfer. If it is 0, then it is fine, 
because, since a bus error would set all bits to 1, you can check 
immediately the sucess of the transfer.

    Hope this helps.
    Didier

Konstantin Boyanov a écrit :
> Hi list,
>
> I'm using the MVME6100 board with the Motorola driver for linux v3.5 
> (kernel 2.6.15). I try to access the CSR registers of an ADC board, in 
> order to configure it as to be able to access its memory, on the VME 
> bus using one of the outbound windows defined by the driver. As I am 
> new to the whole VME stuff, I'm getting into trouble to find out when 
> I'm actually reading something on the VME, i.e. which addresses respond.
> I'm trying the following schema (source code @ EOM):
>
> 1. open() and ioctl() one of the /dev/vme_m* devices, which I assume 
> is corresponding to an outbound window (at least I try to configure it 
> as one),
> 2. then mmap() a memory area to hold the contents of the /dev/vme_m* 
> device file
> 3. and finally doing incrementation of the pointer returned by mmap() 
> and dereferencing it in the hope that I'll read something, which in 
> most cases is 0xFF
>
> In fact my code is very similar to test code that comes with the 
> driver and also with a sample code I found in this thread 
> ->http://ozlabs.org/pipermail/linuxppc-dev/1999-May/001906.html 
> <http://ozlabs.org/pipermail/linuxppc-dev/1999-May/001906.html>
> I've tried to do a read() on the opened /dev/vme_m* device but I only 
> succeed in reading 0 bytes, and when I try to read in chunks from the 
> VME bus i get errno 22 on reads like read(fd, buffer, 1024) for example.
>
> I don't know if my strategy is correct in the first place but that's 
> what I came up with.
> When I try to run one of the test applications that came with the 
> driver (the "testout" one) I get an errno = 29 (Illegal seek?! ) on 
> the read() operations.
> So my question is whether I make the right steps in reading an address 
> on the VME bus. I know I'm missing something, so I'll be glad to get 
> some directions as to how to be sure whether I'm reading something 
> from the VME bus and where I'm able to write.
>
> Best regards,
> Konstantin
> ________________________________
>
> #include <stdio.h>
> #include <string.h>
> #include <errno.h>
> #include <sys/ioctl.h>
> #include <unistd.h>
> #include "vmedrv.h"
>
> int main(int argc, char* argv[])
> {
>     vmeOutWindowCfg_t outWinCfg;
>     vmeOutWindowCfg_t outWinGet;
>
>     int fdOut, status, i, j;
>     unsigned int  n;
>     u_char *rdPtr, *getPtr;
>
>     if(getMyVmeInfo()){
>       printf("getMyVmeInfo failed.\n");
>       exit (1);
>     }
>
>     fdOut = open("/dev/vme_m0", O_RDWR);
>     perror("open");
>     if(fdOut < 0){
>       printf("Opening /dev/vme_m0 failed. Errno = %d\n", errno);
>     }
>
>     memset(&outWinCfgADC, 0, sizeof(vmeOutWindowCfg_t));
>     perror("memset");
>
>     outWinCfgADC.windowNbr           = 0;
>     outWinCfgADC.windowEnable     = 1;
>     outWinCfgADC.wrPostEnable      = 0;
>     outWinCfgADC.userAccessType  = VME_SUPER;
>     outWinCfgADC.dataAccessType  = VME_DATA;
>     outWinCfgADC.windowSizeL        = 0x200000;
>     outWinCfgADC.xferProtocol         = VME_SCT;
>     outWinCfgADC.addrSpace           = VME_A24;
>     outWinCfgADC.maxDataWidth     = VME_D16;
>
>     status = ioctl(fdOut, VME_IOCTL_SET_OUTBOUND, &outWinCfgADC);
>     perror("ioctl");
>     if(status < 0){
>         printf("*** ioctl set on outWinCfgADC failed. Errno = %d\n", 
> errno);
>         exit (1);
>     }
>     memset(&outWinGetADC, 0, sizeof(vmeOutWindowCfg_t));
>     outWinGetADC.windowNbr = 0;
>
>     status = ioctl(fdOut, VME_IOCTL_GET_OUTBOUND, &outWinGetADC);
>     perror("ioctl");
>     if(status < 0){
>         printf("*** ioctl get on outWinGetADC failed. Errno = %d\n", 
> errno);
>         exit (1);
>     }
>
>     /*
>      * Check wheather the get and set configurations are the same
>      */
>
>     getPtr = (u_char *) mmap(0, outWinCfgADC.windowSizeL, 
> PROT_READ|PROT_WRITE, MAP_SHARED, fdOut, 0);
>     perror("mmap");
>     printf("# Start of outbound win in virtual address space of the 
> process: %p\n", getPtr);
>
>     rdPtr = getPtr;
>
>     for(i=0;i<0x100;i++){
>        printf("# Read at address %x = %x\n", rdPtr, *rdPtr);
>        rdPtr++;
>     }
>
>     status = close(fdOut);
>     if(status != 0){
>         printf("*** close() failed. Errno = %d\n", errno);
>         exit (1);
>     }
>    
>     return 0;
> }
>
> __________________________________
> Part of the output:
>
> mmap: Illegal seek
> # Start of outbound win in virtual address space of the process: 
> 0x30029000
> # Read at address 30029000 = ff
> # Read at address 30029001 = ff
> # Read at address 30029002 = ff
> # Read at address 30029003 = ff
> # Read at address 30029004 = ff
> # Read at address 30029005 = ff
> # Read at address 30029006 = ff
> # Read at address 30029007 = ff
> # Read at address 30029008 = ff
> # Read at address 30029009 = ff
> # Read at address 3002900a = ff
> # Read at address 3002900b = ff
>
> and etc.
> ------------------------------------------------------------------------
>
> _______________________________________________
> Linuxppc-embedded mailing list
> [email-masked]
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded