Browse Source

Merge pull request #178 from nelisky/ztex-120417

Firmware 15d4 support
Con Kolivas 13 years ago
parent
commit
ab764da472
5 changed files with 181 additions and 59 deletions
  1. BIN
      bitstreams/ztex_ufm1_15d4.bit
  2. BIN
      bitstreams/ztex_ufm1_15y1.bit
  3. 58 28
      driver-ztex.c
  4. 114 29
      libztex.c
  5. 9 2
      libztex.h

BIN
bitstreams/ztex_ufm1_15d4.bit


BIN
bitstreams/ztex_ufm1_15y1.bit


+ 58 - 28
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);
 		libztex_setFreq(ztex, bestM);
+	}
 
 
 	maxM = ztex->freqMDefault;
 	maxM = ztex->freqMDefault;
 	while (maxM < ztex->freqMaxM && ztex->errorWeight[maxM + 1] > 100)
 	while (maxM < ztex->freqMaxM && ztex->errorWeight[maxM + 1] > 100)
 		maxM++;
 		maxM++;
 	if ((bestM < (1.0 - LIBZTEX_OVERHEATTHRESHOLD) * maxM) && bestM < maxM - 1) {
 	if ((bestM < (1.0 - LIBZTEX_OVERHEATTHRESHOLD) * maxM) && bestM < maxM - 1) {
+		libztex_selectFpga(ztex, 0);
 		libztex_resetFpga(ztex);
 		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.",
 		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);
 		       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;
 	struct libztex_device *ztex;
 	unsigned char sendbuf[44];
 	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;
 	bool overflow, found, rv;
 	struct libztex_hash_data hdata[GOLDEN_BACKLOG];
 	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, work->data + 64, 12);
 	memcpy(sendbuf + 12, work->midstate, 32);
 	memcpy(sendbuf + 12, work->midstate, 32);
-	memset(backlog, 0, sizeof(backlog));
+	
+	libztex_selectFpga(ztex, 0);
 	i = libztex_sendHashData(ztex, sendbuf);
 	i = libztex_sendHashData(ztex, sendbuf);
 	if (i < 0) {
 	if (i < 0) {
 		// Something wrong happened in send
 		// 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;
 	overflow = false;
 
 
+	applog(LOG_DEBUG, "%s: entering poll loop", ztex->repr);
 	while (!(overflow || work_restart[thr->id].restart)) {
 	while (!(overflow || work_restart[thr->id].restart)) {
 		usleep(250000);
 		usleep(250000);
 		if (work_restart[thr->id].restart) {
 		if (work_restart[thr->id].restart) {
 			applog(LOG_DEBUG, "%s: New work detected", ztex->repr);
 			applog(LOG_DEBUG, "%s: New work detected", ztex->repr);
 			break;
 			break;
 		}
 		}
+		libztex_selectFpga(ztex, 0);
 		i = libztex_readHashData(ztex, &hdata[0]);
 		i = libztex_readHashData(ztex, &hdata[0]);
 		if (i < 0) {
 		if (i < 0) {
 			// Something wrong happened in read
 			// 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
 				// And there's nothing we can do about it
 				ztex_disable(thr);
 				ztex_disable(thr);
 				applog(LOG_ERR, "%s: Failed to read hash data with err %d, giving up", ztex->repr, i);
 				applog(LOG_ERR, "%s: Failed to read hash data with err %d, giving up", ztex->repr, i);
+				free(lastnonce);
+				free(backlog);
 				return 0;
 				return 0;
 			}
 			}
 		}
 		}
@@ -227,26 +248,28 @@ static uint64_t ztex_scanhash(struct thr_info *thr, struct work *work,
 				thr->cgpu->hw_errors++;
 				thr->cgpu->hw_errors++;
 				continue;
 				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)
 #if defined(__BIGENDIAN__) || defined(MIPSEB)
-					nonce = swab32(nonce);
+						nonce = swab32(nonce);
 #endif
 #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])
 	if (ztex->errorRate[ztex->freqM] > ztex->maxErrorRate[ztex->freqM])
 		ztex->maxErrorRate[ztex->freqM] = ztex->errorRate[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!
 		// Something really serious happened, so mark this thread as dead!
+		free(lastnonce);
+		free(backlog);
+		
 		return 0;
 		return 0;
+	}
 
 
 	applog(LOG_DEBUG, "%s: exit %1.8X", ztex->repr, noncecnt);
 	applog(LOG_DEBUG, "%s: exit %1.8X", ztex->repr, noncecnt);
 
 
 	work->blk.nonce = 0xffffffff;
 	work->blk.nonce = 0xffffffff;
 
 
+	free(lastnonce);
+	free(backlog);
+	
 	return noncecnt > 0? noncecnt: 1;
 	return noncecnt > 0? noncecnt: 1;
 }
 }
 
 

