|
@@ -31,6 +31,7 @@
|
|
|
#include <string.h>
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "miner.h"
|
|
#include "miner.h"
|
|
|
|
|
+#include "tm_i2c.h"
|
|
|
#include "libbitfury.h"
|
|
#include "libbitfury.h"
|
|
|
|
|
|
|
|
#include "spidevc.h"
|
|
#include "spidevc.h"
|
|
@@ -50,6 +51,8 @@
|
|
|
unsigned char enaconf[4] = { 0xc1, 0x6a, 0x59, 0xe3 };
|
|
unsigned char enaconf[4] = { 0xc1, 0x6a, 0x59, 0xe3 };
|
|
|
unsigned char disconf[4] = { 0, 0, 0, 0 };
|
|
unsigned char disconf[4] = { 0, 0, 0, 0 };
|
|
|
|
|
|
|
|
|
|
+unsigned decnonce(unsigned in);
|
|
|
|
|
+
|
|
|
/* Configuration registers - control oscillators and such stuff. PROGRAMMED when magic number is matches, UNPROGRAMMED (default) otherwise */
|
|
/* Configuration registers - control oscillators and such stuff. PROGRAMMED when magic number is matches, UNPROGRAMMED (default) otherwise */
|
|
|
void config_reg(int cfgreg, int ena)
|
|
void config_reg(int cfgreg, int ena)
|
|
|
{
|
|
{
|
|
@@ -75,7 +78,6 @@ char outbuf[16];
|
|
|
/* Thermal runaway in this case could produce nice flames of chippy fries */
|
|
/* Thermal runaway in this case could produce nice flames of chippy fries */
|
|
|
|
|
|
|
|
// Thermometer code from left to right - more ones ==> faster clock!
|
|
// Thermometer code from left to right - more ones ==> faster clock!
|
|
|
-unsigned char osc6[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00 };
|
|
|
|
|
|
|
|
|
|
/* Test vectors to calculate (using address-translated loads) */
|
|
/* Test vectors to calculate (using address-translated loads) */
|
|
|
unsigned atrvec[] = {
|
|
unsigned atrvec[] = {
|
|
@@ -121,6 +123,41 @@ static const unsigned SHA_K[64] = {
|
|
|
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
|
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+void t_print(struct timespec d_time) {
|
|
|
|
|
+ printf(" %ds %.2fms\n", (int)d_time.tv_sec, (double)d_time.tv_nsec / 1000000.0);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+struct timespec t_add(struct timespec time1, struct timespec time2) {
|
|
|
|
|
+ struct timespec result ;
|
|
|
|
|
+
|
|
|
|
|
+ result.tv_sec = time1.tv_sec + time2.tv_sec ;
|
|
|
|
|
+ result.tv_nsec = time1.tv_nsec + time2.tv_nsec ;
|
|
|
|
|
+ if (result.tv_nsec >= 1000000000L) {
|
|
|
|
|
+ result.tv_sec++ ; result.tv_nsec = result.tv_nsec - 1000000000L ;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return (result) ;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+struct timespec t_diff(struct timespec start, struct timespec end)
|
|
|
|
|
+{
|
|
|
|
|
+ struct timespec temp;
|
|
|
|
|
+ if (end.tv_nsec < start.tv_nsec) {
|
|
|
|
|
+ temp.tv_sec = end.tv_sec-start.tv_sec-1;
|
|
|
|
|
+ temp.tv_nsec = 1000000000LU;
|
|
|
|
|
+ temp.tv_nsec -= start.tv_nsec;
|
|
|
|
|
+ temp.tv_nsec += end.tv_nsec;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ temp.tv_sec = end.tv_sec-start.tv_sec;
|
|
|
|
|
+ temp.tv_nsec = end.tv_nsec-start.tv_nsec;
|
|
|
|
|
+ }
|
|
|
|
|
+ return temp;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
void ms3_compute(unsigned *p)
|
|
void ms3_compute(unsigned *p)
|
|
|
{
|
|
{
|
|
|
unsigned a,b,c,d,e,f,g,h, ne, na, i;
|
|
unsigned a,b,c,d,e,f,g,h, ne, na, i;
|
|
@@ -137,10 +174,102 @@ void ms3_compute(unsigned *p)
|
|
|
p[15] = a; p[14] = b; p[13] = c; p[12] = d; p[11] = e; p[10] = f; p[9] = g; p[8] = h;
|
|
p[15] = a; p[14] = b; p[13] = c; p[12] = d; p[11] = e; p[10] = f; p[9] = g; p[8] = h;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-int detect_chip(int chip_n) {
|
|
|
|
|
|
|
+void send_conf() {
|
|
|
|
|
+ config_reg(7,0); config_reg(8,0); config_reg(9,0); config_reg(10,0); config_reg(11,0);
|
|
|
|
|
+ config_reg(6,0); /* disable OUTSLK */
|
|
|
|
|
+ config_reg(4,1); /* Enable slow oscillator */
|
|
|
|
|
+ config_reg(1,0); config_reg(2,0); config_reg(3,0);
|
|
|
|
|
+ spi_emit_data(0x0100, (void*)counters, 16); /* Program counters correctly for rounds processing, here baby should start consuming power */
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void send_init() {
|
|
|
|
|
+ /* Prepare internal buffers */
|
|
|
|
|
+ /* PREPARE BUFFERS (INITIAL PROGRAMMING) */
|
|
|
unsigned w[16];
|
|
unsigned w[16];
|
|
|
|
|
+ unsigned atrvec[] = {
|
|
|
|
|
+ 0xb0e72d8e, 0x1dc5b862, 0xe9e7c4a6, 0x3050f1f5, 0x8a1a6b7e, 0x7ec384e8, 0x42c1c3fc, 0x8ed158a1, /* MIDSTATE */
|
|
|
|
|
+ 0,0,0,0,0,0,0,0,
|
|
|
|
|
+ 0x8a0bb7b7, 0x33af304f, 0x0b290c1a, 0xf0c4e61f, /* WDATA: hashMerleRoot[7], nTime, nBits, nNonce */
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ ms3_compute(&atrvec[0]);
|
|
|
|
|
+ memset(&w, 0, sizeof(w)); w[3] = 0xffffffff; w[4] = 0x80000000; w[15] = 0x00000280;
|
|
|
|
|
+ spi_emit_data(0x1000, (void*)w, 16*4);
|
|
|
|
|
+ spi_emit_data(0x1400, (void*)w, 8*4);
|
|
|
|
|
+ memset(w, 0, sizeof(w)); w[0] = 0x80000000; w[7] = 0x100;
|
|
|
|
|
+ spi_emit_data(0x1900, (void*)&w[0],8*4); /* Prepare MS and W buffers! */
|
|
|
|
|
+ spi_emit_data(0x3000, (void*)&atrvec[0], 19*4);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void set_freq(int bits) {
|
|
|
|
|
+ uint64_t freq;
|
|
|
|
|
+ unsigned char *osc6;
|
|
|
|
|
+ int i;
|
|
|
|
|
+
|
|
|
|
|
+ osc6 = (unsigned char *)&freq;
|
|
|
|
|
+ freq = (1ULL << bits) - 1ULL;
|
|
|
|
|
+
|
|
|
|
|
+ spi_emit_data(0x6000, (void*)osc6, 8); /* Program internal on-die slow oscillator frequency */
|
|
|
|
|
+ config_reg(4,1); /* Enable slow oscillator */
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void send_reinit(int slot, int chip_n, int n) {
|
|
|
|
|
+ spi_clear_buf();
|
|
|
|
|
+ spi_emit_break();
|
|
|
|
|
+ spi_emit_fasync(chip_n);
|
|
|
|
|
+ set_freq(n);
|
|
|
|
|
+ send_conf();
|
|
|
|
|
+ send_init();
|
|
|
|
|
+ tm_i2c_set_oe(slot);
|
|
|
|
|
+ spi_txrx(spi_gettxbuf(), spi_getrxbuf(), spi_getbufsz());
|
|
|
|
|
+ tm_i2c_clear_oe(slot);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void send_shutdown(int slot, int chip_n) {
|
|
|
|
|
+ spi_clear_buf();
|
|
|
|
|
+ spi_emit_break();
|
|
|
|
|
+ spi_emit_fasync(chip_n);
|
|
|
|
|
+ config_reg(4,0); /* Disable slow oscillator */
|
|
|
|
|
+ tm_i2c_set_oe(slot);
|
|
|
|
|
+ spi_txrx(spi_gettxbuf(), spi_getrxbuf(), spi_getbufsz());
|
|
|
|
|
+ tm_i2c_clear_oe(slot);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void send_freq(int slot, int chip_n, int bits) {
|
|
|
|
|
+ spi_clear_buf();
|
|
|
|
|
+ spi_emit_break();
|
|
|
|
|
+ spi_emit_fasync(chip_n);
|
|
|
|
|
+ set_freq(bits);
|
|
|
|
|
+ tm_i2c_set_oe(slot);
|
|
|
|
|
+ spi_txrx(spi_gettxbuf(), spi_getrxbuf(), spi_getbufsz());
|
|
|
|
|
+ tm_i2c_clear_oe(slot);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+unsigned int c_diff(unsigned ocounter, unsigned counter) {
|
|
|
|
|
+ return counter > ocounter ? counter - ocounter : (0x003FFFFF - ocounter) + counter;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+int get_counter(unsigned int *newbuf, unsigned int *oldbuf) {
|
|
|
|
|
+ int j;
|
|
|
|
|
+ unsigned counter;
|
|
|
|
|
+ for(j = 0; j < 16; j++) {
|
|
|
|
|
+ if (newbuf[j] != oldbuf[j]) {
|
|
|
|
|
+ int counter = decnonce(newbuf[j]);
|
|
|
|
|
+ if ((counter & 0xFFC00000) == 0xdf800000) {
|
|
|
|
|
+ counter -= 0xdf800000;
|
|
|
|
|
+ return counter;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+int detect_chip(int chip_n) {
|
|
|
int i;
|
|
int i;
|
|
|
unsigned newbuf[17], oldbuf[17];
|
|
unsigned newbuf[17], oldbuf[17];
|
|
|
|
|
+ unsigned ocounter;
|
|
|
|
|
+ int odiff;
|
|
|
|
|
+ struct timespec t1, t2, td;
|
|
|
|
|
|
|
|
memset(newbuf, 0, 17 * 4);
|
|
memset(newbuf, 0, 17 * 4);
|
|
|
memset(oldbuf, 0, 17 * 4);
|
|
memset(oldbuf, 0, 17 * 4);
|
|
@@ -154,54 +283,97 @@ int detect_chip(int chip_n) {
|
|
|
spi_clear_buf();
|
|
spi_clear_buf();
|
|
|
spi_emit_break(); /* First we want to break chain! Otherwise we'll get all of traffic bounced to output */
|
|
spi_emit_break(); /* First we want to break chain! Otherwise we'll get all of traffic bounced to output */
|
|
|
spi_emit_fasync(chip_n);
|
|
spi_emit_fasync(chip_n);
|
|
|
- spi_emit_data(0x6000, (void*)osc6, 8); /* Program internal on-die slow oscillator frequency */
|
|
|
|
|
- config_reg(7,0); config_reg(8,0); config_reg(9,0); config_reg(10,0); config_reg(11,0);
|
|
|
|
|
- config_reg(6,1);
|
|
|
|
|
- config_reg(4,1); /* Enable slow oscillator */
|
|
|
|
|
- config_reg(1,0); config_reg(2,0); config_reg(3,0);
|
|
|
|
|
- spi_emit_data(0x0100, (void*)counters, 16); /* Program counters correctly for rounds processing, here baby should start consuming power */
|
|
|
|
|
-
|
|
|
|
|
- /* Prepare internal buffers */
|
|
|
|
|
- /* PREPARE BUFFERS (INITIAL PROGRAMMING) */
|
|
|
|
|
- memset(&w, 0, sizeof(w)); w[3] = 0xffffffff; w[4] = 0x80000000; w[15] = 0x00000280;
|
|
|
|
|
- spi_emit_data(0x1000, (void*)w, 16*4);
|
|
|
|
|
- spi_emit_data(0x1400, (void*)w, 8*4);
|
|
|
|
|
- memset(w, 0, sizeof(w)); w[0] = 0x80000000; w[7] = 0x100;
|
|
|
|
|
- spi_emit_data(0x1900, (void*)&w[0],8*4); /* Prepare MS and W buffers! */
|
|
|
|
|
-
|
|
|
|
|
- spi_emit_data(0x3000, (void*)&atrvec[0], 19*4);
|
|
|
|
|
|
|
+ set_freq(52); //54 - 3F, 53 - 1F
|
|
|
|
|
+ send_conf();
|
|
|
|
|
+ send_init();
|
|
|
spi_txrx(spi_gettxbuf(), spi_getrxbuf(), spi_getbufsz());
|
|
spi_txrx(spi_gettxbuf(), spi_getrxbuf(), spi_getbufsz());
|
|
|
|
|
|
|
|
|
|
+ ocounter = 0;
|
|
|
for (i = 0; i < BITFURY_DETECT_TRIES; i++) {
|
|
for (i = 0; i < BITFURY_DETECT_TRIES; i++) {
|
|
|
|
|
+ int j;
|
|
|
|
|
+ int counter;
|
|
|
|
|
+
|
|
|
spi_clear_buf();
|
|
spi_clear_buf();
|
|
|
spi_emit_break();
|
|
spi_emit_break();
|
|
|
spi_emit_fasync(chip_n);
|
|
spi_emit_fasync(chip_n);
|
|
|
spi_emit_data(0x3000, (void*)&atrvec[0], 19*4);
|
|
spi_emit_data(0x3000, (void*)&atrvec[0], 19*4);
|
|
|
spi_txrx(spi_gettxbuf(), spi_getrxbuf(), spi_getbufsz());
|
|
spi_txrx(spi_gettxbuf(), spi_getrxbuf(), spi_getbufsz());
|
|
|
memcpy(newbuf, spi_getrxbuf() + 4 + chip_n, 17*4);
|
|
memcpy(newbuf, spi_getrxbuf() + 4 + chip_n, 17*4);
|
|
|
|
|
+
|
|
|
|
|
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t1);
|
|
|
|
|
+ counter = get_counter(newbuf, oldbuf);
|
|
|
|
|
+ if (ocounter) {
|
|
|
|
|
+ unsigned int cdiff = c_diff(ocounter, counter);
|
|
|
|
|
+ unsigned per_ms;
|
|
|
|
|
+
|
|
|
|
|
+ td = t_diff(t2, t1);
|
|
|
|
|
+ per_ms = cdiff / (td.tv_nsec / 1000);
|
|
|
|
|
+ if (cdiff > 5000 && cdiff < 100000 && odiff > 5000 && odiff < 100000)
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ odiff = cdiff;
|
|
|
|
|
+ }
|
|
|
|
|
+ ocounter = counter;
|
|
|
|
|
+ t2 = t1;
|
|
|
if (newbuf[16] != 0 && newbuf[16] != 0xFFFFFFFF) {
|
|
if (newbuf[16] != 0 && newbuf[16] != 0xFFFFFFFF) {
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
- if (i && newbuf[16] != oldbuf[16])
|
|
|
|
|
- return 1;
|
|
|
|
|
- nmsleep(BITFURY_REFRESH_DELAY);
|
|
|
|
|
|
|
+ nmsleep(BITFURY_REFRESH_DELAY / 10);
|
|
|
memcpy(oldbuf, newbuf, 17 * 4);
|
|
memcpy(oldbuf, newbuf, 17 * 4);
|
|
|
}
|
|
}
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-int libbitfury_detectChips(void) {
|
|
|
|
|
|
|
+int libbitfury_detectChips(struct bitfury_device *devices) {
|
|
|
int n = 0;
|
|
int n = 0;
|
|
|
- int detected;
|
|
|
|
|
- do {
|
|
|
|
|
- detected = detect_chip(n);
|
|
|
|
|
- if (detected) {
|
|
|
|
|
- n++;
|
|
|
|
|
- applog(LOG_WARNING, "BITFURY chip #%d detected", n);
|
|
|
|
|
- } else {
|
|
|
|
|
|
|
+ int i;
|
|
|
|
|
+ static slot_on[32];
|
|
|
|
|
+ struct timespec t1, t2;
|
|
|
|
|
+
|
|
|
|
|
+ if (tm_i2c_init() < 0) {
|
|
|
|
|
+ printf("I2C init error\n");
|
|
|
|
|
+ return(1);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t1);
|
|
|
|
|
+ for (i = 0; i < 32; i++) {
|
|
|
|
|
+ int slot_detected = tm_i2c_detect(i) != -1;
|
|
|
|
|
+ slot_on[i] = slot_detected;
|
|
|
|
|
+ tm_i2c_clear_oe(i);
|
|
|
|
|
+ nmsleep(1);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ for (i = 0; i < 32; i++) {
|
|
|
|
|
+ if (slot_on[i]) {
|
|
|
|
|
+ int chip_n = 0;
|
|
|
|
|
+ int chip_detected;
|
|
|
|
|
+ tm_i2c_set_oe(i);
|
|
|
|
|
+ do {
|
|
|
|
|
+ chip_detected = detect_chip(chip_n);
|
|
|
|
|
+ if (chip_detected) {
|
|
|
|
|
+ applog(LOG_WARNING, "BITFURY slot: %d, chip #%d detected", i, n);
|
|
|
|
|
+ devices[n].slot = i;
|
|
|
|
|
+ devices[n].fasync = chip_n;
|
|
|
|
|
+ n++;
|
|
|
|
|
+ chip_n++;
|
|
|
|
|
+ }
|
|
|
|
|
+ } while (chip_detected);
|
|
|
|
|
+ tm_i2c_clear_oe(i);
|
|
|
}
|
|
}
|
|
|
- } while (detected);
|
|
|
|
|
- return n;
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t2);
|
|
|
|
|
+
|
|
|
|
|
+ return n; //!!!
|
|
|
|
|
+ //return 1;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+int libbitfury_shutdownChips(struct bitfury_device *devices, int chip_n) {
|
|
|
|
|
+ int i;
|
|
|
|
|
+ for (i = 0; i < chip_n; i++) {
|
|
|
|
|
+ send_shutdown(devices[i].slot, devices[i].fasync);
|
|
|
|
|
+ }
|
|
|
|
|
+ tm_i2c_close();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
unsigned decnonce(unsigned in)
|
|
unsigned decnonce(unsigned in)
|
|
@@ -235,9 +407,12 @@ int rehash(unsigned char *midstate, unsigned m7,
|
|
|
unsigned int *mid32 = (unsigned int *)midstate;
|
|
unsigned int *mid32 = (unsigned int *)midstate;
|
|
|
unsigned out32[8];
|
|
unsigned out32[8];
|
|
|
unsigned char *out = (unsigned char *) out32;
|
|
unsigned char *out = (unsigned char *) out32;
|
|
|
|
|
+ static unsigned history[512];
|
|
|
|
|
+ static unsigned history_p;
|
|
|
int i;
|
|
int i;
|
|
|
sha2_context ctx;
|
|
sha2_context ctx;
|
|
|
|
|
|
|
|
|
|
+
|
|
|
memset( &ctx, 0, sizeof( sha2_context ) );
|
|
memset( &ctx, 0, sizeof( sha2_context ) );
|
|
|
memcpy(ctx.state, mid32, 8*4);
|
|
memcpy(ctx.state, mid32, 8*4);
|
|
|
ctx.total[0] = 64;
|
|
ctx.total[0] = 64;
|
|
@@ -256,7 +431,9 @@ int rehash(unsigned char *midstate, unsigned m7,
|
|
|
if (out32[7] == 0) {
|
|
if (out32[7] == 0) {
|
|
|
hex = bin2hex(midstate, 32);
|
|
hex = bin2hex(midstate, 32);
|
|
|
hex = bin2hex(out, 32);
|
|
hex = bin2hex(out, 32);
|
|
|
- applog(LOG_INFO, "! MS0: %08x, m7: %08x, ntime: %08x, nbits: %08x, nnonce: %08x\n\t\t\t out: %s\n", mid32[0], m7, ntime, nbits, nnonce, hex);
|
|
|
|
|
|
|
+// applog(LOG_INFO, "! MS0: %08x, m7: %08x, ntime: %08x, nbits: %08x, nnonce: %08x\n\t\t\t out: %s\n", mid32[0], m7, ntime, nbits, nnonce, hex);
|
|
|
|
|
+// history[history_p] = nnonce;
|
|
|
|
|
+// history_p++; history_p &= 512 - 1;
|
|
|
return 1;
|
|
return 1;
|
|
|
}
|
|
}
|
|
|
return 0;
|
|
return 0;
|
|
@@ -272,63 +449,233 @@ void work_to_payload(struct bitfury_payload *p, struct work *w) {
|
|
|
p->m7 = bswap_32(*(unsigned *)(flipped_data + 64));
|
|
p->m7 = bswap_32(*(unsigned *)(flipped_data + 64));
|
|
|
p->ntime = bswap_32(*(unsigned *)(flipped_data + 68));
|
|
p->ntime = bswap_32(*(unsigned *)(flipped_data + 68));
|
|
|
p->nbits = bswap_32(*(unsigned *)(flipped_data + 72));
|
|
p->nbits = bswap_32(*(unsigned *)(flipped_data + 72));
|
|
|
- applog(LOG_INFO, "INFO nonc: %08x bitfury_scanHash MS0: %08x, ", p->nnonce, ((unsigned int *)w->midstate)[0]);
|
|
|
|
|
- applog(LOG_INFO, "INFO merkle[7]: %08x, ntime: %08x, nbits: %08x", p->m7, p->ntime, p->nbits);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int libbitfury_sendHashData(struct bitfury_device *bf, int chip_n) {
|
|
int libbitfury_sendHashData(struct bitfury_device *bf, int chip_n) {
|
|
|
- int chip;
|
|
|
|
|
|
|
+ int chip_id;
|
|
|
static unsigned second_run;
|
|
static unsigned second_run;
|
|
|
|
|
|
|
|
- for (chip = 0; chip < chip_n; chip++) {
|
|
|
|
|
|
|
+ for (chip_id = 0; chip_id < chip_n; chip_id++) {
|
|
|
unsigned char *hexstr;
|
|
unsigned char *hexstr;
|
|
|
- struct bitfury_device *d = bf + chip;
|
|
|
|
|
|
|
+ struct bitfury_device *d = bf + chip_id;
|
|
|
unsigned *newbuf = d->newbuf;
|
|
unsigned *newbuf = d->newbuf;
|
|
|
unsigned *oldbuf = d->oldbuf;
|
|
unsigned *oldbuf = d->oldbuf;
|
|
|
struct bitfury_payload *p = &(d->payload);
|
|
struct bitfury_payload *p = &(d->payload);
|
|
|
struct bitfury_payload *op = &(d->opayload);
|
|
struct bitfury_payload *op = &(d->opayload);
|
|
|
|
|
+ struct bitfury_payload *o2p = &(d->o2payload);
|
|
|
|
|
+ struct timespec d_time;
|
|
|
|
|
+ struct timespec time;
|
|
|
|
|
+ int smart = 0;
|
|
|
|
|
+ int i;
|
|
|
|
|
+ int chip = d->fasync;
|
|
|
|
|
+ int slot = d->slot;
|
|
|
|
|
|
|
|
-
|
|
|
|
|
- /* Programming next value */
|
|
|
|
|
memcpy(atrvec, p, 20*4);
|
|
memcpy(atrvec, p, 20*4);
|
|
|
ms3_compute(atrvec);
|
|
ms3_compute(atrvec);
|
|
|
|
|
|
|
|
- spi_clear_buf(); spi_emit_break();
|
|
|
|
|
- spi_emit_fasync(chip);
|
|
|
|
|
- spi_emit_data(0x3000, (void*)&atrvec[0], 19*4);
|
|
|
|
|
- spi_txrx(spi_gettxbuf(), spi_getrxbuf(), spi_getbufsz());
|
|
|
|
|
-
|
|
|
|
|
- memcpy(newbuf, spi_getrxbuf()+4 + chip, 17*4);
|
|
|
|
|
|
|
+ clock_gettime(CLOCK_REALTIME, &(time));
|
|
|
|
|
+
|
|
|
|
|
+ if (!second_run) {
|
|
|
|
|
+ d->predict2 = d->predict1 = time;
|
|
|
|
|
+ d->counter1 = d->counter2 = 0;
|
|
|
|
|
+ d->req2_done = 0;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ d_time = t_diff(time, d->predict1);
|
|
|
|
|
+ if (d_time.tv_sec < 0 && (d->req2_done || !smart)) {
|
|
|
|
|
+ d->otimer1 = d->timer1;
|
|
|
|
|
+ d->timer1 = time;
|
|
|
|
|
+ /* Programming next value */
|
|
|
|
|
+ spi_clear_buf(); spi_emit_break();
|
|
|
|
|
+ spi_emit_fasync(chip);
|
|
|
|
|
+ spi_emit_data(0x3000, (void*)&atrvec[0], 19*4);
|
|
|
|
|
+ if (smart) {
|
|
|
|
|
+ config_reg(3,0);
|
|
|
|
|
+ }
|
|
|
|
|
+ tm_i2c_set_oe(slot);
|
|
|
|
|
+ clock_gettime(CLOCK_REALTIME, &(time));
|
|
|
|
|
+ d_time = t_diff(time, d->predict1);
|
|
|
|
|
+ spi_txrx(spi_gettxbuf(), spi_getrxbuf(), spi_getbufsz());
|
|
|
|
|
+ tm_i2c_clear_oe(slot);
|
|
|
|
|
+ memcpy(newbuf, spi_getrxbuf()+4 + chip, 17*4);
|
|
|
|
|
|
|
|
- d->job_switched = newbuf[16] != oldbuf[16];
|
|
|
|
|
|
|
+ d->job_switched = newbuf[16] != oldbuf[16];
|
|
|
|
|
|
|
|
- if (second_run && d->job_switched) {
|
|
|
|
|
int i;
|
|
int i;
|
|
|
int results_num = 0;
|
|
int results_num = 0;
|
|
|
|
|
+ int found = 0;
|
|
|
unsigned * results = d->results;
|
|
unsigned * results = d->results;
|
|
|
|
|
+
|
|
|
|
|
+ d->old_nonce = 0;
|
|
|
|
|
+ d->future_nonce = 0;
|
|
|
for (i = 0; i < 16; i++) {
|
|
for (i = 0; i < 16; i++) {
|
|
|
- if (oldbuf[i] != newbuf[i]) {
|
|
|
|
|
|
|
+ if (oldbuf[i] != newbuf[i] && op && o2p) {
|
|
|
unsigned pn; //possible nonce
|
|
unsigned pn; //possible nonce
|
|
|
unsigned int s = 0; //TODO zero may be solution
|
|
unsigned int s = 0; //TODO zero may be solution
|
|
|
|
|
+ unsigned int old_f = 0;
|
|
|
|
|
+ if ((newbuf[i] & 0xFF) == 0xE0)
|
|
|
|
|
+ continue;
|
|
|
pn = decnonce(newbuf[i]);
|
|
pn = decnonce(newbuf[i]);
|
|
|
s |= rehash(op->midstate, op->m7, op->ntime, op->nbits, pn) ? pn : 0;
|
|
s |= rehash(op->midstate, op->m7, op->ntime, op->nbits, pn) ? pn : 0;
|
|
|
- s |= rehash(op->midstate, op->m7, op->ntime, op->nbits, pn-0x400000) ? pn - 0x400000 : 0;
|
|
|
|
|
- s |= rehash(op->midstate, op->m7, op->ntime, op->nbits, pn-0x800000) ? pn - 0x800000 : 0;
|
|
|
|
|
- s |= rehash(op->midstate, op->m7, op->ntime, op->nbits, pn+0x2800000)? pn + 0x2800000 : 0;
|
|
|
|
|
- s |= rehash(op->midstate, op->m7, op->ntime, op->nbits, pn+0x2C00000)? pn + 0x2C00000 : 0;
|
|
|
|
|
- s |= rehash(op->midstate, op->m7, op->ntime, op->nbits, pn+0x400000) ? pn + 0x400000 : 0;
|
|
|
|
|
|
|
+ s |= rehash(op->midstate, op->m7, op->ntime, op->nbits, pn-0x00400000) ? pn - 0x00400000 : 0;
|
|
|
|
|
+ s |= rehash(op->midstate, op->m7, op->ntime, op->nbits, pn-0x00800000) ? pn - 0x00800000 : 0;
|
|
|
|
|
+ s |= rehash(op->midstate, op->m7, op->ntime, op->nbits, pn+0x02800000) ? pn + 0x02800000 : 0;
|
|
|
|
|
+ s |= rehash(op->midstate, op->m7, op->ntime, op->nbits, pn+0x02C00000) ? pn + 0x02C00000 : 0;
|
|
|
|
|
+ s |= rehash(op->midstate, op->m7, op->ntime, op->nbits, pn+0x00400000) ? pn + 0x00400000 : 0;
|
|
|
|
|
+ if (s) {
|
|
|
|
|
+ int k;
|
|
|
|
|
+ int dup = 0;
|
|
|
|
|
+ for (k = 0; k < results_num; k++) {
|
|
|
|
|
+ if (results[k] == bswap_32(s)) {
|
|
|
|
|
+ dup = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!dup) {
|
|
|
|
|
+ results[results_num++] = bswap_32(s);
|
|
|
|
|
+ found++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ s = 0;
|
|
|
|
|
+ pn = decnonce(newbuf[i]);
|
|
|
|
|
+ s |= rehash(o2p->midstate, o2p->m7, o2p->ntime, o2p->nbits, pn) ? pn : 0;
|
|
|
|
|
+ s |= rehash(o2p->midstate, o2p->m7, o2p->ntime, o2p->nbits, pn-0x400000) ? pn - 0x400000 : 0;
|
|
|
|
|
+ s |= rehash(o2p->midstate, o2p->m7, o2p->ntime, o2p->nbits, pn-0x800000) ? pn - 0x800000 : 0;
|
|
|
|
|
+ s |= rehash(o2p->midstate, o2p->m7, o2p->ntime, o2p->nbits, pn+0x2800000)? pn + 0x2800000 : 0;
|
|
|
|
|
+ s |= rehash(o2p->midstate, o2p->m7, o2p->ntime, o2p->nbits, pn+0x2C00000)? pn + 0x2C00000 : 0;
|
|
|
|
|
+ s |= rehash(o2p->midstate, o2p->m7, o2p->ntime, o2p->nbits, pn+0x400000) ? pn + 0x400000 : 0;
|
|
|
if (s) {
|
|
if (s) {
|
|
|
- results[results_num++] = bswap_32(s);
|
|
|
|
|
|
|
+ d->old_nonce = bswap_32(s);
|
|
|
|
|
+ found++;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ s = 0;
|
|
|
|
|
+ pn = decnonce(newbuf[i]);
|
|
|
|
|
+ s |= rehash(p->midstate, p->m7, p->ntime, p->nbits, pn) ? pn : 0;
|
|
|
|
|
+ s |= rehash(p->midstate, p->m7, p->ntime, p->nbits, pn-0x400000) ? pn - 0x400000 : 0;
|
|
|
|
|
+ s |= rehash(p->midstate, p->m7, p->ntime, p->nbits, pn-0x800000) ? pn - 0x800000 : 0;
|
|
|
|
|
+ s |= rehash(p->midstate, p->m7, p->ntime, p->nbits, pn+0x2800000)? pn + 0x2800000 : 0;
|
|
|
|
|
+ s |= rehash(p->midstate, p->m7, p->ntime, p->nbits, pn+0x2C00000)? pn + 0x2C00000 : 0;
|
|
|
|
|
+ s |= rehash(p->midstate, p->m7, p->ntime, p->nbits, pn+0x400000) ? pn + 0x400000 : 0;
|
|
|
|
|
+ if (s) {
|
|
|
|
|
+ d->future_nonce = bswap_32(s);
|
|
|
|
|
+ found++;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!found) {
|
|
|
|
|
+ printf("AAA Strange: %08x, chip_id: %d\n", pn, chip_id);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
d->results_n = results_num;
|
|
d->results_n = results_num;
|
|
|
|
|
|
|
|
- memcpy(op, p, sizeof(struct bitfury_payload));
|
|
|
|
|
- memcpy(oldbuf, newbuf, 17 * 4);
|
|
|
|
|
|
|
+ if (smart) {
|
|
|
|
|
+ d_time = t_diff(d->timer2, d->timer1);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ d_time = t_diff(d->otimer1, d->timer1);
|
|
|
|
|
+ }
|
|
|
|
|
+ d->ocounter1 = d->counter1;
|
|
|
|
|
+ d->counter1 = get_counter(newbuf, oldbuf);
|
|
|
|
|
+ if (d->counter2 || !smart) {
|
|
|
|
|
+ int shift;
|
|
|
|
|
+ int cycles;
|
|
|
|
|
+ int req1_cycles;
|
|
|
|
|
+ long long unsigned int period;
|
|
|
|
|
+ double ns;
|
|
|
|
|
+ unsigned full_cycles, half_cycles;
|
|
|
|
|
+ double full_delay, half_delay;
|
|
|
|
|
+ long long unsigned delta;
|
|
|
|
|
+ struct timespec t_delta;
|
|
|
|
|
+ double mhz;
|
|
|
|
|
+ int ccase;
|
|
|
|
|
+
|
|
|
|
|
+ shift = 800000;
|
|
|
|
|
+ if (smart) {
|
|
|
|
|
+ cycles = d->counter1 < d->counter2 ? 0x00400000 - d->counter2 + d->counter1 : d->counter1 - d->counter2; // + 0x003FFFFF;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if (d->counter1 > (0x00400000 - shift * 2) && d->ocounter1 > (0x00400000 - shift)) {
|
|
|
|
|
+ cycles = 0x00400000 - d->ocounter1 + d->counter1; // + 0x003FFFFF;
|
|
|
|
|
+ ccase = 1;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ cycles = d->counter1 - d->ocounter1;
|
|
|
|
|
+ ccase = 2;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ req1_cycles = 0x003FFFFF - d->counter1;
|
|
|
|
|
+ period = (long long unsigned int)d_time.tv_sec * 1000000000ULL + (long long unsigned int)d_time.tv_nsec;
|
|
|
|
|
+ ns = (double)period / (double)(cycles);
|
|
|
|
|
+ mhz = 1.0 / ns * 65.0 * 1000.0;
|
|
|
|
|
+
|
|
|
|
|
+ if (d->counter1 > 0 && d->counter1 < 0x001FFFFF)
|
|
|
|
|
+ printf("AAA chip_id %2d: %llu ms, req1_cycles: %08u, counter1: %08d, ocounter1: %08d, counter2: %08d, cycles: %08d, ns: %.2f, mhz: %.2f \n", chip_id, period / 1000000ULL, req1_cycles, d->counter1, d->ocounter1, d->counter2, cycles, ns, mhz);
|
|
|
|
|
+ if (ns > 2000.0 || ns < 20) {
|
|
|
|
|
+ printf("AAA %d!Stupid ns chip_id %2d: %llu ms, req1_cycles: %08u, counter1: %08d, ocounter1: %08d, counter2: %08d, cycles: %08d, ns: %.2f, mhz: %.2f \n", ccase, chip_id, period / 1000000ULL, req1_cycles, d->counter1, d->ocounter1, d->counter2, cycles, ns, mhz);
|
|
|
|
|
+ ns = 200.0;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ d->ns = ns;
|
|
|
|
|
+ d->mhz = mhz;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (smart) {
|
|
|
|
|
+ half_cycles = req1_cycles + shift;
|
|
|
|
|
+ full_cycles = 0x003FFFFF - 2 * shift;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ half_cycles = 0;
|
|
|
|
|
+ full_cycles = req1_cycles > shift ? req1_cycles - shift : req1_cycles + 0x00400000 - shift;
|
|
|
|
|
+ }
|
|
|
|
|
+ half_delay = (double)half_cycles * ns * (1 +0.92);
|
|
|
|
|
+ full_delay = (double)full_cycles * ns;
|
|
|
|
|
+ delta = (long long unsigned)(full_delay + half_delay);
|
|
|
|
|
+ t_delta.tv_sec = delta / 1000000000ULL;
|
|
|
|
|
+ t_delta.tv_nsec = delta - t_delta.tv_sec * 1000000000ULL;
|
|
|
|
|
+ d->predict1 = t_add(time, t_delta);
|
|
|
|
|
+
|
|
|
|
|
+ if (smart) {
|
|
|
|
|
+ half_cycles = req1_cycles + shift;
|
|
|
|
|
+ full_cycles = 0;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ full_cycles = req1_cycles + shift;
|
|
|
|
|
+ }
|
|
|
|
|
+ half_delay = (double)half_cycles * ns * (1 + 0.92);
|
|
|
|
|
+ full_delay = (double)full_cycles * ns;
|
|
|
|
|
+ delta = (long long unsigned)(full_delay + half_delay);
|
|
|
|
|
+
|
|
|
|
|
+ t_delta.tv_sec = delta / 1000000000ULL;
|
|
|
|
|
+ t_delta.tv_nsec = delta - t_delta.tv_sec * 1000000000ULL;
|
|
|
|
|
+ d->predict2 = t_add(time, t_delta);
|
|
|
|
|
+ d->req2_done = 0; d->req1_done = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (d->job_switched) {
|
|
|
|
|
+ memcpy(o2p, op, sizeof(struct bitfury_payload));
|
|
|
|
|
+ memcpy(op, p, sizeof(struct bitfury_payload));
|
|
|
|
|
+ memcpy(oldbuf, newbuf, 17 * 4);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- nmsleep(BITFURY_REFRESH_DELAY);
|
|
|
|
|
|
|
+ clock_gettime(CLOCK_REALTIME, &(time));
|
|
|
|
|
+ d_time = t_diff(time, d->predict2);
|
|
|
|
|
+ if (d_time.tv_sec < 0 && !d->req2_done) {
|
|
|
|
|
+ if(smart) {
|
|
|
|
|
+ d->otimer2 = d->timer2;
|
|
|
|
|
+ d->timer2 = time;
|
|
|
|
|
+ spi_clear_buf();
|
|
|
|
|
+ spi_emit_break();
|
|
|
|
|
+ spi_emit_fasync(chip);
|
|
|
|
|
+ spi_emit_data(0x3000, (void*)&atrvec[0], 19*4);
|
|
|
|
|
+ if (smart) {
|
|
|
|
|
+ config_reg(3,1);
|
|
|
|
|
+ }
|
|
|
|
|
+ tm_i2c_set_oe(slot);
|
|
|
|
|
+ spi_txrx(spi_gettxbuf(), spi_getrxbuf(), spi_getbufsz());
|
|
|
|
|
+ tm_i2c_clear_oe(slot);
|
|
|
|
|
+ memcpy(newbuf, spi_getrxbuf()+4 + chip, 17*4);
|
|
|
|
|
+ d->counter2 = get_counter(newbuf, oldbuf);
|
|
|
|
|
+
|
|
|
|
|
+ d->req2_done = 1;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ d->req2_done = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
second_run = 1;
|
|
second_run = 1;
|
|
|
|
|
|