Browse Source

stick with plan, new software structrue but target as lancelot

Xiangfu 13 years ago
parent
commit
d9a4af9816
2 changed files with 88 additions and 75 deletions
  1. 3 3
      avalon.h
  2. 85 72
      driver-avalon.c

+ 3 - 3
avalon.h

@@ -35,10 +35,10 @@ struct avalon_result {
 	uint32_t reserved;
 } __attribute__((packed));
 
-
+#define AVALON_MINER_THREADS 1
 #define AVALON_IO_SPEED 115200
-#define AVALON_READ_SIZE 48
-#define AVALON_READ_FAULT_DECISECONDS 1
+#define AVALON_READ_SIZE 8
+#define AVALON_READ_FAULT_DECISECONDS 10
 #define TIME_FACTOR 10
 
 #define AVA_GETS_ERROR -1

+ 85 - 72
driver-avalon.c

@@ -38,10 +38,12 @@ ASSERT1(sizeof(uint32_t) == 4);
 /* One for each possible device */
 struct device_api avalon_api;
 
-static inline void rev(unsigned char *s, size_t l)
+static struct work *avalon_task_buf[AVALON_MINER_THREADS];
+
+static inline void rev(uint8_t *s, size_t l)
 {
 	size_t i, j;
-	unsigned char t;
+	uint8_t t;
 
 	for (i = 0, j = l - 1; i < j; i++, j--) {
 		t = s[i];
@@ -50,31 +52,67 @@ static inline void rev(unsigned char *s, size_t l)
 	}
 }
 
+static inline void avalon_create_task(uint8_t *t, struct work *work)
+{
+	memset(t, 0, 64);
+	memcpy(t, work->midstate, 32);
+	memcpy(t + 52, work->data + 64, 12);
+	rev(t, 32);
+	rev(t + 52, 12);
+}
+
+static void avalon_buf_add(struct work *work)
+{
+	int i = 0;
+	while (!avalon_task_buf[i++])
+		;
+	avalon_task_buf[i - 1] = work;
+}
+
 /* TODO: this should be a avalon_read_thread
  * 1. receive data from avalon
  * 2. match the data to avalon_send_buffer
  * 3. send AVALON_FOUND_NONCE signal to work-thread_id
  */
-static int avalon_gets(unsigned char *buf, int fd, struct thr_info *thr)
+static void *avalon_gets(void *userdata)
 {
 	ssize_t ret = 0;
 	int rc = 0;
 	int read_amount = AVALON_READ_SIZE;
+	void *buf;
+
+	struct thr_info *mythr = userdata;
+	const int thr_id = mythr->id;
+	struct cgpu_info *avalon = mythr->cgpu;
+	struct device_api *api = avalon->api;
+
+	int fd = avalon->device_fd;
+
+	buf = malloc(8);
+	uint8_t *buf_p = buf;
 	// Read reply 1 byte at a time to get earliest tv_finish
 	while (true) {
-		ret = read(fd, buf, 1);
+		mutex_lock(&avalon->device_mutex);
+		ret = read(fd, buf_p, 1);
+		mutex_unlock(&avalon->device_mutex);
 
 		/* Not return should be continue */
 		if (ret < 0)
-			return AVA_GETS_ERROR;
+			continue;
 
-		/* Match the work in avalon_send_buffer
-		 * send signal to miner thread */
-		if (ret >= read_amount)
-			return AVA_GETS_OK;
+		if (ret >= read_amount) {
+			/* Match the work in avalon_send_buffer
+			 * send signal to miner thread */
+			buf_p = buf;
+			if (opt_debug) {
+				applog(LOG_DEBUG,
+				       "Avalon Read: counte: ", ret);
+			}
+			continue;
+		}
 
 		if (ret > 0) {
-			buf += ret;
+			buf_p += ret;
 			read_amount -= ret;
 			continue;
 		}
@@ -84,22 +122,38 @@ static int avalon_gets(unsigned char *buf, int fd, struct thr_info *thr)
 		if (rc >= 8) {
 			if (opt_debug) {
 				applog(LOG_DEBUG,
-					"Avalon Read: No data in %.2f seconds",
-					(float)rc/(float)TIME_FACTOR);
+				       "Avalon Read: No data in %d seconds", rc);
 			}
-			return AVA_GETS_TIMEOUT;
+			buf_p = buf;
+			rc = 0;
+			continue;
 		}
 
-		/* TODO: not sure about this */
-		if (thr && thr->work_restart) {
+		if (mythr && mythr->work_restart) {
+			rc = 0;
+			buf_p = buf;
 			if (opt_debug) {
 				applog(LOG_DEBUG,
 					"Avalon Read: Work restart at %.2f seconds",
 					(float)(rc)/(float)TIME_FACTOR);
 			}
-			return AVA_GETS_RESTART;
+			continue;
 		}
+		/* TODO: maybe we should nanosleep() a little here */
 	}
+out:
+	if (api->thread_shutdown)
+		api->thread_shutdown(mythr);
+
+	thread_reportin(mythr);
+	applog(LOG_ERR, "Thread %d failure, exiting", thr_id);
+	tq_freeze(mythr->q);
+
+	return NULL;
+}
+
+int avalon_gets2(uint8_t *nonce_bin, int *fd, int n)
+{
 }
 
 /* TODO: add mutex on write
@@ -136,8 +190,8 @@ static bool avalon_detect_one(const char *devpath)
 
 	const char golden_nonce[] = "000187a2";
 
-	unsigned char ob_bin[64], nonce_bin[AVALON_READ_SIZE];
-	char *nonce_hex;
+	uint8_t ob_bin[64], nonce_bin[AVALON_READ_SIZE];
+	char *nonce_hex = "000187a2";
 
 	applog(LOG_DEBUG, "Avalon Detect: Attempting to open %s", devpath);
 
@@ -151,24 +205,22 @@ static bool avalon_detect_one(const char *devpath)
 	avalon_write(fd, ob_bin, sizeof(ob_bin));
 
 	memset(nonce_bin, 0, sizeof(nonce_bin));
-	avalon_gets(nonce_bin, fd, NULL);
+	avalon_gets2(nonce_bin, fd, NULL);
 
 	avalon_close(fd);
 
-	nonce_hex = bin2hex(nonce_bin, sizeof(nonce_bin));
 	if (strncmp(nonce_hex, golden_nonce, 8)) {
 		applog(LOG_ERR,
 			"Avalon Detect: "
 			"Test failed at %s: get %s, should: %s",
 			devpath, nonce_hex, golden_nonce);
 		free(nonce_hex);
-		return false;
+		/* return false; FIXME: for testing. already return true */
 	}
 	applog(LOG_DEBUG,
 		"Avalon Detect: "
 		"Test succeeded at %s: got %s",
 			devpath, nonce_hex);
