From 759e82bb9899a1be12300d1d756be15b1cf86a5e Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Wed, 25 Sep 2013 15:30:54 +1000 Subject: [PATCH] Add in first draft for a serialised work model sending/receiving data for BF1 devices. --- cgminer.c | 17 ++++++ driver-bitfury.c | 149 ++++++++++++++++++++++++++++++++++++++++++++--- driver-bitfury.h | 3 + miner.h | 1 + usbutils.c | 2 +- 5 files changed, 163 insertions(+), 9 deletions(-) diff --git a/cgminer.c b/cgminer.c index 29fd52e4..08a9abd6 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 c039e7a1..e4dabf49 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 c427fdc8..5af2dfe5 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 bc10f5e1..14562272 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 9bf0b174..e67cb6c6 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