diff --git a/bitstreams/ztex_ufm1_15d4.bit b/bitstreams/ztex_ufm1_15d4.bit new file mode 100644 index 00000000..09519764 Binary files /dev/null and b/bitstreams/ztex_ufm1_15d4.bit differ diff --git a/bitstreams/ztex_ufm1_15y1.bit b/bitstreams/ztex_ufm1_15y1.bit new file mode 100644 index 00000000..c9b38ae0 Binary files /dev/null and b/bitstreams/ztex_ufm1_15y1.bit differ diff --git a/driver-ztex.c b/driver-ztex.c index a63b4a7f..a938caef 100644 --- a/driver-ztex.c +++ b/driver-ztex.c @@ -87,13 +87,16 @@ static bool ztex_updateFreq(struct libztex_device* ztex) } } - if (bestM != ztex->freqM) + if (bestM != ztex->freqM) { + libztex_selectFpga(ztex, 0); libztex_setFreq(ztex, bestM); + } maxM = ztex->freqMDefault; while (maxM < ztex->freqMaxM && ztex->errorWeight[maxM + 1] > 100) maxM++; if ((bestM < (1.0 - LIBZTEX_OVERHEATTHRESHOLD) * maxM) && bestM < maxM - 1) { + libztex_selectFpga(ztex, 0); libztex_resetFpga(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); @@ -147,10 +150,11 @@ static uint64_t ztex_scanhash(struct thr_info *thr, struct work *work, { struct libztex_device *ztex; unsigned char sendbuf[44]; - int i, j; - uint32_t backlog[GOLDEN_BACKLOG]; - int backlog_p = 0; - uint32_t lastnonce[GOLDEN_BACKLOG], nonce, noncecnt = 0; + int i, j, k; + uint32_t *backlog; + int backlog_p = 0, backlog_max; + uint32_t *lastnonce; + uint32_t nonce, noncecnt = 0; bool overflow, found, rv; struct libztex_hash_data hdata[GOLDEN_BACKLOG]; @@ -158,7 +162,8 @@ static uint64_t ztex_scanhash(struct thr_info *thr, struct work *work, memcpy(sendbuf, work->data + 64, 12); memcpy(sendbuf + 12, work->midstate, 32); - memset(backlog, 0, sizeof(backlog)); + + libztex_selectFpga(ztex, 0); i = libztex_sendHashData(ztex, sendbuf); if (i < 0) { // Something wrong happened in send @@ -173,19 +178,33 @@ static uint64_t ztex_scanhash(struct thr_info *thr, struct work *work, } } - applog(LOG_DEBUG, "sent hashdata"); - - for (i = 0; i < ztex->numNonces; i++) - lastnonce[i] = 0; + applog(LOG_DEBUG, "%s: sent hashdata", ztex->repr); + lastnonce = malloc(sizeof(uint32_t)*ztex->numNonces); + if (lastnonce == NULL) { + applog(LOG_ERR, "%s: failed to allocate lastnonce[%d]", ztex->repr, ztex->numNonces); + return 0; + } + memset(lastnonce, 0, sizeof(uint32_t)*ztex->numNonces); + + backlog_max = ztex->numNonces * (1 + ztex->extraSolutions); + backlog = malloc(sizeof(uint32_t) * backlog_max); + if (backlog == NULL) { + applog(LOG_ERR, "%s: failed to allocate backlog[%d]", ztex->repr, backlog_max); + return 0; + } + memset(backlog, 0, sizeof(uint32_t) * backlog_max); + overflow = false; + applog(LOG_DEBUG, "%s: entering poll loop", ztex->repr); while (!(overflow || work_restart[thr->id].restart)) { usleep(250000); if (work_restart[thr->id].restart) { applog(LOG_DEBUG, "%s: New work detected", ztex->repr); break; } + libztex_selectFpga(ztex, 0); i = libztex_readHashData(ztex, &hdata[0]); if (i < 0) { // Something wrong happened in read @@ -196,6 +215,8 @@ static uint64_t ztex_scanhash(struct thr_info *thr, struct work *work, // 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); return 0; } } @@ -227,26 +248,28 @@ static uint64_t ztex_scanhash(struct thr_info *thr, struct work *work, thr->cgpu->hw_errors++; continue; } - nonce = hdata[i].goldenNonce; - if (nonce > 0) { - found = false; - for (j = 0; j < GOLDEN_BACKLOG; j++) { - if (backlog[j] == nonce) { - found = true; - break; + 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", ztex->repr); - backlog[backlog_p++] = nonce; - if (backlog_p >= GOLDEN_BACKLOG) - backlog_p = 0; + 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); + nonce = swab32(nonce); #endif - work->blk.nonce = 0xffffffff; - rv = submit_nonce(thr, work, nonce); - applog(LOG_DEBUG, "%s: submitted %0.8x %d", ztex->repr, nonce, rv); + work->blk.nonce = 0xffffffff; + rv = submit_nonce(thr, work, nonce); + applog(LOG_DEBUG, "%s: submitted %0.8x %d", ztex->repr, nonce, rv); + } } } @@ -258,14 +281,21 @@ static uint64_t ztex_scanhash(struct thr_info *thr, struct work *work, if (ztex->errorRate[ztex->freqM] > ztex->maxErrorRate[ztex->freqM]) ztex->maxErrorRate[ztex->freqM] = ztex->errorRate[ztex->freqM]; - if (!ztex_updateFreq(ztex)) + if (!ztex_updateFreq(ztex)) { // Something really serious happened, so mark this thread as dead! + free(lastnonce); + free(backlog); + return 0; + } applog(LOG_DEBUG, "%s: exit %1.8X", ztex->repr, noncecnt); work->blk.nonce = 0xffffffff; + free(lastnonce); + free(backlog); + return noncecnt > 0? noncecnt: 1; } diff --git a/libztex.c b/libztex.c index d76d7987..3440d22d 100644 --- a/libztex.c +++ b/libztex.c @@ -41,7 +41,8 @@ #define CAPABILITY_HS_FPGA 0,5 //* Capability index for AVR XMEGA support. #define CAPABILITY_MAC_EEPROM 0,6 - +//* Capability index for multi FPGA support. +#define CAPABILITY_MULTI_FPGA 0,7 static bool libztex_checkDevice(struct libusb_device *dev) @@ -65,7 +66,7 @@ static bool libztex_checkCapability(struct libztex_device *ztex, int i, int j) { if (!((i >= 0) && (i <= 5) && (j >= 0) && (j < 8) && (((ztex->interfaceCapabilities[i] & 255) & (1 << j)) != 0))) { - applog(LOG_ERR, "%s: capability missing: %d %d", ztex->repr, i, i); + applog(LOG_ERR, "%s: capability missing: %d %d", ztex->repr, i, j); return false; } return true; @@ -223,9 +224,48 @@ int libztex_configureFpga(struct libztex_device *ztex) return libztex_configureFpgaLS(ztex, buf, true, 2); } -int libztex_setFreq(struct libztex_device *ztex, uint16_t freq) -{ +int libztex_numberOfFpgas(struct libztex_device *ztex) { int cnt; + unsigned char buf[3]; + if (ztex->numberOfFpgas < 0) { + if (libztex_checkCapability(ztex, CAPABILITY_MULTI_FPGA)) { + cnt = libusb_control_transfer(ztex->hndl, 0xc0, 0x50, 0, 0, buf, 3, 1000); + if (unlikely(cnt < 0)) { + applog(LOG_ERR, "%s: Failed getMultiFpgaInfo with err %d", ztex->repr, cnt); + return cnt; + } + ztex->numberOfFpgas = buf[0] + 1; + ztex->selectedFpga = buf[1]; + ztex->parallelConfigSupport = (buf[2] == 1); + } else { + ztex->numberOfFpgas = 1; + ztex->selectedFpga = 0; + ztex->parallelConfigSupport = false; + } + } + return ztex->numberOfFpgas; +} + +int libztex_selectFpga(struct libztex_device *ztex, int number) { + int cnt, fpgacnt = libztex_numberOfFpgas(ztex); + if (number < 0 || number >= fpgacnt) { + applog(LOG_WARNING, "%s: Trying to select wrong fpga (%d in %d)", ztex->repr, number, fpgacnt); + return 1; + } + if (ztex->selectedFpga != number && libztex_checkCapability(ztex, CAPABILITY_MULTI_FPGA)) { + cnt = libusb_control_transfer(ztex->hndl, 0x40, 0x51, number, 0, NULL, 0, 500); + if (unlikely(cnt < 0)) { + applog(LOG_ERR, "Ztex check device: Failed to set fpga with err %d", cnt); + return cnt; + } + ztex->selectedFpga = number; + } + return 0; +} + +int libztex_setFreq(struct libztex_device *ztex, uint16_t freq) { + int cnt; + uint16_t oldfreq = ztex->freqM; if (freq > ztex->freqMaxM) freq = ztex->freqMaxM; @@ -236,7 +276,8 @@ int libztex_setFreq(struct libztex_device *ztex, uint16_t freq) return cnt; } ztex->freqM = freq; - applog(LOG_WARNING, "%s: Frequency change to %0.2f Mhz", ztex->repr, ztex->freqM1 * (ztex->freqM + 1)); + applog(LOG_WARNING, "%s: Frequency change from %0.2f to %0.2f Mhz", + ztex->repr, ztex->freqM1 * (oldfreq + 1), ztex->freqM1 * (ztex->freqM + 1)); return 0; } @@ -246,14 +287,22 @@ int libztex_resetFpga(struct libztex_device *ztex) return libusb_control_transfer(ztex->hndl, 0x40, 0x31, 0, 0, NULL, 0, 1000); } -int libztex_prepare_device(struct libusb_device *dev, struct libztex_device** ztex) -{ +int libztex_suspend(struct libztex_device *ztex) { + if (ztex->suspendSupported) { + return libusb_control_transfer(ztex->hndl, 0x40, 0x84, 0, 0, NULL, 0, 1000); + } else { + return 0; + } +} + +int libztex_prepare_device(struct libusb_device *dev, struct libztex_device** ztex) { struct libztex_device *newdev; + int i, cnt, err; unsigned char buf[64]; - int cnt, err; newdev = malloc(sizeof(struct libztex_device)); newdev->bitFileName = NULL; + newdev->numberOfFpgas = -1; newdev->valid = false; newdev->hndl = NULL; *ztex = newdev; @@ -266,7 +315,7 @@ int libztex_prepare_device(struct libusb_device *dev, struct libztex_device** zt // Check vendorId and productId if (!(newdev->descriptor.idVendor == LIBZTEX_IDVENDOR && - newdev->descriptor.idProduct == LIBZTEX_IDPRODUCT)) { + newdev->descriptor.idProduct == LIBZTEX_IDPRODUCT)) { applog(LOG_ERR, "Not a ztex device? %0.4X, %0.4X", newdev->descriptor.idVendor, newdev->descriptor.idProduct); return 1; } @@ -290,7 +339,7 @@ int libztex_prepare_device(struct libusb_device *dev, struct libztex_device** zt return cnt; } - if ( buf[0] != 40 || buf[1] != 1 || buf[2] != 'Z' || buf[3] != 'T' || buf[4] != 'E' || buf[5] != 'X' ) { + if (buf[0] != 40 || buf[1] != 1 || buf[2] != 'Z' || buf[3] != 'T' || buf[4] != 'E' || buf[5] != 'X') { applog(LOG_ERR, "Ztex check device: Error reading ztex descriptor"); return 2; } @@ -327,20 +376,46 @@ int libztex_prepare_device(struct libusb_device *dev, struct libztex_device** zt return cnt; } - if (unlikely(buf[0] != 4)) { - if (unlikely(buf[0] != 2)) { + if (unlikely(buf[0] != 5)) { + if (unlikely(buf[0] != 2 && buf[0] != 4)) { applog(LOG_ERR, "Invalid BTCMiner descriptor version. Firmware must be updated (%d).", buf[0]); return 3; } - applog(LOG_WARNING, "Firmware out of date"); + applog(LOG_WARNING, "Firmware out of date (%d).", buf[0]); + } + + i = buf[0] > 4? 11: (buf[0] > 2? 10: 8); + + while (cnt < 64 && buf[cnt] != 0) + cnt++; + if (cnt < i + 1) { + applog(LOG_ERR, "Invalid bitstream file name ."); + return 4; } + newdev->bitFileName = malloc(sizeof(char) * (cnt + 1)); + memcpy(newdev->bitFileName, &buf[i], cnt); + newdev->bitFileName[cnt] = 0; + newdev->numNonces = buf[1] + 1; newdev->offsNonces = ((buf[2] & 255) | ((buf[3] & 255) << 8)) - 10000; newdev->freqM1 = ((buf[4] & 255) | ((buf[5] & 255) << 8) ) * 0.01; newdev->freqMaxM = (buf[7] & 255); newdev->freqM = (buf[6] & 255); newdev->freqMDefault = newdev->freqM; + newdev->suspendSupported = (buf[0] == 5); + newdev->hashesPerClock = buf[0] > 2? (((buf[8] & 255) | ((buf[9] & 255) << 8)) + 1) / 128.0: 1.0; + newdev->extraSolutions = buf[0] > 4? buf[10]: 0; + + applog(LOG_DEBUG, "PID: %d numNonces: %d offsNonces: %d freqM1: %f freqMaxM: %d freqM: %d suspendSupported: %s hashesPerClock: %f extraSolutions: %d", + buf[0], newdev->numNonces, newdev->offsNonces, newdev->freqM1, newdev->freqMaxM, newdev->freqM, newdev->suspendSupported ? "T": "F", + newdev->hashesPerClock, newdev->extraSolutions); + + if (buf[0] < 4) { + if (strncmp(newdev->bitFileName, "ztex_ufm1_15b", 13) != 0) + newdev->hashesPerClock = 0.5; + applog(LOG_WARNING, "HASHES_PER_CLOCK not defined, assuming %0.2f", newdev->hashesPerClock); + } for (cnt=0; cnt < 255; cnt++) { newdev->errorCount[cnt] = 0; @@ -349,10 +424,6 @@ int libztex_prepare_device(struct libusb_device *dev, struct libztex_device** zt newdev->maxErrorRate[cnt] = 0; } - cnt = strlen((char *)&buf[buf[0] == 4? 10: 8]); - newdev->bitFileName = malloc(sizeof(char) * (cnt + 1)); - memcpy(newdev->bitFileName, &buf[buf[0] == 4? 10: 8], cnt + 1); - newdev->usbbus = libusb_get_bus_number(dev); newdev->usbaddress = libusb_get_device_address(dev); sprintf(newdev->repr, "ZTEX %.3d:%.3d-%s", newdev->usbbus, newdev->usbaddress, newdev->snString); @@ -437,29 +508,43 @@ int libztex_sendHashData(struct libztex_device *ztex, unsigned char *sendbuf) return cnt; } -int libztex_readHashData(struct libztex_device *ztex, struct libztex_hash_data nonces[]) -{ - // length of buf must be 8 * (numNonces + 1) - unsigned char rbuf[12 * 8]; - int cnt, i; +int libztex_readHashData(struct libztex_device *ztex, struct libztex_hash_data nonces[]) { + int bufsize = 12 + ztex->extraSolutions * 4; + unsigned char *rbuf; + int cnt, i, j; if (ztex->hndl == NULL) return 0; - cnt = libusb_control_transfer(ztex->hndl, 0xc0, 0x81, 0, 0, rbuf, 12 * ztex->numNonces, 1000); + rbuf = malloc(sizeof(unsigned char) * (ztex->numNonces * bufsize)); + if (rbuf == NULL) { + applog(LOG_ERR, "%s: Failed to allocate memory for reading nonces", ztex->repr); + return 0; + } + cnt = libusb_control_transfer(ztex->hndl, 0xc0, 0x81, 0, 0, rbuf, bufsize * ztex->numNonces, 1000); if (unlikely(cnt < 0)) { applog(LOG_ERR, "%s: Failed readHashData with err %d", ztex->repr, cnt); + free(rbuf); return cnt; } - for (i = 0; i < ztex->numNonces; i++) { - memcpy((char*)&nonces[i].goldenNonce, &rbuf[i * 12], 4); - nonces[i].goldenNonce -= ztex->offsNonces; - memcpy((char*)&nonces[i].nonce, &rbuf[(i * 12) + 4], 4); + for (i=0; inumNonces; i++) { + memcpy((char*)&nonces[i].goldenNonce[0], &rbuf[i*bufsize], 4); + nonces[i].goldenNonce[0] -= ztex->offsNonces; + //applog(LOG_DEBUG, "W %d:0 %0.8x", i, nonces[i].goldenNonce[0]); + + memcpy((char*)&nonces[i].nonce, &rbuf[(i*bufsize)+4], 4); nonces[i].nonce -= ztex->offsNonces; - memcpy((char*)&nonces[i].hash7, &rbuf[(i * 12) + 8], 4); + memcpy((char*)&nonces[i].hash7, &rbuf[(i*bufsize)+8], 4); + + for (j=0; jextraSolutions; j++) { + memcpy((char*)&nonces[i].goldenNonce[j+1], &rbuf[(i*bufsize)+12+(j*4)], 4); + nonces[i].goldenNonce[j+1] -= ztex->offsNonces; + //applog(LOG_DEBUG, "W %d:%d %0.8x", i, j+1, nonces[i].goldenNonce[j+1]); + } } - + + free(rbuf); return cnt; } diff --git a/libztex.h b/libztex.h index 5f88af99..8a506f6e 100644 --- a/libztex.h +++ b/libztex.h @@ -32,7 +32,7 @@ #define LIBZTEX_MAXMAXERRORRATE 0.05 #define LIBZTEX_ERRORHYSTERESIS 0.1 -#define LIBZTEX_OVERHEATTHRESHOLD 0.5 +#define LIBZTEX_OVERHEATTHRESHOLD 0.4 struct libztex_fpgastate { bool fpgaConfigured; @@ -62,12 +62,19 @@ struct libztex_device { uint8_t freqMaxM; uint8_t freqMDefault; char* bitFileName; + bool suspendSupported; + double hashesPerClock; + uint8_t extraSolutions; double errorCount[256]; double errorWeight[256]; double errorRate[256]; double maxErrorRate[256]; + int numberOfFpgas; + int selectedFpga; + bool parallelConfigSupport; + char repr[64]; }; @@ -77,7 +84,7 @@ struct libztex_dev_list { }; struct libztex_hash_data { - uint32_t goldenNonce; + uint32_t goldenNonce[2]; uint32_t nonce; uint32_t hash7; };