Browse Source

Merge branch 'bfgminer' into bifury

Luke Dashjr 12 years ago
parent
commit
1c221287f4
47 changed files with 1040 additions and 798 deletions
  1. 3 0
      AUTHORS
  2. 8 3
      Makefile.am
  3. 61 74
      README
  4. 53 6
      README.ASIC
  5. 45 0
      README.CPU
  6. 47 46
      README.FPGA
  7. 20 18
      README.GPU
  8. 3 2
      README.OpenWrt
  9. 211 199
      README.RPC
  10. 4 4
      README.scrypt
  11. 2 0
      adl.c
  12. 13 1
      api.c
  13. 211 0
      binloader.c
  14. 14 0
      binloader.h
  15. 52 23
      configure.ac
  16. 6 0
      debian/changelog
  17. 1 1
      debian/rules
  18. 8 6
      deviceapi.c
  19. 2 1
      driver-avalon.c
  20. 1 1
      driver-bigpic.c
  21. 4 1
      driver-bitforce.c
  22. 2 1
      driver-bitfury.c
  23. 1 1
      driver-cairnsmore.c
  24. 1 1
      driver-erupter.c
  25. 0 1
      driver-hashbuster.c
  26. 1 1
      driver-icarus.c
  27. 21 19
      driver-klondike.c
  28. 1 1
      driver-littlefury.c
  29. 2 1
      driver-modminer.c
  30. 0 1
      driver-nanofury.c
  31. 1 1
      driver-opencl.c
  32. 2 1
      driver-x6500.c
  33. 1 1
      driver-ztex.c
  34. 0 1
      ft232r.c
  35. 2 1
      libztex.c
  36. 0 1
      lowl-hid.c
  37. 35 1
      lowl-usb.c
  38. 12 0
      lowl-usb.h
  39. 15 327
      lowl-vcom.c
  40. 2 22
      lowl-vcom.h
  41. 66 1
      lowlevel.c
  42. 6 1
      lowlevel.h
  43. 11 1
      mcp2210.c
  44. 80 21
      miner.c
  45. 2 0
      miner.h
  46. 1 1
      miner.php
  47. 6 4
      util.c

+ 3 - 0
AUTHORS

@@ -41,3 +41,6 @@ pontus <liquidpontus@yahoo.se>
 Tydus <Tydus@Tydus.org>
 Raulo <p987341@gmail.com>
 Thorsten Gilling <tgilling@web.de>
+capa66 <capa66@x204.com>
+Red_Wolf_2 <redwolf@wolfnexus.net>
+Mr O <notanatheist@gmail.com>

+ 8 - 3
Makefile.am

@@ -129,6 +129,7 @@ dist_doc_DATA += README.scrypt
 endif
 
 if HAS_CPUMINE
+dist_doc_DATA += README.CPU
 bfgminer_SOURCES	+= \
 		  sha256_generic.c sha256_via.c	\
 		  sha256_cryptopp.c sha256_sse2_amd64.c		\
@@ -167,8 +168,8 @@ endif # HAVE_x86_64
 endif # HAS_YASM
 endif # HAS_CPUMINE
 
-if NEED_FPGAUTILS
-bfgminer_SOURCES += fpgautils.c fpgautils.h
+if NEED_BFG_LOWL_VCOM
+bfgminer_SOURCES += lowl-vcom.c lowl-vcom.h
 if HAVE_WINDOWS
 else
 bfgminer_SOURCES += iospeeds.h iospeeds_posix.h
@@ -176,7 +177,11 @@ endif
 endif
 
 if HAVE_LIBUSB
-bfgminer_SOURCES += lowl-usb.c
+bfgminer_SOURCES += lowl-usb.c lowl-usb.h
+endif
+
+if NEED_BFG_BINLOADER
+bfgminer_SOURCES += binloader.c binloader.h
 endif
 
 if NEED_BFG_LOWLEVEL

+ 61 - 74
README

@@ -67,13 +67,14 @@ If you specify the --socks-proxy option to BFGMiner, it will only be applied to
 all pools that don't specify their own proxy setting like above
 
 
-After saving configuration from the menu, you do not need to give BFGMiner any
-arguments and it will load your configuration.
+After saving configuration from the menu ([S],[W]) you do not need to give
+BFGMiner any arguments, it will load your configuration instead.
 
 Any configuration file may also contain a single
 	"include" : "filename"
 to recursively include another configuration file.
-Writing the configuration will save all settings from all files in the output.
+Writing the configuration will save all settings from all files to the output
+configuration file.
 
 
 ---
@@ -104,7 +105,7 @@ Optional Dependencies:
 	  libpdcurses        http://pdcurses.sourceforge.net/ (Linux/Mac/Windows)
 
 	Multiple ASIC/FPGA autodetection: any one of:
-	  sysfs              (builtin to most Linux kernels, just mount on /sys)
+	  sysfs              (built-in to most Linux kernels, just mount on /sys)
 	  libudev-dev        http://www.freedesktop.org/software/systemd/libudev/
 	
 	HashBuster & NanoFury USB devices:
@@ -146,7 +147,7 @@ BFGMiner specific configuration options:
 	--enable-metabank       Compile support for Metabank (default disabled)
 	--disable-bitforce      Compile support for BitForce (default enabled)
 	--disable-icarus        Compile support for Icarus (default enabled)
-	--enable-klondike       Compile support for Klondike (default disabled)
+	--disable-klondike      Compile support for Klondike (default enabled)
 	--enable-knc            Compile support for KnC (default disabled)
 	--disable-modminer      Compile support for ModMiner (default enabled)
 	--disable-x6500         Compile support for X6500 (default enabled)
@@ -179,6 +180,8 @@ Native WIN32 build instructions: see windows-build.txt
 If you build BFGMiner from source, it is recommended that you run it from the
 build directory. On *nix, you will usually need to prepend your command with a
 path like this (if you are in the bfgminer directory already): ./bfgminer
+To install system wide run 'sudo make install' or 'make install' as root. You
+can then run from any terminal.
 
 ---
 
@@ -226,7 +229,7 @@ Options for both config file and command line:
 --log-file|-L <arg> Append log file for output messages
 --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
+--net-delay         Impose small delays in networking to avoid overloading slow routers
 --no-gbt            Disable getblocktemplate support
 --no-getwork        Disable getwork support
 --no-longpoll       Disable X-Long-Polling support
@@ -248,6 +251,7 @@ Options for both config file and command line:
 --retries <arg>     Number of times to retry failed submissions before giving up (-1 means never) (default: -1)
 --rotate <arg>      Change multipool strategy from failover to regularly rotate at N minutes (default: 0)
 --round-robin       Change multipool strategy from failover to round robin on failure
+--scan|-S <arg>     Configure how to scan for mining devices
 --scan-time|-s <arg> Upper bound on time spent scanning current work, in seconds (default: 60)
 --sched-start <arg> Set a time of day in HH:MM to start mining (a once off without a stop time)
 --sched-stop <arg>  Set a time of day in HH:MM to stop mining (will quit without a start time)
@@ -314,9 +318,6 @@ scrypt only options:
 
 See README.scrypt for more information regarding (non-bitcoin) scrypt mining.
 
-ASIC/FPGA mining device options:
-
---scan-serial|-S <arg> Serial port to probe for mining devices
 
 To use ASICs or FPGAs, you will need to be sure the user BFGMiner is running as
 has appropriate permissions. This varies by operating system.
@@ -337,9 +338,9 @@ On Windows, <arg> is usually of the format \\.\COMn
 
 The official supplied binaries are compiled with support for all ASICs/FPGAs.
 To force the code to only attempt detection with a specific driver,
-prepend the argument with the driver name followed by a colon.
-For example, "icarus:/dev/ttyUSB0" or "bitforce:\\.\COM5"
-or using the short name: "ica:/dev/ttyUSB0" or "bfl:\\.\COM5"
+prepend the argument with the driver name followed by an "at" symbol.
+For example, "icarus@/dev/ttyUSB0" or "bitforce@\\.\COM5"
+or using the short name: "ica@/dev/ttyUSB0" or "bfl@\\.\COM5"
 
 Some FPGAs do not have non-volatile storage for their bitstreams and must be
 programmed every power cycle, including first use. To use these devices, you
@@ -348,22 +349,7 @@ must download the proper bitstream from the vendor's website and copy it to the
 
 See README.ASIC and README.FPGA for more information regarding these.
 
-CPU only options (not included in binaries):
-
---algo|-a <arg>     Specify sha256 implementation for CPU mining:
-        fastauto*       Quick benchmark at startup to pick a working algorithm
-        auto            Benchmark at startup and pick fastest algorithm
-        c               Linux kernel sha256, implemented in C
-        4way            tcatm's 4-way SSE2 implementation
-        via             VIA padlock implementation
-        cryptopp        Crypto++ C/C++ implementation
-        cryptopp_asm32  Crypto++ 32-bit assembler implementation
-        sse2_32         SSE2 32 bit implementation for i386 machines
-        sse2_64         SSE2 64 bit implementation for x86_64 machines
-        sse4_64         SSE4.1 64 bit implementation for x86_64 machines
-        altivec_4way    Altivec implementation for PowerPC G4 and G5 machines
---cpu-threads|-t <arg> Number of miner CPU threads (default: 4)
-
+See README.CPU for information regarding CPU mining.
 
 ---
 
@@ -419,7 +405,7 @@ co[M]pact: off
 Q quits the application.
 
 
-The running log shows output like this:
+The running log shows output similar to that below:
 
  [2013-02-13 00:26:30] Accepted 1758e8df BFL 0  pool 0 Diff 10/1
  [2013-02-13 00:26:32] Accepted 1d9a2199 MMQ 0a pool 0 Diff 8/1
@@ -517,7 +503,8 @@ between the rest of the pools.
 
 BALANCE:
 This strategy monitors the amount of difficulty 1 shares solved for each pool
-and uses it to try to end up doing the same amount of work for all pools.
+and uses it as a basis for trying to doing the same amount of work for each
+pool.
 
 
 ---
