Browse Source

Add Avalon2 (2U size machine) support

Signed-off-by: Xiangfu <xiangfu@openmobilefree.net>

Conflicts:
	Makefile.am
	api.c
	cgminer.c
	configure.ac
	miner.h
Xiangfu 12 years ago
parent
commit
2ab21cb6e1
9 changed files with 1386 additions and 0 deletions
  1. 12 0
      Makefile.am
  2. 14 0
      api.c
  3. 203 0
      configure.ac
  4. 23 0
      crc.h
  5. 45 0
      crc16.c
  6. 800 0
      driver-avalon2.c
  7. 136 0
      driver-avalon2.h
  8. 70 0
      miner.c
  9. 83 0
      miner.h

+ 12 - 0
Makefile.am

@@ -273,8 +273,20 @@ if USE_KNC
 bfgminer_SOURCES += driver-knc.c
 endif
 
+<<<<<<< HEAD
 if HAS_KLONDIKE
 bfgminer_SOURCES += driver-klondike.c driver-klondike.h driver-hashbusteravalon.c
+||||||| parent of 7c5b0b8... Add Avalon2 (2U size machine) support
+if HAS_MINION
+cgminer_SOURCES += driver-minion.c
+=======
+if HAS_AVALON2
+cgminer_SOURCES += driver-avalon2.c driver-avalon2.h crc16.c crc.h
+endif
+
+if HAS_MINION
+cgminer_SOURCES += driver-minion.c
+>>>>>>> 7c5b0b8... Add Avalon2 (2U size machine) support
 endif
 
 if HAS_MODMINER

+ 14 - 0
api.c

@@ -33,9 +33,23 @@
 #endif
 #include "miner.h"
 #include "util.h"
+<<<<<<<
 #include "driver-cpu.h" /* for algo_names[], TODO: re-factor dependency */
 #include "driver-opencl.h"
 #include "version.h"
+|||||||
+#include "klist.h"
+
+#if defined(USE_BFLSC) || defined(USE_AVALON) || defined(USE_HASHFAST) || defined(USE_BITFURY) || defined(USE_KLONDIKE) || defined(USE_KNC) || defined(USE_BAB) || defined(USE_DRILLBIT) || defined(USE_MINION)
+#define HAVE_AN_ASIC 1
+#endif
+=======
+#include "klist.h"
+
+#if defined(USE_BFLSC) || defined(USE_AVALON) || defined(USE_AVALON2) || defined(USE_HASHFAST) || defined(USE_BITFURY) || defined(USE_KLONDIKE) || defined(USE_KNC) || defined(USE_BAB) || defined(USE_DRILLBIT) || defined(USE_MINION)
+#define HAVE_AN_ASIC 1
+#endif
+>>>>>>> 7c5b0b8... Add Avalon2 (2U size machine) support
 
 #define HAVE_AN_FPGA 1
 

+ 203 - 0
configure.ac

@@ -1025,6 +1025,25 @@ if test "x$hashbuster" = "xyes"; then
 fi
 AM_CONDITIONAL([USE_HASHBUSTER], [test x$hashbuster = xyes])
 
