|
@@ -33,27 +33,40 @@
|
|
|
|
|
|
|
|
static const char * const minergate_stats_file = "/var/run/mg_rate_temp";
|
|
static const char * const minergate_stats_file = "/var/run/mg_rate_temp";
|
|
|
|
|
|
|
|
-#define MINERGATE_PROTOCOL_VER 6
|
|
|
|
|
#define MINERGATE_MAGIC 0xcaf4
|
|
#define MINERGATE_MAGIC 0xcaf4
|
|
|
-static const int minergate_max_responses = 300;
|
|
|
|
|
#define MINERGATE_PKT_HEADER_SZ 8
|
|
#define MINERGATE_PKT_HEADER_SZ 8
|
|
|
#define MINERGATE_PKT_REQ_ITEM_SZ 0x34
|
|
#define MINERGATE_PKT_REQ_ITEM_SZ 0x34
|
|
|
-#define MINERGATE_PKT_REQ_MAX 100
|
|
|
|
|
-#define MINERGATE_PKT_RSP_ITEM_SZ 0x14
|
|
|
|
|
-#define MINERGATE_PKT_RSP_MAX 300
|
|
|
|
|
#define MINERGATE_POLL_US 100000
|
|
#define MINERGATE_POLL_US 100000
|
|
|
#define MINERGATE_RETRY_US 5000000
|
|
#define MINERGATE_RETRY_US 5000000
|
|
|
|
|
|
|
|
-#define MINERGATE_PKT_REQ_SZ (MINERGATE_PKT_HEADER_SZ + (MINERGATE_PKT_REQ_ITEM_SZ * MINERGATE_PKT_REQ_MAX))
|
|
|
|
|
-#define MINERGATE_PKT_RSP_SZ (MINERGATE_PKT_HEADER_SZ + (MINERGATE_PKT_RSP_ITEM_SZ * MINERGATE_PKT_RSP_MAX))
|
|
|
|
|
-
|
|
|
|
|
BFG_REGISTER_DRIVER(minergate_drv)
|
|
BFG_REGISTER_DRIVER(minergate_drv)
|
|
|
|
|
|
|
|
|
|
+enum minergate_protocol_ver {
|
|
|
|
|
+ MPV_SP10 = 6,
|
|
|
|
|
+ MPV_SP30 = 30,
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
enum minergate_reqpkt_flags {
|
|
enum minergate_reqpkt_flags {
|
|
|
MRPF_FIRST = 1,
|
|
MRPF_FIRST = 1,
|
|
|
MRPF_FLUSH = 2,
|
|
MRPF_FLUSH = 2,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+struct minergate_config {
|
|
|
|
|
+ uint8_t protover;
|
|
|
|
|
+ int n_req;
|
|
|
|
|
+ int n_req_queue;
|
|
|
|
|
+ int n_rsp;
|
|
|
|
|
+ int queue;
|
|
|
|
|
+ char *stats_file;
|
|
|
|
|
+ int minimum_roll;
|
|
|
|
|
+ int desired_roll;
|
|
|
|
|
+ int work_duration;
|
|
|
|
|
+
|
|
|
|
|
+ int pkt_req_sz;
|
|
|
|
|
+ int pkt_rsp_sz;
|
|
|
|
|
+ int pkt_rsp_item_sz;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
struct minergate_state {
|
|
struct minergate_state {
|
|
|
work_device_id_t next_jobid;
|
|
work_device_id_t next_jobid;
|
|
|
unsigned ready_to_queue;
|
|
unsigned ready_to_queue;
|
|
@@ -107,18 +120,118 @@ ssize_t minergate_read(const int fd, void * const buf_p, size_t bufLen)
|
|
|
return ret;
|
|
return ret;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+#define DEF_POSITIVE_VAR(VARNAME) \
|
|
|
|
|
+static \
|
|
|
|
|
+const char *minergate_init_ ## VARNAME(struct cgpu_info * const proc, const char * const optname, const char * const newvalue, char * const replybuf, enum bfg_set_device_replytype * const out_success) \
|
|
|
|
|
+{ \
|
|
|
|
|
+ struct minergate_config * const mgcfg = proc->device_data; \
|
|
|
|
|
+ int nv = atoi(newvalue); \
|
|
|
|
|
+ if (nv < 0) \
|
|
|
|
|
+ return #VARNAME " must be positive"; \
|
|
|
|
|
+ mgcfg->VARNAME = nv; \
|
|
|
|
|
+ return NULL; \
|
|
|
|
|
+} \
|
|
|
|
|
+// END OF DEF_POSITIVE_VAR
|
|
|
|
|
+
|
|
|
static
|
|
static
|
|
|
-bool minergate_detect_one(const char * const devpath)
|
|
|
|
|
|
|
+const char *minergate_init_protover(struct cgpu_info * const proc, const char * const optname, const char * const newvalue, char * const replybuf, enum bfg_set_device_replytype * const out_success)
|
|
|
|
|
+{
|
|
|
|
|
+ struct minergate_config * const mgcfg = proc->device_data;
|
|
|
|
|
+
|
|
|
|
|
+ int i = atoi(newvalue);
|
|
|
|
|
+
|
|
|
|
|
+ if (i != MPV_SP10 || i != MPV_SP30)
|
|
|
|
|
+ return "Invalid protocol version";
|
|
|
|
|
+
|
|
|
|
|
+ mgcfg->protover = i;
|
|
|
|
|
+
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+DEF_POSITIVE_VAR(n_req)
|
|
|
|
|
+DEF_POSITIVE_VAR(n_req_queue)
|
|
|
|
|
+DEF_POSITIVE_VAR(n_rsp)
|
|
|
|
|
+DEF_POSITIVE_VAR(queue)
|
|
|
|
|
+
|
|
|
|
|
+static
|
|
|
|
|
+const char *minergate_init_stats_file(struct cgpu_info * const proc, const char * const optname, const char * const newvalue, char * const replybuf, enum bfg_set_device_replytype * const out_success)
|
|
|
|
|
+{
|
|
|
|
|
+ struct minergate_config * const mgcfg = proc->device_data;
|
|
|
|
|
+ free(mgcfg->stats_file);
|
|
|
|
|
+ mgcfg->stats_file = trimmed_strdup(newvalue);
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+DEF_POSITIVE_VAR(work_duration)
|
|
|
|
|
+DEF_POSITIVE_VAR(minimum_roll)
|
|
|
|
|
+DEF_POSITIVE_VAR(desired_roll)
|
|
|
|
|
+
|
|
|
|
|
+static const struct bfg_set_device_definition minergate_set_device_funcs_probe[] = {
|
|
|
|
|
+ {"protover", minergate_init_protover, NULL},
|
|
|
|
|
+ {"n_req", minergate_init_n_req, NULL},
|
|
|
|
|
+ {"n_req_queue", minergate_init_n_req_queue, NULL},
|
|
|
|
|
+ {"n_rsp", minergate_init_n_rsp, NULL},
|
|
|
|
|
+ {"queue", minergate_init_queue, NULL},
|
|
|
|
|
+ {"stats_file", minergate_init_stats_file, NULL},
|
|
|
|
|
+ {"work_duration", minergate_init_work_duration, NULL},
|
|
|
|
|
+ {"minimum_roll", minergate_init_minimum_roll, NULL},
|
|
|
|
|
+ {"desired_roll", minergate_init_desired_roll, NULL},
|
|
|
|
|
+ {NULL},
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+static
|
|
|
|
|
+bool minergate_detect_one_extra(const char * const devpath, const enum minergate_protocol_ver def_protover)
|
|
|
{
|
|
{
|
|
|
bool rv = false;
|
|
bool rv = false;
|
|
|
const int fd = minergate_open(devpath);
|
|
const int fd = minergate_open(devpath);
|
|
|
if (unlikely(fd < 0))
|
|
if (unlikely(fd < 0))
|
|
|
applogr(false, LOG_DEBUG, "%s: %s: Cannot connect", minergate_drv.dname, devpath);
|
|
applogr(false, LOG_DEBUG, "%s: %s: Cannot connect", minergate_drv.dname, devpath);
|
|
|
|
|
|
|
|
|
|
+ struct minergate_config * const mgcfg = malloc(sizeof(*mgcfg));
|
|
|
|
|
+ *mgcfg = (struct minergate_config){
|
|
|
|
|
+ .protover = def_protover,
|
|
|
|
|
+ .work_duration = -1,
|
|
|
|
|
+ .minimum_roll = -1,
|
|
|
|
|
+ .desired_roll = -1,
|
|
|
|
|
+ };
|
|
|
|
|
+ drv_set_defaults(&minergate_drv, minergate_set_device_funcs_probe, mgcfg, devpath, NULL, 1);
|
|
|
|
|
+ switch (mgcfg->protover)
|
|
|
|
|
+ {
|
|
|
|
|
+ case MPV_SP10:
|
|
|
|
|
+ BFGINIT(mgcfg->n_req, 100);
|
|
|
|
|
+ BFGINIT(mgcfg->n_req_queue, mgcfg->n_req);
|
|
|
|
|
+ BFGINIT(mgcfg->n_rsp, 300);
|
|
|
|
|
+ BFGINIT(mgcfg->queue, 300);
|
|
|
|
|
+ mgcfg->pkt_rsp_item_sz = 0x14;
|
|
|
|
|
+ mgcfg->minimum_roll = mgcfg->desired_roll = 0; // not supported
|
|
|
|
|
+ break;
|
|
|
|
|
+ case MPV_SP30:
|
|
|
|
|
+ BFGINIT(mgcfg->n_req, 30);
|
|
|
|
|
+ BFGINIT(mgcfg->n_req_queue, min(10, mgcfg->n_req));
|
|
|
|
|
+ BFGINIT(mgcfg->n_rsp, 60);
|
|
|
|
|
+ BFGINIT(mgcfg->queue, 40);
|
|
|
|
|
+ mgcfg->pkt_rsp_item_sz = 0x10;
|
|
|
|
|
+ if (mgcfg->minimum_roll == -1)
|
|
|
|
|
+ mgcfg->minimum_roll = 60;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ BFGINIT(mgcfg->stats_file, strdup(minergate_stats_file));
|
|
|
|
|
+ mgcfg->desired_roll = max(mgcfg->desired_roll, mgcfg->minimum_roll);
|
|
|
|
|
+ if (mgcfg->work_duration == -1)
|
|
|
|
|
+ mgcfg->work_duration = 0x10; // reasonable guess?
|
|
|
|
|
+ mgcfg->pkt_req_sz = MINERGATE_PKT_HEADER_SZ + (MINERGATE_PKT_REQ_ITEM_SZ * mgcfg->n_req);
|
|
|
|
|
+ mgcfg->pkt_rsp_sz = MINERGATE_PKT_HEADER_SZ + (mgcfg->pkt_rsp_item_sz * mgcfg->n_rsp);
|
|
|
|
|
+
|
|
|
int epfd = -1;
|
|
int epfd = -1;
|
|
|
- uint8_t buf[MINERGATE_PKT_REQ_SZ] = {0xbf, 0x90, MINERGATE_PROTOCOL_VER, MRPF_FIRST, 0,0, 0 /* req count */,};
|
|
|
|
|
|
|
+ uint8_t buf[mgcfg->pkt_req_sz];
|
|
|
|
|
+ buf[0] = 0xbf;
|
|
|
|
|
+ buf[1] = 0x90;
|
|
|
|
|
+ buf[2] = mgcfg->protover;
|
|
|
|
|
+ buf[3] = MRPF_FIRST;
|
|
|
pk_u16le(buf, 4, MINERGATE_MAGIC);
|
|
pk_u16le(buf, 4, MINERGATE_MAGIC);
|
|
|
- if (MINERGATE_PKT_REQ_SZ != write(fd, buf, MINERGATE_PKT_REQ_SZ))
|
|
|
|
|
|
|
+ memset(&buf[6], '\0', mgcfg->pkt_req_sz - 6);
|
|
|
|
|
+ if (mgcfg->pkt_req_sz != write(fd, buf, mgcfg->pkt_req_sz))
|
|
|
return_via_applog(out, , LOG_DEBUG, "%s: %s: write incomplete or failed", minergate_drv.dname, devpath);
|
|
return_via_applog(out, , LOG_DEBUG, "%s: %s: write incomplete or failed", minergate_drv.dname, devpath);
|
|
|
|
|
|
|
|
epfd = epoll_create(1);
|
|
epfd = epoll_create(1);
|
|
@@ -145,13 +258,13 @@ bool minergate_detect_one(const char * const devpath)
|
|
|
|
|
|
|
|
if (buf[1] != 0x90)
|
|
if (buf[1] != 0x90)
|
|
|
return_via_applog(out, , LOG_DEBUG, "%s: %s: %s mismatch", minergate_drv.dname, devpath, "request_id");
|
|
return_via_applog(out, , LOG_DEBUG, "%s: %s: %s mismatch", minergate_drv.dname, devpath, "request_id");
|
|
|
- if (buf[2] != MINERGATE_PROTOCOL_VER)
|
|
|
|
|
|
|
+ if (buf[2] != mgcfg->protover)
|
|
|
return_via_applog(out, , LOG_DEBUG, "%s: %s: %s mismatch", minergate_drv.dname, devpath, "Protocol version");
|
|
return_via_applog(out, , LOG_DEBUG, "%s: %s: %s mismatch", minergate_drv.dname, devpath, "Protocol version");
|
|
|
if (upk_u16le(buf, 4) != MINERGATE_MAGIC)
|
|
if (upk_u16le(buf, 4) != MINERGATE_MAGIC)
|
|
|
return_via_applog(out, , LOG_DEBUG, "%s: %s: %s mismatch", minergate_drv.dname, devpath, "magic");
|
|
return_via_applog(out, , LOG_DEBUG, "%s: %s: %s mismatch", minergate_drv.dname, devpath, "magic");
|
|
|
|
|
|
|
|
uint16_t responses = upk_u16le(buf, 6);
|
|
uint16_t responses = upk_u16le(buf, 6);
|
|
|
- if (responses > minergate_max_responses)
|
|
|
|
|
|
|
+ if (responses > mgcfg->n_rsp)
|
|
|
return_via_applog(out, , LOG_DEBUG, "%s: %s: More than maximum responses", minergate_drv.dname, devpath);
|
|
return_via_applog(out, , LOG_DEBUG, "%s: %s: More than maximum responses", minergate_drv.dname, devpath);
|
|
|
|
|
|
|
|
if (bfg_claim_any2(&minergate_drv, devpath, "unix", devpath))
|
|
if (bfg_claim_any2(&minergate_drv, devpath, "unix", devpath))
|
|
@@ -161,22 +274,36 @@ bool minergate_detect_one(const char * const devpath)
|
|
|
*cgpu = (struct cgpu_info){
|
|
*cgpu = (struct cgpu_info){
|
|
|
.drv = &minergate_drv,
|
|
.drv = &minergate_drv,
|
|
|
.device_path = strdup(devpath),
|
|
.device_path = strdup(devpath),
|
|
|
|
|
+ .device_data = mgcfg,
|
|
|
.deven = DEV_ENABLED,
|
|
.deven = DEV_ENABLED,
|
|
|
.threads = 1,
|
|
.threads = 1,
|
|
|
};
|
|
};
|
|
|
rv = add_cgpu(cgpu);
|
|
rv = add_cgpu(cgpu);
|
|
|
|
|
|
|
|
out:
|
|
out:
|
|
|
|
|
+ if (!rv)
|
|
|
|
|
+ free(mgcfg);
|
|
|
close(fd);
|
|
close(fd);
|
|
|
if (epfd >= 0)
|
|
if (epfd >= 0)
|
|
|
close(epfd);
|
|
close(epfd);
|
|
|
return rv;
|
|
return rv;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static
|
|
|
|
|
+bool minergate_detect_one(const char * const devpath)
|
|
|
|
|
+{
|
|
|
|
|
+ return minergate_detect_one_extra(devpath, MPV_SP10);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static
|
|
static
|
|
|
int minergate_detect_auto(void)
|
|
int minergate_detect_auto(void)
|
|
|
{
|
|
{
|
|
|
- return minergate_detect_one("/tmp/connection_pipe") ? 1 : 0;
|
|
|
|
|
|
|
+ int total = 0;
|
|
|
|
|
+ if (minergate_detect_one_extra("/tmp/connection_pipe", MPV_SP10))
|
|
|
|
|
+ ++total;
|
|
|
|
|
+ if (minergate_detect_one_extra("/tmp/connection_pipe_sp30", MPV_SP30))
|
|
|
|
|
+ ++total;
|
|
|
|
|
+ return total;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static
|
|
static
|
|
@@ -189,13 +316,14 @@ static
|
|
|
bool minergate_init(struct thr_info * const thr)
|
|
bool minergate_init(struct thr_info * const thr)
|
|
|
{
|
|
{
|
|
|
struct cgpu_info * const dev = thr->cgpu;
|
|
struct cgpu_info * const dev = thr->cgpu;
|
|
|
|
|
+ struct minergate_config * const mgcfg = dev->device_data;
|
|
|
|
|
|
|
|
const int fd = minergate_open(dev->device_path);
|
|
const int fd = minergate_open(dev->device_path);
|
|
|
dev->device_fd = fd;
|
|
dev->device_fd = fd;
|
|
|
if (fd < 0)
|
|
if (fd < 0)
|
|
|
applogr(false, LOG_ERR, "%s: Cannot connect", dev->dev_repr);
|
|
applogr(false, LOG_ERR, "%s: Cannot connect", dev->dev_repr);
|
|
|
|
|
|
|
|
- struct minergate_state * const state = malloc(sizeof(*state) + MINERGATE_PKT_REQ_SZ);
|
|
|
|
|
|
|
+ struct minergate_state * const state = malloc(sizeof(*state) + mgcfg->pkt_req_sz);
|
|
|
if (!state)
|
|
if (!state)
|
|
|
applogr(false, LOG_ERR, "%s: %s failed", dev->dev_repr, "malloc");
|
|
applogr(false, LOG_ERR, "%s: %s failed", dev->dev_repr, "malloc");
|
|
|
*state = (struct minergate_state){
|
|
*state = (struct minergate_state){
|
|
@@ -205,8 +333,8 @@ bool minergate_init(struct thr_info * const thr)
|
|
|
thr->work = thr->work_list = NULL;
|
|
thr->work = thr->work_list = NULL;
|
|
|
|
|
|
|
|
mutex_init(&dev->device_mutex);
|
|
mutex_init(&dev->device_mutex);
|
|
|
- memset(state->req_buffer, 0, MINERGATE_PKT_REQ_SZ);
|
|
|
|
|
- pk_u8(state->req_buffer, 2, MINERGATE_PROTOCOL_VER);
|
|
|
|
|
|
|
+ memset(state->req_buffer, 0, mgcfg->pkt_req_sz);
|
|
|
|
|
+ pk_u8(state->req_buffer, 2, mgcfg->protover);
|
|
|
state->req_buffer[3] = MRPF_FIRST | MRPF_FLUSH;
|
|
state->req_buffer[3] = MRPF_FIRST | MRPF_FLUSH;
|
|
|
pk_u16le(state->req_buffer, 4, MINERGATE_MAGIC);
|
|
pk_u16le(state->req_buffer, 4, MINERGATE_MAGIC);
|
|
|
timer_set_delay_from_now(&thr->tv_poll, 0);
|
|
timer_set_delay_from_now(&thr->tv_poll, 0);
|
|
@@ -217,14 +345,15 @@ bool minergate_init(struct thr_info * const thr)
|
|
|
static
|
|
static
|
|
|
bool minergate_queue_full(struct thr_info * const thr)
|
|
bool minergate_queue_full(struct thr_info * const thr)
|
|
|
{
|
|
{
|
|
|
- static const unsigned max_minergate_jobs = 300, max_requests = 100;
|
|
|
|
|
|
|
+ struct cgpu_info * const dev = thr->cgpu;
|
|
|
|
|
+ struct minergate_config * const mgcfg = dev->device_data;
|
|
|
struct minergate_state * const state = thr->cgpu_data;
|
|
struct minergate_state * const state = thr->cgpu_data;
|
|
|
bool qf;
|
|
bool qf;
|
|
|
|
|
|
|
|
- if (HASH_COUNT(thr->work) + state->ready_to_queue >= max_minergate_jobs)
|
|
|
|
|
|
|
+ if (HASH_COUNT(thr->work) + state->ready_to_queue >= mgcfg->queue)
|
|
|
qf = true;
|
|
qf = true;
|
|
|
else
|
|
else
|
|
|
- if (state->ready_to_queue >= max_requests)
|
|
|
|
|
|
|
+ if (state->ready_to_queue >= mgcfg->n_req_queue)
|
|
|
qf = true;
|
|
qf = true;
|
|
|
else
|
|
else
|
|
|
if (state->req_buffer[3] & MRPF_FLUSH)
|
|
if (state->req_buffer[3] & MRPF_FLUSH)
|
|
@@ -241,6 +370,7 @@ static
|
|
|
bool minergate_queue_append(struct thr_info * const thr, struct work * const work)
|
|
bool minergate_queue_append(struct thr_info * const thr, struct work * const work)
|
|
|
{
|
|
{
|
|
|
struct cgpu_info * const dev = thr->cgpu;
|
|
struct cgpu_info * const dev = thr->cgpu;
|
|
|
|
|
+ struct minergate_config * const mgcfg = dev->device_data;
|
|
|
struct minergate_state * const state = thr->cgpu_data;
|
|
struct minergate_state * const state = thr->cgpu_data;
|
|
|
|
|
|
|
|
if (minergate_queue_full(thr))
|
|
if (minergate_queue_full(thr))
|
|
@@ -250,6 +380,20 @@ bool minergate_queue_append(struct thr_info * const thr, struct work * const wor
|
|
|
work->tv_stamp.tv_sec = 0;
|
|
work->tv_stamp.tv_sec = 0;
|
|
|
|
|
|
|
|
uint8_t * const my_buf = &state->req_buffer[MINERGATE_PKT_HEADER_SZ + (MINERGATE_PKT_REQ_ITEM_SZ * state->ready_to_queue++)];
|
|
uint8_t * const my_buf = &state->req_buffer[MINERGATE_PKT_HEADER_SZ + (MINERGATE_PKT_REQ_ITEM_SZ * state->ready_to_queue++)];
|
|
|
|
|
+
|
|
|
|
|
+ if (mgcfg->desired_roll)
|
|
|
|
|
+ {
|
|
|
|
|
+ struct timeval tv_now, tv_latest;
|
|
|
|
|
+ timer_set_now(&tv_now);
|
|
|
|
|
+ timer_set_delay(&tv_latest, &tv_now, mgcfg->work_duration * 1000000LL);
|
|
|
|
|
+ int ntimeroll = work_ntime_range(work, &tv_now, &tv_latest, mgcfg->desired_roll);
|
|
|
|
|
+ // NOTE: If minimum_roll bumps ntimeroll up, we may get rejects :(
|
|
|
|
|
+ ntimeroll = min(0xff, max(mgcfg->minimum_roll, ntimeroll));
|
|
|
|
|
+ pk_u8(my_buf, 0x31, ntimeroll); // ntime limit
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ pk_u8(my_buf, 0x31, 0); // ntime limit
|
|
|
|
|
+
|
|
|
pk_u32be(my_buf, 0, work->device_id);
|
|
pk_u32be(my_buf, 0, work->device_id);
|
|
|
memcpy(&my_buf[ 4], &work->data[0x48], 4); // nbits
|
|
memcpy(&my_buf[ 4], &work->data[0x48], 4); // nbits
|
|
|
memcpy(&my_buf[ 8], &work->data[0x44], 4); // ntime
|
|
memcpy(&my_buf[ 8], &work->data[0x44], 4); // ntime
|
|
@@ -263,9 +407,8 @@ bool minergate_queue_append(struct thr_info * const thr, struct work * const wor
|
|
|
const uint16_t zerobits = log2(floor(work->nonce_diff * 4294967296));
|
|
const uint16_t zerobits = log2(floor(work->nonce_diff * 4294967296));
|
|
|
work->nonce_diff = pow(2, zerobits) / 4294967296;
|
|
work->nonce_diff = pow(2, zerobits) / 4294967296;
|
|
|
pk_u8(my_buf, 0x30, zerobits);
|
|
pk_u8(my_buf, 0x30, zerobits);
|
|
|
-
|
|
|
|
|
- pk_u8(my_buf, 0x31, 0); // ntime limit
|
|
|
|
|
- pk_u8(my_buf, 0x32, 0); // ntime offset
|
|
|
|
|
|
|
+ // 0x31 is ntimeroll, which must be set before data ntime (in case it's changed)
|
|
|
|
|
+ pk_u8(my_buf, 0x32, 0); // pv6: ntime offset ; pv30: reserved
|
|
|
pk_u8(my_buf, 0x33, 0); // reserved
|
|
pk_u8(my_buf, 0x33, 0); // reserved
|
|
|
|
|
|
|
|
struct work *oldwork;
|
|
struct work *oldwork;
|
|
@@ -305,17 +448,40 @@ void minergate_queue_flush(struct thr_info * const thr)
|
|
|
timer_set_delay_from_now(&thr->tv_poll, 0);
|
|
timer_set_delay_from_now(&thr->tv_poll, 0);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static
|
|
|
|
|
+bool minergate_submit(struct thr_info * const thr, struct work * const work, const uint32_t nonce, const uint8_t ntime_offset, int64_t * const hashes)
|
|
|
|
|
+{
|
|
|
|
|
+ if (!nonce)
|
|
|
|
|
+ return false;
|
|
|
|
|
+
|
|
|
|
|
+ if (likely(work))
|
|
|
|
|
+ {
|
|
|
|
|
+ submit_noffset_nonce(thr, work, nonce, ntime_offset);
|
|
|
|
|
+
|
|
|
|
|
+ struct cgpu_info * const dev = thr->cgpu;
|
|
|
|
|
+ struct minergate_config * const mgcfg = dev->device_data;
|
|
|
|
|
+ if (mgcfg->desired_roll)
|
|
|
|
|
+ *hashes += 0x100000000 * work->nonce_diff;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ inc_hw_errors3(thr, NULL, &nonce, 1.);
|
|
|
|
|
+
|
|
|
|
|
+ return true;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static
|
|
static
|
|
|
void minergate_poll(struct thr_info * const thr)
|
|
void minergate_poll(struct thr_info * const thr)
|
|
|
{
|
|
{
|
|
|
struct cgpu_info * const dev = thr->cgpu;
|
|
struct cgpu_info * const dev = thr->cgpu;
|
|
|
|
|
+ struct minergate_config * const mgcfg = dev->device_data;
|
|
|
struct minergate_state * const state = thr->cgpu_data;
|
|
struct minergate_state * const state = thr->cgpu_data;
|
|
|
const int fd = dev->device_fd;
|
|
const int fd = dev->device_fd;
|
|
|
|
|
+ uint8_t buf[mgcfg->pkt_rsp_sz];
|
|
|
|
|
|
|
|
if (opt_dev_protocol || state->ready_to_queue)
|
|
if (opt_dev_protocol || state->ready_to_queue)
|
|
|
applog(LOG_DEBUG, "%s: Polling with %u new jobs", dev->dev_repr, state->ready_to_queue);
|
|
applog(LOG_DEBUG, "%s: Polling with %u new jobs", dev->dev_repr, state->ready_to_queue);
|
|
|
pk_u16le(state->req_buffer, 6, state->ready_to_queue);
|
|
pk_u16le(state->req_buffer, 6, state->ready_to_queue);
|
|
|
- if (MINERGATE_PKT_REQ_SZ != write(fd, state->req_buffer, MINERGATE_PKT_REQ_SZ))
|
|
|
|
|
|
|
+ if (mgcfg->pkt_req_sz != write(fd, state->req_buffer, mgcfg->pkt_req_sz))
|
|
|
return_via_applog(err, , LOG_ERR, "%s: write incomplete or failed", dev->dev_repr);
|
|
return_via_applog(err, , LOG_ERR, "%s: write incomplete or failed", dev->dev_repr);
|
|
|
|
|
|
|
|
uint8_t flags = state->req_buffer[3];
|
|
uint8_t flags = state->req_buffer[3];
|
|
@@ -323,11 +489,10 @@ void minergate_poll(struct thr_info * const thr)
|
|
|
state->ready_to_queue = 0;
|
|
state->ready_to_queue = 0;
|
|
|
thr->work_list = NULL;
|
|
thr->work_list = NULL;
|
|
|
|
|
|
|
|
- uint8_t buf[MINERGATE_PKT_RSP_SZ];
|
|
|
|
|
- if (minergate_read(fd, buf, MINERGATE_PKT_RSP_SZ) != MINERGATE_PKT_RSP_SZ)
|
|
|
|
|
|
|
+ if (minergate_read(fd, buf, mgcfg->pkt_rsp_sz) != mgcfg->pkt_rsp_sz)
|
|
|
return_via_applog(err, , LOG_ERR, "%s: %s failed", dev->dev_repr, "read");
|
|
return_via_applog(err, , LOG_ERR, "%s: %s failed", dev->dev_repr, "read");
|
|
|
|
|
|
|
|
- if (upk_u8(buf, 2) != MINERGATE_PROTOCOL_VER || upk_u16le(buf, 4) != MINERGATE_MAGIC)
|
|
|
|
|
|
|
+ if (upk_u8(buf, 2) != mgcfg->protover || upk_u16le(buf, 4) != MINERGATE_MAGIC)
|
|
|
return_via_applog(err, , LOG_ERR, "%s: Protocol mismatch", dev->dev_repr);
|
|
return_via_applog(err, , LOG_ERR, "%s: Protocol mismatch", dev->dev_repr);
|
|
|
|
|
|
|
|
uint8_t *jobrsp = &buf[MINERGATE_PKT_HEADER_SZ];
|
|
uint8_t *jobrsp = &buf[MINERGATE_PKT_HEADER_SZ];
|
|
@@ -336,40 +501,40 @@ void minergate_poll(struct thr_info * const thr)
|
|
|
if (rsp_count || opt_dev_protocol)
|
|
if (rsp_count || opt_dev_protocol)
|
|
|
applog(LOG_DEBUG, "%s: Received %u job completions", dev->dev_repr, rsp_count);
|
|
applog(LOG_DEBUG, "%s: Received %u job completions", dev->dev_repr, rsp_count);
|
|
|
uint32_t nonce;
|
|
uint32_t nonce;
|
|
|
|
|
+ uint8_t ntime_offset;
|
|
|
int64_t hashes = 0;
|
|
int64_t hashes = 0;
|
|
|
- for (unsigned i = 0; i < rsp_count; ++i, (jobrsp += MINERGATE_PKT_RSP_ITEM_SZ))
|
|
|
|
|
|
|
+ for (unsigned i = 0; i < rsp_count; ++i, (jobrsp += mgcfg->pkt_rsp_item_sz))
|
|
|
{
|
|
{
|
|
|
work_device_id_t jobid = upk_u32be(jobrsp, 0);
|
|
work_device_id_t jobid = upk_u32be(jobrsp, 0);
|
|
|
nonce = upk_u32le(jobrsp, 8);
|
|
nonce = upk_u32le(jobrsp, 8);
|
|
|
|
|
+ ntime_offset = upk_u8(jobrsp, (mgcfg->protover == MPV_SP10) ? 0x10 : 0xc);
|
|
|
|
|
+
|
|
|
HASH_FIND(hh, thr->work, &jobid, sizeof(jobid), work);
|
|
HASH_FIND(hh, thr->work, &jobid, sizeof(jobid), work);
|
|
|
- if (!work)
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ if (unlikely(!work))
|
|
|
applog(LOG_ERR, "%s: Unknown job %"PRIwdi, dev->dev_repr, jobid);
|
|
applog(LOG_ERR, "%s: Unknown job %"PRIwdi, dev->dev_repr, jobid);
|
|
|
- if (nonce)
|
|
|
|
|
|
|
+
|
|
|
|
|
+ if (minergate_submit(thr, work, nonce, ntime_offset, &hashes))
|
|
|
|
|
+ {
|
|
|
|
|
+ if (mgcfg->protover == MPV_SP10)
|
|
|
{
|
|
{
|
|
|
- inc_hw_errors3(thr, NULL, &nonce, 1.);
|
|
|
|
|
nonce = upk_u32le(jobrsp, 0xc);
|
|
nonce = upk_u32le(jobrsp, 0xc);
|
|
|
- if (nonce)
|
|
|
|
|
- inc_hw_errors3(thr, NULL, &nonce, 1.);
|
|
|
|
|
|
|
+ minergate_submit(thr, work, nonce, ntime_offset, &hashes);
|
|
|
}
|
|
}
|
|
|
- else
|
|
|
|
|
- inc_hw_errors_only(thr);
|
|
|
|
|
- continue;
|
|
|
|
|
}
|
|
}
|
|
|
- if (nonce)
|
|
|
|
|
|
|
+ else
|
|
|
|
|
+ if (unlikely(!work))
|
|
|
|
|
+ // Increment HW errors even if no nonce to submit
|
|
|
|
|
+ inc_hw_errors_only(thr);
|
|
|
|
|
+
|
|
|
|
|
+ const bool work_completed = (mgcfg->protover == MPV_SP10) ? (bool)work : (bool)jobrsp[0xe];
|
|
|
|
|
+ if (work_completed)
|
|
|
{
|
|
{
|
|
|
- submit_nonce(thr, work, nonce);
|
|
|
|
|
-
|
|
|
|
|
- nonce = upk_u32be(jobrsp, 0xc);
|
|
|
|
|
- if (nonce)
|
|
|
|
|
- submit_nonce(thr, work, nonce);
|
|
|
|
|
|
|
+ HASH_DEL(thr->work, work);
|
|
|
|
|
+ applog(LOG_DEBUG, "%s: %s job %"PRIwdi" completed", dev->dev_repr, work->tv_stamp.tv_sec ? "Flushed" : "Active", work->device_id);
|
|
|
|
|
+ if ((!mgcfg->desired_roll) && !work->tv_stamp.tv_sec)
|
|
|
|
|
+ hashes += 0x100000000 * work->nonce_diff;
|
|
|
|
|
+ free_work(work);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- HASH_DEL(thr->work, work);
|
|
|
|
|
- applog(LOG_DEBUG, "%s: %s job %"PRIwdi" completed", dev->dev_repr, work->tv_stamp.tv_sec ? "Flushed" : "Active", work->device_id);
|
|
|
|
|
- if (!work->tv_stamp.tv_sec)
|
|
|
|
|
- hashes += 100000000 * work->nonce_diff;
|
|
|
|
|
- free_work(work);
|
|
|
|
|
}
|
|
}
|
|
|
hashes_done2(thr, hashes, NULL);
|
|
hashes_done2(thr, hashes, NULL);
|
|
|
|
|
|
|
@@ -396,10 +561,14 @@ static
|
|
|
bool minergate_get_stats(struct cgpu_info * const dev)
|
|
bool minergate_get_stats(struct cgpu_info * const dev)
|
|
|
{
|
|
{
|
|
|
static const int skip_stats = 1;
|
|
static const int skip_stats = 1;
|
|
|
|
|
+ struct minergate_config * const mgcfg = dev->device_data;
|
|
|
struct thr_info * const thr = dev->thr[0];
|
|
struct thr_info * const thr = dev->thr[0];
|
|
|
struct minergate_state * const state = thr->cgpu_data;
|
|
struct minergate_state * const state = thr->cgpu_data;
|
|
|
|
|
|
|
|
- FILE *F = fopen(minergate_stats_file, "r");
|
|
|
|
|
|
|
+ if (!(mgcfg->stats_file && mgcfg->stats_file[0]))
|
|
|
|
|
+ return true;
|
|
|
|
|
+
|
|
|
|
|
+ FILE *F = fopen(mgcfg->stats_file, "r");
|
|
|
char buf[0x100];
|
|
char buf[0x100];
|
|
|
if (F)
|
|
if (F)
|
|
|
{
|
|
{
|