Browse Source

Merge pull request #467 from someone42/master

Support for BitBurner boards
nfactor-troky
kanoi 12 years ago
parent
commit
8dc0935639
  1. 3
      cgminer.c
  2. 119
      driver-avalon.c
  3. 5
      driver-avalon.h
  4. 19
      usbutils.c
  5. 9
      usbutils.h

3
cgminer.c

@ -1075,6 +1075,9 @@ static struct opt_table opt_config_table[] = { @@ -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 BitBurner core voltage, in millivolts"),
#endif
OPT_WITHOUT_ARG("--load-balance",
set_loadbalance, &pool_strategy,

119
driver-avalon.c

@ -46,6 +46,7 @@ int opt_avalon_fan_min = AVALON_DEFAULT_FAN_MIN_PWM; @@ -46,6 +46,7 @@ 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;
@ -291,7 +292,7 @@ static int avalon_reset(struct cgpu_info *avalon, bool initial) @@ -291,7 +292,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 +309,7 @@ static int avalon_reset(struct cgpu_info *avalon, bool initial) @@ -308,7 +309,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 +328,13 @@ static int avalon_reset(struct cgpu_info *avalon, bool initial) @@ -327,13 +328,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 +510,7 @@ static void avalon_idle(struct cgpu_info *avalon, struct avalon_info *info) @@ -509,7 +510,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 +602,51 @@ static void avalon_initialise(struct cgpu_info *avalon) @@ -601,6 +602,51 @@ 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 (usb_ident(avalon) == IDENT_BTB) {
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 (usb_ident(avalon) == IDENT_BTB) {
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));
}
} else {
return 0;
}
}
static bool avalon_detect_one(libusb_device *dev, struct usb_find_devices *found)
{
int baud, miner_count, asic_count, timeout, frequency = 0;
@ -672,6 +718,10 @@ static bool avalon_detect_one(libusb_device *dev, struct usb_find_devices *found @@ -672,6 +718,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 (usb_ident(avalon) == IDENT_BTB &&
opt_bitburner_core_voltage != BITBURNER_DEFAULT_CORE_VOLTAGE)
bitburner_set_core_voltage(avalon, opt_bitburner_core_voltage);
return true;
unshin:
@ -908,8 +958,8 @@ static void *avalon_send_tasks(void *userdata) @@ -908,8 +958,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 +982,8 @@ static void *avalon_send_tasks(void *userdata) @@ -932,8 +982,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 +1011,8 @@ static void *avalon_send_tasks(void *userdata) @@ -961,8 +1011,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 +1024,8 @@ static void *avalon_send_tasks(void *userdata) @@ -974,8 +1024,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 +1179,19 @@ static void avalon_update_temps(struct cgpu_info *avalon, struct avalon_info *in @@ -1129,16 +1179,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 (usb_ident(avalon) == IDENT_BTB) {
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 +1201,17 @@ static void get_avalon_statline_before(char *buf, size_t bufsiz, struct cgpu_inf @@ -1148,13 +1201,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 (usb_ident(avalon) == IDENT_BTB) {
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 +1288,17 @@ static int64_t avalon_scanhash(struct thr_info *thr) @@ -1231,15 +1288,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 (usb_ident(avalon) != IDENT_BTB) {
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 +1338,8 @@ static struct api_data *avalon_api_stats(struct cgpu_info *cgpu) @@ -1279,6 +1338,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];

5
driver-avalon.h

@ -33,6 +33,8 @@ @@ -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 { @@ -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; @@ -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

@ -190,6 +190,21 @@ static struct usb_find_devices find_dev[] = { @@ -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"; @@ -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() @@ -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;
}

9
usbutils.h

@ -48,6 +48,12 @@ @@ -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 { @@ -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 { @@ -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…
Cancel
Save