mirror of
https://github.com/GOSTSec/sgminer
synced 2025-01-22 20:44:19 +00:00
changes to Avalon driver for BitBurner boards
This commit is contained in:
parent
bda1e33322
commit
b0f4d55be7
@ -1075,6 +1075,9 @@ static struct opt_table opt_config_table[] = {
|
||||
OPT_WITH_ARG("--avalon-temp",
|
||||
set_int_0_to_100, opt_show_intval, &opt_avalon_temp,
|
||||
"Set avalon target temperature"),
|
||||
OPT_WITH_ARG("--bitburner-voltage",
|
||||
opt_set_intval, NULL, &opt_bitburner_core_voltage,
|
||||
"Set ASIC core voltage (for BitBurner boards only), in millivolts"),
|
||||
#endif
|
||||
OPT_WITHOUT_ARG("--load-balance",
|
||||
set_loadbalance, &pool_strategy,
|
||||
|
122
driver-avalon.c
122
driver-avalon.c
@ -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];
|
||||
|
@ -33,6 +33,8 @@
|
||||
#define AVALON_TEMP_HYSTERESIS 3
|
||||
#define AVALON_TEMP_OVERHEAT 60
|
||||
|
||||
#define BITBURNER_DEFAULT_CORE_VOLTAGE 1200 /* in millivolts */
|
||||
|
||||
#define AVALON_DEFAULT_TIMEOUT 0x2D
|
||||
#define AVALON_MIN_FREQUENCY 256
|
||||
#define AVALON_MAX_FREQUENCY 450
|
||||
@ -113,6 +115,8 @@ struct avalon_info {
|
||||
int temp_old;
|
||||
int fan_pwm;
|
||||
|
||||
int core_voltage;
|
||||
|
||||
int no_matching_work;
|
||||
int matching_work[AVALON_DEFAULT_MINER_NUM];
|
||||
|
||||
@ -161,6 +165,7 @@ extern int opt_avalon_fan_max;
|
||||
extern int opt_avalon_freq_min;
|
||||
extern int opt_avalon_freq_max;
|
||||
extern bool opt_avalon_auto;
|
||||
extern int opt_bitburner_core_voltage;
|
||||
extern char *set_avalon_fan(char *arg);
|
||||
extern char *set_avalon_freq(char *arg);
|
||||
|
||||
|
19
usbutils.c
19
usbutils.c
@ -190,6 +190,21 @@ static struct usb_find_devices find_dev[] = {
|
||||
.eps = mmq_eps },
|
||||
#endif
|
||||
#ifdef USE_AVALON
|
||||
{
|
||||
.drv = DRV_AVALON,
|
||||
.name = "BTB",
|
||||
.ident = IDENT_BTB,
|
||||
.idVendor = IDVENDOR_FTDI,
|
||||
.idProduct = 0x6001,
|
||||
.iManufacturer = "Burnin Electronics",
|
||||
.iProduct = "BitBurner",
|
||||
.kernel = 0,
|
||||
.config = 1,
|
||||
.interface = 0,
|
||||
.timeout = AVALON_TIMEOUT_MS,
|
||||
.latency = 10,
|
||||
.epcount = ARRAY_SIZE(ava_eps),
|
||||
.eps = ava_eps },
|
||||
{
|
||||
.drv = DRV_AVALON,
|
||||
.name = "AVA",
|
||||
@ -535,6 +550,8 @@ static const char *C_AVALON_RESET_S = "AvalonReset";
|
||||
static const char *C_GET_AVALON_RESET_S = "GetAvalonReset";
|
||||
static const char *C_FTDI_STATUS_S = "FTDIStatus";
|
||||
static const char *C_ENABLE_UART_S = "EnableUART";
|
||||
static const char *C_BB_SET_VOLTAGE_S = "SetCoreVoltage";
|
||||
static const char *C_BB_GET_VOLTAGE_S = "GetCoreVoltage";
|
||||
|
||||
#ifdef EOL
|
||||
#undef EOL
|
||||
@ -1023,6 +1040,8 @@ static void cgusb_check_init()
|
||||
usb_commands[C_GET_AVALON_RESET] = C_GET_AVALON_RESET_S;
|
||||
usb_commands[C_FTDI_STATUS] = C_FTDI_STATUS_S;
|
||||
usb_commands[C_ENABLE_UART] = C_ENABLE_UART_S;
|
||||
usb_commands[C_BB_SET_VOLTAGE] = C_BB_SET_VOLTAGE_S;
|
||||
usb_commands[C_BB_GET_VOLTAGE] = C_BB_GET_VOLTAGE_S;
|
||||
|
||||
stats_initialised = true;
|
||||
}
|
||||
|
@ -48,6 +48,12 @@
|
||||
|
||||
#define FTDI_VALUE_DATA_AVA 8
|
||||
|
||||
// BitBurner
|
||||
#define BITBURNER_REQUEST ((uint8_t)0x42)
|
||||
#define BITBURNER_VALUE 0x4242
|
||||
#define BITBURNER_INDEX_SET_VOLTAGE 1
|
||||
#define BITBURNER_INDEX_GET_VOLTAGE 2
|
||||
|
||||
// CMR = 115200 & 57600
|
||||
#define FTDI_VALUE_BAUD_CMR_115 0xc068
|
||||
#define FTDI_INDEX_BAUD_CMR_115 0x0200
|
||||
@ -121,6 +127,7 @@ enum sub_ident {
|
||||
IDENT_BFL,
|
||||
IDENT_MMQ,
|
||||
IDENT_AVA,
|
||||
IDENT_BTB,
|
||||
IDENT_ICA,
|
||||
IDENT_AMU,
|
||||
IDENT_BLT,
|
||||
@ -304,6 +311,8 @@ enum usb_cmds {
|
||||
C_GET_AVALON_RESET,
|
||||
C_FTDI_STATUS,
|
||||
C_ENABLE_UART,
|
||||
C_BB_SET_VOLTAGE,
|
||||
C_BB_GET_VOLTAGE,
|
||||
C_MAX
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user