|
@@ -20,6 +20,7 @@
|
|
|
|
|
|
|
|
#define GRIDSEED_DEFAULT_FREQUENCY 600
|
|
#define GRIDSEED_DEFAULT_FREQUENCY 600
|
|
|
#define GRIDSEED_MAX_QUEUED 10
|
|
#define GRIDSEED_MAX_QUEUED 10
|
|
|
|
|
+#define GRIDSEED_HASH_SPEED 0.0851128926 // in ms
|
|
|
|
|
|
|
|
BFG_REGISTER_DRIVER(gridseed_drv)
|
|
BFG_REGISTER_DRIVER(gridseed_drv)
|
|
|
|
|
|
|
@@ -38,7 +39,6 @@ struct cgpu_info *gridseed_alloc_device(const char *path, struct device_drv *dri
|
|
|
device->device_path = strdup(path);
|
|
device->device_path = strdup(path);
|
|
|
device->device_fd = -1;
|
|
device->device_fd = -1;
|
|
|
device->threads = 1;
|
|
device->threads = 1;
|
|
|
- device->procs = GC3355_ORB_DEFAULT_CHIPS;
|
|
|
|
|
device->device_data = info;
|
|
device->device_data = info;
|
|
|
|
|
|
|
|
return device;
|
|
return device;
|
|
@@ -140,22 +140,6 @@ bool gridseed_thread_prepare(struct thr_info *thr)
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static
|
|
|
|
|
-bool gridseed_set_queue_full(const struct cgpu_info * const device, int needwork);
|
|
|
|
|
-
|
|
|
|
|
-static
|
|
|
|
|
-bool gridseed_thread_init(struct thr_info *master_thr)
|
|
|
|
|
-{
|
|
|
|
|
- struct cgpu_info * const device = master_thr->cgpu;
|
|
|
|
|
- gridseed_set_queue_full(device, 0);
|
|
|
|
|
- timer_set_now(&master_thr->tv_poll);
|
|
|
|
|
-
|
|
|
|
|
- // kick off queue minerloop
|
|
|
|
|
- gridseed_set_queue_full(device, device->procs * 2);
|
|
|
|
|
-
|
|
|
|
|
- return true;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
static
|
|
static
|
|
|
void gridseed_thread_shutdown(struct thr_info *thr)
|
|
void gridseed_thread_shutdown(struct thr_info *thr)
|
|
|
{
|
|
{
|
|
@@ -165,45 +149,25 @@ void gridseed_thread_shutdown(struct thr_info *thr)
|
|
|
free(thr->cgpu_data);
|
|
free(thr->cgpu_data);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static
|
|
|
|
|
-void gridseed_reinit_device(struct cgpu_info * const proc)
|
|
|
|
|
-{
|
|
|
|
|
- timer_set_now(&proc->thr[0]->tv_poll);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
/*
|
|
/*
|
|
|
- * queued mining loop
|
|
|
|
|
|
|
+ * scanhash mining loop
|
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
|
|
+// send work to the device
|
|
|
static
|
|
static
|
|
|
-bool gridseed_set_queue_full(const struct cgpu_info * const device, int needwork)
|
|
|
|
|
|
|
+bool gridseed_prepare_work(struct thr_info __maybe_unused *thr, struct work *work)
|
|
|
{
|
|
{
|
|
|
- struct gc3355_orb_info * const info = device->device_data;
|
|
|
|
|
- struct thr_info * const master_thr = device->thr[0];
|
|
|
|
|
-
|
|
|
|
|
- if (needwork != -1)
|
|
|
|
|
- info->needwork = needwork;
|
|
|
|
|
-
|
|
|
|
|
- const bool full = (device->device_fd == -1 || !info->needwork);
|
|
|
|
|
-
|
|
|
|
|
- if (full == master_thr->queue_full)
|
|
|
|
|
- return full;
|
|
|
|
|
-
|
|
|
|
|
- for (const struct cgpu_info *proc = device; proc; proc = proc->next_proc)
|
|
|
|
|
- {
|
|
|
|
|
- struct thr_info * const thr = proc->thr[0];
|
|
|
|
|
- thr->queue_full = full;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return full;
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ struct cgpu_info *device = thr->cgpu;
|
|
|
|
|
+ struct gc3355_orb_info *info = device->device_data;
|
|
|
|
|
|
|
|
-static
|
|
|
|
|
-bool gridseed_send_work(const struct cgpu_info * const device, struct work *work)
|
|
|
|
|
-{
|
|
|
|
|
int work_size = opt_scrypt ? 156 : 52;
|
|
int work_size = opt_scrypt ? 156 : 52;
|
|
|
unsigned char cmd[work_size];
|
|
unsigned char cmd[work_size];
|
|
|
|
|
|
|
|
|
|
+ cgtime(&info->scanhash_time);
|
|
|
|
|
+
|
|
|
|
|
+ //from GC3355 docs if we are using FIFO
|
|
|
|
|
+ work->id = 12345678;
|
|
|
|
|
+
|
|
|
if (opt_scrypt)
|
|
if (opt_scrypt)
|
|
|
{
|
|
{
|
|
|
gc3355_scrypt_reset(device->device_fd);
|
|
gc3355_scrypt_reset(device->device_fd);
|
|
@@ -218,149 +182,42 @@ bool gridseed_send_work(const struct cgpu_info * const device, struct work *work
|
|
|
applog(LOG_ERR, "%s: Failed to send work", device->dev_repr);
|
|
applog(LOG_ERR, "%s: Failed to send work", device->dev_repr);
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- return true;
|
|
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
-static
|
|
|
|
|
-void gridseed_prune_queue(const struct cgpu_info * const device, struct work *work)
|
|
|
|
|
-{
|
|
|
|
|
- struct thr_info * const master_thr = device->thr[0];
|
|
|
|
|
-
|
|
|
|
|
- // prune queue
|
|
|
|
|
- int prunequeue = HASH_COUNT(master_thr->work_list) - GRIDSEED_MAX_QUEUED;
|
|
|
|
|
- if (prunequeue > 0)
|
|
|
|
|
- {
|
|
|
|
|
- struct work *tmp;
|
|
|
|
|
- applog(LOG_DEBUG, "%s: Pruning %d old work item%s",
|
|
|
|
|
- device->dev_repr, prunequeue, prunequeue == 1 ? "" : "s");
|
|
|
|
|
- HASH_ITER(hh, master_thr->work_list, work, tmp)
|
|
|
|
|
- {
|
|
|
|
|
- HASH_DEL(master_thr->work_list, work);
|
|
|
|
|
- free_work(work);
|
|
|
|
|
- if (--prunequeue < 1)
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// send work to the device & queue work
|
|
|
|
|
-static
|
|
|
|
|
-bool gridseed_queue_append(struct thr_info * const thr, struct work *work)
|
|
|
|
|
-{
|
|
|
|
|
- const struct cgpu_info * const device = thr->cgpu->device;
|
|
|
|
|
- struct gc3355_orb_info * const info = device->device_data;
|
|
|
|
|
- struct thr_info * const master_thr = device->thr[0];
|
|
|
|
|
-
|
|
|
|
|
- // if queue is full (-1 is a check flag) do not append new work
|
|
|
|
|
- if (gridseed_set_queue_full(device, -1))
|
|
|
|
|
- return false;
|
|
|
|
|
-
|
|
|
|
|
- // send work
|
|
|
|
|
- if (!gridseed_send_work(device, work))
|
|
|
|
|
- return false;
|
|
|
|
|
-
|
|
|
|
|
- // store work in queue
|
|
|
|
|
- HASH_ADD(hh, master_thr->work_list, id, sizeof(work->id), work);
|
|
|
|
|
-
|
|
|
|
|
- // prune queue
|
|
|
|
|
- gridseed_prune_queue(device, work);
|
|
|
|
|
-
|
|
|
|
|
- // sets info->needwork equal to 2nd arg and updates "full" flags
|
|
|
|
|
- gridseed_set_queue_full(device, info->needwork - 1);
|
|
|
|
|
-
|
|
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static
|
|
static
|
|
|
-void gridseed_queue_flush(struct thr_info * const thr)
|
|
|
|
|
|
|
+void gridseed_submit_nonce(struct thr_info * const thr, const unsigned char buf[GC3355_READ_SIZE], struct work * const work)
|
|
|
{
|
|
{
|
|
|
- const struct cgpu_info *device = thr->cgpu;
|
|
|
|
|
- if (device != device->device)
|
|
|
|
|
- return;
|
|
|
|
|
-
|
|
|
|
|
- gridseed_set_queue_full(device, device->procs);
|
|
|
|
|
|
|
+ uint32_t nonce = *(uint32_t *)(buf + 4);
|
|
|
|
|
+ nonce = le32toh(nonce);
|
|
|
|
|
+ submit_nonce(thr, work, nonce);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static
|
|
static
|
|
|
-const struct cgpu_info *gridseed_proc_by_id(const struct cgpu_info * const dev, int procid)
|
|
|
|
|
|
|
+int64_t gridseed_estimate_hashes(struct thr_info *thr)
|
|
|
{
|
|
{
|
|
|
- const struct cgpu_info *proc = dev;
|
|
|
|
|
- for (int i = 0; i < procid; ++i)
|
|
|
|
|
- {
|
|
|
|
|
- proc = proc->next_proc;
|
|
|
|
|
- if (unlikely(!proc))
|
|
|
|
|
- return NULL;
|
|
|
|
|
- }
|
|
|
|
|
- return proc;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-static
|
|
|
|
|
-void gridseed_submit_nonce(struct thr_info * const master_thr, const unsigned char buf[GC3355_READ_SIZE])
|
|
|
|
|
-{
|
|
|
|
|
- struct work *work;
|
|
|
|
|
- uint32_t nonce;
|
|
|
|
|
- int workid;
|
|
|
|
|
- struct cgpu_info * const device = master_thr->cgpu;
|
|
|
|
|
- struct gc3355_orb_info * const info = device->device_data;
|
|
|
|
|
-
|
|
|
|
|
- // extract workid from buffer
|
|
|
|
|
- memcpy(&workid, buf + 8, 4);
|
|
|
|
|
- // extract nonce from buffer
|
|
|
|
|
- memcpy(&nonce, buf + 4, 4);
|
|
|
|
|
- // extract chip # from nonce
|
|
|
|
|
- const int chip = nonce / ((uint32_t)0xffffffff / GC3355_ORB_DEFAULT_CHIPS);
|
|
|
|
|
- // find processor by device & chip
|
|
|
|
|
- const struct cgpu_info *proc = gridseed_proc_by_id(device, chip);
|
|
|
|
|
- // default process to device
|
|
|
|
|
- if (unlikely(!proc))
|
|
|
|
|
- proc = device;
|
|
|
|
|
- // the thread specific to the ASIC chip:
|
|
|
|
|
- struct thr_info * thr = proc->thr[0];
|
|
|
|
|
-
|
|
|
|
|
- nonce = htole32(nonce);
|
|
|
|
|
-
|
|
|
|
|
- // find the queued work for this nonce, by workid
|
|
|
|
|
- HASH_FIND(hh, master_thr->work_list, &workid, sizeof(workid), work);
|
|
|
|
|
- if (work)
|
|
|
|
|
- {
|
|
|
|
|
- submit_nonce(thr, work, nonce);
|
|
|
|
|
-
|
|
|
|
|
- HASH_DEL(master_thr->work_list, work);
|
|
|
|
|
-
|
|
|
|
|
- gridseed_set_queue_full(device, info->needwork + 2);
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ struct cgpu_info *device = thr->cgpu;
|
|
|
|
|
+ struct gc3355_orb_info *info = device->device_data;
|
|
|
|
|
+ struct timeval old_scanhash_time = info->scanhash_time;
|
|
|
|
|
+ cgtime(&info->scanhash_time);
|
|
|
|
|
+ int elapsed_ms = ms_tdiff(&info->scanhash_time, &old_scanhash_time);
|
|
|
|
|
|
|
|
-static
|
|
|
|
|
-void gridseed_estimate_hashes(const struct cgpu_info * const device)
|
|
|
|
|
-{
|
|
|
|
|
- const struct cgpu_info *proc = device;
|
|
|
|
|
- const struct gc3355_orb_info *info = device->device_data;
|
|
|
|
|
-
|
|
|
|
|
- while (true)
|
|
|
|
|
- {
|
|
|
|
|
- hashes_done2(proc->thr[0], info->freq * 0xA4, NULL);
|
|
|
|
|
- proc = proc->next_proc;
|
|
|
|
|
- if (unlikely(!proc))
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ return GRIDSEED_HASH_SPEED * (double)elapsed_ms * (double)(info->freq * GC3355_ORB_DEFAULT_CHIPS);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-#define GRIDSEED_SHORT_WORK_DELAY_MS 20
|
|
|
|
|
-#define GRIDSEED_LONG_WORK_DELAY_MS 30
|
|
|
|
|
-
|
|
|
|
|
// read from device for nonce or command
|
|
// read from device for nonce or command
|
|
|
static
|
|
static
|
|
|
-void gridseed_poll(struct thr_info * const master_thr)
|
|
|
|
|
|
|
+int64_t gridseed_scanhash(struct thr_info *thr, struct work *work, int64_t __maybe_unused max_nonce)
|
|
|
{
|
|
{
|
|
|
- struct cgpu_info * const device = master_thr->cgpu;
|
|
|
|
|
|
|
+ struct cgpu_info *device = thr->cgpu;
|
|
|
|
|
+ struct gc3355_info *info = device->device_data;
|
|
|
|
|
+
|
|
|
unsigned char buf[GC3355_READ_SIZE];
|
|
unsigned char buf[GC3355_READ_SIZE];
|
|
|
int read = 0;
|
|
int read = 0;
|
|
|
- struct timeval tv_timeout;
|
|
|
|
|
- timer_set_delay_from_now(&tv_timeout, GRIDSEED_LONG_WORK_DELAY_MS * 1000); // X MS
|
|
|
|
|
-
|
|
|
|
|
- while (!master_thr->work_restart && (read = gc3355_read(device->device_fd, (char *)buf, GC3355_READ_SIZE)) > 0)
|
|
|
|
|
|
|
+ int fd = device->device_fd;
|
|
|
|
|
+
|
|
|
|
|
+ while (!thr->work_restart && (read = gc3355_read(fd, (char *)buf, GC3355_READ_SIZE)) > 0)
|
|
|
{
|
|
{
|
|
|
if (buf[0] == 0x55)
|
|
if (buf[0] == 0x55)
|
|
|
{
|
|
{
|
|
@@ -372,28 +229,19 @@ void gridseed_poll(struct thr_info * const master_thr)
|
|
|
case 0x10: // BTC result
|
|
case 0x10: // BTC result
|
|
|
case 0x20: // LTC result
|
|
case 0x20: // LTC result
|
|
|
{
|
|
{
|
|
|
- gridseed_submit_nonce(master_thr, buf);
|
|
|
|
|
|
|
+ gridseed_submit_nonce(thr, buf, work);
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- } else
|
|
|
|
|
- {
|
|
|
|
|
- applog(LOG_ERR, "%"PRIpreprv": Unrecognized response", device->proc_repr);
|
|
|
|
|
- break;
|
|
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- if (timer_passed(&tv_timeout, NULL))
|
|
|
|
|
|
|
+ else
|
|
|
{
|
|
{
|
|
|
- // allow work to be sent to the device
|
|
|
|
|
- applog(LOG_DEBUG, "%s poll: timeout met", device->dev_repr);
|
|
|
|
|
|
|
+ applog(LOG_ERR, "%"PRIpreprv": Unrecognized response", device->proc_repr);
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- gridseed_estimate_hashes(device);
|
|
|
|
|
-
|
|
|
|
|
- // allow work to be sent to the device
|
|
|
|
|
- timer_set_delay_from_now(&master_thr->tv_poll, GRIDSEED_SHORT_WORK_DELAY_MS * 1000); // X MS
|
|
|
|
|
|
|
+
|
|
|
|
|
+ return gridseed_estimate_hashes(thr);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -433,16 +281,13 @@ struct device_drv gridseed_drv =
|
|
|
|
|
|
|
|
// initialize device
|
|
// initialize device
|
|
|
.thread_prepare = gridseed_thread_prepare,
|
|
.thread_prepare = gridseed_thread_prepare,
|
|
|
- .thread_init = gridseed_thread_init,
|
|
|
|
|
- .reinit_device = gridseed_reinit_device,
|
|
|
|
|
|
|
|
|
|
// specify mining type - scanhash
|
|
// specify mining type - scanhash
|
|
|
- .minerloop = minerloop_queue,
|
|
|
|
|
|
|
+ .minerloop = minerloop_scanhash,
|
|
|
|
|
|
|
|
- // queued mining hooks
|
|
|
|
|
- .queue_append = gridseed_queue_append,
|
|
|
|
|
- .queue_flush = gridseed_queue_flush,
|
|
|
|
|
- .poll = gridseed_poll,
|
|
|
|
|
|
|
+ // scanhash mining hooks
|
|
|
|
|
+ .prepare_work = gridseed_prepare_work,
|
|
|
|
|
+ .scanhash = gridseed_scanhash,
|
|
|
|
|
|
|
|
// teardown device
|
|
// teardown device
|
|
|
.thread_shutdown = gridseed_thread_shutdown,
|
|
.thread_shutdown = gridseed_thread_shutdown,
|