Untitled diff

Created Diff never expires
21 removals
149 lines
38 additions
165 lines
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
// Copyright (c) 2016, The Regents of the University of California All
// Copyright (c) 2016, The Regents of the University of California All
// rights reserved.
// rights reserved.
//
//
// Redistribution and use in source and binary forms, with or without
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// modification, are permitted provided that the following conditions are
// met:
// met:
//
//
// * Redistributions of source code must retain the above copyright
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// notice, this list of conditions and the following disclaimer.
//
//
// * Redistributions in binary form must reproduce the above
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// with the distribution.
//
//
// * Neither the name of The Regents of the University of California
// * Neither the name of The Regents of the University of California
// nor the names of its contributors may be used to endorse or
// nor the names of its contributors may be used to endorse or
// promote products derived from this software without specific
// promote products derived from this software without specific
// prior written permission.
// prior written permission.
//
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL REGENTS OF THE
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL REGENTS OF THE
// UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY DIRECT, INDIRECT,
// UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
// TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
// DAMAGE.
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------


/*
/*
* Filename: riffa.c
* Filename: riffa.c
* Version: 2.0
* Version: 2.0
* Description: Linux PCIe communications API for RIFFA.
* Description: Linux PCIe communications API for RIFFA.
* Author: Matthew Jacobsen
* Author: Matthew Jacobsen
* History: @mattj: Initial release. Version 2.0.
* History: @mattj: Initial release. Version 2.0.
*/
*/


#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <unistd.h>
#include <pthread.h>
#include <pthread.h>
#include <fcntl.h>
#include <fcntl.h>
#include "riffa.h"
#include "riffa.h"


struct thread_info { /* Used as argument to thread_start() */
struct thread_info { /* Used as argument to thread_start() */
// please refer to API of fpga_send() and fpga_recv() at http://riffa.ucsd.edu/node/10 or https://github.com/KastnerRG/riffa/blob/master/driver/linux/riffa.c#L84-L111
// please refer to API of fpga_send() and fpga_recv() at http://riffa.ucsd.edu/node/10 or https://github.com/KastnerRG/riffa/blob/master/driver/linux/riffa.c#L84-L111
fpga_t * fpga;
fpga_t * fpga;
unsigned int chnl;
unsigned int chnl;
unsigned int * buffer;
unsigned int * buffer;
unsigned int len;
unsigned int len;
unsigned int offset;
unsigned int offset;
unsigned int last;
unsigned int last;
long long timeout;
long long timeout;
};
};


struct fpga_t
struct fpga_t
{
{
int fd;
int fdr; // read file descriptor
int fdw; // write file descriptor
int id;
int id;
};
};


fpga_t * fpga_open(int id)
fpga_t * fpga_open(int id)
{
{
fpga_t * fpga;
fpga_t * fpga;


// Allocate space for the fpga_dev
// Allocate space for the fpga_dev
fpga = (fpga_t *)malloc(sizeof(fpga_t));
fpga = (fpga_t *)malloc(sizeof(fpga_t));

if (fpga == NULL)
if (fpga == NULL)
return NULL;
return NULL;

fpga->id = id;
fpga->id = id;


// Open the device file.
// Open the device file.
fpga->fd = open("/dev/" DEVICE_NAME, O_RDWR | O_SYNC);
fpga->fdr = open("/dev/" DEVICE_NAME "_read", O_RDONLY);
if (fpga->fd < 0) {
fpga->fdw = open("/dev/" DEVICE_NAME "_write", O_WRONLY);

if ((fpga->fdr < 0) || (fpga->fdw < 0)) {
free(fpga);
free(fpga);
return NULL;
return NULL;
}
}
return fpga;
return fpga;
}
}


void fpga_close(fpga_t * fpga)
void fpga_close(fpga_t * fpga)
{
{
// Close the device file.
// Close the device file.
close(fpga->fd);
close(fpga->fdr);
close(fpga->fdw);
free(fpga);
free(fpga);
}
}