+<<<<<<< HEAD
+||||||| parent of 7c5b0b8... Add Avalon2 (2U size machine) support
+minion="no"
+=======
+avalon2="no"
+
+AC_ARG_ENABLE([avalon2],
+	[AC_HELP_STRING([--enable-avalon2],[Compile support for Avalon2 (default disabled)])],
+	[avalon2=$enableval]
+	)
+if test "x$avalon2" = xyes; then
+	AC_DEFINE([USE_FPGA_SERIAL], [1], [Defined to 1 if serial support required])
+	AC_DEFINE([USE_AVALON2], [1], [Defined to 1 if Avalon2 support is wanted])
+fi
+AM_CONDITIONAL([HAS_AVALON2], [test x$avalon2 = xyes])
+
+
+minion="no"
+>>>>>>> 7c5b0b8... Add Avalon2 (2U size machine) support
 
 driverlist="$driverlist hashbusterusb"
 AC_ARG_ENABLE([hashbusterusb],
@@ -1402,6 +1421,7 @@ if $use_udevrules; then
 	fi
 fi
 
+<<<<<<< HEAD
 
 AM_CONDITIONAL([NEED_LIBBLKMAKER], [test x$with_system_libblkmaker != xyes])
 AM_CONDITIONAL([NEED_BFG_BINLOADER], [test x$need_binloader = xyes])
@@ -1416,6 +1436,15 @@ AM_CONDITIONAL([NEED_BFG_LOWL_SPI], [test x$need_lowl_spi = xyes])
 AM_CONDITIONAL([NEED_BFG_LOWLEVEL], [test x$need_lowlevel = xyes])
 AM_CONDITIONAL([NEED_BFG_WORK2D], [test x$need_work2d = xyes])
 AM_CONDITIONAL([HAS_SCRYPT], [test x$scrypt = xyes])
+||||||| parent of 7c5b0b8... Add Avalon2 (2U size machine) support
+AM_CONDITIONAL([NEED_FPGAUTILS], [test x$modminer != xno])
+AM_CONDITIONAL([WANT_USBUTILS], [test x$want_usbutils != xfalse])
+AM_CONDITIONAL([WANT_LIBBITFURY], [test x$want_libbitfury != xfalse])
+=======
+AM_CONDITIONAL([NEED_FPGAUTILS], [test x$avalon2$modminer != xno])
+AM_CONDITIONAL([WANT_USBUTILS], [test x$want_usbutils != xfalse])
+AM_CONDITIONAL([WANT_LIBBITFURY], [test x$want_libbitfury != xfalse])
+>>>>>>> 7c5b0b8... Add Avalon2 (2U size machine) support
 AM_CONDITIONAL([HAVE_CURSES], [test x$curses = xyes])
 AM_CONDITIONAL([HAVE_SENSORS], [test x$with_sensors = xyes])
 AM_CONDITIONAL([HAVE_CYGWIN], [test x$have_cygwin = xtrue])
@@ -1809,6 +1838,170 @@ AC_CONFIG_FILES([
 	ccan.bfg/Makefile
 	lib/Makefile
 	])
+<<<<<<< HEAD
+||||||| parent of 7c5b0b8... Add Avalon2 (2U size machine) support
+AC_OUTPUT
+
+
+echo
+echo
+echo
+echo "------------------------------------------------------------------------"
+echo "$PACKAGE $VERSION"
+echo "------------------------------------------------------------------------"
+echo
+echo
+echo "Configuration Options Summary:"
+echo
+
+if test "x$libcurl" != xno; then
+	echo "  libcurl(GBT+getwork).: Enabled: $LIBCURL_LIBS"
+else
+	echo "  libcurl(GBT+getwork).: Disabled"
+fi
+
+echo "  curses.TUI...........: $cursesmsg"
+
+
+echo
+if test "x$avalon" = xyes; then
+	echo "  Avalon.ASICs.........: Enabled"
+else
+	echo "  Avalon.ASICs.........: Disabled"
+fi
+
+if test "x$minion" = xyes; then
+	echo "  BlackArrowMinion.ASIC: Enabled"
+else
+	echo "  BlackArrowMinion.ASIC: Disabled"
+fi
+
+if test "x$bab" = xyes; then
+	echo "  BlackArrow.ASICs.....: Enabled"
+else
+	echo "  BlackArrow.ASICs.....: Disabled"
+fi
+
+if test "x$bflsc" = xyes; then
+	echo "  BFL.ASICs............: Enabled"
+else
+	echo "  BFL.ASICs............: Disabled"
+fi
+
+if test "x$bitforce" = xyes; then
+	echo "  BitForce.FPGAs.......: Enabled"
+else
+	echo "  BitForce.FPGAs.......: Disabled"
+fi
+
+if test "x$bitfury" = xyes; then
+	echo "  BitFury.ASICs........: Enabled"
+else
+	echo "  BitFury.ASICs........: Disabled"
+fi
+
+if test "x$drillbit" = xyes; then
+	echo "  Drillbit.BitFury.....: Enabled"
+else
+	echo "  Drillbit.BitFury.....: Disabled"
+fi
+
+if test "x$hashfast" = xyes; then
+	echo "  Hashfast.ASICs.......: Enabled"
+else
+	echo "  Hashfast.ASICs.......: Disabled"
+fi
+
+if test "x$icarus" = xyes; then
+	echo "  Icarus.ASICs/FPGAs...: Enabled"
+else
+	echo "  Icarus.ASICs/FPGAs...: Disabled"
+fi
+=======
+AC_OUTPUT
+
+
+echo
+echo
+echo
+echo "------------------------------------------------------------------------"
+echo "$PACKAGE $VERSION"
+echo "------------------------------------------------------------------------"
+echo
+echo
+echo "Configuration Options Summary:"
+echo
+
+if test "x$libcurl" != xno; then
+	echo "  libcurl(GBT+getwork).: Enabled: $LIBCURL_LIBS"
+else
+	echo "  libcurl(GBT+getwork).: Disabled"
+fi
+
+echo "  curses.TUI...........: $cursesmsg"
+
+
+echo
+if test "x$avalon" = xyes; then
+	echo "  Avalon.ASICs.........: Enabled"
+else
+	echo "  Avalon.ASICs.........: Disabled"
+fi
+
+if test "x$avalon2" = xyes; then
+	echo "  Avalon2.ASICs.........: Enabled"
+else
+	echo "  Avalon2.ASICs.........: Disabled"
+fi
+
+if test "x$minion" = xyes; then
+	echo "  BlackArrowMinion.ASIC: Enabled"
+else
+	echo "  BlackArrowMinion.ASIC: Disabled"
+fi
+
+if test "x$bab" = xyes; then
+	echo "  BlackArrow.ASICs.....: Enabled"
+else
+	echo "  BlackArrow.ASICs.....: Disabled"
+fi
+
+if test "x$bflsc" = xyes; then
+	echo "  BFL.ASICs............: Enabled"
+else
+	echo "  BFL.ASICs............: Disabled"
+fi
+
+if test "x$bitforce" = xyes; then
+	echo "  BitForce.FPGAs.......: Enabled"
+else
+	echo "  BitForce.FPGAs.......: Disabled"
+fi
+
+if test "x$bitfury" = xyes; then
+	echo "  BitFury.ASICs........: Enabled"
+else
+	echo "  BitFury.ASICs........: Disabled"
+fi
+
+if test "x$drillbit" = xyes; then
+	echo "  Drillbit.BitFury.....: Enabled"
+else
+	echo "  Drillbit.BitFury.....: Disabled"
+fi
+
+if test "x$hashfast" = xyes; then
+	echo "  Hashfast.ASICs.......: Enabled"
+else
+	echo "  Hashfast.ASICs.......: Disabled"
+fi
+
+if test "x$icarus" = xyes; then
+	echo "  Icarus.ASICs/FPGAs...: Enabled"
+else
+	echo "  Icarus.ASICs/FPGAs...: Disabled"
+fi
+>>>>>>> 7c5b0b8... Add Avalon2 (2U size machine) support
 
 if $use_udevrules; then
 	AC_CONFIG_FILES([70-bfgminer.rules])
@@ -1817,10 +2010,20 @@ fi
 AC_OUTPUT
 
 
+<<<<<<< HEAD
 wordfilter ()
 {
   echo "$1" | sed 's/ \+/ /g;s/^ *//;s/ *$//'
 }
+||||||| parent of 7c5b0b8... Add Avalon2 (2U size machine) support
+if test "x$avalon$bab$bflsc$bitforce$bitfury$hashfast$icarus$klondike$knc$modminer$drillbit$minion" = xnononononononononononono; then
+	AC_MSG_ERROR([No mining configured in])
+fi
+=======
+if test "x$avalon$avalon2$bab$bflsc$bitforce$bitfury$hashfast$icarus$klondike$knc$modminer$drillbit$minion" = xnononononononononononono; then
+	AC_MSG_ERROR([No mining configured in])
+fi
+>>>>>>> 7c5b0b8... Add Avalon2 (2U size machine) support
 
 echo
 echo "------------------------------------------------------------------------"

+ 23 - 0
crc.h

@@ -0,0 +1,23 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
+ *
+ * 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, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _CRC_H_
+#define _CRC_H_
+
+unsigned short crc16(const unsigned char *buffer, int len);
+
+#endif	/* _CRC_H_ */

+ 45 - 0
crc16.c

@@ -0,0 +1,45 @@
+unsigned int crc16_table[256] = {
+	0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
+	0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
+	0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
+	0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
+	0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
+	0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
+	0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
+	0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
+	0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
+	0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
+	0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
+	0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
+	0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
+	0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
+	0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
+	0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
+	0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
+	0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
+	0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
+	0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
+	0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
+	0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+	0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
+	0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
+	0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
+	0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
+	0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
+	0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
+	0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
+	0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
+	0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
+	0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
+};
+
+unsigned short crc16(const unsigned char *buffer, int len)
+{
+	unsigned short crc;
+
+	crc = 0;
+	while(len-- > 0)
+	    crc = crc16_table[((crc >> 8) ^ (*buffer++)) & 0xFF] ^ (crc << 8);
+
+	return crc;
+}

+ 800 - 0
driver-avalon2.c

@@ -0,0 +1,800 @@
+/*
+ * Copyright 2013 Con Kolivas <kernel@kolivas.org>
+ * Copyright 2012-2014 Xiangfu <xiangfu@openmobilefree.com>
+ * Copyright 2012 Luke Dashjr
+ * Copyright 2012 Andrew Smith
+ *
+ * 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 3 of the License, or (at your option)
+ * any later version.  See COPYING for more details.
+ */
+
+#include "config.h"
+
+#include <limits.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/select.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"
+#include "fpgautils.h"
+#include "driver-avalon2.h"
+#include "crc.h"
+#include "hexdump.c"
+
+#define ASSERT1(condition) __maybe_unused static char sizeof_uint32_t_must_be_4[(condition)?1:-1]
+ASSERT1(sizeof(uint32_t) == 4);
+
+int opt_avalon2_freq_min = AVA2_DEFAULT_FREQUENCY;
+int opt_avalon2_freq_max = AVA2_DEFAULT_FREQUENCY_MAX;
+
+int opt_avalon2_fan_min = AVA2_DEFAULT_FAN_PWM;
+int opt_avalon2_fan_max = AVA2_DEFAULT_FAN_MAX;
+
+int opt_avalon2_voltage_min = AVA2_DEFAULT_VOLTAGE;
+int opt_avalon2_voltage_max = AVA2_DEFAULT_VOLTAGE_MAX;
+
+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;
+}
+
+char *set_avalon2_fan(char *arg)
+{
+	int val1, val2, ret;
+
+	ret = sscanf(arg, "%d-%d", &val1, &val2);
+	if (ret < 1)
+		return "No values passed to avalon2-fan";
+	if (ret == 1)
+		val2 = val1;
+
+	if (val1 < 0 || val1 > 100 || val2 < 0 || val2 > 100 || val2 < val1)
+		return "Invalid value passed to avalon2-fan";
+
+	opt_avalon2_fan_min = AVA2_PWM_MAX - val1 * AVA2_PWM_MAX / 100;
+	opt_avalon2_fan_max = AVA2_PWM_MAX - val2 * AVA2_PWM_MAX / 100;
+
+	return NULL;
+}
+
+char *set_avalon2_freq(char *arg)
+{
+	int val1, val2, ret;
+
+	ret = sscanf(arg, "%d-%d", &val1, &val2);
+	if (ret < 1)
+		return "No values passed to avalon2-freq";
+	if (ret == 1)
+		val2 = val1;
+
+	if (val1 < AVA2_DEFAULT_FREQUENCY_MIN || val1 > AVA2_DEFAULT_FREQUENCY_MAX ||
+	    val2 < AVA2_DEFAULT_FREQUENCY_MIN || val2 > AVA2_DEFAULT_FREQUENCY_MAX ||
+	    val2 < val1)
+		return "Invalid value passed to avalon2-freq";
+
+	opt_avalon2_freq_min = val1;
+	opt_avalon2_freq_max = val2;
+
+	return NULL;
+}
+
+char *set_avalon2_voltage(char *arg)
+{
+	int val1, val2, ret;
+
+	ret = sscanf(arg, "%d-%d", &val1, &val2);
+	if (ret < 1)
+		return "No values passed to avalon2-voltage";
+	if (ret == 1)
+		val2 = val1;
+
+	if (val1 < AVA2_DEFAULT_VOLTAGE_MIN || val1 > AVA2_DEFAULT_VOLTAGE_MAX ||
+	    val2 < AVA2_DEFAULT_VOLTAGE_MIN || val2 > AVA2_DEFAULT_VOLTAGE_MAX ||
+	    val2 < val1)
+		return "Invalid value passed to avalon2-voltage";
+
+	opt_avalon2_voltage_min = val1;
+	opt_avalon2_voltage_max = val2;
+
+	return NULL;
+}
+
+static int avalon2_init_pkg(struct avalon2_pkg *pkg, uint8_t type, uint8_t idx, uint8_t cnt)
+{
+	unsigned short crc;
+
+	pkg->head[0] = AVA2_H1;
+	pkg->head[1] = AVA2_H2;
+
+	pkg->type = type;
+	pkg->idx = idx;
+	pkg->cnt = cnt;
+
+	crc = crc16(pkg->data, AVA2_P_DATA_LEN);
+
+	pkg->crc[0] = (crc & 0xff00) >> 8;
+	pkg->crc[1] = crc & 0x00ff;
+	return 0;
+}
+
+static int job_idcmp(uint8_t *job_id, char *pool_job_id)
+{
+	int i = 0;
+	for (i = 0; i < 4; i++) {
+		if (job_id[i] != *(pool_job_id + strlen(pool_job_id) - 4 + i))
+			return 1;
+	}
+	return 0;
+}
+
+extern void submit_nonce2_nonce(struct thr_info *thr, uint32_t pool_no, uint32_t nonce2, uint32_t nonce);
+static int decode_pkg(struct thr_info *thr, struct avalon2_ret *ar, uint8_t *pkg)
+{
+	struct cgpu_info *avalon2;
+	struct avalon2_info *info;
+	struct pool *pool;
+
+	unsigned int expected_crc;
+	unsigned int actual_crc;
+	uint32_t nonce, nonce2, miner, modular_id;
+	int pool_no;
+	uint8_t job_id[5];
+	int tmp;
+
+	int type = AVA2_GETS_ERROR;
+
+	if (thr) {
+		avalon2 = thr->cgpu;
+		info = avalon2->device_data;
+	}
+
+	memcpy((uint8_t *)ar, pkg, AVA2_READ_SIZE);
+
+	if (ar->head[0] == AVA2_H1 && ar->head[1] == AVA2_H2) {
+		expected_crc = crc16(ar->data, AVA2_P_DATA_LEN);
+		actual_crc = (ar->crc[0] & 0xff) |
+			((ar->crc[1] & 0xff) << 8);
+
+		type = ar->type;
+		applog(LOG_DEBUG, "Avalon2: %d: expected crc(%04x), actural_crc(%04x)", type, expected_crc, actual_crc);
+		if (expected_crc != actual_crc)
+			goto out;
+
+		memcpy(&modular_id, ar->data + 28, 4);
+		modular_id = be32toh(modular_id);
+		if (modular_id == 3)
+			modular_id = 0;
+
+		switch(type) {
+		case AVA2_P_NONCE:
+			memcpy(&miner, ar->data + 0, 4);
+			memcpy(&pool_no, ar->data + 4, 4);
+			memcpy(&nonce2, ar->data + 8, 4);
+			/* Calc time    ar->data + 12 */
+			memcpy(&nonce, ar->data + 16, 4);
+			memset(job_id, 0, 5);
+			memcpy(job_id, ar->data + 20, 4);
+
+			miner = be32toh(miner);
+			pool_no = be32toh(pool_no);
+			if (miner >= AVA2_DEFAULT_MINERS ||
+			    modular_id >= AVA2_DEFAULT_MINERS || 
+			    pool_no >= total_pools ||
+			    pool_no < 0) {
+				applog(LOG_DEBUG, "Avalon2: Wrong miner/pool/id no %d,%d,%d", miner, pool_no, modular_id);
+				break;
+			} else
+				info->matching_work[modular_id * AVA2_DEFAULT_MINERS + miner]++;
+			nonce2 = bswap_32(nonce2);
+			nonce = be32toh(nonce);
+			nonce -= 0x180;
+
+			applog(LOG_DEBUG, "Avalon2: Found! [%s] %d:(%08x) (%08x)",
+			       job_id, pool_no, nonce2, nonce);
+			/* FIXME:
+			 * We need remember the pre_pool. then submit the stale work */
+			pool = pools[pool_no];
+			if (job_idcmp(job_id, pool->swork.job_id))
+				break;
+
+			if (thr && !info->new_stratum)
+				submit_nonce2_nonce(thr, pool_no, nonce2, nonce);
+			break;
+		case AVA2_P_STATUS:
+			memcpy(&tmp, ar->data, 4);
+			tmp = be32toh(tmp);
+			info->temp[0 + modular_id * 2] = tmp >> 16;
+			info->temp[1 + modular_id * 2] = tmp & 0xffff;
+
+			memcpy(&tmp, ar->data + 4, 4);
+			tmp = be32toh(tmp);
+			info->fan[0 + modular_id * 2] = tmp >> 16;
+			info->fan[1 + modular_id * 2] = tmp & 0xffff;
+
+			memcpy(&(info->get_frequency[modular_id]), ar->data + 8, 4);
+			memcpy(&(info->get_voltage[modular_id]), ar->data + 12, 4);
+			memcpy(&(info->local_work[modular_id]), ar->data + 16, 4);
+			memcpy(&(info->hw_work[modular_id]), ar->data + 20, 4);
+			info->get_frequency[modular_id] = be32toh(info->get_frequency[modular_id]);
+			info->get_voltage[modular_id] = be32toh(info->get_voltage[modular_id]);
+			info->local_work[modular_id] = be32toh(info->local_work[modular_id]);
+			info->hw_work[modular_id] = be32toh(info->hw_work[modular_id]);
+
+			info->local_works[modular_id] += info->local_work[modular_id];
+			info->hw_works[modular_id] += info->hw_work[modular_id];
+
+			avalon2->temp = info->temp[0]; /* FIXME: */
+			break;
+		case AVA2_P_ACKDETECT:
+			break;
+		case AVA2_P_ACK:
+			break;
+		case AVA2_P_NAK:
+			break;
+		default:
+			type = AVA2_GETS_ERROR;
+			break;
+		}
+	}
+
+out:
+	return type;
+}
+
+static inline int avalon2_gets(int fd, uint8_t *buf)
+{
+	int i;
+	int read_amount = AVA2_READ_SIZE;
+	uint8_t buf_tmp[AVA2_READ_SIZE];
+	uint8_t buf_copy[2 * AVA2_READ_SIZE];
+	uint8_t *buf_back = buf;
+	ssize_t ret = 0;
+
+	while (true) {
+		struct timeval timeout;
+		fd_set rd;
+
+		timeout.tv_sec = 0;
+		timeout.tv_usec = 100000;
+
+		FD_ZERO(&rd);
+		FD_SET(fd, &rd);
+		ret = select(fd + 1, &rd, NULL, NULL, &timeout);
+		if (unlikely(ret < 0)) {
+			applog(LOG_ERR, "Avalon2: Error %d on select in avalon_gets", errno);
+			return AVA2_GETS_ERROR;
+		}
+		if (ret) {
+			memset(buf, 0, read_amount);
+			ret = read(fd, buf, read_amount);
+			if (unlikely(ret < 0)) {
+				applog(LOG_ERR, "Avalon2: Error %d on read in avalon_gets", errno);
+				return AVA2_GETS_ERROR;
+			}
+			if (likely(ret >= read_amount)) {
+				for (i = 1; i < read_amount; i++) {
+					if (buf_back[i - 1] == AVA2_H1 && buf_back[i] == AVA2_H2)
+						break;
+				}
+				i -= 1;
+				if (i) {
+					ret = read(fd, buf_tmp, i);
+					if (unlikely(ret != i)) {
+						applog(LOG_ERR, "Avalon2: Error %d on read in avalon_gets", errno);
+						return AVA2_GETS_ERROR;
+					}
+					memcpy(buf_copy, buf_back + i, AVA2_READ_SIZE - i);
+					memcpy(buf_copy + AVA2_READ_SIZE - i, buf_tmp, i);
+					memcpy(buf_back, buf_copy, AVA2_READ_SIZE);
+				}
+				return AVA2_GETS_OK;
+			}
+			buf += ret;
+			read_amount -= ret;
+			continue;
+		}
+
+		return AVA2_GETS_TIMEOUT;
+	}
+}
+
+static int avalon2_send_pkg(int fd, const struct avalon2_pkg *pkg,
+			    struct thr_info __maybe_unused *thr)
+{
+	int ret;
+	uint8_t buf[AVA2_WRITE_SIZE];
+	size_t nr_len = AVA2_WRITE_SIZE;
+
+	memcpy(buf, pkg, AVA2_WRITE_SIZE);
+	if (opt_debug) {
+		applog(LOG_DEBUG, "Avalon2: Sent(%ld):", nr_len);
+		hexdump((uint8_t *)buf, nr_len);
+	}
+
+	ret = write(fd, buf, nr_len);
+	if (unlikely(ret != nr_len)) {
+		applog(LOG_DEBUG, "Avalon2: Send(%d)!", ret);
+		return AVA2_SEND_ERROR;
+	}
+
+	cgsleep_ms(20);
+#if 0
+	ret = avalon2_gets(fd, result);
+	if (ret != AVA2_GETS_OK) {
+		applog(LOG_DEBUG, "Avalon2: Get(%d)!", ret);
+		return AVA2_SEND_ERROR;
+	}
+
+	ret = decode_pkg(thr, &ar, result);
+	if (ret != AVA2_P_ACK) {
+		applog(LOG_DEBUG, "Avalon2: PKG(%d)!", ret);
+		hexdump((uint8_t *)result, AVA2_READ_SIZE);
+		return AVA2_SEND_ERROR;
+	}
+#endif
+
+	return AVA2_SEND_OK;
+}
+
+static int avalon2_stratum_pkgs(int fd, struct pool *pool, struct thr_info *thr)
+{
+	/* FIXME: what if new stratum arrive when writing */
+	struct avalon2_pkg pkg;
+	int i, a, b, tmp;
+	unsigned char target[32];
+	int job_id_len;
+
+	/* Send out the first stratum message STATIC */
+	applog(LOG_DEBUG, "Avalon2: Pool stratum message STATIC: %ld, %d, %d, %d, %d",
+	       pool->swork.cb_len,
+	       pool->nonce2_offset,
+	       pool->n2size,
+	       pool->merkle_offset,
+	       pool->swork.merkles);
+	memset(pkg.data, 0, AVA2_P_DATA_LEN);
+	tmp = be32toh(pool->swork.cb_len);
+	memcpy(pkg.data, &tmp, 4);
+
+	tmp = be32toh(pool->nonce2_offset);
+	memcpy(pkg.data + 4, &tmp, 4);
+
+	tmp = be32toh(pool->n2size);
+	memcpy(pkg.data + 8, &tmp, 4);
+
+	tmp = be32toh(pool->merkle_offset);
+	memcpy(pkg.data + 12, &tmp, 4);
+
+	tmp = be32toh(pool->swork.merkles);
+	memcpy(pkg.data + 16, &tmp, 4);
+
+	tmp = be32toh((int)pool->swork.diff);
+	memcpy(pkg.data + 20, &tmp, 4);
+
+	tmp = be32toh((int)pool->pool_no);
+	memcpy(pkg.data + 24, &tmp, 4);
+
+	avalon2_init_pkg(&pkg, AVA2_P_STATIC, 1, 1);
+	while (avalon2_send_pkg(fd, &pkg, thr) != AVA2_SEND_OK)
+		;
+
+	set_target(target, pool->swork.diff);
+	memcpy(pkg.data, target, 32);
+	if (opt_debug) {
+		char *target_str;
+		target_str = bin2hex(target, 32);
+		applog(LOG_DEBUG, "Avalon2: Pool stratum target: %s", target_str);
+		free(target_str);
+	}
+	avalon2_init_pkg(&pkg, AVA2_P_TARGET, 1, 1);
+	while (avalon2_send_pkg(fd, &pkg, thr) != AVA2_SEND_OK)
+		;
+
+
+	applog(LOG_DEBUG, "Avalon2: Pool stratum message JOBS_ID: %s",
+	       pool->swork.job_id);
+	memset(pkg.data, 0, AVA2_P_DATA_LEN);
+
+	job_id_len = strlen(pool->swork.job_id);
+	job_id_len = job_id_len >= 4 ? 4 : job_id_len;
+	for (i = 0; i < job_id_len; i++) {
+		pkg.data[i] = *(pool->swork.job_id + strlen(pool->swork.job_id) - 4 + i);
+	}
+	avalon2_init_pkg(&pkg, AVA2_P_JOB_ID, 1, 1);
+	while (avalon2_send_pkg(fd, &pkg, thr) != AVA2_SEND_OK)
+		;
+
+	a = pool->swork.cb_len / AVA2_P_DATA_LEN;
+	b = pool->swork.cb_len % AVA2_P_DATA_LEN;
+	applog(LOG_DEBUG, "Avalon2: Pool stratum message COINBASE: %d %d", a, b);
+	for (i = 0; i < a; i++) {
+		memcpy(pkg.data, pool->coinbase + i * 32, 32);
+		avalon2_init_pkg(&pkg, AVA2_P_COINBASE, i + 1, a + (b ? 1 : 0));
+		while (avalon2_send_pkg(fd, &pkg, thr) != AVA2_SEND_OK)
+			;
+	}
+	if (b) {
+		memset(pkg.data, 0, AVA2_P_DATA_LEN);
+		memcpy(pkg.data, pool->coinbase + i * 32, b);
+		avalon2_init_pkg(&pkg, AVA2_P_COINBASE, i + 1, i + 1);
+		while (avalon2_send_pkg(fd, &pkg, thr) != AVA2_SEND_OK)
+			;
+	}
+
+	b = pool->swork.merkles;
+	applog(LOG_DEBUG, "Avalon2: Pool stratum message MERKLES: %d", b);
+	for (i = 0; i < b; i++) {
+		memset(pkg.data, 0, AVA2_P_DATA_LEN);
+		memcpy(pkg.data, pool->swork.merkle_bin[i], 32);
+		avalon2_init_pkg(&pkg, AVA2_P_MERKLES, i + 1, b);
+		while (avalon2_send_pkg(fd, &pkg, thr) != AVA2_SEND_OK)
+			;
+	}
+
+	applog(LOG_DEBUG, "Avalon2: Pool stratum message HEADER: 4");
+	for (i = 0; i < 4; i++) {
+		memset(pkg.data, 0, AVA2_P_HEADER);
+		memcpy(pkg.data, pool->header_bin + i * 32, 32);
+		avalon2_init_pkg(&pkg, AVA2_P_HEADER, i + 1, 4);
+		while (avalon2_send_pkg(fd, &pkg, thr) != AVA2_SEND_OK)
+			;
+
+	}
+	return 0;
+}
+
+static int avalon2_get_result(struct thr_info *thr, int fd_detect, struct avalon2_ret *ar)
+{
+	struct cgpu_info *avalon2;
+	struct avalon2_info *info;
+	int fd;
+
+	fd = fd_detect;
+	if (thr) {
+		avalon2 = thr->cgpu;
+		info = avalon2->device_data;
+		fd = info->fd;
+	}
+
+	uint8_t result[AVA2_READ_SIZE];
+	int ret;
+
+	memset(result, 0, AVA2_READ_SIZE);
+
+	ret = avalon2_gets(fd, result);
+	if (ret != AVA2_GETS_OK)
+		return ret;
+
+	if (opt_debug) {
+		applog(LOG_DEBUG, "Avalon2: Get(ret = %d):", ret);
+		hexdump((uint8_t *)result, AVA2_READ_SIZE);
+	}
+
+	return decode_pkg(thr, ar, result);
+}
+
+static bool avalon2_detect_one(const char *devpath)
+{
+	struct avalon2_info *info;
+	int ackdetect;
+	int fd;
+	int tmp, i, modular[3];
+	char mm_version[AVA2_DEFAULT_MODULARS][16];
+
+	struct cgpu_info *avalon2;
+	struct avalon2_pkg detect_pkg;
+	struct avalon2_ret ret_pkg;
+
+	applog(LOG_DEBUG, "Avalon2 Detect: Attempting to open %s", devpath);
+
+	fd = avalon2_open(devpath, AVA2_IO_SPEED, true);
+	if (unlikely(fd == -1)) {
+		applog(LOG_ERR, "Avalon2 Detect: Failed to open %s", devpath);
+		return false;
+	}
+	tcflush(fd, TCIOFLUSH);
+
+	for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) {
+		modular[i] = 0;
+		strcpy(mm_version[i], "NONE");
+		/* Send out detect pkg */
+		memset(detect_pkg.data, 0, AVA2_P_DATA_LEN);
+		tmp = be32toh(i);
+		memcpy(detect_pkg.data + 28, &tmp, 4);
+
+		avalon2_init_pkg(&detect_pkg, AVA2_P_DETECT, 1, 1);
+		avalon2_send_pkg(fd, &detect_pkg, NULL);
+		ackdetect = avalon2_get_result(NULL, fd, &ret_pkg);
+		applog(LOG_DEBUG, "Avalon2 Detect ID[%d]: %d", i, ackdetect);
+		if (ackdetect != AVA2_P_ACKDETECT)
+			continue;
+		modular[i] = 1;
+		memcpy(mm_version[i], ret_pkg.data, 15);
+		mm_version[i][15] = '\0';
+	}
+	if (!modular[0] && !modular[1] && !modular[2])
+		return false;
+
+	/* We have a real Avalon! */
+	avalon2 = calloc(1, sizeof(struct cgpu_info));
+	avalon2->drv = &avalon2_drv;
+	avalon2->device_path = strdup(devpath);
+	avalon2->threads = AVA2_MINER_THREADS;
+	add_cgpu(avalon2);
+
+	applog(LOG_INFO, "Avalon2 Detect: Found at %s, mark as %d",
+	       devpath, avalon2->device_id);
+
+	avalon2->device_data = calloc(sizeof(struct avalon2_info), 1);
+	if (unlikely(!(avalon2->device_data)))
+		quit(1, "Failed to malloc avalon2_info");
+
+	info = avalon2->device_data;
+
+	strcpy(info->mm_version[0], mm_version[0]);
+	strcpy(info->mm_version[1], mm_version[1]);
+	strcpy(info->mm_version[2], mm_version[2]);
+
+	info->baud = AVA2_IO_SPEED;
+	info->fan_pwm = AVA2_DEFAULT_FAN_PWM;
+	info->set_voltage = AVA2_DEFAULT_VOLTAGE_MIN;
+	info->set_frequency = AVA2_DEFAULT_FREQUENCY;
+	info->temp_max = 0;
+	info->temp_history_index = 0;
+	info->temp_sum = 0;
+	info->temp_old = 0;
+	info->modulars[0] = modular[0];
+	info->modulars[1] = modular[1];
+	info->modulars[2] = modular[2];	/* Enable modular */
+
+	info->fd = -1;
+	/* Set asic to idle mode after detect */
+	avalon2_close(fd);
+
+	return true;
+}
+
+static inline void avalon2_detect()
+{
+	serial_detect(&avalon2_drv, avalon2_detect_one);
+}
+
+static void avalon2_init(struct cgpu_info *avalon2)
+{
+	int fd;
+	struct avalon2_info *info = avalon2->device_data;
+
+	fd = avalon2_open(avalon2->device_path, info->baud, true);
+	if (unlikely(fd == -1)) {
+		applog(LOG_ERR, "Avalon2: Failed to open on %s", avalon2->device_path);
+		return;
+	}
+	applog(LOG_DEBUG, "Avalon2: Opened on %s", avalon2->device_path);
+
+	info->fd = fd;
+}
+
+static bool avalon2_prepare(struct thr_info *thr)
+{
+	struct cgpu_info *avalon2 = thr->cgpu;
+	struct avalon2_info *info = avalon2->device_data;
+
+	free(avalon2->works);
+	avalon2->works = calloc(sizeof(struct work *), 2);
+	if (!avalon2->works)
+		quit(1, "Failed to calloc avalon2 works in avalon2_prepare");
+
+	if (info->fd == -1)
+		avalon2_init(avalon2);
+
+	info->first = true;
+
+	return true;
+}
+
+static int polling(struct thr_info *thr)
+{
+	int i, tmp;
+
+	struct avalon2_pkg send_pkg;
+	struct avalon2_ret ar;
+
+	struct cgpu_info *avalon2 = thr->cgpu;
+	struct avalon2_info *info = avalon2->device_data;
+
+	for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) {
+		if (info->modulars[i]) {
+			memset(send_pkg.data, 0, AVA2_P_DATA_LEN);
+			tmp = be32toh(i);
+			memcpy(send_pkg.data + 28, &tmp, 4);
+			avalon2_init_pkg(&send_pkg, AVA2_P_POLLING, 1, 1);
+
+			while (avalon2_send_pkg(info->fd, &send_pkg, thr) != AVA2_SEND_OK)
+				;
+			avalon2_get_result(thr, info->fd, &ar);
+		}
+	}
+
+	return 0;
+}
+
+static int64_t avalon2_scanhash(struct thr_info *thr)
+{
+	struct avalon2_pkg send_pkg;
+
+	struct pool *pool;
+	struct cgpu_info *avalon2 = thr->cgpu;
+	struct avalon2_info *info = avalon2->device_data;
+
+	int64_t h;
+	uint32_t tmp, range, start;
+	int i;
+
+	if (thr->work_restart || thr->work_update ||
+	    info->first) {
+		info->new_stratum = true;
+		applog(LOG_DEBUG, "Avalon2: New stratum: restart: %d, update: %d, first: %d",
+		       thr->work_restart, thr->work_update, info->first);
+		thr->work_update = false;
+		thr->work_restart = false;
+		if (unlikely(info->first))
+			info->first = false;
+
+		get_work(thr, thr->id); /* Make sure pool is ready */
+
+		pool = current_pool();
+		if (!pool->has_stratum)
+			quit(1, "Avalon2: Miner Manager have to use stratum pool");
+		if (pool->swork.cb_len > AVA2_P_COINBASE_SIZE)
+			quit(1, "Avalon2: Miner Manager pool coinbase length have to less then %d", AVA2_P_COINBASE_SIZE);
+		if (pool->swork.merkles > AVA2_P_MERKLES_COUNT)
+			quit(1, "Avalon2: Miner Manager merkles have to less then %d", AVA2_P_MERKLES_COUNT);
+
+		info->diff = (int)pool->swork.diff - 1;
+		info->pool_no = pool->pool_no;
+
+		cg_wlock(&pool->data_lock);
+		avalon2_stratum_pkgs(info->fd, pool, thr);
+		cg_wunlock(&pool->data_lock);
+
+		/* Configuer the parameter from outside */
+		info->fan_pwm = opt_avalon2_fan_min;
+		info->set_voltage = opt_avalon2_voltage_min;
+		info->set_frequency = opt_avalon2_freq_min;
+
+		/* Set the Fan, Voltage and Frequency */
+		memset(send_pkg.data, 0, AVA2_P_DATA_LEN);
+
+		tmp = be32toh(info->fan_pwm);
+		memcpy(send_pkg.data, &tmp, 4);
+
+		/* http://www.onsemi.com/pub_link/Collateral/ADP3208D.PDF */
+		tmp = rev8((0x78 - info->set_voltage / 125) << 1 | 1) << 8;
+		tmp = be32toh(tmp);
+		memcpy(send_pkg.data + 4, &tmp, 4);
+
+		tmp = be32toh(info->set_frequency);
+		memcpy(send_pkg.data + 8, &tmp, 4);
+
+		/* Configure the nonce2 offset and range */
+		range = 0xffffffff / total_devices;
+		start = range * avalon2->device_id;
+
+		tmp = be32toh(start);
+		memcpy(send_pkg.data + 12, &tmp, 4);
+
+		tmp = be32toh(range);
+		memcpy(send_pkg.data + 16, &tmp, 4);
+
+		/* Package the data */
+		avalon2_init_pkg(&send_pkg, AVA2_P_SET, 1, 1);
+		while (avalon2_send_pkg(info->fd, &send_pkg, thr) != AVA2_SEND_OK)
+			;
+		info->new_stratum = false;
+	}
+
+	polling(thr);
+
+	h = 0;
+	for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) {
+		h += info->local_work[i];
+	}
+	return h * 0xffffffff;
+}
+
+static struct api_data *avalon2_api_stats(struct cgpu_info *cgpu)
+{
+	struct api_data *root = NULL;
+	struct avalon2_info *info = cgpu->device_data;
+	int i, a, b;
+	char buf[24];
+	double hwp;
+	for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) {
+		sprintf(buf, "ID%d MM Version", i + 1);
+		root = api_add_string(root, buf, &(info->mm_version[i]), false);
+	}
+	for (i = 0; i < AVA2_DEFAULT_MINERS * AVA2_DEFAULT_MODULARS; i++) {
+		sprintf(buf, "Match work count%02d", i + 1);
+		root = api_add_int(root, buf, &(info->matching_work[i]), false);
+	}
+	for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) {
+		sprintf(buf, "Local works%d", i + 1);
+		root = api_add_int(root, buf, &(info->local_works[i]), false);
+	}
+	for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) {
+		sprintf(buf, "Hardware error works%d", i + 1);
+		root = api_add_int(root, buf, &(info->hw_works[i]), false);
+	}
+	for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) {
+		a = info->hw_works[i];
+		b = info->local_works[i];
+		hwp = b ? ((double)a / (double)b) : 0;
+
+		sprintf(buf, "Device hardware error%d%%", i + 1);
+		root = api_add_percent(root, buf, &hwp, true);
+	}
+	for (i = 0; i < 2 * AVA2_DEFAULT_MODULARS; i++) {
+		sprintf(buf, "Temperature%d", i + 1);
+		root = api_add_int(root, buf, &(info->temp[i]), false);
+	}
+	for (i = 0; i < 2 * AVA2_DEFAULT_MODULARS; i++) {
+		sprintf(buf, "Fan%d", i + 1);
+		root = api_add_int(root, buf, &(info->fan[i]), false);
+	}
+	for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) {
+		sprintf(buf, "Voltage%d", i + 1);
+		root = api_add_int(root, buf, &(info->get_voltage[i]), false);
+	}
+	for (i = 0; i < AVA2_DEFAULT_MODULARS; i++) {
+		sprintf(buf, "Frequency%d", i + 1);
+		root = api_add_int(root, buf, &(info->get_frequency[i]), false);
+	}
+
+	return root;
+}
+
+static void avalon2_shutdown(struct thr_info *thr)
+{
+	struct cgpu_info *avalon = thr->cgpu;
+
+	free(avalon->works);
+	avalon->works = NULL;
+}
+
+struct device_drv avalon2_drv = {
+	.drv_id = DRIVER_avalon2,
+	.dname = "avalon2",
+	.name = "AV2",
+	.get_api_stats = avalon2_api_stats,
+	.drv_detect = avalon2_detect,
+	.reinit_device = avalon2_init,
+	.thread_prepare = avalon2_prepare,
+	.hash_work = hash_driver_work,
+	.scanwork = avalon2_scanhash,
+	.thread_shutdown = avalon2_shutdown,
+};

+ 136 - 0
driver-avalon2.h

@@ -0,0 +1,136 @@
+/*
+ * Copyright 2013 Con Kolivas <kernel@kolivas.org>
+ * Copyright 2012-2014 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 3 of the License, or (at your option)
+ * any later version.  See COPYING for more details.
+ */
+
+#ifndef _AVALON2_H_
+#define _AVALON2_H_
+
+#include "util.h"
+#include "fpgautils.h"
+
+#ifdef USE_AVALON2
+
+#define AVA2_MINER_THREADS	1
+
+#define AVA2_RESET_FAULT_DECISECONDS	10
+#define AVA2_IO_SPEED		115200
+
+#define AVA2_DEFAULT_MINERS	10
+#define AVA2_DEFAULT_MODULARS	3
+
+#define AVA2_PWM_MAX	0x3FF
+#define AVA2_DEFAULT_FAN_PWM	80 /* % */
+#define AVA2_DEFAULT_FAN_MIN	0
+#define AVA2_DEFAULT_FAN_MAX	100
+
+#define AVA2_DEFAULT_VOLTAGE	10000 /* V * 10000 */
+#define AVA2_DEFAULT_VOLTAGE_MIN	6000
+#define AVA2_DEFAULT_VOLTAGE_MAX	11000
+
+#define AVA2_DEFAULT_FREQUENCY	1500 /* In MH/s */
+#define AVA2_DEFAULT_FREQUENCY_MIN	300
+#define AVA2_DEFAULT_FREQUENCY_MAX	2000
+
+/* Avalon2 protocol package type */
+#define AVA2_H1	'A'
+#define AVA2_H2	'V'
+
+#define AVA2_P_COINBASE_SIZE	(6 * 1024)
+#define AVA2_P_MERKLES_COUNT	20
+
+#define AVA2_P_COUNT	39
+#define AVA2_P_DATA_LEN		(AVA2_P_COUNT - 7)
+
+#define AVA2_P_DETECT	10
+#define AVA2_P_STATIC	11
+#define AVA2_P_JOB_ID	12
+#define AVA2_P_COINBASE	13
+#define AVA2_P_MERKLES	14
+#define AVA2_P_HEADER	15
+#define AVA2_P_POLLING  16
+#define AVA2_P_TARGET	17
+#define AVA2_P_REQUIRE	18
+#define AVA2_P_SET	19
+#define AVA2_P_TEST	20
+
+#define AVA2_P_ACK		21
+#define AVA2_P_NAK		22
+#define AVA2_P_NONCE		23
+#define AVA2_P_STATUS		24
+#define AVA2_P_ACKDETECT	25
+#define AVA2_P_TEST_RET		26
+/* Avalon2 protocol package type */
+
+struct avalon2_pkg {
+	uint8_t head[2];
+	uint8_t type;
+	uint8_t idx;
+	uint8_t cnt;
+	uint8_t data[32];
+	uint8_t crc[2];
+};
+#define avalon2_ret avalon2_pkg
+
+struct avalon2_info {
+	int fd;
+	int baud;
+
+	int set_frequency;
+	int set_voltage;
+
+	int get_voltage[AVA2_DEFAULT_MODULARS];
+	int get_frequency[AVA2_DEFAULT_MODULARS];
+
+	int fan_pwm;
+
+	int fan[2 * AVA2_DEFAULT_MODULARS];
+	int temp[2 * AVA2_DEFAULT_MODULARS];
+
+	int temp_max;
+	int temp_history_count;
+	int temp_history_index;
+	int temp_sum;
+	int temp_old;
+
+	bool first;
+	bool new_stratum;
+
+	int pool_no;
+	int diff;
+
+	int local_works[AVA2_DEFAULT_MODULARS];
+	int hw_works[AVA2_DEFAULT_MODULARS];
+	int matching_work[AVA2_DEFAULT_MINERS * AVA2_DEFAULT_MODULARS];
+	int local_work[AVA2_DEFAULT_MODULARS];
+	int hw_work[AVA2_DEFAULT_MODULARS];
+
+	int modulars[AVA2_DEFAULT_MODULARS];
+	char mm_version[AVA2_DEFAULT_MODULARS][16];
+};
+
+#define AVA2_WRITE_SIZE (sizeof(struct avalon2_pkg))
+#define AVA2_READ_SIZE AVA2_WRITE_SIZE
+
+#define AVA2_GETS_OK 0
+#define AVA2_GETS_TIMEOUT -1
+#define AVA2_GETS_RESTART -2
+#define AVA2_GETS_ERROR -3
+
+#define AVA2_SEND_OK 0
+#define AVA2_SEND_ERROR -1
+
+#define avalon2_open(devpath, baud, purge)  serial_open(devpath, baud, AVA2_RESET_FAULT_DECISECONDS, purge)
+#define avalon2_close(fd) close(fd)
+
+extern char *set_avalon2_fan(char *arg);
+extern char *set_avalon2_freq(char *arg);
+extern char *set_avalon2_voltage(char *arg);
+
+#endif /* USE_AVALON2 */
+#endif	/* _AVALON2_H_ */

