Merge pull request #588 from kanoi/min Minion Updates
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
diff --git a/ASIC-README b/ASIC-README
index 6e82783..e68837c 100644
--- a/ASIC-README
+++ b/ASIC-README
@@ -7,6 +7,7 @@ Currently supported devices include:
- BF1 (bitfury) USB (red and blue)
- KnCminer Mercury, Saturn and Jupiter
- BlackArrow Bitfury
+- BlackArrow Minion
- Bi*fury USB
- Onestring miner USB
- Hexfury USB
@@ -55,6 +56,14 @@ The current BlackArrow Bitfury devices are similar to the Bitfury GPIO mining
boards, with both V1 and V2 controllers, and come up as BaB.
+BlackArrow Minion devices
+
+BlackArrow Minion devices need the --enable-minion option when compiling
+cgminer.
+
+BlackArrow Minion devices are SPI/GPIO mining devices and come up as MBA
+
+
BITFURY devices
Bitfury devices need the --enable-bitfury option when compiling cgminer.
@@ -225,6 +234,7 @@ ASIC SPECIFIC COMMANDS
--hfa-temp-overheat <arg> Set the hashfast overheat throttling temperature (default: 95)
--hfa-temp-target <arg> Set the hashfast target temperature (0 to disable) (default: 88)
--klondike-options <arg> Set klondike options clock:temptarget
+--minion-freq <arg> Set minion chip frequencies in MHz, single value or comma list, range 100-1400 (default: 1000)
--nfu-bits <arg> Set nanofury bits for overclocking, range 32-63 (default: 50)
diff --git a/README b/README
index 7e59bd7..c3eb8d6 100644
--- a/README
+++ b/README
@@ -218,6 +218,7 @@ Options for both config file and command line:
--load-balance Change multipool strategy from failover to quota based balance
--log|-l <arg> Interval in seconds between log output (default: 5)
--lowmem Minimise caching of shares for low memory applications
+--minion-freq <arg> Set minion chip frequencies in MHz, single value or comma list, range 100-1400 (default: 1000)
--monitor|-m <arg> Use custom pipe cmd for output messages
--nfu-bits <arg> Set nanofury bits for overclocking, range 32-63 (default: 50)
--net-delay Impose small delays in networking to not overload slow routers
diff --git a/api.c b/api.c
index ed28b42..eebd2a0 100644
--- a/api.c
+++ b/api.c
@@ -2190,14 +2190,16 @@ static void devstatus(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __ma
io_close(io_data);
}
-static void edevstatus(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
+static void edevstatus(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
{
bool io_open = false;
int devcount = 0;
int numasc = 0;
int numpga = 0;
int i;
+#ifdef USE_USBUTILS
time_t howoldsec = 0;
+#endif
#ifdef HAVE_AN_ASIC
numasc = numascs();
@@ -2212,8 +2214,10 @@ static void edevstatus(struct io_data *io_data, __maybe_unused SOCKETTYPE c, cha
return;
}
+#ifdef USE_USBUTILS
if (param && *param)
howoldsec = (time_t)atoi(param);
+#endif
message(io_data, MSG_DEVS, 0, NULL, isjson);
if (isjson)
@@ -3315,17 +3319,19 @@ static void minerstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m
io_close(io_data);
}
-static void minerestats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
+static void minerestats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
{
struct cgpu_info *cgpu;
bool io_open = false;
struct api_data *extra;
char id[20];
int i, j;
+#ifdef USE_USBUTILS
time_t howoldsec = 0;
if (param && *param)
howoldsec = (time_t)atoi(param);
+#endif
message(io_data, MSG_MINESTATS, 0, NULL, isjson);
if (isjson)
diff --git a/cgminer.c b/cgminer.c
index 265dd99..10053ab 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -238,6 +238,9 @@ static char *opt_set_bitmain_freq;
static char *opt_set_hfa_fan;
#endif
static char *opt_set_null;
+#ifdef USE_MINION
+char *opt_minion_freq;
+#endif
#ifdef USE_USBUTILS
char *opt_usb_select = NULL;
@@ -1309,6 +1312,11 @@ static struct opt_table opt_config_table[] = {
OPT_WITHOUT_ARG("--lowmem",
opt_set_bool, &opt_lowmem,
"Minimise caching of shares for low memory applications"),
+#ifdef USE_MINION
+ OPT_WITH_ARG("--minion-freq",
+ opt_set_charp, NULL, &opt_minion_freq,
+ "Set minion chip frequencies in MHz, single value or comma list, range 100-1400 (default: 1000)"),
+#endif
#if defined(unix) || defined(__APPLE__)
OPT_WITH_ARG("--monitor|-m",
opt_set_charp, NULL, &opt_stderr_cmd,
diff --git a/driver-minion.c b/driver-minion.c
index 4c12f8c..ffa1f4e 100644
--- a/driver-minion.c
+++ b/driver-minion.c
@@ -10,6 +10,8 @@
#include "config.h"
#include "compat.h"
#include "miner.h"
+#include <ctype.h>
+#include <math.h>
#ifndef LINUX
static void minion_detect(__maybe_unused bool hotplug)
@@ -210,6 +212,29 @@ struct minion_header {
#define MINION_CHIP_SIG_SHIFT3 (((MINION_CHIP_SIG & 0xffffff00) >> 8) & 0x00ffffff)
#define MINION_CHIP_SIG_SHIFT4 (((MINION_CHIP_SIG & 0xffff0000) >> 16) & 0x0000ffff)
+#define MINION_FREQ_MIN 1
+#define MINION_FREQ_DEF 10
+#define MINION_FREQ_MAX 14
+#define MINION_FREQ_FACTOR 100
+
+static uint32_t minion_freq[] = {
+ 0x0,
+ 0x205032, // 1 = 100Mhz
+ 0x203042, // 2 = 200Mhz
+ 0x20204B, // 3 = 300Mhz
+ 0x201042, // 4 = 400Mhz
+ 0x201053, // 5 = 500Mhz
+ 0x200032, // 6 = 600Mhz
+ 0x20003A, // 7 = 700Mhz
+ 0x200042, // 8 = 800Mhz
+ 0x20004B, // 9 = 900Mhz
+ 0x200053, // 10 = 1000Mhz
+ 0x21005B, // 11 = 1100Mhz
+ 0x210064, // 12 = 1200Mhz
+ 0x21006C, // 13 = 1300Mhz
+ 0x210074 // 14 = 1400Mhz
+};
+
#define STA_TEMP(_sta) ((uint16_t)((_sta)[3] & 0x1f))
#define STA_CORES(_sta) ((uint16_t)((_sta)[2]))
#define STA_FREQ(_sta) ((uint32_t)((_sta)[1]) * 0x100 + (uint32_t)((_sta)[0]))
@@ -385,8 +410,9 @@ typedef struct k_list {
#define K_RLOCK(_list) cg_rlock(_list->lock)
#define K_RUNLOCK(_list) cg_runlock(_list->lock)
-// Set this to 0 to remove iostats processing
-#define DO_IO_STATS 1
+// Set this to 1 to enable iostats processing
+// N.B. it slows down mining
+#define DO_IO_STATS 0
#if DO_IO_STATS
#define IO_STAT_NOW(_tv) cgtime(_tv)
@@ -511,6 +537,7 @@ struct minion_info {
// TODO: need to track disabled chips - done?
int chips;
bool chip[MINION_CHIPS];
+ int init_freq[MINION_CHIPS];
uint32_t next_task_id;
@@ -1067,12 +1094,13 @@ static int build_cmd(struct cgpu_info *minioncgpu, struct minion_info *minioninf
return reply;
}
-// TODO: hard coded for now
static void init_chip(struct cgpu_info *minioncgpu, struct minion_info *minioninfo, int chip)
{
uint8_t rbuf[MINION_BUFSIZ];
uint8_t data[4];
__maybe_unused int reply;
+ int choice;
+ uint32_t freq;
// Complete chip reset
data[0] = 0x00;
@@ -1103,6 +1131,20 @@ static void init_chip(struct cgpu_info *minioncgpu, struct minion_info *minionin
reply = build_cmd(minioncgpu, minioninfo,
chip, WRITE_ADDR(MINION_SYS_MISC_CTL),
rbuf, 0, data);
+
+ // Set chip frequency
+ choice = minioninfo->init_freq[chip];
+ if (choice < MINION_FREQ_MIN || choice > MINION_FREQ_MAX)
+ choice = MINION_FREQ_DEF;
+ freq = minion_freq[choice];
+ data[0] = (uint8_t)(freq & 0xff);
+ data[1] = (uint8_t)(((freq & 0xff00) >> 8) & 0xff);
+ data[2] = (uint8_t)(((freq & 0xff0000) >> 16) & 0xff);
+ data[3] = (uint8_t)(((freq & 0xff000000) >> 24) & 0xff);
+
+ reply = build_cmd(minioncgpu, minioninfo,
+ chip, WRITE_ADDR(MINION_SYS_FREQ_CTL),
+ rbuf, 0, data);
}
// TODO: hard coded for now
@@ -1576,6 +1618,40 @@ static bool minion_init_gpio_interrupt(struct cgpu_info *minioncgpu, struct mini
return true;
}
+static void minion_process_options(struct minion_info *minioninfo)
+{
+ int last_freq = MINION_FREQ_DEF;
+ char *freq, *comma, *buf;
+ int i;
+
+ if (opt_minion_freq && *opt_minion_freq) {
+ buf = freq = strdup(opt_minion_freq);
+ comma = strchr(freq, ',');
+ if (comma)
+ *(comma++) = '\0';
+
+ for (i = 0; i < MINION_CHIPS; i++) {
+ if (freq && isdigit(*freq)) {
+ last_freq = (int)round((double)atoi(freq) / (double)MINION_FREQ_FACTOR);
+ if (last_freq < MINION_FREQ_MIN)
+ last_freq = MINION_FREQ_MIN;
+ if (last_freq > MINION_FREQ_MAX)
+ last_freq = MINION_FREQ_MAX;
+
+ freq = comma;
+ if (comma) {
+ comma = strchr(freq, ',');
+ if (comma)
+ *(comma++) = '\0';
+ }
+ }
+ minioninfo->init_freq[i] = last_freq;
+ }
+
+ free(buf);
+ }
+}
+
static void minion_detect(bool hotplug)
{
struct cgpu_info *minioncgpu = NULL;
@@ -1607,6 +1683,11 @@ static void minion_detect(bool hotplug)
mutex_init(&(minioninfo->spi_lock));
mutex_init(&(minioninfo->sta_lock));
+ for (i = 0; i < MINION_CHIPS; i++)
+ minioninfo->init_freq[i] = MINION_FREQ_DEF;
+
+ minion_process_options(minioninfo);
+
applog(LOG_WARNING, "%s: checking for chips ...", minioncgpu->drv->dname);
minion_detect_chips(minioncgpu, minioninfo);
@@ -1903,12 +1984,8 @@ static void *minion_spi_reply(void *userdata)
K_WUNLOCK(minioninfo->rnonce_list);
cgsem_post(&(minioninfo->nonce_ready));
} else {
- applog(LOG_ERR, "%s%i: Invalid task_id - chip %d core %d task 0x%04x nonce 0x%08x",
- minioncgpu->drv->name, minioncgpu->device_id,
- DATAR(item)->chip,
- DATAR(item)->core,
- DATAR(item)->task_id,
- DATAR(item)->nonce);
+ applog(LOG_ERR, "%s%i: Invalid task_id - chip %d",
+ minioncgpu->drv->name, minioncgpu->device_id, chip);
}
}
}
@@ -2565,6 +2642,30 @@ static int64_t minion_scanwork(__maybe_unused struct thr_info *thr)
return hashcount;
}
+static const char *min_temp_0 = "<40";
+static const char *min_temp_1 = "40-60";
+static const char *min_temp_3 = "60-80";
+static const char *min_temp_7 = "80-100";
+static const char *min_temp_15 = ">100";
+static const char *min_temp_invalid = "?";
+
+static const char *temp_str(uint16_t temp)
+{
+ switch (temp) {
+ case 0:
+ return min_temp_0;
+ case 1:
+ return min_temp_1;
+ case 3:
+ return min_temp_3;
+ case 7:
+ return min_temp_7;
+ case 15:
+ return min_temp_15;
+ }
+ return min_temp_invalid;
+}
+
static void minion_get_statline_before(char *buf, size_t bufsiz, struct cgpu_info *minioncgpu)
{
struct minion_info *minioninfo = (struct minion_info *)(minioncgpu->device_data);
@@ -2583,8 +2684,8 @@ static void minion_get_statline_before(char *buf, size_t bufsiz, struct cgpu_inf
}
mutex_unlock(&(minioninfo->sta_lock));
- tailsprintf(buf, bufsiz, "max%3dC Ch:%2d Co:%d",
- (int)max_temp, minioninfo->chips, (int)cores);
+ tailsprintf(buf, bufsiz, "max%sC Ch:%2d Co:%d",
+ temp_str(max_temp), minioninfo->chips, (int)cores);
}
#define CHIPS_PER_STAT 8
@@ -2610,9 +2711,19 @@ static struct api_data *minion_api_stats(struct cgpu_info *minioncgpu)
max_chip = 0;
for (chip = 0; chip < MINION_CHIPS; chip++)
- if (minioninfo->chip[chip])
+ if (minioninfo->chip[chip]) {
max_chip = chip;
+ snprintf(buf, sizeof(buf), "Chip %d Temperature", chip);
+ root = api_add_const(root, buf, temp_str(minioninfo->chip_status[chip].temp), false);
+ snprintf(buf, sizeof(buf), "Chip %d Cores", chip);
+ root = api_add_uint16(root, buf, &(minioninfo->chip_status[chip].cores), true);
+ snprintf(buf, sizeof(buf), "Chip %d Frequency", chip);
+ root = api_add_uint32(root, buf, &(minioninfo->chip_status[chip].freq), true);
+ snprintf(buf, sizeof(buf), "Chip %d InitFreq", chip);
+ root = api_add_int(root, buf, &(minioninfo->init_freq[chip]), true);
+ }
+
for (i = 0; i <= max_chip; i += CHIPS_PER_STAT) {
to = i + CHIPS_PER_STAT - 1;
if (to > max_chip)
@@ -2682,6 +2793,7 @@ static struct api_data *minion_api_stats(struct cgpu_info *minioncgpu)
root = api_add_int(root, "RFree Count", &(minioninfo->rfree_list->count), true);
root = api_add_int(root, "RNonce Count", &(minioninfo->rnonce_list->count), true);
+#if DO_IO_STATS
#define sta_api(_name, _iostat) \
do { \
if ((_iostat).count) { \
@@ -2725,6 +2837,7 @@ static struct api_data *minion_api_stats(struct cgpu_info *minioncgpu)
minioncgpu->drv->name, minioncgpu->device_id,
total_secs, buf, data);
}
+#endif
root = api_add_elapsed(root, "Elapsed", &(total_secs), true);
diff --git a/miner.h b/miner.h
index 388c433..3189842 100644
--- a/miner.h
+++ b/miner.h
@@ -1008,6 +1008,9 @@ extern char *opt_bitmine_a1_options;
extern char *opt_bitmain_options;
extern bool opt_bitmain_hwerror;
#endif
+#ifdef USE_MINION
+extern char *opt_minion_freq;
+#endif
#ifdef USE_USBUTILS
extern char *opt_usb_select;
extern int opt_usbdump;