mirror of https://github.com/GOSTSec/sgminer
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1857 lines
50 KiB
1857 lines
50 KiB
/* |
|
* Copyright 2014 sgminer developers (see AUTHORS.md) |
|
* |
|
* 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 Software Foundation; either version 3 of the License, or (at |
|
* your option) any later version. See COPYING for more details. |
|
*/ |
|
|
|
/* TODO: four-space whitespace */ |
|
|
|
#include "configuration.h" |
|
|
|
/* Used in config parsing, e.g. pool array. */ |
|
static int json_array_index = -1; |
|
|
|
static int total_urls; |
|
|
|
static const char def_conf[] = "sgminer.conf"; |
|
static char *default_config; |
|
static int include_count; |
|
|
|
static struct pool *add_url(void) |
|
{ |
|
total_urls++; |
|
if (total_urls > total_pools) |
|
add_pool(); |
|
return pools[total_urls - 1]; |
|
} |
|
|
|
static void setup_url(struct pool *pool, char *arg) |
|
{ |
|
arg = get_proxy(arg, pool); |
|
|
|
if (detect_stratum(pool, arg)) |
|
return; |
|
|
|
opt_set_charp(arg, &pool->rpc_url); |
|
if (strncmp(arg, "http://", 7) && |
|
strncmp(arg, "https://", 8)) { |
|
char *httpinput; |
|
|
|
httpinput = (char *)malloc(255); |
|
if (!httpinput) |
|
quit(1, "Failed to malloc httpinput"); |
|
strcpy(httpinput, "http://"); |
|
strncat(httpinput, arg, 248); |
|
pool->rpc_url = httpinput; |
|
} |
|
} |
|
|
|
char *load_config(const char *arg, void __maybe_unused *unused) |
|
{ |
|
json_error_t err; |
|
json_t *config; |
|
char *json_error; |
|
size_t siz; |
|
|
|
if (!cnfbuf) |
|
cnfbuf = strdup(arg); |
|
|
|
if (++include_count > JSON_MAX_DEPTH) |
|
return JSON_MAX_DEPTH_ERR; |
|
|
|
#if JANSSON_MAJOR_VERSION > 1 |
|
config = json_load_file(arg, 0, &err); |
|
#else |
|
config = json_load_file(arg, &err); |
|
#endif |
|
if (!json_is_object(config)) { |
|
siz = JSON_LOAD_ERROR_LEN + strlen(arg) + strlen(err.text); |
|
json_error = (char *)malloc(siz); |
|
if (!json_error) |
|
quit(1, "Malloc failure in json error"); |
|
|
|
snprintf(json_error, siz, JSON_LOAD_ERROR, arg, err.text); |
|
return json_error; |
|
} |
|
|
|
config_loaded = true; |
|
|
|
/* Parse the config now, so we can override it. That can keep pointers |
|
* so don't free config object. */ |
|
return parse_config(config, true, -1); |
|
} |
|
|
|
char *parse_config(json_t *config, bool fileconf, int parent_iteration) |
|
{ |
|
static char err_buf[200]; |
|
struct opt_table *opt; |
|
json_t *val; |
|
|
|
json_array_index = parent_iteration; |
|
|
|
if (fileconf && !fileconf_load) |
|
fileconf_load = 1; |
|
|
|
for (opt = opt_config_table; opt->type != OPT_END; opt++) { |
|
char *p, *name; |
|
|
|
/* We don't handle subtables. */ |
|
assert(!(opt->type & OPT_SUBTABLE)); |
|
|
|
if (!opt->names) |
|
continue; |
|
|
|
/* Pull apart the option name(s). */ |
|
name = strdup(opt->names); |
|
for (p = strtok(name, "|"); p; p = strtok(NULL, "|")) { |
|
char *err = NULL; |
|
|
|
/* Ignore short options. */ |
|
if (p[1] != '-') |
|
continue; |
|
|
|
val = json_object_get(config, p+2); |
|
if (!val) |
|
continue; |
|
|
|
if ((opt->type & OPT_HASARG) && json_is_string(val)) { |
|
err = opt->cb_arg(json_string_value(val), |
|
opt->u.arg); |
|
} else if ((opt->type & OPT_HASARG) && json_is_array(val)) { |
|
size_t n, size = json_array_size(val); |
|
|
|
for (n = 0; n < size && !err; n++) { |
|
if (json_is_string(json_array_get(val, n))) |
|
err = opt->cb_arg(json_string_value(json_array_get(val, n)), opt->u.arg); |
|
else if (json_is_object(json_array_get(val, n))) |
|
{ |
|
err = parse_config(json_array_get(val, n), false, n); |
|
} |
|
} |
|
} else if ((opt->type & OPT_NOARG) && json_is_true(val)) |
|
err = opt->cb(opt->u.arg); |
|
else |
|
err = "Invalid value"; |
|
|
|
if (err) { |
|
/* Allow invalid values to be in configuration |
|
* file, just skipping over them provided the |
|
* JSON is still valid after that. */ |
|
if (fileconf) { |
|
applog(LOG_WARNING, "Skipping config option %s: %s", p, err); |
|
fileconf_load = -1; |
|
} else { |
|
snprintf(err_buf, sizeof(err_buf), "Error parsing JSON option %s: %s", |
|
p, err); |
|
return err_buf; |
|
} |
|
} |
|
} |
|
free(name); |
|
} |
|
|
|
val = json_object_get(config, JSON_INCLUDE_CONF); |
|
if (val && json_is_string(val)) |
|
return load_config(json_string_value(val), NULL); |
|
|
|
return NULL; |
|
} |
|
|
|
/* add a mutex if this needs to be thread safe in the future */ |
|
static struct JE { |
|
char *buf; |
|
struct JE *next; |
|
} *jedata = NULL; |
|
|
|
static void json_escape_free() |
|
{ |
|
struct JE *jeptr = jedata; |
|
struct JE *jenext; |
|
|
|
jedata = NULL; |
|
|
|
while (jeptr) { |
|
jenext = jeptr->next; |
|
free(jeptr->buf); |
|
free(jeptr); |
|
jeptr = jenext; |
|
} |
|
} |
|
|
|
static char *json_escape(char *str) |
|
{ |
|
struct JE *jeptr; |
|
char *buf, *ptr; |
|
|
|
/* 2x is the max, may as well just allocate that */ |
|
ptr = buf = (char *)malloc(strlen(str) * 2 + 1); |
|
|
|
jeptr = (struct JE *)malloc(sizeof(*jeptr)); |
|
|
|
jeptr->buf = buf; |
|
jeptr->next = jedata; |
|
jedata = jeptr; |
|
|
|
while (*str) { |
|
if (*str == '\\' || *str == '"') |
|
*(ptr++) = '\\'; |
|
|
|
*(ptr++) = *(str++); |
|
} |
|
|
|
*ptr = '\0'; |
|
|
|
return buf; |
|
} |
|
|
|
void write_config(FILE *fcfg) |
|
{ |
|
int i; |
|
|
|
/* Write pool values */ |
|
fputs("{\n\"pools\" : [", fcfg); |
|
for(i = 0; i < total_pools; i++) { |
|
struct pool *pool = pools[i]; |
|
|
|
/* Using get_pool_name() here is unsafe if opt_incognito is true. */ |
|
if (strcmp(pool->name, "") != 0) { |
|
fprintf(fcfg, "\n\t\t\"name\" : \"%s\",", json_escape(pool->name)); |
|
} |
|
if (strcmp(pool->description, "") != 0) { |
|
fprintf(fcfg, "\n\t\t\"description\" : \"%s\",", json_escape(pool->description)); |
|
} |
|
if (pool->quota != 1) { |
|
fprintf(fcfg, "%s\n\t{\n\t\t\"quota\" : \"%s%s%s%d;%s\",", i > 0 ? "," : "", |
|
pool->rpc_proxy ? json_escape((char *)proxytype(pool->rpc_proxytype)) : "", |
|
pool->rpc_proxy ? json_escape(pool->rpc_proxy) : "", |
|
pool->rpc_proxy ? "|" : "", |
|
pool->quota, |
|
json_escape(pool->rpc_url)); |
|
} else { |
|
fprintf(fcfg, "%s\n\t{\n\t\t\"url\" : \"%s%s%s%s\",", i > 0 ? "," : "", |
|
pool->rpc_proxy ? json_escape((char *)proxytype(pool->rpc_proxytype)) : "", |
|
pool->rpc_proxy ? json_escape(pool->rpc_proxy) : "", |
|
pool->rpc_proxy ? "|" : "", |
|
json_escape(pool->rpc_url)); |
|
} |
|
fprintf(fcfg, "\n\t\t\"user\" : \"%s\",", json_escape(pool->rpc_user)); |
|
fprintf(fcfg, "\n\t\t\"pass\" : \"%s\"\n\t}", json_escape(pool->rpc_pass)); |
|
} |
|
fputs("\n]\n", fcfg); |
|
|
|
/* Write only if there are usable GPUs */ |
|
if (nDevs) { |
|
fputs(",\n\"intensity\" : \"", fcfg); |
|
for(i = 0; i < nDevs; i++) |
|
fprintf(fcfg, gpus[i].dynamic ? "%sd" : "%s%d", i > 0 ? "," : "", gpus[i].intensity); |
|
|
|
fputs("\",\n\"xintensity\" : \"", fcfg); |
|
for(i = 0; i < nDevs; i++) |
|
fprintf(fcfg, "%s%d", i > 0 ? "," : "", gpus[i].xintensity); |
|
|
|
fputs("\",\n\"rawintensity\" : \"", fcfg); |
|
for(i = 0; i < nDevs; i++) |
|
fprintf(fcfg, "%s%d", i > 0 ? "," : "", gpus[i].rawintensity); |
|
|
|
/* All current kernels only support vector=1 */ |
|
/* fputs("\",\n\"vectors\" : \"", fcfg); */ |
|
/* for(i = 0; i < nDevs; i++) */ |
|
/* fprintf(fcfg, "%s%d", i > 0 ? "," : "", */ |
|
/* gpus[i].vwidth); */ |
|
|
|
fputs("\",\n\"worksize\" : \"", fcfg); |
|
for(i = 0; i < nDevs; i++) |
|
fprintf(fcfg, "%s%d", i > 0 ? "," : "", |
|
(int)gpus[i].work_size); |
|
|
|
fputs("\",\n\"kernel\" : \"", fcfg); |
|
for(i = 0; i < nDevs; i++) { |
|
fprintf(fcfg, "%s", i > 0 ? "," : ""); |
|
fprintf(fcfg, "%s", gpus[i].kernelname); |
|
} |
|
|
|
fputs("\",\n\"lookup-gap\" : \"", fcfg); |
|
for(i = 0; i < nDevs; i++) |
|
fprintf(fcfg, "%s%d", i > 0 ? "," : "", |
|
(int)gpus[i].opt_lg); |
|
|
|
fputs("\",\n\"thread-concurrency\" : \"", fcfg); |
|
for(i = 0; i < nDevs; i++) |
|
fprintf(fcfg, "%s%d", i > 0 ? "," : "", |
|
(int)gpus[i].opt_tc); |
|
|
|
fputs("\",\n\"shaders\" : \"", fcfg); |
|
for(i = 0; i < nDevs; i++) |
|
fprintf(fcfg, "%s%d", i > 0 ? "," : "", |
|
(int)gpus[i].shaders); |
|
|
|
fputs("\",\n\"gpu-threads\" : \"", fcfg); |
|
for(i = 0; i < nDevs; i++) |
|
fprintf(fcfg, "%s%d", i > 0 ? "," : "", |
|
(int)gpus[i].threads); |
|
|
|
#ifdef HAVE_ADL |
|
fputs("\",\n\"gpu-engine\" : \"", fcfg); |
|
for(i = 0; i < nDevs; i++) |
|
fprintf(fcfg, "%s%d-%d", i > 0 ? "," : "", gpus[i].min_engine, gpus[i].gpu_engine); |
|
|
|
fputs("\",\n\"gpu-fan\" : \"", fcfg); |
|
for(i = 0; i < nDevs; i++) |
|
fprintf(fcfg, "%s%d-%d", i > 0 ? "," : "", gpus[i].min_fan, gpus[i].gpu_fan); |
|
|
|
fputs("\",\n\"gpu-memclock\" : \"", fcfg); |
|
for(i = 0; i < nDevs; i++) |
|
fprintf(fcfg, "%s%d", i > 0 ? "," : "", gpus[i].gpu_memclock); |
|
|
|
fputs("\",\n\"gpu-memdiff\" : \"", fcfg); |
|
for(i = 0; i < nDevs; i++) |
|
fprintf(fcfg, "%s%d", i > 0 ? "," : "", gpus[i].gpu_memdiff); |
|
|
|
fputs("\",\n\"gpu-powertune\" : \"", fcfg); |
|
for(i = 0; i < nDevs; i++) |
|
fprintf(fcfg, "%s%d", i > 0 ? "," : "", gpus[i].gpu_powertune); |
|
|
|
fputs("\",\n\"gpu-vddc\" : \"", fcfg); |
|
for(i = 0; i < nDevs; i++) |
|
fprintf(fcfg, "%s%1.3f", i > 0 ? "," : "", gpus[i].gpu_vddc); |
|
|
|
fputs("\",\n\"temp-cutoff\" : \"", fcfg); |
|
for(i = 0; i < nDevs; i++) |
|
fprintf(fcfg, "%s%d", i > 0 ? "," : "", gpus[i].cutofftemp); |
|
|
|
fputs("\",\n\"temp-overheat\" : \"", fcfg); |
|
for(i = 0; i < nDevs; i++) |
|
fprintf(fcfg, "%s%d", i > 0 ? "," : "", gpus[i].adl.overtemp); |
|
|
|
fputs("\",\n\"temp-target\" : \"", fcfg); |
|
for(i = 0; i < nDevs; i++) |
|
fprintf(fcfg, "%s%d", i > 0 ? "," : "", gpus[i].adl.targettemp); |
|
#endif |
|
|
|
fputs("\"", fcfg); |
|
} |
|
#ifdef HAVE_ADL |
|
if (opt_reorder) |
|
fprintf(fcfg, ",\n\"gpu-reorder\" : true"); |
|
#endif |
|
|
|
/* Simple bool and int options */ |
|
struct opt_table *opt; |
|
for (opt = opt_config_table; opt->type != OPT_END; opt++) { |
|
char *p, *name = strdup(opt->names); |
|
for (p = strtok(name, "|"); p; p = strtok(NULL, "|")) { |
|
if (p[1] != '-') |
|
continue; |
|
if (opt->type & OPT_NOARG && |
|
((void *)opt->cb == (void *)opt_set_bool || (void *)opt->cb == (void *)opt_set_invbool) && |
|
(*(bool *)opt->u.arg == ((void *)opt->cb == (void *)opt_set_bool))) |
|
fprintf(fcfg, ",\n\"%s\" : true", p+2); |
|
|
|
if (opt->type & OPT_HASARG && |
|
((void *)opt->cb_arg == (void *)set_int_0_to_9999 || |
|
(void *)opt->cb_arg == (void *)set_int_1_to_65535 || |
|
(void *)opt->cb_arg == (void *)set_int_0_to_10 || |
|
(void *)opt->cb_arg == (void *)set_int_1_to_10) && opt->desc != opt_hidden) |
|
fprintf(fcfg, ",\n\"%s\" : \"%d\"", p+2, *(int *)opt->u.arg); |
|
} |
|
} |
|
|
|
/* Special case options */ |
|
fprintf(fcfg, ",\n\"shares\" : \"%d\"", opt_shares); |
|
if (pool_strategy == POOL_BALANCE) |
|
fputs(",\n\"balance\" : true", fcfg); |
|
if (pool_strategy == POOL_LOADBALANCE) |
|
fputs(",\n\"load-balance\" : true", fcfg); |
|
if (pool_strategy == POOL_ROUNDROBIN) |
|
fputs(",\n\"round-robin\" : true", fcfg); |
|
if (pool_strategy == POOL_ROTATE) |
|
fprintf(fcfg, ",\n\"rotate\" : \"%d\"", opt_rotate_period); |
|
#if defined(unix) || defined(__APPLE__) |
|
if (opt_stderr_cmd && *opt_stderr_cmd) |
|
fprintf(fcfg, ",\n\"monitor\" : \"%s\"", json_escape(opt_stderr_cmd)); |
|
#endif // defined(unix) |
|
if (opt_kernel_path && *opt_kernel_path) { |
|
char *kpath = strdup(opt_kernel_path); |
|
if (kpath[strlen(kpath)-1] == '/') |
|
kpath[strlen(kpath)-1] = 0; |
|
fprintf(fcfg, ",\n\"kernel-path\" : \"%s\"", json_escape(kpath)); |
|
} |
|
if (schedstart.enable) |
|
fprintf(fcfg, ",\n\"sched-time\" : \"%d:%d\"", schedstart.tm.tm_hour, schedstart.tm.tm_min); |
|
if (schedstop.enable) |
|
fprintf(fcfg, ",\n\"stop-time\" : \"%d:%d\"", schedstop.tm.tm_hour, schedstop.tm.tm_min); |
|
if (opt_socks_proxy && *opt_socks_proxy) |
|
fprintf(fcfg, ",\n\"socks-proxy\" : \"%s\"", json_escape(opt_socks_proxy)); |
|
if (opt_devs_enabled) { |
|
fprintf(fcfg, ",\n\"device\" : \""); |
|
bool extra_devs = false; |
|
|
|
for (i = 0; i < MAX_DEVICES; i++) { |
|
if (devices_enabled[i]) { |
|
int startd = i; |
|
|
|
if (extra_devs) |
|
fprintf(fcfg, ","); |
|
while (i < MAX_DEVICES && devices_enabled[i + 1]) |
|
++i; |
|
fprintf(fcfg, "%d", startd); |
|
if (i > startd) |
|
fprintf(fcfg, "-%d", i); |
|
} |
|
} |
|
fprintf(fcfg, "\""); |
|
} |
|
if (opt_removedisabled) |
|
fprintf(fcfg, ",\n\"remove-disabled\" : true"); |
|
if (strcmp(opt_algorithm->name, "scrypt") != 0) |
|
fprintf(fcfg, ",\n\"algorithm\" : \"%s\"", json_escape(opt_algorithm->name)); |
|
if (opt_api_allow) |
|
fprintf(fcfg, ",\n\"api-allow\" : \"%s\"", json_escape(opt_api_allow)); |
|
if (strcmp(opt_api_mcast_addr, API_MCAST_ADDR) != 0) |
|
fprintf(fcfg, ",\n\"api-mcast-addr\" : \"%s\"", json_escape(opt_api_mcast_addr)); |
|
if (strcmp(opt_api_mcast_code, API_MCAST_CODE) != 0) |
|
fprintf(fcfg, ",\n\"api-mcast-code\" : \"%s\"", json_escape(opt_api_mcast_code)); |
|
if (*opt_api_mcast_des) |
|
fprintf(fcfg, ",\n\"api-mcast-des\" : \"%s\"", json_escape(opt_api_mcast_des)); |
|
if (strcmp(opt_api_description, PACKAGE_STRING) != 0) |
|
fprintf(fcfg, ",\n\"api-description\" : \"%s\"", json_escape(opt_api_description)); |
|
if (opt_api_groups) |
|
fprintf(fcfg, ",\n\"api-groups\" : \"%s\"", json_escape(opt_api_groups)); |
|
|
|
fputs("\n}\n", fcfg); |
|
|
|
json_escape_free(); |
|
} |
|
|
|
|
|
char *set_default_config(const char *arg) |
|
{ |
|
opt_set_charp(arg, &default_config); |
|
|
|
return NULL; |
|
} |
|
|
|
void default_save_file(char *filename) |
|
{ |
|
if (default_config && *default_config) { |
|
strcpy(filename, default_config); |
|
return; |
|
} |
|
|
|
#if defined(unix) || defined(__APPLE__) |
|
if (getenv("HOME") && *getenv("HOME")) { |
|
strcpy(filename, getenv("HOME")); |
|
strcat(filename, "/"); |
|
} |
|
else |
|
strcpy(filename, ""); |
|
strcat(filename, ".sgminer/"); |
|
mkdir(filename, 0777); |
|
#else |
|
strcpy(filename, ""); |
|
#endif |
|
strcat(filename, def_conf); |
|
} |
|
|
|
void load_default_config(void) |
|
{ |
|
cnfbuf = (char *)malloc(PATH_MAX); |
|
|
|
default_save_file(cnfbuf); |
|
|
|
if (!access(cnfbuf, R_OK)) |
|
load_config(cnfbuf, NULL); |
|
else { |
|
free(cnfbuf); |
|
cnfbuf = NULL; |
|
} |
|
} |
|
|
|
char *set_algo(const char *arg) |
|
{ |
|
if ((json_array_index < 0) || (total_pools == 0)) { |
|
set_algorithm(opt_algorithm, arg); |
|
applog(LOG_INFO, "Set default algorithm to %s", opt_algorithm->name); |
|
} else { |
|
set_pool_algorithm(arg); |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_nfactor(const char *arg) |
|
{ |
|
if ((json_array_index < 0) || (total_pools == 0)) { |
|
set_algorithm_nfactor(opt_algorithm, (const uint8_t) atoi(arg)); |
|
applog(LOG_INFO, "Set algorithm N-factor to %d (N to %d)", |
|
opt_algorithm->nfactor, opt_algorithm->n); |
|
} else { |
|
set_pool_nfactor(arg); |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_api_allow(const char *arg) |
|
{ |
|
opt_set_charp(arg, &opt_api_allow); |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_api_groups(const char *arg) |
|
{ |
|
opt_set_charp(arg, &opt_api_groups); |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_api_description(const char *arg) |
|
{ |
|
opt_set_charp(arg, &opt_api_description); |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_api_mcast_addr(const char *arg) |
|
{ |
|
opt_set_charp(arg, &opt_api_mcast_addr); |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_api_mcast_code(const char *arg) |
|
{ |
|
opt_set_charp(arg, &opt_api_mcast_code); |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_api_mcast_des(const char *arg) |
|
{ |
|
opt_set_charp(arg, &opt_api_mcast_des); |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_null(const char __maybe_unused *arg) |
|
{ |
|
return NULL; |
|
} |
|
|
|
char *set_temp_cutoff(char *arg) |
|
{ |
|
int val; |
|
|
|
if (!(arg && arg[0])) |
|
return "Invalid parameters for set temp cutoff"; |
|
val = atoi(arg); |
|
if (val < 0 || val > 200) |
|
return "Invalid value passed to set temp cutoff"; |
|
temp_cutoff_str = arg; |
|
|
|
return NULL; |
|
} |
|
|
|
char* set_sharelog(char *arg) |
|
{ |
|
char *r = ""; |
|
long int i = strtol(arg, &r, 10); |
|
|
|
if ((!*r) && i >= 0 && i <= INT_MAX) { |
|
sharelog_file = fdopen((int)i, "a"); |
|
if (!sharelog_file) |
|
applog(LOG_ERR, "Failed to open fd %u for share log", (unsigned int)i); |
|
} else if (!strcmp(arg, "-")) { |
|
sharelog_file = stdout; |
|
if (!sharelog_file) |
|
applog(LOG_ERR, "Standard output missing for share log"); |
|
} else { |
|
sharelog_file = fopen(arg, "a"); |
|
if (!sharelog_file) |
|
applog(LOG_ERR, "Failed to open %s for share log", arg); |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_schedtime(const char *arg, struct schedtime *st) |
|
{ |
|
if (sscanf(arg, "%d:%d", &st->tm.tm_hour, &st->tm.tm_min) != 2) |
|
return "Invalid time set, should be HH:MM"; |
|
if (st->tm.tm_hour > 23 || st->tm.tm_min > 59 || st->tm.tm_hour < 0 || st->tm.tm_min < 0) |
|
return "Invalid time set."; |
|
st->enable = true; |
|
return NULL; |
|
} |
|
|
|
char *set_pool_priority(char *arg) |
|
{ |
|
struct pool *pool = get_current_pool(); |
|
|
|
applog(LOG_DEBUG, "Setting pool %i priority to %s", pool->pool_no, arg); |
|
opt_set_intval(arg, &pool->prio); |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_pool_description(char *arg) |
|
{ |
|
struct pool *pool = get_current_pool(); |
|
|
|
applog(LOG_DEBUG, "Setting pool %i description to %s", pool->pool_no, arg); |
|
opt_set_charp(arg, &pool->description); |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_pass(const char *arg) |
|
{ |
|
struct pool *pool = get_current_pool(); |
|
|
|
opt_set_charp(arg, &pool->rpc_pass); |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_userpass(const char *arg) |
|
{ |
|
struct pool *pool = get_current_pool(); |
|
char *updup; |
|
|
|
updup = strdup(arg); |
|
opt_set_charp(arg, &pool->rpc_userpass); |
|
pool->rpc_user = strtok(updup, ":"); |
|
if (!pool->rpc_user) |
|
return "Failed to find : delimited user info"; |
|
pool->rpc_pass = strtok(NULL, ":"); |
|
if (!pool->rpc_pass) |
|
pool->rpc_pass = ""; |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_quota(char *arg) |
|
{ |
|
char *semicolon = strchr(arg, ';'), *url; |
|
size_t len, qlen; |
|
int quota; |
|
struct pool *pool; |
|
|
|
if (!semicolon) |
|
return "No semicolon separated quota;URL pair found"; |
|
len = strlen(arg); |
|
*semicolon = '\0'; |
|
qlen = strlen(arg); |
|
if (!qlen) |
|
return "No parameter for quota found"; |
|
len -= qlen + 1; |
|
if (len < 1) |
|
return "No parameter for URL found"; |
|
quota = atoi(arg); |
|
if (quota < 0) |
|
return "Invalid negative parameter for quota set"; |
|
url = arg + qlen + 1; |
|
pool = add_url(); |
|
setup_url(pool, url); |
|
pool->quota = quota; |
|
applog(LOG_INFO, "Setting %s to quota %d", get_pool_name(pool), pool->quota); |
|
adjust_quota_gcd(); |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_user(const char *arg) |
|
{ |
|
struct pool *pool = get_current_pool(); |
|
|
|
opt_set_charp(arg, &pool->rpc_user); |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_pool_state(char *arg) |
|
{ |
|
struct pool *pool = get_current_pool(); |
|
|
|
applog(LOG_INFO, "Setting pool %s state to %s", get_pool_name(pool), arg); |
|
if (strcmp(arg, "disabled") == 0) { |
|
pool->state = POOL_DISABLED; |
|
} else if (strcmp(arg, "enabled") == 0) { |
|
pool->state = POOL_ENABLED; |
|
} else if (strcmp(arg, "hidden") == 0) { |
|
pool->state = POOL_HIDDEN; |
|
} else if (strcmp(arg, "rejecting") == 0) { |
|
pool->state = POOL_REJECTING; |
|
} else { |
|
pool->state = POOL_ENABLED; |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_url(char *arg) |
|
{ |
|
struct pool *pool = add_url(); |
|
|
|
setup_url(pool, arg); |
|
return NULL; |
|
} |
|
|
|
|
|
char *set_pool_algorithm(const char *arg) |
|
{ |
|
struct pool *pool = get_current_pool(); |
|
|
|
applog(LOG_DEBUG, "Setting pool %i algorithm to %s", pool->pool_no, arg); |
|
set_algorithm(&pool->algorithm, arg); |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_pool_nfactor(const char *arg) |
|
{ |
|
struct pool *pool = get_current_pool(); |
|
|
|
applog(LOG_DEBUG, "Setting pool %i N-factor to %s", pool->pool_no, arg); |
|
set_algorithm_nfactor(&pool->algorithm, (const uint8_t) atoi(arg)); |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_pool_name(char *arg) |
|
{ |
|
struct pool *pool = get_current_pool(); |
|
|
|
applog(LOG_DEBUG, "Setting pool %i name to %s", pool->pool_no, arg); |
|
opt_set_charp(arg, &pool->name); |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_poolname_deprecated(char *arg) |
|
{ |
|
applog(LOG_ERR, "Specifying pool name by --poolname is deprecated. Use --name instead."); |
|
set_pool_name(arg); |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_balance(enum pool_strategy *strategy) |
|
{ |
|
*strategy = POOL_BALANCE; |
|
return NULL; |
|
} |
|
|
|
char *set_loadbalance(enum pool_strategy *strategy) |
|
{ |
|
*strategy = POOL_LOADBALANCE; |
|
return NULL; |
|
} |
|
|
|
char *set_rotate(const char *arg, int *i) |
|
{ |
|
pool_strategy = POOL_ROTATE; |
|
return set_int_range(arg, i, 0, 9999); |
|
} |
|
|
|
char *set_rr(enum pool_strategy *strategy) |
|
{ |
|
*strategy = POOL_ROUNDROBIN; |
|
return NULL; |
|
} |
|
|
|
char *set_int_range(const char *arg, int *i, int min, int max) |
|
{ |
|
char *err = opt_set_intval(arg, i); |
|
|
|
if (err) |
|
return err; |
|
|
|
if (*i < min || *i > max) |
|
return "Value out of range"; |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_int_0_to_9999(const char *arg, int *i) |
|
{ |
|
return set_int_range(arg, i, 0, 9999); |
|
} |
|
|
|
char *set_int_1_to_65535(const char *arg, int *i) |
|
{ |
|
return set_int_range(arg, i, 1, 65535); |
|
} |
|
|
|
char *set_int_0_to_10(const char *arg, int *i) |
|
{ |
|
return set_int_range(arg, i, 0, 10); |
|
} |
|
|
|
char *set_int_1_to_10(const char *arg, int *i) |
|
{ |
|
return set_int_range(arg, i, 1, 10); |
|
} |
|
|
|
void get_intrange(char *arg, int *val1, int *val2) |
|
{ |
|
if (sscanf(arg, "%d-%d", val1, val2) == 1) |
|
*val2 = *val1; |
|
} |
|
|
|
char *set_devices(char *arg) |
|
{ |
|
int i, val1 = 0, val2 = 0; |
|
char *nextptr; |
|
|
|
if (*arg) { |
|
if (*arg == '?') { |
|
opt_display_devs = true; |
|
return NULL; |
|
} |
|
} else |
|
return "Invalid device parameters"; |
|
|
|
nextptr = strtok(arg, ","); |
|
if (nextptr == NULL) |
|
return "Invalid parameters for set devices"; |
|
get_intrange(nextptr, &val1, &val2); |
|
if (val1 < 0 || val1 > MAX_DEVICES || val2 < 0 || val2 > MAX_DEVICES || |
|
val1 > val2) { |
|
return "Invalid value passed to set devices"; |
|
} |
|
|
|
for (i = val1; i <= val2; i++) { |
|
devices_enabled[i] = true; |
|
opt_devs_enabled++; |
|
} |
|
|
|
while ((nextptr = strtok(NULL, ",")) != NULL) { |
|
get_intrange(nextptr, &val1, &val2); |
|
if (val1 < 0 || val1 > MAX_DEVICES || val2 < 0 || val2 > MAX_DEVICES || |
|
val1 > val2) { |
|
return "Invalid value passed to set devices"; |
|
} |
|
|
|
for (i = val1; i <= val2; i++) { |
|
devices_enabled[i] = true; |
|
opt_devs_enabled++; |
|
} |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
struct pool* get_current_pool() |
|
{ |
|
while ((json_array_index + 1) > total_pools) |
|
add_pool(); |
|
|
|
if (json_array_index < 0) { |
|
if (!total_pools) |
|
add_pool(); |
|
return pools[total_pools - 1]; |
|
} |
|
|
|
return pools[json_array_index]; |
|
} |
|
|
|
char *enable_debug(bool *flag) |
|
{ |
|
*flag = true; |
|
/* Turn on verbose output, too. */ |
|
opt_log_output = true; |
|
return NULL; |
|
} |
|
|
|
extern const char *opt_argv0; |
|
|
|
static char *opt_verusage_and_exit(const char *extra) |
|
{ |
|
printf("%s\n", packagename); |
|
printf("%s", opt_usage(opt_argv0, extra)); |
|
fflush(stdout); |
|
exit(0); |
|
} |
|
|
|
char *display_devs(int *ndevs) |
|
{ |
|
*ndevs = 0; |
|
print_ndevs(ndevs); |
|
exit(*ndevs); |
|
} |
|
|
|
char *set_vector(char *arg) |
|
{ |
|
int i, val = 0, device = 0; |
|
char *nextptr; |
|
|
|
nextptr = strtok(arg, ","); |
|
if (nextptr == NULL) |
|
return "Invalid parameters for set vector"; |
|
val = atoi(nextptr); |
|
if (val != 1 && val != 2 && val != 4) |
|
return "Invalid value passed to set_vector"; |
|
|
|
gpus[device++].vwidth = val; |
|
|
|
while ((nextptr = strtok(NULL, ",")) != NULL) { |
|
val = atoi(nextptr); |
|
if (val != 1 && val != 2 && val != 4) |
|
return "Invalid value passed to set_vector"; |
|
|
|
gpus[device++].vwidth = val; |
|
} |
|
if (device == 1) { |
|
for (i = device; i < MAX_GPUDEVICES; i++) |
|
gpus[i].vwidth = gpus[0].vwidth; |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_worksize(char *arg) |
|
{ |
|
int i, val = 0, device = 0; |
|
char *nextptr; |
|
|
|
nextptr = strtok(arg, ","); |
|
if (nextptr == NULL) |
|
return "Invalid parameters for set work size"; |
|
val = atoi(nextptr); |
|
if (val < 1 || val > 9999) |
|
return "Invalid value passed to set_worksize"; |
|
|
|
gpus[device++].work_size = val; |
|
|
|
while ((nextptr = strtok(NULL, ",")) != NULL) { |
|
val = atoi(nextptr); |
|
if (val < 1 || val > 9999) |
|
return "Invalid value passed to set_worksize"; |
|
|
|
gpus[device++].work_size = val; |
|
} |
|
if (device == 1) { |
|
for (i = device; i < MAX_GPUDEVICES; i++) |
|
gpus[i].work_size = gpus[0].work_size; |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_shaders(char *arg) |
|
{ |
|
int i, val = 0, device = 0; |
|
char *nextptr; |
|
|
|
nextptr = strtok(arg, ","); |
|
if (nextptr == NULL) |
|
return "Invalid parameters for set lookup gap"; |
|
val = atoi(nextptr); |
|
|
|
gpus[device++].shaders = val; |
|
|
|
while ((nextptr = strtok(NULL, ",")) != NULL) { |
|
val = atoi(nextptr); |
|
|
|
gpus[device++].shaders = val; |
|
} |
|
if (device == 1) { |
|
for (i = device; i < MAX_GPUDEVICES; i++) |
|
gpus[i].shaders = gpus[0].shaders; |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_lookup_gap(char *arg) |
|
{ |
|
int i, val = 0, device = 0; |
|
char *nextptr; |
|
|
|
nextptr = strtok(arg, ","); |
|
if (nextptr == NULL) |
|
return "Invalid parameters for set lookup gap"; |
|
val = atoi(nextptr); |
|
|
|
gpus[device++].opt_lg = val; |
|
|
|
while ((nextptr = strtok(NULL, ",")) != NULL) { |
|
val = atoi(nextptr); |
|
|
|
gpus[device++].opt_lg = val; |
|
} |
|
if (device == 1) { |
|
for (i = device; i < MAX_GPUDEVICES; i++) |
|
gpus[i].opt_lg = gpus[0].opt_lg; |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_thread_concurrency(char *arg) |
|
{ |
|
int i, val = 0, device = 0; |
|
char *nextptr; |
|
|
|
nextptr = strtok(arg, ","); |
|
if (nextptr == NULL) |
|
return "Invalid parameters for set thread concurrency"; |
|
val = atoi(nextptr); |
|
|
|
gpus[device++].opt_tc = val; |
|
|
|
while ((nextptr = strtok(NULL, ",")) != NULL) { |
|
val = atoi(nextptr); |
|
|
|
gpus[device++].opt_tc = val; |
|
} |
|
if (device == 1) { |
|
for (i = device; i < MAX_GPUDEVICES; i++) |
|
gpus[i].opt_tc = gpus[0].opt_tc; |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_kernel(char *arg) |
|
{ |
|
char *nextptr; |
|
int i, device = 0; |
|
|
|
nextptr = strtok(arg, ","); |
|
if (nextptr == NULL) |
|
return "Invalid parameters for set kernel"; |
|
|
|
if (gpus[device].kernelname != NULL) |
|
free(gpus[device].kernelname); |
|
gpus[device].kernelname = strdup(nextptr); |
|
device++; |
|
|
|
while ((nextptr = strtok(NULL, ",")) != NULL) { |
|
if (gpus[device].kernelname != NULL) |
|
free(gpus[device].kernelname); |
|
gpus[device].kernelname = strdup(nextptr); |
|
device++; |
|
} |
|
|
|
/* If only one kernel name provided, use same for all GPUs. */ |
|
if (device == 1) { |
|
for (i = device; i < MAX_GPUDEVICES; i++) { |
|
if (gpus[i].kernelname != NULL) |
|
free(gpus[i].kernelname); |
|
gpus[i].kernelname = strdup(gpus[0].kernelname); |
|
} |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
#ifdef HAVE_ADL |
|
/* This function allows us to map an adl device to an opencl device for when |
|
* simple enumeration has failed to match them. */ |
|
char *set_gpu_map(char *arg) |
|
{ |
|
int val1 = 0, val2 = 0; |
|
char *nextptr; |
|
|
|
nextptr = strtok(arg, ","); |
|
if (nextptr == NULL) |
|
return "Invalid parameters for set gpu map"; |
|
if (sscanf(arg, "%d:%d", &val1, &val2) != 2) |
|
return "Invalid description for map pair"; |
|
if (val1 < 0 || val1 > MAX_GPUDEVICES || val2 < 0 || val2 > MAX_GPUDEVICES) |
|
return "Invalid value passed to set_gpu_map"; |
|
|
|
gpus[val1].virtual_adl = val2; |
|
gpus[val1].mapped = true; |
|
|
|
while ((nextptr = strtok(NULL, ",")) != NULL) { |
|
if (sscanf(nextptr, "%d:%d", &val1, &val2) != 2) |
|
return "Invalid description for map pair"; |
|
if (val1 < 0 || val1 > MAX_GPUDEVICES || val2 < 0 || val2 > MAX_GPUDEVICES) |
|
return "Invalid value passed to set_gpu_map"; |
|
gpus[val1].virtual_adl = val2; |
|
gpus[val1].mapped = true; |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_gpu_threads(char *arg) |
|
{ |
|
int i, val = 1, device = 0; |
|
char *nextptr; |
|
|
|
nextptr = strtok(arg, ","); |
|
if (nextptr == NULL) |
|
return "Invalid parameters for set_gpu_threads"; |
|
val = atoi(nextptr); |
|
if (val < 1 || val > 10) |
|
return "Invalid value passed to set_gpu_threads"; |
|
|
|
gpus[device++].threads = val; |
|
|
|
while ((nextptr = strtok(NULL, ",")) != NULL) { |
|
val = atoi(nextptr); |
|
if (val < 1 || val > 10) |
|
return "Invalid value passed to set_gpu_threads"; |
|
|
|
gpus[device++].threads = val; |
|
} |
|
if (device == 1) { |
|
for (i = device; i < MAX_GPUDEVICES; i++) |
|
gpus[i].threads = gpus[0].threads; |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_gpu_engine(char *arg) |
|
{ |
|
int i, val1 = 0, val2 = 0, device = 0; |
|
char *nextptr; |
|
|
|
nextptr = strtok(arg, ","); |
|
if (nextptr == NULL) |
|
return "Invalid parameters for set gpu engine"; |
|
get_intrange(nextptr, &val1, &val2); |
|
if (val1 < 0 || val1 > 9999 || val2 < 0 || val2 > 9999) |
|
return "Invalid value passed to set_gpu_engine"; |
|
|
|
gpus[device].min_engine = val1; |
|
gpus[device].gpu_engine = val2; |
|
device++; |
|
|
|
while ((nextptr = strtok(NULL, ",")) != NULL) { |
|
get_intrange(nextptr, &val1, &val2); |
|
if (val1 < 0 || val1 > 9999 || val2 < 0 || val2 > 9999) |
|
return "Invalid value passed to set_gpu_engine"; |
|
gpus[device].min_engine = val1; |
|
gpus[device].gpu_engine = val2; |
|
device++; |
|
} |
|
|
|
if (device == 1) { |
|
for (i = 1; i < MAX_GPUDEVICES; i++) { |
|
gpus[i].min_engine = gpus[0].min_engine; |
|
gpus[i].gpu_engine = gpus[0].gpu_engine; |
|
} |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_gpu_fan(char *arg) |
|
{ |
|
int i, val1 = 0, val2 = 0, device = 0; |
|
char *nextptr; |
|
|
|
nextptr = strtok(arg, ","); |
|
if (nextptr == NULL) |
|
return "Invalid parameters for set gpu fan"; |
|
get_intrange(nextptr, &val1, &val2); |
|
if (val1 < 0 || val1 > 100 || val2 < 0 || val2 > 100) |
|
return "Invalid value passed to set_gpu_fan"; |
|
|
|
gpus[device].min_fan = val1; |
|
gpus[device].gpu_fan = val2; |
|
device++; |
|
|
|
while ((nextptr = strtok(NULL, ",")) != NULL) { |
|
get_intrange(nextptr, &val1, &val2); |
|
if (val1 < 0 || val1 > 100 || val2 < 0 || val2 > 100) |
|
return "Invalid value passed to set_gpu_fan"; |
|
|
|
gpus[device].min_fan = val1; |
|
gpus[device].gpu_fan = val2; |
|
device++; |
|
} |
|
|
|
if (device == 1) { |
|
for (i = 1; i < MAX_GPUDEVICES; i++) { |
|
gpus[i].min_fan = gpus[0].min_fan; |
|
gpus[i].gpu_fan = gpus[0].gpu_fan; |
|
} |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_gpu_memclock(char *arg) |
|
{ |
|
int i, val = 0, device = 0; |
|
char *nextptr; |
|
|
|
nextptr = strtok(arg, ","); |
|
if (nextptr == NULL) |
|
return "Invalid parameters for set gpu memclock"; |
|
val = atoi(nextptr); |
|
if (val < 0 || val >= 9999) |
|
return "Invalid value passed to set_gpu_memclock"; |
|
|
|
gpus[device++].gpu_memclock = val; |
|
|
|
while ((nextptr = strtok(NULL, ",")) != NULL) { |
|
val = atoi(nextptr); |
|
if (val < 0 || val >= 9999) |
|
return "Invalid value passed to set_gpu_memclock"; |
|
|
|
gpus[device++].gpu_memclock = val; |
|
} |
|
if (device == 1) { |
|
for (i = device; i < MAX_GPUDEVICES; i++) |
|
gpus[i].gpu_memclock = gpus[0].gpu_memclock; |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_gpu_memdiff(char *arg) |
|
{ |
|
int i, val = 0, device = 0; |
|
char *nextptr; |
|
|
|
nextptr = strtok(arg, ","); |
|
if (nextptr == NULL) |
|
return "Invalid parameters for set gpu memdiff"; |
|
val = atoi(nextptr); |
|
if (val < -9999 || val > 9999) |
|
return "Invalid value passed to set_gpu_memdiff"; |
|
|
|
gpus[device++].gpu_memdiff = val; |
|
|
|
while ((nextptr = strtok(NULL, ",")) != NULL) { |
|
val = atoi(nextptr); |
|
if (val < -9999 || val > 9999) |
|
return "Invalid value passed to set_gpu_memdiff"; |
|
|
|
gpus[device++].gpu_memdiff = val; |
|
} |
|
if (device == 1) { |
|
for (i = device; i < MAX_GPUDEVICES; i++) |
|
gpus[i].gpu_memdiff = gpus[0].gpu_memdiff; |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_gpu_powertune(char *arg) |
|
{ |
|
int i, val = 0, device = 0; |
|
char *nextptr; |
|
|
|
nextptr = strtok(arg, ","); |
|
if (nextptr == NULL) |
|
return "Invalid parameters for set gpu powertune"; |
|
val = atoi(nextptr); |
|
if (val < -99 || val > 99) |
|
return "Invalid value passed to set_gpu_powertune"; |
|
|
|
gpus[device++].gpu_powertune = val; |
|
|
|
while ((nextptr = strtok(NULL, ",")) != NULL) { |
|
val = atoi(nextptr); |
|
if (val < -99 || val > 99) |
|
return "Invalid value passed to set_gpu_powertune"; |
|
|
|
gpus[device++].gpu_powertune = val; |
|
} |
|
if (device == 1) { |
|
for (i = device; i < MAX_GPUDEVICES; i++) |
|
gpus[i].gpu_powertune = gpus[0].gpu_powertune; |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_gpu_vddc(char *arg) |
|
{ |
|
int i, device = 0; |
|
float val = 0; |
|
char *nextptr; |
|
|
|
nextptr = strtok(arg, ","); |
|
if (nextptr == NULL) |
|
return "Invalid parameters for set gpu vddc"; |
|
val = atof(nextptr); |
|
if (val < 0 || val >= 9999) |
|
return "Invalid value passed to set_gpu_vddc"; |
|
|
|
gpus[device++].gpu_vddc = val; |
|
|
|
while ((nextptr = strtok(NULL, ",")) != NULL) { |
|
val = atof(nextptr); |
|
if (val < 0 || val >= 9999) |
|
return "Invalid value passed to set_gpu_vddc"; |
|
|
|
gpus[device++].gpu_vddc = val; |
|
} |
|
if (device == 1) { |
|
for (i = device; i < MAX_GPUDEVICES; i++) |
|
gpus[i].gpu_vddc = gpus[0].gpu_vddc; |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_temp_overheat(char *arg) |
|
{ |
|
int i, val = 0, device = 0, *to; |
|
char *nextptr; |
|
|
|
nextptr = strtok(arg, ","); |
|
if (nextptr == NULL) |
|
return "Invalid parameters for set temp overheat"; |
|
val = atoi(nextptr); |
|
if (val < 0 || val > 200) |
|
return "Invalid value passed to set temp overheat"; |
|
|
|
to = &gpus[device++].adl.overtemp; |
|
*to = val; |
|
|
|
while ((nextptr = strtok(NULL, ",")) != NULL) { |
|
val = atoi(nextptr); |
|
if (val < 0 || val > 200) |
|
return "Invalid value passed to set temp overheat"; |
|
|
|
to = &gpus[device++].adl.overtemp; |
|
*to = val; |
|
} |
|
if (device == 1) { |
|
for (i = device; i < MAX_GPUDEVICES; i++) { |
|
to = &gpus[i].adl.overtemp; |
|
*to = val; |
|
} |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_temp_target(char *arg) |
|
{ |
|
int i, val = 0, device = 0, *tt; |
|
char *nextptr; |
|
|
|
nextptr = strtok(arg, ","); |
|
if (nextptr == NULL) |
|
return "Invalid parameters for set temp target"; |
|
val = atoi(nextptr); |
|
if (val < 0 || val > 200) |
|
return "Invalid value passed to set temp target"; |
|
|
|
tt = &gpus[device++].adl.targettemp; |
|
*tt = val; |
|
|
|
while ((nextptr = strtok(NULL, ",")) != NULL) { |
|
val = atoi(nextptr); |
|
if (val < 0 || val > 200) |
|
return "Invalid value passed to set temp target"; |
|
|
|
tt = &gpus[device++].adl.targettemp; |
|
*tt = val; |
|
} |
|
if (device == 1) { |
|
for (i = device; i < MAX_GPUDEVICES; i++) { |
|
tt = &gpus[i].adl.targettemp; |
|
*tt = val; |
|
} |
|
} |
|
|
|
return NULL; |
|
} |
|
#endif |
|
|
|
char *set_intensity(char *arg) |
|
{ |
|
int i, device = 0, *tt; |
|
char *nextptr, val = 0; |
|
|
|
nextptr = strtok(arg, ","); |
|
if (nextptr == NULL) |
|
return "Invalid parameters for set intensity"; |
|
if (!strncasecmp(nextptr, "d", 1)) |
|
gpus[device].dynamic = true; |
|
else { |
|
gpus[device].dynamic = false; |
|
val = atoi(nextptr); |
|
if (val == 0) return "disabled"; |
|
if (val < MIN_INTENSITY || val > MAX_INTENSITY) |
|
return "Invalid value passed to set intensity"; |
|
tt = &gpus[device].intensity; |
|
*tt = val; |
|
gpus[device].xintensity = 0; // Disable shader based intensity |
|
gpus[device].rawintensity = 0; // Disable raw intensity |
|
} |
|
|
|
device++; |
|
|
|
while ((nextptr = strtok(NULL, ",")) != NULL) { |
|
if (!strncasecmp(nextptr, "d", 1)) |
|
gpus[device].dynamic = true; |
|
else { |
|
gpus[device].dynamic = false; |
|
val = atoi(nextptr); |
|
if (val == 0) return "disabled"; |
|
if (val < MIN_INTENSITY || val > MAX_INTENSITY) |
|
return "Invalid value passed to set intensity"; |
|
|
|
tt = &gpus[device].intensity; |
|
*tt = val; |
|
gpus[device].xintensity = 0; // Disable shader based intensity |
|
gpus[device].rawintensity = 0; // Disable raw intensity |
|
} |
|
device++; |
|
} |
|
if (device == 1) { |
|
for (i = device; i < MAX_GPUDEVICES; i++) { |
|
gpus[i].dynamic = gpus[0].dynamic; |
|
gpus[i].intensity = gpus[0].intensity; |
|
gpus[i].xintensity = 0; // Disable shader based intensity |
|
gpus[i].rawintensity = 0; // Disable raw intensity |
|
} |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_xintensity(char *arg) |
|
{ |
|
int i, device = 0, val = 0; |
|
char *nextptr; |
|
|
|
nextptr = strtok(arg, ","); |
|
if (nextptr == NULL) |
|
return "Invalid parameters for shader based intensity"; |
|
val = atoi(nextptr); |
|
if (val == 0) return "disabled"; |
|
if (val < MIN_XINTENSITY || val > MAX_XINTENSITY) |
|
return "Invalid value passed to set shader-based intensity"; |
|
|
|
gpus[device].dynamic = false; // Disable dynamic intensity |
|
gpus[device].intensity = 0; // Disable regular intensity |
|
gpus[device].rawintensity = 0; // Disable raw intensity |
|
gpus[device].xintensity = val; |
|
device++; |
|
|
|
while ((nextptr = strtok(NULL, ",")) != NULL) { |
|
val = atoi(nextptr); |
|
if (val == 0) return "disabled"; |
|
if (val < MIN_XINTENSITY || val > MAX_XINTENSITY) |
|
return "Invalid value passed to set shader based intensity"; |
|
gpus[device].dynamic = false; // Disable dynamic intensity |
|
gpus[device].intensity = 0; // Disable regular intensity |
|
gpus[device].rawintensity = 0; // Disable raw intensity |
|
gpus[device].xintensity = val; |
|
device++; |
|
} |
|
if (device == 1) |
|
for (i = device; i < MAX_GPUDEVICES; i++) { |
|
gpus[i].dynamic = gpus[0].dynamic; |
|
gpus[i].intensity = gpus[0].intensity; |
|
gpus[i].rawintensity = gpus[0].rawintensity; |
|
gpus[i].xintensity = gpus[0].xintensity; |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
char *set_rawintensity(char *arg) |
|
{ |
|
int i, device = 0, val = 0; |
|
char *nextptr; |
|
|
|
nextptr = strtok(arg, ","); |
|
if (nextptr == NULL) |
|
return "Invalid parameters for raw intensity"; |
|
val = atoi(nextptr); |
|
if (val == 0) return "disabled"; |
|
if (val < MIN_RAWINTENSITY || val > MAX_RAWINTENSITY) |
|
return "Invalid value passed to set raw intensity"; |
|
|
|
gpus[device].dynamic = false; // Disable dynamic intensity |
|
gpus[device].intensity = 0; // Disable regular intensity |
|
gpus[device].xintensity = 0; // Disable xintensity |
|
gpus[device].rawintensity = val; |
|
device++; |
|
|
|
while ((nextptr = strtok(NULL, ",")) != NULL) { |
|
val = atoi(nextptr); |
|
if (val == 0) return "disabled"; |
|
if (val < MIN_RAWINTENSITY || val > MAX_RAWINTENSITY) |
|
return "Invalid value passed to set raw intensity"; |
|
gpus[device].dynamic = false; // Disable dynamic intensity |
|
gpus[device].intensity = 0; // Disable regular intensity |
|
gpus[device].xintensity = 0; // Disable xintensity |
|
gpus[device].rawintensity = val; |
|
device++; |
|
} |
|
if (device == 1) |
|
for (i = device; i < MAX_GPUDEVICES; i++) { |
|
gpus[i].dynamic = gpus[0].dynamic; |
|
gpus[i].intensity = gpus[0].intensity; |
|
gpus[i].rawintensity = gpus[0].rawintensity; |
|
gpus[i].xintensity = gpus[0].xintensity; |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
|
|
/* These options are available from config file or commandline */ |
|
static struct opt_table opt_config_table[] = { |
|
OPT_WITH_ARG("--algorithm", |
|
set_algo, NULL, NULL, |
|
"Set mining algorithm and most common defaults, default: scrypt"), |
|
OPT_WITH_ARG("--api-allow", |
|
set_api_allow, NULL, NULL, |
|
"Allow API access only to the given list of [G:]IP[/Prefix] addresses[/subnets]"), |
|
OPT_WITH_ARG("--api-description", |
|
set_api_description, NULL, NULL, |
|
"Description placed in the API status header, default: sgminer version"), |
|
OPT_WITH_ARG("--api-groups", |
|
set_api_groups, NULL, NULL, |
|
"API one letter groups G:cmd:cmd[,P:cmd:*...] defining the cmds a groups can use"), |
|
OPT_WITHOUT_ARG("--api-listen", |
|
opt_set_bool, &opt_api_listen, |
|
"Enable API, default: disabled"), |
|
OPT_WITHOUT_ARG("--api-mcast", |
|
opt_set_bool, &opt_api_mcast, |
|
"Enable API Multicast listener, default: disabled"), |
|
OPT_WITH_ARG("--api-mcast-addr", |
|
set_api_mcast_addr, NULL, NULL, |
|
"API Multicast listen address"), |
|
OPT_WITH_ARG("--api-mcast-code", |
|
set_api_mcast_code, NULL, NULL, |
|
"Code expected in the API Multicast message, don't use '-'"), |
|
OPT_WITH_ARG("--api-mcast-des", |
|
set_api_mcast_des, NULL, NULL, |
|
"Description appended to the API Multicast reply, default: ''"), |
|
OPT_WITH_ARG("--api-mcast-port", |
|
set_int_1_to_65535, opt_show_intval, &opt_api_mcast_port, |
|
"API Multicast listen port"), |
|
OPT_WITHOUT_ARG("--api-network", |
|
opt_set_bool, &opt_api_network, |
|
"Allow API (if enabled) to listen on/for any address, default: only 127.0.0.1"), |
|
OPT_WITH_ARG("--api-port", |
|
set_int_1_to_65535, opt_show_intval, &opt_api_port, |
|
"Port number of miner API"), |
|
#ifdef HAVE_ADL |
|
OPT_WITHOUT_ARG("--auto-fan", |
|
opt_set_bool, &opt_autofan, |
|
"Automatically adjust all GPU fan speeds to maintain a target temperature"), |
|
OPT_WITHOUT_ARG("--auto-gpu", |
|
opt_set_bool, &opt_autoengine, |
|
"Automatically adjust all GPU engine clock speeds to maintain a target temperature"), |
|
#endif |
|
OPT_WITHOUT_ARG("--balance", |
|
set_balance, &pool_strategy, |
|
"Change multipool strategy from failover to even share balance"), |
|
#ifdef HAVE_CURSES |
|
OPT_WITHOUT_ARG("--compact", |
|
opt_set_bool, &opt_compact, |
|
"Use compact display without per device statistics"), |
|
#endif |
|
OPT_WITHOUT_ARG("--debug|-D", |
|
enable_debug, &opt_debug, |
|
"Enable debug output"), |
|
OPT_WITH_ARG("--description", |
|
set_pool_description, NULL, NULL, |
|
"Pool description"), |
|
OPT_WITH_ARG("--device|-d", |
|
set_devices, NULL, NULL, |
|
"Select device to use, one value, range and/or comma separated (e.g. 0-2,4) default: all"), |
|
OPT_WITHOUT_ARG("--disable-rejecting", |
|
opt_set_bool, &opt_disable_pool, |
|
"Automatically disable pools that continually reject shares"), |
|
OPT_WITH_ARG("--expiry|-E", |
|
set_int_0_to_9999, opt_show_intval, &opt_expiry, |
|
"Upper bound on how many seconds after getting work we consider a share from it stale"), |
|
OPT_WITHOUT_ARG("--failover-only", |
|
opt_set_bool, &opt_fail_only, |
|
"Don't leak work to backup pools when primary pool is lagging"), |
|
OPT_WITH_ARG("--failover-switch-delay", |
|
set_int_1_to_65535, opt_show_intval, &opt_fail_switch_delay, |
|
"Delay in seconds before switching back to a failed pool"), |
|
OPT_WITHOUT_ARG("--fix-protocol", |
|
opt_set_bool, &opt_fix_protocol, |
|
"Do not redirect to a different getwork protocol (eg. stratum)"), |
|
OPT_WITH_ARG("--gpu-dyninterval", |
|
set_int_1_to_65535, opt_show_intval, &opt_dynamic_interval, |
|
"Set the refresh interval in ms for GPUs using dynamic intensity"), |
|
OPT_WITH_ARG("--gpu-platform", |
|
set_int_0_to_9999, opt_show_intval, &opt_platform_id, |
|
"Select OpenCL platform ID to use for GPU mining"), |
|
#ifndef HAVE_ADL |
|
// gpu-threads can only be set per-card if ADL is available |
|
OPT_WITH_ARG("--gpu-threads|-g", |
|
set_int_1_to_10, opt_show_intval, &opt_g_threads, |
|
"Number of threads per GPU (1 - 10)"), |
|
#else |
|
OPT_WITH_ARG("--gpu-threads|-g", |
|
set_gpu_threads, NULL, NULL, |
|
"Number of threads per GPU - one value or comma separated list (e.g. 1,2,1)"), |
|
OPT_WITH_ARG("--gpu-engine", |
|
set_gpu_engine, NULL, NULL, |
|
"GPU engine (over)clock range in Mhz - one value, range and/or comma separated list (e.g. 850-900,900,750-850)"), |
|
OPT_WITH_ARG("--gpu-fan", |
|
set_gpu_fan, NULL, NULL, |
|
"GPU fan percentage range - one value, range and/or comma separated list (e.g. 0-85,85,65)"), |
|
OPT_WITH_ARG("--gpu-map", |
|
set_gpu_map, NULL, NULL, |
|
"Map OpenCL to ADL device order manually, paired CSV (e.g. 1:0,2:1 maps OpenCL 1 to ADL 0, 2 to 1)"), |
|
OPT_WITH_ARG("--gpu-memclock", |
|
set_gpu_memclock, NULL, NULL, |
|
"Set the GPU memory (over)clock in Mhz - one value for all or separate by commas for per card"), |
|
OPT_WITH_ARG("--gpu-memdiff", |
|
set_gpu_memdiff, NULL, NULL, |
|
"Set a fixed difference in clock speed between the GPU and memory in auto-gpu mode"), |
|
OPT_WITH_ARG("--gpu-powertune", |
|
set_gpu_powertune, NULL, NULL, |
|
"Set the GPU powertune percentage - one value for all or separate by commas for per card"), |
|
OPT_WITHOUT_ARG("--gpu-reorder", |
|
opt_set_bool, &opt_reorder, |
|
"Attempt to reorder GPU devices according to PCI Bus ID"), |
|
OPT_WITH_ARG("--gpu-vddc", |
|
set_gpu_vddc, NULL, NULL, |
|
"Set the GPU voltage in Volts - one value for all or separate by commas for per card"), |
|
#endif |
|
OPT_WITH_ARG("--lookup-gap", |
|
set_lookup_gap, NULL, NULL, |
|
"Set GPU lookup gap for scrypt mining, comma separated"), |
|
#ifdef HAVE_CURSES |
|
OPT_WITHOUT_ARG("--incognito", |
|
opt_set_bool, &opt_incognito, |
|
"Do not display user name in status window"), |
|
#endif |
|
OPT_WITH_ARG("--intensity|-I", |
|
set_intensity, NULL, NULL, |
|
"Intensity of GPU scanning (d or " MIN_INTENSITY_STR |
|
" -> " MAX_INTENSITY_STR |
|
",default: d to maintain desktop interactivity), overridden by --xintensity or --rawintensity."), |
|
OPT_WITH_ARG("--xintensity|-X", |
|
set_xintensity, NULL, NULL, |
|
"Shader based intensity of GPU scanning (" MIN_XINTENSITY_STR " to " |
|
MAX_XINTENSITY_STR "), overrides --intensity|-I, overridden by --rawintensity."), |
|
OPT_WITH_ARG("--rawintensity", |
|
set_rawintensity, NULL, NULL, |
|
"Raw intensity of GPU scanning (" MIN_RAWINTENSITY_STR " to " |
|
MAX_RAWINTENSITY_STR "), overrides --intensity|-I and --xintensity|-X."), |
|
OPT_WITH_ARG("--kernel-path|-K", |
|
opt_set_charp, opt_show_charp, &opt_kernel_path, |
|
"Specify a path to where kernel files are"), |
|
OPT_WITH_ARG("--kernel|-k", |
|
set_kernel, NULL, NULL, |
|
"Override kernel to use - one value or comma separated"), |
|
OPT_WITHOUT_ARG("--load-balance", |
|
set_loadbalance, &pool_strategy, |
|
"Change multipool strategy from failover to quota based balance"), |
|
OPT_WITH_ARG("--log|-l", |
|
set_int_0_to_9999, opt_show_intval, &opt_log_interval, |
|
"Interval in seconds between log output"), |
|
OPT_WITHOUT_ARG("--log-show-date|-L", |
|
opt_set_bool, &opt_log_show_date, |
|
"Show date on every log line"), |
|
OPT_WITHOUT_ARG("--lowmem", |
|
opt_set_bool, &opt_lowmem, |
|
"Minimise caching of shares for low memory applications"), |
|
#if defined(unix) || defined(__APPLE__) |
|
OPT_WITH_ARG("--monitor|-m", |
|
opt_set_charp, NULL, &opt_stderr_cmd, |
|
"Use custom pipe cmd for output messages"), |
|
#endif // defined(unix) |
|
OPT_WITH_ARG("--name", |
|
set_pool_name, NULL, NULL, |
|
"Name of pool"), |
|
OPT_WITHOUT_ARG("--net-delay", |
|
opt_set_bool, &opt_delaynet, |
|
"Impose small delays in networking to not overload slow routers"), |
|
OPT_WITH_ARG("--nfactor", |
|
set_nfactor, NULL, NULL, |
|
"Override default scrypt N-factor parameter."), |
|
#ifdef HAVE_ADL |
|
OPT_WITHOUT_ARG("--no-adl", |
|
opt_set_bool, &opt_noadl, |
|
"Disable the ATI display library used for monitoring and setting GPU parameters"), |
|
#else |
|
OPT_WITHOUT_ARG("--no-adl", |
|
opt_set_bool, &opt_noadl, opt_hidden), |
|
#endif |
|
OPT_WITHOUT_ARG("--no-pool-disable", |
|
opt_set_invbool, &opt_disable_pool, |
|
opt_hidden), |
|
OPT_WITHOUT_ARG("--no-client-reconnect", |
|
opt_set_invbool, &opt_disable_client_reconnect, |
|
"Disable 'client.reconnect' stratum functionality"), |
|
OPT_WITHOUT_ARG("--no-restart", |
|
opt_set_invbool, &opt_restart, |
|
"Do not attempt to restart GPUs that hang"), |
|
OPT_WITHOUT_ARG("--no-submit-stale", |
|
opt_set_invbool, &opt_submit_stale, |
|
"Don't submit shares if they are detected as stale"), |
|
OPT_WITH_ARG("--pass|-p", |
|
set_pass, NULL, NULL, |
|
"Password for bitcoin JSON-RPC server"), |
|
OPT_WITHOUT_ARG("--per-device-stats", |
|
opt_set_bool, &want_per_device_stats, |
|
"Force verbose mode and output per-device statistics"), |
|
OPT_WITH_ARG("--poolname", /* TODO: Backward compatibility, to be removed. */ |
|
set_poolname_deprecated, NULL, NULL, |
|
opt_hidden), |
|
OPT_WITH_ARG("--priority", |
|
set_pool_priority, NULL, NULL, |
|
"Pool priority"), |
|
OPT_WITHOUT_ARG("--protocol-dump|-P", |
|
opt_set_bool, &opt_protocol, |
|
"Verbose dump of protocol-level activities"), |
|
OPT_WITH_ARG("--queue|-Q", |
|
set_int_0_to_9999, opt_show_intval, &opt_queue, |
|
"Minimum number of work items to have queued (0+)"), |
|
OPT_WITHOUT_ARG("--quiet|-q", |
|
opt_set_bool, &opt_quiet, |
|
"Disable logging output, display status and errors"), |
|
OPT_WITH_ARG("--quota|-U", |
|
set_quota, NULL, NULL, |
|
"quota;URL combination for server with load-balance strategy quotas"), |
|
OPT_WITHOUT_ARG("--real-quiet", |
|
opt_set_bool, &opt_realquiet, |
|
"Disable all output"), |
|
OPT_WITHOUT_ARG("--remove-disabled", |
|
opt_set_bool, &opt_removedisabled, |
|
"Remove disabled devices entirely, as if they didn't exist"), |
|
OPT_WITH_ARG("--retries", |
|
set_null, NULL, NULL, |
|
opt_hidden), |
|
OPT_WITH_ARG("--retry-pause", |
|
set_null, NULL, NULL, |
|
opt_hidden), |
|
OPT_WITH_ARG("--rotate", |
|
set_rotate, opt_show_intval, &opt_rotate_period, |
|
"Change multipool strategy from failover to regularly rotate at N minutes"), |
|
OPT_WITHOUT_ARG("--round-robin", |
|
set_rr, &pool_strategy, |
|
"Change multipool strategy from failover to round robin on failure"), |
|
OPT_WITH_ARG("--scan-time|-s", |
|
set_int_0_to_9999, opt_show_intval, &opt_scantime, |
|
"Upper bound on time spent scanning current work, in seconds"), |
|
OPT_WITH_ARG("--sched-start", |
|
set_schedtime, NULL, &schedstart, |
|
"Set a time of day in HH:MM to start mining (a once off without a stop time)"), |
|
OPT_WITH_ARG("--sched-stop", |
|
set_schedtime, NULL, &schedstop, |
|
"Set a time of day in HH:MM to stop mining (will quit without a start time)"), |
|
OPT_WITH_ARG("--shaders", |
|
set_shaders, NULL, NULL, |
|
"GPU shaders per card for tuning scrypt, comma separated"), |
|
OPT_WITH_ARG("--sharelog", |
|
set_sharelog, NULL, NULL, |
|
"Append share log to file"), |
|
OPT_WITH_ARG("--shares", |
|
opt_set_intval, NULL, &opt_shares, |
|
"Quit after mining N shares (default: unlimited)"), |
|
OPT_WITH_ARG("--socks-proxy", |
|
opt_set_charp, NULL, &opt_socks_proxy, |
|
"Set socks4 proxy (host:port)"), |
|
OPT_WITH_ARG("--state", |
|
set_pool_state, NULL, NULL, |
|
"Specify pool state at startup (default: enabled)"), |
|
#ifdef HAVE_SYSLOG_H |
|
OPT_WITHOUT_ARG("--syslog", |
|
opt_set_bool, &use_syslog, |
|
"Use system log for output messages (default: standard error)"), |
|
#endif |
|
#if defined(HAVE_LIBCURL) && defined(CURL_HAS_KEEPALIVE) |
|
OPT_WITH_ARG("--tcp-keepalive", |
|
set_int_0_to_9999, opt_show_intval, &opt_tcp_keepalive, |
|
"TCP keepalive packet idle time"), |
|
#else |
|
OPT_WITH_ARG("--tcp-keepalive", |
|
set_int_0_to_9999, opt_show_intval, &opt_tcp_keepalive, |
|
opt_hidden), |
|
#endif |
|
#ifdef HAVE_ADL |
|
OPT_WITH_ARG("--temp-cutoff", |
|
set_temp_cutoff, opt_show_intval, &opt_cutofftemp, |
|
"Temperature which a device will be automatically disabled at, one value or comma separated list"), |
|
OPT_WITH_ARG("--temp-hysteresis", |
|
set_int_1_to_10, opt_show_intval, &opt_hysteresis, |
|
"Set how much the temperature can fluctuate outside limits when automanaging speeds"), |
|
OPT_WITH_ARG("--temp-overheat", |
|
set_temp_overheat, opt_show_intval, &opt_overheattemp, |
|
"Temperature which a device will be throttled at while automanaging fan and/or GPU, one value or comma separated list"), |
|
OPT_WITH_ARG("--temp-target", |
|
set_temp_target, opt_show_intval, &opt_targettemp, |
|
"Temperature which a device should stay at while automanaging fan and/or GPU, one value or comma separated list"), |
|
#endif |
|
#ifdef HAVE_CURSES |
|
OPT_WITHOUT_ARG("--text-only|-T", |
|
opt_set_invbool, &use_curses, |
|
"Disable ncurses formatted screen output"), |
|
#else |
|
OPT_WITHOUT_ARG("--text-only|-T", |
|
opt_set_invbool, &use_curses, |
|
opt_hidden), |
|
#endif |
|
OPT_WITH_ARG("--thread-concurrency", |
|
set_thread_concurrency, NULL, NULL, |
|
"Set GPU thread concurrency for scrypt mining, comma separated"), |
|
OPT_WITH_ARG("--url|-o", |
|
set_url, NULL, NULL, |
|
"URL for bitcoin JSON-RPC server"), |
|
OPT_WITH_ARG("--pool-algorithm", |
|
set_pool_algorithm, NULL, NULL, |
|
"Set algorithm for pool"), |
|
OPT_WITH_ARG("--pool-nfactor", |
|
set_pool_nfactor, NULL, NULL, |
|
"Set N-factor for pool"), |
|
OPT_WITH_ARG("--user|-u", |
|
set_user, NULL, NULL, |
|
"Username for bitcoin JSON-RPC server"), |
|
OPT_WITH_ARG("--vectors", |
|
set_vector, NULL, NULL, |
|
opt_hidden), |
|
/* All current kernels only support vectors=1 */ |
|
/* "Override detected optimal vector (1, 2 or 4) - one value or comma separated list"), */ |
|
OPT_WITHOUT_ARG("--verbose|-v", |
|
opt_set_bool, &opt_log_output, |
|
"Log verbose output to stderr as well as status output"), |
|
OPT_WITH_ARG("--worksize|-w", |
|
set_worksize, NULL, NULL, |
|
"Override detected optimal worksize - one value or comma separated list"), |
|
OPT_WITH_ARG("--userpass|-O", |
|
set_userpass, NULL, NULL, |
|
"Username:Password pair for bitcoin JSON-RPC server"), |
|
OPT_WITHOUT_ARG("--worktime", |
|
opt_set_bool, &opt_worktime, |
|
"Display extra work time debug information"), |
|
OPT_WITH_ARG("--pools", |
|
opt_set_bool, NULL, NULL, opt_hidden), |
|
OPT_ENDTABLE |
|
}; |
|
|
|
/* These options are available from commandline only */ |
|
struct opt_table opt_cmdline_table[] = { |
|
OPT_WITH_ARG("--config|-c", |
|
load_config, NULL, NULL, |
|
"Load a JSON-format configuration file\n" |
|
"See example.conf for an example configuration."), |
|
OPT_WITH_ARG("--default-config", |
|
set_default_config, NULL, NULL, |
|
"Specify the filename of the default config file\n" |
|
"Loaded at start and used when saving without a name."), |
|
OPT_WITHOUT_ARG("--help|-h", |
|
opt_verusage_and_exit, NULL, |
|
"Print this message"), |
|
OPT_WITHOUT_ARG("--ndevs|-n", |
|
display_devs, &nDevs, |
|
"Display number of detected GPUs, OpenCL platform " |
|
"information, and exit"), |
|
OPT_WITHOUT_ARG("--version|-V", |
|
opt_version_and_exit, packagename, |
|
"Display version and exit"), |
|
OPT_ENDTABLE |
|
};
|
|
|