+ 70 - 0
miner.c

@@ -86,6 +86,20 @@
 #include "driver-avalon.h"
 #endif
 
+<<<<<<<
+|||||||
+#ifdef USE_BFLSC
+#include "driver-bflsc.h"
+#endif
+=======
+#ifdef USE_AVALON2
+#include "driver-avalon2.h"
+#endif
+
+#ifdef USE_BFLSC
+#include "driver-bflsc.h"
+#endif
+>>>>>>>
 #ifdef HAVE_BFG_LOWLEVEL
 #include "lowlevel.h"
 #endif
@@ -100,9 +114,15 @@
 #include "scrypt.h"
 #endif
 
+<<<<<<<
 #include "version.h"
 
 #if defined(USE_AVALON) || defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_MODMINER) || defined(USE_NANOFURY) || defined(USE_X6500) || defined(USE_ZTEX)
+|||||||
+#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_AVALON) || defined(USE_MODMINER)
+=======
+#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_AVALON) || defined(USE_AVALON2) || defined(USE_MODMINER)
+>>>>>>>
 #	define USE_FPGA
 #endif
 
@@ -2141,6 +2161,17 @@ static struct opt_table opt_config_table[] = {
 		     set_avalon_options, NULL, NULL,
 		     opt_hidden),
 #endif
