Browse Source

Merge branch 'cg_merges_20121218' into bfgminer

Luke Dashjr 13 years ago
parent
commit
c0619e5a5a
5 changed files with 178 additions and 14 deletions
  1. 21 0
      API-README
  2. 77 1
      api.c
  3. 74 10
      driver-modminer.c
  4. 5 3
      miner.c
  5. 1 0
      miner.h

+ 21 - 0
API-README

@@ -332,6 +332,20 @@ The list of requests - a (*) means it requires privileged access - and replies a
                                                        0 to 9999)
                               coinbase-sig (string)
 
+ 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=2 to 230 (and a multiple of 2)
+
 When you enable, disable or restart a GPU or PGA, you will also get Thread messages
 in the BFGMiner status window
 
@@ -384,6 +398,13 @@ miner.php - an example web page to access the API
 Feature Changelog for external applications using the API:
 
 
+API V1.23
+
+Added API commands:
+ 'pgaset' - with: MMQ opt=clock val=2 to 230 (and a multiple of 2)
+
+----------
+
 API V1.22
 
 Enforced output limitation:

+ 77 - 1
api.c

@@ -133,7 +133,7 @@ static const char SEPARATOR = '|';
 #define SEPSTR "|"
 static const char GPUSEP = ',';
 
-static const char *APIVERSION = "1.22";
+static const char *APIVERSION = "1.23";
 static const char *DEAD = "Dead";
 static const char *SICK = "Sick";
 static const char *NOSTART = "NoStart";
@@ -380,6 +380,14 @@ static const char *JSON_PARAMETER = "parameter";
 #define MSG_CONPAR 85
 #define MSG_CONVAL 86
 
+#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 {
 	SEVERITY_ERR,
 	SEVERITY_WARN,
@@ -543,6 +551,13 @@ struct CODES {
  { SEVERITY_ERR,   MSG_INVNUM,	PARAM_BOTH,	"Invalid number (%d) for '%s' range is 0-9999" },
  { SEVERITY_ERR,   MSG_CONPAR,	PARAM_NONE,	"Missing config parameters 'name,N'" },
  { SEVERITY_ERR,   MSG_CONVAL,	PARAM_STR,	"Missing config value N for '%s,N'" },
+#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 }
 };
 
@@ -2975,6 +2990,64 @@ static void setconfig(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char
 	message(io_data, MSG_SETCONFIG, value, param, isjson);
 }
 
