Browse Source

Merge tag 'bfgminer-3.1.1' into bigpic

BFGMiner version 3.1.1
Luke Dashjr 12 years ago
parent
commit
3814b379fb
25 changed files with 515 additions and 244 deletions
  1. 1 0
      .gitignore
  2. 26 7
      Makefile.am
  3. 50 0
      NEWS
  4. 1 0
      README
  5. 5 2
      README.ASIC
  6. 16 25
      api.c
  7. 3 2
      configure.ac
  8. 37 0
      debian/changelog
  9. 3 3
      debian/control
  10. 1 1
      deviceapi.c
  11. 39 23
      driver-avalon.c
  12. 40 13
      driver-bitforce.c
  13. 5 1
      driver-modminer.c
  14. 2 3
      driver-opencl.c
  15. 1 0
      fpgautils.c
  16. 30 86
      logging.c
  17. 39 10
      logging.h
  18. 4 3
      make-release
  19. 98 56
      miner.c
  20. 9 4
      miner.h
  21. 1 0
      ocl.c
  22. 1 1
      openwrt/bfgminer/Makefile
  23. 1 1
      phatk121016.cl
  24. 89 0
      usbtest.py
  25. 13 3
      util.c

+ 1 - 0
.gitignore

@@ -47,6 +47,7 @@ lib/c++defs.h
 lib/libgnu.a
 lib/libgnu.a
 lib/signal.h
 lib/signal.h
 lib/string.h
 lib/string.h
+lib/stdint.h
 lib/warn-on-use.h
 lib/warn-on-use.h
 
 
 mkinstalldirs
 mkinstalldirs

+ 26 - 7
Makefile.am

@@ -18,11 +18,7 @@ EXTRA_DIST	= \
 dist_doc_DATA = \
 dist_doc_DATA = \
 		  AUTHORS COPYING HACKING NEWS README \
 		  AUTHORS COPYING HACKING NEWS README \
 		  example.conf \
 		  example.conf \
-		  README.ASIC \
-		  README.FPGA \
-		  README.GPU \
-		  README.RPC \
-		  README.scrypt
+		  README.RPC
 
 
 rpcexamplesdir = $(docdir)/rpc-examples
 rpcexamplesdir = $(docdir)/rpc-examples
 dist_rpcexamples_DATA = \
 dist_rpcexamples_DATA = \
@@ -32,6 +28,14 @@ dist_rpcexamples_DATA = \
 
 
 SUBDIRS		= lib ccan
 SUBDIRS		= lib ccan
 
 
+# Without a redirected rule, code depending on different lib/*.h files may try to build dependencies of that in parallel, which can fail
+lib/%: lib_directory
+	@test -e $@
+lib_directory:
+	$(MAKE) -C lib
+ccan/libccan.a:
+	$(MAKE) -C ccan $*
+
 INCLUDES	= -fno-strict-aliasing
 INCLUDES	= -fno-strict-aliasing
 
 
 bin_PROGRAMS	= bfgminer
 bin_PROGRAMS	= bfgminer
@@ -60,16 +64,19 @@ bfgminer_SOURCES	+= miner.h compat.h bench_block.h	\
 	deviceapi.c deviceapi.h \
 	deviceapi.c deviceapi.h \
 		   util.c util.h logging.h		\
 		   util.c util.h logging.h		\
 		   sha2.c sha2.h api.c
 		   sha2.c sha2.h api.c
-bfgminer_DEPENDENCIES =
+EXTRA_bfgminer_DEPENDENCIES =
 
 
 bitstreamsdir = $(pkgdatadir)/bitstreams
 bitstreamsdir = $(pkgdatadir)/bitstreams
 dist_bitstreams_DATA =
 dist_bitstreams_DATA =
 
 
 if NEED_LIBBLKMAKER
 if NEED_LIBBLKMAKER
 SUBDIRS           += libblkmaker
 SUBDIRS           += libblkmaker
+EXTRA_bfgminer_DEPENDENCIES += libblkmaker_directory
+libblkmaker_directory:
+	cd libblkmaker && $(MAKE)
 
 
 if HAVE_CYGWIN
 if HAVE_CYGWIN
-bfgminer_DEPENDENCIES += cygblkmaker-0.1-0.dll cygblkmaker_jansson-0.1-0.dll
+EXTRA_bfgminer_DEPENDENCIES += cygblkmaker-0.1-0.dll cygblkmaker_jansson-0.1-0.dll
 
 
 cyg%.dll: libblkmaker/.libs/cyg%.dll
 cyg%.dll: libblkmaker/.libs/cyg%.dll
 	cp -p $< $@
 	cp -p $< $@
