vme_tsi148 question

Martyn Welch martyn.welch at ge.com
Mon Jan 13 12:00:46 UTC 2014


On 07/01/14 16:14, Michael Kenney wrote:
> Hi Martyn,
> 
> On Fri, Dec 27, 2013 at 4:34 PM, Michael Kenney <mfkenney at gmail.com> wrote:
>>
>> Hi Martyn,
>>
>> On Fri, Dec 27, 2013 at 4:23 PM, Martyn Welch <martyn at welchs.me.uk> wrote:
>>> On 27/12/13 20:15, Michael Kenney wrote:
>>>>
>>>> We are using the vme_tsi148 bridge driver along with the vme_user
>>>> driver to access the VME boards. The A/D board requires D32 bus cycles
>>>> and the VME master window is configured accordingly, however, when
>>>> monitoring the bus cycles with a logic analyzer, we noticed that the
>>>> CPU is transferring one byte at a time (i.e. four D8 transfers rather
>>>> than one D32).
>>>>
>>>> Is this the expected behavior of the tsi148 driver?
>>>>
>>>
>>> Hi Mike,
>>>
>>> This is certainly not the expected behaviour - if the window is configured
>>> for D32 then it should do 32 bit transfers where possible.
>>>
>>> I've heard of this happening recently, but haven't yet been able to
>>> replicate it. Which VME board are you running Linux on and which flavour of
>>> Linux?
>>
>> I'm running Debian 7.2 with kernel 3.2 on a Fastwel CPC600 (Pentium M
>> based CPU board).
>>
> 
> Just wanted to touch-base and see if you had any insight as to this
> VME protocol issue with the tsi148. Let me know if there are any
> further tests you would like me to run.
> 

Hi Mike,

I'm a little bemused by this one - I haven't managed to replicate it yet. I
have a feeling that the VME driver in version 3.2 won't use 16-bit transfers
at the beginning of blocks that aren't naturally aligned (it does D8, D8, D8,
D32... rather than D8, D16, D32... but I'm fairly sure it was doing the bulk
of a large transfer correctly).

I've got some test code here you could try (VME address may need modifying to
something more appropriate to you - I have an old PPC board acting as a slave
at 0x8BB00000 in my system). I'm running this on a 3.12 kernel, but this
should work (could you try a newer version of the kernel?):

=== START:test_extended.c ===
#define _XOPEN_SOURCE 500
#define u32 unsigned int
#include <linux/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "vme_user.h"

int main(int argc, char *argv[])
{
        int fd;
        int i;
        int retval;
        unsigned char data[128];
	int loop;

        struct vme_master master;

        fd = open("/dev/bus/vme/m0", O_RDWR);
        if (fd == -1) {
                perror("ERROR: Opening window device file");
                return 1;
        }

        master.enable   = 1;
        master.vme_addr = 0x8BB00000;
        master.size     = 0x10000;
        master.aspace   = 4;			// VME_A32
        master.cycle    = 0x2000 | 0x8000;	// user/data access
        master.dwidth   = 4;			// VME_D32

        retval = ioctl(fd, VME_SET_MASTER, &master);
        if (retval != 0) {
                printf("retval=%d\n", retval);
                perror("ERROR: Failed to configure window");
                return 1;
        }
        for (i=0; i<sizeof(data); i++) {
                data[i] = i;
        }

	retval = pwrite(fd, data, sizeof(data), 0x0);
	if (retval < sizeof(data)) {
		printf("WARNING: Only read %d bytes", retval);
	}

	retval = pread(fd, data, sizeof(data), 0x0);
	if (retval < sizeof(data)) {
		printf("WARNING: Only read %d bytes", retval);
	}

	for(i = 0; i < sizeof(data); i++) {
		if (i % 8 == 0) {
			printf("\n""%4.4x: ", i);
		}
		printf("%2.2x ", data[i]);
	}
	printf("\n");

        close(fd);

        return 0;
}

=== END:test_extended.c ===

=== START: vme_user.h ===
#ifndef _VME_USER_H_
#define _VME_USER_H_

#define VME_USER_BUS_MAX	1

/*
 * VMEbus Master Window Configuration Structure
 */
struct vme_master {
	int enable;			/* State of Window */
	unsigned long long vme_addr;	/* Starting Address on the VMEbus */
	unsigned long long size;	/* Window Size */
	int32_t aspace;			/* Address Space */
	int32_t cycle;			/* Cycle properties */
	int32_t dwidth;			/* Maximum Data Width */
#if 0
	char prefetchEnable;		/* Prefetch Read Enable State */
	int prefetchSize;		/* Prefetch Read Size (Cache Lines) */
	char wrPostEnable;		/* Write Post State */
#endif
};


/*
 * IOCTL Commands and structures
 */

/* Magic number for use in ioctls */
#define VME_IOC_MAGIC 0xAE


/* VMEbus Slave Window Configuration Structure */
struct vme_slave {
	int enable;			/* State of Window */
	unsigned long long vme_addr;	/* Starting Address on the VMEbus */
	unsigned long long size;	/* Window Size */
	int32_t aspace;			/* Address Space */
	int32_t cycle;			/* Cycle properties */
#if 0
	char wrPostEnable;		/* Write Post State */
	char rmwLock;			/* Lock PCI during RMW Cycles */
	char data64BitCapable;		/* non-VMEbus capable of 64-bit Data */
#endif
};

struct vme_irq_id {
	int8_t level;
	int8_t statid;
};

#define VME_GET_SLAVE _IOR(VME_IOC_MAGIC, 1, struct vme_slave)
#define VME_SET_SLAVE _IOW(VME_IOC_MAGIC, 2, struct vme_slave)
#define VME_GET_MASTER _IOR(VME_IOC_MAGIC, 3, struct vme_master)
#define VME_SET_MASTER _IOW(VME_IOC_MAGIC, 4, struct vme_master)
#define VME_IRQ_GEN _IOW(VME_IOC_MAGIC, 5, struct vme_irq_id)

#endif /* _VME_USER_H_ */

=== END: vme_user.h ===

Compiled with "gcc -o test_extended test_extended.c".

When run:

root at ge-xvb601:~/vme_test# ./test_extended

0000: 00 01 02 03 04 05 06 07
0008: 08 09 0a 0b 0c 0d 0e 0f
0010: 10 11 12 13 14 15 16 17
0018: 18 19 1a 1b 1c 1d 1e 1f
0020: 20 21 22 23 24 25 26 27
0028: 28 29 2a 2b 2c 2d 2e 2f
0030: 30 31 32 33 34 35 36 37
0038: 38 39 3a 3b 3c 3d 3e 3f
0040: 40 41 42 43 44 45 46 47
0048: 48 49 4a 4b 4c 4d 4e 4f
0050: 50 51 52 53 54 55 56 57
0058: 58 59 5a 5b 5c 5d 5e 5f
0060: 60 61 62 63 64 65 66 67
0068: 68 69 6a 6b 6c 6d 6e 6f
0070: 70 71 72 73 74 75 76 77
0078: 78 79 7a 7b 7c 7d 7e 7f
root at ge-xvb601:~/vme_test#

I've plugged in an analyser, everything looks good here, 32-bit reads and
writes. I've confirmed that I see 16-bit cycles when I set dwidth to 2.

Martyn

-- 
Martyn Welch (Lead Software Engineer)  | Registered in England and Wales
GE Intelligent Platforms               | (3828642) at 100 Barbirolli Square
T +44(0)1327322748                     | Manchester, M2 3AB
E martyn.welch at ge.com                  | VAT:GB 927559189


More information about the devel mailing list