Re: sparc/staging compile error
From: Vijay Kumar
Date: Tue Nov 11 2008 - 01:48:43 EST
Benjamin Herrenschmidt wrote:
In any case, we would need to understand better your driver userspace
API and transfer model to find the right solution.
Please find below the user space skeleton code, to access the driver. It
was written by Robert Fitzsimons robfitz@xxxxxxxx The driver is based on
this user space interface.
In short, there is a ring buffer that is shared between the _device_ and
_user-space_. The ring buffer has a header, that is shared between the
_kernel_ and _user-space_.
The header specifies the offsets of various buffers in the ring buffer. In
Rx, after user space has read a buffer, the user space writes -1 to the
offset in the header. When the device has filled the buffer, the kernel
space writes the offset back to the header.
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#define G_USED -1
struct group_circular_buffer {
int32_t group_size_bytes;
int32_t group_count;
int32_t group_offset[0];
};
int sysfs_write_long(const char *name, long value);
int sysfs_read_long(const char *name, long *value);
int sysfs_read_buffer(const char *name, void *buffer, int len);
int process_group(void *group, int32_t group_size_bytes);
int main(int argc, char **argv)
{
int uio_fd;
int rx_fd;
int group_index;
long mmap_buffer_size;
struct pollfd poll_fds;
struct group_circular_buffer *ring;
char buffer[128];
/* Query supported device and channels */
sysfs_read_buffer("/sys/.../uioX/name", buffer, sizeof(buffer));
sysfs_read_buffer("/sys/.../uioX/version", buffer, sizeof(buffer));
sysfs_read_buffer("/sys/.../uioX/channels", buffer, sizeof(buffer));
/* Open and mmap UIO device */
uio_fd = open("/dev/.../uioX", O_RDWR);
// uio_mmap = mmap(..., uio_fd, ...); /* map BAR1 */
/* Configure 1 megabyte receive dma buffer */
sysfs_write_long("/sys/.../uioX/rx0/block_size", 512);
sysfs_write_long("/sys/.../uioX/rx0/group_size", 1);
sysfs_write_long("/sys/.../uioX/rx0/group_count", 256);
// configure user firmware, uio_mmap
/* Open rx char device, which allocates suitable dma/mmap buffers */
rx_fd = open("/dev/.../uioX/rx0", O_RDWR);
/* Query size of mmap buffer, maybe use mmap for this value? */
sysfs_read_long("/sys/.../uioX/rx0/mmap_buffer_size", &mmap_buffer_size);
ring = mmap(NULL, mmap_buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED,
rx_fd, 0);
// start/reset capture, uio_mmap
group_index = 0;
while (1) {
if (ring->group_offset[group_index] > 0) {
process_group(ring + ring->group_offset[group_index],
ring->group_size_bytes);
ring->group_offset[group_index] = G_USED;
group_index = (group_index + 1) % ring->group_count;
} else {
poll_fds.fd = rx_fd;
poll_fds.events = POLLIN | POLLERR;
poll_fds.revents = 0;
poll(&poll_fds, 1, -1);
}
}
// stop capture, uio_mmap
// munmap(ring)
// munmap(uio_mmap)
close(rx_fd);
close(uio_fd);
return 0;
}
int sysfs_write_long(const char *name, long value)
{
return 0;
}
int sysfs_read_long(const char *name, long *value)
{
return 0;
}
int sysfs_read_buffer(const char *name, void *buffer, int len)
{
return 0;
}
int process_group(void *group, int32_t group_size_bytes)
{
return 0;
}
Regards,
Vijay
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/