Messages in this thread | | | Date | Tue, 11 Nov 2008 12:28:22 +0530 | From | Vijay Kumar <> | Subject | Re: sparc/staging compile error |
| |
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@273k.net 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
| |