mirror of
https://github.com/GOSTSec/sgminer
synced 2025-01-23 04:54:26 +00:00
Merge branch 'usb-dev' of github.com:ckolivas/cgminer into usb-dev
This commit is contained in:
commit
22a50a5a0f
62
API-README
62
API-README
@ -347,6 +347,18 @@ The list of requests - a (*) means it requires privileged access - and replies a
|
||||
The current options are:
|
||||
MMQ opt=clock val=160 to 230 (and a multiple of 2)
|
||||
|
||||
zero|Which,true/false (*)
|
||||
none There is no reply section just the STATUS section
|
||||
stating that the zero, and optional summary, was done
|
||||
If Which='all', all normal cgminer and API statistics
|
||||
will be zeroed other than the numbers displayed by the
|
||||
usbstats and stats commands
|
||||
If Which='bestshare', only the 'Best Share' values
|
||||
are zeroed for each pool and the global 'Best Share'
|
||||
The true/false option determines if a full summary is
|
||||
shown on the cgminer display like is normally displayed
|
||||
on exit.
|
||||
|
||||
When you enable, disable or restart a GPU or PGA, you will also get Thread messages
|
||||
in the cgminer status window
|
||||
|
||||
@ -400,7 +412,18 @@ miner.php - an example web page to access the API
|
||||
Feature Changelog for external applications using the API:
|
||||
|
||||
|
||||
API V1.23
|
||||
API V1.24
|
||||
|
||||
Added API commands:
|
||||
'zero'
|
||||
|
||||
Modified API commands:
|
||||
'pools' - add 'Best Share'
|
||||
'devs' and 'pga' - add 'No Device' for PGAs if MMQ or BFL compiled
|
||||
|
||||
----------
|
||||
|
||||
API V1.23 (cgminer v2.10.2)
|
||||
|
||||
Added API commands:
|
||||
'pgaset' - with: MMQ opt=clock val=160 to 230 (and a multiple of 2)
|
||||
@ -930,6 +953,38 @@ true
|
||||
|
||||
---------
|
||||
|
||||
Default:
|
||||
$userlist = null;
|
||||
|
||||
Define password checking and default access
|
||||
null means there is no password checking
|
||||
|
||||
$userlist is an array of 3 arrays e.g.
|
||||
$userlist = array('sys' => array('boss' => 'bpass'),
|
||||
'usr' => array('user' => 'upass', 'pleb' => 'ppass'),
|
||||
'def' => array('Pools'));
|
||||
|
||||
'sys' is an array of system users and passwords (full access)
|
||||
'usr' is an array of user level users and passwords (readonly access)
|
||||
'def' is an array of custompages that anyone not logged in can view
|
||||
|
||||
Any of the 3 can be null, meaning there are none of that item
|
||||
|
||||
All validated 'usr' users are given $readonly = true; access
|
||||
All validated 'sys' users are given the $readonly access you defined
|
||||
|
||||
If 'def' has one or more values, and allowcustompages is true, then
|
||||
anyone without a password can see the list of custompage buttons given
|
||||
in 'def' and will see the first one when they go to the web page, with
|
||||
a login button at the top right
|
||||
|
||||
From the login page, if you login with no username or password, it will
|
||||
show the first 'def' custompage (if there are any)
|
||||
|
||||
If you are logged in, it will show a logout button at the top right
|
||||
|
||||
---------
|
||||
|
||||
Default:
|
||||
$notify = true;
|
||||
|
||||
@ -1302,9 +1357,12 @@ You can only see fields listed in 'group' and 'calc'
|
||||
|
||||
A 'calc' is formatted as: 'Field' => 'function'
|
||||
The current list of operations available for 'calc' are:
|
||||
'sum', 'avg', 'min', 'max', 'lo', 'hi', 'any'
|
||||
'sum', 'avg', 'min', 'max', 'lo', 'hi', 'coount', 'any'
|
||||
The first 4 are as expected - the numerical sum, average, minimum or maximum
|
||||
'lo' is the first string of the list, sorted ignoring case
|
||||
'hi' is the last string of the list, sorted ignoring case
|
||||
'count' is the number of rows in the section specified in the calc e.g.
|
||||
('DEVS.Name' => 'count') would be the number of DEVS selected in the 'where'
|
||||
of course any valid 'DEVS.Xyz' would give the same 'count' value
|
||||
'any' is effectively random: the field value in the first row of the grouped data
|
||||
An unrecognised 'function' uses 'any'
|
||||
|
13
API.java
13
API.java
@ -76,6 +76,7 @@ class API
|
||||
|
||||
public void process(String cmd, InetAddress ip, int port) throws Exception
|
||||
{
|
||||
StringBuffer sb = new StringBuffer();
|
||||
char buf[] = new char[MAXRECEIVESIZE];
|
||||
int len = 0;
|
||||
|
||||
@ -89,7 +90,15 @@ System.out.println("Attempting to send '"+cmd+"' to "+ip.getHostAddress()+":"+po
|
||||
ps.flush();
|
||||
|
||||
InputStreamReader isr = new InputStreamReader(socket.getInputStream());
|
||||
len = isr.read(buf, 0, MAXRECEIVESIZE);
|
||||
while (0x80085 > 0)
|
||||
{
|
||||
len = isr.read(buf, 0, MAXRECEIVESIZE);
|
||||
if (len < 1)
|
||||
break;
|
||||
sb.append(buf, 0, len);
|
||||
if (buf[len-1] == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
closeAll();
|
||||
}
|
||||
@ -100,7 +109,7 @@ System.out.println("Attempting to send '"+cmd+"' to "+ip.getHostAddress()+":"+po
|
||||
return;
|
||||
}
|
||||
|
||||
String result = new String(buf, 0, len);
|
||||
String result = sb.toString();
|
||||
|
||||
System.out.println("Answer='"+result+"'");
|
||||
|
||||
|
25
FPGA-README
25
FPGA-README
@ -2,15 +2,8 @@
|
||||
This README contains extended details about FPGA mining with cgminer
|
||||
|
||||
|
||||
ModMinerQuad (MMQ)
|
||||
------------------
|
||||
|
||||
The mining bitstream does not survive a power cycle, so cgminer will upload
|
||||
it, if it needs to, before it starts mining (approx 7min 40sec)
|
||||
|
||||
The red LED also flashes while it is uploading the bitstream
|
||||
|
||||
-
|
||||
For ModMinerQuad (MMQ) and BitForce (BFL)
|
||||
-----------------------------------------
|
||||
|
||||
When mining on windows, the driver being used will determine if mining will work.
|
||||
|
||||
@ -39,7 +32,17 @@ problems:
|
||||
|
||||
--usb-dump 0
|
||||
|
||||
It will only help if you have a working MMQ device attached to the computer
|
||||
It will only help if you have a working MMQ or BFL device attached to the
|
||||
computer
|
||||
|
||||
|
||||
ModMinerQuad (MMQ)
|
||||
------------------
|
||||
|
||||
The mining bitstream does not survive a power cycle, so cgminer will upload
|
||||
it, if it needs to, before it starts mining (approx 7min 40sec)
|
||||
|
||||
The red LED also flashes while it is uploading the bitstream
|
||||
|
||||
-
|
||||
|
||||
@ -130,7 +133,7 @@ modem-manager software
|
||||
TODO: check that all MMQ's have the same product ID
|
||||
|
||||
|
||||
Bitforce (BFL)
|
||||
BitForce (BFL)
|
||||
--------------
|
||||
|
||||
--bfl-range Use nonce range on bitforce devices if supported
|
||||
|
@ -82,6 +82,10 @@ if NEED_FPGAUTILS
|
||||
cgminer_SOURCES += fpgautils.c fpgautils.h
|
||||
endif
|
||||
|
||||
if NEED_USBUTILS_C
|
||||
cgminer_SOURCES += usbutils.c
|
||||
endif
|
||||
|
||||
if HAS_BITFORCE
|
||||
cgminer_SOURCES += driver-bitforce.c
|
||||
endif
|
||||
@ -91,7 +95,7 @@ cgminer_SOURCES += driver-icarus.c
|
||||
endif
|
||||
|
||||
if HAS_MODMINER
|
||||
cgminer_SOURCES += driver-modminer.c usbutils.c
|
||||
cgminer_SOURCES += driver-modminer.c
|
||||
bitstreamsdir = $(bindir)/bitstreams
|
||||
dist_bitstreams_DATA = bitstreams/*
|
||||
endif
|
||||
|
20
README
20
README
@ -220,15 +220,16 @@ SCRYPT only options:
|
||||
See SCRYPT-README for more information regarding litecoin mining.
|
||||
|
||||
|
||||
FPGA mining boards(BitForce, Icarus, ModMiner, Ztex) only options:
|
||||
FPGA mining boards (BitForce, Icarus, ModMiner, Ztex) only options:
|
||||
|
||||
cgminer will automatically find your ModMiner or Ztex FPGAs
|
||||
cgminer will automatically find your ModMiner, BitForce or Ztex FPGAs
|
||||
independent of the --scan-serial options specified below
|
||||
|
||||
--scan-serial|-S <arg> Serial port to probe for FPGA mining device
|
||||
--scan-serial|-S <arg> Serial port to probe for Icarus mining device
|
||||
|
||||
This option is only for BitForce and/or Icarus FPGAs
|
||||
This option is only for Icarus bitstream FPGAs
|
||||
|
||||
By default, cgminer will scan for autodetected FPGAs unless at least one
|
||||
By default, cgminer will scan for autodetected Icarus unless at least one
|
||||
-S is specified for that driver. If you specify -S and still want cgminer
|
||||
to scan, you must also use "-S auto". If you want to prevent cgminer from
|
||||
scanning without specifying a device, you can use "-S noauto". Note that
|
||||
@ -237,13 +238,14 @@ device depending on the version of udev being used.
|
||||
|
||||
On linux <arg> is usually of the format /dev/ttyUSBn
|
||||
On windows <arg> is usually of the format \\.\COMn
|
||||
(where n = the correct device number for the FPGA device)
|
||||
(where n = the correct device number for the Icarus device)
|
||||
|
||||
The official supplied binaries are compiled with support for all FPGAs.
|
||||
To force the code to only attempt detection with a specific driver,
|
||||
prepend the argument with the driver name followed by a colon.
|
||||
For example, "icarus:/dev/ttyUSB0" or "bitforce:\\.\COM5"
|
||||
or using the short name: "ica:/dev/ttyUSB0" or "bfl:\\.\COM5"
|
||||
For example, "icarus:/dev/ttyUSB0" or using the short name: "ica:/dev/ttyUSB0"
|
||||
This option not longer matters since Icarus is the only serial-USB
|
||||
device that uses it
|
||||
|
||||
For other FPGA details see the FPGA-README
|
||||
|
||||
@ -455,7 +457,7 @@ The block display shows:
|
||||
Block: 0074c5e482e34a506d2a051a... Started: [17:17:22] Best share: 2.71K
|
||||
|
||||
This shows a short stretch of the current block, when the new block started,
|
||||
and the all time best difficulty share you've submitted since starting cgminer
|
||||
and the all time best difficulty share you've found since starting cgminer
|
||||
this time.
|
||||
|
||||
|
||||
|
2
adl.c
2
adl.c
@ -1392,7 +1392,7 @@ updated:
|
||||
clear_logwin();
|
||||
return;
|
||||
}
|
||||
sleep(1);
|
||||
nmsleep(1000);
|
||||
goto updated;
|
||||
}
|
||||
#endif
|
||||
|
215
api.c
215
api.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2012 Andrew Smith
|
||||
* Copyright 2011-2013 Andrew Smith
|
||||
* Copyright 2011-2012 Con Kolivas
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@ -133,7 +133,7 @@ static const char SEPARATOR = '|';
|
||||
#define SEPSTR "|"
|
||||
static const char GPUSEP = ',';
|
||||
|
||||
static const char *APIVERSION = "1.23";
|
||||
static const char *APIVERSION = "1.24";
|
||||
static const char *DEAD = "Dead";
|
||||
#if defined(HAVE_OPENCL) || defined(HAVE_AN_FPGA)
|
||||
static const char *SICK = "Sick";
|
||||
@ -387,6 +387,12 @@ static const char *JSON_PARAMETER = "parameter";
|
||||
#define MSG_PGASETERR 93
|
||||
#endif
|
||||
|
||||
#define MSG_ZERMIS 94
|
||||
#define MSG_ZERINV 95
|
||||
#define MSG_ZERSUM 96
|
||||
#define MSG_ZERNOSUM 97
|
||||
#define MSG_USBNODEV 98
|
||||
|
||||
enum code_severity {
|
||||
SEVERITY_ERR,
|
||||
SEVERITY_WARN,
|
||||
@ -558,6 +564,13 @@ struct CODES {
|
||||
{ SEVERITY_INFO, MSG_PGAHELP, PARAM_BOTH, "PGA %d set help: %s" },
|
||||
{ SEVERITY_SUCC, MSG_PGASETOK, PARAM_BOTH, "PGA %d set OK" },
|
||||
{ SEVERITY_ERR, MSG_PGASETERR, PARAM_BOTH, "PGA %d set failed: %s" },
|
||||
#endif
|
||||
{ SEVERITY_ERR, MSG_ZERMIS, PARAM_NONE, "Missing zero parameters" },
|
||||
{ SEVERITY_ERR, MSG_ZERINV, PARAM_STR, "Invalid zero parameter '%s'" },
|
||||
{ SEVERITY_SUCC, MSG_ZERSUM, PARAM_STR, "Zeroed %s stats with summary" },
|
||||
{ SEVERITY_SUCC, MSG_ZERNOSUM, PARAM_STR, "Zeroed %s stats without summary" },
|
||||
#if defined(USE_MODMINER) || defined(USE_BITFORCE)
|
||||
{ SEVERITY_ERR, MSG_USBNODEV, PARAM_PGA, "PGA%d has no device" },
|
||||
#endif
|
||||
{ SEVERITY_FAIL, 0, 0, NULL }
|
||||
};
|
||||
@ -599,22 +612,6 @@ struct APIGROUPS {
|
||||
static struct IP4ACCESS *ipaccess = NULL;
|
||||
static int ips = 0;
|
||||
|
||||
#ifdef USE_BITFORCE
|
||||
extern struct device_api bitforce_api;
|
||||
#endif
|
||||
|
||||
#ifdef USE_ICARUS
|
||||
extern struct device_api icarus_api;
|
||||
#endif
|
||||
|
||||
#ifdef USE_ZTEX
|
||||
extern struct device_api ztex_api;
|
||||
#endif
|
||||
|
||||
#ifdef USE_MODMINER
|
||||
extern struct device_api modminer_api;
|
||||
#endif
|
||||
|
||||
struct io_data {
|
||||
size_t siz;
|
||||
char *ptr;
|
||||
@ -1151,24 +1148,26 @@ static int numpgas()
|
||||
int count = 0;
|
||||
int i;
|
||||
|
||||
mutex_lock(&devices_lock);
|
||||
for (i = 0; i < total_devices; i++) {
|
||||
#ifdef USE_BITFORCE
|
||||
if (devices[i]->api == &bitforce_api)
|
||||
if (devices[i]->drv->drv_id == DRIVER_BITFORCE)
|
||||
count++;
|
||||
#endif
|
||||
#ifdef USE_ICARUS
|
||||
if (devices[i]->api == &icarus_api)
|
||||
if (devices[i]->drv->drv_id == DRIVER_ICARUS)
|
||||
count++;
|
||||
#endif
|
||||
#ifdef USE_ZTEX
|
||||
if (devices[i]->api == &ztex_api)
|
||||
if (devices[i]->drv->drv_id == DRIVER_ZTEX)
|
||||
count++;
|
||||
#endif
|
||||
#ifdef USE_MODMINER
|
||||
if (devices[i]->api == &modminer_api)
|
||||
if (devices[i]->drv->drv_id == DRIVER_MODMINER)
|
||||
count++;
|
||||
#endif
|
||||
}
|
||||
mutex_unlock(&devices_lock);
|
||||
return count;
|
||||
}
|
||||
|
||||
@ -1177,27 +1176,35 @@ static int pgadevice(int pgaid)
|
||||
int count = 0;
|
||||
int i;
|
||||
|
||||
mutex_lock(&devices_lock);
|
||||
for (i = 0; i < total_devices; i++) {
|
||||
#ifdef USE_BITFORCE
|
||||
if (devices[i]->api == &bitforce_api)
|
||||
if (devices[i]->drv->drv_id == DRIVER_BITFORCE)
|
||||
count++;
|
||||
#endif
|
||||
#ifdef USE_ICARUS
|
||||
if (devices[i]->api == &icarus_api)
|
||||
if (devices[i]->drv->drv_id == DRIVER_ICARUS)
|
||||
count++;
|
||||
#endif
|
||||
#ifdef USE_ZTEX
|
||||
if (devices[i]->api == &ztex_api)
|
||||
if (devices[i]->drv->drv_id == DRIVER_ZTEX)
|
||||
count++;
|
||||
#endif
|
||||
#ifdef USE_MODMINER
|
||||
if (devices[i]->api == &modminer_api)
|
||||
if (devices[i]->drv->drv_id == DRIVER_MODMINER)
|
||||
count++;
|
||||
#endif
|
||||
if (count == (pgaid + 1))
|
||||
return i;
|
||||
goto foundit;
|
||||
}
|
||||
|
||||
mutex_unlock(&devices_lock);
|
||||
return -1;
|
||||
|
||||
foundit:
|
||||
|
||||
mutex_unlock(&devices_lock);
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1530,16 +1537,16 @@ static void pgastatus(struct io_data *io_data, int pga, bool isjson, bool precom
|
||||
if (dev < 0) // Should never happen
|
||||
return;
|
||||
|
||||
struct cgpu_info *cgpu = devices[dev];
|
||||
struct cgpu_info *cgpu = get_devices(dev);
|
||||
double frequency = 0;
|
||||
float temp = cgpu->temp;
|
||||
|
||||
#ifdef USE_ZTEX
|
||||
if (cgpu->api == &ztex_api && cgpu->device_ztex)
|
||||
if (cgpu->drv->drv_id == DRIVER_ZTEX && cgpu->device_ztex)
|
||||
frequency = cgpu->device_ztex->freqM1 * (cgpu->device_ztex->freqM + 1);
|
||||
#endif
|
||||
#ifdef USE_MODMINER
|
||||
if (cgpu->api == &modminer_api)
|
||||
if (cgpu->drv->drv_id == DRIVER_MODMINER)
|
||||
frequency = cgpu->clock;
|
||||
#endif
|
||||
|
||||
@ -1553,7 +1560,7 @@ static void pgastatus(struct io_data *io_data, int pga, bool isjson, bool precom
|
||||
status = (char *)status2str(cgpu->status);
|
||||
|
||||
root = api_add_int(root, "PGA", &pga, false);
|
||||
root = api_add_string(root, "Name", cgpu->api->name, false);
|
||||
root = api_add_string(root, "Name", cgpu->drv->name, false);
|
||||
root = api_add_int(root, "ID", &(cgpu->device_id), false);
|
||||
root = api_add_string(root, "Enabled", enabled, false);
|
||||
root = api_add_string(root, "Status", status, false);
|
||||
@ -1577,6 +1584,9 @@ static void pgastatus(struct io_data *io_data, int pga, bool isjson, bool precom
|
||||
root = api_add_diff(root, "Difficulty Accepted", &(cgpu->diff_accepted), false);
|
||||
root = api_add_diff(root, "Difficulty Rejected", &(cgpu->diff_rejected), false);
|
||||
root = api_add_diff(root, "Last Share Difficulty", &(cgpu->last_share_diff), false);
|
||||
#if defined(USE_MODMINER) || defined(USE_BITFORCE)
|
||||
root = api_add_bool(root, "No Device", &(cgpu->usbinfo.nodev), false);
|
||||
#endif
|
||||
|
||||
root = print_data(root, buf, isjson, precom);
|
||||
io_add(io_data, buf);
|
||||
@ -1747,6 +1757,7 @@ static void pgadev(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *p
|
||||
|
||||
static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
struct cgpu_info *cgpu;
|
||||
int numpga = numpgas();
|
||||
struct thr_info *thr;
|
||||
int pga;
|
||||
@ -1775,7 +1786,10 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char
|
||||
return;
|
||||
}
|
||||
|
||||
struct cgpu_info *cgpu = devices[dev];
|
||||
cgpu = get_devices(dev);
|
||||
|
||||
applog(LOG_DEBUG, "API: request to pgaenable pgaid %d device %d %s%u",
|
||||
id, dev, cgpu->drv->name, cgpu->device_id);
|
||||
|
||||
if (cgpu->deven != DEV_DISABLED) {
|
||||
message(io_data, MSG_PGALRENA, id, NULL, isjson);
|
||||
@ -1789,11 +1803,19 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_MODMINER) || defined(USE_BITFORCE)
|
||||
if (cgpu->usbinfo.nodev) {
|
||||
message(io_data, MSG_USBNODEV, id, NULL, isjson);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < mining_threads; i++) {
|
||||
pga = thr_info[i].cgpu->device_id;
|
||||
thr = get_thread(i);
|
||||
pga = thr->cgpu->cgminer_id;
|
||||
if (pga == dev) {
|
||||
thr = &thr_info[i];
|
||||
cgpu->deven = DEV_ENABLED;
|
||||
applog(LOG_DEBUG, "API: pushing ping (%d) to thread %d", ping, thr->id);
|
||||
tq_push(thr->q, &ping);
|
||||
}
|
||||
}
|
||||
@ -1803,6 +1825,7 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char
|
||||
|
||||
static void pgadisable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
struct cgpu_info *cgpu;
|
||||
int numpga = numpgas();
|
||||
int id;
|
||||
|
||||
@ -1828,7 +1851,10 @@ static void pgadisable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, cha
|
||||
return;
|
||||
}
|
||||
|
||||
struct cgpu_info *cgpu = devices[dev];
|
||||
cgpu = get_devices(dev);
|
||||
|
||||
applog(LOG_DEBUG, "API: request to pgadisable pgaid %d device %d %s%u",
|
||||
id, dev, cgpu->drv->name, cgpu->device_id);
|
||||
|
||||
if (cgpu->deven == DEV_DISABLED) {
|
||||
message(io_data, MSG_PGALRDIS, id, NULL, isjson);
|
||||
@ -1842,6 +1868,8 @@ static void pgadisable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, cha
|
||||
|
||||
static void pgaidentify(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
struct cgpu_info *cgpu;
|
||||
struct device_drv *drv;
|
||||
int numpga = numpgas();
|
||||
int id;
|
||||
|
||||
@ -1867,13 +1895,13 @@ static void pgaidentify(struct io_data *io_data, __maybe_unused SOCKETTYPE c, ch
|
||||
return;
|
||||
}
|
||||
|
||||
struct cgpu_info *cgpu = devices[dev];
|
||||
struct device_api *api = cgpu->api;
|
||||
cgpu = get_devices(dev);
|
||||
drv = cgpu->drv;
|
||||
|
||||
if (!api->identify_device)
|
||||
if (!drv->identify_device)
|
||||
message(io_data, MSG_PGANOID, id, NULL, isjson);
|
||||
else {
|
||||
api->identify_device(cgpu);
|
||||
drv->identify_device(cgpu);
|
||||
message(io_data, MSG_PGAIDENT, id, NULL, isjson);
|
||||
}
|
||||
}
|
||||
@ -1993,6 +2021,7 @@ static void poolstatus(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m
|
||||
else
|
||||
root = api_add_const(root, "Stratum URL", BLANK, false);
|
||||
root = api_add_bool(root, "Has GBT", &(pool->has_gbt), false);
|
||||
root = api_add_uint64(root, "Best Share", &(pool->best_diff), true);
|
||||
|
||||
root = print_data(root, buf, isjson, isjson && (i > 0));
|
||||
io_add(io_data, buf);
|
||||
@ -2081,23 +2110,25 @@ static void gpuenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char
|
||||
return;
|
||||
}
|
||||
|
||||
applog(LOG_DEBUG, "API: request to gpuenable gpuid %d %s%u",
|
||||
id, gpus[id].drv->name, gpus[id].device_id);
|
||||
|
||||
if (gpus[id].deven != DEV_DISABLED) {
|
||||
message(io_data, MSG_ALRENA, id, NULL, isjson);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < gpu_threads; i++) {
|
||||
gpu = thr_info[i].cgpu->device_id;
|
||||
thr = get_thread(i);
|
||||
gpu = thr->cgpu->device_id;
|
||||
if (gpu == id) {
|
||||
thr = &thr_info[i];
|
||||
if (thr->cgpu->status != LIFE_WELL) {
|
||||
message(io_data, MSG_GPUMRE, id, NULL, isjson);
|
||||
return;
|
||||
}
|
||||
|
||||
gpus[id].deven = DEV_ENABLED;
|
||||
applog(LOG_DEBUG, "API: pushing ping (%d) to thread %d", ping, thr->id);
|
||||
tq_push(thr->q, &ping);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -2124,6 +2155,9 @@ static void gpudisable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, cha
|
||||
return;
|
||||
}
|
||||
|
||||
applog(LOG_DEBUG, "API: request to gpudisable gpuid %d %s%u",
|
||||
id, gpus[id].drv->name, gpus[id].device_id);
|
||||
|
||||
if (gpus[id].deven == DEV_DISABLED) {
|
||||
message(io_data, MSG_ALRDIS, id, NULL, isjson);
|
||||
return;
|
||||
@ -2752,7 +2786,7 @@ void notifystatus(struct io_data *io_data, int device, struct cgpu_info *cgpu, b
|
||||
// ALL counters (and only counters) must start the name with a '*'
|
||||
// Simplifies future external support for identifying new counters
|
||||
root = api_add_int(root, "NOTIFY", &device, false);
|
||||
root = api_add_string(root, "Name", cgpu->api->name, false);
|
||||
root = api_add_string(root, "Name", cgpu->drv->name, false);
|
||||
root = api_add_int(root, "ID", &(cgpu->device_id), false);
|
||||
root = api_add_time(root, "Last Well", &(cgpu->device_last_well), false);
|
||||
root = api_add_time(root, "Last Not Well", &(cgpu->device_last_not_well), false);
|
||||
@ -2774,6 +2808,7 @@ void notifystatus(struct io_data *io_data, int device, struct cgpu_info *cgpu, b
|
||||
|
||||
static void notify(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, char group)
|
||||
{
|
||||
struct cgpu_info *cgpu;
|
||||
bool io_open = false;
|
||||
int i;
|
||||
|
||||
@ -2787,8 +2822,10 @@ static void notify(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe
|
||||
if (isjson)
|
||||
io_open = io_add(io_data, COMSTR JSON_NOTIFY);
|
||||
|
||||
for (i = 0; i < total_devices; i++)
|
||||
notifystatus(io_data, i, devices[i], isjson, group);
|
||||
for (i = 0; i < total_devices; i++) {
|
||||
cgpu = get_devices(i);
|
||||
notifystatus(io_data, i, cgpu, isjson, group);
|
||||
}
|
||||
|
||||
if (isjson && io_open)
|
||||
io_close(io_data);
|
||||
@ -2813,12 +2850,12 @@ static void devdetails(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m
|
||||
io_open = io_add(io_data, COMSTR JSON_DEVDETAILS);
|
||||
|
||||
for (i = 0; i < total_devices; i++) {
|
||||
cgpu = devices[i];
|
||||
cgpu = get_devices(i);
|
||||
|
||||
root = api_add_int(root, "DEVDETAILS", &i, false);
|
||||
root = api_add_string(root, "Name", cgpu->api->name, false);
|
||||
root = api_add_string(root, "Name", cgpu->drv->name, false);
|
||||
root = api_add_int(root, "ID", &(cgpu->device_id), false);
|
||||
root = api_add_string(root, "Driver", cgpu->api->dname, false);
|
||||
root = api_add_string(root, "Driver", cgpu->drv->dname, false);
|
||||
root = api_add_const(root, "Kernel", cgpu->kname ? : BLANK, false);
|
||||
root = api_add_const(root, "Model", cgpu->name ? : BLANK, false);
|
||||
root = api_add_const(root, "Device Path", cgpu->device_path ? : BLANK, false);
|
||||
@ -2895,6 +2932,8 @@ static int itemstats(struct io_data *io_data, int i, char *id, struct cgminer_st
|
||||
root = api_add_uint64(root, "Bytes Sent", &(pool_stats->bytes_sent), false);
|
||||
root = api_add_uint64(root, "Times Recv", &(pool_stats->times_received), false);
|
||||
root = api_add_uint64(root, "Bytes Recv", &(pool_stats->bytes_received), false);
|
||||
root = api_add_uint64(root, "Net Bytes Sent", &(pool_stats->net_bytes_sent), false);
|
||||
root = api_add_uint64(root, "Net Bytes Recv", &(pool_stats->net_bytes_received), false);
|
||||
}
|
||||
|
||||
if (extra)
|
||||
@ -2908,6 +2947,7 @@ static int itemstats(struct io_data *io_data, int i, char *id, struct cgminer_st
|
||||
|
||||
static void minerstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
struct cgpu_info *cgpu;
|
||||
bool io_open = false;
|
||||
struct api_data *extra;
|
||||
char id[20];
|
||||
@ -2920,15 +2960,15 @@ static void minerstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m
|
||||
|
||||
i = 0;
|
||||
for (j = 0; j < total_devices; j++) {
|
||||
struct cgpu_info *cgpu = devices[j];
|
||||
cgpu = get_devices(j);
|
||||
|
||||
if (cgpu && cgpu->api) {
|
||||
if (cgpu->api->get_api_stats)
|
||||
extra = cgpu->api->get_api_stats(cgpu);
|
||||
if (cgpu && cgpu->drv) {
|
||||
if (cgpu->drv->get_api_stats)
|
||||
extra = cgpu->drv->get_api_stats(cgpu);
|
||||
else
|
||||
extra = NULL;
|
||||
|
||||
sprintf(id, "%s%d", cgpu->api->name, cgpu->device_id);
|
||||
sprintf(id, "%s%d", cgpu->drv->name, cgpu->device_id);
|
||||
i = itemstats(io_data, i, id, &(cgpu->cgminer_stats), NULL, extra, isjson);
|
||||
}
|
||||
}
|
||||
@ -3120,7 +3160,7 @@ static void usbstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __may
|
||||
{
|
||||
struct api_data *root = NULL;
|
||||
|
||||
#ifdef USE_MODMINER
|
||||
#if defined(USE_MODMINER) || defined(USE_BITFORCE)
|
||||
char buf[TMPBUFSIZ];
|
||||
bool io_open = false;
|
||||
int count = 0;
|
||||
@ -3133,7 +3173,7 @@ static void usbstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __may
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef USE_MODMINER
|
||||
#if defined(USE_MODMINER) || defined(USE_BITFORCE)
|
||||
|
||||
message(io_data, MSG_USBSTA, 0, NULL, isjson);
|
||||
|
||||
@ -3160,6 +3200,8 @@ static void usbstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __may
|
||||
#ifdef HAVE_AN_FPGA
|
||||
static void pgaset(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
struct cgpu_info *cgpu;
|
||||
struct device_drv *drv;
|
||||
char buf[TMPBUFSIZ];
|
||||
int numpga = numpgas();
|
||||
|
||||
@ -3193,17 +3235,17 @@ static void pgaset(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe
|
||||
return;
|
||||
}
|
||||
|
||||
struct cgpu_info *cgpu = devices[dev];
|
||||
struct device_api *api = cgpu->api;
|
||||
cgpu = get_devices(dev);
|
||||
drv = cgpu->drv;
|
||||
|
||||
char *set = strchr(opt, ',');
|
||||
if (set)
|
||||
*(set++) = '\0';
|
||||
|
||||
if (!api->set_device)
|
||||
if (!drv->set_device)
|
||||
message(io_data, MSG_PGANOSET, id, NULL, isjson);
|
||||
else {
|
||||
char *ret = api->set_device(cgpu, opt, set, buf);
|
||||
char *ret = drv->set_device(cgpu, opt, set, buf);
|
||||
if (ret) {
|
||||
if (strcasecmp(opt, "help") == 0)
|
||||
message(io_data, MSG_PGAHELP, id, ret, isjson);
|
||||
@ -3215,6 +3257,54 @@ static void pgaset(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe
|
||||
}
|
||||
#endif
|
||||
|
||||
static void dozero(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
if (param == NULL || *param == '\0') {
|
||||
message(io_data, MSG_ZERMIS, 0, NULL, isjson);
|
||||
return;
|
||||
}
|
||||
|
||||
char *sum = strchr(param, ',');
|
||||
if (sum)
|
||||
*(sum++) = '\0';
|
||||
if (!sum || !*sum) {
|
||||
message(io_data, MSG_MISBOOL, 0, NULL, isjson);
|
||||
return;
|
||||
}
|
||||
|
||||
bool all = false;
|
||||
bool bs = false;
|
||||
if (strcasecmp(param, "all") == 0)
|
||||
all = true;
|
||||
else if (strcasecmp(param, "bestshare") == 0)
|
||||
bs = true;
|
||||
|
||||
if (all == false && bs == false) {
|
||||
message(io_data, MSG_ZERINV, 0, param, isjson);
|
||||
return;
|
||||
}
|
||||
|
||||
*sum = tolower(*sum);
|
||||
if (*sum != 't' && *sum != 'f') {
|
||||
message(io_data, MSG_INVBOOL, 0, NULL, isjson);
|
||||
return;
|
||||
}
|
||||
|
||||
bool dosum = (*sum == 't');
|
||||
if (dosum)
|
||||
print_summary();
|
||||
|
||||
if (all)
|
||||
zero_stats();
|
||||
if (bs)
|
||||
zero_bestshare();
|
||||
|
||||
if (dosum)
|
||||
message(io_data, MSG_ZERSUM, 0, all ? "All" : "BestShare", isjson);
|
||||
else
|
||||
message(io_data, MSG_ZERNOSUM, 0, all ? "All" : "BestShare", isjson);
|
||||
}
|
||||
|
||||
static void checkcommand(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, char group);
|
||||
|
||||
struct CMDS {
|
||||
@ -3274,6 +3364,7 @@ struct CMDS {
|
||||
#ifdef HAVE_AN_FPGA
|
||||
{ "pgaset", pgaset, true },
|
||||
#endif
|
||||
{ "zero", dozero, true },
|
||||
{ NULL, NULL, false }
|
||||
};
|
||||
|
||||
@ -3701,7 +3792,7 @@ void api(int api_thr_id)
|
||||
|
||||
/* This should be done before curl in needed
|
||||
* to ensure curl has already called WSAStartup() in windows */
|
||||
sleep(opt_log_interval);
|
||||
nmsleep(opt_log_interval*1000);
|
||||
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sock == INVSOCK) {
|
||||
@ -3747,7 +3838,7 @@ void api(int api_thr_id)
|
||||
break;
|
||||
else {
|
||||
applog(LOG_WARNING, "API bind to port %d failed - trying again in 30sec", port);
|
||||
sleep(30);
|
||||
nmsleep(30000);
|
||||
}
|
||||
} else
|
||||
bound = 1;
|
||||
|
@ -273,6 +273,7 @@ fi
|
||||
|
||||
|
||||
AM_CONDITIONAL([NEED_FPGAUTILS], [test x$icarus$bitforce$modminer$ztex != xnononono])
|
||||
AM_CONDITIONAL([NEED_USBUTILS_C], [test x$bitforce$modminer != xnono])
|
||||
AM_CONDITIONAL([HAVE_CURSES], [test x$curses = xyes])
|
||||
AM_CONDITIONAL([WANT_JANSSON], [test x$request_jansson = xtrue])
|
||||
AM_CONDITIONAL([HAVE_WINDOWS], [test x$have_win32 = xtrue])
|
||||
@ -321,7 +322,7 @@ fi
|
||||
|
||||
AM_CONDITIONAL([HAS_YASM], [test x$has_yasm = xtrue])
|
||||
|
||||
if test "x$bitforce" != xno; then
|
||||
if test "x$icarus" != xno; then
|
||||
AC_ARG_WITH([libudev], [AC_HELP_STRING([--without-libudev], [Autodetect FPGAs using libudev (default enabled)])],
|
||||
[libudev=$withval],
|
||||
[libudev=auto]
|
||||
@ -343,7 +344,7 @@ AM_CONDITIONAL([HAVE_LIBUDEV], [test x$libudev != xno])
|
||||
|
||||
PKG_PROG_PKG_CONFIG()
|
||||
|
||||
if test "x$ztex$modminer" != xnono; then
|
||||
if test "x$ztex$modminer$bitforce" != xnonono; then
|
||||
case $target in
|
||||
*-*-freebsd*)
|
||||
LIBUSB_LIBS="-lusb"
|
||||
@ -508,7 +509,7 @@ else
|
||||
echo " Ztex.FPGAs...........: Disabled"
|
||||
fi
|
||||
|
||||
if test "x$bitforce" != xno; then
|
||||
if test "x$icarus" != xno; then
|
||||
echo " libudev.detection....: $libudev"
|
||||
fi
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2013 Andrew Smith
|
||||
* Copyright 2012 Luke Dashjr
|
||||
* Copyright 2012 Con Kolivas
|
||||
*
|
||||
@ -19,34 +20,35 @@
|
||||
#include "config.h"
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#define dlsym (void*)GetProcAddress
|
||||
#define dlclose FreeLibrary
|
||||
|
||||
typedef unsigned long FT_STATUS;
|
||||
typedef PVOID FT_HANDLE;
|
||||
__stdcall FT_STATUS (*FT_ListDevices)(PVOID pArg1, PVOID pArg2, DWORD Flags);
|
||||
__stdcall FT_STATUS (*FT_Open)(int idx, FT_HANDLE*);
|
||||
__stdcall FT_STATUS (*FT_GetComPortNumber)(FT_HANDLE, LPLONG lplComPortNumber);
|
||||
__stdcall FT_STATUS (*FT_Close)(FT_HANDLE);
|
||||
const uint32_t FT_OPEN_BY_DESCRIPTION = 2;
|
||||
const uint32_t FT_LIST_ALL = 0x20000000;
|
||||
const uint32_t FT_LIST_NUMBER_ONLY = 0x80000000;
|
||||
enum {
|
||||
FT_OK,
|
||||
};
|
||||
|
||||
// Code must deal with a timeout. Make it 1 second on windows, 0.1 on linux.
|
||||
#define BFopen(devpath) serial_open(devpath, 0, 10, true)
|
||||
#else /* WIN32 */
|
||||
#define BFopen(devpath) serial_open(devpath, 0, 1, true)
|
||||
#endif /* WIN32 */
|
||||
|
||||
#include "compat.h"
|
||||
#include "miner.h"
|
||||
#include "fpgautils.h"
|
||||
#include "usbutils.h"
|
||||
|
||||
#define BITFORCE_IDENTIFY "ZGX"
|
||||
#define BITFORCE_IDENTIFY_LEN (sizeof(BITFORCE_IDENTIFY)-1)
|
||||
#define BITFORCE_FLASH "ZMX"
|
||||
#define BITFORCE_FLASH_LEN (sizeof(BITFORCE_FLASH)-1)
|
||||
#define BITFORCE_TEMPERATURE "ZLX"
|
||||
#define BITFORCE_TEMPERATURE_LEN (sizeof(BITFORCE_TEMPERATURE)-1)
|
||||
#define BITFORCE_SENDRANGE "ZPX"
|
||||
#define BITFORCE_SENDRANGE_LEN (sizeof(BITFORCE_SENDRANGE)-1)
|
||||
#define BITFORCE_SENDWORK "ZDX"
|
||||
#define BITFORCE_SENDWORK_LEN (sizeof(BITFORCE_SENDWORK)-1)
|
||||
#define BITFORCE_WORKSTATUS "ZFX"
|
||||
#define BITFORCE_WORKSTATUS_LEN (sizeof(BITFORCE_WORKSTATUS)-1)
|
||||
|
||||
// Either of Nonce or No-nonce start with:
|
||||
#define BITFORCE_EITHER "N"
|
||||
#define BITFORCE_EITHER_LEN 1
|
||||
#define BITFORCE_NONCE "NONCE-FOUND"
|
||||
#define BITFORCE_NONCE_LEN (sizeof(BITFORCE_NONCE)-1)
|
||||
#define BITFORCE_NO_NONCE "NO-NONCE"
|
||||
#define BITFORCE_NO_NONCE_MATCH 3
|
||||
#define BITFORCE_IDLE "IDLE"
|
||||
#define BITFORCE_IDLE_MATCH 1
|
||||
|
||||
#define BITFORCE_SLEEP_MS 500
|
||||
#define BITFORCE_TIMEOUT_S 7
|
||||
@ -62,62 +64,197 @@ enum {
|
||||
#define KNAME_WORK "full work"
|
||||
#define KNAME_RANGE "nonce range"
|
||||
|
||||
struct device_api bitforce_api;
|
||||
#define BITFORCE_BUFSIZ (0x200)
|
||||
|
||||
static void BFgets(char *buf, size_t bufLen, int fd)
|
||||
// If initialisation fails the first time,
|
||||
// sleep this amount (ms) and try again
|
||||
#define REINIT_TIME_FIRST_MS 100
|
||||
// Max ms per sleep
|
||||
#define REINIT_TIME_MAX_MS 800
|
||||
// Keep trying up to this many us
|
||||
#define REINIT_TIME_MAX 3000000
|
||||
|
||||
static const char *blank = "";
|
||||
|
||||
struct device_drv bitforce_drv;
|
||||
|
||||
static void bitforce_initialise(struct cgpu_info *bitforce, bool lock)
|
||||
{
|
||||
do {
|
||||
buf[0] = '\0';
|
||||
--bufLen;
|
||||
} while (likely(bufLen && read(fd, buf, 1) == 1 && (buf++)[0] != '\n'));
|
||||
int err;
|
||||
|
||||
buf[0] = '\0';
|
||||
if (lock)
|
||||
mutex_lock(&bitforce->device_mutex);
|
||||
|
||||
// Reset
|
||||
err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET,
|
||||
FTDI_VALUE_RESET, bitforce->usbdev->found->interface, C_RESET);
|
||||
if (opt_debug)
|
||||
applog(LOG_DEBUG, "%s%i: reset got err %d",
|
||||
bitforce->drv->name, bitforce->device_id, err);
|
||||
|
||||
if (bitforce->usbinfo.nodev)
|
||||
goto failed;
|
||||
|
||||
// Set data control
|
||||
err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_DATA,
|
||||
FTDI_VALUE_DATA, bitforce->usbdev->found->interface, C_SETDATA);
|
||||
if (opt_debug)
|
||||
applog(LOG_DEBUG, "%s%i: setdata got err %d",
|
||||
bitforce->drv->name, bitforce->device_id, err);
|
||||
|
||||
if (bitforce->usbinfo.nodev)
|
||||
goto failed;
|
||||
|
||||
// Set the baud
|
||||
err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_BAUD, FTDI_VALUE_BAUD,
|
||||
(FTDI_INDEX_BAUD & 0xff00) | bitforce->usbdev->found->interface,
|
||||
C_SETBAUD);
|
||||
if (opt_debug)
|
||||
applog(LOG_DEBUG, "%s%i: setbaud got err %d",
|
||||
bitforce->drv->name, bitforce->device_id, err);
|
||||
|
||||
if (bitforce->usbinfo.nodev)
|
||||
goto failed;
|
||||
|
||||
// Set Flow Control
|
||||
err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_FLOW,
|
||||
FTDI_VALUE_FLOW, bitforce->usbdev->found->interface, C_SETFLOW);
|
||||
if (opt_debug)
|
||||
applog(LOG_DEBUG, "%s%i: setflowctrl got err %d",
|
||||
bitforce->drv->name, bitforce->device_id, err);
|
||||
|
||||
if (bitforce->usbinfo.nodev)
|
||||
goto failed;
|
||||
|
||||
// Set Modem Control
|
||||
err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_MODEM,
|
||||
FTDI_VALUE_MODEM, bitforce->usbdev->found->interface, C_SETMODEM);
|
||||
if (opt_debug)
|
||||
applog(LOG_DEBUG, "%s%i: setmodemctrl got err %d",
|
||||
bitforce->drv->name, bitforce->device_id, err);
|
||||
|
||||
if (bitforce->usbinfo.nodev)
|
||||
goto failed;
|
||||
|
||||
// Clear any sent data
|
||||
err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET,
|
||||
FTDI_VALUE_PURGE_TX, bitforce->usbdev->found->interface, C_PURGETX);
|
||||
if (opt_debug)
|
||||
applog(LOG_DEBUG, "%s%i: purgetx got err %d",
|
||||
bitforce->drv->name, bitforce->device_id, err);
|
||||
|
||||
if (bitforce->usbinfo.nodev)
|
||||
goto failed;
|
||||
|
||||
// Clear any received data
|
||||
err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET,
|
||||
FTDI_VALUE_PURGE_RX, bitforce->usbdev->found->interface, C_PURGERX);
|
||||
if (opt_debug)
|
||||
applog(LOG_DEBUG, "%s%i: purgerx got err %d",
|
||||
bitforce->drv->name, bitforce->device_id, err);
|
||||
|
||||
failed:
|
||||
|
||||
if (lock)
|
||||
mutex_unlock(&bitforce->device_mutex);
|
||||
}
|
||||
|
||||
static ssize_t BFwrite(int fd, const void *buf, ssize_t bufLen)
|
||||
static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devices *found)
|
||||
{
|
||||
if ((bufLen) != write(fd, buf, bufLen))
|
||||
return 0;
|
||||
else
|
||||
return bufLen;
|
||||
}
|
||||
|
||||
#define BFclose(fd) close(fd)
|
||||
|
||||
static bool bitforce_detect_one(const char *devpath)
|
||||
{
|
||||
int fdDev = BFopen(devpath);
|
||||
struct cgpu_info *bitforce;
|
||||
char pdevbuf[0x100];
|
||||
char buf[BITFORCE_BUFSIZ+1];
|
||||
char devpath[20];
|
||||
int err, amount;
|
||||
char *s;
|
||||
struct timeval init_start, init_now;
|
||||
int init_sleep, init_count;
|
||||
bool ident_first;
|
||||
|
||||
applog(LOG_DEBUG, "BFL: Attempting to open %s", devpath);
|
||||
struct cgpu_info *bitforce = NULL;
|
||||
bitforce = calloc(1, sizeof(*bitforce));
|
||||
bitforce->drv = &bitforce_drv;
|
||||
bitforce->deven = DEV_ENABLED;
|
||||
bitforce->threads = 1;
|
||||
|
||||
if (unlikely(fdDev == -1)) {
|
||||
applog(LOG_ERR, "BFL: Failed to open %s", devpath);
|
||||
return false;
|
||||
if (!usb_init(bitforce, dev, found)) {
|
||||
applog(LOG_ERR, "%s detect (%d:%d) failed to initialise (incorrect device?)",
|
||||
bitforce->drv->dname,
|
||||
(int)(bitforce->usbinfo.bus_number),
|
||||
(int)(bitforce->usbinfo.device_address));
|
||||
goto shin;
|
||||
}
|
||||
|
||||
BFwrite(fdDev, "ZGX", 3);
|
||||
pdevbuf[0] = '\0';
|
||||
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
|
||||
if (unlikely(!pdevbuf[0])) {
|
||||
applog(LOG_ERR, "BFL: Error reading/timeout (ZGX)");
|
||||
return 0;
|
||||
sprintf(devpath, "%d:%d",
|
||||
(int)(bitforce->usbinfo.bus_number),
|
||||
(int)(bitforce->usbinfo.device_address));
|
||||
|
||||
|
||||
// Allow 2 complete attempts if the 1st time returns an unrecognised reply
|
||||
ident_first = true;
|
||||
retry:
|
||||
init_count = 0;
|
||||
init_sleep = REINIT_TIME_FIRST_MS;
|
||||
gettimeofday(&init_start, NULL);
|
||||
reinit:
|
||||
bitforce_initialise(bitforce, false);
|
||||
if ((err = usb_write(bitforce, BITFORCE_IDENTIFY, BITFORCE_IDENTIFY_LEN, &amount, C_REQUESTIDENTIFY)) < 0 || amount != BITFORCE_IDENTIFY_LEN) {
|
||||
applog(LOG_ERR, "%s detect (%s) send identify request failed (%d:%d)",
|
||||
bitforce->drv->dname, devpath, amount, err);
|
||||
goto unshin;
|
||||
}
|
||||
|
||||
BFclose(fdDev);
|
||||
if (unlikely(!strstr(pdevbuf, "SHA256"))) {
|
||||
applog(LOG_ERR, "BFL: Didn't recognise BitForce on %s", devpath);
|
||||
return false;
|
||||
if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETIDENTIFY)) < 0 || amount < 1) {
|
||||
init_count++;
|
||||
gettimeofday(&init_now, NULL);
|
||||
if (us_tdiff(&init_now, &init_start) <= REINIT_TIME_MAX) {
|
||||
if (init_count == 2) {
|
||||
applog(LOG_WARNING, "%s detect (%s) 2nd init failed (%d:%d) - retrying",
|
||||
bitforce->drv->dname, devpath, amount, err);
|
||||
}
|
||||
nmsleep(init_sleep);
|
||||
if ((init_sleep * 2) <= REINIT_TIME_MAX_MS)
|
||||
init_sleep *= 2;
|
||||
goto reinit;
|
||||
}
|
||||
|
||||
if (init_count > 0)
|
||||
applog(LOG_WARNING, "%s detect (%s) init failed %d times %.2fs",
|
||||
bitforce->drv->dname, devpath, init_count, tdiff(&init_now, &init_start));
|
||||
|
||||
if (err < 0) {
|
||||
applog(LOG_ERR, "%s detect (%s) error identify reply (%d:%d)",
|
||||
bitforce->drv->dname, devpath, amount, err);
|
||||
} else {
|
||||
applog(LOG_ERR, "%s detect (%s) empty identify reply (%d)",
|
||||
bitforce->drv->dname, devpath, amount);
|
||||
}
|
||||
|
||||
goto unshin;
|
||||
}
|
||||
buf[amount] = '\0';
|
||||
|
||||
if (unlikely(!strstr(buf, "SHA256"))) {
|
||||
if (ident_first) {
|
||||
applog(LOG_WARNING, "%s detect (%s) didn't recognise '%s' trying again ...",
|
||||
bitforce->drv->dname, devpath, buf);
|
||||
ident_first = false;
|
||||
goto retry;
|
||||
}
|
||||
applog(LOG_ERR, "%s detect (%s) didn't recognise '%s' on 2nd attempt",
|
||||
bitforce->drv->dname, devpath, buf);
|
||||
goto unshin;
|
||||
}
|
||||
|
||||
if (likely((!memcmp(buf, ">>>ID: ", 7)) && (s = strstr(buf + 3, ">>>")))) {
|
||||
s[0] = '\0';
|
||||
bitforce->name = strdup(buf + 7);
|
||||
} else {
|
||||
bitforce->name = (char *)blank;
|
||||
}
|
||||
|
||||
// We have a real BitForce!
|
||||
bitforce = calloc(1, sizeof(*bitforce));
|
||||
bitforce->api = &bitforce_api;
|
||||
bitforce->device_path = strdup(devpath);
|
||||
bitforce->deven = DEV_ENABLED;
|
||||
bitforce->threads = 1;
|
||||
applog(LOG_DEBUG, "%s (%s) identified as: '%s'",
|
||||
bitforce->drv->dname, devpath, bitforce->name);
|
||||
|
||||
/* Initially enable support for nonce range and disable it later if it
|
||||
* fails */
|
||||
if (opt_bfl_noncerange) {
|
||||
@ -129,108 +266,39 @@ static bool bitforce_detect_one(const char *devpath)
|
||||
bitforce->kname = KNAME_WORK;
|
||||
}
|
||||
|
||||
if (likely((!memcmp(pdevbuf, ">>>ID: ", 7)) && (s = strstr(pdevbuf + 3, ">>>")))) {
|
||||
s[0] = '\0';
|
||||
bitforce->name = strdup(pdevbuf + 7);
|
||||
}
|
||||
bitforce->device_path = strdup(devpath);
|
||||
|
||||
if (!add_cgpu(bitforce))
|
||||
goto unshin;
|
||||
|
||||
update_usb_stats(bitforce);
|
||||
|
||||
mutex_init(&bitforce->device_mutex);
|
||||
|
||||
return add_cgpu(bitforce);
|
||||
}
|
||||
return true;
|
||||
|
||||
#define LOAD_SYM(sym) do { \
|
||||
if (!(sym = dlsym(dll, #sym))) { \
|
||||
applog(LOG_DEBUG, "Failed to load " #sym ", not using FTDI bitforce autodetect"); \
|
||||
goto out; \
|
||||
} \
|
||||
} while(0)
|
||||
unshin:
|
||||
|
||||
#ifdef WIN32
|
||||
static int bitforce_autodetect_ftdi(void)
|
||||
{
|
||||
char devpath[] = "\\\\.\\COMnnnnn";
|
||||
char *devpathnum = &devpath[7];
|
||||
char **bufptrs;
|
||||
char *buf;
|
||||
int found = 0;
|
||||
DWORD i;
|
||||
usb_uninit(bitforce);
|
||||
|
||||
FT_STATUS ftStatus;
|
||||
DWORD numDevs;
|
||||
HMODULE dll = LoadLibrary("FTD2XX.DLL");
|
||||
if (!dll) {
|
||||
applog(LOG_DEBUG, "FTD2XX.DLL failed to load, not using FTDI bitforce autodetect");
|
||||
return 0;
|
||||
}
|
||||
LOAD_SYM(FT_ListDevices);
|
||||
LOAD_SYM(FT_Open);
|
||||
LOAD_SYM(FT_GetComPortNumber);
|
||||
LOAD_SYM(FT_Close);
|
||||
|
||||
ftStatus = FT_ListDevices(&numDevs, NULL, FT_LIST_NUMBER_ONLY);
|
||||
if (ftStatus != FT_OK) {
|
||||
applog(LOG_DEBUG, "FTDI device count failed, not using FTDI bitforce autodetect");
|
||||
goto out;
|
||||
}
|
||||
applog(LOG_DEBUG, "FTDI reports %u devices", (unsigned)numDevs);
|
||||
shin:
|
||||
|
||||
buf = alloca(65 * numDevs);
|
||||
bufptrs = alloca(sizeof(*bufptrs) * (numDevs + 1));
|
||||
free(bitforce->device_path);
|
||||
|
||||
for (i = 0; i < numDevs; ++i)
|
||||
bufptrs[i] = &buf[i * 65];
|
||||
bufptrs[numDevs] = NULL;
|
||||
ftStatus = FT_ListDevices(bufptrs, &numDevs, FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION);
|
||||
if (ftStatus != FT_OK) {
|
||||
applog(LOG_DEBUG, "FTDI device list failed, not using FTDI bitforce autodetect");
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = numDevs; i > 0; ) {
|
||||
--i;
|
||||
bufptrs[i][64] = '\0';
|
||||
|
||||
if (!(strstr(bufptrs[i], "BitFORCE") && strstr(bufptrs[i], "SHA256")))
|
||||
continue;
|
||||
|
||||
FT_HANDLE ftHandle;
|
||||
if (FT_OK != FT_Open(i, &ftHandle))
|
||||
continue;
|
||||
LONG lComPortNumber;
|
||||
ftStatus = FT_GetComPortNumber(ftHandle, &lComPortNumber);
|
||||
FT_Close(ftHandle);
|
||||
if (FT_OK != ftStatus || lComPortNumber < 0)
|
||||
continue;
|
||||
|
||||
sprintf(devpathnum, "%d", (int)lComPortNumber);
|
||||
|
||||
if (bitforce_detect_one(devpath))
|
||||
++found;
|
||||
}
|
||||
if (bitforce->name != blank)
|
||||
free(bitforce->name);
|
||||
|
||||
out:
|
||||
dlclose(dll);
|
||||
return found;
|
||||
}
|
||||
#else
|
||||
static int bitforce_autodetect_ftdi(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (bitforce->drv->copy)
|
||||
free(bitforce->drv);
|
||||
|
||||
static int bitforce_detect_auto(void)
|
||||
{
|
||||
return (serial_autodetect_udev (bitforce_detect_one, "BitFORCE*SHA256") ?:
|
||||
serial_autodetect_devserial(bitforce_detect_one, "BitFORCE_SHA256") ?:
|
||||
bitforce_autodetect_ftdi() ?:
|
||||
0);
|
||||
free(bitforce);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void bitforce_detect(void)
|
||||
{
|
||||
serial_detect_auto(&bitforce_api, bitforce_detect_one, bitforce_detect_auto);
|
||||
usb_detect(&bitforce_drv, bitforce_detect_one);
|
||||
}
|
||||
|
||||
static void get_bitforce_statline_before(char *buf, struct cgpu_info *bitforce)
|
||||
@ -247,105 +315,17 @@ static void get_bitforce_statline_before(char *buf, struct cgpu_info *bitforce)
|
||||
static bool bitforce_thread_prepare(struct thr_info *thr)
|
||||
{
|
||||
struct cgpu_info *bitforce = thr->cgpu;
|
||||
int fdDev = BFopen(bitforce->device_path);
|
||||
struct timeval now;
|
||||
|
||||
if (unlikely(fdDev == -1)) {
|
||||
applog(LOG_ERR, "BFL%i: Failed to open %s", bitforce->device_id, bitforce->device_path);
|
||||
return false;
|
||||
}
|
||||
|
||||
bitforce->device_fd = fdDev;
|
||||
|
||||
applog(LOG_INFO, "BFL%i: Opened %s", bitforce->device_id, bitforce->device_path);
|
||||
gettimeofday(&now, NULL);
|
||||
get_datestamp(bitforce->init, &now);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void bitforce_clear_buffer(struct cgpu_info *bitforce)
|
||||
{
|
||||
int fdDev = bitforce->device_fd;
|
||||
char pdevbuf[0x100];
|
||||
int count = 0;
|
||||
|
||||
if (!fdDev)
|
||||
return;
|
||||
|
||||
applog(LOG_DEBUG, "BFL%i: Clearing read buffer", bitforce->device_id);
|
||||
|
||||
mutex_lock(&bitforce->device_mutex);
|
||||
do {
|
||||
pdevbuf[0] = '\0';
|
||||
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
|
||||
} while (pdevbuf[0] && (++count < 10));
|
||||
mutex_unlock(&bitforce->device_mutex);
|
||||
}
|
||||
|
||||
void bitforce_init(struct cgpu_info *bitforce)
|
||||
{
|
||||
char *devpath = bitforce->device_path;
|
||||
int fdDev = bitforce->device_fd, retries = 0;
|
||||
char pdevbuf[0x100];
|
||||
char *s;
|
||||
|
||||
applog(LOG_WARNING, "BFL%i: Re-initialising", bitforce->device_id);
|
||||
|
||||
bitforce_clear_buffer(bitforce);
|
||||
|
||||
mutex_lock(&bitforce->device_mutex);
|
||||
if (fdDev) {
|
||||
BFclose(fdDev);
|
||||
sleep(5);
|
||||
}
|
||||
bitforce->device_fd = 0;
|
||||
|
||||
fdDev = BFopen(devpath);
|
||||
if (unlikely(fdDev == -1)) {
|
||||
mutex_unlock(&bitforce->device_mutex);
|
||||
applog(LOG_ERR, "BFL%i: Failed to open %s", bitforce->device_id, devpath);
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
BFwrite(fdDev, "ZGX", 3);
|
||||
pdevbuf[0] = '\0';
|
||||
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
|
||||
|
||||
if (unlikely(!pdevbuf[0])) {
|
||||
mutex_unlock(&bitforce->device_mutex);
|
||||
applog(LOG_ERR, "BFL%i: Error reading/timeout (ZGX)", bitforce->device_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (retries++)
|
||||
nmsleep(10);
|
||||
} while (!strstr(pdevbuf, "BUSY") && (retries * 10 < BITFORCE_TIMEOUT_MS));
|
||||
|
||||
if (unlikely(!strstr(pdevbuf, "SHA256"))) {
|
||||
mutex_unlock(&bitforce->device_mutex);
|
||||
applog(LOG_ERR, "BFL%i: Didn't recognise BitForce on %s returned: %s", bitforce->device_id, devpath, pdevbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (likely((!memcmp(pdevbuf, ">>>ID: ", 7)) && (s = strstr(pdevbuf + 3, ">>>")))) {
|
||||
s[0] = '\0';
|
||||
bitforce->name = strdup(pdevbuf + 7);
|
||||
}
|
||||
|
||||
bitforce->device_fd = fdDev;
|
||||
bitforce->sleep_ms = BITFORCE_SLEEP_MS;
|
||||
|
||||
mutex_unlock(&bitforce->device_mutex);
|
||||
}
|
||||
|
||||
static void bitforce_flash_led(struct cgpu_info *bitforce)
|
||||
{
|
||||
int fdDev = bitforce->device_fd;
|
||||
|
||||
if (!fdDev)
|
||||
return;
|
||||
int err, amount;
|
||||
|
||||
/* Do not try to flash the led if we're polling for a result to
|
||||
* minimise the chance of interleaved results */
|
||||
@ -353,19 +333,22 @@ static void bitforce_flash_led(struct cgpu_info *bitforce)
|
||||
return;
|
||||
|
||||
/* It is not critical flashing the led so don't get stuck if we
|
||||
* can't grab the mutex here */
|
||||
* can't grab the mutex now */
|
||||
if (mutex_trylock(&bitforce->device_mutex))
|
||||
return;
|
||||
|
||||
BFwrite(fdDev, "ZMX", 3);
|
||||
if ((err = usb_write(bitforce, BITFORCE_FLASH, BITFORCE_FLASH_LEN, &amount, C_REQUESTFLASH)) < 0 || amount != BITFORCE_FLASH_LEN) {
|
||||
applog(LOG_ERR, "%s%i: flash request failed (%d:%d)",
|
||||
bitforce->drv->name, bitforce->device_id, amount, err);
|
||||
} else {
|
||||
/* However, this stops anything else getting a reply
|
||||
* So best to delay any other access to the BFL */
|
||||
nmsleep(4000);
|
||||
}
|
||||
|
||||
/* Once we've tried - don't do it until told to again */
|
||||
bitforce->flash_led = false;
|
||||
|
||||
/* However, this stops anything else getting a reply
|
||||
* So best to delay any other access to the BFL */
|
||||
sleep(4);
|
||||
|
||||
mutex_unlock(&bitforce->device_mutex);
|
||||
|
||||
return; // nothing is returned by the BFL
|
||||
@ -373,11 +356,12 @@ static void bitforce_flash_led(struct cgpu_info *bitforce)
|
||||
|
||||
static bool bitforce_get_temp(struct cgpu_info *bitforce)
|
||||
{
|
||||
int fdDev = bitforce->device_fd;
|
||||
char pdevbuf[0x100];
|
||||
char buf[BITFORCE_BUFSIZ+1];
|
||||
int err, amount;
|
||||
char *s;
|
||||
|
||||
if (!fdDev)
|
||||
// Device is gone
|
||||
if (bitforce->usbinfo.nodev)
|
||||
return false;
|
||||
|
||||
/* Do not try to get the temperature if we're polling for a result to
|
||||
@ -396,18 +380,30 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce)
|
||||
if (mutex_trylock(&bitforce->device_mutex))
|
||||
return false;
|
||||
|
||||
BFwrite(fdDev, "ZLX", 3);
|
||||
pdevbuf[0] = '\0';
|
||||
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
|
||||
mutex_unlock(&bitforce->device_mutex);
|
||||
|
||||
if (unlikely(!pdevbuf[0])) {
|
||||
applog(LOG_ERR, "BFL%i: Error: Get temp returned empty string/timed out", bitforce->device_id);
|
||||
if ((err = usb_write(bitforce, BITFORCE_TEMPERATURE, BITFORCE_TEMPERATURE_LEN, &amount, C_REQUESTTEMPERATURE)) < 0 || amount != BITFORCE_TEMPERATURE_LEN) {
|
||||
mutex_unlock(&bitforce->device_mutex);
|
||||
applog(LOG_ERR, "%s%i: Error: Request temp invalid/timed out (%d:%d)",
|
||||
bitforce->drv->name, bitforce->device_id, amount, err);
|
||||
bitforce->hw_errors++;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((!strncasecmp(pdevbuf, "TEMP", 4)) && (s = strchr(pdevbuf + 4, ':'))) {
|
||||
if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETTEMPERATURE)) < 0 || amount < 1) {
|
||||
mutex_unlock(&bitforce->device_mutex);
|
||||
if (err < 0) {
|
||||
applog(LOG_ERR, "%s%i: Error: Get temp return invalid/timed out (%d:%d)",
|
||||
bitforce->drv->name, bitforce->device_id, amount, err);
|
||||
} else {
|
||||
applog(LOG_ERR, "%s%i: Error: Get temp returned nothing (%d:%d)",
|
||||
bitforce->drv->name, bitforce->device_id, amount, err);
|
||||
}
|
||||
bitforce->hw_errors++;
|
||||
return false;
|
||||
}
|
||||
|
||||
mutex_unlock(&bitforce->device_mutex);
|
||||
|
||||
if ((!strncasecmp(buf, "TEMP", 4)) && (s = strchr(buf + 4, ':'))) {
|
||||
float temp = strtof(s + 1, NULL);
|
||||
|
||||
/* Cope with older software that breaks and reads nonsense
|
||||
@ -418,7 +414,8 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce)
|
||||
if (temp > 0) {
|
||||
bitforce->temp = temp;
|
||||
if (unlikely(bitforce->cutofftemp > 0 && temp > bitforce->cutofftemp)) {
|
||||
applog(LOG_WARNING, "BFL%i: Hit thermal cutoff limit, disabling!", bitforce->device_id);
|
||||
applog(LOG_WARNING, "%s%i: Hit thermal cutoff limit, disabling!",
|
||||
bitforce->drv->name, bitforce->device_id);
|
||||
bitforce->deven = DEV_RECOVER;
|
||||
dev_error(bitforce, REASON_DEV_THERMAL_CUTOFF);
|
||||
}
|
||||
@ -427,11 +424,12 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce)
|
||||
/* Use the temperature monitor as a kind of watchdog for when
|
||||
* our responses are out of sync and flush the buffer to
|
||||
* hopefully recover */
|
||||
applog(LOG_WARNING, "BFL%i: Garbled response probably throttling, clearing buffer", bitforce->device_id);
|
||||
applog(LOG_WARNING, "%s%i: Garbled response probably throttling, clearing buffer",
|
||||
bitforce->drv->name, bitforce->device_id);
|
||||
dev_error(bitforce, REASON_DEV_THROTTLE);
|
||||
/* Count throttling episodes as hardware errors */
|
||||
bitforce->hw_errors++;
|
||||
bitforce_clear_buffer(bitforce);
|
||||
bitforce_initialise(bitforce, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -441,35 +439,53 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce)
|
||||
static bool bitforce_send_work(struct thr_info *thr, struct work *work)
|
||||
{
|
||||
struct cgpu_info *bitforce = thr->cgpu;
|
||||
int fdDev = bitforce->device_fd;
|
||||
unsigned char ob[70];
|
||||
char pdevbuf[0x100];
|
||||
char buf[BITFORCE_BUFSIZ+1];
|
||||
int err, amount;
|
||||
char *s;
|
||||
char *cmd;
|
||||
int len;
|
||||
|
||||
if (!fdDev)
|
||||
return false;
|
||||
re_send:
|
||||
if (bitforce->nonce_range) {
|
||||
cmd = BITFORCE_SENDRANGE;
|
||||
len = BITFORCE_SENDRANGE_LEN;
|
||||
} else {
|
||||
cmd = BITFORCE_SENDWORK;
|
||||
len = BITFORCE_SENDWORK_LEN;
|
||||
}
|
||||
|
||||
mutex_lock(&bitforce->device_mutex);
|
||||
if (bitforce->nonce_range)
|
||||
BFwrite(fdDev, "ZPX", 3);
|
||||
else
|
||||
BFwrite(fdDev, "ZDX", 3);
|
||||
pdevbuf[0] = '\0';
|
||||
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
|
||||
if (!pdevbuf[0] || !strncasecmp(pdevbuf, "B", 1)) {
|
||||
if ((err = usb_write(bitforce, cmd, len, &amount, C_REQUESTSENDWORK)) < 0 || amount != len) {
|
||||
mutex_unlock(&bitforce->device_mutex);
|
||||
applog(LOG_ERR, "%s%i: request send work failed (%d:%d)",
|
||||
bitforce->drv->name, bitforce->device_id, amount, err);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_REQUESTSENDWORKSTATUS)) < 0) {
|
||||
mutex_unlock(&bitforce->device_mutex);
|
||||
applog(LOG_ERR, "%s%d: read request send work status failed (%d:%d)",
|
||||
bitforce->drv->name, bitforce->device_id, amount, err);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (amount == 0 || !buf[0] || !strncasecmp(buf, "B", 1)) {
|
||||
mutex_unlock(&bitforce->device_mutex);
|
||||
nmsleep(WORK_CHECK_INTERVAL_MS);
|
||||
goto re_send;
|
||||
} else if (unlikely(strncasecmp(pdevbuf, "OK", 2))) {
|
||||
} else if (unlikely(strncasecmp(buf, "OK", 2))) {
|
||||
mutex_unlock(&bitforce->device_mutex);
|
||||
if (bitforce->nonce_range) {
|
||||
applog(LOG_WARNING, "BFL%i: Does not support nonce range, disabling", bitforce->device_id);
|
||||
applog(LOG_WARNING, "%s%i: Does not support nonce range, disabling",
|
||||
bitforce->drv->name, bitforce->device_id);
|
||||
bitforce->nonce_range = false;
|
||||
bitforce->sleep_ms *= 5;
|
||||
bitforce->kname = KNAME_WORK;
|
||||
goto re_send;
|
||||
}
|
||||
applog(LOG_ERR, "BFL%i: Error: Send work reports: %s", bitforce->device_id, pdevbuf);
|
||||
applog(LOG_ERR, "%s%i: Error: Send work reports: %s",
|
||||
bitforce->drv->name, bitforce->device_id, buf);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -479,7 +495,7 @@ re_send:
|
||||
if (!bitforce->nonce_range) {
|
||||
sprintf((char *)ob + 8 + 32 + 12, ">>>>>>>>");
|
||||
work->blk.nonce = bitforce->nonces = 0xffffffff;
|
||||
BFwrite(fdDev, ob, 60);
|
||||
len = 60;
|
||||
} else {
|
||||
uint32_t *nonce;
|
||||
|
||||
@ -491,26 +507,41 @@ re_send:
|
||||
*nonce = htobe32(work->blk.nonce + bitforce->nonces);
|
||||
work->blk.nonce += bitforce->nonces + 1;
|
||||
sprintf((char *)ob + 8 + 32 + 12 + 8, ">>>>>>>>");
|
||||
BFwrite(fdDev, ob, 68);
|
||||
len = 68;
|
||||
}
|
||||
|
||||
if ((err = usb_write(bitforce, (char *)ob, len, &amount, C_SENDWORK)) < 0 || amount != len) {
|
||||
mutex_unlock(&bitforce->device_mutex);
|
||||
applog(LOG_ERR, "%s%i: send work failed (%d:%d)",
|
||||
bitforce->drv->name, bitforce->device_id, amount, err);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_SENDWORKSTATUS)) < 0) {
|
||||
mutex_unlock(&bitforce->device_mutex);
|
||||
applog(LOG_ERR, "%s%d: read send work status failed (%d:%d)",
|
||||
bitforce->drv->name, bitforce->device_id, amount, err);
|
||||
return false;
|
||||
}
|
||||
|
||||
pdevbuf[0] = '\0';
|
||||
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
|
||||
mutex_unlock(&bitforce->device_mutex);
|
||||
|
||||
if (opt_debug) {
|
||||
s = bin2hex(ob + 8, 44);
|
||||
applog(LOG_DEBUG, "BFL%i: block data: %s", bitforce->device_id, s);
|
||||
applog(LOG_DEBUG, "%s%i: block data: %s",
|
||||
bitforce->drv->name, bitforce->device_id, s);
|
||||
free(s);
|
||||
}
|
||||
|
||||
if (unlikely(!pdevbuf[0])) {
|
||||
applog(LOG_ERR, "BFL%i: Error: Send block data returned empty string/timed out", bitforce->device_id);
|
||||
if (amount == 0 || !buf[0]) {
|
||||
applog(LOG_ERR, "%s%i: Error: Send block data returned empty string/timed out",
|
||||
bitforce->drv->name, bitforce->device_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (unlikely(strncasecmp(pdevbuf, "OK", 2))) {
|
||||
applog(LOG_ERR, "BFL%i: Error: Send block data reports: %s", bitforce->device_id, pdevbuf);
|
||||
if (unlikely(strncasecmp(buf, "OK", 2))) {
|
||||
applog(LOG_ERR, "%s%i: Error: Send block data reports: %s",
|
||||
bitforce->drv->name, bitforce->device_id, buf);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -521,53 +552,52 @@ re_send:
|
||||
static int64_t bitforce_get_result(struct thr_info *thr, struct work *work)
|
||||
{
|
||||
struct cgpu_info *bitforce = thr->cgpu;
|
||||
int fdDev = bitforce->device_fd;
|
||||
unsigned int delay_time_ms;
|
||||
struct timeval elapsed;
|
||||
struct timeval now;
|
||||
char pdevbuf[0x100];
|
||||
char buf[BITFORCE_BUFSIZ+1];
|
||||
int amount;
|
||||
char *pnoncebuf;
|
||||
uint32_t nonce;
|
||||
|
||||
if (!fdDev)
|
||||
return -1;
|
||||
|
||||
while (1) {
|
||||
if (unlikely(thr->work_restart))
|
||||
return 0;
|
||||
|
||||
mutex_lock(&bitforce->device_mutex);
|
||||
BFwrite(fdDev, "ZFX", 3);
|
||||
pdevbuf[0] = '\0';
|
||||
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
|
||||
usb_write(bitforce, BITFORCE_WORKSTATUS, BITFORCE_WORKSTATUS_LEN, &amount, C_REQUESTWORKSTATUS);
|
||||
usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETWORKSTATUS);
|
||||
mutex_unlock(&bitforce->device_mutex);
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
timersub(&now, &bitforce->work_start_tv, &elapsed);
|
||||
|
||||
if (elapsed.tv_sec >= BITFORCE_LONG_TIMEOUT_S) {
|
||||
applog(LOG_ERR, "BFL%i: took %dms - longer than %dms", bitforce->device_id,
|
||||
applog(LOG_ERR, "%s%i: took %dms - longer than %dms",
|
||||
bitforce->drv->name, bitforce->device_id,
|
||||
tv_to_ms(elapsed), BITFORCE_LONG_TIMEOUT_MS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pdevbuf[0] && strncasecmp(pdevbuf, "B", 1)) /* BFL does not respond during throttling */
|
||||
if (amount > 0 && buf[0] && strncasecmp(buf, "B", 1)) /* BFL does not respond during throttling */
|
||||
break;
|
||||
|
||||
/* if BFL is throttling, no point checking so quickly */
|
||||
delay_time_ms = (pdevbuf[0] ? BITFORCE_CHECK_INTERVAL_MS : 2 * WORK_CHECK_INTERVAL_MS);
|
||||
delay_time_ms = (buf[0] ? BITFORCE_CHECK_INTERVAL_MS : 2 * WORK_CHECK_INTERVAL_MS);
|
||||
nmsleep(delay_time_ms);
|
||||
bitforce->wait_ms += delay_time_ms;
|
||||
}
|
||||
|
||||
if (elapsed.tv_sec > BITFORCE_TIMEOUT_S) {
|
||||
applog(LOG_ERR, "BFL%i: took %dms - longer than %dms", bitforce->device_id,
|
||||
applog(LOG_ERR, "%s%i: took %dms - longer than %dms",
|
||||
bitforce->drv->name, bitforce->device_id,
|
||||
tv_to_ms(elapsed), BITFORCE_TIMEOUT_MS);
|
||||
dev_error(bitforce, REASON_DEV_OVER_HEAT);
|
||||
|
||||
if (!pdevbuf[0]) /* Only return if we got nothing after timeout - there still may be results */
|
||||
/* Only return if we got nothing after timeout - there still may be results */
|
||||
if (amount == 0)
|
||||
return 0;
|
||||
} else if (!strncasecmp(pdevbuf, "N", 1)) {/* Hashing complete (NONCE-FOUND or NO-NONCE) */
|
||||
} else if (!strncasecmp(buf, BITFORCE_EITHER, BITFORCE_EITHER_LEN)) {
|
||||
/* Simple timing adjustment. Allow a few polls to cope with
|
||||
* OS timer delays being variably reliable. wait_ms will
|
||||
* always equal sleep_ms when we've waited greater than or
|
||||
@ -584,26 +614,31 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work)
|
||||
}
|
||||
|
||||
if (delay_time_ms != bitforce->sleep_ms)
|
||||
applog(LOG_DEBUG, "BFL%i: Wait time changed to: %d, waited %u", bitforce->device_id, bitforce->sleep_ms, bitforce->wait_ms);
|
||||
applog(LOG_DEBUG, "%s%i: Wait time changed to: %d, waited %u",
|
||||
bitforce->drv->name, bitforce->device_id,
|
||||
bitforce->sleep_ms, bitforce->wait_ms);
|
||||
|
||||
/* Work out the average time taken. Float for calculation, uint for display */
|
||||
bitforce->avg_wait_f += (tv_to_ms(elapsed) - bitforce->avg_wait_f) / TIME_AVG_CONSTANT;
|
||||
bitforce->avg_wait_d = (unsigned int) (bitforce->avg_wait_f + 0.5);
|
||||
}
|
||||
|
||||
applog(LOG_DEBUG, "BFL%i: waited %dms until %s", bitforce->device_id, bitforce->wait_ms, pdevbuf);
|
||||
if (!strncasecmp(&pdevbuf[2], "-", 1))
|
||||
applog(LOG_DEBUG, "%s%i: waited %dms until %s",
|
||||
bitforce->drv->name, bitforce->device_id,
|
||||
bitforce->wait_ms, buf);
|
||||
if (!strncasecmp(buf, BITFORCE_NO_NONCE, BITFORCE_NO_NONCE_MATCH))
|
||||
return bitforce->nonces; /* No valid nonce found */
|
||||
else if (!strncasecmp(pdevbuf, "I", 1))
|
||||
else if (!strncasecmp(buf, BITFORCE_IDLE, BITFORCE_IDLE_MATCH))
|
||||
return 0; /* Device idle */
|
||||
else if (strncasecmp(pdevbuf, "NONCE-FOUND", 11)) {
|
||||
else if (strncasecmp(buf, BITFORCE_NONCE, BITFORCE_NONCE_LEN)) {
|
||||
bitforce->hw_errors++;
|
||||
applog(LOG_WARNING, "BFL%i: Error: Get result reports: %s", bitforce->device_id, pdevbuf);
|
||||
bitforce_clear_buffer(bitforce);
|
||||
applog(LOG_WARNING, "%s%i: Error: Get result reports: %s",
|
||||
bitforce->drv->name, bitforce->device_id, buf);
|
||||
bitforce_initialise(bitforce, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pnoncebuf = &pdevbuf[12];
|
||||
pnoncebuf = &buf[12];
|
||||
|
||||
while (1) {
|
||||
hex2bin((void*)&nonce, pnoncebuf, 4);
|
||||
@ -612,7 +647,8 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work)
|
||||
#endif
|
||||
if (unlikely(bitforce->nonce_range && (nonce >= work->blk.nonce ||
|
||||
(work->blk.nonce > 0 && nonce < work->blk.nonce - bitforce->nonces - 1)))) {
|
||||
applog(LOG_WARNING, "BFL%i: Disabling broken nonce range support", bitforce->device_id);
|
||||
applog(LOG_WARNING, "%s%i: Disabling broken nonce range support",
|
||||
bitforce->drv->name, bitforce->device_id);
|
||||
bitforce->nonce_range = false;
|
||||
work->blk.nonce = 0xffffffff;
|
||||
bitforce->sleep_ms *= 5;
|
||||
@ -628,19 +664,16 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work)
|
||||
return bitforce->nonces;
|
||||
}
|
||||
|
||||
static void bitforce_shutdown(struct thr_info *thr)
|
||||
static void bitforce_shutdown(__maybe_unused struct thr_info *thr)
|
||||
{
|
||||
struct cgpu_info *bitforce = thr->cgpu;
|
||||
|
||||
BFclose(bitforce->device_fd);
|
||||
bitforce->device_fd = 0;
|
||||
// struct cgpu_info *bitforce = thr->cgpu;
|
||||
}
|
||||
|
||||
static void biforce_thread_enable(struct thr_info *thr)
|
||||
{
|
||||
struct cgpu_info *bitforce = thr->cgpu;
|
||||
|
||||
bitforce_init(bitforce);
|
||||
bitforce_initialise(bitforce, true);
|
||||
}
|
||||
|
||||
static int64_t bitforce_scanhash(struct thr_info *thr, struct work *work, int64_t __maybe_unused max_nonce)
|
||||
@ -649,6 +682,10 @@ static int64_t bitforce_scanhash(struct thr_info *thr, struct work *work, int64_
|
||||
bool send_ret;
|
||||
int64_t ret;
|
||||
|
||||
// Device is gone
|
||||
if (bitforce->usbinfo.nodev)
|
||||
return -1;
|
||||
|
||||
send_ret = bitforce_send_work(thr, work);
|
||||
|
||||
if (!restart_wait(bitforce->sleep_ms))
|
||||
@ -665,11 +702,11 @@ static int64_t bitforce_scanhash(struct thr_info *thr, struct work *work, int64_
|
||||
|
||||
if (ret == -1) {
|
||||
ret = 0;
|
||||
applog(LOG_ERR, "BFL%i: Comms error", bitforce->device_id);
|
||||
applog(LOG_ERR, "%s%i: Comms error", bitforce->drv->name, bitforce->device_id);
|
||||
dev_error(bitforce, REASON_DEV_COMMS_ERROR);
|
||||
bitforce->hw_errors++;
|
||||
/* empty read buffer */
|
||||
bitforce_clear_buffer(bitforce);
|
||||
bitforce_initialise(bitforce, true);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -692,7 +729,8 @@ static bool bitforce_thread_init(struct thr_info *thr)
|
||||
/* Pause each new thread at least 100ms between initialising
|
||||
* so the devices aren't making calls all at the same time. */
|
||||
wait = thr->id * MAX_START_DELAY_MS;
|
||||
applog(LOG_DEBUG, "BFL%i: Delaying start by %dms", bitforce->device_id, wait / 1000);
|
||||
applog(LOG_DEBUG, "%s%d: Delaying start by %dms",
|
||||
bitforce->drv->name, bitforce->device_id, wait / 1000);
|
||||
nmsleep(wait);
|
||||
|
||||
return true;
|
||||
@ -712,12 +750,12 @@ static struct api_data *bitforce_api_stats(struct cgpu_info *cgpu)
|
||||
return root;
|
||||
}
|
||||
|
||||
struct device_api bitforce_api = {
|
||||
.dname = "bitforce",
|
||||
struct device_drv bitforce_drv = {
|
||||
.drv_id = DRIVER_BITFORCE,
|
||||
.dname = "BitForce",
|
||||
.name = "BFL",
|
||||
.api_detect = bitforce_detect,
|
||||
.drv_detect = bitforce_detect,
|
||||
.get_api_stats = bitforce_api_stats,
|
||||
.reinit_device = bitforce_init,
|
||||
.get_statline_before = get_bitforce_statline_before,
|
||||
.get_stats = bitforce_get_stats,
|
||||
.identify_device = bitforce_identify,
|
||||
|
@ -758,7 +758,7 @@ static void cpu_detect()
|
||||
struct cgpu_info *cgpu;
|
||||
|
||||
cgpu = &cpus[i];
|
||||
cgpu->api = &cpu_api;
|
||||
cgpu->drv = &cpu_drv;
|
||||
cgpu->deven = DEV_ENABLED;
|
||||
cgpu->threads = 1;
|
||||
cgpu->kname = algo_names[opt_algo];
|
||||
@ -768,7 +768,7 @@ static void cpu_detect()
|
||||
|
||||
static void reinit_cpu_device(struct cgpu_info *cpu)
|
||||
{
|
||||
tq_push(thr_info[cpur_thr_id].q, cpu);
|
||||
tq_push(control_thr[cpur_thr_id].q, cpu);
|
||||
}
|
||||
|
||||
static bool cpu_thread_prepare(struct thr_info *thr)
|
||||
@ -843,10 +843,11 @@ CPUSearch:
|
||||
return last_nonce - first_nonce + 1;
|
||||
}
|
||||
|
||||
struct device_api cpu_api = {
|
||||
struct device_drv cpu_drv = {
|
||||
.drv_id = DRIVER_CPU,
|
||||
.dname = "cpu",
|
||||
.name = "CPU",
|
||||
.api_detect = cpu_detect,
|
||||
.drv_detect = cpu_detect,
|
||||
.reinit_device = reinit_cpu_device,
|
||||
.thread_prepare = cpu_thread_prepare,
|
||||
.can_limit_work = cpu_can_limit_work,
|
||||
|
@ -53,7 +53,7 @@ enum sha256_algos {
|
||||
|
||||
extern const char *algo_names[];
|
||||
extern bool opt_usecpu;
|
||||
extern struct device_api cpu_api;
|
||||
extern struct device_drv cpu_drv;
|
||||
|
||||
extern char *set_algo(const char *arg, enum sha256_algos *algo);
|
||||
extern void show_algo(char buf[OPT_SHOW_LEN], const enum sha256_algos *algo);
|
||||
|
@ -208,7 +208,7 @@ static struct ICARUS_INFO **icarus_info;
|
||||
//
|
||||
static int option_offset = -1;
|
||||
|
||||
struct device_api icarus_api;
|
||||
struct device_drv icarus_drv;
|
||||
|
||||
static void rev(unsigned char *s, size_t l)
|
||||
{
|
||||
@ -571,7 +571,7 @@ static bool icarus_detect_one(const char *devpath)
|
||||
/* We have a real Icarus! */
|
||||
struct cgpu_info *icarus;
|
||||
icarus = calloc(1, sizeof(struct cgpu_info));
|
||||
icarus->api = &icarus_api;
|
||||
icarus->drv = &icarus_drv;
|
||||
icarus->device_path = strdup(devpath);
|
||||
icarus->device_fd = -1;
|
||||
icarus->threads = 1;
|
||||
@ -609,7 +609,7 @@ static bool icarus_detect_one(const char *devpath)
|
||||
|
||||
static void icarus_detect()
|
||||
{
|
||||
serial_detect(&icarus_api, icarus_detect_one);
|
||||
serial_detect(&icarus_drv, icarus_detect_one);
|
||||
}
|
||||
|
||||
static bool icarus_prepare(struct thr_info *thr)
|
||||
@ -668,7 +668,7 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work,
|
||||
icarus = thr->cgpu;
|
||||
if (icarus->device_fd == -1)
|
||||
if (!icarus_prepare(thr)) {
|
||||
applog(LOG_ERR, "ICA%i: Comms error", icarus->device_id);
|
||||
applog(LOG_ERR, "%s%i: Comms error", icarus->drv->name, icarus->device_id);
|
||||
dev_error(icarus, REASON_DEV_COMMS_ERROR);
|
||||
|
||||
// fail the device if the reopen attempt fails
|
||||
@ -688,7 +688,7 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work,
|
||||
ret = icarus_write(fd, ob_bin, sizeof(ob_bin));
|
||||
if (ret) {
|
||||
do_icarus_close(thr);
|
||||
applog(LOG_ERR, "ICA%i: Comms error", icarus->device_id);
|
||||
applog(LOG_ERR, "%s%i: Comms error", icarus->drv->name, icarus->device_id);
|
||||
dev_error(icarus, REASON_DEV_COMMS_ERROR);
|
||||
return 0; /* This should never happen */
|
||||
}
|
||||
@ -708,7 +708,7 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work,
|
||||
ret = icarus_gets(nonce_bin, fd, &tv_finish, thr, info->read_count);
|
||||
if (ret == ICA_GETS_ERROR) {
|
||||
do_icarus_close(thr);
|
||||
applog(LOG_ERR, "ICA%i: Comms error", icarus->device_id);
|
||||
applog(LOG_ERR, "%s%i: Comms error", icarus->drv->name, icarus->device_id);
|
||||
dev_error(icarus, REASON_DEV_COMMS_ERROR);
|
||||
return 0;
|
||||
}
|
||||
@ -900,10 +900,11 @@ static void icarus_shutdown(struct thr_info *thr)
|
||||
do_icarus_close(thr);
|
||||
}
|
||||
|
||||
struct device_api icarus_api = {
|
||||
.dname = "icarus",
|
||||
struct device_drv icarus_drv = {
|
||||
.drv_id = DRIVER_ICARUS,
|
||||
.dname = "Icarus",
|
||||
.name = "ICA",
|
||||
.api_detect = icarus_detect,
|
||||
.drv_detect = icarus_detect,
|
||||
.get_api_stats = icarus_api_stats,
|
||||
.thread_prepare = icarus_prepare,
|
||||
.scanhash = icarus_scanhash,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012 Andrew Smith
|
||||
* Copyright 2012-2013 Andrew Smith
|
||||
* Copyright 2012 Luke Dashjr
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@ -87,7 +87,7 @@
|
||||
// Limit when reducing shares_to_good
|
||||
#define MODMINER_MIN_BACK 12
|
||||
|
||||
struct device_api modminer_api;
|
||||
struct device_drv modminer_drv;
|
||||
|
||||
// 45 noops sent when detecting, in case the device was left in "start job" reading
|
||||
static const char NOOP[] = MODMINER_PING "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
|
||||
@ -100,15 +100,15 @@ static void do_ping(struct cgpu_info *modminer)
|
||||
// Don't care if it fails
|
||||
err = usb_write(modminer, (char *)NOOP, sizeof(NOOP)-1, &amount, C_PING);
|
||||
applog(LOG_DEBUG, "%s%u: flush noop got %d err %d",
|
||||
modminer->api->name, modminer->fpgaid, amount, err);
|
||||
modminer->drv->name, modminer->fpgaid, amount, err);
|
||||
|
||||
// Clear any outstanding data
|
||||
while ((err = usb_read(modminer, buf, sizeof(buf)-1, &amount, C_CLEAR)) == 0 && amount > 0)
|
||||
applog(LOG_DEBUG, "%s%u: clear got %d",
|
||||
modminer->api->name, modminer->fpgaid, amount);
|
||||
modminer->drv->name, modminer->fpgaid, amount);
|
||||
|
||||
applog(LOG_DEBUG, "%s%u: final clear got %d err %d",
|
||||
modminer->api->name, modminer->fpgaid, amount, err);
|
||||
modminer->drv->name, modminer->fpgaid, amount, err);
|
||||
}
|
||||
|
||||
static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devices *found)
|
||||
@ -121,42 +121,57 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic
|
||||
|
||||
struct cgpu_info *modminer = NULL;
|
||||
modminer = calloc(1, sizeof(*modminer));
|
||||
modminer->api = &modminer_api;
|
||||
modminer->drv = &modminer_drv;
|
||||
modminer->modminer_mutex = calloc(1, sizeof(*(modminer->modminer_mutex)));
|
||||
mutex_init(modminer->modminer_mutex);
|
||||
modminer->fpgaid = (char)0;
|
||||
|
||||
if (!usb_init(modminer, dev, found))
|
||||
if (!usb_init(modminer, dev, found)) {
|
||||
applog(LOG_ERR, "%s detect (%d:%d) failed to initialise (incorrect device?)",
|
||||
modminer->drv->dname,
|
||||
(int)(modminer->usbinfo.bus_number),
|
||||
(int)(modminer->usbinfo.device_address));
|
||||
goto shin;
|
||||
}
|
||||
|
||||
sprintf(devpath, "%d:%d",
|
||||
(int)(modminer->usbinfo.bus_number),
|
||||
(int)(modminer->usbinfo.device_address));
|
||||
|
||||
do_ping(modminer);
|
||||
|
||||
if ((err = usb_write(modminer, MODMINER_GET_VERSION, 1, &amount, C_REQUESTVERSION)) < 0 || amount != 1) {
|
||||
applog(LOG_ERR, "ModMiner detect: send version request failed (%d:%d)", amount, err);
|
||||
applog(LOG_ERR, "%s detect (%s) send version request failed (%d:%d)",
|
||||
modminer->drv->dname, devpath, amount, err);
|
||||
goto unshin;
|
||||
}
|
||||
|
||||
if ((err = usb_read(modminer, buf, sizeof(buf)-1, &amount, C_GETVERSION)) < 0 || amount < 1) {
|
||||
if (err < 0)
|
||||
applog(LOG_ERR, "ModMiner detect: no version reply (%d)", err);
|
||||
applog(LOG_ERR, "%s detect (%s) no version reply (%d)",
|
||||
modminer->drv->dname, devpath, err);
|
||||
else
|
||||
applog(LOG_ERR, "ModMiner detect: empty version reply (%d)", amount);
|
||||
applog(LOG_ERR, "%s detect (%s) empty version reply (%d)",
|
||||
modminer->drv->dname, devpath, amount);
|
||||
|
||||
applog(LOG_DEBUG, "ModMiner detect: check the firmware");
|
||||
applog(LOG_DEBUG, "%s detect (%s) check the firmware",
|
||||
modminer->drv->dname, devpath);
|
||||
|
||||
goto unshin;
|
||||
}
|
||||
buf[amount] = '\0';
|
||||
devname = strdup(buf);
|
||||
applog(LOG_DEBUG, "ModMiner identified as: %s", devname);
|
||||
applog(LOG_DEBUG, "%s (%s) identified as: %s", modminer->drv->dname, devpath, devname);
|
||||
|
||||
if ((err = usb_write(modminer, MODMINER_FPGA_COUNT, 1, &amount, C_REQUESTFPGACOUNT) < 0 || amount != 1)) {
|
||||
applog(LOG_ERR, "ModMiner detect: FPGA count request failed (%d:%d)", amount, err);
|
||||
applog(LOG_ERR, "%s detect (%s) FPGA count request failed (%d:%d)",
|
||||
modminer->drv->dname, devpath, amount, err);
|
||||
goto unshin;
|
||||
}
|
||||
|
||||
if ((err = usb_read(modminer, buf, 1, &amount, C_GETFPGACOUNT)) < 0 || amount != 1) {
|
||||
applog(LOG_ERR, "ModMiner detect: no FPGA count reply (%d:%d)", amount, err);
|
||||
applog(LOG_ERR, "%s detect (%s) no FPGA count reply (%d:%d)",
|
||||
modminer->drv->dname, devpath, amount, err);
|
||||
goto unshin;
|
||||
}
|
||||
|
||||
@ -164,16 +179,19 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic
|
||||
// can detect with modminer->cgusb->serial ?
|
||||
|
||||
if (buf[0] == 0) {
|
||||
applog(LOG_ERR, "ModMiner detect: zero FPGA count from %s", devname);
|
||||
applog(LOG_ERR, "%s detect (%s) zero FPGA count from %s",
|
||||
modminer->drv->dname, devpath, devname);
|
||||
goto unshin;
|
||||
}
|
||||
|
||||
if (buf[0] < 1 || buf[0] > 4) {
|
||||
applog(LOG_ERR, "ModMiner detect: invalid FPGA count (%u) from %s", buf[0], devname);
|
||||
applog(LOG_ERR, "%s detect (%s) invalid FPGA count (%u) from %s",
|
||||
modminer->drv->dname, devpath, buf[0], devname);
|
||||
goto unshin;
|
||||
}
|
||||
|
||||
applog(LOG_DEBUG, "ModMiner %s has %u FPGAs", devname, buf[0]);
|
||||
applog(LOG_DEBUG, "%s (%s) %s has %u FPGAs",
|
||||
modminer->drv->dname, devpath, devname, buf[0]);
|
||||
|
||||
modminer->name = devname;
|
||||
|
||||
@ -182,19 +200,21 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic
|
||||
for (i = 0; i < buf[0]; i++) {
|
||||
struct cgpu_info *tmp = calloc(1, sizeof(*tmp));
|
||||
|
||||
tmp->api = modminer->api;
|
||||
tmp->drv = copy_drv(modminer->drv);
|
||||
tmp->name = devname;
|
||||
|
||||
sprintf(devpath, "%d:%d:%d",
|
||||
(int)(modminer->usbdev->bus_number),
|
||||
(int)(modminer->usbdev->device_address),
|
||||
(int)(modminer->usbinfo.bus_number),
|
||||
(int)(modminer->usbinfo.device_address),
|
||||
i);
|
||||
|
||||
tmp->device_path = strdup(devpath);
|
||||
tmp->usbdev = modminer->usbdev;
|
||||
tmp->usbinfo.bus_number = modminer->usbinfo.bus_number;
|
||||
tmp->usbinfo.device_address = modminer->usbinfo.device_address;
|
||||
// Only the first copy gets the already used stats
|
||||
if (!added)
|
||||
tmp->usbstat = modminer->usbstat;
|
||||
tmp->usbinfo.usbstat = modminer->usbinfo.usbstat;
|
||||
tmp->fpgaid = (char)i;
|
||||
tmp->modminer_mutex = modminer->modminer_mutex;
|
||||
tmp->deven = DEV_ENABLED;
|
||||
@ -202,6 +222,8 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic
|
||||
|
||||
if (!add_cgpu(tmp)) {
|
||||
free(tmp->device_path);
|
||||
if (tmp->drv->copy)
|
||||
free(tmp->drv);
|
||||
free(tmp);
|
||||
goto unshin;
|
||||
}
|
||||
@ -211,6 +233,9 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic
|
||||
added = true;
|
||||
}
|
||||
|
||||
if (modminer->drv->copy)
|
||||
free(modminer->drv);
|
||||
|
||||
free(modminer);
|
||||
|
||||
return true;
|
||||
@ -223,6 +248,9 @@ shin:
|
||||
if (!added)
|
||||
free(modminer->modminer_mutex);
|
||||
|
||||
if (modminer->drv->copy)
|
||||
free(modminer->drv);
|
||||
|
||||
free(modminer);
|
||||
|
||||
if (added)
|
||||
@ -233,7 +261,7 @@ shin:
|
||||
|
||||
static void modminer_detect()
|
||||
{
|
||||
usb_detect(&modminer_api, modminer_detect_one);
|
||||
usb_detect(&modminer_drv, modminer_detect_one);
|
||||
}
|
||||
|
||||
static bool get_expect(struct cgpu_info *modminer, FILE *f, char c)
|
||||
@ -242,13 +270,13 @@ static bool get_expect(struct cgpu_info *modminer, FILE *f, char c)
|
||||
|
||||
if (fread(&buf, 1, 1, f) != 1) {
|
||||
applog(LOG_ERR, "%s%u: Error (%d) reading bitstream (%c)",
|
||||
modminer->api->name, modminer->device_id, errno, c);
|
||||
modminer->drv->name, modminer->device_id, errno, c);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buf != c) {
|
||||
applog(LOG_ERR, "%s%u: firmware code mismatch (%c)",
|
||||
modminer->api->name, modminer->device_id, c);
|
||||
applog(LOG_ERR, "%s%u: bitstream code mismatch (%c)",
|
||||
modminer->drv->name, modminer->device_id, c);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -262,7 +290,7 @@ static bool get_info(struct cgpu_info *modminer, FILE *f, char *buf, int bufsiz,
|
||||
|
||||
if (fread(siz, 2, 1, f) != 1) {
|
||||
applog(LOG_ERR, "%s%u: Error (%d) reading bitstream '%s' len",
|
||||
modminer->api->name, modminer->device_id, errno, name);
|
||||
modminer->drv->name, modminer->device_id, errno, name);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -270,13 +298,13 @@ static bool get_info(struct cgpu_info *modminer, FILE *f, char *buf, int bufsiz,
|
||||
|
||||
if (len >= bufsiz) {
|
||||
applog(LOG_ERR, "%s%u: Bitstream '%s' len too large (%d)",
|
||||
modminer->api->name, modminer->device_id, name, len);
|
||||
modminer->drv->name, modminer->device_id, name, len);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fread(buf, len, 1, f) != 1) {
|
||||
applog(LOG_ERR, "%s%u: Error (%d) reading bitstream '%s'", errno,
|
||||
modminer->api->name, modminer->device_id, errno, name);
|
||||
modminer->drv->name, modminer->device_id, errno, name);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -302,7 +330,7 @@ static bool get_status_timeout(struct cgpu_info *modminer, char *msg, unsigned i
|
||||
mutex_unlock(modminer->modminer_mutex);
|
||||
|
||||
applog(LOG_ERR, "%s%u: Error (%d:%d) getting %s reply",
|
||||
modminer->api->name, modminer->device_id, amount, err, msg);
|
||||
modminer->drv->name, modminer->device_id, amount, err, msg);
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -311,7 +339,7 @@ static bool get_status_timeout(struct cgpu_info *modminer, char *msg, unsigned i
|
||||
mutex_unlock(modminer->modminer_mutex);
|
||||
|
||||
applog(LOG_ERR, "%s%u: Error, invalid %s reply (was %d should be 1)",
|
||||
modminer->api->name, modminer->device_id, msg, buf[0]);
|
||||
modminer->drv->name, modminer->device_id, msg, buf[0]);
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -343,7 +371,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer)
|
||||
mutex_unlock(modminer->modminer_mutex);
|
||||
|
||||
applog(LOG_ERR, "%s%u: Error (%d) opening bitstream file %s",
|
||||
modminer->api->name, modminer->device_id, errno, bsfile);
|
||||
modminer->drv->name, modminer->device_id, errno, bsfile);
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -352,7 +380,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer)
|
||||
mutex_unlock(modminer->modminer_mutex);
|
||||
|
||||
applog(LOG_ERR, "%s%u: Error (%d) reading bitstream magic",
|
||||
modminer->api->name, modminer->device_id, errno);
|
||||
modminer->drv->name, modminer->device_id, errno);
|
||||
|
||||
goto dame;
|
||||
}
|
||||
@ -361,7 +389,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer)
|
||||
mutex_unlock(modminer->modminer_mutex);
|
||||
|
||||
applog(LOG_ERR, "%s%u: bitstream has incorrect magic (%u,%u) instead of (%u,%u)",
|
||||
modminer->api->name, modminer->device_id,
|
||||
modminer->drv->name, modminer->device_id,
|
||||
buf[0], buf[1],
|
||||
BITSTREAM_MAGIC_0, BITSTREAM_MAGIC_1);
|
||||
|
||||
@ -372,7 +400,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer)
|
||||
mutex_unlock(modminer->modminer_mutex);
|
||||
|
||||
applog(LOG_ERR, "%s%u: Error (%d) bitstream seek failed",
|
||||
modminer->api->name, modminer->device_id, errno);
|
||||
modminer->drv->name, modminer->device_id, errno);
|
||||
|
||||
goto dame;
|
||||
}
|
||||
@ -384,7 +412,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer)
|
||||
goto undame;
|
||||
|
||||
applog(LOG_DEBUG, "%s%u: bitstream file '%s' info:",
|
||||
modminer->api->name, modminer->device_id, bsfile);
|
||||
modminer->drv->name, modminer->device_id, bsfile);
|
||||
|
||||
applog(LOG_DEBUG, " Design name: '%s'", buf);
|
||||
|
||||
@ -399,7 +427,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer)
|
||||
mutex_unlock(modminer->modminer_mutex);
|
||||
|
||||
applog(LOG_ERR, "%s%u: Bad usercode in bitstream file",
|
||||
modminer->api->name, modminer->device_id);
|
||||
modminer->drv->name, modminer->device_id);
|
||||
|
||||
goto dame;
|
||||
}
|
||||
@ -408,7 +436,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer)
|
||||
mutex_unlock(modminer->modminer_mutex);
|
||||
|
||||
applog(LOG_ERR, "%s%u: bitstream doesn't support user code",
|
||||
modminer->api->name, modminer->device_id);
|
||||
modminer->drv->name, modminer->device_id);
|
||||
|
||||
goto dame;
|
||||
}
|
||||
@ -446,7 +474,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer)
|
||||
mutex_unlock(modminer->modminer_mutex);
|
||||
|
||||
applog(LOG_ERR, "%s%u: Error (%d) reading bitstream data len",
|
||||
modminer->api->name, modminer->device_id, errno);
|
||||
modminer->drv->name, modminer->device_id, errno);
|
||||
|
||||
goto dame;
|
||||
}
|
||||
@ -460,7 +488,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer)
|
||||
*ptr = '\0';
|
||||
|
||||
applog(LOG_WARNING, "%s%u: Programming all FPGA on %s ... Mining will not start until complete",
|
||||
modminer->api->name, modminer->device_id, devmsg);
|
||||
modminer->drv->name, modminer->device_id, devmsg);
|
||||
|
||||
buf[0] = MODMINER_PROGRAM;
|
||||
buf[1] = fpgaid;
|
||||
@ -473,7 +501,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer)
|
||||
mutex_unlock(modminer->modminer_mutex);
|
||||
|
||||
applog(LOG_ERR, "%s%u: Program init failed (%d:%d)",
|
||||
modminer->api->name, modminer->device_id, amount, err);
|
||||
modminer->drv->name, modminer->device_id, amount, err);
|
||||
|
||||
goto dame;
|
||||
}
|
||||
@ -492,7 +520,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer)
|
||||
mutex_unlock(modminer->modminer_mutex);
|
||||
|
||||
applog(LOG_ERR, "%s%u: bitstream file read error %d (%d bytes left)",
|
||||
modminer->api->name, modminer->device_id, errno, len);
|
||||
modminer->drv->name, modminer->device_id, errno, len);
|
||||
|
||||
goto dame;
|
||||
}
|
||||
@ -507,7 +535,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer)
|
||||
|
||||
if (opt_debug)
|
||||
applog(LOG_DEBUG, "%s%u: Program timeout (%d:%d) sent %d tries %d",
|
||||
modminer->api->name, modminer->device_id,
|
||||
modminer->drv->name, modminer->device_id,
|
||||
amount, err, remaining, tries);
|
||||
|
||||
if (!get_status(modminer, "write status", C_PROGRAMSTATUS2))
|
||||
@ -517,7 +545,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer)
|
||||
mutex_unlock(modminer->modminer_mutex);
|
||||
|
||||
applog(LOG_ERR, "%s%u: Program failed (%d:%d) sent %d",
|
||||
modminer->api->name, modminer->device_id, amount, err, remaining);
|
||||
modminer->drv->name, modminer->device_id, amount, err, remaining);
|
||||
|
||||
goto dame;
|
||||
}
|
||||
@ -532,7 +560,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer)
|
||||
if (upto >= nextmsg) {
|
||||
applog(LOG_WARNING,
|
||||
"%s%u: Programming %.1f%% (%d out of %d)",
|
||||
modminer->api->name, modminer->device_id, upto*100, (totlen - len), totlen);
|
||||
modminer->drv->name, modminer->device_id, upto*100, (totlen - len), totlen);
|
||||
|
||||
nextmsg += 0.1;
|
||||
}
|
||||
@ -542,7 +570,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer)
|
||||
goto undame;
|
||||
|
||||
applog(LOG_WARNING, "%s%u: Programming completed for all FPGA on %s",
|
||||
modminer->api->name, modminer->device_id, devmsg);
|
||||
modminer->drv->name, modminer->device_id, devmsg);
|
||||
|
||||
// Give it a 2/3s delay after programming
|
||||
nmsleep(666);
|
||||
@ -567,8 +595,6 @@ static bool modminer_fpga_prepare(struct thr_info *thr)
|
||||
|
||||
struct modminer_fpga_state *state;
|
||||
state = thr->cgpu_data = calloc(1, sizeof(struct modminer_fpga_state));
|
||||
state->next_work_cmd[0] = MODMINER_SEND_WORK;
|
||||
state->next_work_cmd[1] = modminer->fpgaid;
|
||||
state->shares_to_good = MODMINER_EARLY_UP;
|
||||
state->overheated = false;
|
||||
|
||||
@ -599,6 +625,7 @@ static bool modminer_fpga_prepare(struct thr_info *thr)
|
||||
*
|
||||
* N.B. clock must always be a multiple of 2
|
||||
*/
|
||||
static const char *clocknodev = "clock failed - no device";
|
||||
static const char *clockoldwork = "clock already changed for this work";
|
||||
static const char *clocktoolow = "clock too low";
|
||||
static const char *clocktoohi = "clock too high";
|
||||
@ -612,6 +639,10 @@ static const char *modminer_delta_clock(struct thr_info *thr, int delta, bool te
|
||||
unsigned char cmd[6], buf[1];
|
||||
int err, amount;
|
||||
|
||||
// Device is gone
|
||||
if (modminer->usbinfo.nodev)
|
||||
return clocknodev;
|
||||
|
||||
// Only do once if multiple shares per work or multiple reasons
|
||||
if (!state->new_work && !force)
|
||||
return clockoldwork;
|
||||
@ -653,7 +684,7 @@ static const char *modminer_delta_clock(struct thr_info *thr, int delta, bool te
|
||||
mutex_unlock(modminer->modminer_mutex);
|
||||
|
||||
applog(LOG_ERR, "%s%u: Error writing set clock speed (%d:%d)",
|
||||
modminer->api->name, modminer->device_id, amount, err);
|
||||
modminer->drv->name, modminer->device_id, amount, err);
|
||||
|
||||
return clocksetfail;
|
||||
}
|
||||
@ -662,7 +693,7 @@ static const char *modminer_delta_clock(struct thr_info *thr, int delta, bool te
|
||||
mutex_unlock(modminer->modminer_mutex);
|
||||
|
||||
applog(LOG_ERR, "%s%u: Error reading set clock speed (%d:%d)",
|
||||
modminer->api->name, modminer->device_id, amount, err);
|
||||
modminer->drv->name, modminer->device_id, amount, err);
|
||||
|
||||
return clockreplyfail;
|
||||
}
|
||||
@ -670,7 +701,7 @@ static const char *modminer_delta_clock(struct thr_info *thr, int delta, bool te
|
||||
mutex_unlock(modminer->modminer_mutex);
|
||||
|
||||
applog(LOG_WARNING, "%s%u: Set clock speed %sto %u",
|
||||
modminer->api->name, modminer->device_id,
|
||||
modminer->drv->name, modminer->device_id,
|
||||
(delta < 0) ? "down " : (delta > 0 ? "up " : ""),
|
||||
modminer->clock);
|
||||
|
||||
@ -691,7 +722,7 @@ static bool modminer_fpga_init(struct thr_info *thr)
|
||||
mutex_unlock(modminer->modminer_mutex);
|
||||
|
||||
applog(LOG_ERR, "%s%u: Error requesting USER code (%d:%d)",
|
||||
modminer->api->name, modminer->device_id, amount, err);
|
||||
modminer->drv->name, modminer->device_id, amount, err);
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -700,14 +731,14 @@ static bool modminer_fpga_init(struct thr_info *thr)
|
||||
mutex_unlock(modminer->modminer_mutex);
|
||||
|
||||
applog(LOG_ERR, "%s%u: Error reading USER code (%d:%d)",
|
||||
modminer->api->name, modminer->device_id, amount, err);
|
||||
modminer->drv->name, modminer->device_id, amount, err);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memcmp(buf, BISTREAM_USER_ID, 4)) {
|
||||
applog(LOG_ERR, "%s%u: FPGA not programmed",
|
||||
modminer->api->name, modminer->device_id);
|
||||
modminer->drv->name, modminer->device_id);
|
||||
|
||||
if (!modminer_fpga_upload_bitstream(modminer))
|
||||
return false;
|
||||
@ -717,7 +748,7 @@ static bool modminer_fpga_init(struct thr_info *thr)
|
||||
mutex_unlock(modminer->modminer_mutex);
|
||||
|
||||
applog(LOG_DEBUG, "%s%u: FPGA is already programmed :)",
|
||||
modminer->api->name, modminer->device_id);
|
||||
modminer->drv->name, modminer->device_id);
|
||||
}
|
||||
|
||||
modminer->clock = MODMINER_DEF_CLOCK;
|
||||
@ -740,24 +771,19 @@ static void get_modminer_statline_before(char *buf, struct cgpu_info *modminer)
|
||||
strcat(buf, info);
|
||||
}
|
||||
|
||||
static bool modminer_prepare_next_work(struct modminer_fpga_state *state, struct work *work)
|
||||
{
|
||||
char *midstate = state->next_work_cmd + 2;
|
||||
char *taildata = midstate + 32;
|
||||
if (!(memcmp(midstate, work->midstate, 32) || memcmp(taildata, work->data + 64, 12)))
|
||||
return false;
|
||||
memcpy(midstate, work->midstate, 32);
|
||||
memcpy(taildata, work->data + 64, 12);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool modminer_start_work(struct thr_info *thr)
|
||||
static bool modminer_start_work(struct thr_info *thr, struct work *work)
|
||||
{
|
||||
struct cgpu_info *modminer = thr->cgpu;
|
||||
struct modminer_fpga_state *state = thr->cgpu_data;
|
||||
int err, amount;
|
||||
char cmd[48];
|
||||
bool sta;
|
||||
|
||||
cmd[0] = MODMINER_SEND_WORK;
|
||||
cmd[1] = modminer->fpgaid;
|
||||
memcpy(&cmd[2], work->midstate, 32);
|
||||
memcpy(&cmd[34], work->data + 64, 12);
|
||||
|
||||
if (state->first_work.tv_sec == 0)
|
||||
gettimeofday(&state->first_work, NULL);
|
||||
|
||||
@ -766,20 +792,16 @@ static bool modminer_start_work(struct thr_info *thr)
|
||||
|
||||
mutex_lock(modminer->modminer_mutex);
|
||||
|
||||
if ((err = usb_write(modminer, (char *)(state->next_work_cmd), 46, &amount, C_SENDWORK)) < 0 || amount != 46) {
|
||||
// TODO: err = LIBUSB_ERROR_NO_DEVICE means the MMQ disappeared
|
||||
// - need to delete it and rescan for it? (after a delay?)
|
||||
// but check all (4) disappeared
|
||||
if ((err = usb_write(modminer, cmd, 46, &amount, C_SENDWORK)) < 0 || amount != 46) {
|
||||
mutex_unlock(modminer->modminer_mutex);
|
||||
|
||||
applog(LOG_ERR, "%s%u: Start work failed (%d:%d)",
|
||||
modminer->api->name, modminer->device_id, amount, err);
|
||||
modminer->drv->name, modminer->device_id, amount, err);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
gettimeofday(&state->tv_workstart, NULL);
|
||||
state->hashes = 0;
|
||||
|
||||
sta = get_status(modminer, "start work", C_SENDWORKSTATUS);
|
||||
|
||||
@ -799,6 +821,10 @@ static void check_temperature(struct thr_info *thr)
|
||||
int tbytes, tamount;
|
||||
int amount;
|
||||
|
||||
// Device is gone
|
||||
if (modminer->usbinfo.nodev)
|
||||
return;
|
||||
|
||||
if (state->one_byte_temp) {
|
||||
cmd[0] = MODMINER_TEMP1;
|
||||
tbytes = 1;
|
||||
@ -827,14 +853,14 @@ static void check_temperature(struct thr_info *thr)
|
||||
if (modminer->temp < MODMINER_RECOVER_TEMP) {
|
||||
state->overheated = false;
|
||||
applog(LOG_WARNING, "%s%u: Recovered, temp less than (%.1f) now %.3f",
|
||||
modminer->api->name, modminer->device_id,
|
||||
modminer->drv->name, modminer->device_id,
|
||||
MODMINER_RECOVER_TEMP, modminer->temp);
|
||||
}
|
||||
}
|
||||
else if (modminer->temp >= MODMINER_OVERHEAT_TEMP) {
|
||||
if (modminer->temp >= MODMINER_CUTOFF_TEMP) {
|
||||
applog(LOG_WARNING, "%s%u: Hit thermal cutoff limit! (%.1f) at %.3f",
|
||||
modminer->api->name, modminer->device_id,
|
||||
modminer->drv->name, modminer->device_id,
|
||||
MODMINER_CUTOFF_TEMP, modminer->temp);
|
||||
|
||||
modminer_delta_clock(thr, MODMINER_CLOCK_CUTOFF, true, false);
|
||||
@ -842,7 +868,7 @@ static void check_temperature(struct thr_info *thr)
|
||||
dev_error(modminer, REASON_DEV_THERMAL_CUTOFF);
|
||||
} else {
|
||||
applog(LOG_WARNING, "%s%u: Overheat limit (%.1f) reached %.3f",
|
||||
modminer->api->name, modminer->device_id,
|
||||
modminer->drv->name, modminer->device_id,
|
||||
MODMINER_OVERHEAT_TEMP, modminer->temp);
|
||||
|
||||
// If it's defined to be 0 then don't call modminer_delta_clock()
|
||||
@ -869,11 +895,10 @@ static const double processtime = 17.0;
|
||||
// 160Mhz is 26.84 - when overheated ensure we don't throw away shares
|
||||
static const double overheattime = 26.9;
|
||||
|
||||
static uint64_t modminer_process_results(struct thr_info *thr)
|
||||
static uint64_t modminer_process_results(struct thr_info *thr, struct work *work)
|
||||
{
|
||||
struct cgpu_info *modminer = thr->cgpu;
|
||||
struct modminer_fpga_state *state = thr->cgpu_data;
|
||||
struct work *work = &state->running_work;
|
||||
struct timeval now;
|
||||
char cmd[2];
|
||||
uint32_t nonce;
|
||||
@ -883,6 +908,10 @@ static uint64_t modminer_process_results(struct thr_info *thr)
|
||||
double timeout;
|
||||
int temploop;
|
||||
|
||||
// Device is gone
|
||||
if (modminer->usbinfo.nodev)
|
||||
return -1;
|
||||
|
||||
// If we are overheated it will just keep checking for results
|
||||
// since we can't stop the work
|
||||
// The next work will not start until the temp drops
|
||||
@ -893,23 +922,20 @@ static uint64_t modminer_process_results(struct thr_info *thr)
|
||||
|
||||
timeoutloop = 0;
|
||||
temploop = 0;
|
||||
while (1) {
|
||||
while (0x80085) {
|
||||
mutex_lock(modminer->modminer_mutex);
|
||||
if ((err = usb_write(modminer, cmd, 2, &amount, C_REQUESTWORKSTATUS)) < 0 || amount != 2) {
|
||||
// TODO: err = LIBUSB_ERROR_NO_DEVICE means the MMQ disappeared
|
||||
// - need to delete it and rescan for it? (after a delay?)
|
||||
// but check all (4) disappeared
|
||||
mutex_unlock(modminer->modminer_mutex);
|
||||
|
||||
// timeoutloop never resets so the timeouts can't
|
||||
// accumulate much during a single item of work
|
||||
if (err == LIBUSB_ERROR_TIMEOUT && ++timeoutloop < 10) {
|
||||
if (err == LIBUSB_ERROR_TIMEOUT && ++timeoutloop < 5) {
|
||||
state->timeout_fail++;
|
||||
goto tryagain;
|
||||
}
|
||||
|
||||
applog(LOG_ERR, "%s%u: Error sending (get nonce) (%d:%d)",
|
||||
modminer->api->name, modminer->device_id, amount, err);
|
||||
modminer->drv->name, modminer->device_id, amount, err);
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -936,7 +962,7 @@ static uint64_t modminer_process_results(struct thr_info *thr)
|
||||
}
|
||||
|
||||
applog(LOG_ERR, "%s%u: Error reading (get nonce) (%d:%d)",
|
||||
modminer->api->name, modminer->device_id, amount+amount2, err);
|
||||
modminer->drv->name, modminer->device_id, amount+amount2, err);
|
||||
}
|
||||
|
||||
if (memcmp(&nonce, "\xff\xff\xff\xff", 4)) {
|
||||
@ -975,7 +1001,7 @@ static uint64_t modminer_process_results(struct thr_info *thr)
|
||||
if (state->death_stage_one) {
|
||||
modminer_delta_clock(thr, MODMINER_CLOCK_DEAD, false, true);
|
||||
applog(LOG_ERR, "%s%u: DEATH clock down",
|
||||
modminer->api->name, modminer->device_id);
|
||||
modminer->drv->name, modminer->device_id);
|
||||
|
||||
// reset the death info and DISABLE it
|
||||
state->last_nonce.tv_sec = 0;
|
||||
@ -985,7 +1011,7 @@ static uint64_t modminer_process_results(struct thr_info *thr)
|
||||
} else {
|
||||
modminer_delta_clock(thr, MODMINER_CLOCK_DEAD, false, true);
|
||||
applog(LOG_ERR, "%s%u: death clock down",
|
||||
modminer->api->name, modminer->device_id);
|
||||
modminer->drv->name, modminer->device_id);
|
||||
|
||||
state->death_stage_one = true;
|
||||
}
|
||||
@ -998,8 +1024,8 @@ tryagain:
|
||||
break;
|
||||
|
||||
if (state->overheated == true) {
|
||||
// don't check every time
|
||||
if (++temploop > 30) {
|
||||
// don't check every time (every ~1/2 sec)
|
||||
if (++temploop > 4) {
|
||||
check_temperature(thr);
|
||||
temploop = 0;
|
||||
}
|
||||
@ -1015,7 +1041,8 @@ tryagain:
|
||||
if (tdiff(&now, &state->tv_workstart) > timeout)
|
||||
break;
|
||||
|
||||
nmsleep(10);
|
||||
// 1/10th sec to lower CPU usage
|
||||
nmsleep(100);
|
||||
if (work_restart(thr))
|
||||
break;
|
||||
}
|
||||
@ -1029,35 +1056,37 @@ tryagain:
|
||||
// Overheat will complete the nonce range
|
||||
if (hashes > 0xffffffff)
|
||||
hashes = 0xffffffff;
|
||||
else
|
||||
if (hashes <= state->hashes)
|
||||
hashes = 1;
|
||||
else
|
||||
hashes -= state->hashes;
|
||||
state->hashes += hashes;
|
||||
|
||||
work->blk.nonce = 0xffffffff;
|
||||
|
||||
return hashes;
|
||||
}
|
||||
|
||||
static int64_t modminer_scanhash(struct thr_info *thr, struct work *work, int64_t __maybe_unused max_nonce)
|
||||
{
|
||||
struct modminer_fpga_state *state = thr->cgpu_data;
|
||||
int64_t hashes = 0;
|
||||
bool startwork;
|
||||
struct timeval tv1, tv2;
|
||||
int64_t hashes;
|
||||
|
||||
// Device is gone
|
||||
if (thr->cgpu->usbinfo.nodev)
|
||||
return -1;
|
||||
|
||||
// Don't start new work if overheated
|
||||
if (state->overheated == true) {
|
||||
gettimeofday(&tv1, NULL);
|
||||
if (state->work_running)
|
||||
state->work_running = false;
|
||||
|
||||
while (state->overheated == true) {
|
||||
check_temperature(thr);
|
||||
|
||||
// Device is gone
|
||||
if (thr->cgpu->usbinfo.nodev)
|
||||
return -1;
|
||||
|
||||
if (state->overheated == true) {
|
||||
gettimeofday(&tv2, NULL);
|
||||
|
||||
// give up on this work item
|
||||
// give up on this work item after 30s
|
||||
if (work_restart(thr) || tdiff(&tv2, &tv1) > 30)
|
||||
return 0;
|
||||
|
||||
@ -1067,27 +1096,13 @@ static int64_t modminer_scanhash(struct thr_info *thr, struct work *work, int64_
|
||||
}
|
||||
}
|
||||
|
||||
startwork = modminer_prepare_next_work(state, work);
|
||||
if (state->work_running) {
|
||||
hashes = modminer_process_results(thr);
|
||||
if (hashes == -1)
|
||||
return hashes;
|
||||
if (!modminer_start_work(thr, work))
|
||||
return -1;
|
||||
|
||||
if (work_restart(thr)) {
|
||||
state->work_running = false;
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
state->work_running = true;
|
||||
hashes = modminer_process_results(thr, work);
|
||||
if (hashes == -1)
|
||||
return hashes;
|
||||
|
||||
if (startwork) {
|
||||
if (!modminer_start_work(thr))
|
||||
return -1;
|
||||
__copy_work(&state->running_work, work);
|
||||
}
|
||||
|
||||
// This is intentionally early
|
||||
work->blk.nonce += hashes;
|
||||
return hashes;
|
||||
}
|
||||
|
||||
@ -1141,10 +1156,11 @@ static char *modminer_set_device(struct cgpu_info *modminer, char *option, char
|
||||
return replybuf;
|
||||
}
|
||||
|
||||
struct device_api modminer_api = {
|
||||
.dname = "modminer",
|
||||
struct device_drv modminer_drv = {
|
||||
.drv_id = DRIVER_MODMINER,
|
||||
.dname = "ModMiner",
|
||||
.name = "MMQ",
|
||||
.api_detect = modminer_detect,
|
||||
.drv_detect = modminer_detect,
|
||||
.get_statline_before = get_modminer_statline_before,
|
||||
.set_device = modminer_set_device,
|
||||
.thread_prepare = modminer_fpga_prepare,
|
||||
|
@ -50,24 +50,24 @@ extern int gpur_thr_id;
|
||||
extern bool opt_noadl;
|
||||
extern bool have_opencl;
|
||||
|
||||
|
||||
|
||||
extern void *miner_thread(void *userdata);
|
||||
extern int dev_from_id(int thr_id);
|
||||
extern void tailsprintf(char *f, const char *fmt, ...);
|
||||
extern void wlog(const char *f, ...);
|
||||
extern void decay_time(double *f, double fadd);
|
||||
|
||||
|
||||
/**********************************************/
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
struct device_drv opencl_drv;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ADL
|
||||
extern float gpu_temp(int gpu);
|
||||
extern int gpu_fanspeed(int gpu);
|
||||
extern int gpu_fanpercent(int gpu);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
char *set_vector(char *arg)
|
||||
{
|
||||
@ -591,28 +591,20 @@ char *set_intensity(char *arg)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
struct device_api opencl_api;
|
||||
|
||||
char *print_ndevs_and_exit(int *ndevs)
|
||||
{
|
||||
opt_log_output = true;
|
||||
opencl_api.api_detect();
|
||||
opencl_drv.drv_detect();
|
||||
clear_adl(*ndevs);
|
||||
applog(LOG_INFO, "%i GPU devices max detected", *ndevs);
|
||||
exit(*ndevs);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
struct cgpu_info gpus[MAX_GPUDEVICES]; /* Maximum number apparently possible */
|
||||
struct cgpu_info *cpus;
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
/* In dynamic mode, only the first thread of each device will be in use.
|
||||
@ -624,8 +616,9 @@ void pause_dynamic_threads(int gpu)
|
||||
int i;
|
||||
|
||||
for (i = 1; i < cgpu->threads; i++) {
|
||||
struct thr_info *thr = &thr_info[i];
|
||||
struct thr_info *thr;
|
||||
|
||||
thr = get_thread(i);
|
||||
if (!thr->pause && cgpu->dynamic) {
|
||||
applog(LOG_WARNING, "Disabling extra threads due to dynamic mode.");
|
||||
applog(LOG_WARNING, "Tune dynamic intensity with --gpu-dyninterval");
|
||||
@ -637,9 +630,6 @@ void pause_dynamic_threads(int gpu)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct device_api opencl_api;
|
||||
|
||||
#endif /* HAVE_OPENCL */
|
||||
|
||||
#if defined(HAVE_OPENCL) && defined(HAVE_CURSES)
|
||||
@ -716,7 +706,7 @@ retry:
|
||||
else
|
||||
wlog("%d\n", gpus[gpu].intensity);
|
||||
for (i = 0; i < mining_threads; i++) {
|
||||
thr = &thr_info[i];
|
||||
thr = get_thread(i);
|
||||
if (thr->cgpu != cgpu)
|
||||
continue;
|
||||
get_datestamp(checkin, &thr->last);
|
||||
@ -771,9 +761,9 @@ retry:
|
||||
}
|
||||
gpus[selected].deven = DEV_ENABLED;
|
||||
for (i = 0; i < mining_threads; ++i) {
|
||||
thr = &thr_info[i];
|
||||
thr = get_thread(i);
|
||||
cgpu = thr->cgpu;
|
||||
if (cgpu->api != &opencl_api)
|
||||
if (cgpu->drv->drv_id != DRIVER_OPENCL)
|
||||
continue;
|
||||
if (dev_from_id(i) != selected)
|
||||
continue;
|
||||
@ -1158,14 +1148,14 @@ select_cgpu:
|
||||
gpu = cgpu->device_id;
|
||||
|
||||
for (thr_id = 0; thr_id < mining_threads; ++thr_id) {
|
||||
thr = &thr_info[thr_id];
|
||||
thr = get_thread(thr_id);
|
||||
cgpu = thr->cgpu;
|
||||
if (cgpu->api != &opencl_api)
|
||||
if (cgpu->drv->drv_id != DRIVER_OPENCL)
|
||||
continue;
|
||||
if (dev_from_id(thr_id) != gpu)
|
||||
continue;
|
||||
|
||||
thr = &thr_info[thr_id];
|
||||
thr = get_thread(thr_id);
|
||||
if (!thr) {
|
||||
applog(LOG_WARNING, "No reference to thread %d exists", thr_id);
|
||||
continue;
|
||||
@ -1183,9 +1173,9 @@ select_cgpu:
|
||||
for (thr_id = 0; thr_id < mining_threads; ++thr_id) {
|
||||
int virtual_gpu;
|
||||
|
||||
thr = &thr_info[thr_id];
|
||||
thr = get_thread(thr_id);
|
||||
cgpu = thr->cgpu;
|
||||
if (cgpu->api != &opencl_api)
|
||||
if (cgpu->drv->drv_id != DRIVER_OPENCL)
|
||||
continue;
|
||||
if (dev_from_id(thr_id) != gpu)
|
||||
continue;
|
||||
@ -1220,9 +1210,9 @@ select_cgpu:
|
||||
get_datestamp(cgpu->init, &now);
|
||||
|
||||
for (thr_id = 0; thr_id < mining_threads; ++thr_id) {
|
||||
thr = &thr_info[thr_id];
|
||||
thr = get_thread(thr_id);
|
||||
cgpu = thr->cgpu;
|
||||
if (cgpu->api != &opencl_api)
|
||||
if (cgpu->drv->drv_id != DRIVER_OPENCL)
|
||||
continue;
|
||||
if (dev_from_id(thr_id) != gpu)
|
||||
continue;
|
||||
@ -1243,8 +1233,6 @@ void *reinit_gpu(__maybe_unused void *userdata)
|
||||
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
struct device_api opencl_api;
|
||||
|
||||
static void opencl_detect()
|
||||
{
|
||||
int i;
|
||||
@ -1263,7 +1251,7 @@ static void opencl_detect()
|
||||
|
||||
cgpu = &gpus[i];
|
||||
cgpu->deven = DEV_ENABLED;
|
||||
cgpu->api = &opencl_api;
|
||||
cgpu->drv = &opencl_drv;
|
||||
cgpu->device_id = i;
|
||||
cgpu->threads = opt_g_threads;
|
||||
cgpu->virtual_gpu = i;
|
||||
@ -1276,7 +1264,7 @@ static void opencl_detect()
|
||||
|
||||
static void reinit_opencl_device(struct cgpu_info *gpu)
|
||||
{
|
||||
tq_push(thr_info[gpur_thr_id].q, gpu);
|
||||
tq_push(control_thr[gpur_thr_id].q, gpu);
|
||||
}
|
||||
|
||||
#ifdef HAVE_ADL
|
||||
@ -1299,7 +1287,8 @@ static void get_opencl_statline_before(char *buf, struct cgpu_info *gpu)
|
||||
else
|
||||
tailsprintf(buf, " ");
|
||||
tailsprintf(buf, "| ");
|
||||
}
|
||||
} else
|
||||
gpu->drv->get_statline_before = &blank_get_statline_before;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1570,10 +1559,11 @@ static void opencl_thread_shutdown(struct thr_info *thr)
|
||||
clReleaseContext(clState->context);
|
||||
}
|
||||
|
||||
struct device_api opencl_api = {
|
||||
struct device_drv opencl_drv = {
|
||||
.drv_id = DRIVER_OPENCL,
|
||||
.dname = "opencl",
|
||||
.name = "GPU",
|
||||
.api_detect = opencl_detect,
|
||||
.drv_detect = opencl_detect,
|
||||
.reinit_device = reinit_opencl_device,
|
||||
#ifdef HAVE_ADL
|
||||
.get_statline_before = get_opencl_statline_before,
|
||||
|
@ -30,6 +30,6 @@ extern void pause_dynamic_threads(int gpu);
|
||||
extern bool have_opencl;
|
||||
extern int opt_platform_id;
|
||||
|
||||
extern struct device_api opencl_api;
|
||||
extern struct device_drv opencl_drv;
|
||||
|
||||
#endif /* __DEVICE_GPU_H__ */
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
#define GOLDEN_BACKLOG 5
|
||||
|
||||
struct device_api ztex_api;
|
||||
struct device_drv ztex_drv;
|
||||
|
||||
// Forward declarations
|
||||
static void ztex_disable(struct thr_info* thr);
|
||||
@ -68,7 +68,7 @@ static void ztex_detect(void)
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
ztex = calloc(1, sizeof(struct cgpu_info));
|
||||
ztex->api = &ztex_api;
|
||||
ztex->drv = &ztex_drv;
|
||||
ztex->device_ztex = ztex_devices[i]->dev;
|
||||
ztex->threads = 1;
|
||||
ztex->device_ztex->fpgaNum = 0;
|
||||
@ -82,7 +82,7 @@ static void ztex_detect(void)
|
||||
|
||||
for (j = 1; j < fpgacount; j++) {
|
||||
ztex = calloc(1, sizeof(struct cgpu_info));
|
||||
ztex->api = &ztex_api;
|
||||
ztex->drv = &ztex_drv;
|
||||
ztex_slave = calloc(1, sizeof(struct libztex_device));
|
||||
memcpy(ztex_slave, ztex_devices[i]->dev, sizeof(struct libztex_device));
|
||||
ztex->device_ztex = ztex_slave;
|
||||
@ -389,15 +389,18 @@ static void ztex_shutdown(struct thr_info *thr)
|
||||
|
||||
static void ztex_disable(struct thr_info *thr)
|
||||
{
|
||||
struct cgpu_info *cgpu;
|
||||
|
||||
applog(LOG_ERR, "%s: Disabling!", thr->cgpu->device_ztex->repr);
|
||||
devices[thr->cgpu->device_id]->deven = DEV_DISABLED;
|
||||
cgpu = get_devices(thr->cgpu->device_id);
|
||||
cgpu->deven = DEV_DISABLED;
|
||||
ztex_shutdown(thr);
|
||||
}
|
||||
|
||||
struct device_api ztex_api = {
|
||||
struct device_drv ztex_drv = {
|
||||
.dname = "ztex",
|
||||
.name = "ZTX",
|
||||
.api_detect = ztex_detect,
|
||||
.drv_detect = ztex_detect,
|
||||
.get_statline_before = ztex_statline_before,
|
||||
.thread_prepare = ztex_prepare,
|
||||
.scanhash = ztex_scanhash,
|
||||
|
@ -204,7 +204,7 @@ static void *postcalc_hash(void *userdata)
|
||||
* end of the res[] array */
|
||||
if (unlikely(pcd->res[FOUND] & ~FOUND)) {
|
||||
applog(LOG_WARNING, "%s%d: invalid nonce count - HW error",
|
||||
thr->cgpu->api->name, thr->cgpu->device_id);
|
||||
thr->cgpu->drv->name, thr->cgpu->device_id);
|
||||
hw_errors++;
|
||||
thr->cgpu->hw_errors++;
|
||||
pcd->res[FOUND] &= FOUND;
|
||||
|
10
fpgautils.c
10
fpgautils.c
@ -104,14 +104,14 @@ int serial_autodetect_devserial(__maybe_unused detectone_func_t detectone, __may
|
||||
#endif
|
||||
}
|
||||
|
||||
int _serial_detect(struct device_api *api, detectone_func_t detectone, autoscan_func_t autoscan, bool forceauto)
|
||||
int _serial_detect(struct device_drv *drv, detectone_func_t detectone, autoscan_func_t autoscan, bool forceauto)
|
||||
{
|
||||
struct string_elist *iter, *tmp;
|
||||
const char *dev, *colon;
|
||||
bool inhibitauto = false;
|
||||
char found = 0;
|
||||
size_t namel = strlen(api->name);
|
||||
size_t dnamel = strlen(api->dname);
|
||||
size_t namel = strlen(drv->name);
|
||||
size_t dnamel = strlen(drv->dname);
|
||||
|
||||
list_for_each_entry_safe(iter, tmp, &scan_devices, list) {
|
||||
dev = iter->string;
|
||||
@ -119,8 +119,8 @@ int _serial_detect(struct device_api *api, detectone_func_t detectone, autoscan_
|
||||
size_t idlen = colon - dev;
|
||||
|
||||
// allow either name:device or dname:device
|
||||
if ((idlen != namel || strncasecmp(dev, api->name, idlen))
|
||||
&& (idlen != dnamel || strncasecmp(dev, api->dname, idlen)))
|
||||
if ((idlen != namel || strncasecmp(dev, drv->name, idlen))
|
||||
&& (idlen != dnamel || strncasecmp(dev, drv->dname, idlen)))
|
||||
continue;
|
||||
|
||||
dev = colon + 1;
|
||||
|
14
fpgautils.h
14
fpgautils.h
@ -16,13 +16,13 @@
|
||||
typedef bool(*detectone_func_t)(const char*);
|
||||
typedef int(*autoscan_func_t)();
|
||||
|
||||
extern int _serial_detect(struct device_api *api, detectone_func_t, autoscan_func_t, bool force_autoscan);
|
||||
#define serial_detect_fauto(api, detectone, autoscan) \
|
||||
_serial_detect(api, detectone, autoscan, true)
|
||||
#define serial_detect_auto(api, detectone, autoscan) \
|
||||
_serial_detect(api, detectone, autoscan, false)
|
||||
#define serial_detect(api, detectone) \
|
||||
_serial_detect(api, detectone, NULL, false)
|
||||
extern int _serial_detect(struct device_drv *drv, detectone_func_t, autoscan_func_t, bool force_autoscan);
|
||||
#define serial_detect_fauto(drv, detectone, autoscan) \
|
||||
_serial_detect(drv, detectone, autoscan, true)
|
||||
#define serial_detect_auto(drv, detectone, autoscan) \
|
||||
_serial_detect(drv, detectone, autoscan, false)
|
||||
#define serial_detect(drv, detectone) \
|
||||
_serial_detect(drv, detectone, NULL, false)
|
||||
extern int serial_autodetect_devserial(detectone_func_t, const char *prodname);
|
||||
extern int serial_autodetect_udev(detectone_func_t, const char *prodname);
|
||||
|
||||
|
50
miner.h
50
miner.h
@ -114,7 +114,7 @@ static inline int fsync (int fd)
|
||||
#include "libztex.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_MODMINER
|
||||
#if defined(USE_MODMINER) || defined(USE_BITFORCE)
|
||||
#include "usbutils.h"
|
||||
#endif
|
||||
|
||||
@ -196,6 +196,15 @@ static inline int fsync (int fd)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
enum drv_driver {
|
||||
DRIVER_OPENCL,
|
||||
DRIVER_ICARUS,
|
||||
DRIVER_BITFORCE,
|
||||
DRIVER_MODMINER,
|
||||
DRIVER_ZTEX,
|
||||
DRIVER_CPU,
|
||||
};
|
||||
|
||||
enum alive {
|
||||
LIFE_WELL,
|
||||
LIFE_SICK,
|
||||
@ -259,16 +268,20 @@ struct gpu_adl {
|
||||
};
|
||||
#endif
|
||||
|
||||
extern void blank_get_statline_before(char *buf, struct cgpu_info __maybe_unused *cgpu);
|
||||
|
||||
struct api_data;
|
||||
struct thr_info;
|
||||
struct work;
|
||||
|
||||
struct device_api {
|
||||
struct device_drv {
|
||||
enum drv_driver drv_id;
|
||||
|
||||
char *dname;
|
||||
char *name;
|
||||
|
||||
// API-global functions
|
||||
void (*api_detect)();
|
||||
// DRV-global functions
|
||||
void (*drv_detect)();
|
||||
|
||||
// Device-specific functions
|
||||
void (*reinit_device)(struct cgpu_info *);
|
||||
@ -288,8 +301,13 @@ struct device_api {
|
||||
void (*hw_error)(struct thr_info *);
|
||||
void (*thread_shutdown)(struct thr_info *);
|
||||
void (*thread_enable)(struct thr_info *);
|
||||
|
||||
// Does it need to be free()d?
|
||||
bool copy;
|
||||
};
|
||||
|
||||
extern struct device_drv *copy_drv(struct device_drv*);
|
||||
|
||||
enum dev_enable {
|
||||
DEV_ENABLED,
|
||||
DEV_DISABLED,
|
||||
@ -359,13 +377,15 @@ struct cgminer_pool_stats {
|
||||
uint32_t max_diff_count;
|
||||
uint64_t times_sent;
|
||||
uint64_t bytes_sent;
|
||||
uint64_t net_bytes_sent;
|
||||
uint64_t times_received;
|
||||
uint64_t bytes_received;
|
||||
uint64_t net_bytes_received;
|
||||
};
|
||||
|
||||
struct cgpu_info {
|
||||
int cgminer_id;
|
||||
struct device_api *api;
|
||||
struct device_drv *drv;
|
||||
int device_id;
|
||||
char *name;
|
||||
char *device_path;
|
||||
@ -374,13 +394,17 @@ struct cgpu_info {
|
||||
#ifdef USE_ZTEX
|
||||
struct libztex_device *device_ztex;
|
||||
#endif
|
||||
#ifdef USE_MODMINER
|
||||
#if defined(USE_MODMINER) || defined(USE_BITFORCE)
|
||||
struct cg_usb_device *usbdev;
|
||||
#endif
|
||||
#ifdef USE_ICARUS
|
||||
int device_fd;
|
||||
#endif
|
||||
};
|
||||
#if defined(USE_MODMINER) || defined(USE_BITFORCE)
|
||||
struct cg_usb_info usbinfo;
|
||||
#endif
|
||||
#ifdef USE_MODMINER
|
||||
int usbstat;
|
||||
char fpgaid;
|
||||
unsigned char clock;
|
||||
pthread_mutex_t *modminer_mutex;
|
||||
@ -715,6 +739,8 @@ extern pthread_mutex_t cgusb_lock;
|
||||
extern pthread_mutex_t hash_lock;
|
||||
extern pthread_mutex_t console_lock;
|
||||
extern pthread_mutex_t ch_lock;
|
||||
extern pthread_mutex_t mining_thr_lock;
|
||||
extern pthread_mutex_t devices_lock;
|
||||
|
||||
extern pthread_mutex_t restart_lock;
|
||||
extern pthread_cond_t restart_cond;
|
||||
@ -740,6 +766,7 @@ extern void api(int thr_id);
|
||||
extern struct pool *current_pool(void);
|
||||
extern int enabled_pools;
|
||||
extern bool detect_stratum(struct pool *pool, char *url);
|
||||
extern void print_summary(void);
|
||||
extern struct pool *add_pool(void);
|
||||
extern void add_pool_details(struct pool *pool, bool live, char *url, char *user, char *pass);
|
||||
|
||||
@ -755,6 +782,7 @@ extern void add_pool_details(struct pool *pool, bool live, char *url, char *user
|
||||
#define _MAX_INTENSITY_STR "14"
|
||||
#endif
|
||||
|
||||
extern bool hotplug_mode;
|
||||
extern struct list_head scan_devices;
|
||||
extern int nDevs;
|
||||
extern int opt_n_threads;
|
||||
@ -762,7 +790,8 @@ extern int num_processors;
|
||||
extern int hw_errors;
|
||||
extern bool use_syslog;
|
||||
extern bool opt_quiet;
|
||||
extern struct thr_info *thr_info;
|
||||
extern struct thr_info *control_thr;
|
||||
extern struct thr_info **mining_thr;
|
||||
extern struct cgpu_info gpus[MAX_GPUDEVICES];
|
||||
extern int gpu_threads;
|
||||
#ifdef USE_SCRYPT
|
||||
@ -926,6 +955,7 @@ struct pool {
|
||||
|
||||
time_t last_share_time;
|
||||
double last_share_diff;
|
||||
uint64_t best_diff;
|
||||
|
||||
struct cgminer_stats cgminer_stats;
|
||||
struct cgminer_pool_stats cgminer_pool_stats;
|
||||
@ -1065,6 +1095,8 @@ extern void kill_work(void);
|
||||
extern void switch_pools(struct pool *selected);
|
||||
extern void remove_pool(struct pool *pool);
|
||||
extern void write_config(FILE *fcfg);
|
||||
extern void zero_bestshare(void);
|
||||
extern void zero_stats(void);
|
||||
extern void default_save_file(char *filename);
|
||||
extern bool log_curses_only(int prio, const char *f, va_list ap);
|
||||
extern void clear_logwin(void);
|
||||
@ -1082,6 +1114,8 @@ extern void clean_work(struct work *work);
|
||||
extern void free_work(struct work *work);
|
||||
extern void __copy_work(struct work *work, struct work *base_work);
|
||||
extern struct work *copy_work(struct work *base_work);
|
||||
extern struct thr_info *get_thread(int thr_id);
|
||||
extern struct cgpu_info *get_devices(int id);
|
||||
|
||||
enum api_data_type {
|
||||
API_ESCAPE,
|
||||
|
289
miner.php
289
miner.php
@ -8,7 +8,7 @@ global $checklastshare, $poolinputs, $hidefields;
|
||||
global $ignorerefresh, $changerefresh, $autorefresh;
|
||||
global $allowcustompages, $customsummarypages;
|
||||
global $miner_font_family, $miner_font_size;
|
||||
global $colouroverride, $placebuttons;
|
||||
global $colouroverride, $placebuttons, $userlist;
|
||||
#
|
||||
# See API-README for more details of these variables and how
|
||||
# to configure miner.php
|
||||
@ -20,6 +20,9 @@ $title = 'Mine';
|
||||
# Set $readonly to false then it will check cgminer 'privileged'
|
||||
$readonly = false;
|
||||
#
|
||||
# Set $userlist to null to allow anyone access or read API-README
|
||||
$userlist = null;
|
||||
#
|
||||
# Set $notify to false to NOT attempt to display the notify command
|
||||
# Set $notify to true to attempt to display the notify command
|
||||
$notify = true;
|
||||
@ -113,16 +116,17 @@ $poolspage = array(
|
||||
'POOL.Difficulty Rejected=Diff Rej',
|
||||
'POOL.Has Stratum=Stratum', 'POOL.Stratum Active=StrAct',
|
||||
'POOL.Has GBT=GBT', 'STATS.Times Sent=TSent',
|
||||
'STATS.Bytes Sent=BSent', 'STATS.Times Recv=TRecv',
|
||||
'STATS.Bytes Recv=BRecv'));
|
||||
'STATS.Bytes Sent=BSent', 'STATS.Net Bytes Sent=NSent',
|
||||
'STATS.Times Recv=TRecv', 'STATS.Bytes Recv=BRecv',
|
||||
'STATS.Net Bytes Recv=NRecv'));
|
||||
#
|
||||
$poolssum = array(
|
||||
'SUMMARY' => array('MHS av', 'Found Blocks', 'Accepted',
|
||||
'Rejected', 'Utility', 'Hardware Errors',
|
||||
'Work Utility'),
|
||||
'POOL+STATS' => array('POOL.Difficulty Accepted', 'POOL.Difficulty Rejected',
|
||||
'STATS.Times Sent', 'STATS.Bytes Sent',
|
||||
'STATS.Times Recv', 'STATS.Bytes Recv'));
|
||||
'STATS.Times Sent', 'STATS.Bytes Sent', 'STATS.Net Bytes Sent',
|
||||
'STATS.Times Recv', 'STATS.Bytes Recv', 'STATS.Net Bytes Recv'));
|
||||
#
|
||||
$poolsext = array(
|
||||
'POOL+STATS' => array(
|
||||
@ -130,7 +134,8 @@ $poolsext = array(
|
||||
'group' => array('POOL.URL', 'POOL.Has Stratum', 'POOL.Stratum Active', 'POOL.Has GBT'),
|
||||
'calc' => array('POOL.Difficulty Accepted' => 'sum', 'POOL.Difficulty Rejected' => 'sum',
|
||||
'STATS.Times Sent' => 'sum', 'STATS.Bytes Sent' => 'sum',
|
||||
'STATS.Times Recv' => 'sum', 'STATS.Bytes Recv' => 'sum'),
|
||||
'STATS.Net Bytes Sent' => 'sum', 'STATS.Times Recv' => 'sum',
|
||||
'STATS.Bytes Recv' => 'sum', 'STATS.Net Bytes Recv' => 'sum'),
|
||||
'having' => array(array('STATS.Bytes Recv', '>', 0)))
|
||||
);
|
||||
|
||||
@ -212,6 +217,10 @@ $rigerror = array();
|
||||
global $rownum;
|
||||
$rownum = 0;
|
||||
#
|
||||
// Login
|
||||
global $ses;
|
||||
$ses = 'rutroh';
|
||||
#
|
||||
function getcss($cssname, $dom = false)
|
||||
{
|
||||
global $colourtable, $colouroverride;
|
||||
@ -239,7 +248,7 @@ function getdom($domname)
|
||||
return getcss($domname, true);
|
||||
}
|
||||
#
|
||||
function htmlhead($checkapi, $rig, $pg = null)
|
||||
function htmlhead($checkapi, $rig, $pg = null, $noscript = false)
|
||||
{
|
||||
global $title, $miner_font_family, $miner_font_size;
|
||||
global $error, $readonly, $poolinputs, $here;
|
||||
@ -285,8 +294,10 @@ td.lst { $miner_font ".getcss('td.lst')."}
|
||||
td.hi { $miner_font ".getcss('td.hi')."}
|
||||
td.lo { $miner_font ".getcss('td.lo')."}
|
||||
</style>
|
||||
</head><body".getdom('body').">
|
||||
<script type='text/javascript'>
|
||||
</head><body".getdom('body').">\n";
|
||||
if ($noscript === false)
|
||||
{
|
||||
echo "<script type='text/javascript'>
|
||||
function pr(a,m){if(m!=null){if(!confirm(m+'?'))return}window.location='$here?ref=$autorefresh'+a}\n";
|
||||
|
||||
if ($ignorerefresh == false)
|
||||
@ -300,8 +311,9 @@ function prs2(a,n,r){var v=document.getElementById('gi'+n).value;var c=a.substr(
|
||||
if ($poolinputs === true)
|
||||
echo "function cbs(s){var t=s.replace(/\\\\/g,'\\\\\\\\'); return t.replace(/,/g, '\\\\,')}\nfunction pla(r){var u=document.getElementById('purl').value;var w=document.getElementById('pwork').value;var p=document.getElementById('ppass').value;pr('&rig='+r+'&arg=addpool|'+cbs(u)+','+cbs(w)+','+cbs(p),'Add Pool '+u)}\nfunction psp(r){var p=document.getElementById('prio').value;pr('&rig='+r+'&arg=poolpriority|'+p,'Set Pool Priorities to '+p)}\n";
|
||||
}
|
||||
echo "</script>\n";
|
||||
}
|
||||
?>
|
||||
</script>
|
||||
<table width=100% height=100% border=0 cellpadding=0 cellspacing=0 summary='Mine'>
|
||||
<tr><td align=center valign=top>
|
||||
<table border=0 cellpadding=4 cellspacing=0 summary='Mine'>
|
||||
@ -578,6 +590,14 @@ function classlastshare($when, $alldata, $warnclass, $errorclass)
|
||||
return '';
|
||||
}
|
||||
#
|
||||
function endzero($num)
|
||||
{
|
||||
$rep = preg_replace('/0*$/', '', $num);
|
||||
if ($rep === '')
|
||||
$rep = '0';
|
||||
return $rep;
|
||||
}
|
||||
#
|
||||
function fmt($section, $name, $value, $when, $alldata)
|
||||
{
|
||||
global $dfmt, $rownum;
|
||||
@ -840,12 +860,16 @@ function fmt($section, $name, $value, $when, $alldata)
|
||||
case 'total.Diff1 Work':
|
||||
case 'STATS.Times Sent':
|
||||
case 'STATS.Bytes Sent':
|
||||
case 'STATS.Net Bytes Sent':
|
||||
case 'STATS.Times Recv':
|
||||
case 'STATS.Bytes Recv':
|
||||
case 'STATS.Net Bytes Recv':
|
||||
case 'total.Times Sent':
|
||||
case 'total.Bytes Sent':
|
||||
case 'total.Net Bytes Sent':
|
||||
case 'total.Times Recv':
|
||||
case 'total.Bytes Recv':
|
||||
case 'total.Net Bytes Recv':
|
||||
$parts = explode('.', $value, 2);
|
||||
if (count($parts) == 1)
|
||||
$dec = '';
|
||||
@ -853,6 +877,23 @@ function fmt($section, $name, $value, $when, $alldata)
|
||||
$dec = '.'.$parts[1];
|
||||
$ret = number_format((float)$parts[0]).$dec;
|
||||
break;
|
||||
case 'STATS.Hs':
|
||||
case 'STATS.W':
|
||||
case 'STATS.history_time':
|
||||
case 'STATS.Pool Wait':
|
||||
case 'STATS.Pool Max':
|
||||
case 'STATS.Pool Min':
|
||||
case 'STATS.Pool Av':
|
||||
case 'STATS.Min Diff':
|
||||
case 'STATS.Max Diff':
|
||||
case 'STATS.Work Diff':
|
||||
$parts = explode('.', $value, 2);
|
||||
if (count($parts) == 1)
|
||||
$dec = '';
|
||||
else
|
||||
$dec = '.'.endzero($parts[1]);
|
||||
$ret = number_format((float)$parts[0]).$dec;
|
||||
break;
|
||||
case 'GPU.Status':
|
||||
case 'PGA.Status':
|
||||
case 'DEVS.Status':
|
||||
@ -1507,7 +1548,6 @@ function doforeach($cmd, $des, $sum, $head, $datetime)
|
||||
#
|
||||
function refreshbuttons()
|
||||
{
|
||||
global $readonly;
|
||||
global $ignorerefresh, $changerefresh, $autorefresh;
|
||||
|
||||
if ($ignorerefresh == false && $changerefresh == true)
|
||||
@ -1521,7 +1561,7 @@ function refreshbuttons()
|
||||
#
|
||||
function pagebuttons($rig, $pg)
|
||||
{
|
||||
global $readonly, $rigs;
|
||||
global $readonly, $rigs, $userlist, $ses;
|
||||
global $allowcustompages, $customsummarypages;
|
||||
|
||||
if ($rig === null)
|
||||
@ -1557,18 +1597,33 @@ function pagebuttons($rig, $pg)
|
||||
}
|
||||
|
||||
echo '<tr><td><table cellpadding=0 cellspacing=0 border=0><tr><td nowrap>';
|
||||
if ($prev !== null)
|
||||
echo riginput($prev, 'Prev').' ';
|
||||
echo "<input type=button value='Refresh' onclick='pr(\"$refresh\",null)'> ";
|
||||
if ($next !== null)
|
||||
echo riginput($next, 'Next').' ';
|
||||
echo ' ';
|
||||
if (count($rigs) > 1)
|
||||
echo "<input type=button value='Summary' onclick='pr(\"\",null)'> ";
|
||||
if ($userlist === null || isset($_SESSION[$ses]))
|
||||
{
|
||||
if ($prev !== null)
|
||||
echo riginput($prev, 'Prev').' ';
|
||||
echo "<input type=button value='Refresh' onclick='pr(\"$refresh\",null)'> ";
|
||||
if ($next !== null)
|
||||
echo riginput($next, 'Next').' ';
|
||||
echo ' ';
|
||||
if (count($rigs) > 1)
|
||||
echo "<input type=button value='Summary' onclick='pr(\"\",null)'> ";
|
||||
}
|
||||
|
||||
if ($allowcustompages === true)
|
||||
foreach ($customsummarypages as $pagename => $data)
|
||||
{
|
||||
if ($userlist === null || isset($_SESSION[$ses]))
|
||||
$list = $customsummarypages;
|
||||
else
|
||||
{
|
||||
if ($userlist !== null && isset($userlist['def']))
|
||||
$list = array_flip($userlist['def']);
|
||||
else
|
||||
$list = array();
|
||||
}
|
||||
|
||||
foreach ($list as $pagename => $data)
|
||||
echo "<input type=button value='$pagename' onclick='pr(\"&pg=$pagename\",null)'> ";
|
||||
}
|
||||
|
||||
echo '</td><td width=100%> </td><td nowrap>';
|
||||
if ($rig !== null && $readonly === false)
|
||||
@ -1580,6 +1635,12 @@ function pagebuttons($rig, $pg)
|
||||
echo " <input type=button value='Quit' onclick='prc(\"quit&rig=$rig\",\"Quit CGMiner$rg\")'>";
|
||||
}
|
||||
refreshbuttons();
|
||||
if (isset($_SESSION[$ses]))
|
||||
echo " <input type=button value='Logout' onclick='pr(\"&logout=1\",null)'>";
|
||||
else
|
||||
if ($userlist !== null)
|
||||
echo " <input type=button value='Login' onclick='pr(\"&login=1\",null)'>";
|
||||
|
||||
echo "</td></tr></table></td></tr>";
|
||||
}
|
||||
#
|
||||
@ -2015,6 +2076,8 @@ function docalc($func, $data)
|
||||
if (strcasecmp($val, $ans) > 0)
|
||||
$ans = $val;
|
||||
return $ans;
|
||||
case 'count':
|
||||
return count($data);
|
||||
case 'any':
|
||||
default:
|
||||
return $data[0];
|
||||
@ -2410,13 +2473,126 @@ function showcustompage($pagename)
|
||||
pagebuttons(null, $pagename);
|
||||
}
|
||||
#
|
||||
function onlylogin()
|
||||
{
|
||||
global $here;
|
||||
|
||||
htmlhead(false, null, null, true);
|
||||
|
||||
?>
|
||||
<tr height=15%><td> </td></tr>
|
||||
<tr><td>
|
||||
<center>
|
||||
<table width=384 height=368 cellpadding=0 cellspacing=0 border=0>
|
||||
<tr><td>
|
||||
<table width=100% height=100% border=0 align=center cellpadding=5 cellspacing=0>
|
||||
<tr><td><form action='<?php echo $here; ?>' method=post>
|
||||
<table width=200 border=0 align=center cellpadding=5 cellspacing=0>
|
||||
<tr><td height=120 colspan=2> </td></tr>
|
||||
<tr><td colspan=2 align=center valign=middle>
|
||||
<h2>LOGIN</h2></td></tr>
|
||||
<tr><td align=center valign=middle><div align=right>Username:</div></td>
|
||||
<td height=33 align=center valign=middle>
|
||||
<input type=text name=rut size=18></td></tr>
|
||||
<tr><td align=center valign=middle><div align=right>Password:</div></td>
|
||||
<td height=33 align=center valign=middle>
|
||||
<input type=password name=roh size=18></td></tr>
|
||||
<tr valign=top><td></td><td><input type=submit value=Login>
|
||||
</td></tr>
|
||||
</table></form></td></tr>
|
||||
</table></td></tr>
|
||||
</table></center>
|
||||
</td></tr>
|
||||
<?php
|
||||
}
|
||||
#
|
||||
function checklogin()
|
||||
{
|
||||
global $allowcustompages, $customsummarypages;
|
||||
global $readonly, $userlist, $ses;
|
||||
|
||||
$out = trim(getparam('logout', true));
|
||||
if ($out !== null && $out !== '' && isset($_SESSION[$ses]))
|
||||
unset($_SESSION[$ses]);
|
||||
|
||||
$login = trim(getparam('login', true));
|
||||
if ($login !== null && $login !== '')
|
||||
{
|
||||
if (isset($_SESSION[$ses]))
|
||||
unset($_SESSION[$ses]);
|
||||
|
||||
onlylogin();
|
||||
return 'login';
|
||||
}
|
||||
|
||||
if ($userlist === null)
|
||||
return false;
|
||||
|
||||
$rut = trim(getparam('rut', true));
|
||||
$roh = trim(getparam('roh', true));
|
||||
|
||||
if (($rut !== null && $rut !== '') || ($roh !== null && $roh !== ''))
|
||||
{
|
||||
if (isset($_SESSION[$ses]))
|
||||
unset($_SESSION[$ses]);
|
||||
|
||||
if ($rut !== null && $rut !== '' && $roh !== null && $roh !== '')
|
||||
{
|
||||
if (isset($userlist['sys']) && isset($userlist['sys'][$rut])
|
||||
&& ($userlist['sys'][$rut] === $roh))
|
||||
{
|
||||
$_SESSION[$ses] = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($userlist['usr']) && isset($userlist['usr'][$rut])
|
||||
&& ($userlist['usr'][$rut] === $roh))
|
||||
{
|
||||
$_SESSION[$ses] = false;
|
||||
$readonly = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_SESSION[$ses]))
|
||||
{
|
||||
if ($_SESSION[$ses] == false)
|
||||
$readonly = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($userlist['def']) && $allowcustompages === true)
|
||||
{
|
||||
// Ensure at least one exists
|
||||
foreach ($userlist['def'] as $pg)
|
||||
if (isset($customsummarypages[$pg]))
|
||||
return true;
|
||||
}
|
||||
|
||||
onlylogin();
|
||||
return 'login';
|
||||
}
|
||||
#
|
||||
function display()
|
||||
{
|
||||
global $miner, $port;
|
||||
global $readonly, $notify, $rigs;
|
||||
global $ignorerefresh, $autorefresh;
|
||||
global $allowcustompages;
|
||||
global $allowcustompages, $customsummarypages;
|
||||
global $placebuttons;
|
||||
global $userlist, $ses;
|
||||
|
||||
$pagesonly = checklogin();
|
||||
|
||||
if ($pagesonly === 'login')
|
||||
return;
|
||||
|
||||
if ($rigs == null or count($rigs) == 0)
|
||||
{
|
||||
otherrow("<td>No rigs defined</td>");
|
||||
return;
|
||||
}
|
||||
|
||||
if ($ignorerefresh == false)
|
||||
{
|
||||
@ -2425,52 +2601,65 @@ function display()
|
||||
$autorefresh = intval($ref);
|
||||
}
|
||||
|
||||
$rig = trim(getparam('rig', true));
|
||||
|
||||
$arg = trim(getparam('arg', true));
|
||||
$preprocess = null;
|
||||
if ($arg != null and $arg != '')
|
||||
if ($pagesonly !== true)
|
||||
{
|
||||
$num = null;
|
||||
if ($rig != null and $rig != '')
|
||||
{
|
||||
if ($rig >= 0 and $rig < count($rigs))
|
||||
$num = $rig;
|
||||
}
|
||||
else
|
||||
if (count($rigs) == 0)
|
||||
$num = 0;
|
||||
$rig = trim(getparam('rig', true));
|
||||
|
||||
if ($num != null)
|
||||
$arg = trim(getparam('arg', true));
|
||||
$preprocess = null;
|
||||
if ($arg != null and $arg != '')
|
||||
{
|
||||
$parts = explode(':', $rigs[$num], 3);
|
||||
if (count($parts) >= 2)
|
||||
if ($rig != null and $rig != '' and $rig >= 0 and $rig < count($rigs))
|
||||
{
|
||||
$miner = $parts[0];
|
||||
$port = $parts[1];
|
||||
$parts = explode(':', $rigs[$rig], 3);
|
||||
if (count($parts) >= 2)
|
||||
{
|
||||
$miner = $parts[0];
|
||||
$port = $parts[1];
|
||||
|
||||
if ($readonly !== true)
|
||||
$preprocess = $arg;
|
||||
if ($readonly !== true)
|
||||
$preprocess = $arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($rigs == null or count($rigs) == 0)
|
||||
{
|
||||
otherrow("<td>No rigs defined</td>");
|
||||
return;
|
||||
}
|
||||
|
||||
if ($allowcustompages === true)
|
||||
{
|
||||
$pg = trim(getparam('pg', true));
|
||||
if ($pg != null && $pg != '')
|
||||
if ($pagesonly === true)
|
||||
{
|
||||
if ($pg !== null && $pg !== '')
|
||||
{
|
||||
if ($userlist !== null && isset($userlist['def'])
|
||||
&& !in_array($pg, $userlist['def']))
|
||||
$pg = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($userlist !== null && isset($userlist['def']))
|
||||
foreach ($userlist['def'] as $pglook)
|
||||
if (isset($customsummarypages[$pglook]))
|
||||
{
|
||||
$pg = $pglook;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($pg !== null && $pg !== '')
|
||||
{
|
||||
showcustompage($pg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ($pagesonly === true)
|
||||
{
|
||||
onlylogin();
|
||||
return;
|
||||
}
|
||||
|
||||
if (count($rigs) == 1)
|
||||
{
|
||||
$parts = explode(':', $rigs[0], 3);
|
||||
|
782
usbutils.c
782
usbutils.c
File diff suppressed because it is too large
Load Diff
76
usbutils.h
76
usbutils.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012 Andrew Smith
|
||||
* Copyright 2012-2013 Andrew Smith
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
@ -12,6 +12,29 @@
|
||||
|
||||
#include <libusb.h>
|
||||
|
||||
// for 0x0403/0x6014 FT232H (and possibly others?)
|
||||
#define FTDI_TYPE_OUT (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT)
|
||||
|
||||
#define FTDI_REQUEST_RESET ((uint8_t)0)
|
||||
#define FTDI_REQUEST_MODEM ((uint8_t)1)
|
||||
#define FTDI_REQUEST_FLOW ((uint8_t)2)
|
||||
#define FTDI_REQUEST_BAUD ((uint8_t)3)
|
||||
#define FTDI_REQUEST_DATA ((uint8_t)4)
|
||||
|
||||
#define FTDI_VALUE_RESET 0
|
||||
#define FTDI_VALUE_PURGE_RX 1
|
||||
#define FTDI_VALUE_PURGE_TX 2
|
||||
|
||||
// baud with a 0 divisor is 120,000,000/10
|
||||
//#define FTDI_VALUE_BAUD (0)
|
||||
//#define FTDI_INDEX_BAUD (0)
|
||||
#define FTDI_VALUE_BAUD 0xc068
|
||||
#define FTDI_INDEX_BAUD 0x0200
|
||||
|
||||
#define FTDI_VALUE_DATA 0
|
||||
#define FTDI_VALUE_FLOW 0
|
||||
#define FTDI_VALUE_MODEM 0x0303
|
||||
|
||||
// Use the device defined timeout
|
||||
#define DEVTIMEOUT 0
|
||||
|
||||
@ -32,6 +55,7 @@ struct usb_find_devices {
|
||||
const char *name;
|
||||
uint16_t idVendor;
|
||||
uint16_t idProduct;
|
||||
int kernel;
|
||||
int config;
|
||||
int interface;
|
||||
unsigned int timeout;
|
||||
@ -44,8 +68,6 @@ struct cg_usb_device {
|
||||
libusb_device_handle *handle;
|
||||
pthread_mutex_t *mutex;
|
||||
struct libusb_device_descriptor *descriptor;
|
||||
uint8_t bus_number;
|
||||
uint8_t device_address;
|
||||
uint16_t usbver;
|
||||
int speed;
|
||||
char *prod_string;
|
||||
@ -55,8 +77,18 @@ struct cg_usb_device {
|
||||
unsigned char interfaceVersion; // ??
|
||||
};
|
||||
|
||||
struct cg_usb_info {
|
||||
uint8_t bus_number;
|
||||
uint8_t device_address;
|
||||
int usbstat;
|
||||
bool nodev;
|
||||
int nodev_count;
|
||||
struct timeval last_nodev;
|
||||
};
|
||||
|
||||
enum usb_cmds {
|
||||
C_PING = 0,
|
||||
C_REJECTED = 0,
|
||||
C_PING,
|
||||
C_CLEAR,
|
||||
C_REQUESTVERSION,
|
||||
C_GETVERSION,
|
||||
@ -78,32 +110,48 @@ enum usb_cmds {
|
||||
C_SENDWORKSTATUS,
|
||||
C_REQUESTWORKSTATUS,
|
||||
C_GETWORKSTATUS,
|
||||
C_REQUESTIDENTIFY,
|
||||
C_GETIDENTIFY,
|
||||
C_REQUESTFLASH,
|
||||
C_REQUESTSENDWORK,
|
||||
C_REQUESTSENDWORKSTATUS,
|
||||
C_RESET,
|
||||
C_SETBAUD,
|
||||
C_SETDATA,
|
||||
C_SETFLOW,
|
||||
C_SETMODEM,
|
||||
C_PURGERX,
|
||||
C_PURGETX,
|
||||
C_MAX
|
||||
};
|
||||
|
||||
struct device_api;
|
||||
struct device_drv;
|
||||
struct cgpu_info;
|
||||
|
||||
void usb_uninit(struct cgpu_info *cgpu);
|
||||
bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find_devices *found);
|
||||
void usb_detect(struct device_api *api, bool (*device_detect)(struct libusb_device *, struct usb_find_devices *));
|
||||
void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_device *, struct usb_find_devices *));
|
||||
struct api_data *api_usb_stats(int *count);
|
||||
void update_usb_stats(struct cgpu_info *cgpu);
|
||||
int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, int eol, enum usb_cmds);
|
||||
int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, int eol, enum usb_cmds, bool ftdi);
|
||||
int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, enum usb_cmds);
|
||||
int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned int timeout, enum usb_cmds cmd);
|
||||
void usb_cleanup();
|
||||
|
||||
#define usb_read(cgpu, buf, bufsiz, read, cmd) \
|
||||
_usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, -1, cmd)
|
||||
_usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, -1, cmd, false)
|
||||
|
||||
#define usb_read_nl(cgpu, buf, bufsiz, read, cmd) \
|
||||
_usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, '\n', cmd, false)
|
||||
|
||||
#define usb_read_ep(cgpu, ep, buf, bufsiz, read, cmd) \
|
||||
_usb_read(cgpu, ep, buf, bufsiz, read, DEVTIMEOUT, -1, cmd)
|
||||
_usb_read(cgpu, ep, buf, bufsiz, read, DEVTIMEOUT, -1, cmd, false)
|
||||
|
||||
#define usb_read_timeout(cgpu, buf, bufsiz, read, timeout, cmd) \
|
||||
_usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, timeout, -1, cmd)
|
||||
_usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, timeout, -1, cmd, false)
|
||||
|
||||
#define usb_read_ep_timeout(cgpu, ep, buf, bufsiz, read, timeout, cmd) \
|
||||
_usb_read(cgpu, ep, buf, bufsiz, read, timeout, -1, cmd)
|
||||
_usb_read(cgpu, ep, buf, bufsiz, read, timeout, -1, cmd, false)
|
||||
|
||||
#define usb_write(cgpu, buf, bufsiz, wrote, cmd) \
|
||||
_usb_write(cgpu, DEFAULT_EP_OUT, buf, bufsiz, wrote, DEVTIMEOUT, cmd)
|
||||
@ -117,4 +165,10 @@ void usb_cleanup();
|
||||
#define usb_write_ep_timeout(cgpu, ep, buf, bufsiz, wrote, timeout, cmd) \
|
||||
_usb_write(cgpu, ep, buf, bufsiz, wrote, timeout, cmd)
|
||||
|
||||
#define usb_ftdi_read_nl(cgpu, buf, bufsiz, read, cmd) \
|
||||
_usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, '\n', cmd, true)
|
||||
|
||||
#define usb_transfer(cgpu, typ, req, val, idx, cmd) \
|
||||
_usb_transfer(cgpu, typ, req, val, idx, DEVTIMEOUT, cmd)
|
||||
|
||||
#endif
|
||||
|
34
util.c
34
util.c
@ -261,6 +261,29 @@ static void set_nettime(void)
|
||||
wr_unlock(&netacc_lock);
|
||||
}
|
||||
|
||||
static int curl_debug_cb(__maybe_unused CURL *handle, curl_infotype type,
|
||||
__maybe_unused char *data, size_t size, void *userdata)
|
||||
{
|
||||
struct pool *pool = (struct pool *)userdata;
|
||||
|
||||
switch(type) {
|
||||
case CURLINFO_HEADER_IN:
|
||||
case CURLINFO_DATA_IN:
|
||||
case CURLINFO_SSL_DATA_IN:
|
||||
pool->cgminer_pool_stats.net_bytes_received += size;
|
||||
break;
|
||||
case CURLINFO_HEADER_OUT:
|
||||
case CURLINFO_DATA_OUT:
|
||||
case CURLINFO_SSL_DATA_OUT:
|
||||
pool->cgminer_pool_stats.net_bytes_sent += size;
|
||||
break;
|
||||
case CURLINFO_TEXT:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
json_t *json_rpc_call(CURL *curl, const char *url,
|
||||
const char *userpass, const char *rpc_req,
|
||||
bool probe, bool longpoll, int *rolltime,
|
||||
@ -287,10 +310,11 @@ json_t *json_rpc_call(CURL *curl, const char *url,
|
||||
probing = !pool->probed;
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout);
|
||||
|
||||
#if 0 /* Disable curl debugging since it spews to stderr */
|
||||
if (opt_protocol)
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
||||
#endif
|
||||
// CURLOPT_VERBOSE won't write to stderr if we use CURLOPT_DEBUGFUNCTION
|
||||
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curl_debug_cb);
|
||||
curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void *)pool);
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
curl_easy_setopt(curl, CURLOPT_ENCODING, "");
|
||||
@ -912,6 +936,7 @@ static bool __stratum_send(struct pool *pool, char *s, ssize_t len)
|
||||
|
||||
pool->cgminer_pool_stats.times_sent++;
|
||||
pool->cgminer_pool_stats.bytes_sent += ssent;
|
||||
pool->cgminer_pool_stats.net_bytes_sent += ssent;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1041,6 +1066,7 @@ char *recv_line(struct pool *pool)
|
||||
|
||||
pool->cgminer_pool_stats.times_received++;
|
||||
pool->cgminer_pool_stats.bytes_received += len;
|
||||
pool->cgminer_pool_stats.net_bytes_received += len;
|
||||
out:
|
||||
if (!sret)
|
||||
clear_sock(pool);
|
||||
|
Loading…
x
Reference in New Issue
Block a user