Add userspace tools for SPEC7, derived from the original SPEC ones

parent e2992685
libspec.a
libspec.so
spec-cl
specmem
spec-fwloader
spec-vuart
# If it exists includes Makefile.specific. In this Makefile, you should put
# specific Makefile code that you want to run before this. For example,
# build a particular environment.
-include Makefile.specific
# include parent_common.mk for buildsystem's defines
#REPO_PARENT=../..
#-include $(REPO_PARENT)/parent_common.mk
GIT_VERSION ?= $(shell git describe --dirty --long --tags)
CFLAGS += -ggdb -Wall -fPIC -I../kernel $(EXTRACFLAGS)
CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\"
INSTALL = install
DESTDIR =
PREFIX = /usr/local
BINDIR = $(PREFIX)/sbin
LIBDIR = $(PREFIX)/lib
LIB = libspec.a
LIBOBJ = speclib.o
LIBSHARED = libspec.so
PROGS = spec-fwloader spec-vuart spec-cl specmem
all: $(LIB) $(PROGS) $(LIBSHARED)
$(PROGS): $(LIB)
$(LIB): $(LIBOBJ)
$(AR) r $@ $^
$(LIBSHARED): $(LIB)
$(CC) -shared -o $@ -Wl,--whole-archive $^ -Wl,--no-whole-archive
install:
$(INSTALL) -d $(DESTDIR)$(BINDIR)
$(INSTALL) -m 0755 -t $(DESTDIR)$(BINDIR) $(PROGS)
$(INSTALL) -d $(DESTDIR)$(LIBDIR)
$(INSTALL) -m 0755 -t $(DESTDIR)$(LIBDIR) $(LIB)
$(INSTALL) -m 0755 -t $(DESTDIR)$(LIBDIR) $(LIBOBJ)
$(INSTALL) -m 0755 -t $(DESTDIR)$(LIBDIR) $(LIBSHARED)
clean:
rm -f *.o $(LIB) $(PROGS) $(LIBSHARED) *~
# add the other unused targets, so the rule in ../Makefile works
modules modules_install:
/*
* A tool to program our soft-core (LM32) within the SPEC.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <getopt.h>
#include "speclib.h"
static char git_version[] = "version: " GIT_VERSION;
static void print_version(char *pname)
{
printf("%s %s\n", pname, git_version);
printf("%s\n", libspec_version_s);
}
int main(int argc, char **argv)
{
int bus = -1, dev_fn = -1, c;
uint32_t lm32_base = 0x80000;
void *card;
while ((c = getopt (argc, argv, "b:d:c:V")) != -1)
{
switch(c)
{
case 'b':
sscanf(optarg, "%i", &bus);
break;
case 'd':
sscanf(optarg, "%i", &dev_fn);
break;
case 'c':
sscanf(optarg, "%i", &lm32_base);
break;
case 'V':
print_version(argv[0]);
exit(0);
default:
fprintf(stderr,
"Use: \"%s [-V] [-b bus] [-d devfn] "
"[-c lm32 base address] <lm32_program.bin>\"\n",
argv[0]);
fprintf(stderr,
"By default, the first available SPEC is used "
"and the LM32 is assumed at 0x%x.\n",
lm32_base);
exit(1);
}
}
if (optind >= argc) {
fprintf(stderr, "%s: Expected binary name after options.\n",
argv[0]);
exit(1);
}
card = spec_open(bus, dev_fn);
if(!card)
{
fprintf(stderr, "%s: Can't detect a SPEC card under the given "
"adress.\nMake sure a SPEC card is present in your PC, "
"the driver is loaded and you run the program as root.\n", argv[0]);
exit(1);
}
if(spec_load_lm32(card, argv[optind], lm32_base) < 0)
{
fprintf(stderr, "%s: Loader failure.\n", argv[0]);
exit(1);
}
spec_close(card);
exit (0);
}
/*
* A tool to program the FPGA within the SPEC.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <getopt.h>
#include "speclib.h"
static char git_version[] = "version: " GIT_VERSION;
static void print_version(char *pname)
{
printf("%s %s\n", pname, git_version);
printf("%s\n", libspec_version_s);
}
int main(int argc, char **argv)
{
int bus = -1, dev_fn = -1, c;
void *card;
while ((c = getopt (argc, argv, "b:d:V")) != -1)
{
switch(c)
{
case 'b':
sscanf(optarg, "%i", &bus);
break;
case 'd':
sscanf(optarg, "%i", &dev_fn);
break;
case 'V':
print_version(argv[0]);
exit(0);
default:
fprintf(stderr,
"Use: \"%s [-V] [-b bus] [-d devfn] "
"<fpga_bitstream.bin>\"\n", argv[0]);
fprintf(stderr, "By default, the first available SPEC "
"is used.\n");
exit(1);
}
}
if (optind >= argc) {
fprintf(stderr, "Expected binary name after options.\n");
exit(1);
}
card = spec_open(bus, dev_fn);
if(!card)
{
fprintf(stderr, "Can't detect a SPEC card under the given "
"adress.\nMake sure a SPEC card is present in your PC, "
"the driver is loaded and you run the program as root.\n");
exit(1);
}
if(spec_load_bitstream(card, argv[optind]) < 0)
{
fprintf(stderr, "Loader failure.\n");
exit(1);
}
spec_close(card);
exit (0);
}
/* A simple console for accessing the SPEC virtual UART (i.e. for communicating with the WR Core shell
from a Linux terminal. */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <string.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <getopt.h>
#include <errno.h>
#include "speclib.h"
#define VUART_BASE_WRC 0x20500
#define VUART_BASE_ZYNQ 0x80000
static char git_version[] = "version: " GIT_VERSION;
static void print_version(char *pname)
{
printf("%s %s\n", pname, git_version);
printf("%s\n", libspec_version_s);
}
static void *card;
static int transfer_byte(int from, int is_control, int vuart_zynq) {
char c;
int ret;
do {
ret = read(from, &c, 1);
} while (ret < 0 && errno == EINTR);
if(ret == 1) {
if(is_control) {
if(c == '\x01') { // C-a
return -1;
}
}
spec_vuart_tx(card, &c, 1, vuart_zynq);
} else {
fprintf(stderr, "nothing to read. Port disconnected?\n");
return -2;
}
return 0;
}
void term_main(int keep_term, int vuart_zynq)
{
struct termios oldkey, newkey;
//above is place for old and new port settings for keyboard teletype
int need_exit = 0;
fprintf(stderr, "[press C-a to exit]\n");
if(!keep_term) {
tcgetattr(STDIN_FILENO,&oldkey);
if(vuart_zynq) {
newkey.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
} else {
newkey.c_cflag = B9600 | CS8 | CLOCAL | CREAD;
}
newkey.c_iflag = IGNPAR;
newkey.c_oflag = 0;
newkey.c_lflag = 0;
newkey.c_cc[VMIN]=1;
newkey.c_cc[VTIME]=0;
tcflush(STDIN_FILENO, TCIFLUSH);
tcsetattr(STDIN_FILENO,TCSANOW,&newkey);
}
while(!need_exit) {
fd_set fds;
int ret;
char rx;
int period;
if(vuart_zynq) {
period = 1000;
} else {
period = 10000;
}
struct timeval tv = {0, period};
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
ret = select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
if(ret == -1) {
perror("select");
} else if (ret > 0) {
if(FD_ISSET(STDIN_FILENO, &fds)) {
need_exit = transfer_byte(STDIN_FILENO, 1, vuart_zynq);
}
}
while((spec_vuart_rx(card, &rx, 1, vuart_zynq)) == 1)
fprintf(stderr,"%c", rx);
}
if(!keep_term)
tcsetattr(STDIN_FILENO,TCSANOW,&oldkey);
}
int main(int argc, char **argv)
{
int bus = -1, dev_fn = -1, c;
uint32_t vuart_base;
int vuart_base_override = 0;
int keep_term = 0;
int vuart_zynq = 0;
while ((c = getopt (argc, argv, "b:d:u:zkV")) != -1)
{
switch(c)
{
case 'b':
sscanf(optarg, "%i", &bus);
break;
case 'd':
sscanf(optarg, "%i", &dev_fn);
break;
case 'z':
vuart_zynq = 1;
break;
case 'u':
sscanf(optarg, "%i", &vuart_base);
vuart_base_override = 1;
break;
case 'k':
keep_term = 1;
break;
case 'V':
print_version(argv[0]);
exit(0);
default:
fprintf(stderr,
"Use: \"%s [-V] [-b bus] [-d devfn] [-z] "
"[-u VUART base] [-k]\"\n", argv[0]);
fprintf(stderr,
"By default, the first available SPEC is used.\n"
"-z option connects to the Zynq UART, WRC otherwise.\n"
"-u overrides the VUART base address, default:\n"
" default base address for WRC UART: 0x%x\n"
" default base address for Zynq UART: 0x%x\n"
"-k option keeps the prev terminal config\n",
VUART_BASE_WRC, VUART_BASE_ZYNQ);
exit(1);
}
}
card = spec_open(bus, dev_fn);
if(!card)
{
fprintf(stderr, "Can't detect a SPEC card under the given "
"adress.\nMake sure a SPEC card is present in your PC, "
"the driver is loaded and you run the program as root.\n");
exit(1);
}
if(!vuart_base_override) {
if(vuart_zynq)
vuart_base = VUART_BASE_ZYNQ;
else
vuart_base = VUART_BASE_WRC;
}
spec_vuart_init(card, vuart_base);
if(vuart_zynq) {
spec_vuart_clear(card);
}
term_main(keep_term, vuart_zynq);
spec_close(card);
return 0;
}
/*
* Trivial library function to return one of the spec memory addresses
*/
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <errno.h>
#include <sys/signal.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include "speclib.h"
#include "wb_uart.h"
const char * const libspec_version_s = "libspec version: " GIT_VERSION;
struct spec_private {
/* BAR0 maps the local bus (i.e. we can access FGPA register) */
void *bar0;
/* BAR4 maps the XDMA Bypass zone */
void *bar4;
uint32_t vuart_base;
};
/*
* Check if the PCI device at bus/def_fn is a SPEC board.
* Return 1 if the device is a SPEC and 0 if it is not.
* If there is an error accessing the files, return -1
*/
static int spec_check_id(int bus, int dev)
{
unsigned int vendor, device;
char buf[128];
FILE *f;
// check device
snprintf(buf, sizeof buf,
"/sys/bus/pci/devices/0000:%02x:%02x.0/device",
bus, dev);
f=fopen(buf,"r");
if (f==NULL){
fprintf(stderr,"error accessing to file\n");
return -1;
}
fscanf(f, "%x", &device);
fclose(f);
// check vendor
snprintf(buf, sizeof buf,
"/sys/bus/pci/devices/0000:%02x:%02x.0/vendor",
bus, dev);
f=fopen(buf,"r");
if (f==NULL){
fprintf(stderr,"error accessing to file\n");
return -1;
}
fscanf(f, "%x", &vendor);
fclose(f);
//fprintf(stderr, "Detected: device: %x, vendor: %x\n", device, vendor);
//fprintf(stderr, "Hardcoded: device: %x, vendor: %x\n", PCI_DEVICE_ID_SPEC7, PCI_VENDOR_ID_SPEC7);
if (device== PCI_DEVICE_ID_SPEC7 && vendor== PCI_VENDOR_ID_SPEC7)
return 1;
return 0;
}
/*
* Checks if there's a SPEC card at bus/def_fn.
* If one (or both) parameters are < 0, takes first available card
* and returns 0. If no cards have been detected, returns -1
*/
static int spec_scan(int *bus, int *devfn)
{
struct dirent **namelist;
int n, i, found = 0, ret;
int my_bus, my_devfn;
// Automatic search for the first availabe card
n = scandir("/sys/bus/pci/devices/", &namelist, 0, 0);
if (n < 0)
{
perror("scandir");
exit(-1);
}
for (i = 0; i < n; i++)
{
ret = sscanf(namelist[i]->d_name, "0000:%02x:%02x.0",
&my_bus, &my_devfn);
if(!found && ret == 2)
{
if (*bus >= 0)
my_bus = *bus;
if (*devfn >= 0)
my_devfn = *devfn;
if (spec_check_id(my_bus, my_devfn) > 0)
{
*bus = my_bus;
*devfn = my_devfn;
found = 1;
}
}
free(namelist[i]);
}
free(namelist);
if(!found)
{
fprintf(stderr,"Can't detect any SPEC card :(\n");
return -1;
}
return 0;
}
/* Maps a particular BAR of given SPEC card and returns its virtual address
(or NULL in case of failure) */
static void *spec_map_area(int bus, int dev, int bar, size_t size)
{
char path[1024];
int fd;
void *ptr;
snprintf(path, sizeof(path), "/sys/bus/pci/devices/"
"/0000:%02x:%02x.0/resource%d", bus, dev, bar);
fd = open(path, O_RDWR | O_SYNC);
if(fd <= 0)
return NULL;
ptr = mmap(NULL, size & ~(getpagesize()-1), PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
close(fd);
if((long)ptr == -1)
return NULL;
return ptr;
}
void *spec_open(int bus, int dev)
{
struct spec_private *card = malloc(sizeof(struct spec_private));
if(!card || spec_scan(&bus, &dev) < 0)
return NULL;
card->bar0 = spec_map_area(bus, dev, BASE_BAR0, 0x100000);
card->bar4 = spec_map_area(bus, dev, BASE_BAR4, 0x1000000);
if(!card->bar0 && !card->bar4)
{
free(card);
card = NULL;
}
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;
if(!card)
return;
munmap(p->bar0, 0x100000);
munmap(p->bar4, 0x1000000);
free(card);
}
void spec_writel(void *card, uint32_t data, uint32_t addr)
{
struct spec_private *p = (struct spec_private *) card;
*(volatile uint32_t *) (p->bar0 + addr) = data;
}
uint32_t spec_readl(void *card, uint32_t addr)
{
struct spec_private *p = (struct spec_private *) card;
return *(volatile uint32_t *) (p->bar0 + addr);
}
static int vuart_wb_rx(void *card)
{
struct spec_private *p = (struct spec_private *) card;
int rdr = spec_readl(card, p->vuart_base + UART_REG_HOST_RDR);
if(rdr & UART_HOST_RDR_RDY)
return UART_HOST_RDR_DATA_R(rdr);
else
return -1;
}
static int vuart_lite_rx(void *card)
{
struct spec_private *p = (struct spec_private *) card;
int rx_status = spec_readl(card, p->vuart_base + UARTLITE_REG_SR);
int rx_data;
if(rx_status & UARTLITE_SR_RX_RDY)
{
rx_data = spec_readl(card, p->vuart_base + UARTLITE_REG_HOST_RDR);
return UART_HOST_RDR_DATA_R(rx_data);
}
else
return -1;
}
static int vuart_rx(void *card, int vuart_zynq)
{
if(vuart_zynq)
return vuart_lite_rx(card);
else
return vuart_wb_rx(card);
}
static void vuart_wb_tx(void *card, int c)
{
struct spec_private *p = (struct spec_private *) card;
while( spec_readl(card, p->vuart_base + UART_REG_SR) & UART_SR_RX_RDY);
spec_writel(card, UART_HOST_TDR_DATA_W(c),
p->vuart_base + UART_REG_HOST_TDR);
}
static void vuart_lite_tx(void *card, int c)
{
struct spec_private *p = (struct spec_private *) card;
while( spec_readl(card, p->vuart_base + UARTLITE_REG_SR) & UARTLITE_SR_TX_BUSY);
spec_writel(card, UART_HOST_TDR_DATA_W(c),
p->vuart_base + UARTLITE_REG_HOST_TDR);
}
static void vuart_tx(void *card, int c, int vuart_zynq)
{
if(vuart_zynq)
vuart_lite_tx(card, c);
else
vuart_wb_tx(card, c);
}
static char *load_binary_file(const char *filename, size_t *size)
{
int i;
struct stat stbuf;
char *buf;
FILE *f;
f = fopen(filename, "r");
if (!f) {
fprintf(stderr, "%s: %s\n", filename, strerror(errno));
return NULL;
}
if (fstat(fileno(f), &stbuf) < 0) {
fprintf(stderr, "%s: %s\n", filename, strerror(errno));
fclose(f);
return NULL;
}
if (!S_ISREG(stbuf.st_mode)) {
fprintf(stderr, "%s: not a regular file\n", filename);
fclose(f);
return NULL;
}
buf = malloc(stbuf.st_size);
if (!buf) {
fprintf(stderr, "loading %s: %s\n", filename, strerror(errno));
fclose(f);
return NULL;
}
i = fread(buf, 1, stbuf.st_size, f);
fclose(f);
if (i < 0) {
fprintf(stderr, "reading %s: %s\n", filename, strerror(errno));
free(buf);
return NULL;
}
if (i != stbuf.st_size) {
fprintf(stderr, "%s: short read\n", filename);
free(buf);
return NULL;
}
*size = stbuf.st_size;
return buf;
}
int spec_load_bitstream(void *card, const char *filename)
{
char *buf;
uint32_t *ibuf;
size_t size;
int i;
struct spec_private *p = (struct spec_private *) card;
buf = load_binary_file(filename, &size);
if(!buf)
return -1;
ibuf = (uint32_t *) buf;
for (i = 0; i < (size + 3) / 4; i++)
*(volatile uint32_t *) (p->bar4 + i*4) = ibuf[i];
sync();
for (i = 0; i < (size + 3) / 4; i++) {
uint32_t r = *(volatile uint32_t *) (p->bar4 + i*4);
if (r != ibuf[i])
{
fprintf(stderr, "programming error at %x "
"(expected %08x, found %08x)\n", i*4,
ibuf[i], r);
return -1;
}
}
sync();
free(buf);
return 0;
}
int spec_load_lm32(void *card, const char *filename, uint32_t base_addr)
{
char *buf;
uint32_t *ibuf;
size_t size;
int i;
buf = load_binary_file(filename, &size);
if(!buf)
return -1;
/* Phew... we are there, finally */
spec_writel(card, 0x1deadbee, base_addr + 0x20400);
while ( ! (spec_readl(card, base_addr + 0x20400) & (1<<28)) );
ibuf = (uint32_t *) buf;
for (i = 0; i < (size + 3) / 4; i++)
spec_writel(card, htonl(ibuf[i]), base_addr + i*4);
sync();
for (i = 0; i < (size + 3) / 4; i++) {
uint32_t r = spec_readl(card, base_addr + i * 4);
if (r != htonl(ibuf[i]))
{
fprintf(stderr, "programming error at %x "
"(expected %08x, found %08x)\n", i*4,
htonl(ibuf[i]), r);
return -1;
}
}
sync();
spec_writel(card, 0x0deadbee, base_addr + 0x20400);
return 0;
}
int spec_vuart_init(void *card, uint32_t base_addr)
{
struct spec_private *p = (struct spec_private *) card;
p->vuart_base = base_addr;
return 0;
}
int spec_vuart_clear(void *card)
{
// Clear TX and RX buffers in UARTLite
struct spec_private *p = (struct spec_private *) card;
spec_writel(card, 0x3,
p->vuart_base + UARTLITE_REG_CR);
return 0;
}
size_t spec_vuart_rx(void *card, char *buffer, size_t size, int vuart_zynq)
{
size_t s = size, n_rx = 0;
while(s--)
{
int c = vuart_rx(card, vuart_zynq);
if(c < 0)
return n_rx;
*buffer++ = c;
n_rx ++;
}
return n_rx;
}
size_t spec_vuart_tx(void *card, char *buffer, size_t size, int vuart_zynq)
{
size_t s = size;
while(s--)
vuart_tx(card, *buffer++, vuart_zynq);
return size;
}
#ifndef __SPECLIB_H
#define __SPECLIB_H
#include <stdint.h>
/* Vendor/Device ID to identify the SPEC */
#define PCI_VENDOR_ID_CERN 0x10dc
#define PCI_DEVICE_ID_SPEC_45T 0x018d
#define PCI_DEVICE_ID_SPEC_100T 0x01a2
#define PCI_VENDOR_ID_GENNUM 0x1a39
#define PCI_DEVICE_ID_GN4124 0x0004
#define PCI_VENDOR_ID_SPEC7 0x10ee
#define PCI_DEVICE_ID_SPEC7 0x7022
/* For compatibility */
#define PCI_DEVICE_ID_SPEC PCI_DEVICE_ID_SPEC_45T
/* 'Opens' the SPEC card at PCI bus [bus], device/function [dev].
Returns a handle to the card or NULL in case of failure. */
void *spec_open(int bus, int dev);
/* Closes the SPEC handle [card] */
void spec_close(void *card);
/* Loads the FPGA bitstream into card [card] from file [filename].
Returns 0 on success. */
int spec_load_bitstream(void *card, const char *filename);
/* Load the FPGA bitstram into car [card] from a given buffer [buf]
of size [size] */
int spec_load_bitstream_buffer(void *card, void *buf, size_t size);
/* Loads the WRC LM32 firmware into card [card] from file [filename]. starting at
address [base_addr]. Returns 0 on success.
WARNING: using improper base address/FPGA firmware will freeze the computer. */
int spec_load_lm32(void *card, const char *filename, uint32_t base_addr);
/* Raw I/O to BAR4 (Wishbone) */
void spec_writel(void *card, uint32_t data, uint32_t addr);
uint32_t spec_readl(void *card, uint32_t addr);
/* Initializes a virtual UART at base address [base_addr]. */
int spec_vuart_init(void *card, uint32_t base_addr);
/* Clear the TX/RX buffers of a virtual UART. */
int spec_vuart_clear(void *card);
/* Virtual uart Rx (VUART->Host) and Tx (Host->VUART) functions */
size_t spec_vuart_rx(void *card, char *buffer, size_t size, int vuart_zynq);
size_t spec_vuart_tx(void *card, char *buffer, size_t size, int vuart_zynq);
/* 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 DMA Bypass access */
};
/* libspec version string */
extern const char * const libspec_version_s;
#endif
/*
* A tool to read SPEC-internal memory (only BAR0)
*
* Alessandro Rubini and Tomasz Wlostowski 2012 for CERN, GPLv2 or later.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "speclib.h"
static char git_version[] = "version: " GIT_VERSION;
void help(char *name)
{
fprintf(stderr,
"Use: \"%s [-V] [-b bus] [-d devfn] [-g] <offset> [<value>]\"\n",
name);
fprintf(stderr, "By default, the first available SPEC is used.\n");
exit(1);
}
static void print_version(char *pname)
{
printf("%s %s\n", pname, git_version);
printf("%s\n", libspec_version_s);
}
int main(int argc, char **argv)
{
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;
while ((c = getopt (argc, argv, "b:d:gV")) != -1)
{
switch(c)
{
case 'b':
sscanf(optarg, "%i", &bus);
break;
case 'd':
sscanf(optarg, "%i", &dev_fn);
break;
case 'V':
print_version(argv[0]);
exit(0);
default:
help(argv[0]);
}
}
if (optind >= argc || optind < argc - 2)
help(argv[0]);
do_write = (optind == argc - 2);
/* 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 (uarg[0] & 3) {
fprintf(stderr, "%s: address \"%s\" not multiple of 4\n",
argv[0], argv[optind + 0]);
exit(1);
}
card = spec_open(bus, dev_fn);
if (!card) {
fprintf(stderr, "%s: No SPEC card at bus %i, devfn %i\n",
argv[0], bus, dev_fn);
fprintf(stderr, " please make sure the address is correct,\n"
" spec.ko is loaded and you run as superuser.\n");
exit(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[0];
/* by default, operate quietly (only report read value) */
if (!do_write) {
uarg[1] = *ptr;
if (!getenv("VERBOSE"))
printf("%08x\n", uarg[1]);
} else {
*ptr = uarg[1];
}
/* be verbose, if so requested */
if (getenv("VERBOSE")) {
if (argc == 2)
printf("%08x == %08x\n", uarg[0], uarg[1]);
else
printf("%08x := %08x\n", uarg[0], uarg[1]);
}
spec_close(card);
exit (0);
}
/*
Register definitions for slave core: Simple Wishbone UART
* File : wb_uart.h
* Author : auto-generated by wbgen2 from simple_uart_wb.wb
* Created : Thu May 3 17:36:38 2012
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE simple_uart_wb.wb
DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
*/
#ifndef __WBGEN2_REGDEFS_SIMPLE_UART_WB_WB
#define __WBGEN2_REGDEFS_SIMPLE_UART_WB_WB
#include <inttypes.h>
#if defined( __GNUC__)
#define PACKED __attribute__ ((packed))
#else
#error "Unsupported compiler?"
#endif
#ifndef __WBGEN2_MACROS_DEFINED__
#define __WBGEN2_MACROS_DEFINED__
#define WBGEN2_GEN_MASK(offset, size) (((1<<(size))-1) << (offset))
#define WBGEN2_GEN_WRITE(value, offset, size) (((value) & ((1<<(size))-1)) << (offset))
#define WBGEN2_GEN_READ(reg, offset, size) (((reg) >> (offset)) & ((1<<(size))-1))
#define WBGEN2_SIGN_EXTEND(value, bits) (((value) & (1<<bits) ? ~((1<<(bits))-1): 0 ) | (value))
#endif
/* definitions for register: Status Register */
/* definitions for field: TX busy in reg: Status Register */
#define UART_SR_TX_BUSY WBGEN2_GEN_MASK(0, 1)
/* definitions for field: RX ready in reg: Status Register */
#define UART_SR_RX_RDY WBGEN2_GEN_MASK(1, 1)
/* definitions for register: Baudrate control register */
/* definitions for register: Transmit data regsiter */
/* definitions for field: Transmit data in reg: Transmit data regsiter */
#define UART_TDR_TX_DATA_MASK WBGEN2_GEN_MASK(0, 8)
#define UART_TDR_TX_DATA_SHIFT 0
#define UART_TDR_TX_DATA_W(value) WBGEN2_GEN_WRITE(value, 0, 8)
#define UART_TDR_TX_DATA_R(reg) WBGEN2_GEN_READ(reg, 0, 8)
/* definitions for register: Receive data regsiter */
/* definitions for field: Received data in reg: Receive data regsiter */
#define UART_RDR_RX_DATA_MASK WBGEN2_GEN_MASK(0, 8)
#define UART_RDR_RX_DATA_SHIFT 0
#define UART_RDR_RX_DATA_W(value) WBGEN2_GEN_WRITE(value, 0, 8)
#define UART_RDR_RX_DATA_R(reg) WBGEN2_GEN_READ(reg, 0, 8)
/* definitions for register: Host VUART Tx register */
/* definitions for field: TX Data in reg: Host VUART Tx register */
#define UART_HOST_TDR_DATA_MASK WBGEN2_GEN_MASK(0, 8)
#define UART_HOST_TDR_DATA_SHIFT 0
#define UART_HOST_TDR_DATA_W(value) WBGEN2_GEN_WRITE(value, 0, 8)
#define UART_HOST_TDR_DATA_R(reg) WBGEN2_GEN_READ(reg, 0, 8)
/* definitions for field: TX Ready in reg: Host VUART Tx register */
#define UART_HOST_TDR_RDY WBGEN2_GEN_MASK(8, 1)
/* definitions for register: Host VUART Rx register */
/* definitions for field: RX Data in reg: Host VUART Rx register */
#define UART_HOST_RDR_DATA_MASK WBGEN2_GEN_MASK(0, 8)
#define UART_HOST_RDR_DATA_SHIFT 0
#define UART_HOST_RDR_DATA_W(value) WBGEN2_GEN_WRITE(value, 0, 8)
#define UART_HOST_RDR_DATA_R(reg) WBGEN2_GEN_READ(reg, 0, 8)
/* definitions for field: RX Ready in reg: Host VUART Rx register */
#define UART_HOST_RDR_RDY WBGEN2_GEN_MASK(8, 1)
/* definitions for field: RX FIFO Count in reg: Host VUART Rx register */
#define UART_HOST_RDR_COUNT_MASK WBGEN2_GEN_MASK(9, 16)
#define UART_HOST_RDR_COUNT_SHIFT 9
#define UART_HOST_RDR_COUNT_W(value) WBGEN2_GEN_WRITE(value, 9, 16)
#define UART_HOST_RDR_COUNT_R(reg) WBGEN2_GEN_READ(reg, 9, 16)
#define UART_REG_SR 0x0
#define UART_REG_HOST_TDR 0x10
#define UART_REG_HOST_RDR 0x14
/* Xilinx UARTLite stuff */
/* definitions for field: TX busy in reg: Status Register */
#define UARTLITE_SR_TX_BUSY WBGEN2_GEN_MASK(3, 1)
/* definitions for field: RX ready in reg: Status Register */
#define UARTLITE_SR_RX_RDY WBGEN2_GEN_MASK(0, 1)
#define UARTLITE_REG_CR 0xc
#define UARTLITE_REG_SR 0x8
#define UARTLITE_REG_HOST_TDR 0x4
#define UARTLITE_REG_HOST_RDR 0x0
#endif
Markdown is supported
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