Merge pull request #597 from BitSyncom/rebase More features added on Avalon2/3 driver
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
diff --git a/cgminer.c b/cgminer.c
index 63f8201..c3da2de 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -1117,6 +1117,9 @@ static struct opt_table opt_config_table[] = {
OPT_WITH_CBARG("--avalon2-voltage",
set_avalon2_voltage, NULL, &opt_set_avalon2_voltage,
"Set Avalon2 core voltage, in millivolts"),
+ OPT_WITH_ARG("--avalon2-cutoff",
+ set_int_0_to_100, opt_show_intval, &opt_avalon2_overheat,
+ "Set Avalon2 overheat cut off temperature"),
#endif
#ifdef USE_BAB
OPT_WITH_ARG("--bab-options",
diff --git a/driver-avalon2.c b/driver-avalon2.c
index 5261054..1a318ab 100644
--- a/driver-avalon2.c
+++ b/driver-avalon2.c
@@ -51,6 +51,8 @@ int opt_avalon2_fan_max = AVA2_DEFAULT_FAN_MAX;
int opt_avalon2_voltage_min = AVA2_DEFAULT_VOLTAGE;
int opt_avalon2_voltage_max = AVA2_DEFAULT_VOLTAGE_MAX;
+int opt_avalon2_overheat = AVALON2_TEMP_OVERHEAT;
+
static inline uint8_t rev8(uint8_t d)
{
int i;
@@ -163,6 +165,17 @@ static inline int get_temp_max(struct avalon2_info *info)
return info->temp_max;
}
+static inline int get_currect_temp_max(struct avalon2_info *info)
+{
+ int i;
+ int t = 0;
+ for (i = 0; i < 2 * AVA2_DEFAULT_MODULARS; i++) {
+ if (t <= info->temp[i])
+ t = info->temp[i];
+ }
+ return t;
+}
+
/* http://www.onsemi.com/pub_link/Collateral/ADP3208D.PDF */
static inline uint32_t encode_voltage(uint32_t v)
{
@@ -209,7 +222,7 @@ static int decode_pkg(struct thr_info *thr, struct avalon2_ret *ar, uint8_t *pkg
memcpy(&modular_id, ar->data + 28, 4);
modular_id = be32toh(modular_id);
- if (modular_id == 3)
+ if (modular_id > 3)
modular_id = 0;
switch(type) {
@@ -225,7 +238,7 @@ static int decode_pkg(struct thr_info *thr, struct avalon2_ret *ar, uint8_t *pkg
miner = be32toh(miner);
pool_no = be32toh(pool_no);
if (miner >= AVA2_DEFAULT_MINERS ||
- modular_id >= AVA2_DEFAULT_MINERS ||
+ modular_id >= AVA2_DEFAULT_MINERS ||
pool_no >= total_pools ||
pool_no < 0) {
applog(LOG_DEBUG, "Avalon2: Wrong miner/pool/id no %d,%d,%d", miner, pool_no, modular_id);
@@ -429,7 +442,7 @@ static int avalon2_stratum_pkgs(int fd, struct pool *pool, struct thr_info *thr)
while (avalon2_send_pkg(fd, &pkg, thr) != AVA2_SEND_OK)
;
- set_target(target, pool->swork.diff);
+ set_target(target, pool->sdiff);
memcpy(pkg.data, target, 32);
if (opt_debug) {
char *target_str;
@@ -529,7 +542,7 @@ static bool avalon2_detect_one(const char *devpath)
struct avalon2_info *info;
int ackdetect;
int fd;
- int tmp, i, modular[3];
+ int tmp, i, modular[AVA2_DEFAULT_MODULARS];
char mm_version[AVA2_DEFAULT_MODULARS][16];
struct cgpu_info *avalon2;
@@ -547,7 +560,7 @@ static bool avalon2_detect_one(const char *devpath)
for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) {
modular[i] = 0;
- strcpy(mm_version[i], "NONE");
+ strcpy(mm_version[i], AVA2_MM_VERNULL);
/* Send out detect pkg */
memset(detect_pkg.data, 0, AVA2_P_DATA_LEN);
tmp = be32toh(i);
@@ -563,7 +576,7 @@ static bool avalon2_detect_one(const char *devpath)
memcpy(mm_version[i], ret_pkg.data, 15);
mm_version[i][15] = '\0';
}
- if (!modular[0] && !modular[1] && !modular[2])
+ if (!modular[0] && !modular[1] && !modular[2] && !modular[3])
return false;
/* We have a real Avalon! */
@@ -585,6 +598,7 @@ static bool avalon2_detect_one(const char *devpath)
strcpy(info->mm_version[0], mm_version[0]);
strcpy(info->mm_version[1], mm_version[1]);
strcpy(info->mm_version[2], mm_version[2]);
+ strcpy(info->mm_version[3], mm_version[3]);
info->baud = AVA2_IO_SPEED;
info->fan_pwm = AVA2_DEFAULT_FAN_PWM;
@@ -597,6 +611,7 @@ static bool avalon2_detect_one(const char *devpath)
info->modulars[0] = modular[0];
info->modulars[1] = modular[1];
info->modulars[2] = modular[2]; /* Enable modular */
+ info->modulars[3] = modular[3]; /* Enable modular */
info->fd = -1;
/* Set asic to idle mode after detect */
@@ -696,10 +711,14 @@ static int64_t avalon2_scanhash(struct thr_info *thr)
pool = current_pool();
if (!pool->has_stratum)
quit(1, "Avalon2: Miner Manager have to use stratum pool");
- if (pool->coinbase_len > AVA2_P_COINBASE_SIZE)
- quit(1, "Avalon2: Miner Manager pool coinbase length have to less then %d", AVA2_P_COINBASE_SIZE);
- if (pool->merkles > AVA2_P_MERKLES_COUNT)
- quit(1, "Avalon2: Miner Manager merkles have to less then %d", AVA2_P_MERKLES_COUNT);
+ if (pool->coinbase_len > AVA2_P_COINBASE_SIZE) {
+ applog(LOG_ERR, "Avalon2: Miner Manager pool coinbase length have to less then %d", AVA2_P_COINBASE_SIZE);
+ return 0;
+ }
+ if (pool->merkles > AVA2_P_MERKLES_COUNT) {
+ applog(LOG_ERR, "Avalon2: Miner Manager merkles have to less then %d", AVA2_P_MERKLES_COUNT);
+ return 0;
+ }
info->diff = (int)pool->swork.diff - 1;
info->pool_no = pool->pool_no;
@@ -719,7 +738,12 @@ static int64_t avalon2_scanhash(struct thr_info *thr)
tmp = be32toh(info->fan_pwm);
memcpy(send_pkg.data, &tmp, 4);
- tmp = encode_voltage(info->set_voltage);
+ applog(LOG_ERR, "Avalon2: Temp max: %d, Cut off temp: %d",
+ get_currect_temp_max(info), opt_avalon2_overheat);
+ if (get_currect_temp_max(info) >= opt_avalon2_overheat)
+ tmp = encode_voltage(0);
+ else
+ tmp = encode_voltage(info->set_voltage);
tmp = be32toh(tmp);
memcpy(send_pkg.data + 4, &tmp, 4);
@@ -756,26 +780,61 @@ static struct api_data *avalon2_api_stats(struct cgpu_info *cgpu)
{
struct api_data *root = NULL;
struct avalon2_info *info = cgpu->device_data;
- int i, a, b;
+ int i, j, a, b;
char buf[24];
double hwp;
+ int devtype[AVA2_DEFAULT_MODULARS];
+ int minerindex, minercount;
+
for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) {
+ devtype[i] = AVA2_ID_AVAX;
+ if (!strncmp((char *)&(info->mm_version[i]), AVA2_MM_VERNULL, 4))
+ continue;
+ if (!strncmp((char *)&(info->mm_version[i]), AVA2_FW2_PREFIXSTR, 2))
+ devtype[i] = AVA2_ID_AVA2;
+ if (!strncmp((char *)&(info->mm_version[i]), AVA2_FW3_PREFIXSTR, 2))
+ devtype[i] = AVA2_ID_AVA3;
+
sprintf(buf, "ID%d MM Version", i + 1);
root = api_add_string(root, buf, &(info->mm_version[i]), false);
}
- for (i = 0; i < AVA2_DEFAULT_MINERS * AVA2_DEFAULT_MODULARS; i++) {
- sprintf(buf, "Match work count%02d", i + 1);
- root = api_add_int(root, buf, &(info->matching_work[i]), false);
+
+ minerindex = 0;
+ minercount = 0;
+ for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) {
+ if (devtype[i] == AVA2_ID_AVAX) {
+ minerindex += AVA2_DEFAULT_MINERS;
+ continue;
+ }
+
+ if (devtype[i] == AVA2_ID_AVA2)
+ minercount = AVA2_DEFAULT_MINERS;
+
+ if (devtype[i] == AVA2_ID_AVA3)
+ minercount = AVA2_AVA3_MINERS;
+
+ for (j = minerindex; j < (minerindex + minercount); j++) {
+ sprintf(buf, "Match work count%02d", j+1);
+ root = api_add_int(root, buf, &(info->matching_work[j]), false);
+ }
+ minerindex += AVA2_DEFAULT_MINERS;
}
+
for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) {
+ if(devtype[i] == AVA2_ID_AVAX)
+ continue;
sprintf(buf, "Local works%d", i + 1);
root = api_add_int(root, buf, &(info->local_works[i]), false);
}
for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) {
+ if(devtype[i] == AVA2_ID_AVAX)
+ continue;
sprintf(buf, "Hardware error works%d", i + 1);
root = api_add_int(root, buf, &(info->hw_works[i]), false);
}
for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) {
+ if(devtype[i] == AVA2_ID_AVAX)
+ continue;
a = info->hw_works[i];
b = info->local_works[i];
hwp = b ? ((double)a / (double)b) : 0;
@@ -784,27 +843,36 @@ static struct api_data *avalon2_api_stats(struct cgpu_info *cgpu)
root = api_add_percent(root, buf, &hwp, true);
}
for (i = 0; i < 2 * AVA2_DEFAULT_MODULARS; i++) {
+ if(devtype[i/2] == AVA2_ID_AVAX)
+ continue;
sprintf(buf, "Temperature%d", i + 1);
root = api_add_int(root, buf, &(info->temp[i]), false);
}
for (i = 0; i < 2 * AVA2_DEFAULT_MODULARS; i++) {
+ if(devtype[i/2] == AVA2_ID_AVAX)
+ continue;
sprintf(buf, "Fan%d", i + 1);
root = api_add_int(root, buf, &(info->fan[i]), false);
}
for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) {
+ if(devtype[i] == AVA2_ID_AVAX)
+ continue;
sprintf(buf, "Voltage%d", i + 1);
root = api_add_int(root, buf, &(info->get_voltage[i]), false);
}
for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) {
+ if(devtype[i] == AVA2_ID_AVAX)
+ continue;
sprintf(buf, "Frequency%d", i + 1);
root = api_add_int(root, buf, &(info->get_frequency[i]), false);
}
for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) {
+ if(devtype[i] == AVA2_ID_AVAX)
+ continue;
sprintf(buf, "Power good %02x", i + 1);
- root = api_add_int(root, buf, &(info->power_good[i]), false);
+ root = api_add_int(root, buf, &(info->power_good[i]), false);
}
-
return root;
}
diff --git a/driver-avalon2.h b/driver-avalon2.h
index ca2e2df..ee1fb61 100644
--- a/driver-avalon2.h
+++ b/driver-avalon2.h
@@ -22,7 +22,8 @@
#define AVA2_IO_SPEED 115200
#define AVA2_DEFAULT_MINERS 10
-#define AVA2_DEFAULT_MODULARS 3
+#define AVA2_AVA3_MINERS 5
+#define AVA2_DEFAULT_MODULARS 4
#define AVA2_PWM_MAX 0x3FF
#define AVA2_DEFAULT_FAN_PWM 80 /* % */
@@ -37,6 +38,8 @@
#define AVA2_DEFAULT_FREQUENCY_MIN 300
#define AVA2_DEFAULT_FREQUENCY_MAX 2000
+#define AVALON2_TEMP_OVERHEAT 88
+
/* Avalon2 protocol package type */
#define AVA2_H1 'A'
#define AVA2_H2 'V'
@@ -67,6 +70,16 @@
#define AVA2_P_TEST_RET 26
/* Avalon2 protocol package type */
+/* Avalon2/3 firmware prefix */
+#define AVA2_FW2_PREFIXSTR "20"
+#define AVA2_FW3_PREFIXSTR "33"
+
+#define AVA2_MM_VERNULL "NONE"
+
+#define AVA2_ID_AVA2 3255
+#define AVA2_ID_AVA3 3233
+#define AVA2_ID_AVAX 3200
+
struct avalon2_pkg {
uint8_t head[2];
uint8_t type;
@@ -132,6 +145,7 @@ struct avalon2_info {
extern char *set_avalon2_fan(char *arg);
extern char *set_avalon2_freq(char *arg);
extern char *set_avalon2_voltage(char *arg);
+extern int opt_avalon2_overheat;
#endif /* USE_AVALON2 */
#endif /* _AVALON2_H_ */