static int polling(struct thr_info *thr) { int i, tmp; struct avalon2_pkg send_pkg; struct avalon2_ret ar; struct cgpu_info *avalon2 = thr->cgpu; struct avalon2_info *info = avalon2->device_data; for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) { if (info->modulars[i]) { memset(send_pkg.data, 0, AVA2_P_DATA_LEN); tmp = be32toh(i); memcpy(send_pkg.data + 28, &tmp, 4); avalon2_init_pkg(&send_pkg, AVA2_P_POLLING, 1, 1); while (avalon2_send_pkg(info->fd, &send_pkg, thr) != AVA2_SEND_OK) ; avalon2_get_result(thr, info->fd, &ar); } } return 0; }
static int polling(struct thr_info *thr) { int i, tmp; struct avalon2_pkg send_pkg; struct avalon2_ret ar; struct cgpu_info *avalon2 = thr->cgpu; struct avalon2_info *info = avalon2->device_data; static int pre_led_red[AVA2_DEFAULT_MODULARS]; for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) { if (info->modulars[i] && info->enable[i]) { cgsleep_ms(20); memset(send_pkg.data, 0, AVA2_P_DATA_LEN); tmp = be32toh(info->led_red[i]); /* RED LED */ memcpy(send_pkg.data + 12, &tmp, 4); tmp = be32toh(i); /* ID */ memcpy(send_pkg.data + 28, &tmp, 4); if (info->led_red[i] && mm_cmp_1404(info, i)) { avalon2_init_pkg(&send_pkg, AVA2_P_TEST, 1, 1); while (avalon2_send_pkg(info->fd, &send_pkg, thr) != AVA2_SEND_OK) ; info->enable[i] = 0; continue; } else avalon2_init_pkg(&send_pkg, AVA2_P_POLLING, 1, 1); while (avalon2_send_pkg(info->fd, &send_pkg, thr) != AVA2_SEND_OK) ; avalon2_get_result(thr, info->fd, &ar); } } return 0; }
static int64_t avalon2_scanhash(struct thr_info *thr) { struct avalon2_pkg send_pkg; struct pool *pool; struct cgpu_info *avalon2 = thr->cgpu; struct avalon2_info *info = avalon2->device_data; int64_t h; uint32_t tmp, range, start; int i; if (thr->work_restart || thr->work_update || info->first) { info->new_stratum = true; applog(LOG_DEBUG, "Avalon2: New stratum: restart: %d, update: %d, first: %d", thr->work_restart, thr->work_update, info->first); thr->work_update = false; thr->work_restart = false; if (unlikely(info->first)) info->first = false; get_work(thr, thr->id); /* Make sure pool is ready */ pool = current_pool(); if (!pool->has_stratum) quit(1, "Avalon2: Miner Manager have to use stratum pool"); if (pool->swork.cb_len > AVA2_P_COINBASE_SIZE) quit(1, "Avalon2: Miner Manager pool coinbase length have to less then %d", AVA2_P_COINBASE_SIZE); if (pool->swork.merkles > AVA2_P_MERKLES_COUNT) quit(1, "Avalon2: Miner Manager merkles have to less then %d", AVA2_P_MERKLES_COUNT); info->diff = (int)pool->swork.diff - 1; info->pool_no = pool->pool_no; cg_wlock(&pool->data_lock); avalon2_stratum_pkgs(info->fd, pool, thr); cg_wunlock(&pool->data_lock); /* Configuer the parameter from outside */ info->fan_pwm = opt_avalon2_fan_min; info->set_voltage = opt_avalon2_voltage_min; info->set_frequency = opt_avalon2_freq_min; /* Set the Fan, Voltage and Frequency */ memset(send_pkg.data, 0, AVA2_P_DATA_LEN); tmp = be32toh(info->fan_pwm); memcpy(send_pkg.data, &tmp, 4); tmp = encode_voltage(info->set_voltage); tmp = be32toh(tmp); memcpy(send_pkg.data + 4, &tmp, 4); tmp = be32toh(info->set_frequency); memcpy(send_pkg.data + 8, &tmp, 4); /* Configure the nonce2 offset and range */ range = 0xffffffff / total_devices; start = range * avalon2->device_id; tmp = be32toh(start); memcpy(send_pkg.data + 12, &tmp, 4); tmp = be32toh(range); memcpy(send_pkg.data + 16, &tmp, 4); /* Package the data */ avalon2_init_pkg(&send_pkg, AVA2_P_SET, 1, 1); while (avalon2_send_pkg(info->fd, &send_pkg, thr) != AVA2_SEND_OK) ; info->new_stratum = false; } polling(thr); h = 0; for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) { h += info->local_work[i]; } return h * 0xffffffff; }
static bool avalon2_detect_one(const char *devpath) { struct avalon2_info *info; int ackdetect; int fd; int tmp, i, modular[3]; char mm_version[AVA2_DEFAULT_MODULARS][16]; struct cgpu_info *avalon2; struct avalon2_pkg detect_pkg; struct avalon2_ret ret_pkg; applog(LOG_DEBUG, "Avalon2 Detect: Attempting to open %s", devpath); fd = avalon2_open(devpath, AVA2_IO_SPEED, true); if (unlikely(fd == -1)) { applog(LOG_ERR, "Avalon2 Detect: Failed to open %s", devpath); return false; } tcflush(fd, TCIOFLUSH); for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) { modular[i] = 0; strcpy(mm_version[i], "NONE"); /* Send out detect pkg */ memset(detect_pkg.data, 0, AVA2_P_DATA_LEN); tmp = be32toh(i); memcpy(detect_pkg.data + 28, &tmp, 4); avalon2_init_pkg(&detect_pkg, AVA2_P_DETECT, 1, 1); avalon2_send_pkg(fd, &detect_pkg, NULL); ackdetect = avalon2_get_result(NULL, fd, &ret_pkg); applog(LOG_DEBUG, "Avalon2 Detect ID[%d]: %d", i, ackdetect); if (ackdetect != AVA2_P_ACKDETECT) continue; modular[i] = 1; memcpy(mm_version[i], ret_pkg.data, 15); mm_version[i][15] = '\0'; } if (!modular[0] && !modular[1] && !modular[2]) return false; /* We have a real Avalon! */ avalon2 = calloc(1, sizeof(struct cgpu_info)); avalon2->drv = &avalon2_drv; avalon2->device_path = strdup(devpath); avalon2->threads = AVA2_MINER_THREADS; add_cgpu(avalon2); applog(LOG_INFO, "Avalon2 Detect: Found at %s, mark as %d", devpath, avalon2->device_id); avalon2->device_data = calloc(sizeof(struct avalon2_info), 1); if (unlikely(!(avalon2->device_data))) quit(1, "Failed to malloc avalon2_info"); info = avalon2->device_data; strcpy(info->mm_version[0], mm_version[0]); strcpy(info->mm_version[1], mm_version[1]); strcpy(info->mm_version[2], mm_version[2]); info->baud = AVA2_IO_SPEED; info->fan_pwm = AVA2_DEFAULT_FAN_PWM; info->set_voltage = AVA2_DEFAULT_VOLTAGE_MIN; info->set_frequency = AVA2_DEFAULT_FREQUENCY; info->temp_max = 0; info->temp_history_index = 0; info->temp_sum = 0; info->temp_old = 0; info->modulars[0] = modular[0]; info->modulars[1] = modular[1]; info->modulars[2] = modular[2]; /* Enable modular */ info->fd = -1; /* Set asic to idle mode after detect */ avalon2_close(fd); return true; }
static int avalon2_stratum_pkgs(int fd, struct pool *pool, struct thr_info *thr) { struct avalon2_pkg pkg; int i, a, b, tmp; unsigned char target[32]; int job_id_len; /* Send out the first stratum message STATIC */ applog(LOG_DEBUG, "Avalon2: Pool stratum message STATIC: %ld, %d, %d, %d, %d", pool->swork.cb_len, pool->nonce2_offset, pool->n2size, pool->merkle_offset, pool->swork.merkles); memset(pkg.data, 0, AVA2_P_DATA_LEN); tmp = be32toh(pool->swork.cb_len); memcpy(pkg.data, &tmp, 4); tmp = be32toh(pool->nonce2_offset); memcpy(pkg.data + 4, &tmp, 4); tmp = be32toh(pool->n2size); memcpy(pkg.data + 8, &tmp, 4); tmp = be32toh(pool->merkle_offset); memcpy(pkg.data + 12, &tmp, 4); tmp = be32toh(pool->swork.merkles); memcpy(pkg.data + 16, &tmp, 4); tmp = be32toh((int)pool->swork.diff); memcpy(pkg.data + 20, &tmp, 4); tmp = be32toh((int)pool->pool_no); memcpy(pkg.data + 24, &tmp, 4); avalon2_init_pkg(&pkg, AVA2_P_STATIC, 1, 1); while (avalon2_send_pkg(fd, &pkg, thr) != AVA2_SEND_OK) ; set_target(target, pool->swork.diff); memcpy(pkg.data, target, 32); if (opt_debug) { char *target_str; target_str = bin2hex(target, 32); applog(LOG_DEBUG, "Avalon2: Pool stratum target: %s", target_str); free(target_str); } avalon2_init_pkg(&pkg, AVA2_P_TARGET, 1, 1); while (avalon2_send_pkg(fd, &pkg, thr) != AVA2_SEND_OK) ; applog(LOG_DEBUG, "Avalon2: Pool stratum message JOBS_ID: %s", pool->swork.job_id); memset(pkg.data, 0, AVA2_P_DATA_LEN); job_id_len = strlen(pool->swork.job_id); job_id_len = job_id_len >= 4 ? 4 : job_id_len; for (i = 0; i < job_id_len; i++) { pkg.data[i] = *(pool->swork.job_id + strlen(pool->swork.job_id) - 4 + i); } avalon2_init_pkg(&pkg, AVA2_P_JOB_ID, 1, 1); while (avalon2_send_pkg(fd, &pkg, thr) != AVA2_SEND_OK) ; a = pool->swork.cb_len / AVA2_P_DATA_LEN; b = pool->swork.cb_len % AVA2_P_DATA_LEN; applog(LOG_DEBUG, "Avalon2: Pool stratum message COINBASE: %d %d", a, b); for (i = 0; i < a; i++) { memcpy(pkg.data, pool->coinbase + i * 32, 32); avalon2_init_pkg(&pkg, AVA2_P_COINBASE, i + 1, a + (b ? 1 : 0)); while (avalon2_send_pkg(fd, &pkg, thr) != AVA2_SEND_OK) ; } if (b) { memset(pkg.data, 0, AVA2_P_DATA_LEN); memcpy(pkg.data, pool->coinbase + i * 32, b); avalon2_init_pkg(&pkg, AVA2_P_COINBASE, i + 1, i + 1); while (avalon2_send_pkg(fd, &pkg, thr) != AVA2_SEND_OK) ; } b = pool->swork.merkles; applog(LOG_DEBUG, "Avalon2: Pool stratum message MERKLES: %d", b); for (i = 0; i < b; i++) { memset(pkg.data, 0, AVA2_P_DATA_LEN); memcpy(pkg.data, pool->swork.merkle_bin[i], 32); avalon2_init_pkg(&pkg, AVA2_P_MERKLES, i + 1, b); while (avalon2_send_pkg(fd, &pkg, thr) != AVA2_SEND_OK) ; } applog(LOG_DEBUG, "Avalon2: Pool stratum message HEADER: 4"); for (i = 0; i < 4; i++) { memset(pkg.data, 0, AVA2_P_HEADER); memcpy(pkg.data, pool->header_bin + i * 32, 32); avalon2_init_pkg(&pkg, AVA2_P_HEADER, i + 1, 4); while (avalon2_send_pkg(fd, &pkg, thr) != AVA2_SEND_OK) ; } return 0; }
static int64_t avalon2_scanhash(struct thr_info *thr) { struct avalon2_pkg send_pkg; struct timeval current_stratum; struct pool *pool; struct cgpu_info *avalon2 = thr->cgpu; struct avalon2_info *info = avalon2->device_data; int64_t h; uint32_t tmp, range, start; int i; if (thr->work_restart || thr->work_update || !info->first) { applog(LOG_DEBUG, "Avalon2: New stratum: restart: %d, update: %d, first: %d", thr->work_restart, thr->work_update, info->first); thr->work_update = false; thr->work_restart = false; get_work(thr, thr->id); /* Make sure pool is ready */ pool = current_pool(); if (!pool->has_stratum) quit(1, "Avalon2: Miner Manager have to use stratum pool"); if (pool->coinbase_len > AVA2_P_COINBASE_SIZE) { applog(LOG_ERR, "Avalon2: Miner Manager pool coinbase length have to less then %d", AVA2_P_COINBASE_SIZE); return 0; } if (pool->merkles > AVA2_P_MERKLES_COUNT) { applog(LOG_ERR, "Avalon2: Miner Manager merkles have to less then %d", AVA2_P_MERKLES_COUNT); return 0; } cgtime(&info->last_stratum); cg_rlock(&pool->data_lock); info->pool_no = pool->pool_no; copy_pool_stratum(pool); avalon2_stratum_pkgs(info->fd, pool, thr); cg_runlock(&pool->data_lock); /* Configuer the parameter from outside */ adjust_fan(info); info->set_voltage = opt_avalon2_voltage_min; info->set_frequency = opt_avalon2_freq_min; /* Set the Fan, Voltage and Frequency */ memset(send_pkg.data, 0, AVA2_P_DATA_LEN); tmp = be32toh(info->fan_pwm); memcpy(send_pkg.data, &tmp, 4); applog(LOG_ERR, "Avalon2: Temp max: %d, Cut off temp: %d", get_current_temp_max(info), opt_avalon2_overheat); if (get_current_temp_max(info) >= opt_avalon2_overheat) tmp = encode_voltage(0); else tmp = encode_voltage(info->set_voltage); tmp = be32toh(tmp); memcpy(send_pkg.data + 4, &tmp, 4); tmp = be32toh(info->set_frequency); memcpy(send_pkg.data + 8, &tmp, 4); /* Configure the nonce2 offset and range */ range = 0xffffffff / total_devices; start = range * avalon2->device_id; tmp = be32toh(start); memcpy(send_pkg.data + 12, &tmp, 4); tmp = be32toh(range); memcpy(send_pkg.data + 16, &tmp, 4); /* Package the data */ avalon2_init_pkg(&send_pkg, AVA2_P_SET, 1, 1); while (avalon2_send_pkg(info->fd, &send_pkg, thr) != AVA2_SEND_OK) ; if (unlikely(info->first < 2)) info->first++; } /* Stop polling the device if there is no stratum in 3 minutes, network is down */ cgtime(¤t_stratum); if (tdiff(¤t_stratum, &(info->last_stratum)) > (double)(3.0 * 60.0)) return 0; polling(thr); h = 0; for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) { h += info->enable[i] ? (info->local_work[i] - info->hw_work[i]) : 0; } return h * 0xffffffff; }
static bool avalon2_detect_one(const char *devpath) { struct avalon2_info *info; int ackdetect; int fd; int tmp, i, j, modular[AVA2_DEFAULT_MODULARS]; char mm_version[AVA2_DEFAULT_MODULARS][16]; struct cgpu_info *avalon2; struct avalon2_pkg detect_pkg; struct avalon2_ret ret_pkg; applog(LOG_DEBUG, "Avalon2 Detect: Attempting to open %s", devpath); fd = avalon2_open(devpath, AVA2_IO_SPEED, true); if (unlikely(fd == -1)) { applog(LOG_ERR, "Avalon2 Detect: Failed to open %s", devpath); return false; } tcflush(fd, TCIOFLUSH); for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) modular[i] = 0; for (j = 0; j < 2; j++) { for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) { strcpy(mm_version[i], AVA2_MM_VERNULL); /* Send out detect pkg */ memset(detect_pkg.data, 0, AVA2_P_DATA_LEN); tmp = be32toh(i); memcpy(detect_pkg.data + 28, &tmp, 4); avalon2_init_pkg(&detect_pkg, AVA2_P_DETECT, 1, 1); avalon2_send_pkg(fd, &detect_pkg, NULL); ackdetect = avalon2_get_result(NULL, fd, &ret_pkg); applog(LOG_DEBUG, "Avalon2 Detect ID[%d]: %d", i, ackdetect); if (ackdetect != AVA2_P_ACKDETECT && modular[i] == 0) continue; modular[i] = 1; memcpy(mm_version[i], ret_pkg.data, 15); mm_version[i][15] = '\0'; } } avalon2_close(fd); if (!modular[0] && !modular[1] && !modular[2] && !modular[3]) return false; /* We have a real Avalon! */ avalon2 = calloc(1, sizeof(struct cgpu_info)); avalon2->drv = &avalon2_drv; avalon2->device_path = strdup(devpath); avalon2->threads = AVA2_MINER_THREADS; add_cgpu(avalon2); applog(LOG_INFO, "Avalon2 Detect: Found at %s, mark as %d", devpath, avalon2->device_id); avalon2->device_data = calloc(sizeof(struct avalon2_info), 1); if (unlikely(!(avalon2->device_data))) quit(1, "Failed to malloc avalon2_info"); info = avalon2->device_data; info->fd = -1; info->baud = AVA2_IO_SPEED; info->fan_pwm = AVA2_DEFAULT_FAN_PWM; info->set_voltage = AVA2_DEFAULT_VOLTAGE_MIN; info->set_frequency = AVA2_DEFAULT_FREQUENCY; info->temp_max = 0; for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) { strcpy(info->mm_version[i], mm_version[i]); info->modulars[i] = modular[i]; /* Enable modular */ info->enable[i] = modular[i]; info->dev_type[i] = AVA2_ID_AVAX; if (!strncmp((char *)&(info->mm_version[i]), AVA2_FW2_PREFIXSTR, 2)) info->dev_type[i] = AVA2_ID_AVA2; if (!strncmp((char *)&(info->mm_version[i]), AVA2_FW3_PREFIXSTR, 2)) info->dev_type[i] = AVA2_ID_AVA3; } pool_stratum.swork.job_id = NULL; pool_stratum.merkles = 0; return true; }