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/signal.h
 lib/string.h
+lib/stdint.h
 lib/warn-on-use.h
 
 mkinstalldirs

+ 26 - 7
Makefile.am

@@ -18,11 +18,7 @@ EXTRA_DIST	= \
 dist_doc_DATA = \
 		  AUTHORS COPYING HACKING NEWS README \
 		  example.conf \
-		  README.ASIC \
-		  README.FPGA \
-		  README.GPU \
-		  README.RPC \
-		  README.scrypt
+		  README.RPC
 
 rpcexamplesdir = $(docdir)/rpc-examples
 dist_rpcexamples_DATA = \
@@ -32,6 +28,14 @@ dist_rpcexamples_DATA = \
 
 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
 
 bin_PROGRAMS	= bfgminer
@@ -60,16 +64,19 @@ bfgminer_SOURCES	+= miner.h compat.h bench_block.h	\
 	deviceapi.c deviceapi.h \
 		   util.c util.h logging.h		\
 		   sha2.c sha2.h api.c
-bfgminer_DEPENDENCIES =
+EXTRA_bfgminer_DEPENDENCIES =
 
 bitstreamsdir = $(pkgdatadir)/bitstreams
 dist_bitstreams_DATA =
 
 if NEED_LIBBLKMAKER
 SUBDIRS           += libblkmaker
+EXTRA_bfgminer_DEPENDENCIES += libblkmaker_directory
+libblkmaker_directory:
+	cd libblkmaker && $(MAKE)
 
 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
 	cp -p $< $@
