0% found this document useful (0 votes)
59 views22 pages

bf16 Bitfury16

Uploaded by

alexandr
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
59 views22 pages

bf16 Bitfury16

Uploaded by

alexandr
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 22

#include <arpa/inet.

h>

#include "miner.h"

#include "bf16-bitfury16.h"
#include "bf16-communication.h"
#include "bf16-ctrldevice.h"

#include "math.h"
#include "sha2.h"
#include "driver-bitfury16.h"

//#define FLIP_BITS

bf_cmd_description_t cmd_description[CHIP_CMD_NUM] = {
{
.cmd_code = CHIP_CMD_TASK_STATUS,
.cmd_description = "CHIP_CMD_TASK_STATUS"
},
{
.cmd_code = CHIP_CMD_TASK_WRITE,
.cmd_description = "CHIP_CMD_TASK_WRITE"
},
{
.cmd_code = CHIP_CMD_TASK_SWITCH,
.cmd_description = "CHIP_CMD_TASK_SWITCH"
},
{
.cmd_code = CHIP_CMD_READ_NONCE,
.cmd_description = "CHIP_CMD_READ_NONCE"
},
{
.cmd_code = CHIP_CMD_SET_CLOCK,
.cmd_description = "CHIP_CMD_SET_CLOCK"
},
{
.cmd_code = CHIP_CMD_TOGGLE,
.cmd_description = "CHIP_CMD_TOGGLE"
},
{
.cmd_code = CHIP_CMD_SET_MASK,
.cmd_description = "CHIP_CMD_SET_MASK"
},
{
.cmd_code = CHIP_CMD_CREATE_CHANNEL,
.cmd_description = "CHIP_CMD_CREATE_CHANNEL"
}
};

char* get_cmd_description(bf_cmd_code_t cmd_code)


{
uint8_t i;

for (i = 0; i < CHIP_CMD_NUM; i++)


if (cmd_description[i].cmd_code == cmd_code)
return cmd_description[i].cmd_description;

return NULL;
}
static void shift_bits(uint8_t* data, uint8_t size, uint8_t nbits)
{
uint8_t i;
uint8_t bytes = nbits / 8;
uint8_t bits = nbits % 8;

for (i = 0; i < size; i++) {


data[i] = (data[i + bytes] << bits);
uint8_t minor = (data[i + bytes + 1] >> (8 - bits));
data[i] |= minor;
}
}

static uint8_t extra_bytes(uint8_t depth)


{
return (depth * 3) / 8 + 1;
}

