Skip to content
This repository has been archived by the owner on May 27, 2020. It is now read-only.

BitForce FPGA support #73

Merged
merged 1 commit into from
Jan 19, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,7 @@ AM_CFLAGS = -DHAS_YASM
endif
endif
endif

if USE_BITFORCE
cgminer_SOURCES += bitforce.c
endif
219 changes: 219 additions & 0 deletions bitforce.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
/*
* Copyright 2012 Luke Dashjr
*
* 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. See COPYING for more details.
*/

#include <limits.h>
#include <pthread.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <dirent.h>
#include <termios.h>
#include <unistd.h>

#include "elist.h"
#include "miner.h"


struct device_api bitforce_api;

static bool bitforce_detect_one(const char *devpath)
{
char pdevbuf[0x100];
int i = 0;

if (total_devices == MAX_DEVICES)
return false;

FILE *fileDev = fopen(devpath, "r+b");
if (unlikely(!fileDev))
{
applog(LOG_DEBUG, "BitForce Detect: Failed to open %s", devpath);
return false;
}
setbuf(fileDev, NULL);
fprintf(fileDev, "ZGX");
if (!fgets(pdevbuf, sizeof(pdevbuf), fileDev))
{
applog(LOG_ERR, "Error reading from BitForce (ZGX)");
return 0;
}
fclose(fileDev);
if (unlikely(!strstr(pdevbuf, "SHA256")))
{
applog(LOG_DEBUG, "BitForce Detect: Didn't recognize BitForce on %s", devpath);
return false;
}

// We have a real BitForce!
struct cgpu_info *bitforce;
bitforce = calloc(1, sizeof(*bitforce));
devices[total_devices++] = bitforce;
bitforce->api = &bitforce_api;
bitforce->device_id = i++;
bitforce->device_path = strdup(devpath);
bitforce->enabled = true;
bitforce->threads = 1;

return true;
}

static void bitforce_detect_auto()
{
DIR *D;
struct dirent *de;
const char udevdir[] = "/dev/serial/by-id";
char devpath[sizeof(udevdir) + 1 + NAME_MAX];
char *devfile = devpath + sizeof(udevdir);

D = opendir(udevdir);
if (!D)
return;
memcpy(devpath, udevdir, sizeof(udevdir) - 1);
devpath[sizeof(udevdir) - 1] = '/';
while ( (de = readdir(D)) ) {
if (!strstr(de->d_name, "BitFORCE_SHA256"))
continue;
strcpy(devfile, de->d_name);
bitforce_detect_one(devpath);
}
closedir(D);
}

static void bitforce_detect()
{
struct string_elist *iter, *tmp;

list_for_each_entry_safe(iter, tmp, &scan_devices, list) {
if (bitforce_detect_one(iter->string))
string_elist_del(iter);
}

bitforce_detect_auto();
}

static bool bitforce_thread_prepare(struct thr_info *thr)
{
struct cgpu_info *bitforce = thr->cgpu;

struct timeval now;

FILE *fileDev = fopen(bitforce->device_path, "r+b");
if (unlikely(!fileDev))
{
applog(LOG_ERR, "Failed to open BitForce on %s", bitforce->device_path);
return false;
}

{
int nDevFD = fileno(fileDev);
struct termios pattr;
tcgetattr(nDevFD, &pattr);
pattr.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
pattr.c_oflag &= ~OPOST;
pattr.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
pattr.c_cflag &= ~(CSIZE | PARENB);
pattr.c_cflag |= CS8;
tcsetattr(nDevFD, TCSANOW, &pattr);
}
setbuf(fileDev, NULL);
bitforce->device_file = fileDev;

applog(LOG_INFO, "Opened BitForce on %s", bitforce->device_path);
gettimeofday(&now, NULL);
get_datestamp(bitforce->init, &now);

return true;
}