+#ifdef USE_AVALON2
+	OPT_WITH_ARG("--avalon2-freq",
+		     set_avalon2_freq, NULL, NULL,
+		     "Set frequency range for Avalon2, single value or range"),
+	OPT_WITH_ARG("--avalon2-fan",
+		     set_avalon2_fan, NULL, NULL,
+		     "Set Avalon2 target fan speed"),
+	OPT_WITH_ARG("--avalon2-voltage",
+		     set_avalon2_voltage, NULL, NULL,
+		     "Set Avalon2 core voltage, in millivolts"),
+#endif
 #ifdef USE_KLONDIKE
 	OPT_WITH_ARG("--klondike-options",
 		     set_klondike_options, NULL, NULL,
@@ -3249,7 +3280,18 @@ int bfg_wresize(WINDOW *win, int lines, int columns)
 #else
 #	define bfg_wresize wresize
 #endif
+<<<<<<<
 
+|||||||
+#ifdef USE_BFLSC
+		"bflsc "
+=======
+#ifdef USE_AVALON2
+		"avalon2 "
+#endif
+#ifdef USE_BFLSC
+		"bflsc "
+>>>>>>>
 #endif
 
 void tailsprintf(char *buf, size_t bufsz, const char *fmt, ...)
@@ -9293,6 +9335,24 @@ bool pool_has_usable_swork(const struct pool * const pool)
 	return pool->stratum_notify;
 }
 