@@ -94,6 +101,8 @@ bfgminer_SOURCES += *.cl
 kernelsdir = $(pkgdatadir)/opencl
 dist_kernels_DATA = $(top_srcdir)/*.cl
 
+dist_doc_DATA += README.GPU
+
 if HAVE_SENSORS
 bfgminer_LDADD += $(sensors_LIBS)
 endif
@@ -103,6 +112,7 @@ endif
 
 if HAS_SCRYPT
 bfgminer_SOURCES += scrypt.c scrypt.h
+dist_doc_DATA += README.scrypt
 endif
 
 if HAS_CPUMINE
@@ -127,9 +137,13 @@ if HAS_YASM
 AM_CFLAGS	= -DHAS_YASM
 if HAVE_x86_64
 SUBDIRS		+= x86_64
+x86_64/libx8664.a:
+	$(MAKE) -C x86_64 $*
 bfgminer_LDADD	+= x86_64/libx8664.a
 else # HAVE_x86_64
 SUBDIRS		+= x86_32
+x86_32/libx8632.a:
+	$(MAKE) -C x86_32 $*
 bfgminer_LDADD	+= x86_32/libx8632.a
 
 if HAVE_SSE2
@@ -148,6 +162,10 @@ if NEED_DYNCLOCK
 bfgminer_SOURCES += dynclock.c dynclock.h
 endif
 
+if HAS_FPGA
+dist_doc_DATA += README.FPGA
+endif
+
 if HAS_BITFORCE
 bfgminer_SOURCES += driver-bitforce.c
 
@@ -169,6 +187,7 @@ endif
 
 if HAS_AVALON
 bfgminer_SOURCES += driver-avalon.c driver-avalon.h hexdump.c
+dist_doc_DATA += README.ASIC
 endif
 
 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
 - Bugfix: openwrt: Expect fixed bitstream path for input
 - 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")
 --load-balance      Change multipool strategy from failover to efficiency based balance
 --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
 --net-delay         Impose small delays in networking to not overload slow routers
 --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
 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
 45:282
 47:270
@@ -48,7 +51,7 @@ Sample settings for different frequencies (last 2 values):
 
 Frequency:
 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
 information:

+ 16 - 25
api.c

@@ -124,7 +124,6 @@ char *WSAErrorMsg(void) {
 #endif
 
 static const char *UNAVAILABLE = " - API will not be available";
-static const char *INVAPIGROUPS = "Invalid --api-groups parameter";
 
 static const char *BLANK = "";
 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];
 	int n = 0, i;
 
-	cgpu->utility = cgpu->accepted / ( total_secs ? total_secs : 1 ) * 60;
+	cgpu_utility(cgpu);
 
 	rd_lock(&devices_lock);
 	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];
 	int n = 0, i;
 
-	cgpu->utility = cgpu->accepted / ( total_secs ? total_secs : 1 ) * 60;
+	cgpu_utility(cgpu);
 
 	rd_lock(&devices_lock);
 	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);
 	if (cgpu->temp)
 		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);
 	char mhsname[27];
 	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;
 	char buf[TMPBUFSIZ];
+	double elapsed;
 
 	root = api_add_int(root, "STATS", &i, 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_timeval(root, "Wait", &(stats->getwork_wait), false);
 	root = api_add_timeval(root, "Max", &(stats->getwork_wait_max), false);
@@ -3362,30 +3363,21 @@ static void setup_groups()
 			colon = strchr(ptr, ':');
 			if (colon)
 				*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);
-		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;
 
@@ -3419,8 +3411,7 @@ static void setup_groups()
 						*cmd = '\0';
 					}
 				} 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_min], [1])
-m4_define([v_mic], [0])
+m4_define([v_mic], [1])
 ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
 m4_define([v_ver], [v_maj.v_min.v_mic])
 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_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([HAVE_CURSES], [test x$curses = xyes])
 AM_CONDITIONAL([HAVE_SENSORS], [test x$with_sensors = xyes])
 AM_CONDITIONAL([HAVE_CYGWIN], [test x$have_cygwin = xtrue])
 AM_CONDITIONAL([HAVE_WINDOWS], [test x$have_win32 = 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
 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
 
   * Added scrypt build option.

+ 3 - 3
debian/control

@@ -2,12 +2,12 @@ Source: bfgminer
 Priority: optional
 Section: misc
 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
 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
  monitoring, (over)clocking and fanspeed support for bitcoin and derivative
  coins.

+ 1 - 1
deviceapi.c

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

+ 39 - 23
driver-avalon.c

@@ -96,18 +96,36 @@ static int avalon_init_task(struct avalon_task *at,
 	buf[9] = 0x01;
 	buf[10] = 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;
@@ -454,8 +472,7 @@ static void get_options(int this_option_offset, int *baud, int *miner_count,
 		*baud = 19200;
 		break;
 	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);
 	}
 
@@ -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) {
 				*miner_count = tmp;
 			} else {
-				quit(1,
-					"Invalid avalon-options for "
+				quit(1, "Invalid avalon-options for "
 					"miner_count (%s) must be 1 ~ %d",
 					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)
 				*asic_count = tmp;
 			else {
-				quit(1,
-					"Invalid avalon-options for "
+				quit(1, "Invalid avalon-options for "
 					"asic_count (%s) must be 1 ~ %d",
 					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)
 					*timeout = tmp;
 				else {
-					quit(1,
-						"Invalid avalon-options for "
+					quit(1, "Invalid avalon-options for "
 						"timeout (%s) must be 1 ~ %d",
 						colon3, 0xff);
 				}
@@ -512,12 +526,14 @@ static void get_options(int this_option_offset, int *baud, int *miner_count,
 					case 270:
 					case 282:
 					case 300:
+					case 325:
+					case 350:
+					case 375:
 						*frequency = tmp;
 						break;
 					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;
 	memcpy(&realbuf[3], buf, bufLen);
 	realbuf[0] = '@';
-	realbuf[1] = procid;
-	realbuf[2] = bufLen;
+	realbuf[1] = bufLen;
+	realbuf[2] = procid;
 	bufp = realbuf;
-	while (true)
+	do
 	{
 		rv = BFwrite(fd, bufp, bufLeft);
 		if (rv <= 0)
 			return rv;
 		bufLeft -= rv;
 	}
+	while (bufLeft > 0);
 	return bufLen;
 }
 
@@ -147,6 +148,18 @@ struct bitforce_init_data {
 	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)
 {
 	int fdDev = serial_open(devpath, 0, 10, true);
@@ -154,7 +167,8 @@ static bool bitforce_detect_one(const char *devpath)
 	char pdevbuf[0x100];
 	size_t pdevbuf_len;
 	char *s;
-	int procs = 1, parallel = 1;
+	int procs = 1, parallel = -1;
+	long maxchipno = 0;
 	struct bitforce_init_data *initdata;
 
 	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);
 		
+		if (!strncasecmp(pdevbuf, "PROCESSOR ", 10))
+			maxchipno = max(maxchipno, atoi(&pdevbuf[10]));
+		else
 		if (!strncasecmp(pdevbuf, "DEVICES IN CHAIN:", 17))
 			procs = atoi(&pdevbuf[17]);
 		else
@@ -207,13 +224,16 @@ static bool bitforce_detect_one(const char *devpath)
 		if (!strncasecmp(pdevbuf, "CHIP PARALLELIZATION: YES @", 27))
 			parallel = atoi(&pdevbuf[27]);
 	}
+	parallel = bitforce_chips_to_plan_for(parallel, maxchipno);
 	initdata->parallels = malloc(sizeof(initdata->parallels[0]) * procs);
 	initdata->parallels[0] = parallel;
+	parallel = abs(parallel);
 	for (int proc = 1; proc < procs; ++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)
 			BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
 		for ( ;
@@ -227,17 +247,21 @@ static bool bitforce_detect_one(const char *devpath)
 			
 			applog(LOG_DEBUG, "  %s", pdevbuf);
 			
+			if (!strncasecmp(pdevbuf, "PROCESSOR ", 10))
+				maxchipno = max(maxchipno, atoi(&pdevbuf[10]));
+			else
 			if (!strncasecmp(pdevbuf, "CHIP PARALLELIZATION: YES @", 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);
 	
-	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;
 	}
 	
@@ -285,6 +309,7 @@ struct bitforce_data {
 	int queued;
 	int queued_max;
 	int parallel;
+	bool parallel_protocol;
 	bool already_have_results;
 	bool just_flushed;
 	int ready_to_queue;
@@ -1248,7 +1273,8 @@ static bool bitforce_thread_init(struct thr_info *thr)
 			.proto = BFP_RANGE,
 			.sc = sc,
 			.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));
 		*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);
 		
+		++boardno;
 		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");
 			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");
 			return replybuf;
@@ -1575,7 +1602,7 @@ bool bitforce_queue_do_results(struct thr_info *thr)
 		
 		end = &buf[89];
 		chip_cgpu = bitforce;
-		if (data->parallel > 1)
+		if (data->parallel_protocol)
 		{
 			chipno = strtol(&end[1], &end, 16);
 			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;
+	char buf[LOGBUFSIZ];
+	
 	va_start(ap, fmt);
-	vapplog(prio, fmt, ap);
+	vsnprintf(buf, sizeof(buf), fmt, ap);
 	va_end(ap);
+	_applog(prio, buf);
 	return false;
 }
 #define bailout(...)  return _bailout(fd, NULL, __VA_ARGS__);
@@ -792,6 +795,7 @@ static void
 modminer_fpga_shutdown(struct thr_info *thr)
 {
 	free(thr->cgpu_data);
+	thr->cgpu_data = NULL;
 }
 
 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
 
 extern int mining_threads;
-extern double total_secs;
 extern int opt_g_threads;
 extern bool ping;
 extern bool opt_loginput;
@@ -856,7 +855,7 @@ retry:
 		bool mhash_base = true;
 
 		displayed_rolling = cgpu->rolling;
-		displayed_total = cgpu->total_mhashes / total_secs;
+		displayed_total = cgpu->total_mhashes / cgpu_runtime(cgpu);
 		if (displayed_rolling < 1) {
 			displayed_rolling *= 1000;
 			displayed_total *= 1000;
@@ -898,7 +897,7 @@ retry:
 				if (powertune != -1)
 					tailsprintf(logline, "P: %d%%", powertune);
 				tailsprintf(logline, "\n");
-				wlog("%s", logline);
+				_wlog(logline);
 			}
 		}
 #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)
 			continue;
 		
+		applog(LOG_ERR, "FT_GetComPortNumber(%p (%ld), %ld)", ftHandle, (long)i, (long)lComPortNumber);
 		sprintf(devpathnum, "%d", (int)lComPortNumber);
 		
 		if (detectone(devpath))

+ 30 - 86
logging.c

@@ -1,6 +1,7 @@
 /*
  * Copyright 2011-2012 Con Kolivas
  * Copyright 2012-2013 Luke Dashjr
+ * Copyright 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
@@ -15,75 +16,48 @@
 #include "compat.h"
 #include "logging.h"
 #include "miner.h"
-// #include "util.h"
 
 bool opt_debug = false;
 bool opt_debug_console = false;  // Only used if opt_debug is also enabled
 bool opt_log_output = false;
+bool opt_log_microseconds;
 
 /* per default priorities higher than LOG_NOTICE are logged */
 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)
 		return;
 
 #ifdef HAVE_CURSES
 	extern bool use_curses;
-	if (use_curses && log_curses_only(prio, f, ap))
+	if (use_curses && log_curses_only(prio, datetime, str))
 		;
 	else
 #endif
 	{
-		int len = strlen(f);
 		int cancelstate;
 		bool scs;
-
-		strcpy(f + len - 1, "                    \n");
-
 		scs = !pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancelstate);
 		mutex_lock(&console_lock);
-		vprintf(f, ap);
+		printf("%s%s%s", datetime, str, "                    \n");
 		mutex_unlock(&console_lock);
 		if (scs)
 			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
 	if (use_syslog) {
-		vsyslog(prio, fmt, ap);
+		syslog(prio, "%s", str);
 	}
 #else
 	if (0) {}
@@ -94,8 +68,7 @@ static void log_generic(int prio, const char *fmt, va_list ap)
 		if (!(writetocon || writetofile))
 			return;
 
-		char *f;
-		int len;
+		char datetime[64];
 		struct timeval tv = {0, 0};
 		struct 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);
 
-		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 */
 		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);
 		}
 
 		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__
 
 #include "config.h"
+
 #include <stdbool.h>
+#include <stdio.h>
 #include <stdarg.h>
 
 #ifdef HAVE_SYSLOG_H
@@ -26,31 +28,58 @@ enum {
 };
 #endif
 