+ 114 - 29
libztex.c

@@ -41,7 +41,8 @@
 #define CAPABILITY_HS_FPGA 0,5
 #define CAPABILITY_HS_FPGA 0,5
 //* Capability index for AVR XMEGA support.
 //* Capability index for AVR XMEGA support.
 #define CAPABILITY_MAC_EEPROM 0,6
 #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)
 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) &&
 	if (!((i >= 0) && (i <= 5) && (j >= 0) && (j < 8) &&
 	     (((ztex->interfaceCapabilities[i] & 255) & (1 << j)) != 0))) {
 	     (((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 false;
 	}
 	}
 	return true;
 	return true;
@@ -223,9 +224,48 @@ int libztex_configureFpga(struct libztex_device *ztex)
 	return libztex_configureFpgaLS(ztex, buf, true, 2);
 	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;
 	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)
 	if (freq > ztex->freqMaxM)
 		freq = ztex->freqMaxM;
 		freq = ztex->freqMaxM;
@@ -236,7 +276,8 @@ int libztex_setFreq(struct libztex_device *ztex, uint16_t freq)
 		return cnt;
 		return cnt;
 	}
 	}
 	ztex->freqM = freq;
 	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;
 	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);
 	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;
 	struct libztex_device *newdev;
+	int i, cnt, err;
 	unsigned char buf[64];
 	unsigned char buf[64];
-	int cnt, err;
 
 
 	newdev = malloc(sizeof(struct libztex_device));
 	newdev = malloc(sizeof(struct libztex_device));
 	newdev->bitFileName = NULL;
 	newdev->bitFileName = NULL;
+	newdev->numberOfFpgas = -1;
 	newdev->valid = false;
 	newdev->valid = false;
 	newdev->hndl = NULL;
 	newdev->hndl = NULL;
 	*ztex = newdev;
 	*ztex = newdev;
@@ -266,7 +315,7 @@ int libztex_prepare_device(struct libusb_device *dev, struct libztex_device** zt
 
 
 	// Check vendorId and productId
 	// Check vendorId and productId
 	if (!(newdev->descriptor.idVendor == LIBZTEX_IDVENDOR &&
 	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);
 		applog(LOG_ERR, "Not a ztex device? %0.4X, %0.4X", newdev->descriptor.idVendor, newdev->descriptor.idProduct);
 		return 1;
 		return 1;
 	}
 	}
@@ -290,7 +339,7 @@ int libztex_prepare_device(struct libusb_device *dev, struct libztex_device** zt
 		return cnt;
 		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");
 		applog(LOG_ERR, "Ztex check device: Error reading ztex descriptor");
 		return 2;
 		return 2;
 	}
 	}
