Browse Source

Split fpgautils into lowl-vcom and binloader, and fix internal build dependencies

Luke Dashjr 12 years ago
parent
commit
b092c3c7b3
29 changed files with 453 additions and 389 deletions
  1. 7 3
      Makefile.am
  2. 211 0
      binloader.c
  3. 14 0
      binloader.h
  4. 34 20
      configure.ac
  5. 8 6
      deviceapi.c
  6. 1 1
      driver-avalon.c
  7. 1 1
      driver-bigpic.c
  8. 1 1
      driver-bitforce.c
  9. 1 1
      driver-cairnsmore.c
  10. 1 1
      driver-erupter.c
  11. 0 1
      driver-hashbuster.c
  12. 1 1
      driver-icarus.c
  13. 1 1
      driver-littlefury.c
  14. 2 1
      driver-modminer.c
  15. 0 1
      driver-nanofury.c
  16. 2 1
      driver-x6500.c
  17. 1 1
      driver-ztex.c
  18. 0 1
      ft232r.c
  19. 2 1
      libztex.c
  20. 0 1
      lowl-hid.c
  21. 35 1
      lowl-usb.c
  22. 12 0
      lowl-usb.h
  23. 5 313
      lowl-vcom.c
  24. 2 22
      lowl-vcom.h
  25. 66 1
      lowlevel.c
  26. 6 1
      lowlevel.h
  27. 34 3
      miner.c
  28. 1 0
      miner.h
  29. 4 4
      util.c

+ 7 - 3
Makefile.am

@@ -167,8 +167,8 @@ endif # HAVE_x86_64
 endif # HAS_YASM
 endif # HAS_CPUMINE
 
-if NEED_FPGAUTILS
-bfgminer_SOURCES += fpgautils.c fpgautils.h
+if NEED_BFG_LOWL_VCOM
+bfgminer_SOURCES += lowl-vcom.c lowl-vcom.h
 if HAVE_WINDOWS
 else
 bfgminer_SOURCES += iospeeds.h iospeeds_posix.h
@@ -176,7 +176,11 @@ endif
 endif
 
 if HAVE_LIBUSB
-bfgminer_SOURCES += lowl-usb.c
+bfgminer_SOURCES += lowl-usb.c lowl-usb.h
+endif
+
+if NEED_BFG_BINLOADER
+bfgminer_SOURCES += binloader.c binloader.h
 endif
 
 if NEED_BFG_LOWLEVEL

+ 211 - 0
binloader.c

