Browse Source

icarus: Replace icarus-options with set_device_funcs (including wrapper for single icarus-options case)

Luke Dashjr 12 years ago
parent
commit
e845c353ff
3 changed files with 117 additions and 114 deletions
  1. 86 109
      driver-icarus.c
  2. 1 0
      icarus-common.h
  3. 30 5
      miner.c

+ 86 - 109
driver-icarus.c

@@ -146,24 +146,10 @@ static const char *MODE_UNKNOWN_STR = "unknown";
 #define END_CONDITION 0x0000ffff
 #define DEFAULT_DETECT_THRESHOLD 1
 
-// Looking for options in --icarus-timing and --icarus-options:
-//
-// Code increments this each time we start to look at a device
-// However, this means that if other devices are checked by
-// the Icarus code (e.g. BFL) they will count in the option offset
-//
-// This, however, is deterministic so that's OK
-//
-// If we were to increment after successfully finding an Icarus
-// that would be random since an Icarus may fail and thus we'd
-// not be able to predict the option order
-//
-// This also assumes that serial_detect() checks them sequentially
-// and in the order specified on the command line
-//
 static int option_offset = -1;
 
 BFG_REGISTER_DRIVER(icarus_drv)
+extern const struct bfg_set_device_definition icarus_set_device_funcs[];
 
 extern void convert_icarus_to_cairnsmore(struct cgpu_info *);
 
@@ -454,102 +440,12 @@ static uint32_t mask(int work_division)
 		nonce_mask = 0x1fffffff;
 		break;
 	default:
-		quit(1, "Invalid2 icarus-options for work_division (%d) must be 1, 2, 4 or 8", work_division);
+		quit(1, "Invalid2 work_division (%d) must be 1, 2, 4 or 8", work_division);
 	}
 
 	return nonce_mask;
 }
 
