Skip to content
This repository has been archived by the owner on May 27, 2020. It is now read-only.

API V1.23 - new pgaset command, to be used soon + MMQ add api pgaset for clock + ensure delta clock can never exceed limits #370

Merged
merged 4 commits into from
Dec 19, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions API-README
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -330,9 +330,23 @@ The list of requests - a (*) means it requires privileged access - and replies a
queue, scantime, expiry queue, scantime, expiry
N is an integer in the range 0 to 9999 N is an integer in the range 0 to 9999


substats USBSTATS Stats of all LIBUSB mining devices except ztex usbstats USBSTATS Stats of all LIBUSB mining devices except ztex
e.g. Name=MMQ,ID=0,Stat=SendWork,Count=99,...| e.g. Name=MMQ,ID=0,Stat=SendWork,Count=99,...|


pgaset|N,opt[,val] (*)
none There is no reply section just the STATUS section
stating the results of setting PGA N with opt[,val]
This is only available if PGA mining is enabled

If the PGA does not support any set options, it will
always return a WARN stating pgaset isn't supported

If opt=help it will return an INFO status with a
help message about the options available

The current options are:
MMQ opt=clock val=160 to 230 (and a multiple of 2)

When you enable, disable or restart a GPU or PGA, you will also get Thread messages When you enable, disable or restart a GPU or PGA, you will also get Thread messages
in the cgminer status window in the cgminer status window


Expand Down Expand Up @@ -386,7 +400,14 @@ miner.php - an example web page to access the API
Feature Changelog for external applications using the API: Feature Changelog for external applications using the API:




API V1.22 API V1.23

Added API commands:
'pgaset' - with: MMQ opt=clock val=160 to 230 (and a multiple of 2)

----------

API V1.22 (cgminer v2.10.1)


Enforced output limitation: Enforced output limitation:
all extra records beyond the output limit of the API (~64k) are ignored all extra records beyond the output limit of the API (~64k) are ignored
Expand Down
78 changes: 77 additions & 1 deletion api.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ static const char SEPARATOR = '|';
#define SEPSTR "|" #define SEPSTR "|"
static const char GPUSEP = ','; static const char GPUSEP = ',';


static const char *APIVERSION = "1.22"; static const char *APIVERSION = "1.23";
static const char *DEAD = "Dead"; static const char *DEAD = "Dead";
#if defined(HAVE_OPENCL) || defined(HAVE_AN_FPGA) #if defined(HAVE_OPENCL) || defined(HAVE_AN_FPGA)
static const char *SICK = "Sick"; static const char *SICK = "Sick";
Expand Down Expand Up @@ -379,6 +379,14 @@ static const char *JSON_PARAMETER = "parameter";
#define MSG_USBSTA 87 #define MSG_USBSTA 87
#define MSG_NOUSTA 88 #define MSG_NOUSTA 88


#ifdef HAVE_AN_FPGA
#define MSG_MISPGAOPT 89
#define MSG_PGANOSET 90
#define MSG_PGAHELP 91
#define MSG_PGASETOK 92
#define MSG_PGASETERR 93
#endif

enum code_severity { enum code_severity {
SEVERITY_ERR, SEVERITY_ERR,
SEVERITY_WARN, SEVERITY_WARN,
Expand Down Expand Up @@ -544,6 +552,13 @@ struct CODES {
{ SEVERITY_ERR, MSG_CONVAL, PARAM_STR, "Missing config value N for '%s,N'" }, { SEVERITY_ERR, MSG_CONVAL, PARAM_STR, "Missing config value N for '%s,N'" },
{ SEVERITY_SUCC, MSG_USBSTA, PARAM_NONE, "USB Statistics" }, { SEVERITY_SUCC, MSG_USBSTA, PARAM_NONE, "USB Statistics" },
{ SEVERITY_INFO, MSG_NOUSTA, PARAM_NONE, "No USB Statistics" }, { SEVERITY_INFO, MSG_NOUSTA, PARAM_NONE, "No USB Statistics" },
#ifdef HAVE_AN_FPGA
{ SEVERITY_ERR, MSG_MISPGAOPT, PARAM_NONE, "Missing option after PGA number" },
{ SEVERITY_WARN, MSG_PGANOSET, PARAM_PGA, "PGA %d does not support pgaset" },
{ 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_FAIL, 0, 0, NULL } { SEVERITY_FAIL, 0, 0, NULL }
}; };


Expand Down Expand Up @@ -3142,6 +3157,64 @@ static void usbstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __may
#endif #endif
} }