+#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];
+	const 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);
 
 struct CMDS {
@@ -3031,6 +3104,9 @@ struct CMDS {
 	{ "coin",		minecoin,	false },
 	{ "debug",		debugstate,	true },
 	{ "setconfig",		setconfig,	true },
+#ifdef HAVE_AN_FPGA
+	{ "pgaset",		pgaset,		true },
+#endif
 	{ NULL,			NULL,		false }
 };
 

+ 74 - 10
driver-modminer.c

@@ -1,5 +1,6 @@
 /*
  * Copyright 2012 Luke Dashjr
+ * Copyright 2012 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
@@ -13,6 +14,7 @@
 #define FD_SETSIZE 4096
 #endif
 
+#include <limits.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -26,9 +28,9 @@
 #define BITSTREAM_FILENAME "fpgaminer_top_fixed7_197MHz.bit"
 #define BISTREAM_USER_ID "\2\4$B"
 
-#define MODMINER_MINIMUM_CLOCK    2
-#define MODMINER_DEFAULT_CLOCK  200
-#define MODMINER_MAXIMUM_CLOCK  210
+#define MODMINER_MAX_CLOCK 230
+#define MODMINER_DEF_CLOCK 200
+#define MODMINER_MIN_CLOCK   2
 
 // Commands
 #define MODMINER_PING "\x00"
@@ -353,7 +355,7 @@ modminer_reduce_clock(struct thr_info*thr, bool needlock)
 {
 	struct modminer_fpga_state *state = thr->cgpu_data;
 
-	if (state->dclk.freqM <= MODMINER_MINIMUM_CLOCK / 2)
+	if (state->dclk.freqM <= MODMINER_MIN_CLOCK / 2)
 		return false;
 
 	return modminer_change_clock(thr, needlock, -2);
@@ -416,9 +418,9 @@ modminer_fpga_init(struct thr_info *thr)
 		applog(LOG_DEBUG, "%s %u.%u: FPGA is already programmed :)", modminer->api->name, modminer->device_id, fpgaid);
 	state->pdone = 101;
 
-	state->dclk.freqM = MODMINER_MAXIMUM_CLOCK / 2 + 1;  // Will be reduced immediately
+	state->dclk.freqM = MODMINER_MAX_CLOCK / 2 + 1;  // Will be reduced immediately
 	while (1) {
-		if (state->dclk.freqM <= MODMINER_MINIMUM_CLOCK / 2)
+		if (state->dclk.freqM <= MODMINER_MIN_CLOCK / 2)
 			bailout2(LOG_ERR, "%s %u.%u: Hit minimum trying to find acceptable frequencies", modminer->api->name, modminer->device_id, fpgaid);
 		--state->dclk.freqM;
 		if (!modminer_change_clock(thr, false, 0))
@@ -433,12 +435,12 @@ modminer_fpga_init(struct thr_info *thr)
 	}
 	state->freqMaxMaxM =
 	state->dclk.freqMaxM = state->dclk.freqM;
-	if (MODMINER_DEFAULT_CLOCK / 2 < state->dclk.freqM) {
-		if (!modminer_change_clock(thr, false, -(state->dclk.freqM * 2 - MODMINER_DEFAULT_CLOCK)))
-			applog(LOG_WARNING, "%s %u.%u: Failed to set desired initial frequency of %u", modminer->api->name, modminer->device_id, fpgaid, MODMINER_DEFAULT_CLOCK);
+	if (MODMINER_DEF_CLOCK / 2 < state->dclk.freqM) {
+		if (!modminer_change_clock(thr, false, -(state->dclk.freqM * 2 - MODMINER_DEF_CLOCK)))
+			applog(LOG_WARNING, "%s %u.%u: Failed to set desired initial frequency of %u", modminer->api->name, modminer->device_id, fpgaid, MODMINER_DEF_CLOCK);
 	}
 	state->dclk.freqMDefault = state->dclk.freqM;
-	applog(LOG_WARNING, "%s %u.%u: Frequency set to %u MHz (range: %u-%u)", modminer->api->name, modminer->device_id, fpgaid, state->dclk.freqM * 2, MODMINER_MINIMUM_CLOCK, state->dclk.freqMaxM * 2);
+	applog(LOG_WARNING, "%s %u.%u: Frequency set to %u MHz (range: %u-%u)", modminer->api->name, modminer->device_id, fpgaid, state->dclk.freqM * 2, MODMINER_MIN_CLOCK, state->dclk.freqMaxM * 2);
 
 	mutex_unlock(&modminer->device_mutex);
 
@@ -769,6 +771,67 @@ modminer_fpga_shutdown(struct thr_info *thr)
 	free(thr->cgpu_data);
 }
 
+static char *modminer_set_device(struct cgpu_info *modminer, char *option, char *setting, char *replybuf)
+{
+	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 (!strncasecmp(option, "clock", 5)) {
+		char repr[0x10];
+		int fpgaid, fpgaid_end, multiplier;
+
+		if (option[5])
+			fpgaid = fpgaid_end = abs(atoi(&option[5]));
+		else {
+			fpgaid = 0;
+			fpgaid_end = modminer->threads - 1;
+		}
+		if (fpgaid >= modminer->threads) {
+			sprintf(replybuf, "invalid fpga: '%s' valid range 0-%d", &option[5], modminer->threads - 1);
+			return replybuf;
+		}
+
+		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;
+		}
+
+		multiplier = val / 2;
+		for ( ; fpgaid <= fpgaid_end; ++fpgaid) {
+			struct thr_info *thr = modminer->thr[fpgaid];
+			struct modminer_fpga_state *state = thr->cgpu_data;
+			uint8_t oldFreqM = state->dclk.freqM;
+			signed char delta = (multiplier - oldFreqM) * 2;
+			state->dclk.freqMDefault = multiplier;
+			if (unlikely(!modminer_change_clock(thr, true, delta))) {
+				sprintf(replybuf, "Set clock failed: %s %u.%u",
+				        modminer->api->name, modminer->device_id, fpgaid);
+				return replybuf;
+			}
+
+			sprintf(repr, "%s %u.%u", modminer->api->name, modminer->device_id, fpgaid);
+			dclk_msg_freqchange(repr, oldFreqM * 2, state->dclk.freqM * 2, " on user request");
+		}
+
+		return NULL;
+	}
+
+	sprintf(replybuf, "Unknown option: %s", option);
+	return replybuf;
+}
+
 struct device_api modminer_api = {
 	.dname = "modminer",
 	.name = "MMQ",
@@ -776,6 +839,7 @@ struct device_api modminer_api = {
 	.get_statline_before = get_modminer_statline_before,
 	.get_stats = modminer_get_stats,
 	.get_api_extra_device_status = get_modminer_api_extra_device_status,
+	.set_device = modminer_set_device,
 	.thread_prepare = modminer_fpga_prepare,
 	.thread_init = modminer_fpga_init,
 	.scanhash = modminer_scanhash,

+ 5 - 3
miner.c

@@ -694,9 +694,6 @@ bool detect_stratum(struct pool *pool, char *url)
 	if (!extract_sockaddr(pool, url))
 		return false;
 
-	if (opt_scrypt)
-		return false;
-
 	if (!strncasecmp(url, "stratum+tcp://", 14)) {
 		pool->rpc_url = strdup(url);
 		pool->has_stratum = true;
@@ -2560,10 +2557,12 @@ static uint64_t share_diff(const struct work *work)
 	if (unlikely(!d64))
 		d64 = 1;
 	ret = diffone / d64;
+	mutex_lock(&control_lock);
 	if (ret > best_diff) {
 		best_diff = ret;
 		suffix_string(best_diff, best_share, 0);
 	}
+	mutex_unlock(&control_lock);
 	return ret;
 }
 
@@ -2575,10 +2574,12 @@ static uint64_t scrypt_diff(const struct work *work)
 	if (unlikely(!d64))
 		d64 = 1;
 	ret = scrypt_diffone / d64;
+	mutex_lock(&control_lock);
 	if (ret > best_diff) {
 		best_diff = ret;
 		suffix_string(best_diff, best_share, 0);
 	}
+	mutex_unlock(&control_lock);
 	return ret;
 }
 
@@ -8014,6 +8015,7 @@ begin_bench:
 			total_go++;
 		}
 		pool = select_pool(lagging);
+		lagging = false;
 retry:
 		if (pool->has_stratum) {
 			while (!pool->stratum_active) {

+ 1 - 0
miner.h

@@ -299,6 +299,7 @@ struct device_api {
 	struct api_data *(*get_api_stats)(struct cgpu_info *);
 	bool (*get_stats)(struct cgpu_info *);
 	bool (*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
 	bool (*thread_prepare)(struct thr_info *);