Browse Source

bfx: New driver for BFx2 Bitfury USB stick miners

Luke Dashjr 11 years ago
parent
commit
39bbb62d19
4 changed files with 357 additions and 0 deletions
  1. 4 0
      Makefile.am
  2. 1 0
      README
  3. 33 0
      configure.ac
  4. 319 0
      driver-bfx.c

+ 4 - 0
Makefile.am

@@ -273,6 +273,10 @@ if HAS_BFSB
 bfgminer_SOURCES += driver-bfsb.c
 bfgminer_SOURCES += driver-bfsb.c
 endif
 endif
 
 
+if USE_BFX
+bfgminer_SOURCES += driver-bfx.c
+endif
+
 if HAS_METABANK
 if HAS_METABANK
 bfgminer_SOURCES += driver-metabank.c tm_i2c.h tm_i2c.c
 bfgminer_SOURCES += driver-metabank.c tm_i2c.h tm_i2c.c
 endif
 endif

+ 1 - 0
README

@@ -145,6 +145,7 @@ BFGMiner specific configuration options:
 	--enable-bfsb           Compile support for BFSB (default disabled)
 	--enable-bfsb           Compile support for BFSB (default disabled)
 	--disable-bigpic        Compile support for Big Picture Mining USB (default
 	--disable-bigpic        Compile support for Big Picture Mining USB (default
 	                        enabled)
 	                        enabled)