@@ -565,22 +552,22 @@ semicolon separated --quota(or -U) entry instead of --url. Pools specified with
 --url are given a nominal quota value of 1 and entries can be mixed.
 
 For example:
---url poola:porta -u usernamea -p passa --quota "2;poolb:portb" -u usernameb -p passb
-Will give poola 1/3 of the work and poolb 2/3 of the work.
+--url poolA:portA -u usernameA -p passA --quota "2;poolB:portB" -u usernameB -p passB
+Will give poolA 1/3 of the work and poolB 2/3 of the work.
 
 Writing configuration files with quotas is likewise supported. To use the above
 quotas in a configuration file they would be specified thus:
 
 "pools" : [
         {
-                "url" : "poola:porta",
-                "user" : "usernamea",
-                "pass" : "passa"
+                "url" : "poolA:portA",
+                "user" : "usernameA",
+                "pass" : "passA"
         },
         {
-                "quota" : "2;poolb:portb",
-                "user" : "usernameb",
-                "pass" : "passb"
+                "quota" : "2;poolB:portB",
+                "user" : "usernameB",
+                "pass" : "passB"
         }
 ]
 
@@ -658,9 +645,9 @@ FAQ
 
 Q: Why can't BFGMiner find lib<something> even after I installed it from source
 code?
-A: On UNIX-like operating systems, you often need to run some command to reload
-its library caches such as "ldconfig" or similar. A couple of systems (such as
-Fedora) ship with /usr/local/lib missing from their library search path. In
+A: On UNIX-like operating systems, you often need to run one or more commands to
+reload library caches, such as "ldconfig" or similar. A couple of systems (such
+as Fedora) ship with /usr/local/lib missing from their library search path. In
 this case, you can usually add it like this:
     echo /usr/local/lib >/etc/ld.so.conf.d/local.conf
 Please note that if your libraries installed into lib64 instead of lib, you
@@ -678,11 +665,11 @@ make it invalidate the work from each other.
 
 Q: Can I configure BFGMiner to mine with different login credentials or pools
 for each separate device?
-A: No.
+A: No such feature has been implemented to support this.
 
 Q: Can I put multiple pools in the config file?
 A: Yes, check the example.conf file. Alternatively, set up everything either on
-the command line or via the menu after startup and choose settings->write
+the command line or via the menu after startup and choose [S]ettings->[W]rite
 config file and the file will be loaded one each startup.
 
 Q: The build fails with gcc is unable to build a binary.
@@ -702,17 +689,18 @@ useful and not risk idle periods. You can disable this behaviour with the
 option --failover-only.
 
 Q: Is this a virus?
-A: BFGMiner is being packaged with other trojan scripts and some antivirus
-software is falsely accusing bfgminer.exe as being the actual virus, rather
-than whatever it is being packaged with. If you installed BFGMiner yourself,
-then you do not have a virus on your computer. Complain to your antivirus
-software company. They seem to be flagging even source code now from BFGMiner
-as viruses, even though text source files can't do anything by themself.
+A: As BFGMiner is being packaged with other trojan scripts, some antivirus
+software is falsely accusing bfgminer.exe as being the actual virus, rather than
+whatever it is being packaged with. If you installed BFGMiner yourself from a
+reputable source then you do not have a virus on your computer. Complain to your
+antivirus software company. They seem to be flagging even source code from
+BFGMiner as malicious now, even though text source files can't do anything by
+themselves.
 
 Q: Can you modify the display to include more of one thing in the output and
 less of another, or can you change the quiet mode or can you add yet another
 output mode?
-A: Everyone will always have their own view of what's important to monitor.
+A: Everyone will always have their own view of what is important to monitor.
 The defaults are very sane and I have very little interest in changing this
 any further.
 
@@ -720,36 +708,31 @@ Q: Why is my efficiency above/below 1.00?
 A: Efficiency simply means how many shares you return for the amount of
 bandwidth used. It does not correlate with efficient use of your hardware, and
 is a measure of a combination of hardware speed, block luck, pool design and
-other factors.
+many other factors.
 
 Q: What are the best parameters to pass for X pool/hardware/device.
 A: Virtually always, the DEFAULT parameters give the best results. Most user
 defined settings lead to worse performance.
 
 Q: What happened to CPU mining?
-A: Being increasingly irrelevant for most users, and a maintenance issue, it is
-no longer under active development and will not be supported unless someone
-steps up to help maintain it. No binary builds supporting CPU mining will be
-released for Windows but CPU mining can be built into BFGMiner when it is
-compiled. For builds which do support CPU mining, it is still disabled by
-default, and must be enabled using the -S cpu:auto option.
+A: See README.CPU for more information.
 
-Q: GUI version?
-A: No. The RPC interface makes it possible for someone else to write one
-though.
+Q: Will there ever be a GUI version?
+A: No, however the RPC interface makes it possible for someone else to write one
+if they choose.
 
 Q: I'm having an issue. What debugging information should I provide?
 A: Start BFGMiner with your regular commands and add -D -T --verbose and provide
-the full startup output and a summary of your hardware, operating system, ATI
-driver version and ATI stream version.
+the full startup output and a summary of your hardware, operating system, and if
+applicable, ATI driver version and ATI stream version.
 
 Q: Can I mine with BFGMiner on a Mac?
 A: BFGMiner will compile on OS X, but the performance of GPU mining is
 compromised due to the OpenCL implementation on OS X, there is no temperature or
-fanspeed monitoring, and the cooling design of most Macs, despite having
+fanspeed monitoring and the cooling design of most Macs, despite having
 powerful GPUs, will usually not cope with constant usage leading to a high risk
-of thermal damage. It is highly recommended not to mine on a Mac unless it is to
-a USB device.
+of thermal damage. It is highly recommended not to mine on a Mac unless it is
+with an external USB device.
 
 Q: My network gets slower and slower and then dies for a minute?
 A; Try the --net-delay option if you are on a getwork or GBT server.
@@ -768,7 +751,7 @@ will not work.
 Q: I run PHP on windows to access the API with the example miner.php. Why does
 it fail when php is installed properly but I only get errors about Sockets not
 working in the logs?
-A: http://us.php.net/manual/en/sockets.installation.php
+A: Please check http://us.php.net/manual/en/sockets.installation.php
 
 Q: What is a PGA?
 A: At the moment, BFGMiner supports 5 FPGAs: BitForce, Icarus, ModMiner, X6500,
@@ -779,7 +762,7 @@ been skipped. "PGA" is also used for devices built with Application-Specific
 Integrated Circuits (ASICs).
 
 Q: What is an ASIC?
-A: They are Application Specify Integrated Circuit devices and provide the
+A: They are Application Specific Integrated Circuit devices and provide the
 highest performance per unit power due to being dedicated to only one purpose.
 
 Q: How do I get my BFL/Icarus/Lancelot/Cairnsmore device to auto-recognise?
@@ -804,22 +787,25 @@ Q: I ran cgminer, and now BFGMiner doesn't work!
 A: cgminer has its own non-standard implementations of the drivers for most USB
 devices, and requires you to replace the official drivers with WinUSB on Windows
 (usually using Zadig). Before you can use BFGMiner, you will need to restore the
-original driver.
+original driver. Uninstalling the device (and WinUSB driver) from Device Manager
+and re-plugging it will usually trigger driver re-installation to the default
+drivers.
 
 Q: On Linux I can see the /dev/ttyUSB* devices for my ICA/BFL/MMQ FPGA, but
-BFGMiner can't mine on them
-A: Make sure you have the required priviledges to access the /dev/ttyUSB*
+BFGMiner can't mine on them?
+A: Make sure you have the required privileges to access the /dev/ttyUSB*
 devices:
  sudo ls -las /dev/ttyUSB*
 will give output like:
  0 crw-rw---- 1 root dialout 188, 0 2012-09-11 13:49 /dev/ttyUSB0
-This means your account must have the group 'dialout' or root priviledges
+This means your account must have the group 'dialout' or root privileges
 To permanently give your account the 'dialout' group:
  sudo usermod -G dialout -a `whoami`
 Then logout and back in again
 
 Q: Can I mine scrypt with FPGAs or ASICs?
-A: No.
+A: Currently no. Bitcoin ASICs are only useful for SHA256d systems and FPGAs
+generally aren't designed to handle scrypt efficiently.
 
 Q: Why does BFGMiner show difficulty 0 when mining scrypt?
 A: BFGMiner consistently uses pdiff measurement for difficulty everywhere,
@@ -846,8 +832,9 @@ A: As an example, if you look at 'Difficulty Accepted' in the RPC API, the numbe
 of difficulty shares accepted does not usually exactly equal the amount of work
 done to find them. If you are mining at 8 difficulty, then you would expect on
 average to find one 8 difficulty share, per 8 single difficulty shares found.
-However, the number is actually random and converges over time, it is an average,
-not an exact value, thus you may find more or less than the expected average.
+However, the number is actually random and converges over time as it is an
+average, not an exact value, thus you may find more or less than the expected
+average.
 
 ---
 

+ 53 - 6
README.ASIC

@@ -1,8 +1,9 @@
 SUPPORTED DEVICES
 
 Currently supported ASIC devices include Avalon, Bitfountain's Block Erupter
-series (both USB and blades), a large variety of Bitfury-based miners, Butterfly
-Labs' SC range of devices, and Klondike modules.
+series (both USB and blades), a large variety of Bitfury-based miners,
+Butterfly Labs' SC range of devices, Klondike modules, and KnCminer's Mercury,
+Jupiter and Saturn.
 
 
 AVALON
@@ -26,7 +27,7 @@ router used by the Avalon. eg:
 The values are baud : miners : asic count : timeout : frequency.
 
 Baud:
-The device is pretty much hard coded to emulate 115200 baud so you shouldn't
+The device is essentially hard coded to emulate 115200 baud so you shouldn't
 change this.
 
 Miners:
@@ -37,8 +38,9 @@ Asic count:
 Virtually all have 10, so don't change this.
 
 Timeout:
-This is how long the device will work on a work item before accepting new work
-to replace it. It should be changed according to the frequency (last setting).
+This defines how long the device will work on a work item before accepting new
+work to replace it. It should be changed according to the frequency (last
+setting).
 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.
