mirror of
https://github.com/GOSTSec/sgminer
synced 2025-01-22 20:44:19 +00:00
BitForce FPGA support
cgminer will scan for and mine BitForce FPGAs on USB ports by providing the new --scan-serial <device> option, or autodetect them by searching /dev/serial/by-id for *BitFORCE_SHA256*
This commit is contained in:
parent
69966ffe17
commit
5dfc8b694f
@ -60,3 +60,7 @@ AM_CFLAGS = -DHAS_YASM
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
if USE_BITFORCE
|
||||
cgminer_SOURCES += bitforce.c
|
||||
endif
|
||||
|
219
bitforce.c
Normal file
219
bitforce.c
Normal file
@ -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
configure.ac
16
configure.ac
@ -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]))
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
29
main.c
29
main.c
@ -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;
|
||||
@ -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);
|
||||
@ -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"),
|
||||
@ -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;
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
@ -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)
|
||||
@ -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;
|
||||
@ -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
|
||||
|
31
miner.h
31
miner.h
@ -236,6 +236,9 @@ struct cgpu_info {
|
||||
int cgminer_id;
|
||||
struct device_api *api;
|
||||
int device_id;
|
||||
char *device_path;
|
||||
FILE *device_file;
|
||||
|
||||
bool enabled;
|
||||
int accepted;
|
||||
int rejected;
|
||||
@ -297,6 +300,32 @@ struct thr_info {
|
||||
extern int thr_info_create(struct thr_info *thr, pthread_attr_t *attr, void *(*start) (void *), void *arg);
|
||||
extern void thr_info_cancel(struct thr_info *thr);
|
||||
|
||||
|
||||
struct string_elist {
|
||||
char *string;
|
||||
bool free_me;
|
||||
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
static inline void string_elist_add(const char *s, struct list_head *head)
|
||||
{
|
||||
struct string_elist *n;
|
||||
|
||||
n = calloc(1, sizeof(*n));
|
||||
n->string = strdup(s);
|
||||
n->free_me = true;
|
||||
list_add_tail(&n->list, head);
|
||||
}
|
||||
|
||||
static inline void string_elist_del(struct string_elist *item)
|
||||
{
|
||||
if (item->free_me)
|
||||
free(item->string);
|
||||
list_del(&item->list);
|
||||
}
|
||||
|
||||
|
||||
static inline uint32_t swab32(uint32_t v)
|
||||
{
|
||||
return bswap_32(v);
|
||||
@ -468,6 +497,7 @@ extern void api(void);
|
||||
#define MAX_DEVICES 32
|
||||
#define MAX_POOLS (32)
|
||||
|
||||
extern struct list_head scan_devices;
|
||||
extern int nDevs;
|
||||
extern int opt_n_threads;
|
||||
extern int num_processors;
|
||||
@ -581,6 +611,7 @@ enum cl_kernel {
|
||||
KL_PHATK,
|
||||
};
|
||||
|
||||
extern void get_datestamp(char *, struct timeval *);
|
||||
bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce);
|
||||
extern void wlogprint(const char *f, ...);
|
||||
extern int curses_int(const char *query);
|
||||
|
Loading…
x
Reference in New Issue
Block a user