|
@@ -146,7 +146,9 @@ static int avalon_send_task(const struct avalon_task *at, struct cgpu_info *aval
|
|
|
|
|
|
|
|
{
|
|
{
|
|
|
uint8_t buf[AVALON_WRITE_SIZE + 4 * AVALON_DEFAULT_ASIC_NUM];
|
|
uint8_t buf[AVALON_WRITE_SIZE + 4 * AVALON_DEFAULT_ASIC_NUM];
|
|
|
- int ret, i, ep = C_AVALON_TASK;
|
|
|
|
|
|
|
+ int delay, ret, i, ep = C_AVALON_TASK;
|
|
|
|
|
+ struct avalon_info *info;
|
|
|
|
|
+ cgtimer_t ts_start;
|
|
|
uint32_t nonce_range;
|
|
uint32_t nonce_range;
|
|
|
size_t nr_len;
|
|
size_t nr_len;
|
|
|
|
|
|
|
@@ -187,6 +189,10 @@ static int avalon_send_task(const struct avalon_task *at, struct cgpu_info *aval
|
|
|
tt |= ((buf[4] & 0x80) ? (1 << 0) : 0);
|
|
tt |= ((buf[4] & 0x80) ? (1 << 0) : 0);
|
|
|
buf[4] = tt;
|
|
buf[4] = tt;
|
|
|
#endif
|
|
#endif
|
|
|
|
|
+ info = avalon->device_data;
|
|
|
|
|
+ delay = nr_len * 10 * 1000000;
|
|
|
|
|
+ delay = delay / info->baud;
|
|
|
|
|
+ delay += 4000;
|
|
|
|
|
|
|
|
if (at->reset) {
|
|
if (at->reset) {
|
|
|
ep = C_AVALON_RESET;
|
|
ep = C_AVALON_RESET;
|
|
@@ -196,9 +202,11 @@ static int avalon_send_task(const struct avalon_task *at, struct cgpu_info *aval
|
|
|
applog(LOG_DEBUG, "Avalon: Sent(%u):", (unsigned int)nr_len);
|
|
applog(LOG_DEBUG, "Avalon: Sent(%u):", (unsigned int)nr_len);
|
|
|
hexdump(buf, nr_len);
|
|
hexdump(buf, nr_len);
|
|
|
}
|
|
}
|
|
|
|
|
+ cgsleep_prepare_r(&ts_start);
|
|
|
ret = avalon_write(avalon, (char *)buf, nr_len, ep);
|
|
ret = avalon_write(avalon, (char *)buf, nr_len, ep);
|
|
|
- /* Avalon needs a rest between submissions :P */
|
|
|
|
|
- cgsleep_ms(4);
|
|
|
|
|
|
|
+ cgsleep_us_r(&ts_start, delay);
|
|
|
|
|
+
|
|
|
|
|
+ applog(LOG_DEBUG, "Avalon: Sent: Buffer delay: %dus", delay);
|
|
|
|
|
|
|
|
return ret;
|
|
return ret;
|
|
|
}
|
|
}
|
|
@@ -208,6 +216,7 @@ static int bitburner_send_task(const struct avalon_task *at, struct cgpu_info *a
|
|
|
{
|
|
{
|
|
|
uint8_t buf[AVALON_WRITE_SIZE + 4 * AVALON_DEFAULT_ASIC_NUM];
|
|
uint8_t buf[AVALON_WRITE_SIZE + 4 * AVALON_DEFAULT_ASIC_NUM];
|
|
|
int ret, ep = C_AVALON_TASK;
|
|
int ret, ep = C_AVALON_TASK;
|
|
|
|
|
+ cgtimer_t ts_start;
|
|
|
size_t nr_len;
|
|
size_t nr_len;
|
|
|
|
|
|
|
|
if (at->nonce_elf)
|
|
if (at->nonce_elf)
|
|
@@ -244,7 +253,9 @@ static int bitburner_send_task(const struct avalon_task *at, struct cgpu_info *a
|
|
|
applog(LOG_DEBUG, "Avalon: Sent(%u):", (unsigned int)nr_len);
|
|
applog(LOG_DEBUG, "Avalon: Sent(%u):", (unsigned int)nr_len);
|
|
|
hexdump(buf, nr_len);
|
|
hexdump(buf, nr_len);
|
|
|
}
|
|
}
|
|
|
|
|
+ cgsleep_prepare_r(&ts_start);
|
|
|
ret = avalon_write(avalon, (char *)buf, nr_len, ep);
|
|
ret = avalon_write(avalon, (char *)buf, nr_len, ep);
|
|
|
|
|
+ cgsleep_us_r(&ts_start, 3000); // 3 ms = 333 tasks per second, or 1.4 TH/s
|
|
|
|
|
|
|
|
return ret;
|
|
return ret;
|
|
|
}
|
|
}
|
|
@@ -277,32 +288,14 @@ static inline bool avalon_cts(char c)
|
|
|
return (c & AVALON_CTS);
|
|
return (c & AVALON_CTS);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static int avalon_read(struct cgpu_info *avalon, unsigned char *buf,
|
|
|
|
|
- size_t bufsize, int timeout, int ep)
|
|
|
|
|
|
|
+static int avalon_read(struct cgpu_info *avalon, char *buf, size_t bufsize, int ep)
|
|
|
{
|
|
{
|
|
|
- size_t total = 0, readsize = bufsize + 2;
|
|
|
|
|
- char readbuf[AVALON_READBUF_SIZE];
|
|
|
|
|
- int err, amount, ofs = 2, cp;
|
|
|
|
|
|
|
+ int err, amount;
|
|
|
|
|
|
|
|
- err = usb_read_once_timeout(avalon, readbuf, readsize, &amount, timeout, ep);
|
|
|
|
|
|
|
+ err = usb_read_once(avalon, buf, bufsize, &amount, ep);
|
|
|
applog(LOG_DEBUG, "%s%i: Get avalon read got err %d",
|
|
applog(LOG_DEBUG, "%s%i: Get avalon read got err %d",
|
|
|
avalon->drv->name, avalon->device_id, err);
|
|
avalon->drv->name, avalon->device_id, err);
|
|
|
-
|
|
|
|
|
- if (amount < 2)
|
|
|
|
|
- goto out;
|
|
|
|
|
-
|
|
|
|
|
- /* The first 2 of every 64 bytes are status on FTDIRL */
|
|
|
|
|
- while (amount > 2) {
|
|
|
|
|
- cp = amount - 2;
|
|
|
|
|
- if (cp > 62)
|
|
|
|
|
- cp = 62;
|
|
|
|
|
- memcpy(&buf[total], &readbuf[ofs], cp);
|
|
|
|
|
- total += cp;
|
|
|
|
|
- amount -= cp + 2;
|
|
|
|
|
- ofs += 64;
|
|
|
|
|
- }
|
|
|
|
|
-out:
|
|
|
|
|
- return total;
|
|
|
|
|
|
|
+ return amount;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static int avalon_reset(struct cgpu_info *avalon, bool initial)
|
|
static int avalon_reset(struct cgpu_info *avalon, bool initial)
|
|
@@ -333,8 +326,7 @@ static int avalon_reset(struct cgpu_info *avalon, bool initial)
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- ret = avalon_read(avalon, (unsigned char *)&ar, AVALON_READ_SIZE,
|
|
|
|
|
- AVALON_RESET_TIMEOUT, C_GET_AVALON_RESET);
|
|
|
|
|
|
|
+ ret = avalon_read(avalon, (char *)&ar, AVALON_READ_SIZE, C_GET_AVALON_RESET);
|
|
|
|
|
|
|
|
/* What do these sleeps do?? */
|
|
/* What do these sleeps do?? */
|
|
|
p.tv_sec = 0;
|
|
p.tv_sec = 0;
|
|
@@ -766,9 +758,7 @@ static bool avalon_detect_one(libusb_device *dev, struct usb_find_devices *found
|
|
|
&asic_count, &timeout, &frequency,
|
|
&asic_count, &timeout, &frequency,
|
|
|
(usb_ident(avalon) == IDENT_BBF && opt_bitburner_fury_options != NULL) ? opt_bitburner_fury_options : opt_avalon_options);
|
|
(usb_ident(avalon) == IDENT_BBF && opt_bitburner_fury_options != NULL) ? opt_bitburner_fury_options : opt_avalon_options);
|
|
|
|
|
|
|
|
- /* Even though this is an FTDI type chip, we want to do the parsing
|
|
|
|
|
- * all ourselves so set it to std usb type */
|
|
|
|
|
- avalon->usbdev->usb_type = USB_TYPE_STD;
|
|
|
|
|
|
|
+ avalon->usbdev->usb_type = USB_TYPE_FTDI;
|
|
|
|
|
|
|
|
/* We have a real Avalon! */
|
|
/* We have a real Avalon! */
|
|
|
avalon_initialise(avalon);
|
|
avalon_initialise(avalon);
|
|
@@ -814,9 +804,6 @@ static bool avalon_detect_one(libusb_device *dev, struct usb_find_devices *found
|
|
|
if (!add_cgpu(avalon))
|
|
if (!add_cgpu(avalon))
|
|
|
goto unshin;
|
|
goto unshin;
|
|
|
|
|
|
|
|
- usb_set_cps(avalon, info->baud / 10);
|
|
|
|
|
- usb_enable_cps(avalon);
|
|
|
|
|
-
|
|
|
|
|
ret = avalon_reset(avalon, true);
|
|
ret = avalon_reset(avalon, true);
|
|
|
if (ret && !configured)
|
|
if (ret && !configured)
|
|
|
goto unshin;
|
|
goto unshin;
|
|
@@ -971,16 +958,14 @@ static void *avalon_get_results(void *userdata)
|
|
|
const int rsize = AVALON_FTDI_READSIZE;
|
|
const int rsize = AVALON_FTDI_READSIZE;
|
|
|
char readbuf[AVALON_READBUF_SIZE];
|
|
char readbuf[AVALON_READBUF_SIZE];
|
|
|
struct thr_info *thr = info->thr;
|
|
struct thr_info *thr = info->thr;
|
|
|
- cgtimer_t ts_start;
|
|
|
|
|
int offset = 0, ret = 0;
|
|
int offset = 0, ret = 0;
|
|
|
char threadname[24];
|
|
char threadname[24];
|
|
|
|
|
|
|
|
snprintf(threadname, 24, "ava_recv/%d", avalon->device_id);
|
|
snprintf(threadname, 24, "ava_recv/%d", avalon->device_id);
|
|
|
RenameThread(threadname);
|
|
RenameThread(threadname);
|
|
|
- cgsleep_prepare_r(&ts_start);
|
|
|
|
|
|
|
|
|
|
while (likely(!avalon->shutdown)) {
|
|
while (likely(!avalon->shutdown)) {
|
|
|
- unsigned char buf[rsize];
|
|
|
|
|
|
|
+ char buf[rsize];
|
|
|
|
|
|
|
|
if (offset >= (int)AVALON_READ_SIZE)
|
|
if (offset >= (int)AVALON_READ_SIZE)
|
|
|
avalon_parse_results(avalon, info, thr, readbuf, &offset);
|
|
avalon_parse_results(avalon, info, thr, readbuf, &offset);
|
|
@@ -997,16 +982,7 @@ static void *avalon_get_results(void *userdata)
|
|
|
offset = 0;
|
|
offset = 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /* As the usb read returns after just 1ms, sleep long enough
|
|
|
|
|
- * to leave the interface idle for writes to occur, but do not
|
|
|
|
|
- * sleep if we have been receiving data, and we do not yet have
|
|
|
|
|
- * a full result as more may be coming. */
|
|
|
|
|
- if (ret < 1 || offset == 0)
|
|
|
|
|
- cgsleep_ms_r(&ts_start, AVALON_READ_TIMEOUT);
|
|
|
|
|
-
|
|
|
|
|
- cgsleep_prepare_r(&ts_start);
|
|
|
|
|
- ret = avalon_read(avalon, buf, rsize, AVALON_READ_TIMEOUT,
|
|
|
|
|
- C_AVALON_READ);
|
|
|
|
|
|
|
+ ret = avalon_read(avalon, buf, rsize, C_AVALON_READ);
|
|
|
|
|
|
|
|
if (ret < 1)
|
|
if (ret < 1)
|
|
|
continue;
|
|
continue;
|