@@ -63,7 +65,7 @@ AVA 0: 22/ 46C  60%/2400R
 The values are:
 ambient temp / highest device temp  set fan % / lowest detected fan RPM.
 
-Use the API for more detailed information than this.
+Check the API for more detailed information.
 
 
 BFSB, MEGABIGPOWER, AND METABANK BITFURY BOARDS
@@ -148,6 +150,51 @@ KLONDIKE
 --klondike-options <arg> Set klondike options clock:temptarget
 
 
+KNCMINER
+--------
+
+The KnC miner uses a BeagleBoneBlack(BBB) as the host, this is pluged into a
+cape that holds the FPGA and connections for 4-6 ASICS depending on the cape
+version. The BBB runs the Angstrom linux distribution, the following is a step
+by step install for BFGMiner on this distro;
+
+-----------------Start------------
+cat >/etc/opkg/feeds.conf <<\EOF
+src/gz noarch http://feeds.angstrom-distribution.org/feeds/v2013.06/ipk/eglibc/all/
+src/gz base http://feeds.angstrom-distribution.org/feeds/v2013.06/ipk/eglibc/cortexa8hf-vfp-neon/base/
+src/gz beaglebone http://feeds.angstrom-distribution.org/feeds/v2013.06/ipk/eglibc/cortexa8hf-vfp-neon/machine/beaglebone/
+EOF
+
+opkg update
+opkg install angstrom-feed-configs
+rm /etc/opkg/feeds.conf
+opkg update
+
+opkg install update-alternatives
+opkg install automake autoconf make gcc cpp binutils git less pkgconfig-dev ncurses-dev libtool nano bash i2c-tools-dev
+while ! opkg install libcurl-dev; do true; done
+ln -s aclocal-1.12 /usr/share/aclocal
+
+curl http://www.digip.org/jansson/releases/jansson-2.0.1.tar.bz2 | tar -xjvp
+cd jansson-2.0.1
+./configure --prefix=/usr CC=arm-angstrom-linux-gnueabi-gcc --disable-static NM=arm-angstrom-linux-gnueabi-nm
+make install && ldconfig
+cd ..
+
+git clone git://github.com/luke-jr/bfgminer
+cd bfgminer
+./autogen.sh
+git clone git://github.com/troydhanson/uthash
+./configure --host=arm-angstrom-linux-gnueabi --enable-knc CFLAGS="-I$PWD/uthash/src -O0 -ggdb"
+make AR=arm-angstrom-linux-gnueabi-ar
+
+/etc/init.d/cgminer.sh stop
+./bfgminer -S knc:auto -c /config/cgminer.conf
+
+---------------END-------------
+
+BFGMiner has also been incorporated into an unofficial firmware by uski01 called Bertmod this can be found on the kncminer forum.
+
 ---
 
 This code is provided entirely free of charge by the programmer in his spare

+ 45 - 0
README.CPU

@@ -0,0 +1,45 @@
+EXECUTIVE SUMMARY ON CPU USAGE:
+
+By default, BFGMiner will NOT mine on CPUs unless it is explicitly compiled with
+support and told to do so. CPU mining for bitcoin is generally considered to be
+obsolete as it requires considerably more power per hash computed than either
+GPU, FPGA or ASIC based mining. If you still wish to mine using CPUs you will
+need to build a custom binary with support enabled (refer to the build notes in
+README for further information).
+
+The following CPU mining options are available:
+
+--algo|-a <arg> Specify sha256 implementation for CPU mining:
+        fastauto*       Quick benchmark at startup to pick a working algorithm
+        auto            Benchmark at startup and pick fastest algorithm
+        c               Linux kernel sha256, implemented in C
+        4way            tcatm's 4-way SSE2 implementation
+        via             VIA padlock implementation
+        cryptopp        Crypto++ C/C++ implementation
+        cryptopp_asm32  Crypto++ 32-bit assembler implementation
+        sse2_32         SSE2 32 bit implementation for i386 machines
+        sse2_64         SSE2 64 bit implementation for x86_64 machines
+        sse4_64         SSE4.1 64 bit implementation for x86_64 machines
+        altivec_4way    Altivec implementation for PowerPC G4 and G5 machines
+--cpu-threads|-t <arg> Number of miner CPU threads (default: 4)
+
+CPU FAQ:
+
+Q: What happened to CPU mining?
+A: Being increasingly irrelevant for most users, and a maintenance issue, it is
+no longer under active development and will not be supported unless someone
+steps up to help maintain it. No binary builds supporting CPU mining will be
+released for Windows but CPU mining can be built into BFGMiner when it is
+compiled. For builds which do support CPU mining, it is still disabled by
+default, and must be enabled using the -S cpu:auto option.
+
+Q: So, should I even try CPU mining?
+A: No, it honestly will waste more power and time than it is worth at this stage.
+If you really wish to mine, you are better off getting a suitable ASIC instead.
+
+Q: But, if the computers aren't mine and I'm not paying for the power?
+A: If you are trying to use computers that aren't yours, you really should
+reconsider. Attempting to mine with a large number of devices will often impact
+negatively on many pools and will likely pay almost nothing due to the small
+number of successful shares submitted. Apart from that, you will probably get
+into trouble with someone down the track for misusing the computers.

+ 47 - 46
README.FPGA

@@ -15,27 +15,27 @@ from FPGA Mining LLC's website:
 -
 
 If the MMQ doesn't respond to BFGMiner at all, or the red LED isn't flashing
-then you will need to reset the MMQ
+then you will need to reset the MMQ.
 
-The red LED should always be flashing when it is mining or ready to mine
+The red LED should always be flashing when it is mining or ready to mine.
 
 To reset the MMQ, you are best to press the left "RESET" button on the
-backplane, then unplug and replug the USB cable
+backplane, then unplug and replug the USB cable.
 
 If your MMQ doesn't have a button on the "RESET" pad, you need to join the two
 left pads of the "RESET" pad with conductive wire to reset it. Cutting a small
-(metal) paper-clip in half works well for this
+(metal) paper-clip in half works well for this.
 
-Then unplug the USB cable, wait for 5 seconds, then plug it back in
+Then unplug the USB cable, wait for 5 seconds, then plug it back in.
 
-After you press reset, the red LED near the USB port should blink continuously
+After you press reset, the red LED near the USB port should blink continuously.
 
 If it still wont work, power off, wait for 5 seconds, then power on the MMQ
-This of course means it will upload the bitstream again when you start BFGMiner
+This of course means it will upload the bitstream again when you start BFGMiner.
 
 -
 
-Device 0 is on the power end of the board
+Device 0 is on the power end of the board.
 
 -
 
@@ -45,25 +45,25 @@ Read here for official details of changing the firmware:
 
 The basics of changing the firmware are:
  You need two short pieces of conductive wire if your MMQ doesn't have buttons
- on the "RESET" and "ISP" pads on the backplane board
- Cutting a small (metal) paper-clip in half works well for this
+ on the "RESET" and "ISP" pads on the backplane board.
+ Cutting a small (metal) paper-clip in half works well for this.
 
- Join the 2 left pads of the "RESET" pad with wire and the led will dim
+ Join the 2 left pads of the "RESET" pad with wire and the led will dim.
  Without disconnecting the "RESET", join the 2 left pads of the "ISP" pad with
- a wire and it will stay dim
- Release "RESET" then release "ISP" and is should still be dim
+ a wire and it will stay dim.
+ Release "RESET" then release "ISP" and is should still be dim.
  Unplug the USB and when you plug it back in it will show up as a mass storage
- device
+ device.
   Linux: (as one single line):
    mcopy -i /dev/disk/by-id/usb-NXP_LPC134X_IFLASH_ISP000000000-0:0
       modminer091012.bin ::/firmware.bin
   Windows: delete the MSD device file firmware.bin and copy in the new one
    rename the new file and put it under the same name 'firmware.bin'
  Disconnect the USB correctly (so writes are flushed first)
- Join and then disconnect "RESET" and then plug the USB back in and it's done
+ Join and then disconnect "RESET" and then plug the USB back in and it's done.
 
 Best to update to one of the latest 2 listed below if you don't already
-have one of them in your MMQ
+have one of them in your MMQ.
 
 The current latest different firmware are:
 
@@ -74,27 +74,27 @@ The current latest different firmware are:
   http://btcfpga.com/files/firmware/modminer091012.bin
 
 The code is currently tested on the modminer091012.bin firmware.
-This comment will be updated when others have been tested
+This comment will be updated when others have been tested.
 
 -
 
 On many Linux distributions there is an app called modem-manager that may cause
-problems when it is enabled, due to opening the MMQ device and writing to it
+problems when it is enabled, due to opening the MMQ device and writing to it.
 
 The problem will typically present itself by the flashing led on the backplane
 going out (no longer flashing) and it takes a power cycle to re-enable the MMQ
-firmware - which then can lead to the problem happening again
+firmware - which then can lead to the problem reoccurring.
 
 You can either disable/uninstall modem-manager if you don't need it or:
 a (hack) solution to this is to blacklist the MMQ USB device in
 /lib/udev/rules.d/77-mm-usb-device-blacklist.rules
 
-Adding 2 lines like this (just above APC) should help
+Adding 2 lines like this (just above APC) should help.
 # MMQ
 ATTRS{idVendor}=="1fc9", ATTRS{idProduct}=="0003", ENV{ID_MM_DEVICE_IGNORE}="1"
 
 The change will be lost and need to be re-done, next time you update the
-modem-manager software
+modem-manager software.
 
 
 BitForce (BFL)
@@ -121,7 +121,7 @@ To flash your BFL, specify the BFL port and the flash file e.g.:
  sudo ./bitforce-firmware-flash /dev/ttyUSB0 alphaminer_832.bfl
 It takes a bit under 3 minutes to flash a BFL and shows a progress % counter
 Once it completes, you may also need to wait about 15 seconds, then power the
-BFL off and on again
+BFL off and on again.
 
 If you get an error at the end of the BFL flash process stating:
  "Error reading response from ZBX"
@@ -153,12 +153,12 @@ There are two hidden options in BFGMiner when Icarus support is compiled in:
                                (enabled by default)
 
 If you define fewer comma separated values than Icarus devices, the last values
-will be used for all extra devices
+will be used for all extra devices.
 
 An example would be: --icarus-options 57600:2:1:-r
 This would mean: use 57600 baud, the FPGA board divides the work in half however
 only 1 FPGA actually runs on the board, and don't reopen the device (e.g. like
-an early CM1 Icarus copy bitstream)
+an early CM1 Icarus copy bitstream).
 
 --icarus-timing <arg> Set how the Icarus timing is calculated - one setting/value for all or comma separated
            default[=N]   Use the default Icarus hash time (2.6316ns)
@@ -167,63 +167,62 @@ an early CM1 Icarus copy bitstream)
            value[=N]     Specify the hash time in nanoseconds (e.g. 2.6316) and abort time (e.g. 2.6316=80)
 
 If you define fewer comma separated values than Icarus devices, the last values
-will be used for all extra devices
+will be used for all extra devices.
 
 Icarus timing is required for devices that do not exactly match a default
-Icarus Rev3 in processing speed
+Icarus Rev3 in processing speed.
 If you have an Icarus Rev3 you should not normally need to use --icarus-timing
-since the default values will maximise the Mh/s and display it correctly
+since the default values will maximise the Mh/s and display it correctly.
 
 Icarus timing is used to determine the number of hashes that have been checked
-when it aborts a nonce range (including on a longpoll)
+when it aborts a nonce range (including on a longpoll).
 It is also used to determine the elapsed time when it should abort a nonce
 range to avoid letting the Icarus go idle, but also to safely maximise that
-time
+time.
 
 'short' or 'long' mode should only be used on a computer that has enough CPU
 available to run BFGMiner without any CPU delays (an active desktop or swapping
-computer would not be stable enough)
+computer would not be stable enough).
 Any CPU delays while calculating the hash time will affect the result
 'short' mode only requires the computer to be stable until it has completed
-~315 difficulty 1 shares
-'long' mode requires it to always be stable to ensure accuracy, however, over
-time it continually corrects itself
+~315 difficulty 1 shares, 'long' mode requires it to always be stable to ensure
+accuracy, however, over time it continually corrects itself.
 The optional additional =N for 'short' or 'long' specifies the limit to set the
 timeout to in deciseconds; thus if the timing code calculation is higher while
-running, it will instead use the limit
+running, it will instead use the limit.
 This can be set to the appropriate value to ensure the device never goes idle
-even if the calculation is negatively affected by system performance
+even if the calculation is negatively affected by system performance.
 
 When in 'short' or 'long' mode, it will report the hash time value each time it
-is re-calculated
+is re-calculated.
 In 'short' or 'long' mode, the scan abort time starts at 5 seconds and uses the
 default 2.6316ns scan hash time, for the first 5 nonces or one minute
-(whichever is longer)
+(whichever is longer).
 
 In 'default' or 'value' mode the 'constants' are calculated once at the start,
-based on the default value or the value specified
+based on the default value or the value specified.
 The optional additional =N specifies to set the default abort at N 1/10ths of a
 second, not the calculated value, which is 112 for 2.6316ns
 
 To determine the hash time value for a non Icarus Rev3 device or an Icarus Rev3
 with a different bitstream to the default one, use 'long' mode and give it at
 least a few hundred shares, or use 'short' mode and take note of the final hash
-time value (Hs) calculated
+time value (Hs) calculated.
 You can also use the RPC API 'stats' command to see the current hash time (Hs)
-at any time
+at any time.
 
 The Icarus code currently only works with an FPGA device that supports the same
 commands as Icarus Rev3 requires and also is less than ~840Mh/s and greater
-than 2Mh/s
+than 2Mh/s.
 If an FPGA device does hash faster than ~840Mh/s it should work correctly if
-you supply the correct hash time nanoseconds value
+you supply the correct hash time nanoseconds value.
 
 The timing code itself will affect the Icarus performance since it increases
-the delay after work is completed or aborted until it starts again
+the delay after work is completed or aborted until it starts again.
 The increase is, however, extremely small and the actual increase is reported
-with the RPC API 'stats' command (a very slow CPU will make it more noticeable)
-Using the 'short' mode will remove this delay after 'short' mode completes
-The delay doesn't affect the calculation of the correct hash time
+with the RPC API 'stats' command (a very slow CPU will make it more noticeable).
+Using the 'short' mode will remove this delay after 'short' mode completes.
+The delay doesn't affect the calculation of the correct hash time.
 
 
 X6500
@@ -258,6 +257,7 @@ least the "dummy" mining bitstreams installed on them.
 
 If your boards do not have a mining bitstream yet, you must first, install
 ZTEX's BTCMiner (requires Java JDK version 6 or later) and install one.
+
 === WINDOWS NOTE ===
 Upon first powering up and connecting the board via USB, windows will attempt
 and fail to find the appropriate drivers.  To load the initial firmware on the
@@ -266,6 +266,7 @@ board, you'll need the EZ-USB FX2 SDK from here:
 Extract the firmware kit and use the driver within libusb-win32/ztex.inf.
 Windows should now recognize the board and you're ready to program it.
 === END OF WINDOWS ===
+
 Grab the latest miner jar from http://www.ztex.de/btcminer/#download and program
 the appropriate dummy firmware for your board.  The command should look
 something like (for a single FPGA board):

+ 20 - 18
README.GPU

@@ -50,7 +50,8 @@ SETUP FOR GPU SUPPORT:
 
 To setup GPU mining support:
 
-Install AMD APP sdk, ideal version (see FAQ!) - put it into a system location.
+Install the AMD APP sdk, ideal version (see FAQ!) - put it into a system
+location.
 Download the correct version for either 32 bit or 64 bit from here:
 	http://developer.amd.com/tools/heterogeneous-computing/amd-accelerated-parallel-processing-app-sdk/downloads/
 
@@ -170,8 +171,8 @@ while not reaching overheat temperatures. As a lower clock speed limit, the
 auto-gpu mode checks the GPU card's "normal" clock speed and will not go below
 this unless you have manually set a lower speed in the range. Also, unless a
 higher clock speed was specified at startup, it will not raise the clockspeed.
-If the temperature climbs, fanspeed is adjusted and optimised before GPU engin
-e clockspeed is adjusted. If fan speed control is not available or already
+If the temperature climbs, fanspeed is adjusted and optimised before GPU engine
+clockspeed is adjusted. If fan speed control is not available or already
 optimal, then GPU clock speed is only decreased if it goes over the target
 temperature by the hysteresis amount, which is set to 3 by default and can be
 changed with:
@@ -313,10 +314,10 @@ A: Yes, pass a list separated by commas such as -I d,4,9,9
 
 Q: The CPU usage is high.
 A: The ATI drivers after 11.6 have a bug that makes them consume 100% of one
-CPU core unnecessarily so downgrade to 11.6. Binding BFGMiner to one CPU core on
-windows can minimise it to 100% (instead of more than one core). Driver version
-11.11 on linux and 11.12 on windows appear to have fixed this issue. Note that
-later drivers may have an apparent return of high CPU usage. Try
+CPU core unnecessarily, so downgrade to 11.6. Binding BFGMiner to one CPU core
+on windows can minimise it to 100% (instead of more than one core). Driver
+version 11.11 on linux and 11.12 on windows appear to have fixed this issue.
+Note that later drivers may have an apparent return of high CPU usage. Try
 'export GPU_USE_SYNC_OBJECTS=1' on Linux before starting BFGMiner. You can also
 set this variable in windows via a batch file or on the command line before
 starting BFGMiner with 'setx GPU_USE_SYNC_OBJECTS 1'
@@ -340,7 +341,7 @@ The starting fan speed is set to 50% in auto-fan mode as a safety precaution.
 
 Q: I upgraded BFGMiner version and my hashrate suddenly dropped!
 A: No, you upgraded your SDK version unwittingly between upgrades of BFGMiner
-and that caused your hashrate to drop. See the next question.
+and that caused your hashrate to drop. Please see the next question.
 
 Q: I upgraded my ATI driver/SDK/BFGMiner and my hashrate suddenly dropped!
 A: The hashrate performance in BFGMiner is tied to the version of the ATI SDK
@@ -380,7 +381,8 @@ uninstalling files so you may have to use third party tools like driversweeper
 to remove old versions. The other common reason for this is windows antivirus
 software is disabling one of the DLLs from working. If BFGMiner starts with the
 -T option but never starts without it, this is a sure fire sign you have this
-problem and will have to disable your antivirus or make exceptions.
+problem and will have to disable your antivirus or set up some exceptions in it
+if possible.
 
 Q: Is it faster to mine on Windows or Linux?
 A: It makes no difference. It comes down to choice of operating system for their
@@ -410,8 +412,8 @@ A: If you can install both drivers successfully (easier on windows) then yes,
 using the --gpu-platform option.
 
 Q: Can I mine with Nvidia or Intel GPUs?
-A: Yes, but their hashrate is very poor and likely you'll be using much more
-energy than you'll be earning in coins.
+A: Yes, but the hashrate on these is very poor and it is likely you'll be using
+much more energy than you'll be earning in coins.
 
 Q: Can I mine on both Nvidia and AMD GPUs at the same time?
 A: No, you must run one instance of BFGMiner with the --gpu-platform option for
@@ -422,11 +424,11 @@ A: With Nvidia you can, but with AMD you cannot.
 
 Q: I'm trying to mine a scrypt cryptocurrency but BFGMiner shows MH values
 instead of kH and submits no shares?
-A: Add the --scrypt parameter.
+A: Add the --scrypt parameter to your BFGMiner startup command.
 
 Q: I can't get anywhere near enough hashrate for scrypt compared to other
 people?
-A: You may not have enough system RAM as this is also required.
+A: You may not have enough system RAM, as this is also required.
 
 Q: My scrypt hashrate is high but the pool reports only a tiny proportion of my
 hashrate?