static uint64_t bitforce_scanhash(struct thr_info *thr, struct work *work, uint64_t max_nonce)
{
struct cgpu_info *bitforce = thr->cgpu;
FILE *fileDev = bitforce->device_file;

char pdevbuf[0x100];
unsigned char ob[61] = ">>>>>>>>12345678901234567890123456789012123456789012>>>>>>>>";
int i;
char *pnoncebuf;
uint32_t nonce;

fprintf(fileDev, "ZDX");
if (!fgets(pdevbuf, sizeof(pdevbuf), fileDev)) {
applog(LOG_ERR, "Error reading from BitForce (ZDX)");
return 0;
}
if (unlikely(pdevbuf[0] != 'O' || pdevbuf[1] != 'K'))
{
applog(LOG_ERR, "BitForce ZDX reports: %s", pdevbuf);
return 0;
}

memcpy(ob + 8, work->midstate, 32);
memcpy(ob + 8 + 32, work->data + 64, 12);
fwrite(ob, 60, 1, fileDev);
applog(LOG_DEBUG, "BitForce block data: %s", bin2hex(ob + 8, 44));

if (!fgets(pdevbuf, sizeof(pdevbuf), fileDev))
{
applog(LOG_ERR, "Error reading from BitForce (block data)");
return 0;
}
if (unlikely(pdevbuf[0] != 'O' || pdevbuf[1] != 'K'))
{
applog(LOG_ERR, "BitForce block data reports: %s", pdevbuf);
return 0;
}

usleep(4500000);
i = 4500;
while (1) {
fprintf(fileDev, "ZFX");
if (!fgets(pdevbuf, sizeof(pdevbuf), fileDev))
{
applog(LOG_ERR, "Error reading from BitForce (ZFX)");
return 0;
}
if (pdevbuf[0] != 'B')
break;
usleep(10000);
i += 10;
}
applog(LOG_DEBUG, "BitForce waited %dms until %s\n", i, pdevbuf);
work->blk.nonce = 0xffffffff;
if (pdevbuf[2] == '-')
return 0xffffffff;
else
if (strncasecmp(pdevbuf, "NONCE-FOUND", 11)) {
applog(LOG_ERR, "BitForce result reports: %s", pdevbuf);
return 0;
}

pnoncebuf = &pdevbuf[12];

while (1) {
hex2bin((void*)&nonce, pnoncebuf, 4);
#ifndef __BIG_ENDIAN__
nonce = swab32(nonce);
#endif

submit_nonce(thr, work, nonce);
if (pnoncebuf[8] != ',')
break;
pnoncebuf += 9;
}

return 0xffffffff;
}

struct device_api bitforce_api = {
.name = "BFL",
.api_detect = bitforce_detect,
// .reinit_device = TODO
.thread_prepare = bitforce_thread_prepare,
.scanhash = bitforce_scanhash,
};
16 changes: 14 additions & 2 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,15 @@ else
DLOPEN_FLAGS=""
fi