@@ -94,6 +101,8 @@ bfgminer_SOURCES += *.cl
 kernelsdir = $(pkgdatadir)/opencl
 kernelsdir = $(pkgdatadir)/opencl
 dist_kernels_DATA = $(top_srcdir)/*.cl
 dist_kernels_DATA = $(top_srcdir)/*.cl
 
 
+dist_doc_DATA += README.GPU
+
 if HAVE_SENSORS
 if HAVE_SENSORS
 bfgminer_LDADD += $(sensors_LIBS)
 bfgminer_LDADD += $(sensors_LIBS)
 endif
 endif
@@ -103,6 +112,7 @@ endif
 
 
 if HAS_SCRYPT
 if HAS_SCRYPT
 bfgminer_SOURCES += scrypt.c scrypt.h
 bfgminer_SOURCES += scrypt.c scrypt.h
+dist_doc_DATA += README.scrypt
 endif
 endif
 
 
 if HAS_CPUMINE
 if HAS_CPUMINE
@@ -127,9 +137,13 @@ if HAS_YASM
 AM_CFLAGS	= -DHAS_YASM
 AM_CFLAGS	= -DHAS_YASM
 if HAVE_x86_64
 if HAVE_x86_64
 SUBDIRS		+= x86_64
 SUBDIRS		+= x86_64
+x86_64/libx8664.a:
+	$(MAKE) -C x86_64 $*
 bfgminer_LDADD	+= x86_64/libx8664.a
 bfgminer_LDADD	+= x86_64/libx8664.a
 else # HAVE_x86_64
 else # HAVE_x86_64
 SUBDIRS		+= x86_32
 SUBDIRS		+= x86_32
+x86_32/libx8632.a:
+	$(MAKE) -C x86_32 $*
 bfgminer_LDADD	+= x86_32/libx8632.a
 bfgminer_LDADD	+= x86_32/libx8632.a
 
 
 if HAVE_SSE2
 if HAVE_SSE2
@@ -148,6 +162,10 @@ if NEED_DYNCLOCK
 bfgminer_SOURCES += dynclock.c dynclock.h
 bfgminer_SOURCES += dynclock.c dynclock.h
 endif
 endif
 
 
+if HAS_FPGA
+dist_doc_DATA += README.FPGA
+endif
+
 if HAS_BITFORCE
 if HAS_BITFORCE
 bfgminer_SOURCES += driver-bitforce.c
 bfgminer_SOURCES += driver-bitforce.c
 
 
@@ -169,6 +187,7 @@ endif
 
 
 if HAS_AVALON
 if HAS_AVALON
 bfgminer_SOURCES += driver-avalon.c driver-avalon.h hexdump.c
 bfgminer_SOURCES += driver-avalon.c driver-avalon.h hexdump.c
+dist_doc_DATA += README.ASIC
 endif
 endif
 
 
 if HAS_MODMINER
 if HAS_MODMINER

+ 50 - 0
NEWS

@@ -1,3 +1,53 @@
+BFGMiner Version 3.1.1 - June 22, 2013
+- stratum: Deliver exact socket-error within the debug error message
+- Don't install docs for (compile-time) disabled functionality
+- Bugfix: Handle make dependencies on subdirectory files properly
+- Bugfix: Use EXTRA_*_DEPENDENCIES for Cygwin workaround, to fix program make
+dependencies
+- Support new overclocking speeds for avalon: 325, 350 and 375
+- Bugfix: logging: Since we are inlining snprintf, stdio.h is needed
+- Bugfix: serial_autodetect_ftdi: Debuglog FTDI COM port mappings returned, fix
+type of FT_HANDLE
+- Bugfix: Allow starting non-libusb devices if libusb_init fails
+- Bugfix: Add missing newline to libusb_init failure message
+- Bugfix: opencl: Remove unnecessary casts from rot() macro, which created type
+issues
+- Bugfix: Remove unused variables
+- Suspend stratum connections when we know they've failed and don't try to recv
+data from them once the socket no longer exists.
+- applog/quit fix GPU errors created
+- logging remove extra added <LF>
+- remove varargs from logging/quit/in general as much as possible
+- compile unix code on Mac OS X fixes not finding the config file in $HOME
+- Create a pool_localgen bool function for testing when a pool can generate work
+locally.
+- Use mining start time for device MH/U calculations
+- Bugfix: Save start time for stats to correct "Elapsed" key on "stats" RPC
+request
+- modminer: tidy up free in device detect function
+- bitforce: RPC pgaset fanmode 9 for auto fan control
+- Bugfix: usbtest: Correct obvious typos
+- Initial import of usbtest.py script
+- Include microseconds in log output with new --log-microseconds option
+- bitforce: Workaround chip ids not necessarily being in order by choosing
+processor count based on expected chip ids rather than parallelization
+- serial_autodetect_ftdi: Debuglog FTDI COM port mappings returned
+- Bugfix: On stratum disconnect, clear stratum_active and stratum_notify
+atomically along with sock
+- Windows: Use backtrace.dll to print usable backtraces to stderr on crash
+- Bugfix: bitforce: parallelized: Properly handle parallelized protocol with
+only 1 chip
+- Bugfix: bitforce: XLINK: Increment boardno when moving on to the next board
+- bitforce: XLINK: Update to use actual length,xlinkid header order
+- Bugfix: bitforce: XLINK: Avoid trying to send 0 bytes after each write
+- Bugfix: opencl: Build fpgautils even if OpenCL is the only driver, now that it
+uses it for kernel-finding
+- Bugfix: Do not try to call get_stats or get_statline* if device is still
+initializing
+- Bugfix: opencl: Add missing include for fpgautils.h (needed for
+open_bitstream)
+
+
 BFGMiner Version 3.1.0 - June 13, 2013
 BFGMiner Version 3.1.0 - June 13, 2013
 - Bugfix: openwrt: Expect fixed bitstream path for input
 - Bugfix: openwrt: Expect fixed bitstream path for input
 - Improve Makefile organization and fix "make install"
 - Improve Makefile organization and fix "make install"

+ 1 - 0
README

@@ -178,6 +178,7 @@ Options for both config file and command line:
 --kernel-path|-K <arg> Specify a path to where bitstream and kernel files are (default: "/usr/local/bin")
 --kernel-path|-K <arg> Specify a path to where bitstream and kernel files are (default: "/usr/local/bin")
 --load-balance      Change multipool strategy from failover to efficiency based balance
 --load-balance      Change multipool strategy from failover to efficiency based balance
 --log|-l <arg>      Interval in seconds between log output (default: 5)
 --log|-l <arg>      Interval in seconds between log output (default: 5)
+--log-microseconds  Include microseconds in log output
 --monitor|-m <arg>  Use custom pipe cmd for output messages
 --monitor|-m <arg>  Use custom pipe cmd for output messages
 --net-delay         Impose small delays in networking to not overload slow routers
 --net-delay         Impose small delays in networking to not overload slow routers
 --no-gbt            Disable getblocktemplate support
 --no-gbt            Disable getblocktemplate support

+ 5 - 2
README.ASIC

@@ -40,7 +40,10 @@ It is possible to set this a little lower if you are trying to tune for short
 block mining (eg p2pool) but much lower and the device will start creating
 block mining (eg p2pool) but much lower and the device will start creating
 duplicate shares.
 duplicate shares.
 
 
-Sample settings for different frequencies (last 2 values):
+Sample settings for valid different frequencies (last 2 values):
+34:375
+36:350
+39:325
 43:300
 43:300
 45:282
 45:282
 47:270
 47:270
@@ -48,7 +51,7 @@ Sample settings for different frequencies (last 2 values):
 
 
 Frequency:
 Frequency:
 This is the clock speed of the devices. Only specific values work, 256, 270,
 This is the clock speed of the devices. Only specific values work, 256, 270,
-282 (default) and 300.
+282 (default), 300, 325, 350 and 375.
 
 
 If you use the full curses based interface with Avalons you will get this
 If you use the full curses based interface with Avalons you will get this
 information:
 information:

+ 16 - 25
api.c

@@ -124,7 +124,6 @@ char *WSAErrorMsg(void) {
 #endif
 #endif
 
 
 static const char *UNAVAILABLE = " - API will not be available";
 static const char *UNAVAILABLE = " - API will not be available";
-static const char *INVAPIGROUPS = "Invalid --api-groups parameter";
 
 
 static const char *BLANK = "";
 static const char *BLANK = "";
 static const char *COMMA = ",";
 static const char *COMMA = ",";
@@ -1488,7 +1487,7 @@ static void devdetail_an(struct io_data *io_data, struct cgpu_info *cgpu, bool i
 	char buf[TMPBUFSIZ];
 	char buf[TMPBUFSIZ];
 	int n = 0, i;
 	int n = 0, i;
 
 
-	cgpu->utility = cgpu->accepted / ( total_secs ? total_secs : 1 ) * 60;
+	cgpu_utility(cgpu);
 
 
 	rd_lock(&devices_lock);
 	rd_lock(&devices_lock);
 	for (i = 0; i < total_devices; ++i) {
 	for (i = 0; i < total_devices; ++i) {
@@ -1522,7 +1521,7 @@ static void devstatus_an(struct io_data *io_data, struct cgpu_info *cgpu, bool i
 	char buf[TMPBUFSIZ];
 	char buf[TMPBUFSIZ];
 	int n = 0, i;
 	int n = 0, i;
 
 
-	cgpu->utility = cgpu->accepted / ( total_secs ? total_secs : 1 ) * 60;
+	cgpu_utility(cgpu);
 
 
 	rd_lock(&devices_lock);
 	rd_lock(&devices_lock);
 	for (i = 0; i < total_devices; ++i) {
 	for (i = 0; i < total_devices; ++i) {
@@ -1539,7 +1538,7 @@ static void devstatus_an(struct io_data *io_data, struct cgpu_info *cgpu, bool i
 	root = api_add_string(root, "Status", status2str(cgpu->status), false);
 	root = api_add_string(root, "Status", status2str(cgpu->status), false);
 	if (cgpu->temp)
 	if (cgpu->temp)
 		root = api_add_temp(root, "Temperature", &cgpu->temp, false);
 		root = api_add_temp(root, "Temperature", &cgpu->temp, false);
-	double mhs = cgpu->total_mhashes / total_secs;
+	double mhs = cgpu->total_mhashes / cgpu_runtime(cgpu);
 	root = api_add_mhs(root, "MHS av", &mhs, false);
 	root = api_add_mhs(root, "MHS av", &mhs, false);
 	char mhsname[27];
 	char mhsname[27];
 	sprintf(mhsname, "MHS %ds", opt_log_interval);
 	sprintf(mhsname, "MHS %ds", opt_log_interval);
@@ -2771,10 +2770,12 @@ static int itemstats(struct io_data *io_data, int i, char *id, struct cgminer_st
 {
 {
 	struct api_data *root = NULL;
 	struct api_data *root = NULL;
 	char buf[TMPBUFSIZ];
 	char buf[TMPBUFSIZ];
+	double elapsed;
 
 
 	root = api_add_int(root, "STATS", &i, false);
 	root = api_add_int(root, "STATS", &i, false);
 	root = api_add_string(root, "ID", id, false);
 	root = api_add_string(root, "ID", id, false);
-	root = api_add_elapsed(root, "Elapsed", &(total_secs), false);
+	elapsed = stats_elapsed(stats);
+	root = api_add_elapsed(root, "Elapsed", &elapsed, false);
 	root = api_add_uint32(root, "Calls", &(stats->getwork_calls), false);
 	root = api_add_uint32(root, "Calls", &(stats->getwork_calls), false);
 	root = api_add_timeval(root, "Wait", &(stats->getwork_wait), false);
 	root = api_add_timeval(root, "Wait", &(stats->getwork_wait), false);
 	root = api_add_timeval(root, "Max", &(stats->getwork_wait_max), false);
 	root = api_add_timeval(root, "Max", &(stats->getwork_wait_max), false);
@@ -3362,30 +3363,21 @@ static void setup_groups()
 			colon = strchr(ptr, ':');
 			colon = strchr(ptr, ':');
 			if (colon)
 			if (colon)
 				*colon = '\0';
 				*colon = '\0';
-			applog(LOG_WARNING, "API invalid group name '%s'", ptr);
-			quit(1, "%s", INVAPIGROUPS);
+			quit(1, "API invalid group name '%s'", ptr);
 		}
 		}
 
 
 		group = GROUP(*ptr);
 		group = GROUP(*ptr);
-		if (!VALIDGROUP(group)) {
-			applog(LOG_WARNING, "API invalid group name '%c'", *ptr);
-			quit(1, "%s", INVAPIGROUPS);
-		}
+		if (!VALIDGROUP(group))
+			quit(1, "API invalid group name '%c'", *ptr);
 
 
-		if (group == PRIVGROUP) {
-			applog(LOG_WARNING, "API group name can't be '%c'", PRIVGROUP);
-			quit(1, "%s", INVAPIGROUPS);
-		}
+		if (group == PRIVGROUP)
+			quit(1, "API group name can't be '%c'", PRIVGROUP);
 
 
-		if (group == NOPRIVGROUP) {
-			applog(LOG_WARNING, "API group name can't be '%c'", NOPRIVGROUP);
-			quit(1, "%s", INVAPIGROUPS);
-		}
+		if (group == NOPRIVGROUP)
+			quit(1, "API group name can't be '%c'", NOPRIVGROUP);
 
 
-		if (apigroups[GROUPOFFSET(group)].commands != NULL) {
-			applog(LOG_WARNING, "API duplicate group name '%c'", *ptr);
-			quit(1, "%s", INVAPIGROUPS);
-		}
+		if (apigroups[GROUPOFFSET(group)].commands != NULL)
+			quit(1, "API duplicate group name '%c'", *ptr);
 
 
 		ptr += 2;
 		ptr += 2;
 
 
@@ -3419,8 +3411,7 @@ static void setup_groups()
 						*cmd = '\0';
 						*cmd = '\0';
 					}
 					}
 				} else {
 				} else {
-					applog(LOG_WARNING, "API unknown command '%s' in group '%c'", ptr, group);
-					quit(1, "%s", INVAPIGROUPS);
+					quit(1, "API unknown command '%s' in group '%c'", ptr, group);
 				}
 				}
 			}
 			}
 
 

+ 3 - 2
configure.ac

@@ -14,7 +14,7 @@ dnl * any later version.  See COPYING for more details.
 ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
 ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
 m4_define([v_maj], [3])
 m4_define([v_maj], [3])
 m4_define([v_min], [1])
 m4_define([v_min], [1])
-m4_define([v_mic], [0])
+m4_define([v_mic], [1])
 ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
 ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
 m4_define([v_ver], [v_maj.v_min.v_mic])
 m4_define([v_ver], [v_maj.v_min.v_mic])
 m4_define([lt_rev], m4_eval(v_maj + v_min))
 m4_define([lt_rev], m4_eval(v_maj + v_min))
@@ -536,13 +536,14 @@ AC_SUBST(libblkmaker_LIBS)
 
 
 AM_CONDITIONAL([NEED_LIBBLKMAKER], [test x$with_system_libblkmaker != xyes])
 AM_CONDITIONAL([NEED_LIBBLKMAKER], [test x$with_system_libblkmaker != xyes])
 AM_CONDITIONAL([NEED_DYNCLOCK], [test x$icarus$modminer$x6500$ztex != xnonono])
 AM_CONDITIONAL([NEED_DYNCLOCK], [test x$icarus$modminer$x6500$ztex != xnonono])
-AM_CONDITIONAL([NEED_FPGAUTILS], [test x$avalon$icarus$bitforce$modminer$x6500$ztex != xnononononono])
+AM_CONDITIONAL([NEED_FPGAUTILS], [test x$avalon$icarus$bitforce$modminer$opencl$x6500$ztex != xnonononononono])
 AM_CONDITIONAL([HAS_SCRYPT], [test x$scrypt = xyes])
 AM_CONDITIONAL([HAS_SCRYPT], [test x$scrypt = xyes])
 AM_CONDITIONAL([HAVE_CURSES], [test x$curses = xyes])
 AM_CONDITIONAL([HAVE_CURSES], [test x$curses = xyes])
 AM_CONDITIONAL([HAVE_SENSORS], [test x$with_sensors = xyes])
 AM_CONDITIONAL([HAVE_SENSORS], [test x$with_sensors = xyes])
 AM_CONDITIONAL([HAVE_CYGWIN], [test x$have_cygwin = xtrue])
 AM_CONDITIONAL([HAVE_CYGWIN], [test x$have_cygwin = xtrue])
 AM_CONDITIONAL([HAVE_WINDOWS], [test x$have_win32 = xtrue])
 AM_CONDITIONAL([HAVE_WINDOWS], [test x$have_win32 = xtrue])
 AM_CONDITIONAL([HAVE_x86_64], [test x$have_x86_64 = xtrue])
 AM_CONDITIONAL([HAVE_x86_64], [test x$have_x86_64 = xtrue])
+AM_CONDITIONAL([HAS_FPGA], [test x$bitforce$icarus$modminer$x6500$ztex != xnonononono])
 
 
 dnl Find YASM
 dnl Find YASM
 has_yasm=false
 has_yasm=false

+ 37 - 0
debian/changelog

@@ -1,3 +1,40 @@
+bfgminer (3.1.1-0precise1) precise; urgency=low
+
+  * bitforce: Support for Little Single boards, and Jalapenos with 1.2 firmware.
+  * avalon: Support new overclocking speeds (325, 350 and 375).
+  * Fixed a bunch of bugs, including GPU mining and at least one stratum-related crash.
+
+ -- Luke Dashjr <luke+bfgminer@dashjr.org>  Thu, 22 Jun 2013 17:41:21 -0000
+
+bfgminer (3.1.0-1precise1) precise; urgency=low
+
+  * Properly added in new submodules to Debian packaging.
+  * Added missing fpgautils.h include.
+
+ -- graeme <graeme@sudo.ca>  Fri, 14 Jun 2013 09:52:55 -0700
+
+bfgminer (3.1.0-0precise1) precise; urgency=low
+
+  * BitForce: Support for new long-board job-per-chip protocol.
+  * Reformatted TUI summaries, including percentage of shares rejected or stale.
+  * Icarus-compatible devices: Autodetect work_division by default (eg, for Block Erupter USB ASICs).
+  * Avalon: Driver is now compiled in by default, including in official binaries
+  * Avalon: Will only configure with specific -S avalon:/dev/ttyUSBn option (note the driver name must be included), since there is no reliable probe for it.
+  * Avalon: Full data for 4-module devices in RPC.
+  * OpenCL: Support for reading temperature from free software radeon drivers via libsensors.
+  * Fixes for writing configuration files when --device and/or --remove-disabled are specified.
+  * Faster startup now when pools are slow, connecting to the first pool available!
+  * Adding a pool now from the menu will return quickly while it leaves probing it to the background.
+  * Scrypt: Fixed the failure to create high thread concurrencies.
+  * Scrypt: Intensities above 13 will not lead to garbage being generated on GCN (7xxx) hardware now.
+  * Scrypt: Decreased default GPU threads to 1. Intensities above 13 cannot handle more.
+  * Scrypt: Changed the default choice of thread concurrency if no options are passed as a hint, based on amount of available GPU RAM.
+  * Scrypt: Extensive updates to the SCRYPT-README file in line with changes to the code and new information.
+  * Scrypt: Slightly larger buffer which may lead to less hardware errors on very fast GPUs.
+  * CPU mining: Numerous improvements to portability.
+
+ -- Luke Dashjr <luke+bfgminer@dashjr.org>  Thu, 13 Jun 2013 20:05:29 -0000
+
 bfgminer (3.0.2-1precise1) precise; urgency=low
 bfgminer (3.0.2-1precise1) precise; urgency=low
 
 
   * Added scrypt build option.
   * Added scrypt build option.

+ 3 - 3
debian/control

@@ -2,12 +2,12 @@ Source: bfgminer
 Priority: optional
 Priority: optional
 Section: misc
 Section: misc
 Maintainer: Luke Dashjr <luke_bfgminer@dashjr.org>
 Maintainer: Luke Dashjr <luke_bfgminer@dashjr.org>
-Standards-Version: 3.0.2
-Build-Depends: build-essential, debhelper, autoconf, automake, libtool, libssl-dev, yasm, pkg-config, libudev-dev, libcurl4-openssl-dev, wget, unzip, libjansson-dev, libncurses5-dev, libudev-dev, libusb-1.0-0-dev, git, quilt
+Standards-Version: 3.1.1
+Build-Depends: build-essential, debhelper, autoconf, automake, libtool, libssl-dev, yasm, pkg-config, libudev-dev, libcurl4-openssl-dev, wget, unzip, libjansson-dev, libncurses5-dev, libudev-dev, libusb-1.0-0-dev, git, quilt, uthash-dev, libsensors4-dev
 
 
 Package: bfgminer
 Package: bfgminer
 Architecture: any
 Architecture: any
-Depends: libjansson4, libudev0 | libudev1, libcurl3, libncurses5, libusb-1.0-0
+Depends: libjansson4, libudev0 | libudev1, libcurl3, libncurses5, libusb-1.0-0, libsensors4
 Description: This is a multi-threaded multi-pool GPU, FPGA and CPU miner with ATI GPU
 Description: This is a multi-threaded multi-pool GPU, FPGA and CPU miner with ATI GPU
  monitoring, (over)clocking and fanspeed support for bitcoin and derivative
  monitoring, (over)clocking and fanspeed support for bitcoin and derivative
  coins.
  coins.

+ 1 - 1
deviceapi.c

@@ -552,7 +552,6 @@ redo:
 void *miner_thread(void *userdata)
 void *miner_thread(void *userdata)
 {
 {
 	struct thr_info *mythr = userdata;
 	struct thr_info *mythr = userdata;
-	const int thr_id = mythr->id;
 	struct cgpu_info *cgpu = mythr->cgpu;
 	struct cgpu_info *cgpu = mythr->cgpu;
 	struct device_drv *drv = cgpu->drv;
 	struct device_drv *drv = cgpu->drv;
 
 
@@ -574,6 +573,7 @@ void *miner_thread(void *userdata)
 	applog(LOG_DEBUG, "Popping ping in miner thread");
 	applog(LOG_DEBUG, "Popping ping in miner thread");
 	notifier_read(mythr->notifier);  // Wait for a notification to start
 	notifier_read(mythr->notifier);  // Wait for a notification to start
 
 
+	cgtime(&cgpu->cgminer_stats.start_tv);
 	if (drv->minerloop)
 	if (drv->minerloop)
 		drv->minerloop(mythr);
 		drv->minerloop(mythr);
 	else
 	else

+ 39 - 23
driver-avalon.c

@@ -96,18 +96,36 @@ static int avalon_init_task(struct avalon_task *at,
 	buf[9] = 0x01;
 	buf[9] = 0x01;
 	buf[10] = 0x00;
 	buf[10] = 0x00;
 	buf[11] = 0x00;
 	buf[11] = 0x00;
-	if (frequency == 256) {
-		buf[6] = 0x03;
-		buf[7] = 0x08;
-	} else if (frequency == 270) {
-		buf[6] = 0x73;
-		buf[7] = 0x08;
-	} else if (frequency == 282) {
-		buf[6] = 0xd3;
-		buf[7] = 0x08;
-	} else if (frequency == 300) {
-		buf[6] = 0x63;
-		buf[7] = 0x09;
+	switch (frequency) {
+		case 256:
+			buf[6] = 0x03;
+			buf[7] = 0x08;
+			break;
+		default:
+		case 270:
+			buf[6] = 0x73;
+			buf[7] = 0x08;
+			break;
+		case 282:
+			buf[6] = 0xd3;
+			buf[7] = 0x08;
+			break;
+		case 300:
+			buf[6] = 0x63;
+			buf[7] = 0x09;
+			break;
+		case 325:
+			buf[6] = 0x28;
+			buf[7] = 0x0a;
+			break;
+		case 350:
+			buf[6] = 0xf0;
+			buf[7] = 0x0a;
+			break;
+		case 375:
+			buf[6] = 0xb8;
+			buf[7] = 0x0b;
+			break;
 	}
 	}
 
 
 	return 0;
 	return 0;
@@ -454,8 +472,7 @@ static void get_options(int this_option_offset, int *baud, int *miner_count,
 		*baud = 19200;
 		*baud = 19200;
 		break;
 		break;
 	default:
 	default:
-		quit(1,
-			"Invalid avalon-options for baud (%s) "
+		quit(1, "Invalid avalon-options for baud (%s) "
 			"must be 115200, 57600, 38400 or 19200", buf);
 			"must be 115200, 57600, 38400 or 19200", buf);
 	}
 	}
 
 
@@ -469,8 +486,7 @@ static void get_options(int this_option_offset, int *baud, int *miner_count,
 			if (tmp > 0 && tmp <= AVALON_DEFAULT_MINER_NUM) {
 			if (tmp > 0 && tmp <= AVALON_DEFAULT_MINER_NUM) {
 				*miner_count = tmp;
 				*miner_count = tmp;
 			} else {
 			} else {
-				quit(1,
-					"Invalid avalon-options for "
+				quit(1, "Invalid avalon-options for "
 					"miner_count (%s) must be 1 ~ %d",
 					"miner_count (%s) must be 1 ~ %d",
 					colon, AVALON_DEFAULT_MINER_NUM);
 					colon, AVALON_DEFAULT_MINER_NUM);
 			}
 			}
@@ -485,8 +501,7 @@ static void get_options(int this_option_offset, int *baud, int *miner_count,
 			if (tmp > 0 && tmp <= AVALON_DEFAULT_ASIC_NUM)
 			if (tmp > 0 && tmp <= AVALON_DEFAULT_ASIC_NUM)
 				*asic_count = tmp;
 				*asic_count = tmp;
 			else {
 			else {
-				quit(1,
-					"Invalid avalon-options for "
+				quit(1, "Invalid avalon-options for "
 					"asic_count (%s) must be 1 ~ %d",
 					"asic_count (%s) must be 1 ~ %d",
 					colon2, AVALON_DEFAULT_ASIC_NUM);
 					colon2, AVALON_DEFAULT_ASIC_NUM);
 			}
 			}
@@ -500,8 +515,7 @@ static void get_options(int this_option_offset, int *baud, int *miner_count,
 				if (tmp > 0 && tmp <= 0xff)
 				if (tmp > 0 && tmp <= 0xff)
 					*timeout = tmp;
 					*timeout = tmp;
 				else {
 				else {
-					quit(1,
-						"Invalid avalon-options for "
+					quit(1, "Invalid avalon-options for "
 						"timeout (%s) must be 1 ~ %d",
 						"timeout (%s) must be 1 ~ %d",
 						colon3, 0xff);
 						colon3, 0xff);
 				}
 				}
@@ -512,12 +526,14 @@ static void get_options(int this_option_offset, int *baud, int *miner_count,
 					case 270:
 					case 270:
 					case 282:
 					case 282:
 					case 300:
 					case 300:
+					case 325:
+					case 350:
+					case 375:
 						*frequency = tmp;
 						*frequency = tmp;
 						break;
 						break;
 					default:
 					default:
-						quit(1,
-							"Invalid avalon-options for "
-							"frequency must be 256/270/282/300");
+						quit(1, "Invalid avalon-options for "
+							"frequency must be 256/270/282/300/325/350/375");
 					}
 					}
 				}
 				}
 			}
 			}

+ 40 - 13
driver-bitforce.c

@@ -98,16 +98,17 @@ static ssize_t bitforce_send(int fd, int procid, const void *buf, ssize_t bufLen
 	ssize_t rv;
 	ssize_t rv;
 	memcpy(&realbuf[3], buf, bufLen);
 	memcpy(&realbuf[3], buf, bufLen);
 	realbuf[0] = '@';
 	realbuf[0] = '@';
-	realbuf[1] = procid;
-	realbuf[2] = bufLen;
+	realbuf[1] = bufLen;
+	realbuf[2] = procid;
 	bufp = realbuf;
 	bufp = realbuf;
-	while (true)
+	do
 	{
 	{
 		rv = BFwrite(fd, bufp, bufLeft);
 		rv = BFwrite(fd, bufp, bufLeft);
 		if (rv <= 0)
 		if (rv <= 0)
 			return rv;
 			return rv;
 		bufLeft -= rv;
 		bufLeft -= rv;
 	}
 	}
+	while (bufLeft > 0);
 	return bufLen;
 	return bufLen;
 }
 }
 
 
@@ -147,6 +148,18 @@ struct bitforce_init_data {
 	int *parallels;
 	int *parallels;
 };
 };
 
 
+static
+int bitforce_chips_to_plan_for(int parallel, int chipcount) {
+	if (parallel < 1)
+		return parallel;
+	if (chipcount > 15) return 32;
+	if (chipcount >  7) return 16;
+	if (chipcount >  3) return  8;
+	if (chipcount >  1) return  4;
+	if (chipcount     ) return  2;
+	                    return  1;
+}
+
 static bool bitforce_detect_one(const char *devpath)
 static bool bitforce_detect_one(const char *devpath)
 {
 {
 	int fdDev = serial_open(devpath, 0, 10, true);
 	int fdDev = serial_open(devpath, 0, 10, true);
@@ -154,7 +167,8 @@ static bool bitforce_detect_one(const char *devpath)
 	char pdevbuf[0x100];
 	char pdevbuf[0x100];
 	size_t pdevbuf_len;
 	size_t pdevbuf_len;
 	char *s;
 	char *s;
-	int procs = 1, parallel = 1;
+	int procs = 1, parallel = -1;
+	long maxchipno = 0;
 	struct bitforce_init_data *initdata;
 	struct bitforce_init_data *initdata;
 
 
 	applog(LOG_DEBUG, "BFL: Attempting to open %s", devpath);
 	applog(LOG_DEBUG, "BFL: Attempting to open %s", devpath);
@@ -195,6 +209,9 @@ static bool bitforce_detect_one(const char *devpath)
 		
 		
 		applog(LOG_DEBUG, "  %s", pdevbuf);
 		applog(LOG_DEBUG, "  %s", pdevbuf);
 		
 		
+		if (!strncasecmp(pdevbuf, "PROCESSOR ", 10))
+			maxchipno = max(maxchipno, atoi(&pdevbuf[10]));
+		else
 		if (!strncasecmp(pdevbuf, "DEVICES IN CHAIN:", 17))
 		if (!strncasecmp(pdevbuf, "DEVICES IN CHAIN:", 17))
 			procs = atoi(&pdevbuf[17]);
 			procs = atoi(&pdevbuf[17]);
 		else
 		else
@@ -207,13 +224,16 @@ static bool bitforce_detect_one(const char *devpath)
 		if (!strncasecmp(pdevbuf, "CHIP PARALLELIZATION: YES @", 27))
 		if (!strncasecmp(pdevbuf, "CHIP PARALLELIZATION: YES @", 27))
 			parallel = atoi(&pdevbuf[27]);
 			parallel = atoi(&pdevbuf[27]);
 	}
 	}
+	parallel = bitforce_chips_to_plan_for(parallel, maxchipno);
 	initdata->parallels = malloc(sizeof(initdata->parallels[0]) * procs);
 	initdata->parallels = malloc(sizeof(initdata->parallels[0]) * procs);
 	initdata->parallels[0] = parallel;
 	initdata->parallels[0] = parallel;
+	parallel = abs(parallel);
 	for (int proc = 1; proc < procs; ++proc)
 	for (int proc = 1; proc < procs; ++proc)
 	{
 	{
 		applog(LOG_DEBUG, "Slave board %d:", proc);
 		applog(LOG_DEBUG, "Slave board %d:", proc);
-		initdata->parallels[proc] = 1;
-		bitforce_cmd1(fdDev, 0, pdevbuf, sizeof(pdevbuf), "ZCX");
+		initdata->parallels[proc] = -1;
+		maxchipno = 0;
+		bitforce_cmd1(fdDev, proc, pdevbuf, sizeof(pdevbuf), "ZCX");
 		for (int i = 0; (!pdevbuf[0]) && i < 4; ++i)
 		for (int i = 0; (!pdevbuf[0]) && i < 4; ++i)
 			BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
 			BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
 		for ( ;
 		for ( ;
@@ -227,17 +247,21 @@ static bool bitforce_detect_one(const char *devpath)
 			
 			
 			applog(LOG_DEBUG, "  %s", pdevbuf);
 			applog(LOG_DEBUG, "  %s", pdevbuf);
 			
 			
+			if (!strncasecmp(pdevbuf, "PROCESSOR ", 10))
+				maxchipno = max(maxchipno, atoi(&pdevbuf[10]));
+			else
 			if (!strncasecmp(pdevbuf, "CHIP PARALLELIZATION: YES @", 27))
 			if (!strncasecmp(pdevbuf, "CHIP PARALLELIZATION: YES @", 27))
 				initdata->parallels[proc] = atoi(&pdevbuf[27]);
 				initdata->parallels[proc] = atoi(&pdevbuf[27]);
 		}
 		}
-		parallel += initdata->parallels[proc];
+		initdata->parallels[proc] = bitforce_chips_to_plan_for(initdata->parallels[proc], maxchipno);
+		parallel += abs(initdata->parallels[proc]);
 	}
 	}
 	BFclose(fdDev);
 	BFclose(fdDev);
 	
 	
-	if (unlikely(procs < parallel && !initdata->sc))
+	if (unlikely((procs != 1 || parallel != 1) && !initdata->sc))
 	{
 	{
-		// Only bitforce_queue supports parallelization, so force SC mode and hope for the best
-		applog(LOG_WARNING, "Chip parallelization detected with non-SC device; this is not supported!");
+		// Only bitforce_queue supports parallelization and XLINK, so force SC mode and hope for the best
+		applog(LOG_WARNING, "SC features detected with non-SC device; this is not supported!");
 		initdata->sc = true;
 		initdata->sc = true;
 	}
 	}
 	
 	
@@ -285,6 +309,7 @@ struct bitforce_data {
 	int queued;
 	int queued;
 	int queued_max;
 	int queued_max;
 	int parallel;
 	int parallel;
+	bool parallel_protocol;
 	bool already_have_results;
 	bool already_have_results;
 	bool just_flushed;
 	bool just_flushed;
 	int ready_to_queue;
 	int ready_to_queue;
@@ -1248,7 +1273,8 @@ static bool bitforce_thread_init(struct thr_info *thr)
 			.proto = BFP_RANGE,
 			.proto = BFP_RANGE,
 			.sc = sc,
 			.sc = sc,
 			.sleep_ms_default = BITFORCE_SLEEP_MS,
 			.sleep_ms_default = BITFORCE_SLEEP_MS,
-			.parallel = initdata->parallels[boardno],
+			.parallel = abs(initdata->parallels[boardno]),
+			.parallel_protocol = (initdata->parallels[boardno] != -1),
 		};
 		};
 		thr->cgpu_data = procdata = malloc(sizeof(*procdata));
 		thr->cgpu_data = procdata = malloc(sizeof(*procdata));
 		*procdata = (struct bitforce_proc_data){
 		*procdata = (struct bitforce_proc_data){
@@ -1303,6 +1329,7 @@ static bool bitforce_thread_init(struct thr_info *thr)
 		}
 		}
 		applog(LOG_DEBUG, "%s: Board %d: %"PRIpreprv"-%"PRIpreprv, bitforce->dev_repr, boardno, first_on_this_board->cgpu->proc_repr, bitforce->proc_repr);
 		applog(LOG_DEBUG, "%s: Board %d: %"PRIpreprv"-%"PRIpreprv, bitforce->dev_repr, boardno, first_on_this_board->cgpu->proc_repr, bitforce->proc_repr);
 		
 		
+		++boardno;
 		while (xlink_id < 31 && !(initdata->devmask & (1 << ++xlink_id)))
 		while (xlink_id < 31 && !(initdata->devmask & (1 << ++xlink_id)))
 		{}
 		{}
 	}
 	}
@@ -1382,7 +1409,7 @@ char *bitforce_set_device(struct cgpu_info *proc, char *option, char *setting, c
 			sprintf(replybuf, "missing fanmode setting");
 			sprintf(replybuf, "missing fanmode setting");
 			return replybuf;
 			return replybuf;
 		}
 		}
-		if (setting[1] || setting[0] < '0' || setting[0] > '5')
+		if (setting[1] || ((setting[0] < '0' || setting[0] > '5') && setting[0] != '9'))
 		{
 		{
 			sprintf(replybuf, "invalid fanmode setting");
 			sprintf(replybuf, "invalid fanmode setting");
 			return replybuf;
 			return replybuf;
@@ -1575,7 +1602,7 @@ bool bitforce_queue_do_results(struct thr_info *thr)
 		
 		
 		end = &buf[89];
 		end = &buf[89];
 		chip_cgpu = bitforce;
 		chip_cgpu = bitforce;
-		if (data->parallel > 1)
+		if (data->parallel_protocol)
 		{
 		{
 			chipno = strtol(&end[1], &end, 16);
 			chipno = strtol(&end[1], &end, 16);
 			if (chipno >= data->parallel)
 			if (chipno >= data->parallel)

+ 5 - 1
driver-modminer.c

@@ -85,9 +85,12 @@ _bailout(int fd, struct cgpu_info*modminer, int prio, const char *fmt, ...)
 	}
 	}
 
 
 	va_list ap;
 	va_list ap;
+	char buf[LOGBUFSIZ];
+	
 	va_start(ap, fmt);
 	va_start(ap, fmt);
-	vapplog(prio, fmt, ap);
+	vsnprintf(buf, sizeof(buf), fmt, ap);
 	va_end(ap);
 	va_end(ap);
+	_applog(prio, buf);
 	return false;
 	return false;
 }
 }
 #define bailout(...)  return _bailout(fd, NULL, __VA_ARGS__);
 #define bailout(...)  return _bailout(fd, NULL, __VA_ARGS__);
@@ -792,6 +795,7 @@ static void
 modminer_fpga_shutdown(struct thr_info *thr)
 modminer_fpga_shutdown(struct thr_info *thr)
 {
 {
 	free(thr->cgpu_data);
 	free(thr->cgpu_data);
+	thr->cgpu_data = NULL;
 }
 }
 
 
 static char *modminer_set_device(struct cgpu_info *modminer, char *option, char *setting, char *replybuf)
 static char *modminer_set_device(struct cgpu_info *modminer, char *option, char *setting, char *replybuf)

+ 2 - 3
driver-opencl.c

@@ -265,7 +265,6 @@ extern void enable_curses(void);
 #endif
 #endif
 
 
 extern int mining_threads;
 extern int mining_threads;
-extern double total_secs;
 extern int opt_g_threads;
 extern int opt_g_threads;
 extern bool ping;
 extern bool ping;
 extern bool opt_loginput;
 extern bool opt_loginput;
@@ -856,7 +855,7 @@ retry:
 		bool mhash_base = true;
 		bool mhash_base = true;
 
 
 		displayed_rolling = cgpu->rolling;
 		displayed_rolling = cgpu->rolling;
-		displayed_total = cgpu->total_mhashes / total_secs;
+		displayed_total = cgpu->total_mhashes / cgpu_runtime(cgpu);
 		if (displayed_rolling < 1) {
 		if (displayed_rolling < 1) {
 			displayed_rolling *= 1000;
 			displayed_rolling *= 1000;
 			displayed_total *= 1000;
 			displayed_total *= 1000;
@@ -898,7 +897,7 @@ retry:
 				if (powertune != -1)
 				if (powertune != -1)
 					tailsprintf(logline, "P: %d%%", powertune);
 					tailsprintf(logline, "P: %d%%", powertune);
 				tailsprintf(logline, "\n");
 				tailsprintf(logline, "\n");
-				wlog("%s", logline);
+				_wlog(logline);
 			}
 			}
 		}
 		}
 #endif
 #endif

+ 1 - 0
fpgautils.c

@@ -316,6 +316,7 @@ int _serial_autodetect_ftdi(detectone_func_t detectone, va_list needles)
 		if (FT_OK != ftStatus || lComPortNumber < 0)
 		if (FT_OK != ftStatus || lComPortNumber < 0)
 			continue;
 			continue;
 		
 		
+		applog(LOG_ERR, "FT_GetComPortNumber(%p (%ld), %ld)", ftHandle, (long)i, (long)lComPortNumber);
 		sprintf(devpathnum, "%d", (int)lComPortNumber);
 		sprintf(devpathnum, "%d", (int)lComPortNumber);
 		
 		
 		if (detectone(devpath))
 		if (detectone(devpath))

+ 30 - 86
logging.c

@@ -1,6 +1,7 @@
 /*
 /*
  * Copyright 2011-2012 Con Kolivas
  * Copyright 2011-2012 Con Kolivas
  * Copyright 2012-2013 Luke Dashjr
  * Copyright 2012-2013 Luke Dashjr
+ * Copyright 2013 Andrew Smith
  *
  *
  * This program is free software; you can redistribute it and/or modify it
  * 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
  * under the terms of the GNU General Public License as published by the Free
@@ -15,75 +16,48 @@
 #include "compat.h"
 #include "compat.h"
 #include "logging.h"
 #include "logging.h"
 #include "miner.h"
 #include "miner.h"
-// #include "util.h"
 
 
 bool opt_debug = false;
 bool opt_debug = false;
 bool opt_debug_console = false;  // Only used if opt_debug is also enabled
 bool opt_debug_console = false;  // Only used if opt_debug is also enabled
 bool opt_log_output = false;
 bool opt_log_output = false;
+bool opt_log_microseconds;
 
 
 /* per default priorities higher than LOG_NOTICE are logged */
 /* per default priorities higher than LOG_NOTICE are logged */
 int opt_log_level = LOG_NOTICE;
 int opt_log_level = LOG_NOTICE;
 
 