//int fpga_send(fpga_t * fpga, int chnl, void * data, int len, int destoff, int last, long long timeout)
//int fpga_send(fpga_t * fpga, int chnl, void * data, int len, int destoff, int last, long long timeout)
void* fpga_send(void *arg)
void* fpga_send(void *arg)
{
{
struct thread_info *tinfo_send = (struct thread_info *) arg;
struct thread_info *tinfo_send = (struct thread_info *) arg;


fpga_chnl_io io_send;
fpga_chnl_io io_send;


io_send.id = tinfo_send->fpga->id;
io_send.id = tinfo_send->fpga->id;
io_send.chnl = tinfo_send->chnl;
io_send.chnl = tinfo_send->chnl;
io_send.len = tinfo_send->len;
io_send.len = tinfo_send->len;
io_send.offset = tinfo_send->offset;
io_send.offset = tinfo_send->offset;
io_send.last = tinfo_send->last;
io_send.last = tinfo_send->last;
io_send.timeout = tinfo_send->timeout;
io_send.timeout = tinfo_send->timeout;
io_send.data = (char *)(tinfo_send->buffer);
io_send.data = (char *)(tinfo_send->buffer);


int number_of_words_sent = ioctl(tinfo_send->fpga->fd, IOCTL_SEND, &io_send);
int number_of_words_sent = ioctl(tinfo_send->fpga->fdw, IOCTL_SEND, &io_send);


pthread_exit((void *)(intptr_t)number_of_words_sent);
pthread_exit((void *)(intptr_t)number_of_words_sent);
}
}


//int fpga_recv(fpga_t * fpga, int chnl, void * data, int len, long long timeout)
//int fpga_recv(fpga_t * fpga, int chnl, void * data, int len, long long timeout)
void* fpga_recv(void *arg)
void* fpga_recv(void *arg)
{
{
struct thread_info *tinfo_recv = (struct thread_info *) arg;
struct thread_info *tinfo_recv = (struct thread_info *) arg;


fpga_chnl_io io_recv;
fpga_chnl_io io_recv;


io_recv.id = tinfo_recv->fpga->id;
io_recv.id = tinfo_recv->fpga->id;
io_recv.chnl = tinfo_recv->chnl;
io_recv.chnl = tinfo_recv->chnl;
io_recv.len = tinfo_recv->len;
io_recv.len = tinfo_recv->len;
io_recv.timeout = tinfo_recv->timeout;
io_recv.timeout = tinfo_recv->timeout;
io_recv.data = (char *)(tinfo_recv->buffer);
io_recv.data = (char *)(tinfo_recv->buffer);


int number_of_words_recv = ioctl(tinfo_recv->fpga->fd, IOCTL_RECV, &io_recv);
int number_of_words_recv = ioctl(tinfo_recv->fpga->fdr, IOCTL_RECV, &io_recv);


pthread_exit((void *)(intptr_t)number_of_words_recv);
pthread_exit((void *)(intptr_t)number_of_words_recv);
}
}


void fpga_reset(fpga_t * fpga)
void fpga_reset(fpga_t * fpga)
{
{
ioctl(fpga->fd, IOCTL_RESET, fpga->id);
ioctl(fpga->fdr, IOCTL_RESET, fpga->id);
ioctl(fpga->fdw, IOCTL_RESET, fpga->id);
}
}


int fpga_list(fpga_info_list * list) {
int fpga_list(fpga_info_list * list) {
int fd;
int fdr;
int rc;
int fdw;
int rc_r;
int rc_w;


fd = open("/dev/" DEVICE_NAME, O_RDWR | O_SYNC);
fdr = open("/dev/" DEVICE_NAME "_read", O_RDONLY);
if (fd < 0)
fdw = open("/dev/" DEVICE_NAME "_write", O_WRONLY);
return fd;

rc = ioctl(fd, IOCTL_LIST, list);
if ((fdr < 0) || (fdw < 0))
close(fd);
return -1;
return rc;

rc_r = ioctl(fdr, IOCTL_LIST, list);
rc_w = ioctl(fdw, IOCTL_LIST, list);

close(fdr);
close(fdw);

return (rc_r + rc_w);
}
}