Browse Source

Merge branch 'master' of https://github.com/kanoi/cgminer into kanoi-usb

nfactor-troky
Con Kolivas 12 years ago
parent
commit
70b5b84052
  1. 57
      API-README
  2. 25
      FPGA-README
  3. 6
      Makefile.am
  4. 20
      README
  5. 175
      api.c
  6. 322
      cgminer.c
  7. 7
      configure.ac
  8. 666
      driver-bitforce.c
  9. 9
      driver-cpu.c
  10. 2
      driver-cpu.h
  11. 19
      driver-icarus.c
  12. 182
      driver-modminer.c
  13. 70
      driver-opencl.c
  14. 2
      driver-opencl.h
  15. 10
      driver-ztex.c
  16. 2
      findnonce.c
  17. 10
      fpgautils.c
  18. 14
      fpgautils.h
  19. 44
      miner.h
  20. 251
      miner.php
  21. 714
      usbutils.c
  22. 77
      usbutils.h
  23. 33
      util.c

57
API-README

@ -347,6 +347,18 @@ The list of requests - a (*) means it requires privileged access - and replies a @@ -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 @@ -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 @@ -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;

25
FPGA-README

@ -2,15 +2,8 @@ @@ -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: @@ -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 @@ -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

6
Makefile.am

@ -82,6 +82,10 @@ if NEED_FPGAUTILS @@ -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 @@ -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

@ -220,15 +220,16 @@ SCRYPT only options: @@ -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. @@ -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: @@ -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.

175
api.c

