Browse Source

Use usbutils' own ftdi parser for avalon and the ftdir's own latency for managing timeouts since we can wait on reads with completely asynchronous reads+writes.

Con Kolivas 12 years ago
parent
commit
2dd7d2f676
2 changed files with 23 additions and 49 deletions
  1. 22 46
      driver-avalon.c
  2. 1 3
      driver-avalon.h

+ 22 - 46
driver-avalon.c

@@ -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];
-	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;
 	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);
 	buf[4] = tt;
 #endif
+	info = avalon->device_data;
+	delay = nr_len * 10 * 1000000;
+	delay = delay / info->baud;
+	delay += 4000;
 
 	if (at->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);
 		hexdump(buf, nr_len);
 	}
+	cgsleep_prepare_r(&ts_start);
 	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;
 }
@@ -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];
 	int ret, ep = C_AVALON_TASK;
+	cgtimer_t ts_start;
 	size_t nr_len;
 
 	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);
 		hexdump(buf, nr_len);
 	}
+	cgsleep_prepare_r(&ts_start);
 	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;
 }
@@ -277,32 +288,14 @@ static inline bool avalon_cts(char c)
 	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",
 	       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)
@@ -333,8 +326,7 @@ static int avalon_reset(struct cgpu_info *avalon, bool initial)
 		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?? */
 	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,
 				 (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! */
 	avalon_initialise(avalon);
@@ -814,9 +804,6 @@ static bool avalon_detect_one(libusb_device *dev, struct usb_find_devices *found
 	if (!add_cgpu(avalon))
 		goto unshin;
 
-	usb_set_cps(avalon, info->baud / 10);
-	usb_enable_cps(avalon);
-
 	ret = avalon_reset(avalon, true);
 	if (ret && !configured)
 		goto unshin;
@@ -971,16 +958,14 @@ static void *avalon_get_results(void *userdata)
 	const int rsize = AVALON_FTDI_READSIZE;
 	char readbuf[AVALON_READBUF_SIZE];
 	struct thr_info *thr = info->thr;
-	cgtimer_t ts_start;
 	int offset = 0, ret = 0;
 	char threadname[24];
 
 	snprintf(threadname, 24, "ava_recv/%d", avalon->device_id);
 	RenameThread(threadname);
-	cgsleep_prepare_r(&ts_start);
 
 	while (likely(!avalon->shutdown)) {
-		unsigned char buf[rsize];
+		char buf[rsize];
 
 		if (offset >= (int)AVALON_READ_SIZE)
 			avalon_parse_results(avalon, info, thr, readbuf, &offset);
@@ -997,16 +982,7 @@ static void *avalon_get_results(void *userdata)
 			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)
 			continue;

+ 1 - 3
driver-avalon.h

@@ -65,9 +65,7 @@
 
 #define AVALON_FTDI_READSIZE 510
 #define AVALON_READBUF_SIZE 8192
-#define AVALON_RESET_TIMEOUT 100
-#define AVALON_READ_TIMEOUT 4 /* Just less than the time it takes to fill the buffer */
-#define AVALON_LATENCY 1
+#define AVALON_LATENCY 16 /* This is basically the ftdi default anyway */
 
 struct avalon_task {
 	uint8_t reset		:1;