+	--disable-bfx           Compile support for BFx2 (default if libusb)
 	--disable-littlefury    Compile support for LittleFury (default enabled)
 	--disable-littlefury    Compile support for LittleFury (default enabled)
 	--disable-nanofury      Compile support for NanoFury (default enabled)
 	--disable-nanofury      Compile support for NanoFury (default enabled)
 	--disable-hashbuster    Compile support for HashBuster Nano (default
 	--disable-hashbuster    Compile support for HashBuster Nano (default

+ 33 - 0
configure.ac

@@ -765,6 +765,39 @@ fi
 AM_CONDITIONAL([HAS_BIGPIC], [test x$bigpic = xyes])
 AM_CONDITIONAL([HAS_BIGPIC], [test x$bigpic = xyes])
 
 
 
 
+driverlist="$driverlist bfx"
+AC_ARG_ENABLE([bfx],
+	[AC_HELP_STRING([--disable-bfx],[Compile support for BFx2 (default if libusb)])],
+	[bfx=$enableval],
+	[bfx=$ddauto]
+	)
+if test "x$bfx" = "xno"; then
+	true
+elif test "x$bitfury$libusb" = "xyesyes"; then
+	bfx=yes
+elif test "x$bfx" = "xyes"; then
+	if test "x$want_libusb" = "xno"; then
+		AC_MSG_ERROR([You disabled libusb, required for BFx2 support])
+	elif test "x$libusb" = "xno"; then
+		AC_MSG_ERROR([Could not find libusb, required for BFx2 support])
+	else
+		AC_MSG_ERROR([You explicitly disabled Bitfury and explicitly enabled BFx2])
+	fi
+elif test "x$bfx" = "xauto"; then
+	bfx="$libusb"
+	if test "x$libusb" = xno; then
+		AC_MSG_WARN([Could not find libusb, required for BFx2 support])
+		bfx_enableaction="install libusb 1.0+"
+	fi
+fi
+if test "x$bfx" = xyes; then
+	AC_DEFINE([USE_BFX], [1], [Defined to 1 if BFx2 support is wanted])
+	need_lowl_ftdi=yes
+	has_asic=yes
+fi
+AM_CONDITIONAL([USE_BFX], [test x$bfx = xyes])
+
+
 driverlist="$driverlist drillbit"
 driverlist="$driverlist drillbit"
 AC_ARG_ENABLE([drillbit],
 AC_ARG_ENABLE([drillbit],
 	[AC_HELP_STRING([--disable-drillbit],[Compile support for DrillBit (default enabled)])],
 	[AC_HELP_STRING([--disable-drillbit],[Compile support for DrillBit (default enabled)])],

+ 319 - 0
driver-bfx.c

@@ -0,0 +1,319 @@
+/*
+ * Copyright 2013-2014 Luke Dashjr
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at your option)
+ * any later version.  See COPYING for more details.
+ */
+
+#include "config.h"
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "deviceapi.h"
+#include "driver-bitfury.h"
+#include "libbitfury.h"
+#include "logging.h"
+#include "lowlevel.h"
+#include "ft232r.h"
+#include "miner.h"
+#include "util.h"
+
+#define BFX_ADBUS_DIRECTIONS  0xfb
+#define BFX_ACBUS_DIRECTIONS  0xff
+
+BFG_REGISTER_DRIVER(bfx_drv)
+static const struct bfg_set_device_definition bfx_set_device_funcs[];
+
+struct bfx_state {
+	struct lowlevel_device_info *lowl_info;
+	struct ft232r_device_handle *ftdi;
+};
+
+static
+struct ft232r_device_handle *bfx_open(const struct lowlevel_device_info * const info)
+{
+	struct ft232r_device_handle * const ftdi = ft232h_open_mpsse(info);
+	if (!ftdi)
+		applogr(NULL, LOG_ERR, "%s: Failed to open", __func__);
+	if (!ft232h_mpsse_set_adbus(ftdi, 8, BFX_ADBUS_DIRECTIONS))
+	{
+		applog(LOG_ERR, "%s: Failed to set A%cBUS pins", __func__, 'D');
+		goto err;
+	}
+	if (!ft232h_mpsse_set_acbus(ftdi, 0, BFX_ACBUS_DIRECTIONS))
+	{
+		applog(LOG_ERR, "%s: Failed to set A%cBUS pins", __func__, 'C');
+		goto err;
+	}
+	if (!ft232r_purge_buffers(ftdi, FTDI_PURGE_BOTH))
+		applog(LOG_WARNING, "%s: Failed to purge buffers", __func__);
+	
+	return ftdi;
+
+err:
+	ft232h_mpsse_set_adbus(ftdi, 0, 0);
+	ft232h_mpsse_set_acbus(ftdi, 0, 0);
+	ft232r_close(ftdi);
+	return NULL;
+}
+
+static
+void bfx_device_off(struct ft232r_device_handle * const ftdi)
+{
+	// Try to reset everything back to input
+	ft232h_mpsse_set_adbus(ftdi, 0, 0);
+	ft232h_mpsse_set_acbus(ftdi, 0, 0);
+}
+
+static
+bool bfx_set_cs(struct ft232r_device_handle * const ftdi, bool high)
+{
+	const uint8_t val = high ? 8 : 0;
+	return ft232h_mpsse_set_adbus(ftdi, val, BFX_ADBUS_DIRECTIONS);
+}
+
+static
+bool bfx_spi_reset(struct ft232r_device_handle * const ftdi)
+{
+	uint8_t buf[0x10] = { 0xff };
+	for (int i = 1; i < sizeof(buf); ++i)
+		buf[i] = ~buf[i - 1];
+	
+	bfx_set_cs(ftdi, true);
+	ft232r_write_all(ftdi, buf, sizeof(buf));
+	bfx_set_cs(ftdi, false);
+	ft232r_purge_buffers(ftdi, FTDI_PURGE_BOTH);
+	
+	return true;
+}
+
+static
+bool bfx_spi_txrx(struct spi_port * const port)
+{
+	struct cgpu_info * const cgpu = port->cgpu;
+	struct bfx_state * const state = port->userp;
+	struct ft232r_device_handle * const ftdi = state->ftdi;
+	const void *wrbuf = spi_gettxbuf(port);
+	void *rdbuf = spi_getrxbuf(port);
+	size_t bufsz = spi_getbufsz(port);
+	
+	bfx_spi_reset(ftdi);
+	if (ft232h_mpsse_readwrite_all(ftdi, rdbuf, wrbuf, bufsz) != bufsz)
+		goto err;
+	
+	return true;
+
+err:
+	bfx_device_off(ftdi);
+	if (cgpu)
+	{
+		struct thr_info * const thr = cgpu->thr[0];
+		hashes_done2(thr, -1, NULL);
+	}
+	return false;
+}
+
+static
+bool bfx_lowl_probe(const struct lowlevel_device_info * const info)
+{
+	const char * const product = info->product;
+	const char * const serial = info->serial;
+	struct ft232r_device_handle *ftdi;
+	struct spi_port *port;
+	struct bfx_state *state;
+	int chips;
+	
+	if (info->lowl != &lowl_ft232r)
+	{
+		if (info->lowl != &lowl_usb)
+			applog(LOG_DEBUG, "%s: Matched \"%s\" serial \"%s\", but lowlevel driver is not ft232r!",
+			       __func__, product, serial);
+		return false;
+	}
+	
+	ftdi = bfx_open(info);
+	if (!ftdi)
+		return false;
+	
+	state = malloc(sizeof(*state));
+	*state = (struct bfx_state){
+		.ftdi = ftdi,
+	};
+	port = calloc(1, sizeof(*port));
+	port->userp = state;
+	port->txrx = bfx_spi_txrx;
+	port->repr = bfx_drv.dname;
+	port->logprio = LOG_DEBUG;
+	
+	{
+		struct bitfury_device dummy_bitfury = {
+			.spi = port,
+		};
+		drv_set_defaults(&bfx_drv, bitfury_set_device_funcs_probe, &dummy_bitfury, NULL, NULL, 1);
+	}
+	
+	chips = libbitfury_detectChips1(port);
+	free(port);
+	
+	bfx_device_off(ftdi);
+	ft232r_close(ftdi);
+	
+	if (!chips)
+	{
+		free(state);
+		applog(LOG_DEBUG, "%s: 0 chips detected", __func__);
+		return false;
+	}
+	
+	if (lowlevel_claim(&bfx_drv, true, info))
+	{
+		free(state);
+		return false;
+	}
+	
+	state->lowl_info = lowlevel_ref(info);
+	
+	struct cgpu_info *cgpu;
+	cgpu = malloc(sizeof(*cgpu));
+	*cgpu = (struct cgpu_info){
+		.drv = &bfx_drv,
+		.set_device_funcs = bfx_set_device_funcs,
+		.device_data = state,
+		.threads = 1,
+		.procs = chips,
+		// TODO: .name
+		.dev_manufacturer = maybe_strdup(info->manufacturer),
+		.dev_product = maybe_strdup(product),
+		.dev_serial = maybe_strdup(serial),
+		.deven = DEV_ENABLED,
+		// TODO: .cutofftemp
+	};
+
+	return add_cgpu(cgpu);
+}
+
+static
+bool bfx_init(struct thr_info * const thr)
+{
+	struct cgpu_info * const cgpu = thr->cgpu, *proc;
+	struct bfx_state * const state = cgpu->device_data;
+	struct lowlevel_device_info * const info = state->lowl_info;
+	struct spi_port *port;
+	struct bitfury_device *bitfury;
+	struct ft232r_device_handle *ftdi;
+	
+	ftdi = bfx_open(info);
+	lowlevel_devinfo_free(info);
+	if (!ftdi)
+	{
+		applog(LOG_ERR, "%"PRIpreprv": Failed to open ft232r device", cgpu->proc_repr);
+		return false;
+	}
+	
+	port = malloc(sizeof(*port));
+	bitfury = malloc(sizeof(*bitfury) * cgpu->procs);
+	
+	if (!(port && bitfury && state))
+	{
+		applog(LOG_ERR, "%"PRIpreprv": Failed to allocate structures", cgpu->proc_repr);
+		free(port);
+		free(bitfury);
+		free(state);
+		ft232r_close(ftdi);
+		return false;
+	}
+	
+	/* Be careful, read spidevc.h comments for warnings */
+	memset(port, 0, sizeof(*port));
+	port->txrx = bfx_spi_txrx;
+	port->cgpu = cgpu;
+	port->repr = cgpu->proc_repr;
+	port->logprio = LOG_ERR;
+	
+	state->ftdi = ftdi;
+	port->userp = state;
+	for (proc = cgpu; proc; (proc = proc->next_proc), ++bitfury)
+	{
+		struct thr_info * const mythr = proc->thr[0];
+		*bitfury = (struct bitfury_device){
+			.spi = port,
+			.fasync = proc->proc_id,
+		};
+		proc->device_data = bitfury;
+		mythr->cgpu_data = state;
+		bitfury->osc6_bits = 50;
+		bitfury_send_reinit(bitfury->spi, bitfury->slot, bitfury->fasync, bitfury->osc6_bits);
+		bitfury_init_chip(proc);
+		proc->status = LIFE_INIT2;
+	}
+	
+	timer_set_now(&thr->tv_poll);
+	return true;
+}
+
+static
+void bfx_disable(struct thr_info * const thr)
+{
+	struct bfx_state * const state = thr->cgpu_data;
+	struct ft232r_device_handle * const ftdi = state->ftdi;
+	
+	bitfury_disable(thr);
+	bfx_device_off(ftdi);
+}
+
+static
+void bfx_reinit(struct cgpu_info * const cgpu)
+{
+	struct thr_info * const thr = cgpu->thr[0];
+	struct bfx_state * const state = thr->cgpu_data;
+	struct ft232r_device_handle * const ftdi = state->ftdi;
+	
+	bfx_device_off(ftdi);
+	cgsleep_ms(1);
+	bitfury_enable(thr);
+}
+
+static
+void bfx_shutdown(struct thr_info * const thr)
+{
+	struct bfx_state * const state = thr->cgpu_data;
+	struct ft232r_device_handle * const ftdi = state->ftdi;
+	
+	if (ftdi)
+		bfx_device_off(ftdi);
+}
+
+static const struct bfg_set_device_definition bfx_set_device_funcs[] = {
+	{"osc6_bits", bitfury_set_osc6_bits, "range 1-"BITFURY_MAX_OSC6_BITS_S" (slow to fast)"},
+	{NULL},
+};
+
+struct device_drv bfx_drv = {
+	.dname = "bfx",
+	.name = "BFX",
+	.lowl_probe = bfx_lowl_probe,
+	
+	.thread_init = bfx_init,
+	.thread_disable = bfx_disable,
+	.thread_enable = bitfury_enable,
+	.reinit_device = bfx_reinit,
+	.thread_shutdown = bfx_shutdown,
+	
+	.minerloop = minerloop_async,
+	.job_prepare = bitfury_job_prepare,
+	.job_start = bitfury_noop_job_start,
+	.poll = bitfury_do_io,
+	.job_process_results = bitfury_job_process_results,
+	
+	.get_api_extra_device_detail = bitfury_api_device_detail,
+	.get_api_extra_device_status = bitfury_api_device_status,
+	
+#ifdef HAVE_CURSES
+	.proc_wlogprint_status = bitfury_wlogprint_status,
+	.proc_tui_wlogprint_choices = bitfury_tui_wlogprint_choices,
+	.proc_tui_handle_choice = bitfury_tui_handle_choice,
+#endif
+};