@ -1,5 +1,5 @@ @@ -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 = '|'; @@ -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"; @@ -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 { @@ -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 { @@ -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;
@ -1153,19 +1150,19 @@ static int numpgas() @@ -1153,19 +1150,19 @@ static int numpgas()
for (i = 0; i < total_devices; i++) {
#ifdef USE_BITFORCE
if (devices[i]->api == &bitforce_api)
if (devices[i]->drv->drv == DRIVER_BITFORCE)
count++;
#endif
#ifdef USE_ICARUS
if (devices[i]->api == &icarus_api)
if (devices[i]->drv->drv == DRIVER_ICARUS)
count++;
#endif
#ifdef USE_ZTEX
if (devices[i]->api == &ztex_api)
if (devices[i]->drv->drv == DRIVER_ZTEX)
count++;
#endif
#ifdef USE_MODMINER
if (devices[i]->api == &modminer_api)
if (devices[i]->drv->drv == DRIVER_MODMINER)
count++;
#endif
}
@ -1179,19 +1176,19 @@ static int pgadevice(int pgaid) @@ -1179,19 +1176,19 @@ static int pgadevice(int pgaid)
for (i = 0; i < total_devices; i++) {
#ifdef USE_BITFORCE
if (devices[i]->api == &bitforce_api)
if (devices[i]->drv->drv == DRIVER_BITFORCE)
count++;
#endif
#ifdef USE_ICARUS
if (devices[i]->api == &icarus_api)
if (devices[i]->drv->drv == DRIVER_ICARUS)
count++;
#endif
#ifdef USE_ZTEX
if (devices[i]->api == &ztex_api)
if (devices[i]->drv->drv == DRIVER_ZTEX)
count++;
#endif
#ifdef USE_MODMINER
if (devices[i]->api == &modminer_api)
if (devices[i]->drv->drv == DRIVER_MODMINER)
count++;
#endif
if (count == (pgaid + 1))
@ -1535,11 +1532,11 @@ static void pgastatus(struct io_data *io_data, int pga, bool isjson, bool precom @@ -1535,11 +1532,11 @@ static void pgastatus(struct io_data *io_data, int pga, bool isjson, bool precom
float temp = cgpu->temp;
#ifdef USE_ZTEX
if (cgpu->api == &ztex_api && cgpu->device_ztex)
if (cgpu->drv->drv == 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 == DRIVER_MODMINER)
frequency = cgpu->clock;
#endif
@ -1553,7 +1550,7 @@ static void pgastatus(struct io_data *io_data, int pga, bool isjson, bool precom @@ -1553,7 +1550,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 +1574,9 @@ static void pgastatus(struct io_data *io_data, int pga, bool isjson, bool precom @@ -1577,6 +1574,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);
@ -1777,6 +1777,9 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char @@ -1777,6 +1777,9 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char
struct cgpu_info *cgpu = 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);
return;
@ -1789,11 +1792,21 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char @@ -1789,11 +1792,21 @@ 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;
mutex_lock(&mining_thr_lock);
thr = mining_thr[i];
mutex_unlock(&mining_thr_lock);
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);
}
}
@ -1830,6 +1843,9 @@ static void pgadisable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, cha @@ -1830,6 +1843,9 @@ static void pgadisable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, cha
struct cgpu_info *cgpu = 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);
return;
@ -1868,12 +1884,12 @@ static void pgaidentify(struct io_data *io_data, __maybe_unused SOCKETTYPE c, ch @@ -1868,12 +1884,12 @@ static void pgaidentify(struct io_data *io_data, __maybe_unused SOCKETTYPE c, ch
}
struct cgpu_info *cgpu = devices[dev];
struct device_api *api = cgpu->api;
struct device_drv *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 +2009,7 @@ static void poolstatus(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m @@ -1993,6 +2009,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 +2098,27 @@ static void gpuenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char @@ -2081,23 +2098,27 @@ 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;
mutex_lock(&mining_thr_lock);
thr = mining_thr[i];
mutex_unlock(&mining_thr_lock);
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 +2145,9 @@ static void gpudisable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, cha @@ -2124,6 +2145,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 +2776,7 @@ void notifystatus(struct io_data *io_data, int device, struct cgpu_info *cgpu, b @@ -2752,7 +2776,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);
@ -2816,9 +2840,9 @@ static void devdetails(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m @@ -2816,9 +2840,9 @@ static void devdetails(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m
cgpu = 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 +2919,8 @@ static int itemstats(struct io_data *io_data, int i, char *id, struct cgminer_st @@ -2895,6 +2919,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)
@ -2922,13 +2948,13 @@ static void minerstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m @@ -2922,13 +2948,13 @@ static void minerstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m
for (j = 0; j < total_devices; j++) {
struct cgpu_info *cgpu = 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 +3146,7 @@ static void usbstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __may @@ -3120,7 +3146,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 +3159,7 @@ static void usbstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __may @@ -3133,7 +3159,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);
@ -3194,16 +3220,16 @@ static void pgaset(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe @@ -3194,16 +3220,16 @@ static void pgaset(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe
}
struct cgpu_info *cgpu = devices[dev];
struct device_api *api = cgpu->api;
struct device_drv *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 +3241,54 @@ static void pgaset(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe @@ -3215,6 +3241,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 +3348,7 @@ struct CMDS { @@ -3274,6 +3348,7 @@ struct CMDS {
#ifdef HAVE_AN_FPGA
{ "pgaset", pgaset, true },
#endif
{ "zero", dozero, true },
{ NULL, NULL, false }
};

322
cgminer.c

@ -146,7 +146,8 @@ bool opt_bfl_noncerange; @@ -146,7 +146,8 @@ bool opt_bfl_noncerange;
#endif
#define QUIET (opt_quiet || opt_realquiet)
struct thr_info *thr_info;
struct thr_info *control_thr;
struct thr_info **mining_thr;
static int gwsched_thr_id;
static int stage_thr_id;
static int watchpool_thr_id;
@ -156,7 +157,7 @@ static int input_thr_id; @@ -156,7 +157,7 @@ static int input_thr_id;
#endif
int gpur_thr_id;
static int api_thr_id;
static int total_threads;
static int total_control_threads;
#ifdef HAVE_LIBUSB
pthread_mutex_t cgusb_lock;
@ -171,6 +172,7 @@ static pthread_rwlock_t blk_lock; @@ -171,6 +172,7 @@ static pthread_rwlock_t blk_lock;
static pthread_mutex_t sshare_lock;
pthread_rwlock_t netacc_lock;
pthread_mutex_t mining_thr_lock;
static pthread_mutex_t lp_lock;
static pthread_cond_t lp_cond;
@ -377,7 +379,9 @@ static void sharelog(const char*disposition, const struct work*work) @@ -377,7 +379,9 @@ static void sharelog(const char*disposition, const struct work*work)
return;
thr_id = work->thr_id;
cgpu = thr_info[thr_id].cgpu;
mutex_lock(&mining_thr_lock);
cgpu = mining_thr[thr_id]->cgpu;
mutex_unlock(&mining_thr_lock);
pool = work->pool;
t = (unsigned long int)(work->tv_work_found.tv_sec);
target = bin2hex(work->target, sizeof(work->target));
@ -385,7 +389,7 @@ static void sharelog(const char*disposition, const struct work*work) @@ -385,7 +389,7 @@ static void sharelog(const char*disposition, const struct work*work)
data = bin2hex(work->data, sizeof(work->data));
// timestamp,disposition,target,pool,dev,thr,sharehash,sharedata
rv = snprintf(s, sizeof(s), "%lu,%s,%s,%s,%s%u,%u,%s,%s\n", t, disposition, target, pool->rpc_url, cgpu->api->name, cgpu->device_id, thr_id, hash, data);
rv = snprintf(s, sizeof(s), "%lu,%s,%s,%s,%s%u,%u,%s,%s\n", t, disposition, target, pool->rpc_url, cgpu->drv->name, cgpu->device_id, thr_id, hash, data);
free(target);
free(hash);
free(data);
@ -1722,7 +1726,13 @@ out: @@ -1722,7 +1726,13 @@ out:
int dev_from_id(int thr_id)
{
return thr_info[thr_id].cgpu->device_id;
struct cgpu_info *cgpu;
mutex_lock(&mining_thr_lock);
cgpu = mining_thr[thr_id]->cgpu;
mutex_unlock(&mining_thr_lock);
return cgpu->device_id;
}
/* Make the change in the recent value adjust dynamically when the difference
@ -1875,9 +1885,9 @@ static void get_statline(char *buf, struct cgpu_info *cgpu) @@ -1875,9 +1885,9 @@ static void get_statline(char *buf, struct cgpu_info *cgpu)
suffix_string(dh64, displayed_hashes, 4);
suffix_string(dr64, displayed_rolling, 4);
sprintf(buf, "%s%d ", cgpu->api->name, cgpu->device_id);
if (cgpu->api->get_statline_before)
cgpu->api->get_statline_before(buf, cgpu);
sprintf(buf, "%s%d ", cgpu->drv->name, cgpu->device_id);
if (cgpu->drv->get_statline_before)
cgpu->drv->get_statline_before(buf, cgpu);
else
tailsprintf(buf, " | ");
tailsprintf(buf, "(%ds):%s (avg):%sh/s | A:%d R:%d HW:%d U:%.1f/m",
@ -1888,15 +1898,19 @@ static void get_statline(char *buf, struct cgpu_info *cgpu) @@ -1888,15 +1898,19 @@ static void get_statline(char *buf, struct cgpu_info *cgpu)
cgpu->rejected,
cgpu->hw_errors,
cgpu->utility);
if (cgpu->api->get_statline)
cgpu->api->get_statline(buf, cgpu);
if (cgpu->drv->get_statline)
cgpu->drv->get_statline(buf, cgpu);
}
static void text_print_status(int thr_id)
{
struct cgpu_info *cgpu = thr_info[thr_id].cgpu;
struct cgpu_info *cgpu;
char logline[256];
mutex_lock(&mining_thr_lock);
cgpu = mining_thr[thr_id]->cgpu;
mutex_unlock(&mining_thr_lock);
if (cgpu) {
get_statline(logline, cgpu);
printf("%s\n", logline);
@ -1960,21 +1974,25 @@ static int dev_width; @@ -1960,21 +1974,25 @@ static int dev_width;
static void curses_print_devstatus(int thr_id)
{
static int awidth = 1, rwidth = 1, hwwidth = 1, uwidth = 1;
struct cgpu_info *cgpu = thr_info[thr_id].cgpu;
struct cgpu_info *cgpu;
char logline[256];
char displayed_hashes[16], displayed_rolling[16];
uint64_t dh64, dr64;
mutex_lock(&mining_thr_lock);
cgpu = mining_thr[thr_id]->cgpu;
mutex_unlock(&mining_thr_lock);
if (devcursor + cgpu->cgminer_id > LINES - 2 || opt_compact)
return;
cgpu->utility = cgpu->accepted / total_secs * 60;
wmove(statuswin,devcursor + cgpu->cgminer_id, 0);
wprintw(statuswin, " %s %*d: ", cgpu->api->name, dev_width, cgpu->device_id);
if (cgpu->api->get_statline_before) {
wprintw(statuswin, " %s %*d: ", cgpu->drv->name, dev_width, cgpu->device_id);
if (cgpu->drv->get_statline_before) {
logline[0] = '\0';
cgpu->api->get_statline_before(logline, cgpu);
cgpu->drv->get_statline_before(logline, cgpu);
wprintw(statuswin, "%s", logline);
}
else
@ -2007,9 +2025,9 @@ static void curses_print_devstatus(int thr_id) @@ -2007,9 +2025,9 @@ static void curses_print_devstatus(int thr_id)
hwwidth, cgpu->hw_errors,
uwidth + 3, cgpu->utility);
if (cgpu->api->get_statline) {
if (cgpu->drv->get_statline) {
logline[0] = '\0';
cgpu->api->get_statline(logline, cgpu);
cgpu->drv->get_statline(logline, cgpu);
wprintw(statuswin, "%s", logline);
}
@ -2212,7 +2230,11 @@ share_result(json_t *val, json_t *res, json_t *err, const struct work *work, @@ -2212,7 +2230,11 @@ share_result(json_t *val, json_t *res, json_t *err, const struct work *work,
char *hashshow, bool resubmit, char *worktime)
{
struct pool *pool = work->pool;
struct cgpu_info *cgpu = thr_info[work->thr_id].cgpu;
struct cgpu_info *cgpu;
mutex_lock(&mining_thr_lock);
cgpu = mining_thr[work->thr_id]->cgpu;
mutex_unlock(&mining_thr_lock);
if (json_is_true(res) || (work->gbt && json_is_null(res))) {
mutex_lock(&stats_lock);
@ -2234,10 +2256,10 @@ share_result(json_t *val, json_t *res, json_t *err, const struct work *work, @@ -2234,10 +2256,10 @@ share_result(json_t *val, json_t *res, json_t *err, const struct work *work,
if (!QUIET) {
if (total_pools > 1)
applog(LOG_NOTICE, "Accepted %s %s %d pool %d %s%s",
hashshow, cgpu->api->name, cgpu->device_id, work->pool->pool_no, resubmit ? "(resubmit)" : "", worktime);
hashshow, cgpu->drv->name, cgpu->device_id, work->pool->pool_no, resubmit ? "(resubmit)" : "", worktime);
else
applog(LOG_NOTICE, "Accepted %s %s %d %s%s",
hashshow, cgpu->api->name, cgpu->device_id, resubmit ? "(resubmit)" : "", worktime);
hashshow, cgpu->drv->name, cgpu->device_id, resubmit ? "(resubmit)" : "", worktime);
}
sharelog("accept", work);
if (opt_shares && total_accepted >= opt_shares) {
@ -2302,7 +2324,7 @@ share_result(json_t *val, json_t *res, json_t *err, const struct work *work, @@ -2302,7 +2324,7 @@ share_result(json_t *val, json_t *res, json_t *err, const struct work *work,
}
applog(LOG_NOTICE, "Rejected %s %s %d %s%s %s%s",
hashshow, cgpu->api->name, cgpu->device_id, where, reason, resubmit ? "(resubmit)" : "", worktime);
hashshow, cgpu->drv->name, cgpu->device_id, where, reason, resubmit ? "(resubmit)" : "", worktime);
sharelog(disposition, work);
}
@ -2349,6 +2371,8 @@ static uint64_t share_diff(const struct work *work) @@ -2349,6 +2371,8 @@ static uint64_t share_diff(const struct work *work)
best_diff = ret;
suffix_string(best_diff, best_share, 0);
}
if (ret > work->pool->best_diff)
work->pool->best_diff = ret;
mutex_unlock(&control_lock);
return ret;
}
@ -2360,13 +2384,17 @@ static bool submit_upstream_work(struct work *work, CURL *curl, bool resubmit) @@ -2360,13 +2384,17 @@ static bool submit_upstream_work(struct work *work, CURL *curl, bool resubmit)
char *s;
bool rc = false;
int thr_id = work->thr_id;
struct cgpu_info *cgpu = thr_info[thr_id].cgpu;
struct cgpu_info *cgpu;
struct pool *pool = work->pool;
int rolltime;
struct timeval tv_submit, tv_submit_reply;
char hashshow[64 + 4] = "";
char worktime[200] = "";
mutex_lock(&mining_thr_lock);
cgpu = mining_thr[thr_id]->cgpu;
mutex_unlock(&mining_thr_lock);
#ifdef __BIG_ENDIAN__
int swapcounter = 0;
for (swapcounter = 0; swapcounter < 32; swapcounter++)
@ -2574,7 +2602,7 @@ static inline struct pool *select_pool(bool lagging) @@ -2574,7 +2602,7 @@ static inline struct pool *select_pool(bool lagging)
return pool;
}
static double DIFFEXACTONE = 26959946667150639794667015087019630673637144422540572481103610249216.0;
static double DIFFEXACTONE = 26959946667150639794667015087019630673637144422540572481103610249215.0;
/*
* Calculate the work share difficulty
@ -2730,8 +2758,6 @@ static void disable_curses(void) @@ -2730,8 +2758,6 @@ static void disable_curses(void)
}
#endif
static void print_summary(void);
static void __kill_work(void)
{
struct thr_info *thr;
@ -2744,18 +2770,20 @@ static void __kill_work(void) @@ -2744,18 +2770,20 @@ static void __kill_work(void)
applog(LOG_DEBUG, "Killing off watchpool thread");
/* Kill the watchpool thread */
thr = &thr_info[watchpool_thr_id];
thr = &control_thr[watchpool_thr_id];
thr_info_cancel(thr);
applog(LOG_DEBUG, "Killing off watchdog thread");
/* Kill the watchdog thread */
thr = &thr_info[watchdog_thr_id];
thr = &control_thr[watchdog_thr_id];
thr_info_cancel(thr);
applog(LOG_DEBUG, "Stopping mining threads");
/* Stop the mining threads*/
for (i = 0; i < mining_threads; i++) {
thr = &thr_info[i];
mutex_lock(&mining_thr_lock);
thr = mining_thr[i];
mutex_unlock(&mining_thr_lock);
thr_info_freeze(thr);
thr->pause = true;
}
@ -2765,17 +2793,19 @@ static void __kill_work(void) @@ -2765,17 +2793,19 @@ static void __kill_work(void)
applog(LOG_DEBUG, "Killing off mining threads");
/* Kill the mining threads*/
for (i = 0; i < mining_threads; i++) {
thr = &thr_info[i];
mutex_lock(&mining_thr_lock);
thr = mining_thr[i];
mutex_unlock(&mining_thr_lock);
thr_info_cancel(thr);
}
applog(LOG_DEBUG, "Killing off stage thread");
/* Stop the others */
thr = &thr_info[stage_thr_id];
thr = &control_thr[stage_thr_id];
thr_info_cancel(thr);
applog(LOG_DEBUG, "Killing off API thread");
thr = &thr_info[api_thr_id];
thr = &control_thr[api_thr_id];
thr_info_cancel(thr);
}
@ -3369,8 +3399,10 @@ static void restart_threads(void) @@ -3369,8 +3399,10 @@ static void restart_threads(void)
/* Discard staged work that is now stale */
discard_stale();
mutex_lock(&mining_thr_lock);
for (i = 0; i < mining_threads; i++)
thr_info[i].work_restart = true;
mining_thr[i]->work_restart = true;
mutex_unlock(&mining_thr_lock);
mutex_lock(&restart_lock);
pthread_cond_broadcast(&restart_cond);
@ -3914,6 +3946,20 @@ void write_config(FILE *fcfg) @@ -3914,6 +3946,20 @@ void write_config(FILE *fcfg)
json_escape_free();
}
void zero_bestshare(void)
{
int i;
best_diff = 0;
memset(best_share, 0, 8);
suffix_string(best_diff, best_share, 0);
for (i = 0; i < total_pools; i++) {
struct pool *pool = pools[i];
pool->best_diff = 0;
}
}
void zero_stats(void)
{
int i;
@ -3930,10 +3976,11 @@ void zero_stats(void) @@ -3930,10 +3976,11 @@ void zero_stats(void)
total_go = 0;
total_ro = 0;
total_secs = 1.0;
best_diff = 0;
total_diff1 = 0;
memset(best_share, 0, 8);
suffix_string(best_diff, best_share, 0);
found_blocks = 0;
total_diff_accepted = 0;
total_diff_rejected = 0;
total_diff_stale = 0;
for (i = 0; i < total_pools; i++) {
struct pool *pool = pools[i];
@ -3945,8 +3992,16 @@ void zero_stats(void) @@ -3945,8 +3992,16 @@ void zero_stats(void)
pool->discarded_work = 0;
pool->getfail_occasions = 0;
pool->remotefail_occasions = 0;
pool->last_share_time = 0;
pool->diff1 = 0;
pool->diff_accepted = 0;
pool->diff_rejected = 0;
pool->diff_stale = 0;
pool->last_share_diff = 0;
}
zero_bestshare();
mutex_lock(&hash_lock);
for (i = 0; i < total_devices; ++i) {
struct cgpu_info *cgpu = devices[i];
@ -3956,6 +4011,11 @@ void zero_stats(void) @@ -3956,6 +4011,11 @@ void zero_stats(void)
cgpu->rejected = 0;
cgpu->hw_errors = 0;
cgpu->utility = 0.0;
cgpu->last_share_pool_time = 0;
cgpu->diff1 = 0;
cgpu->diff_accepted = 0;
cgpu->diff_rejected = 0;
cgpu->last_share_diff = 0;
}
mutex_unlock(&hash_lock);
}
@ -4378,20 +4438,23 @@ static void hashmeter(int thr_id, struct timeval *diff, @@ -4378,20 +4438,23 @@ static void hashmeter(int thr_id, struct timeval *diff,
bool showlog = false;
char displayed_hashes[16], displayed_rolling[16];
uint64_t dh64, dr64;
struct thr_info *thr;
local_mhashes = (double)hashes_done / 1000000.0;
/* Update the last time this thread reported in */
if (thr_id >= 0) {
gettimeofday(&thr_info[thr_id].last, NULL);
thr_info[thr_id].cgpu->device_last_well = time(NULL);
mutex_lock(&mining_thr_lock);
thr = mining_thr[thr_id];
mutex_unlock(&mining_thr_lock);
gettimeofday(&(thr->last), NULL);
thr->cgpu->device_last_well = time(NULL);
}
secs = (double)diff->tv_sec + ((double)diff->tv_usec / 1000000.0);
/* So we can call hashmeter from a non worker thread */
if (thr_id >= 0) {
struct thr_info *thr = &thr_info[thr_id];
struct cgpu_info *cgpu = thr_info[thr_id].cgpu;
struct cgpu_info *cgpu = thr->cgpu;
double thread_rolling = 0.0;
int i;
@ -4574,8 +4637,8 @@ static void clear_stratum_shares(struct pool *pool) @@ -4574,8 +4637,8 @@ static void clear_stratum_shares(struct pool *pool)
if (cleared) {
applog(LOG_WARNING, "Lost %d shares due to stratum disconnect on pool %d", cleared, pool->pool_no);
pool->stale_shares++;
total_stale++;
pool->stale_shares += cleared;
total_stale += cleared;
}
}
@ -4881,7 +4944,7 @@ retry_stratum: @@ -4881,7 +4944,7 @@ retry_stratum:
calc_diff(work, 0);
applog(LOG_DEBUG, "Pushing pooltest work to base pool");
tq_push(thr_info[stage_thr_id].q, work);
tq_push(control_thr[stage_thr_id].q, work);
total_getworks++;
pool->getwork_requested++;
ret = true;
@ -5221,15 +5284,15 @@ static bool hashtest(struct thr_info *thr, struct work *work) @@ -5221,15 +5284,15 @@ static bool hashtest(struct thr_info *thr, struct work *work)
if (hash2_32[7] != 0) {
applog(LOG_WARNING, "%s%d: invalid nonce - HW error",
thr->cgpu->api->name, thr->cgpu->device_id);
thr->cgpu->drv->name, thr->cgpu->device_id);
mutex_lock(&stats_lock);
hw_errors++;
thr->cgpu->hw_errors++;
mutex_unlock(&stats_lock);
if (thr->cgpu->api->hw_error)
thr->cgpu->api->hw_error(thr);
if (thr->cgpu->drv->hw_error)
thr->cgpu->drv->hw_error(thr);
goto out;
}
@ -5277,7 +5340,7 @@ static inline bool abandon_work(struct work *work, struct timeval *wdiff, uint64 @@ -5277,7 +5340,7 @@ static inline bool abandon_work(struct work *work, struct timeval *wdiff, uint64
}
static void mt_disable(struct thr_info *mythr, const int thr_id,
struct device_api *api)
struct device_drv *drv)
{
applog(LOG_WARNING, "Thread %d being disabled", thr_id);
mythr->rolling = mythr->cgpu->rolling = 0;
@ -5288,8 +5351,8 @@ static void mt_disable(struct thr_info *mythr, const int thr_id, @@ -5288,8 +5351,8 @@ static void mt_disable(struct thr_info *mythr, const int thr_id,
} while (mythr->pause);
thread_reportin(mythr);
applog(LOG_WARNING, "Thread %d being re-enabled", thr_id);
if (api->thread_enable)
api->thread_enable(mythr);
if (drv->thread_enable)
drv->thread_enable(mythr);
}
void *miner_thread(void *userdata)
@ -5297,7 +5360,7 @@ void *miner_thread(void *userdata) @@ -5297,7 +5360,7 @@ void *miner_thread(void *userdata)
struct thr_info *mythr = userdata;
const int thr_id = mythr->id;
struct cgpu_info *cgpu = mythr->cgpu;
struct device_api *api = cgpu->api;
struct device_drv *drv = cgpu->drv;
struct cgminer_stats *dev_stats = &(cgpu->cgminer_stats);
struct cgminer_stats *pool_stats;
struct timeval getwork_start;
@ -5306,7 +5369,7 @@ void *miner_thread(void *userdata) @@ -5306,7 +5369,7 @@ void *miner_thread(void *userdata)
const long cycle = opt_log_interval / 5 ? : 1;
struct timeval tv_start, tv_end, tv_workstart, tv_lastupdate;
struct timeval diff, sdiff, wdiff = {0, 0};
uint32_t max_nonce = api->can_limit_work ? api->can_limit_work(mythr) : 0xffffffff;
uint32_t max_nonce = drv->can_limit_work ? drv->can_limit_work(mythr) : 0xffffffff;
int64_t hashes_done = 0;
int64_t hashes;
struct work *work;
@ -5320,7 +5383,7 @@ void *miner_thread(void *userdata) @@ -5320,7 +5383,7 @@ void *miner_thread(void *userdata)
gettimeofday(&getwork_start, NULL);
if (api->thread_init && !api->thread_init(mythr)) {
if (drv->thread_init && !drv->thread_init(mythr)) {
dev_error(cgpu, REASON_THREAD_FAIL_INIT);
goto out;
}
@ -5340,7 +5403,7 @@ void *miner_thread(void *userdata) @@ -5340,7 +5403,7 @@ void *miner_thread(void *userdata)
gettimeofday(&tv_workstart, NULL);
work->blk.nonce = 0;
cgpu->max_hashes = 0;
if (api->prepare_work && !api->prepare_work(mythr, work)) {
if (drv->prepare_work && !drv->prepare_work(mythr, work)) {
applog(LOG_ERR, "work prepare failed, exiting "
"mining thread %d", thr_id);
break;
@ -5382,16 +5445,16 @@ void *miner_thread(void *userdata) @@ -5382,16 +5445,16 @@ void *miner_thread(void *userdata)
gettimeofday(&(work->tv_work_start), NULL);
thread_reportin(mythr);
hashes = api->scanhash(mythr, work, work->blk.nonce + max_nonce);
hashes = drv->scanhash(mythr, work, work->blk.nonce + max_nonce);
thread_reportin(mythr);
gettimeofday(&getwork_start, NULL);
if (unlikely(hashes == -1)) {
applog(LOG_ERR, "%s %d failure, disabling!", api->name, cgpu->device_id);
applog(LOG_ERR, "%s %d failure, disabling!", drv->name, cgpu->device_id);
cgpu->deven = DEV_DISABLED;
dev_error(cgpu, REASON_THREAD_ZERO_HASH);
mt_disable(mythr, thr_id, api);
mt_disable(mythr, thr_id, drv);
}
hashes_done += hashes;
@ -5412,7 +5475,7 @@ void *miner_thread(void *userdata) @@ -5412,7 +5475,7 @@ void *miner_thread(void *userdata)
if (unlikely((long)sdiff.tv_sec < cycle)) {
int mult;
if (likely(!api->can_limit_work || max_nonce == 0xffffffff))
if (likely(!drv->can_limit_work || max_nonce == 0xffffffff))
continue;
mult = 1000000 / ((sdiff.tv_usec + 0x400) / 0x400) + 0x10;
@ -5421,9 +5484,9 @@ void *miner_thread(void *userdata) @@ -5421,9 +5484,9 @@ void *miner_thread(void *userdata)
max_nonce = 0xffffffff;
else
max_nonce = (max_nonce * mult) / 0x400;
} else if (unlikely(sdiff.tv_sec > cycle) && api->can_limit_work)
} else if (unlikely(sdiff.tv_sec > cycle) && drv->can_limit_work)
max_nonce = max_nonce * cycle / sdiff.tv_sec;
else if (unlikely(sdiff.tv_usec > 100000) && api->can_limit_work)
else if (unlikely(sdiff.tv_usec > 100000) && drv->can_limit_work)
max_nonce = max_nonce * 0x400 / (((cycle * 1000000) + sdiff.tv_usec) / (cycle * 1000000 / 0x400));
timersub(&tv_end, &tv_lastupdate, &diff);
@ -5449,7 +5512,7 @@ void *miner_thread(void *userdata) @@ -5449,7 +5512,7 @@ void *miner_thread(void *userdata)
}
if (unlikely(mythr->pause || cgpu->deven != DEV_ENABLED))
mt_disable(mythr, thr_id, api);
mt_disable(mythr, thr_id, drv);
sdiff.tv_sec = sdiff.tv_usec = 0;
} while (!abandon_work(work, &wdiff, cgpu->max_hashes));
@ -5457,8 +5520,8 @@ void *miner_thread(void *userdata) @@ -5457,8 +5520,8 @@ void *miner_thread(void *userdata)
}
out:
if (api->thread_shutdown)
api->thread_shutdown(mythr);
if (drv->thread_shutdown)
drv->thread_shutdown(mythr);
thread_reportin(mythr);
applog(LOG_ERR, "Thread %d failure, exiting", thr_id);
@ -5686,8 +5749,8 @@ out: @@ -5686,8 +5749,8 @@ out:
void reinit_device(struct cgpu_info *cgpu)
{
if (cgpu->api->reinit_device)
cgpu->api->reinit_device(cgpu);
if (cgpu->drv->reinit_device)
cgpu->drv->reinit_device(cgpu);
}
static struct timeval rotate_tv;
@ -5829,12 +5892,10 @@ static void *watchdog_thread(void __maybe_unused *userdata) @@ -5829,12 +5892,10 @@ static void *watchdog_thread(void __maybe_unused *userdata)
applog(LOG_WARNING, "Will restart execution as scheduled at %02d:%02d",
schedstart.tm.tm_hour, schedstart.tm.tm_min);
sched_paused = true;
for (i = 0; i < mining_threads; i++) {
struct thr_info *thr;
thr = &thr_info[i];
thr->pause = true;
}
mutex_lock(&mining_thr_lock);
for (i = 0; i < mining_threads; i++)
mining_thr[i]->pause = true;
mutex_unlock(&mining_thr_lock);
} else if (sched_paused && should_run()) {
applog(LOG_WARNING, "Restarting execution as per start time %02d:%02d scheduled",
schedstart.tm.tm_hour, schedstart.tm.tm_min);
@ -5845,7 +5906,10 @@ static void *watchdog_thread(void __maybe_unused *userdata) @@ -5845,7 +5906,10 @@ static void *watchdog_thread(void __maybe_unused *userdata)
for (i = 0; i < mining_threads; i++) {
struct thr_info *thr;
thr = &thr_info[i];
mutex_lock(&mining_thr_lock);
thr = mining_thr[i];
mutex_unlock(&mining_thr_lock);
/* Don't touch disabled devices */
if (thr->cgpu->deven == DEV_DISABLED)
@ -5862,12 +5926,12 @@ static void *watchdog_thread(void __maybe_unused *userdata) @@ -5862,12 +5926,12 @@ static void *watchdog_thread(void __maybe_unused *userdata)
char dev_str[8];
int gpu;
if (cgpu->api->get_stats)
cgpu->api->get_stats(cgpu);
if (cgpu->drv->get_stats)
cgpu->drv->get_stats(cgpu);
gpu = cgpu->device_id;
denable = &cgpu->deven;
sprintf(dev_str, "%s%d", cgpu->api->name, gpu);
sprintf(dev_str, "%s%d", cgpu->drv->name, gpu);
#ifdef HAVE_ADL
if (adl_active && cgpu->has_adl)
@ -5887,7 +5951,7 @@ static void *watchdog_thread(void __maybe_unused *userdata) @@ -5887,7 +5951,7 @@ static void *watchdog_thread(void __maybe_unused *userdata)
continue;
#ifdef WANT_CPUMINE
if (!strcmp(cgpu->api->dname, "cpu"))
if (cgpu->drv->drv == DRIVER_CPU)
continue;
#endif
if (cgpu->status != LIFE_WELL && (now.tv_sec - thr->last.tv_sec < WATCHDOG_SICK_TIME)) {
@ -5944,7 +6008,7 @@ static void log_print_status(struct cgpu_info *cgpu) @@ -5944,7 +6008,7 @@ static void log_print_status(struct cgpu_info *cgpu)
applog(LOG_WARNING, "%s", logline);
}
static void print_summary(void)
void print_summary(void)
{
struct timeval diff;
int hours, mins, secs, i;
@ -6277,26 +6341,27 @@ void enable_curses(void) { @@ -6277,26 +6341,27 @@ void enable_curses(void) {
/* TODO: fix need a dummy CPU device_api even if no support for CPU mining */
#ifndef WANT_CPUMINE
struct device_api cpu_api;
struct device_api cpu_api = {
struct device_drv cpu_drv;
struct device_drv cpu_drv = {
.drv = DRIVER_CPU,
.name = "CPU",
};
#endif
#ifdef USE_BITFORCE
extern struct device_api bitforce_api;
extern struct device_drv bitforce_drv;
#endif
#ifdef USE_ICARUS
extern struct device_api icarus_api;
extern struct device_drv icarus_drv;
#endif
#ifdef USE_MODMINER
extern struct device_api modminer_api;
extern struct device_drv modminer_drv;
#endif
#ifdef USE_ZTEX
extern struct device_api ztex_api;
extern struct device_drv ztex_drv;
#endif
@ -6311,7 +6376,7 @@ void enable_device(struct cgpu_info *cgpu) @@ -6311,7 +6376,7 @@ void enable_device(struct cgpu_info *cgpu)
adj_width(mining_threads, &dev_width);
#endif
#ifdef HAVE_OPENCL
if (cgpu->api == &opencl_api) {
if (cgpu->drv->drv == DRIVER_OPENCL) {
gpu_threads += cgpu->threads;
}
#endif
@ -6328,12 +6393,12 @@ bool add_cgpu(struct cgpu_info*cgpu) @@ -6328,12 +6393,12 @@ bool add_cgpu(struct cgpu_info*cgpu)
static struct _cgpu_devid_counter *devids = NULL;
struct _cgpu_devid_counter *d;
HASH_FIND_STR(devids, cgpu->api->name, d);
HASH_FIND_STR(devids, cgpu->drv->name, d);
if (d)
cgpu->device_id = ++d->lastid;
else {
d = malloc(sizeof(*d));
memcpy(d->name, cgpu->api->name, sizeof(d->name));
memcpy(d->name, cgpu->drv->name, sizeof(d->name));
cgpu->device_id = d->lastid = 0;
HASH_ADD_STR(devids, name, d);
}
@ -6342,6 +6407,21 @@ bool add_cgpu(struct cgpu_info*cgpu) @@ -6342,6 +6407,21 @@ bool add_cgpu(struct cgpu_info*cgpu)
return true;
}
struct device_drv *copy_drv(struct device_drv *drv)
{
struct device_drv *copy;
char buf[100];
if (unlikely(!(copy = malloc(sizeof(*copy))))) {
sprintf(buf, "Failed to allocate device_drv copy of %s (%s)",
drv->name, drv->copy ? "copy" : "original");
quit(1, buf);
}
memcpy(copy, drv, sizeof(*copy));
copy->copy = true;
return copy;
}
int main(int argc, char *argv[])
{
bool pools_active = false;
@ -6382,6 +6462,7 @@ int main(int argc, char *argv[]) @@ -6382,6 +6462,7 @@ int main(int argc, char *argv[])
mutex_init(&sshare_lock);
rwlock_init(&blk_lock);
rwlock_init(&netacc_lock);
mutex_init(&mining_thr_lock);
mutex_init(&lp_lock);
if (unlikely(pthread_cond_init(&lp_cond, NULL)))
@ -6551,32 +6632,32 @@ int main(int argc, char *argv[]) @@ -6551,32 +6632,32 @@ int main(int argc, char *argv[])
#ifdef HAVE_OPENCL
if (!opt_nogpu)
opencl_api.api_detect();
opencl_drv.drv_detect();
gpu_threads = 0;
#endif
#ifdef USE_ICARUS
if (!opt_scrypt)
icarus_api.api_detect();
icarus_drv.drv_detect();
#endif
#ifdef USE_BITFORCE
if (!opt_scrypt)
bitforce_api.api_detect();
bitforce_drv.drv_detect();
#endif
#ifdef USE_MODMINER
if (!opt_scrypt)
modminer_api.api_detect();
modminer_drv.drv_detect();
#endif
#ifdef USE_ZTEX
if (!opt_scrypt)
ztex_api.api_detect();
ztex_drv.drv_detect();
#endif
#ifdef WANT_CPUMINE
cpu_api.api_detect();
cpu_drv.drv_detect();
#endif
if (devices_enabled == -1) {
@ -6584,9 +6665,9 @@ int main(int argc, char *argv[]) @@ -6584,9 +6665,9 @@ int main(int argc, char *argv[])
for (i = 0; i < total_devices; ++i) {
struct cgpu_info *cgpu = devices[i];
if (cgpu->name)
applog(LOG_ERR, " %2d. %s %d: %s (driver: %s)", i, cgpu->api->name, cgpu->device_id, cgpu->name, cgpu->api->dname);
applog(LOG_ERR, " %2d. %s %d: %s (driver: %s)", i, cgpu->drv->name, cgpu->device_id, cgpu->name, cgpu->drv->dname);
else
applog(LOG_ERR, " %2d. %s %d (driver: %s)", i, cgpu->api->name, cgpu->device_id, cgpu->api->dname);
applog(LOG_ERR, " %2d. %s %d (driver: %s)", i, cgpu->drv->name, cgpu->device_id, cgpu->drv->dname);
}
quit(0, "%d devices listed", total_devices);
}
@ -6600,7 +6681,7 @@ int main(int argc, char *argv[]) @@ -6600,7 +6681,7 @@ int main(int argc, char *argv[])
enable_device(devices[i]);
} else if (i < total_devices) {
if (opt_removedisabled) {
if (devices[i]->api == &cpu_api)
if (devices[i]->drv->drv == DRIVER_CPU)
--opt_n_threads;
} else {
enable_device(devices[i]);
@ -6666,14 +6747,23 @@ int main(int argc, char *argv[]) @@ -6666,14 +6747,23 @@ int main(int argc, char *argv[])
fork_monitor();
#endif // defined(unix)
total_threads = mining_threads + 7;
thr_info = calloc(total_threads, sizeof(*thr));
if (!thr_info)
quit(1, "Failed to calloc thr_info");
mining_thr = calloc(mining_threads, sizeof(thr));
if (!mining_thr)
quit(1, "Failed to calloc mining_thr");
for (i = 0; i < mining_threads; i++) {
mining_thr[i] = calloc(1, sizeof(*thr));
if (!mining_thr[i])
quit(1, "Failed to calloc mining_thr[%d]", i);
}
total_control_threads = 7;
control_thr = calloc(total_control_threads, sizeof(*thr));
if (!control_thr)
quit(1, "Failed to calloc control_thr");
gwsched_thr_id = mining_threads;
stage_thr_id = mining_threads + 1;
thr = &thr_info[stage_thr_id];
gwsched_thr_id = 0;
stage_thr_id = 1;
thr = &control_thr[stage_thr_id];
thr->q = tq_new();
if (!thr->q)
quit(1, "Failed to tq_new");
@ -6765,14 +6855,16 @@ begin_bench: @@ -6765,14 +6855,16 @@ begin_bench:
cgpu->status = LIFE_INIT;
for (j = 0; j < cgpu->threads; ++j, ++k) {
thr = &thr_info[k];
mutex_lock(&mining_thr_lock);
thr = mining_thr[k];
mutex_unlock(&mining_thr_lock);
thr->id = k;
thr->cgpu = cgpu;
thr->device_thread = j;
thr->q = tq_new();
if (!thr->q)
quit(1, "tq_new failed in starting %s%d mining thread (#%d)", cgpu->api->name, cgpu->device_id, i);
quit(1, "tq_new failed in starting %s%d mining thread (#%d)", cgpu->drv->name, cgpu->device_id, i);
/* Enable threads for devices set not to mine but disable
* their queue in case we wish to enable them later */
@ -6782,7 +6874,7 @@ begin_bench: @@ -6782,7 +6874,7 @@ begin_bench:
tq_push(thr->q, &ping);
}
if (cgpu->api->thread_prepare && !cgpu->api->thread_prepare(thr))
if (cgpu->drv->thread_prepare && !cgpu->drv->thread_prepare(thr))
continue;
thread_reportout(thr);
@ -6810,15 +6902,15 @@ begin_bench: @@ -6810,15 +6902,15 @@ begin_bench:
gettimeofday(&total_tv_start, NULL);
gettimeofday(&total_tv_end, NULL);
watchpool_thr_id = mining_threads + 2;
thr = &thr_info[watchpool_thr_id];
watchpool_thr_id = 2;
thr = &control_thr[watchpool_thr_id];
/* start watchpool thread */
if (thr_info_create(thr, NULL, watchpool_thread, NULL))
quit(1, "watchpool thread create failed");
pthread_detach(thr->pth);
watchdog_thr_id = mining_threads + 3;
thr = &thr_info[watchdog_thr_id];
watchdog_thr_id = 3;
thr = &control_thr[watchdog_thr_id];
/* start watchdog thread */
if (thr_info_create(thr, NULL, watchdog_thread, NULL))
quit(1, "watchdog thread create failed");
@ -6826,8 +6918,8 @@ begin_bench: @@ -6826,8 +6918,8 @@ begin_bench:
#ifdef HAVE_OPENCL
/* Create reinit gpu thread */
gpur_thr_id = mining_threads + 4;
thr = &thr_info[gpur_thr_id];
gpur_thr_id = 4;
thr = &control_thr[gpur_thr_id];
thr->q = tq_new();
if (!thr->q)
quit(1, "tq_new failed for gpur_thr_id");
@ -6836,8 +6928,8 @@ begin_bench: @@ -6836,8 +6928,8 @@ begin_bench:
#endif
/* Create API socket thread */
api_thr_id = mining_threads + 5;
thr = &thr_info[api_thr_id];
api_thr_id = 5;
thr = &control_thr[api_thr_id];
if (thr_info_create(thr, NULL, api_thread, thr))
quit(1, "API thread create failed");
@ -6845,13 +6937,17 @@ begin_bench: @@ -6845,13 +6937,17 @@ begin_bench:
/* Create curses input thread for keyboard input. Create this last so
* that we know all threads are created since this can call kill_work
* to try and shut down ll previous threads. */
input_thr_id = mining_threads + 6;
thr = &thr_info[input_thr_id];
input_thr_id = 6;
thr = &control_thr[input_thr_id];
if (thr_info_create(thr, NULL, input_thread, thr))
quit(1, "input thread create failed");
pthread_detach(thr->pth);
#endif
/* Just to be sure */
if (total_control_threads != 7)
quit(1, "incorrect total_control_threads (%d) should be 7", total_control_threads);
/* Once everything is set up, main() becomes the getwork scheduler */
while (42) {
int ts, max_staged = opt_queue;

7
configure.ac

@ -273,6 +273,7 @@ fi @@ -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 @@ -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]) @@ -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 @@ -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

666
driver-bitforce.c

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
/*
* Copyright 2012-2013 Andrew Smith
* Copyright 2012 Luke Dashjr
* Copyright 2012 Con Kolivas
*
@ -19,34 +20,35 @@ @@ -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 { @@ -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)
{
do {
buf[0] = '\0';
--bufLen;
} while (likely(bufLen && read(fd, buf, 1) == 1 && (buf++)[0] != '\n'));
// 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
buf[0] = '\0';
}
static const char *blank = "";
struct device_drv bitforce_drv;
static ssize_t BFwrite(int fd, const void *buf, ssize_t bufLen)
static void bitforce_initialise(struct cgpu_info *bitforce, bool lock)
{
if ((bufLen) != write(fd, buf, bufLen))
return 0;
else
return bufLen;
}
int err;
#define BFclose(fd) close(fd)
if (lock)
mutex_lock(&bitforce->device_mutex);
static bool bitforce_detect_one(const char *devpath)
// 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 bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devices *found)
{
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;
}
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;
}
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);
}
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;
goto unshin;
}
buf[amount] = '\0';
BFclose(fdDev);
if (unlikely(!strstr(pdevbuf, "SHA256"))) {
applog(LOG_ERR, "BFL: Didn't recognise BitForce on %s", devpath);
return false;
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) @@ -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);
}
mutex_init(&bitforce->device_mutex);
return add_cgpu(bitforce);
}
bitforce->device_path = strdup(devpath);
#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)
if (!add_cgpu(bitforce))
goto 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;
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);
update_usb_stats(bitforce);
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);
mutex_init(&bitforce->device_mutex);
buf = alloca(65 * numDevs);
bufptrs = alloca(sizeof(*bufptrs) * (numDevs + 1));
return true;
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;
}
unshin:
for (i = numDevs; i > 0; ) {
--i;
bufptrs[i][64] = '\0';
usb_uninit(bitforce);
if (!(strstr(bufptrs[i], "BitFORCE") && strstr(bufptrs[i], "SHA256")))
continue;
shin:
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;
free(bitforce->device_path);
sprintf(devpathnum, "%d", (int)lComPortNumber);
if (bitforce->name != blank)
free(bitforce->name);
if (bitforce_detect_one(devpath))
++found;
}
if (bitforce->drv->copy)
free(bitforce->drv);
out:
dlclose(dll);
return found;
}
#else
static int bitforce_autodetect_ftdi(void)
{
return 0;
}
#endif
free(bitforce);
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);
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) @@ -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,18 +333,21 @@ static void bitforce_flash_led(struct cgpu_info *bitforce) @@ -353,18 +333,21 @@ 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);
/* Once we've tried - don't do it until told to again */
bitforce->flash_led = false;
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 */
sleep(4);
}
/* Once we've tried - don't do it until told to again */
bitforce->flash_led = false;
mutex_unlock(&bitforce->device_mutex);
@ -373,11 +356,12 @@ static void bitforce_flash_led(struct cgpu_info *bitforce) @@ -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) @@ -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);
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 (unlikely(!pdevbuf[0])) {
applog(LOG_ERR, "BFL%i: Error: Get temp returned empty string/timed out", bitforce->device_id);
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;
}
if ((!strncasecmp(pdevbuf, "TEMP", 4)) && (s = strchr(pdevbuf + 4, ':'))) {
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) @@ -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) @@ -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) @@ -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: @@ -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: @@ -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: @@ -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) @@ -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) @@ -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) @@ -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_ @@ -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_ @@ -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) @@ -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) @@ -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 = 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,

9
driver-cpu.c

@ -758,7 +758,7 @@ static void cpu_detect() @@ -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() @@ -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: @@ -843,10 +843,11 @@ CPUSearch:
return last_nonce - first_nonce + 1;
}
struct device_api cpu_api = {
struct device_drv cpu_drv = {
.drv = 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,

2
driver-cpu.h

@ -53,7 +53,7 @@ enum sha256_algos { @@ -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);

19
driver-icarus.c

@ -208,7 +208,7 @@ static struct ICARUS_INFO **icarus_info; @@ -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) @@ -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) @@ -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, @@ -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, @@ -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, @@ -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) @@ -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 = 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,

