Skip to content

Instantly share code, notes, and snippets.

@osamutake
Last active March 26, 2019 13:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save osamutake/c0ca68ddd369710e1e46ce9ce82a5988 to your computer and use it in GitHub Desktop.
Save osamutake/c0ca68ddd369710e1e46ce9ce82a5988 to your computer and use it in GitHub Desktop.
Command for manipulating generic-uio
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>
#include "uio.h"
int sys_read_numerical_string(const char path[], unsigned int *p_result)
{
FILE *fp;
char buffer[128];
fp = fopen(path, "r");
if (!fp) {
perror(path);
return -1;
}
if(fscanf(fp, "0x%08X", p_result)==EOF) {
perror("fscanf");
return -1;
};
fclose(fp);
return 0;
}
volatile unsigned int *uio_access(UIO *uio)
{
return uio->pointer;
}
int uio_close(UIO *uio)
{
int result = munmap((void*)uio->pointer, uio->size) | close(uio->fd);
if (result) perror("uio_close");
free(uio);
return result;
}
UIO *uio_open(int uio_n)
{
char text_buffer[128];
int fd;
volatile unsigned int *uio_reg;
unsigned int offset, size;
UIO *uio;
if (snprintf(text_buffer, sizeof(text_buffer), "/sys/class/uio/uio%d/maps/map0/offset", uio_n) < 0) {
perror("uio number out of range");
return NULL;
}
if (sys_read_numerical_string(text_buffer, &offset) != 0) {
return NULL;
}
if (offset % sysconf(_SC_PAGE_SIZE) != 0) {
fprintf(stderr, "offset must be integer multiple of _SC_PAGE_SIZE = 0x%#lx\n", sysconf(_SC_PAGE_SIZE));
return NULL;
}
if (snprintf(text_buffer, sizeof(text_buffer), "/sys/class/uio/uio%d/maps/map0/size", uio_n) < 0) {
perror("uio number out of range");
return NULL;
}
if (sys_read_numerical_string(text_buffer, &size) != 0) {
return NULL;
}
if (size % sysconf(_SC_PAGE_SIZE) != 0) {
fprintf(stderr, "length must be integer multiple of _SC_PAGE_SIZE = 0x%#lx\n", sysconf(_SC_PAGE_SIZE));
return NULL;
}
if (snprintf(text_buffer, sizeof(text_buffer), "/dev/uio%d", uio_n) < 0) {
perror("uio number out of range");
return NULL;
}
if ((fd = open(text_buffer, O_RDWR | O_SYNC)) < 0) {
perror("open");
return NULL;
}
uio_reg = (volatile unsigned int*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
if (uio_reg == MAP_FAILED) {
perror("mmap");
close(fd);
return NULL;
}
uio = (UIO*)malloc(sizeof(UIO));
if (!uio) {
perror("malloc");
return NULL;
}
uio->pointer = uio_reg;
uio->fd = fd;
uio->size = size;
return uio;
}
#ifndef _UIO_H
#define _UIO_H
typedef struct UIO_tag {
volatile unsigned int *pointer;
int fd;
unsigned int size;
} UIO;
UIO *uio_open(int uio_n);
volatile unsigned int *uio_access(UIO *uio);
int uio_close(UIO *uio);
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "uio.h"
int my_str2num(const char str[], unsigned int *num)
{
unsigned int value;
char *p;
if (strlen(str)>2 && str[0]=='0' && ((str[1]=='x')||str[1]=='X')) {
// hex
value = strtol(str+2, &p, 16);
} else {
// dec
value = strtol(str, &p, 10);
}
if (*p==0) {
*num = value;
return 0;
} else {
fprintf(stderr, "ERROR: Irregal number \"%s\" was given.\n", str);
return 1; // error
}
}
int show_usage()
{
fprintf(stderr, "USAGE: uio uio_num byte_offset [value]\n");
return -1;
}
int main(int argc, const char *argv[])
{
int uio_n, addr, value, write = 0;
UIO *uio;
if (argc!=3 && argc!=4) {
return show_usage();
} else
if (my_str2num(argv[1], &uio_n)) {
return 1;
} else
if (my_str2num(argv[2], &addr)) {
return 1;
} else
if (argc==4) {
if (my_str2num(argv[3], &value)) {
return 1;
}
write = 1;
}
if (addr % 4 != 0) {
fprintf(stderr, "byte_offset should be an integer multiple of four.\n");
return 1;
}
uio = uio_open(uio_n);
if (!uio) {
return 1;
}
if (write) {
uio_access(uio)[addr/4] = value;
} else {
printf("0x%08x\n", uio_access(uio)[addr/4]);
}
uio_close(uio);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment