mirror of
https://github.com/GOSTSec/sgminer
synced 2025-01-22 20:44:19 +00:00
Rework avalon reset sequence to include idling of chips and waiting for them to go idle followed by 2nd reset and then checking result.
This commit is contained in:
parent
569a6f65a0
commit
930317e123
236
driver-avalon.c
236
driver-avalon.c
@ -299,68 +299,139 @@ static bool avalon_decode_nonce(struct thr_info *thr, struct avalon_result *ar,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void avalon_get_reset(int fd, struct avalon_result *ar)
|
static int avalon_write(int fd, char *buf, ssize_t len)
|
||||||
{
|
{
|
||||||
int read_amount = AVALON_READ_SIZE;
|
ssize_t wrote = 0;
|
||||||
uint8_t result[AVALON_READ_SIZE];
|
|
||||||
struct timeval timeout = {1, 0};
|
|
||||||
ssize_t ret = 0, offset = 0;
|
|
||||||
fd_set rd;
|
|
||||||
|
|
||||||
memset(result, 0, AVALON_READ_SIZE);
|
while (len > 0) {
|
||||||
memset(ar, 0, AVALON_READ_SIZE);
|
struct timeval timeout;
|
||||||
FD_ZERO(&rd);
|
ssize_t ret;
|
||||||
FD_SET((SOCKETTYPE)fd, &rd);
|
fd_set wd;
|
||||||
ret = select(fd + 1, &rd, NULL, NULL, &timeout);
|
|
||||||
if (unlikely(ret < 0)) {
|
timeout.tv_sec = 0;
|
||||||
applog(LOG_WARNING, "Avalon: Error %d on select in avalon_get_reset", errno);
|
timeout.tv_usec = 1000;
|
||||||
return;
|
FD_ZERO(&wd);
|
||||||
}
|
FD_SET((SOCKETTYPE)fd, &wd);
|
||||||
if (!ret) {
|
ret = select(fd + 1, NULL, &wd, NULL, &timeout);
|
||||||
applog(LOG_WARNING, "Avalon: Timeout on select in avalon_get_reset");
|
if (unlikely(ret < 1)) {
|
||||||
return;
|
applog(LOG_WARNING, "Select error on avalon_write");
|
||||||
}
|
return AVA_SEND_ERROR;
|
||||||
do {
|
|
||||||
ret = read(fd, result + offset, read_amount);
|
|
||||||
if (unlikely(ret < 0)) {
|
|
||||||
applog(LOG_WARNING, "Avalon: Error %d on read in avalon_get_reset", errno);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
read_amount -= ret;
|
ret = write(fd, buf + wrote, len);
|
||||||
offset += ret;
|
if (unlikely(ret < 1)) {
|
||||||
} while (read_amount > 0);
|
applog(LOG_WARNING, "Write error on avalon_write");
|
||||||
if (opt_debug) {
|
return AVA_SEND_ERROR;
|
||||||
applog(LOG_DEBUG, "Avalon: get:");
|
}
|
||||||
hexdump((uint8_t *)result, AVALON_READ_SIZE);
|
wrote += ret;
|
||||||
|
len -= ret;
|
||||||
}
|
}
|
||||||
memcpy((uint8_t *)ar, result, AVALON_READ_SIZE);
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avalon_reset(int fd, struct avalon_result *ar)
|
static int avalon_read(int fd, char *buf, ssize_t len)
|
||||||
{
|
{
|
||||||
struct avalon_task at;
|
ssize_t aread = 0;
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
struct timeval timeout;
|
||||||
|
ssize_t ret;
|
||||||
|
fd_set rd;
|
||||||
|
|
||||||
|
timeout.tv_sec = 0;
|
||||||
|
timeout.tv_usec = 1000;
|
||||||
|
FD_ZERO(&rd);
|
||||||
|
FD_SET((SOCKETTYPE)fd, &rd);
|
||||||
|
ret = select(fd + 1, &rd, NULL, NULL, &timeout);
|
||||||
|
if (unlikely(ret < 1)) {
|
||||||
|
applog(LOG_WARNING, "Select error on avalon_read");
|
||||||
|
return AVA_GETS_ERROR;
|
||||||
|
}
|
||||||
|
ret = read(fd, buf + aread, len);
|
||||||
|
if (unlikely(ret < 1)) {
|
||||||
|
applog(LOG_WARNING, "Read error on avalon_read");
|
||||||
|
return AVA_GETS_ERROR;
|
||||||
|
}
|
||||||
|
aread += ret;
|
||||||
|
len -= ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Non blocking clearing of anything in the buffer */
|
||||||
|
static void avalon_clear_readbuf(int fd)
|
||||||
|
{
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
do {
|
||||||
|
struct timeval timeout;
|
||||||
|
char buf[AVALON_FTDI_READSIZE];
|
||||||
|
fd_set rd;
|
||||||
|
|
||||||
|
timeout.tv_sec = timeout.tv_usec = 0;
|
||||||
|
FD_ZERO(&rd);
|
||||||
|
FD_SET((SOCKETTYPE)fd, &rd);
|
||||||
|
ret = select(fd + 1, &rd, NULL, NULL, &timeout);
|
||||||
|
if (ret > 0)
|
||||||
|
ret = read(fd, buf, AVALON_FTDI_READSIZE);
|
||||||
|
} while (ret > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void avalon_idle(struct cgpu_info *avalon)
|
||||||
|
{
|
||||||
|
struct avalon_info *info = avalon->device_data;
|
||||||
|
int i, fd = avalon->device_fd;
|
||||||
|
|
||||||
|
for (i = 0; i < info->miner_count; i++) {
|
||||||
|
struct avalon_task at;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (unlikely(avalon_buffer_full(fd))) {
|
||||||
|
applog(LOG_WARNING, "Avalon buffer full in avalon_idle");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
avalon_init_task(&at, 0, 0, info->fan_pwm,
|
||||||
|
info->timeout, info->asic_count,
|
||||||
|
info->miner_count, 1, 1, info->frequency);
|
||||||
|
ret = avalon_write(fd, (char *)&at, AVALON_WRITE_SIZE);
|
||||||
|
if (unlikely(ret == AVA_SEND_ERROR))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
applog(LOG_ERR, "Avalon: Going to idle mode");
|
||||||
|
sleep(2);
|
||||||
|
avalon_clear_readbuf(fd);
|
||||||
|
applog(LOG_ERR, "Avalon: Idle");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int avalon_reset(struct cgpu_info *avalon, int fd)
|
||||||
|
{
|
||||||
|
struct avalon_result ar;
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
int ret, i = 0;
|
int ret, i = 0;
|
||||||
struct timespec p;
|
struct timespec p;
|
||||||
|
|
||||||
avalon_init_task(&at, 1, 0,
|
/* Reset once, then send command to go idle */
|
||||||
AVALON_DEFAULT_FAN_MAX_PWM,
|
ret = avalon_write(fd, "ad", 2);
|
||||||
AVALON_DEFAULT_TIMEOUT,
|
if (unlikely(ret == AVA_SEND_ERROR))
|
||||||
AVALON_DEFAULT_ASIC_NUM,
|
return -1;
|
||||||
AVALON_DEFAULT_MINER_NUM,
|
p.tv_sec = 0;
|
||||||
0, 0,
|
p.tv_nsec = AVALON_RESET_PITCH;
|
||||||
AVALON_DEFAULT_FREQUENCY);
|
nanosleep(&p, NULL);
|
||||||
ret = avalon_send_task(fd, &at, NULL);
|
avalon_clear_readbuf(fd);
|
||||||
if (ret == AVA_SEND_ERROR)
|
avalon_idle(avalon);
|
||||||
return 1;
|
/* Reset again, then check result */
|
||||||
|
ret = avalon_write(fd, "ad", 2);
|
||||||
|
if (unlikely(ret == AVA_SEND_ERROR))
|
||||||
|
return -1;
|
||||||
|
|
||||||
avalon_get_reset(fd, ar);
|
ret = avalon_read(fd, (char *)&ar, AVALON_READ_SIZE);
|
||||||
|
if (unlikely(ret == AVA_GETS_ERROR))
|
||||||
|
return -1;
|
||||||
|
|
||||||
buf = (uint8_t *)ar;
|
nanosleep(&p, NULL);
|
||||||
/* Sometimes there is one extra 0 byte for some reason in the buffer,
|
|
||||||
* so work around it. */
|
buf = (uint8_t *)&ar;
|
||||||
if (buf[0] == 0)
|
|
||||||
buf = (uint8_t *)(ar + 1);
|
|
||||||
if (buf[0] == 0xAA && buf[1] == 0x55 &&
|
if (buf[0] == 0xAA && buf[1] == 0x55 &&
|
||||||
buf[2] == 0xAA && buf[3] == 0x55) {
|
buf[2] == 0xAA && buf[3] == 0x55) {
|
||||||
for (i = 4; i < 11; i++)
|
for (i = 4; i < 11; i++)
|
||||||
@ -368,10 +439,6 @@ static int avalon_reset(int fd, struct avalon_result *ar)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
p.tv_sec = 0;
|
|
||||||
p.tv_nsec = AVALON_RESET_PITCH;
|
|
||||||
nanosleep(&p, NULL);
|
|
||||||
|
|
||||||
if (i != 11) {
|
if (i != 11) {
|
||||||
applog(LOG_ERR, "Avalon: Reset failed! not an Avalon?"
|
applog(LOG_ERR, "Avalon: Reset failed! not an Avalon?"
|
||||||
" (%d: %02x %02x %02x %02x)",
|
" (%d: %02x %02x %02x %02x)",
|
||||||
@ -382,38 +449,6 @@ static int avalon_reset(int fd, struct avalon_result *ar)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void avalon_idle(struct cgpu_info *avalon)
|
|
||||||
{
|
|
||||||
int i, ret;
|
|
||||||
struct avalon_task at;
|
|
||||||
|
|
||||||
int fd = avalon->device_fd;
|
|
||||||
struct avalon_info *info = avalon->device_data;
|
|
||||||
int avalon_get_work_count = info->miner_count;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
while (true) {
|
|
||||||
avalon_init_task(&at, 0, 0, info->fan_pwm,
|
|
||||||
info->timeout, info->asic_count,
|
|
||||||
info->miner_count, 1, 1, info->frequency);
|
|
||||||
ret = avalon_send_task(fd, &at, avalon);
|
|
||||||
if (unlikely(ret == AVA_SEND_ERROR ||
|
|
||||||
(ret == AVA_SEND_BUFFER_EMPTY &&
|
|
||||||
(i + 1 == avalon_get_work_count * 2)))) {
|
|
||||||
applog(LOG_ERR, "AVA%i: Comms error", avalon->device_id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (i + 1 == avalon_get_work_count * 2)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (ret == AVA_SEND_BUFFER_FULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
applog(LOG_ERR, "Avalon: Goto idle mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void get_options(int this_option_offset, int *baud, int *miner_count,
|
static void get_options(int this_option_offset, int *baud, int *miner_count,
|
||||||
int *asic_count, int *timeout, int *frequency)
|
int *asic_count, int *timeout, int *frequency)
|
||||||
{
|
{
|
||||||
@ -550,29 +585,9 @@ static void get_options(int this_option_offset, int *baud, int *miner_count,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Non blocking clearing of anything in the buffer */
|
|
||||||
static void avalon_clear_readbuf(int fd)
|
|
||||||
{
|
|
||||||
ssize_t ret;
|
|
||||||
|
|
||||||
do {
|
|
||||||
struct timeval timeout;
|
|
||||||
char buf[AVALON_FTDI_READSIZE];
|
|
||||||
fd_set rd;
|
|
||||||
|
|
||||||
timeout.tv_sec = timeout.tv_usec = 0;
|
|
||||||
FD_ZERO(&rd);
|
|
||||||
FD_SET((SOCKETTYPE)fd, &rd);
|
|
||||||
ret = select(fd + 1, &rd, NULL, NULL, &timeout);
|
|
||||||
if (ret > 0)
|
|
||||||
ret = read(fd, buf, AVALON_FTDI_READSIZE);
|
|
||||||
} while (ret > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool avalon_detect_one(const char *devpath)
|
static bool avalon_detect_one(const char *devpath)
|
||||||
{
|
{
|
||||||
struct avalon_info *info;
|
struct avalon_info *info;
|
||||||
struct avalon_result ar;
|
|
||||||
int fd, ret;
|
int fd, ret;
|
||||||
int baud, miner_count, asic_count, timeout, frequency = 0;
|
int baud, miner_count, asic_count, timeout, frequency = 0;
|
||||||
struct cgpu_info *avalon;
|
struct cgpu_info *avalon;
|
||||||
@ -600,7 +615,7 @@ static bool avalon_detect_one(const char *devpath)
|
|||||||
avalon->threads = AVALON_MINER_THREADS;
|
avalon->threads = AVALON_MINER_THREADS;
|
||||||
add_cgpu(avalon);
|
add_cgpu(avalon);
|
||||||
|
|
||||||
ret = avalon_reset(fd, &ar);
|
ret = avalon_reset(avalon, fd);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
; /* FIXME: I think IT IS avalon and wait on reset;
|
; /* FIXME: I think IT IS avalon and wait on reset;
|
||||||
* avalon_close(fd);
|
* avalon_close(fd);
|
||||||
@ -640,8 +655,6 @@ static bool avalon_detect_one(const char *devpath)
|
|||||||
info->temp_old = 0;
|
info->temp_old = 0;
|
||||||
info->frequency = frequency;
|
info->frequency = frequency;
|
||||||
|
|
||||||
/* Set asic to idle mode after detect */
|
|
||||||
avalon_idle(avalon);
|
|
||||||
avalon->device_fd = -1;
|
avalon->device_fd = -1;
|
||||||
|
|
||||||
avalon_close(fd);
|
avalon_close(fd);
|
||||||
@ -661,7 +674,6 @@ static void __avalon_init(struct cgpu_info *avalon)
|
|||||||
static void avalon_init(struct cgpu_info *avalon)
|
static void avalon_init(struct cgpu_info *avalon)
|
||||||
{
|
{
|
||||||
struct avalon_info *info = avalon->device_data;
|
struct avalon_info *info = avalon->device_data;
|
||||||
struct avalon_result ar;
|
|
||||||
int fd, ret;
|
int fd, ret;
|
||||||
|
|
||||||
avalon->device_fd = -1;
|
avalon->device_fd = -1;
|
||||||
@ -672,7 +684,7 @@ static void avalon_init(struct cgpu_info *avalon)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = avalon_reset(fd, &ar);
|
ret = avalon_reset(avalon, fd);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
avalon_close(fd);
|
avalon_close(fd);
|
||||||
return;
|
return;
|
||||||
@ -727,14 +739,12 @@ static void avalon_free_work(struct thr_info *thr)
|
|||||||
|
|
||||||
static void do_avalon_close(struct thr_info *thr)
|
static void do_avalon_close(struct thr_info *thr)
|
||||||
{
|
{
|
||||||
struct avalon_result ar;
|
|
||||||
struct cgpu_info *avalon = thr->cgpu;
|
struct cgpu_info *avalon = thr->cgpu;
|
||||||
struct avalon_info *info = avalon->device_data;
|
struct avalon_info *info = avalon->device_data;
|
||||||
|
|
||||||
avalon_free_work(thr);
|
avalon_free_work(thr);
|
||||||
sleep(1);
|
sleep(1);
|
||||||
avalon_reset(avalon->device_fd, &ar);
|
avalon_reset(avalon, avalon->device_fd);
|
||||||
avalon_idle(avalon);
|
|
||||||
avalon_close(avalon->device_fd);
|
avalon_close(avalon->device_fd);
|
||||||
avalon->device_fd = -1;
|
avalon->device_fd = -1;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user