182
driver-modminer.c

@ -1,5 +1,5 @@ @@ -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 @@ @@ -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) @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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: @@ -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: @@ -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) @@ -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, @@ -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, @@ -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 @@ -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 @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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);
@ -599,6 +627,7 @@ static bool modminer_fpga_prepare(struct thr_info *thr) @@ -599,6 +627,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 +641,10 @@ static const char *modminer_delta_clock(struct thr_info *thr, int delta, bool te @@ -612,6 +641,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 +686,7 @@ static const char *modminer_delta_clock(struct thr_info *thr, int delta, bool te @@ -653,7 +686,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 +695,7 @@ static const char *modminer_delta_clock(struct thr_info *thr, int delta, bool te @@ -662,7 +695,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 +703,7 @@ static const char *modminer_delta_clock(struct thr_info *thr, int delta, bool te @@ -670,7 +703,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 +724,7 @@ static bool modminer_fpga_init(struct thr_info *thr) @@ -691,7 +724,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 +733,14 @@ static bool modminer_fpga_init(struct thr_info *thr) @@ -700,14 +733,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 +750,7 @@ static bool modminer_fpga_init(struct thr_info *thr) @@ -717,7 +750,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;
@ -767,13 +800,10 @@ static bool modminer_start_work(struct thr_info *thr) @@ -767,13 +800,10 @@ 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
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;
}
@ -799,6 +829,10 @@ static void check_temperature(struct thr_info *thr) @@ -799,6 +829,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 +861,14 @@ static void check_temperature(struct thr_info *thr) @@ -827,14 +861,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 +876,7 @@ static void check_temperature(struct thr_info *thr) @@ -842,7 +876,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()
@ -883,6 +917,10 @@ static uint64_t modminer_process_results(struct thr_info *thr) @@ -883,6 +917,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
@ -896,9 +934,6 @@ static uint64_t modminer_process_results(struct thr_info *thr) @@ -896,9 +934,6 @@ static uint64_t modminer_process_results(struct thr_info *thr)
while (1) {
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
@ -909,7 +944,7 @@ static uint64_t modminer_process_results(struct thr_info *thr) @@ -909,7 +944,7 @@ static uint64_t modminer_process_results(struct thr_info *thr)
}
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 +971,7 @@ static uint64_t modminer_process_results(struct thr_info *thr) @@ -936,7 +971,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 +1010,7 @@ static uint64_t modminer_process_results(struct thr_info *thr) @@ -975,7 +1010,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 +1020,7 @@ static uint64_t modminer_process_results(struct thr_info *thr) @@ -985,7 +1020,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;
}
@ -1045,6 +1080,10 @@ static int64_t modminer_scanhash(struct thr_info *thr, struct work *work, int64_ @@ -1045,6 +1080,10 @@ static int64_t modminer_scanhash(struct thr_info *thr, struct work *work, int64_
bool startwork;
struct timeval tv1, tv2;
// Device is gone
if (thr->cgpu->usbinfo.nodev)
return -1;
// Don't start new work if overheated
if (state->overheated == true) {
gettimeofday(&tv1, NULL);
@ -1054,6 +1093,10 @@ static int64_t modminer_scanhash(struct thr_info *thr, struct work *work, int64_ @@ -1054,6 +1093,10 @@ static int64_t modminer_scanhash(struct thr_info *thr, struct work *work, int64_
while (state->overheated == true) {
check_temperature(thr);
// Device is gone
if (thr->cgpu->usbinfo.nodev)
return -1;
if (state->overheated == true) {
gettimeofday(&tv2, NULL);
@ -1141,10 +1184,11 @@ static char *modminer_set_device(struct cgpu_info *modminer, char *option, char @@ -1141,10 +1184,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 = 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,

70
driver-opencl.c

@ -50,24 +50,24 @@ extern int gpur_thr_id; @@ -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) @@ -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,7 +616,11 @@ void pause_dynamic_threads(int gpu) @@ -624,7 +616,11 @@ 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;
mutex_lock(&mining_thr_lock);
thr = mining_thr[i];
mutex_unlock(&mining_thr_lock);
if (!thr->pause && cgpu->dynamic) {
applog(LOG_WARNING, "Disabling extra threads due to dynamic mode.");
@ -637,9 +633,6 @@ void pause_dynamic_threads(int gpu) @@ -637,9 +633,6 @@ void pause_dynamic_threads(int gpu)
}
}
struct device_api opencl_api;
#endif /* HAVE_OPENCL */
#if defined(HAVE_OPENCL) && defined(HAVE_CURSES)
@ -716,7 +709,9 @@ retry: @@ -716,7 +709,9 @@ retry:
else
wlog("%d\n", gpus[gpu].intensity);
for (i = 0; i < mining_threads; i++) {
thr = &thr_info[i];
mutex_lock(&mining_thr_lock);
thr = mining_thr[i];
mutex_unlock(&mining_thr_lock);
if (thr->cgpu != cgpu)
continue;
get_datestamp(checkin, &thr->last);
@ -771,9 +766,11 @@ retry: @@ -771,9 +766,11 @@ retry:
}
gpus[selected].deven = DEV_ENABLED;
for (i = 0; i < mining_threads; ++i) {
thr = &thr_info[i];
mutex_lock(&mining_thr_lock);
thr = mining_thr[i];
mutex_unlock(&mining_thr_lock);
cgpu = thr->cgpu;
if (cgpu->api != &opencl_api)
if (cgpu->drv->drv != DRIVER_OPENCL)
continue;
if (dev_from_id(i) != selected)
continue;
@ -1158,14 +1155,18 @@ select_cgpu: @@ -1158,14 +1155,18 @@ select_cgpu:
gpu = cgpu->device_id;
for (thr_id = 0; thr_id < mining_threads; ++thr_id) {
thr = &thr_info[thr_id];
mutex_lock(&mining_thr_lock);
thr = mining_thr[thr_id];
mutex_unlock(&mining_thr_lock);
cgpu = thr->cgpu;
if (cgpu->api != &opencl_api)
if (cgpu->drv->drv != DRIVER_OPENCL)
continue;
if (dev_from_id(thr_id) != gpu)
continue;
thr = &thr_info[thr_id];
mutex_lock(&mining_thr_lock);
thr = mining_thr[thr_id];
mutex_unlock(&mining_thr_lock);
if (!thr) {
applog(LOG_WARNING, "No reference to thread %d exists", thr_id);
continue;
@ -1183,9 +1184,11 @@ select_cgpu: @@ -1183,9 +1184,11 @@ select_cgpu:
for (thr_id = 0; thr_id < mining_threads; ++thr_id) {
int virtual_gpu;
thr = &thr_info[thr_id];
mutex_lock(&mining_thr_lock);
thr = mining_thr[thr_id];
mutex_unlock(&mining_thr_lock);
cgpu = thr->cgpu;
if (cgpu->api != &opencl_api)
if (cgpu->drv->drv != DRIVER_OPENCL)
continue;
if (dev_from_id(thr_id) != gpu)
continue;
@ -1220,9 +1223,11 @@ select_cgpu: @@ -1220,9 +1223,11 @@ select_cgpu:
get_datestamp(cgpu->init, &now);
for (thr_id = 0; thr_id < mining_threads; ++thr_id) {
thr = &thr_info[thr_id];
mutex_lock(&mining_thr_lock);
thr = mining_thr[thr_id];
mutex_unlock(&mining_thr_lock);
cgpu = thr->cgpu;
if (cgpu->api != &opencl_api)
if (cgpu->drv->drv != DRIVER_OPENCL)
continue;
if (dev_from_id(thr_id) != gpu)
continue;
@ -1243,8 +1248,6 @@ void *reinit_gpu(__maybe_unused void *userdata) @@ -1243,8 +1248,6 @@ void *reinit_gpu(__maybe_unused void *userdata)
#ifdef HAVE_OPENCL
struct device_api opencl_api;
static void opencl_detect()
{
int i;
@ -1263,7 +1266,7 @@ static void opencl_detect() @@ -1263,7 +1266,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 +1279,7 @@ static void opencl_detect() @@ -1276,7 +1279,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
@ -1570,10 +1573,11 @@ static void opencl_thread_shutdown(struct thr_info *thr) @@ -1570,10 +1573,11 @@ static void opencl_thread_shutdown(struct thr_info *thr)
clReleaseContext(clState->context);
}
struct device_api opencl_api = {
struct device_drv opencl_drv = {
.drv = 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,

2
driver-opencl.h

@ -30,6 +30,6 @@ extern void pause_dynamic_threads(int gpu); @@ -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__ */

10
driver-ztex.c

@ -30,7 +30,7 @@ @@ -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) @@ -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) @@ -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;
@ -394,10 +394,10 @@ static void ztex_disable(struct thr_info *thr) @@ -394,10 +394,10 @@ static void ztex_disable(struct thr_info *thr)
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,

2
findnonce.c

@ -204,7 +204,7 @@ static void *postcalc_hash(void *userdata) @@ -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

@ -104,14 +104,14 @@ int serial_autodetect_devserial(__maybe_unused detectone_func_t detectone, __may @@ -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_ @@ -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

@ -16,13 +16,13 @@ @@ -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);

44
miner.h

@ -114,7 +114,7 @@ static inline int fsync (int fd) @@ -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) @@ -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,
@ -263,12 +272,14 @@ struct api_data; @@ -263,12 +272,14 @@ struct api_data;
struct thr_info;
struct work;
struct device_api {
struct device_drv {
enum drv_driver drv;
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 +299,13 @@ struct device_api { @@ -288,8 +299,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 +375,15 @@ struct cgminer_pool_stats { @@ -359,13 +375,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 +392,17 @@ struct cgpu_info { @@ -374,13 +392,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 +737,7 @@ extern pthread_mutex_t cgusb_lock; @@ -715,6 +737,7 @@ 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 restart_lock;
extern pthread_cond_t restart_cond;
@ -739,6 +762,7 @@ extern void api(int thr_id); @@ -739,6 +762,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);
@ -761,7 +785,8 @@ extern int num_processors; @@ -761,7 +785,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
@ -920,6 +945,7 @@ struct pool { @@ -920,6 +945,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;
@ -1056,6 +1082,8 @@ extern void kill_work(void); @@ -1056,6 +1082,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);

251
miner.php

@ -8,7 +8,7 @@ global $checklastshare, $poolinputs, $hidefields; @@ -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'; @@ -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( @@ -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( @@ -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(); @@ -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) @@ -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')."} @@ -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( @@ -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) @@ -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) @@ -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) @@ -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) @@ -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() @@ -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,6 +1597,8 @@ function pagebuttons($rig, $pg) @@ -1557,6 +1597,8 @@ function pagebuttons($rig, $pg)
}
echo '<tr><td><table cellpadding=0 cellspacing=0 border=0><tr><td nowrap>';
if ($userlist === null || isset($_SESSION[$ses]))
{
if ($prev !== null)
echo riginput($prev, 'Prev').'&nbsp;';
echo "<input type=button value='Refresh' onclick='pr(\"$refresh\",null)'>&nbsp;";
@ -1565,10 +1607,23 @@ function pagebuttons($rig, $pg) @@ -1565,10 +1607,23 @@ function pagebuttons($rig, $pg)
echo '&nbsp;';
if (count($rigs) > 1)
echo "<input type=button value='Summary' onclick='pr(\"\",null)'>&nbsp;";
}
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)'>&nbsp;";
}
echo '</td><td width=100%>&nbsp;</td><td nowrap>';
if ($rig !== null && $readonly === false)
@ -1580,6 +1635,12 @@ function pagebuttons($rig, $pg) @@ -1580,6 +1635,12 @@ function pagebuttons($rig, $pg)
echo "&nbsp;<input type=button value='Quit' onclick='prc(\"quit&rig=$rig\",\"Quit CGMiner$rg\")'>";
}
refreshbuttons();
if (isset($_SESSION[$ses]))
echo "&nbsp;<input type=button value='Logout' onclick='pr(\"&logout=1\",null)'>";
else
if ($userlist !== null)
echo "&nbsp;<input type=button value='Login' onclick='pr(\"&login=1\",null)'>";
echo "</td></tr></table></td></tr>";
}
#
@ -2410,13 +2471,126 @@ function showcustompage($pagename) @@ -2410,13 +2471,126 @@ function showcustompage($pagename)
pagebuttons(null, $pagename);
}
#
function onlylogin()
{
global $here;
htmlhead(false, null, null, true);
?>
<tr height=15%><td>&nbsp;</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>&nbsp;</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,25 +2599,17 @@ function display() @@ -2425,25 +2599,17 @@ function display()
$autorefresh = intval($ref);
}
if ($pagesonly !== true)
{
$rig = trim(getparam('rig', true));
$arg = trim(getparam('arg', true));
$preprocess = null;
if ($arg != null and $arg != '')
{
$num = null;
if ($rig != null and $rig != '')
{
if ($rig >= 0 and $rig < count($rigs))
$num = $rig;
}
else
if (count($rigs) == 0)
$num = 0;
if ($num != null)
if ($rig != null and $rig != '' and $rig >= 0 and $rig < count($rigs))
{
$parts = explode(':', $rigs[$num], 3);
$parts = explode(':', $rigs[$rig], 3);
if (count($parts) >= 2)
{
$miner = $parts[0];
@ -2454,23 +2620,44 @@ function display() @@ -2454,23 +2620,44 @@ function display()
}
}
}
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);

714
usbutils.c

File diff suppressed because it is too large Load Diff

77
usbutils.h

@ -1,5 +1,5 @@ @@ -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 @@ @@ -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 { @@ -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 { @@ -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 { @@ -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,49 @@ enum usb_cmds { @@ -78,32 +110,49 @@ 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);
void release_cgpu(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 +166,10 @@ void usb_cleanup(); @@ -117,4 +166,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

33
util.c

@ -261,6 +261,30 @@ static void set_nettime(void) @@ -261,6 +261,30 @@ static void set_nettime(void)
wr_unlock(&netacc_lock);
}
static int curl_debug_cb(__maybe_unused CURL *handle, curl_infotype type,
__maybe_unused unsigned 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 +311,11 @@ json_t *json_rpc_call(CURL *curl, const char *url, @@ -287,10 +311,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)
// 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);
#endif
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_ENCODING, "");
@ -912,6 +937,7 @@ static bool __stratum_send(struct pool *pool, char *s, ssize_t len) @@ -912,6 +937,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 +1067,7 @@ char *recv_line(struct pool *pool) @@ -1041,6 +1067,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…
Cancel
Save