Add support for ANU overclocking.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
diff --git a/driver-icarus.c b/driver-icarus.c
index 4be196b..04c25c3 100644
--- a/driver-icarus.c
+++ b/driver-icarus.c
@@ -794,6 +794,122 @@ static void get_options(int this_option_offset, struct cgpu_info *icarus, int *b
}
}
+unsigned char crc5(unsigned char *ptr, unsigned char len)
+{
+ unsigned char i, j, k;
+ unsigned char crc = 0x1f;
+
+ unsigned char crcin[5] = {1, 1, 1, 1, 1};
+ unsigned char crcout[5] = {1, 1, 1, 1, 1};
+ unsigned char din = 0;
+
+ j = 0x80;
+ k = 0;
+ for (i = 0; i < len; i++) {
+ if (*ptr & j)
+ din = 1;
+ else
+ din = 0;
+ crcout[0] = crcin[4] ^ din;
+ crcout[1] = crcin[0];
+ crcout[2] = crcin[1] ^ crcin[4] ^ din;
+ crcout[3] = crcin[2];
+ crcout[4] = crcin[3];
+
+ j = j >> 1;
+ k++;
+ if (k == 8) {
+ j = 0x80;
+ k = 0;
+ ptr++;
+ }
+ memcpy(crcin, crcout, 5);
+ }
+ crc = 0;
+ if(crcin[4])
+ crc |= 0x10;
+ if(crcin[3])
+ crc |= 0x08;
+ if(crcin[2])
+ crc |= 0x04;
+ if(crcin[1])
+ crc |= 0x02;
+ if(crcin[0])
+ crc |= 0x01;
+ return crc;
+}
+
+static unsigned char anu_freq_table[] = {
+ 0x05, // 150
+ 0x06,
+ 0x07, // 200 == default
+ 0x08,
+ 0x09,
+ 0x0a,
+ 0x0b, // 300
+ 0x4c,
+ 0x4d,
+ 0x4e,
+ 0x4f, // 400
+ 0x50,
+ 0x51,
+ 0x52,
+ 0x53 // 500
+};
+
+#define ANU_FREQTODATA(freq) (anu_freq_table[(freq - 150) / 25])
+
+static bool set_anu_freq(struct cgpu_info *icarus, struct ICARUS_INFO *info)
+{
+ unsigned char cmd_buf[4], rdreg_buf[4];
+ int amount, err;
+ char buf[512];
+
+ memset(cmd_buf, 0, 4);
+ memset(rdreg_buf, 0, 4);
+ cmd_buf[0] = 2 | 0x80;
+ cmd_buf[1] = ANU_FREQTODATA(opt_anu_freq); //16-23
+ cmd_buf[2] = 0x81; //8-15
+ cmd_buf[3] = crc5(cmd_buf, 27);
+
+ rdreg_buf[0] = 4 | 0x80;
+ rdreg_buf[1] = 0; //16-23
+ rdreg_buf[2] = 0x04; //8-15
+ rdreg_buf[3] = crc5(rdreg_buf, 27);
+
+ applog(LOG_DEBUG, "%s%i: Send frequency %02x%02x%02x%02x", icarus->drv->name, icarus->device_id,
+ cmd_buf[0], cmd_buf[1], cmd_buf[2], cmd_buf[3]);
+ err = usb_write_ii(icarus, info->intinfo, (char *)cmd_buf, 4, &amount, C_ANU_SEND_CMD);
+ if (err != LIBUSB_SUCCESS || amount != 4) {
+ applog(LOG_ERR, "%s%i: Write freq Comms error (werr=%d amount=%d)",
+ icarus->drv->name, icarus->device_id, err, amount);
+ return false;
+ }
+ err = usb_read_ii_timeout(icarus, info->intinfo, buf, 512, &amount, 100, C_GETRESULTS);
+ if (err < 0 && err != LIBUSB_ERROR_TIMEOUT) {
+ applog(LOG_ERR, "%s%i: Read freq Comms error (rerr=%d amount=%d)",
+ icarus->drv->name, icarus->device_id, err, amount);
+ return false;
+ }
+
+ applog(LOG_DEBUG, "%s%i: Send freq getstatus %02x%02x%02x%02x", icarus->drv->name, icarus->device_id,
+ rdreg_buf[0], rdreg_buf[1], rdreg_buf[2], rdreg_buf[3]);
+ err = usb_write_ii(icarus, info->intinfo, (char *)cmd_buf, 4, &amount, C_ANU_SEND_RDREG);
+ if (err != LIBUSB_SUCCESS || amount != 4) {
+ applog(LOG_ERR, "%s%i: Write freq Comms error (werr=%d amount=%d)",
+ icarus->drv->name, icarus->device_id, err, amount);
+ return false;
+ }
+ err = usb_read_ii_timeout(icarus, info->intinfo, buf, 512, &amount, 100, C_GETRESULTS);
+ if (err < 0 && err != LIBUSB_ERROR_TIMEOUT) {
+ applog(LOG_ERR, "%s%i: Read freq Comms error (rerr=%d amount=%d)",
+ icarus->drv->name, icarus->device_id, err, amount);
+ return false;
+ }
+
+ return true;
+}
+
static struct cgpu_info *icarus_detect_one(struct libusb_device *dev, struct usb_find_devices *found)
{
int this_option_offset = ++option_offset;
@@ -820,6 +936,7 @@ static struct cgpu_info *icarus_detect_one(struct libusb_device *dev, struct usb
int ret, err, amount, tries, i;
bool ok;
bool cmr2_ok[CAIRNSMORE2_INTS];
+ bool anu_freqset = false;
int cmr2_count;
if ((sizeof(workdata) << 1) != (sizeof(golden_ob) - 1))
@@ -877,6 +994,12 @@ cmr2_retry:
while (!ok && tries-- > 0) {
icarus_initialise(icarus, baud);
+ if (info->ident == IDENT_ANU && !set_anu_freq(icarus, info)) {
+ applog(LOG_WARNING, "%s %i: Failed to set frequency, too much overclock?",
+ icarus->drv->name, icarus->device_id);
+ continue;
+ }
+
err = usb_write_ii(icarus, info->intinfo,
(char *)(&workdata), sizeof(workdata), &amount, C_SENDWORK);
@@ -888,9 +1011,9 @@ cmr2_retry:
if (ret != ICA_NONCE_OK)
continue;
- if (unlikely(info->nonce_size == ICARUS_READ_SIZE && usb_buffer_size(icarus) == 1)) {
+ if (info->nonce_size == ICARUS_READ_SIZE && usb_buffer_size(icarus) == 1) {
usb_buffer_clear(icarus);
- icarus->usbdev->ident = IDENT_ANU;
+ icarus->usbdev->ident = info->ident = IDENT_ANU;
info->nonce_size = ANT_READ_SIZE;
info->Hs = ANTMINERUSB_HASH_TIME;
icarus->drv->name = "ANU";
@@ -899,9 +1022,12 @@ cmr2_retry:
}
nonce_hex = bin2hex(nonce_bin, sizeof(nonce_bin));
- if (strncmp(nonce_hex, golden_nonce, 8) == 0)
- ok = true;
- else {
+ if (strncmp(nonce_hex, golden_nonce, 8) == 0) {
+ if (info->ident == IDENT_ANU && !anu_freqset)
+ anu_freqset = true;
+ else
+ ok = true;
+ } else {
if (tries < 0 && info->ident != IDENT_CMR2) {
applog(LOG_ERR,
"Icarus Detect: "
diff --git a/usbutils.h b/usbutils.h
index 60e2209..a9ee127 100644
--- a/usbutils.h
+++ b/usbutils.h
@@ -327,6 +327,8 @@ struct cg_usb_info {
USB_ADD_COMMAND(C_GET_AVALON_RESET, "GetAvalonReset") \
USB_ADD_COMMAND(C_FTDI_STATUS, "FTDIStatus") \
USB_ADD_COMMAND(C_ENABLE_UART, "EnableUART") \
+ USB_ADD_COMMAND(C_ANU_SEND_CMD, "ANUSendcmd") \
+ USB_ADD_COMMAND(C_ANU_SEND_RDREG, "ANUSendrdreg") \
USB_ADD_COMMAND(C_BB_SET_VOLTAGE, "SetCoreVoltage") \
USB_ADD_COMMAND(C_BB_GET_VOLTAGE, "GetCoreVoltage") \
USB_ADD_COMMAND(C_BF_RESET, "BFReset") \