Browse Source

BF1 driver working

Andreas Auer 12 years ago
parent
commit
8f524bba17
3 changed files with 267 additions and 82 deletions
  1. 1 1
      configure.ac
  2. 261 79
      driver-bf1.c
  3. 5 2
      driver-bf1.h

+ 1 - 1
configure.ac

@@ -302,7 +302,7 @@ AC_ARG_ENABLE([bf1],
 if test "x$bf1" = xyes; then
 if test "x$bf1" = xyes; then
 	AC_DEFINE([USE_BF1], [1], [Defined to 1 if Bitfury BF1 support is wanted])
 	AC_DEFINE([USE_BF1], [1], [Defined to 1 if Bitfury BF1 support is wanted])
 fi
 fi
-AM_CONDITIONAL([HAS_BF1], [test x$bf11 = xyes])
+AM_CONDITIONAL([HAS_BF1], [test x$bf1 = xyes])
 
 
 AC_ARG_ENABLE([bitforce],
 AC_ARG_ENABLE([bitforce],
 	[AC_HELP_STRING([--disable-bitforce],[Compile support for BitForce (default enabled)])],
 	[AC_HELP_STRING([--disable-bitforce],[Compile support for BitForce (default enabled)])],

+ 261 - 79
driver-bf1.c

@@ -25,31 +25,106 @@
 
 
 struct device_drv bf1_drv;
 struct device_drv bf1_drv;
 
 
+struct bitfury_payload
+{
+	unsigned char midstate[32];
+	unsigned int junk[8];
+	unsigned m7;
+	unsigned ntime;
+	unsigned nbits;
+	unsigned nnonce;
+};
+
+static inline void flip80(void *dest_p, const void *src_p)
+{
+	uint32_t *dest = dest_p;
+	const uint32_t *src = src_p;
+	int i;
+
+	for (i = 0; i < 20; i++)
+		dest[i] = swab32(src[i]);
+}
+
+void work_to_payload(struct bitfury_payload *p, struct work *w) {
+	unsigned char flipped_data[80];
+
+	memset(p, 0, sizeof(struct bitfury_payload));
+	flip80(flipped_data, w->data);
+
+	memcpy(p->midstate, w->midstate, 32);
+	p->m7 = bswap_32(*(unsigned *)(flipped_data + 64));
+	p->ntime = bswap_32(*(unsigned *)(flipped_data + 68));
+	p->nbits = bswap_32(*(unsigned *)(flipped_data + 72));
+	applog(LOG_INFO, "INFO nonc: %08x bitfury_scanHash MS0: %08x, ", p->nnonce, ((unsigned int *)p->midstate)[0]);
+	applog(LOG_INFO, "INFO merkle[7]: %08x, ntime: %08x, nbits: %08x", p->m7, p->ntime, p->nbits);
+}
+
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
-static bool bf1_checkNonce(struct cgpu_info *cgpu,
-                            struct work *work,
-                            int nonce)
+uint32_t bf1_decnonce(uint32_t in)
 {
 {
-	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;
+	uint32_t out;
 
 
-	swap32[76/4] = htobe32(nonce);
+	/* First part load */
+	out = (in & 0xFF) << 24; in >>= 8;
 
 
-	swap32yes(swap32, data32, 76 / 4);
+	/* Byte reversal */
+	in = (((in & 0xaaaaaaaa) >> 1) | ((in & 0x55555555) << 1));
+	in = (((in & 0xcccccccc) >> 2) | ((in & 0x33333333) << 2));
+	in = (((in & 0xf0f0f0f0) >> 4) | ((in & 0x0f0f0f0f) << 4));
 
 
-	sha2(swap, 80, hash1);
-	sha2(hash1, 32, hash2);
+	out |= (in >> 2)&0x3FFFFF;
 
 
-	if(hash2_32[7] == 0)
-		return true;
+	/* Extraction */
+	if (in & 1) out |= (1 << 23);
+	if (in & 2) out |= (1 << 22);
 
 
-	return false;
+	out -= 0x800004;
+	return out;
 }
 }
 
 
+//------------------------------------------------------------------------------
+int bf1_rehash(unsigned char *midstate, unsigned m7, unsigned ntime, unsigned nbits, unsigned nnonce)
+{
+	uint8_t   in[16];
+	uint8_t   hash1[32];
+	uint32_t *in32 = (uint32_t *)in;
+	uint8_t  *hex;
+	uint32_t *mid32 = (uint32_t *)midstate;
+	uint32_t  out32[8];
+	uint8_t  *out = (uint8_t *) out32;
+	uint32_t  i;
+	sha2_context ctx;
+
+	memset( &ctx, 0, sizeof(sha2_context));
+	memcpy(ctx.state, mid32, 8*4);
+	ctx.total[0] = 64;
+	ctx.total[1] = 0;
+
+	nnonce = bswap_32(nnonce);
+	in32[0] = bswap_32(m7);
+	in32[1] = bswap_32(ntime);
+	in32[2] = bswap_32(nbits);
+	in32[3] = nnonce;
+
+	sha2_update(&ctx, in, 16);
+	sha2_finish(&ctx, out);
+	sha2(out, 32, out);
+
+	if (out32[7] == 0)
+	{
+		hex = bin2hex(midstate, 32);
+		hex = bin2hex(out, 32);
+		applog(LOG_INFO, "! MS0: %08x, m7: %08x, ntime: %08x, nbits: %08x, nnonce: %08x\n\t\t\t out: %s\n", mid32[0], m7, ntime, nbits, nnonce, hex);
+		return 1;
+	}
+#if 0
+	else
+	{
+		applog(LOG_INFO, "DATA: %08X %08X %08X %08X", m7, ntime, nbits, nnonce);
+	}
+#endif
+	return 0;
+}
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 static bool bf1_detect_custom(const char *devpath, struct device_drv *api, struct BF1Info *info)
 static bool bf1_detect_custom(const char *devpath, struct device_drv *api, struct BF1Info *info)
@@ -77,18 +152,22 @@ static bool bf1_detect_custom(const char *devpath, struct device_drv *api, struc
 	applog(LOG_DEBUG, "%d, %s %08x", info->id.version, info->id.product, info->id.serial);
 	applog(LOG_DEBUG, "%d, %s %08x", info->id.version, info->id.product, info->id.serial);
 
 
 	char buf_state[sizeof(struct BF1State)+1];
 	char buf_state[sizeof(struct BF1State)+1];
+	len = 0;
 	write(fd, "R", 1);
 	write(fd, "R", 1);
-	len = serial_read(fd, buf, sizeof(buf_state));
+
+	while(len == 0)
+	{
+		len = serial_read(fd, buf, sizeof(buf_state));
+		nmsleep(100);
+	}
 	serial_close(fd);
 	serial_close(fd);
 
 
 	if(len != sizeof(buf_state))
 	if(len != sizeof(buf_state))
 	{
 	{
+		applog(LOG_ERR, "Not responding to reset: %d", len);
 		return false;
 		return false;
 	}
 	}
 
 
-	serial_close(fd);
-
-
 	if(serial_claim(devpath, api))
 	if(serial_claim(devpath, api))
 	{
 	{
 		const char *claimedby = serial_claim(devpath, api)->dname;
 		const char *claimedby = serial_claim(devpath, api)->dname;
@@ -122,6 +201,7 @@ static bool bf1_detect_one(const char *devpath)
 	if (unlikely(!info))
 	if (unlikely(!info))
 		quit(1, "Failed to malloc bf1Info");
 		quit(1, "Failed to malloc bf1Info");
 
 
+	applog(LOG_INFO, "Detect Bitfury BF1 device: %s", devpath);
 	info->baud = BF1_BAUD;
 	info->baud = BF1_BAUD;
 
 
 	if (!bf1_detect_custom(devpath, &bf1_drv, info))
 	if (!bf1_detect_custom(devpath, &bf1_drv, info))
@@ -132,11 +212,19 @@ static bool bf1_detect_one(const char *devpath)
 	return true;
 	return true;
 }
 }
 
 
+//------------------------------------------------------------------------------
+static int bf1_detect_auto(void)
+{
+	applog(LOG_INFO, "Autodetect Bitfury BF1 devices");
+	return serial_autodetect(bf1_detect_one, "Bitfury_BF1");
+}
+
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 static void bf1_detect()
 static void bf1_detect()
 {
 {
-	applog(LOG_WARNING, "Searching for Bitfury BF1 devices");
-	serial_detect(&bf1_drv, bf1_detect_one);
+	applog(LOG_INFO, "Searching for Bitfury BF1 devices");
+	//serial_detect(&bf1_drv, bf1_detect_one);
+	serial_detect_auto(&bf1_drv, bf1_detect_one, bf1_detect_auto);
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -155,10 +243,104 @@ static bool bf1_init(struct thr_info *thr)
 	}
 	}
 
 
 	bf1->device_fd = fd;
 	bf1->device_fd = fd;
-	//notifier_init(thr->work_restart_notifier);
 
 
 	applog(LOG_INFO, "Opened Bitfury BF1 on %s", bf1->device_path);
 	applog(LOG_INFO, "Opened Bitfury BF1 on %s", bf1->device_path);
 
 
+	struct timeval tv_now;
+	gettimeofday(&tv_now, NULL);
+	timer_set_delay(&thr->tv_poll, &tv_now, 1000000);
+
+	info->work = 0;
+	info->prev_work = 0;
+
+	return true;
+}
+
+//------------------------------------------------------------------------------
+static void bf1_get_results(struct thr_info *thr, struct work *work)
+{
+	struct cgpu_info *board = thr->cgpu;
+	struct BF1Info *info = (struct BF1Info *)board->device_data;
+
+	info->rx_len = serial_read(board->device_fd, info->rx_buffer, sizeof(info->rx_buffer));
+	applog(LOG_INFO, "Length: %d", info->rx_len);
+
+	job_results_fetched(thr);
+}
+
+//------------------------------------------------------------------------------
+static bool duplicate(uint32_t *results, uint32_t size, uint32_t test_nonce)
+{
+	for(uint32_t i=0; i<size; i++)
+	{
+		if(results[i] == test_nonce)
+		{
+			return true;
+		}
+	}
+
+	return false;
+}
+
+//------------------------------------------------------------------------------
+static void bf1_process_results(struct thr_info *thr, struct work *work)
+{
+	struct cgpu_info *board = thr->cgpu;
+	struct BF1Info *info = (struct BF1Info *)board->device_data;
+
+	uint32_t results[16*6];
+	uint32_t num_results;
+
+	uint32_t m7    = *((uint32_t *)&work->data[64]);
+	uint32_t ntime = *((uint32_t *)&work->data[68]);
+	uint32_t nbits = *((uint32_t *)&work->data[72]);
+
+	num_results = 0;
+	for(int i=0; i<info->rx_len; i+=7)
+	{
+		struct BF1State *state = (struct BF1State *)(info->rx_buffer + i + 1);
+
+		if(duplicate(results, num_results, state->nonce))
+		{
+			continue;
+		}
+
+		uint32_t nonce = bf1_decnonce(state->nonce);
+		results[num_results++] = state->nonce;
+
+		//applog(LOG_INFO, "Len: %d Cmd: %c State: %c Switched: %d Nonce: %08X", info->rx_len, info->rx_buffer[i], state->state, state->switched, nonce);
+		if(bf1_rehash(work->midstate, m7, ntime, nbits, nonce))
+		{
+			submit_nonce(thr, work, nonce);
+		}
+		if(bf1_rehash(work->midstate, m7, ntime, nbits, nonce-0x400000))
+		{
+			submit_nonce(thr, work, nonce-0x400000);
+		}
+		if(bf1_rehash(work->midstate, m7, ntime, nbits, nonce-0x800000))
+		{
+			submit_nonce(thr, work, nonce-0x800000);
+		}
+		if(bf1_rehash(work->midstate, m7, ntime, nbits, nonce+0x2800000))
+		{
+			submit_nonce(thr, work, nonce+0x2800000);
+		}
+		if(bf1_rehash(work->midstate, m7, ntime, nbits, nonce+0x2C00000))
+		{
+			submit_nonce(thr, work, nonce+0x2C00000);
+		}
+		if(bf1_rehash(work->midstate, m7, ntime, nbits, nonce+0x400000))
+		{
+			submit_nonce(thr, work, nonce+0x400000);
+		}
+	}
+}
+
+//------------------------------------------------------------------------------
+static bool bf1_work_prepare(struct thr_info *thr, struct work *work, __maybe_unused uint64_t nonce)
+{
+	work->blk.nonce = 0xFFFFFFFFUL;
+
 	return true;
 	return true;
 }
 }
 
 
@@ -170,82 +352,70 @@ static int64_t bf1_scanwork(struct thr_info *thr)
 
 
 	struct BF1HashData hash_data;
 	struct BF1HashData hash_data;
 	uint32_t hashes = 0;
 	uint32_t hashes = 0;
+	uint32_t count = 0;
 
 
 	if(!info->work)
 	if(!info->work)
 	{
 	{
 		info->work = get_queued(board);
 		info->work = get_queued(board);
 		if(info->work == NULL)
 		if(info->work == NULL)
-		{
 			return 0;
 			return 0;
-		}
 	}
 	}
 
 
 	uint8_t sendbuf[45];
 	uint8_t sendbuf[45];
 	sendbuf[0] = 'W';
 	sendbuf[0] = 'W';
-	memcpy(sendbuf + 1, work->midstate, 32);
-	memcpy(sendbuf + 33, work->data + 64, 12);
+	memcpy(sendbuf + 1, info->work->midstate, 32);
+	memcpy(sendbuf + 33, info->work->data + 64, 12);
 	write(board->device_fd, sendbuf, sizeof(sendbuf));
 	write(board->device_fd, sendbuf, sizeof(sendbuf));
 
 
-	applog(LOG_DEBUG, "%"PRIpreprv": sent hashdata", board->proc_repr);
-
-	char rxbuffer[1024];
-	int len;
-	len = serial_read(board->device_fd, rxbuffer, sizeof(rxbuffer));
-	for(int i=0; i<len; i+=7)
+	applog(LOG_INFO, "Work Task sending");
+	while(1)
 	{
 	{
-		applog(LOG_INFO, "Cmd: %c State: %c Valid: %d Nonce: %08X", rxbuffer[0], rxbuffer[1], rxbuffer[2], *((uint32_t *)&rxbuffer[3]));
-		hashes = 0xFFFFFFFFUL;
+		uint8_t buffer[7];
+		int len;
+		len = serial_read(board->device_fd, buffer, 7);
+		if(len > 0)
+			break;
 	}
 	}
 
 
-	return hashes;
-/*
-
-	bool overflow = false;
-	int count = 0;
-	uint32_t nonce_count = 0;
-
-	uint8_t buffer[128];
-	while (!(overflow || thr->work_restart))
+	applog(LOG_INFO, "Work Task sent");
+	while(1)
 	{
 	{
-		if (!restart_wait(thr, 250))
-		{
-			applog(LOG_DEBUG, "%"PRIpreprv": New work detected", board->proc_repr);
+		info->rx_len = serial_read(board->device_fd, info->rx_buffer, sizeof(info->rx_buffer));
+		if(info->rx_len > 0)
 			break;
 			break;
-		}
-
-		int len = serial_read(board->device_fd, buffer, sizeof(struct bf1State)+1);
-		if(len == (sizeof(struct bf1State)+1))
-		{
-			struct bf1State *state = (struct bf1State *)(buffer+1);
-			applog(LOG_DEBUG, "State: %c, %d, %08x", state->state, state->nonce_valid, state->nonce);
-
-			if(state->nonce_valid == 1)
-			{
-				nonce_count = state->nonce;
-				if(bf1_checkNonce(board, work, state->nonce))
-				{
-					applog(LOG_INFO, "Golden nonce found: %08X", state->nonce);
-					submit_nonce(thr, work, state->nonce);
-				}
-				break;
-			}
-			else if(state->state == 'R')
-			{
-				nonce_count = 0xFFFFFFFFUL;
-				break;
-			}
-		}
+	}
+	applog(LOG_INFO, "Work Task accepted");
 
 
-		if (thr->work_restart)
-		{
-			applog(LOG_DEBUG, "%"PRIpreprv": New work detected", board->proc_repr);
-			break;
-		}
+	if(info->prev_work)
+	{
+		bf1_process_results(thr, info->prev_work);
+		work_completed(board, info->prev_work);
+		info->prev_work = 0;
 	}
 	}
+	info->prev_work = info->work;
+	info->work = 0;
+
+	hashes = 0xffffffff;
+	applog(LOG_INFO, "WORK completed");
+
+	return hashes;
+}
+
+//------------------------------------------------------------------------------
+static void bf1_poll(struct thr_info *thr)
+{
+	struct cgpu_info *board = thr->cgpu;
+	struct BF1Info *info = (struct BF1Info *)board->device_data;
+/*
+	uint8_t rx_buf[128];
+	int len = 0;
+	len = serial_read(board->device_fd, rx_buf, sizeof(rx_buf));
 
 
-	work->blk.nonce = 0xffffffff;
-	return nonce_count;
+	applog(LOG_INFO, "POLL: serial read: %d", len);
 */
 */
+	struct timeval tv_now;
+	gettimeofday(&tv_now, NULL);
+	timer_set_delay(&thr->tv_poll, &tv_now, 1000000);
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -276,9 +446,21 @@ static void bf1_shutdown(struct thr_info *thr)
 struct device_drv bf1_drv = {
 struct device_drv bf1_drv = {
 	.dname = "Bitfury BF1",
 	.dname = "Bitfury BF1",
 	.name = "BF1",
 	.name = "BF1",
+	.minerloop = hash_queued_work,
+
 	.drv_detect = bf1_detect,
 	.drv_detect = bf1_detect,
 	.get_statline_before = bf1_statline_before,
 	.get_statline_before = bf1_statline_before,
-	.scanwork = bf1_scanwork,
+
 	.thread_init = bf1_init,
 	.thread_init = bf1_init,
 	.thread_shutdown = bf1_shutdown,
 	.thread_shutdown = bf1_shutdown,
+/*
+	.job_prepare = bf1_work_prepare,
+	.job_get_results = bf1_get_results,
+	.job_process_results = bf1_process_results,
+	.job_start = bf1_scanwork,
+*/
+
+	.poll = bf1_poll,
+
+	.scanwork = bf1_scanwork,
 };
 };

+ 5 - 2
driver-bf1.h

@@ -20,7 +20,7 @@ struct BF1Identity
 struct BF1State
 struct BF1State
 {
 {
     uint8_t state;
     uint8_t state;
-    uint8_t nonce_valid;
+    uint8_t switched;
     uint32_t nonce;
     uint32_t nonce;
 } __attribute__((packed));
 } __attribute__((packed));
 
 
@@ -35,8 +35,11 @@ struct BF1Info
 	uint32_t baud;
 	uint32_t baud;
 
 
 	struct BF1Identity id;
 	struct BF1Identity id;
-
 	struct work *work;
 	struct work *work;
+	struct work *prev_work;
+
+	char rx_buffer[1024];
+	uint32_t rx_len;
 };
 };
 
 
 #endif /* DRIVER_S6LX75_H_ */
 #endif /* DRIVER_S6LX75_H_ */