#ifdef HAVE_AN_FPGA
static void pgaset(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
{
char buf[TMPBUFSIZ];
int numpga = numpgas();

if (numpga == 0) {
message(io_data, MSG_PGANON, 0, NULL, isjson);
return;
}

if (param == NULL || *param == '\0') {
message(io_data, MSG_MISID, 0, NULL, isjson);
return;
}

char *opt = strchr(param, ',');
if (opt)
*(opt++) = '\0';
if (!opt || !*opt) {
message(io_data, MSG_MISPGAOPT, 0, NULL, isjson);
return;
}

int id = atoi(param);
if (id < 0 || id >= numpga) {
message(io_data, MSG_INVPGA, id, NULL, isjson);
return;
}

int dev = pgadevice(id);
if (dev < 0) { // Should never happen
message(io_data, MSG_INVPGA, id, NULL, isjson);
return;
}

struct cgpu_info *cgpu = devices[dev];
struct device_api *api = cgpu->api;

char *set = strchr(opt, ',');
if (set)
*(set++) = '\0';

if (!api->set_device)
message(io_data, MSG_PGANOSET, id, NULL, isjson);
else {
char *ret = api->set_device(cgpu, opt, set, buf);
if (ret) {
if (strcasecmp(opt, "help") == 0)
message(io_data, MSG_PGAHELP, id, ret, isjson);
else
message(io_data, MSG_PGASETERR, id, ret, isjson);
} else
message(io_data, MSG_PGASETOK, id, NULL, isjson);
}
}
#endif

static void checkcommand(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, char group); static void checkcommand(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, char group);


struct CMDS { struct CMDS {
Expand Down Expand Up @@ -3198,6 +3271,9 @@ struct CMDS {
{ "debug", debugstate, true }, { "debug", debugstate, true },
{ "setconfig", setconfig, true }, { "setconfig", setconfig, true },
{ "usbstats", usbstats, false }, { "usbstats", usbstats, false },
#ifdef HAVE_AN_FPGA
{ "pgaset", pgaset, true },
#endif
{ NULL, NULL, false } { NULL, NULL, false }
}; };


Expand Down
79 changes: 62 additions & 17 deletions driver-modminer.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -599,16 +599,22 @@ static bool modminer_fpga_prepare(struct thr_info *thr)
* *
* N.B. clock must always be a multiple of 2 * N.B. clock must always be a multiple of 2
*/ */
static bool modminer_delta_clock(struct thr_info *thr, int delta, bool temp) static const char *clockoldwork = "clock already changed for this work";
static const char *clocktoolow = "clock too low";
static const char *clocktoohi = "clock too high";
static const char *clocksetfail = "clock set command failed";
static const char *clockreplyfail = "clock reply failed";

static const char *modminer_delta_clock(struct thr_info *thr, int delta, bool temp, bool force)
{ {
struct cgpu_info *modminer = thr->cgpu; struct cgpu_info *modminer = thr->cgpu;
struct modminer_fpga_state *state = thr->cgpu_data; struct modminer_fpga_state *state = thr->cgpu_data;
unsigned char cmd[6], buf[1]; unsigned char cmd[6], buf[1];
int err, amount; int err, amount;


// Only do once if multiple shares per work or multiple reasons // Only do once if multiple shares per work or multiple reasons
if (!state->new_work) if (!state->new_work && !force)
return false; return clockoldwork;


state->new_work = false; state->new_work = false;


Expand All @@ -617,11 +623,11 @@ static bool modminer_delta_clock(struct thr_info *thr, int delta, bool temp)
state->hw_errors = 0; state->hw_errors = 0;


// FYI clock drop has little effect on temp // FYI clock drop has little effect on temp
if (delta < 0 && modminer->clock <= MODMINER_MIN_CLOCK) if (delta < 0 && (modminer->clock + delta) < MODMINER_MIN_CLOCK)
return false; return clocktoolow;


if (delta > 0 && modminer->clock >= MODMINER_MAX_CLOCK) if (delta > 0 && (modminer->clock + delta) > MODMINER_MAX_CLOCK)
return false; return clocktoohi;


if (delta < 0) { if (delta < 0) {
if (temp) if (temp)
Expand Down Expand Up @@ -649,7 +655,7 @@ static bool modminer_delta_clock(struct thr_info *thr, int delta, bool temp)
applog(LOG_ERR, "%s%u: Error writing set clock speed (%d:%d)", applog(LOG_ERR, "%s%u: Error writing set clock speed (%d:%d)",
modminer->api->name, modminer->device_id, amount, err); modminer->api->name, modminer->device_id, amount, err);


return false; return clocksetfail;
} }


if ((err = usb_read(modminer, (char *)(&buf), 1, &amount, C_REPLYSETCLOCK)) < 0 || amount != 1) { if ((err = usb_read(modminer, (char *)(&buf), 1, &amount, C_REPLYSETCLOCK)) < 0 || amount != 1) {
Expand All @@ -658,7 +664,7 @@ static bool modminer_delta_clock(struct thr_info *thr, int delta, bool temp)
applog(LOG_ERR, "%s%u: Error reading set clock speed (%d:%d)", applog(LOG_ERR, "%s%u: Error reading set clock speed (%d:%d)",
modminer->api->name, modminer->device_id, amount, err); modminer->api->name, modminer->device_id, amount, err);


return false; return clockreplyfail;
} }


mutex_unlock(modminer->modminer_mutex); mutex_unlock(modminer->modminer_mutex);
Expand All @@ -668,7 +674,7 @@ static bool modminer_delta_clock(struct thr_info *thr, int delta, bool temp)
(delta < 0) ? "down " : (delta > 0 ? "up " : ""), (delta < 0) ? "down " : (delta > 0 ? "up " : ""),
modminer->clock); modminer->clock);


return true; return NULL;
} }


