|
|
@@ -46,11 +46,17 @@ int opt_avalon_fan_min = AVALON_DEFAULT_FAN_MIN_PWM;
|
|
|
int opt_avalon_fan_max = AVALON_DEFAULT_FAN_MAX_PWM;
|
|
|
int opt_avalon_freq_min = AVALON_MIN_FREQUENCY;
|
|
|
int opt_avalon_freq_max = AVALON_MAX_FREQUENCY;
|
|
|
+int opt_bitburner_core_voltage = BITBURNER_DEFAULT_CORE_VOLTAGE;
|
|
|
bool opt_avalon_auto;
|
|
|
|
|
|
static int option_offset = -1;
|
|
|
struct device_drv avalon_drv;
|
|
|
|
|
|
+static int avalon_is_bitburner(struct cgpu_info *avalon)
|
|
|
+{
|
|
|
+ return strcmp(avalon->drv->name, "BTB") == 0;
|
|
|
+}
|
|
|
+
|
|
|
static int avalon_init_task(struct avalon_task *at,
|
|
|
uint8_t reset, uint8_t ff, uint8_t fan,
|
|
|
uint8_t timeout, uint8_t asic_num,
|
|
|
@@ -291,7 +297,7 @@ static int avalon_reset(struct cgpu_info *avalon, bool initial)
|
|
|
return -1;
|
|
|
|
|
|
if (!initial) {
|
|
|
- applog(LOG_ERR, "AVA%d reset sequence sent", avalon->device_id);
|
|
|
+ applog(LOG_ERR, "%s%d reset sequence sent", avalon->drv->name, avalon->device_id);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
@@ -308,7 +314,7 @@ static int avalon_reset(struct cgpu_info *avalon, bool initial)
|
|
|
spare = ret - 10;
|
|
|
buf = tmp = (uint8_t *)&ar;
|
|
|
if (opt_debug) {
|
|
|
- applog(LOG_DEBUG, "AVA%d reset: get:", avalon->device_id);
|
|
|
+ applog(LOG_DEBUG, "%s%d reset: get:", avalon->drv->name, avalon->device_id);
|
|
|
hexdump(tmp, AVALON_READ_SIZE);
|
|
|
}
|
|
|
|
|
|
@@ -327,13 +333,13 @@ static int avalon_reset(struct cgpu_info *avalon, bool initial)
|
|
|
}
|
|
|
|
|
|
if (i != 11) {
|
|
|
- applog(LOG_ERR, "AVA%d: Reset failed! not an Avalon?"
|
|
|
- " (%d: %02x %02x %02x %02x)", avalon->device_id,
|
|
|
+ applog(LOG_ERR, "%s%d: Reset failed! not an Avalon?"
|
|
|
+ " (%d: %02x %02x %02x %02x)", avalon->drv->name, avalon->device_id,
|
|
|
i, buf[0], buf[1], buf[2], buf[3]);
|
|
|
/* FIXME: return 1; */
|
|
|
} else
|
|
|
- applog(LOG_WARNING, "AVA%d: Reset succeeded",
|
|
|
- avalon->device_id);
|
|
|
+ applog(LOG_WARNING, "%s%d: Reset succeeded",
|
|
|
+ avalon->drv->name, avalon->device_id);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
@@ -509,7 +515,7 @@ static void avalon_idle(struct cgpu_info *avalon, struct avalon_info *info)
|
|
|
info->frequency);
|
|
|
avalon_send_task(&at, avalon);
|
|
|
}
|
|
|
- applog(LOG_WARNING, "AVA%i: Idling %d miners", avalon->device_id, i);
|
|
|
+ applog(LOG_WARNING, "%s%i: Idling %d miners", avalon->drv->name, avalon->device_id, i);
|
|
|
wait_avalon_ready(avalon);
|
|
|
}
|
|
|
|
|
|
@@ -601,6 +607,49 @@ static void avalon_initialise(struct cgpu_info *avalon)
|
|
|
avalon->drv->name, avalon->device_id, err);
|
|
|
}
|
|
|
|
|
|
+static void bitburner_set_core_voltage(struct cgpu_info *avalon, int core_voltage)
|
|
|
+{
|
|
|
+ uint8_t buf[2];
|
|
|
+ int err;
|
|
|
+
|
|
|
+ if (avalon_is_bitburner(avalon)) {
|
|
|
+ buf[0] = (uint8_t)core_voltage;
|
|
|
+ buf[1] = (uint8_t)(core_voltage >> 8);
|
|
|
+ err = usb_transfer_data(avalon, FTDI_TYPE_OUT, BITBURNER_REQUEST,
|
|
|
+ BITBURNER_VALUE, BITBURNER_INDEX_SET_VOLTAGE,
|
|
|
+ (uint32_t *)buf, sizeof(buf), C_BB_SET_VOLTAGE);
|
|
|
+ if (unlikely(err < 0)) {
|
|
|
+ applog(LOG_ERR, "%s%i: SetCoreVoltage failed: err = %d",
|
|
|
+ avalon->drv->name, avalon->device_id, err);
|
|
|
+ } else {
|
|
|
+ applog(LOG_WARNING, "%s%i: Core voltage set to %d millivolts",
|
|
|
+ avalon->drv->name, avalon->device_id,
|
|
|
+ core_voltage);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static int bitburner_get_core_voltage(struct cgpu_info *avalon)
|
|
|
+{
|
|
|
+ uint8_t buf[2];
|
|
|
+ int err;
|
|
|
+ int amount;
|
|
|
+
|
|
|
+ if (avalon_is_bitburner(avalon)) {
|
|
|
+ err = usb_transfer_read(avalon, FTDI_TYPE_IN, BITBURNER_REQUEST,
|
|
|
+ BITBURNER_VALUE, BITBURNER_INDEX_GET_VOLTAGE,
|
|
|
+ (char *)buf, sizeof(buf), &amount,
|
|
|
+ C_BB_GET_VOLTAGE);
|
|
|
+ if (unlikely(err != 0 || amount != 2)) {
|
|
|
+ applog(LOG_ERR, "%s%i: GetCoreVoltage failed: err = %d, amount = %d",
|
|
|
+ avalon->drv->name, avalon->device_id, err, amount);
|
|
|
+ return 0;
|
|
|
+ } else {
|
|
|
+ return (int)(buf[0] + ((unsigned int)buf[1] << 8));
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static bool avalon_detect_one(libusb_device *dev, struct usb_find_devices *found)
|
|
|
{
|
|
|
int baud, miner_count, asic_count, timeout, frequency = 0;
|
|
|
@@ -672,6 +721,10 @@ static bool avalon_detect_one(libusb_device *dev, struct usb_find_devices *found
|
|
|
avalon->device_path, info->miner_count, info->asic_count, info->timeout,
|
|
|
info->frequency);
|
|
|
|
|
|
+ if (avalon_is_bitburner(avalon) &&
|
|
|
+ opt_bitburner_core_voltage != BITBURNER_DEFAULT_CORE_VOLTAGE)
|
|
|
+ bitburner_set_core_voltage(avalon, opt_bitburner_core_voltage);
|
|
|
+
|
|
|
return true;
|
|
|
|
|
|
unshin:
|
|
|
@@ -908,8 +961,8 @@ static void *avalon_send_tasks(void *userdata)
|
|
|
if (!info->optimal) {
|
|
|
if (info->fan_pwm >= opt_avalon_fan_max) {
|
|
|
applog(LOG_WARNING,
|
|
|
- "AVA%i: Above optimal temperature, throttling",
|
|
|
- avalon->device_id);
|
|
|
+ "%s%i: Above optimal temperature, throttling",
|
|
|
+ avalon->drv->name, avalon->device_id);
|
|
|
avalon_dec_freq(info);
|
|
|
}
|
|
|
} else if (info->auto_nonces >= (AVALON_AUTO_CYCLE * 19 / 20) &&
|
|
|
@@ -932,8 +985,8 @@ static void *avalon_send_tasks(void *userdata)
|
|
|
for (i = start_count, j = 0; i < end_count; i++, j++) {
|
|
|
if (avalon_buffer_full(avalon)) {
|
|
|
applog(LOG_INFO,
|
|
|
- "AVA%i: Buffer full after only %d of %d work queued",
|
|
|
- avalon->device_id, j, avalon_get_work_count);
|
|
|
+ "%s%i: Buffer full after only %d of %d work queued",
|
|
|
+ avalon->drv->name, avalon->device_id, j, avalon_get_work_count);
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
@@ -961,8 +1014,8 @@ static void *avalon_send_tasks(void *userdata)
|
|
|
ret = avalon_send_task(&at, avalon);
|
|
|
|
|
|
if (unlikely(ret == AVA_SEND_ERROR)) {
|
|
|
- applog(LOG_ERR, "AVA%i: Comms error(buffer)",
|
|
|
- avalon->device_id);
|
|
|
+ applog(LOG_ERR, "%s%i: Comms error(buffer)",
|
|
|
+ avalon->drv->name, avalon->device_id);
|
|
|
dev_error(avalon, REASON_DEV_COMMS_ERROR);
|
|
|
info->reset = true;
|
|
|
break;
|
|
|
@@ -974,8 +1027,8 @@ static void *avalon_send_tasks(void *userdata)
|
|
|
mutex_unlock(&info->qlock);
|
|
|
|
|
|
if (unlikely(idled)) {
|
|
|
- applog(LOG_WARNING, "AVA%i: Idled %d miners",
|
|
|
- avalon->device_id, idled);
|
|
|
+ applog(LOG_WARNING, "%s%i: Idled %d miners",
|
|
|
+ avalon->drv->name, avalon->device_id, idled);
|
|
|
}
|
|
|
}
|
|
|
return NULL;
|
|
|
@@ -1129,16 +1182,19 @@ static void avalon_update_temps(struct cgpu_info *avalon, struct avalon_info *in
|
|
|
info->temp_sum += avalon->temp;
|
|
|
applog(LOG_DEBUG, "Avalon: temp_index: %d, temp_count: %d, temp_old: %d",
|
|
|
info->temp_history_index, info->temp_history_count, info->temp_old);
|
|
|
+ if (avalon_is_bitburner(avalon)) {
|
|
|
+ info->core_voltage = bitburner_get_core_voltage(avalon);
|
|
|
+ }
|
|
|
if (info->temp_history_index == info->temp_history_count) {
|
|
|
adjust_fan(info);
|
|
|
info->temp_history_index = 0;
|
|
|
info->temp_sum = 0;
|
|
|
}
|
|
|
if (unlikely(info->temp_old >= opt_avalon_overheat)) {
|
|
|
- applog(LOG_WARNING, "AVA%d overheat! Idling", avalon->device_id);
|
|
|
+ applog(LOG_WARNING, "%s%d overheat! Idling", avalon->drv->name, avalon->device_id);
|
|
|
info->overheat = true;
|
|
|
} else if (info->overheat && info->temp_old <= opt_avalon_temp) {
|
|
|
- applog(LOG_WARNING, "AVA%d cooled, restarting", avalon->device_id);
|
|
|
+ applog(LOG_WARNING, "%s%d cooled, restarting", avalon->drv->name, avalon->device_id);
|
|
|
info->overheat = false;
|
|
|
}
|
|
|
}
|
|
|
@@ -1148,13 +1204,17 @@ static void get_avalon_statline_before(char *buf, size_t bufsiz, struct cgpu_inf
|
|
|
struct avalon_info *info = avalon->device_data;
|
|
|
int lowfan = 10000;
|
|
|
|
|
|
- /* Find the lowest fan speed of the ASIC cooling fans. */
|
|
|
- if (info->fan1 >= 0 && info->fan1 < lowfan)
|
|
|
- lowfan = info->fan1;
|
|
|
- if (info->fan2 >= 0 && info->fan2 < lowfan)
|
|
|
- lowfan = info->fan2;
|
|
|
+ if (avalon_is_bitburner(avalon)) {
|
|
|
+ tailsprintf(buf, bufsiz, "%2d/%3dC %4dmV | ", info->temp0, info->temp2, info->core_voltage);
|
|
|
+ } else {
|
|
|
+ /* Find the lowest fan speed of the ASIC cooling fans. */
|
|
|
+ if (info->fan1 >= 0 && info->fan1 < lowfan)
|
|
|
+ lowfan = info->fan1;
|
|
|
+ if (info->fan2 >= 0 && info->fan2 < lowfan)
|
|
|
+ lowfan = info->fan2;
|
|
|
|
|
|
- tailsprintf(buf, bufsiz, "%2d/%3dC %04dR | ", info->temp0, info->temp2, lowfan);
|
|
|
+ tailsprintf(buf, bufsiz, "%2d/%3dC %04dR | ", info->temp0, info->temp2, lowfan);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/* We use a replacement algorithm to only remove references to work done from
|
|
|
@@ -1231,15 +1291,17 @@ static int64_t avalon_scanhash(struct thr_info *thr)
|
|
|
|
|
|
/* Check for nothing but consecutive bad results or consistently less
|
|
|
* results than we should be getting and reset the FPGA if necessary */
|
|
|
- if (avalon->results < -miner_count && !info->reset) {
|
|
|
- applog(LOG_ERR, "AVA%d: Result return rate low, resetting!",
|
|
|
- avalon->device_id);
|
|
|
- info->reset = true;
|
|
|
+ if (!avalon_is_bitburner(avalon)) {
|
|
|
+ if (avalon->results < -miner_count && !info->reset) {
|
|
|
+ applog(LOG_ERR, "%s%d: Result return rate low, resetting!",
|
|
|
+ avalon->drv->name, avalon->device_id);
|
|
|
+ info->reset = true;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (unlikely(avalon->usbinfo.nodev)) {
|
|
|
- applog(LOG_ERR, "AVA%d: Device disappeared, shutting down thread",
|
|
|
- avalon->device_id);
|
|
|
+ applog(LOG_ERR, "%s%d: Device disappeared, shutting down thread",
|
|
|
+ avalon->drv->name, avalon->device_id);
|
|
|
avalon->shutdown = true;
|
|
|
}
|
|
|
|
|
|
@@ -1279,6 +1341,8 @@ static struct api_data *avalon_api_stats(struct cgpu_info *cgpu)
|
|
|
root = api_add_int(root, "temp3", &(info->temp2), false);
|
|
|
root = api_add_int(root, "temp_max", &(info->temp_max), false);
|
|
|
|
|
|
+ root = api_add_int(root, "core_voltage", &(info->core_voltage), false);
|
|
|
+
|
|
|
root = api_add_int(root, "no_matching_work", &(info->no_matching_work), false);
|
|
|
for (i = 0; i < info->miner_count; i++) {
|
|
|
char mcw[24];
|