-/* original / legacy debug flags */
+/* debug flags */
 extern bool opt_debug;
 extern bool opt_debug_console;
 extern bool opt_log_output;
+extern bool opt_log_microseconds;
 extern bool opt_realquiet;
 extern bool want_per_device_stats;
 
 /* global log_level, messages with lower or equal prio are logged */
 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 {  \
 	applog(prio, __VA_ARGS__);  \
 	return rv;  \
 } 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);
 

+ 4 - 3
make-release

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

+ 98 - 56
miner.c

@@ -69,7 +69,7 @@
 #include "ft232r.h"
 #endif
 
-#if defined(unix)
+#if defined(unix) || defined(__APPLE__)
 	#include <errno.h>
 	#include <fcntl.h>
 	#include <sys/wait.h>
@@ -171,6 +171,11 @@ bool use_curses = true;
 #else
 bool use_curses;
 #endif
+#ifdef HAVE_LIBUSB
+bool have_libusb = true;
+#else
+const bool have_libusb;
+#endif
 static bool opt_submit_stale = true;
 static int opt_shares;
 static int opt_submit_threads = 0x40;
@@ -324,7 +329,7 @@ static int include_count;
 #define JSON_MAX_DEPTH 10
 #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 int forkpid;
 #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 char exit_buf[512];