@@ -464,20 +466,20 @@ further but BFGMiner does not have access to these means.
 Q: I have multiple GPUs and although many devices show up, it appears to be
 working only on one GPU splitting it up.
 A: Your driver setup is failing to properly use the accessory GPUs. Your driver
-may be configured wrong or you have a driver version that needs a dummy plug on
-all the GPUs that aren't connected to a monitor.
+may be misconfigured or you have a driver version that needs a dummy plug on all
+the GPUs that aren't connected to a monitor.
 
 Q: I have some random GPU performance related problem not addressed above.
 A: Seriously, it's the driver and/or SDK. Uninstall them and start again,
-noting there is no clean way to uninstall them so you have to use extra tools
-or do it manually.
+also noting there is no clean way to uninstall them so you will likely have to
+use extra tools or do it manually.
 
 Q: Do I need to recompile after updating my driver/SDK?
 A: No. The software is unchanged regardless of which driver/SDK/ADL version you
 are running.
 
 Q: I do not want BFGMiner to modify my engine/clock/fanspeed?
-A: BFGMiner only modifies values if you tell it to via some parameters.
+A: BFGMiner only modifies values if you tell it to via the parameters.
 Otherwise it will just monitor the values.
 
 Q: Should I use crossfire/SLI?

+ 3 - 2
README.OpenWrt

@@ -1,11 +1,12 @@
 Open up /etc/opkg.conf (on your router) in your favourite editor. You will see
-a line that looks similar to this at the top:
+a line that looks similar to this at the top (depending on your device):
 	src/gz attitude_adjustment http://downloads.openwrt.org/attitude_adjustment/12.09/ar71xx/generic/packages
 Note the platform following the OpenWrt version. In this example, it is ar71xx.
 
 Now add a new line immediately below it, similar to this:
-	src/gz bfgminer http://luke.dashjr.org/programs/bitcoin/files/bfgminer/testing/openwrt/12.09/ar71xx
+	src/gz bfgminer http://luke.dashjr.org/programs/bitcoin/files/bfgminer/latest/openwrt/12.09/ar71xx
 Be sure you put the same platform at the end as your OpenWrt repository!
+Also note that you can change "latest" to "stable" or "testing" to get better-tested versions.
 
 Next, save the file and exit your editor. Tell opkg to reload its package lists
 by running the command:

File diff suppressed because it is too large
+ 211 - 199
README.RPC


+ 4 - 4
README.scrypt

@@ -1,5 +1,5 @@
 If you wish to donate to the author of scrypt support, Con Kolivas, for his past
-work (he no longer maintains this), please send your donations to
+work (he no longer maintains this), please send your donations to:
 15qSxP1SQcUX3o4nhkfdbgyoWEFMomJ4rZ
 
 ---
@@ -62,7 +62,7 @@ below to determine how many shaders your GPU has, and note that there are some
 variants of these cards, and Nvidia shaders are much much lower and virtually
 pointless trying to mine on. If this is not set, BFGMiner will query the
 device for how much memory it supports and will try to set a value based on
-that.
+that instead.
 SUMMARY: This will get you started but fine tuning for optimal performance is
 required.
 
@@ -179,7 +179,7 @@ Delete any .bin files so you're starting from scratch and see what bins get
 generated.
 
 First try without any thread concurrency or even shaders, as BFGMiner will try to
-find an optimal value
+find an optimal value:
 bfgminer -I 13
 
 If that starts mining, see what bin was generated, it is likely the largest
@@ -187,7 +187,7 @@ meaningful TC you can set.
 Starting it on mine I get:
 scrypt130302Tahitiglg2tc22392w64l8.bin
 
-See tc22392 that's telling you what thread concurrency it was. It should start
+Note that tc22392 tells you what thread concurrency it was. It should start
 without TC parameters, but you never know. So if it doesn't, start with
 --thread-concurrency 8192 and add 2048 to it at a time till you find the highest
 value it will start successfully at.

+ 2 - 0
adl.c

@@ -922,6 +922,8 @@ static float curses_float(const char *query)
 	char *cvar;
 
 	cvar = curses_input(query);
+	if (unlikely(!cvar))
+		return -1;
 	ret = atof(cvar);
 	free(cvar);
 	return ret;

+ 13 - 1
api.c

@@ -60,7 +60,7 @@ static const char SEPARATOR = '|';
 #define SEPSTR "|"
 static const char GPUSEP = ',';
 
-static const char *APIVERSION = "2.2";
+static const char *APIVERSION = "2.3";
 static const char *DEAD = "Dead";
 static const char *SICK = "Sick";
 static const char *NOSTART = "NoStart";