-static void my_log_curses(int prio, char *f, va_list ap) FORMAT_SYNTAX_CHECK(printf, 2, 0);
-
-static void my_log_curses(__maybe_unused int prio, char *f, va_list ap)
+static void my_log_curses(int prio, const char *datetime, const char *str)
 {
 {
 	if (opt_quiet && prio != LOG_ERR)
 	if (opt_quiet && prio != LOG_ERR)
 		return;
 		return;
 
 
 #ifdef HAVE_CURSES
 #ifdef HAVE_CURSES
 	extern bool use_curses;
 	extern bool use_curses;
-	if (use_curses && log_curses_only(prio, f, ap))
+	if (use_curses && log_curses_only(prio, datetime, str))
 		;
 		;
 	else
 	else
 #endif
 #endif
 	{
 	{
-		int len = strlen(f);
 		int cancelstate;
 		int cancelstate;
 		bool scs;
 		bool scs;
-
-		strcpy(f + len - 1, "                    \n");
-
 		scs = !pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancelstate);
 		scs = !pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancelstate);
 		mutex_lock(&console_lock);
 		mutex_lock(&console_lock);
-		vprintf(f, ap);
+		printf("%s%s%s", datetime, str, "                    \n");
 		mutex_unlock(&console_lock);
 		mutex_unlock(&console_lock);
 		if (scs)
 		if (scs)
 			pthread_setcancelstate(cancelstate, &cancelstate);
 			pthread_setcancelstate(cancelstate, &cancelstate);
 	}
 	}
 }
 }
 
 