+#ifdef USE_AVALON2
+void submit_nonce2_nonce(struct thr_info *thr, uint32_t pool_no, uint32_t nonce2, uint32_t nonce)
+{
+	struct cgpu_info *cgpu = thr->cgpu;
+	struct device_drv *drv = cgpu->drv;
+
+	struct pool *pool = pools[pool_no];
+	struct work *work = make_work();
+
+	pool->nonce2 = nonce2;
+	gen_stratum_work(pool, work);
+
+	work->device_diff = MIN(drv->working_diff, work->work_difficulty);
+	submit_nonce(thr, work, nonce);
+	free_work(work);
+}
+#endif
+
 /* Generates stratum based work based on the most recent notify information
  * from the pool. This will keep generating work while a pool is down so we use
  * other means to detect when the pool has died in stratum_thread */
@@ -9905,14 +9965,24 @@ void hash_queued_work(struct thr_info *mythr)
 		struct timeval diff;
 		int64_t hashes;
 
+<<<<<<<
 		fill_queue(mythr, cgpu, drv, thr_id);
+|||||||
+		mythr->work_update = false;
+=======
+#ifndef USE_AVALON2
+		mythr->work_update = false;
+#endif
+>>>>>>>
 
 		thread_reportin(mythr);
 		hashes = drv->scanwork(mythr);
 
