mirror of
https://github.com/GOSTSec/sgminer
synced 2025-01-13 16:27:54 +00:00
Merge branch 'master' of git://github.com/ckolivas/cgminer.git
This commit is contained in:
commit
7b2ada0ee4
537
API-README
537
API-README
@ -1,6 +1,9 @@
|
||||
|
||||
This README contains details about the cgminer RPC API
|
||||
|
||||
It also includes some detailed information at the end,
|
||||
about using miner.php
|
||||
|
||||
|
||||
If you start cgminer with the "--api-listen" option, it will listen on a
|
||||
simple TCP/IP socket for single string API requests from the same machine
|
||||
@ -119,7 +122,9 @@ The list of requests - a (*) means it requires privileged access - and replies a
|
||||
ADL in use=X, <- Y or N if any GPU has ADL
|
||||
Strategy=Name, <- the current pool strategy
|
||||
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
|
||||
Failover-Only=true/false | <- failover-only setting
|
||||
|
||||
summary SUMMARY The status summary of the miner
|
||||
e.g. Elapsed=NNN,Found Blocks=N,Getworks=N,...|
|
||||
@ -272,6 +277,10 @@ The list of requests - a (*) means it requires privileged access - and replies a
|
||||
check|cmd COMMAND Exists=Y/N, <- 'cmd' exists in this version
|
||||
Access=Y/N| <- you have access to use 'cmd'
|
||||
|
||||
failover-only|true/false (*)
|
||||
none There is no reply section just the STATUS section
|
||||
stating what failover-only was set to
|
||||
|
||||
When you enable, disable or restart a GPU or PGA, you will also get Thread messages
|
||||
in the cgminer status window
|
||||
|
||||
@ -316,7 +325,7 @@ api-example.c - a 'C' program to access the API (with source code)
|
||||
|
||||
miner.php - an example web page to access the API
|
||||
This includes buttons and inputs to attempt access to the privileged commands
|
||||
Read the top of the file (miner.php) for details of how to tune the display
|
||||
See the end of this API-README for details of how to tune the display
|
||||
and also to use the option to display a multi-rig summary
|
||||
|
||||
----------
|
||||
@ -324,7 +333,25 @@ miner.php - an example web page to access the API
|
||||
Feature Changelog for external applications using the API:
|
||||
|
||||
|
||||
API V1.15
|
||||
API V1.17
|
||||
|
||||
Modified API commands:
|
||||
'summary' - add 'Work Utility'
|
||||
'pools' - add 'Diff1 Shares'
|
||||
|
||||
----------
|
||||
|
||||
API V1.16 (cgminer v2.6.5)
|
||||
|
||||
Added API commands:
|
||||
'failover-only'
|
||||
|
||||
Modified API commands:
|
||||
'config' - include failover-only state
|
||||
|
||||
----------
|
||||
|
||||
API V1.15 (cgminer v2.6.1)
|
||||
|
||||
Added API commands:
|
||||
'poolpriority'
|
||||
@ -533,3 +560,507 @@ Commands:
|
||||
'cpucount'
|
||||
'quit'
|
||||
|
||||
----------------------------------------
|
||||
|
||||
miner.php
|
||||
=========
|
||||
|
||||
miner.php is a PHP based interface to the cgminer RPC API
|
||||
(referred to simply as the API below)
|
||||
|
||||
It can show rig details, summaries and input fields to allow you to change
|
||||
cgminer
|
||||
You can also create custom summary pages with it
|
||||
|
||||
It has two levels to the security:
|
||||
1) cgminer can be configured to allow or disallow API access and access level
|
||||
security for miner.php
|
||||
2) miner.php can be configured to allow or disallow privileged cgminer
|
||||
access, if cgminer is configured to allow privileged access for miner.php
|
||||
|
||||
---------
|
||||
|
||||
To use miner.php requires a web server with PHP
|
||||
|
||||
Basics: On xubuntu 11.04, to install apache2 and php, the commands are:
|
||||
sudo apt-get install apache2
|
||||
sudo apt-get install php5
|
||||
sudo /etc/init.d/apache2 reload
|
||||
|
||||
On Fedora 17:
|
||||
yum install httpd php
|
||||
systemctl restart httpd.service
|
||||
systemctl enable httpd.service --system
|
||||
|
||||
On windows there are a few options.
|
||||
Try one of these (I've never used either one)
|
||||
http://www.apachefriends.org/en/xampp.html
|
||||
http://www.wampserver.com/en/
|
||||
|
||||
---------
|
||||
|
||||
The basic cgminer option to enable the API is:
|
||||
|
||||
--api-listen
|
||||
|
||||
or in your cgminer.conf
|
||||
|
||||
"api-listen" : true,
|
||||
|
||||
(without the ',' on the end if it is the last item)
|
||||
|
||||
If the web server is running on the cgminer computer, the above
|
||||
is the only change required to give miner.php basic access to
|
||||
the cgminer API
|
||||
|
||||
-
|
||||
|
||||
If the web server runs on a different computer to cgminer,
|
||||
you will also need to tell cgminer to allow the web server
|
||||
to access cgminer's API and tell miner.php where cgminer is
|
||||
|
||||
Assuming a.b.c.d is the IP address of the web server, you
|
||||
would add the following to cgminer:
|
||||
|
||||
--api-listen --api-allow a.b.c.d
|
||||
|
||||
or in your cgminer.conf
|
||||
|
||||
"api-listen" : true,
|
||||
"api-allow" : "a.b.c.d",
|
||||
|
||||
to tell cgminer to give the web server read access to the API
|
||||
|
||||
You also need to tell miner.php where cgminer is.
|
||||
Assuming cgminer is at IP address e.f.g.h, then you would
|
||||
edit miner.php and change the line
|
||||
|
||||
$rigs = array('127.0.0.1:4028');
|
||||
|
||||
to
|
||||
|
||||
$rigs = array('e.f.g.h:4028');
|
||||
|
||||
See --api-network or --api-allow for more access details
|
||||
and how to give write access
|
||||
|
||||
---------
|
||||
|
||||
Once you have a web server with PHP running
|
||||
|
||||
copy your miner.php to the main web folder
|
||||
|
||||
On Xubuntu 11.04
|
||||
/var/www/
|
||||
|
||||
On Fedora 17
|
||||
/var/www/html/
|
||||
|
||||
On Windows
|
||||
see your windows Web/PHP documentation
|
||||
|
||||
Assuming the IP address of the web server is a.b.c.d
|
||||
Then in your web browser go to:
|
||||
|
||||
http://a.b.c.d/miner.php
|
||||
|
||||
Done :)
|
||||
|
||||
---------
|
||||
|
||||
The rest of this documentation deals with the more complex
|
||||
functions of miner.php, using myminer.php, creaing custom
|
||||
summaries and displaying multiple cgminer rigs
|
||||
|
||||
---------
|
||||
|
||||
If you create a file called myminer.php in the same web folder
|
||||
where you put miner.php, miner.php will load it when it runs
|
||||
|
||||
This is useful, to put any changes you need to make to miner.php
|
||||
instead of changing miner.php
|
||||
Thus if you update/get a new miner.php, you won't lose the changes
|
||||
you have made if you put all your changes in myminer.php
|
||||
(and don't change miner.php at all)
|
||||
|
||||
A simple example myminer.php that defines 2 rigs
|
||||
(that I will keep referring to further below) is:
|
||||
|
||||
<?php
|
||||
#
|
||||
$rigs = array('192.168.0.100:4028:A', '192.168.0.102:4028:B');
|
||||
#
|
||||
?>
|
||||
|
||||
Changes in myminer.php superscede what is in miner.php
|
||||
However, this is only valid for variables in miner.php before the
|
||||
2 lines where myminer.php is included by miner.php:
|
||||
|
||||
if (file_exists('myminer.php'))
|
||||
include_once('myminer.php');
|
||||
|
||||
Every variable in miner.php above those 2 lines, can be changed by
|
||||
simply defining them in your myminer.php
|
||||
|
||||
So although miner.php originally contains the line
|
||||
|
||||
$rigs = array('127.0.0.1:4028');
|
||||
|
||||
if you created the example myminer.php given above, it would actually
|
||||
change the value of $rigs that is used when miner.php is running
|
||||
i.e. you don't have to remove or comment out the $rigs line in miner.php
|
||||
It will be superceded by myminer.php
|
||||
|
||||
---------
|
||||
|
||||
The example.php above also shows how to define more that one rig to
|
||||
be shown my miner.php
|
||||
|
||||
Each rig string is 2 or 3 values seperated by colons ':'
|
||||
They are simply an IP address or host name, followed by the
|
||||
port number (usually 4028) and an optional Name string
|
||||
|
||||
miner.php displays rig buttons that will show the defails of a single
|
||||
rig when you click on it - the button shows either the rig number,
|
||||
or the 'Name' string if you provide it
|
||||
|
||||
PHP arrays contain each string seperated by a comma, but no comma after
|
||||
the last one
|
||||
|
||||
So an example for 3 rigs would be:
|
||||
|
||||
$rigs = array('192.168.0.100:4028:A', '192.168.0.102:4028:B', '192.168.0.110:4028:C');
|
||||
|
||||
Of course each of the rigs listed would also have to have the API
|
||||
running and be set to allow the web server to access the API - as
|
||||
explained before
|
||||
|
||||
---------
|
||||
|
||||
So basically, any variable explained below can be put in myminer.php
|
||||
if you wanted to set it to something different to it's default value
|
||||
and did not want to change miner.php itself every time you updated it
|
||||
|
||||
Below is each variable that can be changed and an explanation of each
|
||||
|
||||
---------
|
||||
|
||||
Default:
|
||||
$readonly = false;
|
||||
|
||||
Set $readonly to true to force miner.php to be readonly
|
||||
This means it won't allow you to change cgminer even if the cgminer API
|
||||
options allow it to
|
||||
|
||||
If you set $readonly to false then it will check cgminer 'privileged'
|
||||
and will show input fields and buttons on the single rig page
|
||||
allowing you to change devices, pools and even quit or restart
|
||||
cgminer
|
||||
|
||||
However, if the 'privileged' test fails, the code will set $readonly to
|
||||
true
|
||||
|
||||
---------
|
||||
|
||||
Default:
|
||||
$notify = true;
|
||||
|
||||
Set $notify to false to NOT attempt to display the notify command
|
||||
table of data
|
||||
|
||||
Set $notify to true to attempt to display the notify command on
|
||||
the single rig page
|
||||
If your older version of cgminer returns an 'Invalid command'
|
||||
coz it doesn't have notify - it just shows the error status table
|
||||
|
||||
---------
|
||||
|
||||
Default:
|
||||
$checklastshare = true;
|
||||
|
||||
Set $checklastshare to true to do the following checks:
|
||||
If a device's last share is 12x expected ago then display as an error
|
||||
If a device's last share is 8x expected ago then display as a warning
|
||||
If either of the above is true, also display the whole line highlighted
|
||||
This assumes shares are 1 difficulty shares
|
||||
|
||||
Set $checklastshare to false to not do the above checks
|
||||
|
||||
'expected' is calculated from the device MH/s value
|
||||
So for example, a device that hashes at 380MH/s should (on average)
|
||||
find a share every 11.3s
|
||||
If the last share was found more than 11.3 x 12 seconds (135.6s) ago,
|
||||
it is considered an error and highlighted
|
||||
If the last share was found more than 11.3 x 8 seconds (90.4s) ago,
|
||||
it is considered a warning and highlighted
|
||||
|
||||
The default highlighting is very subtle
|
||||
|
||||
---------
|
||||
|
||||
Default:
|
||||
$poolinputs = false;
|
||||
|
||||
Set $poolinputs to true to show the input fields for adding a pool
|
||||
and changing the pool priorities on a single rig page
|
||||
However, if $readonly is true, it will not display them
|
||||
|
||||
---------
|
||||
|
||||
Default:
|
||||
$rigs = array('127.0.0.1:4028');
|
||||
|
||||
Set $rigs to an array of your cgminer rigs that are running
|
||||
format: 'IP:Port' or 'Host:Port' or 'Host:Port:Name'
|
||||
If you only have one rig, it will just show the detail of that rig
|
||||
If you have more than one rig it will show a summary of all the rigs
|
||||
with buttons to show the details of each rig -
|
||||
the button contents will be 'Name' rather than rig number, if you
|
||||
specify 'Name'
|
||||
e.g. $rigs = array('127.0.0.1:4028','myrig.com:4028:Sugoi');
|
||||
|
||||
---------
|
||||
|
||||
Default:
|
||||
$rigtotals = true;
|
||||
$forcerigtotals = false;
|
||||
|
||||
Set $rigtotals to true to display totals on the single rig page
|
||||
'false' means no totals (and ignores $forcerigtotals)
|
||||
|
||||
If $rigtotals is true, all data is also right aligned
|
||||
With false, it's as before, left aligned
|
||||
|
||||
This option is just here to allow people to set it to false
|
||||
if they prefer the old non-total display when viewing a single rig
|
||||
|
||||
Also, if there is only one line shown in any section, then no
|
||||
total will be shown (to save screen space)
|
||||
You can force it to always show rig totals on the single rig page,
|
||||
even if there is only one line, by setting $forcerigtotals = true;
|
||||
|
||||
---------
|
||||
|
||||
Default:
|
||||
$socksndtimeoutsec = 10;
|
||||
$sockrcvtimeoutsec = 40;
|
||||
|
||||
The numbers are integer seconds
|
||||
|
||||
The defaults should be OK for most cases
|
||||
However, the longer SND is, the longer you have to wait while
|
||||
php hangs if the target cgminer isn't runnning or listening
|
||||
|
||||
RCV should only ever be relevant if cgminer has hung but the
|
||||
API thread is still running, RCV would normally be >= SND
|
||||
|
||||
Feel free to increase SND if your network is very slow
|
||||
or decrease RCV if that happens often to you
|
||||
|
||||
Also, on some windows PHP, apparently the $usec is ignored
|
||||
(so usec can't be specified)
|
||||
|
||||
---------
|
||||
|
||||
Default:
|
||||
$hidefields = array();
|
||||
|
||||
List of fields NOT to be displayed
|
||||
You can use this to hide data you don't want to see or don't want
|
||||
shown on a public web page
|
||||
The list of sections are:
|
||||
SUMMARY, POOL, PGA, GPU, NOTIFY, CONFIG, DEVDETAILS, DEVS
|
||||
See the web page for the list of field names (the table headers)
|
||||
It is an array of 'SECTION.Field Name' => 1
|
||||
|
||||
This example would hide the slightly more sensitive pool information:
|
||||
Pool URL and pool username:
|
||||
$hidefields = array('POOL.URL' => 1, 'POOL.User' => 1);
|
||||
|
||||
If you just want to hide the pool username:
|
||||
$hidefields = array('POOL.User' => 1);
|
||||
|
||||
---------
|
||||
|
||||
Default:
|
||||
$ignorerefresh = false;
|
||||
$changerefresh = true;
|
||||
$autorefresh = 0;
|
||||
|
||||
Auto-refresh of the page (in seconds) - integers only
|
||||
|
||||
$ignorerefresh = true/false always ignore refresh parameters
|
||||
$changerefresh = true/false show buttons to change the value
|
||||
$autorefresh = default value, 0 means dont auto-refresh
|
||||
|
||||
---------
|
||||
|
||||
Default:
|
||||
$placebuttons = 'top';
|
||||
|
||||
Where to place the Refresh, Summary, Custom Pages, Quit, etc. buttons
|
||||
|
||||
Valid values are: 'top' 'bot' 'both'
|
||||
anything else means don't show them - case sensitive
|
||||
|
||||
---------
|
||||
|
||||
Default:
|
||||
$miner_font_family = 'verdana,arial,sans';
|
||||
$miner_font_size = '13pt';
|
||||
|
||||
Change these to set the font and font size used on the web page
|
||||
|
||||
---------
|
||||
|
||||
Default:
|
||||
$colouroverride = array();
|
||||
|
||||
Use this to change the web page colour scheme
|
||||
|
||||
See $colourtable in miner.php for the list of possible names to change
|
||||
|
||||
Simply put in $colouroverride, just the colours you wish to change
|
||||
|
||||
e.g. to change the colour of the header font and background
|
||||
you could do the following:
|
||||
|
||||
$colouroverride = array(
|
||||
'td.h color' => 'green',
|
||||
'td.h background' => 'blue'
|
||||
);
|
||||
|
||||
---------
|
||||
|
||||
Default:
|
||||
$allowcustompages = true;
|
||||
|
||||
Should we allow custom pages?
|
||||
(or just completely ignore them and don't display the buttons)
|
||||
|
||||
---------
|
||||
|
||||
OK this part is more complex: Custom Summary Pages
|
||||
|
||||
A custom summary page in an array of 'section' => array('FieldA','FieldB'...)
|
||||
|
||||
The section defines what data you want in the summary table and the Fields
|
||||
define what data you want shown from that section
|
||||
|
||||
Standard sections are:
|
||||
SUMMARY, POOL, PGA, GPU, NOTIFY, CONFIG, DEVDETAILS, DEVS, STATS
|
||||
|
||||
Fields are the names as shown on the headers on the normal pages
|
||||
|
||||
Fields can be 'name=new name' to display 'name' with a different heading
|
||||
'new name'
|
||||
|
||||
There are also now joined sections:
|
||||
SUMMARY+POOL, SUMMARY+DEVS, SUMMARY+CONFIG, DEVS+NOTIFY, DEVS+DEVDETAILS
|
||||
|
||||
These sections are an SQL join of the two sections and the fields in them
|
||||
are named section.field where section. is the section the field comes from
|
||||
See the example further down
|
||||
|
||||
Also note:
|
||||
- empty tables are not shown
|
||||
- empty columns (e.g. an unknown field) are not shown
|
||||
- missing field data shows as blank
|
||||
- the field name '*' matches all fields except in joined sections
|
||||
(useful for STATS)
|
||||
|
||||
There are 2 hard coded sections:
|
||||
DATE - displays a date table like 'Summary'
|
||||
RIGS - displays a rig table like 'Summary'
|
||||
|
||||
Each custom summary requires a second array, that can be empty, listing fields
|
||||
to be totaled for each section
|
||||
If there is no matching total data, no total will show
|
||||
|
||||
---------
|
||||
|
||||
Looking at the Mobile example:
|
||||
|
||||
$mobilepage = array(
|
||||
'DATE' => null,
|
||||
'RIGS' => null,
|
||||
'SUMMARY' => array('Elapsed', 'MHS av', 'Found Blocks=Blks',
|
||||
Accepted', 'Rejected=Rej', 'Utility'),
|
||||
'DEVS+NOTIFY' => array('DEVS.Name=Name', 'DEVS.ID=ID', 'DEVS.Status=Status',
|
||||
'DEVS.Temperature=Temp', 'DEVS.MHS av=MHS av',
|
||||
'DEVS.Accepted=Accept', 'DEVS.Rejected=Rej',
|
||||
'DEVS.Utility=Utility', 'NOTIFY.Last Not Well=Not Well'),
|
||||
'POOL' => array('POOL', 'Status', 'Accepted', 'Rejected=Rej', 'Last Share Time'));
|
||||
|
||||
$mobilesum = array(
|
||||
'SUMMARY' => array('MHS av', 'Found Blocks', 'Accepted', 'Rejected', 'Utility'),
|
||||
'DEVS+NOTIFY' => array('DEVS.MHS av', 'DEVS.Accepted', 'DEVS.Rejected', 'DEVS.Utility'),
|
||||
'POOL' => array('Accepted', 'Rejected'));
|
||||
|
||||
$customsummarypages = array('Mobile' => array($mobilepage, $mobilesum));
|
||||
|
||||
This will show 5 tables (according to $mobilepage)
|
||||
Each table will have the chosen details for all the rigs specified in $rigs
|
||||
|
||||
DATE
|
||||
A single box with the web server's current date and time
|
||||
|
||||
RIGS
|
||||
A table of the rigs: description, time, versions etc
|
||||
|
||||
SUMMARY
|
||||
|
||||
This will use the API 'summary' command and show the selected fields:
|
||||
Elapsed, MHS av, Found Blocks, Accepted, Rejected and Utility
|
||||
However, 'Rejected=Rej' means that the header displayed for the 'Rejected'
|
||||
field will be 'Rej', instead of 'Rejected' (to save space)
|
||||
Same for 'Found Blocks=Blks' - to save space
|
||||
|
||||
DEVS+NOTIFY
|
||||
|
||||
This will list each of the devices on each rig and display the list of
|
||||
fields as shown
|
||||
It will also include the 'Last Not Well' field from the 'notify' command
|
||||
so you know when the device was last not well
|
||||
|
||||
You will notice that you need to rename each field e.g. 'DEVS.Name=Name'
|
||||
since each field name in the join between DEVS and NOTIFY is actually
|
||||
section.fieldname, not just fieldname
|
||||
|
||||
The join code automatically adds 2 fields to each GPU device: 'Name' and 'ID'
|
||||
They don't exist in the API 'devs' output but you can correctly calculate
|
||||
them from the GPU device data
|
||||
These two fields are used to join DEVS to NOTIFY i.e. find the NOTIFY
|
||||
record that has the same Name and ID as the DEVS record and join them
|
||||
|
||||
POOL
|
||||
|
||||
This will use the API 'pools' command and show the selected fields:
|
||||
POOL, Status, Accepted, Rejected, Last Share Time
|
||||
Again, I renamed the 'Rejected' field using 'Rejected=Rej', to save space
|
||||
|
||||
$mobilesum lists the sections and fields that should have a total
|
||||
You can't define them for 'DATE' or 'RIGS' since they are hard coded tables
|
||||
The example given:
|
||||
|
||||
SUMMARY
|
||||
Show a total at the bottom of the columns for:
|
||||
MHS av, Found Blocks, Accepted, Rejected, Utility
|
||||
|
||||
Firstly note that you use the original name i.e. for 'Rejected=Rej'
|
||||
you use 'Rejected', not 'Rej' and not 'Rejected=Rej'
|
||||
|
||||
Secondly note that it simply adds up the fields
|
||||
If you ask for a total of a string field you will get the numerical
|
||||
sum of the string data
|
||||
|
||||
DEVS+NOTIFY
|
||||
|
||||
Simply note in this join example that you must use the original field
|
||||
names which are section.fieldname, not just fieldname
|
||||
|
||||
POOL
|
||||
Show a total at the bottom of the columns for:
|
||||
Accepted and Rejected
|
||||
|
||||
Again remember to use the original field name 'Rejected'
|
||||
|
80
NEWS
80
NEWS
@ -1,3 +1,83 @@
|
||||
Version 2.7.0 - August 18, 2012
|
||||
|
||||
- Introduce a new statistic, Work Utility, which is the number of difficulty 1
|
||||
shares solved per minute. This is useful for measuring a relative rate of work
|
||||
that is independent of reject rate and target difficulty.
|
||||
- Implement a new pool strategy, BALANCE, which monitors work performed per pool
|
||||
as a rolling average every 10 minutes to try and distribute work evenly over all
|
||||
the pools. Do this by monitoring diff1 solutions to allow different difficulty
|
||||
target pools to be treated equally, along with solo mining. Update the
|
||||
documentation to describe this strategy and more accurately describe the
|
||||
load-balance one.
|
||||
- Getwork fail was not being detected. Remove a vast amount of unused variables
|
||||
and functions used in the old queue request mechanism and redefine the getfail
|
||||
testing.
|
||||
- Don't try to start devices that don't support scrypt when scrypt mining.
|
||||
- 0 is a valid return value for read so only break out if read returns -1.
|
||||
- Consider us lagging only once our queue is almost full and no staged work.
|
||||
- Simplify the enough work algorithm dramatically.
|
||||
- Only queue from backup pools once we have nothing staged.
|
||||
- Don't keep queueing work indefinitely if we're in opt failover mode.
|
||||
- Make sure we don't opt out of queueing more work if all the queued work is
|
||||
from one pool.
|
||||
- Set lagging flag if we're on the last of our staged items.
|
||||
- Reinstate clone on grabbing work.
|
||||
- Grab clones from hashlist wherever possible first.
|
||||
- Cull all the early queue requests since we request every time work is popped
|
||||
now.
|
||||
- Keep track of staged rollable work item counts to speed up clone_available.
|
||||
- Make expiry on should_roll to 2/3 time instead of share duration since some
|
||||
hardware will have very fast share times.
|
||||
- Do the cheaper comparison first.
|
||||
- Check that we'll get 1 shares' worth of work time by rolling before saying we
|
||||
should roll the work.
|
||||
- Simplify all those total_secs usages by initialising it to 1 second.
|
||||
- Overlap queued decrementing with staged incrementing.
|
||||
- Artificially set the pool lagging flag on pool switch in failover only mode as
|
||||
well.
|
||||
- Artificially set the pool lagging flag on work restart to avoid messages about
|
||||
slow pools after every longpoll.
|
||||
- Factor in opt_queue value into enough work queued or staged.
|
||||
- Roll work whenever we can on getwork.
|
||||
- Queue requests for getwork regardless and test whether we should send for a
|
||||
getwork from the getwork thread itself.
|
||||
- Get rid of age_work().
|
||||
- 0 is a valid return value for read so only break out if read returns -1.
|
||||
- Offset libusb reads/writes by length written as well in ztex.
|
||||
- Cope with timeouts and partial reads in ztex code.
|
||||
- fpga serial I/O extra debug (disabled by default)
|
||||
|
||||
|
||||
Version 2.6.5 - August 15, 2012
|
||||
|
||||
- Don't try to get bitforce temperature if we're polling for a result to
|
||||
minimise the chance of interleaved responses.
|
||||
- Set memory clock based on memdiff if present from with engine changes,
|
||||
allowing it to parallel manual changes from the menu as well.
|
||||
- Increase the timeout on bitforce as per Paul Sheppard's suggestion to account
|
||||
for throttling + work time + excess.
|
||||
- Fix ADL gpu-map not working when there are more ADL devices than openCL.
|
||||
Initial patch supplied by Nite69. Modified to suit.
|
||||
- Windows' timer resolution is limited to 15ms accuracy. This was breaking
|
||||
dynamic intensity since it tries to measure below this. Since we are repeatedly
|
||||
sampling similar timeframes, we can average the gpu_us result over 5 different
|
||||
values to get very fine precision.
|
||||
- Fix harmless unused warnings in scrypt.h.
|
||||
- api.c typo
|
||||
- API allow display/change failover-only setting
|
||||
- Check we are not lagging as well as there is enough work in getwork.
|
||||
- Minimise locking and unlocking when getting counts by reusing shared mutex
|
||||
lock functions.
|
||||
- Avoid getting more work if by the time the getwork thread is spawned we find
|
||||
ourselves with enough work.
|
||||
- The bitforce buffer is cleared and hw error count incremented on return from a
|
||||
failed send_work already so no need to do it within the send_work function.
|
||||
- miner.php allow a custom page section to select all fields with '*' - e.g. to
|
||||
create a STATS section on a custom page
|
||||
- Escape " and \ when writing json config file
|
||||
- miner.php optional single rig totals (on by default)
|
||||
|
||||
|
||||
Version 2.6.4 - August 7, 2012
|
||||
|
||||
- Convert the serial autodetect functions to use int instead of char to
|
||||
|
21
README
21
README
@ -141,12 +141,13 @@ Options for both config file and command line:
|
||||
--api-port Port number of miner API (default: 4028)
|
||||
--auto-fan Automatically adjust all GPU fan speeds to maintain a target temperature
|
||||
--auto-gpu Automatically adjust all GPU engine clock speeds to maintain a target temperature
|
||||
--balance Change multipool strategy from failover to even share balance
|
||||
--benchmark Run cgminer in benchmark mode - produces no shares
|
||||
--debug|-D Enable debug output
|
||||
--expiry|-E <arg> Upper bound on how many seconds after getting work we consider a share from it stale (default: 120)
|
||||
--failover-only Don't leak work to backup pools when primary pool is lagging
|
||||
--kernel-path|-K <arg> Specify a path to where bitstream and kernel files are (default: "/usr/local/bin")
|
||||
--load-balance Change multipool strategy from failover to even load balance
|
||||
--load-balance Change multipool strategy from failover to efficiency based balance
|
||||
--log|-l <arg> Interval in seconds between log output (default: 5)
|
||||
--monitor|-m <arg> Use custom pipe cmd for output messages
|
||||
--net-delay Impose small delays in networking to not overload slow routers
|
||||
@ -386,7 +387,7 @@ The number of hardware erorrs
|
||||
The utility defines as the number of shares / minute
|
||||
|
||||
The cgminer status line shows:
|
||||
TQ: 1 ST: 1 SS: 0 DW: 0 NB: 1 LW: 8 GF: 1 RF: 1
|
||||
TQ: 1 ST: 1 SS: 0 DW: 0 NB: 1 LW: 8 GF: 1 RF: 1 WU:4.4/m
|
||||
|
||||
TQ is Total Queued work items.
|
||||
ST is STaged work items (ready to use).
|
||||
@ -396,6 +397,7 @@ NB is New Blocks detected on the network
|
||||
LW is Locally generated Work items
|
||||
GF is Getwork Fail Occasions (server slow to provide work)
|
||||
RF is Remote Fail occasions (server slow to accept work)
|
||||
WU is Work Utility (Rate of difficulty 1 shares solved per minute)
|
||||
|
||||
NOTE: Running intensities above 9 with current hardware is likely to only
|
||||
diminish return performance even if the hash rate might appear better. A good
|
||||
@ -425,8 +427,14 @@ This strategy moves at user-defined intervals from one active pool to the next,
|
||||
skipping pools that are idle.
|
||||
|
||||
LOAD BALANCE:
|
||||
This strategy sends work in equal amounts to all the pools specified. If any
|
||||
pool falls idle, the rest will take up the slack keeping the miner busy.
|
||||
This strategy sends work to all the pools to maintain optimum load. The most
|
||||
efficient pools will tend to get a lot more shares. If any pool falls idle, the
|
||||
rest will tend to take up the slack keeping the miner busy.
|
||||
|
||||
BALANCE:
|
||||
This strategy monitors the amount of difficulty 1 shares solved for each pool
|
||||
and uses it to try to end up doing the same amount of work for all pools.
|
||||
|
||||
|
||||
---
|
||||
LOGGING
|
||||
@ -838,9 +846,8 @@ mining. Since the acronym needs to be only 3 characters, the "Field-" part has
|
||||
been skipped.
|
||||
|
||||
Q: How do I get my BFL device to auto-recognise?
|
||||
A: They are only automatically recognised on linux, and no option needs to be
|
||||
passed to them. The only thing that needs to be done is to load the driver for
|
||||
them, which on linux would require:
|
||||
A: The only thing that needs to be done is to load the driver for them, which
|
||||
on linux would require:
|
||||
sudo modprobe ftdi_sio vendor=0x0403 product=0x6014
|
||||
|
||||
|
||||
|
11
adl.c
11
adl.c
@ -339,6 +339,9 @@ void init_adl(int nDevs)
|
||||
}
|
||||
}
|
||||
|
||||
if (devices > nDevs)
|
||||
devices = nDevs;
|
||||
|
||||
for (gpu = 0; gpu < devices; gpu++) {
|
||||
struct gpu_adl *ga;
|
||||
int iAdapterIndex;
|
||||
@ -788,6 +791,7 @@ static void get_enginerange(int gpu, int *imin, int *imax)
|
||||
int set_engineclock(int gpu, int iEngineClock)
|
||||
{
|
||||
ADLODPerformanceLevels *lpOdPerformanceLevels;
|
||||
struct cgpu_info *cgpu;
|
||||
int i, lev, ret = 1;
|
||||
struct gpu_adl *ga;
|
||||
|
||||
@ -829,6 +833,11 @@ int set_engineclock(int gpu, int iEngineClock)
|
||||
ga->managed = true;
|
||||
out:
|
||||
unlock_adl();
|
||||
|
||||
cgpu = &gpus[gpu];
|
||||
if (cgpu->gpu_memdiff)
|
||||
set_memoryclock(gpu, iEngineClock / 100 + cgpu->gpu_memdiff);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1194,8 +1203,6 @@ void gpu_autotune(int gpu, enum dev_enable *denable)
|
||||
newengine /= 100;
|
||||
applog(LOG_INFO, "Setting GPU %d engine clock to %d", gpu, newengine);
|
||||
set_engineclock(gpu, newengine);
|
||||
if (cgpu->gpu_memdiff)
|
||||
set_memoryclock(gpu, newengine + cgpu->gpu_memdiff);
|
||||
}
|
||||
}
|
||||
ga->lasttemp = temp;
|
||||
|
48
api.c
48
api.c
@ -166,7 +166,7 @@ static const char SEPARATOR = '|';
|
||||
#define SEPSTR "|"
|
||||
static const char GPUSEP = ',';
|
||||
|
||||
static const char *APIVERSION = "1.15";
|
||||
static const char *APIVERSION = "1.17";
|
||||
static const char *DEAD = "Dead";
|
||||
static const char *SICK = "Sick";
|
||||
static const char *NOSTART = "NoStart";
|
||||
@ -184,6 +184,9 @@ static const char *YES = "Y";
|
||||
static const char *NO = "N";
|
||||
static const char *NULLSTR = "(null)";
|
||||
|
||||
static const char *TRUESTR = "true";
|
||||
static const char *FALSESTR = "false";
|
||||
|
||||
static const char *DEVICECODE = ""
|
||||
#ifdef HAVE_OPENCL
|
||||
"GPU "
|
||||
@ -376,6 +379,9 @@ static const char *JSON_PARAMETER = "parameter";
|
||||
#define MSG_CHECK 72
|
||||
#define MSG_POOLPRIO 73
|
||||
#define MSG_DUPPID 74
|
||||
#define MSG_MISBOOL 75
|
||||
#define MSG_INVBOOL 76
|
||||
#define MSG_FOO 77
|
||||
|
||||
enum code_severity {
|
||||
SEVERITY_ERR,
|
||||
@ -403,6 +409,7 @@ enum code_parameters {
|
||||
PARAM_POOL,
|
||||
PARAM_STR,
|
||||
PARAM_BOTH,
|
||||
PARAM_BOOL,
|
||||
PARAM_NONE
|
||||
};
|
||||
|
||||
@ -524,6 +531,9 @@ struct CODES {
|
||||
{ SEVERITY_SUCC, MSG_MINESTATS,PARAM_NONE, "CGMiner stats" },
|
||||
{ SEVERITY_ERR, MSG_MISCHK, PARAM_NONE, "Missing check cmd" },
|
||||
{ SEVERITY_SUCC, MSG_CHECK, PARAM_NONE, "Check command" },
|
||||
{ SEVERITY_ERR, MSG_MISBOOL, PARAM_NONE, "Missing parameter: true/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_FAIL, 0, 0, NULL }
|
||||
};
|
||||
|
||||
@ -928,7 +938,7 @@ static struct api_data *print_data(struct api_data *root, char *buf, bool isjson
|
||||
sprintf(buf, "%.15f", *((double *)(root->data)));
|
||||
break;
|
||||
case API_BOOL:
|
||||
sprintf(buf, "%s", *((bool *)(root->data)) ? "true" : "false");
|
||||
sprintf(buf, "%s", *((bool *)(root->data)) ? TRUESTR : FALSESTR);
|
||||
break;
|
||||
case API_TIMEVAL:
|
||||
sprintf(buf, "%ld.%06ld",
|
||||
@ -1133,6 +1143,9 @@ static char *message(int messageid, int paramid, char *param2, bool isjson)
|
||||
case PARAM_BOTH:
|
||||
sprintf(buf, codes[i].description, paramid, param2);
|
||||
break;
|
||||
case PARAM_BOOL:
|
||||
sprintf(buf, codes[i].description, paramid ? TRUESTR : FALSESTR);
|
||||
break;
|
||||
case PARAM_NONE:
|
||||
default:
|
||||
strcpy(buf, codes[i].description);
|
||||
@ -1233,6 +1246,7 @@ static void minerconfig(__maybe_unused SOCKETTYPE c, __maybe_unused char *param,
|
||||
root = api_add_int(root, "Log Interval", &opt_log_interval, false);
|
||||
root = api_add_const(root, "Device Code", DEVICECODE, false);
|
||||
root = api_add_const(root, "OS", OSINFO, false);
|
||||
root = api_add_bool(root, "Failover-Only", &opt_fail_only, false);
|
||||
|
||||
root = print_data(root, buf, isjson);
|
||||
if (isjson)
|
||||
@ -1240,8 +1254,7 @@ static void minerconfig(__maybe_unused SOCKETTYPE c, __maybe_unused char *param,
|
||||
strcat(io_buffer, buf);
|
||||
}
|
||||
|
||||
static const char*
|
||||
status2str(enum alive status)
|
||||
static const char *status2str(enum alive status)
|
||||
{
|
||||
switch (status) {
|
||||
case LIFE_WELL:
|
||||
@ -1766,6 +1779,7 @@ static void poolstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param,
|
||||
root = api_add_uint(root, "Remote Failures", &(pool->remotefail_occasions), 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_int(root, "Diff1 Shares", &(pool->diff1), false);
|
||||
|
||||
if (isjson && (i > 0))
|
||||
strcat(io_buffer, COMMA);
|
||||
@ -1782,7 +1796,7 @@ static void summary(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, boo
|
||||
{
|
||||
struct api_data *root = NULL;
|
||||
char buf[TMPBUFSIZ];
|
||||
double utility, mhs;
|
||||
double utility, mhs, work_utility;
|
||||
|
||||
#ifdef WANT_CPUMINE
|
||||
char *algo = (char *)(algo_names[opt_algo]);
|
||||
@ -1792,6 +1806,7 @@ static void summary(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, boo
|
||||
|
||||
utility = total_accepted / ( total_secs ? total_secs : 1 ) * 60;
|
||||
mhs = total_mhashes_done / total_secs;
|
||||
work_utility = total_diff1 / ( total_secs ? total_secs : 1 ) * 60;
|
||||
|
||||
sprintf(io_buffer, isjson
|
||||
? "%s," JSON_SUMMARY
|
||||
@ -1816,6 +1831,7 @@ static void summary(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, boo
|
||||
root = api_add_uint(root, "Remote Failures", &(total_ro), 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_utility(root, "Work Utility", &(work_utility), false);
|
||||
|
||||
root = print_data(root, buf, isjson);
|
||||
if (isjson)
|
||||
@ -2704,6 +2720,27 @@ static void minerstats(__maybe_unused SOCKETTYPE c, __maybe_unused char *param,
|
||||
strcat(io_buffer, JSON_CLOSE);
|
||||
}
|
||||
|
||||
static void failoveronly(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
if (param == NULL || *param == '\0') {
|
||||
strcpy(io_buffer, message(MSG_MISBOOL, 0, NULL, isjson));
|
||||
return;
|
||||
}
|
||||
|
||||
*param = tolower(*param);
|
||||
|
||||
if (*param != 't' && *param != 'f') {
|
||||
strcpy(io_buffer, message(MSG_INVBOOL, 0, NULL, isjson));
|
||||
return;
|
||||
}
|
||||
|
||||
bool tf = (*param == 't');
|
||||
|
||||
opt_fail_only = tf;
|
||||
|
||||
strcpy(io_buffer, message(MSG_FOO, tf, NULL, isjson));
|
||||
}
|
||||
|
||||
static void checkcommand(__maybe_unused SOCKETTYPE c, char *param, bool isjson, char group);
|
||||
|
||||
struct CMDS {
|
||||
@ -2754,6 +2791,7 @@ struct CMDS {
|
||||
{ "restart", dorestart, true },
|
||||
{ "stats", minerstats, false },
|
||||
{ "check", checkcommand, false },
|
||||
{ "failover-only", failoveronly, true },
|
||||
{ NULL, NULL, false }
|
||||
};
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
|
||||
##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
|
||||
m4_define([v_maj], [2])
|
||||
m4_define([v_min], [6])
|
||||
m4_define([v_mic], [4])
|
||||
m4_define([v_min], [7])
|
||||
m4_define([v_mic], [0])
|
||||
##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
|
||||
m4_define([v_ver], [v_maj.v_min.v_mic])
|
||||
m4_define([lt_rev], m4_eval(v_maj + v_min))
|
||||
|
@ -51,7 +51,7 @@ enum {
|
||||
#define BITFORCE_SLEEP_MS 500
|
||||
#define BITFORCE_TIMEOUT_S 7
|
||||
#define BITFORCE_TIMEOUT_MS (BITFORCE_TIMEOUT_S * 1000)
|
||||
#define BITFORCE_LONG_TIMEOUT_S 15
|
||||
#define BITFORCE_LONG_TIMEOUT_S 30
|
||||
#define BITFORCE_LONG_TIMEOUT_MS (BITFORCE_LONG_TIMEOUT_S * 1000)
|
||||
#define BITFORCE_CHECK_INTERVAL_MS 10
|
||||
#define WORK_CHECK_INTERVAL_MS 50
|
||||
@ -347,6 +347,11 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce)
|
||||
if (!fdDev)
|
||||
return false;
|
||||
|
||||
/* Do not try to get the temperature if we're polling for a result to
|
||||
* minimise the change of interleaved results */
|
||||
if (bitforce->polling)
|
||||
return true;
|
||||
|
||||
/* It is not critical getting temperature so don't get stuck if we
|
||||
* can't grab the mutex here */
|
||||
if (mutex_trylock(&bitforce->device_mutex))
|
||||
@ -421,8 +426,6 @@ re_send:
|
||||
goto re_send;
|
||||
}
|
||||
applog(LOG_ERR, "BFL%i: Error: Send work reports: %s", bitforce->device_id, pdevbuf);
|
||||
bitforce->hw_errors++;
|
||||
bitforce_clear_buffer(bitforce);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -463,8 +466,6 @@ re_send:
|
||||
|
||||
if (unlikely(strncasecmp(pdevbuf, "OK", 2))) {
|
||||
applog(LOG_ERR, "BFL%i: Error: Send block data reports: %s", bitforce->device_id, pdevbuf);
|
||||
bitforce->hw_errors++;
|
||||
bitforce_clear_buffer(bitforce);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -601,39 +602,21 @@ static void biforce_thread_enable(struct thr_info *thr)
|
||||
static int64_t bitforce_scanhash(struct thr_info *thr, struct work *work, int64_t __maybe_unused max_nonce)
|
||||
{
|
||||
struct cgpu_info *bitforce = thr->cgpu;
|
||||
unsigned int sleep_time;
|
||||
bool send_ret;
|
||||
int64_t ret;
|
||||
|
||||
send_ret = bitforce_send_work(thr, work);
|
||||
|
||||
if (!bitforce->nonce_range) {
|
||||
/* Initially wait 2/3 of the average cycle time so we can request more
|
||||
work before full scan is up */
|
||||
sleep_time = (2 * bitforce->sleep_ms) / 3;
|
||||
if (!restart_wait(sleep_time))
|
||||
return 0;
|
||||
if (!restart_wait(bitforce->sleep_ms))
|
||||
return 0;
|
||||
|
||||
bitforce->wait_ms = sleep_time;
|
||||
queue_request(thr, false);
|
||||
bitforce->wait_ms = bitforce->sleep_ms;
|
||||
|
||||
/* Now wait athe final 1/3rd; no bitforce should be finished by now */
|
||||
sleep_time = bitforce->sleep_ms - sleep_time;
|
||||
if (!restart_wait(sleep_time))
|
||||
return 0;
|
||||
|
||||
bitforce->wait_ms += sleep_time;
|
||||
} else {
|
||||
sleep_time = bitforce->sleep_ms;
|
||||
if (!restart_wait(sleep_time))
|
||||
return 0;
|
||||
|
||||
bitforce->wait_ms = sleep_time;
|
||||
}
|
||||
|
||||
if (send_ret)
|
||||
if (send_ret) {
|
||||
bitforce->polling = true;
|
||||
ret = bitforce_get_result(thr, work);
|
||||
else
|
||||
bitforce->polling = false;
|
||||
} else
|
||||
ret = -1;
|
||||
|
||||
if (ret == -1) {
|
||||
|
@ -1490,6 +1490,7 @@ static int64_t opencl_scanhash(struct thr_info *thr, struct work *work,
|
||||
_clState *clState = clStates[thr_id];
|
||||
const cl_kernel *kernel = &clState->kernel;
|
||||
const int dynamic_us = opt_dynamic_interval * 1000;
|
||||
struct timeval tv_gpuend;
|
||||
cl_bool blocking;
|
||||
|
||||
cl_int status;
|
||||
@ -1508,13 +1509,17 @@ static int64_t opencl_scanhash(struct thr_info *thr, struct work *work,
|
||||
clFinish(clState->commandQueue);
|
||||
|
||||
if (gpu->dynamic) {
|
||||
struct timeval diff;
|
||||
suseconds_t gpu_us;
|
||||
double gpu_us;
|
||||
|
||||
gettimeofday(&gpu->tv_gpuend, NULL);
|
||||
timersub(&gpu->tv_gpuend, &gpu->tv_gpustart, &diff);
|
||||
gpu_us = diff.tv_sec * 1000000 + diff.tv_usec;
|
||||
if (likely(gpu_us >= 0)) {
|
||||
/* Windows returns the same time for gettimeofday due to its
|
||||
* 15ms timer resolution, so we must average the result over
|
||||
* at least 5 values that are actually different to get an
|
||||
* accurate result */
|
||||
gpu->intervals++;
|
||||
gettimeofday(&tv_gpuend, NULL);
|
||||
gpu_us = us_tdiff(&tv_gpuend, &gpu->tv_gpumid);
|
||||
if (gpu_us > 0 && ++gpu->hit > 4) {
|
||||
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
|
||||
@ -1527,6 +1532,7 @@ static int64_t opencl_scanhash(struct thr_info *thr, struct work *work,
|
||||
if (gpu->intensity < MAX_INTENSITY)
|
||||
++gpu->intensity;
|
||||
}
|
||||
gpu->intervals = gpu->hit = 0;
|
||||
}
|
||||
}
|
||||
set_threads_hashes(clState->vwidth, &threads, &hashes, globalThreads,
|
||||
@ -1562,7 +1568,11 @@ static int64_t opencl_scanhash(struct thr_info *thr, struct work *work,
|
||||
clFinish(clState->commandQueue);
|
||||
}
|
||||
|
||||
gettimeofday(&gpu->tv_gpustart, NULL);
|
||||
gettimeofday(&gpu->tv_gpumid, NULL);
|
||||
if (!gpu->intervals) {
|
||||
gpu->tv_gpustart.tv_sec = gpu->tv_gpumid.tv_sec;
|
||||
gpu->tv_gpustart.tv_usec = gpu->tv_gpumid.tv_usec;
|
||||
}
|
||||
|
||||
if (clState->goffset) {
|
||||
size_t global_work_offset[1];
|
||||
|
193
fpgautils.c
193
fpgautils.c
@ -143,6 +143,174 @@ _serial_detect(const char*dname, detectone_func_t detectone, autoscan_func_t aut
|
||||
return found;
|
||||
}
|
||||
|
||||
// This code is purely for debugging but is very useful for that
|
||||
// It also took quite a bit of effort so I left it in
|
||||
// #define TERMIOS_DEBUG 1
|
||||
// Here to include it at compile time
|
||||
// It's off by default
|
||||
#ifndef WIN32
|
||||
#ifdef TERMIOS_DEBUG
|
||||
|
||||
#define BITSSET "Y"
|
||||
#define BITSNOTSET "N"
|
||||
|
||||
int tiospeed(speed_t speed)
|
||||
{
|
||||
switch (speed) {
|
||||
case B0:
|
||||
return 0;
|
||||
case B50:
|
||||
return 50;
|
||||
case B75:
|
||||
return 75;
|
||||
case B110:
|
||||
return 110;
|
||||
case B134:
|
||||
return 134;
|
||||
case B150:
|
||||
return 150;
|
||||
case B200:
|
||||
return 200;
|
||||
case B300:
|
||||
return 300;
|
||||
case B600:
|
||||
return 600;
|
||||
case B1200:
|
||||
return 1200;
|
||||
case B1800:
|
||||
return 1800;
|
||||
case B2400:
|
||||
return 2400;
|
||||
case B4800:
|
||||
return 4800;
|
||||
case B9600:
|
||||
return 9600;
|
||||
case B19200:
|
||||
return 19200;
|
||||
case B38400:
|
||||
return 38400;
|
||||
case B57600:
|
||||
return 57600;
|
||||
case B115200:
|
||||
return 115200;
|
||||
case B230400:
|
||||
return 230400;
|
||||
case B460800:
|
||||
return 460800;
|
||||
case B500000:
|
||||
return 500000;
|
||||
case B576000:
|
||||
return 576000;
|
||||
case B921600:
|
||||
return 921600;
|
||||
case B1000000:
|
||||
return 1000000;
|
||||
case B1152000:
|
||||
return 1152000;
|
||||
case B1500000:
|
||||
return 1500000;
|
||||
case B2000000:
|
||||
return 2000000;
|
||||
case B2500000:
|
||||
return 2500000;
|
||||
case B3000000:
|
||||
return 3000000;
|
||||
case B3500000:
|
||||
return 3500000;
|
||||
case B4000000:
|
||||
return 4000000;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void termios_debug(const char *devpath, struct termios *my_termios, const char *msg)
|
||||
{
|
||||
applog(LOG_DEBUG, "TIOS: Open %s attributes %s: ispeed=%d ospeed=%d",
|
||||
devpath, msg, tiospeed(cfgetispeed(my_termios)), tiospeed(cfgetispeed(my_termios)));
|
||||
|
||||
#define ISSETI(b) ((my_termios->c_iflag | (b)) ? BITSSET : BITSNOTSET)
|
||||
|
||||
applog(LOG_DEBUG, "TIOS: c_iflag: IGNBRK=%s BRKINT=%s IGNPAR=%s PARMRK=%s INPCK=%s ISTRIP=%s INLCR=%s IGNCR=%s ICRNL=%s IUCLC=%s IXON=%s IXANY=%s IOFF=%s IMAXBEL=%s IUTF8=%s",
|
||||
ISSETI(IGNBRK), ISSETI(BRKINT), ISSETI(IGNPAR), ISSETI(PARMRK),
|
||||
ISSETI(INPCK), ISSETI(ISTRIP), ISSETI(INLCR), ISSETI(IGNCR),
|
||||
ISSETI(ICRNL), ISSETI(IUCLC), ISSETI(IXON), ISSETI(IXANY),
|
||||
ISSETI(IXOFF), ISSETI(IMAXBEL), ISSETI(IUTF8));
|
||||
|
||||
#define ISSETO(b) ((my_termios->c_oflag | (b)) ? BITSSET : BITSNOTSET)
|
||||
#define VALO(b) (my_termios->c_oflag | (b))
|
||||
|
||||
applog(LOG_DEBUG, "TIOS: c_oflag: OPOST=%s OLCUC=%s ONLCR=%s OCRNL=%s ONOCR=%s ONLRET=%s OFILL=%s OFDEL=%s NLDLY=%d CRDLY=%d TABDLY=%d BSDLY=%d VTDLY=%d FFDLY=%d",
|
||||
ISSETO(OPOST), ISSETO(OLCUC), ISSETO(ONLCR), ISSETO(OCRNL),
|
||||
ISSETO(ONOCR), ISSETO(ONLRET), ISSETO(OFILL), ISSETO(OFDEL),
|
||||
VALO(NLDLY), VALO(CRDLY), VALO(TABDLY), VALO(BSDLY),
|
||||
VALO(VTDLY), VALO(FFDLY));
|
||||
|
||||
#define ISSETC(b) ((my_termios->c_cflag | (b)) ? BITSSET : BITSNOTSET)
|
||||
#define VALC(b) (my_termios->c_cflag | (b))
|
||||
|
||||
applog(LOG_DEBUG, "TIOS: c_cflag: CBAUDEX=%s CSIZE=%d CSTOPB=%s CREAD=%s PARENB=%s PARODD=%s HUPCL=%s CLOCAL=%s"
|
||||
#ifdef LOBLK
|
||||
" LOBLK=%s"
|
||||
#endif
|
||||
" CMSPAR=%s CRTSCTS=%s",
|
||||
ISSETC(CBAUDEX), VALC(CSIZE), ISSETC(CSTOPB), ISSETC(CREAD),
|
||||
ISSETC(PARENB), ISSETC(PARODD), ISSETC(HUPCL), ISSETC(CLOCAL),
|
||||
#ifdef LOBLK
|
||||
ISSETC(LOBLK),
|
||||
#endif
|
||||
ISSETC(CMSPAR), ISSETC(CRTSCTS));
|
||||
|
||||
#define ISSETL(b) ((my_termios->c_lflag | (b)) ? BITSSET : BITSNOTSET)
|
||||
|
||||
applog(LOG_DEBUG, "TIOS: c_lflag: ISIG=%s ICANON=%s XCASE=%s ECHO=%s ECHOE=%s ECHOK=%s ECHONL=%s ECHOCTL=%s ECHOPRT=%s ECHOKE=%s"
|
||||
#ifdef DEFECHO
|
||||
" DEFECHO=%s"
|
||||
#endif
|
||||
" FLUSHO=%s NOFLSH=%s TOSTOP=%s PENDIN=%s IEXTEN=%s",
|
||||
ISSETL(ISIG), ISSETL(ICANON), ISSETL(XCASE), ISSETL(ECHO),
|
||||
ISSETL(ECHOE), ISSETL(ECHOK), ISSETL(ECHONL), ISSETL(ECHOCTL),
|
||||
ISSETL(ECHOPRT), ISSETL(ECHOKE),
|
||||
#ifdef DEFECHO
|
||||
ISSETL(DEFECHO),
|
||||
#endif
|
||||
ISSETL(FLUSHO), ISSETL(NOFLSH), ISSETL(TOSTOP), ISSETL(PENDIN),
|
||||
ISSETL(IEXTEN));
|
||||
|
||||
#define VALCC(b) (my_termios->c_cc[b])
|
||||
applog(LOG_DEBUG, "TIOS: c_cc: VINTR=0x%02x VQUIT=0x%02x VERASE=0x%02x VKILL=0x%02x VEOF=0x%02x VMIN=%u VEOL=0x%02x VTIME=%u VEOL2=0x%02x"
|
||||
#ifdef VSWTCH
|
||||
" VSWTCH=0x%02x"
|
||||
#endif
|
||||
" VSTART=0x%02x VSTOP=0x%02x VSUSP=0x%02x"
|
||||
#ifdef VDSUSP
|
||||
" VDSUSP=0x%02x"
|
||||
#endif
|
||||
" VLNEXT=0x%02x VWERASE=0x%02x VREPRINT=0x%02x VDISCARD=0x%02x"
|
||||
#ifdef VSTATUS
|
||||
" VSTATUS=0x%02x"
|
||||
#endif
|
||||
,
|
||||
VALCC(VINTR), VALCC(VQUIT), VALCC(VERASE), VALCC(VKILL),
|
||||
VALCC(VEOF), VALCC(VMIN), VALCC(VEOL), VALCC(VTIME),
|
||||
VALCC(VEOL2),
|
||||
#ifdef VSWTCH
|
||||
VALCC(VSWTCH),
|
||||
#endif
|
||||
VALCC(VSTART), VALCC(VSTOP), VALCC(VSUSP),
|
||||
#ifdef VDSUSP
|
||||
VALCC(VDSUSP),
|
||||
#endif
|
||||
VALCC(VLNEXT), VALCC(VWERASE),
|
||||
VALCC(VREPRINT), VALCC(VDISCARD)
|
||||
#ifdef VSTATUS
|
||||
,VALCC(VSTATUS)
|
||||
#endif
|
||||
);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int
|
||||
serial_open(const char*devpath, unsigned long baud, signed short timeout, bool purge)
|
||||
{
|
||||
@ -208,19 +376,24 @@ serial_open(const char*devpath, unsigned long baud, signed short timeout, bool p
|
||||
|
||||
tcgetattr(fdDev, &my_termios);
|
||||
|
||||
#ifdef TERMIOS_DEBUG
|
||||
termios_debug(devpath, &my_termios, "before");
|
||||
#endif
|
||||
|
||||
switch (baud) {
|
||||
case 0:
|
||||
break;
|
||||
case 57600:
|
||||
cfsetispeed( &my_termios, B57600 );
|
||||
cfsetospeed( &my_termios, B57600 );
|
||||
cfsetispeed(&my_termios, B57600);
|
||||
cfsetospeed(&my_termios, B57600);
|
||||
break;
|
||||
case 115200:
|
||||
cfsetispeed( &my_termios, B115200 );
|
||||
cfsetospeed( &my_termios, B115200 );
|
||||
cfsetispeed(&my_termios, B115200);
|
||||
cfsetospeed(&my_termios, B115200);
|
||||
break;
|
||||
// TODO: try some higher speeds with the Icarus and BFL to see
|
||||
// if they support them and if setting them makes any difference
|
||||
// N.B. B3000000 doesn't work on Icarus
|
||||
default:
|
||||
applog(LOG_WARNING, "Unrecognized baud rate: %lu", baud);
|
||||
}
|
||||
@ -239,7 +412,17 @@ serial_open(const char*devpath, unsigned long baud, signed short timeout, bool p
|
||||
my_termios.c_cc[VTIME] = (cc_t)timeout;
|
||||
my_termios.c_cc[VMIN] = 0;
|
||||
|
||||
#ifdef TERMIOS_DEBUG
|
||||
termios_debug(devpath, &my_termios, "settings");
|
||||
#endif
|
||||
|
||||
tcsetattr(fdDev, TCSANOW, &my_termios);
|
||||
|
||||
#ifdef TERMIOS_DEBUG
|
||||
tcgetattr(fdDev, &my_termios);
|
||||
termios_debug(devpath, &my_termios, "after");
|
||||
#endif
|
||||
|
||||
if (purge)
|
||||
tcflush(fdDev, TCIOFLUSH);
|
||||
return fdDev;
|
||||
@ -252,7 +435,7 @@ _serial_read(int fd, char *buf, size_t bufsiz, char *eol)
|
||||
ssize_t len, tlen = 0;
|
||||
while (bufsiz) {
|
||||
len = read(fd, buf, eol ? 1 : bufsiz);
|
||||
if (len < 1)
|
||||
if (unlikely(len == -1))
|
||||
break;
|
||||
tlen += len;
|
||||
if (eol && *eol == buf[0])
|
||||
|
25
libztex.c
25
libztex.c
@ -607,11 +607,19 @@ int libztex_scanDevices(struct libztex_dev_list*** devs_p)
|
||||
|
||||
int libztex_sendHashData(struct libztex_device *ztex, unsigned char *sendbuf)
|
||||
{
|
||||
int cnt;
|
||||
int cnt, ret, len;
|
||||
|
||||
if (ztex == NULL || ztex->hndl == NULL)
|
||||
return 0;
|
||||
cnt = libusb_control_transfer(ztex->hndl, 0x40, 0x80, 0, 0, sendbuf, 44, 1000);
|
||||
ret = 44; len = 0;
|
||||
while (ret > 0) {
|
||||
cnt = libusb_control_transfer(ztex->hndl, 0x40, 0x80, 0, 0, sendbuf + len, ret, 1000);
|
||||
if (cnt >= 0) {
|
||||
ret -= cnt;
|
||||
len += cnt;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
if (unlikely(cnt < 0))
|
||||
applog(LOG_ERR, "%s: Failed sendHashData with err %d", ztex->repr, cnt);
|
||||
|
||||
@ -620,8 +628,8 @@ int libztex_sendHashData(struct libztex_device *ztex, unsigned char *sendbuf)
|
||||
|
||||
int libztex_readHashData(struct libztex_device *ztex, struct libztex_hash_data nonces[]) {
|
||||
int bufsize = 12 + ztex->extraSolutions * 4;
|
||||
int cnt = 0, i, j, ret, len;
|
||||
unsigned char *rbuf;
|
||||
int cnt, i, j;
|
||||
|
||||
if (ztex->hndl == NULL)
|
||||
return 0;
|
||||
@ -631,7 +639,16 @@ int libztex_readHashData(struct libztex_device *ztex, struct libztex_hash_data n
|
||||
applog(LOG_ERR, "%s: Failed to allocate memory for reading nonces", ztex->repr);
|
||||
return 0;
|
||||
}
|
||||
cnt = libusb_control_transfer(ztex->hndl, 0xc0, 0x81, 0, 0, rbuf, bufsize * ztex->numNonces, 1000);
|
||||
ret = bufsize * ztex->numNonces; len = 0;
|
||||
while (ret > 0) {
|
||||
cnt = libusb_control_transfer(ztex->hndl, 0xc0, 0x81, 0, 0, rbuf + len, ret, 1000);
|
||||
if (cnt >= 0) {
|
||||
ret -= cnt;
|
||||
len += cnt;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
if (unlikely(cnt < 0)) {
|
||||
applog(LOG_ERR, "%s: Failed readHashData with err %d", ztex->repr, cnt);
|
||||
free(rbuf);
|
||||
|
21
miner.h
21
miner.h
@ -173,9 +173,10 @@ enum pool_strategy {
|
||||
POOL_ROUNDROBIN,
|
||||
POOL_ROTATE,
|
||||
POOL_LOADBALANCE,
|
||||
POOL_BALANCE,
|
||||
};
|
||||
|
||||
#define TOP_STRATEGY (POOL_LOADBALANCE)
|
||||
#define TOP_STRATEGY (POOL_BALANCE)
|
||||
|
||||
struct strategies {
|
||||
const char *s;
|
||||
@ -329,6 +330,7 @@ struct cgpu_info {
|
||||
unsigned int avg_wait_d;
|
||||
uint32_t nonces;
|
||||
bool nonce_range;
|
||||
bool polling;
|
||||
#endif
|
||||
pthread_mutex_t device_mutex;
|
||||
|
||||
@ -366,9 +368,10 @@ struct cgpu_info {
|
||||
int opt_tc, thread_concurrency;
|
||||
int shaders;
|
||||
#endif
|
||||
struct timeval tv_gpustart;;
|
||||
struct timeval tv_gpuend;
|
||||
struct timeval tv_gpustart;
|
||||
struct timeval tv_gpumid;
|
||||
double gpu_us_average;
|
||||
int intervals, hit;
|
||||
#endif
|
||||
|
||||
float temp;
|
||||
@ -440,6 +443,7 @@ extern int thr_info_create(struct thr_info *thr, pthread_attr_t *attr, void *(*s
|
||||
extern void thr_info_cancel(struct thr_info *thr);
|
||||
extern void thr_info_freeze(struct thr_info *thr);
|
||||
extern void nmsleep(unsigned int msecs);
|
||||
extern double us_tdiff(struct timeval *end, struct timeval *start);
|
||||
|
||||
struct string_elist {
|
||||
char *string;
|
||||
@ -551,6 +555,7 @@ extern bool opt_protocol;
|
||||
extern char *opt_kernel_path;
|
||||
extern char *opt_socks_proxy;
|
||||
extern char *cgminer_path;
|
||||
extern bool opt_fail_only;
|
||||
extern bool opt_autofan;
|
||||
extern bool opt_autoengine;
|
||||
extern bool use_curses;
|
||||
@ -595,7 +600,6 @@ extern pthread_mutex_t restart_lock;
|
||||
extern pthread_cond_t restart_cond;
|
||||
|
||||
extern void thread_reportin(struct thr_info *thr);
|
||||
extern bool queue_request(struct thr_info *thr, bool needed);
|
||||
extern int restart_wait(unsigned int mstime);
|
||||
|
||||
extern void kill_work(void);
|
||||
@ -658,7 +662,7 @@ extern int opt_rotate_period;
|
||||
extern double total_mhashes_done;
|
||||
extern unsigned int new_blocks;
|
||||
extern unsigned int found_blocks;
|
||||
extern int total_accepted, total_rejected;
|
||||
extern int total_accepted, total_rejected, total_diff1;;
|
||||
extern int total_getworks, total_stale, total_discarded;
|
||||
extern unsigned int local_work;
|
||||
extern unsigned int total_go, total_ro;
|
||||
@ -720,8 +724,7 @@ struct pool {
|
||||
int accepted, rejected;
|
||||
int seq_rejects;
|
||||
int solved;
|
||||
int queued;
|
||||
int staged;
|
||||
int diff1;
|
||||
|
||||
bool submit_fail;
|
||||
bool idle;
|
||||
@ -742,6 +745,9 @@ struct pool {
|
||||
unsigned int remotefail_occasions;
|
||||
struct timeval tv_idle;
|
||||
|
||||
double utility;
|
||||
int last_shares, shares;
|
||||
|
||||
char *rpc_url;
|
||||
char *rpc_userpass;
|
||||
char *rpc_user, *rpc_pass;
|
||||
@ -791,6 +797,7 @@ struct work {
|
||||
bool stale;
|
||||
bool mandatory;
|
||||
bool block;
|
||||
bool queued;
|
||||
|
||||
unsigned int work_block;
|
||||
int id;
|
||||
|
150
miner.php
150
miner.php
@ -2,6 +2,7 @@
|
||||
session_start();
|
||||
#
|
||||
global $miner, $port, $readonly, $notify, $rigs;
|
||||
global $rigtotals, $forcerigtotals;
|
||||
global $socksndtimeoutsec, $sockrcvtimeoutsec;
|
||||
global $checklastshare, $poolinputs, $hidefields;
|
||||
global $ignorerefresh, $changerefresh, $autorefresh;
|
||||
@ -9,9 +10,8 @@ global $allowcustompages, $customsummarypages;
|
||||
global $miner_font_family, $miner_font_size;
|
||||
global $colouroverride, $placebuttons;
|
||||
#
|
||||
# Don't touch these 2 - see $rigs below
|
||||
$miner = null;
|
||||
$port = null;
|
||||
# See API-README for more details of these variables and how
|
||||
# to configure miner.php
|
||||
#
|
||||
# Set $readonly to true to force miner.php to be readonly
|
||||
# Set $readonly to false then it will check cgminer 'privileged'
|
||||
@ -19,8 +19,6 @@ $readonly = false;
|
||||
#
|
||||
# Set $notify to false to NOT attempt to display the notify command
|
||||
# Set $notify to true to attempt to display the notify command
|
||||
# If your older version of cgminer returns an 'Invalid command'
|
||||
# coz it doesn't have notify - it just shows the error status table
|
||||
$notify = true;
|
||||
#
|
||||
# Set $checklastshare to true to do the following checks:
|
||||
@ -37,30 +35,20 @@ $poolinputs = false;
|
||||
#
|
||||
# Set $rigs to an array of your cgminer rigs that are running
|
||||
# format: 'IP:Port' or 'Host:Port' or 'Host:Port:Name'
|
||||
# If you only have one rig, it will just show the detail of that rig
|
||||
# If you have more than one rig it will show a summary of all the rigs
|
||||
# with buttons to show the details of each rig -
|
||||
# the button contents will be 'Name' if that was specified
|
||||
# e.g. $rigs = array('127.0.0.1:4028','myrig.com:4028:Sugoi');
|
||||
$rigs = array('127.0.0.1:4028');
|
||||
#
|
||||
# Set $rigtotals to true to display totals on the single rig page
|
||||
# 'false' means no totals (and ignores $forcerigtotals)
|
||||
# You can force it to always show rig totals when there is only
|
||||
# one line by setting $forcerigtotals = true;
|
||||
$rigtotals = true;
|
||||
$forcerigtotals = false;
|
||||
#
|
||||
# These should be OK for most cases
|
||||
# However, the longer SND is, the longer you have to wait while
|
||||
# php hangs if the target cgminer isn't runnning or listening
|
||||
# RCV should only ever be relevant if cgminer has hung but the
|
||||
# API thread is still running, RCV would normally be >= SND
|
||||
# Feel free to increase SND if your network is very slow
|
||||
# or decrease RCV if that happens often to you
|
||||
# Also, on some windows PHP, apparently the $usec is ignored
|
||||
$socksndtimeoutsec = 10;
|
||||
$sockrcvtimeoutsec = 40;
|
||||
#
|
||||
# List of fields NOT to be displayed
|
||||
# You can use this to hide data you don't want to see or don't want
|
||||
# shown on a public web page
|
||||
# The list of sections are: SUMMARY, POOL, PGA, GPU, NOTIFY, CONFIG
|
||||
# See the web page for the list of field names (the table headers)
|
||||
# It is an array of 'SECTION.Field Name' => 1
|
||||
# This example would hide the slightly more sensitive pool information
|
||||
#$hidefields = array('POOL.URL' => 1, 'POOL.User' => 1);
|
||||
$hidefields = array();
|
||||
@ -74,19 +62,11 @@ $changerefresh = true;
|
||||
$autorefresh = 0;
|
||||
#
|
||||
# Should we allow custom pages?
|
||||
# (or just completely ignore then and don't display the buttons)
|
||||
# (or just completely ignore them and don't display the buttons)
|
||||
$allowcustompages = true;
|
||||
#
|
||||
# OK this is a bit more complex item: Custom Summary Pages
|
||||
# A custom summary page in an array of 'section' => array('FieldA','FieldB'...)
|
||||
# Field can be 'name=new name' to display 'name' with a different heading 'new name'
|
||||
# This makes up what is displayed with each 'section' separately as a table
|
||||
# - empty tables are not shown
|
||||
# - empty columns (an unknown field) are not shown
|
||||
# - and missing field data shows as blank
|
||||
# - section = 'DATE' displays a date table like 'Summary'
|
||||
# - section = 'RIGS' displays a rig table like 'Summary'
|
||||
# There is a second array, listing fields to be totaled for each section
|
||||
# As mentioned above, see API-README
|
||||
# see the example below (if there is no matching data, no total will show)
|
||||
$mobilepage = array(
|
||||
'DATE' => null,
|
||||
@ -161,6 +141,10 @@ $colourtable = array(
|
||||
'td.lo background' => '#deffff'
|
||||
);
|
||||
#
|
||||
# Don't touch these 2
|
||||
$miner = null;
|
||||
$port = null;
|
||||
#
|
||||
# Ensure it is only ever shown once
|
||||
global $showndate;
|
||||
$showndate = false;
|
||||
@ -790,7 +774,7 @@ function fmt($section, $name, $value, $when, $alldata)
|
||||
if ($class == '' && ($rownum % 2) == 0)
|
||||
$class = $c2class;
|
||||
|
||||
if ($ret == '')
|
||||
if ($ret === '')
|
||||
$ret = $b;
|
||||
|
||||
return array($ret, $class);
|
||||
@ -829,9 +813,47 @@ function showdatetime()
|
||||
otherrow('<td class=sta>Date: '.date($dfmt).'</td>');
|
||||
}
|
||||
#
|
||||
global $singlerigsum;
|
||||
$singlerigsum = array(
|
||||
'devs' => array('MHS av' => 1, 'MHS 5s' => 1, 'Accepted' => 1, 'Rejected' => 1,
|
||||
'Hardware Errors' => 1, 'Utility' => 1, 'Total MH' => 1),
|
||||
'pools' => array('Getworks' => 1, 'Accepted' => 1, 'Rejected' => 1, 'Discarded' => 1,
|
||||
'Stale' => 1, 'Get Failures' => 1, 'Remote Failures' => 1),
|
||||
'notify' => array('*' => 1));
|
||||
#
|
||||
function showtotal($total, $when, $oldvalues)
|
||||
{
|
||||
global $rigtotals;
|
||||
|
||||
list($showvalue, $class) = fmt('total', '', 'Total:', $when, null);
|
||||
echo "<td$class align=right>$showvalue</td>";
|
||||
|
||||
$skipfirst = true;
|
||||
foreach ($oldvalues as $name => $value)
|
||||
{
|
||||
if ($skipfirst === true)
|
||||
{
|
||||
$skipfirst = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($total[$name]))
|
||||
$newvalue = $total[$name];
|
||||
else
|
||||
$newvalue = '';
|
||||
|
||||
list($showvalue, $class) = fmt('total', $name, $newvalue, $when, null);
|
||||
echo "<td$class";
|
||||
if ($rigtotals === true)
|
||||
echo ' align=right';
|
||||
echo ">$showvalue</td>";
|
||||
}
|
||||
}
|
||||
#
|
||||
function details($cmd, $list, $rig)
|
||||
{
|
||||
global $dfmt, $poolcmd, $readonly, $showndate;
|
||||
global $rownum, $rigtotals, $forcerigtotals, $singlerigsum;
|
||||
|
||||
$when = 0;
|
||||
|
||||
@ -864,8 +886,15 @@ function details($cmd, $list, $rig)
|
||||
endrow();
|
||||
}
|
||||
|
||||
if ($rigtotals === true && isset($singlerigsum[$cmd]))
|
||||
$dototal = $singlerigsum[$cmd];
|
||||
else
|
||||
$dototal = array();
|
||||
|
||||
$total = array();
|
||||
|
||||
$section = '';
|
||||
$oldvalues = null;
|
||||
foreach ($list as $item => $values)
|
||||
{
|
||||
if ($item == 'STATUS')
|
||||
@ -873,8 +902,13 @@ function details($cmd, $list, $rig)
|
||||
|
||||
$sectionname = preg_replace('/\d/', '', $item);
|
||||
|
||||
// Handle 'devs' possibly containing >1 table
|
||||
if ($sectionname != $section)
|
||||
{
|
||||
if ($oldvalues != null && count($total) > 0
|
||||
&& ($rownum > 2 || $forcerigtotals === true))
|
||||
showtotal($total, $when, $oldvalues);
|
||||
|
||||
endtable();
|
||||
newtable();
|
||||
showhead($cmd, $values);
|
||||
@ -886,7 +920,19 @@ function details($cmd, $list, $rig)
|
||||
foreach ($values as $name => $value)
|
||||
{
|
||||
list($showvalue, $class) = fmt($section, $name, $value, $when, $values);
|
||||
echo "<td$class>$showvalue</td>";
|
||||
echo "<td$class";
|
||||
if ($rigtotals === true)
|
||||
echo ' align=right';
|
||||
echo ">$showvalue</td>";
|
||||
|
||||
if (isset($dototal[$name])
|
||||
|| (isset($dototal['*']) and substr($name, 0, 1) == '*'))
|
||||
{
|
||||
if (isset($total[$name]))
|
||||
$total[$name] += $value;
|
||||
else
|
||||
$total[$name] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if ($cmd == 'pools' && $readonly === false)
|
||||
@ -908,7 +954,14 @@ function details($cmd, $list, $rig)
|
||||
}
|
||||
}
|
||||
endrow();
|
||||
|
||||
$oldvalues = $values;
|
||||
}
|
||||
|
||||
if ($oldvalues != null && count($total) > 0
|
||||
&& ($rownum > 2 || $forcerigtotals === true))
|
||||
showtotal($total, $when, $oldvalues);
|
||||
|
||||
endtable();
|
||||
}
|
||||
#
|
||||
@ -1736,14 +1789,29 @@ function processcustompage($pagename, $sections, $sum, $namemap)
|
||||
foreach ($result as $sec => $row)
|
||||
{
|
||||
$secname = preg_replace('/\d/', '', $sec);
|
||||
if (secmatch($section, $secname) && isset($row[$field]))
|
||||
if (secmatch($section, $secname))
|
||||
{
|
||||
$showfields[$field] = 1;
|
||||
$map = $section.'.'.$field;
|
||||
if (isset($namemap[$map]))
|
||||
$showhead[$namemap[$map]] = 1;
|
||||
else
|
||||
$showhead[$field] = 1;
|
||||
if ($field === '*')
|
||||
{
|
||||
foreach ($row as $f => $v)
|
||||
{
|
||||
$showfields[$f] = 1;
|
||||
$map = $section.'.'.$f;
|
||||
if (isset($namemap[$map]))
|
||||
$showhead[$namemap[$map]] = 1;
|
||||
else
|
||||
$showhead[$f] = 1;
|
||||
}
|
||||
}
|
||||
elseif (isset($row[$field]))
|
||||
{
|
||||
$showfields[$field] = 1;
|
||||
$map = $section.'.'.$field;
|
||||
if (isset($namemap[$map]))
|
||||
$showhead[$namemap[$map]] = 1;
|
||||
else
|
||||
$showhead[$field] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
7
scrypt.h
7
scrypt.h
@ -2,9 +2,12 @@
|
||||
#define SCRYPT_H
|
||||
|
||||
#ifdef USE_SCRYPT
|
||||
extern bool scrypt_test(unsigned char *pdata, const unsigned char *ptarget, uint32_t nonce);
|
||||
extern bool scrypt_test(unsigned char *pdata, const unsigned char *ptarget,
|
||||
uint32_t nonce);
|
||||
#else /* USE_SCRYPT */
|
||||
static inline bool scrypt_test(unsigned char *pdata, const unsigned char *ptarget, uint32_t nonce)
|
||||
static inline bool scrypt_test(__maybe_unused unsigned char *pdata,
|
||||
__maybe_unused const unsigned char *ptarget,
|
||||
__maybe_unused uint32_t nonce)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
6
util.c
6
util.c
@ -705,3 +705,9 @@ void nmsleep(unsigned int msecs)
|
||||
ret = nanosleep(&twait, &tleft);
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
}
|
||||
|
||||
/* Returns the microseconds difference between end and start times as a double */
|
||||
double us_tdiff(struct timeval *end, struct timeval *start)
|
||||
{
|
||||
return end->tv_sec * 1000000 + end->tv_usec - start->tv_sec * 1000000 - start->tv_usec;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user