@@ -0,0 +1,211 @@
+/*
+ * Copyright 2012-2013 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 <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "deviceapi.h"
+#include "logging.h"
+#include "miner.h"
+#include "util.h"
+
+#define bailout(...)  do {  \
+	applog(__VA_ARGS__);  \
+	return NULL;  \
+} while(0)
+
+#define check_magic(L)  do {  \
+	if (1 != fread(buf, 1, 1, f))  \
+		bailout(LOG_ERR, "%s: Error reading bitstream ('%c')",  \
+		        repr, L);  \
+	if (buf[0] != L)  \
+		bailout(LOG_ERR, "%s: Firmware has wrong magic ('%c')",  \
+		        repr, L);  \
+} while(0)
+
+#define read_str(eng)  do {  \
+	if (1 != fread(buf, 2, 1, f))  \
+		bailout(LOG_ERR, "%s: Error reading bitstream (" eng " len)",  \
+		        repr);  \
+	len = (ubuf[0] << 8) | ubuf[1];  \
+	if (len >= sizeof(buf))  \
+		bailout(LOG_ERR, "%s: Firmware " eng " too long",  \
+		        repr);  \
+	if (1 != fread(buf, len, 1, f))  \
+		bailout(LOG_ERR, "%s: Error reading bitstream (" eng ")",  \
+		        repr);  \
+	buf[len] = '\0';  \
+} while(0)
+
+void _bitstream_not_found(const char *repr, const char *fn)
+{
+	applog(LOG_ERR, "ERROR: Unable to load '%s', required for %s to work!", fn, repr);
+	applog(LOG_ERR, "ERROR: Please read README.FPGA for instructions");
+}
+
+FILE *open_xilinx_bitstream(const char *dname, const char *repr, const char *fwfile, unsigned long *out_len)
+{
+	char buf[0x100];
+	unsigned char *ubuf = (unsigned char*)buf;
+	unsigned long len;
+	char *p;
+
+	FILE *f = open_bitstream(dname, fwfile);
+	if (!f)
+	{
+		_bitstream_not_found(repr, fwfile);
+		return NULL;
+	}
+	if (1 != fread(buf, 2, 1, f))
+		bailout(LOG_ERR, "%s: Error reading bitstream (magic)",
+		        repr);
+	if (buf[0] || buf[1] != 9)
+		bailout(LOG_ERR, "%s: Firmware has wrong magic (9)",
+		        repr);
+	if (-1 == fseek(f, 11, SEEK_CUR))
+		bailout(LOG_ERR, "%s: Firmware seek failed",
+		        repr);
+	check_magic('a');
+	read_str("design name");
+	applog(LOG_DEBUG, "%s: Firmware file %s info:",
+	       repr, fwfile);
+	applog(LOG_DEBUG, "  Design name: %s", buf);
+	p = strrchr(buf, ';') ?: buf;
+	p = strrchr(buf, '=') ?: p;
+	if (p[0] == '=')
+		++p;
+	unsigned long fwusercode = (unsigned long)strtoll(p, &p, 16);
+	if (p[0] != '\0')
+		bailout(LOG_ERR, "%s: Bad usercode in bitstream file",
+		        repr);
+	if (fwusercode == 0xffffffff)
+		bailout(LOG_ERR, "%s: Firmware doesn't support user code",
+		        repr);
+	applog(LOG_DEBUG, "  Version: %u, build %u", (unsigned)((fwusercode >> 8) & 0xff), (unsigned)(fwusercode & 0xff));
+	check_magic('b');
+	read_str("part number");
+	applog(LOG_DEBUG, "  Part number: %s", buf);
+	check_magic('c');
+	read_str("build date");
+	applog(LOG_DEBUG, "  Build date: %s", buf);
+	check_magic('d');
+	read_str("build time");
+	applog(LOG_DEBUG, "  Build time: %s", buf);
+	check_magic('e');
+	if (1 != fread(buf, 4, 1, f))
+		bailout(LOG_ERR, "%s: Error reading bitstream (data len)",
+		        repr);
+	len = ((unsigned long)ubuf[0] << 24) | ((unsigned long)ubuf[1] << 16) | (ubuf[2] << 8) | ubuf[3];
+	applog(LOG_DEBUG, "  Bitstream size: %lu", len);
+
+	*out_len = len;
+	return f;
+}
+
+bool load_bitstream_intelhex(bytes_t *rv, const char *dname, const char *repr, const char *fn)
+{
+	char buf[0x100];
+	size_t sz;
+	uint8_t xsz, xrt;
+	uint16_t xaddr;
+	FILE *F = open_bitstream(dname, fn);
+	if (!F)
+		return false;
+	while (!feof(F))
+	{
+		if (unlikely(ferror(F)))
+		{
+			applog(LOG_ERR, "Error reading '%s'", fn);
+			goto ihxerr;
+		}
+		if (!fgets(buf, sizeof(buf), F))
+			goto ihxerr;
+		if (unlikely(buf[0] != ':'))
+			goto ihxerr;
+		if (unlikely(!(
+			hex2bin(&xsz, &buf[1], 1)
+		 && hex2bin((unsigned char*)&xaddr, &buf[3], 2)
+		 && hex2bin(&xrt, &buf[7], 1)
+		)))
+		{
+			applog(LOG_ERR, "Error parsing in '%s'", fn);
+			goto ihxerr;
+		}
+		switch (xrt)
+		{
+			case 0:  // data
+				break;
+			case 1:  // EOF
+				fclose(F);
+				return true;
+			default:
+				applog(LOG_ERR, "Unsupported record type in '%s'", fn);
+				goto ihxerr;
+		}
+		xaddr = be16toh(xaddr);
+		sz = bytes_len(rv);
+		bytes_resize(rv, xaddr + xsz);
+		if (sz < xaddr)
+			memset(&bytes_buf(rv)[sz], 0xff, xaddr - sz);
+		if (unlikely(!(hex2bin(&bytes_buf(rv)[xaddr], &buf[9], xsz))))
+		{
+			applog(LOG_ERR, "Error parsing data in '%s'", fn);
+			goto ihxerr;
+		}
+		// TODO: checksum
+	}
+	
+ihxerr:
+	fclose(F);
+	bytes_reset(rv);
+	return false;
+}
+
+bool load_bitstream_bytes(bytes_t *rv, const char *dname, const char *repr, const char *fileprefix)
+{
+	FILE *F;
+	size_t fplen = strlen(fileprefix);
+	char fnbuf[fplen + 4 + 1];
+	int e;
+	
+	bytes_reset(rv);
+	memcpy(fnbuf, fileprefix, fplen);
+	
+	strcpy(&fnbuf[fplen], ".bin");
+	F = open_bitstream(dname, fnbuf);
+	if (F)
+	{
+		char buf[0x100];
+		size_t sz;
+		while ( (sz = fread(buf, 1, sizeof(buf), F)) )
+			bytes_append(rv, buf, sz);
+		e = ferror(F);
+		fclose(F);
+		if (unlikely(e))
+		{
+			applog(LOG_ERR, "Error reading '%s'", fnbuf);
+			bytes_reset(rv);
+		}
+		else
+			return true;
+	}
+	
+	strcpy(&fnbuf[fplen], ".ihx");
+	if (load_bitstream_intelhex(rv, dname, repr, fnbuf))
+		return true;
+	
+	// TODO: Xilinx
+	
+	_bitstream_not_found(repr, fnbuf);
+	return false;
+}

+ 14 - 0
binloader.h

@@ -0,0 +1,14 @@
+#ifndef BFG_BINLOADER_H
+#define BFG_BINLOADER_H
+
+#include <stdbool.h>
+#include <stdio.h>
+
+#include "util.h"
+
+extern void _bitstream_not_found(const char *repr, const char *fn);
+extern FILE *open_xilinx_bitstream(const char *dname, const char *repr, const char *fwfile, unsigned long *out_len);
+extern bool load_bitstream_intelhex(bytes_t *out, const char *dname, const char *repr, const char *fn);
+extern bool load_bitstream_bytes(bytes_t *out, const char *dname, const char *repr, const char *fileprefix);
+
+#endif

+ 34 - 20
configure.ac

@@ -109,10 +109,12 @@ driverlist=
 algolist=SHA256d
 optlist=
 
+need_binloader=no
 need_dynclock=no
-need_fpgautils=no
+need_lowl_vcom=no
 need_lowlevel=no
 need_lowl_hid=no
+need_lowl_usb=no
 have_cygwin=false
 have_win32=false
 have_macho=false
@@ -353,7 +355,7 @@ AC_ARG_ENABLE([bitforce],
 	)
 if test "x$bitforce" = xyes; then
 	AC_DEFINE([USE_BITFORCE], [1], [Defined to 1 if BitForce support is wanted])
-	need_fpgautils=yes
+	need_lowl_vcom=yes
 fi
 AM_CONDITIONAL([HAS_BITFORCE], [test x$bitforce = xyes])
 
@@ -366,7 +368,7 @@ AC_ARG_ENABLE([icarus],
 if test "x$icarus" = xyes; then
 	AC_DEFINE([USE_ICARUS], [1], [Defined to 1 if Icarus support is wanted])
 	need_dynclock=yes
-	need_fpgautils=yes
+	need_lowl_vcom=yes
 fi
 AM_CONDITIONAL([HAS_ICARUS], [test x$icarus = xyes])
 
@@ -380,7 +382,7 @@ AC_ARG_ENABLE([avalon],
 	)
 if test "x$avalon" = xyes; then
 	AC_DEFINE([USE_AVALON], [1], [Defined to 1 if Avalon support is wanted])
-	need_fpgautils=yes
+	need_lowl_vcom=yes
 fi
 AM_CONDITIONAL([HAS_AVALON], [test x$avalon = xyes])
 
@@ -476,7 +478,8 @@ AC_ARG_ENABLE([modminer],
 if test "x$modminer" = xyes; then
 	AC_DEFINE([USE_MODMINER], [1], [Defined to 1 if ModMiner support is wanted])
 	need_dynclock=yes
-	need_fpgautils=yes
+	need_lowl_vcom=yes
+	need_binloader=yes
 fi
 AM_CONDITIONAL([HAS_MODMINER], [test x$modminer = xyes])
 
@@ -528,7 +531,7 @@ elif test "x$klondike" = xauto; then
 fi
 if test "x$klondike" = xyes; then
 	AC_DEFINE([USE_KLONDIKE], [1], [Defined to 1 if Klondike support is wanted])
-	need_lowlevel=yes
+	need_lowl_usb=yes
 fi
 AM_CONDITIONAL([HAS_KLONDIKE], [test x$klondike = xyes])
 
@@ -551,8 +554,8 @@ fi
 if test "x$x6500" = xyes; then
 	AC_DEFINE([USE_X6500], [1], [Defined to 1 if X6500 support is wanted])
 	need_dynclock=yes
-	need_fpgautils=yes
-	need_lowlevel=yes
+	need_lowl_usb=yes
+	need_binloader=yes
 fi
 AM_CONDITIONAL([HAS_X6500], [test x$x6500 = xyes])
 
@@ -574,7 +577,8 @@ fi
 if test "x$ztex" = xyes; then
 	AC_DEFINE([USE_ZTEX], [1], [Defined to 1 if ZTEX support is wanted])
 	need_dynclock=yes
-	need_fpgautils=yes
+	need_lowl_usb=yes
+	need_binloader=yes
 fi
 AM_CONDITIONAL([HAS_ZTEX], [test x$ztex = xyes])
 
@@ -623,7 +627,7 @@ else
 fi
 if test "x$bigpic" = "xyes"; then
 	AC_DEFINE([USE_BIGPIC], [1], [Defined to 1 if Big Picture Mining USB support is wanted])
-	need_fpgautils=yes
+	need_lowl_vcom=yes
 fi
 AM_CONDITIONAL([HAS_BIGPIC], [test x$bigpic = xyes])
 
@@ -645,7 +649,7 @@ else
 fi
 if test "x$littlefury" = "xyes"; then
 	AC_DEFINE([USE_LITTLEFURY], [1], [Defined to 1 if LittleFury support is wanted])
-	need_fpgautils=yes
+	need_lowl_vcom=yes
 fi
 AM_CONDITIONAL([HAS_LITTLEFURY], [test x$littlefury = xyes])
 
@@ -687,8 +691,6 @@ else
 fi
 if test "x$nanofury" = "xyes"; then
 	AC_DEFINE([USE_NANOFURY], [1], [Defined to 1 if NanoFury support is wanted])
-	need_fpgautils=yes
-	need_lowlevel=yes
 	need_lowl_hid=yes
 fi
 AM_CONDITIONAL([HAS_NANOFURY], [test x$nanofury = xyes])
@@ -720,8 +722,6 @@ else
 fi
 if test "x$hashbuster" = "xyes"; then
 	AC_DEFINE([USE_HASHBUSTER], [1], [Defined to 1 if HashBuster support is wanted])
-	need_fpgautils=yes
-	need_lowlevel=yes
 	need_lowl_hid=yes
 fi
 AM_CONDITIONAL([USE_HASHBUSTER], [test x$hashbuster = xyes])
@@ -742,7 +742,12 @@ fi
 AM_CONDITIONAL([HAS_METABANK], [test x$metabank = xyes])
 
 
-if test "x$klondike$x6500$ztex" = "xnonono"; then
+if test "x$need_lowl_vcom" != "xno"; then
+	# Lowlevel VCOM doesn't need libusb, but it can take advantage of it to reattach drivers
+	need_lowl_usb=yes
+fi
+
+if test "x$need_lowl_usb" = "xno"; then
 	libusb=no
 	LIBUSB_LIBS=''
 	LIBUSB_CFLAGS=''
@@ -768,8 +773,8 @@ if test "x$scrypt" = xyes; then
 fi
 
 
-if test x$need_fpgautils = xyes; then
-	AC_DEFINE([HAVE_FPGAUTILS], [1], [Defined to 1 if fpgautils is being used])
+if test x$need_lowl_vcom = xyes; then
+	AC_DEFINE([NEED_BFG_LOWL_VCOM], [1], [Defined to 1 if lowlevel VCOM drivers are being used])
 	need_lowlevel=yes
 	
 	if $have_win32; then
@@ -819,6 +824,14 @@ if test x$need_lowl_hid = xyes; then
 	need_lowlevel=yes
 fi
 
+if test x$need_lowl_usb = xyes; then
+	need_lowlevel=yes
+fi
+
+if test x$need_fpgautils = xyes; then
+	need_lowlevel=yes
+fi
+
 if test x$need_lowlevel = xyes; then
 	AC_DEFINE([HAVE_BFG_LOWLEVEL], [1], [Defined to 1 if lowlevel drivers are being used])
 fi
@@ -974,8 +987,9 @@ AC_SUBST(libblkmaker_LIBS)
 
 
 AM_CONDITIONAL([NEED_LIBBLKMAKER], [test x$with_system_libblkmaker != xyes])
+AM_CONDITIONAL([NEED_BFG_BINLOADER], [test x$need_binloader = xyes])
 AM_CONDITIONAL([NEED_DYNCLOCK], [test x$need_dynclock = xyes])
-AM_CONDITIONAL([NEED_FPGAUTILS], [test x$need_fpgautils = xyes])
+AM_CONDITIONAL([NEED_BFG_LOWL_VCOM], [test x$need_lowl_vcom = xyes])
 AM_CONDITIONAL([NEED_BFG_LOWL_HID], [test x$need_lowl_hid = xyes])
 AM_CONDITIONAL([NEED_BFG_LOWLEVEL], [test x$need_lowlevel = xyes])
 AM_CONDITIONAL([HAS_SCRYPT], [test x$scrypt = xyes])
@@ -1083,7 +1097,7 @@ if test "x$cpumining$have_x86_32" = "xyestrue"; then
 fi
 AM_CONDITIONAL([HAVE_SSE2], [test "x$have_sse2" = "xyes"])
 
-if test "x$need_fpgautils" = "xyes"; then
+if test "x$need_lowl_vcom" = "xyes"; then
 	AC_ARG_WITH([libudev], [AC_HELP_STRING([--without-libudev], [Autodetect FPGAs using libudev (default enabled)])],
 		[libudev=$withval],
 		[libudev=auto]

+ 8 - 6
deviceapi.c

@@ -26,9 +26,11 @@
 
 #include "compat.h"
 #include "deviceapi.h"
-#include "fpgautils.h"
 #include "logging.h"
 #include "lowlevel.h"
+#ifdef NEED_BFG_LOWL_VCOM
+#include "lowl-vcom.h"
+#endif
 #include "miner.h"
 #include "util.h"
 
@@ -728,7 +730,7 @@ bool _add_cgpu(struct cgpu_info *cgpu)
 	strcpy(cgpu->proc_repr, cgpu->dev_repr);
 	sprintf(cgpu->proc_repr_ns, "%s%u", cgpu->drv->name, cgpu->device_id);
 	
-#ifdef HAVE_FPGAUTILS
+#ifdef NEED_BFG_LOWL_VCOM
 	maybe_strdup_if_null(&cgpu->dev_manufacturer, detectone_meta_info.manufacturer);
 	maybe_strdup_if_null(&cgpu->dev_product,      detectone_meta_info.product);
 	maybe_strdup_if_null(&cgpu->dev_serial,       detectone_meta_info.serial);
@@ -819,7 +821,7 @@ bool add_cgpu_slave(struct cgpu_info *cgpu, struct cgpu_info *prev_cgpu)
 	return true;
 }
 
-#ifdef HAVE_FPGAUTILS
+#ifdef NEED_BFG_LOWL_VCOM
 bool _serial_detect_all(struct lowlevel_device_info * const info, void * const userp)
 {
 	detectone_func_t detectone = userp;
@@ -843,7 +845,7 @@ int _serial_detect(struct device_drv *api, detectone_func_t detectone, autoscan_
 	size_t namel = strlen(api->name);
 	size_t dnamel = strlen(api->dname);
 
-#ifdef HAVE_FPGAUTILS
+#ifdef NEED_BFG_LOWL_VCOM
 	clear_detectone_meta_info();
 #endif
 	DL_FOREACH_SAFE(scan_devices, iter, tmp) {
@@ -874,7 +876,7 @@ int _serial_detect(struct device_drv *api, detectone_func_t detectone, autoscan_
 		else
 		if (!strcmp(dev, "all"))
 			doall = true;
-#ifdef HAVE_FPGAUTILS
+#ifdef NEED_BFG_LOWL_VCOM
 		else
 		if (serial_claim(dev, NULL))
 		{
@@ -888,7 +890,7 @@ int _serial_detect(struct device_drv *api, detectone_func_t detectone, autoscan_
 		}
 	}
 
-#ifdef HAVE_FPGAUTILS
+#ifdef NEED_BFG_LOWL_VCOM
 	if (doall && detectone)
 		found += lowlevel_detect_id(_serial_detect_all, detectone, &lowl_vcom, 0, 0);
 #endif

+ 1 - 1
driver-avalon.c

@@ -37,10 +37,10 @@
 
 #include "deviceapi.h"
 #include "miner.h"
-#include "fpgautils.h"
 #include "driver-avalon.h"
 #include "logging.h"
 #include "lowlevel.h"
+#include "lowl-vcom.h"
 #include "util.h"
 
 BFG_REGISTER_DRIVER(avalon_drv)

+ 1 - 1
driver-bigpic.c

@@ -18,11 +18,11 @@
 #include <stdint.h>
 
 #include "miner.h"
-#include "fpgautils.h"
 #include "logging.h"
 
 #include "libbitfury.h"
 #include "lowlevel.h"
+#include "lowl-vcom.h"
 #include "deviceapi.h"
 #include "sha2.h"
 

+ 1 - 1
driver-bitforce.c

@@ -23,8 +23,8 @@
 #include "compat.h"
 #include "deviceapi.h"
 #include "miner.h"
-#include "fpgautils.h"
 #include "lowlevel.h"
+#include "lowl-vcom.h"
 #include "util.h"
 
 #define BITFORCE_SLEEP_MS 500

+ 1 - 1
driver-cairnsmore.c

@@ -14,9 +14,9 @@
 
 #include "compat.h"
 #include "dynclock.h"
-#include "fpgautils.h"
 #include "icarus-common.h"
 #include "lowlevel.h"
+#include "lowl-vcom.h"
 #include "miner.h"
 
 #define CAIRNSMORE1_IO_SPEED 115200

+ 1 - 1
driver-erupter.c

@@ -12,9 +12,9 @@
 #include <stdbool.h>
 
 #include "miner.h"
-#include "fpgautils.h"
 #include "icarus-common.h"
 #include "lowlevel.h"
+#include "lowl-vcom.h"
 
 #define ERUPTER_IO_SPEED 115200
 #define ERUPTER_HASH_TIME 0.0000000029761

+ 0 - 1
driver-hashbuster.c

@@ -15,7 +15,6 @@
 
 #include "deviceapi.h"
 #include "driver-bitfury.h"
-#include "fpgautils.h"
 #include "libbitfury.h"
 #include "logging.h"
 #include "lowlevel.h"

+ 1 - 1
driver-icarus.c

@@ -64,7 +64,7 @@
 #include "compat.h"
 #include "dynclock.h"
 #include "icarus-common.h"
-#include "fpgautils.h"
+#include "lowl-vcom.h"
 
 // The serial I/O speed - Linux uses a define 'B115200' in bits/termios.h
 #define ICARUS_IO_SPEED 115200

+ 1 - 1
driver-littlefury.c

@@ -16,10 +16,10 @@
 
 #include "deviceapi.h"
 #include "driver-bitfury.h"
-#include "fpgautils.h"
 #include "libbitfury.h"
 #include "logging.h"
 #include "lowlevel.h"
+#include "lowl-vcom.h"
 #include "miner.h"
 #include "spidevc.h"
 #include "util.h"

+ 2 - 1
driver-modminer.c

@@ -17,12 +17,13 @@
 #include <stdio.h>
 #include <unistd.h>
 
+#include "binloader.h"
 #include "compat.h"
 #include "dynclock.h"
 #include "logging.h"
 #include "miner.h"
-#include "fpgautils.h"
 #include "lowlevel.h"
+#include "lowl-vcom.h"
 #include "util.h"
 
 #define BITSTREAM_FILENAME "fpgaminer_x6500-overclocker-0402.bit"

+ 0 - 1
driver-nanofury.c

@@ -15,7 +15,6 @@
 
 #include "deviceapi.h"
 #include "driver-bitfury.h"
-#include "fpgautils.h"
 #include "libbitfury.h"
 #include "logging.h"
 #include "lowlevel.h"

+ 2 - 1
driver-x6500.c

@@ -22,15 +22,16 @@
 
 #include <libusb.h>
 
+#include "binloader.h"
 #include "compat.h"
 #include "deviceapi.h"
 #include "dynclock.h"
 #include "jtag.h"
 #include "logging.h"
 #include "miner.h"
-#include "fpgautils.h"
 #include "ft232r.h"
 #include "lowlevel.h"
+#include "lowl-usb.h"
 
 #define X6500_USB_PRODUCT "X6500 FPGA Miner"
 #define X6500_BITSTREAM_FILENAME "fpgaminer_x6500-overclocker-0402.bit"

+ 1 - 1
driver-ztex.c

@@ -25,9 +25,9 @@
 
 #include "deviceapi.h"
 #include "dynclock.h"
-#include "fpgautils.h"
 #include "libztex.h"
 #include "lowlevel.h"
+#include "lowl-usb.h"
 #include "util.h"
 
 #define GOLDEN_BACKLOG 5

+ 0 - 1
ft232r.c

@@ -21,7 +21,6 @@
 #include <libusb.h>
 
 #include "compat.h"
-#include "fpgautils.h"
 #include "ft232r.h"
 #include "logging.h"
 #include "lowlevel.h"

+ 2 - 1
libztex.c

@@ -31,10 +31,11 @@
 #include <unistd.h>
 #include <string.h>
 
+#include "binloader.h"
 #include "compat.h"
+#include "deviceapi.h"
 #include "dynclock.h"
 #include "miner.h"
-#include "fpgautils.h"
 #include "libztex.h"
 #include "util.h"
 

+ 0 - 1
lowl-hid.c

@@ -31,7 +31,6 @@ typedef HMODULE dlh_t;
 #include <hidapi.h>
 #include <utlist.h>
 
-#include "fpgautils.h"
 #include "logging.h"
 #include "lowlevel.h"
 #include "miner.h"

+ 35 - 1
lowl-usb.c

@@ -17,9 +17,9 @@
 
 #include <libusb.h>
 
-#include "fpgautils.h"
 #include "logging.h"
 #include "lowlevel.h"
+#include "lowl-usb.h"
 #include "miner.h"
 #include "util.h"
 
@@ -146,6 +146,40 @@ struct libusb_device_handle *lowl_usb_open(struct lowlevel_device_info * const i
 	return devh;
 }
 
+struct device_drv *bfg_claim_usb(struct device_drv * const api, const bool verbose, const uint8_t usbbus, const uint8_t usbaddr)
+{
+	char * const devpath = bfg_make_devid_usb(usbbus, usbaddr);
+	struct device_drv * const rv = bfg_claim_any(api, verbose ? "" : NULL, devpath);
+	free(devpath);
+	return rv;
+}
+
+#ifdef HAVE_LIBUSB
+void cgpu_copy_libusb_strings(struct cgpu_info *cgpu, libusb_device *usb)
+{
+	unsigned char buf[0x20];
+	libusb_device_handle *h;
+	struct libusb_device_descriptor desc;
+	
+	if (LIBUSB_SUCCESS != libusb_open(usb, &h))
+		return;
+	if (libusb_get_device_descriptor(usb, &desc))
+	{
+		libusb_close(h);
+		return;
+	}
+	
+	if ((!cgpu->dev_manufacturer) && libusb_get_string_descriptor_ascii(h, desc.iManufacturer, buf, sizeof(buf)) >= 0)
+		cgpu->dev_manufacturer = strdup((void *)buf);
+	if ((!cgpu->dev_product) && libusb_get_string_descriptor_ascii(h, desc.iProduct, buf, sizeof(buf)) >= 0)
+		cgpu->dev_product = strdup((void *)buf);
+	if ((!cgpu->dev_serial) && libusb_get_string_descriptor_ascii(h, desc.iSerialNumber, buf, sizeof(buf)) >= 0)
+		cgpu->dev_serial = strdup((void *)buf);
+	
+	libusb_close(h);
+}
+#endif
+
 void lowl_usb_close(struct libusb_device_handle * const devh)
 {
 	libusb_close(devh);

+ 12 - 0
lowl-usb.h

@@ -0,0 +1,12 @@
+#ifndef BFG_LOWL_USB_H
+#define BFG_LOWL_USB_H
+
+#include <libusb.h>
+
+extern struct device_drv *bfg_claim_usb(struct device_drv * const, const bool verbose, const uint8_t usbbus, const uint8_t usbaddr);
+#define bfg_make_devid_libusb(dev)  bfg_make_devid_usb(libusb_get_bus_number(dev), libusb_get_device_address(dev))
+#define bfg_claim_libusb(api, verbose, dev)  bfg_claim_usb(api, verbose, libusb_get_bus_number(dev), libusb_get_device_address(dev))
+
+extern void cgpu_copy_libusb_strings(struct cgpu_info *, libusb_device *);
+
+#endif

+ 5 - 313
fpgautils.c → lowl-vcom.c

@@ -87,7 +87,7 @@ enum {
 #include "miner.h"
 #include "util.h"
 
-#include "fpgautils.h"
+#include "lowl-vcom.h"
 
 struct lowlevel_driver lowl_vcom;
 
@@ -653,11 +653,13 @@ bool vcom_lowl_probe_wrapper(const struct lowlevel_device_info * const info, det
 {
 	if (info->lowl != &lowl_vcom)
 	{
+#ifdef HAVE_LIBUSB
 		if (info->lowl == &lowl_usb)
 		{
 			if (lowl_usb_attach_kernel_driver(info))
 				bfg_need_detect_rescan = true;
 		}
+#endif
 		return false;
 	}
 	detectone_meta_info = (struct detectone_meta_info_t){
@@ -680,12 +682,14 @@ bool _serial_autodetect_found_cb(struct lowlevel_device_info * const devinfo, vo
 	}
 	if (devinfo->lowl != &lowl_vcom)
 	{
+#ifdef HAVE_LIBUSB
 		if (devinfo->lowl == &lowl_usb)
 		{
 			if (lowl_usb_attach_kernel_driver(devinfo))
 				bfg_need_detect_rescan = true;
 		}
 		else
+#endif
 			applog(LOG_WARNING, "Non-VCOM %s (%s) matched", devinfo->path, devinfo->devid);
 		return false;
 	}
@@ -756,86 +760,6 @@ struct lowlevel_device_info *vcom_devinfo_scan()
 }
 
 
-struct _device_claim {
-	struct device_drv *drv;
-	char *devpath;
-	UT_hash_handle hh;
-};
-
-struct device_drv *bfg_claim_any(struct device_drv * const api, const char *verbose, const char * const devpath)
-{
-	static struct _device_claim *claims = NULL;
-	struct _device_claim *c;
-	
-	HASH_FIND_STR(claims, devpath, c);
-	if (c)
-	{
-		if (verbose && opt_debug)
-		{
-			char logbuf[LOGBUFSIZ];
-			logbuf[0] = '\0';
-			if (api)
-				tailsprintf(logbuf, sizeof(logbuf), "%s device ", api->dname);
-			if (verbose[0])
-				tailsprintf(logbuf, sizeof(logbuf), "%s (%s)", verbose, devpath);
-			else
-				tailsprintf(logbuf, sizeof(logbuf), "%s", devpath);
-			tailsprintf(logbuf, sizeof(logbuf), " already claimed by ");
-			if (api)
-				tailsprintf(logbuf, sizeof(logbuf), "other ");
-			tailsprintf(logbuf, sizeof(logbuf), "driver: %s", c->drv->dname);
-			_applog(LOG_DEBUG, logbuf);
-		}
-		return c->drv;
-	}
-	
-	if (!api)
-		return NULL;
-	
-	c = malloc(sizeof(*c));
-	c->devpath = strdup(devpath);
-	c->drv = api;
-	HASH_ADD_KEYPTR(hh, claims, c->devpath, strlen(devpath), c);
-	return NULL;
-}
-
-struct device_drv *bfg_claim_any2(struct device_drv * const api, const char * const verbose, const char * const llname, const char * const path)
-{
-	const size_t llnamesz = strlen(llname);
-	const size_t pathsz = strlen(path);
-	char devpath[llnamesz + 1 + pathsz + 1];
-	memcpy(devpath, llname, llnamesz);
-	devpath[llnamesz] = ':';
-	memcpy(&devpath[llnamesz+1], path, pathsz + 1);
-	return bfg_claim_any(api, verbose, devpath);
-}
-
-char *devpath_to_devid(const char * const devpath)
-{
-#ifndef WIN32
-	char *devs = malloc(6 + (sizeof(dev_t) * 2) + 1);
-	{
-		struct stat my_stat;
-		if (stat(devpath, &my_stat))
-			return NULL;
-		memcpy(devs, "dev_t:", 6);
-		bin2hex(&devs[6], &my_stat.st_rdev, sizeof(dev_t));
-	}
-#else
-		char *p = strstr(devpath, "COM"), *p2;
-		if (!p)
-			return NULL;
-		const int com = strtol(&p[3], &p2, 10);
-		if (p2 == p)
-			return NULL;
-	char dummy;
-	const int sz = snprintf(&dummy, 1, "%d", com);
-	char *devs = malloc(4 + sz + 1);
-	sprintf(devs, "com:%d", com);
-#endif
-	return devs;
-}
-
 struct device_drv *bfg_claim_serial(struct device_drv * const api, const bool verbose, const char * const devpath)
 {
 	char * const devs = _vcom_unique_id(devpath);
@@ -846,47 +770,6 @@ struct device_drv *bfg_claim_serial(struct device_drv * const api, const bool ve
 	return rv;
 }
 
-char *bfg_make_devid_usb(const uint8_t usbbus, const uint8_t usbaddr)
-{
-	char * const devpath = malloc(12);
-	sprintf(devpath, "usb:%03u:%03u", (unsigned)usbbus, (unsigned)usbaddr);
-	return devpath;
-}
-
-struct device_drv *bfg_claim_usb(struct device_drv * const api, const bool verbose, const uint8_t usbbus, const uint8_t usbaddr)
-{
-	char * const devpath = bfg_make_devid_usb(usbbus, usbaddr);
-	struct device_drv * const rv = bfg_claim_any(api, verbose ? "" : NULL, devpath);
-	free(devpath);
-	return rv;
-}
-
-#ifdef HAVE_LIBUSB
-void cgpu_copy_libusb_strings(struct cgpu_info *cgpu, libusb_device *usb)
-{
-	unsigned char buf[0x20];
-	libusb_device_handle *h;
-	struct libusb_device_descriptor desc;
-	
-	if (LIBUSB_SUCCESS != libusb_open(usb, &h))
-		return;
-	if (libusb_get_device_descriptor(usb, &desc))
-	{
-		libusb_close(h);
-		return;
-	}
-	
-	if ((!cgpu->dev_manufacturer) && libusb_get_string_descriptor_ascii(h, desc.iManufacturer, buf, sizeof(buf)) >= 0)
-		cgpu->dev_manufacturer = strdup((void *)buf);
-	if ((!cgpu->dev_product) && libusb_get_string_descriptor_ascii(h, desc.iProduct, buf, sizeof(buf)) >= 0)
-		cgpu->dev_product = strdup((void *)buf);
-	if ((!cgpu->dev_serial) && libusb_get_string_descriptor_ascii(h, desc.iSerialNumber, buf, sizeof(buf)) >= 0)
-		cgpu->dev_serial = strdup((void *)buf);
-	
-	libusb_close(h);
-}
-#endif
-
 // This code is purely for debugging but is very useful for that
 // It also took quite a bit of effort so I left it in
 // #define TERMIOS_DEBUG 1
@@ -1183,197 +1066,6 @@ ssize_t _serial_read(int fd, char *buf, size_t bufsiz, char *eol)
 	return tlen;
 }
 
-#define bailout(...)  do {  \
-	applog(__VA_ARGS__);  \
-	return NULL;  \
-} while(0)
-
-#define check_magic(L)  do {  \
-	if (1 != fread(buf, 1, 1, f))  \
-		bailout(LOG_ERR, "%s: Error reading bitstream ('%c')",  \
-		        repr, L);  \
-	if (buf[0] != L)  \
-		bailout(LOG_ERR, "%s: Firmware has wrong magic ('%c')",  \
-		        repr, L);  \
-} while(0)
-
-#define read_str(eng)  do {  \
-	if (1 != fread(buf, 2, 1, f))  \
-		bailout(LOG_ERR, "%s: Error reading bitstream (" eng " len)",  \
-		        repr);  \
-	len = (ubuf[0] << 8) | ubuf[1];  \
-	if (len >= sizeof(buf))  \
-		bailout(LOG_ERR, "%s: Firmware " eng " too long",  \
-		        repr);  \
-	if (1 != fread(buf, len, 1, f))  \
-		bailout(LOG_ERR, "%s: Error reading bitstream (" eng ")",  \
-		        repr);  \
-	buf[len] = '\0';  \
-} while(0)
-
-void _bitstream_not_found(const char *repr, const char *fn)
-{
-	applog(LOG_ERR, "ERROR: Unable to load '%s', required for %s to work!", fn, repr);
-	applog(LOG_ERR, "ERROR: Please read README.FPGA for instructions");
-}
-
-FILE *open_xilinx_bitstream(const char *dname, const char *repr, const char *fwfile, unsigned long *out_len)
-{
-	char buf[0x100];
-	unsigned char *ubuf = (unsigned char*)buf;
-	unsigned long len;
-	char *p;
-
-	FILE *f = open_bitstream(dname, fwfile);
-	if (!f)
-	{
-		_bitstream_not_found(repr, fwfile);
-		return NULL;
-	}
-	if (1 != fread(buf, 2, 1, f))
-		bailout(LOG_ERR, "%s: Error reading bitstream (magic)",
-		        repr);
-	if (buf[0] || buf[1] != 9)
-		bailout(LOG_ERR, "%s: Firmware has wrong magic (9)",
-		        repr);
-	if (-1 == fseek(f, 11, SEEK_CUR))
-		bailout(LOG_ERR, "%s: Firmware seek failed",
-		        repr);
-	check_magic('a');
-	read_str("design name");
-	applog(LOG_DEBUG, "%s: Firmware file %s info:",
-	       repr, fwfile);
-	applog(LOG_DEBUG, "  Design name: %s", buf);
-	p = strrchr(buf, ';') ?: buf;
-	p = strrchr(buf, '=') ?: p;
-	if (p[0] == '=')
-		++p;
-	unsigned long fwusercode = (unsigned long)strtoll(p, &p, 16);
-	if (p[0] != '\0')
-		bailout(LOG_ERR, "%s: Bad usercode in bitstream file",
-		        repr);
-	if (fwusercode == 0xffffffff)
-		bailout(LOG_ERR, "%s: Firmware doesn't support user code",
-		        repr);
-	applog(LOG_DEBUG, "  Version: %u, build %u", (unsigned)((fwusercode >> 8) & 0xff), (unsigned)(fwusercode & 0xff));
-	check_magic('b');
-	read_str("part number");
-	applog(LOG_DEBUG, "  Part number: %s", buf);
-	check_magic('c');
-	read_str("build date");
-	applog(LOG_DEBUG, "  Build date: %s", buf);
-	check_magic('d');
-	read_str("build time");
-	applog(LOG_DEBUG, "  Build time: %s", buf);
-	check_magic('e');
-	if (1 != fread(buf, 4, 1, f))
-		bailout(LOG_ERR, "%s: Error reading bitstream (data len)",
-		        repr);
-	len = ((unsigned long)ubuf[0] << 24) | ((unsigned long)ubuf[1] << 16) | (ubuf[2] << 8) | ubuf[3];
-	applog(LOG_DEBUG, "  Bitstream size: %lu", len);
-
-	*out_len = len;
-	return f;
-}
-
-bool load_bitstream_intelhex(bytes_t *rv, const char *dname, const char *repr, const char *fn)
-{
-	char buf[0x100];
-	size_t sz;
-	uint8_t xsz, xrt;
-	uint16_t xaddr;
-	FILE *F = open_bitstream(dname, fn);
-	if (!F)
-		return false;
-	while (!feof(F))
-	{
-		if (unlikely(ferror(F)))
-		{
-			applog(LOG_ERR, "Error reading '%s'", fn);
-			goto ihxerr;
-		}
-		if (!fgets(buf, sizeof(buf), F))
-			goto ihxerr;
-		if (unlikely(buf[0] != ':'))
-			goto ihxerr;
-		if (unlikely(!(
-			hex2bin(&xsz, &buf[1], 1)
-		 && hex2bin((unsigned char*)&xaddr, &buf[3], 2)
-		 && hex2bin(&xrt, &buf[7], 1)
-		)))
-		{
-			applog(LOG_ERR, "Error parsing in '%s'", fn);
-			goto ihxerr;
-		}
-		switch (xrt)
-		{
-			case 0:  // data
-				break;
-			case 1:  // EOF
-				fclose(F);
-				return true;
-			default:
-				applog(LOG_ERR, "Unsupported record type in '%s'", fn);
-				goto ihxerr;
-		}
-		xaddr = be16toh(xaddr);
-		sz = bytes_len(rv);
-		bytes_resize(rv, xaddr + xsz);
-		if (sz < xaddr)
-			memset(&bytes_buf(rv)[sz], 0xff, xaddr - sz);
-		if (unlikely(!(hex2bin(&bytes_buf(rv)[xaddr], &buf[9], xsz))))
-		{
-			applog(LOG_ERR, "Error parsing data in '%s'", fn);
-			goto ihxerr;
-		}
-		// TODO: checksum
-	}
-	
-ihxerr:
-	fclose(F);
-	bytes_reset(rv);
-	return false;
-}
-
-bool load_bitstream_bytes(bytes_t *rv, const char *dname, const char *repr, const char *fileprefix)
-{
-	FILE *F;
-	size_t fplen = strlen(fileprefix);
-	char fnbuf[fplen + 4 + 1];
-	int e;
-	
-	bytes_reset(rv);
-	memcpy(fnbuf, fileprefix, fplen);
-	
-	strcpy(&fnbuf[fplen], ".bin");
-	F = open_bitstream(dname, fnbuf);
-	if (F)
-	{
-		char buf[0x100];
-		size_t sz;
-		while ( (sz = fread(buf, 1, sizeof(buf), F)) )
-			bytes_append(rv, buf, sz);
-		e = ferror(F);
-		fclose(F);
-		if (unlikely(e))
-		{
-			applog(LOG_ERR, "Error reading '%s'", fnbuf);
-			bytes_reset(rv);
-		}
-		else
-			return true;
-	}
-	
-	strcpy(&fnbuf[fplen], ".ihx");
-	if (load_bitstream_intelhex(rv, dname, repr, fnbuf))
-		return true;
-	
-	// TODO: Xilinx
-	
-	_bitstream_not_found(repr, fnbuf);
-	return false;
-}
-
 #ifndef WIN32
 
 int get_serial_cts(int fd)

+ 2 - 22
fpgautils.h → lowl-vcom.h

@@ -1,15 +1,11 @@
-#ifndef FPGAUTILS_H
-#define FPGAUTILS_H
+#ifndef BFG_LOWL_VCOM_H
+#define BFG_LOWL_VCOM_H
 
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <unistd.h>
 
-#ifdef HAVE_LIBUSB
-#include <libusb.h>
-#endif
-
 #include "deviceapi.h"
 
 struct device_drv;
@@ -25,25 +21,14 @@ extern struct detectone_meta_info_t *_detectone_meta_info();
 #define detectone_meta_info (*_detectone_meta_info())
 extern void clear_detectone_meta_info(void);
 
-extern char *devpath_to_devid(const char *);
 extern bool vcom_lowl_probe_wrapper(const struct lowlevel_device_info *, detectone_func_t);
 
 extern int _serial_autodetect(detectone_func_t, ...);
 #define serial_autodetect(...)  _serial_autodetect(__VA_ARGS__, NULL)
 
-extern struct device_drv *bfg_claim_any(struct device_drv *, const char *verbose, const char *devpath);
-extern struct device_drv *bfg_claim_any2(struct device_drv *, const char *verbose, const char *llname, const char *path);
 extern struct device_drv *bfg_claim_serial(struct device_drv * const, const bool verbose, const char * const devpath);
 #define serial_claim(devpath, drv)    bfg_claim_serial(drv, false, devpath)
 #define serial_claim_v(devpath, drv)  bfg_claim_serial(drv, true , devpath)
-extern char *bfg_make_devid_usb(uint8_t usbbus, uint8_t usbaddr);
-extern struct device_drv *bfg_claim_usb(struct device_drv * const, const bool verbose, const uint8_t usbbus, const uint8_t usbaddr);
-#define bfg_make_devid_libusb(dev)  bfg_make_devid_usb(libusb_get_bus_number(dev), libusb_get_device_address(dev))
-#define bfg_claim_libusb(api, verbose, dev)  bfg_claim_usb(api, verbose, libusb_get_bus_number(dev), libusb_get_device_address(dev))
-
-#ifdef HAVE_LIBUSB
-extern void cgpu_copy_libusb_strings(struct cgpu_info *, libusb_device *);
-#endif
 
 extern int serial_open(const char *devpath, unsigned long baud, uint8_t timeout, bool purge);
 extern ssize_t _serial_read(int fd, char *buf, size_t buflen, char *eol);
@@ -53,11 +38,6 @@ extern ssize_t _serial_read(int fd, char *buf, size_t buflen, char *eol);
 	_serial_read(fd, buf, bufsiz, &eol)
 extern int serial_close(int fd);
 
-extern void _bitstream_not_found(const char *repr, const char *fn);
-extern FILE *open_xilinx_bitstream(const char *dname, const char *repr, const char *fwfile, unsigned long *out_len);
-extern bool load_bitstream_intelhex(bytes_t *out, const char *dname, const char *repr, const char *fn);
-extern bool load_bitstream_bytes(bytes_t *out, const char *dname, const char *repr, const char *fileprefix);
-
 extern int get_serial_cts(int fd);
 extern bool valid_baud(int baud);
 

+ 66 - 1
lowlevel.c

@@ -18,9 +18,19 @@
 #include "compat.h"
 #include "logging.h"
 #include "lowlevel.h"
+#include "miner.h"
 
 static struct lowlevel_device_info *devinfo_list;
 
+#if defined(HAVE_LIBUSB) || defined(NEED_BFG_LOWL_HID)
+char *bfg_make_devid_usb(const uint8_t usbbus, const uint8_t usbaddr)
+{
+	char * const devpath = malloc(12);
+	sprintf(devpath, "usb:%03u:%03u", (unsigned)usbbus, (unsigned)usbaddr);
+	return devpath;
+}
+#endif
+
 void lowlevel_devinfo_semicpy(struct lowlevel_device_info * const dst, const struct lowlevel_device_info * const src)
 {
 #define COPYSTR(key)  BFGINIT(dst->key, maybe_strdup(src->key))
@@ -99,7 +109,7 @@ struct lowlevel_device_info *lowlevel_scan()
 	LL_CONCAT(devinfo_list, devinfo_mid_list);
 #endif
 	
-#ifdef HAVE_FPGAUTILS
+#ifdef NEED_BFG_LOWL_VCOM
 	devinfo_mid_list = lowl_vcom.devinfo_scan();
 	LL_CONCAT(devinfo_list, devinfo_mid_list);
 #endif
@@ -184,3 +194,58 @@ int lowlevel_detect_id(const lowl_found_devinfo_func_t cb, void * const userp, c
 			continue;
 	DETECT_END
 }
+
+
+struct _device_claim {
+	struct device_drv *drv;
+	char *devpath;
+	UT_hash_handle hh;
+};
+
+struct device_drv *bfg_claim_any(struct device_drv * const api, const char *verbose, const char * const devpath)
+{
+	static struct _device_claim *claims = NULL;
+	struct _device_claim *c;
+	
+	HASH_FIND_STR(claims, devpath, c);
+	if (c)
+	{
+		if (verbose && opt_debug)
+		{
+			char logbuf[LOGBUFSIZ];
+			logbuf[0] = '\0';
+			if (api)
+				tailsprintf(logbuf, sizeof(logbuf), "%s device ", api->dname);
+			if (verbose[0])
+				tailsprintf(logbuf, sizeof(logbuf), "%s (%s)", verbose, devpath);
+			else
+				tailsprintf(logbuf, sizeof(logbuf), "%s", devpath);
+			tailsprintf(logbuf, sizeof(logbuf), " already claimed by ");
+			if (api)
+				tailsprintf(logbuf, sizeof(logbuf), "other ");
+			tailsprintf(logbuf, sizeof(logbuf), "driver: %s", c->drv->dname);
+			_applog(LOG_DEBUG, logbuf);
+		}
+		return c->drv;
+	}
+	
+	if (!api)
+		return NULL;
+	
+	c = malloc(sizeof(*c));
+	c->devpath = strdup(devpath);
+	c->drv = api;
+	HASH_ADD_KEYPTR(hh, claims, c->devpath, strlen(devpath), c);
+	return NULL;
+}
+
+struct device_drv *bfg_claim_any2(struct device_drv * const api, const char * const verbose, const char * const llname, const char * const path)
+{
+	const size_t llnamesz = strlen(llname);
+	const size_t pathsz = strlen(path);
+	char devpath[llnamesz + 1 + pathsz + 1];
+	memcpy(devpath, llname, llnamesz);
+	devpath[llnamesz] = ':';
+	memcpy(&devpath[llnamesz+1], path, pathsz + 1);
+	return bfg_claim_any(api, verbose, devpath);
+}

+ 6 - 1
lowlevel.h

@@ -36,6 +36,8 @@ struct lowlevel_device_info {
 	int ref;
 };
 
+extern char *bfg_make_devid_usb(uint8_t usbbus, uint8_t usbaddr);
+
 extern struct lowlevel_device_info *lowlevel_scan();
 extern bool _lowlevel_match_product(const struct lowlevel_device_info *, const char **);
 #define lowlevel_match_product(info, ...)  \
@@ -70,8 +72,11 @@ extern struct lowlevel_driver lowl_usb;
 // Dummy definition for the various "don't warn if just a lower-level interface" checks
 static struct lowlevel_driver lowl_usb;
 #endif
-#ifdef HAVE_FPGAUTILS
+#ifdef NEED_BFG_LOWL_VCOM
 extern struct lowlevel_driver lowl_vcom;
 #endif
 
+extern struct device_drv *bfg_claim_any(struct device_drv *, const char *verbose, const char *devpath);
+extern struct device_drv *bfg_claim_any2(struct device_drv *, const char *verbose, const char *llname, const char *path);
+
 #endif

+ 34 - 3
miner.c

@@ -68,7 +68,6 @@
 #include "logging.h"
 #include "miner.h"
 #include "findnonce.h"
-#include "fpgautils.h"
 #include "adl.h"
 #include "driver-cpu.h"
 #include "driver-opencl.h"
@@ -496,6 +495,32 @@ static void applog_and_exit(const char *fmt, ...)
 	exit(1);
 }
 
+char *devpath_to_devid(const char * const devpath)
+{
+#ifndef WIN32
+	char *devs = malloc(6 + (sizeof(dev_t) * 2) + 1);
+	{
+		struct stat my_stat;
+		if (stat(devpath, &my_stat))
+			return NULL;
+		memcpy(devs, "dev_t:", 6);
+		bin2hex(&devs[6], &my_stat.st_rdev, sizeof(dev_t));
+	}
+#else
+		char *p = strstr(devpath, "COM"), *p2;
+		if (!p)
+			return NULL;
+		const int com = strtol(&p[3], &p2, 10);
+		if (p2 == p)
+			return NULL;
+	char dummy;
+	const int sz = snprintf(&dummy, 1, "%d", com);
+	char *devs = malloc(4 + sz + 1);
+	sprintf(devs, "com:%d", com);
+#endif
+	return devs;
+}
+
 static
 bool devpaths_match(const char * const ap, const char * const bp)
 {
@@ -994,9 +1019,9 @@ char *set_request_diff(const char *arg, float *p)
 	return NULL;
 }
 
+#ifdef NEED_BFG_LOWL_VCOM
 extern struct lowlevel_device_info *_vcom_devinfo_findorcreate(struct lowlevel_device_info **, const char *);
 
-#ifdef HAVE_FPGAUTILS
 #ifdef WIN32
 void _vcom_devinfo_scan_querydosdevice(struct lowlevel_device_info ** const devinfo_list)
 {
@@ -10340,6 +10365,7 @@ void _scan_serial(void *p)
 	}
 }
 
+#ifdef HAVE_BFG_LOWLEVEL
 static
 bool _probe_device_match(const struct lowlevel_device_info * const info, const char * const ser)
 {
@@ -10466,7 +10492,11 @@ void *probe_device_thread(void *p)
 		{
 			LL_FOREACH2(infolist, info, same_devid_next)
 			{
-				if ((info->lowl == &lowl_vcom && !strcasecmp(dname, "all")) || _probe_device_match(info, dname))
+				if (
+#ifdef NEED_BFG_LOWL_VCOM
+					(info->lowl == &lowl_vcom && !strcasecmp(dname, "all")) ||
+#endif
+					_probe_device_match(info, dname))
 				{
 					BFG_FOREACH_DRIVER_BY_PRIORITY(dreg, dreg_tmp)
 					{
@@ -10498,6 +10528,7 @@ void probe_device(struct lowlevel_device_info * const info)
 {
 	pthread_create(&info->probe_pth, NULL, probe_device_thread, info);
 }
+#endif
 
 int create_new_cgpus(void (*addfunc)(void*), void *arg)
 {

+ 1 - 0
miner.h

@@ -1460,6 +1460,7 @@ extern void clean_work(struct work *work);
 extern void free_work(struct work *work);
 extern void __copy_work(struct work *work, const struct work *base_work);
 extern struct work *copy_work(const struct work *base_work);
+extern char *devpath_to_devid(const char *);
 extern struct thr_info *get_thread(int thr_id);
 extern struct cgpu_info *get_devices(int id);
 extern int create_new_cgpus(void (*addfunc)(void*), void *arg);

+ 4 - 4
util.c

@@ -52,8 +52,8 @@
 
 #include <utlist.h>
 
-#ifdef HAVE_FPGAUTILS
-#include "fpgautils.h"
+#ifdef NEED_BFG_LOWL_VCOM
+#include "lowl-vcom.h"
 #endif
 #include "miner.h"
 #include "compat.h"
@@ -2504,7 +2504,7 @@ struct bfgtls_data {
 #ifdef WIN32
 	LPSTR bfg_strerror_socketresult;
 #endif
-#ifdef HAVE_FPGAUTILS
+#ifdef NEED_BFG_LOWL_VCOM
 	struct detectone_meta_info_t __detectone_meta_info;
 #endif
 };
@@ -2534,7 +2534,7 @@ struct bfgtls_data *get_bfgtls()
 	return bfgtls;
 }
 
-#ifdef HAVE_FPGAUTILS
+#ifdef NEED_BFG_LOWL_VCOM
 struct detectone_meta_info_t *_detectone_meta_info()
 {
 	return &get_bfgtls()->__detectone_meta_info;