@@ -1471,13 +1471,24 @@ static void devdetail_an(struct io_data *io_data, struct cgpu_info *cgpu, bool i
 
 	root = api_add_int(root, "DEVDETAILS", &n, true);
 	root = api_add_device_identifier(root, cgpu);
+	if (!per_proc)
+		root = api_add_int(root, "Processors", &cgpu->procs, false);
 	root = api_add_string(root, "Driver", cgpu->drv->dname, false);
 	if (cgpu->kname)
 		root = api_add_string(root, "Kernel", cgpu->kname, false);
 	if (cgpu->name)
 		root = api_add_string(root, "Model", cgpu->name, false);
+	if (cgpu->dev_manufacturer)
+		root = api_add_string(root, "Manufacturer", cgpu->dev_manufacturer, false);
+	if (cgpu->dev_product)
+		root = api_add_string(root, "Product", cgpu->dev_product, false);
+	if (cgpu->dev_serial)
+		root = api_add_string(root, "Serial", cgpu->dev_serial, false);
 	if (cgpu->device_path)
 		root = api_add_string(root, "Device Path", cgpu->device_path, false);
+	
+	root = api_add_int(root, "Target Temperature", &cgpu->targettemp, false);
+	root = api_add_int(root, "Cutoff Temperature", &cgpu->cutofftemp, false);
 
 	if (cgpu->drv->get_api_extra_device_detail)
 		root = api_add_extra(root, cgpu->drv->get_api_extra_device_detail(cgpu));
@@ -3547,6 +3558,7 @@ static void tidyup(__maybe_unused void *arg)
 		shutdown(*apisock, SHUT_RDWR);
 		CLOSESOCKET(*apisock);
 		*apisock = INVSOCK;
+		free(apisock);
 	}
 
 	if (ipaccess != NULL) {

+ 211 - 0
binloader.c

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

+ 14 - 0
binloader.h

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

+ 52 - 23
configure.ac

@@ -109,10 +109,14 @@ driverlist=
 algolist=SHA256d
 optlist=
 
+has_fpga=no
+has_asic=no
+need_binloader=no
 need_dynclock=no
-need_fpgautils=no
+need_lowl_vcom=no
 need_lowlevel=no
 need_lowl_hid=no
+need_lowl_usb=no
 have_cygwin=false
 have_win32=false
 have_macho=false
@@ -353,7 +357,9 @@ AC_ARG_ENABLE([bitforce],
 	)
 if test "x$bitforce" = xyes; then
 	AC_DEFINE([USE_BITFORCE], [1], [Defined to 1 if BitForce support is wanted])
-	need_fpgautils=yes
+	need_lowl_vcom=yes
+	has_fpga=yes
+	has_asic=yes
 fi
 AM_CONDITIONAL([HAS_BITFORCE], [test x$bitforce = xyes])
 
@@ -366,7 +372,9 @@ AC_ARG_ENABLE([icarus],
 if test "x$icarus" = xyes; then
 	AC_DEFINE([USE_ICARUS], [1], [Defined to 1 if Icarus support is wanted])
 	need_dynclock=yes
-	need_fpgautils=yes
+	need_lowl_vcom=yes
+	has_fpga=yes
+	has_asic=yes
 fi
 AM_CONDITIONAL([HAS_ICARUS], [test x$icarus = xyes])
 
@@ -380,7 +388,8 @@ AC_ARG_ENABLE([avalon],
 	)
 if test "x$avalon" = xyes; then
 	AC_DEFINE([USE_AVALON], [1], [Defined to 1 if Avalon support is wanted])
-	need_fpgautils=yes
+	need_lowl_vcom=yes
+	has_asic=yes
 fi
 AM_CONDITIONAL([HAS_AVALON], [test x$avalon = xyes])
 
@@ -476,7 +485,9 @@ AC_ARG_ENABLE([modminer],
 if test "x$modminer" = xyes; then
 	AC_DEFINE([USE_MODMINER], [1], [Defined to 1 if ModMiner support is wanted])
 	need_dynclock=yes
-	need_fpgautils=yes
+	need_lowl_vcom=yes
+	need_binloader=yes
+	has_fpga=yes
 fi
 AM_CONDITIONAL([HAS_MODMINER], [test x$modminer = xyes])
 
@@ -513,7 +524,7 @@ PKG_CHECK_MODULES([LIBUSB], [libusb-1.0],[
 
 driverlist="$driverlist klondike"
 AC_ARG_ENABLE([klondike],
-	[AC_HELP_STRING([--enable-klondike],[Compile support for Klondike (default disabled)])],
+	[AC_HELP_STRING([--disable-klondike],[Compile support for Klondike (default enabled)])],
 	[klondike=$enableval],
 	[klondike=auto]
 	)
@@ -528,7 +539,8 @@ elif test "x$klondike" = xauto; then
 fi
 if test "x$klondike" = xyes; then
 	AC_DEFINE([USE_KLONDIKE], [1], [Defined to 1 if Klondike support is wanted])
-	need_lowlevel=yes
+	need_lowl_usb=yes
+	has_asic=yes
 fi
 AM_CONDITIONAL([HAS_KLONDIKE], [test x$klondike = xyes])
 
@@ -551,8 +563,9 @@ fi
 if test "x$x6500" = xyes; then
 	AC_DEFINE([USE_X6500], [1], [Defined to 1 if X6500 support is wanted])
 	need_dynclock=yes
-	need_fpgautils=yes
-	need_lowlevel=yes
+	need_lowl_usb=yes
+	need_binloader=yes
+	has_fpga=yes
 fi
 AM_CONDITIONAL([HAS_X6500], [test x$x6500 = xyes])
 
@@ -574,7 +587,9 @@ fi
 if test "x$ztex" = xyes; then
 	AC_DEFINE([USE_ZTEX], [1], [Defined to 1 if ZTEX support is wanted])
 	need_dynclock=yes
-	need_fpgautils=yes
+	need_lowl_usb=yes
+	need_binloader=yes
+	has_fpga=yes
 fi
 AM_CONDITIONAL([HAS_ZTEX], [test x$ztex = xyes])
 
@@ -636,7 +651,8 @@ else
 fi
 if test "x$bigpic" = "xyes"; then
 	AC_DEFINE([USE_BIGPIC], [1], [Defined to 1 if Big Picture Mining USB support is wanted])
-	need_fpgautils=yes
+	need_lowl_vcom=yes
+	has_asic=yes
 fi
 AM_CONDITIONAL([HAS_BIGPIC], [test x$bigpic = xyes])
 
@@ -658,7 +674,8 @@ else
 fi
 if test "x$littlefury" = "xyes"; then
 	AC_DEFINE([USE_LITTLEFURY], [1], [Defined to 1 if LittleFury support is wanted])
-	need_fpgautils=yes
+	need_lowl_vcom=yes
+	has_asic=yes
 fi
 AM_CONDITIONAL([HAS_LITTLEFURY], [test x$littlefury = xyes])
 
@@ -700,9 +717,8 @@ else
 fi
 if test "x$nanofury" = "xyes"; then
 	AC_DEFINE([USE_NANOFURY], [1], [Defined to 1 if NanoFury support is wanted])
-	need_fpgautils=yes
-	need_lowlevel=yes
 	need_lowl_hid=yes
+	has_asic=yes
 fi
 AM_CONDITIONAL([HAS_NANOFURY], [test x$nanofury = xyes])
 
@@ -733,9 +749,8 @@ else
 fi
 if test "x$hashbuster" = "xyes"; then
 	AC_DEFINE([USE_HASHBUSTER], [1], [Defined to 1 if HashBuster support is wanted])
-	need_fpgautils=yes
-	need_lowlevel=yes
 	need_lowl_hid=yes
+	has_asic=yes
 fi
 AM_CONDITIONAL([USE_HASHBUSTER], [test x$hashbuster = xyes])
 
@@ -755,7 +770,12 @@ fi
 AM_CONDITIONAL([HAS_METABANK], [test x$metabank = xyes])
 
 
-if test "x$klondike$x6500$ztex" = "xnonono"; then
+if test "x$need_lowl_vcom" != "xno"; then
+	# Lowlevel VCOM doesn't need libusb, but it can take advantage of it to reattach drivers
+	need_lowl_usb=yes
+fi
+
+if test "x$need_lowl_usb" = "xno"; then
 	libusb=no
 	LIBUSB_LIBS=''
 	LIBUSB_CFLAGS=''
@@ -781,8 +801,8 @@ if test "x$scrypt" = xyes; then
 fi
 
 
-if test x$need_fpgautils = xyes; then
-	AC_DEFINE([HAVE_FPGAUTILS], [1], [Defined to 1 if fpgautils is being used])
+if test x$need_lowl_vcom = xyes; then
+	AC_DEFINE([NEED_BFG_LOWL_VCOM], [1], [Defined to 1 if lowlevel VCOM drivers are being used])
 	need_lowlevel=yes
 	
 	if $have_win32; then
@@ -832,6 +852,14 @@ if test x$need_lowl_hid = xyes; then
 	need_lowlevel=yes
 fi
 
+if test x$need_lowl_usb = xyes; then
+	need_lowlevel=yes
+fi
+
+if test x$need_fpgautils = xyes; then
+	need_lowlevel=yes
+fi
+
 if test x$need_lowlevel = xyes; then
 	AC_DEFINE([HAVE_BFG_LOWLEVEL], [1], [Defined to 1 if lowlevel drivers are being used])
 fi
@@ -987,8 +1015,9 @@ AC_SUBST(libblkmaker_LIBS)
 
 
 AM_CONDITIONAL([NEED_LIBBLKMAKER], [test x$with_system_libblkmaker != xyes])
+AM_CONDITIONAL([NEED_BFG_BINLOADER], [test x$need_binloader = xyes])
 AM_CONDITIONAL([NEED_DYNCLOCK], [test x$need_dynclock = xyes])
-AM_CONDITIONAL([NEED_FPGAUTILS], [test x$need_fpgautils = xyes])
+AM_CONDITIONAL([NEED_BFG_LOWL_VCOM], [test x$need_lowl_vcom = xyes])
 AM_CONDITIONAL([NEED_BFG_LOWL_HID], [test x$need_lowl_hid = xyes])
 AM_CONDITIONAL([NEED_BFG_LOWLEVEL], [test x$need_lowlevel = xyes])
 AM_CONDITIONAL([HAS_SCRYPT], [test x$scrypt = xyes])
@@ -999,8 +1028,8 @@ AM_CONDITIONAL([HAVE_LIBUSB], [test x$libusb = xyes])
 AM_CONDITIONAL([HAVE_WINDOWS], [test x$have_win32 = xtrue])
 AM_CONDITIONAL([HAVE_x86_64], [test x$have_x86_64 = xtrue])
 AM_CONDITIONAL([HAVE_WIN_DDKUSB], [test x$found_ddkusb = xtrue])
-AM_CONDITIONAL([HAS_FPGA], [test x$bitforce$icarus$modminer$x6500$ztex != xnonononono])
-AM_CONDITIONAL([HAS_ASIC], [test x$avalon$bfsb$bigpic$icarus$httpsrv$metabank != xnononononono])
+AM_CONDITIONAL([HAS_FPGA], [test x$has_fpga != xno])
+AM_CONDITIONAL([HAS_ASIC], [test x$has_asic != xno])
 
 dnl Find YASM
 has_yasm=false
@@ -1096,7 +1125,7 @@ if test "x$cpumining$have_x86_32" = "xyestrue"; then
 fi
 AM_CONDITIONAL([HAVE_SSE2], [test "x$have_sse2" = "xyes"])
 
-if test "x$need_fpgautils" = "xyes"; then
+if test "x$need_lowl_vcom" = "xyes"; then
 	AC_ARG_WITH([libudev], [AC_HELP_STRING([--without-libudev], [Autodetect FPGAs using libudev (default enabled)])],
 		[libudev=$withval],
 		[libudev=auto]

+ 6 - 0
debian/changelog

@@ -1,3 +1,9 @@
+bfgminer (3.6.0-1precise1) precise; urgency=medium
+
+  * Explicitly added OpenCL to Debian build rules.
+
+ -- graeme <graeme@sudo.ca>  Thu, 21 Nov 2013 10:19:10 -0800
+
 bfgminer (3.6.0-0precise1) precise; urgency=low
 
   * klondike: New driver, just imported from cgminer mostly as-is for now.

+ 1 - 1
debian/rules

@@ -5,7 +5,7 @@
 
 override_dh_auto_configure:
 	NOSUBMODULES=1 ./autogen.sh
-	dh_auto_configure -- --enable-ztex --enable-bitforce --enable-icarus --enable-cpumining --enable-scrypt
+	dh_auto_configure -- --enable-ztex --enable-bitforce --enable-icarus --enable-cpumining --enable-scrypt --enable-opencl
 
 override_dh_auto_install:
 	$(MAKE) DESTDIR=$(CURDIR)/debian/bfgminer install

+ 8 - 6
deviceapi.c

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

+ 2 - 1
driver-avalon.c

@@ -37,10 +37,10 @@
 
 #include "deviceapi.h"
 #include "miner.h"
-#include "fpgautils.h"
 #include "driver-avalon.h"
 #include "logging.h"
 #include "lowlevel.h"
+#include "lowl-vcom.h"
 #include "util.h"
 
 BFG_REGISTER_DRIVER(avalon_drv)
@@ -1017,6 +1017,7 @@ static void avalon_shutdown(struct thr_info *thr)
 struct device_drv avalon_drv = {
 	.dname = "avalon",
 	.name = "AVA",
+	.lowl_probe_by_name_only = true,
 	.lowl_probe = avalon_lowl_probe,
 	.thread_prepare = avalon_prepare,
 	.minerloop = hash_queued_work,

+ 1 - 1
driver-bigpic.c

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

+ 4 - 1
driver-bitforce.c

@@ -23,8 +23,8 @@
 #include "compat.h"
 #include "deviceapi.h"
 #include "miner.h"
-#include "fpgautils.h"
 #include "lowlevel.h"
+#include "lowl-vcom.h"
 #include "util.h"
 
 #define BITFORCE_SLEEP_MS 500
@@ -2106,6 +2106,9 @@ static void bitforce_queue_thread_enable(struct thr_info *thr)
 struct device_drv bitforce_queue_api = {
 	.dname = "bitforce_queue",
 	.name = "BFL",
+	.lowl_probe_by_name_only = true,
+	.lowl_match = bitforce_lowl_match,
+	.lowl_probe = bitforce_lowl_probe,
 	.minerloop = minerloop_queue,
 	.reinit_device = bitforce_reinit,
 #ifdef HAVE_CURSES

+ 2 - 1
driver-bitfury.c

@@ -285,7 +285,7 @@ void bitfury_noop_job_start(struct thr_info __maybe_unused * const thr)
 void bitfury_init_freq_stat(struct freq_stat * const c, const int osc6_min, const int osc6_max)
 {
 	const int osc6_values = (osc6_max + 1 - osc6_min);
-	void * const p = malloc(osc6_values * (sizeof(*c->mh) + sizeof(*c->s)));
+	void * const p = calloc(osc6_values, (sizeof(*c->mh) + sizeof(*c->s)));
 	c->mh = p - (sizeof(*c->mh) * osc6_min);
 	c->s = p + (sizeof(*c->mh) * osc6_values) - (sizeof(*c->s) * osc6_min);
 	c->osc6_min = osc6_min;
@@ -532,6 +532,7 @@ void bitfury_do_io(struct thr_info * const master_thr)
 				if (opt_debug && !c->best_done)
 				{
 					char logbuf[0x100];
+					logbuf[0] = '\0';
 					for (i = c->osc6_min; i <= c->osc6_max; ++i)
 						tailsprintf(logbuf, sizeof(logbuf), " %d=%.3f/%3.0fs",
 						            i, c->mh[i] / c->s[i], c->s[i]);

+ 1 - 1
driver-cairnsmore.c

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

+ 1 - 1
driver-erupter.c

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

+ 0 - 1
driver-hashbuster.c

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

+ 1 - 1
driver-icarus.c

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

+ 21 - 19
driver-klondike.c

@@ -1211,26 +1211,28 @@ static void klondike_flush_work(struct cgpu_info *klncgpu)
 	KLINE kline;
 	int slaves, dev;
 
-	wr_lock(&(klninfo->stat_lock));
-	klninfo->block_seq++;
-	slaves = klninfo->status[0].kline.ws.slavecount;
-	wr_unlock(&(klninfo->stat_lock));
+	if (klninfo->initialised) {
+		wr_lock(&(klninfo->stat_lock));
+		klninfo->block_seq++;
+		slaves = klninfo->status[0].kline.ws.slavecount;
+		wr_unlock(&(klninfo->stat_lock));
 
-	applog(LOG_DEBUG, "%s%i: flushing work",
-			  klncgpu->drv->name, klncgpu->device_id);
-	zero_kline(&kline);
-	kline.hd.cmd = KLN_CMD_ABORT;
-	for (dev = 0; dev <= slaves; dev++) {
-		kline.hd.dev = dev;
-		kitem = SendCmdGetReply(klncgpu, &kline, KSENDHD(0));
-		if (kitem != NULL) {
-			wr_lock(&(klninfo->stat_lock));
-			memcpy((void *)&(klninfo->status[dev]),
-				kitem,
-				sizeof(klninfo->status[dev]));
-			klninfo->jobque[dev].flushed = true;
-			wr_unlock(&(klninfo->stat_lock));
-			kitem = release_kitem(klncgpu, kitem);
+		applog(LOG_DEBUG, "%s%i: flushing work",
+				  klncgpu->drv->name, klncgpu->device_id);
+		zero_kline(&kline);
+		kline.hd.cmd = KLN_CMD_ABORT;
+		for (dev = 0; dev <= slaves; dev++) {
+			kline.hd.dev = dev;
+			kitem = SendCmdGetReply(klncgpu, &kline, KSENDHD(0));
+			if (kitem != NULL) {
+				wr_lock(&(klninfo->stat_lock));
+				memcpy((void *)&(klninfo->status[dev]),
+					kitem,
+					sizeof(klninfo->status[dev]));
+				klninfo->jobque[dev].flushed = true;
+				wr_unlock(&(klninfo->stat_lock));
+				kitem = release_kitem(klncgpu, kitem);
+			}
 		}
 	}
 }

+ 1 - 1
driver-littlefury.c

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

+ 2 - 1
driver-modminer.c

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

+ 0 - 1
driver-nanofury.c

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

+ 1 - 1
driver-opencl.c

@@ -818,7 +818,7 @@ void pause_dynamic_threads(int gpu)
 	for (i = 1; i < cgpu->threads; i++) {
 		struct thr_info *thr;
 
-		thr = get_thread(i);
+		thr = cgpu->thr[i];
 		if (!thr->pause && cgpu->dynamic) {
 			applog(LOG_WARNING, "Disabling extra threads due to dynamic mode.");
 			applog(LOG_WARNING, "Tune dynamic intensity with --gpu-dyninterval");

+ 2 - 1
driver-x6500.c

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

+ 1 - 1
driver-ztex.c

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

+ 0 - 1
ft232r.c

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

+ 2 - 1
libztex.c

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

+ 0 - 1
lowl-hid.c

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

+ 35 - 1
lowl-usb.c

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

+ 12 - 0
lowl-usb.h

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

+ 15 - 327
fpgautils.c → lowl-vcom.c

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

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

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

+ 66 - 1
lowlevel.c

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

+ 6 - 1
lowlevel.h

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

+ 11 - 1
mcp2210.c

@@ -77,10 +77,20 @@ struct mcp2210_device {
 static
 bool mcp2210_io(hid_device * const hid, uint8_t * const cmd, uint8_t * const buf)
 {
-	return likely(
+	char hexcmd[(0x41 * 2) + 1];
+	if (opt_dev_protocol)
+		bin2hex(hexcmd, cmd, 0x41);
+	const bool rv = likely(
 		0x41 == hid_write(hid, cmd, 0x41) &&
 		64 == hid_read(hid, buf, 64)
 	);
+	if (opt_dev_protocol)
+	{
+		char hexbuf[(0x40 * 2) + 1];
+		bin2hex(hexbuf, buf, 0x40);
+		applog(LOG_DEBUG, "mcp2210_io(%p, %s, %s)", hid, hexcmd, hexbuf);
+	}
+	return rv;
 }
 
 static

+ 80 - 21
miner.c

@@ -68,7 +68,6 @@
 #include "logging.h"
 #include "miner.h"
 #include "findnonce.h"
-#include "fpgautils.h"
 #include "adl.h"
 #include "driver-cpu.h"
 #include "driver-opencl.h"
@@ -500,6 +499,34 @@ static void applog_and_exit(const char *fmt, ...)
 	exit(1);
 }
 
+char *devpath_to_devid(const char *devpath)
+{
+#ifndef WIN32
+	char *devs = malloc(6 + (sizeof(dev_t) * 2) + 1);
+	{
+		struct stat my_stat;
+		if (stat(devpath, &my_stat))
+			return NULL;
+		memcpy(devs, "dev_t:", 6);
+		bin2hex(&devs[6], &my_stat.st_rdev, sizeof(dev_t));
+	}
+#else
+	if (!strncmp(devpath, "\\\\.\\", 4))
+		devpath += 4;
+	if (strncasecmp(devpath, "COM", 3) || !devpath[3])
+		return NULL;
+	devpath += 3;
+	char *p;
+	const int com = strtol(devpath, &p, 10);
+	if (p[0])
+		return NULL;
+	const int sz = (p - devpath);
+	char *devs = malloc(4 + sz + 1);
+	sprintf(devs, "com:%s", devpath);
+#endif
+	return devs;
+}
+
 static
 bool devpaths_match(const char * const ap, const char * const bp)
 {
@@ -998,9 +1025,9 @@ char *set_request_diff(const char *arg, float *p)
 	return NULL;
 }
 
+#ifdef NEED_BFG_LOWL_VCOM
 extern struct lowlevel_device_info *_vcom_devinfo_findorcreate(struct lowlevel_device_info **, const char *);
 
-#ifdef HAVE_FPGAUTILS
 #ifdef WIN32
 void _vcom_devinfo_scan_querydosdevice(struct lowlevel_device_info ** const devinfo_list)
 {
@@ -1916,7 +1943,7 @@ static struct opt_table opt_config_table[] = {
 #endif // defined(unix)
 	OPT_WITHOUT_ARG("--net-delay",
 			opt_set_bool, &opt_delaynet,
-			"Impose small delays in networking to not overload slow routers"),
+			"Impose small delays in networking to avoid overloading slow routers"),
 	OPT_WITHOUT_ARG("--no-adl",
 			opt_set_bool, &opt_noadl,
 #ifdef HAVE_ADL
@@ -1976,6 +2003,9 @@ static struct opt_table opt_config_table[] = {
 	OPT_WITHOUT_ARG("--per-device-stats",
 			opt_set_bool, &want_per_device_stats,
 			"Force verbose mode and output per-device statistics"),
+	OPT_WITH_ARG("--userpass|-O",  // duplicate to ensure config loads it before pool-priority
+	             set_userpass, NULL, NULL,
+	             opt_hidden),
 	OPT_WITH_ARG("--pool-priority",
 			 set_pool_priority, NULL, NULL,
 			 "Priority for just the previous-defined pool"),
@@ -2018,9 +2048,12 @@ static struct opt_table opt_config_table[] = {
 	OPT_WITHOUT_ARG("--round-robin",
 		     set_rr, &pool_strategy,
 		     "Change multipool strategy from failover to round robin on failure"),
-	OPT_WITH_ARG("--scan-serial|-S",
+	OPT_WITH_ARG("--scan|-S",
 		     add_serial, NULL, NULL,
-		     "Serial port to probe for mining devices"),
+		     "Configure how to scan for mining devices"),
+	OPT_WITH_ARG("--scan-device|--scan-serial|--devscan",
+		     add_serial, NULL, NULL,
+		     opt_hidden),
 	OPT_WITH_ARG("--scan-time|-s",
 		     set_int_0_to_9999, opt_show_intval, &opt_scantime,
 		     "Upper bound on time spent scanning current work, in seconds"),
@@ -2535,8 +2568,8 @@ static bool work_decode(struct pool *pool, struct work *work, json_t *val)
 				}
 			} else if (ae >= 3 || opt_coinbase_sig) {
 				const char *cbappend = opt_coinbase_sig;
+				const char full[] = PACKAGE " " VERSION;
 				if (!cbappend) {
-					const char full[] = PACKAGE " " VERSION;
 					if ((size_t)ae >= sizeof(full) - 1)
 						cbappend = full;
 					else if ((size_t)ae >= sizeof(PACKAGE) - 1)
@@ -6010,6 +6043,8 @@ int curses_int(const char *query)
 	char *cvar;
 
 	cvar = curses_input(query);
+	if (unlikely(!cvar))
+		return -1;
 	ret = atoi(cvar);
 	free(cvar);
 	return ret;
@@ -6386,7 +6421,7 @@ void write_config(FILE *fcfg)
 	if (opt_socks_proxy && *opt_socks_proxy)
 		fprintf(fcfg, ",\n\"socks-proxy\" : \"%s\"", json_escape(opt_socks_proxy));
 	
-	_write_config_string_elist(fcfg, "scan-serial", scan_devices);
+	_write_config_string_elist(fcfg, "scan", scan_devices);
 	_write_config_string_elist(fcfg, "device", opt_devices_enabled_list);
 	_write_config_string_elist(fcfg, "set-device", opt_set_device_list);
 	
@@ -6408,7 +6443,7 @@ void write_config(FILE *fcfg)
 		fprintf(fcfg, ",\n\"icarus-timing\" : \"%s\"", json_escape(opt_icarus_timing));
 #ifdef USE_KLONDIKE
 	if (opt_klondike_options)
-		fprintf(fcfg, ",\n\"klondike-options\" : \"%s\"", json_escape(opt_icarus_options));
+		fprintf(fcfg, ",\n\"klondike-options\" : \"%s\"", json_escape(opt_klondike_options));
 #endif
 	fputs("\n}\n", fcfg);
 
@@ -6722,6 +6757,11 @@ retry:
 		goto updated;
         } else if (!strncasecmp(&input, "p", 1)) {
 			char *prilist = curses_input("Enter new pool priority (comma separated list)");
+			if (!prilist)
+			{
+				wlogprint("Not changing priorities\n");
+				goto retry;
+			}
 			int res = prioritize_pools(prilist, &i);
 			free(prilist);
 			switch (res) {
@@ -6946,7 +6986,7 @@ retry:
 		default_save_file(filename);
 		snprintf(prompt, sizeof(prompt), "Config filename to write (Enter for default) [%s]", filename);
 		str = curses_input(prompt);
-		if (strcmp(str, "-1")) {
+		if (str) {
 			struct stat statbuf;
 
 			strcpy(filename, str);
@@ -6958,8 +6998,6 @@ retry:
 					goto retry;
 			}
 		}
-		else
-			free(str);
 		fcfg = fopen(filename, "w");
 		if (!fcfg) {
 			wlogprint("Cannot open or create file\n");
@@ -7134,7 +7172,7 @@ refresh:
 			{
 				static char *pattern = NULL;
 				char *newpattern = curses_input("Enter pattern");
-				if (strcmp(newpattern, "-1"))
+				if (newpattern)
 				{
 					free(pattern);
 					pattern = newpattern;
@@ -9909,7 +9947,10 @@ char *curses_input(const char *query)
 	wlogprint("%s:\n", query);
 	wgetnstr(logwin, input, 255);
 	if (!strlen(input))
-		strcpy(input, "-1");
+	{
+		free(input);
+		input = NULL;
+	}
 	leaveok(logwin, true);
 	noecho();
 	return input;
@@ -9997,7 +10038,7 @@ static bool input_pool(bool live)
 
 	pass = curses_input("Password");
 	if (!pass)
-		goto out;
+		pass = calloc(1, 1);
 
 	pool = add_pool();
 
@@ -10387,6 +10428,7 @@ void _scan_serial(void *p)
 	}
 }
 
+#ifdef HAVE_BFG_LOWLEVEL
 static
 bool _probe_device_match(const struct lowlevel_device_info * const info, const char * const ser)
 {
@@ -10407,16 +10449,22 @@ bool _probe_device_match(const struct lowlevel_device_info * const info, const c
 }
 
 static
-const struct device_drv *_probe_device_find_drv(const char * const dname, const size_t dnamelen)
+const struct device_drv *_probe_device_find_drv(const char * const _dname, const size_t dnamelen)
 {
 	struct driver_registration *dreg;
+	char dname[dnamelen];
+	int i;
 	
+	for (i = 0; i < dnamelen; ++i)
+		dname[i] = tolower(_dname[i]);
 	BFG_FIND_DRV_BY_DNAME(dreg, dname, dnamelen);
 	if (!dreg)
 	{
+		for (i = 0; i < dnamelen; ++i)
+			dname[i] = toupper(_dname[i]);
 		BFG_FIND_DRV_BY_NAME(dreg, dname, dnamelen);
 		if (!dreg)
-			return false;
+			return NULL;
 	}
 	
 	return dreg->drv;
@@ -10426,7 +10474,7 @@ static
 bool _probe_device_internal(struct lowlevel_device_info * const info, const char * const dname, const size_t dnamelen)
 {
 	const struct device_drv * const drv = _probe_device_find_drv(dname, dnamelen);
-	if (!drv->lowl_probe)
+	if (!(drv && drv->lowl_probe))
 		return false;
 	return drv->lowl_probe(info);
 }
@@ -10454,8 +10502,8 @@ void *probe_device_thread(void *p)
 	DL_FOREACH_SAFE(scan_devices, sd_iter, sd_tmp)
 	{
 		const char * const dname = sd_iter->string;
-		const char * const colon = strchr(dname, ':');
-		if (!colon)
+		const char * const colon = strpbrk(dname, ":@");
+		if (!(colon && colon != dname))
 			continue;
 		const char * const ser = &colon[1];
 		LL_FOREACH2(infolist, info, same_devid_next)
@@ -10479,6 +10527,7 @@ void *probe_device_thread(void *p)
 		DL_FOREACH_SAFE(scan_devices, sd_iter, sd_tmp)
 		{
 			const char * const dname = sd_iter->string;
+			// NOTE: Only checking flags here, NOT path/serial, so @ is unacceptable
 			const char *colon = strchr(dname, ':');
 			if (!colon)
 				colon = &dname[-1];
@@ -10508,16 +10557,23 @@ void *probe_device_thread(void *p)
 	DL_FOREACH_SAFE(scan_devices, sd_iter, sd_tmp)
 	{
 		const char * const dname = sd_iter->string;
+		// NOTE: Only checking flags here, NOT path/serial, so @ is unacceptable
 		const char * const colon = strchr(dname, ':');
 		if (!colon)
 		{
 			LL_FOREACH2(infolist, info, same_devid_next)
 			{
-				if ((info->lowl == &lowl_vcom && !strcasecmp(dname, "all")) || _probe_device_match(info, dname))
+				if (
+#ifdef NEED_BFG_LOWL_VCOM
+					(info->lowl == &lowl_vcom && !strcasecmp(dname, "all")) ||
+#endif
+					_probe_device_match(info, (dname[0] == '@') ? &dname[1] : dname))
 				{
 					BFG_FOREACH_DRIVER_BY_PRIORITY(dreg, dreg_tmp)
 					{
 						const struct device_drv * const drv = dreg->drv;
+						if (drv->lowl_probe_by_name_only)
+							continue;
 						if (!drv->lowl_probe)
 							continue;
 						if (drv->lowl_probe(info))
@@ -10545,6 +10601,7 @@ void probe_device(struct lowlevel_device_info * const info)
 {
 	pthread_create(&info->probe_pth, NULL, probe_device_thread, info);
 }
+#endif
 
 int create_new_cgpus(void (*addfunc)(void*), void *arg)
 {
@@ -10972,6 +11029,7 @@ int main(int argc, char *argv[])
 	devices_new = NULL;
 
 	if (opt_display_devs) {
+		int devcount = 0;
 		applog(LOG_ERR, "Devices detected:");
 		for (i = 0; i < total_devices; ++i) {
 			struct cgpu_info *cgpu = devices[i];
@@ -10995,8 +11053,9 @@ int main(int argc, char *argv[])
 				tailsprintf(buf, sizeof(buf), "; path=%s", cgpu->device_path);
 			tailsprintf(buf, sizeof(buf), ")");
 			_applog(LOG_NOTICE, buf);
+			++devcount;
 		}
-		quit(0, "%d devices listed", total_devices);
+		quit(0, "%d devices listed", devcount);
 	}
 
 	mining_threads = 0;

+ 2 - 0
miner.h

@@ -294,6 +294,7 @@ struct device_drv {
 	const char *dname;
 	const char *name;
 	int8_t probe_priority;
+	bool lowl_probe_by_name_only;
 	supported_algos_t supported_algos;
 
 	// DRV-global functions
@@ -1463,6 +1464,7 @@ extern void clean_work(struct work *work);
 extern void free_work(struct work *work);
 extern void __copy_work(struct work *work, const struct work *base_work);
 extern struct work *copy_work(const struct work *base_work);
+extern char *devpath_to_devid(const char *);
 extern struct thr_info *get_thread(int thr_id);
 extern struct cgpu_info *get_devices(int id);
 extern int create_new_cgpus(void (*addfunc)(void*), void *arg);

+ 1 - 1
miner.php

@@ -2941,7 +2941,7 @@ function display()
 
  if ($allowcustompages === true)
  {
-	$pg = trim(getparam('pg', true));
+	$pg = urlencode(trim(getparam('pg', true)));
 	if ($pagesonly === true)
 	{
 		if ($pg !== null && $pg !== '')

+ 6 - 4
util.c

@@ -52,8 +52,8 @@
 
 #include <utlist.h>
 
-#ifdef HAVE_FPGAUTILS
-#include "fpgautils.h"
+#ifdef NEED_BFG_LOWL_VCOM
+#include "lowl-vcom.h"
 #endif
 #include "miner.h"
 #include "compat.h"
@@ -2248,8 +2248,10 @@ static bool setup_stratum_curl(struct pool *pool)
 	
 	curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);
 	if (pool->rpc_proxy) {
+		curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, 1);
 		curl_easy_setopt(curl, CURLOPT_PROXY, pool->rpc_proxy);
 	} else if (opt_socks_proxy) {
+		curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, 1);
 		curl_easy_setopt(curl, CURLOPT_PROXY, opt_socks_proxy);
 		curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
 	}
@@ -2621,7 +2623,7 @@ struct bfgtls_data {
 #ifdef WIN32
 	LPSTR bfg_strerror_socketresult;
 #endif
-#ifdef HAVE_FPGAUTILS
+#ifdef NEED_BFG_LOWL_VCOM
 	struct detectone_meta_info_t __detectone_meta_info;
 #endif
 };
@@ -2651,7 +2653,7 @@ struct bfgtls_data *get_bfgtls()
 	return bfgtls;
 }
 
-#ifdef HAVE_FPGAUTILS
+#ifdef NEED_BFG_LOWL_VCOM
 struct detectone_meta_info_t *_detectone_meta_info()
 {
 	return &get_bfgtls()->__detectone_meta_info;

Some files were not shown because too many files changed in this diff