-static void get_options(int this_option_offset, struct ICARUS_INFO *info)
-{
-	int *baud = &info->baud;
-	int *work_division = &info->work_division;
-	int *fpga_count = &info->fpga_count;
-
-	char buf[BUFSIZ+1];
-	char *ptr, *comma, *colon, *colon2;
-	size_t max;
-	int i, tmp;
-
-	if (opt_icarus_options == NULL)
-		buf[0] = '\0';
-	else {
-		ptr = opt_icarus_options;
-		for (i = 0; i < this_option_offset; i++) {
-			comma = strchr(ptr, ',');
-			if (comma == NULL)
-				break;
-			ptr = comma + 1;
-		}
-
-		comma = strchr(ptr, ',');
-		if (comma == NULL)
-			max = strlen(ptr);
-		else
-			max = comma - ptr;
-
-		if (max > BUFSIZ)
-			max = BUFSIZ;
-		strncpy(buf, ptr, max);
-		buf[max] = '\0';
-	}
-
-	if (*buf) {
-		colon = strchr(buf, ':');
-		if (colon)
-			*(colon++) = '\0';
-
-		if (*buf) {
-			tmp = atoi(buf);
-			if (!valid_baud(*baud = tmp))
-				quit(1, "Invalid icarus-options for baud (%s)", buf);
-		}
-
-		if (colon && *colon) {
-			colon2 = strchr(colon, ':');
-			if (colon2)
-				*(colon2++) = '\0';
-
-			if (*colon) {
-				info->user_set |= IUS_WORK_DIVISION;
-				tmp = atoi(colon);
-				if (tmp == 1 || tmp == 2 || tmp == 4 || tmp == 8) {
-					*work_division = tmp;
-					*fpga_count = tmp;	// default to the same
-				} else {
-					quit(1, "Invalid icarus-options for work_division (%s) must be 1, 2, 4 or 8", colon);
-				}
-			}
-
-			if (colon2 && *colon2) {
-			  colon = strchr(colon2, ':');
-			  if (colon)
-					*(colon++) = '\0';
-
-			  if (*colon2) {
-				info->user_set |= IUS_FPGA_COUNT;
-				tmp = atoi(colon2);
-				if (tmp > 0 && tmp <= *work_division)
-					*fpga_count = tmp;
-				else {
-					quit(1, "Invalid icarus-options for fpga_count (%s) must be >0 and <=work_division (%d)", colon2, *work_division);
-				}
-			  }
-
-			  if (colon && *colon) {
-					colon2 = strchr(colon, '-') ?: "";
-					if (*colon2)
-						*(colon2++) = '\0';
-					if (strchr(colon, 'r'))
-						info->reopen_mode = IRM_CYCLE;
-					if (strchr(colon2, 'r'))
-						info->reopen_mode = IRM_NEVER;
-			  }
-			}
-		}
-	}
-}
-
 // Number of bytes remaining after reading a nonce from Icarus
 int icarus_excess_nonce_size(int fd, struct ICARUS_INFO *info)
 {
@@ -599,7 +495,7 @@ bool icarus_detect_custom(const char *devpath, struct device_drv *api, struct IC
 	unsigned char ob_bin[64], nonce_bin[ICARUS_NONCE_SIZE];
 	char nonce_hex[(sizeof(nonce_bin) * 2) + 1];
 
-	get_options(this_option_offset, info);
+	drv_set_defaults2(api, icarus_set_device_funcs, info);
 
 	int baud = info->baud;
 	int work_division = info->work_division;
@@ -666,6 +562,7 @@ bool icarus_detect_custom(const char *devpath, struct device_drv *api, struct IC
 	icarus->device_path = strdup(devpath);
 	icarus->device_fd = -1;
 	icarus->threads = 1;
+	icarus->set_device_funcs = icarus_set_device_funcs;
 	add_cgpu(icarus);
 
 	applog(LOG_INFO, "Found %"PRIpreprv" at %s",
@@ -1109,8 +1006,13 @@ keepwaiting:
 			dclk_errorCount(&info->dclk, qsec);
 	}
 	
-	// Force a USB close/reopen on any hw error
-	if (was_hw_error && info->reopen_mode != IRM_CYCLE) {
+	// Force a USB close/reopen on any hw error (or on request, eg for baud change)
+	if (was_hw_error || info->reopen_now)
+	{
+		info->reopen_now = false;
+		if (info->reopen_mode == IRM_CYCLE)
+		{}  // Do nothing here, we reopen after sending the job
+		else
 		if (!icarus_reopen(icarus, state, &fd))
 			state->firstrun = true;
 	}
@@ -1353,12 +1255,87 @@ static struct api_data *icarus_drv_stats(struct cgpu_info *cgpu)
 	return root;
 }
 
+static
+const char *icarus_set_baud(struct cgpu_info * const proc, const char * const optname, const char * const newvalue, char * const replybuf, enum bfg_set_device_replytype * const out_success)
+{
+	struct ICARUS_INFO * const info = proc->device_data;
+	const int baud = atoi(newvalue);
+	if (!valid_baud(baud))
+		return "Invalid baud setting";
+	if (info->baud != baud)
+	{
+		info->baud = baud;
+		info->reopen_now = true;
+	}
+	return NULL;
+}
+
+static
+const char *icarus_set_work_division(struct cgpu_info * const proc, const char * const optname, const char * const newvalue, char * const replybuf, enum bfg_set_device_replytype * const out_success)
+{
+	struct ICARUS_INFO * const info = proc->device_data;
+	const int work_division = atoi(newvalue);
+	if (!(work_division == 1 || work_division == 2 || work_division == 4 || work_division == 8))
+		return "Invalid work_division: must be 1, 2, 4 or 8";
+	if (info->user_set & IUS_FPGA_COUNT)
+	{
+		if (info->fpga_count > work_division)
+			return "work_division must be >= fpga_count";
+	}
+	else
+		info->fpga_count = work_division;
+	info->user_set |= IUS_WORK_DIVISION;
+	info->work_division = work_division;
+	info->nonce_mask = mask(work_division);
+	return NULL;
+}
+
+static
+const char *icarus_set_fpga_count(struct cgpu_info * const proc, const char * const optname, const char * const newvalue, char * const replybuf, enum bfg_set_device_replytype * const out_success)
+{
+	struct ICARUS_INFO * const info = proc->device_data;
+	const int fpga_count = atoi(newvalue);
+	if (fpga_count < 1 || fpga_count > info->work_division)
+		return "Invalid fpga_count: must be >0 and <=work_division";
+	info->fpga_count = fpga_count;
+	return NULL;
+}
+
+static
+const char *icarus_set_reopen(struct cgpu_info * const proc, const char * const optname, const char * const newvalue, char * const replybuf, enum bfg_set_device_replytype * const out_success)
+{
+	struct ICARUS_INFO * const info = proc->device_data;
+	if ((!strcasecmp(newvalue, "never")) || !strcasecmp(newvalue, "-r"))
+		info->reopen_mode = IRM_NEVER;
+	else
+	if (!strcasecmp(newvalue, "timeout"))
+		info->reopen_mode = IRM_TIMEOUT;
+	else
+	if ((!strcasecmp(newvalue, "cycle")) || !strcasecmp(newvalue, "r"))
+		info->reopen_mode = IRM_CYCLE;
+	else
+	if (!strcasecmp(newvalue, "now"))
+		info->reopen_now = true;
+	else
+		return "Invalid reopen mode";
+	return NULL;
+}
+
 static void icarus_shutdown(struct thr_info *thr)
 {
 	do_icarus_close(thr);
 	free(thr->cgpu_data);
 }
 
+const struct bfg_set_device_definition icarus_set_device_funcs[] = {
+	// NOTE: Order of parameters below is important for --icarus-options
+	{"baud"         , icarus_set_baud         , "serial baud rate"},
+	{"work_division", icarus_set_work_division, "number of pieces work is split into"},
+	{"fpga_count"   , icarus_set_fpga_count   , "number of chips working on pieces"},
+	{"reopen"       , icarus_set_reopen       , "how often to reopen device: never, timeout, cycle, (or now for a one-shot reopen)"},
+	{NULL},
+};
+
 struct device_drv icarus_drv = {
 	.dname = "icarus",
 	.name = "ICA",

+ 1 - 0
icarus-common.h

@@ -100,6 +100,7 @@ struct ICARUS_INFO {
 	int fpga_count;
 	uint32_t nonce_mask;
 	enum icarus_reopen_mode reopen_mode;
+	bool reopen_now;
 	uint8_t user_set;
 	bool continue_search;
 

+ 30 - 5
miner.c

@@ -214,7 +214,6 @@ bool opt_api_network;
 bool opt_delaynet;
 bool opt_disable_pool;
 static bool no_work;
-char *opt_icarus_options = NULL;
 char *opt_icarus_timing = NULL;
 bool opt_worktime;
 bool opt_weighed_stats;
@@ -1768,10 +1767,38 @@ static char *set_api_mcast_des(const char *arg)
 }
 
 #ifdef USE_ICARUS
+extern const struct bfg_set_device_definition icarus_set_device_funcs[];
+
 static char *set_icarus_options(const char *arg)
 {
-	opt_set_charp(arg, &opt_icarus_options);
-
+	if (strchr(arg, ','))
+		return "icarus-options no longer supports comma-delimited syntax, see README.FPGA for better control";
+	applog(LOG_WARNING, "icarus-options is deprecated! See README.FPGA for better control");
+	
+	char *opts = strdup(arg), *argdup;
+	argdup = opts;
+	const struct bfg_set_device_definition *sdf = icarus_set_device_funcs;
+	const char *drivers[] = {"antminer", "cairnsmore", "erupter", "icarus"};
+	char buf[0x100], *saveptr, *opt;
+	for (int i = 0; i < 4; ++i, ++sdf)
+	{
+		opt = strtok_r(opts, ":", &saveptr);
+		opts = NULL;
+		
+		if (!opt)
+			break;
+		
+		if (!opt[0])
+			continue;
+		
+		for (int j = 0; j < 4; ++j)
+		{
+			snprintf(buf, sizeof(buf), "%s:%s=%s", drivers[j], sdf->optname, opt);
+			applog(LOG_DEBUG, "%s: Using --set-device %s", __func__, buf);
+			string_elist_add(buf, &opt_set_device_list);
+		}
+	}
+	free(argdup);
 	return NULL;
 }
 
@@ -6650,8 +6677,6 @@ void write_config(FILE *fcfg)
 		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));
-	if (opt_icarus_options)
-		fprintf(fcfg, ",\n\"icarus-options\" : \"%s\"", json_escape(opt_icarus_options));
 	if (opt_icarus_timing)
 		fprintf(fcfg, ",\n\"icarus-timing\" : \"%s\"", json_escape(opt_icarus_timing));
 #ifdef USE_KLONDIKE