Skip to content
Snippets Groups Projects
Commit 48a83b4e authored by Alessandro Rubini's avatar Alessandro Rubini
Browse files

tools: resurrected specmem

parent 3c17b81d
Branches
Tags
No related merge requests found
......@@ -5,7 +5,7 @@ LDFLAGS = -L. -lspec
LIB = libspec.a
LIBOBJ = speclib.o loader-ll.o
PROGS = spec-cl spec-fwloader spec-vuart # specmem
PROGS = spec-cl spec-fwloader spec-vuart specmem
all: $(LIB) $(PROGS)
......
......@@ -19,10 +19,6 @@
#include "loader-ll.h"
#include "wb_uart.h"
#define BASE_BAR0 0
#define BASE_BAR4 4
struct spec_private {
void *bar0;
void *bar4;
......@@ -90,12 +86,10 @@ static void *spec_map_area(int bus, int dev, int bar, size_t size)
ptr = mmap(NULL, size & ~(getpagesize()-1), PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
close(fd);
if((int)ptr == -1)
{
close(fd);
return NULL;
}
return ptr;
}
......@@ -113,6 +107,17 @@ void *spec_open(int bus, int dev)
return card;
}
void *spec_get_base(void *card, int basenr)
{
struct spec_private *p = card;
if (basenr == BASE_BAR0)
return p->bar0;
if (basenr == BASE_BAR4)
return p->bar4;
return NULL;
}
void spec_close(void *card)
{
struct spec_private *p = (struct spec_private *) card;
......
......@@ -30,4 +30,13 @@ int spec_vuart_init(void *card, uint32_t base_addr);
size_t spec_vuart_rx(void *card, char *buffer, size_t size);
size_t spec_vuart_tx(void *card, char *buffer, size_t size);
/* Get the pointer to access SPEC memory directly */
void *spec_get_base(void *card, int basenr);
enum {
BASE_BAR0 = 0, /* for wrpc etc (but lm32 is at 0x80000 offset) */
BASE_BAR2 = 2,
BASE_BAR4 = 4 /* for gennum-internal registers */
};
#endif
/*
* A tool to read SPEC-internal memory (only BAR0)
*
* Alessandro Rubini 2012 for CERN, GPLv2 or later.
* Alessandro Rubini and Tomasz Wlostowski 2012 for CERN, GPLv2 or later.
*/
#include <stdio.h>
......@@ -13,84 +13,102 @@
#include <fcntl.h>
#include <sys/mman.h>
#include "spec-tools.h"
#include "speclib.h"
void help(char *name)
{
fprintf(stderr,
"Use: \"%s [-b bus] [-d devfn] [-g] <offset> [<value>]\"\n",
name);
fprintf(stderr, "By default, the first available SPEC is used.\n");
exit(1);
}
int main(int argc, char **argv)
{
int i, fd, bar = BASE_BAR0;
uint32_t base, *ptr;
uint32_t uarg[3];
int i, bar = BASE_BAR0;
int bus = -1, dev_fn = -1, c;
uint32_t *ptr;
uint32_t uarg[2];
int do_write;
void *card;
void *map_base;
char *end;
if (argc > 1 && !strcmp(argv[1], "-g")) {
bar = BASE_BAR4;
argv[1] = argv[0];
argc--; argv++;
while ((c = getopt (argc, argv, "b:d:g")) != -1)
{
switch(c)
{
case 'b':
sscanf(optarg, "%i", &bus);
break;
case 'd':
sscanf(optarg, "%i", &dev_fn);
break;
case 'g':
bar = BASE_BAR4;
break;
default:
help(argv[0]);
}
}
if (optind >= argc || optind < argc - 2)
help(argv[0]);
do_write = (optind == argc - 2);
if (argc < 2 || argc > 3) {
fprintf(stderr,
"Use: \"%s [-g] <offset> [<value>]\" "
"(-g selects gennum memory, I/O is 32 bits)\n",
argv[0]);
exit(1);
/* convert the trailing hex number or numbers */
for (i = 0; i <= do_write; i++) {
uarg[i] = strtol(argv[optind + i], &end, 16);
if (end && *end) {
fprintf(stderr, "%s: \"%s\" is not an hex number\n",
argv[0], argv[optind + i]);
exit(1);
}
}
if((fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) {
fprintf(stderr, "%s: open(/dev/mem): %s\n", argv[0],
strerror(errno));
if (uarg[0] & 3) {
fprintf(stderr, "%s: address \"%s\" not multiple of 4\n",
argv[0], argv[1]);
exit(1);
}
base = spec_get_base(bar);
if (base == (typeof(base))-1) {
fprintf(stderr, "%s: spec_get_base(): %s\n", argv[0],
strerror(errno));
exit(1);
}
map_base = mmap(0, 1024 * 1024, /* gennum's bar 0 is 1M */
PROT_READ | PROT_WRITE, MAP_SHARED, fd, base);
if(map_base == (void *) -1) {
fprintf(stderr, "%s: mmap(/dev/mem): %s\n", argv[0],
strerror(errno));
card = spec_open(bus, dev_fn);
if(!card)
{
fprintf(stderr, "Can't detect a SPEC card under the given "
"adress. Make sure a SPEC card is present in your PC "
"and the driver is loaded.\n");
exit(1);
}
for (i = 1; i < argc; i++) {
uarg[i] = strtol(argv[i], &end, 16);
if (end && *end) {
fprintf(stderr, "%s: \"%s\" is not an hex number\n",
argv[0], argv[i]);
exit(1);
}
}
if (uarg[1] & 3) {
fprintf(stderr, "%s: address \"%s\" not multiple of 4\n",
argv[0], argv[1]);
map_base = spec_get_base(card, bar);
if(!map_base || map_base == (void *) -1) {
fprintf(stderr, "%s: mmap(/dev/mem): %s\n", argv[0],
strerror(errno));
exit(1);
}
ptr = map_base + uarg[1];
ptr = map_base + uarg[0];
printf("%p\n", ptr);
/* by default, operate quietly (only report read value) */
if (argc == 2) {
uarg[2] = *ptr;
if (!do_write) {
uarg[1] = *ptr;
if (!getenv("VERBOSE"))
printf("%08x\n", uarg[2]);
printf("%08x\n", uarg[1]);
} else {
*ptr = uarg[2];
*ptr = uarg[1];
}
/* be verbose, if so requested */
if (getenv("VERBOSE")) {
if (argc == 2)
printf("%08x == %08x\n", uarg[1], uarg[2]);
printf("%08x == %08x\n", uarg[0], uarg[1]);
else
printf("%08x := %08x\n", uarg[1], uarg[2]);
printf("%08x := %08x\n", uarg[0], uarg[1]);
}
spec_close(card);
exit (0);
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment