Browse Source

Merge branch 'update_old_avalon_20130513' into bfgminer

Luke Dashjr 13 years ago
parent
commit
2ca311f6ec
1 changed files with 89 additions and 80 deletions
  1. 89 80
      driver-avalon.c

+ 89 - 80
driver-avalon.c

@@ -1,5 +1,6 @@
 /*
  * Copyright 2012-2013 Xiangfu
+ * Copyright 2013 Con Kolivas <kernel@kolivas.org>
  * Copyright 2012 Luke Dashjr
  * Copyright 2012 Andrew Smith
  *
@@ -16,6 +17,7 @@
 #include <stdio.h>
 #include <sys/time.h>
 #include <sys/types.h>
+#include <sys/select.h>
 #include <dirent.h>
 #include <unistd.h>
 #ifndef WIN32
@@ -41,19 +43,6 @@ static int option_offset = -1;
 struct avalon_info **avalon_info;
 struct device_drv avalon_drv;
 
-static inline uint8_t rev8(uint8_t d)
-{
-	int i;
-	uint8_t out = 0;
-
-	/* from left to right */
-	for (i = 0; i < 8; i++)
-		if (d & (1 << i))
-			out |= (1 << (7 - i));
-
-	return out;
-}
-
 static int avalon_init_task(struct avalon_task *at,
 			    uint8_t reset, uint8_t ff, uint8_t fan,
 			    uint8_t timeout, uint8_t asic_num,
@@ -221,22 +210,28 @@ static int avalon_gets(int fd, uint8_t *buf, int read_count,
 	int read_amount = AVALON_READ_SIZE;
 	bool first = true;
 
-	/* Read reply 1 byte at a time to get earliest tv_finish */
 	while (true) {
-		ret = read(fd, buf, 1);
-		if (ret < 0)
-			return AVA_GETS_ERROR;
-
-		if (first && tv_finish != NULL)
-			gettimeofday(tv_finish, NULL);
+		struct timeval timeout = {0, 100000};
+		fd_set rd;
 
-		if (ret >= read_amount)
-			return AVA_GETS_OK;
-
-		if (ret > 0) {
+		FD_ZERO(&rd);
+		FD_SET(fd, &rd);
+		ret = select(fd + 1, &rd, NULL, NULL, &timeout);
+		if (unlikely(ret < 0))
+			return AVA_GETS_ERROR;
+		if (ret) {
+			ret = read(fd, buf, read_amount);
+			if (unlikely(ret < 0))
+				return AVA_GETS_ERROR;
+			if (likely(first)) {
+				if (likely(tv_finish))
+					gettimeofday(tv_finish, NULL);
+				first = false;
+			}
+			if (likely(ret >= read_amount))
+				return AVA_GETS_OK;
 			buf += ret;
 			read_amount -= ret;
-			first = false;
 			continue;
 		}
 
@@ -313,10 +308,7 @@ static int avalon_decode_nonce(struct thr_info *thr, struct work **work,
 		return -1;
 
 	info->matching_work[i]++;
-	*nonce = ar->nonce;
-#if defined (__BIG_ENDIAN__) || defined(MIPSEB)
-	*nonce = swab32(*nonce);
-#endif
+	*nonce = htole32(ar->nonce);
 
 	applog(LOG_DEBUG, "Avalon: match to work[%d](%p): %d",i, work[i],
 	       info->matching_work[i]);
@@ -344,6 +336,10 @@ static int avalon_reset(int fd, struct avalon_result *ar)
 	avalon_get_result(fd, ar, NULL, NULL);
 
 	buf = (uint8_t *)ar;
+	/* Sometimes there is one extra 0 byte for some reason in the buffer,
+	 * so work around it. */
+	if (buf[0] == 0)
+		buf = (uint8_t  *)(ar + 1);
 	if (buf[0] == 0xAA && buf[1] == 0x55 &&
 	    buf[2] == 0xAA && buf[3] == 0x55) {
 		for (i = 4; i < 11; i++)
@@ -351,18 +347,17 @@ static int avalon_reset(int fd, struct avalon_result *ar)
 				break;
 	}
 
-	if (i != 11) {
-		applog(LOG_ERR, "Avalon: Reset failed! not a Avalon?"
-		       " (%d: %02x %02x %02x %02x)",
-		       i, buf[0], buf[1], buf[2], buf[3]);
-		/* FIXME: return 1; */
-	}
-
 	p.tv_sec = 0;
 	p.tv_nsec = AVALON_RESET_PITCH;
 	nanosleep(&p, NULL);
 
-	applog(LOG_WARNING, "Avalon: Reset succeeded");
+	if (i != 11) {
+		applog(LOG_ERR, "Avalon: Reset failed! not an Avalon?"
+		       " (%d: %02x %02x %02x %02x)",
+		       i, buf[0], buf[1], buf[2], buf[3]);
+		/* FIXME: return 1; */
+	} else
+		applog(LOG_WARNING, "Avalon: Reset succeeded");
 	return 0;
 }
 
@@ -534,6 +529,7 @@ static bool avalon_detect_one(const char *devpath)
 	struct avalon_result ar;
 	int fd, ret;
 	int baud, miner_count, asic_count, timeout, frequency = 0;
+	struct cgpu_info *avalon;
 
 	int this_option_offset = ++option_offset;
 	get_options(this_option_offset, &baud, &miner_count, &asic_count,
@@ -549,22 +545,21 @@ static bool avalon_detect_one(const char *devpath)
 		return false;
 	}
 
-	ret = avalon_reset(fd, &ar);
-
-	if (ret) {
-		; /* FIXME: I think IT IS avalon and wait on reset;
-		   * avalon_close(fd);
-		   * return false; */
-	}
-
 	/* We have a real Avalon! */
-	struct cgpu_info *avalon;
 	avalon = calloc(1, sizeof(struct cgpu_info));
 	avalon->drv = &avalon_drv;
 	avalon->device_path = strdup(devpath);
 	avalon->device_fd = fd;
 	avalon->threads = AVALON_MINER_THREADS;
 	add_cgpu(avalon);
+
+	ret = avalon_reset(fd, &ar);
+	if (ret) {
+		; /* FIXME: I think IT IS avalon and wait on reset;
+		   * avalon_close(fd);
+		   * return false; */
+	}
+	
 	avalon_info = realloc(avalon_info,
 			      sizeof(struct avalon_info *) *
 			      (total_devices + 1));
@@ -600,11 +595,14 @@ static bool avalon_detect_one(const char *devpath)
 	info->temp_old = 0;
 	info->frequency = frequency;
 
-	/* Set asic to idle mode after detect */
-	avalon_idle(avalon);
-	avalon->device_fd = -1;
+	/* Do something for failed reset ? */
+	if (0) {
+		/* Set asic to idle mode after detect */
+		avalon_idle(avalon);
+		avalon->device_fd = -1;
 
-	avalon_close(fd);
+		avalon_close(fd);
+	}
 	return true;
 }
 
@@ -613,6 +611,11 @@ static inline void avalon_detect()
 	serial_detect(&avalon_drv, avalon_detect_one);
 }
 
+static void __avalon_init(struct cgpu_info *avalon)
+{
+	applog(LOG_INFO, "Avalon: Opened on %s", avalon->device_path);
+}
+
 static void avalon_init(struct cgpu_info *avalon)
 {
 	struct avalon_result ar;
@@ -633,10 +636,9 @@ static void avalon_init(struct cgpu_info *avalon)
 		return;
 	}
 
+	avalon->status = LIFE_INIT;
 	avalon->device_fd = fd;
-	applog(LOG_INFO, "Avalon: Opened on %s", avalon->device_path);
-
-	return;
+	__avalon_init(avalon);
 }
 
 static bool avalon_prepare(struct thr_info *thr)
@@ -644,9 +646,10 @@ static bool avalon_prepare(struct thr_info *thr)
 	struct cgpu_info *avalon = thr->cgpu;
 	struct timeval now;
 
-	avalon_init(avalon);
 	if (avalon->device_fd == -1)
-		return false;
+		avalon_init(avalon);
+	else
+		__avalon_init(avalon);
 
 	gettimeofday(&now, NULL);
 	get_datestamp(avalon->init, &now);
@@ -818,6 +821,7 @@ static int64_t avalon_scanhash(struct thr_info *thr, struct work **work,
 			dev_error(avalon, REASON_DEV_COMMS_ERROR);
 			first_try = 0;
 			nmsleep(1000);
+			avalon_init(avalon);
 			return 0;	/* This should never happen */
 		}
 		if (ret == AVA_SEND_BUFFER_EMPTY && (i + 1 == avalon_get_work_count)) {
@@ -873,34 +877,36 @@ static int64_t avalon_scanhash(struct thr_info *thr, struct work **work,
 			avalon_free_work(thr, info->bulk1);
 			avalon_free_work(thr, info->bulk2);
 			avalon_free_work(thr, info->bulk3);
-			continue;
+			break;
 		}
 		result_count++;
 
 		work_i0 = avalon_decode_nonce(thr, info->bulk0, &ar, &nonce);
-		work_i1 = avalon_decode_nonce(thr, info->bulk1, &ar, &nonce);
-		work_i2 = avalon_decode_nonce(thr, info->bulk2, &ar, &nonce);
-		work_i3 = avalon_decode_nonce(thr, info->bulk3, &ar, &nonce);
-		if ((work_i0 < 0) && (work_i1 < 0) && (work_i2 < 0) && (work_i3 < 0)) {
-			info->no_matching_work++;
-			result_wrong++;
-
-			if (opt_debug) {
-				timersub(&tv_finish, &tv_start, &elapsed);
-				applog(LOG_DEBUG,"Avalon: no matching work: %d"
-				       " (%ld.%06lds)", info->no_matching_work,
-				       elapsed.tv_sec, elapsed.tv_usec);
-			}
-			continue;
-		}
-		if (work_i0 >= 0)
+		if (work_i0 < 0) {
+			work_i1 = avalon_decode_nonce(thr, info->bulk1, &ar, &nonce);
+			if (work_i1 < 0) {
+				work_i2 = avalon_decode_nonce(thr, info->bulk2, &ar, &nonce);
+				if (work_i2 < 0) {
+					work_i3 = avalon_decode_nonce(thr, info->bulk3, &ar, &nonce);
+					if (work_i3 < 0) {
+						info->no_matching_work++;
+						result_wrong++;
+
+						if (opt_debug) {
+							timersub(&tv_finish, &tv_start, &elapsed);
+							applog(LOG_DEBUG,"Avalon: no matching work: %d"
+							" (%ld.%06lds)", info->no_matching_work,
+							elapsed.tv_sec, elapsed.tv_usec);
+						}
+						continue;
+					} else
+						submit_nonce(thr, info->bulk3[work_i3], nonce);
+				} else
+					submit_nonce(thr, info->bulk2[work_i2], nonce);
+			} else
+				submit_nonce(thr, info->bulk1[work_i1], nonce);
+		} else
 			submit_nonce(thr, info->bulk0[work_i0], nonce);
-		if (work_i1 >= 0)
-			submit_nonce(thr, info->bulk1[work_i1], nonce);
-		if (work_i2 >= 0)
-			submit_nonce(thr, info->bulk2[work_i2], nonce);
-		if (work_i3 >= 0)
-			submit_nonce(thr, info->bulk3[work_i3], nonce);
 
 		hash_count += nonce;
 		if (opt_debug) {
@@ -911,7 +917,7 @@ static int64_t avalon_scanhash(struct thr_info *thr, struct work **work,
 			       elapsed.tv_sec, elapsed.tv_usec);
 		}
 	}
-	if (result_count == result_wrong) {
+	if (result_wrong && result_count == result_wrong) {
 		/* This mean FPGA controller give all wrong result
 		 * try to reset the Avalon */
 		avalon_free_work(thr, info->bulk0);
@@ -922,13 +928,16 @@ static int64_t avalon_scanhash(struct thr_info *thr, struct work **work,
 		applog(LOG_ERR,
 		       "AVA%i: FPGA controller mess up", avalon->device_id);
 		dev_error(avalon, REASON_DEV_COMMS_ERROR);
+		do_avalon_close(thr);
+		nmsleep(1000);
+		avalon_init(avalon);
 		return 0;
 	}
 
 	avalon_free_work(thr, info->bulk0);
 
 	record_temp_fan(info, &ar, &(avalon->temp));
-	applog(LOG_WARNING,
+	applog(LOG_INFO,
 	       "Avalon: Fan1: %d/m, Fan2: %d/m, Fan3: %d/m\t"
 	       "Temp1: %dC, Temp2: %dC, Temp3: %dC, TempMAX: %dC",
 	       info->fan0, info->fan1, info->fan2,