-static void log_generic(int prio, const char *fmt, va_list ap) FORMAT_SYNTAX_CHECK(printf, 2, 0);
-
-void vapplog(int prio, const char *fmt, va_list ap)
-{
-	if (!opt_debug && prio == LOG_DEBUG)
-		return;
-
-	log_generic(prio, fmt, ap);
-}
-
-void applog(int prio, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	vapplog(prio, fmt, ap);
-	va_end(ap);
-}
-
-
-/* high-level logging functions, based on global opt_log_level */
+/* high-level logging function, based on global opt_log_level */
 
 
 /*
 /*
- * generic log function used by priority specific ones
- * equals vapplog() without additional priority checks
+ * log function
  */
  */
-static void log_generic(int prio, const char *fmt, va_list ap)
+void _applog(int prio, const char *str)
 {
 {
 #ifdef HAVE_SYSLOG_H
 #ifdef HAVE_SYSLOG_H
 	if (use_syslog) {
 	if (use_syslog) {
-		vsyslog(prio, fmt, ap);
+		syslog(prio, "%s", str);
 	}
 	}
 #else
 #else
 	if (0) {}
 	if (0) {}
@@ -94,8 +68,7 @@ static void log_generic(int prio, const char *fmt, va_list ap)
 		if (!(writetocon || writetofile))
 		if (!(writetocon || writetofile))
 			return;
 			return;
 
 
-		char *f;
-		int len;
+		char datetime[64];
 		struct timeval tv = {0, 0};
 		struct timeval tv = {0, 0};
 		struct tm _tm;
 		struct tm _tm;
 		struct tm *tm = &_tm;
 		struct tm *tm = &_tm;
@@ -104,60 +77,31 @@ static void log_generic(int prio, const char *fmt, va_list ap)
 
 
 		localtime_r(&tv.tv_sec, tm);
 		localtime_r(&tv.tv_sec, tm);
 
 
-		len = 40 + strlen(fmt) + 22;
-		f = alloca(len);
-		sprintf(f, " [%d-%02d-%02d %02d:%02d:%02d] %s\n",
-			tm->tm_year + 1900,
-			tm->tm_mon + 1,
-			tm->tm_mday,
-			tm->tm_hour,
-			tm->tm_min,
-			tm->tm_sec,
-			fmt);
+		if (opt_log_microseconds)
+			sprintf(datetime, " [%d-%02d-%02d %02d:%02d:%02d.%06ld] ",
+				tm->tm_year + 1900,
+				tm->tm_mon + 1,
+				tm->tm_mday,
+				tm->tm_hour,
+				tm->tm_min,
+				tm->tm_sec,
+				(long)tv.tv_usec);
+		else
+			sprintf(datetime, " [%d-%02d-%02d %02d:%02d:%02d] ",
+				tm->tm_year + 1900,
+				tm->tm_mon + 1,
+				tm->tm_mday,
+				tm->tm_hour,
+				tm->tm_min,
+				tm->tm_sec);
+
 		/* Only output to stderr if it's not going to the screen as well */
 		/* Only output to stderr if it's not going to the screen as well */
 		if (writetofile) {
 		if (writetofile) {
-			va_list apc;
-
-			va_copy(apc, ap);
-			vfprintf(stderr, f, apc);	/* atomic write to stderr */
-			va_end(apc);
+			fprintf(stderr, "%s%s\n", datetime, str);	/* atomic write to stderr */
 			fflush(stderr);
 			fflush(stderr);
 		}
 		}
 
 
 		if (writetocon)
 		if (writetocon)
-			my_log_curses(prio, f, ap);
+			my_log_curses(prio, datetime, str);
 	}
 	}
 }
 }
