mirror of
https://github.com/bmartini/zynq-axis.git
synced 2024-09-05 19:19:27 +08:00
This change makes a clear distention of the physical address and the user space address for the memory array. It also scopes the variables to the file so they will not be exported in the object file which can cause naming conflicts in programs that use it.
210 lines
4.0 KiB
C
210 lines
4.0 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;
|
|
static unsigned int phy_addr = 0;
|
|
static unsigned int mem_current = 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", &phy_addr);
|
|
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 mem_next = mem_current + mem_alloc_size(length, byte_nb);
|
|
|
|
if (MEM_SIZE < mem_next) {
|
|
fprintf(stderr,
|
|
"ERROR <Out Of Memory> attempted total memory allocation: %i bytes\n",
|
|
mem_next);
|
|
assert(0);
|
|
}
|
|
// pointer to new array
|
|
void *ptr = &mem[mem_current];
|
|
|
|
// update memory pointer to the next free area
|
|
mem_current = mem_next;
|
|
|
|
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_current;
|
|
}
|
|
|
|
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 (phy_addr + ((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);
|
|
}
|