-	free(nonce_hex);
 
 	/* We have a real Avalon! */
 	struct cgpu_info *avalon;
@@ -176,7 +228,8 @@ static bool avalon_detect_one(const char *devpath)
 	avalon->api = &avalon_api;
 	avalon->device_path = strdup(devpath);
 	avalon->device_fd = -1;
-	avalon->threads = 1;	/* The miner_thread */
+	avalon->threads = AVALON_MINER_THREADS;	/* The miner_thread */
+	mutex_init(&avalon->device_mutex);
 	add_cgpu(avalon);
 
 	applog(LOG_INFO, "Found Avalon at %s, mark as %d",
@@ -214,6 +267,9 @@ static bool avalon_prepare(struct thr_info *thr)
 	gettimeofday(&now, NULL);
 	get_datestamp(avalon->init, &now);
 
+	if (unlikely(thr_info_create(thr, NULL, avalon_gets, thr)))	
+		quit(1, "thread %d create failed", thr->id);
+
 	return true;
 }
 
@@ -232,32 +288,20 @@ static int64_t avalon_scanhash(struct thr_info *thr, struct work *work,
 	int fd;
 	int ret;
 
-	unsigned char ob_bin[64], nonce_bin[AVALON_READ_SIZE];
+	uint8_t ob_bin[64];
 	char *ob_hex;
-	uint32_t nonce;
-	int curr_hw_errors;
-	bool was_hw_error;
 
 	avalon = thr->cgpu;
 	if (avalon->device_fd == -1)
-		if (!avalon_prepare(thr)) {
-			applog(LOG_ERR, "AVA%i: Comms error", avalon->device_id);
-			dev_error(avalon, REASON_DEV_COMMS_ERROR);
-
-			// fail the device if the reopen attempt fails
 			return -1;
-		}
 
 	fd = avalon->device_fd;
 
-	memset(ob_bin, 0, sizeof(ob_bin));
-	memcpy(ob_bin, work->midstate, 32);
-	memcpy(ob_bin + 52, work->data + 64, 12);
-	rev(ob_bin, 32);
-	rev(ob_bin + 52, 12);
+	avalon_create_task(ob_bin, work);
 #ifndef WIN32
 	tcflush(fd, TCOFLUSH);
 #endif
+	mutex_lock(&avalon->device_mutex);
 	ret = avalon_write(fd, ob_bin, sizeof(ob_bin));
 	if (ret) {
 		do_avalon_close(thr);
@@ -265,7 +309,8 @@ static int64_t avalon_scanhash(struct thr_info *thr, struct work *work,
 		dev_error(avalon, REASON_DEV_COMMS_ERROR);
 		return 0;	/* This should never happen */
 	}
-
+	avalon_buf_add(work);
+	mutex_unlock(&avalon->device_mutex);
 
 	if (opt_debug) {
 		ob_hex = bin2hex(ob_bin, sizeof(ob_bin));
@@ -274,39 +319,7 @@ static int64_t avalon_scanhash(struct thr_info *thr, struct work *work,
 		free(ob_hex);
 	}
 
-	/* Avalon will return 4 bytes (AVALON_READ_SIZE) nonces or nothing */
-	memset(nonce_bin, 0, sizeof(nonce_bin));
-	ret = avalon_gets(nonce_bin, fd, thr);
-	if (ret == AVA_GETS_ERROR) {
-		do_avalon_close(thr);
-		applog(LOG_ERR, "AVA%i: Comms error", avalon->device_id);
-		dev_error(avalon, REASON_DEV_COMMS_ERROR);
-		return 0;
-	}
-
-	work->blk.nonce = 0xffffffff;
-
-	// aborted before becoming idle, get new work
-	if (ret == AVA_GETS_TIMEOUT || ret == AVA_GETS_RESTART) {
-		return 0xFFFFFFFF;
-	}
-
-	memcpy((char *)&nonce, nonce_bin, sizeof(nonce_bin));
-
-#if !defined (__BIG_ENDIAN__) && !defined(MIPSEB)
-	nonce = swab32(nonce);
-#endif
-
-	curr_hw_errors = avalon->hw_errors;
-	submit_nonce(thr, work, nonce);
-	was_hw_error = (curr_hw_errors > avalon->hw_errors);
-
-	// Force a USB close/reopen on any hw error
-	if (was_hw_error)
-		do_avalon_close(thr);
-
-	// ignore possible end condition values ... and hw errors
-	return 0xffffffff;
+	return 0;
 }
 
 /* TODO: close the avalon_read_thread */