1
0
mirror of https://github.com/bmartini/zynq-axis.git synced 2024-09-05 19:19:27 +08:00
zynq-axis/lib/interface.c
Berin Martini a53998a69d Replace axis_memory_offset function with mem_alloc_state
The functionality of the axis_memory_offset function can be replicated by using
mem_alloc_state while at the same times provides a more powerful interface to
the memory allocation system.

The 1st argument passed to the new mem_alloc_state functions is a pointer to a
void pointer (start) whose value will be overwritten to be the start pointer of
the CMA memory area. The 2nd argument is a pointer to a unsigned int whose
values will be overwritten to be the current 'offset' from that start pointer
and thus represents how many bytes has been allocated.
2015-10-29 14:42:25 +00:00

210 lines
3.9 KiB
C

#include "interface.h"
#include <assert.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#define AXIS_BUS_BYTES 4
#define SRC 0
#define DST 1
static void *cfg;
static char *mem;
unsigned int mem_start = 0;
unsigned int mem_offset = 0;
int axis_init(const char *path)
{
int fd;
FILE *sys_fd;
char sys_path[1024];
char uio_name[1024];
ssize_t len = 0;
assert((fd = open(path, O_RDWR)) >= 0);
// configuration bus memory map
cfg =
mmap(NULL, REGISTER_NB, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (cfg == MAP_FAILED) {
fprintf(stderr,
"ERROR <Memory Map Failed> could not mmap *cfg* memory\n");
assert(0);
}
// dma array memory map
mem = (char *)
mmap(NULL, MEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
sysconf(_SC_PAGESIZE));
if (mem == MAP_FAILED) {
fprintf(stderr,
"ERROR <Memory Map Failed> could not mmap *mem* memory\n");
assert(0);
}
close(fd);
// dma ram start address
if ((len = readlink(path, uio_name, sizeof(uio_name) - 1)) == -1) {
perror("Error cannot resolve uio driver filename");
assert(0);
}
uio_name[len] = '\0';
sprintf(sys_path, "%s%s%s",
"/sys/class/uio/", uio_name, "/maps/map1/addr");
assert((sys_fd = fopen(sys_path, "r")) >= 0);
fscanf(sys_fd, "%x", &mem_start);
fclose(sys_fd);
return 0;
}
int axis_exit()
{
if (munmap(cfg, REGISTER_NB) != 0) {
perror("Error un-mmapping the axis cfg");
return -1;
}
if (munmap(mem, MEM_SIZE) != 0) {
perror("Error un-mmapping the axis mem");
return -1;
}
return 0;
}
void cfg_write(unsigned int addr, unsigned int data)
{
volatile unsigned int *reg = ((volatile unsigned int *)cfg) + addr;
*reg = data;
}
void cfg_write_array(unsigned int addr, unsigned int *data, int length)
{
int xx;
volatile unsigned int *reg = ((volatile unsigned int *)cfg) + addr;
for (xx = 0; xx < length; xx++) {
*reg = data[xx];
}
}
void cfg_write_sequence(unsigned int *addr, unsigned int *data, int length)
{
int xx;
volatile unsigned int *reg = ((volatile unsigned int *)cfg);
for (xx = 0; xx < length; xx++) {
*(reg + addr[xx]) = data[xx];
}
}
int cfg_read(unsigned int addr)
{
volatile unsigned int *reg = ((volatile unsigned int *)cfg) + addr;
return *reg;
}
void cfg_poll(unsigned int addr, unsigned int data)
{
int test = 0;
do {
test = cfg_read(addr);
} while (data > test);
}
void *mem_alloc(const int length, const int byte_nb)
{
assert(mem);
// calculate start of next array
int next_offset = mem_offset + mem_alloc_size(length, byte_nb);
if (MEM_SIZE < next_offset) {
fprintf(stderr,
"ERROR <Out Of Memory> attempted total memory allocation: %i bytes\n",
next_offset);
assert(0);
}
// pointer to new array
void *ptr = &mem[mem_offset];
// update memory pointer to the next free area
mem_offset = next_offset;
return ptr;
}
int mem_alloc_size(const int length, const int byte_nb)
{
assert(length);
assert(byte_nb);
int size = length * byte_nb;
int remainder = size % 8;
if (0 != remainder) {
size = size + 8 - remainder;
}
return size;
}
int mem_alloc_length(const int length, const int byte_nb)
{
assert(length);
assert(byte_nb);
return (mem_alloc_size(length, byte_nb) / byte_nb);
}
void mem_alloc_state(void **start, unsigned int *offset)
{
assert(mem);
assert(start);
assert(offset);
*start = &mem[0];
*offset = mem_offset;
}
unsigned int axis_port_id(const int index, const int dirc)
{
assert(index >= 0);
assert((dirc == SRC) || (dirc == DST));
return ((2 * index) + (dirc + 1));
}
unsigned int axis_memory_addr(void *ptr)
{
assert(((char *)ptr) >= mem);
assert(((char *)ptr) < (mem + MEM_SIZE));
return (mem_start + ((unsigned int)ptr) - ((unsigned int)mem));
}
unsigned int axis_stream_length(const int length, const int byte_nb)
{
assert(length);
assert(byte_nb);
int size = length * byte_nb;
int remainder = size % AXIS_BUS_BYTES;
if (0 != remainder) {
size = size + AXIS_BUS_BYTES - remainder;
}
return (size / AXIS_BUS_BYTES);
}