Browse Source

Merge branch 'master' of git://github.com/ckolivas/cgminer.git

nfactor-troky
Paul Sheppard 12 years ago
parent
commit
7b2ada0ee4
  1. 537
      API-README
  2. 80
      NEWS
  3. 21
      README
  4. 11
      adl.c
  5. 48
      api.c
  6. 569
      cgminer.c
  7. 4
      configure.ac
  8. 41
      driver-bitforce.c
  9. 26
      driver-opencl.c
  10. 193
      fpgautils.c
  11. 25
      libztex.c
  12. 21
      miner.h
  13. 138
      miner.php
  14. 7
      scrypt.h
  15. 6
      util.c

537
API-README

@ -1,6 +1,9 @@
This README contains details about the cgminer RPC API 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 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 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 ADL in use=X, <- Y or N if any GPU has ADL
Strategy=Name, <- the current pool strategy Strategy=Name, <- the current pool strategy
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
Failover-Only=true/false | <- failover-only 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,...|
@ -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 check|cmd COMMAND Exists=Y/N, <- 'cmd' exists in this version
Access=Y/N| <- you have access to use 'cmd' 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 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
@ -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 miner.php - an example web page to access the API
This includes buttons and inputs to attempt access to the privileged commands 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 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: 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: Added API commands:
'poolpriority' 'poolpriority'
@ -533,3 +560,507 @@ Commands:
'cpucount' 'cpucount'
'quit' '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

@ -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 Version 2.6.4 - August 7, 2012
- Convert the serial autodetect functions to use int instead of char to - Convert the serial autodetect functions to use int instead of char to

21
README

@ -141,12 +141,13 @@ Options for both config file and command line:
--api-port Port number of miner API (default: 4028) --api-port Port number of miner API (default: 4028)
--auto-fan Automatically adjust all GPU fan speeds to maintain a target temperature --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 --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 --benchmark Run cgminer in benchmark mode - produces no shares
--debug|-D Enable debug output --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) --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 --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") --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) --log|-l <arg> Interval in seconds between log output (default: 5)
--monitor|-m <arg> Use custom pipe cmd for output messages --monitor|-m <arg> Use custom pipe cmd for output messages
--net-delay Impose small delays in networking to not overload slow routers --net-delay Impose small delays in networking to not overload slow routers
@ -386,7 +387,7 @@ The number of hardware erorrs
The utility defines as the number of shares / minute The utility defines as the number of shares / minute
The cgminer status line shows: 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. TQ is Total Queued work items.
ST is STaged work items (ready to use). 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 LW is Locally generated Work items
GF is Getwork Fail Occasions (server slow to provide work) GF is Getwork Fail Occasions (server slow to provide work)
RF is Remote Fail occasions (server slow to accept 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 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 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. skipping pools that are idle.
LOAD BALANCE: LOAD BALANCE:
This strategy sends work in equal amounts to all the pools specified. If any This strategy sends work to all the pools to maintain optimum load. The most
pool falls idle, the rest will take up the slack keeping the miner busy. 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 LOGGING
@ -838,9 +846,8 @@ 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 device to auto-recognise?
A: They are only automatically recognised on linux, and no option needs to be A: The only thing that needs to be done is to load the driver for them, which
passed to them. The only thing that needs to be done is to load the driver for on linux would require:
them, which on linux would require:
sudo modprobe ftdi_sio vendor=0x0403 product=0x6014 sudo modprobe ftdi_sio vendor=0x0403 product=0x6014

11
adl.c

@ -339,6 +339,9 @@ void init_adl(int nDevs)
} }
} }
if (devices > nDevs)
devices = nDevs;
for (gpu = 0; gpu < devices; gpu++) { for (gpu = 0; gpu < devices; gpu++) {
struct gpu_adl *ga; struct gpu_adl *ga;
int iAdapterIndex; int iAdapterIndex;
@ -788,6 +791,7 @@ static void get_enginerange(int gpu, int *imin, int *imax)
int set_engineclock(int gpu, int iEngineClock) int set_engineclock(int gpu, int iEngineClock)
{ {
ADLODPerformanceLevels *lpOdPerformanceLevels; ADLODPerformanceLevels *lpOdPerformanceLevels;
struct cgpu_info *cgpu;
int i, lev, ret = 1; int i, lev, ret = 1;
struct gpu_adl *ga; struct gpu_adl *ga;
@ -829,6 +833,11 @@ int set_engineclock(int gpu, int iEngineClock)
ga->managed = true; ga->managed = true;
out: out:
unlock_adl(); unlock_adl();
cgpu = &gpus[gpu];
if (cgpu->gpu_memdiff)
set_memoryclock(gpu, iEngineClock / 100 + cgpu->gpu_memdiff);
return ret; return ret;
} }
@ -1194,8 +1203,6 @@ void gpu_autotune(int gpu, enum dev_enable *denable)
newengine /= 100; newengine /= 100;
applog(LOG_INFO, "Setting GPU %d engine clock to %d", gpu, newengine); applog(LOG_INFO, "Setting GPU %d engine clock to %d", gpu, newengine);
set_engineclock(gpu, newengine); set_engineclock(gpu, newengine);
if (cgpu->gpu_memdiff)
set_memoryclock(gpu, newengine + cgpu->gpu_memdiff);
} }
} }
ga->lasttemp = temp; ga->lasttemp = temp;

