Last active
March 26, 2019 13:52
-
-
Save osamutake/c0ca68ddd369710e1e46ce9ce82a5988 to your computer and use it in GitHub Desktop.
Command for manipulating generic-uio
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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