|
@@ -413,27 +413,7 @@ const char *icarus_set_timing(struct cgpu_info * const proc, const char * const
|
|
|
|
|
|
|
|
static uint32_t mask(int work_division)
|
|
static uint32_t mask(int work_division)
|
|
|
{
|
|
{
|
|
|
- uint32_t nonce_mask = 0x7fffffff;
|
|
|
|
|
-
|
|
|
|
|
- // yes we can calculate these, but this way it's easy to see what they are
|
|
|
|
|
- switch (work_division) {
|
|
|
|
|
- case 1:
|
|
|
|
|
- nonce_mask = 0xffffffff;
|
|
|
|
|
- break;
|
|
|
|
|
- case 2:
|
|
|
|
|
- nonce_mask = 0x7fffffff;
|
|
|
|
|
- break;
|
|
|
|
|
- case 4:
|
|
|
|
|
- nonce_mask = 0x3fffffff;
|
|
|
|
|
- break;
|
|
|
|
|
- case 8:
|
|
|
|
|
- nonce_mask = 0x1fffffff;
|
|
|
|
|
- break;
|
|
|
|
|
- default:
|
|
|
|
|
- quit(1, "Invalid2 work_division (%d) must be 1, 2, 4 or 8", work_division);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return nonce_mask;
|
|
|
|
|
|
|
+ return 0xffffffff / work_division;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Number of bytes remaining after reading a nonce from Icarus
|
|
// Number of bytes remaining after reading a nonce from Icarus
|
|
@@ -512,42 +492,47 @@ bool icarus_detect_custom(const char *devpath, struct device_drv *api, struct IC
|
|
|
int ob_size = strlen(info->golden_ob) / 2;
|
|
int ob_size = strlen(info->golden_ob) / 2;
|
|
|
unsigned char ob_bin[ob_size];
|
|
unsigned char ob_bin[ob_size];
|
|
|
BFGINIT(info->ob_size, ob_size);
|
|
BFGINIT(info->ob_size, ob_size);
|
|
|
-
|
|
|
|
|
- hex2bin(ob_bin, info->golden_ob, sizeof(ob_bin));
|
|
|
|
|
- icarus_write(fd, ob_bin, sizeof(ob_bin));
|
|
|
|
|
- cgtime(&tv_start);
|
|
|
|
|
-
|
|
|
|
|
- memset(nonce_bin, 0, sizeof(nonce_bin));
|
|
|
|
|
- // Do not use info->read_size here, instead read exactly ICARUS_NONCE_SIZE
|
|
|
|
|
- // We will then compare the bytes left in fd with info->read_size to determine
|
|
|
|
|
- // if this is a valid device
|
|
|
|
|
- icarus_gets(nonce_bin, fd, &tv_finish, NULL, info->probe_read_count, ICARUS_NONCE_SIZE);
|
|
|
|
|
-
|
|
|
|
|
- // How many bytes were left after reading the above nonce
|
|
|
|
|
- int bytes_left = icarus_excess_nonce_size(fd, info);
|
|
|
|
|
-
|
|
|
|
|
- icarus_close(fd);
|
|
|
|
|
|
|
|
|
|
- bin2hex(nonce_hex, nonce_bin, sizeof(nonce_bin));
|
|
|
|
|
- if (strncmp(nonce_hex, info->golden_nonce, 8))
|
|
|
|
|
|
|
+ if (!info->ignore_golden_nonce)
|
|
|
{
|
|
{
|
|
|
- applog(LOG_DEBUG,
|
|
|
|
|
- "%s: "
|
|
|
|
|
- "Test failed at %s: get %s, should: %s",
|
|
|
|
|
- api->dname,
|
|
|
|
|
- devpath, nonce_hex, info->golden_nonce);
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ hex2bin(ob_bin, info->golden_ob, sizeof(ob_bin));
|
|
|
|
|
+ icarus_write(fd, ob_bin, sizeof(ob_bin));
|
|
|
|
|
+ cgtime(&tv_start);
|
|
|
|
|
|
|
|
- if (info->read_size - ICARUS_NONCE_SIZE != bytes_left)
|
|
|
|
|
- {
|
|
|
|
|
- applog(LOG_DEBUG,
|
|
|
|
|
- "%s: "
|
|
|
|
|
- "Test failed at %s: expected %d bytes, got %d",
|
|
|
|
|
- api->dname,
|
|
|
|
|
- devpath, info->read_size, ICARUS_NONCE_SIZE + bytes_left);
|
|
|
|
|
- return false;
|
|
|
|
|
|
|
+ memset(nonce_bin, 0, sizeof(nonce_bin));
|
|
|
|
|
+ // Do not use info->read_size here, instead read exactly ICARUS_NONCE_SIZE
|
|
|
|
|
+ // We will then compare the bytes left in fd with info->read_size to determine
|
|
|
|
|
+ // if this is a valid device
|
|
|
|
|
+ icarus_gets(nonce_bin, fd, &tv_finish, NULL, info->probe_read_count, ICARUS_NONCE_SIZE);
|
|
|
|
|
+
|
|
|
|
|
+ // How many bytes were left after reading the above nonce
|
|
|
|
|
+ int bytes_left = icarus_excess_nonce_size(fd, info);
|
|
|
|
|
+
|
|
|
|
|
+ icarus_close(fd);
|
|
|
|
|
+
|
|
|
|
|
+ bin2hex(nonce_hex, nonce_bin, sizeof(nonce_bin));
|
|
|
|
|
+ if (strncmp(nonce_hex, info->golden_nonce, 8))
|
|
|
|
|
+ {
|
|
|
|
|
+ applog(LOG_DEBUG,
|
|
|
|
|
+ "%s: "
|
|
|
|
|
+ "Test failed at %s: get %s, should: %s",
|
|
|
|
|
+ api->dname,
|
|
|
|
|
+ devpath, nonce_hex, info->golden_nonce);
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (info->read_size - ICARUS_NONCE_SIZE != bytes_left)
|
|
|
|
|
+ {
|
|
|
|
|
+ applog(LOG_DEBUG,
|
|
|
|
|
+ "%s: "
|
|
|
|
|
+ "Test failed at %s: expected %d bytes, got %d",
|
|
|
|
|
+ api->dname,
|
|
|
|
|
+ devpath, info->read_size, ICARUS_NONCE_SIZE + bytes_left);
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
+ else
|
|
|
|
|
+ icarus_close(fd);
|
|
|
|
|
|
|
|
applog(LOG_DEBUG,
|
|
applog(LOG_DEBUG,
|
|
|
"%s: "
|
|
"%s: "
|
|
@@ -704,6 +689,8 @@ bool icarus_init(struct thr_info *thr)
|
|
|
if (!info->fpga_count)
|
|
if (!info->fpga_count)
|
|
|
info->fpga_count = info->work_division;
|
|
info->fpga_count = info->work_division;
|
|
|
|
|
|
|
|
|
|
+ if (!is_power_of_two(info->work_division))
|
|
|
|
|
+ info->work_division = upper_power_of_two_u32(info->work_division);
|
|
|
info->nonce_mask = mask(info->work_division);
|
|
info->nonce_mask = mask(info->work_division);
|
|
|
|
|
|
|
|
return true;
|
|
return true;
|
|
@@ -894,7 +881,6 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work,
|
|
|
double Hs, W, fullnonce;
|
|
double Hs, W, fullnonce;
|
|
|
int read_count;
|
|
int read_count;
|
|
|
bool limited;
|
|
bool limited;
|
|
|
- int64_t estimate_hashes;
|
|
|
|
|
uint32_t values;
|
|
uint32_t values;
|
|
|
int64_t hash_count_range;
|
|
int64_t hash_count_range;
|
|
|
|
|
|
|
@@ -1038,46 +1024,56 @@ keepwaiting:
|
|
|
|
|
|
|
|
// OK, done starting Icarus's next job... now process the last run's result!
|
|
// OK, done starting Icarus's next job... now process the last run's result!
|
|
|
|
|
|
|
|
- // aborted before becoming idle, get new work
|
|
|
|
|
- if (ret == ICA_GETS_TIMEOUT || ret == ICA_GETS_RESTART) {
|
|
|
|
|
|
|
+ if (ret == ICA_GETS_OK && !was_hw_error)
|
|
|
|
|
+ {
|
|
|
|
|
+ submit_nonce(thr, nonce_work, nonce);
|
|
|
|
|
+
|
|
|
icarus_transition_work(state, work);
|
|
icarus_transition_work(state, work);
|
|
|
- // ONLY up to just when it aborted
|
|
|
|
|
- // We didn't read a reply so we don't subtract ICARUS_READ_TIME
|
|
|
|
|
- estimate_hashes = ((double)(elapsed.tv_sec)
|
|
|
|
|
- + ((double)(elapsed.tv_usec))/((double)1000000)) / info->Hs;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ hash_count = (nonce & info->nonce_mask);
|
|
|
|
|
+ hash_count++;
|
|
|
|
|
+ hash_count *= info->fpga_count;
|
|
|
|
|
+
|
|
|
|
|
+ applog(LOG_DEBUG, "%"PRIpreprv" nonce = 0x%08x = 0x%08" PRIx64 " hashes (%"PRId64".%06lus)",
|
|
|
|
|
+ icarus->proc_repr,
|
|
|
|
|
+ nonce,
|
|
|
|
|
+ (uint64_t)hash_count,
|
|
|
|
|
+ (int64_t)elapsed.tv_sec, (unsigned long)elapsed.tv_usec);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ double estimate_hashes = elapsed.tv_sec;
|
|
|
|
|
+ estimate_hashes += ((double)elapsed.tv_usec) / 1000000.;
|
|
|
|
|
+
|
|
|
|
|
+ if (ret == ICA_GETS_OK)
|
|
|
|
|
+ {
|
|
|
|
|
+ inc_hw_errors(thr, state->last_work, nonce);
|
|
|
|
|
+ estimate_hashes -= ICARUS_READ_TIME(info->baud, info->read_size);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ icarus_transition_work(state, work);
|
|
|
|
|
+
|
|
|
|
|
+ estimate_hashes /= info->Hs;
|
|
|
|
|
|
|
|
// If some Serial-USB delay allowed the full nonce range to
|
|
// If some Serial-USB delay allowed the full nonce range to
|
|
|
// complete it can't have done more than a full nonce
|
|
// complete it can't have done more than a full nonce
|
|
|
if (unlikely(estimate_hashes > 0xffffffff))
|
|
if (unlikely(estimate_hashes > 0xffffffff))
|
|
|
estimate_hashes = 0xffffffff;
|
|
estimate_hashes = 0xffffffff;
|
|
|
|
|
|
|
|
- applog(LOG_DEBUG, "%"PRIpreprv" no nonce = 0x%08"PRIx64" hashes (%"PRId64".%06lus)",
|
|
|
|
|
|
|
+ applog(LOG_DEBUG, "%"PRIpreprv" %s nonce = 0x%08"PRIx64" hashes (%"PRId64".%06lus)",
|
|
|
icarus->proc_repr,
|
|
icarus->proc_repr,
|
|
|
|
|
+ (ret == ICA_GETS_OK) ? "bad" : "no",
|
|
|
(uint64_t)estimate_hashes,
|
|
(uint64_t)estimate_hashes,
|
|
|
(int64_t)elapsed.tv_sec, (unsigned long)elapsed.tv_usec);
|
|
(int64_t)elapsed.tv_sec, (unsigned long)elapsed.tv_usec);
|
|
|
|
|
|
|
|
hash_count = estimate_hashes;
|
|
hash_count = estimate_hashes;
|
|
|
- goto out;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ if (ret != ICA_GETS_OK)
|
|
|
|
|
+ goto out;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Only ICA_GETS_OK gets here
|
|
// Only ICA_GETS_OK gets here
|
|
|
|
|
|
|
|
- if (likely(!was_hw_error))
|
|
|
|
|
- submit_nonce(thr, nonce_work, nonce);
|
|
|
|
|
- else
|
|
|
|
|
- inc_hw_errors(thr, state->last_work, nonce);
|
|
|
|
|
- icarus_transition_work(state, work);
|
|
|
|
|
-
|
|
|
|
|
- hash_count = (nonce & info->nonce_mask);
|
|
|
|
|
- hash_count++;
|
|
|
|
|
- hash_count *= info->fpga_count;
|
|
|
|
|
-
|
|
|
|
|
- applog(LOG_DEBUG, "%"PRIpreprv" nonce = 0x%08x = 0x%08" PRIx64 " hashes (%"PRId64".%06lus)",
|
|
|
|
|
- icarus->proc_repr,
|
|
|
|
|
- nonce,
|
|
|
|
|
- (uint64_t)hash_count,
|
|
|
|
|
- (int64_t)elapsed.tv_sec, (unsigned long)elapsed.tv_usec);
|
|
|
|
|
-
|
|
|
|
|
if (info->do_default_detection && elapsed.tv_sec >= DEFAULT_DETECT_THRESHOLD) {
|
|
if (info->do_default_detection && elapsed.tv_sec >= DEFAULT_DETECT_THRESHOLD) {
|
|
|
int MHs = (double)hash_count / ((double)elapsed.tv_sec * 1e6 + (double)elapsed.tv_usec);
|
|
int MHs = (double)hash_count / ((double)elapsed.tv_sec * 1e6 + (double)elapsed.tv_usec);
|
|
|
--info->do_default_detection;
|
|
--info->do_default_detection;
|
|
@@ -1282,8 +1278,8 @@ const char *icarus_set_work_division(struct cgpu_info * const proc, const char *
|
|
|
{
|
|
{
|
|
|
struct ICARUS_INFO * const info = proc->device_data;
|
|
struct ICARUS_INFO * const info = proc->device_data;
|
|
|
const int work_division = atoi(newvalue);
|
|
const int work_division = atoi(newvalue);
|
|
|
- if (!(work_division == 1 || work_division == 2 || work_division == 4 || work_division == 8))
|
|
|
|
|
- return "Invalid work_division: must be 1, 2, 4 or 8";
|
|
|
|
|
|
|
+ if (!is_power_of_two(work_division))
|
|
|
|
|
+ return "Invalid work_division: must be a power of two";
|
|
|
if (info->user_set & IUS_FPGA_COUNT)
|
|
if (info->user_set & IUS_FPGA_COUNT)
|
|
|
{
|
|
{
|
|
|
if (info->fpga_count > work_division)
|
|
if (info->fpga_count > work_division)
|