48
api.c

@ -166,7 +166,7 @@ static const char SEPARATOR = '|';
#define SEPSTR "|" #define SEPSTR "|"
static const char GPUSEP = ','; static const char GPUSEP = ',';
static const char *APIVERSION = "1.15"; static const char *APIVERSION = "1.17";
static const char *DEAD = "Dead"; static const char *DEAD = "Dead";
static const char *SICK = "Sick"; static const char *SICK = "Sick";
static const char *NOSTART = "NoStart"; static const char *NOSTART = "NoStart";
@ -184,6 +184,9 @@ static const char *YES = "Y";
static const char *NO = "N"; static const char *NO = "N";
static const char *NULLSTR = "(null)"; static const char *NULLSTR = "(null)";
static const char *TRUESTR = "true";
static const char *FALSESTR = "false";
static const char *DEVICECODE = "" static const char *DEVICECODE = ""
#ifdef HAVE_OPENCL #ifdef HAVE_OPENCL
"GPU " "GPU "
@ -376,6 +379,9 @@ static const char *JSON_PARAMETER = "parameter";
#define MSG_CHECK 72 #define MSG_CHECK 72
#define MSG_POOLPRIO 73 #define MSG_POOLPRIO 73
#define MSG_DUPPID 74 #define MSG_DUPPID 74
#define MSG_MISBOOL 75
#define MSG_INVBOOL 76
#define MSG_FOO 77
enum code_severity { enum code_severity {
SEVERITY_ERR, SEVERITY_ERR,
@ -403,6 +409,7 @@ enum code_parameters {
PARAM_POOL, PARAM_POOL,
PARAM_STR, PARAM_STR,
PARAM_BOTH, PARAM_BOTH,
PARAM_BOOL,
PARAM_NONE PARAM_NONE
}; };
@ -524,6 +531,9 @@ struct CODES {
{ SEVERITY_SUCC, MSG_MINESTATS,PARAM_NONE, "CGMiner stats" }, { SEVERITY_SUCC, MSG_MINESTATS,PARAM_NONE, "CGMiner stats" },
{ SEVERITY_ERR, MSG_MISCHK, PARAM_NONE, "Missing check cmd" }, { SEVERITY_ERR, MSG_MISCHK, PARAM_NONE, "Missing check cmd" },
{ SEVERITY_SUCC, MSG_CHECK, PARAM_NONE, "Check command" }, { 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 } { 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))); sprintf(buf, "%.15f", *((double *)(root->data)));
break; break;
case API_BOOL: case API_BOOL:
sprintf(buf, "%s", *((bool *)(root->data)) ? "true" : "false"); sprintf(buf, "%s", *((bool *)(root->data)) ? TRUESTR : FALSESTR);
break; break;
case API_TIMEVAL: case API_TIMEVAL:
sprintf(buf, "%ld.%06ld", sprintf(buf, "%ld.%06ld",
@ -1133,6 +1143,9 @@ static char *message(int messageid, int paramid, char *param2, bool isjson)
case PARAM_BOTH: case PARAM_BOTH:
sprintf(buf, codes[i].description, paramid, param2); sprintf(buf, codes[i].description, paramid, param2);
break; break;
case PARAM_BOOL:
sprintf(buf, codes[i].description, paramid ? TRUESTR : FALSESTR);
break;
case PARAM_NONE: case PARAM_NONE:
default: default:
strcpy(buf, codes[i].description); 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_int(root, "Log Interval", &opt_log_interval, false);
root = api_add_const(root, "Device Code", DEVICECODE, false); root = api_add_const(root, "Device Code", DEVICECODE, false);
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 = print_data(root, buf, isjson); root = print_data(root, buf, isjson);
if (isjson) if (isjson)
@ -1240,8 +1254,7 @@ static void minerconfig(__maybe_unused SOCKETTYPE c, __maybe_unused char *param,
strcat(io_buffer, buf); strcat(io_buffer, buf);
} }
static const char* static const char *status2str(enum alive status)
status2str(enum alive status)
{ {
switch (status) { switch (status) {
case LIFE_WELL: 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_uint(root, "Remote Failures", &(pool->remotefail_occasions), false);
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);
if (isjson && (i > 0)) if (isjson && (i > 0))
strcat(io_buffer, COMMA); 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; struct api_data *root = NULL;
char buf[TMPBUFSIZ]; char buf[TMPBUFSIZ];
double utility, mhs; double utility, mhs, work_utility;
#ifdef WANT_CPUMINE #ifdef WANT_CPUMINE
char *algo = (char *)(algo_names[opt_algo]); 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; utility = total_accepted / ( total_secs ? total_secs : 1 ) * 60;
mhs = total_mhashes_done / total_secs; mhs = total_mhashes_done / total_secs;
work_utility = total_diff1 / ( total_secs ? total_secs : 1 ) * 60;
sprintf(io_buffer, isjson sprintf(io_buffer, isjson
? "%s," JSON_SUMMARY ? "%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, "Remote Failures", &(total_ro), false);
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 = print_data(root, buf, isjson); root = print_data(root, buf, isjson);
if (isjson) if (isjson)
@ -2704,6 +2720,27 @@ static void minerstats(__maybe_unused SOCKETTYPE c, __maybe_unused char *param,
strcat(io_buffer, JSON_CLOSE); 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); static void checkcommand(__maybe_unused SOCKETTYPE c, char *param, bool isjson, char group);
struct CMDS { struct CMDS {
@ -2754,6 +2791,7 @@ struct CMDS {
{ "restart", dorestart, true }, { "restart", dorestart, true },
{ "stats", minerstats, false }, { "stats", minerstats, false },
{ "check", checkcommand, false }, { "check", checkcommand, false },
{ "failover-only", failoveronly, true },
{ NULL, NULL, false } { NULL, NULL, false }
}; };

569
cgminer.c

File diff suppressed because it is too large Load Diff

4
configure.ac

@ -1,8 +1,8 @@
##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
m4_define([v_maj], [2]) m4_define([v_maj], [2])
m4_define([v_min], [6]) m4_define([v_min], [7])
m4_define([v_mic], [4]) m4_define([v_mic], [0])
##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
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))

41
driver-bitforce.c

@ -51,7 +51,7 @@ enum {
#define BITFORCE_SLEEP_MS 500 #define BITFORCE_SLEEP_MS 500
#define BITFORCE_TIMEOUT_S 7 #define BITFORCE_TIMEOUT_S 7
#define BITFORCE_TIMEOUT_MS (BITFORCE_TIMEOUT_S * 1000) #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_LONG_TIMEOUT_MS (BITFORCE_LONG_TIMEOUT_S * 1000)
#define BITFORCE_CHECK_INTERVAL_MS 10 #define BITFORCE_CHECK_INTERVAL_MS 10
#define WORK_CHECK_INTERVAL_MS 50 #define WORK_CHECK_INTERVAL_MS 50
@ -347,6 +347,11 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce)
if (!fdDev) if (!fdDev)
return false; 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 /* 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))
@ -421,8 +426,6 @@ re_send:
goto re_send; goto re_send;
} }
applog(LOG_ERR, "BFL%i: Error: Send work reports: %s", bitforce->device_id, pdevbuf); applog(LOG_ERR, "BFL%i: Error: Send work reports: %s", bitforce->device_id, pdevbuf);
bitforce->hw_errors++;
bitforce_clear_buffer(bitforce);
return false; return false;
} }
@ -463,8 +466,6 @@ re_send:
if (unlikely(strncasecmp(pdevbuf, "OK", 2))) { if (unlikely(strncasecmp(pdevbuf, "OK", 2))) {
applog(LOG_ERR, "BFL%i: Error: Send block data reports: %s", bitforce->device_id, pdevbuf); applog(LOG_ERR, "BFL%i: Error: Send block data reports: %s", bitforce->device_id, pdevbuf);
bitforce->hw_errors++;
bitforce_clear_buffer(bitforce);
return false; 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) static int64_t bitforce_scanhash(struct thr_info *thr, struct work *work, int64_t __maybe_unused max_nonce)
{ {
struct cgpu_info *bitforce = thr->cgpu; struct cgpu_info *bitforce = thr->cgpu;
unsigned int sleep_time;
bool send_ret; bool send_ret;
int64_t ret; int64_t ret;
send_ret = bitforce_send_work(thr, work); send_ret = bitforce_send_work(thr, work);
if (!bitforce->nonce_range) { if (!restart_wait(bitforce->sleep_ms))
/* 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; return 0;
bitforce->wait_ms = sleep_time; bitforce->wait_ms = bitforce->sleep_ms;
queue_request(thr, false);
/* Now wait athe final 1/3rd; no bitforce should be finished by now */ if (send_ret) {
sleep_time = bitforce->sleep_ms - sleep_time; bitforce->polling = true;
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)
ret = bitforce_get_result(thr, work); ret = bitforce_get_result(thr, work);
else bitforce->polling = false;
} else
ret = -1; ret = -1;
if (ret == -1) { if (ret == -1) {

26
driver-opencl.c

@ -1490,6 +1490,7 @@ static int64_t opencl_scanhash(struct thr_info *thr, struct work *work,
_clState *clState = clStates[thr_id]; _clState *clState = clStates[thr_id];
const cl_kernel *kernel = &clState->kernel; const cl_kernel *kernel = &clState->kernel;
const int dynamic_us = opt_dynamic_interval * 1000; const int dynamic_us = opt_dynamic_interval * 1000;
struct timeval tv_gpuend;
cl_bool blocking; cl_bool blocking;
cl_int status; cl_int status;
@ -1508,13 +1509,17 @@ static int64_t opencl_scanhash(struct thr_info *thr, struct work *work,
clFinish(clState->commandQueue); clFinish(clState->commandQueue);
if (gpu->dynamic) { if (gpu->dynamic) {
struct timeval diff; double gpu_us;
suseconds_t gpu_us;
/* Windows returns the same time for gettimeofday due to its
gettimeofday(&gpu->tv_gpuend, NULL); * 15ms timer resolution, so we must average the result over
timersub(&gpu->tv_gpuend, &gpu->tv_gpustart, &diff); * at least 5 values that are actually different to get an
gpu_us = diff.tv_sec * 1000000 + diff.tv_usec; * accurate result */
if (likely(gpu_us >= 0)) { 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; 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
@ -1527,6 +1532,7 @@ static int64_t opencl_scanhash(struct thr_info *thr, struct work *work,
if (gpu->intensity < MAX_INTENSITY) if (gpu->intensity < MAX_INTENSITY)
++gpu->intensity; ++gpu->intensity;
} }
gpu->intervals = gpu->hit = 0;
} }
} }
set_threads_hashes(clState->vwidth, &threads, &hashes, globalThreads, 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); 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) { if (clState->goffset) {
size_t global_work_offset[1]; size_t global_work_offset[1];

193
fpgautils.c

@ -143,6 +143,174 @@ _serial_detect(const char*dname, detectone_func_t detectone, autoscan_func_t aut
return found; 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 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)
{ {
@ -208,19 +376,24 @@ serial_open(const char*devpath, unsigned long baud, signed short timeout, bool p
tcgetattr(fdDev, &my_termios); tcgetattr(fdDev, &my_termios);
#ifdef TERMIOS_DEBUG
termios_debug(devpath, &my_termios, "before");
#endif
switch (baud) { switch (baud) {
case 0: case 0:
break; break;
case 57600: case 57600:
cfsetispeed( &my_termios, B57600 ); cfsetispeed(&my_termios, B57600);
cfsetospeed( &my_termios, B57600 ); cfsetospeed(&my_termios, B57600);
break; break;
case 115200: case 115200:
cfsetispeed( &my_termios, B115200 ); cfsetispeed(&my_termios, B115200);
cfsetospeed( &my_termios, B115200 ); cfsetospeed(&my_termios, B115200);
break; break;
// TODO: try some higher speeds with the Icarus and BFL to see // TODO: try some higher speeds with the Icarus and BFL to see
// if they support them and if setting them makes any difference // if they support them and if setting them makes any difference
// N.B. B3000000 doesn't work on Icarus
default: default:
applog(LOG_WARNING, "Unrecognized baud rate: %lu", baud); 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[VTIME] = (cc_t)timeout;
my_termios.c_cc[VMIN] = 0; my_termios.c_cc[VMIN] = 0;
#ifdef TERMIOS_DEBUG
termios_debug(devpath, &my_termios, "settings");
#endif
tcsetattr(fdDev, TCSANOW, &my_termios); tcsetattr(fdDev, TCSANOW, &my_termios);
#ifdef TERMIOS_DEBUG
tcgetattr(fdDev, &my_termios);
termios_debug(devpath, &my_termios, "after");
#endif
if (purge) if (purge)
tcflush(fdDev, TCIOFLUSH); tcflush(fdDev, TCIOFLUSH);
return fdDev; return fdDev;
@ -252,7 +435,7 @@ _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) {
len = read(fd, buf, eol ? 1 : bufsiz); len = read(fd, buf, eol ? 1 : bufsiz);
if (len < 1) if (unlikely(len == -1))
break; break;
tlen += len; tlen += len;
if (eol && *eol == buf[0]) if (eol && *eol == buf[0])

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 libztex_sendHashData(struct libztex_device *ztex, unsigned char *sendbuf)
{ {
int cnt; int cnt, ret, len;
if (ztex == NULL || ztex->hndl == NULL) if (ztex == NULL || ztex->hndl == NULL)
return 0; 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)) if (unlikely(cnt < 0))
applog(LOG_ERR, "%s: Failed sendHashData with err %d", ztex->repr, cnt); 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 libztex_readHashData(struct libztex_device *ztex, struct libztex_hash_data nonces[]) {
int bufsize = 12 + ztex->extraSolutions * 4; int bufsize = 12 + ztex->extraSolutions * 4;
int cnt = 0, i, j, ret, len;
unsigned char *rbuf; unsigned char *rbuf;
int cnt, i, j;
if (ztex->hndl == NULL) if (ztex->hndl == NULL)
return 0; 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); applog(LOG_ERR, "%s: Failed to allocate memory for reading nonces", ztex->repr);
return 0; 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)) { if (unlikely(cnt < 0)) {
applog(LOG_ERR, "%s: Failed readHashData with err %d", ztex->repr, cnt); applog(LOG_ERR, "%s: Failed readHashData with err %d", ztex->repr, cnt);
free(rbuf); free(rbuf);

21
miner.h

@ -173,9 +173,10 @@ enum pool_strategy {
POOL_ROUNDROBIN, POOL_ROUNDROBIN,
POOL_ROTATE, POOL_ROTATE,
POOL_LOADBALANCE, POOL_LOADBALANCE,
POOL_BALANCE,
}; };
#define TOP_STRATEGY (POOL_LOADBALANCE) #define TOP_STRATEGY (POOL_BALANCE)
struct strategies { struct strategies {
const char *s; const char *s;
@ -329,6 +330,7 @@ struct cgpu_info {
unsigned int avg_wait_d; unsigned int avg_wait_d;
uint32_t nonces; uint32_t nonces;
bool nonce_range; bool nonce_range;
bool polling;
#endif #endif
pthread_mutex_t device_mutex; pthread_mutex_t device_mutex;
@ -366,9 +368,10 @@ struct cgpu_info {
int opt_tc, thread_concurrency; int opt_tc, thread_concurrency;
int shaders; int shaders;
#endif #endif
struct timeval tv_gpustart;; struct timeval tv_gpustart;
struct timeval tv_gpuend; struct timeval tv_gpumid;
double gpu_us_average; double gpu_us_average;
int intervals, hit;
#endif #endif
float temp; 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_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);
struct string_elist { struct string_elist {
char *string; char *string;
@ -551,6 +555,7 @@ extern bool opt_protocol;
extern char *opt_kernel_path; extern char *opt_kernel_path;
extern char *opt_socks_proxy; extern char *opt_socks_proxy;
extern char *cgminer_path; extern char *cgminer_path;
extern bool opt_fail_only;
extern bool opt_autofan; extern bool opt_autofan;
extern bool opt_autoengine; extern bool opt_autoengine;
extern bool use_curses; extern bool use_curses;
@ -595,7 +600,6 @@ extern pthread_mutex_t restart_lock;
extern pthread_cond_t restart_cond; extern pthread_cond_t restart_cond;
extern void thread_reportin(struct thr_info *thr); 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 int restart_wait(unsigned int mstime);
extern void kill_work(void); extern void kill_work(void);
@ -658,7 +662,7 @@ extern int opt_rotate_period;
extern double total_mhashes_done; extern double total_mhashes_done;
extern unsigned int new_blocks; extern unsigned int new_blocks;
extern unsigned int found_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 int total_getworks, total_stale, total_discarded;
extern unsigned int local_work; extern unsigned int local_work;
extern unsigned int total_go, total_ro; extern unsigned int total_go, total_ro;
@ -720,8 +724,7 @@ struct pool {
int accepted, rejected; int accepted, rejected;
int seq_rejects; int seq_rejects;
int solved; int solved;
int queued; int diff1;
int staged;
bool submit_fail; bool submit_fail;
bool idle; bool idle;
@ -742,6 +745,9 @@ struct pool {
unsigned int remotefail_occasions; unsigned int remotefail_occasions;
struct timeval tv_idle; struct timeval tv_idle;
double utility;
int last_shares, shares;
char *rpc_url; char *rpc_url;
char *rpc_userpass; char *rpc_userpass;
char *rpc_user, *rpc_pass; char *rpc_user, *rpc_pass;
@ -791,6 +797,7 @@ struct work {
bool stale; bool stale;
bool mandatory; bool mandatory;
bool block; bool block;
bool queued;
unsigned int work_block; unsigned int work_block;
int id; int id;

138
miner.php

@ -2,6 +2,7 @@
session_start(); session_start();
# #
global $miner, $port, $readonly, $notify, $rigs; global $miner, $port, $readonly, $notify, $rigs;
global $rigtotals, $forcerigtotals;
global $socksndtimeoutsec, $sockrcvtimeoutsec; global $socksndtimeoutsec, $sockrcvtimeoutsec;
global $checklastshare, $poolinputs, $hidefields; global $checklastshare, $poolinputs, $hidefields;
global $ignorerefresh, $changerefresh, $autorefresh; global $ignorerefresh, $changerefresh, $autorefresh;
@ -9,9 +10,8 @@ global $allowcustompages, $customsummarypages;
global $miner_font_family, $miner_font_size; global $miner_font_family, $miner_font_size;
global $colouroverride, $placebuttons; global $colouroverride, $placebuttons;
# #
# Don't touch these 2 - see $rigs below # See API-README for more details of these variables and how
$miner = null; # to configure miner.php
$port = null;
# #
# Set $readonly to true to force miner.php to be readonly # Set $readonly to true to force miner.php to be readonly
# Set $readonly to false then it will check cgminer 'privileged' # 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 false to NOT attempt to display the notify command
# Set $notify to true to 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; $notify = true;
# #
# Set $checklastshare to true to do the following checks: # 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 # Set $rigs to an array of your cgminer rigs that are running
# format: 'IP:Port' or 'Host:Port' or 'Host:Port:Name' # 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'); $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 # 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; $socksndtimeoutsec = 10;
$sockrcvtimeoutsec = 40; $sockrcvtimeoutsec = 40;
# #
# List of fields NOT to be displayed # 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 # This example would hide the slightly more sensitive pool information
#$hidefields = array('POOL.URL' => 1, 'POOL.User' => 1); #$hidefields = array('POOL.URL' => 1, 'POOL.User' => 1);
$hidefields = array(); $hidefields = array();
@ -74,19 +62,11 @@ $changerefresh = true;
$autorefresh = 0; $autorefresh = 0;
# #
# Should we allow custom pages? # 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; $allowcustompages = true;
# #
# OK this is a bit more complex item: Custom Summary Pages # OK this is a bit more complex item: Custom Summary Pages
# A custom summary page in an array of 'section' => array('FieldA','FieldB'...) # As mentioned above, see API-README
# 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
# see the example below (if there is no matching data, no total will show) # see the example below (if there is no matching data, no total will show)
$mobilepage = array( $mobilepage = array(
'DATE' => null, 'DATE' => null,
@ -161,6 +141,10 @@ $colourtable = array(
'td.lo background' => '#deffff' 'td.lo background' => '#deffff'
); );
# #
# Don't touch these 2
$miner = null;
$port = null;
#
# Ensure it is only ever shown once # Ensure it is only ever shown once
global $showndate; global $showndate;
$showndate = false; $showndate = false;
@ -790,7 +774,7 @@ function fmt($section, $name, $value, $when, $alldata)
if ($class == '' && ($rownum % 2) == 0) if ($class == '' && ($rownum % 2) == 0)
$class = $c2class; $class = $c2class;
if ($ret == '') if ($ret === '')
$ret = $b; $ret = $b;
return array($ret, $class); return array($ret, $class);
@ -829,9 +813,47 @@ function showdatetime()
otherrow('<td class=sta>Date: '.date($dfmt).'</td>'); 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) function details($cmd, $list, $rig)
{ {
global $dfmt, $poolcmd, $readonly, $showndate; global $dfmt, $poolcmd, $readonly, $showndate;
global $rownum, $rigtotals, $forcerigtotals, $singlerigsum;
$when = 0; $when = 0;
@ -864,8 +886,15 @@ function details($cmd, $list, $rig)
endrow(); endrow();
} }
if ($rigtotals === true && isset($singlerigsum[$cmd]))
$dototal = $singlerigsum[$cmd];
else
$dototal = array();
$total = array();
$section = ''; $section = '';
$oldvalues = null;
foreach ($list as $item => $values) foreach ($list as $item => $values)
{ {
if ($item == 'STATUS') if ($item == 'STATUS')
@ -873,8 +902,13 @@ function details($cmd, $list, $rig)
$sectionname = preg_replace('/\d/', '', $item); $sectionname = preg_replace('/\d/', '', $item);
// Handle 'devs' possibly containing >1 table
if ($sectionname != $section) if ($sectionname != $section)
{ {
if ($oldvalues != null && count($total) > 0
&& ($rownum > 2 || $forcerigtotals === true))
showtotal($total, $when, $oldvalues);
endtable(); endtable();
newtable(); newtable();
showhead($cmd, $values); showhead($cmd, $values);
@ -886,7 +920,19 @@ function details($cmd, $list, $rig)
foreach ($values as $name => $value) foreach ($values as $name => $value)
{ {
list($showvalue, $class) = fmt($section, $name, $value, $when, $values); 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) if ($cmd == 'pools' && $readonly === false)
@ -908,7 +954,14 @@ function details($cmd, $list, $rig)
} }
} }
endrow(); endrow();
$oldvalues = $values;
} }
if ($oldvalues != null && count($total) > 0
&& ($rownum > 2 || $forcerigtotals === true))
showtotal($total, $when, $oldvalues);
endtable(); endtable();
} }
# #
@ -1736,7 +1789,21 @@ function processcustompage($pagename, $sections, $sum, $namemap)
foreach ($result as $sec => $row) foreach ($result as $sec => $row)
{ {
$secname = preg_replace('/\d/', '', $sec); $secname = preg_replace('/\d/', '', $sec);
if (secmatch($section, $secname) && isset($row[$field])) if (secmatch($section, $secname))
{
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; $showfields[$field] = 1;
$map = $section.'.'.$field; $map = $section.'.'.$field;
@ -1746,6 +1813,7 @@ function processcustompage($pagename, $sections, $sum, $namemap)
$showhead[$field] = 1; $showhead[$field] = 1;
} }
} }
}
if (count($showfields) > 0) if (count($showfields) > 0)
{ {

7
scrypt.h

@ -2,9 +2,12 @@
#define SCRYPT_H #define SCRYPT_H
#ifdef USE_SCRYPT #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 */ #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; return false;
} }

6
util.c

@ -705,3 +705,9 @@ void nmsleep(unsigned int msecs)
ret = nanosleep(&twait, &tleft); ret = nanosleep(&twait, &tleft);
} while (ret == -1 && errno == EINTR); } 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…
Cancel
Save