static void bitforce_flash_led(struct cgpu_info *bitforce) { int err, amount; /* Do not try to flash the led if we're polling for a result to * minimise the chance of interleaved results */ if (bitforce->polling) return; /* It is not critical flashing the led so don't get stuck if we * can't grab the mutex now */ if (mutex_trylock(&bitforce->device_mutex)) return; if ((err = usb_write(bitforce, BITFORCE_FLASH, BITFORCE_FLASH_LEN, &amount, C_REQUESTFLASH)) < 0 || amount != BITFORCE_FLASH_LEN) { applog(LOG_ERR, "%s%i: flash request failed (%d:%d)", bitforce->drv->name, bitforce->device_id, amount, err); } else { /* However, this stops anything else getting a reply * So best to delay any other access to the BFL */ nmsleep(4000); } /* Once we've tried - don't do it until told to again */ bitforce->flash_led = false; mutex_unlock(&bitforce->device_mutex); return; // nothing is returned by the BFL }
void bitforce_init(struct cgpu_info *bitforce) { char *devpath = bitforce->device_path; int fdDev = bitforce->device_fd, retries = 0; char pdevbuf[0x100]; char *s; applog(LOG_WARNING, "BFL%i: Re-initialising", bitforce->device_id); bitforce_clear_buffer(bitforce); mutex_lock(&bitforce->device_mutex); if (fdDev) { BFclose(fdDev); sleep(5); } bitforce->device_fd = 0; fdDev = BFopen(devpath); if (unlikely(fdDev == -1)) { mutex_unlock(&bitforce->device_mutex); applog(LOG_ERR, "BFL%i: Failed to open %s", bitforce->device_id, devpath); return; } do { BFwrite(fdDev, "ZGX", 3); pdevbuf[0] = '\0'; BFgets(pdevbuf, sizeof(pdevbuf), fdDev); if (unlikely(!pdevbuf[0])) { mutex_unlock(&bitforce->device_mutex); applog(LOG_ERR, "BFL%i: Error reading/timeout (ZGX)", bitforce->device_id); return; } if (retries++) nmsleep(10); } while (!strstr(pdevbuf, "BUSY") && (retries * 10 < BITFORCE_TIMEOUT_MS)); if (unlikely(!strstr(pdevbuf, "SHA256"))) { mutex_unlock(&bitforce->device_mutex); applog(LOG_ERR, "BFL%i: Didn't recognise BitForce on %s returned: %s", bitforce->device_id, devpath, pdevbuf); return; } if (likely((!memcmp(pdevbuf, ">>>ID: ", 7)) && (s = strstr(pdevbuf + 3, ">>>")))) { s[0] = '\0'; bitforce->name = strdup(pdevbuf + 7); } bitforce->device_fd = fdDev; bitforce->sleep_ms = BITFORCE_SLEEP_MS; mutex_unlock(&bitforce->device_mutex); }
static bool bitforce_thread_init(struct thr_info *thr) { struct cgpu_info *bitforce = thr->cgpu; unsigned int wait; /* Pause each new thread at least 100ms between initialising * so the devices aren't making calls all at the same time. */ wait = thr->id * MAX_START_DELAY_MS; applog(LOG_DEBUG, "BFL%i: Delaying start by %dms", bitforce->device_id, wait / 1000); nmsleep(wait); return true; }
static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) { struct cgpu_info *bitforce = thr->cgpu; int fdDev = bitforce->device_fd; unsigned int delay_time_ms; struct timeval elapsed; struct timeval now; char pdevbuf[0x100]; char *pnoncebuf; uint32_t nonce; if (!fdDev) return -1; while (1) { if (unlikely(thr->work_restart)) return 0; mutex_lock(&bitforce->device_mutex); BFwrite(fdDev, "ZFX", 3); BFgets(pdevbuf, sizeof(pdevbuf), fdDev); mutex_unlock(&bitforce->device_mutex); gettimeofday(&now, NULL); timersub(&now, &bitforce->work_start_tv, &elapsed); if (elapsed.tv_sec >= BITFORCE_LONG_TIMEOUT_S) { applog(LOG_ERR, "BFL%i: took %dms - longer than %dms", bitforce->device_id, tv_to_ms(elapsed), BITFORCE_LONG_TIMEOUT_MS); return 0; } if (pdevbuf[0] && strncasecmp(pdevbuf, "B", 1)) /* BFL does not respond during throttling */ break; /* if BFL is throttling, no point checking so quickly */ delay_time_ms = (pdevbuf[0] ? BITFORCE_CHECK_INTERVAL_MS : 2 * WORK_CHECK_INTERVAL_MS); nmsleep(delay_time_ms); bitforce->wait_ms += delay_time_ms; } if (elapsed.tv_sec > BITFORCE_TIMEOUT_S) { applog(LOG_ERR, "BFL%i: took %dms - longer than %dms", bitforce->device_id, tv_to_ms(elapsed), BITFORCE_TIMEOUT_MS); bitforce->device_last_not_well = time(NULL); bitforce->device_not_well_reason = REASON_DEV_OVER_HEAT; bitforce->dev_over_heat_count++; if (!pdevbuf[0]) /* Only return if we got nothing after timeout - there still may be results */ return 0; } else if (!strncasecmp(pdevbuf, "N", 1)) {/* Hashing complete (NONCE-FOUND or NO-NONCE) */ /* Simple timing adjustment. Allow a few polls to cope with * OS timer delays being variably reliable. wait_ms will * always equal sleep_ms when we've waited greater than or * equal to the result return time.*/ delay_time_ms = bitforce->sleep_ms; if (bitforce->wait_ms > bitforce->sleep_ms + (WORK_CHECK_INTERVAL_MS * 2)) bitforce->sleep_ms += (bitforce->wait_ms - bitforce->sleep_ms) / 2; else if (bitforce->wait_ms == bitforce->sleep_ms) { if (bitforce->sleep_ms > WORK_CHECK_INTERVAL_MS) bitforce->sleep_ms -= WORK_CHECK_INTERVAL_MS; else if (bitforce->sleep_ms > BITFORCE_CHECK_INTERVAL_MS) bitforce->sleep_ms -= BITFORCE_CHECK_INTERVAL_MS; } if (delay_time_ms != bitforce->sleep_ms) applog(LOG_DEBUG, "BFL%i: Wait time changed to: %d, waited %u", bitforce->device_id, bitforce->sleep_ms, bitforce->wait_ms); /* Work out the average time taken. Float for calculation, uint for display */ bitforce->avg_wait_f += (tv_to_ms(elapsed) - bitforce->avg_wait_f) / TIME_AVG_CONSTANT; bitforce->avg_wait_d = (unsigned int) (bitforce->avg_wait_f + 0.5); } applog(LOG_DEBUG, "BFL%i: waited %dms until %s", bitforce->device_id, bitforce->wait_ms, pdevbuf); if (!strncasecmp(&pdevbuf[2], "-", 1)) return bitforce->nonces; /* No valid nonce found */ else if (!strncasecmp(pdevbuf, "I", 1)) return 0; /* Device idle */ else if (strncasecmp(pdevbuf, "NONCE-FOUND", 11)) { bitforce->hw_errors++; applog(LOG_WARNING, "BFL%i: Error: Get result reports: %s", bitforce->device_id, pdevbuf); bitforce_clear_buffer(bitforce); return 0; } pnoncebuf = &pdevbuf[12]; while (1) { hex2bin((void*)&nonce, pnoncebuf, 4); #ifndef __BIG_ENDIAN__ nonce = swab32(nonce); #endif if (unlikely(bitforce->nonce_range && (nonce >= work->blk.nonce || (work->blk.nonce > 0 && nonce < work->blk.nonce - bitforce->nonces - 1)))) { applog(LOG_WARNING, "BFL%i: Disabling broken nonce range support", bitforce->device_id); bitforce->nonce_range = false; work->blk.nonce = 0xffffffff; bitforce->sleep_ms *= 5; bitforce->kname = KNAME_WORK; } submit_nonce(thr, work, nonce); if (strncmp(&pnoncebuf[8], ",", 1)) break; pnoncebuf += 9; } return bitforce->nonces; }
static bool bitforce_send_work(struct thr_info *thr, struct work *work) { struct cgpu_info *bitforce = thr->cgpu; int fdDev = bitforce->device_fd; unsigned char ob[70]; char pdevbuf[0x100]; char *s; if (!fdDev) return false; re_send: mutex_lock(&bitforce->device_mutex); if (bitforce->nonce_range) BFwrite(fdDev, "ZPX", 3); else BFwrite(fdDev, "ZDX", 3); BFgets(pdevbuf, sizeof(pdevbuf), fdDev); if (!pdevbuf[0] || !strncasecmp(pdevbuf, "B", 1)) { mutex_unlock(&bitforce->device_mutex); nmsleep(WORK_CHECK_INTERVAL_MS); goto re_send; } else if (unlikely(strncasecmp(pdevbuf, "OK", 2))) { mutex_unlock(&bitforce->device_mutex); if (bitforce->nonce_range) { applog(LOG_WARNING, "BFL%i: Does not support nonce range, disabling", bitforce->device_id); bitforce->nonce_range = false; bitforce->sleep_ms *= 5; bitforce->kname = KNAME_WORK; goto re_send; } applog(LOG_ERR, "BFL%i: Error: Send work reports: %s", bitforce->device_id, pdevbuf); return false; } sprintf((char *)ob, ">>>>>>>>"); memcpy(ob + 8, work->midstate, 32); memcpy(ob + 8 + 32, work->data + 64, 12); if (!bitforce->nonce_range) { sprintf((char *)ob + 8 + 32 + 12, ">>>>>>>>"); work->blk.nonce = bitforce->nonces = 0xffffffff; BFwrite(fdDev, ob, 60); } else { uint32_t *nonce; nonce = (uint32_t *)(ob + 8 + 32 + 12); *nonce = htobe32(work->blk.nonce); nonce = (uint32_t *)(ob + 8 + 32 + 12 + 4); /* Split work up into 1/5th nonce ranges */ bitforce->nonces = 0x33333332; *nonce = htobe32(work->blk.nonce + bitforce->nonces); work->blk.nonce += bitforce->nonces + 1; sprintf((char *)ob + 8 + 32 + 12 + 8, ">>>>>>>>"); BFwrite(fdDev, ob, 68); } BFgets(pdevbuf, sizeof(pdevbuf), fdDev); mutex_unlock(&bitforce->device_mutex); if (opt_debug) { s = bin2hex(ob + 8, 44); applog(LOG_DEBUG, "BFL%i: block data: %s", bitforce->device_id, s); free(s); } if (unlikely(!pdevbuf[0])) { applog(LOG_ERR, "BFL%i: Error: Send block data returned empty string/timed out", bitforce->device_id); return false; } if (unlikely(strncasecmp(pdevbuf, "OK", 2))) { applog(LOG_ERR, "BFL%i: Error: Send block data reports: %s", bitforce->device_id, pdevbuf); return false; } gettimeofday(&bitforce->work_start_tv, NULL); return true; }
static bool bitforce_send_work(struct thr_info *thr, struct work *work) { struct cgpu_info *bitforce = thr->cgpu; unsigned char ob[70]; char buf[BITFORCE_BUFSIZ+1]; int err, amount; char *s; char *cmd; int len; re_send: if (bitforce->nonce_range) { cmd = BITFORCE_SENDRANGE; len = BITFORCE_SENDRANGE_LEN; } else { cmd = BITFORCE_SENDWORK; len = BITFORCE_SENDWORK_LEN; } mutex_lock(&bitforce->device_mutex); if ((err = usb_write(bitforce, cmd, len, &amount, C_REQUESTSENDWORK)) < 0 || amount != len) { mutex_unlock(&bitforce->device_mutex); applog(LOG_ERR, "%s%i: request send work failed (%d:%d)", bitforce->drv->name, bitforce->device_id, amount, err); return false; } if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_REQUESTSENDWORKSTATUS)) < 0) { mutex_unlock(&bitforce->device_mutex); applog(LOG_ERR, "%s%d: read request send work status failed (%d:%d)", bitforce->drv->name, bitforce->device_id, amount, err); return false; } if (amount == 0 || !buf[0] || !strncasecmp(buf, "B", 1)) { mutex_unlock(&bitforce->device_mutex); nmsleep(WORK_CHECK_INTERVAL_MS); goto re_send; } else if (unlikely(strncasecmp(buf, "OK", 2))) { mutex_unlock(&bitforce->device_mutex); if (bitforce->nonce_range) { applog(LOG_WARNING, "%s%i: Does not support nonce range, disabling", bitforce->drv->name, bitforce->device_id); bitforce->nonce_range = false; bitforce->sleep_ms *= 5; bitforce->kname = KNAME_WORK; goto re_send; } applog(LOG_ERR, "%s%i: Error: Send work reports: %s", bitforce->drv->name, bitforce->device_id, buf); return false; } sprintf((char *)ob, ">>>>>>>>"); memcpy(ob + 8, work->midstate, 32); memcpy(ob + 8 + 32, work->data + 64, 12); if (!bitforce->nonce_range) { sprintf((char *)ob + 8 + 32 + 12, ">>>>>>>>"); work->blk.nonce = bitforce->nonces = 0xffffffff; len = 60; } else { uint32_t *nonce; nonce = (uint32_t *)(ob + 8 + 32 + 12); *nonce = htobe32(work->blk.nonce); nonce = (uint32_t *)(ob + 8 + 32 + 12 + 4); /* Split work up into 1/5th nonce ranges */ bitforce->nonces = 0x33333332; *nonce = htobe32(work->blk.nonce + bitforce->nonces); work->blk.nonce += bitforce->nonces + 1; sprintf((char *)ob + 8 + 32 + 12 + 8, ">>>>>>>>"); len = 68; } if ((err = usb_write(bitforce, (char *)ob, len, &amount, C_SENDWORK)) < 0 || amount != len) { mutex_unlock(&bitforce->device_mutex); applog(LOG_ERR, "%s%i: send work failed (%d:%d)", bitforce->drv->name, bitforce->device_id, amount, err); return false; } if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_SENDWORKSTATUS)) < 0) { mutex_unlock(&bitforce->device_mutex); applog(LOG_ERR, "%s%d: read send work status failed (%d:%d)", bitforce->drv->name, bitforce->device_id, amount, err); return false; } mutex_unlock(&bitforce->device_mutex); if (opt_debug) { s = bin2hex(ob + 8, 44); applog(LOG_DEBUG, "%s%i: block data: %s", bitforce->drv->name, bitforce->device_id, s); free(s); } if (amount == 0 || !buf[0]) { applog(LOG_ERR, "%s%i: Error: Send block data returned empty string/timed out", bitforce->drv->name, bitforce->device_id); return false; } if (unlikely(strncasecmp(buf, "OK", 2))) { applog(LOG_ERR, "%s%i: Error: Send block data reports: %s", bitforce->drv->name, bitforce->device_id, buf); return false; } gettimeofday(&bitforce->work_start_tv, NULL); return true; }
static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devices *found) { char buf[BITFORCE_BUFSIZ+1]; char devpath[20]; int err, amount; char *s; struct cgpu_info *bitforce = NULL; bitforce = calloc(1, sizeof(*bitforce)); bitforce->drv = &bitforce_drv; bitforce->deven = DEV_ENABLED; bitforce->threads = 1; if (!usb_init(bitforce, dev, found)) { applog(LOG_ERR, "%s detect (%d:%d) failed to initialise (incorrect device?)", bitforce->drv->dname, (int)libusb_get_bus_number(dev), (int)libusb_get_device_address(dev)); goto shin; } sprintf(devpath, "%d:%d", (int)(bitforce->usbdev->bus_number), (int)(bitforce->usbdev->device_address)); int init_count = 0; reinit: bitforce_initialise(bitforce, false); if ((err = usb_write(bitforce, BITFORCE_IDENTIFY, BITFORCE_IDENTIFY_LEN, &amount, C_REQUESTIDENTIFY)) < 0 || amount != BITFORCE_IDENTIFY_LEN) { applog(LOG_ERR, "%s detect (%s) send identify request failed (%d:%d)", bitforce->drv->dname, devpath, amount, err); goto unshin; } if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETIDENTIFY)) < 0 || amount < 1) { // Maybe it was still processing previous work? if (++init_count <= REINIT_COUNT) { if (init_count < 2) { applog(LOG_WARNING, "%s detect (%s) 1st init failed - retrying (%d:%d)", bitforce->drv->dname, devpath, amount, err); } nmsleep(REINIT_TIME_MS); goto reinit; } if (init_count > 0) applog(LOG_WARNING, "%s detect (%s) init failed %d times", bitforce->drv->dname, devpath, init_count); if (err < 0) { applog(LOG_ERR, "%s detect (%s) error identify reply (%d:%d)", bitforce->drv->dname, devpath, amount, err); } else { applog(LOG_ERR, "%s detect (%s) empty identify reply (%d)", bitforce->drv->dname, devpath, amount); } goto unshin; } buf[amount] = '\0'; if (unlikely(!strstr(buf, "SHA256"))) { applog(LOG_ERR, "%s detect (%s) didn't recognise '%s'", bitforce->drv->dname, devpath, buf); goto unshin; } if (likely((!memcmp(buf, ">>>ID: ", 7)) && (s = strstr(buf + 3, ">>>")))) { s[0] = '\0'; bitforce->name = strdup(buf + 7); } else { bitforce->name = (char *)blank; } // We have a real BitForce! applog(LOG_DEBUG, "%s (%s) identified as: '%s'", bitforce->drv->dname, devpath, bitforce->name); /* Initially enable support for nonce range and disable it later if it * fails */ if (opt_bfl_noncerange) { bitforce->nonce_range = true; bitforce->sleep_ms = BITFORCE_SLEEP_MS; bitforce->kname = KNAME_RANGE; } else { bitforce->sleep_ms = BITFORCE_SLEEP_MS * 5; bitforce->kname = KNAME_WORK; } bitforce->device_path = strdup(devpath); if (!add_cgpu(bitforce)) goto unshin; update_usb_stats(bitforce); mutex_init(&bitforce->device_mutex); return true; unshin: usb_uninit(bitforce); shin: free(bitforce->device_path); if (bitforce->name != blank) free(bitforce->name); free(bitforce); return false; }
static bool ztex_checkNonce(struct libztex_device *ztex, struct work *work, struct libztex_hash_data *hdata) { uint32_t *data32 = (uint32_t *)(work->data); unsigned char swap[80]; uint32_t *swap32 = (uint32_t *)swap; unsigned char hash1[32]; unsigned char hash2[32]; uint32_t *hash2_32 = (uint32_t *)hash2; int i; #if defined(__BIGENDIAN__) || defined(MIPSEB) hdata->nonce = swab32(hdata->nonce); hdata->hash7 = swab32(hdata->hash7); #endif work->data[64 + 12 + 0] = (hdata->nonce >> 0) & 0xff; work->data[64 + 12 + 1] = (hdata->nonce >> 8) & 0xff; work->data[64 + 12 + 2] = (hdata->nonce >> 16) & 0xff; work->data[64 + 12 + 3] = (hdata->nonce >> 24) & 0xff; for (i = 0; i < 80 / 4; i++) swap32[i] = swab32(data32[i]); sha2(swap, 80, hash1, false); sha2(hash1, 32, hash2, false); #if defined(__BIGENDIAN__) || defined(MIPSEB) if (hash2_32[7] != ((hdata->hash7 + 0x5be0cd19) & 0xFFFFFFFF)) { #else if (swab32(hash2_32[7]) != ((hdata->hash7 + 0x5be0cd19) & 0xFFFFFFFF)) { #endif ztex->errorCount[ztex->freqM] += 1.0 / ztex->numNonces; applog(LOG_DEBUG, "%s: checkNonce failed for %0.8X", ztex->repr, hdata->nonce); return false; } return true; } static int64_t ztex_scanhash(struct thr_info *thr, struct work *work, __maybe_unused int64_t max_nonce) { struct libztex_device *ztex; unsigned char sendbuf[44]; int i, j, k; uint32_t *backlog; int backlog_p = 0, backlog_max; uint32_t *lastnonce; uint32_t nonce, noncecnt = 0; bool overflow, found; struct libztex_hash_data hdata[GOLDEN_BACKLOG]; if (thr->cgpu->deven == DEV_DISABLED) return -1; ztex = thr->cgpu->device_ztex; memcpy(sendbuf, work->data + 64, 12); memcpy(sendbuf + 12, work->midstate, 32); ztex_selectFpga(ztex); i = libztex_sendHashData(ztex, sendbuf); if (i < 0) { // Something wrong happened in send applog(LOG_ERR, "%s: Failed to send hash data with err %d, retrying", ztex->repr, i); nmsleep(500); i = libztex_sendHashData(ztex, sendbuf); if (i < 0) { // And there's nothing we can do about it ztex_disable(thr); applog(LOG_ERR, "%s: Failed to send hash data with err %d, giving up", ztex->repr, i); ztex_releaseFpga(ztex); return -1; } } ztex_releaseFpga(ztex); applog(LOG_DEBUG, "%s: sent hashdata", ztex->repr); lastnonce = calloc(1, sizeof(uint32_t)*ztex->numNonces); if (lastnonce == NULL) { applog(LOG_ERR, "%s: failed to allocate lastnonce[%d]", ztex->repr, ztex->numNonces); return -1; } /* Add an extra slot for detecting dupes that lie around */ backlog_max = ztex->numNonces * (2 + ztex->extraSolutions); backlog = calloc(1, sizeof(uint32_t) * backlog_max); if (backlog == NULL) { applog(LOG_ERR, "%s: failed to allocate backlog[%d]", ztex->repr, backlog_max); return -1; } overflow = false; applog(LOG_DEBUG, "%s: entering poll loop", ztex->repr); while (!(overflow || thr->work_restart)) { nmsleep(250); if (thr->work_restart) { applog(LOG_DEBUG, "%s: New work detected", ztex->repr); break; } ztex_selectFpga(ztex); i = libztex_readHashData(ztex, &hdata[0]); if (i < 0) { // Something wrong happened in read applog(LOG_ERR, "%s: Failed to read hash data with err %d, retrying", ztex->repr, i); nmsleep(500); i = libztex_readHashData(ztex, &hdata[0]); if (i < 0) { // And there's nothing we can do about it ztex_disable(thr); applog(LOG_ERR, "%s: Failed to read hash data with err %d, giving up", ztex->repr, i); free(lastnonce); free(backlog); ztex_releaseFpga(ztex); return -1; } } ztex_releaseFpga(ztex); if (thr->work_restart) { applog(LOG_DEBUG, "%s: New work detected", ztex->repr); break; } ztex->errorCount[ztex->freqM] *= 0.995; ztex->errorWeight[ztex->freqM] = ztex->errorWeight[ztex->freqM] * 0.995 + 1.0; for (i = 0; i < ztex->numNonces; i++) { nonce = hdata[i].nonce; #if defined(__BIGENDIAN__) || defined(MIPSEB) nonce = swab32(nonce); #endif if (nonce > noncecnt) noncecnt = nonce; if (((0xffffffff - nonce) < (nonce - lastnonce[i])) || nonce < lastnonce[i]) { applog(LOG_DEBUG, "%s: overflow nonce=%0.8x lastnonce=%0.8x", ztex->repr, nonce, lastnonce[i]); overflow = true; } else lastnonce[i] = nonce; #if !(defined(__BIGENDIAN__) || defined(MIPSEB)) nonce = swab32(nonce); #endif if (!ztex_checkNonce(ztex, work, &hdata[i])) { thr->cgpu->hw_errors++; continue; } for (j=0; j<=ztex->extraSolutions; j++) { nonce = hdata[i].goldenNonce[j]; if (nonce > 0) { found = false; for (k = 0; k < backlog_max; k++) { if (backlog[k] == nonce) { found = true; break; } } if (!found) { applog(LOG_DEBUG, "%s: Share found N%dE%d", ztex->repr, i, j); backlog[backlog_p++] = nonce; if (backlog_p >= backlog_max) backlog_p = 0; #if defined(__BIGENDIAN__) || defined(MIPSEB) nonce = swab32(nonce); #endif work->blk.nonce = 0xffffffff; submit_nonce(thr, work, nonce); applog(LOG_DEBUG, "%s: submitted %0.8x", ztex->repr, nonce); } } } } } ztex->errorRate[ztex->freqM] = ztex->errorCount[ztex->freqM] / ztex->errorWeight[ztex->freqM] * (ztex->errorWeight[ztex->freqM] < 100? ztex->errorWeight[ztex->freqM] * 0.01: 1.0); if (ztex->errorRate[ztex->freqM] > ztex->maxErrorRate[ztex->freqM]) ztex->maxErrorRate[ztex->freqM] = ztex->errorRate[ztex->freqM]; if (!ztex_updateFreq(ztex)) { // Something really serious happened, so mark this thread as dead! free(lastnonce); free(backlog); return -1; } applog(LOG_DEBUG, "%s: exit %1.8X", ztex->repr, noncecnt); work->blk.nonce = 0xffffffff; free(lastnonce); free(backlog); return noncecnt; } static void ztex_statline_before(char *buf, struct cgpu_info *cgpu) { if (cgpu->deven == DEV_ENABLED) { tailsprintf(buf, "%s-%d | ", cgpu->device_ztex->snString, cgpu->device_ztex->fpgaNum+1); tailsprintf(buf, "%0.1fMHz | ", cgpu->device_ztex->freqM1 * (cgpu->device_ztex->freqM + 1)); } } static bool ztex_prepare(struct thr_info *thr) { struct timeval now; struct cgpu_info *cgpu = thr->cgpu; struct libztex_device *ztex = cgpu->device_ztex; gettimeofday(&now, NULL); get_datestamp(cgpu->init, &now); ztex_selectFpga(ztex); if (libztex_configureFpga(ztex) != 0) { libztex_resetFpga(ztex); ztex_releaseFpga(ztex); applog(LOG_ERR, "%s: Disabling!", thr->cgpu->device_ztex->repr); thr->cgpu->deven = DEV_DISABLED; return true; } ztex->freqM = ztex->freqMaxM+1;; //ztex_updateFreq(ztex); libztex_setFreq(ztex, ztex->freqMDefault); ztex_releaseFpga(ztex); applog(LOG_DEBUG, "%s: prepare", ztex->repr); return true; } static void ztex_shutdown(struct thr_info *thr) { if (thr->cgpu->device_ztex != NULL) { if (thr->cgpu->device_ztex->fpgaNum == 0) pthread_mutex_destroy(&thr->cgpu->device_ztex->mutex); applog(LOG_DEBUG, "%s: shutdown", thr->cgpu->device_ztex->repr); libztex_destroy_device(thr->cgpu->device_ztex); thr->cgpu->device_ztex = NULL; } } static void ztex_disable(struct thr_info *thr) { applog(LOG_ERR, "%s: Disabling!", thr->cgpu->device_ztex->repr); devices[thr->cgpu->device_id]->deven = DEV_DISABLED; ztex_shutdown(thr); }
static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) { struct cgpu_info *bitforce = thr->cgpu; unsigned int delay_time_ms; struct timeval elapsed; struct timeval now; char buf[BITFORCE_BUFSIZ+1]; int amount; char *pnoncebuf; uint32_t nonce; while (1) { if (unlikely(thr->work_restart)) return 0; mutex_lock(&bitforce->device_mutex); usb_write(bitforce, BITFORCE_WORKSTATUS, BITFORCE_WORKSTATUS_LEN, &amount, C_REQUESTWORKSTATUS); usb_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETWORKSTATUS); mutex_unlock(&bitforce->device_mutex); cgtime(&now); timersub(&now, &bitforce->work_start_tv, &elapsed); if (elapsed.tv_sec >= BITFORCE_LONG_TIMEOUT_S) { applog(LOG_ERR, "%s%i: took %ldms - longer than %dms", bitforce->drv->name, bitforce->device_id, tv_to_ms(elapsed), BITFORCE_LONG_TIMEOUT_MS); return 0; } if (amount > 0 && buf[0] && strncasecmp(buf, "B", 1)) /* BFL does not respond during throttling */ break; /* if BFL is throttling, no point checking so quickly */ delay_time_ms = (buf[0] ? BITFORCE_CHECK_INTERVAL_MS : 2 * WORK_CHECK_INTERVAL_MS); nmsleep(delay_time_ms); bitforce->wait_ms += delay_time_ms; } if (elapsed.tv_sec > BITFORCE_TIMEOUT_S) { applog(LOG_ERR, "%s%i: took %ldms - longer than %dms", bitforce->drv->name, bitforce->device_id, tv_to_ms(elapsed), BITFORCE_TIMEOUT_MS); dev_error(bitforce, REASON_DEV_OVER_HEAT); /* Only return if we got nothing after timeout - there still may be results */ if (amount == 0) return 0; } else if (!strncasecmp(buf, BITFORCE_EITHER, BITFORCE_EITHER_LEN)) { /* Simple timing adjustment. Allow a few polls to cope with * OS timer delays being variably reliable. wait_ms will * always equal sleep_ms when we've waited greater than or * equal to the result return time.*/ delay_time_ms = bitforce->sleep_ms; if (bitforce->wait_ms > bitforce->sleep_ms + (WORK_CHECK_INTERVAL_MS * 2)) bitforce->sleep_ms += (bitforce->wait_ms - bitforce->sleep_ms) / 2; else if (bitforce->wait_ms == bitforce->sleep_ms) { if (bitforce->sleep_ms > WORK_CHECK_INTERVAL_MS) bitforce->sleep_ms -= WORK_CHECK_INTERVAL_MS; else if (bitforce->sleep_ms > BITFORCE_CHECK_INTERVAL_MS) bitforce->sleep_ms -= BITFORCE_CHECK_INTERVAL_MS; } if (delay_time_ms != bitforce->sleep_ms) applog(LOG_DEBUG, "%s%i: Wait time changed to: %d, waited %u", bitforce->drv->name, bitforce->device_id, bitforce->sleep_ms, bitforce->wait_ms); /* Work out the average time taken. Float for calculation, uint for display */ bitforce->avg_wait_f += (tv_to_ms(elapsed) - bitforce->avg_wait_f) / TIME_AVG_CONSTANT; bitforce->avg_wait_d = (unsigned int) (bitforce->avg_wait_f + 0.5); } applog(LOG_DEBUG, "%s%i: waited %dms until %s", bitforce->drv->name, bitforce->device_id, bitforce->wait_ms, buf); if (!strncasecmp(buf, BITFORCE_NO_NONCE, BITFORCE_NO_NONCE_MATCH)) return bitforce->nonces; /* No valid nonce found */ else if (!strncasecmp(buf, BITFORCE_IDLE, BITFORCE_IDLE_MATCH)) return 0; /* Device idle */ else if (strncasecmp(buf, BITFORCE_NONCE, BITFORCE_NONCE_LEN)) { bitforce->hw_errors++; applog(LOG_WARNING, "%s%i: Error: Get result reports: %s", bitforce->drv->name, bitforce->device_id, buf); bitforce_initialise(bitforce, true); return 0; } pnoncebuf = &buf[12]; while (1) { hex2bin((void*)&nonce, pnoncebuf, 4); #ifndef __BIG_ENDIAN__ nonce = swab32(nonce); #endif if (unlikely(bitforce->nonce_range && (nonce >= work->blk.nonce || (work->blk.nonce > 0 && nonce < work->blk.nonce - bitforce->nonces - 1)))) { applog(LOG_WARNING, "%s%i: Disabling broken nonce range support", bitforce->drv->name, bitforce->device_id); bitforce->nonce_range = false; work->blk.nonce = 0xffffffff; bitforce->sleep_ms *= 5; bitforce->kname = KNAME_WORK; } submit_nonce(thr, work, nonce); if (strncmp(&pnoncebuf[8], ",", 1)) break; pnoncebuf += 9; } return bitforce->nonces; }
static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devices *found) { char buf[BITFORCE_BUFSIZ+1]; int err, amount; char *s; struct timeval init_start, init_now; int init_sleep, init_count; bool ident_first; struct cgpu_info *bitforce = usb_alloc_cgpu(&bitforce_drv, 1); if (!usb_init(bitforce, dev, found)) goto shin; // Allow 2 complete attempts if the 1st time returns an unrecognised reply ident_first = true; retry: init_count = 0; init_sleep = REINIT_TIME_FIRST_MS; cgtime(&init_start); reinit: bitforce_initialise(bitforce, false); if ((err = usb_write(bitforce, BITFORCE_IDENTIFY, BITFORCE_IDENTIFY_LEN, &amount, C_REQUESTIDENTIFY)) < 0 || amount != BITFORCE_IDENTIFY_LEN) { applog(LOG_ERR, "%s detect (%s) send identify request failed (%d:%d)", bitforce->drv->dname, bitforce->device_path, amount, err); goto unshin; } if ((err = usb_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETIDENTIFY)) < 0 || amount < 1) { init_count++; cgtime(&init_now); if (us_tdiff(&init_now, &init_start) <= REINIT_TIME_MAX) { if (init_count == 2) { applog(LOG_WARNING, "%s detect (%s) 2nd init failed (%d:%d) - retrying", bitforce->drv->dname, bitforce->device_path, amount, err); } nmsleep(init_sleep); if ((init_sleep * 2) <= REINIT_TIME_MAX_MS) init_sleep *= 2; goto reinit; } if (init_count > 0) applog(LOG_WARNING, "%s detect (%s) init failed %d times %.2fs", bitforce->drv->dname, bitforce->device_path, init_count, tdiff(&init_now, &init_start)); if (err < 0) { applog(LOG_ERR, "%s detect (%s) error identify reply (%d:%d)", bitforce->drv->dname, bitforce->device_path, amount, err); } else { applog(LOG_ERR, "%s detect (%s) empty identify reply (%d)", bitforce->drv->dname, bitforce->device_path, amount); } goto unshin; } buf[amount] = '\0'; if (unlikely(!strstr(buf, "SHA256"))) { if (ident_first) { applog(LOG_WARNING, "%s detect (%s) didn't recognise '%s' trying again ...", bitforce->drv->dname, bitforce->device_path, buf); ident_first = false; goto retry; } applog(LOG_ERR, "%s detect (%s) didn't recognise '%s' on 2nd attempt", bitforce->drv->dname, bitforce->device_path, buf); goto unshin; } if (strstr(buf, "SHA256 SC")) { #ifdef USE_BFLSC applog(LOG_DEBUG, "SC device detected, will defer to BFLSC driver"); #else applog(LOG_WARNING, "SC device detected but no BFLSC support compiled in!"); #endif goto unshin; } if (likely((!memcmp(buf, ">>>ID: ", 7)) && (s = strstr(buf + 3, ">>>")))) { s[0] = '\0'; bitforce->name = strdup(buf + 7); } else { bitforce->name = (char *)blank; } // We have a real BitForce! applog(LOG_DEBUG, "%s (%s) identified as: '%s'", bitforce->drv->dname, bitforce->device_path, bitforce->name); /* Initially enable support for nonce range and disable it later if it * fails */ if (opt_bfl_noncerange) { bitforce->nonce_range = true; bitforce->sleep_ms = BITFORCE_SLEEP_MS; bitforce->kname = KNAME_RANGE; } else { bitforce->sleep_ms = BITFORCE_SLEEP_MS * 5; bitforce->kname = KNAME_WORK; } if (!add_cgpu(bitforce)) goto unshin; update_usb_stats(bitforce); mutex_init(&bitforce->device_mutex); return true; unshin: usb_uninit(bitforce); shin: if (bitforce->name != blank) { free(bitforce->name); bitforce->name = NULL; } bitforce = usb_free_cgpu(bitforce); return false; }
static int64_t ztex_scanhash(struct thr_info *thr, struct work *work, __maybe_unused int64_t max_nonce) { struct libztex_device *ztex; unsigned char sendbuf[44]; int i, j, k; uint32_t *backlog; int backlog_p = 0, backlog_max; uint32_t *lastnonce; uint32_t nonce, noncecnt = 0; bool overflow, found; struct libztex_hash_data hdata[GOLDEN_BACKLOG]; if (thr->cgpu->deven == DEV_DISABLED) return -1; ztex = thr->cgpu->device_ztex; memcpy(sendbuf, work->data + 64, 12); memcpy(sendbuf + 12, work->midstate, 32); ztex_selectFpga(ztex); i = libztex_sendHashData(ztex, sendbuf); if (i < 0) { // Something wrong happened in send applog(LOG_ERR, "%s: Failed to send hash data with err %d, retrying", ztex->repr, i); nmsleep(500); i = libztex_sendHashData(ztex, sendbuf); if (i < 0) { // And there's nothing we can do about it ztex_disable(thr); applog(LOG_ERR, "%s: Failed to send hash data with err %d, giving up", ztex->repr, i); ztex_releaseFpga(ztex); return -1; } } ztex_releaseFpga(ztex); applog(LOG_DEBUG, "%s: sent hashdata", ztex->repr); lastnonce = calloc(1, sizeof(uint32_t)*ztex->numNonces); if (lastnonce == NULL) { applog(LOG_ERR, "%s: failed to allocate lastnonce[%d]", ztex->repr, ztex->numNonces); return -1; } /* Add an extra slot for detecting dupes that lie around */ backlog_max = ztex->numNonces * (2 + ztex->extraSolutions); backlog = calloc(1, sizeof(uint32_t) * backlog_max); if (backlog == NULL) { applog(LOG_ERR, "%s: failed to allocate backlog[%d]", ztex->repr, backlog_max); return -1; } overflow = false; int count = 0; int validNonces = 0; double errorCount = 0; applog(LOG_DEBUG, "%s: entering poll loop", ztex->repr); while (!(overflow || thr->work_restart)) { count++; int sleepcount = 0; while (thr->work_restart == 0 && sleepcount < 25) { nmsleep(10); sleepcount += 1; } if (thr->work_restart) { applog(LOG_DEBUG, "%s: New work detected", ztex->repr); break; } ztex_selectFpga(ztex); i = libztex_readHashData(ztex, &hdata[0]); if (i < 0) { // Something wrong happened in read applog(LOG_ERR, "%s: Failed to read hash data with err %d, retrying", ztex->repr, i); nmsleep(500); i = libztex_readHashData(ztex, &hdata[0]); if (i < 0) { // And there's nothing we can do about it ztex_disable(thr); applog(LOG_ERR, "%s: Failed to read hash data with err %d, giving up", ztex->repr, i); free(lastnonce); free(backlog); ztex_releaseFpga(ztex); return -1; } } ztex_releaseFpga(ztex); if (thr->work_restart) { applog(LOG_DEBUG, "%s: New work detected", ztex->repr); break; } ztex->errorCount[ztex->freqM] *= 0.995; ztex->errorWeight[ztex->freqM] = ztex->errorWeight[ztex->freqM] * 0.995 + 1.0; for (i = 0; i < ztex->numNonces; i++) { nonce = hdata[i].nonce; if (nonce > noncecnt) noncecnt = nonce; if (((0xffffffff - nonce) < (nonce - lastnonce[i])) || nonce < lastnonce[i]) { applog(LOG_DEBUG, "%s: overflow nonce=%0.8x lastnonce=%0.8x", ztex->repr, nonce, lastnonce[i]); overflow = true; } else lastnonce[i] = nonce; if (ztex_checkNonce(work, nonce) != (hdata->hash7 + 0x5be0cd19)) { applog(LOG_DEBUG, "%s: checkNonce failed for %0.8X", ztex->repr, nonce); // do not count errors in the first 500ms after sendHashData (2x250 wait time) if (count > 2) { thr->cgpu->hw_errors++; errorCount += (1.0 / ztex->numNonces); } } else validNonces++; for (j=0; j<=ztex->extraSolutions; j++) { nonce = hdata[i].goldenNonce[j]; if (nonce == ztex->offsNonces) { continue; } // precheck the extraSolutions since they often fail if (j > 0 && ztex_checkNonce(work, nonce) != 0) { continue; } found = false; for (k = 0; k < backlog_max; k++) { if (backlog[k] == nonce) { found = true; break; } } if (!found) { applog(LOG_DEBUG, "%s: Share found N%dE%d", ztex->repr, i, j); backlog[backlog_p++] = nonce; if (backlog_p >= backlog_max) backlog_p = 0; work->blk.nonce = 0xffffffff; submit_nonce(thr, work, nonce); applog(LOG_DEBUG, "%s: submitted %0.8x", ztex->repr, nonce); } } } } // only add the errorCount if we had at least some valid nonces or // had no valid nonces in the last round if (errorCount > 0.0) { if (ztex->nonceCheckValid > 0 && validNonces == 0) { applog(LOG_ERR, "%s: resetting %.1f errors", ztex->repr, errorCount); } else { ztex->errorCount[ztex->freqM] += errorCount; } } // remember the number of valid nonces for the check in the next round ztex->nonceCheckValid = validNonces; ztex->errorRate[ztex->freqM] = ztex->errorCount[ztex->freqM] / ztex->errorWeight[ztex->freqM] * (ztex->errorWeight[ztex->freqM] < 100? ztex->errorWeight[ztex->freqM] * 0.01: 1.0); if (ztex->errorRate[ztex->freqM] > ztex->maxErrorRate[ztex->freqM]) ztex->maxErrorRate[ztex->freqM] = ztex->errorRate[ztex->freqM]; if (!ztex_updateFreq(ztex)) { // Something really serious happened, so mark this thread as dead! free(lastnonce); free(backlog); return -1; } applog(LOG_DEBUG, "%s: exit %1.8X", ztex->repr, noncecnt); work->blk.nonce = 0xffffffff; free(lastnonce); free(backlog); return noncecnt; }
static int64_t bitfury_scanHash(struct thr_info *thr) { static struct bitfury_device *devices; // TODO Move somewhere to appropriate place int chip_n; int chip; uint64_t hashes = 0; struct timeval now; unsigned char line[2048]; int short_stat = 10; static time_t short_out_t; int long_stat = 1800; static time_t long_out_t; int long_long_stat = 60 * 30; static time_t long_long_out_t; static first = 0; //TODO Move to detect() int i; devices = thr->cgpu->devices; chip_n = thr->cgpu->chip_n; if (!first) { for (i = 0; i < chip_n; i++) { devices[i].osc6_bits = 54; } for (i = 0; i < chip_n; i++) { send_reinit(devices[i].slot, devices[i].fasync, devices[i].osc6_bits); } } first = 1; for (chip = 0; chip < chip_n; chip++) { devices[chip].job_switched = 0; if(!devices[chip].work) { devices[chip].work = get_queued(thr->cgpu); if (devices[chip].work == NULL) { return 0; } work_to_payload(&(devices[chip].payload), devices[chip].work); } } libbitfury_sendHashData(devices, chip_n); nmsleep(5); cgtime(&now); chip = 0; for (;chip < chip_n; chip++) { if (devices[chip].job_switched) { int i,j; int *res = devices[chip].results; struct work *work = devices[chip].work; struct work *owork = devices[chip].owork; struct work *o2work = devices[chip].o2work; i = devices[chip].results_n; for (j = i - 1; j >= 0; j--) { if (owork) { submit_nonce(thr, owork, bswap_32(res[j])); devices[chip].stat_ts[devices[chip].stat_counter++] = now.tv_sec; if (devices[chip].stat_counter == BITFURY_STAT_N) { devices[chip].stat_counter = 0; } } if (o2work) { // TEST //submit_nonce(thr, owork, bswap_32(res[j])); } } devices[chip].results_n = 0; devices[chip].job_switched = 0; if (devices[chip].old_nonce && o2work) { submit_nonce(thr, o2work, bswap_32(devices[chip].old_nonce)); i++; } if (devices[chip].future_nonce) { submit_nonce(thr, work, bswap_32(devices[chip].future_nonce)); i++; } if (o2work) work_completed(thr->cgpu, o2work); devices[chip].o2work = devices[chip].owork; devices[chip].owork = devices[chip].work; devices[chip].work = NULL; hashes += 0xffffffffull * i; } } if (now.tv_sec - short_out_t > short_stat) { int shares_first = 0, shares_last = 0, shares_total = 0; char stat_lines[32][256] = {0}; int len, k; double gh[32][8] = {0}; double ghsum = 0, gh1h = 0, gh2h = 0; unsigned strange_counter = 0; for (chip = 0; chip < chip_n; chip++) { int shares_found = calc_stat(devices[chip].stat_ts, short_stat, now); double ghash; len = strlen(stat_lines[devices[chip].slot]); ghash = shares_to_ghashes(shares_found, short_stat); gh[devices[chip].slot][chip & 0x07] = ghash; snprintf(stat_lines[devices[chip].slot] + len, 256 - len, "%.1f-%3.0f ", ghash, devices[chip].mhz); if(short_out_t && ghash < 0.5) { applog(LOG_WARNING, "Chip_id %d FREQ CHANGE\n", chip); send_freq(devices[chip].slot, devices[chip].fasync, devices[chip].osc6_bits - 1); nmsleep(1); send_freq(devices[chip].slot, devices[chip].fasync, devices[chip].osc6_bits); } shares_total += shares_found; shares_first += chip < 4 ? shares_found : 0; shares_last += chip > 3 ? shares_found : 0; strange_counter += devices[chip].strange_counter; devices[chip].strange_counter = 0; } sprintf(line, "vvvvwww SHORT stat %ds: wwwvvvv", short_stat); applog(LOG_WARNING, line); sprintf(line, "stranges: %u", strange_counter); applog(LOG_WARNING, line); for(i = 0; i < 32; i++) if(strlen(stat_lines[i])) { len = strlen(stat_lines[i]); ghsum = 0; gh1h = 0; gh2h = 0; for(k = 0; k < 4; k++) { gh1h += gh[i][k]; gh2h += gh[i][k+4]; ghsum += gh[i][k] + gh[i][k+4]; } snprintf(stat_lines[i] + len, 256 - len, "- %2.1f + %2.1f = %2.1f slot %i ", gh1h, gh2h, ghsum, i); applog(LOG_WARNING, stat_lines[i]); } short_out_t = now.tv_sec; } if (now.tv_sec - long_out_t > long_stat) { int shares_first = 0, shares_last = 0, shares_total = 0; char stat_lines[32][256] = {0}; int len, k; double gh[32][8] = {0}; double ghsum = 0, gh1h = 0, gh2h = 0; for (chip = 0; chip < chip_n; chip++) { int shares_found = calc_stat(devices[chip].stat_ts, long_stat, now); double ghash; len = strlen(stat_lines[devices[chip].slot]); ghash = shares_to_ghashes(shares_found, long_stat); gh[devices[chip].slot][chip & 0x07] = ghash; snprintf(stat_lines[devices[chip].slot] + len, 256 - len, "%.1f-%3.0f ", ghash, devices[chip].mhz); shares_total += shares_found; shares_first += chip < 4 ? shares_found : 0; shares_last += chip > 3 ? shares_found : 0; } sprintf(line, "!!!_________ LONG stat %ds: ___________!!!", long_stat); applog(LOG_WARNING, line); for(i = 0; i < 32; i++) if(strlen(stat_lines[i])) { len = strlen(stat_lines[i]); ghsum = 0; gh1h = 0; gh2h = 0; for(k = 0; k < 4; k++) { gh1h += gh[i][k]; gh2h += gh[i][k+4]; ghsum += gh[i][k] + gh[i][k+4]; } snprintf(stat_lines[i] + len, 256 - len, "- %2.1f + %2.1f = %2.1f slot %i ", gh1h, gh2h, ghsum, i); applog(LOG_WARNING, stat_lines[i]); } long_out_t = now.tv_sec; } return hashes; }
static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devices *found) { char buf[BITFORCE_BUFSIZ+1]; char devpath[20]; int err, amount; char *s; struct timeval init_start, init_now; int init_sleep, init_count; bool ident_first; struct cgpu_info *bitforce = NULL; bitforce = calloc(1, sizeof(*bitforce)); bitforce->drv = &bitforce_drv; bitforce->deven = DEV_ENABLED; bitforce->threads = 1; if (!usb_init(bitforce, dev, found)) { applog(LOG_ERR, "%s detect (%d:%d) failed to initialise (incorrect device?)", bitforce->drv->dname, (int)(bitforce->usbinfo.bus_number), (int)(bitforce->usbinfo.device_address)); goto shin; } sprintf(devpath, "%d:%d", (int)(bitforce->usbinfo.bus_number), (int)(bitforce->usbinfo.device_address)); // Allow 2 complete attempts if the 1st time returns an unrecognised reply ident_first = true; retry: init_count = 0; init_sleep = REINIT_TIME_FIRST_MS; gettimeofday(&init_start, NULL); reinit: bitforce_initialise(bitforce, false); if ((err = usb_write(bitforce, BITFORCE_IDENTIFY, BITFORCE_IDENTIFY_LEN, &amount, C_REQUESTIDENTIFY)) < 0 || amount != BITFORCE_IDENTIFY_LEN) { applog(LOG_ERR, "%s detect (%s) send identify request failed (%d:%d)", bitforce->drv->dname, devpath, amount, err); goto unshin; } if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETIDENTIFY)) < 0 || amount < 1) { init_count++; gettimeofday(&init_now, NULL); if (us_tdiff(&init_now, &init_start) <= REINIT_TIME_MAX) { if (init_count == 2) { applog(LOG_WARNING, "%s detect (%s) 2nd init failed (%d:%d) - retrying", bitforce->drv->dname, devpath, amount, err); } nmsleep(init_sleep); if ((init_sleep * 2) <= REINIT_TIME_MAX_MS) init_sleep *= 2; goto reinit; } if (init_count > 0) applog(LOG_WARNING, "%s detect (%s) init failed %d times %.2fs", bitforce->drv->dname, devpath, init_count, tdiff(&init_now, &init_start)); if (err < 0) { applog(LOG_ERR, "%s detect (%s) error identify reply (%d:%d)", bitforce->drv->dname, devpath, amount, err); } else { applog(LOG_ERR, "%s detect (%s) empty identify reply (%d)", bitforce->drv->dname, devpath, amount); } goto unshin; } buf[amount] = '\0'; if (unlikely(!strstr(buf, "SHA256"))) { if (ident_first) { applog(LOG_WARNING, "%s detect (%s) didn't recognise '%s' trying again ...", bitforce->drv->dname, devpath, buf); ident_first = false; goto retry; } applog(LOG_ERR, "%s detect (%s) didn't recognise '%s' on 2nd attempt", bitforce->drv->dname, devpath, buf); goto unshin; } if (likely((!memcmp(buf, ">>>ID: ", 7)) && (s = strstr(buf + 3, ">>>")))) { s[0] = '\0'; bitforce->name = strdup(buf + 7); } else { bitforce->name = (char *)blank; } // We have a real BitForce! applog(LOG_DEBUG, "%s (%s) identified as: '%s'", bitforce->drv->dname, devpath, bitforce->name); /* Initially enable support for nonce range and disable it later if it * fails */ if (opt_bfl_noncerange) { bitforce->nonce_range = true; bitforce->sleep_ms = BITFORCE_SLEEP_MS; bitforce->kname = KNAME_RANGE; } else { bitforce->sleep_ms = BITFORCE_SLEEP_MS * 5; bitforce->kname = KNAME_WORK; } bitforce->device_path = strdup(devpath); if (!add_cgpu(bitforce)) goto unshin; update_usb_stats(bitforce); mutex_init(&bitforce->device_mutex); return true; unshin: usb_uninit(bitforce); shin: free(bitforce->device_path); if (bitforce->name != blank) free(bitforce->name); if (bitforce->drv->copy) free(bitforce->drv); free(bitforce); return false; }
static int64_t ztex_scanhash(struct thr_info *thr, struct work *work, __maybe_unused int64_t max_nonce) { // int numbytes = 80; // KRAMBLE 80 byte protocol int numbytes = 76; // KRAMBLE 76 byte protocol struct libztex_device *ztex; unsigned char sendbuf[80]; // KRAMBLE int i, j, k; uint32_t *backlog; int backlog_p = 0, backlog_max; uint32_t *lastnonce; uint32_t nonce, noncecnt = 0; bool overflow, found; struct libztex_hash_data hdata[GOLDEN_BACKLOG]; if (thr->cgpu->deven == DEV_DISABLED) return -1; ztex = thr->cgpu->device_ztex; // memcpy(sendbuf, work->data + 64, 12); // memcpy(sendbuf + 12, work->midstate, 32); memcpy(sendbuf, work->data, numbytes); // KRAMBLE ztex_selectFpga(ztex); i = libztex_sendHashData(ztex, sendbuf, numbytes); if (i < 0) { // Something wrong happened in send applog(LOG_ERR, "%s: Failed to send hash data with err %d, retrying", ztex->repr, i); nmsleep(500); i = libztex_sendHashData(ztex, sendbuf, numbytes); if (i < 0) { // And there's nothing we can do about it ztex_disable(thr); applog(LOG_ERR, "%s: Failed to send hash data with err %d, giving up", ztex->repr, i); ztex_releaseFpga(ztex); return -1; } } ztex_releaseFpga(ztex); #if 0 // KRAMBLE char *data = bin2hex(work->data, sizeof(work->data)); applog(LOG_INFO, "%s: sent data %s", ztex->repr, data); #endif lastnonce = calloc(1, sizeof(uint32_t)*ztex->numNonces); if (lastnonce == NULL) { applog(LOG_ERR, "%s: failed to allocate lastnonce[%d]", ztex->repr, ztex->numNonces); return -1; } /* Add an extra slot for detecting dupes that lie around */ backlog_max = ztex->numNonces * (2 + ztex->extraSolutions); backlog = calloc(1, sizeof(uint32_t) * backlog_max); if (backlog == NULL) { applog(LOG_ERR, "%s: failed to allocate backlog[%d]", ztex->repr, backlog_max); return -1; } overflow = false; int count = 0; int validNonces = 0; double errorCount = 0; applog(LOG_DEBUG, "%s: entering poll loop", ztex->repr); while (!(overflow || thr->work_restart)) { count++; int sleepcount = 0; while (thr->work_restart == 0 && sleepcount < 25) { nmsleep(10); sleepcount += 1; } if (thr->work_restart) { applog(LOG_DEBUG, "%s: New work detected", ztex->repr); break; } ztex_selectFpga(ztex); i = libztex_readHashData(ztex, &hdata[0]); if (i < 0) { // Something wrong happened in read applog(LOG_ERR, "%s: Failed to read hash data with err %d, retrying", ztex->repr, i); nmsleep(500); i = libztex_readHashData(ztex, &hdata[0]); if (i < 0) { // And there's nothing we can do about it ztex_disable(thr); applog(LOG_ERR, "%s: Failed to read hash data with err %d, giving up", ztex->repr, i); free(lastnonce); free(backlog); ztex_releaseFpga(ztex); return -1; } } ztex_releaseFpga(ztex); if (thr->work_restart) { applog(LOG_DEBUG, "%s: New work detected", ztex->repr); break; } ztex->errorCount[ztex->freqM] *= 0.995; ztex->errorWeight[ztex->freqM] = ztex->errorWeight[ztex->freqM] * 0.995 + 1.0; for (i = 0; i < ztex->numNonces; i++) { nonce = hdata[i].nonce; //if (nonce > noncecnt) by smartbitcoin // fix the verilog bug which send INT_MAX as nonce sometime. // NB: cgminer , nonce counter was int64, but ztex driver was int32. if( nonce > noncecnt && nonce < 1<<28 ) noncecnt = nonce; // KRAMBLE don't overflow if nonce == 0 (eg if fpga is not hashing) if ( (((0xffffffff - nonce) < (nonce - lastnonce[i])) || nonce < lastnonce[i]) && nonce ) { applog(LOG_INFO, "%s: overflow nonce=%08x lastnonce=%08x", ztex->repr, nonce, lastnonce[i]); // KRAMBLE not in production ?? // applog(LOG_DEBUG, "%s: overflow nonce=%08x lastnonce=%08x", ztex->repr, nonce, lastnonce[i]); // overflow = true; // KRAMBLE disabled as it should not happen at litecoin hash rates (except when broken // so leave warning message enabled) } else lastnonce[i] = nonce; // KRAMBLE try forcing overflow every so often to see if this fixes DIFF & SICK problems // if (nonce > 0x00040000) // Overflow every 256k nonces (a few times a minute, depending on hash rate) if (nonce > 0x00100000) // Overflow every 1M nonces (single core needs larger range to avoid duplicates) { // applog(LOG_INFO, "%s: force overflow nonce=%08x lastnonce=%08x", ztex->repr, nonce, lastnonce[i]); // KRAMBLE not in production overflow = true; } if (ztex_checkNonce(work, nonce) != (hdata->hash7)) { applog(LOG_INFO, "%s: checkNonce failed for %08X hash7 %08X", ztex->repr, nonce, hdata->hash7); // KRAMBLE not in production ?? // applog(LOG_DEBUG, "%s: checkNonce failed for %08X", ztex->repr, nonce); // do not count errors in the first 500ms after sendHashData (2x250 wait time) if (count > 2) { thr->cgpu->hw_errors++; errorCount += (1.0 / ztex->numNonces); } } else validNonces++; for (j=0; j<=ztex->extraSolutions; j++) { nonce = hdata[i].goldenNonce[j]; if (nonce == ztex->offsNonces) { continue; } // precheck the extraSolutions since they often fail if (j > 0 && ztex_checkNonce(work, nonce) != 0) { continue; } found = false; for (k = 0; k < backlog_max; k++) { if (backlog[k] == nonce) { found = true; break; } } if (!found) { applog(LOG_INFO, "%s: Share found %08x", ztex->repr, nonce); // KRAMBLE useful to show its working // applog(LOG_DEBUG, "%s: Share found N%dE%d", ztex->repr, i, j); backlog[backlog_p++] = nonce; if (backlog_p >= backlog_max) backlog_p = 0; work->blk.nonce = 0xffffffff; submit_nonce(thr, work, nonce); applog(LOG_DEBUG, "%s: submitted %08x", ztex->repr, nonce); } } } } // only add the errorCount if we had at least some valid nonces or // had no valid nonces in the last round if (errorCount > 0.0) { if (ztex->nonceCheckValid > 0 && validNonces == 0) { applog(LOG_ERR, "%s: resetting %.1f errors", ztex->repr, errorCount); } else { ztex->errorCount[ztex->freqM] += errorCount; } } // remember the number of valid nonces for the check in the next round ztex->nonceCheckValid = validNonces; ztex->errorRate[ztex->freqM] = ztex->errorCount[ztex->freqM] / ztex->errorWeight[ztex->freqM] * (ztex->errorWeight[ztex->freqM] < 100? ztex->errorWeight[ztex->freqM] * 0.01: 1.0); if (ztex->errorRate[ztex->freqM] > ztex->maxErrorRate[ztex->freqM]) ztex->maxErrorRate[ztex->freqM] = ztex->errorRate[ztex->freqM]; // KRAMBLE Disable ztex_updateFreq if lockClock flag set (ie --ztex-clock set initial and max freq to the same value) if (!ztex->lockClock) { if (!ztex_updateFreq(ztex)) { // Something really serious happened, so mark this thread as dead! free(lastnonce); free(backlog); return -1; } } applog(LOG_DEBUG, "%s: exit %1.8X", ztex->repr, noncecnt); work->blk.nonce = 0xffffffff; free(lastnonce); free(backlog); return noncecnt; }