Commit 759e82bb9899a1be12300d1d756be15b1cf86a5e

Con Kolivas 2013-09-25T15:30:54

Add in first draft for a serialised work model sending/receiving data for BF1 devices.

diff --git a/cgminer.c b/cgminer.c
index 29fd52e..08a9abd 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -6016,6 +6016,23 @@ void inc_hw_errors(struct thr_info *thr)
 	thr->cgpu->drv->hw_error(thr);
 }
 
+bool test_nonce(struct work *work, uint32_t nonce)
+{
+	uint32_t *work_nonce = (uint32_t *)(work->data + 64 + 12);
+	unsigned char hash2[32];
+	uint32_t *hash2_32 = (uint32_t *)hash2;
+	uint32_t diff1targ;
+
+	*work_nonce = htole32(nonce);
+
+	/* Do one last check before attempting to submit the work */
+	rebuild_hash(work);
+	flip32(hash2_32, work->hash);
+
+	diff1targ = opt_scrypt ? 0x0000ffffUL : 0;
+	return (be32toh(hash2_32[7] <= diff1targ));
+}
+
 /* Returns true if nonce for work was a valid share */
 bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce)
 {
diff --git a/driver-bitfury.c b/driver-bitfury.c
index c039e7a..e4dabf4 100644
--- a/driver-bitfury.c
+++ b/driver-bitfury.c
@@ -11,6 +11,7 @@
 
 #include "miner.h"
 #include "driver-bitfury.h"
+#include "sha2.h"
 
 struct device_drv bitfury_drv;
 
@@ -100,7 +101,13 @@ static bool bitfury_detect_one(struct libusb_device *dev, struct usb_find_device
 
 	bitfury_identify(bitfury);
 	bitfury_empty_buffer(bitfury);
-	//return true;
+
+	if (!add_cgpu(bitfury))
+		goto out_close;
+	update_usb_stats(bitfury);
+	applog(LOG_INFO, "%s%d: Found at %s",
+	       bitfury->drv->name, bitfury->device_id, bitfury->device_path);
+	return true;
 out_close:
 	bitfury_close(bitfury);
 out:
@@ -114,7 +121,7 @@ static void bitfury_detect(void)
 
 static bool bitfury_prepare(struct thr_info __maybe_unused *thr)
 {
-	return false;
+	return true;
 }
 
 static bool bitfury_fill(struct cgpu_info __maybe_unused *bitfury)
@@ -122,9 +129,137 @@ static bool bitfury_fill(struct cgpu_info __maybe_unused *bitfury)
 	return true;
 }
 
-static int64_t bitfury_scanhash(struct thr_info __maybe_unused *thr)
+static bool rehash(unsigned char *midstate, unsigned m7, unsigned ntime, unsigned nbits, unsigned nnonce)
+{
+	uint8_t   in[16];
+	uint32_t *in32 = (uint32_t *)in;
+	uint32_t *mid32 = (uint32_t *)midstate;
+	uint32_t  out32[8];
+	uint8_t  *out = (uint8_t *) out32;
+	sha256_ctx ctx;
+
+	memset( &ctx, 0, sizeof(sha256_ctx));
+	memcpy(ctx.h, mid32, 8*4);
+	ctx.tot_len = 64;
+
+	nnonce = bswap_32(nnonce);
+	in32[0] = bswap_32(m7);
+	in32[1] = bswap_32(ntime);
+	in32[2] = bswap_32(nbits);
+	in32[3] = nnonce;
+
+	sha256_update(&ctx, in, 16);
+	sha256_final(&ctx, out);
+	sha256(out, 32, out);
+
+	if (out32[7] == 0)
+		return true;
+	return false;
+}
+
+static uint32_t decnonce(uint32_t in)
+{
+	uint32_t out;
+
+	/* First part load */
+	out = (in & 0xFF) << 24; in >>= 8;
+
+	/* Byte reversal */
+	in = (((in & 0xaaaaaaaa) >> 1) | ((in & 0x55555555) << 1));
+	in = (((in & 0xcccccccc) >> 2) | ((in & 0x33333333) << 2));
+	in = (((in & 0xf0f0f0f0) >> 4) | ((in & 0x0f0f0f0f) << 4));
+
+	out |= (in >> 2)&0x3FFFFF;
+
+	/* Extraction */
+	if (in & 1) out |= (1 << 23);
+	if (in & 2) out |= (1 << 22);
+
+	out -= 0x800004;
+	return out;
+}
+
+static bool bitfury_checkresults(struct thr_info *thr, struct work *work, uint32_t nonce)
+{
+	uint32_t nonceoff;
+
+	if (test_nonce(work, nonce)) {
+		submit_nonce(thr, work, nonce);
+		return true;
+	}
+	nonceoff = nonce - 0x400000;
+	if (test_nonce(work, nonceoff)) {
+		submit_nonce(thr, work, nonceoff);
+		return true;
+	}
+	nonceoff = nonce - 0x800000;
+	if (test_nonce(work, nonceoff)) {
+		submit_nonce(thr, work, nonceoff);
+		return true;
+	}
+	nonceoff = nonce + 0x2800000;
+	if (test_nonce(work, nonceoff)) {
+		submit_nonce(thr, work, nonceoff);
+		return true;
+	}
+	nonceoff = nonce + 0x2C800000;
+	if (test_nonce(work, nonceoff)) {
+		submit_nonce(thr, work, nonceoff);
+		return true;
+	}
+	nonceoff = nonce + 0x400000;
+	if (test_nonce(work, nonceoff)) {
+		submit_nonce(thr, work, nonceoff);
+		return true;
+	}
+	return false;
+}
+
+static int64_t bitfury_scanhash(struct thr_info *thr, struct work *work,
+				int64_t __maybe_unused max_nonce)
 {
-	return 0;
+	struct cgpu_info *bitfury = thr->cgpu;
+	struct bitfury_info *info = bitfury->device_data;
+	char sendbuf[45], buf[512];
+	int64_t hashes = 0;
+	int amount, i, tot;
+
+	sendbuf[0] = 'W';
+	memcpy(sendbuf + 1, work->midstate, 32);
+	memcpy(sendbuf + 33, work->data + 64, 12);
+	usb_write(bitfury, sendbuf, 45, &amount, C_PING);
+	usb_read(bitfury, buf, 7, &amount, C_PING);
+
+	if (unlikely(!info->prevwork)) {
+		info->prevwork = copy_work(work);
+		return 0;
+	}
+
+	usb_read_once_timeout(bitfury, buf, 7, &amount, 2000, C_PING);
+	tot = amount;
+	while (amount) {
+		usb_read_once_timeout(bitfury, buf + tot, 512, &amount, 10, C_PING);
+		tot += amount;
+	}
+
+	for (i = 0; i < tot; i += 7) {
+		uint32_t nonce;
+
+		/* Ignore state & switched data in results for now. */
+		memcpy(&nonce, buf + i + 3, 4);
+		nonce = decnonce(nonce);
+		if (bitfury_checkresults(thr, work, nonce)) {
+			hashes += 0xffffffff;
+			continue;
+		}
+		if (bitfury_checkresults(thr, info->prevwork, nonce))
+			hashes += 0xffffffff;
+	}
+
+	free_work(info->prevwork);
+	info->prevwork = copy_work(work);
+	work->blk.nonce = 0xffffffff;
+	return hashes;
 }
 
 static void bitfury_flush_work(struct cgpu_info __maybe_unused *bitfury)
@@ -158,12 +293,10 @@ struct device_drv bitfury_drv = {
 	.dname = "bitfury",
 	.name = "BFO",
 	.drv_detect = bitfury_detect,
-	.thread_prepare = bitfury_prepare,
-	.hash_work = hash_queued_work,
-	.queue_full = bitfury_fill,
-	.scanwork = bitfury_scanhash,
+	.scanhash = bitfury_scanhash,
 	.flush_work = bitfury_flush_work,
 	.get_api_stats = bitfury_api_stats,
+	.thread_prepare = bitfury_prepare,
 	.get_statline_before = get_bitfury_statline_before,
 	.reinit_device = bitfury_init,
 	.thread_shutdown = bitfury_shutdown,
diff --git a/driver-bitfury.h b/driver-bitfury.h
index c427fdc..5af2dfe 100644
--- a/driver-bitfury.h
+++ b/driver-bitfury.h
@@ -10,12 +10,15 @@
 #ifndef BITFURY_H
 #define BITFURY_H
 
+#include "miner.h"
 #include "usbutils.h"
 
 struct bitfury_info {
 	uint8_t version;
 	char product[8];
 	uint32_t serial;
+	struct work *prevwork;
+	char readbuf[512];
 };
 
 #endif /* BITFURY_H */
diff --git a/miner.h b/miner.h
index bc10f5e..1456227 100644
--- a/miner.h
+++ b/miner.h
@@ -1356,6 +1356,7 @@ struct modminer_fpga_state {
 
 extern void get_datestamp(char *, size_t, struct timeval *);
 extern void inc_hw_errors(struct thr_info *thr);
+extern bool test_nonce(struct work *work, uint32_t nonce);
 extern bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce);
 extern struct work *get_queued(struct cgpu_info *cgpu);
 extern struct work *__find_work_bymidstate(struct work *que, char *midstate, size_t midstatelen, char *data, int offset, size_t datalen);
diff --git a/usbutils.c b/usbutils.c
index 9bf0b17..e67cb6c 100644
--- a/usbutils.c
+++ b/usbutils.c
@@ -84,7 +84,7 @@
 #else
 #define BFLSC_TIMEOUT_MS 300
 #define BITFORCE_TIMEOUT_MS 200
-#define BITFURY_TIMEOUT_MS 200
+#define BITFURY_TIMEOUT_MS 100
 #define MODMINER_TIMEOUT_MS 100
 #define AVALON_TIMEOUT_MS 200
 #define ICARUS_TIMEOUT_MS 200