-/* we can not generalize variable argument list */
-#define LOG_TEMPLATE(PRIO)		\
-	if (PRIO <= opt_log_level) {	\
-		va_list ap;		\
-		va_start(ap, fmt);	\
-		vapplog(PRIO, fmt, ap);	\
-		va_end(ap);		\
-	}
-
-void log_error(const char *fmt, ...)
-{
-	LOG_TEMPLATE(LOG_ERR);
-}
-
-void log_warning(const char *fmt, ...)
-{
-	LOG_TEMPLATE(LOG_WARNING);
-}
-
-void log_notice(const char *fmt, ...)
-{
-	LOG_TEMPLATE(LOG_NOTICE);
-}
-
-void log_info(const char *fmt, ...)
-{
-	LOG_TEMPLATE(LOG_INFO);
-}
-
-void log_debug(const char *fmt, ...)
-{
-	LOG_TEMPLATE(LOG_DEBUG);
-}

+ 39 - 10
logging.h

@@ -11,7 +11,9 @@
 #define __LOGGING_H__
 #define __LOGGING_H__
 
 
 #include "config.h"
 #include "config.h"
+
 #include <stdbool.h>
 #include <stdbool.h>
+#include <stdio.h>
 #include <stdarg.h>
 #include <stdarg.h>
 
 
 #ifdef HAVE_SYSLOG_H
 #ifdef HAVE_SYSLOG_H
@@ -26,31 +28,58 @@ enum {
 };
 };
 #endif
 #endif
 
 
-/* original / legacy debug flags */
+/* debug flags */
 extern bool opt_debug;
 extern bool opt_debug;
 extern bool opt_debug_console;
 extern bool opt_debug_console;
 extern bool opt_log_output;
 extern bool opt_log_output;
+extern bool opt_log_microseconds;
 extern bool opt_realquiet;
 extern bool opt_realquiet;
 extern bool want_per_device_stats;
 extern bool want_per_device_stats;
 
 
 /* global log_level, messages with lower or equal prio are logged */
 /* global log_level, messages with lower or equal prio are logged */
 extern int opt_log_level;
 extern int opt_log_level;
 
 
-/* low-level logging functions with priority parameter */
-extern void vapplog(int prio, const char *fmt, va_list ap) FORMAT_SYNTAX_CHECK(printf, 2, 0);
-extern void applog(int prio, const char *fmt, ...) FORMAT_SYNTAX_CHECK(printf, 2, 3);
+#define LOGBUFSIZ 256
+
+extern void _applog(int prio, const char *str);
+
+#define applog(prio, fmt, ...) do { \
+	if (opt_debug || prio != LOG_DEBUG) { \
+			char tmp42[LOGBUFSIZ]; \
+			snprintf(tmp42, sizeof(tmp42), fmt, ##__VA_ARGS__); \
+			_applog(prio, tmp42); \
+	} \
+} while (0)
 
 
 #define applogr(rv, prio, ...)  do {  \
 #define applogr(rv, prio, ...)  do {  \
 	applog(prio, __VA_ARGS__);  \
 	applog(prio, __VA_ARGS__);  \
 	return rv;  \
 	return rv;  \
 } while (0)
 } while (0)
 
 
-/* high-level logging functions with implicit priority */
-extern void log_error(const char *fmt, ...) FORMAT_SYNTAX_CHECK(printf, 1, 2);
-extern void log_warning(const char *fmt, ...) FORMAT_SYNTAX_CHECK(printf, 1, 2);
-extern void log_notice(const char *fmt, ...) FORMAT_SYNTAX_CHECK(printf, 1, 2);
-extern void log_info(const char *fmt, ...) FORMAT_SYNTAX_CHECK(printf, 1, 2);
-extern void log_debug(const char *fmt, ...) FORMAT_SYNTAX_CHECK(printf, 1, 2);
+#define quit(status, fmt, ...) do { \
+	if (fmt) { \
+		char tmp42[LOGBUFSIZ]; \
+		snprintf(tmp42, sizeof(tmp42), fmt, ##__VA_ARGS__); \
+		_applog(LOG_ERR, tmp42); \
+	} \
+	_quit(status); \
+} while (0)
+
+#ifdef HAVE_CURSES
+
+#define wlog(fmt, ...) do { \
+	char tmp42[LOGBUFSIZ]; \
+	snprintf(tmp42, sizeof(tmp42), fmt, ##__VA_ARGS__); \
+	_wlog(tmp42); \
+} while (0)
+
+#define wlogprint(fmt, ...) do { \
+	char tmp42[LOGBUFSIZ]; \
+	snprintf(tmp42, sizeof(tmp42), fmt, ##__VA_ARGS__); \
+	_wlogprint(tmp42); \
+} while (0)
+
+#endif
 
 
 extern void hexdump(const void *, unsigned int len);
 extern void hexdump(const void *, unsigned int len);
 
 

+ 4 - 3
make-release

@@ -16,10 +16,10 @@ sw="$1"; shift || true
 builds=(win32 win64)
 builds=(win32 win64)
 
 
 win32_machine='i686-pc-mingw32'
 win32_machine='i686-pc-mingw32'
-win32_CFLAGS='-march=i686'
+win32_CFLAGS='-g -march=i686'
 
 
 win64_machine='x86_64-w64-mingw32'
 win64_machine='x86_64-w64-mingw32'
-win64_CFLAGS=''
+win64_CFLAGS='-g'
 
 
 IDIR="$PWD"
 IDIR="$PWD"
 OUTDIR="$PWD"
 OUTDIR="$PWD"
@@ -50,6 +50,7 @@ tar cjvpf "$OUTDIR/${sw}.tbz2" "$sw"
 SRCDIR="$TMPDIR/$sw"
 SRCDIR="$TMPDIR/$sw"
 
 
 dlls='
 dlls='
+	backtrace.dll
 	pdcurses.dll
 	pdcurses.dll
 	libcurl-4.dll
 	libcurl-4.dll
 	pthreadGC2.dll
 	pthreadGC2.dll
@@ -74,7 +75,7 @@ for build in "${builds[@]}"; do
 	cd "$TMPDIR"
 	cd "$TMPDIR"
 	mkdir -vp "$PKGDIR"
 	mkdir -vp "$PKGDIR"
 	for v in machine CFLAGS; do
 	for v in machine CFLAGS; do
-		eval "${v}"="$(eval echo "\${${build}_${v}}")"
+		eval "${v}"="'$(eval echo "\${${build}_${v}}")'"
 	done
 	done
 	libdir="/usr/$machine/usr/bin/$dll"
 	libdir="/usr/$machine/usr/bin/$dll"
 	for dll in $dlls; do
 	for dll in $dlls; do

+ 98 - 56
miner.c

@@ -69,7 +69,7 @@
 #include "ft232r.h"
 #include "ft232r.h"
 #endif
 #endif
 
 
-#if defined(unix)
+#if defined(unix) || defined(__APPLE__)
 	#include <errno.h>
 	#include <errno.h>
 	#include <fcntl.h>
 	#include <fcntl.h>
 	#include <sys/wait.h>
 	#include <sys/wait.h>
@@ -171,6 +171,11 @@ bool use_curses = true;
 #else
 #else
 bool use_curses;
 bool use_curses;
 #endif
 #endif
+#ifdef HAVE_LIBUSB
+bool have_libusb = true;
+#else
+const bool have_libusb;
+#endif
 static bool opt_submit_stale = true;
 static bool opt_submit_stale = true;
 static int opt_shares;
 static int opt_shares;
 static int opt_submit_threads = 0x40;
 static int opt_submit_threads = 0x40;
