Commit b7f3c485 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

software/tests/gs_logger: crude VME version (needs cleanup & some fixes)

parent eae0d98c
/*
* Public header for the raw I/O interface for PCI or PCI express interfaces
*
* Copyright (C) 2010 CERN (www.cern.ch)
* Author: Alessandro Rubini <rubini@gnudd.com>
*
* Released according to the GNU GPL, version 2 or any later version.
*
* This work is part of the White Rabbit project, a research effort led
* by CERN, the European Institute for Nuclear Research.
*/
#ifndef __RAWRABBIT_H__
#define __RAWRABBIT_H__
#include <linux/types.h>
#include <linux/ioctl.h>
#ifdef __KERNEL__ /* The initial part of the file is driver-internal stuff */
#include <linux/pci.h>
#include <linux/completion.h>
#include <linux/workqueue.h>
#include <linux/firmware.h>
#include <linux/wait.h>
#include <linux/completion.h>
struct rr_devsel;
struct rr_dev {
struct rr_devsel *devsel;
struct pci_driver *pci_driver;
struct pci_device_id *id_table;
struct pci_dev *pdev; /* non-null after pciprobe */
struct mutex mutex;
wait_queue_head_t q;
void *dmabuf;
char *fwname;
struct timespec irqtime;
unsigned long irqcount;
struct completion complete;
struct resource *area[3]; /* bar 0, 2, 4 */
void *remap[3]; /* ioremap of bar 0, 2, 4 */
unsigned long flags;
struct work_struct work;
const struct firmware *fw;
struct completion fw_load;
void (*load_program)(struct rr_dev *); /* lm32 */
int usecount;
#ifdef IS_SPEC_DEMO
struct miscdevice misc;
char miscname[32]; /* "spec-demo-<bus>-<slot> */
struct list_head list;
#endif
};
extern char *rr_fwname; /* module parameter. If "" then defaults apply */
#define RR_FLAG_REGISTERED 0x00000001
#define RR_FLAG_IRQDISABLE 0x00000002
#define RR_FLAG_IRQREQUEST 0x00000002
#define RR_PROBE_TIMEOUT (HZ) /* for pci_register_drv */
/* These two live in ./loader.c */
extern void rr_ask_firmware(struct rr_dev *dev);
extern void rr_load_firmware(struct work_struct *work);
/* And, for the spec only, this is in ./spec-loader.c */
extern void spec_ask_program(struct rr_dev *dev);
#endif /* __KERNEL__ */
/* By default, the driver registers for this vendor/devid */
#define RR_DEFAULT_VENDOR 0x1a39
#define RR_DEFAULT_DEVICE 0x0004
#define RR_DEFAULT_FWNAME "rrabbit-%P-%p@%b"
#define RR_MAX_FWNAME_SIZE 64
#define RR_DEFAULT_BUFSIZE (1<<20) /* 1MB */
#define RR_PLIST_SIZE 4096 /* no PAGE_SIZE in user space */
#define RR_PLIST_LEN (RR_PLIST_SIZE / sizeof(void *))
#define RR_MAX_BUFSIZE (RR_PLIST_SIZE * RR_PLIST_LEN)
/* This structure is used to select the device to be accessed, via ioctl */
struct rr_devsel {
__u16 vendor;
__u16 device;
__u16 subvendor; /* RR_DEVSEL_UNUSED to ignore subvendor/dev */
__u16 subdevice;
__u16 bus; /* RR_DEVSEL_UNUSED to ignore bus and devfn */
__u16 devfn;
};
#define RR_DEVSEL_UNUSED 0xffff
/* Offsets for BAR areas in llseek() and/or ioctl */
#define RR_BAR_0 0x00000000
#define RR_BAR_2 0x20000000
#define RR_BAR_4 0x40000000
#define RR_BAR_BUF 0xc0000000 /* The DMA buffer */
#define RR_IS_DMABUF(addr) ((addr) >= RR_BAR_BUF)
#define __RR_GET_BAR(x) ((x) >> 28)
#define __RR_SET_BAR(x) ((x) << 28)
#define __RR_GET_OFF(x) ((x) & 0x0fffffff)
static inline int rr_is_valid_bar(unsigned long address)
{
int bar = __RR_GET_BAR(address);
return bar == 0 || bar == 2 || bar == 4 || bar == 0x0c;
}
static inline int rr_is_dmabuf_bar(unsigned long address)
{
int bar = __RR_GET_BAR(address);
return bar == 0x0c;
}
struct rr_iocmd {
__u32 address; /* bar and offset */
__u32 datasize; /* 1 or 2 or 4 or 8 */
union {
__u8 data8;
__u16 data16;
__u32 data32;
__u64 data64;
};
};
/* ioctl commands */
#define __RR_IOC_MAGIC '4' /* random or so */
#define RR_DEVSEL _IOW(__RR_IOC_MAGIC, 0, struct rr_devsel)
#define RR_DEVGET _IOR(__RR_IOC_MAGIC, 1, struct rr_devsel)
#define RR_READ _IOWR(__RR_IOC_MAGIC, 2, struct rr_iocmd)
#define RR_WRITE _IOW(__RR_IOC_MAGIC, 3, struct rr_iocmd)
#define RR_IRQWAIT _IO(__RR_IOC_MAGIC, 4)
#define RR_IRQENA _IO(__RR_IOC_MAGIC, 5)
#define RR_GETDMASIZE _IO(__RR_IOC_MAGIC, 6)
/* #define RR_SETDMASIZE _IO(__RR_IOC_MAGIC, 7, unsigned long) */
#define RR_GETPLIST _IO(__RR_IOC_MAGIC, 8) /* returns a whole page */
#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
/* Registers from the gennum header files */
enum {
GNGPIO_BASE = 0xA00,
GNGPIO_DIRECTION_MODE = GNGPIO_BASE + 0x4,
GNGPIO_OUTPUT_ENABLE = GNGPIO_BASE + 0x8,
GNGPIO_OUTPUT_VALUE = GNGPIO_BASE + 0xC,
GNGPIO_INPUT_VALUE = GNGPIO_BASE + 0x10,
FCL_BASE = 0xB00,
FCL_CTRL = FCL_BASE,
FCL_STATUS = FCL_BASE + 0x4,
FCL_IODATA_IN = FCL_BASE + 0x8,
FCL_IODATA_OUT = FCL_BASE + 0xC,
FCL_EN = FCL_BASE + 0x10,
FCL_TIMER_0 = FCL_BASE + 0x14,
FCL_TIMER_1 = FCL_BASE + 0x18,
FCL_CLK_DIV = FCL_BASE + 0x1C,
FCL_IRQ = FCL_BASE + 0x20,
FCL_TIMER_CTRL = FCL_BASE + 0x24,
FCL_IM = FCL_BASE + 0x28,
FCL_TIMER2_0 = FCL_BASE + 0x2C,
FCL_TIMER2_1 = FCL_BASE + 0x30,
FCL_DBG_STS = FCL_BASE + 0x34,
FCL_FIFO = 0xE00,
PCI_SYS_CFG_SYSTEM = 0x800
};
#endif /* __RAWRABBIT_H__ */
#ifndef __RR_IO_H
#define __RR_IO_H
#include <stdint.h>
#include <rawrabbit.h>
int rr_bind(int a_fd);
int rr_init(int bus, int devfn);
int rr_writel(uint32_t data, uint32_t addr);
uint32_t rr_readl(uint32_t addr);
int rr_load_bitstream(const void *data, int size8);
int rr_load_bitstream_from_file(const char *file_name);
#endif
SPEC_SW ?= $(shell readlink -f ~/wr-repos/spec-sw) SPEC_SW ?= $(shell readlink -f ~/wr-repos/spec-sw)
ETHERBONE ?= $(shell readlink -f ~/wr-repos/etherbone-core/api) ETHERBONE ?= $(shell readlink -f ~/wr-repos/etherbone-core/api)
OBJS = fdelay_lib.o i2c_master.o onewire.o fdelay_bus.o spec/tools/speclib.o spec/kernel/loader-ll.o fdelay_dmtd_calibration.o simple-eb.o OBJS = fdelay_lib.o i2c_master.o onewire.o fdelay_vme.o fdelay_dmtd_calibration.o sveclib/sveclib.o sveclib/libvmebus.o
CFLAGS = -I../include -g -Imini_bone -Ispec/tools -Ietherbone CFLAGS = -I../include -g -Imini_bone -Ispec/tools -Isveclib
ifeq ($(SPEC_SW),) #ifeq ($(SPEC_SW),)
throw_error: #throw_error:
@echo "SPEC software package location environment variable is not set. Can't compile :(" # @echo "SPEC software package location environment variable is not set. Can't compile :("
endif #endif
all: spec lib all: lib
spec: #spec:
ln -s $(SPEC_SW) spec # ln -s $(SPEC_SW) spec
ln -s $(ETHERBONE) etherbone # ln -s $(ETHERBONE) etherbone
lib: $(OBJS) lib: $(OBJS)
gcc -shared -o libfinedelay.so $(OBJS) -letherbone gcc -shared -o libfinedelay.so $(OBJS)
ar rc libfinedelay.a $(OBJS) ar rc libfinedelay.a $(OBJS)
clean: clean:
......
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <getopt.h>
#include "fdelay_lib.h"
#include "sveclib/sveclib.h"
#include "fdelay_lib.h"
void printk() {};
static void fd_svec_writel(void *priv, uint32_t data, uint32_t addr)
{
svec_writel(priv, data, addr);
}
static uint32_t fd_svec_readl(void *priv, uint32_t addr)
{
return svec_readl(priv, addr);
}
#if 0
static int spec_fdelay_create(fdelay_device_t *dev, int bus, int dev_fn)
{
uint32_t base;
dev->priv_io = spec_open(bus, dev_fn);
if(!dev->priv_io)
{
fprintf(stderr,"Can't map the SPEC @ %x:%x\n", bus, dev_fn);
return -1;
}
dev->writel = fd_spec_writel;
dev->readl = fd_spec_readl;
dev->base_addr = base;
//spec_vuart_init(dev->priv_io, 0xe0500); /* for communication with WRCore during DMTD calibration */
return 0;
}
#endif
#define VENDOR_CERN 0xce42
#define DEVICE_FD_CORE 0xf19ede1a
#define DEVICE_VUART 0xe2d13d04
int fdelay_probe(fdelay_device_t *dev, const char *location)
{
int bus = -1, dev_fn = -1;
char ip_addr[128];
int use_eb = 0;
uint32_t base_core;
void *card;
if(!strncmp(location, "eb:", 3))
{
snprintf(ip_addr, sizeof(ip_addr), "udp/%s", location+3);
use_eb = 1;
} else if (!strncmp(location, "svec:"), 5) {
sscanf(location+5, "%d,%d", &bus, &dev_fn);
}
card = svec_open(8);
if(!card)
{
fprintf(stderr,"SVEC probe failed.\n");
return -1;
}
dev->priv_io = card;
dev->writel = fd_svec_writel;
dev->readl = fd_svec_readl;
dev->base_addr = 0x10000;
dbg("Found FD core @ 0x%x\n", base_core);
}
fdelay_device_t *fdelay_create()
{
return (fdelay_device_t *) malloc(sizeof(fdelay_device_t));
}
*.o
svec-cl
svec-fwloader
svec-vuart
OBJS=sveclib.o libvmebus.o
CFLAGS=-I. -Wall -DDEBUG -g
CC=gcc
all: cl fwloader vuart svecmem
cl: svec-cl.o $(OBJS)
gcc -o svec-cl $(OBJS) svec-cl.o
fwloader: svec-fwloader.o $(OBJS)
gcc -o svec-fwloader $(OBJS) svec-fwloader.o
vuart: svec-vuart.o $(OBJS)
gcc -o svec-vuart $(OBJS) svec-vuart.o
svecmem: svecmem.o $(OBJS)
gcc -o svecmem $(OBJS) svecmem.o
clean:
rm -f *.o svec-cl svec-test svec-fwloader svec-vuart
\ No newline at end of file
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!! WARNING !!!!!!!!
!!!!!!!! DEVELOPER USE ONLY !!!!!!!!
!!!!!!!! DO NOT DEPLOY IN PRODUCTION ENVIRONMENTS !!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
sveclib - a tiny userspace library (and a set of tools) allowing developers to play with the svec.
The library provides:
- raw I/O to a spec in particular slot (uses geographical addressing). Currently, there's
a fixed A32/D32/SINGLE mapping available and the memory can be accesed by calling
svec_writel()/svec_readl()
- application FPGA firmware loader (svec-fwloader)
- LM32 CPU firmware loader (svec-cl)
- WR Core virtual UART console (svec-vuart)
All these tools require the slot location to be specified with -b command line switch.
Requirements: Requires vmebus driver to be installed (tested on MEN A20).
Compilation: just run make.
\ No newline at end of file
/**
* \file libvmebus.c
* \brief VME Bus access user library
* \author Sbastien Dugu
* \date 04/02/2009
*
* This library gives userspace applications access to the VME bus
*
* Copyright (c) 2009 \em Sbastien \em Dugu
*
* \par License:
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <string.h>
#include <vmebus.h>
/** \brief VME address space mapping device */
#define VME_MWINDOW_DEV "/dev/vme_mwindow"
/** \brief VME DMA device */
#define VME_DMA_DEV "/dev/vme_dma"
/**
* \brief Check for VME a bus error
* \param desc VME mapping descriptor
*
* \return 0 if no bus error occured, 1 if bus error occured or -1 on
* any other error (with errno set appropriately).
*
* Note: This function is DEPRECATED. Use vme_bus_error_check_clear instead.
*/
int vme_bus_error_check(struct vme_mapping *desc)
{
int bus_err;
if (ioctl(desc->fd, VME_IOCTL_GET_BUS_ERROR, &bus_err) < 0) {
#ifdef DEBUG
printf("libvmebus: Failed to get bus error status: %s\n",
strerror(errno));
#endif
return -1;
}
return bus_err;
}
/**
* \brief Check and clear a VME bus error from a given address and mapping
* \param desc VME mapping descriptor
* \param address VME address to be checked
*
* \return 0 if no bus error occured, 1 if bus error occured or -1 on
* any other error (with errno set appropriately).
*
* Note that the VME bus error is cleared _only_ if it matches the
* given address/am pair.
*/
int vme_bus_error_check_clear(struct vme_mapping *vme_desc, __u64 address)
{
struct vme_bus_error_desc desc;
desc.valid = 0;
desc.error.address = address;
desc.error.am = vme_desc->am;
if (ioctl(vme_desc->fd, VME_IOCTL_CHECK_CLEAR_BUS_ERROR, &desc) < 0) {
#ifdef DEBUG
printf("libvmebus: Failed to check bus error status: %s\n",
strerror(errno));
#endif
return -1;
}
return desc.valid;
}
static off_t __page_addr(off_t address)
{
long pagemask = sysconf(_SC_PAGESIZE) - 1;
return address & ~pagemask;
}
static size_t __page_aligned_size(struct vme_mapping *desc)
{
return desc->pci_addrl + desc->sizel - __page_addr(desc->pci_addrl);
}
static size_t __page_aligned_size_incr(struct vme_mapping *desc)
{
return desc->pci_addrl - __page_addr(desc->pci_addrl);
}
/*
* Note that the caller might want to map a non-page-aligned region.
* In order to comply with the alignment requirements of mmap, we map a larger,
* page-aligned region and then store the mapped address of the requested
* non-page-aligned region.
*/
static int vme_mmap(struct vme_mapping *desc)
{
void *addr;
size_t size;
off_t page_addr;
page_addr = __page_addr(desc->pci_addrl);
size = __page_aligned_size(desc);
addr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, desc->fd, page_addr);
if (addr == MAP_FAILED)
return -1;
desc->user_va = addr + __page_aligned_size_incr(desc);
return 0;
}
static int vme_munmap(struct vme_mapping *desc)
{
void *addr = desc->user_va - __page_aligned_size_incr(desc);
return munmap(addr, __page_aligned_size(desc));
}
/**
* \brief Map a VME address space into the user address space
* \param vmeaddr VME physical start address of the mapping
* \param len Window size (must be a multiple of 64k)
* \param am VME address modifier
* \param offset Offset in the mapping for read access test (Not used)
* \param size Data width
* \param param VME mapping parameters
*
* \return the virtual address of the mapping on succes, or 0 if an error
* occurs (in that case errno is set appropriately).
*
* \deprecated This function is an emulation of the CES functionality on LynxOS,
* new applications should use the vme_map() function instead.
*
* The CES function interface does not give all the needed VME parameters, so
* the following choices were made and may have to be tweaked:
*
* \li if read prefetch is enabled then the prefetch size is set to 2 cache
* lines
* \li the VME address and size are automatically aligned on 64k if needed
* \li the VME address is limited to 32 bits
*
* \note The descriptor allocated by this function is stored into the
* pdparam_master->sgmin field and the file descriptor in
* pdparam_master->dum[1].
*
* \note We voluntarily do not close the file descriptor here, because doing
* so would automatically remove the mapping made using it. The
* mapping will be removed at return_controller() time.
*/
unsigned long find_controller(unsigned long vmeaddr, unsigned long len,
unsigned long am, unsigned long offset,
unsigned long size, struct pdparam_master *param)
{
struct vme_mapping *desc;
int org_force_create;
int force_create = 1;
int fd;
/* Allocate our mapping descriptor */
if ((desc = calloc(1, sizeof(struct vme_mapping))) == NULL)
return 0;
/* Now fill it with the parameters we got */
desc->window_num = 0;
desc->am = am;
if (param->rdpref) {
desc->read_prefetch_enabled = 1;
desc->read_prefetch_size = VME_PREFETCH_2;
}
switch (size) {
case 2:
desc->data_width = VME_D16;
break;
case 4:
desc->data_width = VME_D32;
break;
default:
printf("libvmebus: %s - "
"Unsupported data width %ld\n", __func__, size);
goto out_free;
break;
}
desc->bcast_select = 0;
if (len & 0xffff) {
printf("libvmebus: %s - "
"Mapping size %lx is not 64k aligned, "
"aligning it to %lx.\n",
__func__, len, (len + 0x10000) & ~0xffff);
len &= ~0xffff;
}
desc->sizel = len;
desc->sizeu = 0;
if (vmeaddr & 0xffff) {
printf("libvmebus: %s - "
"VME address %lx is not 64k aligned, "
"aligning it to %lx.\n",
__func__, vmeaddr, vmeaddr & ~0xffff);
vmeaddr &= ~0xffff;
}
desc->vme_addrl = vmeaddr;
desc->vme_addru = 0;
/*
* Now we're all set up, let's start the real stuff
*/
if ((fd = open(VME_MWINDOW_DEV, O_RDWR)) < 0)
goto out_free;
desc->fd = fd;
/* Save the force create flag */
if (ioctl(fd, VME_IOCTL_GET_CREATE_ON_FIND_FAIL, &org_force_create) < 0)
goto out_free;
/* Set the force create flag */
if (ioctl(fd, VME_IOCTL_SET_CREATE_ON_FIND_FAIL, &force_create) < 0)
goto out_free;
/* Create a new mapping for the area */
if (ioctl(fd, VME_IOCTL_FIND_MAPPING, desc) < 0)
goto out_restore_flag;
/* Now mmap the area */
if (vme_mmap(desc))
goto out_restore_flag;
/*
* Save the descriptor address into the struct pdparam_master sgmin
* field, it will be freed with the call to return_controller().
*/
param->sgmin = (unsigned long)desc;
/* Restore the force create flag */
ioctl(fd, VME_IOCTL_SET_CREATE_ON_FIND_FAIL, &org_force_create);
#ifdef DEBUG
printf("Created mapping\n\tVME addr: 0x%08x size: 0x%08x "
"AM: 0x%02x data width: %d\n\n",
desc->vme_addrl, desc->sizel, desc->am, desc->data_width);
#endif
return (unsigned long)desc->user_va;
out_restore_flag:
ioctl(fd, VME_IOCTL_SET_CREATE_ON_FIND_FAIL, &org_force_create);
out_free:
free(desc);
return 0;
}
/**
* \brief Release a VME mapping
* \param desc VME mapping descriptor
*
* \return 0 on success, or -1 if an error occurs (in that case errno is set
* appropriately).
*
* \deprecated This function is an emulation of the CES functionality on LynxOS,
* new applications should use the vme_unmap() function instead.
*
* \warning The function interface has been changed to a single parameter,
* a struct vme_mapping descriptor as the CES original parameters
* are not enough to match a VME mapping.
*/
unsigned long return_controller(struct vme_mapping *desc)
{
int ret = 0;
int org_force_destroy;
int force_destroy = 1;
if (!desc) {
errno = -EFAULT;
return -1;
}
if (vme_munmap(desc)) {
printf("libvmebus: %s - failed to munmap\n", __func__);
ret = -1;
}
/* Save the force destroy flag */
if (ioctl(desc->fd, VME_IOCTL_GET_DESTROY_ON_REMOVE,
&org_force_destroy) < 0) {
printf("libvmebus: %s - "
"Failed to get the force destroy flag\n", __func__);
}
/* Set the force destroy flag */
if (ioctl(desc->fd, VME_IOCTL_SET_DESTROY_ON_REMOVE,
&force_destroy) < 0) {
printf("libvmebus: %s - "
"Failed to set the force destroy flag\n", __func__);
}
if (ioctl(desc->fd, VME_IOCTL_RELEASE_MAPPING, desc) < 0) {
printf("libvmebus: %s - "
"failed to release mapping\n", __func__);
ret = -1;
}
/* Restore the force destroy flag */
if (ioctl(desc->fd, VME_IOCTL_SET_DESTROY_ON_REMOVE,
&org_force_destroy) < 0)
printf("libvmebus: %s - "
"Failed to restore force destroy flag\n", __func__);
close(desc->fd);
free(desc);
return ret;
}
/**
* \brief Map a VME address space into the user address space
*
* \param desc -- a struct vme_mapping descriptor describing the mapping
* \param force -- flag indicating whether a new window should be created if
* needed.
*
* \return a userspace virtual address for the mapping or NULL on error
* (in that case errno is set appropriately).
*/
void *vme_map(struct vme_mapping *desc, int force)
{
int fd;
int org_force_create;
fprintf(stderr,"Open\n");
if ((fd = open(VME_MWINDOW_DEV, O_RDWR)) < 0)
return NULL;
desc->fd = fd;
fprintf(stderr,"i1\n");
/* Save the force create flag */
if (ioctl(fd, VME_IOCTL_GET_CREATE_ON_FIND_FAIL, &org_force_create) < 0)
goto out_close;
fprintf(stderr,"i2\n");
/* Set the force create flag */
if (ioctl(fd, VME_IOCTL_SET_CREATE_ON_FIND_FAIL, &force) < 0)
goto out_close;
fprintf(stderr,"i3\n");
/* Create a new mapping for the area */
if (ioctl(fd, VME_IOCTL_FIND_MAPPING, desc) < 0)
{
perror("ioctl");
goto out_restore_flag;
}
fprintf(stderr,"i4\n");
/* Now mmap the area */
if (vme_mmap(desc))
goto out_restore_flag;
fprintf(stderr,"i5\n");
/* Restore the force create flag */
ioctl(fd, VME_IOCTL_SET_CREATE_ON_FIND_FAIL, &org_force_create);
fprintf(stderr,"i6\n");
#ifdef DEBUG
printf("Created mapping\n\tVME addr: 0x%08x size: 0x%08x "
"AM: 0x%02x data width: %d\n\n",
desc->vme_addrl, desc->sizel, desc->am, desc->data_width);
#endif
return desc->user_va;
out_restore_flag:
// perror("dsfdsf");
ioctl(fd, VME_IOCTL_SET_CREATE_ON_FIND_FAIL, &org_force_create);
out_close:
close(fd);
return NULL;
}
/**
* \brief Unmap a VME address space
* \param desc a struct vme_mapping descriptor describing the mapping
* \param force flag indicating whether the window should be destroyed if
* needed
*
* \return 0 on success or -1 on error (in that case errno is set
* appropriately).
*
* This function unmaps a VME address space mapped using vme_map().
*
*/
int vme_unmap(struct vme_mapping *desc, int force)
{
int ret = 0;
int org_force_destroy;
if (!desc) {
errno = -EFAULT;
return -1;
}
if (vme_munmap(desc)) {
printf("libvmebus: %s - failed to munmap\n", __func__);
ret = -1;
}
if (force) {
/* Save the force destroy flag */
if (ioctl(desc->fd, VME_IOCTL_GET_DESTROY_ON_REMOVE,
&org_force_destroy) < 0) {
printf("libvmebus: %s - "
"Failed to get the force destroy flag\n",
__func__);
}
/* Set the force destroy flag */
if (ioctl(desc->fd, VME_IOCTL_SET_DESTROY_ON_REMOVE,
&force) < 0) {
printf("libvmebus: %s - "
"Failed to set the force destroy flag\n",
__func__);
}
}
if (ioctl(desc->fd, VME_IOCTL_RELEASE_MAPPING, desc) < 0) {
printf("libvmebus: %s - "
"failed to release mapping\n",
__func__);
ret = -1;
}
if (force) {
/* Restore the force destroy flag */
if (ioctl(desc->fd, VME_IOCTL_SET_DESTROY_ON_REMOVE,
&org_force_destroy) < 0)
printf("libvmebus: %s - "
"Failed to restore force destroy flag\n",
__func__);
}
close(desc->fd);
return ret;
}
/**
* \brief Perform a DMA read on the VME bus
* \param desc DMA transfer descriptor
*
* \return 0 on success or -1 on error (in that case errno is set
* appropriately).
*
* This function performs a DMA read with the parameters specified in the
* struct vme_dma descriptor.
*/
int vme_dma_read(struct vme_dma *desc)
{
int rc = 0;
int fd;
if ((fd = open(VME_DMA_DEV, O_RDONLY)) < 0)
return -1;
if (ioctl(fd, VME_IOCTL_START_DMA, desc) < 0)
rc = -1;
close(fd);
return rc;
}
/**
* \brief Perform a DMA write on the VME bus
* \param desc DMA transfer descriptor
*
* \return 0 on success or -1 on error (in that case errno is set
* appropriately).
*
* This function performs a DMA write with the parameters specified in the
* struct vme_dma descriptor.
*
*/
int vme_dma_write(struct vme_dma *desc)
{
int rc = 0;
int fd;
if ((fd = open(VME_DMA_DEV, O_WRONLY)) < 0)
return -1;
if (ioctl(fd, VME_IOCTL_START_DMA, desc) < 0)
rc = -1;
close(fd);
return rc;
}
/**
* \file libvmebus.h
* \brief VME Bus access user library interface
* \author Sbastien Dugu
* \date 04/02/2009
*
* This library gives userspace applications access to the VME bus
*
* Copyright (c) 2009 \em Sbastien \em Dugu
*
* \par License:
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
*/
#ifndef _LIBVMEBUS_H_INCLUDE_
#define _LIBVMEBUS_H_INCLUDE_
#ifdef __cplusplus
extern "C" {
#endif
#include <vmebus.h>
/**
* \brief Swap a 16-bit halfword bytewise
* \param val The 16-bit halfword to swap
*
* \return The swapped value
*
*/
static inline unsigned short swapbe16(unsigned short val)
{
return (((val & 0xff00) >> 8) | ((val & 0xff) << 8));
}
/**
* \brief Swap a 32-bit word bytewise
* \param val The 32-bit word to swap
*
* \return The swapped value
*
*/
static inline unsigned int swapbe32(unsigned int val)
{
return (((val & 0xff000000) >> 24) | ((val & 0xff0000) >> 8) |
((val & 0xff00) << 8) | ((val & 0xff) << 24));
}
extern int vme_bus_error_check(struct vme_mapping *desc);
extern int vme_bus_error_check_clear(struct vme_mapping *desc, __u64 address);
/* VME address space mapping - CES library emulation */
extern unsigned long find_controller(unsigned long vmeaddr, unsigned long len,
unsigned long am, unsigned long offset,
unsigned long size,
struct pdparam_master *param);
extern unsigned long return_controller(struct vme_mapping *desc);
/* VME address space mapping */
extern void *vme_map(struct vme_mapping *, int);
extern int vme_unmap(struct vme_mapping *, int);
/* DMA access */
extern int vme_dma_read(struct vme_dma *);
extern int vme_dma_write(struct vme_dma *);
#ifdef __cplusplus
}
#endif
#endif /* _LIBVMEBUS_H_INCLUDE_ */
/*
* A tool to program our soft-core (LM32) within the SVEC.
*
* Alessandro Rubini 2012 for CERN, GPLv2 or later.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <getopt.h>
#include "sveclib.h"
int main(int argc, char **argv)
{
int bus = -1, c;
uint32_t lm32_base = 0x00000;
void *card;
while ((c = getopt (argc, argv, "b:c:")) != -1)
{
switch(c)
{
case 'b':
sscanf(optarg, "%i", &bus);
break;
case 'c':
sscanf(optarg, "%i", &lm32_base);
break;
default:
fprintf(stderr,
"Use: \"%s [-b slot] [-c lm32 base address] <lm32_program.bin>\"\n", argv[0]);
fprintf(stderr,
"By default, the first available SVEC is used and the LM32 is assumed at 0x%x.\n", lm32_base);
exit(1);
}
}
if (optind >= argc) {
fprintf(stderr, "Expected binary name after options.\n");
exit(1);
}
card = svec_open(bus);
if(!card)
{
fprintf(stderr, "Can't detect a SVEC card under the given adress. Make sure a SVEC card is present in your PC and the driver is loaded.\n");
exit(1);
}
fprintf(stderr,"Loading..\n");
if(svec_load_lm32(card, argv[optind], lm32_base) < 0)
{
fprintf(stderr, "Loader failure.\n");
exit(1);
}
svec_close(card);
exit (0);
}
/*
* A tool to program the FPGA within the SPEC.
*
* Alessandro Rubini 2012 for CERN, GPLv2 or later.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <getopt.h>
#include "sveclib.h"
int main(int argc, char **argv)
{
int bus = -1, c;
void *card;
while ((c = getopt (argc, argv, "b:")) != -1)
{
switch(c)
{
case 'b':
sscanf(optarg, "%i", &bus);
break;
default:
fprintf(stderr,
"Use: \"%s -b slot <fpga_bitstream.bin>\"\n", argv[0]);
exit(1);
}
}
if (optind >= argc) {
fprintf(stderr, "Expected binary name after options.\n");
exit(1);
}
if(bus < 0)
{
fprintf(stderr, "You must specify the slot number.\n");
return -1;
}
card = svec_open(bus);
if(!card)
{
fprintf(stderr, "Can't detect a SVEC card under the given adress. Make sure a SVEC card is present in your PC and the driver is loaded.\n");
exit(1);
}
if(svec_load_bitstream(card, argv[optind]) < 0)
{
fprintf(stderr, "Loader failure.\n");
exit(1);
}
svec_close(card);
exit (0);
}
#include <stdio.h>
#include "sveclib.h"
int main()
{
void *card =svec_open(8);
svec_writel(card, 0x1deadbee, 0x20400);
printf("readback:%x\n", svec_readl(card, 0x20400));
}
\ No newline at end of file
/* A simple console for accessing the SVEC 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 "sveclib.h"
static void *card;
static int transfer_byte(int from, int is_control) {
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;
}
}
svec_vuart_tx(card, &c, 1);
} else {
fprintf(stderr, "\nnothing to read. probably port disconnected.\n");
return -2;
}
return 0;
}
void term_main(int keep_term)
{
struct termios oldkey, newkey; //place tor 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);
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;
struct timeval tv = {0, 10000};
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);
}
}
while((svec_vuart_rx(card, &rx, 1)) == 1)
fprintf(stderr,"%c", rx);
}
if(!keep_term)
tcsetattr(STDIN_FILENO,TCSANOW,&oldkey);
}
int main(int argc, char **argv)
{
int bus = -1, c;
uint32_t vuart_base = 0x20500;
int keep_term = 0;
while ((c = getopt (argc, argv, "b:u:k")) != -1)
{
switch(c)
{
case 'b':
sscanf(optarg, "%i", &bus);
break;
case 'u':
sscanf(optarg, "%i", &vuart_base);
break;
case 'k':
keep_term = 1;
break;
default:
fprintf(stderr,
"Use: \"%s [-b slot] [-u VUART base] [-k]\"\n", argv[0]);
fprintf(stderr,
"By default, the VUART is assumed at 0x%x.\n \
-k option keeps the terminal config unchanged.\n", vuart_base);
exit(1);
}
}
if(bus < 0)
{
fprintf(stderr, "Missing slot number.\n");
return -1;
}
card = svec_open(bus);
if(!card)
{
fprintf(stderr, "Can't detect a SVEC card under the given adress. Make sure a SVEC card is present in your PC and the driver is loaded.\n");
return -1;
}
svec_vuart_init(card, vuart_base);
term_main(keep_term);
svec_close(card);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include "libvmebus.h"
#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 "sveclib.h"
#include "xloader_regs.h"
#include "wb_uart.h"
#define BASE_LOADER 0x70000
struct svec_private {
int slot;
void *csr_base;
void *bar_base;
struct vme_mapping csr_mapping;
struct vme_mapping bar_mapping;
uint32_t vuart_base;
};
#define MAX_HANDLES 8
static void *active_handles[MAX_HANDLES] = {0,0,0,0,0,0,0,0};
void add_handle(void *handle)
{
int i;
for(i=0;i<MAX_HANDLES;i++)
if(!active_handles[i])
{
active_handles[i] = handle;
return;
}
}
void remove_handle(void *handle)
{
int i;
for(i=0;i<MAX_HANDLES;i++)
if(active_handles[i] == handle)
{
active_handles[i] = NULL;
return;
}
}
void cleanup_self(int sig)
{
int i;
for(i=0;i<MAX_HANDLES;i++)
if(active_handles[i])
{
fprintf(stderr,"[caught %d, forced cleanup]\n", sig);
svec_close(active_handles[i]);
}
// atexit(NULL);
if(sig)
exit(0);
}
void atexit_callback()
{
cleanup_self(0);
}
void *svec_open(int slot)
{
struct svec_private *card = malloc(sizeof(struct svec_private));
if(!card)
return NULL;
signal (SIGKILL, cleanup_self);
signal (SIGSEGV, cleanup_self);
signal (SIGTERM, cleanup_self);
atexit(atexit_callback);
struct vme_mapping *mapping = &card->csr_mapping;
memset(mapping, 0, sizeof(struct vme_mapping));
card->slot = slot;
mapping->am = 0x2f;
mapping->data_width = VME_D32;
mapping->vme_addru = 0;
mapping->vme_addrl = slot * 0x80000;
mapping->sizeu = 0;
mapping->sizel = 0x80000;
mapping->read_prefetch_enabled = 0;
mapping->bcast_select = 0;
mapping->window_num = 0;
card->csr_base = vme_map(mapping, 0);
card->bar_base = NULL;
if(!card->csr_base)
{
fprintf(stderr, "Mapping CSR I/O space failed\n");
free(card);
return NULL;
}
add_handle(card);
return card;
}
void map_bar(struct svec_private *card)
{
struct vme_mapping *mapping = &card->bar_mapping;
memset(mapping, 0, sizeof(struct vme_mapping));
mapping->am = 0x9; // A32
mapping->data_width = VME_D32;
mapping->vme_addru = 0;
mapping->vme_addrl = 0x80000000;
mapping->sizeu = 0;
mapping->sizel = 0xff000;
mapping->read_prefetch_enabled = 0;
mapping->bcast_select = 0;
mapping->window_num = 0;
svec_csr_writel(card, 0x80, 0x7ff60);
svec_csr_writel(card, 0, 0x7ff64);
svec_csr_writel(card, 0, 0x7ff68);
svec_csr_writel(card, 0x24, 0x7ff6c);
svec_csr_writel(card, 0x01, 0x7ff30);
svec_csr_writel(card, 0x10, 0x7fff8);
card->bar_base = vme_map(mapping, 0);
}
void svec_close(void *card)
{
struct svec_private *p = (struct svec_private *) card;
if(!card)
return;
vme_unmap(&p->csr_mapping, 0);
if (p->bar_base)
vme_unmap(&p->bar_mapping, 0);
remove_handle(card);
free(card);
}
void svec_writel(void *card, uint32_t data, uint32_t addr)
{
struct svec_private *p = (struct svec_private *) card;
if(!p->bar_base)
map_bar(p);
*(volatile uint32_t *) (p->bar_base + addr) = swapbe32(data);
}
uint32_t svec_readl(void *card, uint32_t addr)
{
struct svec_private *p = (struct svec_private *) card;
if(!p->bar_base)
map_bar(p);
uint32_t rv = swapbe32(*(volatile uint32_t *) (p->bar_base + addr));
return rv;
}
void svec_csr_writel(void *card, uint32_t data, uint32_t addr)
{
struct svec_private *p = (struct svec_private *) card;
*(volatile uint32_t *) (p->csr_base + addr) = swapbe32(data);
}
uint32_t svec_csr_readl(void *card, uint32_t addr)
{
struct svec_private *p = (struct svec_private *) card;
uint32_t rv = swapbe32(*(volatile uint32_t *) (p->csr_base + addr));
return rv;
}
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)
return NULL;
if (fstat(fileno(f), &stbuf))
{
fclose(f);
return NULL;
}
if (!S_ISREG(stbuf.st_mode))
{
fclose(f);
return NULL;
}
buf = malloc(stbuf.st_size);
if (!buf)
{
fclose(f);
return NULL;
}
i = fread(buf, 1, stbuf.st_size, f);
if (i < 0) {
fclose(f);
free(buf);
return NULL;
}
if (i != stbuf.st_size) {
fclose(f);
free(buf);
return NULL;
}
fclose(f);
*size = stbuf.st_size;
return buf;
}
int svec_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 */
svec_writel(card, 0x1deadbee, base_addr + 0x20400);
while ( ! (svec_readl(card, base_addr + 0x20400) & (1<<28)) );
ibuf = (uint32_t *) buf;
for (i = 0; i < (size + 3) / 4; i++)
{
// fprintf(stderr, "i %x\n", i);
svec_writel(card, htonl(ibuf[i]), base_addr + i*4);
}
sync();
for (i = 0; i < (size + 3) / 4; i++) {
uint32_t r = svec_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();
svec_writel(card, 0x0deadbee, base_addr + 0x20400);
return 0;
}
int svec_load_bitstream(void *card, const char *filename)
{
struct svec_private *p = (struct svec_private *) card;
int i = 0;
const uint32_t boot_seq[8] = {0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe};
const char svec_idr[4] = "SVEC";
char idr[5];
uint32_t *buf;
size_t size;
buf = (uint32_t * )load_binary_file(filename, &size);
if(!buf)
return -1;
/* magic sequence: unlock bootloader mode, disable application FPGA */
for(i=0;i<8;i++)
svec_csr_writel(card, boot_seq[i], BASE_LOADER + XLDR_REG_BTRIGR);
/* check if we are really talking to a SVEC */
uint32_t idc = svec_csr_readl(card, BASE_LOADER + XLDR_REG_IDR);
idr[0] = (idc >> 24) & 0xff;
idr[1] = (idc >> 16) & 0xff;
idr[2] = (idc >> 8) & 0xff;
idr[3] = (idc >> 0) & 0xff;
idr[4] = 0;
printf("IDCode: '%s'\n", idr);
if(strncmp(idr, svec_idr, 4))
{
fprintf(stderr,"Invalid IDCode value. \n");
free(buf);
return -1;
}
svec_csr_writel(card, XLDR_CSR_SWRST, BASE_LOADER + XLDR_REG_CSR);
svec_csr_writel(card, XLDR_CSR_START | XLDR_CSR_MSBF, BASE_LOADER + XLDR_REG_CSR);
while(i < size) {
if(! (svec_csr_readl(card, BASE_LOADER + XLDR_REG_FIFO_CSR) & XLDR_FIFO_CSR_FULL)) {
int n = (size-i>4?4:size-i);
svec_csr_writel(card, (n - 1) | ((n<4) ? XLDR_FIFO_R0_XLAST : 0), BASE_LOADER + XLDR_REG_FIFO_R0);
svec_csr_writel(card, htonl(buf[i>>2]), BASE_LOADER + XLDR_REG_FIFO_R1);
i+=n;
}
}
free(buf);
while(1)
{
uint32_t rval = svec_csr_readl(card, BASE_LOADER + XLDR_REG_CSR);
if(rval & XLDR_CSR_DONE) {
printf("Bitstream loaded, status: %s\n", (rval & XLDR_CSR_ERROR ? "ERROR" : "OK"));
/* give the VME bus control to App FPGA */
svec_csr_writel(card, XLDR_CSR_EXIT, BASE_LOADER + XLDR_REG_CSR);
return rval & XLDR_CSR_ERROR ? -1 : 0;
}
}
return -1;
};
static int vuart_rx(void *card)
{
struct svec_private *p = (struct svec_private *) card;
int rdr = svec_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 void vuart_tx(void *card, int c)
{
struct svec_private *p = (struct svec_private *) card;
while( svec_readl(card, p->vuart_base + UART_REG_SR) & UART_SR_RX_RDY);
svec_writel(card, UART_HOST_TDR_DATA_W(c), p->vuart_base + UART_REG_HOST_TDR);
}
int svec_vuart_init(void *card, uint32_t base_addr)
{
struct svec_private *p = (struct svec_private *) card;
p->vuart_base = base_addr;
return 0;
}
size_t svec_vuart_rx(void *card, char *buffer, size_t size)
{
size_t s = size, n_rx = 0;
while(s--)
{
int c = vuart_rx(card);
if(c < 0)
return n_rx;
*buffer++ = (char) c;
n_rx ++;
}
return n_rx;
}
size_t svec_vuart_tx(void *card, char *buffer, size_t size)
{
size_t s = size;
while(s--)
vuart_tx(card, *buffer++);
return size;
}
#ifndef __SVECLIB_H
#define __SVECLIB_H
#include <stdint.h>
/* 'Opens' the SVEC card at VME slot [slot].
Returns a handle to the card or NULL in case of failure. */
void *svec_open(int slot);
/* Closes the SVEC handle [card] */
void svec_close(void *card);
/* Loads the FPGA bitstream into card [card] from file [filename].
Returns 0 on success. */
int svec_load_bitstream(void *card, const char *filename);
/* 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 svec_load_lm32(void *card, const char *filename, uint32_t base_addr);
/* Raw I/O to BAR4 (Wishbone) */
void svec_writel(void *card, uint32_t data, uint32_t addr);
uint32_t svec_readl(void *card, uint32_t addr);
void svec_csr_writel(void *card, uint32_t data, uint32_t addr);
uint32_t svec_csr_readl(void *card, uint32_t addr);
/* Initializes a virtual UART at base address [base_addr]. */
int svec_vuart_init(void *card, uint32_t base_addr);
/* Virtual uart Rx (VUART->Host) and Tx (Host->VUART) functions */
size_t svec_vuart_rx(void *card, char *buffer, size_t size);
size_t svec_vuart_tx(void *card, char *buffer, size_t size);
int svec_flash_read(void *card, int flash_id, uint32_t offset, void *buffer, uint32_t size);
int svec_flash_write(void *card, int flash_id, uint32_t offset, void *buffer, uint32_t size);
int svec_flash_protect(void *card, int flash_id, uint32_t offset, uint32_t size, int on_off);
#endif
/*
* A tool to program the FPGA within the SPEC.
*
* Alessandro Rubini 2012 for CERN, GPLv2 or later.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <getopt.h>
#include "sveclib.h"
int main(int argc, char **argv)
{
int bus = -1, c, do_write = 0;
uint32_t addr, data;
void *card;
int is_csr = 0;
while ((c = getopt (argc, argv, "b:c")) != -1)
{
switch(c)
{
case 'b':
sscanf(optarg, "%i", &bus);
break;
case 'c':
is_csr= 1;
break;
default:
fprintf(stderr,
"Use: \"%s [-c] -b slot addr [data]\"\n", argv[0]);
exit(1);
}
}
if(bus < 0)
{
fprintf(stderr, "You must specify the slot number.\n");
return -1;
}
if(optind >= argc)
{
fprintf(stderr, "Address expected.\n");
return -1;
}
sscanf(argv[optind++], "%i", &addr);
if(optind < argc)
{
sscanf(argv[optind], "%i", &data);
do_write = 1;
}
card = svec_open(bus);
if(!card)
{
fprintf(stderr, "Can't detect a SVEC card under the given adress. Make sure a SVEC card is present in your PC and the driver is loaded.\n");
exit(1);
}
if(do_write)
svec_writel(card, data, addr);
else
printf("%08x\n", svec_readl(card, addr));
svec_close(card);
return 0;
}
/**
* \file vmebus.h
* \brief PCI-VME public API
* \author Sebastien Dugue
* \date 04/02/2009
*
* This API presents in fact 2 APIs with some common definitions. One for
* drivers and one for user applications. User applications cannot use the
* driver specific parts enclosed in \#ifdef __KERNEL__ sections.
*
* Copyright (c) 2009 \em Sebastien \em Dugue
*
* \par License:
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
*/
#ifndef _VME_H
#define _VME_H
#ifdef __KERNEL__
#include <linux/device.h>
#include <linux/kernel.h>
#endif /* __KERNEL__ */
#include <linux/types.h>
/*
* VME window attributes
*/
/**
* \brief Read prefetch size
*/
enum vme_read_prefetch_size {
VME_PREFETCH_2 = 0,
VME_PREFETCH_4,
VME_PREFETCH_8,
VME_PREFETCH_16
};
/**
* \brief Data width
*/
enum vme_data_width {
VME_D8 = 8,
VME_D16 = 16,
VME_D32 = 32,
VME_D64 = 64
};
/**
* \brief 2eSST data transfer speed
*/
enum vme_2esst_mode {
VME_SST160 = 0,
VME_SST267,
VME_SST320
};
/**
* \brief Address modifiers
*/
enum vme_address_modifier {
VME_A64_MBLT = 0, /* 0x00 */
VME_A64_SCT, /* 0x01 */
VME_A64_BLT = 3, /* 0x03 */
VME_A64_LCK, /* 0x04 */
VME_A32_LCK, /* 0x05 */
VME_A32_USER_MBLT = 8, /* 0x08 */
VME_A32_USER_DATA_SCT, /* 0x09 */
VME_A32_USER_PRG_SCT, /* 0x0a */
VME_A32_USER_BLT, /* 0x0b */
VME_A32_SUP_MBLT, /* 0x0c */
VME_A32_SUP_DATA_SCT, /* 0x0d */
VME_A32_SUP_PRG_SCT, /* 0x0e */
VME_A32_SUP_BLT, /* 0x0f */
VME_2e6U = 0x20, /* 0x20 */
VME_2e3U, /* 0x21 */
VME_A16_USER = 0x29, /* 0x29 */
VME_A16_LCK = 0x2c, /* 0x2c */
VME_A16_SUP = 0x2d, /* 0x2d */
VME_CR_CSR = 0x2f, /* 0x2f */
VME_A40_SCT = 0x34, /* 0x34 */
VME_A40_LCK, /* 0x35 */
VME_A40_BLT = 0x37, /* 0x37 */
VME_A24_USER_MBLT, /* 0x38 */
VME_A24_USER_DATA_SCT, /* 0x39 */
VME_A24_USER_PRG_SCT, /* 0x3a */
VME_A24_USER_BLT, /* 0x3b */
VME_A24_SUP_MBLT, /* 0x3c */
VME_A24_SUP_DATA_SCT, /* 0x3d */
VME_A24_SUP_PRG_SCT, /* 0x3e */
VME_A24_SUP_BLT, /* 0x3f */
};
/**
* \brief PCI-VME mapping descriptor
* \param window_num Hardware window number
* \param kernel_va Kernel virtual address of the mapping for use by drivers
* \param user_va User virtual address of the mapping for use by applications
* \param fd User file descriptor for this mapping
* \param window_enabled State of the hardware window
* \param data_width VME data width
* \param am VME address modifier
* \param read_prefetch_enabled PCI read prefetch enabled state
* \param read_prefetch_size PCI read prefetch size (in cache lines)
* \param v2esst_mode VME 2eSST transfer speed
* \param bcast_select VME 2eSST broadcast select
* \param pci_addru PCI bus start address upper 32 bits
* \param pci_addrl PCI bus start address lower 32 bits
* \param sizeu Window size upper 32 bits
* \param sizel Window size lower 32 bits
* \param vme_addru VME bus start address upper 32 bits
* \param vme_addrl VME bus start address lower 32 bits
*
* This data structure is used for describing both a hardware window
* and a logical mapping on top of a hardware window. Therefore some of
* the fields are only relevant to one of those two entities.
*/
struct vme_mapping {
int window_num;
/* Reserved for kernel use */
void *kernel_va;
/* Reserved for userspace */
void *user_va;
int fd;
/* Window settings */
int window_enabled;
enum vme_data_width data_width;
enum vme_address_modifier am;
int read_prefetch_enabled;
enum vme_read_prefetch_size read_prefetch_size;
enum vme_2esst_mode v2esst_mode;
int bcast_select;
unsigned int pci_addru;
unsigned int pci_addrl;
unsigned int sizeu;
unsigned int sizel;
unsigned int vme_addru;
unsigned int vme_addrl;
};
/**
* \brief VME RMW descriptor
* \param vme_addru VME address for the RMW cycle upper 32 bits
* \param vme_addrl VME address for the RMW cycle lower 32 bits
* \param am VME address modifier
* \param enable_mask Bitmask of the bit
* \param compare_data
* \param swap_data
*
*/
struct vme_rmw {
unsigned int vme_addru;
unsigned int vme_addrl;
enum vme_address_modifier am;
unsigned int enable_mask;
unsigned int compare_data;
unsigned int swap_data;
};
/**
* \brief DMA endpoint attributes
* \param data_width VME data width (only used if endpoint is on the VME bus)
* \param am VME address modifier (ditto)
* \param v2esst_mode VME 2eSST transfer speed (ditto)
* \param bcast_select VME 2eSST broadcast select (ditto)
* \param addru Address upper 32 bits
* \param addrl Address lower 32 bits
*
* This data structure is used for describing the attributes of a DMA endpoint.
* All the field excepted for the address are only relevant for an endpoint
* on the VME bus.
*/
struct vme_dma_attr {
enum vme_data_width data_width;
enum vme_address_modifier am;
enum vme_2esst_mode v2esst_mode;
unsigned int bcast_select;
unsigned int addru;
unsigned int addrl;
};
/** \brief DMA block size on the PCI or VME bus */
enum vme_dma_block_size {
VME_DMA_BSIZE_32 = 0,
VME_DMA_BSIZE_64,
VME_DMA_BSIZE_128,
VME_DMA_BSIZE_256,
VME_DMA_BSIZE_512,
VME_DMA_BSIZE_1024,
VME_DMA_BSIZE_2048,
VME_DMA_BSIZE_4096
};
/** \brief DMA backoff time (us) on the PCI or VME bus */
enum vme_dma_backoff {
VME_DMA_BACKOFF_0 = 0,
VME_DMA_BACKOFF_1,
VME_DMA_BACKOFF_2,
VME_DMA_BACKOFF_4,
VME_DMA_BACKOFF_8,
VME_DMA_BACKOFF_16,
VME_DMA_BACKOFF_32,
VME_DMA_BACKOFF_64
};
/**
* \brief DMA control
* \param vme_block_size VME bus block size when the source is VME
* \param vme_backoff_time VME bus backoff time when the source is VME
* \param pci_block_size PCI/X bus block size when the source is PCI
* \param pci_backoff_time PCI bus backoff time when the source is PCI
*
*/
struct vme_dma_ctrl {
enum vme_dma_block_size vme_block_size;
enum vme_dma_backoff vme_backoff_time;
enum vme_dma_block_size pci_block_size;
enum vme_dma_backoff pci_backoff_time;
};
/** \brief DMA transfer direction */
enum vme_dma_dir {
VME_DMA_TO_DEVICE = 1,
VME_DMA_FROM_DEVICE
};
/**
* \brief VME DMA transfer descriptor
* \param status Transfer status
* \param length Transfer size in bytes
* \param novmeinc Must be set to 1 when accessing a FIFO like device on the VME
* \param dir Transfer direction
* \param src Transfer source attributes
* \param dst Transfer destination attributes
* \param opt Transfer control
*
*/
struct vme_dma {
unsigned int status;
unsigned int length;
unsigned int novmeinc;
enum vme_dma_dir dir;
struct vme_dma_attr src;
struct vme_dma_attr dst;
struct vme_dma_ctrl ctrl;
};
/**
* \brief VME Bus Error
* \param address Address of the bus error
* \param am Address Modifier of the bus error
*/
struct vme_bus_error {
__u64 address;
enum vme_address_modifier am;
};
/**
* \brief VME Bus Error descriptor
* \param error Address/AM of the bus error
* \param valid Valid Flag: 0 -> no error, 1 -> error
*/
struct vme_bus_error_desc {
struct vme_bus_error error;
int valid;
};
/*! @name VME single access swapping policy
*@{
*/
#define SINGLE_NO_SWAP 0
#define SINGLE_AUTO_SWAP 1
#define SINGLE_WORD_SWAP 2
#define SINGLE_BYTEWORD_SWAP 3
/*@}*/
/*! @name page qualifier
*
*@{
*/
#define VME_PG_SHARED 0x00
#define VME_PG_PRIVATE 0x02
/*@}*/
/**
* \brief VME mapping attributes
* \param iack VME IACK 0 -> IACK pages
* \param rdpref VME read prefetch option 0 -> Disable
* \param wrpost VME write posting option
* \param swap VME swap options
* \param sgmin page descriptor number returned by find_controller
* \param dum -- dum[0] page qualifier (shared/private), dum[1] XPC ADP-type
* dum[2] - reserved, _must_ be 0.
*
* This structure is used for the find_controller() and return_controller()
* LynxOS CES driver emulation.
*/
struct pdparam_master
{
unsigned long iack;
unsigned long rdpref;
unsigned long wrpost;
unsigned long swap;
unsigned long sgmin;
unsigned long dum[3];
};
/**
* \name Window management ioctl numbers
* \{
*/
/** Get a physical window attributes */
#define VME_IOCTL_GET_WINDOW_ATTR _IOWR('V', 0, struct vme_mapping)
/** Create a physical window */
#define VME_IOCTL_CREATE_WINDOW _IOW( 'V', 1, struct vme_mapping)
/** Destroy a physical window */
#define VME_IOCTL_DESTROY_WINDOW _IOW( 'V', 2, int)
/** Create a mapping over a physical window */
#define VME_IOCTL_FIND_MAPPING _IOWR('V', 3, struct vme_mapping)
/** Remove a mapping */
#define VME_IOCTL_RELEASE_MAPPING _IOW( 'V', 4, struct vme_mapping)
/** Get the create on find failed flag */
#define VME_IOCTL_GET_CREATE_ON_FIND_FAIL _IOR( 'V', 5, unsigned int)
/** Set the create on find failed flag */
#define VME_IOCTL_SET_CREATE_ON_FIND_FAIL _IOW( 'V', 6, unsigned int)
/** Get the destroy on remove flag */
#define VME_IOCTL_GET_DESTROY_ON_REMOVE _IOR( 'V', 7, unsigned int)
/** Set the destroy on remove flag */
#define VME_IOCTL_SET_DESTROY_ON_REMOVE _IOW( 'V', 8, unsigned int)
/** Get bus error status -- DEPRECATED */
#define VME_IOCTL_GET_BUS_ERROR _IOR( 'V', 9, unsigned int)
/** Check (and possibly clear) the bus error status */
#define VME_IOCTL_CHECK_CLEAR_BUS_ERROR _IOWR('V',10, struct vme_bus_error_desc)
/* \}*/
/**
* DMA ioctls
* \{
*/
/** Start a DMA transfer */
#define VME_IOCTL_START_DMA _IOWR('V', 10, struct vme_dma)
/* \}*/
#ifdef __KERNEL__
/*
* Those definitions are for drivers only and are not visible to userspace.
*/
struct vme_driver {
int (*match)(struct device *, unsigned int);
int (*probe)(struct device *, unsigned int);
int (*remove)(struct device *, unsigned int);
void (*shutdown)(struct device *, unsigned int);
int (*suspend)(struct device *, unsigned int, pm_message_t);
int (*resume)(struct device *, unsigned int);
struct device_driver driver;
struct device *devices;
};
#define to_vme_driver(x) container_of((x), struct vme_driver, driver)
typedef void (*vme_berr_handler_t)(struct vme_bus_error *);
/* API for new drivers */
extern int vme_register_driver(struct vme_driver *vme_driver, unsigned int ndev);
extern void vme_unregister_driver(struct vme_driver *vme_driver);
extern int vme_request_irq(unsigned int, int (*)(void *),
void *, const char *);
extern int vme_free_irq(unsigned int );
extern int vme_generate_interrupt(int, int, signed long);
extern struct vme_mapping* find_vme_mapping_from_addr(unsigned);
extern int vme_get_window_attr(struct vme_mapping *);
extern int vme_create_window(struct vme_mapping *);
extern int vme_destroy_window(int);
extern int vme_find_mapping(struct vme_mapping *, int);
extern int vme_release_mapping(struct vme_mapping *, int);
extern int vme_do_dma(struct vme_dma *);
extern int vme_do_dma_kernel(struct vme_dma *);
extern int vme_bus_error_check(int);
extern struct vme_berr_handler *
vme_register_berr_handler(struct vme_bus_error *, size_t, vme_berr_handler_t);
extern void vme_unregister_berr_handler(struct vme_berr_handler *);
/* API providing an emulation of the CES VME driver for legacy drivers */
extern unsigned long find_controller(unsigned long, unsigned long,
unsigned long, unsigned long,
unsigned long, struct pdparam_master *);
extern unsigned long return_controller(unsigned, unsigned);
extern int vme_intset(int, int (*)(void *), void *, void *);
extern int vme_intclr(int, void *);
#endif /* __KERNEL__ */
#endif /* _VME_H */
/*
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
#endif
/*
Register definitions for slave core: Xilinx FPGA loader
* File : xloader_regs.h
* Author : auto-generated by wbgen2 from xloader_wb.wb
* Created : Thu Jun 21 15:17:30 2012
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE xloader_wb.wb
DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
*/
#ifndef __WBGEN2_REGDEFS_XLOADER_WB_WB
#define __WBGEN2_REGDEFS_XLOADER_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: Control/status register */
/* definitions for field: Start configuration in reg: Control/status register */
#define XLDR_CSR_START WBGEN2_GEN_MASK(0, 1)
/* definitions for field: Configuration done in reg: Control/status register */
#define XLDR_CSR_DONE WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Configuration error in reg: Control/status register */
#define XLDR_CSR_ERROR WBGEN2_GEN_MASK(2, 1)
/* definitions for field: Loader busy in reg: Control/status register */
#define XLDR_CSR_BUSY WBGEN2_GEN_MASK(3, 1)
/* definitions for field: Byte order select in reg: Control/status register */
#define XLDR_CSR_MSBF WBGEN2_GEN_MASK(4, 1)
/* definitions for field: Software resest in reg: Control/status register */
#define XLDR_CSR_SWRST WBGEN2_GEN_MASK(5, 1)
/* definitions for field: Exit bootloader mode in reg: Control/status register */
#define XLDR_CSR_EXIT WBGEN2_GEN_MASK(6, 1)
/* definitions for field: Serial clock divider in reg: Control/status register */
#define XLDR_CSR_CLKDIV_MASK WBGEN2_GEN_MASK(8, 6)
#define XLDR_CSR_CLKDIV_SHIFT 8
#define XLDR_CSR_CLKDIV_W(value) WBGEN2_GEN_WRITE(value, 8, 6)
#define XLDR_CSR_CLKDIV_R(reg) WBGEN2_GEN_READ(reg, 8, 6)
/* definitions for register: Bootloader Trigger Register */
/* definitions for register: GPIO Output Register */
/* definitions for register: ID Register */
/* definitions for register: FIFO 'Bitstream FIFO' data input register 0 */
/* definitions for field: Entry size in reg: FIFO 'Bitstream FIFO' data input register 0 */
#define XLDR_FIFO_R0_XSIZE_MASK WBGEN2_GEN_MASK(0, 2)
#define XLDR_FIFO_R0_XSIZE_SHIFT 0
#define XLDR_FIFO_R0_XSIZE_W(value) WBGEN2_GEN_WRITE(value, 0, 2)
#define XLDR_FIFO_R0_XSIZE_R(reg) WBGEN2_GEN_READ(reg, 0, 2)
/* definitions for field: Last xfer in reg: FIFO 'Bitstream FIFO' data input register 0 */
#define XLDR_FIFO_R0_XLAST WBGEN2_GEN_MASK(2, 1)
/* definitions for register: FIFO 'Bitstream FIFO' data input register 1 */
/* definitions for field: Data in reg: FIFO 'Bitstream FIFO' data input register 1 */
#define XLDR_FIFO_R1_XDATA_MASK WBGEN2_GEN_MASK(0, 32)
#define XLDR_FIFO_R1_XDATA_SHIFT 0
#define XLDR_FIFO_R1_XDATA_W(value) WBGEN2_GEN_WRITE(value, 0, 32)
#define XLDR_FIFO_R1_XDATA_R(reg) WBGEN2_GEN_READ(reg, 0, 32)
/* definitions for register: FIFO 'Bitstream FIFO' control/status register */
/* definitions for field: FIFO full flag in reg: FIFO 'Bitstream FIFO' control/status register */
#define XLDR_FIFO_CSR_FULL WBGEN2_GEN_MASK(16, 1)
/* definitions for field: FIFO empty flag in reg: FIFO 'Bitstream FIFO' control/status register */
#define XLDR_FIFO_CSR_EMPTY WBGEN2_GEN_MASK(17, 1)
/* definitions for field: FIFO clear in reg: FIFO 'Bitstream FIFO' control/status register */
#define XLDR_FIFO_CSR_CLEAR_BUS WBGEN2_GEN_MASK(18, 1)
/* definitions for field: FIFO counter in reg: FIFO 'Bitstream FIFO' control/status register */
#define XLDR_FIFO_CSR_USEDW_MASK WBGEN2_GEN_MASK(0, 8)
#define XLDR_FIFO_CSR_USEDW_SHIFT 0
#define XLDR_FIFO_CSR_USEDW_W(value) WBGEN2_GEN_WRITE(value, 0, 8)
#define XLDR_FIFO_CSR_USEDW_R(reg) WBGEN2_GEN_READ(reg, 0, 8)
/* [0x0]: REG Control/status register */
#define XLDR_REG_CSR 0x00000000
/* [0x4]: REG Bootloader Trigger Register */
#define XLDR_REG_BTRIGR 0x00000004
/* [0x8]: REG GPIO Output Register */
#define XLDR_REG_GPIOR 0x00000008
/* [0xc]: REG ID Register */
#define XLDR_REG_IDR 0x0000000c
/* [0x10]: REG FIFO 'Bitstream FIFO' data input register 0 */
#define XLDR_REG_FIFO_R0 0x00000010
/* [0x14]: REG FIFO 'Bitstream FIFO' data input register 1 */
#define XLDR_REG_FIFO_R1 0x00000014
/* [0x18]: REG FIFO 'Bitstream FIFO' control/status register */
#define XLDR_REG_FIFO_CSR 0x00000018
#endif
TESTS = gs_logger # dmtd_calibration gs_logger random_pulse_test sweep_test temperature_calibration TESTS = gs_logger # dmtd_calibration gs_logger random_pulse_test sweep_test temperature_calibration
CFLAGS = -I../include CFLAGS = -I../include
LDFLAGS = -L../lib ../lib/libfinedelay.a -lm -letherbone LDFLAGS = -L../lib ../lib/libfinedelay.a -lm
CC=gcc CC=gcc
.PHONY: all .PHONY: all
......
...@@ -84,13 +84,16 @@ void log_start(char *log_file_name) ...@@ -84,13 +84,16 @@ void log_start(char *log_file_name)
if(!log_file) if(!log_file)
{ {
fprintf(stderr, "Can't open the log file: %s\n", log_file_name); fprintf(stderr, "Can't open the log file: %s\n", log_file_name);
exit(-1); // exit(-1);
} }
bt.card_id = 0; bt.card_id = 0;
bt.type = TYPE_START_LOGGING; bt.type = TYPE_START_LOGGING;
fwrite(&bt, sizeof(struct binary_timestamp), 1, log_file); if(log_file)
fflush(log_file); {
fwrite(&bt, sizeof(struct binary_timestamp), 1, log_file);
fflush(log_file);
}
} }
void log_stop() void log_stop()
...@@ -267,7 +270,9 @@ void enable_wr(fdelay_device_t *b) ...@@ -267,7 +270,9 @@ void enable_wr(fdelay_device_t *b)
printf("Locking to WR network ..."); printf("Locking to WR network ...");
fflush(stdout); fflush(stdout);
fdelay_configure_sync(b, FDELAY_SYNC_WR); fdelay_configure_sync(b, FDELAY_SYNC_LOCAL);
return;
while(fdelay_check_sync(b) <= 0) while(fdelay_check_sync(b) <= 0)
{ {
......
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