Professional Documents
Culture Documents
#define PACK32(str, x) \
{ \
*(x) = ((uint32_t) *((str) + 3) ) \
| ((uint32_t) *((str) + 2) << 8) \
| ((uint32_t) *((str) + 1) << 16) \
| ((uint32_t) *((str) + 0) << 24); \
}
return 0;
}
pkg->head[0] = AVAM_H1;
pkg->head[1] = AVAM_H2;
pkg->type = type;
pkg->opt = 0;
pkg->idx = idx;
pkg->cnt = cnt;
return ret;
}
PACK32(report, &id);
chip_id = report[6];
if (chip_id >= info->asic_cnts) {
applog(LOG_DEBUG, "%s-%d: chip_id >= info->asic_cnts(%d > %d)",
avalonm->drv->name, avalonm->device_id,
chip_id, info->asic_cnts);
return;
}
ntime = report[7];
PACK32(report + 8, &nonce);
nonce -= 0x4000;
info->usbfifo_cnt = report[13];
info->workfifo_cnt = report[14];
info->noncefifo_cnt = report[15];
info->matching_work[chip_id]++;
free_work(work);
info->nonce_cnts++;
}
switch(ar->type) {
case AVAM_P_NONCE_M:
ret = ar->type;
applog(LOG_DEBUG, "%s-%d: AVAM_P_NONCE", avalonm->drv->name, avalonm-
>device_id);
hexdump(ar->data, 32);
process_nonce(avalonm, ar->data);
if (ar->data[22] != 0xff) {
process_nonce(avalonm, ar->data + 16);
}
break;
case AVAM_P_STATUS_M:
ret = ar->type;
applog(LOG_DEBUG, "%s-%d: AVAM_P_STATUS_M", avalonm->drv->name,
avalonm->device_id);
hexdump(ar->data, 32);
memcpy(&tmp, ar->data, 4);
if (!strncmp(info->ver, "3U", 2))
info->get_frequency[0][0] = be32toh(tmp);
else
info->spi_speed = be32toh(tmp);
memcpy(&tmp, ar->data + 4, 4);
info->led_status = be32toh(tmp);
memcpy(&tmp, ar->data + 8, 4);
info->fan_pwm = be32toh(tmp);
memcpy(&tmp, ar->data + 12, 4);
if (!strncmp(info->ver, "3U", 2))
info->get_voltage = convert_voltage(be32toh(tmp), 0.5);
else
info->get_voltage = decode_voltage((uint8_t)be32toh(tmp));
memcpy(&tmp, ar->data + 16, 4);
info->adc[0] = be32toh(tmp);
memcpy(&tmp, ar->data + 20, 4);
info->adc[1] = be32toh(tmp);
memcpy(&tmp, ar->data + 24, 4);
info->adc[2] = be32toh(tmp);
memcpy(&tmp, ar->data + 28 , 4);
info->power_good = be32toh(tmp);
if (!ar->opt) {
for (i = 0; i < info->asic_cnts; i++) {
info->get_frequency[i][0] = freq[0];
info->get_frequency[i][1] = freq[1];
info->get_frequency[i][2] = freq[2];
}
}
if (ar->opt) {
info->get_frequency[ar->opt - 1][0] = freq[0];
info->get_frequency[ar->opt - 1][1] = freq[1];
info->get_frequency[ar->opt - 1][2] = freq[2];
}
break;
default:
applog(LOG_DEBUG, "%s-%d: Unknown response (%x)", avalonm->drv->name,
avalonm->device_id,
ar->type);
ret = 0;
break;
}
return ret;
}
if (unlikely(avalonm->usbinfo.nodev))
return -1;
return writecnt;
}
if (unlikely(avalonm->usbinfo.nodev))
return -1;
return readcnt;
}
return AVAM_SEND_OK;
}
memset(send_pkg.data, 0, AVAM_P_DATA_LEN);
avalonm_init_pkg(&send_pkg, AVAM_P_GET_FREQ, 1, 1);
send_pkg.opt = asic_index;
ret = avalonm_xfer_pkg(avalonm, &send_pkg, &ar);
if (ret == AVAM_SEND_OK) {
ret = decode_pkg(thr, &ar);
}
return ret;
}
memset(send_pkg.data, 0, AVAM_P_DATA_LEN);
tmp = speed | 0x80000000;
tmp = be32toh(tmp);
memcpy(send_pkg.data, &tmp, 4);
avalonm_init_pkg(&send_pkg, AVAM_P_SETM, 1, 1);
avalonm_send_pkg(avalonm, &send_pkg);
}
usb_buffer_clear(avalonm);
update_usb_stats(avalonm);
add_cgpu(avalonm);
avalonm_set_spispeed(avalonm, opt_avalonm_spispeed);
cgtime(&info->elapsed);
info->lastadj = info->lasttime = info->elapsed;
info->time_i = 0;
memset(info->hw_work_i, 0, sizeof(int) * info->asic_cnts *
AVAM_DEFAULT_MOV_TIMES);
return avalonm;
}
if (asic_index == AVAM_ASIC_ALL) {
index = 0;
for (i = 0; i < info->asic_cnts; i++) {
if ((info->set_frequency[i][0] == freq[0]) &&
(info->set_frequency[i][1] == freq[1]) &&
(info->set_frequency[i][2] == freq[2]))
continue;
change = 1;
info->set_frequency[i][0] = freq[0];
info->set_frequency[i][1] = freq[1];
info->set_frequency[i][2] = freq[2];
FLAG_SET(info->freq_update, AVAM_ASIC_ALL);
}
}
if (asic_index != AVAM_ASIC_ALL) {
index = asic_index - 1;
if (!((info->set_frequency[index][0] == freq[0]) &&
(info->set_frequency[index][1] == freq[1]) &&
(info->set_frequency[index][2] == freq[2]))) {
change = 1;
info->set_frequency[index][0] = freq[0];
info->set_frequency[index][1] = freq[1];
info->set_frequency[index][2] = freq[2];
FLAG_SET(info->freq_update, asic_index);
}
}
if (!change)
return;
info->delay_ms = CAL_DELAY(max_freq);
memset(send_pkg.data, 0, AVAM_P_DATA_LEN);
tmp = avalonm_get_cpm(freq[0]);
tmp = be32toh(tmp);
memcpy(send_pkg.data, &tmp, 4);
tmp = avalonm_get_cpm(freq[1]);
tmp = be32toh(tmp);
memcpy(send_pkg.data + 4, &tmp, 4);
tmp = avalonm_get_cpm(freq[2]);
tmp = be32toh(tmp);
memcpy(send_pkg.data + 8, &tmp, 4);
info->set_voltage = info->opt_voltage;
memset(send_pkg.data, 0, AVAM_P_DATA_LEN);
/* Use shifter to set voltage */
tmp = info->set_voltage;
tmp = encode_voltage(tmp);
tmp = htobe16(tmp);
memcpy(send_pkg.data, &tmp, 2);
if (info->power_on)
cgsleep_ms(1000);
info->power_on = 0;
}
memset(send_pkg.data, 0, AVAM_P_DATA_LEN);
avalonm_init_pkg(&send_pkg, AVAM_P_POLLING, 1, 1);
ret = avalonm_xfer_pkg(avalonm, &send_pkg, &ar);
if (ret == AVAM_SEND_OK) {
ret = decode_pkg(thr, &ar);
}
return ret;
}
hash_count = info->nonce_cnts++;
info->nonce_cnts = 0;
cgtime(¤t);
device_tdiff = tdiff(¤t, &(info->lastadj));
if (opt_avalonm_autof && (device_tdiff > AVAM_DEFAULT_ADJ_INTERVAL ||
device_tdiff < 0)) {
copy_time(&info->lastadj, ¤t);
if (info->opt_freq[i][0] * 10 % 125)
info->opt_freq[i][0] -= 13;
else
info->opt_freq[i][0] -= 12;
if (info->opt_freq[i][1] * 10 % 125)
info->opt_freq[i][1] -= 13;
else
info->opt_freq[i][1] -= 12;
if (info->opt_freq[i][2] * 10 % 125)
info->opt_freq[i][2] -= 13;
else
info->opt_freq[i][2] -= 12;
FLAG_SET(info->freq_set, i + 1);
applog(LOG_NOTICE, "%s-%d: Automatic decrease [%d] freq to
%d,%d,%d",
avalonm->drv->name, avalonm->device_id, i,
info->opt_freq[i][0],
info->opt_freq[i][1],
info->opt_freq[i][2]);
}
if (info->opt_freq[i][0] * 10 % 125)
info->opt_freq[i][0] += 12;
else
info->opt_freq[i][0] += 13;
if (info->opt_freq[i][1] * 10 % 125)
info->opt_freq[i][1] += 12;
else
info->opt_freq[i][1] += 13;
if (info->opt_freq[i][2] * 10 % 125)
info->opt_freq[i][2] += 12;
else
info->opt_freq[i][2] += 13;
FLAG_SET(info->freq_set, i + 1);
applog(LOG_NOTICE, "%s-%d: Automatic increase [%d] freq to
%d,%d,%d",
avalonm->drv->name, avalonm->device_id, i,
info->opt_freq[i][0],
info->opt_freq[i][1],
info->opt_freq[i][2]);
}
}
}
while (likely(!avalonm->shutdown)) {
if (unlikely(avalonm->usbinfo.nodev)) {
applog(LOG_ERR, "%s-%d: Device disappeared, shutting down
thread",
avalonm->drv->name, avalonm->device_id);
goto out;
}
cgtime(¤t);
device_tdiff = tdiff(¤t, &(info->lasttime));
if (device_tdiff >= AVAM_DEFAULT_MOV_TIMES || device_tdiff < 0) {
copy_time(&info->lasttime, ¤t);
if (info->time_i++ >= AVAM_DEFAULT_MOV_TIMES)
info->time_i = 0;
mutex_lock(&info->qlock);
if (FLAG_GET(info->freq_set, 0)) {
avalonm_set_freq(avalonm, AVAM_ASIC_ALL, info-
>opt_freq[0]);
FLAG_CLEAR(info->freq_set, 0);
cgsleep_ms(20);
}
/* P_WORK part 2:
*
id(6)+reserved(2)+ntime(1)+fan(3)+led(4)+reserved(4)+data(12) */
memset(send_pkg.data, 0, AVAM_P_DATA_LEN);
UNPACK32(work->id, send_pkg.data);
/* TODO led */
UNPACK32(0, send_pkg.data + 12);
mutex_unlock(&info->qlock);
avalonm_rotate_array(avalonm, info);
cgsem_post(&info->qsem);
/* Get result */
do {
ret = avalonm_get_reports(avalonm);
cgsleep_ms(5);
} while (ret != AVAM_P_STATUS_M);
if (info->freq_update) {
applog(LOG_NOTICE, "%s-%d: avalonm_process_tasks freq change flag
%02x",
avalonm->drv->name, avalonm->device_id,
info->freq_update);
if (FLAG_GET(info->freq_update, 0)) {
avalonm_get_frequency(avalonm, 0);
FLAG_CLEAR(info->freq_update, 0);
}
cgsleep_ms(info->delay_ms);
}
out:
return NULL;
}
free(avalonm->works);
avalonm->works = calloc(info->asic_cnts * sizeof(struct work *),
AVAM_DEFAULT_ARRAY_SIZE);
if (!avalonm->works)
quit(1, "Failed to calloc avalon miner works in avalonm_prepare");
info->thr = thr;
info->delay_ms = CAL_DELAY(AVAM_DEFAULT_FREQUENCY);
info->power_on = 1;
mutex_init(&info->lock);
mutex_init(&info->qlock);
cgsem_init(&info->qsem);
return true;
}
pthread_join(info->process_thr, NULL);
cgsem_destroy(&info->qsem);
mutex_destroy(&info->qlock);
mutex_destroy(&info->lock);
free(avalonm->works);
avalonm->works = NULL;
}
char *set_avalonm_freq(char *arg)
{
char *colon1, *colon2;
int val1 = 0, val2 = 0, val3 = 0;
if (!(*arg))
return NULL;
if (*arg) {
val1 = atoi(arg);
if (val1 < AVAM_DEFAULT_FREQUENCY_MIN || val1 >
AVAM_DEFAULT_FREQUENCY_MAX)
return "Invalid value1 passed to set_avalonm_freq";
}
if (*colon1) {
val2 = atoi(colon1);
if (val2 < AVAM_DEFAULT_FREQUENCY_MIN || val2 >
AVAM_DEFAULT_FREQUENCY_MAX)
return "Invalid value2 passed to set_avalonm_freq";
}
if (!val1)
val3 = val2 = val1 = AVAM_DEFAULT_FREQUENCY;
if (!val2)
val3 = val2 = val1;
if (!val3)
val3 = val2;
opt_avalonm_freq[0] = val1;
opt_avalonm_freq[1] = val2;
opt_avalonm_freq[2] = val3;
applog(LOG_NOTICE, "Update all asic frequency to %d",
(opt_avalonm_freq[0] * 4 + opt_avalonm_freq[1] * 4 +
opt_avalonm_freq[2]) / 9);
return NULL;
}
char *set_avalonm_device_freq(struct cgpu_info *avalonm, char *arg)
{
struct avalonm_info *info = avalonm->device_data;
char *colon1, *colon2;
int val1 = 0, val2 = 0, val3 = 0;
int asic_index = AVAM_ASIC_ALL;
uint8_t i;
if (!(*arg))
return NULL;
if (*arg) {
val1 = atoi(arg);
if (val1 < AVAM_DEFAULT_FREQUENCY_MIN || val1 >
AVAM_DEFAULT_FREQUENCY_MAX)
return "Invalid value1 passed to set_avalonm_freq";
}
if (*colon1) {
val2 = atoi(colon1);
if (val2 < AVAM_DEFAULT_FREQUENCY_MIN || val2 >
AVAM_DEFAULT_FREQUENCY_MAX)
return "Invalid value2 passed to set_avalonm_freq";
}
if (!val1)
val3 = val2 = val1 = AVAM_DEFAULT_FREQUENCY;
if (!val2)
val3 = val2 = val1;
if (!val3)
val3 = val2;
if (!asic_index) {
for (i = 0; i < info->asic_cnts; i++) {
info->opt_freq[i][0] = val1;
info->opt_freq[i][1] = val2;
info->opt_freq[i][2] = val3;
}
FLAG_SET(info->freq_set, AVAM_ASIC_ALL);
applog(LOG_NOTICE, "Update all asic frequency to %d",
(val1 * 4 + val2 * 4 + val3) / 9);
}
if (asic_index) {
info->opt_freq[asic_index - 1][0] = val1;
info->opt_freq[asic_index - 1][1] = val2;
info->opt_freq[asic_index - 1][2] = val3;
FLAG_SET(info->freq_set, asic_index);
applog(LOG_NOTICE, "Update asic %d frequency to %d",
asic_index - 1,
(val1 * 4 + val2 * 4 + val3) / 9);
}
return NULL;
}
opt_avalonm_voltage = val;
return NULL;
}
info->opt_voltage = val;
applog(LOG_NOTICE, "%s-%d: Update voltage to %d",
avalonm->drv->name, avalonm->device_id, info->opt_voltage);
return NULL;
}
if (strcasecmp(option, "frequency") == 0) {
if (!setting || !*setting) {
sprintf(replybuf, "missing frequency value");
return replybuf;
}
if (set_avalonm_device_freq(avalonm, setting)) {
sprintf(replybuf, "invalid frequency value, valid range %d-%d",
AVAM_DEFAULT_FREQUENCY_MIN, AVAM_DEFAULT_FREQUENCY_MAX);
return replybuf;
}
return NULL;
}
if (strcasecmp(option, "voltage") == 0) {
if (!setting || !*setting) {
sprintf(replybuf, "missing voltage value");
return replybuf;
}
if (set_avalonm_device_voltage(avalonm, setting)) {
sprintf(replybuf, "invalid voltage value, valid range %d-%d",
AVAM_DEFAULT_VOLTAGE_MIN, AVAM_DEFAULT_VOLTAGE_MAX);
return replybuf;
}
return NULL;
}
memset(statbuf, 0, STATBUFLEN);
cgtime(&now);
sprintf(buf, " Elapsed[%.0f]", tdiff(&now, &(info->elapsed)));
strcat(statbuf, buf);
ac = info->asic_cnts;
mutex_lock(&info->qlock);
if (avalonm->queued >= ac)
goto out_unlock;
work = get_queued(avalonm);
if (unlikely(!work)) {
ret = false;
goto out_unlock;
}
subid = avalonm->queued++;
work->subid = subid;
slot = avalonm->work_array * ac + subid;
if (likely(avalonm->works[slot]))
work_completed(avalonm, avalonm->works[slot]);
avalonm->works[slot] = work;
if (avalonm->queued < ac)
ret = false;
out_unlock:
mutex_unlock(&info->qlock);
return ret;
}
/* Will overwrite any work queued. Do this unlocked since it's just
* changing a single non-critical value and prevents deadlocks */
avalonm->queued = 0;
.hash_work = hash_queued_work,
.scanwork = avalonm_scanhash,
.queue_full = avalonm_fill,
.flush_work = avalonm_flush_work,
.thread_shutdown = avalonm_shutdown,
};