Browse Source

bitfury: Rewrite using async minerloop (currently only setup on metabank driver)

Luke Dashjr 12 years ago
parent
commit
884389b197
3 changed files with 216 additions and 1 deletions
  1. 200 0
      driver-bitfury.c
  2. 14 1
      driver-metabank.c
  3. 2 0
      libbitfury.h

+ 200 - 0
driver-bitfury.c

@@ -75,6 +75,69 @@ static void bitfury_detect(void)
 }
 }
 
 
 
 
+void *bitfury_just_io(struct bitfury_device * const bitfury)
+{
+	struct spi_port * const spi = bitfury->spi;
+	const int chip = bitfury->fasync;
+	
+	spi_clear_buf(spi);
+	spi_emit_break(spi);
+	spi_emit_fasync(spi, chip);
+	spi_emit_data(spi, 0x3000, &bitfury->atrvec[0], 19 * 4);
+	spi_txrx(spi);
+	return spi_getrxbuf(spi) + 4 + chip;
+}
+
+bool bitfury_init_oldbuf(struct cgpu_info * const proc)
+{
+	struct bitfury_device * const bitfury = proc->device_data;
+	uint32_t * const oldbuf = &bitfury->oldbuf[0];
+	uint32_t * const buf = &bitfury->newbuf[0];
+	const uint32_t *inp;
+	int i, differ, tried = 0;
+	
+	inp = bitfury_just_io(bitfury);
+tryagain:
+	if (tried > 3)
+	{
+		applog(LOG_ERR, "%"PRIpreprv": %s: Giving up after %d tries",
+		       proc->proc_repr, __func__, tried);
+		return false;
+	}
+	++tried;
+	memcpy(buf, inp, 0x10 * 4);
+	inp = bitfury_just_io(bitfury);
+	differ = -1;
+	for (i = 0; i < 0x10; ++i)
+	{
+		if (inp[i] != buf[i])
+		{
+			if (differ != -1)
+			{
+				applog(LOG_DEBUG, "%"PRIpreprv": %s: Second differ at %d; trying again",
+				       proc->proc_repr, __func__, i);
+				goto tryagain;
+			}
+			differ = i;
+			applog(LOG_DEBUG, "%"PRIpreprv": %s: Differ at %d",
+			       proc->proc_repr, __func__, i);
+		}
+	}
+	if (-1 == differ)
+	{
+		applog(LOG_DEBUG, "%"PRIpreprv": %s: No differ found; trying again",
+		       proc->proc_repr, __func__);
+		goto tryagain;
+	}
+	
+	bitfury->active = differ;
+	memcpy(&oldbuf[0], &inp[bitfury->active], 4 * (0x10 - bitfury->active));
+	memcpy(&oldbuf[0x10 - bitfury->active], &inp[0], 4 * bitfury->active);
+	bitfury->oldjob = inp[0x10];
+	
+	return true;
+}
+
 static
 static
 bool bitfury_init(struct thr_info *thr)
 bool bitfury_init(struct thr_info *thr)
 {
 {
@@ -88,6 +151,7 @@ bool bitfury_init(struct thr_info *thr)
 			.spi = sys_spi,
 			.spi = sys_spi,
 			.fasync = proc->proc_id,
 			.fasync = proc->proc_id,
 		};
 		};
+		bitfury_init_oldbuf(proc);
 	}
 	}
 	
 	
 	return true;
 	return true;
@@ -316,6 +380,142 @@ void bitfury_shutdown(struct thr_info *thr) {
 	}
 	}
 }
 }
 
 