+
 static void applog_and_exit(const char *fmt, ...)
 {
 	va_list ap;
 
 	va_start(ap, fmt);
-	vapplog(LOG_ERR, fmt, ap);
+	vsnprintf(exit_buf, sizeof(exit_buf), fmt, ap);
 	va_end(ap);
+	_applog(LOG_ERR, exit_buf);
 	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 */
 	pool->tv_idle.tv_sec = ~0UL;
+	
+	cgtime(&pool->cgminer_stats.start_tv);
 
 	pool->rpc_proxy = NULL;
 
@@ -1371,7 +1381,10 @@ static struct opt_table opt_config_table[] = {
 	OPT_WITH_ARG("--log|-l",
 		     set_int_0_to_9999, opt_show_intval, &opt_log_interval,
 		     "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_set_charp, NULL, &opt_stderr_cmd,
 		     "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;
 }
 
+/* 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)
 {
 	struct cgpu_info *cgpu = get_thr_cgpu(thr_id);
@@ -2185,6 +2204,30 @@ void tailsprintf(char *f, const char *fmt, ...)
 	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
  * associated suitable for Mega, Giga etc. Buf array needs to be long enough */
 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;
 	char cHr[h2bs_fmt_size[H2B_NOUNIT]], aHr[h2bs_fmt_size[H2B_NOUNIT]], uHr[h2bs_fmt_size[hashrate_style]];
 	char rejpcbuf[6];
+	double dev_runtime;
 	
 	if (!opt_show_procs)
 		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 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)
 		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;
 			mhashes += slave->total_mhashes;
@@ -2391,7 +2436,7 @@ static void get_statline2(char *buf, struct cgpu_info *cgpu, bool for_curses)
 	ti_hashrate_bufstr(
 		(char*[]){cHr, aHr, uHr},
 		1e6*rolling,
-		1e6*mhashes / total_secs,
+		1e6*mhashes / dev_runtime,
 		utility_to_hashrate(wutil),
 		hashrate_style);
 
@@ -2408,6 +2453,12 @@ static void get_statline2(char *buf, struct cgpu_info *cgpu, bool for_curses)
 #endif
 		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)
@@ -2697,31 +2748,23 @@ static void switch_logsize(void)
 }
 
 /* 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 */
-void wlogprint(const char *f, ...)
+void _wlogprint(const char *str)
 {
-	va_list ap;
-
 	if (curses_active_locked()) {
-		va_start(ap, f);
-		vw_printw(logwin, f, ap);
-		va_end(ap);
+		wprintw(logwin, "%s", str);
 		unlock_curses();
 	}
 }
 #endif
 
 #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;
 
