mirror of
https://github.com/GOSTSec/sgminer
synced 2025-01-23 13:04:29 +00:00
Merge branch 'master' of git://github.com/ckolivas/cgminer.git
This commit is contained in:
commit
b519470f2c
85
API-README
85
API-README
@ -124,7 +124,10 @@ The list of requests - a (*) means it requires privileged access - and replies a
|
|||||||
Log Interval=N, <- log interval (--log N)
|
Log Interval=N, <- log interval (--log N)
|
||||||
Device Code=GPU ICA , <- spaced list of compiled devices
|
Device Code=GPU ICA , <- spaced list of compiled devices
|
||||||
OS=Linux/Apple/..., <- operating System
|
OS=Linux/Apple/..., <- operating System
|
||||||
Failover-Only=true/false | <- failover-only setting
|
Failover-Only=true/false, <- failover-only setting
|
||||||
|
ScanTime=N, <- --scan-time setting
|
||||||
|
Queue=N, <- --queue setting
|
||||||
|
Expiry=N| <- --expiry setting
|
||||||
|
|
||||||
summary SUMMARY The status summary of the miner
|
summary SUMMARY The status summary of the miner
|
||||||
e.g. Elapsed=NNN,Found Blocks=N,Getworks=N,...|
|
e.g. Elapsed=NNN,Found Blocks=N,Getworks=N,...|
|
||||||
@ -259,6 +262,22 @@ The list of requests - a (*) means it requires privileged access - and replies a
|
|||||||
stating the results of the disable request
|
stating the results of the disable request
|
||||||
This is only available if PGA mining is enabled
|
This is only available if PGA mining is enabled
|
||||||
|
|
||||||
|
pgaidentify|N (*)
|
||||||
|
none There is no reply section just the STATUS section
|
||||||
|
stating the results of the identify request
|
||||||
|
This is only available if PGA mining is enabled
|
||||||
|
and currently only BFL singles support this command
|
||||||
|
On a BFL single it will flash the led on the front
|
||||||
|
of the device for appoximately 4s
|
||||||
|
All other non BFL PGA devices will return a warning
|
||||||
|
status message stating that they dont support it
|
||||||
|
This adds a 4s delay to the BFL share being processed
|
||||||
|
so you may get a message stating that procssing took
|
||||||
|
longer than 7000ms if the request was sent towards
|
||||||
|
the end of the timing of any work being worked on
|
||||||
|
e.g.: BFL0: took 8438ms - longer than 7000ms
|
||||||
|
You should ignore this
|
||||||
|
|
||||||
devdetails DEVDETAILS Each device with a list of their static details
|
devdetails DEVDETAILS Each device with a list of their static details
|
||||||
This lists all devices including those not supported
|
This lists all devices including those not supported
|
||||||
by the 'devs' command
|
by the 'devs' command
|
||||||
@ -287,6 +306,30 @@ The list of requests - a (*) means it requires privileged access - and replies a
|
|||||||
Current Block Hash=XXXX..., <- blank if none
|
Current Block Hash=XXXX..., <- blank if none
|
||||||
LP=true/false| <- LP is in use on at least 1 pool
|
LP=true/false| <- LP is in use on at least 1 pool
|
||||||
|
|
||||||
|
debug|setting (*)
|
||||||
|
DEBUG Debug settings
|
||||||
|
The optional commands for 'setting' are the same as
|
||||||
|
the screen curses debug settings
|
||||||
|
You can only specify one setting
|
||||||
|
Only the first character is checked (case insensitive):
|
||||||
|
Silent, Quiet, Verbose, Debug, RPCProto, PerDevice,
|
||||||
|
WorkTime, Normal
|
||||||
|
The output fields are (as above):
|
||||||
|
Silent=true/false,
|
||||||
|
Quiet=true/false,
|
||||||
|
Verbose=true/false,
|
||||||
|
Debug=true/false,
|
||||||
|
RPCProto=true/false,
|
||||||
|
PerDevice=true/false,
|
||||||
|
WorkTime=true/false|
|
||||||
|
|
||||||
|
setconfig|name,N (*)
|
||||||
|
none There is no reply section just the STATUS section
|
||||||
|
stating the results of setting 'name' to N
|
||||||
|
The valid values for name are currently:
|
||||||
|
queue, scantime, expiry
|
||||||
|
N is an integer in the range 0 to 9999
|
||||||
|
|
||||||
When you enable, disable or restart a GPU or PGA, you will also get Thread messages
|
When you enable, disable or restart a GPU or PGA, you will also get Thread messages
|
||||||
in the cgminer status window
|
in the cgminer status window
|
||||||
|
|
||||||
@ -306,8 +349,9 @@ windows
|
|||||||
Obviously, the JSON format is simply just the names as given before the '='
|
Obviously, the JSON format is simply just the names as given before the '='
|
||||||
with the values after the '='
|
with the values after the '='
|
||||||
|
|
||||||
If you enable cgminer debug (-D or --debug) you will also get messages showing
|
If you enable cgminer debug (-D or --debug) or, when cgminer debug is off,
|
||||||
details of the requests received and the replies
|
turn on debug with the API command 'debug|debug' you will also get messages
|
||||||
|
showing some details of the requests received and the replies
|
||||||
|
|
||||||
There are included 4 program examples for accessing the API:
|
There are included 4 program examples for accessing the API:
|
||||||
|
|
||||||
@ -339,13 +383,34 @@ miner.php - an example web page to access the API
|
|||||||
Feature Changelog for external applications using the API:
|
Feature Changelog for external applications using the API:
|
||||||
|
|
||||||
|
|
||||||
API V1.18
|
API V1.19
|
||||||
|
|
||||||
|
Added API commands:
|
||||||
|
'debug'
|
||||||
|
'pgaidentify|N' (only works for BFL Singles so far)
|
||||||
|
'setconfig|name,N'
|
||||||
|
|
||||||
|
Modified API commands:
|
||||||
|
'devs' - add 'Diff1 Work', 'Difficulty Accepted', 'Difficulty Rejected',
|
||||||
|
'Last Share Difficulty' to all devices
|
||||||
|
'gpu|N' - add 'Diff1 Work', 'Difficulty Accepted',
|
||||||
|
'Difficulty Rejected', 'Last Share Difficulty'
|
||||||
|
'pga|N' - add 'Diff1 Work', 'Difficulty Accepted',
|
||||||
|
'Difficulty Rejected', 'Last Share Difficulty'
|
||||||
|
'notify' - add '*Dev Throttle' (for BFL Singles)
|
||||||
|
'pools' - add 'Proxy Type', 'Proxy', 'Difficulty Accepted', 'Difficulty Rejected',
|
||||||
|
'Difficulty Stale', 'Last Share Difficulty'
|
||||||
|
'config' - add 'Queue', 'Expiry'
|
||||||
|
'stats' - add 'Work Diff', 'Min Diff', 'Max Diff', 'Min Diff Count',
|
||||||
|
'Max Diff Count' to the pool stats
|
||||||
|
|
||||||
|
----------
|
||||||
|
|
||||||
|
API V1.18 (cgminer v2.7.4)
|
||||||
|
|
||||||
Modified API commands:
|
Modified API commands:
|
||||||
'stats' - add 'Work Had Roll Time', 'Work Can Roll', 'Work Had Expire',
|
'stats' - add 'Work Had Roll Time', 'Work Can Roll', 'Work Had Expire',
|
||||||
'Work Roll Time' to the pool stats
|
'Work Roll Time' to the pool stats
|
||||||
|
|
||||||
Modified API commands:
|
|
||||||
'config' - include 'ScanTime'
|
'config' - include 'ScanTime'
|
||||||
|
|
||||||
----------
|
----------
|
||||||
@ -866,6 +931,14 @@ e.g. $rigs = array('127.0.0.1:4028','myrig.com:4028:Sugoi');
|
|||||||
|
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
Default:
|
||||||
|
$rigipsecurity = true;
|
||||||
|
|
||||||
|
Set $rigipsecurity to false to show the IP/Port of the rig
|
||||||
|
in the socket error messages and also show the full socket message
|
||||||
|
|
||||||
|
---------
|
||||||
|
|
||||||
Default:
|
Default:
|
||||||
$rigtotals = true;
|
$rigtotals = true;
|
||||||
$forcerigtotals = false;
|
$forcerigtotals = false;
|
||||||
|
57
NEWS
57
NEWS
@ -1,3 +1,60 @@
|
|||||||
|
Version 2.7.6 - September 24, 2012
|
||||||
|
|
||||||
|
- Display share difficulty on log with a shortened hash display on submission.
|
||||||
|
- API stats add some pool getwork difficulty stats
|
||||||
|
- Ignore any pings pushed to the worker threads if the thread is still paused to
|
||||||
|
prevent it being enabled and disabled repeatedly.
|
||||||
|
- README - FAQ - usermod group - shouldn't remove other groups
|
||||||
|
- Test for sequential getwork failures on a pool that might actually be up but
|
||||||
|
failing to deliver work as we may end up hammering it repeatedly by mistake.
|
||||||
|
- reduce windows compile warnings
|
||||||
|
- util.c - bug - proxy - no data end condition
|
||||||
|
- As we average gpu time over 5 work intervals for dynamic GPU intensity, there
|
||||||
|
is no need to maintain a rolling average and it avoids the potential long term
|
||||||
|
corruption of a single overflow value.
|
||||||
|
- Test for the now-automatically exported variable AMDAPPSDKROOT when looking
|
||||||
|
for the presence of the OpenCL headers.
|
||||||
|
- API don't change 'Diff1 Shares' - backward compatability FTW
|
||||||
|
- miner.php highlighting correctly handling difficulty
|
||||||
|
- API - Add last share difficulty for devices and pool
|
||||||
|
- Store and report Accepted,Rejected,Stale difficulty in the summary and API
|
||||||
|
- WorkTime - display prevblock for scrypt
|
||||||
|
- api.c remove compile warnings
|
||||||
|
- Calculate work difficulty for each getwork and display with WorkTime debug
|
||||||
|
- remove MMQ unused variable warning
|
||||||
|
- FPGA - allow long or short device names in detect code + style police
|
||||||
|
- WorkTime - multiple nonce per work and identify the work source
|
||||||
|
- Optional WorkTime details with each Accepted/Rejected work item
|
||||||
|
- Icarus - ignore hardware errors in timing mode
|
||||||
|
- miner.php oops - mistype
|
||||||
|
- miner.php by default don't display IP/Port numbers in error messages
|
||||||
|
- api.c all STATUS messages automatically escaped
|
||||||
|
- api.c add missing escape for comma in MSG_PGAUNW
|
||||||
|
- API add display of and setting queue,scantime,expiry
|
||||||
|
- HW: dont submit bad shares
|
||||||
|
- save individual pool proxy settings to config
|
||||||
|
- --default-config - allow command line to define the default configuration file
|
||||||
|
for loading and saving
|
||||||
|
- API-README update for pools proxy info
|
||||||
|
- README URL proxy must use quote so show in the example
|
||||||
|
- bug: remove proxy: from the front of the proxy used
|
||||||
|
- CURL support for individual proxy per pool and all proxy types
|
||||||
|
- README spelling/etc
|
||||||
|
- README - FPGA device FAQ
|
||||||
|
- HW: error counter auto for all devices - ztex code not fixed
|
||||||
|
- API pgaidentify - unsupported message should be a warning
|
||||||
|
- API/BFL identify a device - currently only BFL to flash the led
|
||||||
|
- BFL add throttle count to internal stats + API
|
||||||
|
- BFL: missing device id in log message
|
||||||
|
- miner.php correct to new Diff1 Work field names
|
||||||
|
- API add device diff1 work
|
||||||
|
- API-README update
|
||||||
|
- api.c Correct diff1 field name
|
||||||
|
- count device diff1 shares
|
||||||
|
- API-README more debug parameter information
|
||||||
|
- API allow full debug settings control
|
||||||
|
|
||||||
|
|
||||||
Version 2.7.5 - August 31, 2012
|
Version 2.7.5 - August 31, 2012
|
||||||
|
|
||||||
- Adjust opencl intensity when adjusting thread count to prevent it getting
|
- Adjust opencl intensity when adjusting thread count to prevent it getting
|
||||||
|
72
README
72
README
@ -168,7 +168,7 @@ Options for both config file and command line:
|
|||||||
--scrypt Use the scrypt algorithm for mining (litecoin only)
|
--scrypt Use the scrypt algorithm for mining (litecoin only)
|
||||||
--sharelog <arg> Append share log to file
|
--sharelog <arg> Append share log to file
|
||||||
--shares <arg> Quit after mining N shares (default: unlimited)
|
--shares <arg> Quit after mining N shares (default: unlimited)
|
||||||
--socks-proxy <arg> Set socks4 proxy (host:port)
|
--socks-proxy <arg> Set socks4 proxy (host:port) for all pools without a proxy specified
|
||||||
--syslog Use system log for output messages (default: standard error)
|
--syslog Use system log for output messages (default: standard error)
|
||||||
--temp-cutoff <arg> Temperature where a device will be automatically disabled, one value or comma separated list (default: 95)
|
--temp-cutoff <arg> Temperature where a device will be automatically disabled, one value or comma separated list (default: 95)
|
||||||
--text-only|-T Disable ncurses formatted screen output
|
--text-only|-T Disable ncurses formatted screen output
|
||||||
@ -239,6 +239,7 @@ The official supplied binaries are compiled with support for all FPGAs.
|
|||||||
To force the code to only attempt detection with a specific driver,
|
To force the code to only attempt detection with a specific driver,
|
||||||
prepend the argument with the driver name followed by a colon.
|
prepend the argument with the driver name followed by a colon.
|
||||||
For example, "icarus:/dev/ttyUSB0" or "bitforce:\\.\COM5"
|
For example, "icarus:/dev/ttyUSB0" or "bitforce:\\.\COM5"
|
||||||
|
or using the short name: "ica:/dev/ttyUSB0" or "bfl:\\.\COM5"
|
||||||
|
|
||||||
For other FPGA details see the FPGA-README
|
For other FPGA details see the FPGA-README
|
||||||
|
|
||||||
@ -295,6 +296,28 @@ Add overclocking settings, GPU and fan control with different engine settings fo
|
|||||||
|
|
||||||
cgminer -o http://pool:port -u username -p password -I 9 --auto-fan --auto-gpu --gpu-engine 750-950,945,700-930,960 --gpu-memclock 300
|
cgminer -o http://pool:port -u username -p password -I 9 --auto-fan --auto-gpu --gpu-engine 750-950,945,700-930,960 --gpu-memclock 300
|
||||||
|
|
||||||
|
Single pool with a standard http proxy, regular desktop:
|
||||||
|
|
||||||
|
cgminer -o "http:proxy:port|http://pool:port" -u username -p password
|
||||||
|
|
||||||
|
Single pool with a socks5 proxy, regular desktop:
|
||||||
|
|
||||||
|
cgminer -o "socks5:proxy:port|http://pool:port" -u username -p password
|
||||||
|
|
||||||
|
The list of proxy types are:
|
||||||
|
http: standard http 1.1 proxy
|
||||||
|
http0: http 1.0 proxy
|
||||||
|
socks4: socks4 proxy
|
||||||
|
socks5: socks5 proxy
|
||||||
|
socks4a: socks4a proxy
|
||||||
|
socks5h: socks5 proxy using a hostname
|
||||||
|
|
||||||
|
If you compile cgminer with a version of CURL before 7.19.4 then some of the above will
|
||||||
|
not be available. All are available since CURL version 7.19.4
|
||||||
|
|
||||||
|
If you specify the --socks-proxy option to cgminer, it will only be applied to all pools
|
||||||
|
that don't specify their own proxy setting like above
|
||||||
|
|
||||||
READ WARNINGS AND DOCUMENTATION BELOW ABOUT OVERCLOCKING
|
READ WARNINGS AND DOCUMENTATION BELOW ABOUT OVERCLOCKING
|
||||||
|
|
||||||
On Linux you virtually always need to export your display settings before
|
On Linux you virtually always need to export your display settings before
|
||||||
@ -451,6 +474,26 @@ it will log to a file called logfile.txt and otherwise work the same.
|
|||||||
There is also the -m option on linux which will spawn a command of your choice
|
There is also the -m option on linux which will spawn a command of your choice
|
||||||
and pipe the output directly to that command.
|
and pipe the output directly to that command.
|
||||||
|
|
||||||
|
The WorkTime details 'debug' option adds details on the end of each line
|
||||||
|
displayed for Accepted or Rejected work done. An example would be:
|
||||||
|
|
||||||
|
<-00000059.ed4834a3 M:X D:1.0 G:17:02:38:0.405 C:1.855 (2.995) W:3.440 (0.000) S:0.461 R:17:02:47
|
||||||
|
|
||||||
|
The first 2 hex codes are the previous block hash, the rest are reported in
|
||||||
|
seconds unless stated otherwise:
|
||||||
|
The previous hash is followed by the getwork mode used M:X where X is one of
|
||||||
|
P:Pool, T:Test Pool, L:LP or B:Benchmark,
|
||||||
|
then D:d.ddd is the difficulty required to get a share from the work,
|
||||||
|
then G:hh:mm:ss:n.nnn, which is when the getwork or LP was sent to the pool and
|
||||||
|
the n.nnn is how long it took to reply,
|
||||||
|
followed by 'O' on it's own if it is an original getwork, or 'C:n.nnn' if it was
|
||||||
|
a clone with n.nnn stating how long after the work was recieved that it was cloned,
|
||||||
|
(m.mmm) is how long from when the original work was received until work started,
|
||||||
|
W:n.nnn is how long the work took to process until it was ready to submit,
|
||||||
|
(m.mmm) is how long from ready to submit to actually doing the submit, this is
|
||||||
|
usually 0.000 unless there was a problem with submitting the work,
|
||||||
|
S:n.nnn is how long it took to submit the completed work and await the reply,
|
||||||
|
R:hh:mm:ss is the actual time the work submit reply was received
|
||||||
|
|
||||||
If you start cgminer with the --sharelog option, you can get detailed
|
If you start cgminer with the --sharelog option, you can get detailed
|
||||||
information for each share found. The argument to the option may be "-" for
|
information for each share found. The argument to the option may be "-" for
|
||||||
@ -816,7 +859,7 @@ driver version and ATI stream version.
|
|||||||
|
|
||||||
Q: cgminer reports no devices or only one device on startup on Linux although
|
Q: cgminer reports no devices or only one device on startup on Linux although
|
||||||
I have multiple devices and drivers+SDK installed properly?
|
I have multiple devices and drivers+SDK installed properly?
|
||||||
A: Try 'export DISPLAY=:0" before running cgminer.
|
A: Try "export DISPLAY=:0" before running cgminer.
|
||||||
|
|
||||||
Q: My network gets slower and slower and then dies for a minute?
|
Q: My network gets slower and slower and then dies for a minute?
|
||||||
A; Try the --net-delay option.
|
A; Try the --net-delay option.
|
||||||
@ -843,10 +886,27 @@ They are Field-Programmable Gate Arrays that have been programmed to do Bitcoin
|
|||||||
mining. Since the acronym needs to be only 3 characters, the "Field-" part has
|
mining. Since the acronym needs to be only 3 characters, the "Field-" part has
|
||||||
been skipped.
|
been skipped.
|
||||||
|
|
||||||
Q: How do I get my BFL device to auto-recognise?
|
Q: How do I get my BFL/Icarus/Lancelot/Cairnsmore device to auto-recognise?
|
||||||
A: The only thing that needs to be done is to load the driver for them, which
|
A: On linux, if the /dev/ttyUSB* devices don't automatically appear, the only
|
||||||
on linux would require:
|
thing that needs to be done is to load the driver for them:
|
||||||
sudo modprobe ftdi_sio vendor=0x0403 product=0x6014
|
BFL: sudo modprobe ftdi_sio vendor=0x0403 product=0x6014
|
||||||
|
Icarus: sudo modprobe pl2303 vendor=0x067b product=0x230
|
||||||
|
Lancelot: sudo modprobe ftdi_sio vendor=0x0403 product=0x6001
|
||||||
|
Cairnsmore: sudo modprobe ftdi_sio product=0x8350 vendor=0x0403
|
||||||
|
On windows you must install the pl2303 or ftdi driver required for the device
|
||||||
|
pl2303: http://prolificusa.com/pl-2303hx-drivers/
|
||||||
|
ftdi: http://www.ftdichip.com/Drivers/VCP.htm
|
||||||
|
|
||||||
|
Q: On linux I can see the /dev/ttyUSB* devices for my ICA/BFL/MMQ FPGA, but
|
||||||
|
cgminer can't mine on them
|
||||||
|
A: Make sure you have the required priviledges 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
|
||||||
|
To permanently give your account the 'dialout' group:
|
||||||
|
sudo usermod -G dialout -a `whoami`
|
||||||
|
Then logout and back in again
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
239
api.c
239
api.c
@ -166,11 +166,13 @@ static const char SEPARATOR = '|';
|
|||||||
#define SEPSTR "|"
|
#define SEPSTR "|"
|
||||||
static const char GPUSEP = ',';
|
static const char GPUSEP = ',';
|
||||||
|
|
||||||
static const char *APIVERSION = "1.18";
|
static const char *APIVERSION = "1.19";
|
||||||
static const char *DEAD = "Dead";
|
static const char *DEAD = "Dead";
|
||||||
|
#if defined(HAVE_OPENCL) || defined(HAVE_AN_FPGA)
|
||||||
static const char *SICK = "Sick";
|
static const char *SICK = "Sick";
|
||||||
static const char *NOSTART = "NoStart";
|
static const char *NOSTART = "NoStart";
|
||||||
static const char *INIT = "Initialising";
|
static const char *INIT = "Initialising";
|
||||||
|
#endif
|
||||||
static const char *DISABLED = "Disabled";
|
static const char *DISABLED = "Disabled";
|
||||||
static const char *ALIVE = "Alive";
|
static const char *ALIVE = "Alive";
|
||||||
static const char *REJECTING = "Rejecting";
|
static const char *REJECTING = "Rejecting";
|
||||||
@ -258,6 +260,8 @@ static const char *OSINFO =
|
|||||||
#define _MINESTATS "STATS"
|
#define _MINESTATS "STATS"
|
||||||
#define _CHECK "CHECK"
|
#define _CHECK "CHECK"
|
||||||
#define _MINECOIN "COIN"
|
#define _MINECOIN "COIN"
|
||||||
|
#define _DEBUGSET "DEBUG"
|
||||||
|
#define _SETCONFIG "SETCONFIG"
|
||||||
|
|
||||||
static const char ISJSON = '{';
|
static const char ISJSON = '{';
|
||||||
#define JSON0 "{"
|
#define JSON0 "{"
|
||||||
@ -295,6 +299,8 @@ static const char ISJSON = '{';
|
|||||||
#define JSON_MINESTATS JSON1 _MINESTATS JSON2
|
#define JSON_MINESTATS JSON1 _MINESTATS JSON2
|
||||||
#define JSON_CHECK JSON1 _CHECK JSON2
|
#define JSON_CHECK JSON1 _CHECK JSON2
|
||||||
#define JSON_MINECOIN JSON1 _MINECOIN JSON2
|
#define JSON_MINECOIN JSON1 _MINECOIN JSON2
|
||||||
|
#define JSON_DEBUGSET JSON1 _DEBUGSET JSON2
|
||||||
|
#define JSON_SETCONFIG JSON1 _SETCONFIG JSON2
|
||||||
#define JSON_END JSON4 JSON5
|
#define JSON_END JSON4 JSON5
|
||||||
|
|
||||||
static const char *JSON_COMMAND = "command";
|
static const char *JSON_COMMAND = "command";
|
||||||
@ -390,6 +396,14 @@ static const char *JSON_PARAMETER = "parameter";
|
|||||||
#define MSG_INVBOOL 76
|
#define MSG_INVBOOL 76
|
||||||
#define MSG_FOO 77
|
#define MSG_FOO 77
|
||||||
#define MSG_MINECOIN 78
|
#define MSG_MINECOIN 78
|
||||||
|
#define MSG_DEBUGSET 79
|
||||||
|
#define MSG_PGAIDENT 80
|
||||||
|
#define MSG_PGANOID 81
|
||||||
|
#define MSG_SETCONFIG 82
|
||||||
|
#define MSG_UNKCON 83
|
||||||
|
#define MSG_INVNUM 84
|
||||||
|
#define MSG_CONPAR 85
|
||||||
|
#define MSG_CONVAL 86
|
||||||
|
|
||||||
enum code_severity {
|
enum code_severity {
|
||||||
SEVERITY_ERR,
|
SEVERITY_ERR,
|
||||||
@ -418,6 +432,7 @@ enum code_parameters {
|
|||||||
PARAM_STR,
|
PARAM_STR,
|
||||||
PARAM_BOTH,
|
PARAM_BOTH,
|
||||||
PARAM_BOOL,
|
PARAM_BOOL,
|
||||||
|
PARAM_SET,
|
||||||
PARAM_NONE
|
PARAM_NONE
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -543,12 +558,24 @@ struct CODES {
|
|||||||
{ SEVERITY_ERR, MSG_INVBOOL, PARAM_NONE, "Invalid parameter should be true or false" },
|
{ SEVERITY_ERR, MSG_INVBOOL, PARAM_NONE, "Invalid parameter should be true or false" },
|
||||||
{ SEVERITY_SUCC, MSG_FOO, PARAM_BOOL, "Failover-Only set to %s" },
|
{ SEVERITY_SUCC, MSG_FOO, PARAM_BOOL, "Failover-Only set to %s" },
|
||||||
{ SEVERITY_SUCC, MSG_MINECOIN,PARAM_NONE, "CGMiner coin" },
|
{ SEVERITY_SUCC, MSG_MINECOIN,PARAM_NONE, "CGMiner coin" },
|
||||||
|
{ SEVERITY_SUCC, MSG_DEBUGSET,PARAM_STR, "Debug settings" },
|
||||||
|
#ifdef HAVE_AN_FPGA
|
||||||
|
{ SEVERITY_SUCC, MSG_PGAIDENT,PARAM_PGA, "Identify command sent to PGA%d" },
|
||||||
|
{ SEVERITY_WARN, MSG_PGANOID, PARAM_PGA, "PGA%d does not support identify" },
|
||||||
|
#endif
|
||||||
|
{ SEVERITY_SUCC, MSG_SETCONFIG,PARAM_SET, "Set config '%s' to %d" },
|
||||||
|
{ SEVERITY_ERR, MSG_UNKCON, PARAM_STR, "Unknown config '%s'" },
|
||||||
|
{ SEVERITY_ERR, MSG_INVNUM, PARAM_BOTH, "Invalid number (%d) for '%s' range is 0-9999" },
|
||||||
|
{ SEVERITY_ERR, MSG_CONPAR, PARAM_NONE, "Missing config parameters 'name,N'" },
|
||||||
|
{ SEVERITY_ERR, MSG_CONVAL, PARAM_STR, "Missing config value N for '%s,N'" },
|
||||||
{ SEVERITY_FAIL, 0, 0, NULL }
|
{ SEVERITY_FAIL, 0, 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static int my_thr_id = 0;
|
static int my_thr_id = 0;
|
||||||
static bool bye;
|
static bool bye;
|
||||||
|
#if defined(HAVE_OPENCL) || defined(HAVE_AN_FPGA)
|
||||||
static bool ping = true;
|
static bool ping = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Used to control quit restart access to shutdown variables
|
// Used to control quit restart access to shutdown variables
|
||||||
static pthread_mutex_t quit_restart_lock;
|
static pthread_mutex_t quit_restart_lock;
|
||||||
@ -749,6 +776,7 @@ static struct api_data *api_add_data_full(struct api_data *root, char *name, enu
|
|||||||
case API_UTILITY:
|
case API_UTILITY:
|
||||||
case API_FREQ:
|
case API_FREQ:
|
||||||
case API_HS:
|
case API_HS:
|
||||||
|
case API_DIFF:
|
||||||
api_data->data = (void *)malloc(sizeof(double));
|
api_data->data = (void *)malloc(sizeof(double));
|
||||||
*((double *)(api_data->data)) = *((double *)data);
|
*((double *)(api_data->data)) = *((double *)data);
|
||||||
break;
|
break;
|
||||||
@ -875,6 +903,11 @@ struct api_data *api_add_hs(struct api_data *root, char *name, double *data, boo
|
|||||||
return api_add_data_full(root, name, API_HS, (void *)data, copy_data);
|
return api_add_data_full(root, name, API_HS, (void *)data, copy_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct api_data *api_add_diff(struct api_data *root, char *name, double *data, bool copy_data)
|
||||||
|
{
|
||||||
|
return api_add_data_full(root, name, API_DIFF, (void *)data, copy_data);
|
||||||
|
}
|
||||||
|
|
||||||
static struct api_data *print_data(struct api_data *root, char *buf, bool isjson)
|
static struct api_data *print_data(struct api_data *root, char *buf, bool isjson)
|
||||||
{
|
{
|
||||||
struct api_data *tmp;
|
struct api_data *tmp;
|
||||||
@ -946,6 +979,9 @@ static struct api_data *print_data(struct api_data *root, char *buf, bool isjson
|
|||||||
case API_HS:
|
case API_HS:
|
||||||
sprintf(buf, "%.15f", *((double *)(root->data)));
|
sprintf(buf, "%.15f", *((double *)(root->data)));
|
||||||
break;
|
break;
|
||||||
|
case API_DIFF:
|
||||||
|
sprintf(buf, "%.8f", *((double *)(root->data)));
|
||||||
|
break;
|
||||||
case API_BOOL:
|
case API_BOOL:
|
||||||
sprintf(buf, "%s", *((bool *)(root->data)) ? TRUESTR : FALSESTR);
|
sprintf(buf, "%s", *((bool *)(root->data)) ? TRUESTR : FALSESTR);
|
||||||
break;
|
break;
|
||||||
@ -1155,6 +1191,9 @@ static char *message(int messageid, int paramid, char *param2, bool isjson)
|
|||||||
case PARAM_BOOL:
|
case PARAM_BOOL:
|
||||||
sprintf(buf, codes[i].description, paramid ? TRUESTR : FALSESTR);
|
sprintf(buf, codes[i].description, paramid ? TRUESTR : FALSESTR);
|
||||||
break;
|
break;
|
||||||
|
case PARAM_SET:
|
||||||
|
sprintf(buf, codes[i].description, param2, paramid);
|
||||||
|
break;
|
||||||
case PARAM_NONE:
|
case PARAM_NONE:
|
||||||
default:
|
default:
|
||||||
strcpy(buf, codes[i].description);
|
strcpy(buf, codes[i].description);
|
||||||
@ -1163,8 +1202,8 @@ static char *message(int messageid, int paramid, char *param2, bool isjson)
|
|||||||
root = api_add_string(root, _STATUS, severity, false);
|
root = api_add_string(root, _STATUS, severity, false);
|
||||||
root = api_add_time(root, "When", &when, false);
|
root = api_add_time(root, "When", &when, false);
|
||||||
root = api_add_int(root, "Code", &messageid, false);
|
root = api_add_int(root, "Code", &messageid, false);
|
||||||
root = api_add_string(root, "Msg", buf, false);
|
root = api_add_escape(root, "Msg", buf, false);
|
||||||
root = api_add_string(root, "Description", opt_api_description, false);
|
root = api_add_escape(root, "Description", opt_api_description, false);
|
||||||
|
|
||||||
root = print_data(root, ptr, isjson);
|
root = print_data(root, ptr, isjson);
|
||||||
if (isjson)
|
if (isjson)
|
||||||
@ -1178,8 +1217,8 @@ static char *message(int messageid, int paramid, char *param2, bool isjson)
|
|||||||
int id = -1;
|
int id = -1;
|
||||||
root = api_add_int(root, "Code", &id, false);
|
root = api_add_int(root, "Code", &id, false);
|
||||||
sprintf(buf, "%d", messageid);
|
sprintf(buf, "%d", messageid);
|
||||||
root = api_add_string(root, "Msg", buf, false);
|
root = api_add_escape(root, "Msg", buf, false);
|
||||||
root = api_add_string(root, "Description", opt_api_description, false);
|
root = api_add_escape(root, "Description", opt_api_description, false);
|
||||||
|
|
||||||
root = print_data(root, ptr, isjson);
|
root = print_data(root, ptr, isjson);
|
||||||
if (isjson)
|
if (isjson)
|
||||||
@ -1257,6 +1296,8 @@ static void minerconfig(__maybe_unused SOCKETTYPE c, __maybe_unused char *param,
|
|||||||
root = api_add_const(root, "OS", OSINFO, false);
|
root = api_add_const(root, "OS", OSINFO, false);
|
||||||
root = api_add_bool(root, "Failover-Only", &opt_fail_only, false);
|
root = api_add_bool(root, "Failover-Only", &opt_fail_only, false);
|
||||||
root = api_add_int(root, "ScanTime", &opt_scantime, false);
|
root = api_add_int(root, "ScanTime", &opt_scantime, false);
|
||||||
|
root = api_add_int(root, "Queue", &opt_queue, false);
|
||||||
|
root = api_add_int(root, "Expiry", &opt_expiry, false);
|
||||||
|
|
||||||
root = print_data(root, buf, isjson);
|
root = print_data(root, buf, isjson);
|
||||||
if (isjson)
|
if (isjson)
|
||||||
@ -1264,6 +1305,7 @@ static void minerconfig(__maybe_unused SOCKETTYPE c, __maybe_unused char *param,
|
|||||||
strcat(io_buffer, buf);
|
strcat(io_buffer, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(HAVE_OPENCL) || defined(HAVE_AN_FPGA)
|
||||||
static const char *status2str(enum alive status)
|
static const char *status2str(enum alive status)
|
||||||
{
|
{
|
||||||
switch (status) {
|
switch (status) {
|
||||||
@ -1281,6 +1323,7 @@ static const char *status2str(enum alive status)
|
|||||||
return UNKNOWN;
|
return UNKNOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_OPENCL
|
#ifdef HAVE_OPENCL
|
||||||
static void gpustatus(int gpu, bool isjson)
|
static void gpustatus(int gpu, bool isjson)
|
||||||
@ -1341,6 +1384,10 @@ static void gpustatus(int gpu, bool isjson)
|
|||||||
root = api_add_int(root, "Last Share Pool", &last_share_pool, false);
|
root = api_add_int(root, "Last Share Pool", &last_share_pool, false);
|
||||||
root = api_add_time(root, "Last Share Time", &(cgpu->last_share_pool_time), false);
|
root = api_add_time(root, "Last Share Time", &(cgpu->last_share_pool_time), false);
|
||||||
root = api_add_mhtotal(root, "Total MH", &(cgpu->total_mhashes), false);
|
root = api_add_mhtotal(root, "Total MH", &(cgpu->total_mhashes), false);
|
||||||
|
root = api_add_int(root, "Diff1 Work", &(cgpu->diff1), false);
|
||||||
|
root = api_add_diff(root, "Difficulty Accepted", &(cgpu->diff_accepted), false);
|
||||||
|
root = api_add_diff(root, "Difficulty Rejected", &(cgpu->diff_rejected), false);
|
||||||
|
root = api_add_diff(root, "Last Share Difficulty", &(cgpu->last_share_diff), false);
|
||||||
|
|
||||||
root = print_data(root, buf, isjson);
|
root = print_data(root, buf, isjson);
|
||||||
strcat(io_buffer, buf);
|
strcat(io_buffer, buf);
|
||||||
@ -1424,6 +1471,10 @@ static void pgastatus(int pga, bool isjson)
|
|||||||
root = api_add_time(root, "Last Share Time", &(cgpu->last_share_pool_time), false);
|
root = api_add_time(root, "Last Share Time", &(cgpu->last_share_pool_time), false);
|
||||||
root = api_add_mhtotal(root, "Total MH", &(cgpu->total_mhashes), false);
|
root = api_add_mhtotal(root, "Total MH", &(cgpu->total_mhashes), false);
|
||||||
root = api_add_freq(root, "Frequency", &frequency, false);
|
root = api_add_freq(root, "Frequency", &frequency, false);
|
||||||
|
root = api_add_int(root, "Diff1 Work", &(cgpu->diff1), false);
|
||||||
|
root = api_add_diff(root, "Difficulty Accepted", &(cgpu->diff_accepted), false);
|
||||||
|
root = api_add_diff(root, "Difficulty Rejected", &(cgpu->diff_rejected), false);
|
||||||
|
root = api_add_diff(root, "Last Share Difficulty", &(cgpu->last_share_diff), false);
|
||||||
|
|
||||||
root = print_data(root, buf, isjson);
|
root = print_data(root, buf, isjson);
|
||||||
strcat(io_buffer, buf);
|
strcat(io_buffer, buf);
|
||||||
@ -1456,6 +1507,10 @@ static void cpustatus(int cpu, bool isjson)
|
|||||||
root = api_add_int(root, "Last Share Pool", &last_share_pool, false);
|
root = api_add_int(root, "Last Share Pool", &last_share_pool, false);
|
||||||
root = api_add_time(root, "Last Share Time", &(cgpu->last_share_pool_time), false);
|
root = api_add_time(root, "Last Share Time", &(cgpu->last_share_pool_time), false);
|
||||||
root = api_add_mhtotal(root, "Total MH", &(cgpu->total_mhashes), false);
|
root = api_add_mhtotal(root, "Total MH", &(cgpu->total_mhashes), false);
|
||||||
|
root = api_add_int(root, "Diff1 Work", &(cgpu->diff1), false);
|
||||||
|
root = api_add_diff(root, "Difficulty Accepted", &(cgpu->diff_accepted), false);
|
||||||
|
root = api_add_diff(root, "Difficulty Rejected", &(cgpu->diff_rejected), false);
|
||||||
|
root = api_add_diff(root, "Last Share Difficulty", &(cgpu->last_share_diff), false);
|
||||||
|
|
||||||
root = print_data(root, buf, isjson);
|
root = print_data(root, buf, isjson);
|
||||||
strcat(io_buffer, buf);
|
strcat(io_buffer, buf);
|
||||||
@ -1693,6 +1748,44 @@ static void pgadisable(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __
|
|||||||
|
|
||||||
strcpy(io_buffer, message(MSG_PGADIS, id, NULL, isjson));
|
strcpy(io_buffer, message(MSG_PGADIS, id, NULL, isjson));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pgaidentify(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||||
|
{
|
||||||
|
int numpga = numpgas();
|
||||||
|
int id;
|
||||||
|
|
||||||
|
if (numpga == 0) {
|
||||||
|
strcpy(io_buffer, message(MSG_PGANON, 0, NULL, isjson));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (param == NULL || *param == '\0') {
|
||||||
|
strcpy(io_buffer, message(MSG_MISID, 0, NULL, isjson));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
id = atoi(param);
|
||||||
|
if (id < 0 || id >= numpga) {
|
||||||
|
strcpy(io_buffer, message(MSG_INVPGA, id, NULL, isjson));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev = pgadevice(id);
|
||||||
|
if (dev < 0) { // Should never happen
|
||||||
|
strcpy(io_buffer, message(MSG_INVPGA, id, NULL, isjson));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cgpu_info *cgpu = devices[dev];
|
||||||
|
struct device_api *api = cgpu->api;
|
||||||
|
|
||||||
|
if (!api->identify_device)
|
||||||
|
strcpy(io_buffer, message(MSG_PGANOID, id, NULL, isjson));
|
||||||
|
else {
|
||||||
|
api->identify_device(cgpu);
|
||||||
|
strcpy(io_buffer, message(MSG_PGAIDENT, id, NULL, isjson));
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WANT_CPUMINE
|
#ifdef WANT_CPUMINE
|
||||||
@ -1790,6 +1883,17 @@ static void poolstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param,
|
|||||||
root = api_add_escape(root, "User", pool->rpc_user, false);
|
root = api_add_escape(root, "User", pool->rpc_user, false);
|
||||||
root = api_add_time(root, "Last Share Time", &(pool->last_share_time), false);
|
root = api_add_time(root, "Last Share Time", &(pool->last_share_time), false);
|
||||||
root = api_add_int(root, "Diff1 Shares", &(pool->diff1), false);
|
root = api_add_int(root, "Diff1 Shares", &(pool->diff1), false);
|
||||||
|
if (pool->rpc_proxy) {
|
||||||
|
root = api_add_const(root, "Proxy Type", proxytype(pool->rpc_proxytype), false);
|
||||||
|
root = api_add_escape(root, "Proxy", pool->rpc_proxy, false);
|
||||||
|
} else {
|
||||||
|
root = api_add_const(root, "Proxy Type", BLANK, false);
|
||||||
|
root = api_add_const(root, "Proxy", BLANK, false);
|
||||||
|
}
|
||||||
|
root = api_add_diff(root, "Difficulty Accepted", &(pool->diff_accepted), false);
|
||||||
|
root = api_add_diff(root, "Difficulty Rejected", &(pool->diff_rejected), false);
|
||||||
|
root = api_add_diff(root, "Difficulty Stale", &(pool->diff_stale), false);
|
||||||
|
root = api_add_diff(root, "Last Share Difficulty", &(pool->last_share_diff), false);
|
||||||
|
|
||||||
if (isjson && (i > 0))
|
if (isjson && (i > 0))
|
||||||
strcat(io_buffer, COMMA);
|
strcat(io_buffer, COMMA);
|
||||||
@ -1842,6 +1946,9 @@ static void summary(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, boo
|
|||||||
root = api_add_uint(root, "Network Blocks", &(new_blocks), false);
|
root = api_add_uint(root, "Network Blocks", &(new_blocks), false);
|
||||||
root = api_add_mhtotal(root, "Total MH", &(total_mhashes_done), false);
|
root = api_add_mhtotal(root, "Total MH", &(total_mhashes_done), false);
|
||||||
root = api_add_utility(root, "Work Utility", &(work_utility), false);
|
root = api_add_utility(root, "Work Utility", &(work_utility), false);
|
||||||
|
root = api_add_diff(root, "Difficulty Accepted", &(total_diff_accepted), false);
|
||||||
|
root = api_add_diff(root, "Difficulty Rejected", &(total_diff_rejected), false);
|
||||||
|
root = api_add_diff(root, "Difficulty Stale", &(total_diff_stale), false);
|
||||||
|
|
||||||
root = print_data(root, buf, isjson);
|
root = print_data(root, buf, isjson);
|
||||||
if (isjson)
|
if (isjson)
|
||||||
@ -2554,6 +2661,7 @@ void notifystatus(int device, struct cgpu_info *cgpu, bool isjson, __maybe_unuse
|
|||||||
root = api_add_int(root, "*Dev Over Heat", &(cgpu->dev_over_heat_count), false);
|
root = api_add_int(root, "*Dev Over Heat", &(cgpu->dev_over_heat_count), false);
|
||||||
root = api_add_int(root, "*Dev Thermal Cutoff", &(cgpu->dev_thermal_cutoff_count), false);
|
root = api_add_int(root, "*Dev Thermal Cutoff", &(cgpu->dev_thermal_cutoff_count), false);
|
||||||
root = api_add_int(root, "*Dev Comms Error", &(cgpu->dev_comms_error_count), false);
|
root = api_add_int(root, "*Dev Comms Error", &(cgpu->dev_comms_error_count), false);
|
||||||
|
root = api_add_int(root, "*Dev Throttle", &(cgpu->dev_throttle_count), false);
|
||||||
|
|
||||||
if (isjson && (device > 0))
|
if (isjson && (device > 0))
|
||||||
strcat(io_buffer, COMMA);
|
strcat(io_buffer, COMMA);
|
||||||
@ -2681,6 +2789,11 @@ static int itemstats(int i, char *id, struct cgminer_stats *stats, struct cgmine
|
|||||||
root = api_add_bool(root, "Work Can Roll", &(pool_stats->canroll), false);
|
root = api_add_bool(root, "Work Can Roll", &(pool_stats->canroll), false);
|
||||||
root = api_add_bool(root, "Work Had Expire", &(pool_stats->hadexpire), false);
|
root = api_add_bool(root, "Work Had Expire", &(pool_stats->hadexpire), false);
|
||||||
root = api_add_uint32(root, "Work Roll Time", &(pool_stats->rolltime), false);
|
root = api_add_uint32(root, "Work Roll Time", &(pool_stats->rolltime), false);
|
||||||
|
root = api_add_diff(root, "Work Diff", &(pool_stats->last_diff), false);
|
||||||
|
root = api_add_diff(root, "Min Diff", &(pool_stats->min_diff), false);
|
||||||
|
root = api_add_diff(root, "Max Diff", &(pool_stats->max_diff), false);
|
||||||
|
root = api_add_uint32(root, "Min Diff Count", &(pool_stats->min_diff_count), false);
|
||||||
|
root = api_add_uint32(root, "Max Diff Count", &(pool_stats->max_diff_count), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extra)
|
if (extra)
|
||||||
@ -2772,7 +2885,7 @@ static void minecoin(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bo
|
|||||||
#endif
|
#endif
|
||||||
root = api_add_const(root, "Hash Method", SHA256STR, false);
|
root = api_add_const(root, "Hash Method", SHA256STR, false);
|
||||||
|
|
||||||
mutex_lock(&ch_lock);
|
mutex_lock(&ch_lock);
|
||||||
if (current_fullhash && *current_fullhash) {
|
if (current_fullhash && *current_fullhash) {
|
||||||
root = api_add_timeval(root, "Current Block Time", &block_timeval, true);
|
root = api_add_timeval(root, "Current Block Time", &block_timeval, true);
|
||||||
root = api_add_string(root, "Current Block Hash", current_fullhash, true);
|
root = api_add_string(root, "Current Block Hash", current_fullhash, true);
|
||||||
@ -2781,7 +2894,7 @@ static void minecoin(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bo
|
|||||||
root = api_add_timeval(root, "Current Block Time", &t, true);
|
root = api_add_timeval(root, "Current Block Time", &t, true);
|
||||||
root = api_add_const(root, "Current Block Hash", BLANK, false);
|
root = api_add_const(root, "Current Block Hash", BLANK, false);
|
||||||
}
|
}
|
||||||
mutex_unlock(&ch_lock);
|
mutex_unlock(&ch_lock);
|
||||||
|
|
||||||
root = api_add_bool(root, "LP", &have_longpoll, false);
|
root = api_add_bool(root, "LP", &have_longpoll, false);
|
||||||
|
|
||||||
@ -2791,6 +2904,115 @@ static void minecoin(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bo
|
|||||||
strcat(io_buffer, buf);
|
strcat(io_buffer, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void debugstate(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||||
|
{
|
||||||
|
struct api_data *root = NULL;
|
||||||
|
char buf[TMPBUFSIZ];
|
||||||
|
|
||||||
|
if (param == NULL)
|
||||||
|
param = (char *)BLANK;
|
||||||
|
else
|
||||||
|
*param = tolower(*param);
|
||||||
|
|
||||||
|
switch(*param) {
|
||||||
|
case 's':
|
||||||
|
opt_realquiet = true;
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
opt_quiet ^= true;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
opt_log_output ^= true;
|
||||||
|
if (opt_log_output)
|
||||||
|
opt_quiet = false;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
opt_debug ^= true;
|
||||||
|
opt_log_output = opt_debug;
|
||||||
|
if (opt_debug)
|
||||||
|
opt_quiet = false;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
opt_protocol ^= true;
|
||||||
|
if (opt_protocol)
|
||||||
|
opt_quiet = false;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
want_per_device_stats ^= true;
|
||||||
|
opt_log_output = want_per_device_stats;
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
opt_log_output = false;
|
||||||
|
opt_debug = false;
|
||||||
|
opt_quiet = false;
|
||||||
|
opt_protocol = false;
|
||||||
|
want_per_device_stats = false;
|
||||||
|
opt_worktime = false;
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
opt_worktime ^= true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// anything else just reports the settings
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(io_buffer, isjson
|
||||||
|
? "%s," JSON_DEBUGSET
|
||||||
|
: "%s" _DEBUGSET ",",
|
||||||
|
message(MSG_DEBUGSET, 0, NULL, isjson));
|
||||||
|
|
||||||
|
root = api_add_bool(root, "Silent", &opt_realquiet, false);
|
||||||
|
root = api_add_bool(root, "Quiet", &opt_quiet, false);
|
||||||
|
root = api_add_bool(root, "Verbose", &opt_log_output, false);
|
||||||
|
root = api_add_bool(root, "Debug", &opt_debug, false);
|
||||||
|
root = api_add_bool(root, "RPCProto", &opt_protocol, false);
|
||||||
|
root = api_add_bool(root, "PerDevice", &want_per_device_stats, false);
|
||||||
|
root = api_add_bool(root, "WorkTime", &opt_worktime, false);
|
||||||
|
|
||||||
|
root = print_data(root, buf, isjson);
|
||||||
|
if (isjson)
|
||||||
|
strcat(buf, JSON_CLOSE);
|
||||||
|
strcat(io_buffer, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setconfig(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||||
|
{
|
||||||
|
char *comma;
|
||||||
|
int value;
|
||||||
|
|
||||||
|
if (param == NULL || *param == '\0') {
|
||||||
|
strcpy(io_buffer, message(MSG_CONPAR, 0, NULL, isjson));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
comma = strchr(param, ',');
|
||||||
|
if (!comma) {
|
||||||
|
strcpy(io_buffer, message(MSG_CONVAL, 0, param, isjson));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(comma++) = '\0';
|
||||||
|
value = atoi(comma);
|
||||||
|
if (value < 0 || value > 9999) {
|
||||||
|
strcpy(io_buffer, message(MSG_INVNUM, value, param, isjson));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcasecmp(param, "queue") == 0)
|
||||||
|
opt_queue = value;
|
||||||
|
else if (strcasecmp(param, "scantime") == 0)
|
||||||
|
opt_scantime = value;
|
||||||
|
else if (strcasecmp(param, "expiry") == 0)
|
||||||
|
opt_expiry = value;
|
||||||
|
else {
|
||||||
|
strcpy(io_buffer, message(MSG_UNKCON, 0, param, isjson));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(io_buffer, message(MSG_SETCONFIG, value, param, isjson));
|
||||||
|
}
|
||||||
|
|
||||||
static void checkcommand(__maybe_unused SOCKETTYPE c, char *param, bool isjson, char group);
|
static void checkcommand(__maybe_unused SOCKETTYPE c, char *param, bool isjson, char group);
|
||||||
|
|
||||||
struct CMDS {
|
struct CMDS {
|
||||||
@ -2813,6 +3035,7 @@ struct CMDS {
|
|||||||
{ "pga", pgadev, false },
|
{ "pga", pgadev, false },
|
||||||
{ "pgaenable", pgaenable, true },
|
{ "pgaenable", pgaenable, true },
|
||||||
{ "pgadisable", pgadisable, true },
|
{ "pgadisable", pgadisable, true },
|
||||||
|
{ "pgaidentify", pgaidentify, true },
|
||||||
#endif
|
#endif
|
||||||
#ifdef WANT_CPUMINE
|
#ifdef WANT_CPUMINE
|
||||||
{ "cpu", cpudev, false },
|
{ "cpu", cpudev, false },
|
||||||
@ -2843,6 +3066,8 @@ struct CMDS {
|
|||||||
{ "check", checkcommand, false },
|
{ "check", checkcommand, false },
|
||||||
{ "failover-only", failoveronly, true },
|
{ "failover-only", failoveronly, true },
|
||||||
{ "coin", minecoin, false },
|
{ "coin", minecoin, false },
|
||||||
|
{ "debug", debugstate, true },
|
||||||
|
{ "setconfig", setconfig, true },
|
||||||
{ NULL, NULL, false }
|
{ NULL, NULL, false }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
279
cgminer.c
279
cgminer.c
@ -86,14 +86,14 @@ static char packagename[255];
|
|||||||
bool opt_protocol;
|
bool opt_protocol;
|
||||||
static bool opt_benchmark;
|
static bool opt_benchmark;
|
||||||
bool have_longpoll;
|
bool have_longpoll;
|
||||||
static bool want_per_device_stats;
|
bool want_per_device_stats;
|
||||||
bool use_syslog;
|
bool use_syslog;
|
||||||
bool opt_quiet;
|
bool opt_quiet;
|
||||||
static bool opt_realquiet;
|
bool opt_realquiet;
|
||||||
bool opt_loginput;
|
bool opt_loginput;
|
||||||
const int opt_cutofftemp = 95;
|
const int opt_cutofftemp = 95;
|
||||||
int opt_log_interval = 5;
|
int opt_log_interval = 5;
|
||||||
static int opt_queue = 1;
|
int opt_queue = 1;
|
||||||
int opt_scantime = 60;
|
int opt_scantime = 60;
|
||||||
int opt_expiry = 120;
|
int opt_expiry = 120;
|
||||||
int opt_bench_algo = -1;
|
int opt_bench_algo = -1;
|
||||||
@ -142,6 +142,7 @@ bool opt_delaynet;
|
|||||||
bool opt_disable_pool = true;
|
bool opt_disable_pool = true;
|
||||||
char *opt_icarus_options = NULL;
|
char *opt_icarus_options = NULL;
|
||||||
char *opt_icarus_timing = NULL;
|
char *opt_icarus_timing = NULL;
|
||||||
|
bool opt_worktime;
|
||||||
|
|
||||||
char *opt_kernel_path;
|
char *opt_kernel_path;
|
||||||
char *cgminer_path;
|
char *cgminer_path;
|
||||||
@ -186,6 +187,7 @@ pthread_mutex_t control_lock;
|
|||||||
int hw_errors;
|
int hw_errors;
|
||||||
int total_accepted, total_rejected, total_diff1;
|
int total_accepted, total_rejected, total_diff1;
|
||||||
int total_getworks, total_stale, total_discarded;
|
int total_getworks, total_stale, total_discarded;
|
||||||
|
double total_diff_accepted, total_diff_rejected, total_diff_stale;
|
||||||
static int total_queued, staged_rollable;
|
static int total_queued, staged_rollable;
|
||||||
unsigned int new_blocks;
|
unsigned int new_blocks;
|
||||||
static unsigned int work_block;
|
static unsigned int work_block;
|
||||||
@ -226,6 +228,7 @@ static struct block *blocks = NULL;
|
|||||||
char *opt_socks_proxy = NULL;
|
char *opt_socks_proxy = NULL;
|
||||||
|
|
||||||
static const char def_conf[] = "cgminer.conf";
|
static const char def_conf[] = "cgminer.conf";
|
||||||
|
static char *default_config;
|
||||||
static bool config_loaded;
|
static bool config_loaded;
|
||||||
static int include_count;
|
static int include_count;
|
||||||
#define JSON_INCLUDE_CONF "include"
|
#define JSON_INCLUDE_CONF "include"
|
||||||
@ -357,7 +360,7 @@ static void sharelog(const char*disposition, const struct work*work)
|
|||||||
thr_id = work->thr_id;
|
thr_id = work->thr_id;
|
||||||
cgpu = thr_info[thr_id].cgpu;
|
cgpu = thr_info[thr_id].cgpu;
|
||||||
pool = work->pool;
|
pool = work->pool;
|
||||||
t = (unsigned long int)work->share_found_time;
|
t = (unsigned long int)(work->tv_work_found.tv_sec);
|
||||||
target = bin2hex(work->target, sizeof(work->target));
|
target = bin2hex(work->target, sizeof(work->target));
|
||||||
if (unlikely(!target)) {
|
if (unlikely(!target)) {
|
||||||
applog(LOG_ERR, "sharelog target OOM");
|
applog(LOG_ERR, "sharelog target OOM");
|
||||||
@ -419,6 +422,8 @@ static struct pool *add_pool(void)
|
|||||||
/* Make sure the pool doesn't think we've been idle since time 0 */
|
/* Make sure the pool doesn't think we've been idle since time 0 */
|
||||||
pool->tv_idle.tv_sec = ~0UL;
|
pool->tv_idle.tv_sec = ~0UL;
|
||||||
|
|
||||||
|
pool->rpc_proxy = NULL;
|
||||||
|
|
||||||
return pool;
|
return pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -547,6 +552,8 @@ static char *set_url(char *arg)
|
|||||||
add_pool();
|
add_pool();
|
||||||
pool = pools[total_urls - 1];
|
pool = pools[total_urls - 1];
|
||||||
|
|
||||||
|
arg = get_proxy(arg, pool);
|
||||||
|
|
||||||
opt_set_charp(arg, &pool->rpc_url);
|
opt_set_charp(arg, &pool->rpc_url);
|
||||||
if (strncmp(arg, "http://", 7) &&
|
if (strncmp(arg, "http://", 7) &&
|
||||||
strncmp(arg, "https://", 8)) {
|
strncmp(arg, "https://", 8)) {
|
||||||
@ -1058,6 +1065,9 @@ static struct opt_table opt_config_table[] = {
|
|||||||
OPT_WITH_ARG("--userpass|-O",
|
OPT_WITH_ARG("--userpass|-O",
|
||||||
set_userpass, NULL, NULL,
|
set_userpass, NULL, NULL,
|
||||||
"Username:Password pair for bitcoin JSON-RPC server"),
|
"Username:Password pair for bitcoin JSON-RPC server"),
|
||||||
|
OPT_WITHOUT_ARG("--worktime",
|
||||||
|
opt_set_bool, &opt_worktime,
|
||||||
|
"Display extra work time debug information"),
|
||||||
OPT_WITH_ARG("--pools",
|
OPT_WITH_ARG("--pools",
|
||||||
opt_set_bool, NULL, NULL, opt_hidden),
|
opt_set_bool, NULL, NULL, opt_hidden),
|
||||||
OPT_ENDTABLE
|
OPT_ENDTABLE
|
||||||
@ -1171,21 +1181,21 @@ static char *load_config(const char *arg, void __maybe_unused *unused)
|
|||||||
return parse_config(config, true);
|
return parse_config(config, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *set_default_config(const char *arg)
|
||||||
|
{
|
||||||
|
opt_set_charp(arg, &default_config);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void default_save_file(char *filename);
|
||||||
|
|
||||||
static void load_default_config(void)
|
static void load_default_config(void)
|
||||||
{
|
{
|
||||||
cnfbuf = malloc(PATH_MAX);
|
cnfbuf = malloc(PATH_MAX);
|
||||||
|
|
||||||
#if defined(unix)
|
default_save_file(cnfbuf);
|
||||||
if (getenv("HOME") && *getenv("HOME")) {
|
|
||||||
strcpy(cnfbuf, getenv("HOME"));
|
|
||||||
strcat(cnfbuf, "/");
|
|
||||||
} else
|
|
||||||
strcpy(cnfbuf, "");
|
|
||||||
strcat(cnfbuf, ".cgminer/");
|
|
||||||
#else
|
|
||||||
strcpy(cnfbuf, "");
|
|
||||||
#endif
|
|
||||||
strcat(cnfbuf, def_conf);
|
|
||||||
if (!access(cnfbuf, R_OK))
|
if (!access(cnfbuf, R_OK))
|
||||||
load_config(cnfbuf, NULL);
|
load_config(cnfbuf, NULL);
|
||||||
else {
|
else {
|
||||||
@ -1233,6 +1243,10 @@ static struct opt_table opt_cmdline_table[] = {
|
|||||||
load_config, NULL, NULL,
|
load_config, NULL, NULL,
|
||||||
"Load a JSON-format configuration file\n"
|
"Load a JSON-format configuration file\n"
|
||||||
"See example.conf for an example configuration."),
|
"See example.conf for an example configuration."),
|
||||||
|
OPT_WITH_ARG("--default-config",
|
||||||
|
set_default_config, NULL, NULL,
|
||||||
|
"Specify the filename of the default config file\n"
|
||||||
|
"Loaded at start and used when saving without a name."),
|
||||||
OPT_WITHOUT_ARG("--help|-h",
|
OPT_WITHOUT_ARG("--help|-h",
|
||||||
opt_verusage_and_exit, NULL,
|
opt_verusage_and_exit, NULL,
|
||||||
"Print this message"),
|
"Print this message"),
|
||||||
@ -1755,7 +1769,9 @@ static bool submit_upstream_work(const struct work *work, CURL *curl, bool resub
|
|||||||
struct pool *pool = work->pool;
|
struct pool *pool = work->pool;
|
||||||
int rolltime;
|
int rolltime;
|
||||||
uint32_t *hash32;
|
uint32_t *hash32;
|
||||||
|
struct timeval tv_submit, tv_submit_reply;
|
||||||
char hashshow[64+1] = "";
|
char hashshow[64+1] = "";
|
||||||
|
char worktime[200] = "";
|
||||||
|
|
||||||
#ifdef __BIG_ENDIAN__
|
#ifdef __BIG_ENDIAN__
|
||||||
int swapcounter = 0;
|
int swapcounter = 0;
|
||||||
@ -1780,8 +1796,10 @@ static bool submit_upstream_work(const struct work *work, CURL *curl, bool resub
|
|||||||
|
|
||||||
applog(LOG_DEBUG, "DBG: sending %s submit RPC call: %s", pool->rpc_url, sd);
|
applog(LOG_DEBUG, "DBG: sending %s submit RPC call: %s", pool->rpc_url, sd);
|
||||||
|
|
||||||
|
gettimeofday(&tv_submit, NULL);
|
||||||
/* issue JSON-RPC request */
|
/* issue JSON-RPC request */
|
||||||
val = json_rpc_call(curl, pool->rpc_url, pool->rpc_userpass, s, false, false, &rolltime, pool, true);
|
val = json_rpc_call(curl, pool->rpc_url, pool->rpc_userpass, s, false, false, &rolltime, pool, true);
|
||||||
|
gettimeofday(&tv_submit_reply, NULL);
|
||||||
if (unlikely(!val)) {
|
if (unlikely(!val)) {
|
||||||
applog(LOG_INFO, "submit_upstream_work json_rpc_call failed");
|
applog(LOG_INFO, "submit_upstream_work json_rpc_call failed");
|
||||||
if (!pool_tset(pool, &pool->submit_fail)) {
|
if (!pool_tset(pool, &pool->submit_fail)) {
|
||||||
@ -1800,9 +1818,52 @@ static bool submit_upstream_work(const struct work *work, CURL *curl, bool resub
|
|||||||
if (opt_scrypt)
|
if (opt_scrypt)
|
||||||
sprintf(hashshow, "%08lx.%08lx", (unsigned long)(hash32[7]), (unsigned long)(hash32[6]));
|
sprintf(hashshow, "%08lx.%08lx", (unsigned long)(hash32[7]), (unsigned long)(hash32[6]));
|
||||||
else {
|
else {
|
||||||
sprintf(hashshow, "%08lx.%08lx%s", (unsigned long)(hash32[6]), (unsigned long)(hash32[5]),
|
int intdiff = round(work->work_difficulty);
|
||||||
|
|
||||||
|
sprintf(hashshow, "%08lx Diff %d%s", (unsigned long)(hash32[6]), intdiff,
|
||||||
work->block? " BLOCK!" : "");
|
work->block? " BLOCK!" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opt_worktime) {
|
||||||
|
char workclone[20];
|
||||||
|
struct tm *tm, tm_getwork, tm_submit_reply;
|
||||||
|
double getwork_time = tdiff((struct timeval *)&(work->tv_getwork_reply),
|
||||||
|
(struct timeval *)&(work->tv_getwork));
|
||||||
|
double getwork_to_work = tdiff((struct timeval *)&(work->tv_work_start),
|
||||||
|
(struct timeval *)&(work->tv_getwork_reply));
|
||||||
|
double work_time = tdiff((struct timeval *)&(work->tv_work_found),
|
||||||
|
(struct timeval *)&(work->tv_work_start));
|
||||||
|
double work_to_submit = tdiff(&tv_submit,
|
||||||
|
(struct timeval *)&(work->tv_work_found));
|
||||||
|
double submit_time = tdiff(&tv_submit_reply, &tv_submit);
|
||||||
|
int diffplaces = 3;
|
||||||
|
|
||||||
|
tm = localtime(&(work->tv_getwork.tv_sec));
|
||||||
|
memcpy(&tm_getwork, tm, sizeof(struct tm));
|
||||||
|
tm = localtime(&(tv_submit_reply.tv_sec));
|
||||||
|
memcpy(&tm_submit_reply, tm, sizeof(struct tm));
|
||||||
|
|
||||||
|
if (work->clone) {
|
||||||
|
sprintf(workclone, "C:%1.3f",
|
||||||
|
tdiff((struct timeval *)&(work->tv_cloned),
|
||||||
|
(struct timeval *)&(work->tv_getwork_reply)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
strcpy(workclone, "O");
|
||||||
|
|
||||||
|
if (work->work_difficulty < 1)
|
||||||
|
diffplaces = 6;
|
||||||
|
|
||||||
|
sprintf(worktime, " <-%08lx.%08lx M:%c D:%1.*f G:%02d:%02d:%02d:%1.3f %s (%1.3f) W:%1.3f (%1.3f) S:%1.3f R:%02d:%02d:%02d",
|
||||||
|
(unsigned long)swab32(*(uint32_t *)&(work->data[opt_scrypt ? 32 : 28])),
|
||||||
|
(unsigned long)swab32(*(uint32_t *)&(work->data[opt_scrypt ? 28 : 24])),
|
||||||
|
work->getwork_mode, diffplaces, work->work_difficulty,
|
||||||
|
tm_getwork.tm_hour, tm_getwork.tm_min,
|
||||||
|
tm_getwork.tm_sec, getwork_time, workclone,
|
||||||
|
getwork_to_work, work_time, work_to_submit, submit_time,
|
||||||
|
tm_submit_reply.tm_hour, tm_submit_reply.tm_min,
|
||||||
|
tm_submit_reply.tm_sec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Theoretically threads could race when modifying accepted and
|
/* Theoretically threads could race when modifying accepted and
|
||||||
@ -1812,18 +1873,23 @@ static bool submit_upstream_work(const struct work *work, CURL *curl, bool resub
|
|||||||
cgpu->accepted++;
|
cgpu->accepted++;
|
||||||
total_accepted++;
|
total_accepted++;
|
||||||
pool->accepted++;
|
pool->accepted++;
|
||||||
|
cgpu->diff_accepted += work->work_difficulty;
|
||||||
|
total_diff_accepted += work->work_difficulty;
|
||||||
|
pool->diff_accepted += work->work_difficulty;
|
||||||
pool->seq_rejects = 0;
|
pool->seq_rejects = 0;
|
||||||
cgpu->last_share_pool = pool->pool_no;
|
cgpu->last_share_pool = pool->pool_no;
|
||||||
cgpu->last_share_pool_time = time(NULL);
|
cgpu->last_share_pool_time = time(NULL);
|
||||||
|
cgpu->last_share_diff = work->work_difficulty;
|
||||||
pool->last_share_time = cgpu->last_share_pool_time;
|
pool->last_share_time = cgpu->last_share_pool_time;
|
||||||
|
pool->last_share_diff = work->work_difficulty;
|
||||||
applog(LOG_DEBUG, "PROOF OF WORK RESULT: true (yay!!!)");
|
applog(LOG_DEBUG, "PROOF OF WORK RESULT: true (yay!!!)");
|
||||||
if (!QUIET) {
|
if (!QUIET) {
|
||||||
if (total_pools > 1)
|
if (total_pools > 1)
|
||||||
applog(LOG_NOTICE, "Accepted %s %s %d pool %d %s",
|
applog(LOG_NOTICE, "Accepted %s %s %d pool %d %s%s",
|
||||||
hashshow, cgpu->api->name, cgpu->device_id, work->pool->pool_no, resubmit ? "(resubmit)" : "");
|
hashshow, cgpu->api->name, cgpu->device_id, work->pool->pool_no, resubmit ? "(resubmit)" : "", worktime);
|
||||||
else
|
else
|
||||||
applog(LOG_NOTICE, "Accepted %s %s %d %s",
|
applog(LOG_NOTICE, "Accepted %s %s %d %s%s",
|
||||||
hashshow, cgpu->api->name, cgpu->device_id, resubmit ? "(resubmit)" : "");
|
hashshow, cgpu->api->name, cgpu->device_id, resubmit ? "(resubmit)" : "", worktime);
|
||||||
}
|
}
|
||||||
sharelog("accept", work);
|
sharelog("accept", work);
|
||||||
if (opt_shares && total_accepted >= opt_shares) {
|
if (opt_shares && total_accepted >= opt_shares) {
|
||||||
@ -1845,6 +1911,9 @@ static bool submit_upstream_work(const struct work *work, CURL *curl, bool resub
|
|||||||
cgpu->rejected++;
|
cgpu->rejected++;
|
||||||
total_rejected++;
|
total_rejected++;
|
||||||
pool->rejected++;
|
pool->rejected++;
|
||||||
|
cgpu->diff_rejected += work->work_difficulty;
|
||||||
|
total_diff_rejected += work->work_difficulty;
|
||||||
|
pool->diff_rejected += work->work_difficulty;
|
||||||
pool->seq_rejects++;
|
pool->seq_rejects++;
|
||||||
applog(LOG_DEBUG, "PROOF OF WORK RESULT: false (booooo)");
|
applog(LOG_DEBUG, "PROOF OF WORK RESULT: false (booooo)");
|
||||||
if (!QUIET) {
|
if (!QUIET) {
|
||||||
@ -1872,8 +1941,8 @@ static bool submit_upstream_work(const struct work *work, CURL *curl, bool resub
|
|||||||
} else
|
} else
|
||||||
strcpy(reason, "");
|
strcpy(reason, "");
|
||||||
|
|
||||||
applog(LOG_NOTICE, "Rejected %s %s %d %s%s %s",
|
applog(LOG_NOTICE, "Rejected %s %s %d %s%s %s%s",
|
||||||
hashshow, cgpu->api->name, cgpu->device_id, where, reason, resubmit ? "(resubmit)" : "");
|
hashshow, cgpu->api->name, cgpu->device_id, where, reason, resubmit ? "(resubmit)" : "", worktime);
|
||||||
sharelog(disposition, work);
|
sharelog(disposition, work);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1973,6 +2042,42 @@ static inline struct pool *select_pool(bool lagging)
|
|||||||
return pool;
|
return pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double DIFFEXACTONE = 26959946667150639794667015087019630673637144422540572481103610249216.0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate the work share difficulty
|
||||||
|
*/
|
||||||
|
static void calc_diff(struct work *work)
|
||||||
|
{
|
||||||
|
struct cgminer_pool_stats *pool_stats = &(work->pool->cgminer_pool_stats);
|
||||||
|
double targ;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
targ = 0;
|
||||||
|
for (i = 31; i >= 0; i--) {
|
||||||
|
targ *= 256;
|
||||||
|
targ += work->target[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
work->work_difficulty = DIFFEXACTONE / (targ ? : DIFFEXACTONE);
|
||||||
|
|
||||||
|
pool_stats->last_diff = work->work_difficulty;
|
||||||
|
|
||||||
|
if (work->work_difficulty == pool_stats->min_diff)
|
||||||
|
pool_stats->min_diff_count++;
|
||||||
|
else if (work->work_difficulty < pool_stats->min_diff || pool_stats->min_diff == 0) {
|
||||||
|
pool_stats->min_diff = work->work_difficulty;
|
||||||
|
pool_stats->min_diff_count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (work->work_difficulty == pool_stats->max_diff)
|
||||||
|
pool_stats->max_diff_count++;
|
||||||
|
else if (work->work_difficulty > pool_stats->max_diff) {
|
||||||
|
pool_stats->max_diff = work->work_difficulty;
|
||||||
|
pool_stats->max_diff_count = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void get_benchmark_work(struct work *work)
|
static void get_benchmark_work(struct work *work)
|
||||||
{
|
{
|
||||||
// Use a random work block pulled from a pool
|
// Use a random work block pulled from a pool
|
||||||
@ -1985,13 +2090,17 @@ static void get_benchmark_work(struct work *work)
|
|||||||
memcpy(work, &bench_block, min_size);
|
memcpy(work, &bench_block, min_size);
|
||||||
work->mandatory = true;
|
work->mandatory = true;
|
||||||
work->pool = pools[0];
|
work->pool = pools[0];
|
||||||
|
gettimeofday(&(work->tv_getwork), NULL);
|
||||||
|
memcpy(&(work->tv_getwork_reply), &(work->tv_getwork), sizeof(struct timeval));
|
||||||
|
work->getwork_mode = GETWORK_MODE_BENCHMARK;
|
||||||
|
calc_diff(work);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool get_upstream_work(struct work *work, CURL *curl)
|
static bool get_upstream_work(struct work *work, CURL *curl)
|
||||||
{
|
{
|
||||||
struct pool *pool = work->pool;
|
struct pool *pool = work->pool;
|
||||||
struct cgminer_pool_stats *pool_stats = &(pool->cgminer_pool_stats);
|
struct cgminer_pool_stats *pool_stats = &(pool->cgminer_pool_stats);
|
||||||
struct timeval tv_start, tv_end, tv_elapsed;
|
struct timeval tv_elapsed;
|
||||||
json_t *val = NULL;
|
json_t *val = NULL;
|
||||||
bool rc = false;
|
bool rc = false;
|
||||||
char *url;
|
char *url;
|
||||||
@ -2000,7 +2109,7 @@ static bool get_upstream_work(struct work *work, CURL *curl)
|
|||||||
|
|
||||||
url = pool->rpc_url;
|
url = pool->rpc_url;
|
||||||
|
|
||||||
gettimeofday(&tv_start, NULL);
|
gettimeofday(&(work->tv_getwork), NULL);
|
||||||
|
|
||||||
val = json_rpc_call(curl, url, pool->rpc_userpass, rpc_req, false,
|
val = json_rpc_call(curl, url, pool->rpc_userpass, rpc_req, false,
|
||||||
false, &work->rolltime, pool, false);
|
false, &work->rolltime, pool, false);
|
||||||
@ -2013,8 +2122,8 @@ static bool get_upstream_work(struct work *work, CURL *curl)
|
|||||||
} else
|
} else
|
||||||
applog(LOG_DEBUG, "Failed json_rpc_call in get_upstream_work");
|
applog(LOG_DEBUG, "Failed json_rpc_call in get_upstream_work");
|
||||||
|
|
||||||
gettimeofday(&tv_end, NULL);
|
gettimeofday(&(work->tv_getwork_reply), NULL);
|
||||||
timersub(&tv_end, &tv_start, &tv_elapsed);
|
timersub(&(work->tv_getwork_reply), &(work->tv_getwork), &tv_elapsed);
|
||||||
pool_stats->getwork_wait_rolling += ((double)tv_elapsed.tv_sec + ((double)tv_elapsed.tv_usec / 1000000)) * 0.63;
|
pool_stats->getwork_wait_rolling += ((double)tv_elapsed.tv_sec + ((double)tv_elapsed.tv_usec / 1000000)) * 0.63;
|
||||||
pool_stats->getwork_wait_rolling /= 1.63;
|
pool_stats->getwork_wait_rolling /= 1.63;
|
||||||
|
|
||||||
@ -2031,6 +2140,8 @@ static bool get_upstream_work(struct work *work, CURL *curl)
|
|||||||
|
|
||||||
work->pool = pool;
|
work->pool = pool;
|
||||||
work->longpoll = false;
|
work->longpoll = false;
|
||||||
|
work->getwork_mode = GETWORK_MODE_POOL;
|
||||||
|
calc_diff(work);
|
||||||
total_getworks++;
|
total_getworks++;
|
||||||
pool->getwork_requested++;
|
pool->getwork_requested++;
|
||||||
|
|
||||||
@ -2339,6 +2450,7 @@ static struct work *make_clone(struct work *work)
|
|||||||
|
|
||||||
memcpy(work_clone, work, sizeof(struct work));
|
memcpy(work_clone, work, sizeof(struct work));
|
||||||
work_clone->clone = true;
|
work_clone->clone = true;
|
||||||
|
gettimeofday((struct timeval *)&(work_clone->tv_cloned), NULL);
|
||||||
work_clone->longpoll = false;
|
work_clone->longpoll = false;
|
||||||
work_clone->mandatory = false;
|
work_clone->mandatory = false;
|
||||||
/* Make cloned work appear slightly older to bias towards keeping the
|
/* Make cloned work appear slightly older to bias towards keeping the
|
||||||
@ -2383,6 +2495,15 @@ out:
|
|||||||
|
|
||||||
static bool queue_request(void);
|
static bool queue_request(void);
|
||||||
|
|
||||||
|
static void pool_died(struct pool *pool)
|
||||||
|
{
|
||||||
|
if (!pool_tset(pool, &pool->idle)) {
|
||||||
|
applog(LOG_WARNING, "Pool %d %s not responding!", pool->pool_no, pool->rpc_url);
|
||||||
|
gettimeofday(&pool->tv_idle, NULL);
|
||||||
|
switch_pools(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void *get_work_thread(void *userdata)
|
static void *get_work_thread(void *userdata)
|
||||||
{
|
{
|
||||||
struct workio_cmd *wc = (struct workio_cmd *)userdata;
|
struct workio_cmd *wc = (struct workio_cmd *)userdata;
|
||||||
@ -2415,13 +2536,17 @@ static void *get_work_thread(void *userdata)
|
|||||||
|
|
||||||
/* obtain new work from bitcoin via JSON-RPC */
|
/* obtain new work from bitcoin via JSON-RPC */
|
||||||
if (!get_upstream_work(ret_work, ce->curl)) {
|
if (!get_upstream_work(ret_work, ce->curl)) {
|
||||||
/* pause, then restart work-request loop */
|
|
||||||
applog(LOG_DEBUG, "json_rpc_call failed on get work, retrying");
|
applog(LOG_DEBUG, "json_rpc_call failed on get work, retrying");
|
||||||
dec_queued(pool);
|
dec_queued(pool);
|
||||||
|
/* Make sure the pool just hasn't stopped serving
|
||||||
|
* requests but is up as we'll keep hammering it */
|
||||||
|
if (++pool->seq_getfails > mining_threads + opt_queue)
|
||||||
|
pool_died(pool);
|
||||||
queue_request();
|
queue_request();
|
||||||
free_work(ret_work);
|
free_work(ret_work);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
pool->seq_getfails = 0;
|
||||||
|
|
||||||
ret_work->queued = true;
|
ret_work->queued = true;
|
||||||
}
|
}
|
||||||
@ -2537,6 +2662,8 @@ static void *submit_work_thread(void *userdata)
|
|||||||
sharelog("discard", work);
|
sharelog("discard", work);
|
||||||
total_stale++;
|
total_stale++;
|
||||||
pool->stale_shares++;
|
pool->stale_shares++;
|
||||||
|
total_diff_stale += work->work_difficulty;
|
||||||
|
pool->diff_stale += work->work_difficulty;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
work->stale = true;
|
work->stale = true;
|
||||||
@ -2550,6 +2677,8 @@ static void *submit_work_thread(void *userdata)
|
|||||||
applog(LOG_NOTICE, "Share became stale while retrying submit, discarding");
|
applog(LOG_NOTICE, "Share became stale while retrying submit, discarding");
|
||||||
total_stale++;
|
total_stale++;
|
||||||
pool->stale_shares++;
|
pool->stale_shares++;
|
||||||
|
total_diff_stale += work->work_difficulty;
|
||||||
|
pool->diff_stale += work->work_difficulty;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2996,6 +3125,8 @@ static void display_pool_summary(struct pool *pool)
|
|||||||
wlog(" Share submissions: %d\n", pool->accepted + pool->rejected);
|
wlog(" Share submissions: %d\n", pool->accepted + pool->rejected);
|
||||||
wlog(" Accepted shares: %d\n", pool->accepted);
|
wlog(" Accepted shares: %d\n", pool->accepted);
|
||||||
wlog(" Rejected shares: %d\n", pool->rejected);
|
wlog(" Rejected shares: %d\n", pool->rejected);
|
||||||
|
wlog(" Accepted difficulty shares: %1.f\n", pool->diff_accepted);
|
||||||
|
wlog(" Rejected difficulty shares: %1.f\n", pool->diff_rejected);
|
||||||
if (pool->accepted || pool->rejected)
|
if (pool->accepted || pool->rejected)
|
||||||
wlog(" Reject ratio: %.1f%%\n", (double)(pool->rejected * 100) / (double)(pool->accepted + pool->rejected));
|
wlog(" Reject ratio: %.1f%%\n", (double)(pool->rejected * 100) / (double)(pool->accepted + pool->rejected));
|
||||||
efficiency = pool->getwork_requested ? pool->accepted * 100.0 / pool->getwork_requested : 0.0;
|
efficiency = pool->getwork_requested ? pool->accepted * 100.0 / pool->getwork_requested : 0.0;
|
||||||
@ -3089,7 +3220,11 @@ void write_config(FILE *fcfg)
|
|||||||
/* Write pool values */
|
/* Write pool values */
|
||||||
fputs("{\n\"pools\" : [", fcfg);
|
fputs("{\n\"pools\" : [", fcfg);
|
||||||
for(i = 0; i < total_pools; i++) {
|
for(i = 0; i < total_pools; i++) {
|
||||||
fprintf(fcfg, "%s\n\t{\n\t\t\"url\" : \"%s\",", i > 0 ? "," : "", json_escape(pools[i]->rpc_url));
|
fprintf(fcfg, "%s\n\t{\n\t\t\"url\" : \"%s%s%s%s\",", i > 0 ? "," : "",
|
||||||
|
pools[i]->rpc_proxy ? json_escape((char *)proxytype(pools[i]->rpc_proxytype)) : "",
|
||||||
|
pools[i]->rpc_proxy ? json_escape(pools[i]->rpc_proxy) : "",
|
||||||
|
pools[i]->rpc_proxy ? "|" : "",
|
||||||
|
json_escape(pools[i]->rpc_url));
|
||||||
fprintf(fcfg, "\n\t\t\"user\" : \"%s\",", json_escape(pools[i]->rpc_user));
|
fprintf(fcfg, "\n\t\t\"user\" : \"%s\",", json_escape(pools[i]->rpc_user));
|
||||||
fprintf(fcfg, "\n\t\t\"pass\" : \"%s\"\n\t}", json_escape(pools[i]->rpc_pass));
|
fprintf(fcfg, "\n\t\t\"pass\" : \"%s\"\n\t}", json_escape(pools[i]->rpc_pass));
|
||||||
}
|
}
|
||||||
@ -3412,12 +3547,13 @@ static void display_options(void)
|
|||||||
clear_logwin();
|
clear_logwin();
|
||||||
retry:
|
retry:
|
||||||
wlogprint("[N]ormal [C]lear [S]ilent mode (disable all output)\n");
|
wlogprint("[N]ormal [C]lear [S]ilent mode (disable all output)\n");
|
||||||
wlogprint("[D]ebug:%s\n[P]er-device:%s\n[Q]uiet:%s\n[V]erbose:%s\n[R]PC debug:%s\n[L]og interval:%d\n",
|
wlogprint("[D]ebug:%s\n[P]er-device:%s\n[Q]uiet:%s\n[V]erbose:%s\n[R]PC debug:%s\n[W]orkTime details:%s\n[L]og interval:%d\n",
|
||||||
opt_debug ? "on" : "off",
|
opt_debug ? "on" : "off",
|
||||||
want_per_device_stats? "on" : "off",
|
want_per_device_stats? "on" : "off",
|
||||||
opt_quiet ? "on" : "off",
|
opt_quiet ? "on" : "off",
|
||||||
opt_log_output ? "on" : "off",
|
opt_log_output ? "on" : "off",
|
||||||
opt_protocol ? "on" : "off",
|
opt_protocol ? "on" : "off",
|
||||||
|
opt_worktime ? "on" : "off",
|
||||||
opt_log_interval);
|
opt_log_interval);
|
||||||
wlogprint("Select an option or any other key to return\n");
|
wlogprint("Select an option or any other key to return\n");
|
||||||
input = getch();
|
input = getch();
|
||||||
@ -3470,6 +3606,10 @@ retry:
|
|||||||
goto retry;
|
goto retry;
|
||||||
} else if (!strncasecmp(&input, "s", 1)) {
|
} else if (!strncasecmp(&input, "s", 1)) {
|
||||||
opt_realquiet = true;
|
opt_realquiet = true;
|
||||||
|
} else if (!strncasecmp(&input, "w", 1)) {
|
||||||
|
opt_worktime ^= true;
|
||||||
|
wlogprint("WorkTime details %s\n", opt_worktime ? "enabled" : "disabled");
|
||||||
|
goto retry;
|
||||||
} else
|
} else
|
||||||
clear_logwin();
|
clear_logwin();
|
||||||
|
|
||||||
@ -3480,6 +3620,11 @@ retry:
|
|||||||
|
|
||||||
void default_save_file(char *filename)
|
void default_save_file(char *filename)
|
||||||
{
|
{
|
||||||
|
if (default_config && *default_config) {
|
||||||
|
strcpy(filename, default_config);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(unix)
|
#if defined(unix)
|
||||||
if (getenv("HOME") && *getenv("HOME")) {
|
if (getenv("HOME") && *getenv("HOME")) {
|
||||||
strcpy(filename, getenv("HOME"));
|
strcpy(filename, getenv("HOME"));
|
||||||
@ -3794,6 +3939,7 @@ static void *longpoll_thread(void *userdata);
|
|||||||
|
|
||||||
static bool pool_active(struct pool *pool, bool pinging)
|
static bool pool_active(struct pool *pool, bool pinging)
|
||||||
{
|
{
|
||||||
|
struct timeval tv_getwork, tv_getwork_reply;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
json_t *val;
|
json_t *val;
|
||||||
CURL *curl;
|
CURL *curl;
|
||||||
@ -3806,8 +3952,10 @@ static bool pool_active(struct pool *pool, bool pinging)
|
|||||||
}
|
}
|
||||||
|
|
||||||
applog(LOG_INFO, "Testing pool %s", pool->rpc_url);
|
applog(LOG_INFO, "Testing pool %s", pool->rpc_url);
|
||||||
|
gettimeofday(&tv_getwork, NULL);
|
||||||
val = json_rpc_call(curl, pool->rpc_url, pool->rpc_userpass, rpc_req,
|
val = json_rpc_call(curl, pool->rpc_url, pool->rpc_userpass, rpc_req,
|
||||||
true, false, &rolltime, pool, false);
|
true, false, &rolltime, pool, false);
|
||||||
|
gettimeofday(&tv_getwork_reply, NULL);
|
||||||
|
|
||||||
if (val) {
|
if (val) {
|
||||||
struct work *work = make_work();
|
struct work *work = make_work();
|
||||||
@ -3819,6 +3967,10 @@ static bool pool_active(struct pool *pool, bool pinging)
|
|||||||
pool->pool_no, pool->rpc_url);
|
pool->pool_no, pool->rpc_url);
|
||||||
work->pool = pool;
|
work->pool = pool;
|
||||||
work->rolltime = rolltime;
|
work->rolltime = rolltime;
|
||||||
|
memcpy(&(work->tv_getwork), &tv_getwork, sizeof(struct timeval));
|
||||||
|
memcpy(&(work->tv_getwork_reply), &tv_getwork_reply, sizeof(struct timeval));
|
||||||
|
work->getwork_mode = GETWORK_MODE_TESTPOOL;
|
||||||
|
calc_diff(work);
|
||||||
applog(LOG_DEBUG, "Pushing pooltest work to base pool");
|
applog(LOG_DEBUG, "Pushing pooltest work to base pool");
|
||||||
|
|
||||||
tq_push(thr_info[stage_thr_id].q, work);
|
tq_push(thr_info[stage_thr_id].q, work);
|
||||||
@ -3878,15 +4030,6 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pool_died(struct pool *pool)
|
|
||||||
{
|
|
||||||
if (!pool_tset(pool, &pool->idle)) {
|
|
||||||
applog(LOG_WARNING, "Pool %d %s not responding!", pool->pool_no, pool->rpc_url);
|
|
||||||
gettimeofday(&pool->tv_idle, NULL);
|
|
||||||
switch_pools(NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int cp_prio(void)
|
static inline int cp_prio(void)
|
||||||
{
|
{
|
||||||
int prio;
|
int prio;
|
||||||
@ -4110,7 +4253,7 @@ out:
|
|||||||
work->mined = true;
|
work->mined = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool submit_work_sync(struct thr_info *thr, const struct work *work_in)
|
bool submit_work_sync(struct thr_info *thr, const struct work *work_in, struct timeval *tv_work_found)
|
||||||
{
|
{
|
||||||
struct workio_cmd *wc;
|
struct workio_cmd *wc;
|
||||||
|
|
||||||
@ -4125,7 +4268,8 @@ bool submit_work_sync(struct thr_info *thr, const struct work *work_in)
|
|||||||
wc->cmd = WC_SUBMIT_WORK;
|
wc->cmd = WC_SUBMIT_WORK;
|
||||||
wc->thr = thr;
|
wc->thr = thr;
|
||||||
memcpy(wc->work, work_in, sizeof(*work_in));
|
memcpy(wc->work, work_in, sizeof(*work_in));
|
||||||
wc->work->share_found_time = time(NULL);
|
if (tv_work_found)
|
||||||
|
memcpy(&(wc->work->tv_work_found), tv_work_found, sizeof(struct timeval));
|
||||||
|
|
||||||
applog(LOG_DEBUG, "Pushing submit work to work thread");
|
applog(LOG_DEBUG, "Pushing submit work to work thread");
|
||||||
|
|
||||||
@ -4141,7 +4285,7 @@ err_out:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hashtest(const struct work *work)
|
static bool hashtest(struct thr_info *thr, const struct work *work)
|
||||||
{
|
{
|
||||||
uint32_t *data32 = (uint32_t *)(work->data);
|
uint32_t *data32 = (uint32_t *)(work->data);
|
||||||
unsigned char swap[128];
|
unsigned char swap[128];
|
||||||
@ -4162,11 +4306,22 @@ bool hashtest(const struct work *work)
|
|||||||
|
|
||||||
memcpy((void*)work->hash, hash2, 32);
|
memcpy((void*)work->hash, hash2, 32);
|
||||||
|
|
||||||
return fulltest(work->hash, work->target);
|
if (hash2_32[7] != 0) {
|
||||||
|
applog(LOG_WARNING, "%s%d: invalid nonce - HW error",
|
||||||
|
thr->cgpu->api->name, thr->cgpu->device_id);
|
||||||
|
hw_errors++;
|
||||||
|
thr->cgpu->hw_errors++;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test = fulltest(work->hash, work->target);
|
||||||
|
if (!test)
|
||||||
|
applog(LOG_INFO, "Share below target");
|
||||||
|
|
||||||
|
return test;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool test_nonce(struct work *work, uint32_t nonce)
|
static bool test_nonce(struct thr_info *thr, struct work *work, uint32_t nonce)
|
||||||
{
|
{
|
||||||
if (opt_scrypt) {
|
if (opt_scrypt) {
|
||||||
uint32_t *work_nonce = (uint32_t *)(work->data + 64 + 12);
|
uint32_t *work_nonce = (uint32_t *)(work->data + 64 + 12);
|
||||||
@ -4180,21 +4335,24 @@ bool test_nonce(struct work *work, uint32_t nonce)
|
|||||||
work->data[64 + 12 + 2] = (nonce >> 16) & 0xff;
|
work->data[64 + 12 + 2] = (nonce >> 16) & 0xff;
|
||||||
work->data[64 + 12 + 3] = (nonce >> 24) & 0xff;
|
work->data[64 + 12 + 3] = (nonce >> 24) & 0xff;
|
||||||
|
|
||||||
return hashtest(work);
|
return hashtest(thr, work);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce)
|
bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce)
|
||||||
{
|
{
|
||||||
|
struct timeval tv_work_found;
|
||||||
|
gettimeofday(&tv_work_found, NULL);
|
||||||
|
|
||||||
total_diff1++;
|
total_diff1++;
|
||||||
|
thr->cgpu->diff1++;
|
||||||
work->pool->diff1++;
|
work->pool->diff1++;
|
||||||
|
|
||||||
/* Do one last check before attempting to submit the work */
|
/* Do one last check before attempting to submit the work */
|
||||||
/* Side effect: sets work->data for us */
|
/* Side effect: sets work->data for us */
|
||||||
if (!test_nonce(work, nonce)) {
|
if (!test_nonce(thr, work, nonce))
|
||||||
applog(LOG_INFO, "Share below target");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
return submit_work_sync(thr, work);
|
return submit_work_sync(thr, work, &tv_work_found);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool abandon_work(struct work *work, struct timeval *wdiff, uint64_t hashes)
|
static inline bool abandon_work(struct work *work, struct timeval *wdiff, uint64_t hashes)
|
||||||
@ -4214,7 +4372,9 @@ static void mt_disable(struct thr_info *mythr, const int thr_id,
|
|||||||
mythr->rolling = mythr->cgpu->rolling = 0;
|
mythr->rolling = mythr->cgpu->rolling = 0;
|
||||||
applog(LOG_DEBUG, "Popping wakeup ping in miner thread");
|
applog(LOG_DEBUG, "Popping wakeup ping in miner thread");
|
||||||
thread_reportout(mythr);
|
thread_reportout(mythr);
|
||||||
tq_pop(mythr->q, NULL); /* Ignore ping that's popped */
|
do {
|
||||||
|
tq_pop(mythr->q, NULL); /* Ignore ping that's popped */
|
||||||
|
} while (mythr->pause);
|
||||||
thread_reportin(mythr);
|
thread_reportin(mythr);
|
||||||
applog(LOG_WARNING, "Thread %d being re-enabled", thr_id);
|
applog(LOG_WARNING, "Thread %d being re-enabled", thr_id);
|
||||||
if (api->thread_enable)
|
if (api->thread_enable)
|
||||||
@ -4309,6 +4469,8 @@ void *miner_thread(void *userdata)
|
|||||||
}
|
}
|
||||||
pool_stats->getwork_calls++;
|
pool_stats->getwork_calls++;
|
||||||
|
|
||||||
|
gettimeofday(&(work->tv_work_start), NULL);
|
||||||
|
|
||||||
thread_reportin(mythr);
|
thread_reportin(mythr);
|
||||||
hashes = api->scanhash(mythr, work, work->blk.nonce + max_nonce);
|
hashes = api->scanhash(mythr, work, work->blk.nonce + max_nonce);
|
||||||
thread_reportin(mythr);
|
thread_reportin(mythr);
|
||||||
@ -4405,7 +4567,7 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Stage another work item from the work returned in a longpoll */
|
/* Stage another work item from the work returned in a longpoll */
|
||||||
static void convert_to_work(json_t *val, int rolltime, struct pool *pool)
|
static void convert_to_work(json_t *val, int rolltime, struct pool *pool, struct timeval *tv_lp, struct timeval *tv_lp_reply)
|
||||||
{
|
{
|
||||||
struct work *work;
|
struct work *work;
|
||||||
bool rc;
|
bool rc;
|
||||||
@ -4421,6 +4583,10 @@ static void convert_to_work(json_t *val, int rolltime, struct pool *pool)
|
|||||||
work->pool = pool;
|
work->pool = pool;
|
||||||
work->rolltime = rolltime;
|
work->rolltime = rolltime;
|
||||||
work->longpoll = true;
|
work->longpoll = true;
|
||||||
|
memcpy(&(work->tv_getwork), tv_lp, sizeof(struct timeval));
|
||||||
|
memcpy(&(work->tv_getwork_reply), tv_lp_reply, sizeof(struct timeval));
|
||||||
|
work->getwork_mode = GETWORK_MODE_LP;
|
||||||
|
calc_diff(work);
|
||||||
|
|
||||||
if (pool->enabled == POOL_REJECTING)
|
if (pool->enabled == POOL_REJECTING)
|
||||||
work->mandatory = true;
|
work->mandatory = true;
|
||||||
@ -4489,7 +4655,7 @@ static void *longpoll_thread(void *userdata)
|
|||||||
/* This *pool is the source of the actual longpoll, not the pool we've
|
/* This *pool is the source of the actual longpoll, not the pool we've
|
||||||
* tied it to */
|
* tied it to */
|
||||||
struct pool *pool = NULL;
|
struct pool *pool = NULL;
|
||||||
struct timeval start, end;
|
struct timeval start, reply, end;
|
||||||
CURL *curl = NULL;
|
CURL *curl = NULL;
|
||||||
int failures = 0;
|
int failures = 0;
|
||||||
int rolltime;
|
int rolltime;
|
||||||
@ -4534,13 +4700,16 @@ retry_pool:
|
|||||||
curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1);
|
curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1);
|
||||||
val = json_rpc_call(curl, pool->lp_url, pool->rpc_userpass, rpc_req,
|
val = json_rpc_call(curl, pool->lp_url, pool->rpc_userpass, rpc_req,
|
||||||
false, true, &rolltime, pool, false);
|
false, true, &rolltime, pool, false);
|
||||||
|
|
||||||
|
gettimeofday(&reply, NULL);
|
||||||
|
|
||||||
if (likely(val)) {
|
if (likely(val)) {
|
||||||
soval = json_object_get(json_object_get(val, "result"), "submitold");
|
soval = json_object_get(json_object_get(val, "result"), "submitold");
|
||||||
if (soval)
|
if (soval)
|
||||||
pool->submit_old = json_is_true(soval);
|
pool->submit_old = json_is_true(soval);
|
||||||
else
|
else
|
||||||
pool->submit_old = false;
|
pool->submit_old = false;
|
||||||
convert_to_work(val, rolltime, pool);
|
convert_to_work(val, rolltime, pool, &start, &reply);
|
||||||
failures = 0;
|
failures = 0;
|
||||||
json_decref(val);
|
json_decref(val);
|
||||||
} else {
|
} else {
|
||||||
@ -4867,6 +5036,8 @@ static void print_summary(void)
|
|||||||
applog(LOG_WARNING, "Share submissions: %d", total_accepted + total_rejected);
|
applog(LOG_WARNING, "Share submissions: %d", total_accepted + total_rejected);
|
||||||
applog(LOG_WARNING, "Accepted shares: %d", total_accepted);
|
applog(LOG_WARNING, "Accepted shares: %d", total_accepted);
|
||||||
applog(LOG_WARNING, "Rejected shares: %d", total_rejected);
|
applog(LOG_WARNING, "Rejected shares: %d", total_rejected);
|
||||||
|
applog(LOG_WARNING, "Accepted difficulty shares: %1.f", total_diff_accepted);
|
||||||
|
applog(LOG_WARNING, "Rejected difficulty shares: %1.f", total_diff_rejected);
|
||||||
if (total_accepted || total_rejected)
|
if (total_accepted || total_rejected)
|
||||||
applog(LOG_WARNING, "Reject ratio: %.1f%%", (double)(total_rejected * 100) / (double)(total_accepted + total_rejected));
|
applog(LOG_WARNING, "Reject ratio: %.1f%%", (double)(total_rejected * 100) / (double)(total_accepted + total_rejected));
|
||||||
applog(LOG_WARNING, "Hardware errors: %d", hw_errors);
|
applog(LOG_WARNING, "Hardware errors: %d", hw_errors);
|
||||||
@ -4892,6 +5063,8 @@ static void print_summary(void)
|
|||||||
applog(LOG_WARNING, " Share submissions: %d", pool->accepted + pool->rejected);
|
applog(LOG_WARNING, " Share submissions: %d", pool->accepted + pool->rejected);
|
||||||
applog(LOG_WARNING, " Accepted shares: %d", pool->accepted);
|
applog(LOG_WARNING, " Accepted shares: %d", pool->accepted);
|
||||||
applog(LOG_WARNING, " Rejected shares: %d", pool->rejected);
|
applog(LOG_WARNING, " Rejected shares: %d", pool->rejected);
|
||||||
|
applog(LOG_WARNING, " Accepted difficulty shares: %1.f", pool->diff_accepted);
|
||||||
|
applog(LOG_WARNING, " Rejected difficulty shares: %1.f", pool->diff_rejected);
|
||||||
if (pool->accepted || pool->rejected)
|
if (pool->accepted || pool->rejected)
|
||||||
applog(LOG_WARNING, " Reject ratio: %.1f%%", (double)(pool->rejected * 100) / (double)(pool->accepted + pool->rejected));
|
applog(LOG_WARNING, " Reject ratio: %.1f%%", (double)(pool->rejected * 100) / (double)(pool->accepted + pool->rejected));
|
||||||
efficiency = pool->getwork_requested ? pool->accepted * 100.0 / pool->getwork_requested : 0.0;
|
efficiency = pool->getwork_requested ? pool->accepted * 100.0 / pool->getwork_requested : 0.0;
|
||||||
@ -4988,6 +5161,8 @@ void add_pool_details(bool live, char *url, char *user, char *pass)
|
|||||||
|
|
||||||
pool = add_pool();
|
pool = add_pool();
|
||||||
|
|
||||||
|
url = get_proxy(url, pool);
|
||||||
|
|
||||||
pool->rpc_url = url;
|
pool->rpc_url = url;
|
||||||
pool->rpc_user = user;
|
pool->rpc_user = user;
|
||||||
pool->rpc_pass = pass;
|
pool->rpc_pass = pass;
|
||||||
|
2
compat.h
2
compat.h
@ -57,7 +57,7 @@ enum {
|
|||||||
PRIO_PROCESS = 0,
|
PRIO_PROCESS = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int setpriority(int which, int who, int prio)
|
static inline int setpriority(__maybe_unused int which, __maybe_unused int who, __maybe_unused int prio)
|
||||||
{
|
{
|
||||||
/* FIXME - actually do something */
|
/* FIXME - actually do something */
|
||||||
return 0;
|
return 0;
|
||||||
|
18
configure.ac
18
configure.ac
@ -2,7 +2,7 @@
|
|||||||
##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
|
##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
|
||||||
m4_define([v_maj], [2])
|
m4_define([v_maj], [2])
|
||||||
m4_define([v_min], [7])
|
m4_define([v_min], [7])
|
||||||
m4_define([v_mic], [5])
|
m4_define([v_mic], [6])
|
||||||
##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
|
##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
|
||||||
m4_define([v_ver], [v_maj.v_min.v_mic])
|
m4_define([v_ver], [v_maj.v_min.v_mic])
|
||||||
m4_define([lt_rev], m4_eval(v_maj + v_min))
|
m4_define([lt_rev], m4_eval(v_maj + v_min))
|
||||||
@ -104,14 +104,18 @@ case $target in
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
if test "x$have_x86_64" = xtrue; then
|
||||||
|
ARCH_DIR=x86_64
|
||||||
|
else
|
||||||
|
ARCH_DIR=x86
|
||||||
|
fi
|
||||||
|
|
||||||
if test "x$ATISTREAMSDKROOT" != x; then
|
if test "x$ATISTREAMSDKROOT" != x; then
|
||||||
if test "x$have_x86_64" = xtrue; then
|
|
||||||
ATI_STREAM_ARCH_DIR=x86_64
|
|
||||||
else
|
|
||||||
ATI_STREAM_ARCH_DIR=x86
|
|
||||||
fi
|
|
||||||
OPENCL_FLAGS="-I$ATISTREAMSDKROOT/include $OPENCL_FLAGS"
|
OPENCL_FLAGS="-I$ATISTREAMSDKROOT/include $OPENCL_FLAGS"
|
||||||
OPENCL_LIBS="-L$ATISTREAMSDKROOT/lib/$ATI_STREAM_ARCH_DIR $OPENCL_LIBS"
|
OPENCL_LIBS="-L$ATISTREAMSDKROOT/lib/$ARCH_DIR $OPENCL_LIBS"
|
||||||
|
elif test "x$AMDAPPSDKROOT" != x; then
|
||||||
|
OPENCL_FLAGS="-I$AMDAPPSDKROOT/include $OPENCL_FLAGS"
|
||||||
|
OPENCL_LIBS="-L$AMDAPPSDKROOT/lib/$ARCH_DIR $OPENCL_LIBS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cpumining="no"
|
cpumining="no"
|
||||||
|
@ -45,8 +45,8 @@ enum {
|
|||||||
#endif /* WIN32 */
|
#endif /* WIN32 */
|
||||||
|
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "fpgautils.h"
|
|
||||||
#include "miner.h"
|
#include "miner.h"
|
||||||
|
#include "fpgautils.h"
|
||||||
|
|
||||||
#define BITFORCE_SLEEP_MS 500
|
#define BITFORCE_SLEEP_MS 500
|
||||||
#define BITFORCE_TIMEOUT_S 7
|
#define BITFORCE_TIMEOUT_S 7
|
||||||
@ -99,6 +99,7 @@ static bool bitforce_detect_one(const char *devpath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
BFwrite(fdDev, "ZGX", 3);
|
BFwrite(fdDev, "ZGX", 3);
|
||||||
|
pdevbuf[0] = '\0';
|
||||||
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
|
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
|
||||||
if (unlikely(!pdevbuf[0])) {
|
if (unlikely(!pdevbuf[0])) {
|
||||||
applog(LOG_ERR, "BFL: Error reading/timeout (ZGX)");
|
applog(LOG_ERR, "BFL: Error reading/timeout (ZGX)");
|
||||||
@ -229,7 +230,7 @@ static int bitforce_detect_auto(void)
|
|||||||
|
|
||||||
static void bitforce_detect(void)
|
static void bitforce_detect(void)
|
||||||
{
|
{
|
||||||
serial_detect_auto(bitforce_api.dname, bitforce_detect_one, bitforce_detect_auto);
|
serial_detect_auto(&bitforce_api, bitforce_detect_one, bitforce_detect_auto);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_bitforce_statline_before(char *buf, struct cgpu_info *bitforce)
|
static void get_bitforce_statline_before(char *buf, struct cgpu_info *bitforce)
|
||||||
@ -309,6 +310,7 @@ void bitforce_init(struct cgpu_info *bitforce)
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
BFwrite(fdDev, "ZGX", 3);
|
BFwrite(fdDev, "ZGX", 3);
|
||||||
|
pdevbuf[0] = '\0';
|
||||||
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
|
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
|
||||||
|
|
||||||
if (unlikely(!pdevbuf[0])) {
|
if (unlikely(!pdevbuf[0])) {
|
||||||
@ -338,6 +340,37 @@ void bitforce_init(struct cgpu_info *bitforce)
|
|||||||
mutex_unlock(&bitforce->device_mutex);
|
mutex_unlock(&bitforce->device_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bitforce_flash_led(struct cgpu_info *bitforce)
|
||||||
|
{
|
||||||
|
int fdDev = bitforce->device_fd;
|
||||||
|
|
||||||
|
if (!fdDev)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Do not try to flash the led if we're polling for a result to
|
||||||
|
* minimise the chance of interleaved results */
|
||||||
|
if (bitforce->polling)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* It is not critical flashing the led so don't get stuck if we
|
||||||
|
* can't grab the mutex here */
|
||||||
|
if (mutex_trylock(&bitforce->device_mutex))
|
||||||
|
return;
|
||||||
|
|
||||||
|
BFwrite(fdDev, "ZMX", 3);
|
||||||
|
|
||||||
|
/* Once we've tried - don't do it until told to again */
|
||||||
|
bitforce->flash_led = false;
|
||||||
|
|
||||||
|
/* However, this stops anything else getting a reply
|
||||||
|
* So best to delay any other access to the BFL */
|
||||||
|
sleep(4);
|
||||||
|
|
||||||
|
mutex_unlock(&bitforce->device_mutex);
|
||||||
|
|
||||||
|
return; // nothing is returned by the BFL
|
||||||
|
}
|
||||||
|
|
||||||
static bool bitforce_get_temp(struct cgpu_info *bitforce)
|
static bool bitforce_get_temp(struct cgpu_info *bitforce)
|
||||||
{
|
{
|
||||||
int fdDev = bitforce->device_fd;
|
int fdDev = bitforce->device_fd;
|
||||||
@ -348,16 +381,23 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Do not try to get the temperature if we're polling for a result to
|
/* Do not try to get the temperature if we're polling for a result to
|
||||||
* minimise the change of interleaved results */
|
* minimise the chance of interleaved results */
|
||||||
if (bitforce->polling)
|
if (bitforce->polling)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* It is not critical getting temperature so don't get stuck if we
|
// Flash instead of Temp - doing both can be too slow
|
||||||
|
if (bitforce->flash_led) {
|
||||||
|
bitforce_flash_led(bitforce);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* It is not critical getting temperature so don't get stuck if we
|
||||||
* can't grab the mutex here */
|
* can't grab the mutex here */
|
||||||
if (mutex_trylock(&bitforce->device_mutex))
|
if (mutex_trylock(&bitforce->device_mutex))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
BFwrite(fdDev, "ZLX", 3);
|
BFwrite(fdDev, "ZLX", 3);
|
||||||
|
pdevbuf[0] = '\0';
|
||||||
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
|
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
|
||||||
mutex_unlock(&bitforce->device_mutex);
|
mutex_unlock(&bitforce->device_mutex);
|
||||||
|
|
||||||
@ -385,11 +425,14 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce)
|
|||||||
/* Use the temperature monitor as a kind of watchdog for when
|
/* Use the temperature monitor as a kind of watchdog for when
|
||||||
* our responses are out of sync and flush the buffer to
|
* our responses are out of sync and flush the buffer to
|
||||||
* hopefully recover */
|
* hopefully recover */
|
||||||
applog(LOG_WARNING, "BFL%i: Garbled response probably throttling, clearing buffer");
|
applog(LOG_WARNING, "BFL%i: Garbled response probably throttling, clearing buffer", bitforce->device_id);
|
||||||
|
bitforce->device_last_not_well = time(NULL);
|
||||||
|
bitforce->device_not_well_reason = REASON_DEV_THROTTLE;
|
||||||
|
bitforce->dev_throttle_count++;
|
||||||
/* Count throttling episodes as hardware errors */
|
/* Count throttling episodes as hardware errors */
|
||||||
bitforce->hw_errors++;
|
bitforce->hw_errors++;
|
||||||
bitforce_clear_buffer(bitforce);
|
bitforce_clear_buffer(bitforce);
|
||||||
return false;;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -411,6 +454,7 @@ re_send:
|
|||||||
BFwrite(fdDev, "ZPX", 3);
|
BFwrite(fdDev, "ZPX", 3);
|
||||||
else
|
else
|
||||||
BFwrite(fdDev, "ZDX", 3);
|
BFwrite(fdDev, "ZDX", 3);
|
||||||
|
pdevbuf[0] = '\0';
|
||||||
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
|
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
|
||||||
if (!pdevbuf[0] || !strncasecmp(pdevbuf, "B", 1)) {
|
if (!pdevbuf[0] || !strncasecmp(pdevbuf, "B", 1)) {
|
||||||
mutex_unlock(&bitforce->device_mutex);
|
mutex_unlock(&bitforce->device_mutex);
|
||||||
@ -450,6 +494,7 @@ re_send:
|
|||||||
BFwrite(fdDev, ob, 68);
|
BFwrite(fdDev, ob, 68);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pdevbuf[0] = '\0';
|
||||||
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
|
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
|
||||||
mutex_unlock(&bitforce->device_mutex);
|
mutex_unlock(&bitforce->device_mutex);
|
||||||
|
|
||||||
@ -493,6 +538,7 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work)
|
|||||||
|
|
||||||
mutex_lock(&bitforce->device_mutex);
|
mutex_lock(&bitforce->device_mutex);
|
||||||
BFwrite(fdDev, "ZFX", 3);
|
BFwrite(fdDev, "ZFX", 3);
|
||||||
|
pdevbuf[0] = '\0';
|
||||||
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
|
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
|
||||||
mutex_unlock(&bitforce->device_mutex);
|
mutex_unlock(&bitforce->device_mutex);
|
||||||
|
|
||||||
@ -637,6 +683,11 @@ static bool bitforce_get_stats(struct cgpu_info *bitforce)
|
|||||||
return bitforce_get_temp(bitforce);
|
return bitforce_get_temp(bitforce);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bitforce_identify(struct cgpu_info *bitforce)
|
||||||
|
{
|
||||||
|
bitforce->flash_led = true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool bitforce_thread_init(struct thr_info *thr)
|
static bool bitforce_thread_init(struct thr_info *thr)
|
||||||
{
|
{
|
||||||
struct cgpu_info *bitforce = thr->cgpu;
|
struct cgpu_info *bitforce = thr->cgpu;
|
||||||
@ -673,6 +724,7 @@ struct device_api bitforce_api = {
|
|||||||
.reinit_device = bitforce_init,
|
.reinit_device = bitforce_init,
|
||||||
.get_statline_before = get_bitforce_statline_before,
|
.get_statline_before = get_bitforce_statline_before,
|
||||||
.get_stats = bitforce_get_stats,
|
.get_stats = bitforce_get_stats,
|
||||||
|
.identify_device = bitforce_identify,
|
||||||
.thread_prepare = bitforce_thread_prepare,
|
.thread_prepare = bitforce_thread_prepare,
|
||||||
.thread_init = bitforce_thread_init,
|
.thread_init = bitforce_thread_init,
|
||||||
.scanhash = bitforce_scanhash,
|
.scanhash = bitforce_scanhash,
|
||||||
|
@ -75,7 +75,7 @@ static inline void affine_to_cpu(int id, int cpu)
|
|||||||
|
|
||||||
|
|
||||||
/* TODO: resolve externals */
|
/* TODO: resolve externals */
|
||||||
extern bool submit_work_sync(struct thr_info *thr, const struct work *work_in);
|
extern bool submit_work_sync(struct thr_info *thr, const struct work *work_in, struct timeval *tv);
|
||||||
extern char *set_int_range(const char *arg, int *i, int min, int max);
|
extern char *set_int_range(const char *arg, int *i, int min, int max);
|
||||||
extern int dev_from_id(int thr_id);
|
extern int dev_from_id(int thr_id);
|
||||||
|
|
||||||
@ -827,7 +827,7 @@ CPUSearch:
|
|||||||
/* if nonce found, submit work */
|
/* if nonce found, submit work */
|
||||||
if (unlikely(rc)) {
|
if (unlikely(rc)) {
|
||||||
applog(LOG_DEBUG, "CPU %d found something?", dev_from_id(thr_id));
|
applog(LOG_DEBUG, "CPU %d found something?", dev_from_id(thr_id));
|
||||||
if (unlikely(!submit_work_sync(thr, work))) {
|
if (unlikely(!submit_work_sync(thr, work, NULL))) {
|
||||||
applog(LOG_ERR, "Failed to submit_work_sync in miner_thread %d", thr_id);
|
applog(LOG_ERR, "Failed to submit_work_sync in miner_thread %d", thr_id);
|
||||||
}
|
}
|
||||||
work->blk.nonce = last_nonce + 1;
|
work->blk.nonce = last_nonce + 1;
|
||||||
|
@ -49,8 +49,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "elist.h"
|
#include "elist.h"
|
||||||
#include "fpgautils.h"
|
|
||||||
#include "miner.h"
|
#include "miner.h"
|
||||||
|
#include "fpgautils.h"
|
||||||
|
|
||||||
// The serial I/O speed - Linux uses a define 'B115200' in bits/termios.h
|
// The serial I/O speed - Linux uses a define 'B115200' in bits/termios.h
|
||||||
#define ICARUS_IO_SPEED 115200
|
#define ICARUS_IO_SPEED 115200
|
||||||
@ -598,7 +598,7 @@ static bool icarus_detect_one(const char *devpath)
|
|||||||
|
|
||||||
static void icarus_detect()
|
static void icarus_detect()
|
||||||
{
|
{
|
||||||
serial_detect(icarus_api.dname, icarus_detect_one);
|
serial_detect(&icarus_api, icarus_detect_one);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool icarus_prepare(struct thr_info *thr)
|
static bool icarus_prepare(struct thr_info *thr)
|
||||||
@ -639,7 +639,8 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work,
|
|||||||
struct timeval tv_start, tv_finish, elapsed;
|
struct timeval tv_start, tv_finish, elapsed;
|
||||||
struct timeval tv_history_start, tv_history_finish;
|
struct timeval tv_history_start, tv_history_finish;
|
||||||
double Ti, Xi;
|
double Ti, Xi;
|
||||||
int i;
|
int curr_hw_errors, i;
|
||||||
|
bool was_hw_error;
|
||||||
|
|
||||||
struct ICARUS_HISTORY *history0, *history;
|
struct ICARUS_HISTORY *history0, *history;
|
||||||
int count;
|
int count;
|
||||||
@ -712,7 +713,9 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work,
|
|||||||
nonce = swab32(nonce);
|
nonce = swab32(nonce);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
curr_hw_errors = icarus->hw_errors;
|
||||||
submit_nonce(thr, work, nonce);
|
submit_nonce(thr, work, nonce);
|
||||||
|
was_hw_error = (curr_hw_errors > icarus->hw_errors);
|
||||||
|
|
||||||
hash_count = (nonce & info->nonce_mask);
|
hash_count = (nonce & info->nonce_mask);
|
||||||
hash_count++;
|
hash_count++;
|
||||||
@ -726,8 +729,9 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work,
|
|||||||
icarus->device_id, nonce, hash_count, elapsed.tv_sec, elapsed.tv_usec);
|
icarus->device_id, nonce, hash_count, elapsed.tv_sec, elapsed.tv_usec);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore possible end condition values
|
// ignore possible end condition values ... and hw errors
|
||||||
if (info->do_icarus_timing
|
if (info->do_icarus_timing
|
||||||
|
&& !was_hw_error
|
||||||
&& ((nonce & info->nonce_mask) > END_CONDITION)
|
&& ((nonce & info->nonce_mask) > END_CONDITION)
|
||||||
&& ((nonce & info->nonce_mask) < (info->nonce_mask & ~END_CONDITION))) {
|
&& ((nonce & info->nonce_mask) < (info->nonce_mask & ~END_CONDITION))) {
|
||||||
gettimeofday(&tv_history_start, NULL);
|
gettimeofday(&tv_history_start, NULL);
|
||||||
|
@ -13,9 +13,9 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "fpgautils.h"
|
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "miner.h"
|
#include "miner.h"
|
||||||
|
#include "fpgautils.h"
|
||||||
|
|
||||||
#define BITSTREAM_FILENAME "fpgaminer_top_fixed7_197MHz.ncd"
|
#define BITSTREAM_FILENAME "fpgaminer_top_fixed7_197MHz.ncd"
|
||||||
#define BISTREAM_USER_ID "\2\4$B"
|
#define BISTREAM_USER_ID "\2\4$B"
|
||||||
@ -103,7 +103,7 @@ modminer_detect_auto()
|
|||||||
static void
|
static void
|
||||||
modminer_detect()
|
modminer_detect()
|
||||||
{
|
{
|
||||||
serial_detect_auto(modminer_api.dname, modminer_detect_one, modminer_detect_auto);
|
serial_detect_auto(&modminer_api, modminer_detect_one, modminer_detect_auto);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define bailout(...) return _bailout(-1, modminer, __VA_ARGS__);
|
#define bailout(...) return _bailout(-1, modminer, __VA_ARGS__);
|
||||||
@ -404,7 +404,7 @@ modminer_process_results(struct thr_info*thr)
|
|||||||
char cmd[2], temperature;
|
char cmd[2], temperature;
|
||||||
uint32_t nonce;
|
uint32_t nonce;
|
||||||
long iter;
|
long iter;
|
||||||
bool bad;
|
int curr_hw_errors;
|
||||||
cmd[0] = '\x0a';
|
cmd[0] = '\x0a';
|
||||||
cmd[1] = fpgaid;
|
cmd[1] = fpgaid;
|
||||||
|
|
||||||
@ -441,12 +441,10 @@ modminer_process_results(struct thr_info*thr)
|
|||||||
mutex_unlock(&modminer->device_mutex);
|
mutex_unlock(&modminer->device_mutex);
|
||||||
if (memcmp(&nonce, "\xff\xff\xff\xff", 4)) {
|
if (memcmp(&nonce, "\xff\xff\xff\xff", 4)) {
|
||||||
state->no_nonce_counter = 0;
|
state->no_nonce_counter = 0;
|
||||||
bad = !test_nonce(work, nonce);
|
curr_hw_errors = modminer->hw_errors;
|
||||||
if (!bad)
|
submit_nonce(thr, work, nonce);
|
||||||
submit_nonce(thr, work, nonce);
|
if (modminer->hw_errors > curr_hw_errors) {
|
||||||
else {
|
if (modminer->hw_errors * 100 > 1000 + state->good_share_counter)
|
||||||
++hw_errors;
|
|
||||||
if (++modminer->hw_errors * 100 > 1000 + state->good_share_counter)
|
|
||||||
// Only reduce clocks if hardware errors are more than ~1% of results
|
// Only reduce clocks if hardware errors are more than ~1% of results
|
||||||
modminer_reduce_clock(thr, true);
|
modminer_reduce_clock(thr, true);
|
||||||
}
|
}
|
||||||
|
@ -1585,15 +1585,14 @@ static int64_t opencl_scanhash(struct thr_info *thr, struct work *work,
|
|||||||
gpu_us = us_tdiff(&tv_gpuend, &gpu->tv_gpumid);
|
gpu_us = us_tdiff(&tv_gpuend, &gpu->tv_gpumid);
|
||||||
if (gpu_us > 0 && ++gpu->hit > 4) {
|
if (gpu_us > 0 && ++gpu->hit > 4) {
|
||||||
gpu_us = us_tdiff(&tv_gpuend, &gpu->tv_gpustart) / gpu->intervals;
|
gpu_us = us_tdiff(&tv_gpuend, &gpu->tv_gpustart) / gpu->intervals;
|
||||||
gpu->gpu_us_average = (gpu->gpu_us_average + gpu_us * 0.63) / 1.63;
|
|
||||||
|
|
||||||
/* Try to not let the GPU be out for longer than
|
/* Try to not let the GPU be out for longer than
|
||||||
* opt_dynamic_interval in ms, but increase
|
* opt_dynamic_interval in ms, but increase
|
||||||
* intensity when the system is idle in dynamic mode */
|
* intensity when the system is idle in dynamic mode */
|
||||||
if (gpu->gpu_us_average > dynamic_us) {
|
if (gpu_us > dynamic_us) {
|
||||||
if (gpu->intensity > MIN_INTENSITY)
|
if (gpu->intensity > MIN_INTENSITY)
|
||||||
--gpu->intensity;
|
--gpu->intensity;
|
||||||
} else if (gpu->gpu_us_average < dynamic_us / 2) {
|
} else if (gpu_us < dynamic_us / 2) {
|
||||||
if (gpu->intensity < MAX_INTENSITY)
|
if (gpu->intensity < MAX_INTENSITY)
|
||||||
++gpu->intensity;
|
++gpu->intensity;
|
||||||
}
|
}
|
||||||
|
16
findnonce.c
16
findnonce.c
@ -131,6 +131,8 @@ void precalc_hash(dev_blk_ctx *blk, uint32_t *state, uint32_t *data)
|
|||||||
blk->sevenA = blk->ctx_h + SHA256_K[7];
|
blk->sevenA = blk->ctx_h + SHA256_K[7];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0 // not used any more
|
||||||
|
|
||||||
#define P(t) (W[(t)&0xF] = W[(t-16)&0xF] + (rotate(W[(t-15)&0xF], 25) ^ rotate(W[(t-15)&0xF], 14) ^ (W[(t-15)&0xF] >> 3)) + W[(t-7)&0xF] + (rotate(W[(t-2)&0xF], 15) ^ rotate(W[(t-2)&0xF], 13) ^ (W[(t-2)&0xF] >> 10)))
|
#define P(t) (W[(t)&0xF] = W[(t-16)&0xF] + (rotate(W[(t-15)&0xF], 25) ^ rotate(W[(t-15)&0xF], 14) ^ (W[(t-15)&0xF] >> 3)) + W[(t-7)&0xF] + (rotate(W[(t-2)&0xF], 15) ^ rotate(W[(t-2)&0xF], 13) ^ (W[(t-2)&0xF] >> 10)))
|
||||||
|
|
||||||
#define IR(u) \
|
#define IR(u) \
|
||||||
@ -167,6 +169,8 @@ void precalc_hash(dev_blk_ctx *blk, uint32_t *state, uint32_t *data)
|
|||||||
R(E, F, G, H, A, B, C, D, P(u+4), SHA256_K[u+4]); \
|
R(E, F, G, H, A, B, C, D, P(u+4), SHA256_K[u+4]); \
|
||||||
R(D, E, F, G, H, A, B, C, P(u+5), SHA256_K[u+5])
|
R(D, E, F, G, H, A, B, C, P(u+5), SHA256_K[u+5])
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
struct pc_data {
|
struct pc_data {
|
||||||
struct thr_info *thr;
|
struct thr_info *thr;
|
||||||
struct work *work;
|
struct work *work;
|
||||||
@ -175,6 +179,8 @@ struct pc_data {
|
|||||||
int found;
|
int found;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if 0 // not used any more
|
||||||
|
|
||||||
static void send_sha_nonce(struct pc_data *pcd, cl_uint nonce)
|
static void send_sha_nonce(struct pc_data *pcd, cl_uint nonce)
|
||||||
{
|
{
|
||||||
dev_blk_ctx *blk = &pcd->work->blk;
|
dev_blk_ctx *blk = &pcd->work->blk;
|
||||||
@ -222,6 +228,8 @@ static void send_sha_nonce(struct pc_data *pcd, cl_uint nonce)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static void send_scrypt_nonce(struct pc_data *pcd, uint32_t nonce)
|
static void send_scrypt_nonce(struct pc_data *pcd, uint32_t nonce)
|
||||||
{
|
{
|
||||||
struct thr_info *thr = pcd->thr;
|
struct thr_info *thr = pcd->thr;
|
||||||
@ -238,6 +246,8 @@ static void send_scrypt_nonce(struct pc_data *pcd, uint32_t nonce)
|
|||||||
static void *postcalc_hash(void *userdata)
|
static void *postcalc_hash(void *userdata)
|
||||||
{
|
{
|
||||||
struct pc_data *pcd = (struct pc_data *)userdata;
|
struct pc_data *pcd = (struct pc_data *)userdata;
|
||||||
|
struct thr_info *thr = pcd->thr;
|
||||||
|
struct work *work = pcd->work;
|
||||||
unsigned int entry = 0;
|
unsigned int entry = 0;
|
||||||
|
|
||||||
pthread_detach(pthread_self());
|
pthread_detach(pthread_self());
|
||||||
@ -248,8 +258,10 @@ static void *postcalc_hash(void *userdata)
|
|||||||
applog(LOG_DEBUG, "OCL NONCE %u found in slot %d", nonce, entry);
|
applog(LOG_DEBUG, "OCL NONCE %u found in slot %d", nonce, entry);
|
||||||
if (opt_scrypt)
|
if (opt_scrypt)
|
||||||
send_scrypt_nonce(pcd, nonce);
|
send_scrypt_nonce(pcd, nonce);
|
||||||
else
|
else {
|
||||||
send_sha_nonce(pcd, nonce);
|
if (unlikely(submit_nonce(thr, work, nonce) == false))
|
||||||
|
applog(LOG_ERR, "Failed to submit work, exiting");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(pcd);
|
free(pcd);
|
||||||
|
53
fpgautils.c
53
fpgautils.c
@ -33,13 +33,12 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "elist.h"
|
#include "elist.h"
|
||||||
#include "fpgautils.h"
|
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "miner.h"
|
#include "miner.h"
|
||||||
|
#include "fpgautils.h"
|
||||||
|
|
||||||
#ifdef HAVE_LIBUDEV
|
#ifdef HAVE_LIBUDEV
|
||||||
int
|
int serial_autodetect_udev(detectone_func_t detectone, const char*prodname)
|
||||||
serial_autodetect_udev(detectone_func_t detectone, const char*prodname)
|
|
||||||
{
|
{
|
||||||
struct udev *udev = udev_new();
|
struct udev *udev = udev_new();
|
||||||
struct udev_enumerate *enumerate = udev_enumerate_new(udev);
|
struct udev_enumerate *enumerate = udev_enumerate_new(udev);
|
||||||
@ -69,15 +68,13 @@ serial_autodetect_udev(detectone_func_t detectone, const char*prodname)
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int
|
int serial_autodetect_udev(__maybe_unused detectone_func_t detectone, __maybe_unused const char*prodname)
|
||||||
serial_autodetect_udev(__maybe_unused detectone_func_t detectone, __maybe_unused const char*prodname)
|
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int
|
int serial_autodetect_devserial(detectone_func_t detectone, const char*prodname)
|
||||||
serial_autodetect_devserial(detectone_func_t detectone, const char*prodname)
|
|
||||||
{
|
{
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
DIR *D;
|
DIR *D;
|
||||||
@ -107,30 +104,32 @@ serial_autodetect_devserial(detectone_func_t detectone, const char*prodname)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int _serial_detect(struct device_api *api, detectone_func_t detectone, autoscan_func_t autoscan, bool forceauto)
|
||||||
_serial_detect(const char*dname, detectone_func_t detectone, autoscan_func_t autoscan, bool forceauto)
|
|
||||||
{
|
{
|
||||||
struct string_elist *iter, *tmp;
|
struct string_elist *iter, *tmp;
|
||||||
const char*s, *p;
|
const char *dev, *colon;
|
||||||
bool inhibitauto = false;
|
bool inhibitauto = false;
|
||||||
char found = 0;
|
char found = 0;
|
||||||
size_t dnamel = strlen(dname);
|
size_t namel = strlen(api->name);
|
||||||
|
size_t dnamel = strlen(api->dname);
|
||||||
|
|
||||||
list_for_each_entry_safe(iter, tmp, &scan_devices, list) {
|
list_for_each_entry_safe(iter, tmp, &scan_devices, list) {
|
||||||
s = iter->string;
|
dev = iter->string;
|
||||||
if ((p = strchr(s, ':')) && p[1] != '\0') {
|
if ((colon = strchr(dev, ':')) && colon[1] != '\0') {
|
||||||
size_t plen = p - s;
|
size_t idlen = colon - dev;
|
||||||
if (plen != dnamel || strncasecmp(s, dname, plen))
|
|
||||||
|
// allow either name:device or dname:device
|
||||||
|
if ((idlen != namel || strncasecmp(dev, api->name, idlen))
|
||||||
|
&& (idlen != dnamel || strncasecmp(dev, api->dname, idlen)))
|
||||||
continue;
|
continue;
|
||||||
s = p + 1;
|
|
||||||
|
dev = colon + 1;
|
||||||
}
|
}
|
||||||
if (!strcmp(s, "auto"))
|
if (!strcmp(dev, "auto"))
|
||||||
forceauto = true;
|
forceauto = true;
|
||||||
else
|
else if (!strcmp(dev, "noauto"))
|
||||||
if (!strcmp(s, "noauto"))
|
|
||||||
inhibitauto = true;
|
inhibitauto = true;
|
||||||
else
|
else if (detectone(dev)) {
|
||||||
if (detectone(s)) {
|
|
||||||
string_elist_del(iter);
|
string_elist_del(iter);
|
||||||
inhibitauto = true;
|
inhibitauto = true;
|
||||||
++found;
|
++found;
|
||||||
@ -311,8 +310,7 @@ void termios_debug(const char *devpath, struct termios *my_termios, const char *
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int
|
int serial_open(const char *devpath, unsigned long baud, signed short timeout, bool purge)
|
||||||
serial_open(const char*devpath, unsigned long baud, signed short timeout, bool purge)
|
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
HANDLE hSerial = CreateFile(devpath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
HANDLE hSerial = CreateFile(devpath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||||
@ -429,8 +427,7 @@ serial_open(const char*devpath, unsigned long baud, signed short timeout, bool p
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t
|
ssize_t _serial_read(int fd, char *buf, size_t bufsiz, char *eol)
|
||||||
_serial_read(int fd, char *buf, size_t bufsiz, char *eol)
|
|
||||||
{
|
{
|
||||||
ssize_t len, tlen = 0;
|
ssize_t len, tlen = 0;
|
||||||
while (bufsiz) {
|
while (bufsiz) {
|
||||||
@ -446,8 +443,7 @@ _serial_read(int fd, char *buf, size_t bufsiz, char *eol)
|
|||||||
return tlen;
|
return tlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FILE*
|
static FILE *_open_bitstream(const char *path, const char *subdir, const char *filename)
|
||||||
_open_bitstream(const char*path, const char*subdir, const char*filename)
|
|
||||||
{
|
{
|
||||||
char fullpath[PATH_MAX];
|
char fullpath[PATH_MAX];
|
||||||
strcpy(fullpath, path);
|
strcpy(fullpath, path);
|
||||||
@ -471,8 +467,7 @@ _open_bitstream(const char*path, const char*subdir, const char*filename)
|
|||||||
_open_bitstream(path, NULL); \
|
_open_bitstream(path, NULL); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
FILE*
|
FILE *open_bitstream(const char *dname, const char *filename)
|
||||||
open_bitstream(const char*dname, const char*filename)
|
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
|
26
fpgautils.h
26
fpgautils.h
@ -16,24 +16,24 @@
|
|||||||
typedef bool(*detectone_func_t)(const char*);
|
typedef bool(*detectone_func_t)(const char*);
|
||||||
typedef int(*autoscan_func_t)();
|
typedef int(*autoscan_func_t)();
|
||||||
|
|
||||||
extern int _serial_detect(const char*dname, detectone_func_t, autoscan_func_t, bool force_autoscan);
|
extern int _serial_detect(struct device_api *api, detectone_func_t, autoscan_func_t, bool force_autoscan);
|
||||||
#define serial_detect_fauto(dname, detectone, autoscan) \
|
#define serial_detect_fauto(api, detectone, autoscan) \
|
||||||
_serial_detect(dname, detectone, autoscan, true)
|
_serial_detect(api, detectone, autoscan, true)
|
||||||
#define serial_detect_auto(dname, detectone, autoscan) \
|
#define serial_detect_auto(api, detectone, autoscan) \
|
||||||
_serial_detect(dname, detectone, autoscan, false)
|
_serial_detect(api, detectone, autoscan, false)
|
||||||
#define serial_detect(dname, detectone) \
|
#define serial_detect(api, detectone) \
|
||||||
_serial_detect(dname, detectone, NULL, false)
|
_serial_detect(api, detectone, NULL, false)
|
||||||
extern int serial_autodetect_devserial(detectone_func_t, const char*prodname);
|
extern int serial_autodetect_devserial(detectone_func_t, const char *prodname);
|
||||||
extern int serial_autodetect_udev (detectone_func_t, const char*prodname);
|
extern int serial_autodetect_udev(detectone_func_t, const char *prodname);
|
||||||
|
|
||||||
extern int serial_open(const char*devpath, unsigned long baud, signed short timeout, bool purge);
|
extern int serial_open(const char *devpath, unsigned long baud, signed short timeout, bool purge);
|
||||||
extern ssize_t _serial_read(int fd, char *buf, size_t buflen, char*eol);
|
extern ssize_t _serial_read(int fd, char *buf, size_t buflen, char *eol);
|
||||||
#define serial_read(fd, buf, count) \
|
#define serial_read(fd, buf, count) \
|
||||||
_serial_read(fd, (char*)(buf), count, NULL)
|
_serial_read(fd, (char*)(buf), count, NULL)
|
||||||
#define serial_read_line(fd, buf, bufsiz, eol) \
|
#define serial_read_line(fd, buf, bufsiz, eol) \
|
||||||
_serial_read(fd, buf, count, &eol)
|
_serial_read(fd, buf, bufsiz, &eol)
|
||||||
#define serial_close(fd) close(fd)
|
#define serial_close(fd) close(fd)
|
||||||
|
|
||||||
extern FILE*open_bitstream(const char*dname, const char*filename);
|
extern FILE *open_bitstream(const char *dname, const char *filename);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -23,8 +23,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "fpgautils.h"
|
|
||||||
#include "miner.h"
|
#include "miner.h"
|
||||||
|
#include "fpgautils.h"
|
||||||
#include "libztex.h"
|
#include "libztex.h"
|
||||||
|
|
||||||
#define BUFSIZE 256
|
#define BUFSIZE 256
|
||||||
|
@ -20,6 +20,8 @@ enum {
|
|||||||
/* original / legacy debug flags */
|
/* original / legacy debug flags */
|
||||||
extern bool opt_debug;
|
extern bool opt_debug;
|
||||||
extern bool opt_log_output;
|
extern bool opt_log_output;
|
||||||
|
extern bool opt_realquiet;
|
||||||
|
extern bool want_per_device_stats;
|
||||||
|
|
||||||
/* global log_level, messages with lower or equal prio are logged */
|
/* global log_level, messages with lower or equal prio are logged */
|
||||||
extern int opt_log_level;
|
extern int opt_log_level;
|
||||||
|
51
miner.h
51
miner.h
@ -239,6 +239,7 @@ struct device_api {
|
|||||||
void (*get_statline)(char*, struct cgpu_info*);
|
void (*get_statline)(char*, struct cgpu_info*);
|
||||||
struct api_data *(*get_api_stats)(struct cgpu_info*);
|
struct api_data *(*get_api_stats)(struct cgpu_info*);
|
||||||
bool (*get_stats)(struct cgpu_info*);
|
bool (*get_stats)(struct cgpu_info*);
|
||||||
|
void (*identify_device)(struct cgpu_info*); // e.g. to flash a led
|
||||||
|
|
||||||
// Thread-specific functions
|
// Thread-specific functions
|
||||||
bool (*thread_prepare)(struct thr_info*);
|
bool (*thread_prepare)(struct thr_info*);
|
||||||
@ -276,6 +277,7 @@ enum dev_reason {
|
|||||||
REASON_DEV_OVER_HEAT,
|
REASON_DEV_OVER_HEAT,
|
||||||
REASON_DEV_THERMAL_CUTOFF,
|
REASON_DEV_THERMAL_CUTOFF,
|
||||||
REASON_DEV_COMMS_ERROR,
|
REASON_DEV_COMMS_ERROR,
|
||||||
|
REASON_DEV_THROTTLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define REASON_NONE "None"
|
#define REASON_NONE "None"
|
||||||
@ -288,6 +290,7 @@ enum dev_reason {
|
|||||||
#define REASON_DEV_OVER_HEAT_STR "Device over heated"
|
#define REASON_DEV_OVER_HEAT_STR "Device over heated"
|
||||||
#define REASON_DEV_THERMAL_CUTOFF_STR "Device reached thermal cutoff"
|
#define REASON_DEV_THERMAL_CUTOFF_STR "Device reached thermal cutoff"
|
||||||
#define REASON_DEV_COMMS_ERROR_STR "Device comms error"
|
#define REASON_DEV_COMMS_ERROR_STR "Device comms error"
|
||||||
|
#define REASON_DEV_THROTTLE_STR "Device throttle"
|
||||||
#define REASON_UNKNOWN_STR "Unknown reason - code bug"
|
#define REASON_UNKNOWN_STR "Unknown reason - code bug"
|
||||||
|
|
||||||
#define MIN_SEC_UNSET 99999999
|
#define MIN_SEC_UNSET 99999999
|
||||||
@ -311,6 +314,11 @@ struct cgminer_pool_stats {
|
|||||||
bool canroll;
|
bool canroll;
|
||||||
bool hadexpire;
|
bool hadexpire;
|
||||||
uint32_t rolltime;
|
uint32_t rolltime;
|
||||||
|
double min_diff;
|
||||||
|
double max_diff;
|
||||||
|
double last_diff;
|
||||||
|
uint32_t min_diff_count;
|
||||||
|
uint32_t max_diff_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cgpu_info {
|
struct cgpu_info {
|
||||||
@ -335,6 +343,7 @@ struct cgpu_info {
|
|||||||
uint32_t nonces;
|
uint32_t nonces;
|
||||||
bool nonce_range;
|
bool nonce_range;
|
||||||
bool polling;
|
bool polling;
|
||||||
|
bool flash_led;
|
||||||
#endif
|
#endif
|
||||||
pthread_mutex_t device_mutex;
|
pthread_mutex_t device_mutex;
|
||||||
|
|
||||||
@ -374,7 +383,6 @@ struct cgpu_info {
|
|||||||
#endif
|
#endif
|
||||||
struct timeval tv_gpustart;
|
struct timeval tv_gpustart;
|
||||||
struct timeval tv_gpumid;
|
struct timeval tv_gpumid;
|
||||||
double gpu_us_average;
|
|
||||||
int intervals, hit;
|
int intervals, hit;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -396,8 +404,12 @@ struct cgpu_info {
|
|||||||
int gpu_powertune;
|
int gpu_powertune;
|
||||||
float gpu_vddc;
|
float gpu_vddc;
|
||||||
#endif
|
#endif
|
||||||
|
int diff1;
|
||||||
|
double diff_accepted;
|
||||||
|
double diff_rejected;
|
||||||
int last_share_pool;
|
int last_share_pool;
|
||||||
time_t last_share_pool_time;
|
time_t last_share_pool_time;
|
||||||
|
double last_share_diff;
|
||||||
|
|
||||||
time_t device_last_well;
|
time_t device_last_well;
|
||||||
time_t device_last_not_well;
|
time_t device_last_not_well;
|
||||||
@ -411,6 +423,7 @@ struct cgpu_info {
|
|||||||
int dev_over_heat_count; // It's a warning but worth knowing
|
int dev_over_heat_count; // It's a warning but worth knowing
|
||||||
int dev_thermal_cutoff_count;
|
int dev_thermal_cutoff_count;
|
||||||
int dev_comms_error_count;
|
int dev_comms_error_count;
|
||||||
|
int dev_throttle_count;
|
||||||
|
|
||||||
struct cgminer_stats cgminer_stats;
|
struct cgminer_stats cgminer_stats;
|
||||||
};
|
};
|
||||||
@ -450,6 +463,7 @@ extern void thr_info_cancel(struct thr_info *thr);
|
|||||||
extern void thr_info_freeze(struct thr_info *thr);
|
extern void thr_info_freeze(struct thr_info *thr);
|
||||||
extern void nmsleep(unsigned int msecs);
|
extern void nmsleep(unsigned int msecs);
|
||||||
extern double us_tdiff(struct timeval *end, struct timeval *start);
|
extern double us_tdiff(struct timeval *end, struct timeval *start);
|
||||||
|
extern double tdiff(struct timeval *end, struct timeval *start);
|
||||||
|
|
||||||
struct string_elist {
|
struct string_elist {
|
||||||
char *string;
|
char *string;
|
||||||
@ -576,6 +590,7 @@ extern bool opt_delaynet;
|
|||||||
extern bool opt_restart;
|
extern bool opt_restart;
|
||||||
extern char *opt_icarus_options;
|
extern char *opt_icarus_options;
|
||||||
extern char *opt_icarus_timing;
|
extern char *opt_icarus_timing;
|
||||||
|
extern bool opt_worktime;
|
||||||
#ifdef USE_BITFORCE
|
#ifdef USE_BITFORCE
|
||||||
extern bool opt_bfl_noncerange;
|
extern bool opt_bfl_noncerange;
|
||||||
#endif
|
#endif
|
||||||
@ -586,6 +601,8 @@ extern const uint32_t sha256_init_state[];
|
|||||||
extern json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass,
|
extern json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass,
|
||||||
const char *rpc_req, bool, bool, int *,
|
const char *rpc_req, bool, bool, int *,
|
||||||
struct pool *pool, bool);
|
struct pool *pool, bool);
|
||||||
|
extern const char *proxytype(curl_proxytype proxytype);
|
||||||
|
extern char *get_proxy(char *url, struct pool *pool);
|
||||||
extern char *bin2hex(const unsigned char *p, size_t len);
|
extern char *bin2hex(const unsigned char *p, size_t len);
|
||||||
extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len);
|
extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len);
|
||||||
|
|
||||||
@ -599,7 +616,9 @@ typedef bool (*sha256_func)(struct thr_info*, const unsigned char *pmidstate,
|
|||||||
|
|
||||||
extern bool fulltest(const unsigned char *hash, const unsigned char *target);
|
extern bool fulltest(const unsigned char *hash, const unsigned char *target);
|
||||||
|
|
||||||
|
extern int opt_queue;
|
||||||
extern int opt_scantime;
|
extern int opt_scantime;
|
||||||
|
extern int opt_expiry;
|
||||||
|
|
||||||
extern pthread_mutex_t console_lock;
|
extern pthread_mutex_t console_lock;
|
||||||
extern pthread_mutex_t ch_lock;
|
extern pthread_mutex_t ch_lock;
|
||||||
@ -672,6 +691,7 @@ extern unsigned int new_blocks;
|
|||||||
extern unsigned int found_blocks;
|
extern unsigned int found_blocks;
|
||||||
extern int total_accepted, total_rejected, total_diff1;;
|
extern int total_accepted, total_rejected, total_diff1;;
|
||||||
extern int total_getworks, total_stale, total_discarded;
|
extern int total_getworks, total_stale, total_discarded;
|
||||||
|
extern double total_diff_accepted, total_diff_rejected, total_diff_stale;
|
||||||
extern unsigned int local_work;
|
extern unsigned int local_work;
|
||||||
extern unsigned int total_go, total_ro;
|
extern unsigned int total_go, total_ro;
|
||||||
extern const int opt_cutofftemp;
|
extern const int opt_cutofftemp;
|
||||||
@ -733,9 +753,14 @@ struct pool {
|
|||||||
int prio;
|
int prio;
|
||||||
int accepted, rejected;
|
int accepted, rejected;
|
||||||
int seq_rejects;
|
int seq_rejects;
|
||||||
|
int seq_getfails;
|
||||||
int solved;
|
int solved;
|
||||||
int diff1;
|
int diff1;
|
||||||
|
|
||||||
|
double diff_accepted;
|
||||||
|
double diff_rejected;
|
||||||
|
double diff_stale;
|
||||||
|
|
||||||
int queued;
|
int queued;
|
||||||
int staged;
|
int staged;
|
||||||
|
|
||||||
@ -764,6 +789,8 @@ struct pool {
|
|||||||
char *rpc_url;
|
char *rpc_url;
|
||||||
char *rpc_userpass;
|
char *rpc_userpass;
|
||||||
char *rpc_user, *rpc_pass;
|
char *rpc_user, *rpc_pass;
|
||||||
|
curl_proxytype rpc_proxytype;
|
||||||
|
char *rpc_proxy;
|
||||||
|
|
||||||
pthread_mutex_t pool_lock;
|
pthread_mutex_t pool_lock;
|
||||||
|
|
||||||
@ -779,11 +806,17 @@ struct pool {
|
|||||||
struct list_head curlring;
|
struct list_head curlring;
|
||||||
|
|
||||||
time_t last_share_time;
|
time_t last_share_time;
|
||||||
|
double last_share_diff;
|
||||||
|
|
||||||
struct cgminer_stats cgminer_stats;
|
struct cgminer_stats cgminer_stats;
|
||||||
struct cgminer_pool_stats cgminer_pool_stats;
|
struct cgminer_pool_stats cgminer_pool_stats;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define GETWORK_MODE_TESTPOOL 'T'
|
||||||
|
#define GETWORK_MODE_POOL 'P'
|
||||||
|
#define GETWORK_MODE_LP 'L'
|
||||||
|
#define GETWORK_MODE_BENCHMARK 'B'
|
||||||
|
|
||||||
struct work {
|
struct work {
|
||||||
unsigned char data[128];
|
unsigned char data[128];
|
||||||
unsigned char hash1[64];
|
unsigned char hash1[64];
|
||||||
@ -814,9 +847,16 @@ struct work {
|
|||||||
|
|
||||||
unsigned int work_block;
|
unsigned int work_block;
|
||||||
int id;
|
int id;
|
||||||
UT_hash_handle hh;
|
UT_hash_handle hh;
|
||||||
|
|
||||||
time_t share_found_time;
|
double work_difficulty;
|
||||||
|
|
||||||
|
struct timeval tv_getwork;
|
||||||
|
struct timeval tv_getwork_reply;
|
||||||
|
struct timeval tv_cloned;
|
||||||
|
struct timeval tv_work_start;
|
||||||
|
struct timeval tv_work_found;
|
||||||
|
char getwork_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef USE_MODMINER
|
#ifdef USE_MODMINER
|
||||||
@ -838,7 +878,6 @@ struct modminer_fpga_state {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void get_datestamp(char *, struct timeval *);
|
extern void get_datestamp(char *, struct timeval *);
|
||||||
extern bool test_nonce(struct work *work, uint32_t nonce);
|
|
||||||
bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce);
|
bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce);
|
||||||
extern void tailsprintf(char *f, const char *fmt, ...);
|
extern void tailsprintf(char *f, const char *fmt, ...);
|
||||||
extern void wlogprint(const char *f, ...);
|
extern void wlogprint(const char *f, ...);
|
||||||
@ -881,7 +920,8 @@ enum api_data_type {
|
|||||||
API_UTILITY,
|
API_UTILITY,
|
||||||
API_FREQ,
|
API_FREQ,
|
||||||
API_VOLTS,
|
API_VOLTS,
|
||||||
API_HS
|
API_HS,
|
||||||
|
API_DIFF
|
||||||
};
|
};
|
||||||
|
|
||||||
struct api_data {
|
struct api_data {
|
||||||
@ -912,5 +952,6 @@ extern struct api_data *api_add_utility(struct api_data *root, char *name, doubl
|
|||||||
extern struct api_data *api_add_freq(struct api_data *root, char *name, double *data, bool copy_data);
|
extern struct api_data *api_add_freq(struct api_data *root, char *name, double *data, bool copy_data);
|
||||||
extern struct api_data *api_add_volts(struct api_data *root, char *name, float *data, bool copy_data);
|
extern struct api_data *api_add_volts(struct api_data *root, char *name, float *data, bool copy_data);
|
||||||
extern struct api_data *api_add_hs(struct api_data *root, char *name, double *data, bool copy_data);
|
extern struct api_data *api_add_hs(struct api_data *root, char *name, double *data, bool copy_data);
|
||||||
|
extern struct api_data *api_add_diff(struct api_data *root, char *name, double *data, bool copy_data);
|
||||||
|
|
||||||
#endif /* __MINER_H__ */
|
#endif /* __MINER_H__ */
|
||||||
|
91
miner.php
91
miner.php
@ -2,7 +2,7 @@
|
|||||||
session_start();
|
session_start();
|
||||||
#
|
#
|
||||||
global $title, $miner, $port, $readonly, $notify, $rigs;
|
global $title, $miner, $port, $readonly, $notify, $rigs;
|
||||||
global $rigtotals, $forcerigtotals;
|
global $rigipsecurity, $rigtotals, $forcerigtotals;
|
||||||
global $socksndtimeoutsec, $sockrcvtimeoutsec;
|
global $socksndtimeoutsec, $sockrcvtimeoutsec;
|
||||||
global $checklastshare, $poolinputs, $hidefields;
|
global $checklastshare, $poolinputs, $hidefields;
|
||||||
global $ignorerefresh, $changerefresh, $autorefresh;
|
global $ignorerefresh, $changerefresh, $autorefresh;
|
||||||
@ -40,6 +40,10 @@ $poolinputs = false;
|
|||||||
# format: 'IP:Port' or 'Host:Port' or 'Host:Port:Name'
|
# format: 'IP:Port' or 'Host:Port' or 'Host:Port:Name'
|
||||||
$rigs = array('127.0.0.1:4028');
|
$rigs = array('127.0.0.1:4028');
|
||||||
#
|
#
|
||||||
|
# Set $rigipsecurity to false to show the IP/Port of the rig
|
||||||
|
# in the socket error messages and also show the full socket message
|
||||||
|
$rigipsecurity = true;
|
||||||
|
#
|
||||||
# Set $rigtotals to true to display totals on the single rig page
|
# Set $rigtotals to true to display totals on the single rig page
|
||||||
# 'false' means no totals (and ignores $forcerigtotals)
|
# 'false' means no totals (and ignores $forcerigtotals)
|
||||||
# You can force it to always show rig totals when there is only
|
# You can force it to always show rig totals when there is only
|
||||||
@ -226,7 +230,7 @@ function htmlhead($checkapi, $rig, $pg = null)
|
|||||||
if ($readonly === false && $checkapi === true)
|
if ($readonly === false && $checkapi === true)
|
||||||
{
|
{
|
||||||
$error = null;
|
$error = null;
|
||||||
$access = api('privileged');
|
$access = api($rig, 'privileged');
|
||||||
if ($error != null
|
if ($error != null
|
||||||
|| !isset($access['STATUS']['STATUS'])
|
|| !isset($access['STATUS']['STATUS'])
|
||||||
|| $access['STATUS']['STATUS'] != 'S')
|
|| $access['STATUS']['STATUS'] != 'S')
|
||||||
@ -275,8 +279,9 @@ global $haderror, $error;
|
|||||||
$haderror = false;
|
$haderror = false;
|
||||||
$error = null;
|
$error = null;
|
||||||
#
|
#
|
||||||
function getsock($addr, $port)
|
function getsock($rig, $addr, $port)
|
||||||
{
|
{
|
||||||
|
global $rigipsecurity;
|
||||||
global $haderror, $error, $socksndtimeoutsec, $sockrcvtimeoutsec;
|
global $haderror, $error, $socksndtimeoutsec, $sockrcvtimeoutsec;
|
||||||
|
|
||||||
$error = null;
|
$error = null;
|
||||||
@ -285,9 +290,15 @@ function getsock($addr, $port)
|
|||||||
if ($socket === false || $socket === null)
|
if ($socket === false || $socket === null)
|
||||||
{
|
{
|
||||||
$haderror = true;
|
$haderror = true;
|
||||||
$error = socket_strerror(socket_last_error());
|
if ($rigipsecurity === false)
|
||||||
$msg = "socket create(TCP) failed";
|
{
|
||||||
$error = "ERR: $msg '$error'\n";
|
$error = socket_strerror(socket_last_error());
|
||||||
|
$msg = "socket create(TCP) failed";
|
||||||
|
$error = "ERR: $msg '$error'\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$error = "ERR: socket create(TCP) failed\n";
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,9 +312,15 @@ function getsock($addr, $port)
|
|||||||
if ($res === false)
|
if ($res === false)
|
||||||
{
|
{
|
||||||
$haderror = true;
|
$haderror = true;
|
||||||
$error = socket_strerror(socket_last_error());
|
if ($rigipsecurity === false)
|
||||||
$msg = "socket connect($addr,$port) failed";
|
{
|
||||||
$error = "ERR: $msg '$error'\n";
|
$error = socket_strerror(socket_last_error());
|
||||||
|
$msg = "socket connect($addr,$port) failed";
|
||||||
|
$error = "ERR: $msg '$error'\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$error = "ERR: socket connect($rig) failed\n";
|
||||||
|
|
||||||
socket_close($socket);
|
socket_close($socket);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -365,12 +382,12 @@ function revert($str)
|
|||||||
return str_replace(array("\1", "\2", "\3", "\4"), array("|", "\\", "=", ","), $str);
|
return str_replace(array("\1", "\2", "\3", "\4"), array("|", "\\", "=", ","), $str);
|
||||||
}
|
}
|
||||||
#
|
#
|
||||||
function api($cmd)
|
function api($rig, $cmd)
|
||||||
{
|
{
|
||||||
global $haderror, $error;
|
global $haderror, $error;
|
||||||
global $miner, $port, $hidefields;
|
global $miner, $port, $hidefields;
|
||||||
|
|
||||||
$socket = getsock($miner, $port);
|
$socket = getsock($rig, $miner, $port);
|
||||||
if ($socket != null)
|
if ($socket != null)
|
||||||
{
|
{
|
||||||
socket_write($socket, $cmd, strlen($cmd));
|
socket_write($socket, $cmd, strlen($cmd));
|
||||||
@ -506,7 +523,15 @@ function classlastshare($when, $alldata, $warnclass, $errorclass)
|
|||||||
if (!isset($alldata['Last Share Time']))
|
if (!isset($alldata['Last Share Time']))
|
||||||
return '';
|
return '';
|
||||||
|
|
||||||
|
if (!isset($alldata['Last Share Difficulty']))
|
||||||
|
return '';
|
||||||
|
|
||||||
$expected = pow(2, 32) / ($alldata['MHS av'] * pow(10, 6));
|
$expected = pow(2, 32) / ($alldata['MHS av'] * pow(10, 6));
|
||||||
|
|
||||||
|
// If the share difficulty changes while waiting on a share,
|
||||||
|
// this calculation will of course be incorrect
|
||||||
|
$expected *= $alldata['Last Share Difficulty'];
|
||||||
|
|
||||||
$howlong = $when - $alldata['Last Share Time'];
|
$howlong = $when - $alldata['Last Share Time'];
|
||||||
if ($howlong < 1)
|
if ($howlong < 1)
|
||||||
$howlong = 1;
|
$howlong = 1;
|
||||||
@ -641,11 +666,20 @@ function fmt($section, $name, $value, $when, $alldata)
|
|||||||
if ($value == 0)
|
if ($value == 0)
|
||||||
$class = $errorclass;
|
$class = $errorclass;
|
||||||
else
|
else
|
||||||
if (isset($alldata['MHS av']))
|
if (isset($alldata['Difficulty Accepted'])
|
||||||
|
&& isset($alldata['Accepted'])
|
||||||
|
&& isset($alldata['MHS av'])
|
||||||
|
&& ($alldata['Difficulty Accepted'] > 0)
|
||||||
|
&& ($alldata['Accepted'] > 0))
|
||||||
{
|
{
|
||||||
$expected = 60 * $alldata['MHS av'] * (pow(10, 6) / pow(2, 32));
|
$expected = 60 * $alldata['MHS av'] * (pow(10, 6) / pow(2, 32));
|
||||||
if ($expected == 0)
|
if ($expected == 0)
|
||||||
$expected = 0.000001; // 1 H/s
|
$expected = 0.000001; // 1 H/s
|
||||||
|
|
||||||
|
$da = $alldata['Difficulty Accepted'];
|
||||||
|
$a = $alldata['Accepted'];
|
||||||
|
$expected /= ($da / $a);
|
||||||
|
|
||||||
$ratio = $value / $expected;
|
$ratio = $value / $expected;
|
||||||
if ($ratio < 0.9)
|
if ($ratio < 0.9)
|
||||||
$class = $loclass;
|
$class = $loclass;
|
||||||
@ -713,16 +747,26 @@ function fmt($section, $name, $value, $when, $alldata)
|
|||||||
$dec = '';
|
$dec = '';
|
||||||
else
|
else
|
||||||
$dec = '.'.$parts[1];
|
$dec = '.'.$parts[1];
|
||||||
$ret = number_format($parts[0]).$dec;
|
$ret = number_format((float)$parts[0]).$dec;
|
||||||
|
|
||||||
if ($value == 0)
|
if ($value == 0)
|
||||||
$class = $errorclass;
|
$class = $errorclass;
|
||||||
else
|
else
|
||||||
if (isset($alldata['Utility']))
|
if (isset($alldata['Difficulty Accepted'])
|
||||||
|
&& isset($alldata['Accepted'])
|
||||||
|
&& isset($alldata['Utility'])
|
||||||
|
&& ($alldata['Difficulty Accepted'] > 0)
|
||||||
|
&& ($alldata['Accepted'] > 0))
|
||||||
{
|
{
|
||||||
$expected = 60 * $value * (pow(10, 6) / pow(2, 32));
|
$expected = 60 * $value * (pow(10, 6) / pow(2, 32));
|
||||||
$utility = $alldata['Utility'];
|
if ($expected == 0)
|
||||||
$ratio = $utility / $expected;
|
$expected = 0.000001; // 1 H/s
|
||||||
|
|
||||||
|
$da = $alldata['Difficulty Accepted'];
|
||||||
|
$a = $alldata['Accepted'];
|
||||||
|
$expected /= ($da / $a);
|
||||||
|
|
||||||
|
$ratio = $alldata['Utility'] / $expected;
|
||||||
if ($ratio < 0.9)
|
if ($ratio < 0.9)
|
||||||
$class = $hiclass;
|
$class = $hiclass;
|
||||||
else
|
else
|
||||||
@ -757,12 +801,15 @@ function fmt($section, $name, $value, $when, $alldata)
|
|||||||
case 'total.Discarded':
|
case 'total.Discarded':
|
||||||
case 'POOL.Diff1 Shares':
|
case 'POOL.Diff1 Shares':
|
||||||
case 'total.Diff1 Shares':
|
case 'total.Diff1 Shares':
|
||||||
|
case 'GPU.Diff1 Work':
|
||||||
|
case 'PGA.Diff1 Work':
|
||||||
|
case 'total.Diff1 Work':
|
||||||
$parts = explode('.', $value, 2);
|
$parts = explode('.', $value, 2);
|
||||||
if (count($parts) == 1)
|
if (count($parts) == 1)
|
||||||
$dec = '';
|
$dec = '';
|
||||||
else
|
else
|
||||||
$dec = '.'.$parts[1];
|
$dec = '.'.$parts[1];
|
||||||
$ret = number_format($parts[0]).$dec;
|
$ret = number_format((float)$parts[0]).$dec;
|
||||||
break;
|
break;
|
||||||
case 'GPU.Status':
|
case 'GPU.Status':
|
||||||
case 'PGA.Status':
|
case 'PGA.Status':
|
||||||
@ -1067,7 +1114,7 @@ function processgpus($rig)
|
|||||||
global $error;
|
global $error;
|
||||||
global $warnfont, $warnoff;
|
global $warnfont, $warnoff;
|
||||||
|
|
||||||
$gpus = api('gpucount');
|
$gpus = api($rig, 'gpucount');
|
||||||
|
|
||||||
if ($error != null)
|
if ($error != null)
|
||||||
otherrow("<td>Error getting GPU count: $warnfont$error$warnoff</td>");
|
otherrow("<td>Error getting GPU count: $warnfont$error$warnoff</td>");
|
||||||
@ -1136,7 +1183,7 @@ function process($cmds, $rig)
|
|||||||
$count = count($cmds);
|
$count = count($cmds);
|
||||||
foreach ($cmds as $cmd => $des)
|
foreach ($cmds as $cmd => $des)
|
||||||
{
|
{
|
||||||
$process = api($cmd);
|
$process = api($rig, $cmd);
|
||||||
|
|
||||||
if ($error != null)
|
if ($error != null)
|
||||||
{
|
{
|
||||||
@ -1251,7 +1298,7 @@ function doforeach($cmd, $des, $sum, $head, $datetime)
|
|||||||
else
|
else
|
||||||
$name = $num;
|
$name = $num;
|
||||||
|
|
||||||
$ans = api($cmd);
|
$ans = api($name, $cmd);
|
||||||
|
|
||||||
if ($error != null)
|
if ($error != null)
|
||||||
{
|
{
|
||||||
@ -1763,7 +1810,7 @@ function processcustompage($pagename, $sections, $sum, $namemap)
|
|||||||
|
|
||||||
foreach ($cmds as $cmd => $one)
|
foreach ($cmds as $cmd => $one)
|
||||||
{
|
{
|
||||||
$process = api($cmd);
|
$process = api($name, $cmd);
|
||||||
|
|
||||||
if ($error != null)
|
if ($error != null)
|
||||||
{
|
{
|
||||||
@ -2052,7 +2099,7 @@ function display()
|
|||||||
|
|
||||||
newtable();
|
newtable();
|
||||||
doforeach('version', 'rig summary', array(), array(), true);
|
doforeach('version', 'rig summary', array(), array(), true);
|
||||||
$sum = array('MHS av', 'Getworks', 'Found Blocks', 'Accepted', 'Rejected', 'Discarded', 'Stale', 'Utility', 'Local Work', 'Total MH', 'Work Utility', 'Diff1 Shares');
|
$sum = array('MHS av', 'Getworks', 'Found Blocks', 'Accepted', 'Rejected', 'Discarded', 'Stale', 'Utility', 'Local Work', 'Total MH', 'Work Utility', 'Diff1 Shares', 'Diff1 Work');
|
||||||
doforeach('summary', 'summary information', $sum, array(), false);
|
doforeach('summary', 'summary information', $sum, array(), false);
|
||||||
endtable();
|
endtable();
|
||||||
otherrow('<td><br><br></td>');
|
otherrow('<td><br><br></td>');
|
||||||
|
74
util.c
74
util.c
@ -305,7 +305,10 @@ json_t *json_rpc_call(CURL *curl, const char *url,
|
|||||||
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, resp_hdr_cb);
|
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, resp_hdr_cb);
|
||||||
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &hi);
|
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &hi);
|
||||||
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);
|
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);
|
||||||
if (opt_socks_proxy) {
|
if (pool->rpc_proxy) {
|
||||||
|
curl_easy_setopt(curl, CURLOPT_PROXY, pool->rpc_proxy);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_PROXYTYPE, pool->rpc_proxytype);
|
||||||
|
} else if (opt_socks_proxy) {
|
||||||
curl_easy_setopt(curl, CURLOPT_PROXY, opt_socks_proxy);
|
curl_easy_setopt(curl, CURLOPT_PROXY, opt_socks_proxy);
|
||||||
curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
|
curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
|
||||||
}
|
}
|
||||||
@ -460,6 +463,69 @@ err_out:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 10) || (LIBCURL_VERSION_MAJOR > 7)
|
||||||
|
static struct {
|
||||||
|
const char *name;
|
||||||
|
curl_proxytype proxytype;
|
||||||
|
} proxynames[] = {
|
||||||
|
{ "http:", CURLPROXY_HTTP },
|
||||||
|
#if (LIBCURL_VERSION_MAJOR > 7) || (LIBCURL_VERSION_MINOR > 19) || (LIBCURL_VERSION_MINOR == 19 && LIBCURL_VERSION_PATCH >= 4)
|
||||||
|
{ "http0:", CURLPROXY_HTTP_1_0 },
|
||||||
|
#endif
|
||||||
|
#if (LIBCURL_VERSION_MAJOR > 7) || (LIBCURL_VERSION_MINOR > 15) || (LIBCURL_VERSION_MINOR == 15 && LIBCURL_VERSION_PATCH >= 2)
|
||||||
|
{ "socks4:", CURLPROXY_SOCKS4 },
|
||||||
|
#endif
|
||||||
|
{ "socks5:", CURLPROXY_SOCKS5 },
|
||||||
|
#if (LIBCURL_VERSION_MAJOR > 7) || (LIBCURL_VERSION_MINOR >= 18)
|
||||||
|
{ "socks4a:", CURLPROXY_SOCKS4A },
|
||||||
|
{ "socks5h:", CURLPROXY_SOCKS5_HOSTNAME },
|
||||||
|
#endif
|
||||||
|
{ NULL, 0 }
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char *proxytype(curl_proxytype proxytype)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; proxynames[i].name; i++)
|
||||||
|
if (proxynames[i].proxytype == proxytype)
|
||||||
|
return proxynames[i].name;
|
||||||
|
|
||||||
|
return "invalid";
|
||||||
|
}
|
||||||
|
|
||||||
|
char *get_proxy(char *url, struct pool *pool)
|
||||||
|
{
|
||||||
|
pool->rpc_proxy = NULL;
|
||||||
|
|
||||||
|
#if (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 10) || (LIBCURL_VERSION_MAJOR > 7)
|
||||||
|
char *split;
|
||||||
|
int plen, len, i;
|
||||||
|
|
||||||
|
for (i = 0; proxynames[i].name; i++) {
|
||||||
|
plen = strlen(proxynames[i].name);
|
||||||
|
if (strncmp(url, proxynames[i].name, plen) == 0) {
|
||||||
|
if (!(split = strchr(url, '|')))
|
||||||
|
return url;
|
||||||
|
|
||||||
|
*split = '\0';
|
||||||
|
len = split - url;
|
||||||
|
pool->rpc_proxy = malloc(1 + len - plen);
|
||||||
|
if (!(pool->rpc_proxy))
|
||||||
|
quit(1, "Failed to malloc rpc_proxy");
|
||||||
|
|
||||||
|
strcpy(pool->rpc_proxy, url + plen);
|
||||||
|
pool->rpc_proxytype = proxynames[i].proxytype;
|
||||||
|
url = split + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
char *bin2hex(const unsigned char *p, size_t len)
|
char *bin2hex(const unsigned char *p, size_t len)
|
||||||
{
|
{
|
||||||
char *s = malloc((len * 2) + 1);
|
char *s = malloc((len * 2) + 1);
|
||||||
@ -722,3 +788,9 @@ double us_tdiff(struct timeval *end, struct timeval *start)
|
|||||||
{
|
{
|
||||||
return end->tv_sec * 1000000 + end->tv_usec - start->tv_sec * 1000000 - start->tv_usec;
|
return end->tv_sec * 1000000 + end->tv_usec - start->tv_sec * 1000000 - start->tv_usec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns the seconds difference between end and start times as a double */
|
||||||
|
double tdiff(struct timeval *end, struct timeval *start)
|
||||||
|
{
|
||||||
|
return end->tv_sec - start->tv_sec + (end->tv_usec - start->tv_usec) / 1000000.0;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user