@@ -324,7 +329,7 @@ static int include_count;
 #define JSON_MAX_DEPTH 10
 #define JSON_MAX_DEPTH 10
 #define JSON_MAX_DEPTH_ERR "Too many levels of JSON includes (limit 10) or a loop"
 #define JSON_MAX_DEPTH_ERR "Too many levels of JSON includes (limit 10) or a loop"
 
 
-#if defined(unix)
+#if defined(unix) || defined(__APPLE__)
 	static char *opt_stderr_cmd = NULL;
 	static char *opt_stderr_cmd = NULL;
 	static int forkpid;
 	static int forkpid;
 #endif // defined(unix)
 #endif // defined(unix)
@@ -408,13 +413,16 @@ void get_timestamp(char *f, struct timeval *tv)
 
 
 static void applog_and_exit(const char *fmt, ...) FORMAT_SYNTAX_CHECK(printf, 1, 2);
 static void applog_and_exit(const char *fmt, ...) FORMAT_SYNTAX_CHECK(printf, 1, 2);
 
 
+static char exit_buf[512];
+
 static void applog_and_exit(const char *fmt, ...)
 static void applog_and_exit(const char *fmt, ...)
 {
 {
 	va_list ap;
 	va_list ap;
 
 
 	va_start(ap, fmt);
 	va_start(ap, fmt);
-	vapplog(LOG_ERR, fmt, ap);
+	vsnprintf(exit_buf, sizeof(exit_buf), fmt, ap);
 	va_end(ap);
 	va_end(ap);
+	_applog(LOG_ERR, exit_buf);
 	exit(1);
 	exit(1);
 }
 }
 
 
@@ -513,6 +521,8 @@ struct pool *add_pool(void)
 
 
 	/* Make sure the pool doesn't think we've been idle since time 0 */
 	/* Make sure the pool doesn't think we've been idle since time 0 */
 	pool->tv_idle.tv_sec = ~0UL;
 	pool->tv_idle.tv_sec = ~0UL;
+	
+	cgtime(&pool->cgminer_stats.start_tv);
 
 
 	pool->rpc_proxy = NULL;
 	pool->rpc_proxy = NULL;
 
 
@@ -1371,7 +1381,10 @@ static struct opt_table opt_config_table[] = {
 	OPT_WITH_ARG("--log|-l",
 	OPT_WITH_ARG("--log|-l",
 		     set_int_0_to_9999, opt_show_intval, &opt_log_interval,
 		     set_int_0_to_9999, opt_show_intval, &opt_log_interval,
 		     "Interval in seconds between log output"),
 		     "Interval in seconds between log output"),
-#if defined(unix)
+	OPT_WITHOUT_ARG("--log-microseconds",
+	                opt_set_bool, &opt_log_microseconds,
+	                "Include microseconds in log output"),
+#if defined(unix) || defined(__APPLE__)
 	OPT_WITH_ARG("--monitor|-m",
 	OPT_WITH_ARG("--monitor|-m",
 		     opt_set_charp, NULL, &opt_stderr_cmd,
 		     opt_set_charp, NULL, &opt_stderr_cmd,
 		     "Use custom pipe cmd for output messages"),
 		     "Use custom pipe cmd for output messages"),
@@ -2068,6 +2081,12 @@ static bool work_decode(struct pool *pool, struct work *work, json_t *val)
 	return ret;
 	return ret;
 }
 }
 
 
+/* Returns whether the pool supports local work generation or not. */
+static bool pool_localgen(struct pool *pool)
+{
+	return (pool->last_work_copy || pool->has_stratum);
+}
+
 int dev_from_id(int thr_id)
 int dev_from_id(int thr_id)
 {
 {
 	struct cgpu_info *cgpu = get_thr_cgpu(thr_id);
 	struct cgpu_info *cgpu = get_thr_cgpu(thr_id);
@@ -2185,6 +2204,30 @@ void tailsprintf(char *f, const char *fmt, ...)
 	va_end(ap);
 	va_end(ap);
 }
 }
 
 
+double stats_elapsed(struct cgminer_stats *stats)
+{
+	struct timeval now;
+	double elapsed;
+
+	if (stats->start_tv.tv_sec == 0)
+		elapsed = total_secs;
+	else {
+		cgtime(&now);
+		elapsed = tdiff(&now, &stats->start_tv);
+	}
+
+	if (elapsed < 1.0)
+		elapsed = 1.0;
+
+	return elapsed;
+}
+
+double cgpu_utility(struct cgpu_info *cgpu)
+{
+	double dev_runtime = cgpu_runtime(cgpu);
+	return cgpu->utility = cgpu->accepted / dev_runtime * 60;
+}
+
 /* Convert a uint64_t value into a truncated string for displaying with its
 /* Convert a uint64_t value into a truncated string for displaying with its
  * associated suitable for Mega, Giga etc. Buf array needs to be long enough */
  * associated suitable for Mega, Giga etc. Buf array needs to be long enough */
 static void suffix_string(uint64_t val, char *buf, int sigdigits)
 static void suffix_string(uint64_t val, char *buf, int sigdigits)
@@ -2354,12 +2397,14 @@ static void get_statline2(char *buf, struct cgpu_info *cgpu, bool for_curses)
 	enum h2bs_fmt hashrate_style = for_curses ? H2B_SHORT : H2B_SPACED;
 	enum h2bs_fmt hashrate_style = for_curses ? H2B_SHORT : H2B_SPACED;
 	char cHr[h2bs_fmt_size[H2B_NOUNIT]], aHr[h2bs_fmt_size[H2B_NOUNIT]], uHr[h2bs_fmt_size[hashrate_style]];
 	char cHr[h2bs_fmt_size[H2B_NOUNIT]], aHr[h2bs_fmt_size[H2B_NOUNIT]], uHr[h2bs_fmt_size[hashrate_style]];
 	char rejpcbuf[6];
 	char rejpcbuf[6];
+	double dev_runtime;
 	
 	
 	if (!opt_show_procs)
 	if (!opt_show_procs)
 		cgpu = cgpu->device;
 		cgpu = cgpu->device;
 	
 	
-	cgpu->utility = cgpu->accepted / total_secs * 60;
-	cgpu->utility_diff1 = cgpu->diff_accepted / total_secs * 60;
+	dev_runtime = cgpu_runtime(cgpu);
+	cgpu_utility(cgpu);
+	cgpu->utility_diff1 = cgpu->diff_accepted / dev_runtime * 60;
 	
 	
 	double rolling = cgpu->rolling;
 	double rolling = cgpu->rolling;
 	double mhashes = cgpu->total_mhashes;
 	double mhashes = cgpu->total_mhashes;