@@ -327,20 +376,46 @@ int libztex_prepare_device(struct libusb_device *dev, struct libztex_device** zt
 		return cnt;
 		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]);
 			applog(LOG_ERR, "Invalid BTCMiner descriptor version. Firmware must be updated (%d).", buf[0]);
 			return 3;
 			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->numNonces = buf[1] + 1;
 	newdev->offsNonces = ((buf[2] & 255) | ((buf[3] & 255) << 8)) - 10000;
 	newdev->offsNonces = ((buf[2] & 255) | ((buf[3] & 255) << 8)) - 10000;
 	newdev->freqM1 = ((buf[4] & 255) | ((buf[5] & 255) << 8) ) * 0.01;
 	newdev->freqM1 = ((buf[4] & 255) | ((buf[5] & 255) << 8) ) * 0.01;
 	newdev->freqMaxM = (buf[7] & 255);
 	newdev->freqMaxM = (buf[7] & 255);
 	newdev->freqM = (buf[6] & 255);
 	newdev->freqM = (buf[6] & 255);
 	newdev->freqMDefault = newdev->freqM;
 	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++) {
 	for (cnt=0; cnt < 255; cnt++) {
 		newdev->errorCount[cnt] = 0;
 		newdev->errorCount[cnt] = 0;
@@ -349,10 +424,6 @@ int libztex_prepare_device(struct libusb_device *dev, struct libztex_device** zt
 		newdev->maxErrorRate[cnt] = 0;
 		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->usbbus = libusb_get_bus_number(dev);
 	newdev->usbaddress = libusb_get_device_address(dev);
 	newdev->usbaddress = libusb_get_device_address(dev);
 	sprintf(newdev->repr, "ZTEX %.3d:%.3d-%s", newdev->usbbus, newdev->usbaddress, newdev->snString);
 	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;
 	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)
 	if (ztex->hndl == NULL)
 		return 0;
 		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)) {
 	if (unlikely(cnt < 0)) {
 		applog(LOG_ERR, "%s: Failed readHashData with err %d", ztex->repr, cnt);
 		applog(LOG_ERR, "%s: Failed readHashData with err %d", ztex->repr, cnt);
+		free(rbuf);
 		return cnt;
 		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; i<ztex->numNonces; 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;
 		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; j<ztex->extraSolutions; 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;
 	return cnt;
 }
 }
 
 

+ 9 - 2
libztex.h

@@ -32,7 +32,7 @@
 
 
 #define LIBZTEX_MAXMAXERRORRATE 0.05
 #define LIBZTEX_MAXMAXERRORRATE 0.05
 #define LIBZTEX_ERRORHYSTERESIS 0.1
 #define LIBZTEX_ERRORHYSTERESIS 0.1
-#define LIBZTEX_OVERHEATTHRESHOLD 0.5
+#define LIBZTEX_OVERHEATTHRESHOLD 0.4
 
 
 struct libztex_fpgastate {
 struct libztex_fpgastate {
 	bool fpgaConfigured;
 	bool fpgaConfigured;
@@ -62,12 +62,19 @@ struct libztex_device {
 	uint8_t freqMaxM;
 	uint8_t freqMaxM;
 	uint8_t freqMDefault;
 	uint8_t freqMDefault;
 	char* bitFileName;
 	char* bitFileName;
+	bool suspendSupported;
+	double hashesPerClock;
+	uint8_t extraSolutions;
 
 
 	double errorCount[256];
 	double errorCount[256];
 	double errorWeight[256];
 	double errorWeight[256];
 	double errorRate[256];
 	double errorRate[256];
 	double maxErrorRate[256];
 	double maxErrorRate[256];
 
 
+	int numberOfFpgas;
+	int selectedFpga;
+	bool parallelConfigSupport;
+	
 	char repr[64];
 	char repr[64];
 };
 };
 
 
@@ -77,7 +84,7 @@ struct libztex_dev_list {
 };
 };
 
 
 struct libztex_hash_data {
 struct libztex_hash_data {
-	uint32_t goldenNonce;
+	uint32_t goldenNonce[2];
 	uint32_t nonce;
 	uint32_t nonce;
 	uint32_t hash7;
 	uint32_t hash7;
 };
 };