static bool ztex_prepare(struct thr_info *thr) { struct cgpu_info *cgpu = thr->cgpu; struct libztex_device *ztex = cgpu->device_ztex; { char *fpganame = malloc(LIBZTEX_SNSTRING_LEN+3+1); sprintf(fpganame, "%s-%u", ztex->snString, cgpu->proc_id+1); cgpu->name = fpganame; } ztex_selectFpga(ztex, cgpu->proc_id); if (libztex_configureFpga(ztex, cgpu->proc_repr) != 0) { libztex_resetFpga(ztex); ztex_releaseFpga(ztex); applog(LOG_ERR, "%"PRIpreprv": Disabling!", cgpu->proc_repr); thr->cgpu->deven = DEV_DISABLED; return true; } ztex->dclk.freqM = ztex->dclk.freqMaxM+1; //ztex_updateFreq(thr); libztex_setFreq(ztex, ztex->dclk.freqMDefault, cgpu->proc_repr); ztex_releaseFpga(ztex); notifier_init(thr->work_restart_notifier); applog(LOG_DEBUG, "%"PRIpreprv": prepare", cgpu->proc_repr); cgpu->status = LIFE_INIT2; return true; }
static bool ztex_updateFreq(struct libztex_device* ztex) { int i, maxM, bestM; double bestR, r; for (i = 0; i < ztex->freqMaxM; i++) if (ztex->maxErrorRate[i + 1] * i < ztex->maxErrorRate[i] * (i + 20)) ztex->maxErrorRate[i + 1] = ztex->maxErrorRate[i] * (1.0 + 20.0 / i); maxM = 0; while (maxM < ztex->freqMDefault && ztex->maxErrorRate[maxM + 1] < LIBZTEX_MAXMAXERRORRATE) maxM++; while (maxM < ztex->freqMaxM && ztex->errorWeight[maxM] > 150 && ztex->maxErrorRate[maxM + 1] < LIBZTEX_MAXMAXERRORRATE) maxM++; bestM = 0; bestR = 0; for (i = 0; i <= maxM; i++) { r = (i + 1 + (i == ztex->freqM? LIBZTEX_ERRORHYSTERESIS: 0)) * (1 - ztex->maxErrorRate[i]); if (r > bestR) { bestM = i; bestR = r; } } if (bestM != ztex->freqM) { ztex_selectFpga(ztex); libztex_setFreq(ztex, bestM); ztex_releaseFpga(ztex); } maxM = ztex->freqMDefault; while (maxM < ztex->freqMaxM && ztex->errorWeight[maxM + 1] > 100) maxM++; if ((bestM < (1.0 - LIBZTEX_OVERHEATTHRESHOLD) * maxM) && bestM < maxM - 1) { ztex_selectFpga(ztex); libztex_resetFpga(ztex); ztex_releaseFpga(ztex); applog(LOG_ERR, "%s: frequency drop of %.1f%% detect. This may be caused by overheating. FPGA is shut down to prevent damage.", ztex->repr, (1.0 - 1.0 * bestM / maxM) * 100); return false; } return true; }
static bool ztex_change_clock_func(struct thr_info *thr, int bestM) { struct cgpu_info *cgpu = thr->cgpu; struct libztex_device *ztex = thr->cgpu->device_ztex; ztex_selectFpga(ztex, cgpu->proc_id); libztex_setFreq(ztex, bestM, cgpu->proc_repr); ztex_releaseFpga(ztex); return true; }
static bool ztex_updateFreq(struct thr_info *thr) { struct cgpu_info *cgpu = thr->cgpu; struct libztex_device *ztex = thr->cgpu->device_ztex; bool rv = dclk_updateFreq(&ztex->dclk, ztex_change_clock_func, thr); if (unlikely(!rv)) { ztex_selectFpga(ztex, cgpu->proc_id); libztex_resetFpga(ztex); ztex_releaseFpga(ztex); } return rv; }
static bool ztex_prepare(struct thr_info *thr) { struct cgpu_info *cgpu = thr->cgpu; struct libztex_device *ztex = cgpu->device_ztex; 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 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 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 ztex_scanhash(struct thr_info *thr, struct work *work, __maybe_unused int64_t max_nonce) { struct cgpu_info *cgpu = thr->cgpu; 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, cgpu->proc_id); i = libztex_sendHashData(ztex, sendbuf); if (i < 0) { // Something wrong happened in send applog(LOG_ERR, "%"PRIpreprv": Failed to send hash data with err %d, retrying", cgpu->proc_repr, i); cgsleep_ms(500); i = libztex_sendHashData(ztex, sendbuf); if (i < 0) { // And there's nothing we can do about it ztex_disable(thr); applog(LOG_ERR, "%"PRIpreprv": Failed to send hash data with err %d, giving up", cgpu->proc_repr, i); ztex_releaseFpga(ztex); return -1; } } ztex_releaseFpga(ztex); applog(LOG_DEBUG, "%"PRIpreprv": sent hashdata", cgpu->proc_repr); lastnonce = calloc(1, sizeof(uint32_t)*ztex->numNonces); if (lastnonce == NULL) { applog(LOG_ERR, "%"PRIpreprv": failed to allocate lastnonce[%d]", cgpu->proc_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, "%"PRIpreprv": failed to allocate backlog[%d]", cgpu->proc_repr, backlog_max); free(lastnonce); return -1; } overflow = false; int count = 0; applog(LOG_DEBUG, "%"PRIpreprv": entering poll loop", cgpu->proc_repr); while (!(overflow || thr->work_restart)) { count++; if (!restart_wait(thr, 250)) { applog(LOG_DEBUG, "%"PRIpreprv": New work detected", cgpu->proc_repr); break; } ztex_selectFpga(ztex, cgpu->proc_id); i = libztex_readHashData(ztex, &hdata[0]); if (i < 0) { // Something wrong happened in read applog(LOG_ERR, "%"PRIpreprv": Failed to read hash data with err %d, retrying", cgpu->proc_repr, i); cgsleep_ms(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, "%"PRIpreprv": Failed to read hash data with err %d, giving up", cgpu->proc_repr, i); free(lastnonce); free(backlog); ztex_releaseFpga(ztex); return -1; } } ztex_releaseFpga(ztex); if (thr->work_restart) { applog(LOG_DEBUG, "%"PRIpreprv": New work detected", cgpu->proc_repr); break; } dclk_gotNonces(&ztex->dclk); 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, "%"PRIpreprv": overflow nonce=%08x lastnonce=%08x", cgpu->proc_repr, nonce, lastnonce[i]); overflow = true; } else lastnonce[i] = nonce; if (!ztex_checkNonce(cgpu, work, &hdata[i])) { // do not count errors in the first 500ms after sendHashData (2x250 wait time) if (count > 2) dclk_errorCount(&ztex->dclk, 1.0 / ztex->numNonces); inc_hw_errors_only(thr); } for (j=0; j<=ztex->extraSolutions; j++) { nonce = hdata[i].goldenNonce[j]; if (nonce == ztex->offsNonces) { continue; } found = false; for (k = 0; k < backlog_max; k++) { if (backlog[k] == nonce) { found = true; break; } } if (!found) { backlog[backlog_p++] = nonce; if (backlog_p >= backlog_max) backlog_p = 0; work->blk.nonce = 0xffffffff; if (!j || test_nonce(work, nonce, false)) submit_nonce(thr, work, nonce); applog(LOG_DEBUG, "%"PRIpreprv": submitted %08x (from N%dE%d)", cgpu->proc_repr, nonce, i, j); } } } } dclk_preUpdate(&ztex->dclk); if (!ztex_updateFreq(thr)) { // Something really serious happened, so mark this thread as dead! free(lastnonce); free(backlog); return -1; } applog(LOG_DEBUG, "%"PRIpreprv": exit %1.8X", cgpu->proc_repr, noncecnt); work->blk.nonce = 0xffffffff; free(lastnonce); free(backlog); return noncecnt; }
static bool ztex_prepare(struct thr_info *thr) { struct timeval now; struct cgpu_info *cgpu = thr->cgpu; struct libztex_device *ztex = cgpu->device_ztex; cgtime(&now); 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; } // KRAMBLE Handle options, based on get_options in driver-icarus.c // Use as --ztex-clock freqM:freqMaxM // Multiple comma separated vaues are allowed eg 160:180,180:184 { // Bare block to isolate variables char err_buf[BUFSIZ+1]; char buf[BUFSIZ+1]; char *ptr, *comma, *colon, *colon2; size_t max; int i, tmp; int this_option_offset = ++option_offset; if (opt_ztex_clock == NULL) buf[0] = '\0'; else { ptr = opt_ztex_clock; for (i = 0; i < this_option_offset; i++) { comma = strchr(ptr, ','); if (comma == NULL) break; ptr = comma + 1; } comma = strchr(ptr, ','); if (comma == NULL) max = strlen(ptr); else max = comma - ptr; if (max > BUFSIZ) max = BUFSIZ; strncpy(buf, ptr, max); buf[max] = '\0'; } if (*buf) { colon = strchr(buf, ':'); if (colon) *(colon++) = '\0'; if (*buf) { tmp = atoi(buf); if (tmp >= 100 && tmp <= 250) ztex->freqM = ztex->freqMDefault = tmp/4 - 1; // NB 4Mhz units else { sprintf(err_buf, "Invalid ztex_clock must be between 100 and 250", buf); quit(1, err_buf); } } if (colon && *colon) { tmp = atoi(colon); if (tmp >= 100 && tmp <= 250) { if (tmp/4 - 1 >= ztex->freqM) { ztex->freqMaxM = tmp/4 - 1; // NB 4Mhz units // If both initial and max were set, and were the same, lock the clock if (ztex->freqMDefault == ztex->freqMaxM) ztex->lockClock = 1; } else { sprintf(err_buf, "Invalid ztex_clock max must be less than min", buf); quit(1, err_buf); } } else { sprintf(err_buf, "Invalid ztex_clock must be between 100 and 250", buf); quit(1, err_buf); } } } } // End bare block ztex->freqM = ztex->freqMaxM+1; // KRAMBLE is in original // ztex_updateFreq(ztex); // KRAMBLE Was already commented out in original #if 1 libztex_setFreq(ztex, ztex->freqMDefault); // KRAMBLE PRODUCTION CODE #else // KRAMBLE build customised settings for a specific board if (ztex->repr[strlen(ztex->repr)-1] == '4') libztex_setFreq(ztex, ztex->freqMDefault-1); // Run it 4MHz slower else libztex_setFreq(ztex, ztex->freqMDefault); #endif ztex_releaseFpga(ztex); applog(LOG_DEBUG, "%s: prepare", ztex->repr); return true; }
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; }