@@ -2374,8 +2419,8 @@ static void get_statline2(char *buf, struct cgpu_info *cgpu, bool for_curses)
 	if (!opt_show_procs)
 	if (!opt_show_procs)
 		for (struct cgpu_info *slave = cgpu; (slave = slave->next_proc); )
 		for (struct cgpu_info *slave = cgpu; (slave = slave->next_proc); )
 		{
 		{
-			slave->utility = slave->accepted / total_secs * 60;
-			slave->utility_diff1 = slave->diff_accepted / total_secs * 60;
+			slave->utility = slave->accepted / dev_runtime * 60;
+			slave->utility_diff1 = slave->diff_accepted / dev_runtime * 60;
 			
 			
 			rolling += slave->rolling;
 			rolling += slave->rolling;
 			mhashes += slave->total_mhashes;
 			mhashes += slave->total_mhashes;
@@ -2391,7 +2436,7 @@ static void get_statline2(char *buf, struct cgpu_info *cgpu, bool for_curses)
 	ti_hashrate_bufstr(
 	ti_hashrate_bufstr(
 		(char*[]){cHr, aHr, uHr},
 		(char*[]){cHr, aHr, uHr},
 		1e6*rolling,
 		1e6*rolling,
-		1e6*mhashes / total_secs,
+		1e6*mhashes / dev_runtime,
 		utility_to_hashrate(wutil),
 		utility_to_hashrate(wutil),
 		hashrate_style);
 		hashrate_style);
 
 
@@ -2408,6 +2453,12 @@ static void get_statline2(char *buf, struct cgpu_info *cgpu, bool for_curses)
 #endif
 #endif
 		sprintf(buf, "%s ", opt_show_procs ? cgpu->proc_repr_ns : cgpu->dev_repr_ns);
 		sprintf(buf, "%s ", opt_show_procs ? cgpu->proc_repr_ns : cgpu->dev_repr_ns);
 	
 	
+	if (unlikely(cgpu->status == LIFE_INIT))
+	{
+		tailsprintf(buf, "Initializing...");
+		return;
+	}
+	
 	if (drv->get_dev_statline_before || drv->get_statline_before)
 	if (drv->get_dev_statline_before || drv->get_statline_before)
 	{
 	{
 		if (drv->get_dev_statline_before && drv->get_statline_before)
 		if (drv->get_dev_statline_before && drv->get_statline_before)
@@ -2697,31 +2748,23 @@ static void switch_logsize(void)
 }
 }
 
 
 /* For mandatory printing when mutex is already locked */
 /* For mandatory printing when mutex is already locked */
-void wlog(const char *f, ...)
+void _wlog(const char *str)
 {
 {
-	va_list ap;
-
-	va_start(ap, f);
-	vw_printw(logwin, f, ap);
-	va_end(ap);
+	wprintw(logwin, "%s", str);
 }
 }
 
 
 /* Mandatory printing */
 /* Mandatory printing */
-void wlogprint(const char *f, ...)
+void _wlogprint(const char *str)
 {
 {
-	va_list ap;
-
 	if (curses_active_locked()) {
 	if (curses_active_locked()) {
-		va_start(ap, f);
-		vw_printw(logwin, f, ap);
-		va_end(ap);
+		wprintw(logwin, "%s", str);
 		unlock_curses();
 		unlock_curses();
 	}
 	}
 }
 }
 #endif
 #endif
 
 
 #ifdef HAVE_CURSES
 #ifdef HAVE_CURSES
-bool log_curses_only(int prio, const char *f, va_list ap)
+bool log_curses_only(int prio, const char *datetime, const char *str)
 {
 {
 	bool high_prio;
 	bool high_prio;
 
 
@@ -2729,7 +2772,7 @@ bool log_curses_only(int prio, const char *f, va_list ap)
 
 
 	if (curses_active_locked()) {
 	if (curses_active_locked()) {
 		if (!opt_loginput || high_prio) {
 		if (!opt_loginput || high_prio) {
-			vw_printw(logwin, f, ap);
+			wprintw(logwin, "%s%s\n", datetime, str);
 			if (high_prio) {
 			if (high_prio) {
 				touchwin(logwin);
 				touchwin(logwin);
 				wrefresh(logwin);
 				wrefresh(logwin);
@@ -3558,8 +3601,6 @@ static void __kill_work(void)
 	applog(LOG_DEBUG, "Killing off mining threads");
 	applog(LOG_DEBUG, "Killing off mining threads");
 	/* Kill the mining threads*/
 	/* Kill the mining threads*/
 	for (i = 0; i < mining_threads; i++) {
 	for (i = 0; i < mining_threads; i++) {
-		pthread_t *pth = NULL;
-		
 		thr = get_thread(i);
 		thr = get_thread(i);
 		if (!(thr && thr->cgpu->threads))
 		if (!(thr && thr->cgpu->threads))
 			continue;
 			continue;
@@ -3604,7 +3645,7 @@ void app_restart(void)
 	__kill_work();
 	__kill_work();
 	clean_up();
 	clean_up();
 
 
-#if defined(unix)
+#if defined(unix) || defined(__APPLE__)
 	if (forkpid > 0) {
 	if (forkpid > 0) {
 		kill(forkpid, SIGTERM);
 		kill(forkpid, SIGTERM);
 		forkpid = 0;
 		forkpid = 0;
@@ -4615,7 +4656,7 @@ void switch_pools(struct pool *selected)
 		pool->block_id = 0;
 		pool->block_id = 0;
 		if (pool_strategy != POOL_LOADBALANCE && pool_strategy != POOL_BALANCE) {
 		if (pool_strategy != POOL_LOADBALANCE && pool_strategy != POOL_BALANCE) {
 			applog(LOG_WARNING, "Switching to pool %d %s", pool->pool_no, pool->rpc_url);
 			applog(LOG_WARNING, "Switching to pool %d %s", pool->pool_no, pool->rpc_url);
-			if (pool->last_work_copy || pool->has_stratum || opt_fail_only)
+			if (pool_localgen(pool) || opt_fail_only)
 				clear_pool_work(last_pool);
 				clear_pool_work(last_pool);
 		}
 		}
 	}
 	}
@@ -5242,7 +5283,7 @@ void write_config(FILE *fcfg)
 		fputs(",\n\"round-robin\" : true", fcfg);
 		fputs(",\n\"round-robin\" : true", fcfg);
 	if (pool_strategy == POOL_ROTATE)
 	if (pool_strategy == POOL_ROTATE)
 		fprintf(fcfg, ",\n\"rotate\" : \"%d\"", opt_rotate_period);
 		fprintf(fcfg, ",\n\"rotate\" : \"%d\"", opt_rotate_period);
-#if defined(unix)
+#if defined(unix) || defined(__APPLE__)
 	if (opt_stderr_cmd && *opt_stderr_cmd)
 	if (opt_stderr_cmd && *opt_stderr_cmd)
 		fprintf(fcfg, ",\n\"monitor\" : \"%s\"", json_escape(opt_stderr_cmd));
 		fprintf(fcfg, ",\n\"monitor\" : \"%s\"", json_escape(opt_stderr_cmd));
 #endif // defined(unix)
 #endif // defined(unix)
@@ -5367,6 +5408,7 @@ void zero_stats(void)
 		pool->diff_rejected = 0;
 		pool->diff_rejected = 0;
 		pool->diff_stale = 0;
 		pool->diff_stale = 0;
 		pool->last_share_diff = 0;
 		pool->last_share_diff = 0;
+		pool->cgminer_stats.start_tv = total_tv_start;
 		pool->cgminer_stats.getwork_calls = 0;
 		pool->cgminer_stats.getwork_calls = 0;
 		pool->cgminer_stats.getwork_wait_min.tv_sec = MIN_SEC_UNSET;
 		pool->cgminer_stats.getwork_wait_min.tv_sec = MIN_SEC_UNSET;
 		pool->cgminer_stats.getwork_wait_max.tv_sec = 0;
 		pool->cgminer_stats.getwork_wait_max.tv_sec = 0;
@@ -5416,6 +5458,7 @@ void zero_stats(void)
 		cgpu->dev_thermal_cutoff_count = 0;
 		cgpu->dev_thermal_cutoff_count = 0;
 		cgpu->dev_comms_error_count = 0;
 		cgpu->dev_comms_error_count = 0;
 		cgpu->dev_throttle_count = 0;
 		cgpu->dev_throttle_count = 0;
+		cgpu->cgminer_stats.start_tv = total_tv_start;
 		cgpu->cgminer_stats.getwork_calls = 0;
 		cgpu->cgminer_stats.getwork_calls = 0;
 		cgpu->cgminer_stats.getwork_wait_min.tv_sec = MIN_SEC_UNSET;
 		cgpu->cgminer_stats.getwork_wait_min.tv_sec = MIN_SEC_UNSET;
 		cgpu->cgminer_stats.getwork_wait_max.tv_sec = 0;
 		cgpu->cgminer_stats.getwork_wait_max.tv_sec = 0;
@@ -5735,7 +5778,7 @@ retry:
 
 
 void default_save_file(char *filename)
 void default_save_file(char *filename)
 {
 {
-#if defined(unix)
+#if defined(unix) || defined(__APPLE__)
 	if (getenv("HOME") && *getenv("HOME")) {
 	if (getenv("HOME") && *getenv("HOME")) {
 	        strcpy(filename, getenv("HOME"));
 	        strcpy(filename, getenv("HOME"));
 		strcat(filename, "/");
 		strcat(filename, "/");
@@ -6358,7 +6401,7 @@ static bool cnx_needed(struct pool *pool)
 	cp = current_pool();
 	cp = current_pool();
 	if (cp == pool)
 	if (cp == pool)
 		return true;
 		return true;
-	if (!cp->has_stratum && (!opt_fail_only || !cp->hdr_path))
+	if (!pool_localgen(cp) && (!opt_fail_only || !cp->hdr_path))
 		return true;
 		return true;
 
 
 	/* Keep the connection open to allow any stray shares to be submitted
 	/* Keep the connection open to allow any stray shares to be submitted
@@ -6468,7 +6511,10 @@ static void *stratum_thread(void *userdata)
 			pool->getfail_occasions++;
 			pool->getfail_occasions++;
 			total_go++;
 			total_go++;
 
 
+			mutex_lock(&pool->stratum_lock);
+			pool->stratum_active = pool->stratum_notify = false;
 			pool->sock = INVSOCK;
 			pool->sock = INVSOCK;
+			mutex_unlock(&pool->stratum_lock);
 
 
 			/* If the socket to our stratum pool disconnects, all
 			/* If the socket to our stratum pool disconnects, all
 			 * submissions need to be discarded or resent. */
 			 * submissions need to be discarded or resent. */
@@ -7897,7 +7943,7 @@ static void *watchdog_thread(void __maybe_unused *userdata)
 			char *dev_str = cgpu->proc_repr;
 			char *dev_str = cgpu->proc_repr;
 			int gpu;
 			int gpu;
 
 
-			if (cgpu->drv->get_stats)
+			if (cgpu->drv->get_stats && likely(cgpu->status != LIFE_INIT))
 			  cgpu->drv->get_stats(cgpu);
 			  cgpu->drv->get_stats(cgpu);
 
 
 			gpu = cgpu->device_id;
 			gpu = cgpu->device_id;
@@ -8125,6 +8171,7 @@ static void clean_up(void)
 	clear_adl(nDevs);
 	clear_adl(nDevs);
 #endif
 #endif
 #ifdef HAVE_LIBUSB
 #ifdef HAVE_LIBUSB
+	if (likely(have_libusb))
         libusb_exit(NULL);
         libusb_exit(NULL);
 #endif
 #endif
 
 
@@ -8141,30 +8188,20 @@ static void clean_up(void)
 	curl_global_cleanup();
 	curl_global_cleanup();
 }
 }
 
 
-void quit(int status, const char *format, ...)
+void _quit(int status)
 {
 {
-	va_list ap;
-
 	clean_up();
 	clean_up();
 
 
-	if (format) {
-		va_start(ap, format);
-		vfprintf(stderr, format, ap);
-		va_end(ap);
-	}
-	fprintf(stderr, "\n");
-	fflush(stderr);
-
 	if (status) {
 	if (status) {
 		const char *ev = getenv("__BFGMINER_SEGFAULT_ERRQUIT");
 		const char *ev = getenv("__BFGMINER_SEGFAULT_ERRQUIT");
 		if (unlikely(ev && ev[0] && ev[0] != '0')) {
 		if (unlikely(ev && ev[0] && ev[0] != '0')) {
-			const char **p = NULL;
+			int *p = NULL;
 			// NOTE debugger can bypass with: p = &p
 			// NOTE debugger can bypass with: p = &p
-			*p = format;  // Segfault, hopefully dumping core
+			*p = status;  // Segfault, hopefully dumping core
 		}
 		}
 	}
 	}
 
 
-#if defined(unix)
+#if defined(unix) || defined(__APPLE__)
 	if (forkpid > 0) {
 	if (forkpid > 0) {
 		kill(forkpid, SIGTERM);
 		kill(forkpid, SIGTERM);
 		forkpid = 0;
 		forkpid = 0;
@@ -8303,7 +8340,7 @@ out:
 }
 }
 #endif
 #endif
 
 
-#if defined(unix)
+#if defined(unix) || defined(__APPLE__)
 static void fork_monitor()
 static void fork_monitor()
 {
 {
 	// Make a pipe: [readFD, writeFD]
 	// Make a pipe: [readFD, writeFD]
@@ -8547,6 +8584,10 @@ int main(int argc, char *argv[])
 	int i, j;
 	int i, j;
 	char *s;
 	char *s;
 
 
+#ifdef WIN32
+	LoadLibrary("backtrace.dll");
+#endif
+
 	blkmk_sha256_impl = my_blkmaker_sha256_callback;
 	blkmk_sha256_impl = my_blkmaker_sha256_callback;
 
 
 #ifndef HAVE_PTHREAD_CANCEL
 #ifndef HAVE_PTHREAD_CANCEL
@@ -8566,9 +8607,8 @@ int main(int argc, char *argv[])
 #ifdef HAVE_LIBUSB
 #ifdef HAVE_LIBUSB
 	int err = libusb_init(NULL);
 	int err = libusb_init(NULL);
 	if (err) {
 	if (err) {
-		fprintf(stderr, "libusb_init() failed err %d", err);
-		fflush(stderr);
-		quit(1, "libusb_init() failed");
+		applog(LOG_WARNING, "libusb_init() failed err %d", err);
+		have_libusb = false;
 	}
 	}
 #endif
 #endif
 
 
@@ -8690,7 +8730,8 @@ int main(int argc, char *argv[])
 	}
 	}
 
 
 #ifdef USE_X6500
 #ifdef USE_X6500
-	ft232r_scan();
+	if (likely(have_libusb))
+		ft232r_scan();
 #endif
 #endif
 
 
 #ifdef HAVE_CURSES
 #ifdef HAVE_CURSES
@@ -8801,12 +8842,12 @@ int main(int argc, char *argv[])
 #endif
 #endif
 
 
 #ifdef USE_X6500
 #ifdef USE_X6500
-	if (!opt_scrypt)
+	if (likely(have_libusb) && !opt_scrypt)
 		x6500_api.drv_detect();
 		x6500_api.drv_detect();
 #endif
 #endif
 
 
 #ifdef USE_ZTEX
 #ifdef USE_ZTEX
-	if (!opt_scrypt)
+	if (likely(have_libusb) && !opt_scrypt)
 		ztex_drv.drv_detect();
 		ztex_drv.drv_detect();
 #endif
 #endif
 
 
@@ -8822,7 +8863,8 @@ int main(int argc, char *argv[])
 #endif
 #endif
 
 
 #ifdef USE_X6500
 #ifdef USE_X6500
-	ft232r_scan_free();
+	if (likely(have_libusb))
+		ft232r_scan_free();
 #endif
 #endif
 
 
 	for (i = 0; i < total_devices; ++i)
 	for (i = 0; i < total_devices; ++i)
@@ -8923,7 +8965,7 @@ int main(int argc, char *argv[])
 		openlog(PACKAGE, LOG_PID, LOG_USER);
 		openlog(PACKAGE, LOG_PID, LOG_USER);
 #endif
 #endif
 
 
-	#if defined(unix)
+	#if defined(unix) || defined(__APPLE__)
 		if (opt_stderr_cmd)
 		if (opt_stderr_cmd)
 			fork_monitor();
 			fork_monitor();
 	#endif // defined(unix)
 	#endif // defined(unix)
@@ -9172,13 +9214,13 @@ begin_bench:
 
 
 		/* If the primary pool is a getwork pool and cannot roll work,
 		/* If the primary pool is a getwork pool and cannot roll work,
 		 * try to stage one extra work per mining thread */
 		 * try to stage one extra work per mining thread */
-		if (!cp->has_stratum && cp->proto != PLP_GETBLOCKTEMPLATE && !staged_rollable)
+		if (!pool_localgen(cp) && !staged_rollable)
 			max_staged += mining_threads;
 			max_staged += mining_threads;
 
 
 		mutex_lock(stgd_lock);
 		mutex_lock(stgd_lock);
 		ts = __total_staged();
 		ts = __total_staged();
 
 
-		if (!cp->has_stratum && cp->proto != PLP_GETBLOCKTEMPLATE && !ts && !opt_fail_only)
+		if (!pool_localgen(cp) && !ts && !opt_fail_only)
 			lagging = true;
 			lagging = true;
 
 
 		/* Wait until hash_pop tells us we need to create more work */
 		/* Wait until hash_pop tells us we need to create more work */

+ 9 - 4
miner.h

@@ -384,6 +384,8 @@ enum {
 };
 };
 
 
 struct cgminer_stats {
 struct cgminer_stats {
+	struct timeval start_tv;
+	
 	uint32_t getwork_calls;
 	uint32_t getwork_calls;
 	struct timeval getwork_wait;
 	struct timeval getwork_wait;
 	struct timeval getwork_wait_max;
 	struct timeval getwork_wait_max;
@@ -715,7 +717,7 @@ static inline void swab256(void *dest_p, const void *src_p)
 
 
 #define flip32(dest_p, src_p) swap32yes(dest_p, src_p, 32 / 4)
 #define flip32(dest_p, src_p) swap32yes(dest_p, src_p, 32 / 4)
 
 
-extern void quit(int status, const char *format, ...) NORETURN FORMAT_SYNTAX_CHECK(printf, 2, 3);
+extern void _quit(int status);
 
 
 static inline void mutex_lock(pthread_mutex_t *lock)
 static inline void mutex_lock(pthread_mutex_t *lock)
 {
 {
@@ -1258,10 +1260,13 @@ extern void work_completed(struct cgpu_info *cgpu, struct work *work);
 extern bool abandon_work(struct work *, struct timeval *work_runtime, uint64_t hashes);
 extern bool abandon_work(struct work *, struct timeval *work_runtime, uint64_t hashes);
 extern void hash_queued_work(struct thr_info *mythr);
 extern void hash_queued_work(struct thr_info *mythr);
 extern void tailsprintf(char *f, const char *fmt, ...) FORMAT_SYNTAX_CHECK(printf, 2, 3);
 extern void tailsprintf(char *f, const char *fmt, ...) FORMAT_SYNTAX_CHECK(printf, 2, 3);
-extern void wlog(const char *f, ...) FORMAT_SYNTAX_CHECK(printf, 1, 2);
-extern void wlogprint(const char *f, ...) FORMAT_SYNTAX_CHECK(printf, 1, 2);
+extern void _wlog(const char *str);
+extern void _wlogprint(const char *str);
 extern int curses_int(const char *query);
 extern int curses_int(const char *query);
 extern char *curses_input(const char *query);
 extern char *curses_input(const char *query);
+extern double stats_elapsed(struct cgminer_stats *);
+#define cgpu_runtime(cgpu)  stats_elapsed(&((cgpu)->cgminer_stats))
+extern double cgpu_utility(struct cgpu_info *);
 extern void kill_work(void);
 extern void kill_work(void);
 extern int prioritize_pools(char *param, int *pid);
 extern int prioritize_pools(char *param, int *pid);
 extern void validate_pool_priorities(void);
 extern void validate_pool_priorities(void);
@@ -1271,7 +1276,7 @@ extern void write_config(FILE *fcfg);
 extern void zero_bestshare(void);
 extern void zero_bestshare(void);
 extern void zero_stats(void);
 extern void zero_stats(void);
 extern void default_save_file(char *filename);
 extern void default_save_file(char *filename);
-extern bool log_curses_only(int prio, const char *f, va_list ap) FORMAT_SYNTAX_CHECK(printf, 2, 0);
+extern bool log_curses_only(int prio, const char *datetime, const char *str);
 extern void clear_logwin(void);
 extern void clear_logwin(void);
 extern void logwin_update(void);
 extern void logwin_update(void);
 extern bool pool_tclear(struct pool *pool, bool *var);
 extern bool pool_tclear(struct pool *pool, bool *var);

+ 1 - 0
ocl.c

@@ -34,6 +34,7 @@
 #define OMIT_OPENCL_API
 #define OMIT_OPENCL_API
 
 
 #include "findnonce.h"
 #include "findnonce.h"
+#include "fpgautils.h"
 #include "ocl.h"
 #include "ocl.h"
 
 
 /* Platform API */
 /* Platform API */

+ 1 - 1
openwrt/bfgminer/Makefile

@@ -11,7 +11,7 @@ include $(TOPDIR)/rules.mk
 
 
 PKG_NAME:=bfgminer
 PKG_NAME:=bfgminer
 PKG_TITLE:=BFGMiner
 PKG_TITLE:=BFGMiner
-PKG_VERSION:=3.1.0
+PKG_VERSION:=3.1.1
 PKG_RELEASE:=1
 PKG_RELEASE:=1
 
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tbz2
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tbz2

+ 1 - 1
phatk121016.cl

@@ -81,7 +81,7 @@ __constant uint H[8] = {
 #else // BITALIGN
 #else // BITALIGN
 	#define Ch(x, y, z) (z ^ (x & (y ^ z)))
 	#define Ch(x, y, z) (z ^ (x & (y ^ z)))
 	#define Ma(x, y, z) ((x & z) | (y & (x | z)))
 	#define Ma(x, y, z) ((x & z) | (y & (x | z)))
-	#define rot(x, y) rotate((u)x, (u)y)
+	#define rot(x, y) rotate(x, y)
 	#define rotr(x, y) rotate((u)x, (u)(32-y))
 	#define rotr(x, y) rotate((u)x, (u)(32-y))
 #endif
 #endif
 
 

+ 89 - 0
usbtest.py

@@ -0,0 +1,89 @@
+#!/usr/bin/env python2.7
+# Copyright 2012 Xiangfu
+# Copyright 2012-2013 Andrew Smith
+#
+# 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.
+
+# Linux usage: ./usbtest.py /dev/ttyUSB0 0xhexcodes|string|icarus
+#  OR          python usbtest.py /dev/ttyUSB0 0xhexcodes|string|icarus
+#
+# Windows usage: ./usbtest.py COM1 0xhexcodes|string|icarus
+#
+#   sends the data sepcified to the USB device and waits
+#   for a reply then displays it
+#
+#   the data can be:
+#	0xhexcodes: e.g. 0x68656c6c6f20776f726c640a
+#			would send "hello world\n"
+#
+#	string: e.g. sendsometext
+#
+#	icarus: sends 2 known block payloads for an icarus device
+#		and shows the expected and actual answers if it's
+#		a working V3 icarus
+
+import sys
+import serial
+import binascii
+
+if len(sys.argv) < 2:
+	sys.stderr.write("Usage: " + sys.argv[0] + " device strings...\n")
+	sys.stderr.write(" where device is either like /dev/ttyUSB0 or COM1\n")
+	sys.stderr.write(" and strings are either '0xXXXX' or 'text'\n")
+	sys.stderr.write(" if the first string is 'icarus' the rest are ignored\n")
+	sys.stderr.write("  and 2 valid icarus test payloads are sent with results displayed\n")
+	sys.stderr.write("\nAfter any command is sent it waits up to 30 seconds for a reply\n");
+	sys.exit("Aborting")
+
+# Open with a 10 second timeout - just to be sure
+ser = serial.Serial(sys.argv[1], 115200, serial.EIGHTBITS, serial.PARITY_NONE, serial.STOPBITS_ONE, 10, False, False, 5, False, None)
+
+if sys.argv[2] == "icarus":
+
+	# This show how Icarus use the block and midstate data
+	# This will produce nonce 063c5e01
+	block = "0000000120c8222d0497a7ab44a1a2c7bf39de941c9970b1dc7cdc400000079700000000e88aabe1f353238c668d8a4df9318e614c10c474f8cdf8bc5f6397b946c33d7c4e7242c31a098ea500000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000"
+	midstate = "33c5bf5751ec7f7e056443b5aee3800331432c83f404d9de38b94ecbf907b92d"
+
+	rdata2  = block.decode('hex')[95:63:-1]
+	rmid    = midstate.decode('hex')[::-1]
+	payload = rmid + rdata2
+
+	print("Push payload to icarus: " + binascii.hexlify(payload))
+	ser.write(payload)
+
+	b=ser.read(4)
+	print("Result:(should be: 063c5e01): " + binascii.hexlify(b))
+
+	# Just another test
+	payload2 = "ce92099c5a80bb81c52990d5c0924c625fd25a535640607d5a4bdf8174e2c8d500000000000000000000000080000000000000000b290c1a42313b4f21b5bcb8"
+	print("Push payload to icarus: " + payload2)
+	ser.write(payload2.decode('hex'))
+
+	b=ser.read(4)
+	print("Result:(should be: 8e0b31c5): " + binascii.hexlify(b))
+else:
+	data = ""
+	for arg in sys.argv[2::]:
+		if arg[0:2:] == '0x':
+			data += arg[2::].decode('hex')
+		else:
+			data += arg
+
+	print("Sending: 0x" + binascii.hexlify(data))
+	ser.write(data)
+
+	# If you're expecting more than one linefeed terminated reply,
+	# you'll only see the first one
+	# AND with no linefeed, this will wait the 10 seconds before returning
+	print("Waiting up to 10 seconds ...")
+	b=ser.readline()
+	print("Result: hex 0x" + binascii.hexlify(b))
+
+	# This could mess up the display - do it last
+	print("Result: asc '" + b + "'")
+
+ser.close()

+ 13 - 3
util.c

@@ -1270,9 +1270,11 @@ bool stratum_send(struct pool *pool, char *s, ssize_t len)
 			break;
 			break;
 		case SEND_SELECTFAIL:
 		case SEND_SELECTFAIL:
 			applog(LOG_DEBUG, "Write select failed on pool %d sock", pool->pool_no);
 			applog(LOG_DEBUG, "Write select failed on pool %d sock", pool->pool_no);
+			suspend_stratum(pool);
 			break;
 			break;
 		case SEND_SENDFAIL:
 		case SEND_SENDFAIL:
-			applog(LOG_DEBUG, "Failed to curl_easy_send in stratum_send");
+			applog(LOG_DEBUG, "Failed to send in stratum_send");
+			suspend_stratum(pool);
 			break;
 			break;
 		case SEND_INACTIVE:
 		case SEND_INACTIVE:
 			applog(LOG_DEBUG, "Stratum send failed due to no pool stratum_active");
 			applog(LOG_DEBUG, "Stratum send failed due to no pool stratum_active");
@@ -1319,7 +1321,10 @@ static void clear_sock(struct pool *pool)
 
 
 	mutex_lock(&pool->stratum_lock);
 	mutex_lock(&pool->stratum_lock);
 	do {
 	do {
-		n = recv(pool->sock, pool->sockbuf, RECVSIZE, 0);
+		if (pool->sock)
+			n = recv(pool->sock, pool->sockbuf, RECVSIZE, 0);
+		else
+			n = 0;
 	} while (n > 0);
 	} while (n > 0);
 	mutex_unlock(&pool->stratum_lock);
 	mutex_unlock(&pool->stratum_lock);
 
 
@@ -1372,11 +1377,16 @@ char *recv_line(struct pool *pool)
 			n = recv(pool->sock, s, RECVSIZE, 0);
 			n = recv(pool->sock, s, RECVSIZE, 0);
 			if (!n) {
 			if (!n) {
 				applog(LOG_DEBUG, "Socket closed waiting in recv_line");
 				applog(LOG_DEBUG, "Socket closed waiting in recv_line");
+				suspend_stratum(pool);
 				break;
 				break;
 			}
 			}
 			if (n < 0) {
 			if (n < 0) {
+				//Save errno from being overweitten bei socket_ commands 
+				int socket_recv_errno;
+				socket_recv_errno = errno;
 				if (!sock_blocks() || !socket_full(pool, false)) {
 				if (!sock_blocks() || !socket_full(pool, false)) {
-					applog(LOG_DEBUG, "Failed to recv sock in recv_line");
+					applog(LOG_DEBUG, "Failed to recv sock in recv_line: %d", socket_recv_errno);
+					suspend_stratum(pool);
 					break;
 					break;
 				}
 				}
 			} else {
 			} else {