static uint8_t analyze_rx_data(bf_command_t* command, bf_cmd_status_t* cmd_status,


uint32_t* nonces)
{
uint8_t i;
uint8_t res = 0;

if (command->cmd_code & CHIP_CMD_READ_NONCE) {


shift_bits(command->rx, 49 + 2 + extra_bytes(command->depth), command-
>depth * 3);

command->status = command->rx[0];
cmd_status->status = command->rx[0];
command->checksum = command->rx[1];
cmd_status->checksum_expected = command->checksum;

if (nonces == NULL)
return 1;

uint32_t nonce = 0x00000000;

/* fill nonces buffer */


for (i = 0; i <= 48; i++) {
if ((i % 4 == 0) && (i != 0)) {
if ((nonce & 0x0fffffff) != 0x0fffffff)
nonce ^= 0xaaaaaaaa;
nonces[i/4 - 1] = nonce;

if (i == 48)
break;

nonce = 0x00000000;
}

nonce |= (command->rx[i + 2] << 8*(4 - (i%4) - 1));


}

#if 0
char data[128];
memset(data, 0, sizeof(data));
for (i = 0; i < 49 + 2 + extra_bytes(command->depth); i++)
sprintf(data, "%s%02x", data, command->rx[i]);
applog(LOG_DEBUG, "BF16: RX <- [%s]", data);
#endif

for (i = 0; i < 48; i ++)


command->nonce_checksum += command->rx[i + 2];
command->nonce_checksum += command->rx[1];

cmd_status->nonce_checksum_expected = command->nonce_checksum;

if (command->checksum != command->rx[1]) {
command->checksum_error = true;
cmd_status->checksum_error = true;
cmd_status->checksum_received = command->rx[50];
res = 1;
#if 0
applog(LOG_ERR, "Checksum mismatch: received [%02x] expected
[%02x]", command->rx[1], 0x04);
#endif
} else {
command->checksum_error = false;
cmd_status->checksum_error = false;
}

if ((command->nonce_checksum != command->rx[50]) &&


(command->nonce_checksum != command->rx[50] + 1)) {
command->nonce_checksum_error = true;
cmd_status->nonce_checksum_error = true;
cmd_status->nonce_checksum_received = command->rx[50];

res += 2;
#if 0
applog(LOG_ERR, "Nonce checksum mismatch: received [%02x]
expected [%02x]", command->rx[50], checksum);
#endif
} else {
command->nonce_checksum_error = false;
cmd_status->nonce_checksum_error = false;
}
} else {
shift_bits(command->rx, 2 + extra_bytes(command->depth), command->depth
* 3);

if (opt_bf16_test_chip != NULL) {
char data[16];
memset(data, 0, sizeof(data));
for (i = 0; i < 2 + extra_bytes(command->depth); i++)
sprintf(data, "%s%02x", data, command->rx[i]);
applog(LOG_NOTICE, "BF16: RX <- [%s]", data);
}

command->status = command->rx[0];
cmd_status->status = command->rx[0];
uint8_t cmd_checksum = command->rx[1];
cmd_status->checksum_expected = command->checksum;

#if 0
applog(LOG_DEBUG, "Command checksum: [%02x]", cmd_checksum);
applog(LOG_DEBUG, "Command status: [%02x]", command->status);
#endif

if ((command->checksum != cmd_checksum) &&


(command->checksum != cmd_checksum + 1)) {
command->checksum_error = true;
cmd_status->checksum_error = true;
cmd_status->checksum_received = cmd_checksum;
res = 1;

if (opt_bf16_test_chip != NULL) {
applog(LOG_ERR, "BF16: checksum mismatch: received [%02x]
expected [%02x]",
cmd_checksum, command->checksum);
}
} else {
command->checksum_error = false;
cmd_status->checksum_error = false;
}
}

return res;
}

/* SPI BTC250 primitives */


uint8_t create_channel(spi_channel_id_t spi_channel, uint8_t* channel_path, uint8_t
channel_length)
{
int res = 0;

uint8_t* channel_path_buff = cgcalloc(channel_length, sizeof(uint8_t));


cg_memcpy(channel_path_buff, channel_path, channel_length);

res = device_spi_transfer(spi_channel, channel_path_buff, channel_length);

free(channel_path_buff);

return res;
}

uint8_t destroy_channel(spi_channel_id_t spi_channel, uint8_t depth)


{
bf_command_t chip_command;
bf_chip_address_t chip_address = { 0x00, 0x00, 0x0f };

/* send command to 0x0f address */


spi_command_init(&chip_command, depth, chip_address, CHIP_CMD_TASK_SWITCH, 0,
NULL);
return spi_command_exec(spi_channel, &chip_command, NULL);
}

/* SPI BTC16 primitives */


void spi_emit_reset(spi_channel_id_t spi_channel)
{
device_ctrl_transfer(spi_channel, 1, F_RST);

uint8_t data[2] = { 0x00, 0x00 };


device_spi_transfer(spi_channel, data, sizeof(data));

device_ctrl_transfer(spi_channel, 0, F_RST);
}

uint8_t send_toggle(spi_channel_id_t spi_channel, uint8_t depth, bf_chip_address_t


chip_address)
{
bf_command_t chip_command;
uint8_t toggle[4] = { 0xa5, 0x00, 0x00, 0x02 };

spi_command_init(&chip_command, depth, chip_address, CHIP_CMD_TOGGLE, 3,


toggle);
return spi_command_exec(spi_channel, &chip_command, NULL);
}

uint8_t set_clock(spi_channel_id_t spi_channel, uint8_t depth,


bf_chip_address_t chip_address, uint8_t clock)
{
bf_command_t chip_command;
uint8_t clock_buf[4];

memset(clock_buf, 0, 4);
gen_clock_data(clock, 1, clock_buf);
spi_command_init(&chip_command, depth, chip_address, CHIP_CMD_SET_CLOCK, 3,
clock_buf);
return spi_command_exec(spi_channel, &chip_command, NULL);
}

/* cmd buffer primitives */


int8_t cmd_buffer_init(bf_cmd_buffer_t* cmd_buffer)
{
if (cmd_buffer == NULL)
return -1;

cmd_buffer->cmd_list = cgmalloc(sizeof(bf_list_t));
cmd_buffer->cmd_list->head = NULL;
cmd_buffer->cmd_list->tail = NULL;
cmd_buffer->cmd_list->count = 0;

cmd_buffer->tx_buffer = cgcalloc(CMD_BUFFER_LEN, sizeof(uint8_t));


cmd_buffer->rx_buffer = cgcalloc(CMD_BUFFER_LEN, sizeof(uint8_t));

memset(cmd_buffer->tx_buffer, 0, CMD_BUFFER_LEN);
memset(cmd_buffer->rx_buffer, 0, CMD_BUFFER_LEN);

cmd_buffer->free_bytes = CMD_BUFFER_LEN;
cmd_buffer->tx_offset = 0;
cmd_buffer->rx_offset = 0;
cmd_buffer->status = EMPTY;

return 0;
}

int8_t cmd_buffer_deinit(bf_cmd_buffer_t* cmd_buffer)


{
if (cmd_buffer == NULL)
return -1;

/* free cmd buffer */


while (cmd_buffer->cmd_list->head != NULL) {
bf_data_t* cdata = cmd_buffer->cmd_list->head;
LIST_POP_HEAD(cmd_buffer->cmd_list);
free(cdata->data);
free(cdata);
}

free(cmd_buffer->cmd_list);

/* free RX/TX buffer */


free(cmd_buffer->tx_buffer);
free(cmd_buffer->rx_buffer);

cmd_buffer->free_bytes = CMD_BUFFER_LEN;
cmd_buffer->tx_offset = 0;
cmd_buffer->rx_offset = 0;
cmd_buffer->status = EMPTY;

return 0;
}

int8_t cmd_buffer_clear(bf_cmd_buffer_t* cmd_buffer)


{
if (cmd_buffer == NULL)
return -1;

/* release cmd buffer data memory */


while (cmd_buffer->cmd_list->head != NULL) {
bf_data_t* cdata = cmd_buffer->cmd_list->head;
LIST_POP_HEAD(cmd_buffer->cmd_list);
free(cdata->data);
free(cdata);
}

cmd_buffer->cmd_list->count = 0;

/* clear RX/TX buffer */


memset(cmd_buffer->tx_buffer, 0, CMD_BUFFER_LEN);
memset(cmd_buffer->rx_buffer, 0, CMD_BUFFER_LEN);

cmd_buffer->free_bytes = CMD_BUFFER_LEN;
cmd_buffer->tx_offset = 0;
cmd_buffer->rx_offset = 0;
cmd_buffer->status = EMPTY;

return 0;
}

int8_t cmd_buffer_push(bf_cmd_buffer_t* cmd_buffer, const uint8_t depth,


const bf_chip_address_t chip_address, const bf_chip_address_t
src_address,
const bf_works_t work, const uint32_t id,
const bf_cmd_code_t cmd_code, const uint8_t data_length, const uint8_t*
tx)
{
uint8_t res = 0;

if (cmd_buffer == NULL)
return -1;

if (cmd_buffer->status == EXECUTED)
return -2;

bf_command_t command;
memset(&command, 0, sizeof(bf_command_t));

uint8_t buff[192];
memset(buff, 0, sizeof(buff));

if (cmd_code != CHIP_CMD_CREATE_CHANNEL) {
res = spi_command_init(&command, depth, chip_address, cmd_code,
data_length, tx);
if (res != 0)
return res;
}

/* init structure */
bf_data_t* cdata = cgmalloc(sizeof(bf_data_t));
cdata->data = cgmalloc(sizeof(bf_cmd_t));
cdata->next = NULL;
cdata->prev = NULL;

cg_memcpy(&CMD(cdata)->chip_address, &chip_address,
sizeof(bf_chip_address_t));
cg_memcpy(&CMD(cdata)->src_address, &src_address,
sizeof(bf_chip_address_t));
cg_memcpy(&CMD(cdata)->work, &work, sizeof(bf_works_t));
CMD(cdata)->id = id;
CMD(cdata)->depth = command.depth;
CMD(cdata)->checksum = command.checksum;
CMD(cdata)->cmd_code = cmd_code;

if (CMD(cdata)->cmd_code & CHIP_CMD_READ_NONCE)


CMD(cdata)->data_length = command.data_length + 49 + 2 +
extra_bytes(command.depth);
else if (CMD(cdata)->cmd_code == CHIP_CMD_CREATE_CHANNEL)
CMD(cdata)->data_length = data_length;
else
CMD(cdata)->data_length = command.data_length + 2 +
extra_bytes(command.depth);

if (cmd_buffer->free_bytes < CMD(cdata)->data_length) {


/* not enough TX/RX buffer space available */
free(cdata->data);
free(cdata);
return -3;
}

/* init send buffer */


if (cmd_code != CHIP_CMD_CREATE_CHANNEL) {
cg_memcpy(buff, command.tx, command.data_length);
cg_memcpy(cmd_buffer->tx_buffer + cmd_buffer->tx_offset, buff,
CMD(cdata)->data_length);
} else
cg_memcpy(cmd_buffer->tx_buffer + cmd_buffer->tx_offset, tx,
CMD(cdata)->data_length);

#if 0
uint16_t i;
char data[384];
memset(data, 0, sizeof(data));
for (i = 0; i < command.data_length; i++)
sprintf(data, "%s%02x", data, command.tx[i]);
applog(LOG_DEBUG, "BF16: TX -> [%s]", data);
#endif

cmd_buffer->tx_offset += CMD(cdata)->data_length;
cmd_buffer->free_bytes -= CMD(cdata)->data_length;

/* add cmd to buffer */


LIST_PUSH_TAIL(cmd_buffer->cmd_list, cdata);
cmd_buffer->cmd_list->count++;

return 0;
}

int8_t cmd_buffer_push_send_toggle(bf_cmd_buffer_t* cmd_buffer, const uint8_t


depth,
const bf_chip_address_t chip_address)
{
bf_works_t work;
uint8_t toggle[4] = { 0xa5, 0x00, 0x00, 0x02 };

return cmd_buffer_push(cmd_buffer, depth, chip_address, chip_address,


work, 0, CHIP_CMD_TOGGLE, 3, toggle);
}

int8_t cmd_buffer_push_set_clock(bf_cmd_buffer_t* cmd_buffer, const uint8_t depth,


const bf_chip_address_t chip_address, uint8_t clock)
{
bf_works_t work;
uint8_t clock_buf[4];

memset(clock_buf, 0, 4);
gen_clock_data(clock, 1, clock_buf);

return cmd_buffer_push(cmd_buffer, depth, chip_address, chip_address,


work, 0, CHIP_CMD_SET_CLOCK, 3, clock_buf);
}

int8_t cmd_buffer_push_set_mask(bf_cmd_buffer_t* cmd_buffer, const uint8_t depth,


const bf_chip_address_t chip_address, uint8_t mask)
{
uint8_t i;
bf_works_t work;
uint8_t noncemask[4];

for (i = 0; i < 4; i++)


noncemask[i] = (mask >> (8*(4 - i - 1))) & 0xff;

return cmd_buffer_push(cmd_buffer, depth, chip_address, chip_address,


work, 0, CHIP_CMD_SET_MASK, 3, noncemask);
}

int8_t cmd_buffer_push_create_channel(bf_cmd_buffer_t* cmd_buffer,


uint8_t* channel_path, uint8_t channel_length)
{
bf_works_t work;
bf_chip_address_t chip_address = { 0x00, 0x00, 0x00 };
return cmd_buffer_push(cmd_buffer, 0, chip_address, chip_address,
work, 0, CHIP_CMD_CREATE_CHANNEL, channel_length, channel_path);
}

int8_t cmd_buffer_push_destroy_channel(bf_cmd_buffer_t* cmd_buffer, const uint8_t


depth)
{
bf_works_t work;
bf_chip_address_t chip_address = { 0x00, 0x00, 0x0f };

return cmd_buffer_push(cmd_buffer, depth, chip_address, chip_address,


work, 0, CHIP_CMD_TASK_SWITCH, 0, NULL);
}

bool match_nonce(uint32_t nonce, uint32_t mask, uint8_t nbits)


{
uint32_t fixed_mask = (uint32_t)(pow(2, nbits) - 1);
return ((nonce & fixed_mask) == (mask & fixed_mask));
}

uint8_t find_nonces(uint32_t* curr_nonces, uint32_t* prev_nonces, uint32_t*


valid_nonces)
{
uint8_t i, j;
uint8_t found = 0;
uint8_t nonces = 0;
uint8_t diff = 0;

uint32_t found_nonces[12];
memset(found_nonces, 0, sizeof(found_nonces));

for (i = 0; i < 12; i++) {


if (((curr_nonces[i] & 0x0fffffff) != 0x0fffffff) &&
(curr_nonces[i] != prev_nonces[i])) {
found_nonces[found++] = curr_nonces[i];
}

if (((curr_nonces[i] & 0x0fffffff) == 0x0fffffff) &&


(curr_nonces[i] != prev_nonces[i]))
diff++;
}

for (i = 0; i < found; i++) {


if (found_nonces[i] == 0x00000000)
continue;

for (j = i; j < found; j++) {


if ((j != i) && (found_nonces[i] == found_nonces[j]))
found_nonces[j] = 0x00000000;
}

valid_nonces[nonces++] = found_nonces[i];
}

return nonces;
}

int8_t cmd_buffer_pop(bf_cmd_buffer_t* cmd_buffer, bf_cmd_status_t* cmd_status,


uint32_t* nonces)
{
if (cmd_buffer == NULL)
return -1;

if (cmd_buffer->status != EXECUTED)
return -2;

if (cmd_buffer->cmd_list->head == NULL)
return -3;

uint8_t buff[192];
bf_command_t chip_command;
memset(buff, 0, sizeof(buff));
memset(chip_command.rx, 0, sizeof(chip_command.rx));

/* extract command from list */


bf_data_t* cdata = cmd_buffer->cmd_list->head;

chip_command.cmd_code = CMD(cdata)->cmd_code;
chip_command.depth = CMD(cdata)->depth;
chip_command.data_length = CMD(cdata)->data_length;
chip_command.status = 0;
chip_command.checksum = CMD(cdata)->checksum;
chip_command.nonce_checksum = 0;
chip_command.checksum_error = false;
chip_command.nonce_checksum_error = false;

/* extract chip return data */


cg_memcpy(buff, cmd_buffer->rx_buffer + cmd_buffer->rx_offset, CMD(cdata)-
>data_length);
cmd_buffer->rx_offset += CMD(cdata)->data_length;
if (CMD(cdata)->cmd_code & CHIP_CMD_READ_NONCE) {
cg_memcpy(chip_command.rx, buff + CMD(cdata)->data_length - (49 + 2 +
extra_bytes(chip_command.depth)),
49 + 2 + extra_bytes(chip_command.depth));
memset(nonces, 0, 12 * sizeof(uint32_t));
analyze_rx_data(&chip_command, cmd_status, nonces);
} else if (CMD(cdata)->cmd_code == CHIP_CMD_CREATE_CHANNEL) {
cg_memcpy(chip_command.rx, buff, CMD(cdata)->data_length);
} else {
cg_memcpy(chip_command.rx, buff + CMD(cdata)->data_length - (2 +
extra_bytes(chip_command.depth)),
2 + extra_bytes(chip_command.depth));
analyze_rx_data(&chip_command, cmd_status, NULL);
}

/* prepare cmd_status */
cg_memcpy(&cmd_status->chip_address, &CMD(cdata)->chip_address,
sizeof(bf_chip_address_t));
cg_memcpy(&cmd_status->src_address, &CMD(cdata)->src_address,
sizeof(bf_chip_address_t));
cg_memcpy(&cmd_status->work, &CMD(cdata)->work,
sizeof(bf_works_t));
cmd_status->id = CMD(cdata)->id;
cmd_status->cmd_code = CMD(cdata)->cmd_code;

/* push memory back to free cmd list */


LIST_POP_HEAD(cmd_buffer->cmd_list);
cmd_buffer->cmd_list->count--;
free(cdata->data);
free(cdata);

return 0;
}

int8_t cmd_buffer_exec(spi_channel_id_t spi_channel, bf_cmd_buffer_t* cmd_buffer)


{
if (cmd_buffer == NULL)
return -1;

if (cmd_buffer->status == TX_READY) {
device_spi_txrx(spi_channel, cmd_buffer->tx_buffer, cmd_buffer-
>rx_buffer, cmd_buffer->tx_offset);
cmd_buffer->status = EXECUTED;
} else
return -2;

return 0;
}

/* BF16 command primitives */


uint8_t gen_clock_data(uint8_t clock, uint8_t prescaler, uint8_t data[4])
{
uint8_t i;
uint32_t data32 = 0x00000000;

if (clock > 0x3f)


return -1;

if ((prescaler != 0) && (prescaler != 1))


return -1;

uint32_t magic_const = 0x38;


uint32_t prescaler1 = prescaler;
uint32_t clock1 = clock;
uint32_t prescaler2 = prescaler;
uint32_t clock2 = clock;

magic_const <<= 20;

if (prescaler == 1) {
prescaler1 <<= 19;
prescaler2 <<= 12;
}

clock1 <<= 13;


clock2 <<= 6;

data32 = magic_const | prescaler1 | clock1 | prescaler2 | clock2;


for (i = 0; i < 4; i++)
data[i] = (data32 >> (8*(4 - i - 1))) & 0xff;

return 0;
}

#ifdef FLIP_BITS
static uint32_t flip_bits(uint32_t data, uint8_t nbits)
{
uint32_t ret = 0x00000000;
uint8_t i;

for (i = 0; i < nbits; i++)


ret |= (((data >> i) & 0x1) << (nbits - (i + 1)));

return ret;
}
#endif

uint32_t gen_mask(uint32_t nonce, uint8_t nbits)


{
uint32_t mask = 0x00000000;

uint32_t mask_code = (nbits << 16);

/* highest 16 bits of nonce counter */


uint32_t nonce_code = (nonce & 0x0007ffff);
#ifdef FLIP_BITS
uint32_t nonce_cntr = flip_bits(nonce_code, 19);
nonce_code = (flip_bits(nonce_cntr - 2, 19) ^ 0xaaaaaaaa);
mask = (mask_code | (nonce_code & (uint32_t)(pow(2, nbits) - 1)));
#else
nonce_code = ((nonce_code ^ 0xaaaaaaaa) & (uint32_t)(pow(2, nbits) - 1));
mask = (mask_code | nonce_code);
#endif

return mask;
}

void ms3steps16(uint32_t* p, uint32_t* w, uint32_t* task)


{
uint32_t a, b, c, d, e, f, g, h, new_e, new_a;
uint8_t i;

a = p[0];
b = p[1];
c = p[2];
d = p[3];
e = p[4];
f = p[5];
g = p[6];
h = p[7];
for (i = 0; i < 3; i++) {
new_e = w[i] + sha256_k[i] + h + CH(e,f,g) + SHA256_F2(e) + d;
new_a = w[i] + sha256_k[i] + h + CH(e,f,g) + SHA256_F2(e) +
SHA256_F1(a) + MAJ(a,b,c);
d = c;
c = b;
b = a;
a = new_a;
h = g;
g = f;
f = e;
e = new_e;
}

task[18] = ntohl(a ^ 0xaaaaaaaa);


task[17] = ntohl(b ^ 0xaaaaaaaa);
task[16] = ntohl(c ^ 0xaaaaaaaa);
task[15] = ntohl(d ^ 0xaaaaaaaa);
task[11] = ntohl(e ^ 0xaaaaaaaa);
task[10] = ntohl(f ^ 0xaaaaaaaa);
task[9] = ntohl(g ^ 0xaaaaaaaa);
task[8] = ntohl(h ^ 0xaaaaaaaa);
}

uint8_t gen_task_data(uint32_t* midstate, uint32_t merkle, uint32_t ntime,


uint32_t nbits, uint32_t mask, uint8_t* task)
{
uint8_t i;
uint32_t tmp;
uint32_t w[3];

w[0] = merkle;
w[1] = ntime;
w[2] = nbits;

for (i = 0; i < 8; i++) {


tmp = midstate[i];
tmp ^= 0xaaaaaaaa;
tmp = ntohl(tmp);
cg_memcpy(task + i*4, &tmp, sizeof(tmp));
}

ms3steps16(midstate, w, (uint32_t*)task);

for (i = 0; i < 3; i++) {


tmp = w[i];
tmp ^= 0xaaaaaaaa;
tmp = ntohl(tmp);
cg_memcpy(task + (12 + i)*4, &tmp, sizeof(tmp));
}

mask = ntohl(mask);
cg_memcpy(task + 19*4, &mask, sizeof(mask));

return 0;
}

uint8_t spi_command_init(bf_command_t* command, const uint8_t depth,


const bf_chip_address_t chip_address, const bf_cmd_code_t cmd_code,
const uint8_t data_length, const uint8_t* tx)
{
uint8_t i;

memset(command->tx, 0, sizeof(command->tx));
memset(command->rx, 0, sizeof(command->rx));

command->tx[0] = 0x01;
command->data_length = 1;

if ((chip_address.chip_id > 10) && (chip_address.chip_id != 0x0f))


return 1;
else {
cg_memcpy(&command->chip_address, &chip_address,
sizeof(bf_chip_address_t));
command->tx[1] = (command->chip_address.chip_id << 4);
command->data_length++;
}

command->depth = depth;

command->cmd_code = cmd_code;
command->tx[2] = command->cmd_code;
command->data_length++;

if (data_length <= 79) {


command->tx[3] = data_length;
command->data_length++;
} else
return 1;

/* fill TX data */
if (data_length == 0) {
command->tx[4] = 0x00;
command->data_length++;
} else if (tx != NULL) {
cg_memcpy(command->tx + 4, tx, data_length + 1);
command->data_length += (data_length + 1);
} else
return 1;

/* calculate checksum */
command->checksum = 0;
command->nonce_checksum = 0;
for (i = 2; i < command->data_length; i++)
command->checksum += command->tx[i];

command->checksum_error = false;
command->nonce_checksum_error = false;

return 0;
}

uint8_t spi_command_exec(spi_channel_id_t spi_channel, bf_command_t* command,


uint32_t* nonces)
{
uint8_t buff[192];
uint8_t res = 0;
bf_cmd_status_t cmd_status;

if (command->cmd_code & CHIP_CMD_READ_NONCE) {


memset(buff, 0x00, command->data_length + 49 + 2 + extra_bytes(command-
>depth));
cg_memcpy(buff, command->tx, command->data_length);
device_spi_transfer(spi_channel, buff, command->data_length + 49 + 2 +
extra_bytes(command->depth));
cg_memcpy(command->rx, buff + command->data_length, 49 + 2 +
extra_bytes(command->depth));

#if 0
uint16_t i;
char data[256];
memset(data, 0, sizeof(data));
for (i = 0; i < command->data_length; i++)
sprintf(data, "%s%02x", data, command->tx[i]);
applog(LOG_DEBUG, "BF16: TX -> [%s]", data);
#endif

return analyze_rx_data(command, &cmd_status, nonces);


} else {
memset(buff, 0x00, command->data_length + 2 + extra_bytes(command-
>depth));
cg_memcpy(buff, command->tx, command->data_length);
device_spi_transfer(spi_channel, buff, command->data_length + 2 +
extra_bytes(command->depth));
cg_memcpy(command->rx, buff + command->data_length, 2 +
extra_bytes(command->depth));

if (opt_bf16_test_chip != NULL) {
uint16_t i;
char data[256];
memset(data, 0, sizeof(data));
for (i = 0; i < command->data_length; i++)
sprintf(data, "%s%02x", data, command->tx[i]);
applog(LOG_NOTICE, "BF16: TX -> [%s]", data);
}

return analyze_rx_data(command, &cmd_status, nonces);


}

return res;
}

/* dynamic work list primitives */


bf_list_t* workd_list_init(void)
{
bf_list_t* list = cgmalloc(sizeof(bf_list_t));
list->head = NULL;
list->tail = NULL;
list->count = 0;
pthread_mutex_init(&list->lock, NULL);

return list;
}

int8_t workd_list_deinit(bf_list_t* list, struct cgpu_info *bitfury)


{
if (list == NULL)
return -1;

/* free work list */


L_LOCK(list);
while (list->head != NULL) {
bf_data_t* wdata = list->head;
LIST_POP_HEAD(list);

if (WORKD(wdata)->rolled)
free_work(WORKD(wdata)->work);
else
work_completed(bitfury, WORKD(wdata)->work);

free(wdata);
}
L_UNLOCK(list);

pthread_mutex_destroy(&list->lock);
list->count = 0;
free(list);

return 0;
}

int8_t workd_list_push(bf_list_t* list, bf_workd_t* work)


{
if ((list == NULL) || (work == NULL))
return -1;

bf_data_t* wdata = cgmalloc(sizeof(bf_data_t));


wdata->data = work;
wdata->next = NULL;
wdata->prev = NULL;

LIST_PUSH_TAIL(list, wdata);
list->count++;

return 0;
}

int8_t workd_list_pop(bf_list_t* list, struct cgpu_info *bitfury)


{
if (list == NULL)
return -1;

bf_data_t* wdata = list->head;


if (wdata != NULL) {
LIST_POP_HEAD(list);

if (WORKD(wdata)->rolled)
free_work(WORKD(wdata)->work);
else
work_completed(bitfury, WORKD(wdata)->work);

list->count--;
free(wdata->data);
free(wdata);
} else
return -1;

return 0;
}

int8_t workd_list_remove(bf_list_t* list, bf_works_t* works)


{
if (list == NULL)
return -1;

bf_data_t* wdata = list->head;


if (wdata != NULL) {
LIST_POP_HEAD(list);

cg_memcpy(&works->work, WORKD(wdata)->work, sizeof(struct


work));
cg_memcpy(&works->payload, &WORKD(wdata)->payload,
sizeof(bf_payload_t));

list->count--;
free(wdata);
} else
return -1;

return 0;
}

/* nonces list primitives */


bf_list_t* nonce_list_init(void)
{
bf_list_t* list = cgmalloc(sizeof(bf_list_t));
list->head = NULL;
list->tail = NULL;
list->count = 0;
pthread_mutex_init(&list->lock, NULL);

return list;
}

int8_t nonce_list_deinit(bf_list_t* list)


{
if (list == NULL)
return -1;

/* free nonce list */


L_LOCK(list);
while (list->head != NULL) {
bf_data_t* ndata = list->head;
LIST_POP_HEAD(list);
free(ndata->data);
free(ndata);
}
L_UNLOCK(list);

pthread_mutex_destroy(&list->lock);
list->count = 0;
free(list);

return 0;
}

int8_t nonce_list_push(bf_list_t* list, uint32_t nonce)


{
if (list == NULL)
return -1;

/* find nonce duplicates */


bf_data_t* ndata = list->head;
while (ndata != NULL) {
if (NONCE(ndata)->nonce == nonce)
return -1;
ndata = ndata->next;
}

ndata = cgmalloc(sizeof(bf_data_t));
ndata->data = cgmalloc(sizeof(bf_nonce_t));
NONCE(ndata)->nonce = nonce;
ndata->next = NULL;
ndata->prev = NULL;

LIST_PUSH_TAIL(list, ndata);
list->count++;

return 0;
}

uint32_t nonce_list_pop(bf_list_t* list)


{
uint32_t nonce = 0;

bf_data_t* ndata = list->head;


if (ndata != NULL) {
nonce = NONCE(ndata)->nonce;
LIST_POP_HEAD(list);
list->count--;
free(ndata->data);
free(ndata);
} else
return -1;

return nonce;
}

/* renoncework list primitives */


bf_list_t* renoncework_list_init(void)
{
bf_list_t* list = cgmalloc(sizeof(bf_list_t));
list->head = NULL;
list->tail = NULL;
list->count = 0;
pthread_mutex_init(&list->lock, NULL);

return list;
}

int8_t renoncework_list_deinit(bf_list_t* list)


{
if (list == NULL)
return -1;

/* free renoncework list */


L_LOCK(list);
while (list->head != NULL) {
bf_data_t* rnwdata = list->head;
LIST_POP_HEAD(list);

free(rnwdata->data);
free(rnwdata);
}
L_UNLOCK(list);

pthread_mutex_destroy(&list->lock);
list->count = 0;
free(list);
return 0;
}

int8_t renoncework_list_push(bf_list_t* list, bf_chip_address_t src_address,


uint32_t nonce)
{
if (list == NULL)
return -1;

bf_data_t* rnwdata = cgmalloc(sizeof(bf_data_t));


rnwdata->data = cgmalloc(sizeof(bf_renoncework_t));
rnwdata->next = NULL;
rnwdata->prev = NULL;

cg_memcpy(&RENONCEWORK(rnwdata)->src_address, &src_address,
sizeof(bf_chip_address_t));
RENONCEWORK(rnwdata)->nonce = nonce;

LIST_PUSH_TAIL(list, rnwdata);
list->count++;

return 0;
}

int8_t renoncework_list_pop(bf_list_t* list)


{
if (list == NULL)
return -1;

bf_data_t* rnwdata = list->head;


if (rnwdata != NULL) {
LIST_POP_HEAD(list);
list->count--;
free(rnwdata->data);
free(rnwdata);
} else
return -1;

return 0;
}

/* noncework list primitives */


bf_list_t* noncework_list_init(void)
{
bf_list_t* list = cgmalloc(sizeof(bf_list_t));
list->head = NULL;
list->tail = NULL;
list->count = 0;
pthread_mutex_init(&list->lock, NULL);

return list;
}

int8_t noncework_list_deinit(bf_list_t* list)


{
if (list == NULL)
return -1;
/* free noncework list */
L_LOCK(list);
while (list->head != NULL) {
bf_data_t* nwdata = list->head;
LIST_POP_HEAD(list);

free(nwdata->data);
free(nwdata);
}
L_UNLOCK(list);

pthread_mutex_destroy(&list->lock);
list->count = 0;
free(list);

return 0;
}

int8_t noncework_list_push(bf_list_t* list, bf_chip_address_t chip_address,


bf_chip_address_t src_address, bf_works_t cwork, bf_works_t owork,
uint32_t nonce)
{
if (list == NULL)
return -1;

bf_data_t* nwdata = cgmalloc(sizeof(bf_data_t));


nwdata->data = cgmalloc(sizeof(bf_noncework_t));
nwdata->next = NULL;
nwdata->prev = NULL;

cg_memcpy(&NONCEWORK(nwdata)->cwork, &cwork, sizeof(bf_works_t));


cg_memcpy(&NONCEWORK(nwdata)->owork, &owork, sizeof(bf_works_t));
cg_memcpy(&NONCEWORK(nwdata)->chip_address, &chip_address,
sizeof(bf_chip_address_t));
cg_memcpy(&NONCEWORK(nwdata)->src_address, &src_address,
sizeof(bf_chip_address_t));
NONCEWORK(nwdata)->nonce = nonce;

LIST_PUSH_TAIL(list, nwdata);
list->count++;

return 0;
}

int8_t noncework_list_pop(bf_list_t* list)


{
if (list == NULL)
return -1;

bf_data_t* nwdata = list->head;


if (nwdata != NULL) {
LIST_POP_HEAD(list);
list->count--;
free(nwdata->data);
free(nwdata);
} else
return -1;

return 0;
}

/* renonce list primitives */


bf_list_t* renonce_list_init(void)
{
bf_list_t* list = cgmalloc(sizeof(bf_list_t));
list->head = NULL;
list->tail = NULL;
list->count = 0;
pthread_mutex_init(&list->lock, NULL);

return list;
}

int8_t renonce_list_deinit(bf_list_t* list)


{
if (list == NULL)
return -1;

/* free renonce list */


L_LOCK(list);
while (list->head != NULL) {
bf_data_t* rdata = list->head;
LIST_POP_HEAD(list);

free(rdata->data);
free(rdata);
}
L_UNLOCK(list);

pthread_mutex_destroy(&list->lock);
list->count = 0;
free(list);

return 0;
}

int8_t renonce_list_push(bf_list_t* list, uint32_t id, uint32_t nonce,


bf_chip_address_t src_address,
bf_works_t cwork, bf_works_t owork)
{
if (list == NULL)
return -1;

bf_data_t* rdata = cgmalloc(sizeof(bf_data_t));


rdata->data = cgmalloc(sizeof(bf_renonce_t));
rdata->next = NULL;
rdata->prev = NULL;

cg_memcpy(&RENONCE(rdata)->cwork, &cwork, sizeof(bf_works_t));


cg_memcpy(&RENONCE(rdata)->owork, &owork, sizeof(bf_works_t));
cg_memcpy(&RENONCE(rdata)->src_address, &src_address,
sizeof(bf_chip_address_t));
RENONCE(rdata)->id = id;
RENONCE(rdata)->nonce = nonce;
RENONCE(rdata)->stage = RENONCE_STAGE0;
RENONCE(rdata)->sent = false;
RENONCE(rdata)->received = false;
RENONCE(rdata)->match = false;
LIST_PUSH_TAIL(list, rdata);
list->count++;

return 0;
}

int8_t renonce_list_pop(bf_list_t* list)


{
if (list == NULL)
return -1;

bf_data_t* rdata = list->head;


if (rdata != NULL) {
LIST_POP_HEAD(list);
list->count--;
free(rdata->data);
free(rdata);
} else
return -1;

return 0;
}

int8_t renonce_list_remove(bf_list_t* list, bf_data_t* rdata)


{
if (list == NULL)
return -1;

if (rdata != NULL) {
LIST_REMOVE(list, rdata);
list->count--;
free(rdata->data);
free(rdata);
} else
return -1;

return 0;
}

You might also like