mirror of
https://github.com/GOSTSec/sgminer
synced 2025-03-09 20:21:01 +00:00
Merge pull request #123 from xiangfu/icarus
Add Icarus Support to Cgminer
This commit is contained in:
commit
882e4d85de
@ -70,3 +70,6 @@ if HAS_BITFORCE
|
||||
cgminer_SOURCES += bitforce.c
|
||||
endif
|
||||
|
||||
if HAS_ICARUS
|
||||
cgminer_SOURCES += icarus.c
|
||||
endif
|
||||
|
21
README
21
README
@ -50,6 +50,7 @@ CGMiner specific configuration options:
|
||||
--disable-opencl Override detection and disable building with opencl
|
||||
--disable-adl Override detection and disable building with adl
|
||||
--enable-bitforce Compile support for BitForce FPGAs(default disabled)
|
||||
--enable-icarus Compile support for Icarus Board(default disabled)
|
||||
|
||||
Basic *nix build instructions:
|
||||
To build with GPU mining support:
|
||||
@ -196,9 +197,9 @@ GPU only options:
|
||||
--ndevs|-n Enumerate number of detected GPUs and exit
|
||||
|
||||
|
||||
BitForce only options:
|
||||
FPGA mining boards(BitForce, Icarus) only options:
|
||||
|
||||
--scan-serial|-S <arg> Serial port to probe for BitForce device
|
||||
--scan-serial|-S <arg> Serial port to probe for FPGA mining device
|
||||
|
||||
|
||||
CPU only options:
|
||||
@ -317,14 +318,14 @@ The output line shows the following:
|
||||
(5s):1713.6 (avg):1707.8 Mh/s | Q:301 A:729 R:8 HW:0 E:242% U:22.53/m
|
||||
|
||||
Each column is as follows:
|
||||
A 5 second exponentially decaying average hash rate
|
||||
An all time average hash rate
|
||||
The number of requested (Queued) work items from the pools
|
||||
The number of Accepted shares
|
||||
The number of Rejected shares
|
||||
The number of HardWare errors
|
||||
The Efficiency defined as number of shares returned / work item
|
||||
The Utility defined as the number of shares / minute
|
||||
5s: A 5 second exponentially decaying average hash rate
|
||||
avg: An all time average hash rate
|
||||
Q: The number of requested (Queued) work items from the pools
|
||||
A: The number of Accepted shares
|
||||
R: The number of Rejected shares
|
||||
HW: The number of HardWare errors
|
||||
E: The Efficiency defined as number of shares returned / work item
|
||||
U: The Utility defined as the number of shares / minute
|
||||
|
||||
GPU 1: 73.5C 2551RPM | 427.3/443.0Mh/s | A:8 R:0 HW:0 U:4.39/m
|
||||
|
||||
|
19
cgminer.c
19
cgminer.c
@ -399,7 +399,7 @@ static char *set_int_1_to_10(const char *arg, int *i)
|
||||
return set_int_range(arg, i, 1, 10);
|
||||
}
|
||||
|
||||
#ifdef USE_BITFORCE
|
||||
#if defined(USE_BITFORCE) || defined(USE_ICARUS)
|
||||
static char *add_serial(char *arg)
|
||||
{
|
||||
string_elist_add(arg, &scan_devices);
|
||||
@ -661,7 +661,7 @@ static struct opt_table opt_config_table[] = {
|
||||
OPT_WITHOUT_ARG("--disable-gpu|-G",
|
||||
opt_set_bool, &opt_nogpu,
|
||||
"Disable GPU mining even if suitable devices exist"),
|
||||
#if defined(WANT_CPUMINE) && (defined(HAVE_OPENCL) || defined(USE_BITFORCE))
|
||||
#if defined(WANT_CPUMINE) && (defined(HAVE_OPENCL) || defined(USE_BITFORCE) || defined(USE_ICARUS))
|
||||
OPT_WITHOUT_ARG("--enable-cpu|-C",
|
||||
opt_set_bool, &opt_usecpu,
|
||||
"Enable CPU mining with other mining (default: no CPU mining if other devices exist)"),
|
||||
@ -776,10 +776,10 @@ 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
|
||||
#if defined(USE_BITFORCE) || defined(USE_ICARUS)
|
||||
OPT_WITH_ARG("--scan-serial|-S",
|
||||
add_serial, NULL, NULL,
|
||||
"Serial port to probe for BitForce device"),
|
||||
"Serial port to probe for FPGA Mining device"),
|
||||
#endif
|
||||
OPT_WITH_ARG("--scan-time|-s",
|
||||
set_int_0_to_9999, opt_show_intval, &opt_scantime,
|
||||
@ -960,6 +960,9 @@ static char *opt_verusage_and_exit(const char *extra)
|
||||
#endif
|
||||
#ifdef USE_BITFORCE
|
||||
"bitforce "
|
||||
#endif
|
||||
#ifdef USE_ICARUS
|
||||
"icarus "
|
||||
#endif
|
||||
"mining support.\n"
|
||||
, packagename);
|
||||
@ -4157,6 +4160,10 @@ struct device_api cpu_api = {
|
||||
extern struct device_api bitforce_api;
|
||||
#endif
|
||||
|
||||
#ifdef USE_ICARUS
|
||||
extern struct device_api icarus_api;
|
||||
#endif
|
||||
|
||||
|
||||
static int cgminer_id_count = 0;
|
||||
|
||||
@ -4311,6 +4318,10 @@ int main (int argc, char *argv[])
|
||||
bitforce_api.api_detect();
|
||||
#endif
|
||||
|
||||
#ifdef USE_ICARUS
|
||||
icarus_api.api_detect();
|
||||
#endif
|
||||
|
||||
#ifdef WANT_CPUMINE
|
||||
cpu_api.api_detect();
|
||||
#endif
|
||||
|
21
configure.ac
21
configure.ac
@ -196,6 +196,17 @@ if test "x$bitforce" = xyes; then
|
||||
fi
|
||||
AM_CONDITIONAL([HAS_BITFORCE], [test x$bitforce = xyes])
|
||||
|
||||
icarus="no"
|
||||
|
||||
AC_ARG_ENABLE([icarus],
|
||||
[AC_HELP_STRING([--enable-icarus],[Compile support for Icarus (default disabled)])],
|
||||
[icarus=$enableval]
|
||||
)
|
||||
if test "x$icarus" = xyes; then
|
||||
AC_DEFINE([USE_ICARUS], [1], [Defined to 1 if Icarus support is wanted])
|
||||
fi
|
||||
AM_CONDITIONAL([HAS_ICARUS], [test x$icarus = xyes])
|
||||
|
||||
AC_SEARCH_LIBS(addstr, ncurses pdcurses, ,
|
||||
AC_MSG_ERROR([Could not find curses library - please install libncurses-dev or pdcurses-dev]))
|
||||
|
||||
@ -338,13 +349,13 @@ if test "x$opencl" != xno; then
|
||||
echo " OpenCL...............: FOUND. GPU mining support enabled"
|
||||
else
|
||||
echo " OpenCL...............: NOT FOUND. GPU mining support DISABLED"
|
||||
if test "x$cpumining$bitforce" = xnono; then
|
||||
if test "x$cpumining$bitforce$icarus" = xnonono; then
|
||||
AC_MSG_ERROR([No mining configured in])
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo " OpenCL...............: Detection overrided. GPU mining support DISABLED"
|
||||
if test "x$cpumining$bitforce" = xnono; then
|
||||
if test "x$cpumining$bitforce$icarus" = xnonono; then
|
||||
AC_MSG_ERROR([No mining configured in])
|
||||
fi
|
||||
fi
|
||||
@ -366,6 +377,12 @@ else
|
||||
echo " BitForce.FPGAs.......: Disabled"
|
||||
fi
|
||||
|
||||
if test "x$icarus" = xyes; then
|
||||
echo " Icarus.FPGAs.........: Enabled"
|
||||
else
|
||||
echo " Icarus.FPGAs.........: Disabled"
|
||||
fi
|
||||
|
||||
echo
|
||||
if test "x$cpumining" = xyes; then
|
||||
echo " CPU Mining...........: Enabled"
|
||||
|
333
icarus.c
Normal file
333
icarus.c
Normal file
@ -0,0 +1,333 @@
|
||||
/*
|
||||
* Copyright 2012 Luke Dashjr
|
||||
* Copyright 2012 Xiangfu <xiangfu@openmobilefree.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Those code should be works fine with V2 and V3 bitstream of Icarus.
|
||||
* Operation:
|
||||
* No detection implement.
|
||||
* Input: 64B = 32B midstate + 20B fill bytes + last 12 bytes of block head.
|
||||
* Return: send back 32bits immediately when Icarus found a valid nonce.
|
||||
* no query protocol implemented here, if no data send back in ~11.3
|
||||
* seconds (full cover time on 32bit nonce range by 380MH/s speed)
|
||||
* just send another work.
|
||||
* Notice:
|
||||
* 1. Icarus will start calculate when you push a work to them, even they
|
||||
* are busy.
|
||||
* 2. The 2 FPGAs on Icarus will distribute the job, one will calculate the
|
||||
* 0 ~ 7FFFFFFF, another one will cover the 80000000 ~ FFFFFFFF.
|
||||
* 3. It's possible for 2 FPGAs both find valid nonce in the meantime, the 2
|
||||
* valid nonce will all be send back.
|
||||
* 4. Icarus will stop work when: a valid nonce has been found or 32 bits
|
||||
* nonce range is completely calculated.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#ifndef WIN32
|
||||
#include <termios.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
#else
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#include "elist.h"
|
||||
#include "miner.h"
|
||||
|
||||
#define ICARUS_READ_FAULT_COUNT (8)
|
||||
|
||||
static int icarus_read_count;
|
||||
static int icarus_write_fault;
|
||||
|
||||
struct device_api icarus_api;
|
||||
|
||||
static void rev(unsigned char *s, size_t l)
|
||||
{
|
||||
size_t i, j;
|
||||
unsigned char t;
|
||||
|
||||
for (i = 0, j = l - 1; i < j; i++, j--) {
|
||||
t = s[i];
|
||||
s[i] = s[j];
|
||||
s[j] = t;
|
||||
}
|
||||
}
|
||||
|
||||
static int icarus_open(const char *devpath)
|
||||
{
|
||||
#ifndef WIN32
|
||||
struct termios my_termios;
|
||||
|
||||
int serialfd = open(devpath, O_RDWR | O_CLOEXEC | O_NOCTTY);
|
||||
|
||||
if (serialfd == -1)
|
||||
return -1;
|
||||
|
||||
tcgetattr(serialfd, &my_termios);
|
||||
my_termios.c_cflag = B115200;
|
||||
my_termios.c_cflag |= CS8;
|
||||
my_termios.c_cflag |= CREAD;
|
||||
my_termios.c_cflag |= CLOCAL;
|
||||
my_termios.c_cflag &= ~(CSIZE | PARENB);
|
||||
|
||||
my_termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK |
|
||||
ISTRIP | INLCR | IGNCR | ICRNL | IXON);
|
||||
my_termios.c_oflag &= ~OPOST;
|
||||
my_termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
|
||||
my_termios.c_cc[VTIME] = 10; /* block 1 second */
|
||||
my_termios.c_cc[VMIN] = 0;
|
||||
tcsetattr(serialfd, TCSANOW, &my_termios);
|
||||
|
||||
tcflush(serialfd, TCOFLUSH);
|
||||
tcflush(serialfd, TCIFLUSH);
|
||||
|
||||
return serialfd;
|
||||
#else
|
||||
HANDLE hSerial = CreateFile(devpath, GENERIC_READ | GENERIC_WRITE, 0,
|
||||
NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (unlikely(hSerial == INVALID_HANDLE_VALUE))
|
||||
return -1;
|
||||
/* TODO: Needs setup read block time. just like VTIME = 10 */
|
||||
return _open_osfhandle((LONG)hSerial, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void icarus_gets(char *buf, size_t bufLen, int fd)
|
||||
{
|
||||
ssize_t ret = 0;
|
||||
|
||||
icarus_read_count = 0;
|
||||
|
||||
while (bufLen) {
|
||||
ret = read(fd, buf, 1);
|
||||
if (ret == 1) {
|
||||
bufLen--;
|
||||
buf++;
|
||||
continue;
|
||||
}
|
||||
|
||||
icarus_read_count++;
|
||||
if (icarus_read_count == ICARUS_READ_FAULT_COUNT) {
|
||||
applog(LOG_WARNING,
|
||||
"Icarus Read: No data in %d seconds",
|
||||
ICARUS_READ_FAULT_COUNT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void icarus_write(int fd, const void *buf, size_t bufLen)
|
||||
{
|
||||
ssize_t ret;
|
||||
|
||||
ret = write(fd, buf, bufLen);
|
||||
if (unlikely(ret != bufLen))
|
||||
icarus_write_fault = 1;
|
||||
}
|
||||
|
||||
#define icarus_close(fd) close(fd)
|
||||
|
||||
static bool icarus_detect_one(const char *devpath)
|
||||
{
|
||||
int fd;
|
||||
|
||||
const unsigned char golden_ob[] =
|
||||
"2db907f9cb4eb938ded904f4832c4331"
|
||||
"0380e3aeb54364057e7fec5157bfc533"
|
||||
"00000000000000000000000080000000"
|
||||
"00000000a58e091ac342724e7c3dc346";
|
||||
const unsigned char golden_nonce[] = "063c5e01";
|
||||
|
||||
char ob_bin[64], nonce_bin[4];
|
||||
char *nonce_hex;
|
||||
|
||||
if (total_devices == MAX_DEVICES)
|
||||
return false;
|
||||
|
||||
fd = icarus_open(devpath);
|
||||
if (unlikely(fd == -1)) {
|
||||
applog(LOG_ERR, "Icarus Detect: Failed to open %s", devpath);
|
||||
return false;
|
||||
}
|
||||
|
||||
hex2bin(ob_bin, golden_ob, sizeof(ob_bin));
|
||||
icarus_write(fd, ob_bin, sizeof(ob_bin));
|
||||
|
||||
memset(nonce_bin, 0, sizeof(nonce_bin));
|
||||
icarus_gets(nonce_bin, sizeof(nonce_bin), fd);
|
||||
|
||||
icarus_close(fd);
|
||||
|
||||
nonce_hex = bin2hex(nonce_bin, sizeof(nonce_bin));
|
||||
if (nonce_hex) {
|
||||
if (strncmp(nonce_hex, golden_nonce, 8)) {
|
||||
applog(LOG_ERR,
|
||||
"Icarus Detect: "
|
||||
"Test failed at %s : get %s, should: %s",
|
||||
devpath, nonce_hex, golden_nonce);
|
||||
free(nonce_hex);
|
||||
return false;
|
||||
}
|
||||
free(nonce_hex);
|
||||
} else
|
||||
return false;
|
||||
|
||||
/* We have a real Icarus! */
|
||||
struct cgpu_info *icarus;
|
||||
icarus = calloc(1, sizeof(struct cgpu_info));
|
||||
icarus->api = &icarus_api;
|
||||
icarus->device_id = total_devices;
|
||||
icarus->device_path = strdup(devpath);
|
||||
icarus->threads = 1;
|
||||
devices[total_devices++] = icarus;
|
||||
|
||||
icarus_write_fault = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void icarus_detect()
|
||||
{
|
||||
struct string_elist *iter, *tmp;
|
||||
|
||||
list_for_each_entry_safe(iter, tmp, &scan_devices, list) {
|
||||
if (icarus_detect_one(iter->string))
|
||||
string_elist_del(iter);
|
||||
}
|
||||
}
|
||||
|
||||
static bool icarus_prepare(struct thr_info *thr)
|
||||
{
|
||||
struct cgpu_info *icarus = thr->cgpu;
|
||||
|
||||
struct timeval now;
|
||||
|
||||
int fd = icarus_open(icarus->device_path);
|
||||
if (unlikely(-1 == fd)) {
|
||||
applog(LOG_ERR, "Failed to open Icarus on %s",
|
||||
icarus->device_path);
|
||||
return false;
|
||||
}
|
||||
|
||||
icarus->device_fd = fd;
|
||||
|
||||
applog(LOG_INFO, "Opened Icarus on %s", icarus->device_path);
|
||||
gettimeofday(&now, NULL);
|
||||
get_datestamp(icarus->init, &now);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint64_t icarus_scanhash(struct thr_info *thr, struct work *work,
|
||||
uint64_t max_nonce)
|
||||
{
|
||||
struct cgpu_info *icarus;
|
||||
int fd;
|
||||
|
||||
unsigned char ob_bin[64], nonce_bin[4];
|
||||
unsigned char *ob_hex, *nonce_hex;
|
||||
uint32_t nonce;
|
||||
uint32_t hash_count;
|
||||
time_t t;
|
||||
|
||||
icarus = thr->cgpu;
|
||||
fd = icarus->device_fd;
|
||||
|
||||
memset(ob_bin, 0, sizeof(ob_bin));
|
||||
memcpy(ob_bin, work->midstate, 32);
|
||||
memcpy(ob_bin + 52, work->data + 64, 12);
|
||||
rev(ob_bin, 32);
|
||||
rev(ob_bin + 52, 12);
|
||||
#ifndef WIN32
|
||||
tcflush(fd, TCOFLUSH);
|
||||
#endif
|
||||
icarus_write(fd, ob_bin, sizeof(ob_bin));
|
||||
if (icarus_write_fault)
|
||||
return 0; /* This should never happen */
|
||||
|
||||
ob_hex = bin2hex(ob_bin, sizeof(ob_bin));
|
||||
if (ob_hex) {
|
||||
t = time(NULL);
|
||||
applog(LOG_DEBUG, "Icarus send : %s", ob_hex);
|
||||
free(ob_hex);
|
||||
}
|
||||
|
||||
/* Icarus will return 8 bytes nonces or nothing */
|
||||
memset(nonce_bin, 0, sizeof(nonce_bin));
|
||||
icarus_gets(nonce_bin, sizeof(nonce_bin), fd);
|
||||
|
||||
nonce_hex = bin2hex(nonce_bin, sizeof(nonce_bin));
|
||||
if (nonce_hex) {
|
||||
t = time(NULL) - t;
|
||||
applog(LOG_DEBUG, "Icarus return (elapse %d seconds): %s",
|
||||
t, nonce_hex);
|
||||
free(nonce_hex);
|
||||
}
|
||||
|
||||
memcpy((char *)&nonce, nonce_bin, sizeof(nonce_bin));
|
||||
|
||||
if (nonce == 0 && icarus_read_count == ICARUS_READ_FAULT_COUNT)
|
||||
return 0xffffffff;
|
||||
|
||||
#ifndef __BIG_ENDIAN__
|
||||
nonce = swab32(nonce);
|
||||
#endif
|
||||
work->blk.nonce = 0xffffffff;
|
||||
submit_nonce(thr, work, nonce);
|
||||
|
||||
hash_count = (nonce & 0x7fffffff);
|
||||
if (hash_count == 0)
|
||||
hash_count = 2;
|
||||
else {
|
||||
if (hash_count++ == 0x7fffffff)
|
||||
hash_count = 0xffffffff;
|
||||
else
|
||||
hash_count <<= 1;
|
||||
}
|
||||
|
||||
return hash_count;
|
||||
}
|
||||
|
||||
static void icarus_shutdown(struct thr_info *thr)
|
||||
{
|
||||
struct cgpu_info *icarus;
|
||||
int fd;
|
||||
|
||||
if (thr->cgpu) {
|
||||
icarus = thr->cgpu;
|
||||
|
||||
if (icarus->device_path)
|
||||
free(icarus->device_path);
|
||||
|
||||
close(icarus->device_fd);
|
||||
|
||||
devices[icarus->device_id] = NULL;
|
||||
free(icarus);
|
||||
|
||||
thr->cgpu = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct device_api icarus_api = {
|
||||
.name = "Icarus",
|
||||
.api_detect = icarus_detect,
|
||||
.thread_prepare = icarus_prepare,
|
||||
.scanhash = icarus_scanhash,
|
||||
.thread_shutdown = icarus_shutdown,
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user