@@ -2729,7 +2772,7 @@ bool log_curses_only(int prio, const char *f, va_list ap)
 
 	if (curses_active_locked()) {
 		if (!opt_loginput || high_prio) {
-			vw_printw(logwin, f, ap);
+			wprintw(logwin, "%s%s\n", datetime, str);
 			if (high_prio) {
 				touchwin(logwin);
 				wrefresh(logwin);
@@ -3558,8 +3601,6 @@ static void __kill_work(void)
 	applog(LOG_DEBUG, "Killing off mining threads");
 	/* Kill the mining threads*/
 	for (i = 0; i < mining_threads; i++) {
-		pthread_t *pth = NULL;
-		
 		thr = get_thread(i);
 		if (!(thr && thr->cgpu->threads))
 			continue;
@@ -3604,7 +3645,7 @@ void app_restart(void)
 	__kill_work();
 	clean_up();
 
-#if defined(unix)
+#if defined(unix) || defined(__APPLE__)
 	if (forkpid > 0) {
 		kill(forkpid, SIGTERM);
 		forkpid = 0;
@@ -4615,7 +4656,7 @@ void switch_pools(struct pool *selected)
 		pool->block_id = 0;
 		if (pool_strategy != POOL_LOADBALANCE && pool_strategy != POOL_BALANCE) {
 			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);
 		}
 	}
@@ -5242,7 +5283,7 @@ void write_config(FILE *fcfg)
 		fputs(",\n\"round-robin\" : true", fcfg);
 	if (pool_strategy == POOL_ROTATE)
 		fprintf(fcfg, ",\n\"rotate\" : \"%d\"", opt_rotate_period);
-#if defined(unix)
+#if defined(unix) || defined(__APPLE__)
 	if (opt_stderr_cmd && *opt_stderr_cmd)
 		fprintf(fcfg, ",\n\"monitor\" : \"%s\"", json_escape(opt_stderr_cmd));
 #endif // defined(unix)
@@ -5367,6 +5408,7 @@ void zero_stats(void)
 		pool->diff_rejected = 0;
 		pool->diff_stale = 0;
 		pool->last_share_diff = 0;
+		pool->cgminer_stats.start_tv = total_tv_start;
 		pool->cgminer_stats.getwork_calls = 0;
 		pool->cgminer_stats.getwork_wait_min.tv_sec = MIN_SEC_UNSET;
 		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_comms_error_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_wait_min.tv_sec = MIN_SEC_UNSET;
 		cgpu->cgminer_stats.getwork_wait_max.tv_sec = 0;
@@ -5735,7 +5778,7 @@ retry:
 
 void default_save_file(char *filename)
 {
-#if defined(unix)
+#if defined(unix) || defined(__APPLE__)
 	if (getenv("HOME") && *getenv("HOME")) {
 	        strcpy(filename, getenv("HOME"));
 		strcat(filename, "/");
@@ -6358,7 +6401,7 @@ static bool cnx_needed(struct pool *pool)
 	cp = current_pool();
 	if (cp == pool)
 		return true;
-	if (!cp->has_stratum && (!opt_fail_only || !cp->hdr_path))
+	if (!pool_localgen(cp) && (!opt_fail_only || !cp->hdr_path))
 		return true;
 
 	/* 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++;
 			total_go++;
 
+			mutex_lock(&pool->stratum_lock);
+			pool->stratum_active = pool->stratum_notify = false;
 			pool->sock = INVSOCK;
+			mutex_unlock(&pool->stratum_lock);
 
 			/* If the socket to our stratum pool disconnects, all
 			 * 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;
 			int gpu;
 
-			if (cgpu->drv->get_stats)
+			if (cgpu->drv->get_stats && likely(cgpu->status != LIFE_INIT))
 			  cgpu->drv->get_stats(cgpu);
 
 			gpu = cgpu->device_id;
@@ -8125,6 +8171,7 @@ static void clean_up(void)
 	clear_adl(nDevs);
 #endif
 #ifdef HAVE_LIBUSB
+	if (likely(have_libusb))
         libusb_exit(NULL);
 #endif
 
@@ -8141,30 +8188,20 @@ static void clean_up(void)
 	curl_global_cleanup();
 }
 
-void quit(int status, const char *format, ...)
+void _quit(int status)
 {
-	va_list ap;
-
 	clean_up();
 
-	if (format) {
-		va_start(ap, format);
-		vfprintf(stderr, format, ap);
-		va_end(ap);
-	}
-	fprintf(stderr, "\n");
-	fflush(stderr);
-
 	if (status) {
 		const char *ev = getenv("__BFGMINER_SEGFAULT_ERRQUIT");
 		if (unlikely(ev && ev[0] && ev[0] != '0')) {
-			const char **p = NULL;
+			int *p = NULL;
 			// 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) {
 		kill(forkpid, SIGTERM);
 		forkpid = 0;
@@ -8303,7 +8340,7 @@ out:
 }
 #endif
 
-#if defined(unix)
+#if defined(unix) || defined(__APPLE__)
 static void fork_monitor()
 {
 	// Make a pipe: [readFD, writeFD]
@@ -8547,6 +8584,10 @@ int main(int argc, char *argv[])
 	int i, j;
 	char *s;
 
+#ifdef WIN32
+	LoadLibrary("backtrace.dll");
+#endif
+
 	blkmk_sha256_impl = my_blkmaker_sha256_callback;
 
 #ifndef HAVE_PTHREAD_CANCEL
@@ -8566,9 +8607,8 @@ int main(int argc, char *argv[])
 #ifdef HAVE_LIBUSB
 	int err = libusb_init(NULL);
 	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
 
@@ -8690,7 +8730,8 @@ int main(int argc, char *argv[])
 	}
 
 #ifdef USE_X6500
-	ft232r_scan();
+	if (likely(have_libusb))
+		ft232r_scan();
 #endif
 
 #ifdef HAVE_CURSES
@@ -8801,12 +8842,12 @@ int main(int argc, char *argv[])
 #endif
 
 #ifdef USE_X6500
-	if (!opt_scrypt)
+	if (likely(have_libusb) && !opt_scrypt)
 		x6500_api.drv_detect();
 #endif
 
 #ifdef USE_ZTEX
-	if (!opt_scrypt)
+	if (likely(have_libusb) && !opt_scrypt)
 		ztex_drv.drv_detect();
 #endif
 
@@ -8822,7 +8863,8 @@ int main(int argc, char *argv[])
 #endif
 
 #ifdef USE_X6500
-	ft232r_scan_free();
+	if (likely(have_libusb))
+		ft232r_scan_free();
 #endif
 
 	for (i = 0; i < total_devices; ++i)
@@ -8923,7 +8965,7 @@ int main(int argc, char *argv[])
 		openlog(PACKAGE, LOG_PID, LOG_USER);
 #endif
 
-	#if defined(unix)
+	#if defined(unix) || defined(__APPLE__)
 		if (opt_stderr_cmd)
 			fork_monitor();
 	#endif // defined(unix)
@@ -9172,13 +9214,13 @@ begin_bench:
 
 		/* If the primary pool is a getwork pool and cannot roll work,
 		 * 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;
 
 		mutex_lock(stgd_lock);
 		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;
 
 		/* 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 timeval start_tv;
+	
 	uint32_t getwork_calls;
 	struct timeval getwork_wait;
 	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)
 
-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)
 {
@@ -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 void hash_queued_work(struct thr_info *mythr);
 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 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 int prioritize_pools(char *param, int *pid);
 extern void validate_pool_priorities(void);
@@ -1271,7 +1276,7 @@ extern void write_config(FILE *fcfg);
 extern void zero_bestshare(void);
 extern void zero_stats(void);
 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 logwin_update(void);
 extern bool pool_tclear(struct pool *pool, bool *var);

+ 1 - 0
ocl.c

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

+ 1 - 1
openwrt/bfgminer/Makefile

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

+ 1 - 1
phatk121016.cl

@@ -81,7 +81,7 @@ __constant uint H[8] = {
 #else // BITALIGN
 	#define Ch(x, y, z) (z ^ (x & (y ^ 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))
 #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;
 		case SEND_SELECTFAIL:
 			applog(LOG_DEBUG, "Write select failed on pool %d sock", pool->pool_no);
+			suspend_stratum(pool);
 			break;
 		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;
 		case SEND_INACTIVE:
 			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);
 	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);
 	mutex_unlock(&pool->stratum_lock);
 
@@ -1372,11 +1377,16 @@ char *recv_line(struct pool *pool)
 			n = recv(pool->sock, s, RECVSIZE, 0);
 			if (!n) {
 				applog(LOG_DEBUG, "Socket closed waiting in recv_line");
+				suspend_stratum(pool);
 				break;
 			}
 			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)) {
-					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;
 				}
 			} else {