+bool bitfury_job_prepare(struct thr_info *thr, struct work *work, __maybe_unused uint64_t max_nonce)
+{
+	struct cgpu_info * const proc = thr->cgpu;
+	struct bitfury_device * const bitfury = proc->device_data;
+	
+	if (opt_debug)
+	{
+		char hex[153];
+		bin2hex(hex, &work->data[0], 76);
+		applog(LOG_DEBUG, "%"PRIpreprv": Preparing work %s",
+		       proc->proc_repr, hex);
+	}
+	work_to_payload(&bitfury->payload, work);
+	payload_to_atrvec(bitfury->atrvec, &bitfury->payload);
+	
+	work->blk.nonce = 0xffffffff;
+	return true;
+}
+
+extern unsigned decnonce(unsigned);
+
+static
+bool fudge_nonce(struct work * const work, uint32_t *nonce_p) {
+	static const uint32_t offsets[] = {0, 0xffc00000, 0xff800000, 0x02800000, 0x02C00000, 0x00400000};
+	uint32_t nonce;
+	int i;
+	
+	if (unlikely(!work))
+		return false;
+	
+	for (i = 0; i < 6; ++i)
+	{
+		nonce = *nonce_p + offsets[i];
+		if (test_nonce(work, nonce, false))
+		{
+			*nonce_p = nonce;
+			return true;
+		}
+	}
+	return false;
+}
+
+void bitfury_do_io(struct thr_info *thr)
+{
+	struct cgpu_info * const proc = thr->cgpu;
+	struct bitfury_device * const bitfury = proc->device_data;
+	const uint32_t *inp;
+	uint32_t * const newbuf = &bitfury->newbuf[0];
+	uint32_t * const oldbuf = &bitfury->oldbuf[0];
+	int n, i;
+	bool newjob;
+	uint32_t nonce;
+	
+	inp = bitfury_just_io(bitfury);
+	
+	if (opt_debug)
+	{
+		char hex[137];
+		bin2hex(hex, inp, 17 * 4);
+		applog(LOG_DEBUG, "%"PRIpreprv": Read %s (active=%d)",
+		       proc->proc_repr, hex, bitfury->active);
+	}
+	
+	// To avoid dealing with wrap-around entirely, just rotate array so previous active uint32_t is at index 0
+	memcpy(&newbuf[0], &inp[bitfury->active], 4 * (0x10 - bitfury->active));
+	memcpy(&newbuf[0x10 - bitfury->active], &inp[0], 4 * bitfury->active);
+	newjob = inp[0x10];
+	
+	if (bitfury->oldjob != newjob && thr->next_work)
+	{
+		mt_job_transition(thr);
+		// TODO: Delay morework until right before it's needed
+		timer_set_now(&thr->tv_morework);
+		job_start_complete(thr);
+	}
+	
+	for (n = 1; newbuf[n] != oldbuf[n]; ++n)
+	{
+		if (unlikely(n >= 0xf))
+		{
+			inc_hw_errors2(thr, NULL, NULL);
+			applog(LOG_DEBUG, "%"PRIpreprv": Mismatch of previous 2 nonces, ignoring response",
+			       proc->proc_repr);
+			goto out;
+		}
+	}
+	--n;
+	
+	if (n)
+	{
+		if (opt_debug)
+		{
+			char hex[(4 * 2 * n) + 1];
+			bin2hex(hex, newbuf, 4 * n);
+			applog(LOG_DEBUG, "%"PRIpreprv": Got %d results: %s",
+			       proc->proc_repr, n, hex);
+		}
+		for (i = 0; i < n; ++i)
+		{
+			nonce = decnonce(newbuf[i]);
+			if (fudge_nonce(thr->work, &nonce))
+			{
+				applog(LOG_DEBUG, "%"PRIpreprv": nonce %d = %08lx (work=%p)",
+				       proc->proc_repr, i, (unsigned long)nonce, thr->work);
+				submit_nonce(thr, thr->work, nonce);
+			}
+			else
+			if (fudge_nonce(thr->prev_work, &nonce))
+			{
+				applog(LOG_DEBUG, "%"PRIpreprv": nonce %d = %08lx (prev work=%p)",
+				       proc->proc_repr, i, (unsigned long)nonce, thr->prev_work);
+				submit_nonce(thr, thr->prev_work, nonce);
+			}
+			else
+				inc_hw_errors(thr, thr->work, nonce);
+		}
+		bitfury->active = (bitfury->active + n) % 0x10;
+	}
+	
+	memcpy(&oldbuf[0], &inp[bitfury->active], 4 * (0x10 - bitfury->active));
+	memcpy(&oldbuf[0x10 - bitfury->active], &inp[0], 4 * bitfury->active);
+	bitfury->oldjob = newjob;
+	
+out:
+	timer_set_delay_from_now(&thr->tv_poll, 10000);
+}
+
+int64_t bitfury_job_process_results(struct thr_info *thr, struct work *work, bool stopping)
+{
+	if (unlikely(stopping))
+		timer_unset(&thr->tv_poll);
+	
+	// Bitfury chips process only 768/1024 of the nonce range
+	return 0xbd000000;
+}
+
 struct device_drv bitfury_drv = {
 struct device_drv bitfury_drv = {
 	.dname = "bitfury_gpio",
 	.dname = "bitfury_gpio",
 	.name = "BFY",
 	.name = "BFY",

+ 14 - 1
driver-metabank.c

@@ -162,6 +162,7 @@ bool metabank_init(struct thr_info *thr)
 		bitfury = devicelist[proc->proc_id];
 		bitfury = devicelist[proc->proc_id];
 		proc->device_data = bitfury;
 		proc->device_data = bitfury;
 		bitfury->spi->cgpu = proc;
 		bitfury->spi->cgpu = proc;
+		bitfury_init_oldbuf(proc);
 	}
 	}
 	
 	
 	free(devicelist);
 	free(devicelist);
@@ -178,14 +179,26 @@ static void metabank_shutdown(struct thr_info *thr)
 	tm_i2c_close();
 	tm_i2c_close();
 }
 }
 
 
+extern bool bitfury_job_prepare(struct thr_info *, struct work *, uint64_t max_nonce);
+extern void bitfury_do_io(struct thr_info *);
+extern int64_t bitfury_job_process_results(struct thr_info *, struct work *, bool stopping);
+
 struct device_drv metabank_drv = {
 struct device_drv metabank_drv = {
 	.dname = "metabank",
 	.dname = "metabank",
 	.name = "MBF",
 	.name = "MBF",
 	.drv_detect = metabank_detect,
 	.drv_detect = metabank_detect,
+	.thread_init = metabank_init,
 	
 	
+#if 0
 	.minerloop = hash_queued_work,
 	.minerloop = hash_queued_work,
 	.thread_prepare = bitfury_prepare,
 	.thread_prepare = bitfury_prepare,
-	.thread_init = metabank_init,
 	.scanwork = bitfury_scanHash,
 	.scanwork = bitfury_scanHash,
+#endif
+	.minerloop = minerloop_async,
+	.job_prepare = bitfury_job_prepare,
+	.job_start = bitfury_do_io,
+	.poll = bitfury_do_io,
+	.job_process_results = bitfury_job_process_results,
+	
 	.thread_shutdown = metabank_shutdown,
 	.thread_shutdown = metabank_shutdown,
 };
 };

+ 2 - 0
libbitfury.h

@@ -20,6 +20,8 @@ struct bitfury_device {
 	unsigned char osc6_bits;
 	unsigned char osc6_bits;
 	unsigned newbuf[17];
 	unsigned newbuf[17];
 	unsigned oldbuf[17];
 	unsigned oldbuf[17];
+	bool oldjob;
+	int active;
 	struct work * work;
 	struct work * work;
 	struct work * owork;
 	struct work * owork;
 	struct work * o2work;
 	struct work * o2work;