bitforce=yes
AC_ARG_ENABLE([bitforce],
[AC_HELP_STRING([--disable-bitforce],[Don't compile support for BitForce FPGAs])],
[bitforce=$enableval]
)
if test "x$bitforce" != xno; then
AC_DEFINE([USE_BITFORCE], [1], [Defined to 1 if BitForce support is wanted.])
fi

AC_SEARCH_LIBS(addstr, ncurses pdcurses, ,
AC_MSG_ERROR([Could not find curses library - please install libncurses-dev or pdcurses-dev]))

Expand All @@ -190,6 +199,7 @@ AC_CHECK_LIB(pdcurses, addstr, PDCURSES_LIBS=-lpdcurses)
AM_CONDITIONAL([WANT_JANSSON], [test x$request_jansson = xtrue])
AM_CONDITIONAL([HAVE_WINDOWS], [test x$have_win32 = xtrue])
AM_CONDITIONAL([HAVE_x86_64], [test x$have_x86_64 = xtrue])
AM_CONDITIONAL([USE_BITFORCE], [test x$bitforce != xno])

if test x$request_jansson = xtrue
then
Expand Down Expand Up @@ -312,18 +322,20 @@ echo
echo "Configuration Options Summary:"
echo

echo " BitForce.FPGAs.......: $bitforce"

if test "x$opencl" != xno; then
if test $found_opencl = 1; then
echo " OpenCL...............: FOUND. GPU mining support enabled"
else
echo " OpenCL...............: NOT FOUND. GPU mining support DISABLED"
if test "x$cpumining" != xyes; then
if test "x$cpumining$bitforce" = xnono; then
AC_MSG_ERROR([No mining configured in])
fi
fi
else
echo " OpenCL...............: Detection overrided. GPU mining support DISABLED"
if test "x$cpumining" != xyes; then
if test "x$cpumining$bitforce" = xnono; then
AC_MSG_ERROR([No mining configured in])
fi
fi
Expand Down
29 changes: 27 additions & 2 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ static bool opt_restart = true;
static bool opt_nogpu;
#endif

struct list_head scan_devices;
int nDevs;
static int opt_g_threads = 2;
static signed int devices_enabled = 0;
Expand Down Expand Up @@ -1003,6 +1004,12 @@ static char *set_float_0_to_99(const char *arg, float *f)
return NULL;
}

static char *add_serial(char *arg)
{
string_elist_add(arg, &scan_devices);
return NULL;
}

static char *set_devices(char *arg)
{
int i = strtol(arg, &arg, 0);
Expand Down Expand Up @@ -1670,6 +1677,11 @@ static struct opt_table opt_config_table[] = {
OPT_WITHOUT_ARG("--round-robin",
set_rr, &pool_strategy,
"Change multipool strategy from failover to round robin on failure"),
#ifdef USE_BITFORCE
OPT_WITH_ARG("--scan-serial|-S",
add_serial, NULL, NULL,
"Serial port to probe for BitForce device"),
#endif
OPT_WITH_ARG("--scan-time|-s",
set_int_0_to_9999, opt_show_intval, &opt_scantime,
"Upper bound on time spent scanning current work, in seconds"),
Expand Down Expand Up @@ -4340,6 +4352,7 @@ static inline bool abandon_work(int thr_id, struct work *work, struct timeval *w
{
if (wdiff->tv_sec > opt_scantime ||
work->blk.nonce >= MAXTHREADS - hashes ||
hashes >= 0xfffffffe ||
stale_work(work, false))
return true;
return false;
Expand Down Expand Up @@ -4432,7 +4445,7 @@ static void *miner_thread(void *userdata)
}
}

if (sdiff.tv_sec < cycle) {
if (unlikely(sdiff.tv_sec < cycle)) {
if (likely(!api->can_limit_work || max_nonce == 0xffffffff))
continue;

Expand Down Expand Up @@ -5386,7 +5399,7 @@ static void cpu_detect()
#endif /* !WIN32 */

if (opt_n_threads < 0 || !forced_n_threads) {
if (nDevs && !opt_usecpu)
if (total_devices && !opt_usecpu)
opt_n_threads = 0;
else
opt_n_threads = num_processors;
Expand Down Expand Up @@ -5803,6 +5816,12 @@ struct device_api opencl_api = {
};
#endif


#ifdef USE_BITFORCE
extern struct device_api bitforce_api;
#endif


static int cgminer_id_count = 0;

void enable_device(struct cgpu_info *cgpu)
Expand Down Expand Up @@ -5877,6 +5896,8 @@ int main (int argc, char *argv[])
HASH_ADD_STR(blocks, hash, block);
strcpy(current_block, block->hash);

INIT_LIST_HEAD(&scan_devices);

memset(gpus, 0, sizeof(gpus));
for (i = 0; i < MAX_GPUDEVICES; i++)
gpus[i].dynamic = true;
Expand Down Expand Up @@ -5946,6 +5967,10 @@ int main (int argc, char *argv[])
opencl_api.api_detect();
#endif

#ifdef USE_BITFORCE
bitforce_api.api_detect();
#endif

#ifdef WANT_CPUMINE
cpu_api.api_detect();
#endif
Expand Down
Loading