mirror of
git://projects.qi-hardware.com/openwrt-packages.git
synced 2024-11-26 05:45:19 +02:00
327 lines
8.1 KiB
Diff
327 lines
8.1 KiB
Diff
|
From 340b923e42d32bd5173fe6b285923635a6fcc67f Mon Sep 17 00:00:00 2001
|
||
|
From: Xiangfu <xiangfu@openmobilefree.net>
|
||
|
Date: Mon, 13 Feb 2012 16:04:34 +0800
|
||
|
Subject: [PATCH 1/7] add icarus.c, base on bitforce.c
|
||
|
|
||
|
---
|
||
|
icarus.c | 307 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
1 files changed, 307 insertions(+), 0 deletions(-)
|
||
|
create mode 100644 icarus.c
|
||
|
|
||
|
diff --git a/icarus.c b/icarus.c
|
||
|
new file mode 100644
|
||
|
index 0000000..56b8d8a
|
||
|
--- /dev/null
|
||
|
+++ b/icarus.c
|
||
|
@@ -0,0 +1,307 @@
|
||
|
+/*
|
||
|
+ * Copyright 2012 Luke Dashjr
|
||
|
+ * Copyright 2012 Xiangfu <xiangfu@openmobilefree.com>
|
||
|
+ *
|
||
|
+ * This program is free software; you can redistribute it and/or modify it
|
||
|
+ * under the terms of the GNU General Public License as published by the Free
|
||
|
+ * Software Foundation; either version 2 of the License, or (at your option)
|
||
|
+ * any later version. See COPYING for more details.
|
||
|
+ */
|
||
|
+
|
||
|
+/*
|
||
|
+ * Those code should be works fine with V2 and V3 bitstream of Icarus.
|
||
|
+ * Operation:
|
||
|
+ * No detection implement.
|
||
|
+ * Input: 64B = 32B midstate + 20B fill bytes + last 12 bytes of block head.
|
||
|
+ * Return: send back 32bits immediately when Icarus found a valid nonce.
|
||
|
+ * no query protocol implemented here, if no data send back in ~11.3
|
||
|
+ * seconds (full cover time on 32bit nonce range by 380MH/s speed)
|
||
|
+ * just send another work.
|
||
|
+ * Notice:
|
||
|
+ * 1. Icarus will start calculate when you push a work to them, even they
|
||
|
+ * are busy.
|
||
|
+ * 2. The 2 FPGAs on Icarus will distribute the job, one will calculate the
|
||
|
+ * 0 ~ 7FFFFFFF, another one will cover the 80000000 ~ FFFFFFFF.
|
||
|
+ * 3. It's possible for 2 FPGAs both find valid nonce in the meantime, the 2
|
||
|
+ * valid nonce will all be send back.
|
||
|
+ * 4. Icarus will stop work when: a valid nonce has been found or 32 bits
|
||
|
+ * nonce range is completely calculated.
|
||
|
+ */
|
||
|
+
|
||
|
+#include <limits.h>
|
||
|
+#include <pthread.h>
|
||
|
+#include <stdio.h>
|
||
|
+#include <sys/time.h>
|
||
|
+#include <sys/types.h>
|
||
|
+#include <dirent.h>
|
||
|
+#include <unistd.h>
|
||
|
+#ifndef WIN32
|
||
|
+ #include <termios.h>
|
||
|
+ #include <sys/stat.h>
|
||
|
+ #include <fcntl.h>
|
||
|
+ #ifndef O_CLOEXEC
|
||
|
+ #define O_CLOEXEC 0
|
||
|
+ #endif
|
||
|
+#else
|
||
|
+ #include <windows.h>
|
||
|
+ #include <io.h>
|
||
|
+#endif
|
||
|
+
|
||
|
+#include "elist.h"
|
||
|
+#include "miner.h"
|
||
|
+
|
||
|
+#define ICARUS_READ_FAULT_COUNT (8)
|
||
|
+
|
||
|
+int icarus_read_count;
|
||
|
+struct device_api icarus_api;
|
||
|
+
|
||
|
+static void rev(unsigned char *s, size_t l)
|
||
|
+{
|
||
|
+ size_t i, j;
|
||
|
+ unsigned char t;
|
||
|
+
|
||
|
+ for (i = 0, j = l - 1; i < j; i++, j--) {
|
||
|
+ t = s[i];
|
||
|
+ s[i] = s[j];
|
||
|
+ s[j] = t;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static int icarus_open(const char *devpath)
|
||
|
+{
|
||
|
+#ifndef WIN32
|
||
|
+ struct termios my_termios;
|
||
|
+
|
||
|
+ int serialfd = open(devpath, O_RDWR | O_CLOEXEC | O_NOCTTY);
|
||
|
+
|
||
|
+ if (serialfd == -1)
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ tcgetattr(serialfd, &my_termios);
|
||
|
+ my_termios.c_cflag = B115200;
|
||
|
+ my_termios.c_cflag |= CS8;
|
||
|
+ my_termios.c_cflag |= CREAD;
|
||
|
+ my_termios.c_cflag |= CLOCAL;
|
||
|
+ my_termios.c_cflag &= ~(CSIZE | PARENB);
|
||
|
+
|
||
|
+ my_termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK |
|
||
|
+ ISTRIP | INLCR | IGNCR | ICRNL | IXON);
|
||
|
+ my_termios.c_oflag &= ~OPOST;
|
||
|
+ my_termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
|
||
|
+ my_termios.c_cc[VTIME] = 10; /* block 1 second */
|
||
|
+ my_termios.c_cc[VMIN] = 0;
|
||
|
+ tcsetattr(serialfd, TCSANOW, &my_termios);
|
||
|
+
|
||
|
+ tcflush(serialfd, TCOFLUSH);
|
||
|
+ tcflush(serialfd, TCIFLUSH);
|
||
|
+
|
||
|
+ return serialfd;
|
||
|
+#else
|
||
|
+ HANDLE hSerial = CreateFile(devpath, GENERIC_READ | GENERIC_WRITE, 0,
|
||
|
+ NULL, OPEN_EXISTING, 0, NULL);
|
||
|
+ if (unlikely(hSerial == INVALID_HANDLE_VALUE))
|
||
|
+ return -1;
|
||
|
+ /* TODO: Needs setup read block time. just like VTIME = 10 */
|
||
|
+ return _open_osfhandle((LONG)hSerial, 0);
|
||
|
+#endif
|
||
|
+}
|
||
|
+
|
||
|
+static void icarus_gets(char *buf, size_t bufLen, int fd)
|
||
|
+{
|
||
|
+ ssize_t ret = 0;
|
||
|
+
|
||
|
+ icarus_read_count = 0;
|
||
|
+
|
||
|
+ while (bufLen) {
|
||
|
+ ret = read(fd, buf, 1);
|
||
|
+ if (ret == 1) {
|
||
|
+ bufLen--;
|
||
|
+ buf++;
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+
|
||
|
+ icarus_read_count++;
|
||
|
+ if (icarus_read_count == ICARUS_READ_FAULT_COUNT) {
|
||
|
+ applog(LOG_WARNING,
|
||
|
+ "Icarus Read: No data in %d seconds",
|
||
|
+ ICARUS_READ_FAULT_COUNT);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static void icarus_write(int fd, const void *buf, size_t bufLen)
|
||
|
+{
|
||
|
+ ssize_t ret;
|
||
|
+
|
||
|
+ ret = write(fd, buf, bufLen);
|
||
|
+ if (unlikely(ret != bufLen))
|
||
|
+ quit(1, "Icarus: Send data failed!");
|
||
|
+}
|
||
|
+
|
||
|
+#define icarus_close(fd) close(fd)
|
||
|
+
|
||
|
+static bool icarus_detect_one(const char *devpath)
|
||
|
+{
|
||
|
+ int fd;
|
||
|
+ static int i = 0;
|
||
|
+
|
||
|
+ const unsigned char golden_ob[] =
|
||
|
+ "2db907f9cb4eb938ded904f4832c4331"
|
||
|
+ "0380e3aeb54364057e7fec5157bfc533"
|
||
|
+ "00000000000000000000000080000000"
|
||
|
+ "00000000a58e091ac342724e7c3dc346";
|
||
|
+ const unsigned char golden_nonce[] = "063c5e01";
|
||
|
+
|
||
|
+ char ob_bin[64], nonce_bin[4];
|
||
|
+ char *nonce_hex;
|
||
|
+
|
||
|
+ if (total_devices == MAX_DEVICES)
|
||
|
+ return false;
|
||
|
+
|
||
|
+ fd = icarus_open(devpath);
|
||
|
+ if (unlikely(fd == -1)) {
|
||
|
+ applog(LOG_ERR, "Icarus Detect: Failed to open %s", devpath);
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+
|
||
|
+ hex2bin(ob_bin, golden_ob, sizeof(ob_bin));
|
||
|
+ icarus_write(fd, ob_bin, sizeof(ob_bin));
|
||
|
+
|
||
|
+ memset(nonce_bin, 0, sizeof(nonce_bin));
|
||
|
+ icarus_gets(nonce_bin, sizeof(nonce_bin), fd);
|
||
|
+
|
||
|
+ icarus_close(fd);
|
||
|
+
|
||
|
+ nonce_hex = bin2hex(nonce_bin, sizeof(nonce_bin));
|
||
|
+ if (nonce_hex) {
|
||
|
+ if (strncmp(nonce_hex, golden_nonce, 8)) {
|
||
|
+ applog(LOG_ERR,
|
||
|
+ "Icarus Detect: "
|
||
|
+ "Test failed at %s : get %s, should: %s",
|
||
|
+ devpath, nonce_hex, golden_nonce);
|
||
|
+ free(nonce_hex);
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+ free(nonce_hex);
|
||
|
+ } else
|
||
|
+ return false;
|
||
|
+
|
||
|
+ /* We have a real Icarus! */
|
||
|
+ struct cgpu_info *icarus;
|
||
|
+ icarus = calloc(1, sizeof(*icarus));
|
||
|
+ devices[total_devices++] = icarus;
|
||
|
+ icarus->api = &icarus_api;
|
||
|
+ icarus->device_id = i++;
|
||
|
+ icarus->device_path = strdup(devpath);
|
||
|
+ icarus->threads = 1;
|
||
|
+
|
||
|
+ return true;
|
||
|
+}
|
||
|
+
|
||
|
+static void icarus_detect()
|
||
|
+{
|
||
|
+ struct string_elist *iter, *tmp;
|
||
|
+
|
||
|
+ list_for_each_entry_safe(iter, tmp, &scan_devices, list) {
|
||
|
+ if (icarus_detect_one(iter->string))
|
||
|
+ string_elist_del(iter);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static bool icarus_thread_prepare(struct thr_info *thr)
|
||
|
+{
|
||
|
+ struct cgpu_info *icarus = thr->cgpu;
|
||
|
+
|
||
|
+ struct timeval now;
|
||
|
+
|
||
|
+ int fd = icarus_open(icarus->device_path);
|
||
|
+ if (unlikely(-1 == fd)) {
|
||
|
+ applog(LOG_ERR, "Failed to open Icarus on %s",
|
||
|
+ icarus->device_path);
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+
|
||
|
+ icarus->device_fd = fd;
|
||
|
+
|
||
|
+ applog(LOG_INFO, "Opened Icarus on %s", icarus->device_path);
|
||
|
+ gettimeofday(&now, NULL);
|
||
|
+ get_datestamp(icarus->init, &now);
|
||
|
+
|
||
|
+ return true;
|
||
|
+}
|
||
|
+
|
||
|
+static uint64_t icarus_scanhash(struct thr_info *thr, struct work *work,
|
||
|
+ uint64_t max_nonce)
|
||
|
+{
|
||
|
+ struct cgpu_info *icarus;
|
||
|
+ int fd;
|
||
|
+
|
||
|
+ unsigned char ob_bin[64], nonce_bin[4];
|
||
|
+ unsigned char *ob_hex, *nonce_hex;
|
||
|
+ uint32_t nonce;
|
||
|
+ uint32_t hash_count;
|
||
|
+ time_t t;
|
||
|
+
|
||
|
+ icarus = thr->cgpu;
|
||
|
+ fd = icarus->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);
|
||
|
+#ifndef WIN32
|
||
|
+ tcflush(fd, TCOFLUSH);
|
||
|
+#endif
|
||
|
+ icarus_write(fd, ob_bin, sizeof(ob_bin));
|
||
|
+
|
||
|
+ ob_hex = bin2hex(ob_bin, sizeof(ob_bin));
|
||
|
+ if (ob_hex) {
|
||
|
+ t = time(NULL);
|
||
|
+ applog(LOG_DEBUG, "Icarus send : %s", ob_hex);
|
||
|
+ free(ob_hex);
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Icarus will return 8 bytes nonces or nothing */
|
||
|
+ memset(nonce_bin, 0, sizeof(nonce_bin));
|
||
|
+ icarus_gets(nonce_bin, sizeof(nonce_bin), fd);
|
||
|
+
|
||
|
+ nonce_hex = bin2hex(nonce_bin, sizeof(nonce_bin));
|
||
|
+ if (nonce_hex) {
|
||
|
+ t = time(NULL) - t;
|
||
|
+ applog(LOG_DEBUG, "Icarus return (elapse %d seconds): %s",
|
||
|
+ t, nonce_hex);
|
||
|
+ free(nonce_hex);
|
||
|
+ }
|
||
|
+
|
||
|
+ memcpy((char *)&nonce, nonce_bin, sizeof(nonce_bin));
|
||
|
+
|
||
|
+ if (nonce == 0 && icarus_read_count == ICARUS_READ_FAULT_COUNT)
|
||
|
+ return 0xffffffff;
|
||
|
+
|
||
|
+#ifndef __BIG_ENDIAN__
|
||
|
+ nonce = swab32(nonce);
|
||
|
+#endif
|
||
|
+ work->blk.nonce = 0xffffffff;
|
||
|
+ submit_nonce(thr, work, nonce);
|
||
|
+
|
||
|
+ hash_count = (nonce & 0x7fffffff);
|
||
|
+ if (hash_count == 0)
|
||
|
+ hash_count = 2;
|
||
|
+ else {
|
||
|
+ if (hash_count++ == 0x7fffffff)
|
||
|
+ hash_count = 0xffffffff;
|
||
|
+ else
|
||
|
+ hash_count <<= 1;
|
||
|
+ }
|
||
|
+
|
||
|
+ return hash_count;
|
||
|
+}
|
||
|
+
|
||
|
+struct device_api icarus_api = {
|
||
|
+ .name = "Icarus",
|
||
|
+ .api_detect = icarus_detect,
|
||
|
+ .thread_prepare = icarus_thread_prepare,
|
||
|
+ .scanhash = icarus_scanhash,
|
||
|
+};
|
||
|
--
|
||
|
1.7.5.4
|
||
|
|