|
|
@ -49,6 +49,7 @@ int opt_avalon_fan_max = AVALON_DEFAULT_FAN_MAX_PWM; |
|
|
|
int opt_avalon_freq_min = AVALON_MIN_FREQUENCY; |
|
|
|
int opt_avalon_freq_min = AVALON_MIN_FREQUENCY; |
|
|
|
int opt_avalon_freq_max = AVALON_MAX_FREQUENCY; |
|
|
|
int opt_avalon_freq_max = AVALON_MAX_FREQUENCY; |
|
|
|
int opt_bitburner_core_voltage = BITBURNER_DEFAULT_CORE_VOLTAGE; |
|
|
|
int opt_bitburner_core_voltage = BITBURNER_DEFAULT_CORE_VOLTAGE; |
|
|
|
|
|
|
|
int opt_bitburner_fury_core_voltage = BITBURNER_FURY_DEFAULT_CORE_VOLTAGE; |
|
|
|
bool opt_avalon_auto; |
|
|
|
bool opt_avalon_auto; |
|
|
|
|
|
|
|
|
|
|
|
static int option_offset = -1; |
|
|
|
static int option_offset = -1; |
|
|
@ -209,6 +210,55 @@ static int avalon_send_task(const struct avalon_task *at, struct cgpu_info *aval |
|
|
|
return ret; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int bitburner_send_task(const struct avalon_task *at, struct cgpu_info *avalon) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
uint8_t buf[AVALON_WRITE_SIZE + 4 * AVALON_DEFAULT_ASIC_NUM]; |
|
|
|
|
|
|
|
int ret, ep = C_AVALON_TASK; |
|
|
|
|
|
|
|
cgtimer_t ts_start; |
|
|
|
|
|
|
|
size_t nr_len; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (at->nonce_elf) |
|
|
|
|
|
|
|
nr_len = AVALON_WRITE_SIZE + 4 * at->asic_num; |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
nr_len = AVALON_WRITE_SIZE; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memset(buf, 0, nr_len); |
|
|
|
|
|
|
|
memcpy(buf, at, AVALON_WRITE_SIZE); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(__BIG_ENDIAN__) || defined(MIPSEB) |
|
|
|
|
|
|
|
uint8_t tt = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tt = (buf[0] & 0x0f) << 4; |
|
|
|
|
|
|
|
tt |= ((buf[0] & 0x10) ? (1 << 3) : 0); |
|
|
|
|
|
|
|
tt |= ((buf[0] & 0x20) ? (1 << 2) : 0); |
|
|
|
|
|
|
|
tt |= ((buf[0] & 0x40) ? (1 << 1) : 0); |
|
|
|
|
|
|
|
tt |= ((buf[0] & 0x80) ? (1 << 0) : 0); |
|
|
|
|
|
|
|
buf[0] = tt; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tt = (buf[4] & 0x0f) << 4; |
|
|
|
|
|
|
|
tt |= ((buf[4] & 0x10) ? (1 << 3) : 0); |
|
|
|
|
|
|
|
tt |= ((buf[4] & 0x20) ? (1 << 2) : 0); |
|
|
|
|
|
|
|
tt |= ((buf[4] & 0x40) ? (1 << 1) : 0); |
|
|
|
|
|
|
|
tt |= ((buf[4] & 0x80) ? (1 << 0) : 0); |
|
|
|
|
|
|
|
buf[4] = tt; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (at->reset) { |
|
|
|
|
|
|
|
ep = C_AVALON_RESET; |
|
|
|
|
|
|
|
nr_len = 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (opt_debug) { |
|
|
|
|
|
|
|
applog(LOG_DEBUG, "Avalon: Sent(%u):", (unsigned int)nr_len); |
|
|
|
|
|
|
|
hexdump(buf, nr_len); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
cgsleep_prepare_r(&ts_start); |
|
|
|
|
|
|
|
ret = avalon_write(avalon, (char *)buf, nr_len, ep); |
|
|
|
|
|
|
|
cgsleep_us_r(&ts_start, 3000); // 3 ms = 333 tasks per second, or 1.4 TH/s
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static bool avalon_decode_nonce(struct thr_info *thr, struct cgpu_info *avalon, |
|
|
|
static bool avalon_decode_nonce(struct thr_info *thr, struct cgpu_info *avalon, |
|
|
|
struct avalon_info *info, struct avalon_result *ar, |
|
|
|
struct avalon_info *info, struct avalon_result *ar, |
|
|
|
struct work *work) |
|
|
|
struct work *work) |
|
|
@ -414,12 +464,12 @@ static bool get_options(int this_option_offset, int *baud, int *miner_count, |
|
|
|
|
|
|
|
|
|
|
|
if (*colon) { |
|
|
|
if (*colon) { |
|
|
|
tmp = atoi(colon); |
|
|
|
tmp = atoi(colon); |
|
|
|
if (tmp > 0 && tmp <= AVALON_DEFAULT_MINER_NUM) { |
|
|
|
if (tmp > 0 && tmp <= AVALON_MAX_MINER_NUM) { |
|
|
|
*miner_count = tmp; |
|
|
|
*miner_count = tmp; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
quit(1, "Invalid avalon-options for " |
|
|
|
quit(1, "Invalid avalon-options for " |
|
|
|
"miner_count (%s) must be 1 ~ %d", |
|
|
|
"miner_count (%s) must be 1 ~ %d", |
|
|
|
colon, AVALON_DEFAULT_MINER_NUM); |
|
|
|
colon, AVALON_MAX_MINER_NUM); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -620,12 +670,20 @@ static void avalon_initialise(struct cgpu_info *avalon) |
|
|
|
avalon->drv->name, avalon->device_id, err); |
|
|
|
avalon->drv->name, avalon->device_id, err); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bool is_bitburner(struct cgpu_info *avalon) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
enum sub_ident ident; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ident = usb_ident(avalon); |
|
|
|
|
|
|
|
return ident == IDENT_BTB || ident == IDENT_BBF; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static bool bitburner_set_core_voltage(struct cgpu_info *avalon, int core_voltage) |
|
|
|
static bool bitburner_set_core_voltage(struct cgpu_info *avalon, int core_voltage) |
|
|
|
{ |
|
|
|
{ |
|
|
|
uint8_t buf[2]; |
|
|
|
uint8_t buf[2]; |
|
|
|
int err; |
|
|
|
int err; |
|
|
|
|
|
|
|
|
|
|
|
if (usb_ident(avalon) == IDENT_BTB) { |
|
|
|
if (is_bitburner(avalon)) { |
|
|
|
buf[0] = (uint8_t)core_voltage; |
|
|
|
buf[0] = (uint8_t)core_voltage; |
|
|
|
buf[1] = (uint8_t)(core_voltage >> 8); |
|
|
|
buf[1] = (uint8_t)(core_voltage >> 8); |
|
|
|
err = usb_transfer_data(avalon, FTDI_TYPE_OUT, BITBURNER_REQUEST, |
|
|
|
err = usb_transfer_data(avalon, FTDI_TYPE_OUT, BITBURNER_REQUEST, |
|
|
@ -651,7 +709,7 @@ static int bitburner_get_core_voltage(struct cgpu_info *avalon) |
|
|
|
int err; |
|
|
|
int err; |
|
|
|
int amount; |
|
|
|
int amount; |
|
|
|
|
|
|
|
|
|
|
|
if (usb_ident(avalon) == IDENT_BTB) { |
|
|
|
if (is_bitburner(avalon)) { |
|
|
|
err = usb_transfer_read(avalon, FTDI_TYPE_IN, BITBURNER_REQUEST, |
|
|
|
err = usb_transfer_read(avalon, FTDI_TYPE_IN, BITBURNER_REQUEST, |
|
|
|
BITBURNER_VALUE, BITBURNER_INDEX_GET_VOLTAGE, |
|
|
|
BITBURNER_VALUE, BITBURNER_INDEX_GET_VOLTAGE, |
|
|
|
(char *)buf, sizeof(buf), &amount, |
|
|
|
(char *)buf, sizeof(buf), &amount, |
|
|
@ -780,7 +838,18 @@ static bool avalon_detect_one(libusb_device *dev, struct usb_find_devices *found |
|
|
|
BITBURNER_MAX_COREMV); |
|
|
|
BITBURNER_MAX_COREMV); |
|
|
|
} else |
|
|
|
} else |
|
|
|
bitburner_set_core_voltage(avalon, opt_bitburner_core_voltage); |
|
|
|
bitburner_set_core_voltage(avalon, opt_bitburner_core_voltage); |
|
|
|
|
|
|
|
} else if (usb_ident(avalon) == IDENT_BBF) { |
|
|
|
|
|
|
|
if (opt_bitburner_fury_core_voltage < BITBURNER_FURY_MIN_COREMV || |
|
|
|
|
|
|
|
opt_bitburner_fury_core_voltage > BITBURNER_FURY_MAX_COREMV) { |
|
|
|
|
|
|
|
quit(1, "Invalid bitburner-fury-voltage %d must be %dmv - %dmv", |
|
|
|
|
|
|
|
opt_bitburner_fury_core_voltage, |
|
|
|
|
|
|
|
BITBURNER_FURY_MIN_COREMV, |
|
|
|
|
|
|
|
BITBURNER_FURY_MAX_COREMV); |
|
|
|
|
|
|
|
} else |
|
|
|
|
|
|
|
bitburner_set_core_voltage(avalon, opt_bitburner_fury_core_voltage); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (is_bitburner(avalon)) { |
|
|
|
bitburner_get_version(avalon); |
|
|
|
bitburner_get_version(avalon); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1181,7 +1250,7 @@ static void *bitburner_send_tasks(void *userdata) |
|
|
|
avalon_reset_auto(info); |
|
|
|
avalon_reset_auto(info); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ret = avalon_send_task(&at, avalon); |
|
|
|
ret = bitburner_send_task(&at, avalon); |
|
|
|
|
|
|
|
|
|
|
|
if (unlikely(ret == AVA_SEND_ERROR)) { |
|
|
|
if (unlikely(ret == AVA_SEND_ERROR)) { |
|
|
|
applog(LOG_ERR, "%s%i: Comms error(buffer)", |
|
|
|
applog(LOG_ERR, "%s%i: Comms error(buffer)", |
|
|
@ -1211,7 +1280,7 @@ static bool avalon_prepare(struct thr_info *thr) |
|
|
|
int array_size = AVALON_ARRAY_SIZE; |
|
|
|
int array_size = AVALON_ARRAY_SIZE; |
|
|
|
void *(*write_thread_fn)(void *) = avalon_send_tasks; |
|
|
|
void *(*write_thread_fn)(void *) = avalon_send_tasks; |
|
|
|
|
|
|
|
|
|
|
|
if (usb_ident(avalon) == IDENT_BTB) { |
|
|
|
if (is_bitburner(avalon)) { |
|
|
|
array_size = BITBURNER_ARRAY_SIZE; |
|
|
|
array_size = BITBURNER_ARRAY_SIZE; |
|
|
|
write_thread_fn = bitburner_send_tasks; |
|
|
|
write_thread_fn = bitburner_send_tasks; |
|
|
|
} |
|
|
|
} |
|
|
@ -1356,7 +1425,7 @@ static void avalon_update_temps(struct cgpu_info *avalon, struct avalon_info *in |
|
|
|
info->temp_sum += avalon->temp; |
|
|
|
info->temp_sum += avalon->temp; |
|
|
|
applog(LOG_DEBUG, "Avalon: temp_index: %d, temp_count: %d, temp_old: %d", |
|
|
|
applog(LOG_DEBUG, "Avalon: temp_index: %d, temp_count: %d, temp_old: %d", |
|
|
|
info->temp_history_index, info->temp_history_count, info->temp_old); |
|
|
|
info->temp_history_index, info->temp_history_count, info->temp_old); |
|
|
|
if (usb_ident(avalon) == IDENT_BTB) { |
|
|
|
if (is_bitburner(avalon)) { |
|
|
|
info->core_voltage = bitburner_get_core_voltage(avalon); |
|
|
|
info->core_voltage = bitburner_get_core_voltage(avalon); |
|
|
|
} |
|
|
|
} |
|
|
|
if (info->temp_history_index == info->temp_history_count) { |
|
|
|
if (info->temp_history_index == info->temp_history_count) { |
|
|
@ -1378,7 +1447,7 @@ static void get_avalon_statline_before(char *buf, size_t bufsiz, struct cgpu_inf |
|
|
|
struct avalon_info *info = avalon->device_data; |
|
|
|
struct avalon_info *info = avalon->device_data; |
|
|
|
int lowfan = 10000; |
|
|
|
int lowfan = 10000; |
|
|
|
|
|
|
|
|
|
|
|
if (usb_ident(avalon) == IDENT_BTB) { |
|
|
|
if (is_bitburner(avalon)) { |
|
|
|
int temp = info->temp0; |
|
|
|
int temp = info->temp0; |
|
|
|
if (info->temp2 > temp) |
|
|
|
if (info->temp2 > temp) |
|
|
|
temp = info->temp2; |
|
|
|
temp = info->temp2; |
|
|
@ -1464,7 +1533,7 @@ static int64_t avalon_scanhash(struct thr_info *thr) |
|
|
|
|
|
|
|
|
|
|
|
/* Check for nothing but consecutive bad results or consistently less
|
|
|
|
/* Check for nothing but consecutive bad results or consistently less
|
|
|
|
* results than we should be getting and reset the FPGA if necessary */ |
|
|
|
* results than we should be getting and reset the FPGA if necessary */ |
|
|
|
if (usb_ident(avalon) != IDENT_BTB) { |
|
|
|
if (!is_bitburner(avalon)) { |
|
|
|
if (avalon->results < -miner_count && !info->reset) { |
|
|
|
if (avalon->results < -miner_count && !info->reset) { |
|
|
|
applog(LOG_ERR, "%s%d: Result return rate low, resetting!", |
|
|
|
applog(LOG_ERR, "%s%d: Result return rate low, resetting!", |
|
|
|
avalon->drv->name, avalon->device_id); |
|
|
|
avalon->drv->name, avalon->device_id); |
|
|
@ -1525,7 +1594,7 @@ static struct api_data *avalon_api_stats(struct cgpu_info *cgpu) |
|
|
|
sprintf(mcw, "match_work_count%d", i + 1); |
|
|
|
sprintf(mcw, "match_work_count%d", i + 1); |
|
|
|
root = api_add_int(root, mcw, &(info->matching_work[i]), false); |
|
|
|
root = api_add_int(root, mcw, &(info->matching_work[i]), false); |
|
|
|
} |
|
|
|
} |
|
|
|
if (usb_ident(cgpu) == IDENT_BTB) { |
|
|
|
if (is_bitburner(cgpu)) { |
|
|
|
root = api_add_int(root, "core_voltage", &(info->core_voltage), false); |
|
|
|
root = api_add_int(root, "core_voltage", &(info->core_voltage), false); |
|
|
|
snprintf(buf, sizeof(buf), "%"PRIu8".%"PRIu8".%"PRIu8, |
|
|
|
snprintf(buf, sizeof(buf), "%"PRIu8".%"PRIu8".%"PRIu8, |
|
|
|
info->version1, info->version2, info->version3); |
|
|
|
info->version1, info->version2, info->version3); |
|
|
@ -1553,7 +1622,7 @@ static char *avalon_set_device(struct cgpu_info *avalon, char *option, char *set |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (strcasecmp(option, "millivolts") == 0 || strcasecmp(option, "mv") == 0) { |
|
|
|
if (strcasecmp(option, "millivolts") == 0 || strcasecmp(option, "mv") == 0) { |
|
|
|
if (usb_ident(avalon) != IDENT_BTB) { |
|
|
|
if (!is_bitburner(avalon)) { |
|
|
|
sprintf(replybuf, "%s cannot set millivolts", avalon->drv->name); |
|
|
|
sprintf(replybuf, "%s cannot set millivolts", avalon->drv->name); |
|
|
|
return replybuf; |
|
|
|
return replybuf; |
|
|
|
} |
|
|
|
} |
|
|
|