static bool modminer_fpga_init(struct thr_info *thr) static bool modminer_fpga_init(struct thr_info *thr)
Expand Down Expand Up @@ -715,7 +721,7 @@ static bool modminer_fpga_init(struct thr_info *thr)
} }


modminer->clock = MODMINER_DEF_CLOCK; modminer->clock = MODMINER_DEF_CLOCK;
modminer_delta_clock(thr, MODMINER_CLOCK_SET, false); modminer_delta_clock(thr, MODMINER_CLOCK_SET, false, false);


thr->primary_thread = true; thr->primary_thread = true;


Expand Down Expand Up @@ -831,7 +837,7 @@ static void check_temperature(struct thr_info *thr)
modminer->api->name, modminer->device_id, modminer->api->name, modminer->device_id,
MODMINER_CUTOFF_TEMP, modminer->temp); MODMINER_CUTOFF_TEMP, modminer->temp);


modminer_delta_clock(thr, MODMINER_CLOCK_CUTOFF, true); modminer_delta_clock(thr, MODMINER_CLOCK_CUTOFF, true, false);
state->overheated = true; state->overheated = true;
dev_error(modminer, REASON_DEV_THERMAL_CUTOFF); dev_error(modminer, REASON_DEV_THERMAL_CUTOFF);
} else { } else {
Expand All @@ -841,7 +847,7 @@ static void check_temperature(struct thr_info *thr)


// If it's defined to be 0 then don't call modminer_delta_clock() // If it's defined to be 0 then don't call modminer_delta_clock()
if (MODMINER_CLOCK_OVERHEAT != 0) if (MODMINER_CLOCK_OVERHEAT != 0)
modminer_delta_clock(thr, MODMINER_CLOCK_OVERHEAT, true); modminer_delta_clock(thr, MODMINER_CLOCK_OVERHEAT, true, false);
state->overheated = true; state->overheated = true;
dev_error(modminer, REASON_DEV_OVER_HEAT); dev_error(modminer, REASON_DEV_OVER_HEAT);
} }
Expand Down Expand Up @@ -950,7 +956,7 @@ static uint64_t modminer_process_results(struct thr_info *thr)
if (modminer->clock > MODMINER_DEF_CLOCK || state->hw_errors > 1) { if (modminer->clock > MODMINER_DEF_CLOCK || state->hw_errors > 1) {
float pct = (state->hw_errors * 100.0 / (state->shares ? : 1.0)); float pct = (state->hw_errors * 100.0 / (state->shares ? : 1.0));
if (pct >= MODMINER_HW_ERROR_PERCENT) if (pct >= MODMINER_HW_ERROR_PERCENT)
modminer_delta_clock(thr, MODMINER_CLOCK_DOWN, false); modminer_delta_clock(thr, MODMINER_CLOCK_DOWN, false, false);
} }
} }
} else { } else {
Expand All @@ -959,15 +965,15 @@ static uint64_t modminer_process_results(struct thr_info *thr)
// If we've reached the required good shares in a row then clock up // If we've reached the required good shares in a row then clock up
if (((state->shares - state->shares_last_hw) >= state->shares_to_good) && if (((state->shares - state->shares_last_hw) >= state->shares_to_good) &&
modminer->temp < MODMINER_TEMP_UP_LIMIT) modminer->temp < MODMINER_TEMP_UP_LIMIT)
modminer_delta_clock(thr, MODMINER_CLOCK_UP, false); modminer_delta_clock(thr, MODMINER_CLOCK_UP, false, false);
} }
} else { } else {
// on rare occasions - the MMQ can just stop returning valid nonces // on rare occasions - the MMQ can just stop returning valid nonces
double death = ITS_DEAD_JIM * (state->death_stage_one ? 2.0 : 1.0); double death = ITS_DEAD_JIM * (state->death_stage_one ? 2.0 : 1.0);
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
if (tdiff(&now, &state->last_nonce) >= death) { if (tdiff(&now, &state->last_nonce) >= death) {
if (state->death_stage_one) { if (state->death_stage_one) {
modminer_delta_clock(thr, MODMINER_CLOCK_DEAD, false); modminer_delta_clock(thr, MODMINER_CLOCK_DEAD, false, true);
applog(LOG_ERR, "%s%u: DEATH clock down", applog(LOG_ERR, "%s%u: DEATH clock down",
modminer->api->name, modminer->device_id); modminer->api->name, modminer->device_id);


Expand All @@ -977,7 +983,7 @@ static uint64_t modminer_process_results(struct thr_info *thr)
state->death_stage_one = false; state->death_stage_one = false;
return -1; return -1;
} else { } else {
modminer_delta_clock(thr, MODMINER_CLOCK_DEAD, false); modminer_delta_clock(thr, MODMINER_CLOCK_DEAD, false, true);
applog(LOG_ERR, "%s%u: death clock down", applog(LOG_ERR, "%s%u: death clock down",
modminer->api->name, modminer->device_id); modminer->api->name, modminer->device_id);


Expand Down Expand Up @@ -1097,11 +1103,50 @@ static void modminer_fpga_shutdown(struct thr_info *thr)
free(thr->cgpu_data); free(thr->cgpu_data);
} }


static char *modminer_set_device(struct cgpu_info *modminer, char *option, char *setting, char *replybuf)
{
const char *ret;
int val;

if (strcasecmp(option, "help") == 0) {
sprintf(replybuf, "clock: range %d-%d and a multiple of 2",
MODMINER_MIN_CLOCK, MODMINER_MAX_CLOCK);
return replybuf;
}

if (strcasecmp(option, "clock") == 0) {
if (!setting || !*setting) {
sprintf(replybuf, "missing clock setting");
return replybuf;
}

val = atoi(setting);
if (val < MODMINER_MIN_CLOCK || val > MODMINER_MAX_CLOCK || (val & 1) != 0) {
sprintf(replybuf, "invalid clock: '%s' valid range %d-%d and a multiple of 2",
setting, MODMINER_MIN_CLOCK, MODMINER_MAX_CLOCK);
return replybuf;
}

val -= (int)(modminer->clock);

ret = modminer_delta_clock(modminer->thr[0], val, false, true);
if (ret) {
sprintf(replybuf, "Set clock failed: %s", ret);
return replybuf;
} else
return NULL;
}

sprintf(replybuf, "Unknown option: %s", option);
return replybuf;
}

struct device_api modminer_api = { struct device_api modminer_api = {
.dname = "modminer", .dname = "modminer",
.name = "MMQ", .name = "MMQ",
.api_detect = modminer_detect, .api_detect = modminer_detect,
.get_statline_before = get_modminer_statline_before, .get_statline_before = get_modminer_statline_before,
.set_device = modminer_set_device,
.thread_prepare = modminer_fpga_prepare, .thread_prepare = modminer_fpga_prepare,
.thread_init = modminer_fpga_init, .thread_init = modminer_fpga_init,
.scanhash = modminer_scanhash, .scanhash = modminer_scanhash,
Expand Down
1 change: 1 addition & 0 deletions miner.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ struct device_api {
struct api_data *(*get_api_stats)(struct cgpu_info *); struct api_data *(*get_api_stats)(struct cgpu_info *);
bool (*get_stats)(struct cgpu_info *); bool (*get_stats)(struct cgpu_info *);
void (*identify_device)(struct cgpu_info *); // e.g. to flash a led void (*identify_device)(struct cgpu_info *); // e.g. to flash a led
char *(*set_device)(struct cgpu_info *, char *option, char *setting, char *replybuf);


// Thread-specific functions // Thread-specific functions
bool (*thread_prepare)(struct thr_info *); bool (*thread_prepare)(struct thr_info *);
Expand Down