+#ifndef USE_AVALON2
 		/* Reset the bool here in case the driver looks for it
 		 * synchronously in the scanwork loop. */
 		mythr->work_restart = false;
+#endif
 
 		if (unlikely(hashes == -1 )) {
 			applog(LOG_ERR, "%s %d failure, disabling!", drv->name, cgpu->device_id);

+ 83 - 0
miner.h

@@ -206,6 +206,83 @@ static inline int fsync (int fd)
 #	endif
 #endif
 
+<<<<<<< HEAD
+||||||| parent of 7c5b0b8... Add Avalon2 (2U size machine) support
+/* Put avalon last to make it the last device it tries to detect to prevent it
+ * trying to claim same chip but different devices. Adding a device here will
+ * update all macros in the code that use the *_PARSE_COMMANDS macros for each
+ * listed driver. */
+#define FPGA_PARSE_COMMANDS(DRIVER_ADD_COMMAND) \
+	DRIVER_ADD_COMMAND(bitforce) \
+	DRIVER_ADD_COMMAND(icarus) \
+	DRIVER_ADD_COMMAND(modminer)
+
+#define ASIC_PARSE_COMMANDS(DRIVER_ADD_COMMAND) \
+	DRIVER_ADD_COMMAND(bflsc) \
+	DRIVER_ADD_COMMAND(bitfury) \
+	DRIVER_ADD_COMMAND(hashfast) \
+	DRIVER_ADD_COMMAND(klondike) \
+	DRIVER_ADD_COMMAND(knc) \
+	DRIVER_ADD_COMMAND(drillbit) \
+	DRIVER_ADD_COMMAND(bab) \
+	DRIVER_ADD_COMMAND(minion) \
+	DRIVER_ADD_COMMAND(avalon)
+
+#define DRIVER_PARSE_COMMANDS(DRIVER_ADD_COMMAND) \
+	FPGA_PARSE_COMMANDS(DRIVER_ADD_COMMAND) \
+	ASIC_PARSE_COMMANDS(DRIVER_ADD_COMMAND)
+
+#define DRIVER_ENUM(X) DRIVER_##X,
+#define DRIVER_PROTOTYPE(X) struct device_drv X##_drv;
+
+/* Create drv_driver enum from DRIVER_PARSE_COMMANDS macro */
+enum drv_driver {
+	DRIVER_PARSE_COMMANDS(DRIVER_ENUM)
+	DRIVER_MAX
+};
+
+/* Use DRIVER_PARSE_COMMANDS to generate extern device_drv prototypes */
+DRIVER_PARSE_COMMANDS(DRIVER_PROTOTYPE)
+
+=======
+/* Put avalon last to make it the last device it tries to detect to prevent it
+ * trying to claim same chip but different devices. Adding a device here will
+ * update all macros in the code that use the *_PARSE_COMMANDS macros for each
+ * listed driver. */
+#define FPGA_PARSE_COMMANDS(DRIVER_ADD_COMMAND) \
+	DRIVER_ADD_COMMAND(bitforce) \
+	DRIVER_ADD_COMMAND(icarus) \
+	DRIVER_ADD_COMMAND(modminer)
+
+#define ASIC_PARSE_COMMANDS(DRIVER_ADD_COMMAND) \
+	DRIVER_ADD_COMMAND(bflsc) \
+	DRIVER_ADD_COMMAND(bitfury) \
+	DRIVER_ADD_COMMAND(hashfast) \
+	DRIVER_ADD_COMMAND(klondike) \
+	DRIVER_ADD_COMMAND(knc) \
+	DRIVER_ADD_COMMAND(drillbit) \
+	DRIVER_ADD_COMMAND(bab) \
+	DRIVER_ADD_COMMAND(minion) \
+	DRIVER_ADD_COMMAND(avalon2) \
+	DRIVER_ADD_COMMAND(avalon)
+
+#define DRIVER_PARSE_COMMANDS(DRIVER_ADD_COMMAND) \
+	FPGA_PARSE_COMMANDS(DRIVER_ADD_COMMAND) \
+	ASIC_PARSE_COMMANDS(DRIVER_ADD_COMMAND)
+
+#define DRIVER_ENUM(X) DRIVER_##X,
+#define DRIVER_PROTOTYPE(X) struct device_drv X##_drv;
+
+/* Create drv_driver enum from DRIVER_PARSE_COMMANDS macro */
+enum drv_driver {
+	DRIVER_PARSE_COMMANDS(DRIVER_ENUM)
+	DRIVER_MAX
+};
+
+/* Use DRIVER_PARSE_COMMANDS to generate extern device_drv prototypes */
+DRIVER_PARSE_COMMANDS(DRIVER_PROTOTYPE)
+
+>>>>>>> 7c5b0b8... Add Avalon2 (2U size machine) support
 enum alive {
 	LIFE_WELL,
 	LIFE_SICK,
@@ -478,12 +555,18 @@ struct cgpu_info {
 #ifdef USE_ZTEX
 		struct libztex_device *device_ztex;
 #endif
+<<<<<<< HEAD
 		int device_fd;
 #ifdef USE_X6500
 		struct ft232r_device_handle *device_ft232r;
 #endif
 	};
 #ifdef USE_AVALON
+||||||| parent of 7c5b0b8... Add Avalon2 (2U size machine) support
+#ifdef USE_AVALON
+=======
+#if defined(USE_AVALON) || defined(USE_AVALON2)
+>>>>>>> 7c5b0b8... Add Avalon2 (2U size machine) support
 	struct work **works;
 	int work_array;
 	int queued;