mirror of https://github.com/GOSTSec/sgminer
Browse Source
Code referencing these files is still present, but not compiled through the use of defines.nfactor-troky
Noel Maersk
11 years ago
26 changed files with 0 additions and 20399 deletions
@ -1,32 +0,0 @@
@@ -1,32 +0,0 @@
|
||||
# Butterfly Labs FPGA and ASIC devices |
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6014", SUBSYSTEMS=="usb", ACTION=="add", MODE="0666", GROUP="plugdev" |
||||
|
||||
# ModMinerQuad |
||||
ATTRS{idVendor}=="1fc9", ATTRS{idProduct}=="0003", SUBSYSTEMS=="usb", ACTION=="add", MODE="0666", GROUP="plugdev" |
||||
|
||||
# Lancelot and Avalon |
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", SUBSYSTEMS=="usb", ACTION=="add", MODE="0666", GROUP="plugdev" |
||||
|
||||
# Icarus |
||||
ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", SUBSYSTEMS=="usb", ACTION=="add", MODE="0666", GROUP="plugdev" |
||||
|
||||
# AsicminerUSB |
||||
ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", SUBSYSTEMS=="usb", ACTION=="add", MODE="0666", GROUP="plugdev" |
||||
|
||||
# Cairnsmore1 |
||||
ATTRS{idVendor}=="067b", ATTRS{idProduct}=="0230", SUBSYSTEMS=="usb", ACTION=="add", MODE="0666", GROUP="plugdev" |
||||
|
||||
# Cairnsmore1-2 |
||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8350", SUBSYSTEMS=="usb", ACTION=="add", MODE="0666", GROUP="plugdev" |
||||
|
||||
# Ztex |
||||
ATTRS{idVendor}=="221a", ATTRS{idProduct}=="0100", SUBSYSTEMS=="usb", ACTION=="add", MODE="0666", GROUP="plugdev" |
||||
|
||||
# BF1 |
||||
ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="204b", SUBSYSTEMS=="usb", ACTION=="add", MODE="0666", GROUP="plugdev" |
||||
|
||||
#Klondike |
||||
ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="f60a", SUBSYSTEMS=="usb", ACTION=="add", MODE="0666", GROUP="plugdev" |
||||
|
||||
#HashFast |
||||
ATTRS{idVendor}=="297c", ATTRS{idProduct}=="0001", SUBSYSTEMS=="usb", ACTION=="add", MODE="0666", GROUP="plugdev", ENV{ID_MM_DEVICE_IGNORE}="1" |
@ -1,108 +0,0 @@
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 Luke Dashjr |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#define _BSD_SOURCE |
||||
#include <stdint.h> |
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
|
||||
#include <libgen.h> |
||||
#include <arpa/inet.h> |
||||
|
||||
#define BFL_FILE_MAGIC "BFLDATA" |
||||
#define BFL_UPLOAD_MAGIC "NGH-STREAM" |
||||
|
||||
#define myassert(expr, n, ...) \ |
||||
do { \ |
||||
if (!(expr)) { \ |
||||
fprintf(stderr, __VA_ARGS__); \ |
||||
return n; \ |
||||
} \ |
||||
} while(0) |
||||
|
||||
#define ERRRESP(buf) buf, (buf[strlen(buf)-1] == '\n' ? "" : "\n") |
||||
|
||||
#define WAITFOROK(n, msg) \ |
||||
do { \ |
||||
myassert(fgets(buf, sizeof(buf), BFL), n, "Error reading response from " msg "\n"); \ |
||||
myassert(!strcmp(buf, "OK\n"), n, "Invalid response from " msg ": %s%s", ERRRESP(buf)); \ |
||||
} while(0) |
||||
|
||||
int main(int argc, char**argv) |
||||
{ |
||||
myassert(argc == 3, 1, "Usage: %s <serialdev> <firmware.bfl>\n", argv[0]); |
||||
setbuf(stdout, NULL); |
||||
|
||||
// Check filename
|
||||
char *FWname = basename(strdup(argv[2])); |
||||
size_t FWnameLen = strlen(FWname); |
||||
myassert(FWnameLen <= 255, 0x0f, "Firmware filename '%s' is too long\n", FWname); |
||||
uint8_t n8 = FWnameLen; |
||||
|
||||
// Open and check firmware file
|
||||
FILE *FW = fopen(argv[2], "r"); |
||||
myassert(FW, 0x10, "Failed to open '%s' for reading\n", argv[2]); |
||||
char buf[0x20]; |
||||
myassert(1 == fread(buf, 7, 1, FW), 0x10, "Failed to read from '%s'\n", argv[2]); |
||||
myassert(!memcmp(buf, BFL_FILE_MAGIC, sizeof(BFL_FILE_MAGIC)-1), 0x11, "'%s' doesn't look like a BFL firmware\n", argv[2]); |
||||
myassert(!fseek(FW, 0, SEEK_END), 0x12, "Failed to find end of '%s'\n", argv[2]); |
||||
long FWlen = ftell(FW); |
||||
myassert(FWlen > 0, 0x12, "Couldn't get size of '%s'\n", argv[2]); |
||||
myassert(!fseek(FW, 7, SEEK_SET), 0x12, "Failed to rewind firmware file after getting size\n"); |
||||
FWlen -= 7; |
||||
printf("Firmware file looks OK :)\n"); |
||||
|
||||
// Open device
|
||||
FILE *BFL = fopen(argv[1], "r+"); |
||||
myassert(BFL, 0x20, "Failed to open '%s' for read/write\n", argv[1]); |
||||
myassert(!setvbuf(BFL, NULL, _IOFBF, 1032), 0x21, "Failed to setup buffer for device"); |
||||
|
||||
// ZAX: Start firmware upload
|
||||
printf("Starting firmware upload... "); |
||||
myassert(1 == fwrite("ZAX", 3, 1, BFL), 0x22, "Failed to issue ZAX command\n"); |
||||
WAITFOROK(0x22, "ZAX"); |
||||
|
||||
// Firmware upload header
|
||||
myassert(1 == fwrite(BFL_UPLOAD_MAGIC, sizeof(BFL_UPLOAD_MAGIC)-1, 1, BFL), 0x23, "Failed to send firmware upload header (magic)\n"); |
||||
uint32_t n32 = htonl(FWlen - FWlen / 6); |
||||
myassert(1 == fwrite(&n32, sizeof(n32), 1, BFL), 0x23, "Failed to send firmware upload header (size)\n"); |
||||
myassert(1 == fwrite("\0\0", 2 , 1, BFL), 0x23, "Failed to send firmware upload header (padding 1)\n"); |
||||
myassert(1 == fwrite(&n8, sizeof(n8) , 1, BFL), 0x23, "Failed to send firmware upload header (filename length)\n"); |
||||
myassert(1 == fwrite(FWname, n8 , 1, BFL), 0x23, "Failed to send firmware upload header (filename)\n"); |
||||
myassert(1 == fwrite("\0>>>>>>>>", 9 , 1, BFL), 0x23, "Failed to send firmware upload header (padding 2)\n"); |
||||
WAITFOROK(0x23, "firmware upload header"); |
||||
printf("OK, sending...\n"); |
||||
|
||||
// Actual firmware upload
|
||||
long i, j; |
||||
for (i = 0, j = 0; i < FWlen; ++i) { |
||||
myassert(1 == fread(&n8, sizeof(n8), 1, FW), 0x30, "Error reading data from firmware file\n"); |
||||
if (5 == i % 6) |
||||
continue; |
||||
n8 ^= 0x2f; |
||||
myassert(1 == fwrite(&n8, sizeof(n8), 1, BFL), 0x31, "Error sending data to device\n"); |
||||
if (!(++j % 0x400)) { |
||||
myassert(1 == fwrite(">>>>>>>>", 8, 1, BFL), 0x32, "Error sending block-finish to device\n"); |
||||
printf("\r%5.2f%% complete", (double)i * 100. / (double)FWlen); |
||||
WAITFOROK(0x32, "block-finish"); |
||||
} |
||||
} |
||||
printf("\r100%% complete :)\n"); |
||||
myassert(1 == fwrite(">>>>>>>>", 8, 1, BFL), 0x3f, "Error sending upload-finished to device\n"); |
||||
myassert(fgets(buf, sizeof(buf), BFL), 0x3f, "Error reading response from upload-finished\n"); |
||||
myassert(!strcmp(buf, "DONE\n"), 0x3f, "Invalid response from upload-finished: %s%s", ERRRESP(buf)); |
||||
|
||||
// ZBX: Finish programming
|
||||
printf("Waiting for device... "); |
||||
myassert(1 == fwrite("ZBX", 3, 1, BFL), 0x40, "Failed to issue ZBX command\n"); |
||||
WAITFOROK(0x40, "ZBX"); |
||||
printf("All done! Try mining to test the flash succeeded.\n"); |
||||
|
||||
return 0; |
||||
} |
@ -1,23 +0,0 @@
@@ -1,23 +0,0 @@
|
||||
All the bitstream files included in this directory that follow the name pattern fpgaminer_*.ncd are: |
||||
|
||||
---- |
||||
|
||||
Copyright (c) 2011-2012 fpgaminer@bitcoin-mining.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. |
||||
|
||||
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/>. |
||||
|
||||
---- |
||||
|
||||
You can find the original sources at the Open Source FPGA Bitcoin Miner project GitHub repository: |
||||
https://github.com/progranism/Open-Source-FPGA-Bitcoin-Miner/tree/master/projects/X6000_ztex_comm4/hdl |
Binary file not shown.
@ -1,599 +0,0 @@
@@ -1,599 +0,0 @@
|
||||
// DiaKGCN 27-04-2012 - OpenCL kernel by Diapolo |
||||
// |
||||
// Parts and / or ideas for this kernel are based upon the public-domain poclbm project, the phatk kernel by Phateus and the DiabloMiner kernel by DiabloD3. |
||||
// The kernel was rewritten by me (Diapolo) and is still public-domain! |
||||
|
||||
#ifdef VECTORS4 |
||||
typedef uint4 u; |
||||
#elif defined VECTORS2 |
||||
typedef uint2 u; |
||||
#else |
||||
typedef uint u; |
||||
#endif |
||||
|
||||
#ifdef BITALIGN |
||||
#pragma OPENCL EXTENSION cl_amd_media_ops : enable |
||||
#ifdef BFI_INT |
||||
#define ch(x, y, z) amd_bytealign(x, y, z) |
||||
#define ma(x, y, z) amd_bytealign(z ^ x, y, x) |
||||
#else |
||||
#define ch(x, y, z) bitselect(z, y, x) |
||||
#define ma(z, x, y) bitselect(z, y, z ^ x) |
||||
#endif |
||||
#else |
||||
#define ch(x, y, z) (z ^ (x & (y ^ z))) |
||||
#define ma(x, y, z) ((x & z) | (y & (x | z))) |
||||
#endif |
||||
|
||||
#define rotr15(n) (rotate(n, 15U) ^ rotate(n, 13U) ^ (n >> 10U)) |
||||
#define rotr25(n) (rotate(n, 25U) ^ rotate(n, 14U) ^ (n >> 3U)) |
||||
#define rotr26(n) (rotate(n, 26U) ^ rotate(n, 21U) ^ rotate(n, 7U)) |
||||
#define rotr30(n) (rotate(n, 30U) ^ rotate(n, 19U) ^ rotate(n, 10U)) |
||||
|
||||
__kernel |
||||
__attribute__((reqd_work_group_size(WORKSIZE, 1, 1))) |
||||
void search( |
||||
#ifndef GOFFSET |
||||
const u base, |
||||
#endif |
||||
const uint PreVal0, const uint PreVal4, |
||||
const uint H1, const uint D1A, const uint B1, const uint C1, |
||||
const uint F1, const uint G1, const uint C1addK5, const uint B1addK6, const uint PreVal0addK7, |
||||
const uint W16addK16, const uint W17addK17, |
||||
const uint PreW18, const uint PreW19, |
||||
const uint W16, const uint W17, |
||||
const uint PreW31, const uint PreW32, |
||||
const uint state0, const uint state1, const uint state2, const uint state3, |
||||
const uint state4, const uint state5, const uint state6, const uint state7, |
||||
const uint state0A, const uint state0B, |
||||
const uint state1A, const uint state2A, const uint state3A, const uint state4A, |
||||
const uint state5A, const uint state6A, const uint state7A, |
||||
volatile __global uint * output) |
||||
{ |
||||
u V[8]; |
||||
u W[16]; |
||||
|
||||
#ifdef VECTORS4 |
||||
const u nonce = (uint)(get_local_id(0)) * 4U + (uint)(get_group_id(0)) * (uint)(WORKVEC) + base; |
||||
#elif defined VECTORS2 |
||||
const u nonce = (uint)(get_local_id(0)) * 2U + (uint)(get_group_id(0)) * (uint)(WORKVEC) + base; |
||||
#else |
||||
#ifdef GOFFSET |
||||
const u nonce = (uint)(get_global_id(0)); |
||||
#else |
||||
const u nonce = (uint)(get_local_id(0)) + (uint)(get_group_id(0)) * (uint)(WORKSIZE) + base; |
||||
#endif |
||||
#endif |
||||
|
||||
V[0] = PreVal0 + nonce; |
||||
V[1] = B1; |
||||
V[2] = C1; |
||||
V[3] = D1A; |
||||
V[4] = PreVal4 + nonce; |
||||
V[5] = F1; |
||||
V[6] = G1; |
||||
V[7] = H1; |
||||
|
||||
V[7] += V[3] + ch(V[0], V[1], V[2]) + rotr26(V[0]); |
||||
V[3] = V[3] + ch(V[0], V[1], V[2]) + rotr26(V[0]) + rotr30(V[4]) + ma(V[5], V[6], V[4]); |
||||
|
||||
V[6] += C1addK5 + ch(V[7], V[0], V[1]) + rotr26(V[7]); |
||||
V[2] = C1addK5 + ch(V[7], V[0], V[1]) + rotr26(V[7]) + rotr30(V[3]) + ma(V[4], V[5], V[3]); |
||||
|
||||
V[5] += B1addK6 + ch(V[6], V[7], V[0]) + rotr26(V[6]); |
||||
V[1] = B1addK6 + ch(V[6], V[7], V[0]) + rotr26(V[6]) + rotr30(V[2]) + ma(V[3], V[4], V[2]); |
||||
|
||||
V[4] += PreVal0addK7 + nonce + ch(V[5], V[6], V[7]) + rotr26(V[5]); |
||||
V[0] = PreVal0addK7 + nonce + ch(V[5], V[6], V[7]) + rotr26(V[5]) + rotr30(V[1]) + ma(V[2], V[3], V[1]); |
||||
|
||||
V[3] += 0xd807aa98U + V[7] + ch(V[4], V[5], V[6]) + rotr26(V[4]); |
||||
V[7] = 0xd807aa98U + V[7] + ch(V[4], V[5], V[6]) + rotr26(V[4]) + rotr30(V[0]) + ma(V[1], V[2], V[0]); |
||||
|
||||
V[2] += 0x12835b01U + V[6] + ch(V[3], V[4], V[5]) + rotr26(V[3]); |
||||
V[6] = 0x12835b01U + V[6] + ch(V[3], V[4], V[5]) + rotr26(V[3]) + rotr30(V[7]) + ma(V[0], V[1], V[7]); |
||||
|
||||
V[1] += 0x243185beU + V[5] + ch(V[2], V[3], V[4]) + rotr26(V[2]); |
||||
V[5] = 0x243185beU + V[5] + ch(V[2], V[3], V[4]) + rotr26(V[2]) + rotr30(V[6]) + ma(V[7], V[0], V[6]); |
||||
|
||||
V[0] += 0x550c7dc3U + V[4] + ch(V[1], V[2], V[3]) + rotr26(V[1]); |
||||
V[4] = 0x550c7dc3U + V[4] + ch(V[1], V[2], V[3]) + rotr26(V[1]) + rotr30(V[5]) + ma(V[6], V[7], V[5]); |
||||
|
||||
V[7] += 0x72be5d74U + V[3] + ch(V[0], V[1], V[2]) + rotr26(V[0]); |
||||
V[3] = 0x72be5d74U + V[3] + ch(V[0], V[1], V[2]) + rotr26(V[0]) + rotr30(V[4]) + ma(V[5], V[6], V[4]); |
||||
|
||||
V[6] += 0x80deb1feU + V[2] + ch(V[7], V[0], V[1]) + rotr26(V[7]); |
||||
V[2] = 0x80deb1feU + V[2] + ch(V[7], V[0], V[1]) + rotr26(V[7]) + rotr30(V[3]) + ma(V[4], V[5], V[3]); |
||||
|
||||
V[5] += 0x9bdc06a7U + V[1] + ch(V[6], V[7], V[0]) + rotr26(V[6]); |
||||
V[1] = 0x9bdc06a7U + V[1] + ch(V[6], V[7], V[0]) + rotr26(V[6]) + rotr30(V[2]) + ma(V[3], V[4], V[2]); |
||||
|
||||
V[4] += 0xc19bf3f4U + V[0] + ch(V[5], V[6], V[7]) + rotr26(V[5]); |
||||
V[0] = 0xc19bf3f4U + V[0] + ch(V[5], V[6], V[7]) + rotr26(V[5]) + rotr30(V[1]) + ma(V[2], V[3], V[1]); |
||||
|
||||
V[3] += W16addK16 + V[7] + ch(V[4], V[5], V[6]) + rotr26(V[4]); |
||||
V[7] = W16addK16 + V[7] + ch(V[4], V[5], V[6]) + rotr26(V[4]) + rotr30(V[0]) + ma(V[1], V[2], V[0]); |
||||
|
||||
V[2] += W17addK17 + V[6] + ch(V[3], V[4], V[5]) + rotr26(V[3]); |
||||
V[6] = W17addK17 + V[6] + ch(V[3], V[4], V[5]) + rotr26(V[3]) + rotr30(V[7]) + ma(V[0], V[1], V[7]); |
||||
|
||||
//---------------------------------------------------------------------------------- |
||||
|
||||
#ifdef VECTORS4 |
||||
W[0] = PreW18 + (u)(rotr25(nonce.x), rotr25(nonce.x) ^ 0x2004000U, rotr25(nonce.x) ^ 0x4008000U, rotr25(nonce.x) ^ 0x600c000U); |
||||
#elif defined VECTORS2 |
||||
W[0] = PreW18 + (u)(rotr25(nonce.x), rotr25(nonce.x) ^ 0x2004000U); |
||||
#else |
||||
W[0] = PreW18 + rotr25(nonce); |
||||
#endif |
||||
W[1] = PreW19 + nonce; |
||||
W[2] = 0x80000000U + rotr15(W[0]); |
||||
W[3] = rotr15(W[1]); |
||||
W[4] = 0x00000280U + rotr15(W[2]); |
||||
W[5] = W16 + rotr15(W[3]); |
||||
W[6] = W17 + rotr15(W[4]); |
||||
W[7] = W[0] + rotr15(W[5]); |
||||
W[8] = W[1] + rotr15(W[6]); |
||||
W[9] = W[2] + rotr15(W[7]); |
||||
W[10] = W[3] + rotr15(W[8]); |
||||
W[11] = W[4] + rotr15(W[9]); |
||||
W[12] = W[5] + 0x00a00055U + rotr15(W[10]); |
||||
W[13] = W[6] + PreW31 + rotr15(W[11]); |
||||
W[14] = W[7] + PreW32 + rotr15(W[12]); |
||||
W[15] = W[8] + W17 + rotr15(W[13]) + rotr25(W[0]); |
||||
|
||||
V[1] += 0x0fc19dc6U + V[5] + ch(V[2], V[3], V[4]) + rotr26(V[2]) + W[0]; |
||||
V[5] = 0x0fc19dc6U + V[5] + ch(V[2], V[3], V[4]) + rotr26(V[2]) + W[0] + rotr30(V[6]) + ma(V[7], V[0], V[6]); |
||||
|
||||
V[0] += 0x240ca1ccU + V[4] + W[1] + ch(V[1], V[2], V[3]) + rotr26(V[1]); |
||||
V[4] = 0x240ca1ccU + V[4] + W[1] + ch(V[1], V[2], V[3]) + rotr26(V[1]) + rotr30(V[5]) + ma(V[6], V[7], V[5]); |
||||
|
||||
V[7] += 0x2de92c6fU + V[3] + W[2] + ch(V[0], V[1], V[2]) + rotr26(V[0]); |
||||
V[3] = 0x2de92c6fU + V[3] + W[2] + ch(V[0], V[1], V[2]) + rotr26(V[0]) + rotr30(V[4]) + ma(V[5], V[6], V[4]); |
||||
|
||||
V[6] += 0x4a7484aaU + V[2] + W[3] + ch(V[7], V[0], V[1]) + rotr26(V[7]); |
||||
V[2] = 0x4a7484aaU + V[2] + W[3] + ch(V[7], V[0], V[1]) + rotr26(V[7]) + rotr30(V[3]) + ma(V[4], V[5], V[3]); |
||||
|
||||
V[5] += 0x5cb0a9dcU + V[1] + W[4] + ch(V[6], V[7], V[0]) + rotr26(V[6]); |
||||
V[1] = 0x5cb0a9dcU + V[1] + W[4] + ch(V[6], V[7], V[0]) + rotr26(V[6]) + rotr30(V[2]) + ma(V[3], V[4], V[2]); |
||||
|
||||
V[4] += 0x76f988daU + V[0] + W[5] + ch(V[5], V[6], V[7]) + rotr26(V[5]); |
||||
V[0] = 0x76f988daU + V[0] + W[5] + ch(V[5], V[6], V[7]) + rotr26(V[5]) + rotr30(V[1]) + ma(V[2], V[3], V[1]); |
||||
|
||||
V[3] += 0x983e5152U + V[7] + W[6] + ch(V[4], V[5], V[6]) + rotr26(V[4]); |
||||
V[7] = 0x983e5152U + V[7] + W[6] + ch(V[4], V[5], V[6]) + rotr26(V[4]) + rotr30(V[0]) + ma(V[1], V[2], V[0]); |
||||
|
||||
V[2] += 0xa831c66dU + V[6] + W[7] + ch(V[3], V[4], V[5]) + rotr26(V[3]); |
||||
V[6] = 0xa831c66dU + V[6] + W[7] + ch(V[3], V[4], V[5]) + rotr26(V[3]) + rotr30(V[7]) + ma(V[0], V[1], V[7]); |
||||
|
||||
V[1] += 0xb00327c8U + V[5] + W[8] + ch(V[2], V[3], V[4]) + rotr26(V[2]); |
||||
V[5] = 0xb00327c8U + V[5] + W[8] + ch(V[2], V[3], V[4]) + rotr26(V[2]) + rotr30(V[6]) + ma(V[7], V[0], V[6]); |
||||
|
||||
V[0] += 0xbf597fc7U + V[4] + W[9] + ch(V[1], V[2], V[3]) + rotr26(V[1]); |
||||
V[4] = 0xbf597fc7U + V[4] + W[9] + ch(V[1], V[2], V[3]) + rotr26(V[1]) + rotr30(V[5]) + ma(V[6], V[7], V[5]); |
||||
|
||||
V[7] += 0xc6e00bf3U + V[3] + W[10] + ch(V[0], V[1], V[2]) + rotr26(V[0]); |
||||
V[3] = 0xc6e00bf3U + V[3] + W[10] + ch(V[0], V[1], V[2]) + rotr26(V[0]) + rotr30(V[4]) + ma(V[5], V[6], V[4]); |
||||
|
||||
V[6] += 0xd5a79147U + V[2] + W[11] + ch(V[7], V[0], V[1]) + rotr26(V[7]); |
||||
V[2] = 0xd5a79147U + V[2] + W[11] + ch(V[7], V[0], V[1]) + rotr26(V[7]) + rotr30(V[3]) + ma(V[4], V[5], V[3]); |
||||
|
||||
V[5] += 0x06ca6351U + V[1] + W[12] + ch(V[6], V[7], V[0]) + rotr26(V[6]); |
||||
V[1] = 0x06ca6351U + V[1] + W[12] + ch(V[6], V[7], V[0]) + rotr26(V[6]) + rotr30(V[2]) + ma(V[3], V[4], V[2]); |
||||
|
||||
V[4] += 0x14292967U + V[0] + W[13] + ch(V[5], V[6], V[7]) + rotr26(V[5]); |
||||
V[0] = 0x14292967U + V[0] + W[13] + ch(V[5], V[6], V[7]) + rotr26(V[5]) + rotr30(V[1]) + ma(V[2], V[3], V[1]); |
||||
|
||||
V[3] += 0x27b70a85U + V[7] + W[14] + ch(V[4], V[5], V[6]) + rotr26(V[4]); |
||||
V[7] = 0x27b70a85U + V[7] + W[14] + ch(V[4], V[5], V[6]) + rotr26(V[4]) + rotr30(V[0]) + ma(V[1], V[2], V[0]); |
||||
|
||||
V[2] += 0x2e1b2138U + V[6] + W[15] + ch(V[3], V[4], V[5]) + rotr26(V[3]); |
||||
V[6] = 0x2e1b2138U + V[6] + W[15] + ch(V[3], V[4], V[5]) + rotr26(V[3]) + rotr30(V[7]) + ma(V[0], V[1], V[7]); |
||||
|
||||
//---------------------------------------------------------------------------------- |
||||
|
||||
W[0] = W[0] + W[9] + rotr15(W[14]) + rotr25( W[1]); |
||||
W[1] = W[1] + W[10] + rotr15(W[15]) + rotr25( W[2]); |
||||
W[2] = W[2] + W[11] + rotr15( W[0]) + rotr25( W[3]); |
||||
W[3] = W[3] + W[12] + rotr15( W[1]) + rotr25( W[4]); |
||||
W[4] = W[4] + W[13] + rotr15( W[2]) + rotr25( W[5]); |
||||
W[5] = W[5] + W[14] + rotr15( W[3]) + rotr25( W[6]); |
||||
W[6] = W[6] + W[15] + rotr15( W[4]) + rotr25( W[7]); |
||||
W[7] = W[7] + W[0] + rotr15( W[5]) + rotr25( W[8]); |
||||
W[8] = W[8] + W[1] + rotr15( W[6]) + rotr25( W[9]); |
||||
W[9] = W[9] + W[2] + rotr15( W[7]) + rotr25(W[10]); |
||||
W[10] = W[10] + W[3] + rotr15( W[8]) + rotr25(W[11]); |
||||
W[11] = W[11] + W[4] + rotr15( W[9]) + rotr25(W[12]); |
||||
W[12] = W[12] + W[5] + rotr15(W[10]) + rotr25(W[13]); |
||||
W[13] = W[13] + W[6] + rotr15(W[11]) + rotr25(W[14]); |
||||
W[14] = W[14] + W[7] + rotr15(W[12]) + rotr25(W[15]); |
||||
W[15] = W[15] + W[8] + rotr15(W[13]) + rotr25( W[0]); |
||||
|
||||
V[1] += 0x4d2c6dfcU + V[5] + W[0] + ch(V[2], V[3], V[4]) + rotr26(V[2]); |
||||
V[5] = 0x4d2c6dfcU + V[5] + W[0] + ch(V[2], V[3], V[4]) + rotr26(V[2]) + rotr30(V[6]) + ma(V[7], V[0], V[6]); |
||||
|
||||
V[0] += 0x53380d13U + V[4] + W[1] + ch(V[1], V[2], V[3]) + rotr26(V[1]); |
||||
V[4] = 0x53380d13U + V[4] + W[1] + ch(V[1], V[2], V[3]) + rotr26(V[1]) + rotr30(V[5]) + ma(V[6], V[7], V[5]); |
||||
|
||||
V[7] += 0x650a7354U + V[3] + W[2] + ch(V[0], V[1], V[2]) + rotr26(V[0]); |
||||
V[3] = 0x650a7354U + V[3] + W[2] + ch(V[0], V[1], V[2]) + rotr26(V[0]) + rotr30(V[4]) + ma(V[5], V[6], V[4]); |
||||
|
||||
V[6] += 0x766a0abbU + V[2] + W[3] + ch(V[7], V[0], V[1]) + rotr26(V[7]); |
||||
V[2] = 0x766a0abbU + V[2] + W[3] + ch(V[7], V[0], V[1]) + rotr26(V[7]) + rotr30(V[3]) + ma(V[4], V[5], V[3]); |
||||
|
||||
V[5] += 0x81c2c92eU + V[1] + W[4] + ch(V[6], V[7], V[0]) + rotr26(V[6]); |
||||
V[1] = 0x81c2c92eU + V[1] + W[4] + ch(V[6], V[7], V[0]) + rotr26(V[6]) + rotr30(V[2]) + ma(V[3], V[4], V[2]); |
||||
|
||||
V[4] += 0x92722c85U + V[0] + W[5] + ch(V[5], V[6], V[7]) + rotr26(V[5]); |
||||
V[0] = 0x92722c85U + V[0] + W[5] + ch(V[5], V[6], V[7]) + rotr26(V[5]) + rotr30(V[1]) + ma(V[2], V[3], V[1]); |
||||
|
||||
V[3] += 0xa2bfe8a1U + V[7] + W[6] + ch(V[4], V[5], V[6]) + rotr26(V[4]); |
||||
V[7] = 0xa2bfe8a1U + V[7] + W[6] + ch(V[4], V[5], V[6]) + rotr26(V[4]) + rotr30(V[0]) + ma(V[1], V[2], V[0]); |
||||
|
||||
V[2] += 0xa81a664bU + V[6] + W[7] + ch(V[3], V[4], V[5]) + rotr26(V[3]); |
||||
V[6] = 0xa81a664bU + V[6] + W[7] + ch(V[3], V[4], V[5]) + rotr26(V[3]) + rotr30(V[7]) + ma(V[0], V[1], V[7]); |
||||
|
||||
V[1] += 0xc24b8b70U + V[5] + W[8] + ch(V[2], V[3], V[4]) + rotr26(V[2]); |
||||
V[5] = 0xc24b8b70U + V[5] + W[8] + ch(V[2], V[3], V[4]) + rotr26(V[2]) + rotr30(V[6]) + ma(V[7], V[0], V[6]); |
||||
|
||||
V[0] += 0xc76c51a3U + V[4] + W[9] + ch(V[1], V[2], V[3]) + rotr26(V[1]); |
||||
V[4] = 0xc76c51a3U + V[4] + W[9] + ch(V[1], V[2], V[3]) + rotr26(V[1]) + rotr30(V[5]) + ma(V[6], V[7], V[5]); |
||||
|
||||
V[7] += 0xd192e819U + V[3] + W[10] + ch(V[0], V[1], V[2]) + rotr26(V[0]); |
||||
V[3] = 0xd192e819U + V[3] + W[10] + ch(V[0], V[1], V[2]) + rotr26(V[0]) + rotr30(V[4]) + ma(V[5], V[6], V[4]); |
||||
|
||||
V[6] += 0xd6990624U + V[2] + W[11] + ch(V[7], V[0], V[1]) + rotr26(V[7]); |
||||
V[2] = 0xd6990624U + V[2] + W[11] + ch(V[7], V[0], V[1]) + rotr26(V[7]) + rotr30(V[3]) + ma(V[4], V[5], V[3]); |
||||
|
||||
V[5] += 0xf40e3585U + V[1] + W[12] + ch(V[6], V[7], V[0]) + rotr26(V[6]); |
||||
V[1] = 0xf40e3585U + V[1] + W[12] + ch(V[6], V[7], V[0]) + rotr26(V[6]) + rotr30(V[2]) + ma(V[3], V[4], V[2]); |
||||
|
||||
V[4] += 0x106aa070U + V[0] + W[13] + ch(V[5], V[6], V[7]) + rotr26(V[5]); |
||||
V[0] = 0x106aa070U + V[0] + W[13] + ch(V[5], V[6], V[7]) + rotr26(V[5]) + rotr30(V[1]) + ma(V[2], V[3], V[1]); |
||||
|
||||
V[3] += 0x19a4c116U + V[7] + W[14] + ch(V[4], V[5], V[6]) + rotr26(V[4]); |
||||
V[7] = 0x19a4c116U + V[7] + W[14] + ch(V[4], V[5], V[6]) + rotr26(V[4]) + rotr30(V[0]) + ma(V[1], V[2], V[0]); |
||||
|
||||
V[2] += 0x1e376c08U + V[6] + W[15] + ch(V[3], V[4], V[5]) + rotr26(V[3]); |
||||
V[6] = 0x1e376c08U + V[6] + W[15] + ch(V[3], V[4], V[5]) + rotr26(V[3]) + rotr30(V[7]) + ma(V[0], V[1], V[7]); |
||||
|
||||
//---------------------------------------------------------------------------------- |
||||
|
||||
W[0] = W[0] + W[9] + rotr15(W[14]) + rotr25( W[1]); |
||||
W[1] = W[1] + W[10] + rotr15(W[15]) + rotr25( W[2]); |
||||
W[2] = W[2] + W[11] + rotr15( W[0]) + rotr25( W[3]); |
||||
W[3] = W[3] + W[12] + rotr15( W[1]) + rotr25( W[4]); |
||||
W[4] = W[4] + W[13] + rotr15( W[2]) + rotr25( W[5]); |
||||
W[5] = W[5] + W[14] + rotr15( W[3]) + rotr25( W[6]); |
||||
W[6] = W[6] + W[15] + rotr15( W[4]) + rotr25( W[7]); |
||||
W[7] = W[7] + W[0] + rotr15( W[5]) + rotr25( W[8]); |
||||
W[8] = W[8] + W[1] + rotr15( W[6]) + rotr25( W[9]); |
||||
W[9] = W[9] + W[2] + rotr15( W[7]) + rotr25(W[10]); |
||||
W[10] = W[10] + W[3] + rotr15( W[8]) + rotr25(W[11]); |
||||
W[11] = W[11] + W[4] + rotr15( W[9]) + rotr25(W[12]); |
||||
W[12] = W[12] + W[5] + rotr15(W[10]) + rotr25(W[13]); |
||||
W[13] = W[13] + W[6] + rotr15(W[11]) + rotr25(W[14]); |
||||
|
||||
V[1] += 0x2748774cU + V[5] + W[0] + ch(V[2], V[3], V[4]) + rotr26(V[2]); |
||||
V[5] = 0x2748774cU + V[5] + W[0] + ch(V[2], V[3], V[4]) + rotr26(V[2]) + rotr30(V[6]) + ma(V[7], V[0], V[6]); |
||||
|
||||
V[0] += 0x34b0bcb5U + V[4] + W[1] + ch(V[1], V[2], V[3]) + rotr26(V[1]); |
||||
V[4] = 0x34b0bcb5U + V[4] + W[1] + ch(V[1], V[2], V[3]) + rotr26(V[1]) + rotr30(V[5]) + ma(V[6], V[7], V[5]); |
||||
|
||||
V[7] += 0x391c0cb3U + V[3] + W[2] + ch(V[0], V[1], V[2]) + rotr26(V[0]); |
||||
V[3] = 0x391c0cb3U + V[3] + W[2] + ch(V[0], V[1], V[2]) + rotr26(V[0]) + rotr30(V[4]) + ma(V[5], V[6], V[4]); |
||||
|
||||
V[6] += 0x4ed8aa4aU + V[2] + W[3] + ch(V[7], V[0], V[1]) + rotr26(V[7]); |
||||
V[2] = 0x4ed8aa4aU + V[2] + W[3] + ch(V[7], V[0], V[1]) + rotr26(V[7]) + rotr30(V[3]) + ma(V[4], V[5], V[3]); |
||||
|
||||
V[5] += 0x5b9cca4fU + V[1] + W[4] + ch(V[6], V[7], V[0]) + rotr26(V[6]); |
||||
V[1] = 0x5b9cca4fU + V[1] + W[4] + ch(V[6], V[7], V[0]) + rotr26(V[6]) + rotr30(V[2]) + ma(V[3], V[4], V[2]); |
||||
|
||||
V[4] += 0x682e6ff3U + V[0] + W[5] + ch(V[5], V[6], V[7]) + rotr26(V[5]); |
||||
V[0] = 0x682e6ff3U + V[0] + W[5] + ch(V[5], V[6], V[7]) + rotr26(V[5]) + rotr30(V[1]) + ma(V[2], V[3], V[1]); |
||||
|
||||
V[3] += 0x748f82eeU + V[7] + W[6] + ch(V[4], V[5], V[6]) + rotr26(V[4]); |
||||
V[7] = 0x748f82eeU + V[7] + W[6] + ch(V[4], V[5], V[6]) + rotr26(V[4]) + rotr30(V[0]) + ma(V[1], V[2], V[0]); |
||||
|
||||
V[2] += 0x78a5636fU + V[6] + W[7] + ch(V[3], V[4], V[5]) + rotr26(V[3]); |
||||
V[6] = 0x78a5636fU + V[6] + W[7] + ch(V[3], V[4], V[5]) + rotr26(V[3]) + rotr30(V[7]) + ma(V[0], V[1], V[7]); |
||||
|
||||
V[1] += 0x84c87814U + V[5] + W[8] + ch(V[2], V[3], V[4]) + rotr26(V[2]); |
||||
V[5] = 0x84c87814U + V[5] + W[8] + ch(V[2], V[3], V[4]) + rotr26(V[2]) + rotr30(V[6]) + ma(V[7], V[0], V[6]); |
||||
|
||||
V[0] += 0x8cc70208U + V[4] + W[9] + ch(V[1], V[2], V[3]) + rotr26(V[1]); |
||||
V[4] = 0x8cc70208U + V[4] + W[9] + ch(V[1], V[2], V[3]) + rotr26(V[1]) + rotr30(V[5]) + ma(V[6], V[7], V[5]); |
||||
|
||||
V[7] += 0x90befffaU + V[3] + W[10] + ch(V[0], V[1], V[2]) + rotr26(V[0]); |
||||
V[3] = 0x90befffaU + V[3] + W[10] + ch(V[0], V[1], V[2]) + rotr26(V[0]) + rotr30(V[4]) + ma(V[5], V[6], V[4]); |
||||
|
||||
V[6] += 0xa4506cebU + V[2] + W[11] + ch(V[7], V[0], V[1]) + rotr26(V[7]); |
||||
V[2] = 0xa4506cebU + V[2] + W[11] + ch(V[7], V[0], V[1]) + rotr26(V[7]) + rotr30(V[3]) + ma(V[4], V[5], V[3]); |
||||
|
||||
V[5] += 0xbef9a3f7U + V[1] + W[12] + ch(V[6], V[7], V[0]) + rotr26(V[6]); |
||||
V[1] = 0xbef9a3f7U + V[1] + W[12] + ch(V[6], V[7], V[0]) + rotr26(V[6]) + rotr30(V[2]) + ma(V[3], V[4], V[2]); |
||||
|
||||
V[4] += 0xc67178f2U + V[0] + W[13] + ch(V[5], V[6], V[7]) + rotr26(V[5]); |
||||
V[0] = 0xc67178f2U + V[0] + W[13] + ch(V[5], V[6], V[7]) + rotr26(V[5]) + rotr30(V[1]) + ma(V[2], V[3], V[1]); |
||||
|
||||
//---------------------------------------------------------------------------------- |
||||
|
||||
W[0] = state0 + V[0] + rotr25(state1 + V[1]); |
||||
W[1] = state1 + V[1] + 0x00a00000U + rotr25(state2 + V[2]); |
||||
W[2] = state2 + V[2] + rotr15(W[0]) + rotr25(state3 + V[3]); |
||||
W[3] = state3 + V[3] + rotr15(W[1]) + rotr25(state4 + V[4]); |
||||
W[4] = state4 + V[4] + rotr15(W[2]) + rotr25(state5 + V[5]); |
||||
W[5] = state5 + V[5] + rotr15(W[3]) + rotr25(state6 + V[6]); |
||||
W[6] = state6 + V[6] + 0x00000100U + rotr15(W[4]) + rotr25(state7 + V[7]); |
||||
W[7] = state7 + V[7] + W[0] + 0x11002000U + rotr15(W[5]); |
||||
W[8] = W[1] + 0x80000000U + rotr15(W[6]); |
||||
W[9] = W[2] + rotr15(W[7]); |
||||
W[10] = W[3] + rotr15(W[8]); |
||||
W[11] = W[4] + rotr15(W[9]); |
||||
W[12] = W[5] + rotr15(W[10]); |
||||
W[13] = W[6] + rotr15(W[11]); |
||||
W[14] = W[7] + 0x00400022U + rotr15(W[12]); |
||||
W[15] = W[8] + 0x00000100U + rotr15(W[13]) + rotr25(W[0]); |
||||
|
||||
// 0x71374491U + 0x1f83d9abU + state1 |
||||
const u state1AaddV1 = state1A + V[1]; |
||||
// 0xb5c0fbcfU + 0x9b05688cU + state2 |
||||
const u state2AaddV2 = state2A + V[2]; |
||||
// 0x510e527fU + 0xe9b5dba5U + state3 |
||||
const u state3AaddV3 = state3A + V[3]; |
||||
// 0x3956c25bU + state4 |
||||
const u state4AaddV4 = state4A + V[4]; |
||||
// 0x59f111f1U + state5 |
||||
const u state5AaddV5 = state5A + V[5]; |
||||
// 0x923f82a4U + state6 |
||||
const u state6AaddV6 = state6A + V[6]; |
||||
// 0xab1c5ed5U + state7 |
||||
const u state7AaddV7 = state7A + V[7]; |
||||
|
||||
// 0x98c7e2a2U + state0 |
||||
V[3] = state0A + V[0]; |
||||
// 0xfc08884dU + state0 |
||||
V[7] = state0B + V[0]; |
||||
V[0] = 0x6a09e667U; |
||||
V[1] = 0xbb67ae85U; |
||||
V[2] = 0x3c6ef372U; |
||||
V[4] = 0x510e527fU; |
||||
V[5] = 0x9b05688cU; |
||||
V[6] = 0x1f83d9abU; |
||||
|
||||
V[2] += state1AaddV1 + ch(V[3], V[4], V[5]) + rotr26(V[3]); |
||||
V[6] = state1AaddV1 + ch(V[3], V[4], V[5]) + rotr26(V[3]) + rotr30(V[7]) + ma(V[0], V[1], V[7]); |
||||
|
||||
V[1] += state2AaddV2 + ch(V[2], V[3], V[4]) + rotr26(V[2]); |
||||
V[5] = state2AaddV2 + ch(V[2], V[3], V[4]) + rotr26(V[2]) + rotr30(V[6]) + ma(V[7], V[0], V[6]); |
||||
|
||||
V[0] += state3AaddV3 + ch(V[1], V[2], V[3]) + rotr26(V[1]); |
||||
V[4] = state3AaddV3 + ch(V[1], V[2], V[3]) + rotr26(V[1]) + rotr30(V[5]) + ma(V[6], V[7], V[5]); |
||||
|
||||
V[7] += state4AaddV4 + V[3] + ch(V[0], V[1], V[2]) + rotr26(V[0]); |
||||
V[3] = state4AaddV4 + V[3] + ch(V[0], V[1], V[2]) + rotr26(V[0]) + rotr30(V[4]) + ma(V[5], V[6], V[4]); |
||||
|
||||
V[6] += state5AaddV5 + V[2] + ch(V[7], V[0], V[1]) + rotr26(V[7]); |
||||
V[2] = state5AaddV5 + V[2] + ch(V[7], V[0], V[1]) + rotr26(V[7]) + rotr30(V[3]) + ma(V[4], V[5], V[3]); |
||||
|
||||
V[5] += state6AaddV6 + V[1] + ch(V[6], V[7], V[0]) + rotr26(V[6]); |
||||
V[1] = state6AaddV6 + V[1] + ch(V[6], V[7], V[0]) + rotr26(V[6]) + rotr30(V[2]) + ma(V[3], V[4], V[2]); |
||||
|
||||
V[4] += state7AaddV7 + V[0] + ch(V[5], V[6], V[7]) + rotr26(V[5]); |
||||
V[0] = state7AaddV7 + V[0] + ch(V[5], V[6], V[7]) + rotr26(V[5]) + rotr30(V[1]) + ma(V[2], V[3], V[1]); |
||||
|
||||
V[3] += 0x5807aa98U + V[7] + ch(V[4], V[5], V[6]) + rotr26(V[4]); |
||||
V[7] = 0x5807aa98U + V[7] + ch(V[4], V[5], V[6]) + rotr26(V[4]) + rotr30(V[0]) + ma(V[1], V[2], V[0]); |
||||
|
||||
V[2] += 0x12835b01U + V[6] + ch(V[3], V[4], V[5]) + rotr26(V[3]); |
||||
V[6] = 0x12835b01U + V[6] + ch(V[3], V[4], V[5]) + rotr26(V[3]) + rotr30(V[7]) + ma(V[0], V[1], V[7]); |
||||
|
||||
V[1] += 0x243185beU + V[5] + ch(V[2], V[3], V[4]) + rotr26(V[2]); |
||||
V[5] = 0x243185beU + V[5] + ch(V[2], V[3], V[4]) + rotr26(V[2]) + rotr30(V[6]) + ma(V[7], V[0], V[6]); |
||||
|
||||
V[0] += 0x550c7dc3U + V[4] + ch(V[1], V[2], V[3]) + rotr26(V[1]); |
||||
V[4] = 0x550c7dc3U + V[4] + ch(V[1], V[2], V[3]) + rotr26(V[1]) + rotr30(V[5]) + ma(V[6], V[7], V[5]); |
||||
|
||||
V[7] += 0x72be5d74U + V[3] + ch(V[0], V[1], V[2]) + rotr26(V[0]); |
||||
V[3] = 0x72be5d74U + V[3] + ch(V[0], V[1], V[2]) + rotr26(V[0]) + rotr30(V[4]) + ma(V[5], V[6], V[4]); |
||||
|
||||
V[6] += 0x80deb1feU + V[2] + ch(V[7], V[0], V[1]) + rotr26(V[7]); |
||||
V[2] = 0x80deb1feU + V[2] + ch(V[7], V[0], V[1]) + rotr26(V[7]) + rotr30(V[3]) + ma(V[4], V[5], V[3]); |
||||
|
||||
V[5] += 0x9bdc06a7U + V[1] + ch(V[6], V[7], V[0]) + rotr26(V[6]); |
||||
V[1] = 0x9bdc06a7U + V[1] + ch(V[6], V[7], V[0]) + rotr26(V[6]) + rotr30(V[2]) + ma(V[3], V[4], V[2]); |
||||
|
||||
V[4] += 0xc19bf274U + V[0] + ch(V[5], V[6], V[7]) + rotr26(V[5]); |
||||
V[0] = 0xc19bf274U + V[0] + ch(V[5], V[6], V[7]) + rotr26(V[5]) + rotr30(V[1]) + ma(V[2], V[3], V[1]); |
||||
|
||||
V[3] += 0xe49b69c1U + V[7] + W[0] + ch(V[4], V[5], V[6]) + rotr26(V[4]); |
||||
V[7] = 0xe49b69c1U + V[7] + W[0] + ch(V[4], V[5], V[6]) + rotr26(V[4]) + rotr30(V[0]) + ma(V[1], V[2], V[0]); |
||||
|
||||
V[2] += 0xefbe4786U + V[6] + W[1] + ch(V[3], V[4], V[5]) + rotr26(V[3]); |
||||
V[6] = 0xefbe4786U + V[6] + W[1] + ch(V[3], V[4], V[5]) + rotr26(V[3]) + rotr30(V[7]) + ma(V[0], V[1], V[7]); |
||||
|
||||
V[1] += 0x0fc19dc6U + V[5] + W[2] + ch(V[2], V[3], V[4]) + rotr26(V[2]); |
||||
V[5] = 0x0fc19dc6U + V[5] + W[2] + ch(V[2], V[3], V[4]) + rotr26(V[2]) + rotr30(V[6]) + ma(V[7], V[0], V[6]); |
||||
|
||||
V[0] += 0x240ca1ccU + V[4] + W[3] + ch(V[1], V[2], V[3]) + rotr26(V[1]); |
||||
V[4] = 0x240ca1ccU + V[4] + W[3] + ch(V[1], V[2], V[3]) + rotr26(V[1]) + rotr30(V[5]) + ma(V[6], V[7], V[5]); |
||||
|
||||
V[7] += 0x2de92c6fU + V[3] + W[4] + ch(V[0], V[1], V[2]) + rotr26(V[0]); |
||||
V[3] = 0x2de92c6fU + V[3] + W[4] + ch(V[0], V[1], V[2]) + rotr26(V[0]) + rotr30(V[4]) + ma(V[5], V[6], V[4]); |
||||
|
||||
V[6] += 0x4a7484aaU + V[2] + W[5] + ch(V[7], V[0], V[1]) + rotr26(V[7]); |
||||
V[2] = 0x4a7484aaU + V[2] + W[5] + ch(V[7], V[0], V[1]) + rotr26(V[7]) + rotr30(V[3]) + ma(V[4], V[5], V[3]); |
||||
|
||||
V[5] += 0x5cb0a9dcU + V[1] + W[6] + ch(V[6], V[7], V[0]) + rotr26(V[6]); |
||||
V[1] = 0x5cb0a9dcU + V[1] + W[6] + ch(V[6], V[7], V[0]) + rotr26(V[6]) + rotr30(V[2]) + ma(V[3], V[4], V[2]); |
||||
|
||||
V[4] += 0x76f988daU + V[0] + W[7] + ch(V[5], V[6], V[7]) + rotr26(V[5]); |
||||
V[0] = 0x76f988daU + V[0] + W[7] + ch(V[5], V[6], V[7]) + rotr26(V[5]) + rotr30(V[1]) + ma(V[2], V[3], V[1]); |
||||
|
||||
V[3] += 0x983e5152U + V[7] + W[8] + ch(V[4], V[5], V[6]) + rotr26(V[4]); |
||||
V[7] = 0x983e5152U + V[7] + W[8] + ch(V[4], V[5], V[6]) + rotr26(V[4]) + rotr30(V[0]) + ma(V[1], V[2], V[0]); |
||||
|
||||
V[2] += 0xa831c66dU + V[6] + W[9] + ch(V[3], V[4], V[5]) + rotr26(V[3]); |
||||
V[6] = 0xa831c66dU + V[6] + W[9] + ch(V[3], V[4], V[5]) + rotr26(V[3]) + rotr30(V[7]) + ma(V[0], V[1], V[7]); |
||||
|
||||
V[1] += 0xb00327c8U + V[5] + W[10] + ch(V[2], V[3], V[4]) + rotr26(V[2]); |
||||
V[5] = 0xb00327c8U + V[5] + W[10] + ch(V[2], V[3], V[4]) + rotr26(V[2]) + rotr30(V[6]) + ma(V[7], V[0], V[6]); |
||||
|
||||
V[0] += 0xbf597fc7U + V[4] + W[11] + ch(V[1], V[2], V[3]) + rotr26(V[1]); |
||||
V[4] = 0xbf597fc7U + V[4] + W[11] + ch(V[1], V[2], V[3]) + rotr26(V[1]) + rotr30(V[5]) + ma(V[6], V[7], V[5]); |
||||
|
||||
V[7] += 0xc6e00bf3U + V[3] + W[12] + ch(V[0], V[1], V[2]) + rotr26(V[0]); |
||||
V[3] = 0xc6e00bf3U + V[3] + W[12] + ch(V[0], V[1], V[2]) + rotr26(V[0]) + rotr30(V[4]) + ma(V[5], V[6], V[4]); |
||||
|
||||
V[6] += 0xd5a79147U + V[2] + W[13] + ch(V[7], V[0], V[1]) + rotr26(V[7]); |
||||
V[2] = 0xd5a79147U + V[2] + W[13] + ch(V[7], V[0], V[1]) + rotr26(V[7]) + rotr30(V[3]) + ma(V[4], V[5], V[3]); |
||||
|
||||
V[5] += 0x06ca6351U + V[1] + W[14] + ch(V[6], V[7], V[0]) + rotr26(V[6]); |
||||
V[1] = 0x06ca6351U + V[1] + W[14] + ch(V[6], V[7], V[0]) + rotr26(V[6]) + rotr30(V[2]) + ma(V[3], V[4], V[2]); |
||||
|
||||
V[4] += 0x14292967U + V[0] + W[15] + ch(V[5], V[6], V[7]) + rotr26(V[5]); |
||||
V[0] = 0x14292967U + V[0] + W[15] + ch(V[5], V[6], V[7]) + rotr26(V[5]) + rotr30(V[1]) + ma(V[2], V[3], V[1]); |
||||
|
||||
//---------------------------------------------------------------------------------- |
||||
|
||||
W[0] = W[0] + W[9] + rotr15(W[14]) + rotr25( W[1]); |
||||
W[1] = W[1] + W[10] + rotr15(W[15]) + rotr25( W[2]); |
||||
W[2] = W[2] + W[11] + rotr15( W[0]) + rotr25( W[3]); |
||||
W[3] = W[3] + W[12] + rotr15( W[1]) + rotr25( W[4]); |
||||
W[4] = W[4] + W[13] + rotr15( W[2]) + rotr25( W[5]); |
||||
W[5] = W[5] + W[14] + rotr15( W[3]) + rotr25( W[6]); |
||||
W[6] = W[6] + W[15] + rotr15( W[4]) + rotr25( W[7]); |
||||
W[7] = W[7] + W[0] + rotr15( W[5]) + rotr25( W[8]); |
||||
W[8] = W[8] + W[1] + rotr15( W[6]) + rotr25( W[9]); |
||||
W[9] = W[9] + W[2] + rotr15( W[7]) + rotr25(W[10]); |
||||
W[10] = W[10] + W[3] + rotr15( W[8]) + rotr25(W[11]); |
||||
W[11] = W[11] + W[4] + rotr15( W[9]) + rotr25(W[12]); |
||||
W[12] = W[12] + W[5] + rotr15(W[10]) + rotr25(W[13]); |
||||
W[13] = W[13] + W[6] + rotr15(W[11]) + rotr25(W[14]); |
||||
W[14] = W[14] + W[7] + rotr15(W[12]) + rotr25(W[15]); |
||||
W[15] = W[15] + W[8] + rotr15(W[13]) + rotr25( W[0]); |
||||
|
||||
V[3] += 0x27b70a85U + V[7] + W[0] + ch(V[4], V[5], V[6]) + rotr26(V[4]); |
||||
V[7] = 0x27b70a85U + V[7] + W[0] + ch(V[4], V[5], V[6]) + rotr26(V[4]) + rotr30(V[0]) + ma(V[1], V[2], V[0]); |
||||
|
||||
V[2] += 0x2e1b2138U + V[6] + W[1] + ch(V[3], V[4], V[5]) + rotr26(V[3]); |
||||
V[6] = 0x2e1b2138U + V[6] + W[1] + ch(V[3], V[4], V[5]) + rotr26(V[3]) + rotr30(V[7]) + ma(V[0], V[1], V[7]); |
||||
|
||||
V[1] += 0x4d2c6dfcU + V[5] + W[2] + ch(V[2], V[3], V[4]) + rotr26(V[2]); |
||||
V[5] = 0x4d2c6dfcU + V[5] + W[2] + ch(V[2], V[3], V[4]) + rotr26(V[2]) + rotr30(V[6]) + ma(V[7], V[0], V[6]); |
||||
|
||||
V[0] += 0x53380d13U + V[4] + W[3] + ch(V[1], V[2], V[3]) + rotr26(V[1]); |
||||
V[4] = 0x53380d13U + V[4] + W[3] + ch(V[1], V[2], V[3]) + rotr26(V[1]) + rotr30(V[5]) + ma(V[6], V[7], V[5]); |
||||
|
||||
V[7] += 0x650a7354U + V[3] + W[4] + ch(V[0], V[1], V[2]) + rotr26(V[0]); |
||||
V[3] = 0x650a7354U + V[3] + W[4] + ch(V[0], V[1], V[2]) + rotr26(V[0]) + rotr30(V[4]) + ma(V[5], V[6], V[4]); |
||||
|
||||
V[6] += 0x766a0abbU + V[2] + W[5] + ch(V[7], V[0], V[1]) + rotr26(V[7]); |
||||
V[2] = 0x766a0abbU + V[2] + W[5] + ch(V[7], V[0], V[1]) + rotr26(V[7]) + rotr30(V[3]) + ma(V[4], V[5], V[3]); |
||||
|
||||
V[5] += 0x81c2c92eU + V[1] + W[6] + ch(V[6], V[7], V[0]) + rotr26(V[6]); |
||||
V[1] = 0x81c2c92eU + V[1] + W[6] + ch(V[6], V[7], V[0]) + rotr26(V[6]) + rotr30(V[2]) + ma(V[3], V[4], V[2]); |
||||
|
||||
V[4] += 0x92722c85U + V[0] + W[7] + ch(V[5], V[6], V[7]) + rotr26(V[5]); |
||||
V[0] = 0x92722c85U + V[0] + W[7] + ch(V[5], V[6], V[7]) + rotr26(V[5]) + rotr30(V[1]) + ma(V[2], V[3], V[1]); |
||||
|
||||
V[3] += 0xa2bfe8a1U + V[7] + W[8] + ch(V[4], V[5], V[6]) + rotr26(V[4]); |
||||
V[7] = 0xa2bfe8a1U + V[7] + W[8] + ch(V[4], V[5], V[6]) + rotr26(V[4]) + rotr30(V[0]) + ma(V[1], V[2], V[0]); |
||||
|
||||
V[2] += 0xa81a664bU + V[6] + W[9] + ch(V[3], V[4], V[5]) + rotr26(V[3]); |
||||
V[6] = 0xa81a664bU + V[6] + W[9] + ch(V[3], V[4], V[5]) + rotr26(V[3]) + rotr30(V[7]) + ma(V[0], V[1], V[7]); |
||||
|
||||
V[1] += 0xc24b8b70U + V[5] + W[10] + ch(V[2], V[3], V[4]) + rotr26(V[2]); |
||||
V[5] = 0xc24b8b70U + V[5] + W[10] + ch(V[2], V[3], V[4]) + rotr26(V[2]) + rotr30(V[6]) + ma(V[7], V[0], V[6]); |
||||
|
||||
V[0] += 0xc76c51a3U + V[4] + W[11] + ch(V[1], V[2], V[3]) + rotr26(V[1]); |
||||
V[4] = 0xc76c51a3U + V[4] + W[11] + ch(V[1], V[2], V[3]) + rotr26(V[1]) + rotr30(V[5]) + ma(V[6], V[7], V[5]); |
||||
|
||||
V[7] += 0xd192e819U + V[3] + W[12] + ch(V[0], V[1], V[2]) + rotr26(V[0]); |
||||
V[3] = 0xd192e819U + V[3] + W[12] + ch(V[0], V[1], V[2]) + rotr26(V[0]) + rotr30(V[4]) + ma(V[5], V[6], V[4]); |
||||
|
||||
V[6] += 0xd6990624U + V[2] + W[13] + ch(V[7], V[0], V[1]) + rotr26(V[7]); |
||||
V[2] = 0xd6990624U + V[2] + W[13] + ch(V[7], V[0], V[1]) + rotr26(V[7]) + rotr30(V[3]) + ma(V[4], V[5], V[3]); |
||||
|
||||
V[5] += 0xf40e3585U + V[1] + W[14] + ch(V[6], V[7], V[0]) + rotr26(V[6]); |
||||
V[1] = 0xf40e3585U + V[1] + W[14] + ch(V[6], V[7], V[0]) + rotr26(V[6]) + rotr30(V[2]) + ma(V[3], V[4], V[2]); |
||||
|
||||
V[4] += 0x106aa070U + V[0] + W[15] + ch(V[5], V[6], V[7]) + rotr26(V[5]); |
||||
V[0] = 0x106aa070U + V[0] + W[15] + ch(V[5], V[6], V[7]) + rotr26(V[5]) + rotr30(V[1]) + ma(V[2], V[3], V[1]); |
||||
|
||||
//---------------------------------------------------------------------------------- |
||||
|
||||
W[0] = W[0] + W[9] + rotr15(W[14]) + rotr25( W[1]); |
||||
W[1] = W[1] + W[10] + rotr15(W[15]) + rotr25( W[2]); |
||||
W[2] = W[2] + W[11] + rotr15( W[0]) + rotr25( W[3]); |
||||
W[3] = W[3] + W[12] + rotr15( W[1]) + rotr25( W[4]); |
||||
W[4] = W[4] + W[13] + rotr15( W[2]) + rotr25( W[5]); |
||||
W[5] = W[5] + W[14] + rotr15( W[3]) + rotr25( W[6]); |
||||
W[6] = W[6] + W[15] + rotr15( W[4]) + rotr25( W[7]); |
||||
W[7] = W[7] + W[0] + rotr15( W[5]) + rotr25( W[8]); |
||||
W[8] = W[8] + W[1] + rotr15( W[6]) + rotr25( W[9]); |
||||
W[9] = W[9] + W[2] + rotr15( W[7]) + rotr25(W[10]); |
||||
W[10] = W[10] + W[3] + rotr15( W[8]) + rotr25(W[11]); |
||||
W[11] = W[11] + W[4] + rotr15( W[9]) + rotr25(W[12]); |
||||
W[12] = W[12] + W[5] + rotr15(W[10]) + rotr25(W[13]); |
||||
|
||||
V[3] += 0x19a4c116U + V[7] + W[0] + ch(V[4], V[5], V[6]) + rotr26(V[4]); |
||||
V[7] = 0x19a4c116U + V[7] + W[0] + ch(V[4], V[5], V[6]) + rotr26(V[4]) + rotr30(V[0]) + ma(V[1], V[2], V[0]); |
||||
|
||||
V[2] += 0x1e376c08U + V[6] + W[1] + ch(V[3], V[4], V[5]) + rotr26(V[3]); |
||||
V[6] = 0x1e376c08U + V[6] + W[1] + ch(V[3], V[4], V[5]) + rotr26(V[3]) + rotr30(V[7]) + ma(V[0], V[1], V[7]); |
||||
|
||||
V[1] += 0x2748774cU + V[5] + W[2] + ch(V[2], V[3], V[4]) + rotr26(V[2]); |
||||
V[5] = 0x2748774cU + V[5] + W[2] + ch(V[2], V[3], V[4]) + rotr26(V[2]) + rotr30(V[6]) + ma(V[7], V[0], V[6]); |
||||
|
||||
V[0] += 0x34b0bcb5U + V[4] + W[3] + ch(V[1], V[2], V[3]) + rotr26(V[1]); |
||||
V[4] = 0x34b0bcb5U + V[4] + W[3] + ch(V[1], V[2], V[3]) + rotr26(V[1]) + rotr30(V[5]) + ma(V[6], V[7], V[5]); |
||||
|
||||
V[7] += 0x391c0cb3U + V[3] + W[4] + ch(V[0], V[1], V[2]) + rotr26(V[0]); |
||||
V[3] = 0x391c0cb3U + V[3] + W[4] + ch(V[0], V[1], V[2]) + rotr26(V[0]) + rotr30(V[4]) + ma(V[5], V[6], V[4]); |
||||
|
||||
V[6] += 0x4ed8aa4aU + V[2] + W[5] + ch(V[7], V[0], V[1]) + rotr26(V[7]); |
||||
V[2] = 0x4ed8aa4aU + V[2] + W[5] + ch(V[7], V[0], V[1]) + rotr26(V[7]) + rotr30(V[3]) + ma(V[4], V[5], V[3]); |
||||
|
||||
V[5] += 0x5b9cca4fU + V[1] + W[6] + ch(V[6], V[7], V[0]) + rotr26(V[6]); |
||||
V[1] = 0x5b9cca4fU + V[1] + W[6] + ch(V[6], V[7], V[0]) + rotr26(V[6]) + rotr30(V[2]) + ma(V[3], V[4], V[2]); |
||||
|
||||
V[4] += 0x682e6ff3U + V[0] + W[7] + ch(V[5], V[6], V[7]) + rotr26(V[5]); |
||||
V[0] = 0x682e6ff3U + V[0] + W[7] + ch(V[5], V[6], V[7]) + rotr26(V[5]) + rotr30(V[1]) + ma(V[2], V[3], V[1]); |
||||
|
||||
V[3] += 0x748f82eeU + V[7] + W[8] + ch(V[4], V[5], V[6]) + rotr26(V[4]); |
||||
V[7] = 0x748f82eeU + V[7] + W[8] + ch(V[4], V[5], V[6]) + rotr26(V[4]) + rotr30(V[0]) + ma(V[1], V[2], V[0]); |
||||
|
||||
V[2] += 0x78a5636fU + V[6] + W[9] + ch(V[3], V[4], V[5]) + rotr26(V[3]); |
||||
|
||||
V[1] += 0x84c87814U + V[5] + W[10] + ch(V[2], V[3], V[4]) + rotr26(V[2]); |
||||
|
||||
V[0] += 0x8cc70208U + V[4] + W[11] + ch(V[1], V[2], V[3]) + rotr26(V[1]); |
||||
|
||||
V[7] += V[3] + W[12] + ch(V[0], V[1], V[2]) + rotr26(V[0]); |
||||
|
||||
#define FOUND (0x0F) |
||||
#define SETFOUND(Xnonce) output[output[FOUND]++] = Xnonce |
||||
|
||||
#ifdef VECTORS4 |
||||
if ((V[7].x == 0x136032edU) ^ (V[7].y == 0x136032edU) ^ (V[7].z == 0x136032edU) ^ (V[7].w == 0x136032edU)) { |
||||
if (V[7].x == 0x136032edU) |
||||
SETFOUND(nonce.x); |
||||
if (V[7].y == 0x136032edU) |
||||
SETFOUND(nonce.y); |
||||
if (V[7].z == 0x136032edU) |
||||
SETFOUND(nonce.z); |
||||
if (V[7].w == 0x136032edU) |
||||
SETFOUND(nonce.w); |
||||
} |
||||
#elif defined VECTORS2 |
||||
if ((V[7].x == 0x136032edU) + (V[7].y == 0x136032edU)) { |
||||
if (V[7].x == 0x136032edU) |
||||
SETFOUND(nonce.x); |
||||
if (V[7].y == 0x136032edU) |
||||
SETFOUND(nonce.y); |
||||
} |
||||
#else |
||||
if (V[7] == 0x136032edU) |
||||
SETFOUND(nonce); |
||||
#endif |
||||
} |
@ -1,200 +0,0 @@
@@ -1,200 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 Avalon project |
||||
* Copyright 2013 Con Kolivas <kernel@kolivas.org> |
||||
* |
||||
* 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 AVALON_H |
||||
#define AVALON_H |
||||
|
||||
#ifdef USE_AVALON |
||||
|
||||
#include "util.h" |
||||
|
||||
#define AVALON_RESET_FAULT_DECISECONDS 1 |
||||
#define AVALON_MINER_THREADS 1 |
||||
|
||||
#define AVALON_IO_SPEED 115200 |
||||
#define AVALON_HASH_TIME_FACTOR ((float)1.67/0x32) |
||||
#define AVALON_RESET_PITCH (300*1000*1000) |
||||
|
||||
#define AVALON_FAN_FACTOR 120 |
||||
#define AVALON_PWM_MAX 0xA0 |
||||
#define AVALON_DEFAULT_FAN_MIN 20 |
||||
#define AVALON_DEFAULT_FAN_MAX 100 |
||||
#define AVALON_DEFAULT_FAN_MAX_PWM 0xA0 /* 100% */ |
||||
#define AVALON_DEFAULT_FAN_MIN_PWM 0x20 /* 20% */ |
||||
|
||||
#define AVALON_TEMP_TARGET 50 |
||||
#define AVALON_TEMP_HYSTERESIS 3 |
||||
#define AVALON_TEMP_OVERHEAT 60 |
||||
|
||||
/* Avalon-based BitBurner. */ |
||||
#define BITBURNER_DEFAULT_CORE_VOLTAGE 1200 /* in millivolts */ |
||||
#define BITBURNER_MIN_COREMV 1000 |
||||
/* change here if you want to risk killing it :) */ |
||||
#define BITBURNER_MAX_COREMV 1400 |
||||
|
||||
/* BitFury-based BitBurner. */ |
||||
#define BITBURNER_FURY_DEFAULT_CORE_VOLTAGE 900 /* in millivolts */ |
||||
#define BITBURNER_FURY_MIN_COREMV 700 |
||||
/* change here if you want to risk killing it :) */ |
||||
#define BITBURNER_FURY_MAX_COREMV 1100 |
||||
|
||||
|
||||
#define AVALON_DEFAULT_TIMEOUT 0x2D |
||||
#define AVALON_MIN_FREQUENCY 256 |
||||
#define AVALON_MAX_FREQUENCY 1024 |
||||
#define AVALON_TIMEOUT_FACTOR 12690 |
||||
#define AVALON_DEFAULT_FREQUENCY 282 |
||||
#define AVALON_DEFAULT_MINER_NUM 0x20 |
||||
#define AVALON_MAX_MINER_NUM 0x100 |
||||
#define AVALON_DEFAULT_ASIC_NUM 0xA |
||||
|
||||
/* Default number of miners for Bitburner Fury is for a stack of 8 boards,
|
||||
but it will work acceptably for smaller stacks, too */ |
||||
#define BITBURNER_FURY_DEFAULT_MINER_NUM 128 |
||||
#define BITBURNER_FURY_DEFAULT_FREQUENCY 256 |
||||
#define BITBURNER_FURY_DEFAULT_TIMEOUT 50 |
||||
|
||||
#define AVALON_AUTO_CYCLE 1024 |
||||
|
||||
#define AVALON_FTDI_READSIZE 510 |
||||
#define AVALON_READBUF_SIZE 8192 |
||||
#define AVALON_RESET_TIMEOUT 100 |
||||
#define AVALON_READ_TIMEOUT 18 /* Enough to only half fill the buffer */ |
||||
#define AVALON_LATENCY 1 |
||||
|
||||
struct avalon_task { |
||||
uint8_t reset :1; |
||||
uint8_t flush_fifo :1; |
||||
uint8_t fan_eft :1; |
||||
uint8_t timer_eft :1; |
||||
uint8_t asic_num :4; |
||||
uint8_t fan_pwm_data; |
||||
uint8_t timeout_data; |
||||
uint8_t miner_num; |
||||
|
||||
uint8_t nonce_elf :1; |
||||
uint8_t gate_miner_elf :1; |
||||
uint8_t asic_pll :1; |
||||
uint8_t gate_miner :1; |
||||
uint8_t _pad0 :4; |
||||
uint8_t _pad1[3]; |
||||
uint32_t _pad2; |
||||
|
||||
uint8_t midstate[32]; |
||||
uint8_t data[12]; |
||||
} __attribute__((packed, aligned(4))); |
||||
|
||||
struct avalon_result { |
||||
uint32_t nonce; |
||||
uint8_t data[12]; |
||||
uint8_t midstate[32]; |
||||
|
||||
uint8_t fan0; |
||||
uint8_t fan1; |
||||
uint8_t fan2; |
||||
uint8_t temp0; |
||||
uint8_t temp1; |
||||
uint8_t temp2; |
||||
uint8_t _pad0[2]; |
||||
|
||||
uint16_t fifo_wp; |
||||
uint16_t fifo_rp; |
||||
uint8_t chip_num; |
||||
uint8_t pwm_data; |
||||
uint8_t timeout; |
||||
uint8_t miner_num; |
||||
} __attribute__((packed, aligned(4))); |
||||
|
||||
struct avalon_info { |
||||
int baud; |
||||
int miner_count; |
||||
int asic_count; |
||||
int timeout; |
||||
|
||||
int fan0; |
||||
int fan1; |
||||
int fan2; |
||||
|
||||
int temp0; |
||||
int temp1; |
||||
int temp2; |
||||
int temp_max; |
||||
int temp_history_count; |
||||
int temp_history_index; |
||||
int temp_sum; |
||||
int temp_old; |
||||
int fan_pwm; |
||||
|
||||
int core_voltage; |
||||
|
||||
int no_matching_work; |
||||
int matching_work[AVALON_MAX_MINER_NUM]; |
||||
|
||||
int frequency; |
||||
uint32_t ctlr_ver; |
||||
|
||||
struct thr_info *thr; |
||||
pthread_t read_thr; |
||||
pthread_t write_thr; |
||||
pthread_mutex_t lock; |
||||
pthread_mutex_t qlock; |
||||
cgsem_t qsem; |
||||
int nonces; |
||||
|
||||
int auto_queued; |
||||
int auto_nonces; |
||||
int auto_hw; |
||||
|
||||
int idle; |
||||
bool reset; |
||||
bool overheat; |
||||
bool optimal; |
||||
|
||||
uint8_t version1; |
||||
uint8_t version2; |
||||
uint8_t version3; |
||||
}; |
||||
|
||||
#define BITBURNER_VERSION1 1 |
||||
#define BITBURNER_VERSION2 0 |
||||
#define BITBURNER_VERSION3 0 |
||||
|
||||
#define AVALON_WRITE_SIZE (sizeof(struct avalon_task)) |
||||
#define AVALON_READ_SIZE (sizeof(struct avalon_result)) |
||||
#define AVALON_ARRAY_SIZE 3 |
||||
#define BITBURNER_ARRAY_SIZE 4 |
||||
|
||||
#define AVA_GETS_ERROR -1 |
||||
#define AVA_GETS_OK 0 |
||||
|
||||
#define AVA_SEND_ERROR -1 |
||||
#define AVA_SEND_OK 0 |
||||
|
||||
#define avalon_buffer_full(avalon) !usb_ftdi_cts(avalon) |
||||
|
||||
#define AVALON_READ_TIME(baud) ((double)AVALON_READ_SIZE * (double)8.0 / (double)(baud)) |
||||
#define ASSERT1(condition) __maybe_unused static char sizeof_uint32_t_must_be_4[(condition)?1:-1] |
||||
ASSERT1(sizeof(uint32_t) == 4); |
||||
|
||||
extern struct avalon_info **avalon_info; |
||||
extern int opt_avalon_temp; |
||||
extern int opt_avalon_overheat; |
||||
extern int opt_avalon_fan_min; |
||||
extern int opt_avalon_fan_max; |
||||
extern int opt_avalon_freq_min; |
||||
extern int opt_avalon_freq_max; |
||||
extern bool opt_avalon_auto; |
||||
extern int opt_bitburner_core_voltage; |
||||
extern int opt_bitburner_fury_core_voltage; |
||||
extern char *set_avalon_fan(char *arg); |
||||
extern char *set_avalon_freq(char *arg); |
||||
|
||||
#endif /* USE_AVALON */ |
||||
#endif /* AVALON_H */ |
@ -1,363 +0,0 @@
@@ -1,363 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 Con Kolivas <kernel@kolivas.org> |
||||
* Copyright 2013 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. |
||||
*/ |
||||
|
||||
#ifndef BFLSC_H |
||||
#define BFLSC_H |
||||
#define BLANK "" |
||||
#define LFSTR "<LF>" |
||||
|
||||
/*
|
||||
* Firmware |
||||
* DRV_V2 expects (beyond V1) the GetInfo to return the chip count |
||||
* The queues are 40 instead of 20 and are *usually* consumed and filled |
||||
* in bursts due to e.g. a 16 chip device doing 16 items at a time and |
||||
* returning 16 results at a time |
||||
* If the device has varying chip speeds, it will gradually break up the |
||||
* burst of results as we progress |
||||
*/ |
||||
enum driver_version { |
||||
BFLSC_DRVUNDEF = 0, |
||||
BFLSC_DRV1, |
||||
BFLSC_DRV2 |
||||
}; |
||||
|
||||
/*
|
||||
* With Firmware 1.0.0 and a result queue of 20 the Max is: |
||||
* inprocess = 12 |
||||
* max count = 9 |
||||
* 64+1+24+1+1+(1+8)*8+1 per line = 164 * 20 |
||||
* OK = 3 |
||||
* Total: 3304 |
||||
* |
||||
* With Firmware 1.2.* and a result queue of 40 but a limit of 15 replies: |
||||
* inprocess = 12 |
||||
* max count = 9 |
||||
* 64+1+24+1+1+1+1+(1+8)*8+1 per line = 166 * 15 |
||||
* OK = 3 |
||||
* Total: 2514 |
||||
* |
||||
*/ |
||||
#define BFLSC_BUFSIZ (0x1000) |
||||
|
||||
// Should be big enough
|
||||
#define BFLSC_APPLOGSIZ 8192 |
||||
|
||||
#define BFLSC_INFO_TIMEOUT 999 |
||||
|
||||
#define BFLSC_DI_FIRMWARE "FIRMWARE" |
||||
#define BFLSC_DI_ENGINES "ENGINES" |
||||
#define BFLSC_DI_JOBSINQUE "JOBS IN QUEUE" |
||||
#define BFLSC_DI_XLINKMODE "XLINK MODE" |
||||
#define BFLSC_DI_XLINKPRESENT "XLINK PRESENT" |
||||
#define BFLSC_DI_DEVICESINCHAIN "DEVICES IN CHAIN" |
||||
#define BFLSC_DI_CHAINPRESENCE "CHAIN PRESENCE MASK" |
||||
#define BFLSC_DI_CHIPS "CHIP PARALLELIZATION" |
||||
#define BFLSC_DI_CHIPS_PARALLEL "YES" |
||||
|
||||
#define FULLNONCE 0x100000000ULL |
||||
|
||||
struct bflsc_dev { |
||||
// Work
|
||||
unsigned int ms_work; |
||||
int work_queued; |
||||
int work_complete; |
||||
int nonces_hw; // TODO: this - need to add a paramter to submit_nonce()
|
||||
// so can pass 'dev' to hw_error
|
||||
uint64_t hashes_unsent; |
||||
uint64_t hashes_sent; |
||||
uint64_t nonces_found; |
||||
|
||||
struct timeval last_check_result; |
||||
struct timeval last_dev_result; // array > 0
|
||||
struct timeval last_nonce_result; // > 0 nonce
|
||||
|
||||
// Info
|
||||
char getinfo[(BFLSC_BUFSIZ+4)*4]; |
||||
char *firmware; |
||||
int engines; // each engine represents a 'thread' in a chip
|
||||
char *xlink_mode; |
||||
char *xlink_present; |
||||
char *chips; |
||||
|
||||
// Status
|
||||
bool dead; // TODO: handle seperate x-link devices failing?
|
||||
bool overheat; |
||||
|
||||
// Stats
|
||||
float temp1; |
||||
float temp2; |
||||
float vcc1; |
||||
float vcc2; |
||||
float vmain; |
||||
float temp1_max; |
||||
float temp2_max; |
||||
time_t temp1_max_time; |
||||
time_t temp2_max_time; |
||||
float temp1_5min_av; // TODO:
|
||||
float temp2_5min_av; // TODO:
|
||||
|
||||
// To handle the fact that flushing the queue may not remove all work
|
||||
// (normally one item is still being processed)
|
||||
// and also that once the queue is flushed, results may still be in
|
||||
// the output queue - but we don't want to process them at the time of doing an LP
|
||||
// when result_id > flush_id+1, flushed work can be discarded since it
|
||||
// is no longer in the device
|
||||
uint64_t flush_id; // counter when results were last flushed
|
||||
uint64_t result_id; // counter when results were last checked
|
||||
bool flushed; // are any flushed?
|
||||
}; |
||||
|
||||
#define QUE_MAX_RESULTS 8 |
||||
|
||||
struct bflsc_info { |
||||
enum driver_version driver_version; |
||||
pthread_rwlock_t stat_lock; |
||||
struct thr_info results_thr; |
||||
uint64_t hashes_sent; |
||||
uint32_t update_count; |
||||
struct timeval last_update; |
||||
int sc_count; |
||||
struct bflsc_dev *sc_devs; |
||||
unsigned int scan_sleep_time; |
||||
unsigned int results_sleep_time; |
||||
unsigned int default_ms_work; |
||||
bool shutdown; |
||||
bool flash_led; |
||||
bool not_first_work; // allow ignoring the first nonce error
|
||||
bool fanauto; |
||||
int que_size; |
||||
int que_full_enough; |
||||
int que_watermark; |
||||
int que_low; |
||||
int que_noncecount; |
||||
int que_fld_min; |
||||
int que_fld_max; |
||||
int flush_size; |
||||
// count of given size, [+2] is for any > QUE_MAX_RESULTS
|
||||
uint64_t result_size[QUE_MAX_RESULTS+2]; |
||||
}; |
||||
|
||||
#define BFLSC_XLINKHDR '@' |
||||
#define BFLSC_MAXPAYLOAD 255 |
||||
|
||||
struct DataForwardToChain { |
||||
uint8_t header; |
||||
uint8_t payloadSize; |
||||
uint8_t deviceAddress; |
||||
uint8_t payloadData[BFLSC_MAXPAYLOAD]; |
||||
}; |
||||
|
||||
#define DATAFORWARDSIZE(data) (1 + 1 + 1 + data.payloadSize) |
||||
|
||||
#define MIDSTATE_BYTES 32 |
||||
#define MERKLE_OFFSET 64 |
||||
#define MERKLE_BYTES 12 |
||||
#define BFLSC_QJOBSIZ (MIDSTATE_BYTES+MERKLE_BYTES+1) |
||||
#define BFLSC_EOB 0xaa |
||||
|
||||
struct QueueJobStructure { |
||||
uint8_t payloadSize; |
||||
uint8_t midState[MIDSTATE_BYTES]; |
||||
uint8_t blockData[MERKLE_BYTES]; |
||||
uint8_t endOfBlock; |
||||
}; |
||||
|
||||
#define QUE_RES_LINES_MIN 3 |
||||
#define QUE_MIDSTATE 0 |
||||
#define QUE_BLOCKDATA 1 |
||||
|
||||
#define QUE_NONCECOUNT_V1 2 |
||||
#define QUE_FLD_MIN_V1 3 |
||||
#define QUE_FLD_MAX_V1 (QUE_MAX_RESULTS+QUE_FLD_MIN_V1) |
||||
|
||||
#define QUE_CHIP_V2 2 |
||||
#define QUE_NONCECOUNT_V2 3 |
||||
#define QUE_FLD_MIN_V2 4 |
||||
#define QUE_FLD_MAX_V2 (QUE_MAX_RESULTS+QUE_FLD_MIN_V2) |
||||
|
||||
#define BFLSC_SIGNATURE 0xc1 |
||||
#define BFLSC_EOW 0xfe |
||||
|
||||
// N.B. this will only work with 5 jobs
|
||||
// requires a different jobs[N] for each job count
|
||||
// but really only need to handle 5 anyway
|
||||
struct QueueJobPackStructure { |
||||
uint8_t payloadSize; |
||||
uint8_t signature; |
||||
uint8_t jobsInArray; |
||||
struct QueueJobStructure jobs[5]; |
||||
uint8_t endOfWrapper; |
||||
}; |
||||
|
||||
// TODO: Implement in API and also in usb device selection
|
||||
struct SaveString { |
||||
uint8_t payloadSize; |
||||
uint8_t payloadData[BFLSC_MAXPAYLOAD]; |
||||
}; |
||||
|
||||
// Commands (Single Stage)
|
||||
#define BFLSC_IDENTIFY "ZGX" |
||||
#define BFLSC_IDENTIFY_LEN (sizeof(BFLSC_IDENTIFY)-1) |
||||
#define BFLSC_DETAILS "ZCX" |
||||
#define BFLSC_DETAILS_LEN (sizeof(BFLSC_DETAILS)-1) |
||||
#define BFLSC_FIRMWARE "ZJX" |
||||
#define BFLSC_FIRMWARE_LEN (sizeof(BFLSC_FIRMWARE)-1) |
||||
#define BFLSC_FLASH "ZMX" |
||||
#define BFLSC_FLASH_LEN (sizeof(BFLSC_FLASH)-1) |
||||
#define BFLSC_VOLTAGE "ZTX" |
||||
#define BFLSC_VOLTAGE_LEN (sizeof(BFLSC_VOLTAGE)-1) |
||||
#define BFLSC_TEMPERATURE "ZLX" |
||||
#define BFLSC_TEMPERATURE_LEN (sizeof(BFLSC_TEMPERATURE)-1) |
||||
#define BFLSC_QRES "ZOX" |
||||
#define BFLSC_QRES_LEN (sizeof(BFLSC_QRES)-1) |
||||
#define BFLSC_QFLUSH "ZQX" |
||||
#define BFLSC_QFLUSH_LEN (sizeof(BFLSC_QFLUSH)-1) |
||||
#define BFLSC_FANAUTO "Z9X" |
||||
#define BFLSC_FANOUT_LEN (sizeof(BFLSC_FANAUTO)-1) |
||||
#define BFLSC_FAN0 "Z0X" |
||||
#define BFLSC_FAN0_LEN (sizeof(BFLSC_FAN0)-1) |
||||
#define BFLSC_FAN1 "Z1X" |
||||
#define BFLSC_FAN1_LEN (sizeof(BFLSC_FAN1)-1) |
||||
#define BFLSC_FAN2 "Z2X" |
||||
#define BFLSC_FAN2_LEN (sizeof(BFLSC_FAN2)-1) |
||||
#define BFLSC_FAN3 "Z3X" |
||||
#define BFLSC_FAN3_LEN (sizeof(BFLSC_FAN3)-1) |
||||
#define BFLSC_FAN4 "Z4X" |
||||
#define BFLSC_FAN4_LEN (sizeof(BFLSC_FAN4)-1) |
||||
#define BFLSC_LOADSTR "ZUX" |
||||
#define BFLSC_LOADSTR_LEN (sizeof(BFLSC_LOADSTR)-1) |
||||
|
||||
// Commands (Dual Stage)
|
||||
#define BFLSC_QJOB "ZNX" |
||||
#define BFLSC_QJOB_LEN (sizeof(BFLSC_QJOB)-1) |
||||
#define BFLSC_QJOBS "ZWX" |
||||
#define BFLSC_QJOBS_LEN (sizeof(BFLSC_QJOBS)-1) |
||||
#define BFLSC_SAVESTR "ZSX" |
||||
#define BFLSC_SAVESTR_LEN (sizeof(BFLSC_SAVESTR)-1) |
||||
|
||||
// Replies
|
||||
#define BFLSC_IDENTITY "BitFORCE SC" |
||||
#define BFLSC_BFLSC "SHA256 SC" |
||||
|
||||
#define BFLSC_OK "OK\n" |
||||
#define BFLSC_OK_LEN (sizeof(BFLSC_OK)-1) |
||||
#define BFLSC_SUCCESS "SUCCESS\n" |
||||
#define BFLSC_SUCCESS_LEN (sizeof(BFLSC_SUCCESS)-1) |
||||
|
||||
#define BFLSC_RESULT "COUNT:" |
||||
#define BFLSC_RESULT_LEN (sizeof(BFLSC_RESULT)-1) |
||||
|
||||
#define BFLSC_ANERR "ERR:" |
||||
#define BFLSC_ANERR_LEN (sizeof(BFLSC_ANERR)-1) |
||||
#define BFLSC_TIMEOUT BFLSC_ANERR "TIMEOUT" |
||||
#define BFLSC_TIMEOUT_LEN (sizeof(BFLSC_TIMEOUT)-1) |
||||
// x-link timeout has a space (a number follows)
|
||||
#define BFLSC_XTIMEOUT BFLSC_ANERR "TIMEOUT " |
||||
#define BFLSC_XTIMEOUT_LEN (sizeof(BFLSC_XTIMEOUT)-1) |
||||
#define BFLSC_INVALID BFLSC_ANERR "INVALID DATA" |
||||
#define BFLSC_INVALID_LEN (sizeof(BFLSC_INVALID)-1) |
||||
#define BFLSC_ERRSIG BFLSC_ANERR "SIGNATURE" |
||||
#define BFLSC_ERRSIG_LEN (sizeof(BFLSC_ERRSIG)-1) |
||||
#define BFLSC_OKQ "OK:QUEUED" |
||||
#define BFLSC_OKQ_LEN (sizeof(BFLSC_OKQ)-1) |
||||
#define BFLSC_INPROCESS "INPROCESS" |
||||
#define BFLSC_INPROCESS_LEN (sizeof(BFLSC_INPROCESS)-1) |
||||
// Followed by N=1..5
|
||||
#define BFLSC_OKQN "OK:QUEUED " |
||||
#define BFLSC_OKQN_LEN (sizeof(BFLSC_OKQN)-1) |
||||
#define BFLSC_QFULL "QUEUE FULL" |
||||
#define BFLSC_QFULL_LEN (sizeof(BFLSC_QFULL)-1) |
||||
#define BFLSC_HITEMP "HIGH TEMPERATURE RECOVERY" |
||||
#define BFLSC_HITEMP_LEN (sizeof(BFLSC_HITEMP)-1) |
||||
#define BFLSC_EMPTYSTR "MEMORY EMPTY" |
||||
#define BFLSC_EMPTYSTR_LEN (sizeof(BFLSC_EMPTYSTR)-1) |
||||
|
||||
// Queued and non-queued are the same
|
||||
#define FullNonceRangeJob QueueJobStructure |
||||
#define BFLSC_JOBSIZ BFLSC_QJOBSIZ |
||||
|
||||
// Non queued commands (not used)
|
||||
#define BFLSC_SENDWORK "ZDX" |
||||
#define BFLSC_SENDWORK_LEN (sizeof(BFLSC_SENDWORK)-1) |
||||
#define BFLSC_WORKSTATUS "ZFX" |
||||
#define BFLSC_WORKSTATUS_LEN (sizeof(BFLSC_WORKSTATUS)-1) |
||||
#define BFLSC_SENDRANGE "ZPX" |
||||
#define BFLSC_SENDRANGE_LEN (sizeof(BFLSC_SENDRANGE)-1) |
||||
|
||||
// Non queued work replies (not used)
|
||||
#define BFLSC_NONCE "NONCE-FOUND:" |
||||
#define BFLSC_NONCE_LEN (sizeof(BFLSC_NONCE)-1) |
||||
#define BFLSC_NO_NONCE "NO-NONCE" |
||||
#define BFLSC_NO_NONCE_LEN (sizeof(BFLSC_NO_NONCE)-1) |
||||
#define BFLSC_IDLE "IDLE" |
||||
#define BFLSC_IDLE_LEN (sizeof(BFLSC_IDLE)-1) |
||||
#define BFLSC_BUSY "BUSY" |
||||
#define BFLSC_BUSY_LEN (sizeof(BFLSC_BUSY)-1) |
||||
|
||||
#define BFLSC_MINIRIG "BAM" |
||||
#define BFLSC_SINGLE "BAS" |
||||
#define BFLSC_LITTLESINGLE "BAL" |
||||
#define BFLSC_JALAPENO "BAJ" |
||||
|
||||
// Default expected time for a nonce range
|
||||
// - thus no need to check until this + last time work was found
|
||||
// 60GH/s MiniRig (1 board) or Single
|
||||
#define BAM_WORK_TIME 71.58 |
||||
#define BAS_WORK_TIME 71.58 |
||||
// 30GH/s Little Single
|
||||
#define BAL_WORK_TIME 143.17 |
||||
// 4.5GH/s Jalapeno
|
||||
#define BAJ_WORK_TIME 954.44 |
||||
|
||||
// Defaults (slightly over half the work time) but ensure none are above 100
|
||||
// SCAN_TIME - delay after sending work
|
||||
// RES_TIME - delay between checking for results
|
||||
#define BAM_SCAN_TIME 20 |
||||
#define BAS_SCAN_TIME 360 |
||||
#define BAL_SCAN_TIME 720 |
||||
#define BAJ_SCAN_TIME 1000 |
||||
#define BFLSC_RES_TIME 100 |
||||
#define BFLSC_MAX_SLEEP 2000 |
||||
|
||||
#define BAJ_LATENCY LATENCY_STD |
||||
#define BAL_LATENCY 12 |
||||
#define BAS_LATENCY 12 |
||||
// For now a BAM doesn't really exist - it's currently 8 independent BASs
|
||||
#define BAM_LATENCY 2 |
||||
|
||||
#define BFLSC_TEMP_SLEEPMS 5 |
||||
|
||||
#define BFLSC_QUE_SIZE_V1 20 |
||||
#define BFLSC_QUE_FULL_ENOUGH_V1 13 |
||||
#define BFLSC_QUE_WATERMARK_V1 6 |
||||
#define BFLSC_QUE_LOW_V1 3 |
||||
|
||||
// TODO: use 5 batch jobs
|
||||
// TODO: base these numbers on the chip count?
|
||||
#define BFLSC_QUE_SIZE_V2 40 |
||||
#define BFLSC_QUE_FULL_ENOUGH_V2 36 |
||||
#define BFLSC_QUE_WATERMARK_V2 32 |
||||
#define BFLSC_QUE_LOW_V2 16 |
||||
|
||||
#define BFLSC_TEMP_OVERHEAT 90 |
||||
// Must drop this far below cutoff before resuming work
|
||||
#define BFLSC_TEMP_RECOVER 5 |
||||
|
||||
// If initialisation fails the first time,
|
||||
// sleep this amount (ms) and try again
|
||||
#define REINIT_TIME_FIRST_MS 100 |
||||
// Max ms per sleep
|
||||
#define REINIT_TIME_MAX_MS 800 |
||||
// Keep trying up to this many us
|
||||
#define REINIT_TIME_MAX 3000000 |
||||
|
||||
int opt_bflsc_overheat; |
||||
|
||||
#endif /* BFLSC_H */ |
@ -1,756 +0,0 @@
@@ -1,756 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 Andrew Smith |
||||
* Copyright 2012 Luke Dashjr |
||||
* Copyright 2012 Con Kolivas |
||||
* |
||||
* 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 <stdint.h> |
||||
#include <stdio.h> |
||||
#include <strings.h> |
||||
#include <sys/time.h> |
||||
#include <unistd.h> |
||||
|
||||
#include "compat.h" |
||||
#include "miner.h" |
||||
#include "usbutils.h" |
||||
#include "util.h" |
||||
|
||||
#ifdef WIN32 |
||||
#include <windows.h> |
||||
#endif /* WIN32 */ |
||||
|
||||
#define BITFORCE_IDENTIFY "ZGX" |
||||
#define BITFORCE_IDENTIFY_LEN (sizeof(BITFORCE_IDENTIFY)-1) |
||||
#define BITFORCE_FLASH "ZMX" |
||||
#define BITFORCE_FLASH_LEN (sizeof(BITFORCE_FLASH)-1) |
||||
#define BITFORCE_TEMPERATURE "ZLX" |
||||
#define BITFORCE_TEMPERATURE_LEN (sizeof(BITFORCE_TEMPERATURE)-1) |
||||
#define BITFORCE_SENDRANGE "ZPX" |
||||
#define BITFORCE_SENDRANGE_LEN (sizeof(BITFORCE_SENDRANGE)-1) |
||||
#define BITFORCE_SENDWORK "ZDX" |
||||
#define BITFORCE_SENDWORK_LEN (sizeof(BITFORCE_SENDWORK)-1) |
||||
#define BITFORCE_WORKSTATUS "ZFX" |
||||
#define BITFORCE_WORKSTATUS_LEN (sizeof(BITFORCE_WORKSTATUS)-1) |
||||
|
||||
// Either of Nonce or No-nonce start with:
|
||||
#define BITFORCE_EITHER "N" |
||||
#define BITFORCE_EITHER_LEN 1 |
||||
#define BITFORCE_NONCE "NONCE-FOUND" |
||||
#define BITFORCE_NONCE_LEN (sizeof(BITFORCE_NONCE)-1) |
||||
#define BITFORCE_NO_NONCE "NO-NONCE" |
||||
#define BITFORCE_NO_NONCE_MATCH 3 |
||||
#define BITFORCE_IDLE "IDLE" |
||||
#define BITFORCE_IDLE_MATCH 1 |
||||
|
||||
#define BITFORCE_SLEEP_MS 500 |
||||
#define BITFORCE_TIMEOUT_S 7 |
||||
#define BITFORCE_TIMEOUT_MS (BITFORCE_TIMEOUT_S * 1000) |
||||
#define BITFORCE_LONG_TIMEOUT_S 30 |
||||
#define BITFORCE_LONG_TIMEOUT_MS (BITFORCE_LONG_TIMEOUT_S * 1000) |
||||
#define BITFORCE_CHECK_INTERVAL_MS 10 |
||||
#define WORK_CHECK_INTERVAL_MS 50 |
||||
#define MAX_START_DELAY_MS 100 |
||||
#define tv_to_ms(tval) (tval.tv_sec * 1000 + tval.tv_usec / 1000) |
||||
#define TIME_AVG_CONSTANT 8 |
||||
|
||||
#define KNAME_WORK "full work" |
||||
#define KNAME_RANGE "nonce range" |
||||
|
||||
#define BITFORCE_BUFSIZ (0x200) |
||||
|
||||
// If initialisation fails the first time,
|
||||
// sleep this amount (ms) and try again
|
||||
#define REINIT_TIME_FIRST_MS 100 |
||||
// Max ms per sleep
|
||||
#define REINIT_TIME_MAX_MS 800 |
||||
// Keep trying up to this many us
|
||||
#define REINIT_TIME_MAX 3000000 |
||||
|
||||
static const char *blank = ""; |
||||
|
||||
static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) |
||||
{ |
||||
int err, interface; |
||||
|
||||
if (lock) |
||||
mutex_lock(&bitforce->device_mutex); |
||||
|
||||
if (bitforce->usbinfo.nodev) |
||||
goto failed; |
||||
|
||||
interface = usb_interface(bitforce); |
||||
// Reset
|
||||
err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, |
||||
FTDI_VALUE_RESET, interface, C_RESET); |
||||
if (opt_debug) |
||||
applog(LOG_DEBUG, "%s%i: reset got err %d", |
||||
bitforce->drv->name, bitforce->device_id, err); |
||||
|
||||
if (bitforce->usbinfo.nodev) |
||||
goto failed; |
||||
|
||||
// Set data control
|
||||
err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_DATA, |
||||
FTDI_VALUE_DATA_BFL, interface, C_SETDATA); |
||||
if (opt_debug) |
||||
applog(LOG_DEBUG, "%s%i: setdata got err %d", |
||||
bitforce->drv->name, bitforce->device_id, err); |
||||
|
||||
if (bitforce->usbinfo.nodev) |
||||
goto failed; |
||||
|
||||
// Set the baud
|
||||
err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_BAUD, FTDI_VALUE_BAUD_BFL, |
||||
(FTDI_INDEX_BAUD_BFL & 0xff00) | interface, |
||||
C_SETBAUD); |
||||
if (opt_debug) |
||||
applog(LOG_DEBUG, "%s%i: setbaud got err %d", |
||||
bitforce->drv->name, bitforce->device_id, err); |
||||
|
||||
if (bitforce->usbinfo.nodev) |
||||
goto failed; |
||||
|
||||
// Set Flow Control
|
||||
err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_FLOW, |
||||
FTDI_VALUE_FLOW, interface, C_SETFLOW); |
||||
if (opt_debug) |
||||
applog(LOG_DEBUG, "%s%i: setflowctrl got err %d", |
||||
bitforce->drv->name, bitforce->device_id, err); |
||||
|
||||
if (bitforce->usbinfo.nodev) |
||||
goto failed; |
||||
|
||||
// Set Modem Control
|
||||
err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_MODEM, |
||||
FTDI_VALUE_MODEM, interface, C_SETMODEM); |
||||
if (opt_debug) |
||||
applog(LOG_DEBUG, "%s%i: setmodemctrl got err %d", |
||||
bitforce->drv->name, bitforce->device_id, err); |
||||
|
||||
if (bitforce->usbinfo.nodev) |
||||
goto failed; |
||||
|
||||
// Clear any sent data
|
||||
err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, |
||||
FTDI_VALUE_PURGE_TX, interface, C_PURGETX); |
||||
if (opt_debug) |
||||
applog(LOG_DEBUG, "%s%i: purgetx got err %d", |
||||
bitforce->drv->name, bitforce->device_id, err); |
||||
|
||||
if (bitforce->usbinfo.nodev) |
||||
goto failed; |
||||
|
||||
// Clear any received data
|
||||
err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, |
||||
FTDI_VALUE_PURGE_RX, interface, C_PURGERX); |
||||
if (opt_debug) |
||||
applog(LOG_DEBUG, "%s%i: purgerx got err %d", |
||||
bitforce->drv->name, bitforce->device_id, err); |
||||
|
||||
failed: |
||||
|
||||
if (lock) |
||||
mutex_unlock(&bitforce->device_mutex); |
||||
} |
||||
|
||||
static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devices *found) |
||||
{ |
||||
char buf[BITFORCE_BUFSIZ+1]; |
||||
int err, amount; |
||||
char *s; |
||||
struct timeval init_start, init_now; |
||||
int init_sleep, init_count; |
||||
bool ident_first; |
||||
|
||||
struct cgpu_info *bitforce = usb_alloc_cgpu(&bitforce_drv, 1); |
||||
|
||||
if (!usb_init(bitforce, dev, found)) |
||||
goto shin; |
||||
|
||||
// Allow 2 complete attempts if the 1st time returns an unrecognised reply
|
||||
ident_first = true; |
||||
retry: |
||||
init_count = 0; |
||||
init_sleep = REINIT_TIME_FIRST_MS; |
||||
cgtime(&init_start); |
||||
reinit: |
||||
bitforce_initialise(bitforce, false); |
||||
if ((err = usb_write(bitforce, BITFORCE_IDENTIFY, BITFORCE_IDENTIFY_LEN, &amount, C_REQUESTIDENTIFY)) < 0 || amount != BITFORCE_IDENTIFY_LEN) { |
||||
applog(LOG_ERR, "%s detect (%s) send identify request failed (%d:%d)", |
||||
bitforce->drv->dname, bitforce->device_path, amount, err); |
||||
goto unshin; |
||||
} |
||||
|
||||
if ((err = usb_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETIDENTIFY)) < 0 || amount < 1) { |
||||
init_count++; |
||||
cgtime(&init_now); |
||||
if (us_tdiff(&init_now, &init_start) <= REINIT_TIME_MAX) { |
||||
if (init_count == 2) { |
||||
applog(LOG_WARNING, "%s detect (%s) 2nd init failed (%d:%d) - retrying", |
||||
bitforce->drv->dname, bitforce->device_path, amount, err); |
||||
} |
||||
cgsleep_ms(init_sleep); |
||||
if ((init_sleep * 2) <= REINIT_TIME_MAX_MS) |
||||
init_sleep *= 2; |
||||
goto reinit; |
||||
} |
||||
|
||||
if (init_count > 0) |
||||
applog(LOG_WARNING, "%s detect (%s) init failed %d times %.2fs", |
||||
bitforce->drv->dname, bitforce->device_path, init_count, tdiff(&init_now, &init_start)); |
||||
|
||||
if (err < 0) { |
||||
applog(LOG_ERR, "%s detect (%s) error identify reply (%d:%d)", |
||||
bitforce->drv->dname, bitforce->device_path, amount, err); |
||||
} else { |
||||
applog(LOG_ERR, "%s detect (%s) empty identify reply (%d)", |
||||
bitforce->drv->dname, bitforce->device_path, amount); |
||||
} |
||||
|
||||
goto unshin; |
||||
} |
||||
buf[amount] = '\0'; |
||||
|
||||
if (unlikely(!strstr(buf, "SHA256"))) { |
||||
if (ident_first) { |
||||
applog(LOG_WARNING, "%s detect (%s) didn't recognise '%s' trying again ...", |
||||
bitforce->drv->dname, bitforce->device_path, buf); |
||||
ident_first = false; |
||||
goto retry; |
||||
} |
||||
applog(LOG_ERR, "%s detect (%s) didn't recognise '%s' on 2nd attempt", |
||||
bitforce->drv->dname, bitforce->device_path, buf); |
||||
goto unshin; |
||||
} |
||||
|
||||
if (strstr(buf, "SHA256 SC")) { |
||||
#ifdef USE_BFLSC |
||||
applog(LOG_DEBUG, "SC device detected, will defer to BFLSC driver"); |
||||
#else |
||||
applog(LOG_WARNING, "SC device detected but no BFLSC support compiled in!"); |
||||
#endif |
||||
goto unshin; |
||||
} |
||||
|
||||
if (likely((!memcmp(buf, ">>>ID: ", 7)) && (s = strstr(buf + 3, ">>>")))) { |
||||
s[0] = '\0'; |
||||
bitforce->name = strdup(buf + 7); |
||||
} else { |
||||
bitforce->name = (char *)blank; |
||||
} |
||||
|
||||
// We have a real BitForce!
|
||||
applog(LOG_DEBUG, "%s (%s) identified as: '%s'", |
||||
bitforce->drv->dname, bitforce->device_path, bitforce->name); |
||||
|
||||
/* Initially enable support for nonce range and disable it later if it
|
||||
* fails */ |
||||
if (opt_bfl_noncerange) { |
||||
bitforce->nonce_range = true; |
||||
bitforce->sleep_ms = BITFORCE_SLEEP_MS; |
||||
bitforce->kname = KNAME_RANGE; |
||||
} else { |
||||
bitforce->sleep_ms = BITFORCE_SLEEP_MS * 5; |
||||
bitforce->kname = KNAME_WORK; |
||||
} |
||||
|
||||
if (!add_cgpu(bitforce)) |
||||
goto unshin; |
||||
|
||||
update_usb_stats(bitforce); |
||||
|
||||
mutex_init(&bitforce->device_mutex); |
||||
|
||||
return true; |
||||
|
||||
unshin: |
||||
|
||||
usb_uninit(bitforce); |
||||
|
||||
shin: |
||||
|
||||
if (bitforce->name != blank) { |
||||
free(bitforce->name); |
||||
bitforce->name = NULL; |
||||
} |
||||
|
||||
bitforce = usb_free_cgpu(bitforce); |
||||
|
||||
return false; |
||||
} |
||||
|
||||
static void bitforce_detect(bool __maybe_unused hotplug) |
||||
{ |
||||
usb_detect(&bitforce_drv, bitforce_detect_one); |
||||
} |
||||
|
||||
static void get_bitforce_statline_before(char *buf, size_t bufsiz, struct cgpu_info *bitforce) |
||||
{ |
||||
float gt = bitforce->temp; |
||||
|
||||
if (gt > 0) |
||||
tailsprintf(buf, bufsiz, "%5.1fC ", gt); |
||||
else |
||||
tailsprintf(buf, bufsiz, " "); |
||||
|
||||
tailsprintf(buf, bufsiz, " | "); |
||||
} |
||||
|
||||
static bool bitforce_thread_prepare(__maybe_unused struct thr_info *thr) |
||||
{ |
||||
// struct cgpu_info *bitforce = thr->cgpu;
|
||||
|
||||
return true; |
||||
} |
||||
|
||||
static void bitforce_flash_led(struct cgpu_info *bitforce) |
||||
{ |
||||
int err, amount; |
||||
|
||||
/* Do not try to flash the led if we're polling for a result to
|
||||
* minimise the chance of interleaved results */ |
||||
if (bitforce->polling) |
||||
return; |
||||
|
||||
/* It is not critical flashing the led so don't get stuck if we
|
||||
* can't grab the mutex now */ |
||||
if (mutex_trylock(&bitforce->device_mutex)) |
||||
return; |
||||
|
||||
if ((err = usb_write(bitforce, BITFORCE_FLASH, BITFORCE_FLASH_LEN, &amount, C_REQUESTFLASH)) < 0 || amount != BITFORCE_FLASH_LEN) { |
||||
applog(LOG_ERR, "%s%i: flash request failed (%d:%d)", |
||||
bitforce->drv->name, bitforce->device_id, amount, err); |
||||
} else { |
||||
/* However, this stops anything else getting a reply
|
||||
* So best to delay any other access to the BFL */ |
||||
cgsleep_ms(4000); |
||||
} |
||||
|
||||
/* Once we've tried - don't do it until told to again */ |
||||
bitforce->flash_led = false; |
||||
|
||||
mutex_unlock(&bitforce->device_mutex); |
||||
|
||||
return; // nothing is returned by the BFL
|
||||
} |
||||
|
||||
static bool bitforce_get_temp(struct cgpu_info *bitforce) |
||||
{ |
||||
char buf[BITFORCE_BUFSIZ+1]; |
||||
int err, amount; |
||||
char *s; |
||||
|
||||
// Device is gone
|
||||
if (bitforce->usbinfo.nodev) |
||||
return false; |
||||
|
||||
/* Do not try to get the temperature if we're polling for a result to
|
||||
* minimise the chance of interleaved results */ |
||||
if (bitforce->polling) |
||||
return true; |
||||
|
||||
// Flash instead of Temp - doing both can be too slow
|
||||
if (bitforce->flash_led) { |
||||
bitforce_flash_led(bitforce); |
||||
return true; |
||||
} |
||||
|
||||
/* It is not critical getting temperature so don't get stuck if we
|
||||
* can't grab the mutex here */ |
||||
if (mutex_trylock(&bitforce->device_mutex)) |
||||
return false; |
||||
|
||||
if ((err = usb_write(bitforce, BITFORCE_TEMPERATURE, BITFORCE_TEMPERATURE_LEN, &amount, C_REQUESTTEMPERATURE)) < 0 || amount != BITFORCE_TEMPERATURE_LEN) { |
||||
mutex_unlock(&bitforce->device_mutex); |
||||
applog(LOG_ERR, "%s%i: Error: Request temp invalid/timed out (%d:%d)", |
||||
bitforce->drv->name, bitforce->device_id, amount, err); |
||||
bitforce->hw_errors++; |
||||
return false; |
||||
} |
||||
|
||||
if ((err = usb_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETTEMPERATURE)) < 0 || amount < 1) { |
||||
mutex_unlock(&bitforce->device_mutex); |
||||
if (err < 0) { |
||||
applog(LOG_ERR, "%s%i: Error: Get temp return invalid/timed out (%d:%d)", |
||||
bitforce->drv->name, bitforce->device_id, amount, err); |
||||
} else { |
||||
applog(LOG_ERR, "%s%i: Error: Get temp returned nothing (%d:%d)", |
||||
bitforce->drv->name, bitforce->device_id, amount, err); |
||||
} |
||||
bitforce->hw_errors++; |
||||
return false; |
||||
} |
||||
|
||||
mutex_unlock(&bitforce->device_mutex); |
||||
|
||||
if ((!strncasecmp(buf, "TEMP", 4)) && (s = strchr(buf + 4, ':'))) { |
||||
float temp = strtof(s + 1, NULL); |
||||
|
||||
/* Cope with older software that breaks and reads nonsense
|
||||
* values */ |
||||
if (temp > 100) |
||||
temp = strtod(s + 1, NULL); |
||||
|
||||
if (temp > 0) { |
||||
bitforce->temp = temp; |
||||
if (unlikely(bitforce->cutofftemp > 0 && temp > bitforce->cutofftemp)) { |
||||
applog(LOG_WARNING, "%s%i: Hit thermal cutoff limit, disabling!", |
||||
bitforce->drv->name, bitforce->device_id); |
||||
bitforce->deven = DEV_RECOVER; |
||||
dev_error(bitforce, REASON_DEV_THERMAL_CUTOFF); |
||||
} |
||||
} |
||||
} else { |
||||
/* Use the temperature monitor as a kind of watchdog for when
|
||||
* our responses are out of sync and flush the buffer to |
||||
* hopefully recover */ |
||||
applog(LOG_WARNING, "%s%i: Garbled response probably throttling, clearing buffer", |
||||
bitforce->drv->name, bitforce->device_id); |
||||
dev_error(bitforce, REASON_DEV_THROTTLE); |
||||
/* Count throttling episodes as hardware errors */ |
||||
bitforce->hw_errors++; |
||||
bitforce_initialise(bitforce, true); |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
static bool bitforce_send_work(struct thr_info *thr, struct work *work) |
||||
{ |
||||
struct cgpu_info *bitforce = thr->cgpu; |
||||
unsigned char ob[70]; |
||||
char buf[BITFORCE_BUFSIZ+1]; |
||||
int err, amount; |
||||
char *s; |
||||
char *cmd; |
||||
int len; |
||||
|
||||
re_send: |
||||
if (bitforce->nonce_range) { |
||||
cmd = BITFORCE_SENDRANGE; |
||||
len = BITFORCE_SENDRANGE_LEN; |
||||
} else { |
||||
cmd = BITFORCE_SENDWORK; |
||||
len = BITFORCE_SENDWORK_LEN; |
||||
} |
||||
|
||||
mutex_lock(&bitforce->device_mutex); |
||||
if ((err = usb_write(bitforce, cmd, len, &amount, C_REQUESTSENDWORK)) < 0 || amount != len) { |
||||
mutex_unlock(&bitforce->device_mutex); |
||||
applog(LOG_ERR, "%s%i: request send work failed (%d:%d)", |
||||
bitforce->drv->name, bitforce->device_id, amount, err); |
||||
return false; |
||||
} |
||||
|
||||
if ((err = usb_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_REQUESTSENDWORKSTATUS)) < 0) { |
||||
mutex_unlock(&bitforce->device_mutex); |
||||
applog(LOG_ERR, "%s%d: read request send work status failed (%d:%d)", |
||||
bitforce->drv->name, bitforce->device_id, amount, err); |
||||
return false; |
||||
} |
||||
|
||||
if (amount == 0 || !buf[0] || !strncasecmp(buf, "B", 1)) { |
||||
mutex_unlock(&bitforce->device_mutex); |
||||
cgsleep_ms(WORK_CHECK_INTERVAL_MS); |
||||
goto re_send; |
||||
} else if (unlikely(strncasecmp(buf, "OK", 2))) { |
||||
mutex_unlock(&bitforce->device_mutex); |
||||
if (bitforce->nonce_range) { |
||||
applog(LOG_WARNING, "%s%i: Does not support nonce range, disabling", |
||||
bitforce->drv->name, bitforce->device_id); |
||||
bitforce->nonce_range = false; |
||||
bitforce->sleep_ms *= 5; |
||||
bitforce->kname = KNAME_WORK; |
||||
goto re_send; |
||||
} |
||||
applog(LOG_ERR, "%s%i: Error: Send work reports: %s", |
||||
bitforce->drv->name, bitforce->device_id, buf); |
||||
return false; |
||||
} |
||||
|
||||
sprintf((char *)ob, ">>>>>>>>"); |
||||
memcpy(ob + 8, work->midstate, 32); |
||||
memcpy(ob + 8 + 32, work->data + 64, 12); |
||||
if (!bitforce->nonce_range) { |
||||
sprintf((char *)ob + 8 + 32 + 12, ">>>>>>>>"); |
||||
work->blk.nonce = bitforce->nonces = 0xffffffff; |
||||
len = 60; |
||||
} else { |
||||
uint32_t *nonce; |
||||
|
||||
nonce = (uint32_t *)(ob + 8 + 32 + 12); |
||||
*nonce = htobe32(work->blk.nonce); |
||||
nonce = (uint32_t *)(ob + 8 + 32 + 12 + 4); |
||||
/* Split work up into 1/5th nonce ranges */ |
||||
bitforce->nonces = 0x33333332; |
||||
*nonce = htobe32(work->blk.nonce + bitforce->nonces); |
||||
work->blk.nonce += bitforce->nonces + 1; |
||||
sprintf((char *)ob + 8 + 32 + 12 + 8, ">>>>>>>>"); |
||||
len = 68; |
||||
} |
||||
|
||||
if ((err = usb_write(bitforce, (char *)ob, len, &amount, C_SENDWORK)) < 0 || amount != len) { |
||||
mutex_unlock(&bitforce->device_mutex); |
||||
applog(LOG_ERR, "%s%i: send work failed (%d:%d)", |
||||
bitforce->drv->name, bitforce->device_id, amount, err); |
||||
return false; |
||||
} |
||||
|
||||
if ((err = usb_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_SENDWORKSTATUS)) < 0) { |
||||
mutex_unlock(&bitforce->device_mutex); |
||||
applog(LOG_ERR, "%s%d: read send work status failed (%d:%d)", |
||||
bitforce->drv->name, bitforce->device_id, amount, err); |
||||
return false; |
||||
} |
||||
|
||||
mutex_unlock(&bitforce->device_mutex); |
||||
|
||||
if (opt_debug) { |
||||
s = bin2hex(ob + 8, 44); |
||||
applog(LOG_DEBUG, "%s%i: block data: %s", |
||||
bitforce->drv->name, bitforce->device_id, s); |
||||
free(s); |
||||
} |
||||
|
||||
if (amount == 0 || !buf[0]) { |
||||
applog(LOG_ERR, "%s%i: Error: Send block data returned empty string/timed out", |
||||
bitforce->drv->name, bitforce->device_id); |
||||
return false; |
||||
} |
||||
|
||||
if (unlikely(strncasecmp(buf, "OK", 2))) { |
||||
applog(LOG_ERR, "%s%i: Error: Send block data reports: %s", |
||||
bitforce->drv->name, bitforce->device_id, buf); |
||||
return false; |
||||
} |
||||
|
||||
cgtime(&bitforce->work_start_tv); |
||||
return true; |
||||
} |
||||
|
||||
static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) |
||||
{ |
||||
struct cgpu_info *bitforce = thr->cgpu; |
||||
unsigned int delay_time_ms; |
||||
struct timeval elapsed; |
||||
struct timeval now; |
||||
char buf[BITFORCE_BUFSIZ+1]; |
||||
int amount; |
||||
char *pnoncebuf; |
||||
uint32_t nonce; |
||||
|
||||
while (1) { |
||||
if (unlikely(thr->work_restart)) |
||||
return 0; |
||||
|
||||
mutex_lock(&bitforce->device_mutex); |
||||
usb_write(bitforce, BITFORCE_WORKSTATUS, BITFORCE_WORKSTATUS_LEN, &amount, C_REQUESTWORKSTATUS); |
||||
usb_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETWORKSTATUS); |
||||
mutex_unlock(&bitforce->device_mutex); |
||||
|
||||
cgtime(&now); |
||||
timersub(&now, &bitforce->work_start_tv, &elapsed); |
||||
|
||||
if (elapsed.tv_sec >= BITFORCE_LONG_TIMEOUT_S) { |
||||
applog(LOG_ERR, "%s%i: took %ldms - longer than %dms", |
||||
bitforce->drv->name, bitforce->device_id, |
||||
tv_to_ms(elapsed), BITFORCE_LONG_TIMEOUT_MS); |
||||
return 0; |
||||
} |
||||
|
||||
if (amount > 0 && buf[0] && strncasecmp(buf, "B", 1)) /* BFL does not respond during throttling */ |
||||
break; |
||||
|
||||
/* if BFL is throttling, no point checking so quickly */ |
||||
delay_time_ms = (buf[0] ? BITFORCE_CHECK_INTERVAL_MS : 2 * WORK_CHECK_INTERVAL_MS); |
||||
cgsleep_ms(delay_time_ms); |
||||
bitforce->wait_ms += delay_time_ms; |
||||
} |
||||
|
||||
if (elapsed.tv_sec > BITFORCE_TIMEOUT_S) { |
||||
applog(LOG_ERR, "%s%i: took %ldms - longer than %dms", |
||||
bitforce->drv->name, bitforce->device_id, |
||||
tv_to_ms(elapsed), BITFORCE_TIMEOUT_MS); |
||||
dev_error(bitforce, REASON_DEV_OVER_HEAT); |
||||
|
||||
/* Only return if we got nothing after timeout - there still may be results */ |
||||
if (amount == 0) |
||||
return 0; |
||||
} else if (!strncasecmp(buf, BITFORCE_EITHER, BITFORCE_EITHER_LEN)) { |
||||
/* Simple timing adjustment. Allow a few polls to cope with
|
||||
* OS timer delays being variably reliable. wait_ms will |
||||
* always equal sleep_ms when we've waited greater than or |
||||
* equal to the result return time.*/ |
||||
delay_time_ms = bitforce->sleep_ms; |
||||
|
||||
if (bitforce->wait_ms > bitforce->sleep_ms + (WORK_CHECK_INTERVAL_MS * 2)) |
||||
bitforce->sleep_ms += (bitforce->wait_ms - bitforce->sleep_ms) / 2; |
||||
else if (bitforce->wait_ms == bitforce->sleep_ms) { |
||||
if (bitforce->sleep_ms > WORK_CHECK_INTERVAL_MS) |
||||
bitforce->sleep_ms -= WORK_CHECK_INTERVAL_MS; |
||||
else if (bitforce->sleep_ms > BITFORCE_CHECK_INTERVAL_MS) |
||||
bitforce->sleep_ms -= BITFORCE_CHECK_INTERVAL_MS; |
||||
} |
||||
|
||||
if (delay_time_ms != bitforce->sleep_ms) |
||||
applog(LOG_DEBUG, "%s%i: Wait time changed to: %d, waited %u", |
||||
bitforce->drv->name, bitforce->device_id, |
||||
bitforce->sleep_ms, bitforce->wait_ms); |
||||
|
||||
/* Work out the average time taken. Float for calculation, uint for display */ |
||||
bitforce->avg_wait_f += (tv_to_ms(elapsed) - bitforce->avg_wait_f) / TIME_AVG_CONSTANT; |
||||
bitforce->avg_wait_d = (unsigned int) (bitforce->avg_wait_f + 0.5); |
||||
} |
||||
|
||||
applog(LOG_DEBUG, "%s%i: waited %dms until %s", |
||||
bitforce->drv->name, bitforce->device_id, |
||||
bitforce->wait_ms, buf); |
||||
if (!strncasecmp(buf, BITFORCE_NO_NONCE, BITFORCE_NO_NONCE_MATCH)) |
||||
return bitforce->nonces; /* No valid nonce found */ |
||||
else if (!strncasecmp(buf, BITFORCE_IDLE, BITFORCE_IDLE_MATCH)) |
||||
return 0; /* Device idle */ |
||||
else if (strncasecmp(buf, BITFORCE_NONCE, BITFORCE_NONCE_LEN)) { |
||||
bitforce->hw_errors++; |
||||
applog(LOG_WARNING, "%s%i: Error: Get result reports: %s", |
||||
bitforce->drv->name, bitforce->device_id, buf); |
||||
bitforce_initialise(bitforce, true); |
||||
return 0; |
||||
} |
||||
|
||||
pnoncebuf = &buf[12]; |
||||
|
||||
while (1) { |
||||
hex2bin((void*)&nonce, pnoncebuf, 4); |
||||
#ifndef __BIG_ENDIAN__ |
||||
nonce = swab32(nonce); |
||||
#endif |
||||
if (unlikely(bitforce->nonce_range && (nonce >= work->blk.nonce || |
||||
(work->blk.nonce > 0 && nonce < work->blk.nonce - bitforce->nonces - 1)))) { |
||||
applog(LOG_WARNING, "%s%i: Disabling broken nonce range support", |
||||
bitforce->drv->name, bitforce->device_id); |
||||
bitforce->nonce_range = false; |
||||
work->blk.nonce = 0xffffffff; |
||||
bitforce->sleep_ms *= 5; |
||||
bitforce->kname = KNAME_WORK; |
||||
} |
||||
|
||||
submit_nonce(thr, work, nonce); |
||||
if (strncmp(&pnoncebuf[8], ",", 1)) |
||||
break; |
||||
pnoncebuf += 9; |
||||
} |
||||
|
||||
return bitforce->nonces; |
||||
} |
||||
|
||||
static void bitforce_shutdown(__maybe_unused struct thr_info *thr) |
||||
{ |
||||
// struct cgpu_info *bitforce = thr->cgpu;
|
||||
} |
||||
|
||||
static void biforce_thread_enable(struct thr_info *thr) |
||||
{ |
||||
struct cgpu_info *bitforce = thr->cgpu; |
||||
|
||||
bitforce_initialise(bitforce, true); |
||||
} |
||||
|
||||
static int64_t bitforce_scanhash(struct thr_info *thr, struct work *work, int64_t __maybe_unused max_nonce) |
||||
{ |
||||
struct cgpu_info *bitforce = thr->cgpu; |
||||
bool send_ret; |
||||
int64_t ret; |
||||
|
||||
// Device is gone
|
||||
if (bitforce->usbinfo.nodev) |
||||
return -1; |
||||
|
||||
send_ret = bitforce_send_work(thr, work); |
||||
|
||||
if (!restart_wait(thr, bitforce->sleep_ms)) |
||||
return 0; |
||||
|
||||
bitforce->wait_ms = bitforce->sleep_ms; |
||||
|
||||
if (send_ret) { |
||||
bitforce->polling = true; |
||||
ret = bitforce_get_result(thr, work); |
||||
bitforce->polling = false; |
||||
} else |
||||
ret = -1; |
||||
|
||||
if (ret == -1) { |
||||
ret = 0; |
||||
applog(LOG_ERR, "%s%i: Comms error", bitforce->drv->name, bitforce->device_id); |
||||
dev_error(bitforce, REASON_DEV_COMMS_ERROR); |
||||
bitforce->hw_errors++; |
||||
/* empty read buffer */ |
||||
bitforce_initialise(bitforce, true); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static bool bitforce_get_stats(struct cgpu_info *bitforce) |
||||
{ |
||||
return bitforce_get_temp(bitforce); |
||||
} |
||||
|
||||
static void bitforce_identify(struct cgpu_info *bitforce) |
||||
{ |
||||
bitforce->flash_led = true; |
||||
} |
||||
|
||||
static bool bitforce_thread_init(struct thr_info *thr) |
||||
{ |
||||
struct cgpu_info *bitforce = thr->cgpu; |
||||
unsigned int wait; |
||||
|
||||
/* Pause each new thread at least 100ms between initialising
|
||||
* so the devices aren't making calls all at the same time. */ |
||||
wait = thr->id * MAX_START_DELAY_MS; |
||||
applog(LOG_DEBUG, "%s%d: Delaying start by %dms", |
||||
bitforce->drv->name, bitforce->device_id, wait / 1000); |
||||
cgsleep_ms(wait); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
static struct api_data *bitforce_api_stats(struct cgpu_info *cgpu) |
||||
{ |
||||
struct api_data *root = NULL; |
||||
|
||||
// Warning, access to these is not locked - but we don't really
|
||||
// care since hashing performance is way more important than
|
||||
// locking access to displaying API debug 'stats'
|
||||
// If locking becomes an issue for any of them, use copy_data=true also
|
||||
root = api_add_uint(root, "Sleep Time", &(cgpu->sleep_ms), false); |
||||
root = api_add_uint(root, "Avg Wait", &(cgpu->avg_wait_d), false); |
||||
|
||||
return root; |
||||
} |
||||
|
||||
struct device_drv bitforce_drv = { |
||||
.drv_id = DRIVER_bitforce, |
||||
.dname = "BitForce", |
||||
.name = "BFL", |
||||
.drv_detect = bitforce_detect, |
||||
.get_api_stats = bitforce_api_stats, |
||||
.get_statline_before = get_bitforce_statline_before, |
||||
.get_stats = bitforce_get_stats, |
||||
.identify_device = bitforce_identify, |
||||
.thread_prepare = bitforce_thread_prepare, |
||||
.thread_init = bitforce_thread_init, |
||||
.scanhash = bitforce_scanhash, |
||||
.thread_shutdown = bitforce_shutdown, |
||||
.thread_enable = biforce_thread_enable |
||||
}; |
@ -1,370 +0,0 @@
@@ -1,370 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 Con Kolivas |
||||
* |
||||
* 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 "miner.h" |
||||
#include "driver-bitfury.h" |
||||
#include "sha2.h" |
||||
|
||||
/* Wait longer 1/3 longer than it would take for a full nonce range */ |
||||
#define BF1WAIT 1600 |
||||
#define BF1MSGSIZE 7 |
||||
#define BF1INFOSIZE 14 |
||||
|
||||
static void bitfury_empty_buffer(struct cgpu_info *bitfury) |
||||
{ |
||||
char buf[512]; |
||||
int amount; |
||||
|
||||
do { |
||||
usb_read_once(bitfury, buf, 512, &amount, C_BF1_FLUSH); |
||||
} while (amount); |
||||
} |
||||
|
||||
static int bitfury_open(struct cgpu_info *bitfury) |
||||
{ |
||||
uint32_t buf[2]; |
||||
int err; |
||||
|
||||
bitfury_empty_buffer(bitfury); |
||||
/* Magic sequence to reset device only really needed for windows but
|
||||
* harmless on linux. */ |
||||
buf[0] = 0x80250000; |
||||
buf[1] = 0x00000800; |
||||
err = usb_transfer(bitfury, 0, 9, 1, 0, C_ATMEL_RESET); |
||||
if (!err) |
||||
err = usb_transfer(bitfury, 0x21, 0x22, 0, 0, C_ATMEL_OPEN); |
||||
if (!err) { |
||||
err = usb_transfer_data(bitfury, 0x21, 0x20, 0x0000, 0, buf, |
||||
BF1MSGSIZE, C_ATMEL_INIT); |
||||
} |
||||
|
||||
if (err < 0) { |
||||
applog(LOG_INFO, "%s %d: Failed to open with error %s", bitfury->drv->name, |
||||
bitfury->device_id, libusb_error_name(err)); |
||||
} |
||||
return (err == BF1MSGSIZE); |
||||
} |
||||
|
||||
static void bitfury_close(struct cgpu_info *bitfury) |
||||
{ |
||||
bitfury_empty_buffer(bitfury); |
||||
} |
||||
|
||||
static void bitfury_identify(struct cgpu_info *bitfury) |
||||
{ |
||||
int amount; |
||||
|
||||
usb_write(bitfury, "L", 1, &amount, C_BF1_IDENTIFY); |
||||
} |
||||
|
||||
static bool bitfury_getinfo(struct cgpu_info *bitfury, struct bitfury_info *info) |
||||
{ |
||||
int amount, err; |
||||
char buf[16]; |
||||
|
||||
err = usb_write(bitfury, "I", 1, &amount, C_BF1_REQINFO); |
||||
if (err) { |
||||
applog(LOG_INFO, "%s %d: Failed to write REQINFO", |
||||
bitfury->drv->name, bitfury->device_id); |
||||
return false; |
||||
} |
||||
err = usb_read(bitfury, buf, BF1INFOSIZE, &amount, C_BF1_GETINFO); |
||||
if (err) { |
||||
applog(LOG_INFO, "%s %d: Failed to read GETINFO", |
||||
bitfury->drv->name, bitfury->device_id); |
||||
return false; |
||||
} |
||||
if (amount != BF1INFOSIZE) { |
||||
applog(LOG_INFO, "%s %d: Getinfo received %d bytes instead of %d", |
||||
bitfury->drv->name, bitfury->device_id, amount, BF1INFOSIZE); |
||||
return false; |
||||
} |
||||
info->version = buf[1]; |
||||
memcpy(&info->product, buf + 2, 8); |
||||
memcpy(&info->serial, buf + 10, 4); |
||||
|
||||
applog(LOG_INFO, "%s %d: Getinfo returned version %d, product %s serial %08x", bitfury->drv->name, |
||||
bitfury->device_id, info->version, info->product, info->serial); |
||||
bitfury_empty_buffer(bitfury); |
||||
return true; |
||||
} |
||||
|
||||
static bool bitfury_reset(struct cgpu_info *bitfury) |
||||
{ |
||||
int amount, err; |
||||
char buf[16]; |
||||
|
||||
err = usb_write(bitfury, "R", 1, &amount, C_BF1_REQRESET); |
||||
if (err) { |
||||
applog(LOG_INFO, "%s %d: Failed to write REQRESET", |
||||
bitfury->drv->name, bitfury->device_id); |
||||
return false; |
||||
} |
||||
err = usb_read_timeout(bitfury, buf, BF1MSGSIZE, &amount, BF1WAIT, |
||||
C_BF1_GETRESET); |
||||
if (err) { |
||||
applog(LOG_INFO, "%s %d: Failed to read GETRESET", |
||||
bitfury->drv->name, bitfury->device_id); |
||||
return false; |
||||
} |
||||
if (amount != BF1MSGSIZE) { |
||||
applog(LOG_INFO, "%s %d: Getreset received %d bytes instead of %d", |
||||
bitfury->drv->name, bitfury->device_id, amount, BF1MSGSIZE); |
||||
return false; |
||||
} |
||||
applog(LOG_DEBUG, "%s %d: Getreset returned %s", bitfury->drv->name, |
||||
bitfury->device_id, buf); |
||||
bitfury_empty_buffer(bitfury); |
||||
return true; |
||||
} |
||||
|
||||
static bool bitfury_detect_one(struct libusb_device *dev, struct usb_find_devices *found) |
||||
{ |
||||
struct cgpu_info *bitfury; |
||||
struct bitfury_info *info; |
||||
|
||||
bitfury = usb_alloc_cgpu(&bitfury_drv, 1); |
||||
|
||||
if (!usb_init(bitfury, dev, found)) |
||||
goto out; |
||||
applog(LOG_INFO, "%s %d: Found at %s", bitfury->drv->name, |
||||
bitfury->device_id, bitfury->device_path); |
||||
|
||||
info = calloc(sizeof(struct bitfury_info), 1); |
||||
if (!info) |
||||
quit(1, "Failed to calloc info in bitfury_detect_one"); |
||||
bitfury->device_data = info; |
||||
/* This does not artificially raise hashrate, it simply allows the
|
||||
* hashrate to adapt quickly on starting. */ |
||||
info->total_nonces = 1; |
||||
|
||||
if (!bitfury_open(bitfury)) |
||||
goto out_close; |
||||
|
||||
/* Send getinfo request */ |
||||
if (!bitfury_getinfo(bitfury, info)) |
||||
goto out_close; |
||||
|
||||
/* Send reset request */ |
||||
if (!bitfury_reset(bitfury)) |
||||
goto out_close; |
||||
|
||||
bitfury_identify(bitfury); |
||||
bitfury_empty_buffer(bitfury); |
||||
|
||||
if (!add_cgpu(bitfury)) |
||||
quit(1, "Failed to add_cgpu in bitfury_detect_one"); |
||||
|
||||
update_usb_stats(bitfury); |
||||
applog(LOG_INFO, "%s %d: Successfully initialised %s", |
||||
bitfury->drv->name, bitfury->device_id, bitfury->device_path); |
||||
return true; |
||||
out_close: |
||||
bitfury_close(bitfury); |
||||
usb_uninit(bitfury); |
||||
out: |
||||
bitfury = usb_free_cgpu(bitfury); |
||||
return false; |
||||
} |
||||
|
||||
static void bitfury_detect(bool __maybe_unused hotplug) |
||||
{ |
||||
usb_detect(&bitfury_drv, bitfury_detect_one); |
||||
} |
||||
|
||||
static uint32_t decnonce(uint32_t in) |
||||
{ |
||||
uint32_t out; |
||||
|
||||
/* First part load */ |
||||
out = (in & 0xFF) << 24; in >>= 8; |
||||
|
||||
/* Byte reversal */ |
||||
in = (((in & 0xaaaaaaaa) >> 1) | ((in & 0x55555555) << 1)); |
||||
in = (((in & 0xcccccccc) >> 2) | ((in & 0x33333333) << 2)); |
||||
in = (((in & 0xf0f0f0f0) >> 4) | ((in & 0x0f0f0f0f) << 4)); |
||||
|
||||
out |= (in >> 2)&0x3FFFFF; |
||||
|
||||
/* Extraction */ |
||||
if (in & 1) out |= (1 << 23); |
||||
if (in & 2) out |= (1 << 22); |
||||
|
||||
out -= 0x800004; |
||||
return out; |
||||
} |
||||
|
||||
#define BT_OFFSETS 3 |
||||
const uint32_t bf_offsets[] = {-0x800000, 0, -0x400000}; |
||||
|
||||
static bool bitfury_checkresults(struct thr_info *thr, struct work *work, uint32_t nonce) |
||||
{ |
||||
int i; |
||||
|
||||
for (i = 0; i < BT_OFFSETS; i++) { |
||||
if (test_nonce(work, nonce + bf_offsets[i])) { |
||||
submit_tested_work(thr, work); |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
static int64_t bitfury_scanwork(struct thr_info *thr) |
||||
{ |
||||
struct cgpu_info *bitfury = thr->cgpu; |
||||
struct bitfury_info *info = bitfury->device_data; |
||||
struct timeval tv_now; |
||||
struct work *work; |
||||
double nonce_rate; |
||||
int64_t ret = 0; |
||||
int amount, i; |
||||
char buf[45]; |
||||
int ms_diff; |
||||
|
||||
work = get_work(thr, thr->id); |
||||
if (unlikely(thr->work_restart)) { |
||||
free_work(work); |
||||
return 0; |
||||
} |
||||
|
||||
buf[0] = 'W'; |
||||
memcpy(buf + 1, work->midstate, 32); |
||||
memcpy(buf + 33, work->data + 64, 12); |
||||
|
||||
/* New results may spill out from the latest work, making us drop out
|
||||
* too early so read whatever we get for the first half nonce and then |
||||
* look for the results to prev work. */ |
||||
cgtime(&tv_now); |
||||
ms_diff = 600 - ms_tdiff(&tv_now, &info->tv_start); |
||||
if (ms_diff > 0) { |
||||
usb_read_timeout_cancellable(bitfury, info->buf, 512, &amount, ms_diff, C_BF1_GETRES); |
||||
info->tot += amount; |
||||
} |
||||
|
||||
if (unlikely(thr->work_restart)) |
||||
goto cascade; |
||||
|
||||
/* Now look for the bulk of the previous work results, they will come
|
||||
* in a batch following the first data. */ |
||||
cgtime(&tv_now); |
||||
ms_diff = BF1WAIT - ms_tdiff(&tv_now, &info->tv_start); |
||||
if (unlikely(ms_diff < 10)) |
||||
ms_diff = 10; |
||||
usb_read_once_timeout_cancellable(bitfury, info->buf + info->tot, BF1MSGSIZE, |
||||
&amount, ms_diff, C_BF1_GETRES); |
||||
info->tot += amount; |
||||
while (amount) { |
||||
usb_read_once_timeout(bitfury, info->buf + info->tot, 512, &amount, 10, C_BF1_GETRES); |
||||
info->tot += amount; |
||||
}; |
||||
|
||||
if (unlikely(thr->work_restart)) |
||||
goto cascade; |
||||
|
||||
/* Send work */ |
||||
usb_write(bitfury, buf, 45, &amount, C_BF1_REQWORK); |
||||
cgtime(&info->tv_start); |
||||
/* Get response acknowledging work */ |
||||
usb_read(bitfury, buf, BF1MSGSIZE, &amount, C_BF1_GETWORK); |
||||
|
||||
/* Only happens on startup */ |
||||
if (unlikely(!info->prevwork[BF1ARRAY_SIZE])) |
||||
goto cascade; |
||||
|
||||
/* Search for what work the nonce matches in order of likelihood. Last
|
||||
* entry is end of result marker. */ |
||||
for (i = 0; i < info->tot - BF1MSGSIZE; i += BF1MSGSIZE) { |
||||
uint32_t nonce; |
||||
int j; |
||||
|
||||
/* Ignore state & switched data in results for now. */ |
||||
memcpy(&nonce, info->buf + i + 3, 4); |
||||
nonce = decnonce(nonce); |
||||
for (j = 0; j < BF1ARRAY_SIZE; j++) { |
||||
if (bitfury_checkresults(thr, info->prevwork[j], nonce)) { |
||||
info->nonces++; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
info->tot = 0; |
||||
free_work(info->prevwork[BF1ARRAY_SIZE]); |
||||
cascade: |
||||
for (i = BF1ARRAY_SIZE; i > 0; i--) |
||||
info->prevwork[i] = info->prevwork[i - 1]; |
||||
info->prevwork[0] = work; |
||||
|
||||
info->cycles++; |
||||
info->total_nonces += info->nonces; |
||||
info->saved_nonces += info->nonces; |
||||
info->nonces = 0; |
||||
nonce_rate = (double)info->total_nonces / (double)info->cycles; |
||||
if (info->saved_nonces >= nonce_rate) { |
||||
info->saved_nonces -= nonce_rate; |
||||
ret = (double)0xffffffff * nonce_rate; |
||||
} |
||||
|
||||
if (unlikely(bitfury->usbinfo.nodev)) { |
||||
applog(LOG_WARNING, "%s %d: Device disappeared, disabling thread", |
||||
bitfury->drv->name, bitfury->device_id); |
||||
ret = -1; |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static struct api_data *bitfury_api_stats(struct cgpu_info *cgpu) |
||||
{ |
||||
struct bitfury_info *info = cgpu->device_data; |
||||
struct api_data *root = NULL; |
||||
double nonce_rate; |
||||
char serial[16]; |
||||
int version; |
||||
|
||||
version = info->version; |
||||
root = api_add_int(root, "Version", &version, true); |
||||
root = api_add_string(root, "Product", info->product, false); |
||||
sprintf(serial, "%08x", info->serial); |
||||
root = api_add_string(root, "Serial", serial, true); |
||||
nonce_rate = (double)info->total_nonces / (double)info->cycles; |
||||
root = api_add_double(root, "NonceRate", &nonce_rate, true); |
||||
|
||||
return root; |
||||
} |
||||
|
||||
static void bitfury_init(struct cgpu_info *bitfury) |
||||
{ |
||||
bitfury_close(bitfury); |
||||
bitfury_open(bitfury); |
||||
bitfury_reset(bitfury); |
||||
} |
||||
|
||||
static void bitfury_shutdown(struct thr_info *thr) |
||||
{ |
||||
struct cgpu_info *bitfury = thr->cgpu; |
||||
|
||||
bitfury_close(bitfury); |
||||
} |
||||
|
||||
/* Currently hardcoded to BF1 devices */ |
||||
struct device_drv bitfury_drv = { |
||||
.drv_id = DRIVER_bitfury, |
||||
.dname = "bitfury", |
||||
.name = "BF1", |
||||
.drv_detect = bitfury_detect, |
||||
.hash_work = &hash_driver_work, |
||||
.scanwork = bitfury_scanwork, |
||||
.get_api_stats = bitfury_api_stats, |
||||
.reinit_device = bitfury_init, |
||||
.thread_shutdown = bitfury_shutdown, |
||||
.identify_device = bitfury_identify |
||||
}; |
@ -1,33 +0,0 @@
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 Con Kolivas |
||||
* |
||||
* 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 BITFURY_H |
||||
#define BITFURY_H |
||||
|
||||
#include "miner.h" |
||||
#include "usbutils.h" |
||||
|
||||
#define BF1ARRAY_SIZE 2 |
||||
|
||||
struct bitfury_info { |
||||
struct cgpu_info *base_cgpu; |
||||
uint8_t version; |
||||
char product[8]; |
||||
uint32_t serial; |
||||
struct work *prevwork[BF1ARRAY_SIZE + 1]; |
||||
char buf[512]; |
||||
int tot; |
||||
int nonces; |
||||
int total_nonces; |
||||
double saved_nonces; |
||||
int cycles; |
||||
struct timeval tv_start; |
||||
}; |
||||
|
||||
#endif /* BITFURY_H */ |
@ -1,937 +0,0 @@
@@ -1,937 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 Con Kolivas <kernel@kolivas.org> |
||||
* Copyright 2013 Hashfast Inc. |
||||
* |
||||
* 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 <stdbool.h> |
||||
|
||||
#include "miner.h" |
||||
#include "usbutils.h" |
||||
|
||||
#include "driver-hashfast.h" |
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Support for the CRC's used in header (CRC-8) and packet body (CRC-32)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define GP8 0x107 /* x^8 + x^2 + x + 1 */ |
||||
#define DI8 0x07 |
||||
|
||||
static unsigned char crc8_table[256]; /* CRC-8 table */ |
||||
|
||||
static void hfa_init_crc8(void) |
||||
{ |
||||
int i,j; |
||||
unsigned char crc; |
||||
|
||||
for (i = 0; i < 256; i++) { |
||||
crc = i; |
||||
for (j = 0; j < 8; j++) |
||||
crc = (crc << 1) ^ ((crc & 0x80) ? DI8 : 0); |
||||
crc8_table[i] = crc & 0xFF; |
||||
} |
||||
} |
||||
|
||||
static unsigned char hfa_crc8(unsigned char *h) |
||||
{ |
||||
int i; |
||||
unsigned char crc; |
||||
|
||||
h++; // Preamble not included
|
||||
for (i = 1, crc = 0xff; i < 7; i++) |
||||
crc = crc8_table[crc ^ *h++]; |
||||
|
||||
return crc; |
||||
} |
||||
|
||||
struct hfa_cmd { |
||||
uint8_t cmd; |
||||
char *cmd_name; |
||||
enum usb_cmds usb_cmd; |
||||
}; |
||||
|
||||
/* Entries in this array need to align with the actual op values specified
|
||||
* in hf_protocol.h */ |
||||
#define C_NULL C_MAX |
||||
static const struct hfa_cmd hfa_cmds[] = { |
||||
{OP_NULL, "OP_NULL", C_NULL}, // 0
|
||||
{OP_ROOT, "OP_ROOT", C_NULL}, |
||||
{OP_RESET, "OP_RESET", C_HF_RESET}, |
||||
{OP_PLL_CONFIG, "OP_PLL_CONFIG", C_HF_PLL_CONFIG}, |
||||
{OP_ADDRESS, "OP_ADDRESS", C_HF_ADDRESS}, |
||||
{OP_READDRESS, "OP_READDRESS", C_NULL}, |
||||
{OP_HIGHEST, "OP_HIGHEST", C_NULL}, |
||||
{OP_BAUD, "OP_BAUD", C_HF_BAUD}, |
||||
{OP_UNROOT, "OP_UNROOT", C_NULL}, // 8
|
||||
{OP_HASH, "OP_HASH", C_HF_HASH}, |
||||
{OP_NONCE, "OP_NONCE", C_HF_NONCE}, |
||||
{OP_ABORT, "OP_ABORT", C_HF_ABORT}, |
||||
{OP_STATUS, "OP_STATUS", C_HF_STATUS}, |
||||
{OP_GPIO, "OP_GPIO", C_NULL}, |
||||
{OP_CONFIG, "OP_CONFIG", C_HF_CONFIG}, |
||||
{OP_STATISTICS, "OP_STATISTICS", C_HF_STATISTICS}, |
||||
{OP_GROUP, "OP_GROUP", C_NULL}, // 16
|
||||
{OP_CLOCKGATE, "OP_CLOCKGATE", C_HF_CLOCKGATE}, |
||||
|
||||
{OP_USB_INIT, "OP_USB_INIT", C_HF_USB_INIT}, // 18
|
||||
{OP_GET_TRACE, "OP_GET_TRACE", C_NULL}, |
||||
{OP_LOOPBACK_USB, "OP_LOOPBACK_USB", C_NULL}, |
||||
{OP_LOOPBACK_UART, "OP_LOOPBACK_UART", C_NULL}, |
||||
{OP_DFU, "OP_DFU", C_NULL}, |
||||
{OP_USB_SHUTDOWN, "OP_USB_SHUTDOWN", C_NULL}, |
||||
{OP_DIE_STATUS, "OP_DIE_STATUS", C_HF_DIE_STATUS}, // 24
|
||||
{OP_GWQ_STATUS, "OP_GWQ_STATUS", C_HF_GWQ_STATUS}, |
||||
{OP_WORK_RESTART, "OP_WORK_RESTART", C_HF_WORK_RESTART}, |
||||
{OP_USB_STATS1, "OP_USB_STATS1", C_NULL}, |
||||
{OP_USB_GWQSTATS, "OP_USB_GWQSTATS", C_HF_GWQSTATS} |
||||
}; |
||||
|
||||
#define HF_USB_CMD_OFFSET (128 - 18) |
||||
#define HF_USB_CMD(X) (X - HF_USB_CMD_OFFSET) |
||||
|
||||
/* Send an arbitrary frame, consisting of an 8 byte header and an optional
|
||||
* packet body. */ |
||||
|
||||
static bool hfa_send_frame(struct cgpu_info *hashfast, uint8_t opcode, uint16_t hdata, |
||||
uint8_t *data, int len) |
||||
{ |
||||
int tx_length, ret, amount, id = hashfast->device_id; |
||||
uint8_t packet[256]; |
||||
struct hf_header *p = (struct hf_header *)packet; |
||||
|
||||
p->preamble = HF_PREAMBLE; |
||||
p->operation_code = hfa_cmds[opcode].cmd; |
||||
p->chip_address = HF_GWQ_ADDRESS; |
||||
p->core_address = 0; |
||||
p->hdata = htole16(hdata); |
||||
p->data_length = len / 4; |
||||
p->crc8 = hfa_crc8(packet); |
||||
|
||||
if (len) |
||||
memcpy(&packet[sizeof(struct hf_header)], data, len); |
||||
tx_length = sizeof(struct hf_header) + len; |
||||
|
||||
ret = usb_write(hashfast, (char *)packet, tx_length, &amount, |
||||
hfa_cmds[opcode].usb_cmd); |
||||
if (unlikely(ret < 0 || amount != tx_length)) { |
||||
applog(LOG_ERR, "HFA %d: hfa_send_frame: USB Send error, ret %d amount %d vs. tx_length %d", |
||||
id, ret, amount, tx_length); |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
static bool hfa_send_header(struct cgpu_info *hashfast, struct hf_header *h, int cmd) |
||||
{ |
||||
int amount, ret, len; |
||||
|
||||
len = sizeof(*h); |
||||
ret = usb_write(hashfast, (char *)h, len, &amount, hfa_cmds[cmd].usb_cmd); |
||||
if (ret < 0 || amount != len) { |
||||
applog(LOG_WARNING, "HFA%d: send_header: %s USB Send error, ret %d amount %d vs. length %d", |
||||
hashfast->device_id, hfa_cmds[cmd].cmd_name, ret, amount, len); |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
static bool hfa_get_header(struct cgpu_info *hashfast, struct hf_header *h, uint8_t *computed_crc) |
||||
{ |
||||
int amount, ret, orig_len, len, ofs = 0, reads = 0; |
||||
char buf[512]; |
||||
char *header; |
||||
|
||||
/* Read for up to 200ms till we find the first occurrence of HF_PREAMBLE
|
||||
* though it should be the first byte unless we get woefully out of |
||||
* sync. */ |
||||
orig_len = len = sizeof(*h); |
||||
do { |
||||
|
||||
if (++reads > 20) |
||||
return false; |
||||
|
||||
ret = usb_read_timeout(hashfast, buf + ofs, len, &amount, 10, C_HF_GETHEADER); |
||||
if (unlikely(ret && ret != LIBUSB_ERROR_TIMEOUT)) |
||||
return false; |
||||
ofs += amount; |
||||
header = memchr(buf, HF_PREAMBLE, ofs); |
||||
if (header) |
||||
len -= ofs - (header - buf); |
||||
} while (len); |
||||
|
||||
memcpy(h, header, orig_len); |
||||
*computed_crc = hfa_crc8((uint8_t *)h); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
static bool hfa_get_data(struct cgpu_info *hashfast, char *buf, int len4) |
||||
{ |
||||
int amount, ret, len = len4 * 4; |
||||
|
||||
ret = usb_read(hashfast, buf, len, &amount, C_HF_GETDATA); |
||||
if (ret) |
||||
return false; |
||||
if (amount != len) { |
||||
applog(LOG_WARNING, "HFA %d: get_data: Strange amount returned %d vs. expected %d", |
||||
hashfast->device_id, amount, len); |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
static bool hfa_reset(struct cgpu_info *hashfast, struct hashfast_info *info) |
||||
{ |
||||
struct hf_usb_init_header usb_init, *hu = &usb_init; |
||||
struct hf_usb_init_base *db; |
||||
char buf[1024]; |
||||
struct hf_header *h = (struct hf_header *)buf; |
||||
uint8_t hcrc; |
||||
bool ret; |
||||
int i; |
||||
|
||||
info->hash_clock_rate = 550; // Hash clock rate in Mhz
|
||||
// Assemble the USB_INIT request
|
||||
memset(hu, 0, sizeof(*hu)); |
||||
hu->preamble = HF_PREAMBLE; |
||||
hu->operation_code = OP_USB_INIT; |
||||
hu->protocol = PROTOCOL_GLOBAL_WORK_QUEUE; // Protocol to use
|
||||
hu->hash_clock = info->hash_clock_rate; // Hash clock rate in Mhz
|
||||
hu->crc8 = hfa_crc8((uint8_t *)hu); |
||||
applog(LOG_INFO, "HFA%d: Sending OP_USB_INIT with GWQ protocol specified", |
||||
hashfast->device_id); |
||||
|
||||
if (!hfa_send_header(hashfast, (struct hf_header *)hu, HF_USB_CMD(OP_USB_INIT))) |
||||
return false; |
||||
|
||||
// Check for the correct response.
|
||||
// We extend the normal timeout - a complete device initialization, including
|
||||
// bringing power supplies up from standby, etc., can take over a second.
|
||||
for (i = 0; i < 30; i++) { |
||||
ret = hfa_get_header(hashfast, h, &hcrc); |
||||
if (ret) |
||||
break; |
||||
} |
||||
if (!ret) { |
||||
applog(LOG_WARNING, "HFA %d: OP_USB_INIT failed!", hashfast->device_id); |
||||
return false; |
||||
} |
||||
if (h->crc8 != hcrc) { |
||||
applog(LOG_WARNING, "HFA %d: OP_USB_INIT failed! CRC mismatch", hashfast->device_id); |
||||
return false; |
||||
} |
||||
if (h->operation_code != OP_USB_INIT) { |
||||
applog(LOG_WARNING, "HFA %d: OP_USB_INIT: Tossing packet, valid but unexpected type", hashfast->device_id); |
||||
hfa_get_data(hashfast, buf, h->data_length); |
||||
return false; |
||||
} |
||||
|
||||
applog(LOG_DEBUG, "HFA %d: Good reply to OP_USB_INIT", hashfast->device_id); |
||||
applog(LOG_DEBUG, "HFA %d: OP_USB_INIT: %d die in chain, %d cores, device_type %d, refclk %d Mhz", |
||||
hashfast->device_id, h->chip_address, h->core_address, h->hdata & 0xff, (h->hdata >> 8) & 0xff); |
||||
|
||||
// Save device configuration
|
||||
info->asic_count = h->chip_address; |
||||
info->core_count = h->core_address; |
||||
info->device_type = (uint8_t)h->hdata; |
||||
info->ref_frequency = (uint8_t)(h->hdata>>8); |
||||
info->hash_sequence_head = 0; |
||||
info->hash_sequence_tail = 0; |
||||
info->device_sequence_tail = 0; |
||||
|
||||
// Size in bytes of the core bitmap in bytes
|
||||
info->core_bitmap_size = (((info->asic_count * info->core_count) + 31) / 32) * 4; |
||||
|
||||
// Get the usb_init_base structure
|
||||
if (!hfa_get_data(hashfast, (char *)&info->usb_init_base, U32SIZE(info->usb_init_base))) { |
||||
applog(LOG_WARNING, "HFA %d: OP_USB_INIT failed! Failure to get usb_init_base data", |
||||
hashfast->device_id); |
||||
return false; |
||||
} |
||||
db = &info->usb_init_base; |
||||
applog(LOG_INFO, "HFA %d: firmware_rev: %d.%d", hashfast->device_id, |
||||
(db->firmware_rev >> 8) & 0xff, db->firmware_rev & 0xff); |
||||
applog(LOG_INFO, "HFA %d: hardware_rev: %d.%d", hashfast->device_id, |
||||
(db->hardware_rev >> 8) & 0xff, db->hardware_rev & 0xff); |
||||
applog(LOG_INFO, "HFA %d: serial number: %d", hashfast->device_id, |
||||
db->serial_number); |
||||
applog(LOG_INFO, "HFA %d: hash clockrate: %d Mhz", hashfast->device_id, |
||||
db->hash_clockrate); |
||||
applog(LOG_INFO, "HFA %d: inflight_target: %d", hashfast->device_id, |
||||
db->inflight_target); |
||||
applog(LOG_INFO, "HFA %d: sequence_modulus: %d", hashfast->device_id, |
||||
db->sequence_modulus); |
||||
info->num_sequence = db->sequence_modulus; |
||||
|
||||
// Now a copy of the config data used
|
||||
if (!hfa_get_data(hashfast, (char *)&info->config_data, U32SIZE(info->config_data))) { |
||||
applog(LOG_WARNING, "HFA %d: OP_USB_INIT failed! Failure to get config_data", |
||||
hashfast->device_id); |
||||
return false; |
||||
} |
||||
|
||||
// Now the core bitmap
|
||||
info->core_bitmap = malloc(info->core_bitmap_size); |
||||
if (!info->core_bitmap) |
||||
quit(1, "Failed to malloc info core bitmap in hfa_reset"); |
||||
if (!hfa_get_data(hashfast, (char *)info->core_bitmap, info->core_bitmap_size / 4)) { |
||||
applog(LOG_WARNING, "HFA %d: OP_USB_INIT failed! Failure to get core_bitmap", hashfast->device_id); |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
static void hfa_send_shutdown(struct cgpu_info *hashfast) |
||||
{ |
||||
hfa_send_frame(hashfast, HF_USB_CMD(OP_USB_SHUTDOWN), 0, NULL, 0); |
||||
} |
||||
|
||||
static void hfa_clear_readbuf(struct cgpu_info *hashfast) |
||||
{ |
||||
int amount, ret; |
||||
char buf[512]; |
||||
|
||||
do { |
||||
ret = usb_read(hashfast, buf, 512, &amount, C_HF_CLEAR_READ); |
||||
} while (!ret || amount); |
||||
} |
||||
|
||||
static bool hfa_detect_common(struct cgpu_info *hashfast) |
||||
{ |
||||
struct hashfast_info *info; |
||||
bool ret; |
||||
|
||||
info = calloc(sizeof(struct hashfast_info), 1); |
||||
if (!info) |
||||
quit(1, "Failed to calloc hashfast_info in hfa_detect_common"); |
||||
hashfast->device_data = info; |
||||
/* hashfast_reset should fill in details for info */ |
||||
ret = hfa_reset(hashfast, info); |
||||
if (!ret) { |
||||
hfa_send_shutdown(hashfast); |
||||
hfa_clear_readbuf(hashfast); |
||||
free(info); |
||||
hashfast->device_data = NULL; |
||||
return false; |
||||
} |
||||
|
||||
// The per-die status array
|
||||
info->die_status = calloc(info->asic_count, sizeof(struct hf_g1_die_data)); |
||||
if (unlikely(!(info->die_status))) |
||||
quit(1, "Failed to calloc die_status"); |
||||
|
||||
// The per-die statistics array
|
||||
info->die_statistics = calloc(info->asic_count, sizeof(struct hf_long_statistics)); |
||||
if (unlikely(!(info->die_statistics))) |
||||
quit(1, "Failed to calloc die_statistics"); |
||||
|
||||
info->works = calloc(sizeof(struct work *), info->num_sequence); |
||||
if (!info->works) |
||||
quit(1, "Failed to calloc info works in hfa_detect_common"); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
static bool hfa_initialise(struct cgpu_info *hashfast) |
||||
{ |
||||
int err; |
||||
|
||||
if (hashfast->usbinfo.nodev) |
||||
return false; |
||||
|
||||
hfa_clear_readbuf(hashfast); |
||||
|
||||
err = usb_transfer(hashfast, 0, 9, 1, 0, C_ATMEL_RESET); |
||||
if (!err) |
||||
err = usb_transfer(hashfast, 0x21, 0x22, 0, 0, C_ATMEL_OPEN); |
||||
if (!err) { |
||||
uint32_t buf[2]; |
||||
|
||||
/* Magic sequence to reset device only really needed for windows
|
||||
* but harmless on linux. */ |
||||
buf[0] = 0x80250000; |
||||
buf[1] = 0x00000800; |
||||
err = usb_transfer_data(hashfast, 0x21, 0x20, 0x0000, 0, buf, |
||||
7, C_ATMEL_INIT); |
||||
} |
||||
if (err < 0) { |
||||
applog(LOG_INFO, "HFA %d: Failed to open with error %s", |
||||
hashfast->device_id, libusb_error_name(err)); |
||||
} |
||||
/* Must have transmitted init sequence sized buffer */ |
||||
return (err == 7); |
||||
} |
||||
|
||||
static bool hfa_detect_one_usb(libusb_device *dev, struct usb_find_devices *found) |
||||
{ |
||||
struct cgpu_info *hashfast; |
||||
|
||||
hashfast = usb_alloc_cgpu(&hashfast_drv, HASHFAST_MINER_THREADS); |
||||
if (!hashfast) |
||||
quit(1, "Failed to usb_alloc_cgpu hashfast"); |
||||
|
||||
if (!usb_init(hashfast, dev, found)) { |
||||
hashfast = usb_free_cgpu(hashfast); |
||||
return false; |
||||
} |
||||
|
||||
hashfast->usbdev->usb_type = USB_TYPE_STD; |
||||
|
||||
if (!hfa_initialise(hashfast)) { |
||||
hashfast = usb_free_cgpu(hashfast); |
||||
return false; |
||||
} |
||||
|
||||
add_cgpu(hashfast); |
||||
|
||||
return hfa_detect_common(hashfast); |
||||
} |
||||
|
||||
static void hfa_detect(bool hotplug) |
||||
{ |
||||
/* Set up the CRC tables only once. */ |
||||
if (!hotplug) |
||||
hfa_init_crc8(); |
||||
usb_detect(&hashfast_drv, hfa_detect_one_usb); |
||||
} |
||||
|
||||
static bool hfa_get_packet(struct cgpu_info *hashfast, struct hf_header *h) |
||||
{ |
||||
uint8_t hcrc; |
||||
bool ret; |
||||
|
||||
ret = hfa_get_header(hashfast, h, &hcrc); |
||||
if (unlikely(!ret)) |
||||
goto out; |
||||
if (unlikely(h->crc8 != hcrc)) { |
||||
applog(LOG_WARNING, "HFA %d: Bad CRC %d vs %d, attempting to process anyway", |
||||
hashfast->device_id, h->crc8, hcrc); |
||||
} |
||||
if (h->data_length > 0) |
||||
ret = hfa_get_data(hashfast, (char *)(h + 1), h->data_length); |
||||
if (unlikely(!ret)) { |
||||
applog(LOG_WARNING, "HFA %d: Failed to get data associated with header", |
||||
hashfast->device_id); |
||||
} |
||||
|
||||
out: |
||||
return ret; |
||||
} |
||||
|
||||
static void hfa_parse_gwq_status(struct cgpu_info *hashfast, struct hashfast_info *info, |
||||
struct hf_header *h) |
||||
{ |
||||
struct hf_gwq_data *g = (struct hf_gwq_data *)(h + 1); |
||||
struct work *work; |
||||
|
||||
applog(LOG_DEBUG, "HFA %d: OP_GWQ_STATUS, device_head %4d tail %4d my tail %4d shed %3d inflight %4d", |
||||
hashfast->device_id, g->sequence_head, g->sequence_tail, info->hash_sequence_tail, |
||||
g->shed_count, HF_SEQUENCE_DISTANCE(info->hash_sequence_head,g->sequence_tail)); |
||||
|
||||
mutex_lock(&info->lock); |
||||
info->hash_count += g->hash_count; |
||||
info->device_sequence_head = g->sequence_head; |
||||
info->device_sequence_tail = g->sequence_tail; |
||||
info->shed_count = g->shed_count; |
||||
/* Free any work that is no longer required */ |
||||
while (info->device_sequence_tail != info->hash_sequence_tail) { |
||||
if (++info->hash_sequence_tail >= info->num_sequence) |
||||
info->hash_sequence_tail = 0; |
||||
if (unlikely(!(work = info->works[info->hash_sequence_tail]))) { |
||||
applog(LOG_ERR, "HFA %d: Bad work sequence tail", |
||||
hashfast->device_id); |
||||
hashfast->shutdown = true; |
||||
break; |
||||
} |
||||
applog(LOG_DEBUG, "HFA %d: Completing work on hash_sequence_tail %d", |
||||
hashfast->device_id, info->hash_sequence_tail); |
||||
free_work(work); |
||||
info->works[info->hash_sequence_tail] = NULL; |
||||
} |
||||
mutex_unlock(&info->lock); |
||||
} |
||||
|
||||
static void hfa_update_die_status(struct cgpu_info *hashfast, struct hashfast_info *info, |
||||
struct hf_header *h) |
||||
{ |
||||
struct hf_g1_die_data *d = (struct hf_g1_die_data *)(h + 1), *ds; |
||||
int num_included = (h->data_length * 4) / sizeof(struct hf_g1_die_data); |
||||
int i, j; |
||||
|
||||
float die_temperature; |
||||
float core_voltage[6]; |
||||
|
||||
if (info->device_type == HFD_G1) { |
||||
// Copy in the data. They're numbered sequentially from the starting point
|
||||
ds = info->die_status + h->chip_address; |
||||
for (i = 0; i < num_included; i++) |
||||
memcpy(ds++, d++, sizeof(struct hf_g1_die_data)); |
||||
|
||||
for (i = 0, d = &info->die_status[h->chip_address]; i < num_included; i++, d++) { |
||||
die_temperature = GN_DIE_TEMPERATURE(d->die.die_temperature); |
||||
for (j = 0; j < 6; j++) |
||||
core_voltage[j] = GN_CORE_VOLTAGE(d->die.core_voltage[j]); |
||||
|
||||
applog(LOG_DEBUG, "HFA %d: die %2d: OP_DIE_STATUS Die temp %.2fC vdd's %.2f %.2f %.2f %.2f %.2f %.2f", |
||||
hashfast->device_id, h->chip_address + i, die_temperature, |
||||
core_voltage[0], core_voltage[1], core_voltage[2], |
||||
core_voltage[3], core_voltage[4], core_voltage[5]); |
||||
// XXX Convert board phase currents, voltage, temperature
|
||||
} |
||||
} |
||||
} |
||||
|
||||
static void search_for_extra_nonce(struct thr_info *thr, struct work *work, |
||||
struct hf_candidate_nonce *n) |
||||
{ |
||||
uint32_t nonce = n->nonce; |
||||
int i; |
||||
|
||||
/* No function to test with ntime offsets yet */ |
||||
if (n->ntime & HF_NTIME_MASK) |
||||
return; |
||||
for (i = 0; i < 128; i++, nonce++) { |
||||
/* We could break out of this early if nonce wraps or if we
|
||||
* find one correct nonce since the chance of more is extremely |
||||
* low but this function will be hit so infrequently we may as |
||||
* well test the entire range with the least code. */ |
||||
if (test_nonce(work, nonce)) |
||||
submit_tested_work(thr, work); |
||||
} |
||||
} |
||||
|
||||
static void hfa_parse_nonce(struct thr_info *thr, struct cgpu_info *hashfast, |
||||
struct hashfast_info *info, struct hf_header *h) |
||||
{ |
||||
struct hf_candidate_nonce *n = (struct hf_candidate_nonce *)(h + 1); |
||||
int i, num_nonces = h->data_length / U32SIZE(sizeof(struct hf_candidate_nonce)); |
||||
|
||||
applog(LOG_DEBUG, "HFA %d: OP_NONCE: %2d:, num_nonces %d hdata 0x%04x", |
||||
hashfast->device_id, h->chip_address, num_nonces, h->hdata); |
||||
for (i = 0; i < num_nonces; i++, n++) { |
||||
struct work *work; |
||||
|
||||
applog(LOG_DEBUG, "HFA %d: OP_NONCE: %2d: %2d: ntime %2d sequence %4d nonce 0x%08x", |
||||
hashfast->device_id, h->chip_address, i, n->ntime & HF_NTIME_MASK, n->sequence, n->nonce); |
||||
|
||||
// Find the job from the sequence number
|
||||
mutex_lock(&info->lock); |
||||
work = info->works[n->sequence]; |
||||
mutex_unlock(&info->lock); |
||||
|
||||
if (unlikely(!work)) { |
||||
info->no_matching_work++; |
||||
applog(LOG_INFO, "HFA %d: No matching work!", hashfast->device_id); |
||||
} else { |
||||
applog(LOG_DEBUG, "HFA %d: OP_NONCE: sequence %d: submitting nonce 0x%08x ntime %d", |
||||
hashfast->device_id, n->sequence, n->nonce, n->ntime & HF_NTIME_MASK); |
||||
if ((n->nonce & 0xffff0000) == 0x42420000) // XXX REMOVE THIS
|
||||
break; // XXX PHONEY EMULATOR NONCE
|
||||
submit_noffset_nonce(thr, work, n->nonce, n->ntime & HF_NTIME_MASK); // XXX Return value from submit_nonce is error if set
|
||||
if (unlikely(n->ntime & HF_NONCE_SEARCH)) { |
||||
/* This tells us there is another share in the
|
||||
* next 128 nonces */ |
||||
applog(LOG_DEBUG, "HFA %d: OP_NONCE: SEARCH PROXIMITY EVENT FOUND", |
||||
hashfast->device_id); |
||||
search_for_extra_nonce(thr, work, n); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
static void hfa_update_die_statistics(struct hashfast_info *info, struct hf_header *h) |
||||
{ |
||||
struct hf_statistics *s = (struct hf_statistics *)(h + 1); |
||||
struct hf_long_statistics *l; |
||||
|
||||
// Accumulate the data
|
||||
l = info->die_statistics + h->chip_address; |
||||
|
||||
l->rx_header_crc += s->rx_header_crc; |
||||
l->rx_body_crc += s->rx_body_crc; |
||||
l->rx_header_timeouts += s->rx_header_timeouts; |
||||
l->rx_body_timeouts += s->rx_body_timeouts; |
||||
l->core_nonce_fifo_full += s->core_nonce_fifo_full; |
||||
l->array_nonce_fifo_full += s->array_nonce_fifo_full; |
||||
l->stats_overrun += s->stats_overrun; |
||||
} |
||||
|
||||
static void hfa_update_stats1(struct cgpu_info *hashfast, struct hashfast_info *info, |
||||
struct hf_header *h) |
||||
{ |
||||
struct hf_long_usb_stats1 *s1 = &info->stats1; |
||||
struct hf_usb_stats1 *sd = (struct hf_usb_stats1 *)(h + 1); |
||||
|
||||
s1->usb_rx_preambles += sd->usb_rx_preambles; |
||||
s1->usb_rx_receive_byte_errors += sd->usb_rx_receive_byte_errors; |
||||
s1->usb_rx_bad_hcrc += sd->usb_rx_bad_hcrc; |
||||
|
||||
s1->usb_tx_attempts += sd->usb_tx_attempts; |
||||
s1->usb_tx_packets += sd->usb_tx_packets; |
||||
s1->usb_tx_timeouts += sd->usb_tx_timeouts; |
||||
s1->usb_tx_incompletes += sd->usb_tx_incompletes; |
||||
s1->usb_tx_endpointstalled += sd->usb_tx_endpointstalled; |
||||
s1->usb_tx_disconnected += sd->usb_tx_disconnected; |
||||
s1->usb_tx_suspended += sd->usb_tx_suspended; |
||||
#if 0 |
||||
/* We don't care about UART stats so they're not in our struct */ |
||||
s1->uart_tx_queue_dma += sd->uart_tx_queue_dma; |
||||
s1->uart_tx_interrupts += sd->uart_tx_interrupts; |
||||
|
||||
s1->uart_rx_preamble_ints += sd->uart_rx_preamble_ints; |
||||
s1->uart_rx_missed_preamble_ints += sd->uart_rx_missed_preamble_ints; |
||||
s1->uart_rx_header_done += sd->uart_rx_header_done; |
||||
s1->uart_rx_data_done += sd->uart_rx_data_done; |
||||
s1->uart_rx_bad_hcrc += sd->uart_rx_bad_hcrc; |
||||
s1->uart_rx_bad_dma += sd->uart_rx_bad_dma; |
||||
s1->uart_rx_short_dma += sd->uart_rx_short_dma; |
||||
s1->uart_rx_buffers_full += sd->uart_rx_buffers_full; |
||||
#endif |
||||
if (sd->max_tx_buffers > s1->max_tx_buffers) |
||||
s1->max_tx_buffers = sd->max_tx_buffers; |
||||
if (sd->max_rx_buffers > s1->max_rx_buffers) |
||||
s1->max_rx_buffers = sd->max_rx_buffers; |
||||
|
||||
applog(LOG_DEBUG, "HFA %d: OP_USB_STATS1:", hashfast->device_id); |
||||
applog(LOG_DEBUG, " usb_rx_preambles: %6d", sd->usb_rx_preambles); |
||||
applog(LOG_DEBUG, " usb_rx_receive_byte_errors: %6d", sd->usb_rx_receive_byte_errors); |
||||
applog(LOG_DEBUG, " usb_rx_bad_hcrc: %6d", sd->usb_rx_bad_hcrc); |
||||
|
||||
applog(LOG_DEBUG, " usb_tx_attempts: %6d", sd->usb_tx_attempts); |
||||
applog(LOG_DEBUG, " usb_tx_packets: %6d", sd->usb_tx_packets); |
||||
applog(LOG_DEBUG, " usb_tx_timeouts: %6d", sd->usb_tx_timeouts); |
||||
applog(LOG_DEBUG, " usb_tx_incompletes: %6d", sd->usb_tx_incompletes); |
||||
applog(LOG_DEBUG, " usb_tx_endpointstalled: %6d", sd->usb_tx_endpointstalled); |
||||
applog(LOG_DEBUG, " usb_tx_disconnected: %6d", sd->usb_tx_disconnected); |
||||
applog(LOG_DEBUG, " usb_tx_suspended: %6d", sd->usb_tx_suspended); |
||||
#if 0 |
||||
applog(LOG_DEBUG, " uart_tx_queue_dma: %6d", sd->uart_tx_queue_dma); |
||||
applog(LOG_DEBUG, " uart_tx_interrupts: %6d", sd->uart_tx_interrupts); |
||||
|
||||
applog(LOG_DEBUG, " uart_rx_preamble_ints: %6d", sd->uart_rx_preamble_ints); |
||||
applog(LOG_DEBUG, " uart_rx_missed_preamble_ints: %6d", sd->uart_rx_missed_preamble_ints); |
||||
applog(LOG_DEBUG, " uart_rx_header_done: %6d", sd->uart_rx_header_done); |
||||
applog(LOG_DEBUG, " uart_rx_data_done: %6d", sd->uart_rx_data_done); |
||||
applog(LOG_DEBUG, " uart_rx_bad_hcrc: %6d", sd->uart_rx_bad_hcrc); |
||||
applog(LOG_DEBUG, " uart_rx_bad_dma: %6d", sd->uart_rx_bad_dma); |
||||
applog(LOG_DEBUG, " uart_rx_short_dma: %6d", sd->uart_rx_short_dma); |
||||
applog(LOG_DEBUG, " uart_rx_buffers_full: %6d", sd->uart_rx_buffers_full); |
||||
#endif |
||||
applog(LOG_DEBUG, " max_tx_buffers: %6d", sd->max_tx_buffers); |
||||
applog(LOG_DEBUG, " max_rx_buffers: %6d", sd->max_rx_buffers); |
||||
|
||||
} |
||||
|
||||
static void *hfa_read(void *arg) |
||||
{ |
||||
struct thr_info *thr = (struct thr_info *)arg; |
||||
struct cgpu_info *hashfast = thr->cgpu; |
||||
struct hashfast_info *info = hashfast->device_data; |
||||
char threadname[24]; |
||||
|
||||
snprintf(threadname, 24, "hfa_read/%d", hashfast->device_id); |
||||
RenameThread(threadname); |
||||
|
||||
while (likely(!hashfast->shutdown)) { |
||||
char buf[512]; |
||||
struct hf_header *h = (struct hf_header *)buf; |
||||
bool ret = hfa_get_packet(hashfast, h); |
||||
|
||||
if (unlikely(!ret)) |
||||
continue; |
||||
|
||||
switch (h->operation_code) { |
||||
case OP_GWQ_STATUS: |
||||
hfa_parse_gwq_status(hashfast, info, h); |
||||
break; |
||||
case OP_DIE_STATUS: |
||||
hfa_update_die_status(hashfast, info, h); |
||||
break; |
||||
case OP_NONCE: |
||||
hfa_parse_nonce(thr, hashfast, info, h); |
||||
break; |
||||
case OP_STATISTICS: |
||||
hfa_update_die_statistics(info, h); |
||||
break; |
||||
case OP_USB_STATS1: |
||||
hfa_update_stats1(hashfast, info, h); |
||||
break; |
||||
default: |
||||
applog(LOG_WARNING, "HFA %d: Unhandled operation code %d", |
||||
hashfast->device_id, h->operation_code); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return NULL; |
||||
} |
||||
|
||||
static bool hfa_prepare(struct thr_info *thr) |
||||
{ |
||||
struct cgpu_info *hashfast = thr->cgpu; |
||||
struct hashfast_info *info = hashfast->device_data; |
||||
struct timeval now; |
||||
|
||||
mutex_init(&info->lock); |
||||
if (pthread_create(&info->read_thr, NULL, hfa_read, (void *)thr)) |
||||
quit(1, "Failed to pthread_create read thr in hfa_prepare"); |
||||
|
||||
cgtime(&now); |
||||
get_datestamp(hashfast->init, sizeof(hashfast->init), &now); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/* Figure out how many jobs to send. */ |
||||
static int hfa_jobs(struct hashfast_info *info) |
||||
{ |
||||
int ret; |
||||
|
||||
mutex_lock(&info->lock); |
||||
ret = info->usb_init_base.inflight_target - HF_SEQUENCE_DISTANCE(info->hash_sequence_head, info->device_sequence_tail); |
||||
/* Place an upper limit on how many jobs to queue to prevent sending
|
||||
* more work than the device can use after a period of outage. */ |
||||
if (ret > info->usb_init_base.inflight_target) |
||||
ret = info->usb_init_base.inflight_target; |
||||
mutex_unlock(&info->lock); |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
static int64_t hfa_scanwork(struct thr_info *thr) |
||||
{ |
||||
struct cgpu_info *hashfast = thr->cgpu; |
||||
struct hashfast_info *info = hashfast->device_data; |
||||
int64_t hashes; |
||||
int jobs, ret; |
||||
|
||||
if (unlikely(hashfast->usbinfo.nodev)) { |
||||
applog(LOG_WARNING, "HFA %d: device disappeared, disabling", |
||||
hashfast->device_id); |
||||
return -1; |
||||
} |
||||
|
||||
if (unlikely(thr->work_restart)) { |
||||
restart: |
||||
ret = hfa_send_frame(hashfast, HF_USB_CMD(OP_WORK_RESTART), 0, (uint8_t *)NULL, 0); |
||||
if (unlikely(!ret)) { |
||||
ret = hfa_reset(hashfast, info); |
||||
if (unlikely(!ret)) { |
||||
applog(LOG_ERR, "HFA %d: Failed to reset after write failure, disabling", |
||||
hashfast->device_id); |
||||
return -1; |
||||
} |
||||
} |
||||
} |
||||
|
||||
jobs = hfa_jobs(info); |
||||
|
||||
if (!jobs) { |
||||
ret = restart_wait(thr, 100); |
||||
if (unlikely(!ret)) |
||||
goto restart; |
||||
jobs = hfa_jobs(info); |
||||
} |
||||
|
||||
while (jobs-- > 0) { |
||||
struct hf_hash_usb op_hash_data; |
||||
struct work *work; |
||||
uint64_t intdiff; |
||||
int i, sequence; |
||||
uint32_t *p; |
||||
|
||||
/* This is a blocking function if there's no work */ |
||||
work = get_work(thr, thr->id); |
||||
|
||||
/* Assemble the data frame and send the OP_HASH packet */ |
||||
memcpy(op_hash_data.midstate, work->midstate, sizeof(op_hash_data.midstate)); |
||||
memcpy(op_hash_data.merkle_residual, work->data + 64, 4); |
||||
p = (uint32_t *)(work->data + 64 + 4); |
||||
op_hash_data.timestamp = *p++; |
||||
op_hash_data.bits = *p++; |
||||
op_hash_data.nonce_loops = 0; |
||||
|
||||
/* Set the number of leading zeroes to look for based on diff.
|
||||
* Diff 1 = 32, Diff 2 = 33, Diff 4 = 34 etc. */ |
||||
intdiff = (uint64_t)work->device_diff; |
||||
for (i = 31; intdiff; i++, intdiff >>= 1); |
||||
op_hash_data.search_difficulty = i; |
||||
if ((sequence = info->hash_sequence_head + 1) >= info->num_sequence) |
||||
sequence = 0; |
||||
ret = hfa_send_frame(hashfast, OP_HASH, sequence, (uint8_t *)&op_hash_data, sizeof(op_hash_data)); |
||||
if (unlikely(!ret)) { |
||||
ret = hfa_reset(hashfast, info); |
||||
if (unlikely(!ret)) { |
||||
applog(LOG_ERR, "HFA %d: Failed to reset after write failure, disabling", |
||||
hashfast->device_id); |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
mutex_lock(&info->lock); |
||||
info->hash_sequence_head = sequence; |
||||
info->works[info->hash_sequence_head] = work; |
||||
mutex_unlock(&info->lock); |
||||
|
||||
applog(LOG_DEBUG, "HFA %d: OP_HASH sequence %d search_difficulty %d work_difficulty %g", |
||||
hashfast->device_id, info->hash_sequence_head, op_hash_data.search_difficulty, work->work_difficulty); |
||||
} |
||||
|
||||
mutex_lock(&info->lock); |
||||
hashes = info->hash_count; |
||||
info->hash_count = 0; |
||||
mutex_unlock(&info->lock); |
||||
|
||||
return hashes; |
||||
} |
||||
|
||||
static struct api_data *hfa_api_stats(struct cgpu_info *cgpu) |
||||
{ |
||||
struct hashfast_info *info = cgpu->device_data; |
||||
struct hf_long_usb_stats1 *s1; |
||||
struct api_data *root = NULL; |
||||
struct hf_usb_init_base *db; |
||||
int varint, i; |
||||
char buf[64]; |
||||
|
||||
root = api_add_int(root, "asic count", &info->asic_count, false); |
||||
root = api_add_int(root, "core count", &info->core_count, false); |
||||
|
||||
db = &info->usb_init_base; |
||||
sprintf(buf, "%d.%d", (db->firmware_rev >> 8) & 0xff, db->firmware_rev & 0xff); |
||||
root = api_add_string(root, "firmware rev", buf, true); |
||||
sprintf(buf, "%d.%d", (db->hardware_rev >> 8) & 0xff, db->hardware_rev & 0xff); |
||||
root = api_add_string(root, "hardware rev", buf, true); |
||||
varint = db->serial_number; |
||||
root = api_add_int(root, "serial number", &varint, true); |
||||
varint = db->hash_clockrate; |
||||
root = api_add_int(root, "hash clockrate", &varint, true); |
||||
varint = db->inflight_target; |
||||
root = api_add_int(root, "inflight target", &varint, true); |
||||
varint = db->sequence_modulus; |
||||
root = api_add_int(root, "sequence modules", &varint, true); |
||||
|
||||
s1 = &info->stats1; |
||||
root = api_add_uint64(root, "rx preambles", &s1->usb_rx_preambles, false); |
||||
root = api_add_uint64(root, "rx rcv byte err", &s1->usb_rx_receive_byte_errors, false); |
||||
root = api_add_uint64(root, "rx bad hcrc", &s1->usb_rx_bad_hcrc, false); |
||||
root = api_add_uint64(root, "tx attempts", &s1->usb_tx_attempts, false); |
||||
root = api_add_uint64(root, "tx packets", &s1->usb_tx_packets, false); |
||||
root = api_add_uint64(root, "tx incompletes", &s1->usb_tx_incompletes, false); |
||||
root = api_add_uint64(root, "tx ep stalled", &s1->usb_tx_endpointstalled, false); |
||||
root = api_add_uint64(root, "tx disconnect", &s1->usb_tx_disconnected, false); |
||||
root = api_add_uint64(root, "tx suspend", &s1->usb_tx_suspended, false); |
||||
varint = s1->max_tx_buffers; |
||||
root = api_add_int(root, "max tx buf", &varint, true); |
||||
varint = s1->max_rx_buffers; |
||||
root = api_add_int(root, "max rx buf", &varint, true); |
||||
|
||||
for (i = 0; i < info->asic_count; i++) { |
||||
struct hf_long_statistics *l = &info->die_statistics[i]; |
||||
struct hf_g1_die_data *d = &info->die_status[i]; |
||||
double die_temp, core_voltage; |
||||
int j; |
||||
|
||||
root = api_add_int(root, "Core", &i, true); |
||||
die_temp = GN_DIE_TEMPERATURE(d->die.die_temperature); |
||||
root = api_add_double(root, "die temperature", &die_temp, true); |
||||
for (j = 0; j < 6; j++) { |
||||
core_voltage = GN_CORE_VOLTAGE(d->die.core_voltage[j]); |
||||
sprintf(buf, "%d: %.2f", j, core_voltage); |
||||
root = api_add_string(root, "core voltage", buf, true); |
||||
} |
||||
root = api_add_uint64(root, "rx header crc", &l->rx_header_crc, false); |
||||
root = api_add_uint64(root, "rx body crc", &l->rx_body_crc, false); |
||||
root = api_add_uint64(root, "rx header to", &l->rx_header_timeouts, false); |
||||
root = api_add_uint64(root, "rx body to", &l->rx_body_timeouts, false); |
||||
root = api_add_uint64(root, "cn fifo full", &l->core_nonce_fifo_full, false); |
||||
root = api_add_uint64(root, "an fifo full", &l->array_nonce_fifo_full, false); |
||||
root = api_add_uint64(root, "stats overrun", &l->stats_overrun, false); |
||||
} |
||||
|
||||
return root; |
||||
} |
||||
|
||||
static void hfa_statline_before(char *buf, size_t bufsiz, struct cgpu_info *hashfast) |
||||
{ |
||||
struct hashfast_info *info = hashfast->device_data; |
||||
double max_temp, max_volt; |
||||
struct hf_g1_die_data *d; |
||||
int i; |
||||
|
||||
max_temp = max_volt = 0.0; |
||||
|
||||
for (i = 0; i < info->asic_count; i++) { |
||||
double temp; |
||||
int j; |
||||
|
||||
d = &info->die_status[i]; |
||||
temp = GN_DIE_TEMPERATURE(d->die.die_temperature); |
||||
if (temp > max_temp) |
||||
max_temp = temp; |
||||
for (j = 0; j < 6; j++) { |
||||
double volt = GN_CORE_VOLTAGE(d->die.core_voltage[j]); |
||||
|
||||
if (volt > max_volt) |
||||
max_volt = volt; |
||||
} |
||||
} |
||||
|
||||
tailsprintf(buf, bufsiz, " max%3.0fC %3.2fV | ", max_temp, max_volt); |
||||
} |
||||
|
||||
static void hfa_init(struct cgpu_info __maybe_unused *hashfast) |
||||
{ |
||||
} |
||||
|
||||
static void hfa_free_all_work(struct hashfast_info *info) |
||||
{ |
||||
while (info->device_sequence_tail != info->hash_sequence_head) { |
||||
struct work *work; |
||||
|
||||
if (++info->hash_sequence_tail >= info->num_sequence) |
||||
info->hash_sequence_tail = 0; |
||||
if (unlikely(!(work = info->works[info->hash_sequence_tail]))) |
||||
break; |
||||
free_work(work); |
||||
info->works[info->hash_sequence_tail] = NULL; |
||||
} |
||||
} |
||||
|
||||
static void hfa_shutdown(struct thr_info *thr) |
||||
{ |
||||
struct cgpu_info *hashfast = thr->cgpu; |
||||
struct hashfast_info *info = hashfast->device_data; |
||||
|
||||
hfa_send_shutdown(hashfast); |
||||
pthread_join(info->read_thr, NULL); |
||||
hfa_free_all_work(info); |
||||
hfa_clear_readbuf(hashfast); |
||||
free(info->works); |
||||
free(info->die_statistics); |
||||
free(info->die_status); |
||||
free(info); |
||||
} |
||||
|
||||
struct device_drv hashfast_drv = { |
||||
.drv_id = DRIVER_hashfast, |
||||
.dname = "Hashfast", |
||||
.name = "HFA", |
||||
.max_diff = 256.0, // Limit max diff to get some nonces back regardless
|
||||
.drv_detect = hfa_detect, |
||||
.thread_prepare = hfa_prepare, |
||||
.hash_work = &hash_driver_work, |
||||
.scanwork = hfa_scanwork, |
||||
.get_api_stats = hfa_api_stats, |
||||
.get_statline_before = hfa_statline_before, |
||||
.reinit_device = hfa_init, |
||||
.thread_shutdown = hfa_shutdown, |
||||
}; |
@ -1,97 +0,0 @@
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 Con Kolivas <kernel@kolivas.org> |
||||
* Copyright 2013 Hashfast |
||||
* |
||||
* 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 HASHFAST_H |
||||
#define HASHFAST_H |
||||
|
||||
#ifdef USE_HASHFAST |
||||
#include "miner.h" |
||||
#include "elist.h" |
||||
#include "hf_protocol.h" |
||||
|
||||
#define HASHFAST_MINER_THREADS 1 |
||||
|
||||
// Matching fields for hf_statistics, but large #s for local accumulation, per-die
|
||||
struct hf_long_statistics { |
||||
uint64_t rx_header_crc; // Header CRCs
|
||||
uint64_t rx_body_crc; // Data CRCs
|
||||
uint64_t rx_header_timeouts; // Header timeouts
|
||||
uint64_t rx_body_timeouts; // Data timeouts
|
||||
uint64_t core_nonce_fifo_full; // Core nonce Q overrun events
|
||||
uint64_t array_nonce_fifo_full; // System nonce Q overrun events
|
||||
uint64_t stats_overrun; // Overrun in statistics reporting
|
||||
}; |
||||
|
||||
// Matching fields for hf_usb_stats1, but large #s for local accumulation, per device
|
||||
struct hf_long_usb_stats1 { |
||||
// USB incoming
|
||||
uint64_t usb_rx_preambles; |
||||
uint64_t usb_rx_receive_byte_errors; |
||||
uint64_t usb_rx_bad_hcrc; |
||||
|
||||
// USB outgoing
|
||||
uint64_t usb_tx_attempts; |
||||
uint64_t usb_tx_packets; |
||||
uint64_t usb_tx_timeouts; |
||||
uint64_t usb_tx_incompletes; |
||||
uint64_t usb_tx_endpointstalled; |
||||
uint64_t usb_tx_disconnected; |
||||
uint64_t usb_tx_suspended; |
||||
#if 0 |
||||
/* We don't care about UART stats */ |
||||
// UART transmit
|
||||
uint64_t uart_tx_queue_dma; |
||||
uint64_t uart_tx_interrupts; |
||||
|
||||
// UART receive
|
||||
uint64_t uart_rx_preamble_ints; |
||||
uint64_t uart_rx_missed_preamble_ints; |
||||
uint64_t uart_rx_header_done; |
||||
uint64_t uart_rx_data_done; |
||||
uint64_t uart_rx_bad_hcrc; |
||||
uint64_t uart_rx_bad_dma; |
||||
uint64_t uart_rx_short_dma; |
||||
uint64_t uart_rx_buffers_full; |
||||
#endif |
||||
|
||||
uint8_t max_tx_buffers; |
||||
uint8_t max_rx_buffers; |
||||
}; |
||||
|
||||
struct hashfast_info { |
||||
int asic_count; // # of chips in the chain
|
||||
int core_count; // # of cores per chip
|
||||
int device_type; // What sort of device this is
|
||||
int num_sequence; // A power of 2. What the sequence number range is.
|
||||
int ref_frequency; // Reference clock rate
|
||||
struct hf_g1_die_data *die_status; // Array of per-die voltage, current, temperature sensor data
|
||||
struct hf_long_statistics *die_statistics; // Array of per-die error counters
|
||||
struct hf_long_usb_stats1 stats1; |
||||
int hash_clock_rate; // Hash clock rate to use, in Mhz
|
||||
struct hf_usb_init_base usb_init_base; // USB Base information from USB_INIT
|
||||
struct hf_config_data config_data; // Configuration data used from USB_INIT
|
||||
int core_bitmap_size; // in bytes
|
||||
uint32_t *core_bitmap; // Core OK bitmap test results, run with PLL Bypassed
|
||||
|
||||
pthread_mutex_t lock; |
||||
struct work **works; |
||||
uint16_t hash_sequence_head; // HOST: The next hash sequence # to be sent
|
||||
uint16_t hash_sequence_tail; // HOST: Follows device_sequence_tail around to free work
|
||||
uint16_t device_sequence_head; // DEVICE: The most recent sequence number the device dispatched
|
||||
uint16_t device_sequence_tail; // DEVICE: The most recently completed job in the device
|
||||
int64_t hash_count; |
||||
uint16_t shed_count; // Dynamic copy of #cores device has shed for thermal control
|
||||
int no_matching_work; |
||||
|
||||
pthread_t read_thr; |
||||
}; |
||||
|
||||
#endif /* USE_HASHFAST */ |
||||
#endif /* HASHFAST_H */ |
@ -1,762 +0,0 @@
@@ -1,762 +0,0 @@
|
||||
/*
|
||||
* cgminer driver for KnCminer devices |
||||
* |
||||
* Copyright 2013 Con Kolivas <kernel@kolivas.org> |
||||
* Copyright 2013 KnCminer |
||||
* |
||||
* 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 <stdlib.h> |
||||
#include <assert.h> |
||||
#include <fcntl.h> |
||||
#include <limits.h> |
||||
#include <unistd.h> |
||||
#include <sys/ioctl.h> |
||||
#include <linux/types.h> |
||||
#include <linux/spi/spidev.h> |
||||
|
||||
#include "logging.h" |
||||
#include "miner.h" |
||||
|
||||
#define MAX_SPIS 1 |
||||
#define MAX_BYTES_IN_SPI_XSFER 4096 |
||||
/* /dev/spidevB.C, where B = bus, C = chipselect */ |
||||
#define SPI_DEVICE_TEMPLATE "/dev/spidev%d.%d" |
||||
#define SPI_MODE (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH) |
||||
#define SPI_BITS_PER_WORD 32 |
||||
#define SPI_MAX_SPEED 3000000 |
||||
#define SPI_DELAY_USECS 0 |
||||
/* Max number of ASICs permitted on one SPI device */ |
||||
#define MAX_ASICS 6 |
||||
|
||||
/* How many hardware errors in a row before disabling the core */ |
||||
#define HW_ERR_LIMIT 10 |
||||
#define DISA_ERR_LIMIT 3 |
||||
|
||||
#define MAX_ACTIVE_WORKS (192 * 2 * 6 * 2) |
||||
|
||||
#define WORK_MIDSTATE_WORDS 8 |
||||
#define WORK_DATA_WORDS 3 |
||||
|
||||
#define WORK_STALE_US 60000000 |
||||
|
||||
/* Keep core disabled for no longer than 15 minutes */ |
||||
#define CORE_DISA_PERIOD_US (15 * 60 * 1000000) |
||||
|
||||
struct spidev_context { |
||||
int fd; |
||||
uint32_t speed; |
||||
uint16_t delay; |
||||
uint8_t mode; |
||||
uint8_t bits; |
||||
}; |
||||
|
||||
struct spi_request { |
||||
#define CMD_NOP 0 |
||||
#define CMD_GET_VERSION 1 |
||||
#define CMD_SUBMIT_WORK 2 |
||||
#define CMD_FLUSH_QUEUE 3 |
||||
|
||||
#define WORK_ID_MASK 0x7FFF |
||||
|
||||
#if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) |
||||
uint32_t cmd :4; |
||||
uint32_t rsvd :1; /* set to zero */ |
||||
uint32_t queue_id :12; |
||||
uint32_t work_id :15; |
||||
#else |
||||
uint32_t work_id :15; |
||||
uint32_t queue_id :12; |
||||
uint32_t rsvd :1; /* set to zero */ |
||||
uint32_t cmd :4; |
||||
#endif |
||||
uint32_t midstate[WORK_MIDSTATE_WORDS]; |
||||
uint32_t data[WORK_DATA_WORDS]; |
||||
}; |
||||
|
||||
struct spi_response { |
||||
#define RESPONSE_TYPE_NOP 0 |
||||
#define RESPONSE_TYPE_NONCE_FOUND 1 |
||||
#define RESPONSE_TYPE_WORK_DONE 2 |
||||
#if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) |
||||
uint32_t type :2; |
||||
uint32_t asic :3; |
||||
uint32_t queue_id :12; |
||||
uint32_t work_id :15; |
||||
#else |
||||
uint32_t work_id :15; |
||||
uint32_t queue_id :12; |
||||
uint32_t asic :3; |
||||
uint32_t type :2; |
||||
#endif |
||||
uint32_t nonce; |
||||
uint32_t core; |
||||
}; |
||||
|
||||
#define MAX_REQUESTS_IN_BATCH ( MAX_BYTES_IN_SPI_XSFER / \ |
||||
sizeof(struct spi_request) \ |
||||
) |
||||
|
||||
static struct spi_request spi_txbuf[MAX_REQUESTS_IN_BATCH]; |
||||
|
||||
#define MAX_RESPONSES_IN_BATCH ( (sizeof(spi_txbuf) - 12) / \ |
||||
sizeof(struct spi_response) \ |
||||
) |
||||
|
||||
struct spi_rx_t { |
||||
#if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) |
||||
uint32_t rsvd_1 :31; |
||||
uint32_t response_queue_full :1; |
||||
#else |
||||
uint32_t response_queue_full :1; |
||||
uint32_t rsvd_1 :31; |
||||
#endif |
||||
#if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) |
||||
uint32_t rsvd_2 :16; |
||||
uint32_t works_accepted :16; |
||||
#else |
||||
uint32_t works_accepted :16; |
||||
uint32_t rsvd_2 :16; |
||||
#endif |
||||
uint32_t rsvd_3; |
||||
struct spi_response responses[MAX_RESPONSES_IN_BATCH]; |
||||
}; |
||||
|
||||
static struct spi_rx_t spi_rxbuf; |
||||
|
||||
struct active_work { |
||||
struct work *work; |
||||
uint32_t work_id; |
||||
struct timeval begin; |
||||
}; |
||||
|
||||
struct core_disa_data { |
||||
struct timeval disa_begin; |
||||
uint8_t asic; |
||||
uint8_t core; |
||||
}; |
||||
|
||||
struct knc_state { |
||||
struct spidev_context *ctx; |
||||
int devices; |
||||
uint32_t salt; |
||||
uint32_t next_work_id; |
||||
|
||||
/* read - last read item, next is at (read + 1) mod BUFSIZE
|
||||
* write - next write item, last written at (write - 1) mod BUFSIZE |
||||
* When buffer is empty, read + 1 == write |
||||
* Buffer full condition: read == write |
||||
*/ |
||||
int read_q, write_q; |
||||
#define KNC_QUEUED_BUFFER_SIZE (MAX_REQUESTS_IN_BATCH + 1) |
||||
struct active_work queued_fifo[KNC_QUEUED_BUFFER_SIZE]; |
||||
|
||||
int read_a, write_a; |
||||
#define KNC_ACTIVE_BUFFER_SIZE (MAX_ACTIVE_WORKS + 1) |
||||
struct active_work active_fifo[KNC_ACTIVE_BUFFER_SIZE]; |
||||
|
||||
uint8_t hwerrs[MAX_ASICS * 256]; |
||||
uint8_t disa_cnt[MAX_ASICS * 256]; |
||||
uint32_t hwerr_work_id[MAX_ASICS * 256]; |
||||
int read_d, write_d; |
||||
#define KNC_DISA_CORES_SIZE (MAX_ASICS * 256) |
||||
struct core_disa_data disa_cores_fifo[KNC_DISA_CORES_SIZE]; |
||||
|
||||
pthread_mutex_t lock; |
||||
}; |
||||
|
||||
static inline bool knc_queued_fifo_full(struct knc_state *knc) |
||||
{ |
||||
return (knc->read_q == knc->write_q); |
||||
} |
||||
|
||||
static inline bool knc_active_fifo_full(struct knc_state *knc) |
||||
{ |
||||
return (knc->read_a == knc->write_a); |
||||
} |
||||
|
||||
static inline void knc_queued_fifo_inc_idx(int *idx) |
||||
{ |
||||
if (unlikely(*idx >= ((int)KNC_QUEUED_BUFFER_SIZE - 1))) |
||||
*idx = 0; |
||||
else |
||||
++(*idx); |
||||
} |
||||
|
||||
static inline void knc_active_fifo_inc_idx(int *idx) |
||||
{ |
||||
if (unlikely(*idx >= (KNC_ACTIVE_BUFFER_SIZE - 1))) |
||||
*idx = 0; |
||||
else |
||||
++(*idx); |
||||
} |
||||
|
||||
static inline void knc_disa_cores_fifo_inc_idx(int *idx) |
||||
{ |
||||
if (unlikely(*idx >= (KNC_DISA_CORES_SIZE - 1))) |
||||
*idx = 0; |
||||
else |
||||
++(*idx); |
||||
} |
||||
|
||||
/* Find SPI device with index idx, init it */ |
||||
static struct spidev_context *spi_new(int idx) |
||||
{ |
||||
struct spidev_context *ctx; |
||||
char dev_fname[PATH_MAX]; |
||||
|
||||
if (NULL == (ctx = malloc(sizeof(struct spidev_context)))) { |
||||
applog(LOG_ERR, "KnC spi: Out of memory"); |
||||
goto l_exit_error; |
||||
} |
||||
ctx->mode = SPI_MODE; |
||||
ctx->bits = SPI_BITS_PER_WORD; |
||||
ctx->speed = SPI_MAX_SPEED; |
||||
ctx->delay = SPI_DELAY_USECS; |
||||
|
||||
ctx->fd = -1; |
||||
|
||||
sprintf(dev_fname, SPI_DEVICE_TEMPLATE, |
||||
idx, /* bus */ |
||||
0 /* chipselect */ |
||||
); |
||||
if (0 > (ctx->fd = open(dev_fname, O_RDWR))) { |
||||
applog(LOG_ERR, "KnC spi: Can not open SPI device %s: %m", |
||||
dev_fname); |
||||
goto l_free_exit_error; |
||||
} |
||||
|
||||
/*
|
||||
* spi mode |
||||
*/ |
||||
if (0 > ioctl(ctx->fd, SPI_IOC_WR_MODE, &ctx->mode)) |
||||
goto l_ioctl_error; |
||||
if (0 > ioctl(ctx->fd, SPI_IOC_RD_MODE, &ctx->mode)) |
||||
goto l_ioctl_error; |
||||
|
||||
/*
|
||||
* bits per word |
||||
*/ |
||||
if (0 > ioctl(ctx->fd, SPI_IOC_WR_BITS_PER_WORD, &ctx->bits)) |
||||
goto l_ioctl_error; |
||||
if (0 > ioctl(ctx->fd, SPI_IOC_RD_BITS_PER_WORD, &ctx->bits)) |
||||
goto l_ioctl_error; |
||||
|
||||
/*
|
||||
* max speed hz |
||||
*/ |
||||
if (0 > ioctl(ctx->fd, SPI_IOC_WR_MAX_SPEED_HZ, &ctx->speed)) |
||||
goto l_ioctl_error; |
||||
if (0 > ioctl(ctx->fd, SPI_IOC_RD_MAX_SPEED_HZ, &ctx->speed)) |
||||
goto l_ioctl_error; |
||||
|
||||
applog(LOG_INFO, "KnC spi: device %s uses mode %hhu, bits %hhu, speed %u", |
||||
dev_fname, ctx->mode, ctx->bits, ctx->speed); |
||||
|
||||
return ctx; |
||||
|
||||
l_ioctl_error: |
||||
applog(LOG_ERR, "KnC spi: ioctl error on SPI device %s: %m", dev_fname); |
||||
close(ctx->fd); |
||||
l_free_exit_error: |
||||
free(ctx); |
||||
l_exit_error: |
||||
return NULL; |
||||
} |
||||
|
||||
static void spi_free(struct spidev_context *ctx) |
||||
{ |
||||
if (NULL == ctx) |
||||
return; |
||||
|
||||
close(ctx->fd); |
||||
free(ctx); |
||||
} |
||||
|
||||
static int spi_transfer(struct spidev_context *ctx, uint8_t *txbuf, |
||||
uint8_t *rxbuf, int len) |
||||
{ |
||||
struct spi_ioc_transfer xfr; |
||||
int ret; |
||||
|
||||
memset(rxbuf, 0xff, len); |
||||
|
||||
ret = len; |
||||
|
||||
xfr.tx_buf = (unsigned long)txbuf; |
||||
xfr.rx_buf = (unsigned long)rxbuf; |
||||
xfr.len = len; |
||||
xfr.speed_hz = ctx->speed; |
||||
xfr.delay_usecs = ctx->delay; |
||||
xfr.bits_per_word = ctx->bits; |
||||
xfr.cs_change = 0; |
||||
xfr.pad = 0; |
||||
|
||||
if (1 > (ret = ioctl(ctx->fd, SPI_IOC_MESSAGE(1), &xfr))) |
||||
applog(LOG_ERR, "KnC spi xfer: ioctl error on SPI device: %m"); |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
static void disable_core(uint8_t asic, uint8_t core) |
||||
{ |
||||
char str[256]; |
||||
|
||||
snprintf(str, sizeof(str), "i2cset -y 2 0x2%hhu %hhu 0", asic, core); |
||||
if (0 != WEXITSTATUS(system(str))) |
||||
applog(LOG_ERR, "KnC: system call failed"); |
||||
} |
||||
|
||||
static void enable_core(uint8_t asic, uint8_t core) |
||||
{ |
||||
char str[256]; |
||||
|
||||
snprintf(str, sizeof(str), "i2cset -y 2 0x2%hhu %hhu 1", asic, core); |
||||
if (0 != WEXITSTATUS(system(str))) |
||||
applog(LOG_ERR, "KnC: system call failed"); |
||||
} |
||||
|
||||
static int64_t timediff(const struct timeval *a, const struct timeval *b) |
||||
{ |
||||
struct timeval diff; |
||||
|
||||
timersub(a, b, &diff); |
||||
|
||||
return diff.tv_sec * 1000000 + diff.tv_usec; |
||||
} |
||||
|
||||
static void knc_check_disabled_cores(struct knc_state *knc) |
||||
{ |
||||
struct core_disa_data *core; |
||||
int next_read_d, cidx; |
||||
struct timeval now; |
||||
int64_t us; |
||||
|
||||
next_read_d = knc->read_d; |
||||
knc_disa_cores_fifo_inc_idx(&next_read_d); |
||||
if (next_read_d == knc->write_d) |
||||
return; /* queue empty */ |
||||
|
||||
core = &knc->disa_cores_fifo[next_read_d]; |
||||
gettimeofday(&now, NULL); |
||||
us = timediff(&now, &core->disa_begin); |
||||
if ((us >= 0) && (us < CORE_DISA_PERIOD_US)) |
||||
return; /* latest disabled core still not expired */ |
||||
|
||||
cidx = core->asic * 256 + core->core; |
||||
enable_core(core->asic, core->core); |
||||
knc->hwerrs[cidx] = 0; |
||||
applog(LOG_NOTICE, |
||||
"KnC: core %u-%u was enabled back from disabled state", |
||||
core->asic, core->core); |
||||
knc->read_d = next_read_d; |
||||
} |
||||
|
||||
static void knc_work_from_queue_to_spi(struct knc_state *knc, |
||||
struct active_work *q_work, |
||||
struct spi_request *spi_req) |
||||
{ |
||||
uint32_t *buf_from, *buf_to; |
||||
int i; |
||||
|
||||
spi_req->cmd = CMD_SUBMIT_WORK; |
||||
spi_req->queue_id = 0; /* at the moment we have one and only queue #0 */ |
||||
spi_req->work_id = (knc->next_work_id ^ knc->salt) & WORK_ID_MASK; |
||||
q_work->work_id = spi_req->work_id; |
||||
++(knc->next_work_id); |
||||
buf_to = spi_req->midstate; |
||||
buf_from = (uint32_t *)q_work->work->midstate; |
||||
|
||||
for (i = 0; i < WORK_MIDSTATE_WORDS; ++i) |
||||
buf_to[i] = le32toh(buf_from[8 - i - 1]); |
||||
buf_to = spi_req->data; |
||||
buf_from = (uint32_t *)&(q_work->work->data[16 * 4]); |
||||
|
||||
for (i = 0; i < WORK_DATA_WORDS; ++i) |
||||
buf_to[i] = le32toh(buf_from[3 - i - 1]); |
||||
} |
||||
|
||||
static int64_t knc_process_response(struct thr_info *thr, struct cgpu_info *cgpu, |
||||
struct spi_rx_t *rxbuf) |
||||
{ |
||||
struct knc_state *knc = cgpu->device_data; |
||||
int submitted, successful, i, num_sent; |
||||
int next_read_q, next_read_a; |
||||
struct timeval now; |
||||
struct work *work; |
||||
int64_t us; |
||||
|
||||
num_sent = knc->write_q - knc->read_q - 1; |
||||
if (knc->write_q <= knc->read_q) |
||||
num_sent += KNC_QUEUED_BUFFER_SIZE; |
||||
|
||||
/* Actually process SPI response */ |
||||
if (rxbuf->works_accepted) { |
||||
applog(LOG_DEBUG, "KnC spi: raw response %08X %08X", |
||||
((uint32_t *)rxbuf)[0], ((uint32_t *)rxbuf)[1]); |
||||
applog(LOG_DEBUG, |
||||
"KnC spi: response, accepted %u (from %u), full %u", |
||||
rxbuf->works_accepted, num_sent, |
||||
rxbuf->response_queue_full); |
||||
} |
||||
/* move works_accepted number of items from queued_fifo to active_fifo */ |
||||
gettimeofday(&now, NULL); |
||||
submitted = 0; |
||||
|
||||
for (i = 0; i < rxbuf->works_accepted; ++i) { |
||||
next_read_q = knc->read_q; |
||||
knc_queued_fifo_inc_idx(&next_read_q); |
||||
if ((next_read_q == knc->write_q) || knc_active_fifo_full(knc)) |
||||
break; |
||||
|
||||
memcpy(&knc->active_fifo[knc->write_a], |
||||
&knc->queued_fifo[next_read_q], |
||||
sizeof(struct active_work)); |
||||
knc->active_fifo[knc->write_a].begin = now; |
||||
knc->queued_fifo[next_read_q].work = NULL; |
||||
knc->read_q = next_read_q; |
||||
knc_active_fifo_inc_idx(&knc->write_a); |
||||
++submitted; |
||||
} |
||||
if (submitted != rxbuf->works_accepted) { |
||||
applog(LOG_ERR, |
||||
"KnC: accepted by FPGA %u works, but only %d submitted", |
||||
rxbuf->works_accepted, submitted); |
||||
} |
||||
|
||||
/* check for completed works and calculated nonces */ |
||||
gettimeofday(&now, NULL); |
||||
successful = 0; |
||||
|
||||
for (i = 0; i < (int)MAX_RESPONSES_IN_BATCH; ++i) { |
||||
if ((rxbuf->responses[i].type != RESPONSE_TYPE_NONCE_FOUND) && |
||||
(rxbuf->responses[i].type != RESPONSE_TYPE_WORK_DONE)) |
||||
continue; |
||||
|
||||
applog(LOG_DEBUG, "KnC spi: raw response %08X %08X", |
||||
((uint32_t *)&rxbuf->responses[i])[0], |
||||
((uint32_t *)&rxbuf->responses[i])[1]); |
||||
applog(LOG_DEBUG, "KnC spi: response, T:%u C:%u-%u Q:%u W:%u", |
||||
rxbuf->responses[i].type, |
||||
rxbuf->responses[i].asic, rxbuf->responses[i].core, |
||||
rxbuf->responses[i].queue_id, |
||||
rxbuf->responses[i].work_id); |
||||
/* Find active work with matching ID */ |
||||
next_read_a = knc->read_a; |
||||
knc_active_fifo_inc_idx(&next_read_a); |
||||
|
||||
while (next_read_a != knc->write_a) { |
||||
if (knc->active_fifo[next_read_a].work_id == |
||||
rxbuf->responses[i].work_id) |
||||
break; |
||||
|
||||
/* check for stale works */ |
||||
us = timediff(&now, |
||||
&knc->active_fifo[next_read_a].begin); |
||||
if ((us < 0) || (us >= WORK_STALE_US)) { |
||||
applog(LOG_DEBUG, |
||||
"KnC spi: remove stale work %u", |
||||
knc->active_fifo[next_read_a].work_id); |
||||
work = knc->active_fifo[next_read_a].work; |
||||
knc_active_fifo_inc_idx(&knc->read_a); |
||||
work_completed(cgpu, work); |
||||
if (next_read_a != knc->read_a) { |
||||
memcpy(&(knc->active_fifo[next_read_a]), |
||||
&(knc->active_fifo[knc->read_a]), |
||||
sizeof(struct active_work)); |
||||
} |
||||
knc->active_fifo[knc->read_a].work = NULL; |
||||
} |
||||
|
||||
knc_active_fifo_inc_idx(&next_read_a); |
||||
} |
||||
if (next_read_a == knc->write_a) |
||||
continue; |
||||
|
||||
applog(LOG_DEBUG, "KnC spi: response work %u found", |
||||
rxbuf->responses[i].work_id); |
||||
work = knc->active_fifo[next_read_a].work; |
||||
|
||||
if (rxbuf->responses[i].type == RESPONSE_TYPE_NONCE_FOUND) { |
||||
if (NULL != thr) { |
||||
int cidx = rxbuf->responses[i].asic * 256 + |
||||
rxbuf->responses[i].core; |
||||
|
||||
if (submit_nonce(thr, work, |
||||
rxbuf->responses[i].nonce)) { |
||||
if (cidx < (int)sizeof(knc->hwerrs)) { |
||||
knc->hwerrs[cidx] = 0; |
||||
knc->disa_cnt[cidx] = 0; |
||||
knc->hwerr_work_id[cidx] = 0xFFFFFFFF; |
||||
} |
||||
successful++; |
||||
} else { |
||||
if ((cidx < (int)sizeof(knc->hwerrs)) && |
||||
(knc->hwerr_work_id[cidx] != rxbuf->responses[i].work_id)) { |
||||
knc->hwerr_work_id[cidx] = rxbuf->responses[i].work_id; |
||||
if (++(knc->hwerrs[cidx]) >= HW_ERR_LIMIT) { |
||||
struct core_disa_data *core; |
||||
|
||||
core = &knc->disa_cores_fifo[knc->write_d]; |
||||
core->disa_begin = now; |
||||
core->asic = rxbuf->responses[i].asic; |
||||
core->core = rxbuf->responses[i].core; |
||||
disable_core(core->asic, core->core); |
||||
if (++(knc->disa_cnt[cidx]) >= DISA_ERR_LIMIT) { |
||||
applog(LOG_WARNING, |
||||
"KnC: core %u-%u was disabled permanently", core->asic, core->core); |
||||
} else { |
||||
applog(LOG_WARNING, |
||||
"KnC: core %u-%u was disabled due to %u HW errors in a row", |
||||
core->asic, core->core, HW_ERR_LIMIT); |
||||
knc_disa_cores_fifo_inc_idx(&knc->write_d); |
||||
} |
||||
} |
||||
} |
||||
}; |
||||
} |
||||
continue; |
||||
} |
||||
|
||||
/* Work completed */ |
||||
knc_active_fifo_inc_idx(&knc->read_a); |
||||
work_completed(cgpu, work); |
||||
if (next_read_a != knc->read_a) { |
||||
memcpy(&(knc->active_fifo[next_read_a]), |
||||
&(knc->active_fifo[knc->read_a]), |
||||
sizeof(struct active_work)); |
||||
} |
||||
knc->active_fifo[knc->read_a].work = NULL; |
||||
} |
||||
|
||||
return ((uint64_t)successful) * 0x100000000UL; |
||||
} |
||||
|
||||
/* Send flush command via SPI */ |
||||
static int _internal_knc_flush_fpga(struct knc_state *knc) |
||||
{ |
||||
int len; |
||||
|
||||
spi_txbuf[0].cmd = CMD_FLUSH_QUEUE; |
||||
spi_txbuf[0].queue_id = 0; /* at the moment we have one and only queue #0 */ |
||||
len = spi_transfer(knc->ctx, (uint8_t *)spi_txbuf, |
||||
(uint8_t *)&spi_rxbuf, sizeof(struct spi_request)); |
||||
if (len != sizeof(struct spi_request)) |
||||
return -1; |
||||
|
||||
len /= sizeof(struct spi_response); |
||||
|
||||
return len; |
||||
} |
||||
|
||||
static bool knc_detect_one(struct spidev_context *ctx) |
||||
{ |
||||
/* Scan device for ASICs */ |
||||
int chip_id, devices = 0; |
||||
struct cgpu_info *cgpu; |
||||
struct knc_state *knc; |
||||
|
||||
for (chip_id = 0; chip_id < MAX_ASICS; ++chip_id) { |
||||
/* TODO: perform the ASIC test/detection */ |
||||
++devices; |
||||
} |
||||
|
||||
if (!devices) { |
||||
applog(LOG_INFO, "SPI detected, but not KnCminer ASICs"); |
||||
return false; |
||||
} |
||||
|
||||
applog(LOG_INFO, "Found a KnC miner with %d ASICs", devices); |
||||
|
||||
cgpu = calloc(1, sizeof(*cgpu)); |
||||
knc = calloc(1, sizeof(*knc)); |
||||
if (!cgpu || !knc) { |
||||
applog(LOG_ERR, "KnC miner detected, but failed to allocate memory"); |
||||
return false; |
||||
} |
||||
|
||||
knc->ctx = ctx; |
||||
knc->devices = devices; |
||||
knc->read_q = 0; |
||||
knc->write_q = 1; |
||||
knc->read_a = 0; |
||||
knc->write_a = 1; |
||||
knc->read_d = 0; |
||||
knc->write_d = 1; |
||||
knc->salt = rand(); |
||||
mutex_init(&knc->lock); |
||||
|
||||
memset(knc->hwerr_work_id, 0xFF, sizeof(knc->hwerr_work_id)); |
||||
|
||||
_internal_knc_flush_fpga(knc); |
||||
|
||||
cgpu->drv = &knc_drv; |
||||
cgpu->name = "KnCminer"; |
||||
cgpu->threads = 1; // .. perhaps our number of devices?
|
||||
|
||||
cgpu->device_data = knc; |
||||
add_cgpu(cgpu); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
// http://www.concentric.net/~Ttwang/tech/inthash.htm
|
||||
static unsigned long mix(unsigned long a, unsigned long b, unsigned long c) |
||||
{ |
||||
a = a - b; a = a - c; a = a ^ (c >> 13); |
||||
b = b - c; b = b - a; b = b ^ (a << 8); |
||||
c = c - a; c = c - b; c = c ^ (b >> 13); |
||||
a = a - b; a = a - c; a = a ^ (c >> 12); |
||||
b = b - c; b = b - a; b = b ^ (a << 16); |
||||
c = c - a; c = c - b; c = c ^ (b >> 5); |
||||
a = a - b; a = a - c; a = a ^ (c >> 3); |
||||
b = b - c; b = b - a; b = b ^ (a << 10); |
||||
c = c - a; c = c - b; c = c ^ (b >> 15); |
||||
|
||||
return c; |
||||
} |
||||
|
||||
/* Probe devices and register with add_cgpu */ |
||||
void knc_detect(bool __maybe_unused hotplug) |
||||
{ |
||||
int idx; |
||||
|
||||
srand(mix(clock(), time(NULL), getpid())); |
||||
|
||||
/* Loop through all possible SPI interfaces */ |
||||
for (idx = 0; idx < MAX_SPIS; ++idx) { |
||||
struct spidev_context *ctx = spi_new(idx + 1); |
||||
|
||||
if (ctx != NULL) { |
||||
if (!knc_detect_one(ctx)) |
||||
spi_free(ctx); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/* return value is number of nonces that have been checked since
|
||||
* previous call |
||||
*/ |
||||
static int64_t knc_scanwork(struct thr_info *thr) |
||||
{ |
||||
struct cgpu_info *cgpu = thr->cgpu; |
||||
struct knc_state *knc = cgpu->device_data; |
||||
int len, num, next_read_q; |
||||
int64_t ret; |
||||
|
||||
applog(LOG_DEBUG, "KnC running scanwork"); |
||||
|
||||
knc_check_disabled_cores(knc); |
||||
|
||||
/* Prepare tx buffer */ |
||||
memset(spi_txbuf, 0, sizeof(spi_txbuf)); |
||||
num = 0; |
||||
|
||||
mutex_lock(&knc->lock); |
||||
next_read_q = knc->read_q; |
||||
knc_queued_fifo_inc_idx(&next_read_q); |
||||
|
||||
while (next_read_q != knc->write_q) { |
||||
knc_work_from_queue_to_spi(knc, &knc->queued_fifo[next_read_q], |
||||
&spi_txbuf[num]); |
||||
knc_queued_fifo_inc_idx(&next_read_q); |
||||
++num; |
||||
} |
||||
/* knc->read_q is advanced in knc_process_response, not here */ |
||||
|
||||
len = spi_transfer(knc->ctx, (uint8_t *)spi_txbuf, |
||||
(uint8_t *)&spi_rxbuf, sizeof(spi_txbuf)); |
||||
if (len != sizeof(spi_rxbuf)) { |
||||
ret = -1; |
||||
goto out_unlock; |
||||
} |
||||
|
||||
applog(LOG_DEBUG, "KnC spi: %d works in request", num); |
||||
|
||||
ret = knc_process_response(thr, cgpu, &spi_rxbuf); |
||||
out_unlock: |
||||
mutex_unlock(&knc->lock); |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
static bool knc_queue_full(struct cgpu_info *cgpu) |
||||
{ |
||||
struct knc_state *knc = cgpu->device_data; |
||||
int queue_full = false; |
||||
struct work *work; |
||||
|
||||
applog(LOG_DEBUG, "KnC running queue full"); |
||||
|
||||
mutex_lock(&knc->lock); |
||||
if (knc_queued_fifo_full(knc)) { |
||||
queue_full = true; |
||||
goto out_unlock; |
||||
} |
||||
work = get_queued(cgpu); |
||||
if (!work) |
||||
goto out_unlock; |
||||
knc->queued_fifo[knc->write_q].work = work; |
||||
knc_queued_fifo_inc_idx(&(knc->write_q)); |
||||
if (knc_queued_fifo_full(knc)) |
||||
queue_full = true; |
||||
out_unlock: |
||||
mutex_unlock(&knc->lock); |
||||
|
||||
return queue_full; |
||||
} |
||||
|
||||
static void knc_flush_work(struct cgpu_info *cgpu) |
||||
{ |
||||
struct knc_state *knc = cgpu->device_data; |
||||
int len, next_read_q, next_read_a; |
||||
struct work *work; |
||||
|
||||
applog(LOG_ERR, "KnC running flushwork"); |
||||
|
||||
mutex_lock(&knc->lock); |
||||
/* Drain queued works */ |
||||
next_read_q = knc->read_q; |
||||
knc_queued_fifo_inc_idx(&next_read_q); |
||||
|
||||
while (next_read_q != knc->write_q) { |
||||
work = knc->queued_fifo[next_read_q].work; |
||||
work_completed(cgpu, work); |
||||
knc->queued_fifo[next_read_q].work = NULL; |
||||
knc->read_q = next_read_q; |
||||
knc_queued_fifo_inc_idx(&next_read_q); |
||||
} |
||||
|
||||
/* Drain active works */ |
||||
next_read_a = knc->read_a; |
||||
knc_active_fifo_inc_idx(&next_read_a); |
||||
|
||||
while (next_read_a != knc->write_a) { |
||||
work = knc->active_fifo[next_read_a].work; |
||||
work_completed(cgpu, work); |
||||
knc->active_fifo[next_read_a].work = NULL; |
||||
knc->read_a = next_read_a; |
||||
knc_active_fifo_inc_idx(&next_read_a); |
||||
} |
||||
|
||||
len = _internal_knc_flush_fpga(knc); |
||||
if (len > 0) |
||||
knc_process_response(NULL, cgpu, &spi_rxbuf); |
||||
mutex_unlock(&knc->lock); |
||||
} |
||||
|
||||
struct device_drv knc_drv = { |
||||
.drv_id = DRIVER_knc, |
||||
.dname = "KnCminer", |
||||
.name = "KnC", |
||||
.drv_detect = knc_detect, // Probe for devices, add with add_cgpu
|
||||
|
||||
.hash_work = hash_queued_work, |
||||
.scanwork = knc_scanwork, |
||||
.queue_full = knc_queue_full, |
||||
.flush_work = knc_flush_work, |
||||
}; |
@ -1,610 +0,0 @@
@@ -1,610 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 Con Kolivas <kernel@kolivas.org> |
||||
* 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 <sys/types.h> |
||||
#include <dirent.h> |
||||
#include <string.h> |
||||
|
||||
#include "miner.h" |
||||
|
||||
#ifndef WIN32 |
||||
#include <errno.h> |
||||
#include <termios.h> |
||||
#include <sys/ioctl.h> |
||||
#include <sys/stat.h> |
||||
#include <unistd.h> |
||||
#include <fcntl.h> |
||||
#ifndef O_CLOEXEC |
||||
#define O_CLOEXEC 0 |
||||
#endif |
||||
#else |
||||
#include <windows.h> |
||||
#include <io.h> |
||||
#endif |
||||
|
||||
#ifdef HAVE_LIBUDEV |
||||
#include <libudev.h> |
||||
#include <sys/ioctl.h> |
||||
#endif |
||||
|
||||
#include "elist.h" |
||||
#include "logging.h" |
||||
#include "miner.h" |
||||
#include "fpgautils.h" |
||||
|
||||
#ifdef HAVE_LIBUDEV |
||||
int serial_autodetect_udev(detectone_func_t detectone, const char*prodname) |
||||
{ |
||||
struct udev *udev = udev_new(); |
||||
struct udev_enumerate *enumerate = udev_enumerate_new(udev); |
||||
struct udev_list_entry *list_entry; |
||||
char found = 0; |
||||
|
||||
udev_enumerate_add_match_subsystem(enumerate, "tty"); |
||||
udev_enumerate_add_match_property(enumerate, "ID_MODEL", prodname); |
||||
udev_enumerate_scan_devices(enumerate); |
||||
udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) { |
||||
struct udev_device *device = udev_device_new_from_syspath( |
||||
udev_enumerate_get_udev(enumerate), |
||||
udev_list_entry_get_name(list_entry) |
||||
); |
||||
if (!device) |
||||
continue; |
||||
|
||||
const char *devpath = udev_device_get_devnode(device); |
||||
if (devpath && detectone(devpath)) |
||||
++found; |
||||
|
||||
udev_device_unref(device); |
||||
} |
||||
udev_enumerate_unref(enumerate); |
||||
udev_unref(udev); |
||||
|
||||
return found; |
||||
} |
||||
#else |
||||
int serial_autodetect_udev(__maybe_unused detectone_func_t detectone, __maybe_unused const char*prodname) |
||||
{ |
||||
return 0; |
||||
} |
||||
#endif |
||||
|
||||
int serial_autodetect_devserial(__maybe_unused detectone_func_t detectone, __maybe_unused const char*prodname) |
||||
{ |
||||
#ifndef WIN32 |
||||
DIR *D; |
||||
struct dirent *de; |
||||
const char udevdir[] = "/dev/serial/by-id"; |
||||
char devpath[sizeof(udevdir) + 1 + NAME_MAX]; |
||||
char *devfile = devpath + sizeof(udevdir); |
||||
char found = 0; |
||||
|
||||
D = opendir(udevdir); |
||||
if (!D) |
||||
return 0; |
||||
memcpy(devpath, udevdir, sizeof(udevdir) - 1); |
||||
devpath[sizeof(udevdir) - 1] = '/'; |
||||
while ( (de = readdir(D)) ) { |
||||
if (!strstr(de->d_name, prodname)) |
||||
continue; |
||||
strcpy(devfile, de->d_name); |
||||
if (detectone(devpath)) |
||||
++found; |
||||
} |
||||
closedir(D); |
||||
|
||||
return found; |
||||
#else |
||||
return 0; |
||||
#endif |
||||
} |
||||
|
||||
int _serial_detect(struct device_drv *drv, detectone_func_t detectone, autoscan_func_t autoscan, bool forceauto) |
||||
{ |
||||
struct string_elist *iter, *tmp; |
||||
const char *dev, *colon; |
||||
bool inhibitauto = false; |
||||
char found = 0; |
||||
size_t namel = strlen(drv->name); |
||||
size_t dnamel = strlen(drv->dname); |
||||
|
||||
list_for_each_entry_safe(iter, tmp, &scan_devices, list) { |
||||
dev = iter->string; |
||||
if ((colon = strchr(dev, ':')) && colon[1] != '\0') { |
||||
size_t idlen = colon - dev; |
||||
|
||||
// allow either name:device or dname:device
|
||||
if ((idlen != namel || strncasecmp(dev, drv->name, idlen)) |
||||
&& (idlen != dnamel || strncasecmp(dev, drv->dname, idlen))) |
||||
continue; |
||||
|
||||
dev = colon + 1; |
||||
} |
||||
if (!strcmp(dev, "auto")) |
||||
forceauto = true; |
||||
else if (!strcmp(dev, "noauto")) |
||||
inhibitauto = true; |
||||
else if (detectone(dev)) { |
||||
string_elist_del(iter); |
||||
inhibitauto = true; |
||||
++found; |
||||
} |
||||
} |
||||
|
||||
if ((forceauto || !inhibitauto) && autoscan) |
||||
found += autoscan(); |
||||
|
||||
return found; |
||||
} |
||||
|
||||
// This code is purely for debugging but is very useful for that
|
||||
// It also took quite a bit of effort so I left it in
|
||||
// #define TERMIOS_DEBUG 1
|
||||
// Here to include it at compile time
|
||||
// It's off by default
|
||||
#ifndef WIN32 |
||||
#ifdef TERMIOS_DEBUG |
||||
|
||||
#define BITSSET "Y" |
||||
#define BITSNOTSET "N" |
||||
|
||||
int tiospeed(speed_t speed) |
||||
{ |
||||
switch (speed) { |
||||
case B0: |
||||
return 0; |
||||
case B50: |
||||
return 50; |
||||
case B75: |
||||
return 75; |
||||
case B110: |
||||
return 110; |
||||
case B134: |
||||
return 134; |
||||
case B150: |
||||
return 150; |
||||
case B200: |
||||
return 200; |
||||
case B300: |
||||
return 300; |
||||
case B600: |
||||
return 600; |
||||
case B1200: |
||||
return 1200; |
||||
case B1800: |
||||
return 1800; |
||||
case B2400: |
||||
return 2400; |
||||
case B4800: |
||||
return 4800; |
||||
case B9600: |
||||
return 9600; |
||||
case B19200: |
||||
return 19200; |
||||
case B38400: |
||||
return 38400; |
||||
case B57600: |
||||
return 57600; |
||||
case B115200: |
||||
return 115200; |
||||
case B230400: |
||||
return 230400; |
||||
case B460800: |
||||
return 460800; |
||||
case B500000: |
||||
return 500000; |
||||
case B576000: |
||||
return 576000; |
||||
case B921600: |
||||
return 921600; |
||||
case B1000000: |
||||
return 1000000; |
||||
case B1152000: |
||||
return 1152000; |
||||
case B1500000: |
||||
return 1500000; |
||||
case B2000000: |
||||
return 2000000; |
||||
case B2500000: |
||||
return 2500000; |
||||
case B3000000: |
||||
return 3000000; |
||||
case B3500000: |
||||
return 3500000; |
||||
case B4000000: |
||||
return 4000000; |
||||
default: |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
void termios_debug(const char *devpath, struct termios *my_termios, const char *msg) |
||||
{ |
||||
applog(LOG_DEBUG, "TIOS: Open %s attributes %s: ispeed=%d ospeed=%d", |
||||
devpath, msg, tiospeed(cfgetispeed(my_termios)), tiospeed(cfgetispeed(my_termios))); |
||||
|
||||
#define ISSETI(b) ((my_termios->c_iflag | (b)) ? BITSSET : BITSNOTSET) |
||||
|
||||
applog(LOG_DEBUG, "TIOS: c_iflag: IGNBRK=%s BRKINT=%s IGNPAR=%s PARMRK=%s INPCK=%s ISTRIP=%s INLCR=%s IGNCR=%s ICRNL=%s IUCLC=%s IXON=%s IXANY=%s IOFF=%s IMAXBEL=%s IUTF8=%s", |
||||
ISSETI(IGNBRK), ISSETI(BRKINT), ISSETI(IGNPAR), ISSETI(PARMRK), |
||||
ISSETI(INPCK), ISSETI(ISTRIP), ISSETI(INLCR), ISSETI(IGNCR), |
||||
ISSETI(ICRNL), ISSETI(IUCLC), ISSETI(IXON), ISSETI(IXANY), |
||||
ISSETI(IXOFF), ISSETI(IMAXBEL), ISSETI(IUTF8)); |
||||
|
||||
#define ISSETO(b) ((my_termios->c_oflag | (b)) ? BITSSET : BITSNOTSET) |
||||
#define VALO(b) (my_termios->c_oflag | (b)) |
||||
|
||||
applog(LOG_DEBUG, "TIOS: c_oflag: OPOST=%s OLCUC=%s ONLCR=%s OCRNL=%s ONOCR=%s ONLRET=%s OFILL=%s OFDEL=%s NLDLY=%d CRDLY=%d TABDLY=%d BSDLY=%d VTDLY=%d FFDLY=%d", |
||||
ISSETO(OPOST), ISSETO(OLCUC), ISSETO(ONLCR), ISSETO(OCRNL), |
||||
ISSETO(ONOCR), ISSETO(ONLRET), ISSETO(OFILL), ISSETO(OFDEL), |
||||
VALO(NLDLY), VALO(CRDLY), VALO(TABDLY), VALO(BSDLY), |
||||
VALO(VTDLY), VALO(FFDLY)); |
||||
|
||||
#define ISSETC(b) ((my_termios->c_cflag | (b)) ? BITSSET : BITSNOTSET) |
||||
#define VALC(b) (my_termios->c_cflag | (b)) |
||||
|
||||
applog(LOG_DEBUG, "TIOS: c_cflag: CBAUDEX=%s CSIZE=%d CSTOPB=%s CREAD=%s PARENB=%s PARODD=%s HUPCL=%s CLOCAL=%s" |
||||
#ifdef LOBLK |
||||
" LOBLK=%s" |
||||
#endif |
||||
" CMSPAR=%s CRTSCTS=%s", |
||||
ISSETC(CBAUDEX), VALC(CSIZE), ISSETC(CSTOPB), ISSETC(CREAD), |
||||
ISSETC(PARENB), ISSETC(PARODD), ISSETC(HUPCL), ISSETC(CLOCAL), |
||||
#ifdef LOBLK |
||||
ISSETC(LOBLK), |
||||
#endif |
||||
ISSETC(CMSPAR), ISSETC(CRTSCTS)); |
||||
|
||||
#define ISSETL(b) ((my_termios->c_lflag | (b)) ? BITSSET : BITSNOTSET) |
||||
|
||||
applog(LOG_DEBUG, "TIOS: c_lflag: ISIG=%s ICANON=%s XCASE=%s ECHO=%s ECHOE=%s ECHOK=%s ECHONL=%s ECHOCTL=%s ECHOPRT=%s ECHOKE=%s" |
||||
#ifdef DEFECHO |
||||
" DEFECHO=%s" |
||||
#endif |
||||
" FLUSHO=%s NOFLSH=%s TOSTOP=%s PENDIN=%s IEXTEN=%s", |
||||
ISSETL(ISIG), ISSETL(ICANON), ISSETL(XCASE), ISSETL(ECHO), |
||||
ISSETL(ECHOE), ISSETL(ECHOK), ISSETL(ECHONL), ISSETL(ECHOCTL), |
||||
ISSETL(ECHOPRT), ISSETL(ECHOKE), |
||||
#ifdef DEFECHO |
||||
ISSETL(DEFECHO), |
||||
#endif |
||||
ISSETL(FLUSHO), ISSETL(NOFLSH), ISSETL(TOSTOP), ISSETL(PENDIN), |
||||
ISSETL(IEXTEN)); |
||||
|
||||
#define VALCC(b) (my_termios->c_cc[b]) |
||||
applog(LOG_DEBUG, "TIOS: c_cc: VINTR=0x%02x VQUIT=0x%02x VERASE=0x%02x VKILL=0x%02x VEOF=0x%02x VMIN=%u VEOL=0x%02x VTIME=%u VEOL2=0x%02x" |
||||
#ifdef VSWTCH |
||||
" VSWTCH=0x%02x" |
||||
#endif |
||||
" VSTART=0x%02x VSTOP=0x%02x VSUSP=0x%02x" |
||||
#ifdef VDSUSP |
||||
" VDSUSP=0x%02x" |
||||
#endif |
||||
" VLNEXT=0x%02x VWERASE=0x%02x VREPRINT=0x%02x VDISCARD=0x%02x" |
||||
#ifdef VSTATUS |
||||
" VSTATUS=0x%02x" |
||||
#endif |
||||
, |
||||
VALCC(VINTR), VALCC(VQUIT), VALCC(VERASE), VALCC(VKILL), |
||||
VALCC(VEOF), VALCC(VMIN), VALCC(VEOL), VALCC(VTIME), |
||||
VALCC(VEOL2), |
||||
#ifdef VSWTCH |
||||
VALCC(VSWTCH), |
||||
#endif |
||||
VALCC(VSTART), VALCC(VSTOP), VALCC(VSUSP), |
||||
#ifdef VDSUSP |
||||
VALCC(VDSUSP), |
||||
#endif |
||||
VALCC(VLNEXT), VALCC(VWERASE), |
||||
VALCC(VREPRINT), VALCC(VDISCARD) |
||||
#ifdef VSTATUS |
||||
,VALCC(VSTATUS) |
||||
#endif |
||||
); |
||||
} |
||||
#endif |
||||
#endif |
||||
|
||||
int serial_open(const char *devpath, unsigned long baud, signed short timeout, bool purge) |
||||
{ |
||||
#ifdef WIN32 |
||||
HANDLE hSerial = CreateFile(devpath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); |
||||
if (unlikely(hSerial == INVALID_HANDLE_VALUE)) |
||||
{ |
||||
DWORD e = GetLastError(); |
||||
switch (e) { |
||||
case ERROR_ACCESS_DENIED: |
||||
applog(LOG_ERR, "Do not have user privileges required to open %s", devpath); |
||||
break; |
||||
case ERROR_SHARING_VIOLATION: |
||||
applog(LOG_ERR, "%s is already in use by another process", devpath); |
||||
break; |
||||
default: |
||||
applog(LOG_DEBUG, "Open %s failed, GetLastError:%d", devpath, (int)e); |
||||
break; |
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
// thanks to af_newbie for pointers about this
|
||||
COMMCONFIG comCfg = {0}; |
||||
comCfg.dwSize = sizeof(COMMCONFIG); |
||||
comCfg.wVersion = 1; |
||||
comCfg.dcb.DCBlength = sizeof(DCB); |
||||
comCfg.dcb.BaudRate = baud; |
||||
comCfg.dcb.fBinary = 1; |
||||
comCfg.dcb.fDtrControl = DTR_CONTROL_ENABLE; |
||||
comCfg.dcb.fRtsControl = RTS_CONTROL_ENABLE; |
||||
comCfg.dcb.ByteSize = 8; |
||||
|
||||
SetCommConfig(hSerial, &comCfg, sizeof(comCfg)); |
||||
|
||||
// Code must specify a valid timeout value (0 means don't timeout)
|
||||
const DWORD ctoms = (timeout * 100); |
||||
COMMTIMEOUTS cto = {ctoms, 0, ctoms, 0, ctoms}; |
||||
SetCommTimeouts(hSerial, &cto); |
||||
|
||||
if (purge) { |
||||
PurgeComm(hSerial, PURGE_RXABORT); |
||||
PurgeComm(hSerial, PURGE_TXABORT); |
||||
PurgeComm(hSerial, PURGE_RXCLEAR); |
||||
PurgeComm(hSerial, PURGE_TXCLEAR); |
||||
} |
||||
|
||||
return _open_osfhandle((intptr_t)hSerial, 0); |
||||
#else |
||||
int fdDev = open(devpath, O_RDWR | O_CLOEXEC | O_NOCTTY); |
||||
|
||||
if (unlikely(fdDev == -1)) |
||||
{ |
||||
if (errno == EACCES) |
||||
applog(LOG_ERR, "Do not have user privileges required to open %s", devpath); |
||||
else |
||||
applog(LOG_DEBUG, "Open %s failed, errno:%d", devpath, errno); |
||||
|
||||
return -1; |
||||
} |
||||
|
||||
struct termios my_termios; |
||||
|
||||
tcgetattr(fdDev, &my_termios); |
||||
|
||||
#ifdef TERMIOS_DEBUG |
||||
termios_debug(devpath, &my_termios, "before"); |
||||
#endif |
||||
|
||||
switch (baud) { |
||||
case 0: |
||||
break; |
||||
case 19200: |
||||
cfsetispeed(&my_termios, B19200); |
||||
cfsetospeed(&my_termios, B19200); |
||||
break; |
||||
case 38400: |
||||
cfsetispeed(&my_termios, B38400); |
||||
cfsetospeed(&my_termios, B38400); |
||||
break; |
||||
case 57600: |
||||
cfsetispeed(&my_termios, B57600); |
||||
cfsetospeed(&my_termios, B57600); |
||||
break; |
||||
case 115200: |
||||
cfsetispeed(&my_termios, B115200); |
||||
cfsetospeed(&my_termios, B115200); |
||||
break; |
||||
// TODO: try some higher speeds with the Icarus and BFL to see
|
||||
// if they support them and if setting them makes any difference
|
||||
// N.B. B3000000 doesn't work on Icarus
|
||||
default: |
||||
applog(LOG_WARNING, "Unrecognized baud rate: %lu", baud); |
||||
} |
||||
|
||||
my_termios.c_cflag &= ~(CSIZE | PARENB); |
||||
my_termios.c_cflag |= CS8; |
||||
my_termios.c_cflag |= CREAD; |
||||
my_termios.c_cflag |= CLOCAL; |
||||
|
||||
my_termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | |
||||
ISTRIP | INLCR | IGNCR | ICRNL | IXON); |
||||
my_termios.c_oflag &= ~OPOST; |
||||
my_termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); |
||||
|
||||
// Code must specify a valid timeout value (0 means don't timeout)
|
||||
my_termios.c_cc[VTIME] = (cc_t)timeout; |
||||
my_termios.c_cc[VMIN] = 0; |
||||
|
||||
#ifdef TERMIOS_DEBUG |
||||
termios_debug(devpath, &my_termios, "settings"); |
||||
#endif |
||||
|
||||
tcsetattr(fdDev, TCSANOW, &my_termios); |
||||
|
||||
#ifdef TERMIOS_DEBUG |
||||
tcgetattr(fdDev, &my_termios); |
||||
termios_debug(devpath, &my_termios, "after"); |
||||
#endif |
||||
|
||||
if (purge) |
||||
tcflush(fdDev, TCIOFLUSH); |
||||
return fdDev; |
||||
#endif |
||||
} |
||||
|
||||
ssize_t _serial_read(int fd, char *buf, size_t bufsiz, char *eol) |
||||
{ |
||||
ssize_t len, tlen = 0; |
||||
while (bufsiz) { |
||||
len = read(fd, buf, eol ? 1 : bufsiz); |
||||
if (unlikely(len == -1)) |
||||
break; |
||||
tlen += len; |
||||
if (eol && *eol == buf[0]) |
||||
break; |
||||
buf += len; |
||||
bufsiz -= len; |
||||
} |
||||
return tlen; |
||||
} |
||||
|
||||
static FILE *_open_bitstream(const char *path, const char *subdir, const char *filename) |
||||
{ |
||||
char fullpath[PATH_MAX]; |
||||
strcpy(fullpath, path); |
||||
strcat(fullpath, "/"); |
||||
if (subdir) { |
||||
strcat(fullpath, subdir); |
||||
strcat(fullpath, "/"); |
||||
} |
||||
strcat(fullpath, filename); |
||||
return fopen(fullpath, "rb"); |
||||
} |
||||
#define _open_bitstream(path, subdir) do { \ |
||||
f = _open_bitstream(path, subdir, filename); \ |
||||
if (f) \ |
||||
return f; \ |
||||
} while(0) |
||||
|
||||
#define _open_bitstream3(path) do { \ |
||||
_open_bitstream(path, dname); \ |
||||
_open_bitstream(path, "bitstreams"); \ |
||||
_open_bitstream(path, NULL); \ |
||||
} while(0) |
||||
|
||||
FILE *open_bitstream(const char *dname, const char *filename) |
||||
{ |
||||
FILE *f; |
||||
|
||||
_open_bitstream3(opt_kernel_path); |
||||
_open_bitstream3(cgminer_path); |
||||
_open_bitstream3("."); |
||||
|
||||
return NULL; |
||||
} |
||||
|
||||
#ifndef WIN32 |
||||
|
||||
static bool _select_wait_read(int fd, struct timeval *timeout) |
||||
{ |
||||
fd_set rfds; |
||||
|
||||
FD_ZERO(&rfds); |
||||
FD_SET(fd, &rfds); |
||||
|
||||
if (select(fd+1, &rfds, NULL, NULL, timeout) > 0) |
||||
return true; |
||||
else |
||||
return false; |
||||
} |
||||
|
||||
// Default timeout 100ms - only for device initialisation
|
||||
const struct timeval tv_timeout_default = { 0, 100000 }; |
||||
// Default inter character timeout = 1ms - only for device initialisation
|
||||
const struct timeval tv_inter_char_default = { 0, 1000 }; |
||||
|
||||
// Device initialisation function - NOT for work processing
|
||||
size_t _select_read(int fd, char *buf, size_t bufsiz, struct timeval *timeout, struct timeval *char_timeout, int finished) |
||||
{ |
||||
struct timeval tv_time, tv_char; |
||||
ssize_t siz, red = 0; |
||||
char got; |
||||
|
||||
// timeout is the maximum time to wait for the first character
|
||||
tv_time.tv_sec = timeout->tv_sec; |
||||
tv_time.tv_usec = timeout->tv_usec; |
||||
|
||||
if (!_select_wait_read(fd, &tv_time)) |
||||
return 0; |
||||
|
||||
while (4242) { |
||||
if ((siz = read(fd, buf, 1)) < 0) |
||||
return red; |
||||
|
||||
got = *buf; |
||||
buf += siz; |
||||
red += siz; |
||||
bufsiz -= siz; |
||||
|
||||
if (bufsiz < 1 || (finished >= 0 && got == finished)) |
||||
return red; |
||||
|
||||
// char_timeout is the maximum time to wait for each subsequent character
|
||||
// this is OK for initialisation, but bad for work processing
|
||||
// work processing MUST have a fixed size so this doesn't come into play
|
||||
tv_char.tv_sec = char_timeout->tv_sec; |
||||
tv_char.tv_usec = char_timeout->tv_usec; |
||||
|
||||
if (!_select_wait_read(fd, &tv_char)) |
||||
return red; |
||||
} |
||||
|
||||
return red; |
||||
} |
||||
|
||||
// Device initialisation function - NOT for work processing
|
||||
size_t _select_write(int fd, char *buf, size_t siz, struct timeval *timeout) |
||||
{ |
||||
struct timeval tv_time, tv_now, tv_finish; |
||||
fd_set rfds; |
||||
ssize_t wrote = 0, ret; |
||||
|
||||
cgtime(&tv_now); |
||||
timeradd(&tv_now, timeout, &tv_finish); |
||||
|
||||
// timeout is the maximum time to spend trying to write
|
||||
tv_time.tv_sec = timeout->tv_sec; |
||||
tv_time.tv_usec = timeout->tv_usec; |
||||
|
||||
FD_ZERO(&rfds); |
||||
FD_SET(fd, &rfds); |
||||
|
||||
while (siz > 0 && (tv_now.tv_sec < tv_finish.tv_sec || (tv_now.tv_sec == tv_finish.tv_sec && tv_now.tv_usec < tv_finish.tv_usec)) && select(fd+1, NULL, &rfds, NULL, &tv_time) > 0) { |
||||
if ((ret = write(fd, buf, 1)) > 0) { |
||||
buf++; |
||||
wrote++; |
||||
siz--; |
||||
} |
||||
else if (ret < 0) |
||||
return wrote; |
||||
|
||||
cgtime(&tv_now); |
||||
} |
||||
|
||||
return wrote; |
||||
} |
||||
|
||||
int get_serial_cts(int fd) |
||||
{ |
||||
int flags; |
||||
|
||||
if (!fd) |
||||
return -1; |
||||
|
||||
ioctl(fd, TIOCMGET, &flags); |
||||
return (flags & TIOCM_CTS) ? 1 : 0; |
||||
} |
||||
#else |
||||
int get_serial_cts(const int fd) |
||||
{ |
||||
if (!fd) |
||||
return -1; |
||||
const HANDLE fh = (HANDLE)_get_osfhandle(fd); |
||||
if (!fh) |
||||
return -1; |
||||
|
||||
DWORD flags; |
||||
if (!GetCommModemStatus(fh, &flags)) |
||||
return -1; |
||||
|
||||
return (flags & MS_CTS_ON) ? 1 : 0; |
||||
} |
||||
#endif // ! WIN32
|
@ -1,84 +0,0 @@
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 Luke Dashjr |
||||
* |
||||
* 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 FPGAUTILS_H |
||||
#define FPGAUTILS_H |
||||
|
||||
#include <stdbool.h> |
||||
#include <stdio.h> |
||||
|
||||
typedef bool(*detectone_func_t)(const char*); |
||||
typedef int(*autoscan_func_t)(); |
||||
|
||||
extern int _serial_detect(struct device_drv *drv, detectone_func_t, autoscan_func_t, bool force_autoscan); |
||||
#define serial_detect_fauto(drv, detectone, autoscan) \ |
||||
_serial_detect(drv, detectone, autoscan, true) |
||||
#define serial_detect_auto(drv, detectone, autoscan) \ |
||||
_serial_detect(drv, detectone, autoscan, false) |
||||
#define serial_detect(drv, detectone) \ |
||||
_serial_detect(drv, detectone, NULL, false) |
||||
extern int serial_autodetect_devserial(detectone_func_t, const char *prodname); |
||||
extern int serial_autodetect_udev(detectone_func_t, const char *prodname); |
||||
|
||||
extern int serial_open(const char *devpath, unsigned long baud, signed short timeout, bool purge); |
||||
extern ssize_t _serial_read(int fd, char *buf, size_t buflen, char *eol); |
||||
#define serial_read(fd, buf, count) \ |
||||
_serial_read(fd, (char*)(buf), count, NULL) |
||||
#define serial_read_line(fd, buf, bufsiz, eol) \ |
||||
_serial_read(fd, buf, bufsiz, &eol) |
||||
#define serial_close(fd) close(fd) |
||||
|
||||
extern FILE *open_bitstream(const char *dname, const char *filename); |
||||
|
||||
extern int get_serial_cts(int fd); |
||||
|
||||
#ifndef WIN32 |
||||
extern const struct timeval tv_timeout_default; |
||||
extern const struct timeval tv_inter_char_default; |
||||
|
||||
extern size_t _select_read(int fd, char *buf, size_t bufsiz, struct timeval *timeout, struct timeval *char_timeout, int finished); |
||||
extern size_t _select_write(int fd, char *buf, size_t siz, struct timeval *timeout); |
||||
|
||||
#define select_open(devpath) \ |
||||
serial_open(devpath, 0, 0, false) |
||||
|
||||
#define select_open_purge(devpath, purge)\ |
||||
serial_open(devpath, 0, 0, purge) |
||||
|
||||
#define select_write(fd, buf, siz) \ |
||||
_select_write(fd, buf, siz, (struct timeval *)(&tv_timeout_default)) |
||||
|
||||
#define select_write_full _select_write |
||||
|
||||
#define select_read(fd, buf, bufsiz) \ |
||||
_select_read(fd, buf, bufsiz, (struct timeval *)(&tv_timeout_default), \ |
||||
(struct timeval *)(&tv_inter_char_default), -1) |
||||
|
||||
#define select_read_til(fd, buf, bufsiz, eol) \ |
||||
_select_read(fd, buf, bufsiz, (struct timeval *)(&tv_timeout_default), \ |
||||
(struct timeval *)(&tv_inter_char_default), eol) |
||||
|
||||
#define select_read_wait(fd, buf, bufsiz, timeout) \ |
||||
_select_read(fd, buf, bufsiz, timeout, \ |
||||
(struct timeval *)(&tv_inter_char_default), -1) |
||||
|
||||
#define select_read_wait_til(fd, buf, bufsiz, timeout, eol) \ |
||||
_select_read(fd, buf, bufsiz, timeout, \ |
||||
(struct timeval *)(&tv_inter_char_default), eol) |
||||
|
||||
#define select_read_wait_both(fd, buf, bufsiz, timeout, char_timeout) \ |
||||
_select_read(fd, buf, bufsiz, timeout, char_timeout, -1) |
||||
|
||||
#define select_read_full _select_read |
||||
|
||||
#define select_close(fd) close(fd) |
||||
|
||||
#endif // ! WIN32
|
||||
|
||||
#endif |
@ -1,305 +0,0 @@
@@ -1,305 +0,0 @@
|
||||
How to setup a cgminer using xubuntu 11.04 live on a USB |
||||
|
||||
The master version of this document is here: |
||||
https://github.com/kanoi/linux-usb-cgminer |
||||
|
||||
The actual file is: |
||||
https://github.com/kanoi/linux-usb-cgminer/blob/master/linux-usb-cgminer |
||||
|
||||
The copy in cgminer (check to make sure it isn't older) is: |
||||
https://github.com/ckolivas/cgminer/blob/master/linux-usb-cgminer |
||||
|
||||
The original old verion on bitcointalk is: |
||||
https://bitcointalk.org/index.php?topic=28402.msg426741#msg426741 |
||||
|
||||
======== |
||||
|
||||
I have said to select English for the install process for 2 reasons: |
||||
1) I don't know any other spoken language very well |
||||
and |
||||
2) I'm not sure what problems installing under a different language |
||||
might cause (it will probably cause no problems but I don't know) |
||||
|
||||
Software |
||||
======== |
||||
Short hardware comment: |
||||
Your mining computer doesn't need any HDD or CD/DVD/BD as long as it has at |
||||
least 2GB of RAM, can boot USB, has some network connection to the internet |
||||
and of course a reasonable mining ATI graphics card |
||||
... Or you can boot a windows PC with the USB to only do mining ... and ignore |
||||
the system HDD ... wasting energy running the HDD (roughly 10 Watts per HDD) :) |
||||
|
||||
If you wish to install to an HDD instead of a USB, |
||||
see the changes to the instructions at the end |
||||
|
||||
To create the USB, you need of course a 4GB USB and temporarily need a PC |
||||
with a CD (or DVD/BD) writer, a USB port and of course an internet |
||||
connection to the PC |
||||
|
||||
1) Download the xubuntu 11.04 desktop live CD iso for amd64 |
||||
( look here for mirrors: http://www.xubuntu.org/getubuntu ) |
||||
|
||||
2) Burn it to CD then boot that temporarily on any PC with a CD/DVD/BD and |
||||
a USB port (this and the next 2 step won't effect that PC) |
||||
Select "English" then select "Try Xubuntu without installing" |
||||
and wait for the desktop to appear |
||||
(this happens by default if you wait for the timeouts) |
||||
|
||||
3) Plug in your 4GB USB device and it should appear on the desktop - you can |
||||
leave it's contents as long as there is at least 2.8GB free |
||||
|
||||
4) Now run "Startup Disk Creator" in "Applications->System" |
||||
(the system menu is the little rat in the top left corner) |
||||
|
||||
(if you have no mouse you can get the menu with <ctr><esc> and navigate |
||||
the menu with the arrow keys and <return> key) |
||||
|
||||
From here select the boot CD as the "Source" and the USB as the "Disk to use" |
||||
lastly move the slider to 2GB for reserved extra space |
||||
|
||||
The 2GB should be enough for modifications |
||||
|
||||
Click: "Make Install Disk" |
||||
After about 10-15 minutes you have a base xubuntu 11.04 boot USB |
||||
(you can shut down this computer now) |
||||
|
||||
5) Boot your cgminer PC with this USB stick, select "English" |
||||
then select "Try Xubuntu without installing" and wait for the desktop to |
||||
appear (this happens by default if you wait for the timeouts) |
||||
|
||||
6) Start a terminal |
||||
"Applications->Accessories->Terminal Emulator" |
||||
|
||||
7) sudo apt-get install openssh-server screen |
||||
|
||||
if you have a problem here then it's probably coz the internet isn't |
||||
available ... sort that out by reading elsewhere about routers etc |
||||
|
||||
8) sudo apt-get install fglrx fglrx-amdcccle fglrx-dev |
||||
sudo sync |
||||
sudo shutdown -r now |
||||
|
||||
N.B. always do a "sudo sync" and wait for it to finish every time before |
||||
shutting down the PC to ensure all data is written to the USB |
||||
|
||||
9) sudo aticonfig --lsa |
||||
this lists your ATI cards so you can see them |
||||
sudo aticonfig --adapter=all --odgt |
||||
this checks it can access all the cards ... |
||||
|
||||
10) sudo aticonfig --adapter=all --initial |
||||
this gets an error - no idea why but the xorg.conf is OK |
||||
sudo sync |
||||
sudo shutdown -r now |
||||
|
||||
11) sudo aticonfig --adapter=all --odgt |
||||
this checks it can access all the cards ... |
||||
|
||||
12) get AMD-APP-SDK-v2.4-lnx64.tgz from |
||||
http://developer.amd.com/sdks/amdappsdk/downloads/pages/default.aspx |
||||
( http://developer.amd.com/Downloads/AMD-APP-SDK-v2.4-lnx64.tgz ) |
||||
|
||||
sudo su |
||||
cd /opt |
||||
(replace /home/ubuntu/ with wherever you put the file: ) |
||||
tar -xvzf /home/ubuntu/AMD-APP-SDK-v2.4-lnx64.tgz |
||||
|
||||
cd AMD-APP-SDK-v2.4-lnx64/ |
||||
cp -pv lib/x86_64/* /usr/lib/ |
||||
rsync -avl include/CL/ /usr/include/CL/ |
||||
tar -xvzf icd-registration.tgz |
||||
rsync -avl etc/OpenCL/ /etc/OpenCL/ |
||||
ldconfig |
||||
sync |
||||
shutdown -r now |
||||
|
||||
You now have an OpenCL enabled xubuntu |
||||
|
||||
13) cgminer: |
||||
sudo apt-get install curl |
||||
|
||||
get the binary linux cgminer |
||||
(see the bitcoin forum cgminer thread for where to get it) |
||||
https://bitcointalk.org/index.php?topic=28402.0 |
||||
|
||||
./cgminer -n |
||||
this shows you the GPU's it found on your PC |
||||
See further below if you get an error regarding libtinfo.so.5 |
||||
|
||||
14) An OC option: |
||||
This is no longer needed since cgminer 2.* includes OC, however: |
||||
|
||||
sudo apt-get install libwxbase2.8-0 libwxgtk2.8-0 |
||||
|
||||
http://sourceforge.net/projects/amdovdrvctrl/ |
||||
for an Over/underclocking application and get the file listed below then: |
||||
sudo dpkg -i amdoverdrivectrl_1.2.1_amd64.deb |
||||
|
||||
15) set the screen saver to ONLY blank ... |
||||
|
||||
Move the mouse to the bottom of the screen and you see a set of icons like |
||||
on an Apple PC |
||||
Click on Settings, then in the Settings window "Screensaver" |
||||
Set "Mode:" to "Blank Screen Only" |
||||
|
||||
16) apt-get install ntpd |
||||
An accurate clock is always a good idea :) |
||||
|
||||
17) if you wish to ssh into the box you must set a password |
||||
to do this you simply have to be logged into it at the screen and type |
||||
|
||||
sudo passwd ubuntu |
||||
|
||||
it will prompt you (twice) to enter a password for the ubuntu account |
||||
|
||||
|
||||
Initial setup complete. |
||||
|
||||
======== |
||||
|
||||
If you want to SSH into the machine and run cgminer: |
||||
From a terminal on the miner display each time after you boot: |
||||
xhost + |
||||
|
||||
'xhost +' isn't needed if you ssh into the machine with the same |
||||
username that the GUI boots into (which is 'ubuntu' in this case) |
||||
|
||||
Then after you ssh into the machine: |
||||
export DISPLAY=:0 |
||||
before running cgminer |
||||
|
||||
Also note, that you should force the screen to blank when mining if |
||||
the ATI card is displaying the screen (using the screen saver |
||||
application menu) |
||||
In my case it takes away 50Mh/s when the screen isn't blanked |
||||
It will auto blank - but make sure the blank is of course just blank |
||||
as mentioned above at 15) |
||||
|
||||
|
||||
This is of course just the basics ... but it should get you a computer |
||||
up and running and able to run cgminer |
||||
|
||||
======== |
||||
|
||||
You should keep an eye on USB disk space |
||||
The system logger writes log files in the /var/log/ directory |
||||
The two main ones that grow large are 'kern.log' and 'syslog' |
||||
If you want to keep them, save them away to some other computer |
||||
When space is low, just delete them e.g. |
||||
|
||||
sudo rm -i /var/log/syslog |
||||
sudo rm -i /var/log/kern.log |
||||
|
||||
The 'df' command will show you the current space e.g.: |
||||
|
||||
sudo df |
||||
|
||||
Filesystem 1K-blocks Used Available Use% Mounted on |
||||
aufs 2099420 892024 1100748 45% / |
||||
none 1015720 628 1015092 1% /dev |
||||
/dev/sda1 3909348 2837248 1072100 73% /cdrom |
||||
/dev/loop0 670848 670848 0 100% /rofs |
||||
none 1023772 136 1023636 1% /dev/shm |
||||
tmpfs 1023772 16 1023756 1% /tmp |
||||
none 1023772 124 1023648 1% /var/run |
||||
none 1023772 0 1023772 0% /var/lock |
||||
|
||||
|
||||
This shows the 2GB space allocated when you setup the USB as '/' (aufs) |
||||
In this example, it's currently 45% full with almost 1.1GB of free space |
||||
|
||||
======== |
||||
|
||||
The latest version (2.0.8) of cgminer is built with 11.10 (not 11.04) |
||||
If you get the following error when running the prebuilt version in 11.04: |
||||
|
||||
./cgminer: error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory |
||||
|
||||
The fix is to simply link the old curses library to the new name e.g.: |
||||
|
||||
cd /lib64/ |
||||
sudo ln -s libncurses.so.5 libtinfo.so.5 |
||||
|
||||
======== |
||||
|
||||
If you wish to install to an HDD instead of a USB: |
||||
-------------------------------------------------- |
||||
|
||||
As per before: |
||||
|
||||
1) Download the xubuntu 11.04 desktop live CD iso for amd64 |
||||
( look here for mirrors: http://www.xubuntu.org/getubuntu ) |
||||
|
||||
Then: |
||||
|
||||
2) Burn it to CD then boot that on your new mining PC |
||||
Select "English" then select "Install Xubuntu" |
||||
(you have 30 seconds to do this) |
||||
|
||||
3) When the Install window comes up - again select "English" and click "Forward" |
||||
|
||||
4) The next page will show you if you meet certain install requirements |
||||
(make sure you do meet them all) |
||||
Don't select the download option |
||||
The 3rd party option isn't needed for mining so ignore that also |
||||
|
||||
Click "Forward" |
||||
|
||||
5) With "Allocate drive space" it's probably easiest to say to use the |
||||
"Erase" option. |
||||
|
||||
This is just for mining right? :) |
||||
|
||||
However, if you have anything on the HDD that you want to keep - the |
||||
"Erase" install process will delete it - so back it up (quit the install) |
||||
Also make sure there are no OTHER HDD attached that it may erase also |
||||
i.e. only have attached the one HDD that you want to install onto unless |
||||
you know exactly what you are doing |
||||
|
||||
If you see the "Install Xubuntu 11.04 alongside 'something'" then that |
||||
just means that the HDD wasn't blank. |
||||
If you want to try this option - do that yourself and then skip to step |
||||
7) below when you get to that. |
||||
|
||||
There are plenty of other options available if you select "Something else" |
||||
but I'm not going to go into all the details here other than to say that |
||||
my preferred partioning is: /boot = 1GB = ext2, swap = twice memory size, |
||||
/ = 100GB = ext3 and the rest: /extra = ext3 |
||||
|
||||
Click "Forward" |
||||
|
||||
6) If you selected "Erase" then it allows you to choose the drive to install to |
||||
Then click "Install Now" |
||||
|
||||
7) "Where are you?" sort that out then click "Forward" |
||||
|
||||
8) "Keyboard layout" sort that out (use the default) then click "Forward" |
||||
|
||||
9) "Who are you?" The important one here is "Pick a username:" coz that's |
||||
the name you will need to ssh into, to access it remotely (and of course |
||||
the "Choose a Password" you set) |
||||
|
||||
If you set the "username" to anything but "ubuntu" then: wherever in this |
||||
document I have mentioned the username "ubuntu" you must of course use the |
||||
username you chose here instead of "ubuntu" |
||||
|
||||
Important: set it to "log in automatically" if you ever want to be able |
||||
to start cgminer without being in front of the computer since 'X' must |
||||
be running to use cgminer properly |
||||
That does of course mean that the computer isn't secure from anyone who |
||||
has access to it - but then again no computer that can automatically |
||||
reboot is secure from anyone who has access to the actual computer itself |
||||
|
||||
Then click "Forward" |
||||
|
||||
10) Of course when it completes click on "Restart Now" |
||||
... and remove the Xubuntu CD when it asks you |
||||
|
||||
11) Wait for it to finish rebooting ... and it will auto login |
||||
(unless you didn't do step 9) "Important:") |
||||
|
||||
12) After it logs in, an upgrade popup for 11.10 (or later) will appear |
||||
Select "Don't Upgrade" |
||||
|
||||
13) Now go to step 6) of the USB script above for what to do next and that |
||||
covers everything else needed |
@ -1,417 +0,0 @@
@@ -1,417 +0,0 @@
|
||||
// This file is taken and modified from the public-domain poclbm project, and |
||||
// I have therefore decided to keep it public-domain. |
||||
// Modified version copyright 2011-2012 Con Kolivas |
||||
|
||||
#ifdef VECTORS4 |
||||
typedef uint4 u; |
||||
#elif defined VECTORS2 |
||||
typedef uint2 u; |
||||
#else |
||||
typedef uint u; |
||||
#endif |
||||
|
||||
__constant uint K[64] = { |
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, |
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, |
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, |
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, |
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, |
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, |
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, |
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 |
||||
}; |
||||
|
||||
__constant uint ConstW[128] = { |
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000U, 0x00000000, 0x00000000, 0x00000000, |
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000280U, |
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
||||
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
||||
0x80000000U, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000100U, |
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 |
||||
}; |
||||
|
||||
__constant uint H[8] = { |
||||
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 |
||||
}; |
||||
|
||||
|
||||
#ifdef BITALIGN |
||||
#pragma OPENCL EXTENSION cl_amd_media_ops : enable |
||||
#define rot(x, y) amd_bitalign(x, x, (uint)(32 - y)) |
||||
|
||||
// This part is not from the stock poclbm kernel. It's part of an optimization |
||||
// added in the Phoenix Miner. |
||||
|
||||
// Some AMD devices have Vals[0] BFI_INT opcode, which behaves exactly like the |
||||
// SHA-256 Ch function, but provides it in exactly one instruction. If |
||||
// detected, use it for Ch. Otherwise, construct Ch out of simpler logical |
||||
// primitives. |
||||
|
||||
#ifdef BFI_INT |
||||
// Well, slight problem... It turns out BFI_INT isn't actually exposed to |
||||
// OpenCL (or CAL IL for that matter) in any way. However, there is |
||||
// a similar instruction, BYTE_ALIGN_INT, which is exposed to OpenCL via |
||||
// amd_bytealign, takes the same inputs, and provides the same output. |
||||
// We can use that as a placeholder for BFI_INT and have the application |
||||
// patch it after compilation. |
||||
|
||||
// This is the BFI_INT function |
||||
#define Ch(x, y, z) amd_bytealign(x,y,z) |
||||
// Ma can also be implemented in terms of BFI_INT... |
||||
#define Ma(z, x, y) amd_bytealign(z^x,y,x) |
||||
#else // BFI_INT |
||||
// Later SDKs optimise this to BFI INT without patching and GCN |
||||
// actually fails if manually patched with BFI_INT |
||||
|
||||
#define Ch(x, y, z) bitselect((u)z, (u)y, (u)x) |
||||
#define Ma(x, y, z) bitselect((u)x, (u)y, (u)z ^ (u)x) |
||||
#define rotr(x, y) amd_bitalign((u)x, (u)x, (u)y) |
||||
#endif |
||||
#else // BITALIGN |
||||
#define Ch(x, y, z) (z ^ (x & (y ^ z))) |
||||
#define Ma(x, y, z) ((x & z) | (y & (x | z))) |
||||
#define rot(x, y) rotate((u)x, (u)y) |
||||
#define rotr(x, y) rotate((u)x, (u)(32-y)) |
||||
#endif |
||||
|
||||
|
||||
|
||||
//Various intermediate calculations for each SHA round |
||||
#define s0(n) (S0(Vals[(0 + 128 - (n)) % 8])) |
||||
#define S0(n) (rot(n, 30u)^rot(n, 19u)^rot(n,10u)) |
||||
|
||||
#define s1(n) (S1(Vals[(4 + 128 - (n)) % 8])) |
||||
#define S1(n) (rot(n, 26u)^rot(n, 21u)^rot(n, 7u)) |
||||
|
||||
#define ch(n) Ch(Vals[(4 + 128 - (n)) % 8],Vals[(5 + 128 - (n)) % 8],Vals[(6 + 128 - (n)) % 8]) |
||||
#define maj(n) Ma(Vals[(1 + 128 - (n)) % 8],Vals[(2 + 128 - (n)) % 8],Vals[(0 + 128 - (n)) % 8]) |
||||
|
||||
//t1 calc when W is already calculated |
||||
#define t1(n) K[(n) % 64] + Vals[(7 + 128 - (n)) % 8] + W[(n)] + s1(n) + ch(n) |
||||
|
||||
//t1 calc which calculates W |
||||
#define t1W(n) K[(n) % 64] + Vals[(7 + 128 - (n)) % 8] + W(n) + s1(n) + ch(n) |
||||
|
||||
//Used for constant W Values (the compiler optimizes out zeros) |
||||
#define t1C(n) (K[(n) % 64]+ ConstW[(n)]) + Vals[(7 + 128 - (n)) % 8] + s1(n) + ch(n) |
||||
|
||||
//t2 Calc |
||||
#define t2(n) maj(n) + s0(n) |
||||
|
||||
#define rotC(x,n) (x<<n | x >> (32-n)) |
||||
|
||||
//W calculation used for SHA round |
||||
#define W(n) (W[n] = P4(n) + P3(n) + P2(n) + P1(n)) |
||||
|
||||
|
||||
|
||||
//Partial W calculations (used for the begining where only some values are nonzero) |
||||
#define P1(n) ((rot(W[(n)-2],15u)^rot(W[(n)-2],13u)^((W[(n)-2])>>10U))) |
||||
#define P2(n) ((rot(W[(n)-15],25u)^rot(W[(n)-15],14u)^((W[(n)-15])>>3U))) |
||||
|
||||
|
||||
#define p1(x) ((rot(x,15u)^rot(x,13u)^((x)>>10U))) |
||||
#define p2(x) ((rot(x,25u)^rot(x,14u)^((x)>>3U))) |
||||
|
||||
|
||||
#define P3(n) W[n-7] |
||||
#define P4(n) W[n-16] |
||||
|
||||
|
||||
//Partial Calcs for constant W values |
||||
#define P1C(n) ((rotC(ConstW[(n)-2],15)^rotC(ConstW[(n)-2],13)^((ConstW[(n)-2])>>10U))) |
||||
#define P2C(n) ((rotC(ConstW[(n)-15],25)^rotC(ConstW[(n)-15],14)^((ConstW[(n)-15])>>3U))) |
||||
#define P3C(x) ConstW[x-7] |
||||
#define P4C(x) ConstW[x-16] |
||||
|
||||
//SHA round with built in W calc |
||||
#define sharoundW(n) Barrier1(n); Vals[(3 + 128 - (n)) % 8] += t1W(n); Vals[(7 + 128 - (n)) % 8] = t1W(n) + t2(n); |
||||
|
||||
//SHA round without W calc |
||||
#define sharound(n) Barrier2(n); Vals[(3 + 128 - (n)) % 8] += t1(n); Vals[(7 + 128 - (n)) % 8] = t1(n) + t2(n); |
||||
|
||||
//SHA round for constant W values |
||||
#define sharoundC(n) Barrier3(n); Vals[(3 + 128 - (n)) % 8] += t1C(n); Vals[(7 + 128 - (n)) % 8] = t1C(n) + t2(n); |
||||
|
||||
//The compiler is stupid... I put this in there only to stop the compiler from (de)optimizing the order |
||||
#define Barrier1(n) t1 = t1C((n+1)) |
||||
#define Barrier2(n) t1 = t1C((n)) |
||||
#define Barrier3(n) t1 = t1C((n)) |
||||
|
||||
//#define WORKSIZE 256 |
||||
#define MAXBUFFERS (4095) |
||||
|
||||
__kernel |
||||
__attribute__((reqd_work_group_size(WORKSIZE, 1, 1))) |
||||
void search( const uint state0, const uint state1, const uint state2, const uint state3, |
||||
const uint state4, const uint state5, const uint state6, const uint state7, |
||||
const uint B1, const uint C1, const uint D1, |
||||
const uint F1, const uint G1, const uint H1, |
||||
const u base, |
||||
const uint W16, const uint W17, |
||||
const uint PreVal4, const uint PreVal0, |
||||
const uint PreW18, const uint PreW19, |
||||
const uint PreW31, const uint PreW32, |
||||
|
||||
volatile __global uint * output) |
||||
{ |
||||
|
||||
|
||||
u W[124]; |
||||
u Vals[8]; |
||||
|
||||
//Dummy Variable to prevent compiler from reordering between rounds |
||||
u t1; |
||||
|
||||
//Vals[0]=state0; |
||||
Vals[1]=B1; |
||||
Vals[2]=C1; |
||||
Vals[3]=D1; |
||||
//Vals[4]=PreVal4; |
||||
Vals[5]=F1; |
||||
Vals[6]=G1; |
||||
Vals[7]=H1; |
||||
|
||||
W[16] = W16; |
||||
W[17] = W17; |
||||
|
||||
#ifdef VECTORS4 |
||||
//Less dependencies to get both the local id and group id and then add them |
||||
W[3] = base + (uint)(get_local_id(0)) * 4u + (uint)(get_group_id(0)) * (WORKSIZE * 4u); |
||||
uint r = rot(W[3].x,25u)^rot(W[3].x,14u)^((W[3].x)>>3U); |
||||
//Since only the 2 LSB is opposite between the nonces, we can save an instruction by flipping the 4 bits in W18 rather than the 1 bit in W3 |
||||
W[18] = PreW18 + (u){r, r ^ 0x2004000U, r ^ 0x4008000U, r ^ 0x600C000U}; |
||||
#elif defined VECTORS2 |
||||
W[3] = base + (uint)(get_local_id(0)) * 2u + (uint)(get_group_id(0)) * (WORKSIZE * 2u); |
||||
uint r = rot(W[3].x,25u)^rot(W[3].x,14u)^((W[3].x)>>3U); |
||||
W[18] = PreW18 + (u){r, r ^ 0x2004000U}; |
||||
#else |
||||
W[3] = base + get_local_id(0) + get_group_id(0) * (WORKSIZE); |
||||
u r = rot(W[3],25u)^rot(W[3],14u)^((W[3])>>3U); |
||||
W[18] = PreW18 + r; |
||||
#endif |
||||
//the order of the W calcs and Rounds is like this because the compiler needs help finding how to order the instructions |
||||
|
||||
|
||||
|
||||
Vals[4] = PreVal4 + W[3]; |
||||
Vals[0] = PreVal0 + W[3]; |
||||
|
||||
sharoundC(4); |
||||
W[19] = PreW19 + W[3]; |
||||
sharoundC(5); |
||||
W[20] = P4C(20) + P1(20); |
||||
sharoundC(6); |
||||
W[21] = P1(21); |
||||
sharoundC(7); |
||||
W[22] = P3C(22) + P1(22); |
||||
sharoundC(8); |
||||
W[23] = W[16] + P1(23); |
||||
sharoundC(9); |
||||
W[24] = W[17] + P1(24); |
||||
sharoundC(10); |
||||
W[25] = P1(25) + P3(25); |
||||
W[26] = P1(26) + P3(26); |
||||
sharoundC(11); |
||||
W[27] = P1(27) + P3(27); |
||||
W[28] = P1(28) + P3(28); |
||||
sharoundC(12); |
||||
W[29] = P1(29) + P3(29); |
||||
sharoundC(13); |
||||
W[30] = P1(30) + P2C(30) + P3(30); |
||||
W[31] = PreW31 + (P1(31) + P3(31)); |
||||
sharoundC(14); |
||||
W[32] = PreW32 + (P1(32) + P3(32)); |
||||
sharoundC(15); |
||||
sharound(16); |
||||
sharound(17); |
||||
sharound(18); |
||||
sharound(19); |
||||
sharound(20); |
||||
sharound(21); |
||||
sharound(22); |
||||
sharound(23); |
||||
sharound(24); |
||||
sharound(25); |
||||
sharound(26); |
||||
sharound(27); |
||||
sharound(28); |
||||
sharound(29); |
||||
sharound(30); |
||||
sharound(31); |
||||
sharound(32); |
||||
sharoundW(33); |
||||
sharoundW(34); |
||||
sharoundW(35); |
||||
sharoundW(36); |
||||
sharoundW(37); |
||||
sharoundW(38); |
||||
sharoundW(39); |
||||
sharoundW(40); |
||||
sharoundW(41); |
||||
sharoundW(42); |
||||
sharoundW(43); |
||||
sharoundW(44); |
||||
sharoundW(45); |
||||
sharoundW(46); |
||||
sharoundW(47); |
||||
sharoundW(48); |
||||
sharoundW(49); |
||||
sharoundW(50); |
||||
sharoundW(51); |
||||
sharoundW(52); |
||||
sharoundW(53); |
||||
sharoundW(54); |
||||
sharoundW(55); |
||||
sharoundW(56); |
||||
sharoundW(57); |
||||
sharoundW(58); |
||||
sharoundW(59); |
||||
sharoundW(60); |
||||
sharoundW(61); |
||||
sharoundW(62); |
||||
sharoundW(63); |
||||
|
||||
W[64]=state0+Vals[0]; |
||||
W[65]=state1+Vals[1]; |
||||
W[66]=state2+Vals[2]; |
||||
W[67]=state3+Vals[3]; |
||||
W[68]=state4+Vals[4]; |
||||
W[69]=state5+Vals[5]; |
||||
W[70]=state6+Vals[6]; |
||||
W[71]=state7+Vals[7]; |
||||
|
||||
Vals[0]=H[0]; |
||||
Vals[1]=H[1]; |
||||
Vals[2]=H[2]; |
||||
Vals[3]=H[3]; |
||||
Vals[4]=H[4]; |
||||
Vals[5]=H[5]; |
||||
Vals[6]=H[6]; |
||||
Vals[7]=H[7]; |
||||
|
||||
//sharound(64 + 0); |
||||
const u Temp = (0xb0edbdd0U + K[0]) + W[64]; |
||||
Vals[7] = Temp + 0x08909ae5U; |
||||
Vals[3] = 0xa54ff53aU + Temp; |
||||
|
||||
#define P124(n) P2(n) + P1(n) + P4(n) |
||||
|
||||
|
||||
W[64 + 16] = + P2(64 + 16) + P4(64 + 16); |
||||
sharound(64 + 1); |
||||
W[64 + 17] = P1C(64 + 17) + P2(64 + 17) + P4(64 + 17); |
||||
sharound(64 + 2); |
||||
W[64 + 18] = P124(64 + 18); |
||||
sharound(64 + 3); |
||||
W[64 + 19] = P124(64 + 19); |
||||
sharound(64 + 4); |
||||
W[64 + 20] = P124(64 + 20); |
||||
sharound(64 + 5); |
||||
W[64 + 21] = P124(64 + 21); |
||||
sharound(64 + 6); |
||||
W[64 + 22] = P4(64 + 22) + P3C(64 + 22) + P2(64 + 22) + P1(64 + 22); |
||||
sharound(64 + 7); |
||||
W[64 + 23] = P4(64 + 23) + P3(64 + 23) + P2C(64 + 23) + P1(64 + 23); |
||||
sharoundC(64 + 8); |
||||
W[64 + 24] = P1(64 + 24) + P4C(64 + 24) + P3(64 + 24); |
||||
sharoundC(64 + 9); |
||||
W[64 + 25] = P3(64 + 25) + P1(64 + 25); |
||||
sharoundC(64 + 10); |
||||
W[64 + 26] = P3(64 + 26) + P1(64 + 26); |
||||
sharoundC(64 + 11); |
||||
W[64 + 27] = P3(64 + 27) + P1(64 + 27); |
||||
sharoundC(64 + 12); |
||||
W[64 + 28] = P3(64 + 28) + P1(64 + 28); |
||||
sharoundC(64 + 13); |
||||
W[64 + 29] = P1(64 + 29) + P3(64 + 29); |
||||
W[64 + 30] = P3(64 + 30) + P2C(64 + 30) + P1(64 + 30); |
||||
sharoundC(64 + 14); |
||||
W[64 + 31] = P4C(64 + 31) + P3(64 + 31) + P2(64 + 31) + P1(64 + 31); |
||||
sharoundC(64 + 15); |
||||
sharound(64 + 16); |
||||
sharound(64 + 17); |
||||
sharound(64 + 18); |
||||
sharound(64 + 19); |
||||
sharound(64 + 20); |
||||
sharound(64 + 21); |
||||
sharound(64 + 22); |
||||
sharound(64 + 23); |
||||
sharound(64 + 24); |
||||
sharound(64 + 25); |
||||
sharound(64 + 26); |
||||
sharound(64 + 27); |
||||
sharound(64 + 28); |
||||
sharound(64 + 29); |
||||
sharound(64 + 30); |
||||
sharound(64 + 31); |
||||
sharoundW(64 + 32); |
||||
sharoundW(64 + 33); |
||||
sharoundW(64 + 34); |
||||
sharoundW(64 + 35); |
||||
sharoundW(64 + 36); |
||||
sharoundW(64 + 37); |
||||
sharoundW(64 + 38); |
||||
sharoundW(64 + 39); |
||||
sharoundW(64 + 40); |
||||
sharoundW(64 + 41); |
||||
sharoundW(64 + 42); |
||||
sharoundW(64 + 43); |
||||
sharoundW(64 + 44); |
||||
sharoundW(64 + 45); |
||||
sharoundW(64 + 46); |
||||
sharoundW(64 + 47); |
||||
sharoundW(64 + 48); |
||||
sharoundW(64 + 49); |
||||
sharoundW(64 + 50); |
||||
sharoundW(64 + 51); |
||||
sharoundW(64 + 52); |
||||
sharoundW(64 + 53); |
||||
sharoundW(64 + 54); |
||||
sharoundW(64 + 55); |
||||
sharoundW(64 + 56); |
||||
sharoundW(64 + 57); |
||||
sharoundW(64 + 58); |
||||
|
||||
W[117] += W[108] + Vals[3] + Vals[7] + P2(124) + P1(124) + Ch((Vals[0] + Vals[4]) + (K[59] + W(59+64)) + s1(64+59)+ ch(59+64),Vals[1],Vals[2]) - |
||||
(-(K[60] + H[7]) - S1((Vals[0] + Vals[4]) + (K[59] + W(59+64)) + s1(64+59)+ ch(59+64))); |
||||
|
||||
#define FOUND (0x0F) |
||||
#define SETFOUND(Xnonce) output[output[FOUND]++] = Xnonce |
||||
|
||||
#ifdef VECTORS4 |
||||
bool result = W[117].x & W[117].y & W[117].z & W[117].w; |
||||
if (!result) { |
||||
if (!W[117].x) |
||||
SETFOUND(W[3].x); |
||||
if (!W[117].y) |
||||
SETFOUND(W[3].y); |
||||
if (!W[117].z) |
||||
SETFOUND(W[3].z); |
||||
if (!W[117].w) |
||||
SETFOUND(W[3].w); |
||||
} |
||||
#elif defined VECTORS2 |
||||
bool result = W[117].x & W[117].y; |
||||
if (!result) { |
||||
if (!W[117].x) |
||||
SETFOUND(W[3].x); |
||||
if (!W[117].y) |
||||
SETFOUND(W[3].y); |
||||
} |
||||
#else |
||||
if (!W[117]) |
||||
SETFOUND(W[3]); |
||||
#endif |
||||
} |
@ -1,486 +0,0 @@
@@ -1,486 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2013 Andrew Smith |
||||
* Copyright 2013 Con Kolivas <kernel@kolivas.org> |
||||
* |
||||
* 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 USBUTILS_H |
||||
#define USBUTILS_H |
||||
|
||||
#include <libusb.h> |
||||
|
||||
#include "util.h" |
||||
|
||||
#define EPI(x) (LIBUSB_ENDPOINT_IN | (unsigned char)(x)) |
||||
#define EPO(x) (LIBUSB_ENDPOINT_OUT | (unsigned char)(x)) |
||||
|
||||
|
||||
// For 0x0403:0x6014/0x6001 FT232H (and possibly others?) - BFL, BAS, BLT, LLT, AVA
|
||||
#define FTDI_TYPE_OUT (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT) |
||||
#define FTDI_TYPE_IN (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN) |
||||
|
||||
#define FTDI_REQUEST_RESET ((uint8_t)0) |
||||
#define FTDI_REQUEST_MODEM ((uint8_t)1) |
||||
#define FTDI_REQUEST_FLOW ((uint8_t)2) |
||||
#define FTDI_REQUEST_BAUD ((uint8_t)3) |
||||
#define FTDI_REQUEST_DATA ((uint8_t)4) |
||||
#define FTDI_REQUEST_LATENCY ((uint8_t)9) |
||||
|
||||
#define FTDI_VALUE_RESET 0 |
||||
#define FTDI_VALUE_PURGE_RX 1 |
||||
#define FTDI_VALUE_PURGE_TX 2 |
||||
#define FTDI_VALUE_LATENCY 1 |
||||
|
||||
// Baud
|
||||
#define FTDI_VALUE_BAUD_BFL 0xc068 |
||||
#define FTDI_INDEX_BAUD_BFL 0x0200 |
||||
#define FTDI_VALUE_BAUD_BAS FTDI_VALUE_BAUD_BFL |
||||
#define FTDI_INDEX_BAUD_BAS FTDI_INDEX_BAUD_BFL |
||||
// LLT = BLT (same code)
|
||||
#define FTDI_VALUE_BAUD_BLT 0x001a |
||||
#define FTDI_INDEX_BAUD_BLT 0x0000 |
||||
|
||||
// Avalon
|
||||
#define FTDI_VALUE_BAUD_AVA 0x001A |
||||
#define FTDI_INDEX_BAUD_AVA 0x0000 |
||||
|
||||
#define FTDI_VALUE_DATA_AVA 8 |
||||
|
||||
// BitBurner
|
||||
#define BITBURNER_REQUEST ((uint8_t)0x42) |
||||
#define BITBURNER_VALUE 0x4242 |
||||
#define BITBURNER_INDEX_SET_VOLTAGE 1 |
||||
#define BITBURNER_INDEX_GET_VOLTAGE 2 |
||||
#define BITBURNER_INDEX_GET_VERSION 4 |
||||
|
||||
// CMR = 115200 & 57600
|
||||
#define FTDI_VALUE_BAUD_CMR_115 0xc068 |
||||
#define FTDI_INDEX_BAUD_CMR_115 0x0200 |
||||
|
||||
#define FTDI_VALUE_BAUD_CMR_57 0x80d0 |
||||
#define FTDI_INDEX_BAUD_CMR_57 0x0200 |
||||
|
||||
// Data control
|
||||
#define FTDI_VALUE_DATA_BFL 0 |
||||
#define FTDI_VALUE_DATA_BAS FTDI_VALUE_DATA_BFL |
||||
// LLT = BLT (same code)
|
||||
#define FTDI_VALUE_DATA_BLT 8 |
||||
|
||||
#define FTDI_VALUE_FLOW 0 |
||||
#define FTDI_VALUE_MODEM 0x0303 |
||||
|
||||
|
||||
// For 0x10c4:0xea60 USB cp210x chip - AMU
|
||||
#define CP210X_TYPE_OUT 0x41 |
||||
|
||||
#define CP210X_REQUEST_IFC_ENABLE 0x00 |
||||
#define CP210X_REQUEST_DATA 0x07 |
||||
#define CP210X_REQUEST_BAUD 0x1e |
||||
|
||||
#define CP210X_VALUE_UART_ENABLE 0x0001 |
||||
#define CP210X_VALUE_DATA 0x0303 |
||||
#define CP210X_DATA_BAUD 0x0001c200 |
||||
|
||||
|
||||
// For 0x067b:0x2303 Prolific PL2303 - ICA
|
||||
#define PL2303_CTRL_DTR 0x01 |
||||
#define PL2303_CTRL_RTS 0x02 |
||||
|
||||
#define PL2303_CTRL_OUT 0x21 |
||||
#define PL2303_VENDOR_OUT 0x40 |
||||
|
||||
#define PL2303_REQUEST_CTRL 0x22 |
||||
#define PL2303_REQUEST_LINE 0x20 |
||||
#define PL2303_REQUEST_VENDOR 0x01 |
||||
|
||||
#define PL2303_REPLY_CTRL 0x21 |
||||
|
||||
#define PL2303_VALUE_CTRL (PL2303_CTRL_DTR | PL2303_CTRL_RTS) |
||||
#define PL2303_VALUE_LINE 0 |
||||
#define PL2303_VALUE_LINE0 0x0001c200 |
||||
#define PL2303_VALUE_LINE1 0x080000 |
||||
#define PL2303_VALUE_LINE_SIZE 7 |
||||
#define PL2303_VALUE_VENDOR 0 |
||||
|
||||
// Use the device defined timeout
|
||||
#define DEVTIMEOUT 0 |
||||
|
||||
// The default intinfo structure used is the first one
|
||||
#define DEFAULT_INTINFO 0 |
||||
|
||||
// For endpoints defined in usb_find_devices.intinfos.epinfos,
|
||||
// the first two must be the default IN and OUT and both must always exist
|
||||
#define DEFAULT_EP_IN 0 |
||||
#define DEFAULT_EP_OUT 1 |
||||
|
||||
struct usb_epinfo { |
||||
uint8_t att; |
||||
uint16_t size; |
||||
unsigned char ep; |
||||
uint16_t wMaxPacketSize; |
||||
bool found; |
||||
}; |
||||
|
||||
struct usb_intinfo { |
||||
int interface; |
||||
int ctrl_transfer; |
||||
int epinfo_count; |
||||
struct usb_epinfo *epinfos; |
||||
}; |
||||
|
||||
enum sub_ident { |
||||
IDENT_UNK = 0, |
||||
IDENT_BAJ, |
||||
IDENT_BAL, |
||||
IDENT_BAS, |
||||
IDENT_BAM, |
||||
IDENT_BFL, |
||||
IDENT_BFU, |
||||
IDENT_MMQ, |
||||
IDENT_AVA, |
||||
IDENT_BTB, |
||||
IDENT_HFA, |
||||
IDENT_BBF, |
||||
IDENT_KLN, |
||||
IDENT_ICA, |
||||
IDENT_AMU, |
||||
IDENT_BLT, |
||||
IDENT_LLT, |
||||
IDENT_CMR1, |
||||
IDENT_CMR2, |
||||
IDENT_ZTX |
||||
}; |
||||
|
||||
struct usb_find_devices { |
||||
int drv; |
||||
const char *name; |
||||
enum sub_ident ident; |
||||
uint16_t idVendor; |
||||
uint16_t idProduct; |
||||
char *iManufacturer; |
||||
char *iProduct; |
||||
int config; |
||||
unsigned int timeout; |
||||
uint16_t latency; |
||||
int intinfo_count; |
||||
struct usb_intinfo *intinfos; |
||||
}; |
||||
|
||||
/* Latency is set to 32ms to prevent a transfer ever being more than 512 bytes
|
||||
* +2 bytes of status such as the ftdi chip, when the chips emulate a 115200 |
||||
* baud rate, to avoid status bytes being interleaved in larger transfers. */ |
||||
#define LATENCY_UNUSED 0 |
||||
#define LATENCY_STD 32 |
||||
|
||||
enum usb_types { |
||||
USB_TYPE_STD = 0, |
||||
USB_TYPE_FTDI |
||||
}; |
||||
|
||||
#define USB_MAX_READ 8192 |
||||
|
||||
struct cg_usb_device { |
||||
struct usb_find_devices *found; |
||||
libusb_device_handle *handle; |
||||
pthread_mutex_t *mutex; |
||||
struct libusb_device_descriptor *descriptor; |
||||
enum usb_types usb_type; |
||||
enum sub_ident ident; |
||||
uint16_t usbver; |
||||
int cps; |
||||
bool usecps; |
||||
char *prod_string; |
||||
char *manuf_string; |
||||
char *serial_string; |
||||
unsigned char fwVersion; // ??
|
||||
unsigned char interfaceVersion; // ??
|
||||
char buffer[USB_MAX_READ]; |
||||
uint32_t bufsiz; |
||||
uint32_t bufamt; |
||||
}; |
||||
|
||||
#define USB_NOSTAT 0 |
||||
|
||||
#define USB_TMO_0 50 |
||||
#define USB_TMO_1 100 |
||||
#define USB_TMO_2 500 |
||||
#define USB_TMOS 3 |
||||
|
||||
struct cg_usb_tmo { |
||||
uint32_t count; |
||||
uint32_t min_tmo; |
||||
uint32_t max_tmo; |
||||
uint64_t total_over; |
||||
uint64_t total_tmo; |
||||
}; |
||||
|
||||
struct cg_usb_info { |
||||
uint8_t bus_number; |
||||
uint8_t device_address; |
||||
int usbstat; |
||||
bool nodev; |
||||
int nodev_count; |
||||
struct timeval last_nodev; |
||||
uint32_t ioerr_count; |
||||
uint32_t continuous_ioerr_count; |
||||
|
||||
/*
|
||||
* for nodev and cgusb access (read and write) |
||||
* it's a pointer so MMQ can have it in multiple devices |
||||
* |
||||
* N.B. general mining code doesn't need to use the read |
||||
* lock for 'nodev' if it calls a usb_read/write/etc function |
||||
* that uses the lock - however, all usbutils code MUST use it |
||||
* to avoid devices disappearing while in use by multiple threads |
||||
*/ |
||||
cglock_t devlock; |
||||
|
||||
time_t last_pipe; |
||||
uint64_t pipe_count; |
||||
uint64_t clear_err_count; |
||||
uint64_t retry_err_count; |
||||
uint64_t clear_fail_count; |
||||
|
||||
uint64_t read_delay_count; |
||||
double total_read_delay; |
||||
uint64_t write_delay_count; |
||||
double total_write_delay; |
||||
|
||||
/*
|
||||
* We add 4: 1 for null, 2 for FTDI status and 1 to round to 4 bytes |
||||
* If a single device ever has multiple end points then it will need |
||||
* multiple of these |
||||
*/ |
||||
unsigned char bulkbuf[USB_MAX_READ+4]; |
||||
|
||||
uint64_t tmo_count; |
||||
struct cg_usb_tmo usb_tmo[USB_TMOS]; |
||||
}; |
||||
|
||||
#define ENUMERATION(a,b) a, |
||||
#define JUMPTABLE(a,b) b, |
||||
|
||||
#define USB_PARSE_COMMANDS(USB_ADD_COMMAND) \ |
||||
USB_ADD_COMMAND(C_REJECTED, "RejectedNoDevice") \ |
||||
USB_ADD_COMMAND(C_PING, "Ping") \ |
||||
USB_ADD_COMMAND(C_CLEAR, "Clear") \ |
||||
USB_ADD_COMMAND(C_REQUESTVERSION, "RequestVersion") \ |
||||
USB_ADD_COMMAND(C_GETVERSION, "GetVersion") \ |
||||
USB_ADD_COMMAND(C_REQUESTFPGACOUNT, "RequestFPGACount") \ |
||||
USB_ADD_COMMAND(C_GETFPGACOUNT, "GetFPGACount") \ |
||||
USB_ADD_COMMAND(C_STARTPROGRAM, "StartProgram") \ |
||||
USB_ADD_COMMAND(C_STARTPROGRAMSTATUS, "StartProgramStatus") \ |
||||
USB_ADD_COMMAND(C_PROGRAM, "Program") \ |
||||
USB_ADD_COMMAND(C_PROGRAMSTATUS, "ProgramStatus") \ |
||||
USB_ADD_COMMAND(C_PROGRAMSTATUS2, "ProgramStatus2") \ |
||||
USB_ADD_COMMAND(C_FINALPROGRAMSTATUS, "FinalProgramStatus") \ |
||||
USB_ADD_COMMAND(C_SETCLOCK, "SetClock") \ |
||||
USB_ADD_COMMAND(C_REPLYSETCLOCK, "ReplySetClock") \ |
||||
USB_ADD_COMMAND(C_REQUESTUSERCODE, "RequestUserCode") \ |
||||
USB_ADD_COMMAND(C_GETUSERCODE, "GetUserCode") \ |
||||
USB_ADD_COMMAND(C_REQUESTTEMPERATURE, "RequestTemperature") \ |
||||
USB_ADD_COMMAND(C_GETTEMPERATURE, "GetTemperature") \ |
||||
USB_ADD_COMMAND(C_SENDWORK, "SendWork") \ |
||||
USB_ADD_COMMAND(C_SENDWORKSTATUS, "SendWorkStatus") \ |
||||
USB_ADD_COMMAND(C_REQUESTWORKSTATUS, "RequestWorkStatus") \ |
||||
USB_ADD_COMMAND(C_GETWORKSTATUS, "GetWorkStatus") \ |
||||
USB_ADD_COMMAND(C_REQUESTIDENTIFY, "RequestIdentify") \ |
||||
USB_ADD_COMMAND(C_GETIDENTIFY, "GetIdentify") \ |
||||
USB_ADD_COMMAND(C_REQUESTFLASH, "RequestFlash") \ |
||||
USB_ADD_COMMAND(C_REQUESTSENDWORK, "RequestSendWork") \ |
||||
USB_ADD_COMMAND(C_REQUESTSENDWORKSTATUS, "RequestSendWorkStatus") \ |
||||
USB_ADD_COMMAND(C_RESET, "Reset") \ |
||||
USB_ADD_COMMAND(C_SETBAUD, "SetBaud") \ |
||||
USB_ADD_COMMAND(C_SETDATA, "SetDataCtrl") \ |
||||
USB_ADD_COMMAND(C_SETFLOW, "SetFlowCtrl") \ |
||||
USB_ADD_COMMAND(C_SETMODEM, "SetModemCtrl") \ |
||||
USB_ADD_COMMAND(C_PURGERX, "PurgeRx") \ |
||||
USB_ADD_COMMAND(C_PURGETX, "PurgeTx") \ |
||||
USB_ADD_COMMAND(C_FLASHREPLY, "FlashReply") \ |
||||
USB_ADD_COMMAND(C_REQUESTDETAILS, "RequestDetails") \ |
||||
USB_ADD_COMMAND(C_GETDETAILS, "GetDetails") \ |
||||
USB_ADD_COMMAND(C_REQUESTRESULTS, "RequestResults") \ |
||||
USB_ADD_COMMAND(C_GETRESULTS, "GetResults") \ |
||||
USB_ADD_COMMAND(C_REQUESTQUEJOB, "RequestQueJob") \ |
||||
USB_ADD_COMMAND(C_REQUESTQUEJOBSTATUS, "RequestQueJobStatus") \ |
||||
USB_ADD_COMMAND(C_QUEJOB, "QueJob") \ |
||||
USB_ADD_COMMAND(C_QUEJOBSTATUS, "QueJobStatus") \ |
||||
USB_ADD_COMMAND(C_QUEFLUSH, "QueFlush") \ |
||||
USB_ADD_COMMAND(C_QUEFLUSHREPLY, "QueFlushReply") \ |
||||
USB_ADD_COMMAND(C_REQUESTVOLTS, "RequestVolts") \ |
||||
USB_ADD_COMMAND(C_GETVOLTS, "GetVolts") \ |
||||
USB_ADD_COMMAND(C_SENDTESTWORK, "SendTestWork") \ |
||||
USB_ADD_COMMAND(C_LATENCY, "SetLatency") \ |
||||
USB_ADD_COMMAND(C_SETLINE, "SetLine") \ |
||||
USB_ADD_COMMAND(C_VENDOR, "Vendor") \ |
||||
USB_ADD_COMMAND(C_SETFAN, "SetFan") \ |
||||
USB_ADD_COMMAND(C_FANREPLY, "GetFan") \ |
||||
USB_ADD_COMMAND(C_AVALON_TASK, "AvalonTask") \ |
||||
USB_ADD_COMMAND(C_AVALON_READ, "AvalonRead") \ |
||||
USB_ADD_COMMAND(C_GET_AVALON_READY, "AvalonReady") \ |
||||
USB_ADD_COMMAND(C_AVALON_RESET, "AvalonReset") \ |
||||
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_BB_SET_VOLTAGE, "SetCoreVoltage") \ |
||||
USB_ADD_COMMAND(C_BB_GET_VOLTAGE, "GetCoreVoltage") \ |
||||
USB_ADD_COMMAND(C_ATMEL_RESET, "AtmelReset") \ |
||||
USB_ADD_COMMAND(C_ATMEL_OPEN, "AtmelOpen") \ |
||||
USB_ADD_COMMAND(C_ATMEL_INIT, "AtmelInit") \ |
||||
USB_ADD_COMMAND(C_ATMEL_CLOSE, "AtmelClose") \ |
||||
USB_ADD_COMMAND(C_BF1_REQINFO, "BF1RequestInfo") \ |
||||
USB_ADD_COMMAND(C_BF1_GETINFO, "BF1GetInfo") \ |
||||
USB_ADD_COMMAND(C_BF1_REQRESET, "BF1RequestReset") \ |
||||
USB_ADD_COMMAND(C_BF1_GETRESET, "BF1GetReset") \ |
||||
USB_ADD_COMMAND(C_BF1_REQWORK, "BF1RequestWork") \ |
||||
USB_ADD_COMMAND(C_BF1_GETWORK, "BF1GetWork") \ |
||||
USB_ADD_COMMAND(C_BF1_GETRES, "BF1GetResults") \ |
||||
USB_ADD_COMMAND(C_BF1_FLUSH, "BF1Flush") \ |
||||
USB_ADD_COMMAND(C_BF1_IFLUSH, "BF1InterruptFlush") \ |
||||
USB_ADD_COMMAND(C_BF1_IDENTIFY, "BF1Identify") \ |
||||
USB_ADD_COMMAND(C_HF_RESET, "HFReset") \ |
||||
USB_ADD_COMMAND(C_HF_PLL_CONFIG, "HFPLLConfig") \ |
||||
USB_ADD_COMMAND(C_HF_ADDRESS, "HFAddress") \ |
||||
USB_ADD_COMMAND(C_HF_BAUD, "HFBaud") \ |
||||
USB_ADD_COMMAND(C_HF_HASH, "HFHash") \ |
||||
USB_ADD_COMMAND(C_HF_NONCE, "HFNonce") \ |
||||
USB_ADD_COMMAND(C_HF_ABORT, "HFAbort") \ |
||||
USB_ADD_COMMAND(C_HF_STATUS, "HFStatus") \ |
||||
USB_ADD_COMMAND(C_HF_CONFIG, "HFConfig") \ |
||||
USB_ADD_COMMAND(C_HF_STATISTICS, "HFStatistics") \ |
||||
USB_ADD_COMMAND(C_HF_CLOCKGATE, "HFClockGate") \ |
||||
USB_ADD_COMMAND(C_HF_USB_INIT, "HFUSBInit") \ |
||||
USB_ADD_COMMAND(C_HF_DIE_STATUS, "HFDieStatus") \ |
||||
USB_ADD_COMMAND(C_HF_GWQ_STATUS, "HFGWQStatus") \ |
||||
USB_ADD_COMMAND(C_HF_WORK_RESTART, "HFWorkRestart") \ |
||||
USB_ADD_COMMAND(C_HF_GWQSTATS, "HFGWQStats") \ |
||||
USB_ADD_COMMAND(C_HF_GETHEADER, "HFGetHeader") \ |
||||
USB_ADD_COMMAND(C_HF_GETDATA, "HFGetData") \ |
||||
USB_ADD_COMMAND(C_HF_CLEAR_READ, "HFClearRead") |
||||
|
||||
/* Create usb_cmds enum from USB_PARSE_COMMANDS macro */ |
||||
enum usb_cmds { |
||||
USB_PARSE_COMMANDS(ENUMERATION) |
||||
C_MAX |
||||
}; |
||||
|
||||
struct device_drv; |
||||
struct cgpu_info; |
||||
|
||||
bool async_usb_transfers(void); |
||||
void cancel_usb_transfers(void); |
||||
void usb_all(int level); |
||||
const char *usb_cmdname(enum usb_cmds cmd); |
||||
void usb_applog(struct cgpu_info *cgpu, enum usb_cmds cmd, char *msg, int amount, int err); |
||||
void usb_nodev(struct cgpu_info *cgpu); |
||||
struct cgpu_info *usb_copy_cgpu(struct cgpu_info *orig); |
||||
struct cgpu_info *usb_alloc_cgpu(struct device_drv *drv, int threads); |
||||
struct cgpu_info *usb_free_cgpu(struct cgpu_info *cgpu); |
||||
void usb_uninit(struct cgpu_info *cgpu); |
||||
bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find_devices *found); |
||||
void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_device *, struct usb_find_devices *)); |
||||
struct api_data *api_usb_stats(int *count); |
||||
void update_usb_stats(struct cgpu_info *cgpu); |
||||
int _usb_read(struct cgpu_info *cgpu, int intinfo, int epinfo, char *buf, size_t bufsiz, int *processed, int timeout, const char *end, enum usb_cmds cmd, bool readonce, bool cancellable); |
||||
int _usb_write(struct cgpu_info *cgpu, int intinfo, int epinfo, char *buf, size_t bufsiz, int *processed, int timeout, enum usb_cmds); |
||||
int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint32_t *data, int siz, unsigned int timeout, enum usb_cmds cmd); |
||||
int _usb_transfer_read(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, char *buf, int bufsiz, int *amount, unsigned int timeout, enum usb_cmds cmd); |
||||
int usb_ftdi_cts(struct cgpu_info *cgpu); |
||||
int _usb_ftdi_set_latency(struct cgpu_info *cgpu, int intinfo); |
||||
#define usb_ftdi_set_latency(_cgpu) _usb_ftdi_set_latency(_cgpu, DEFAULT_INTINFO) |
||||
void usb_buffer_clear(struct cgpu_info *cgpu); |
||||
uint32_t usb_buffer_size(struct cgpu_info *cgpu); |
||||
void usb_set_cps(struct cgpu_info *cgpu, int cps); |
||||
void usb_enable_cps(struct cgpu_info *cgpu); |
||||
void usb_disable_cps(struct cgpu_info *cgpu); |
||||
int _usb_interface(struct cgpu_info *cgpu, int intinfo); |
||||
#define usb_interface(_cgpu) _usb_interface(_cgpu, DEFAULT_INTINFO) |
||||
enum sub_ident usb_ident(struct cgpu_info *cgpu); |
||||
void usb_set_dev_start(struct cgpu_info *cgpu); |
||||
void usb_cleanup(); |
||||
void usb_initialise(); |
||||
void *usb_resource_thread(void *userdata); |
||||
|
||||
#define usb_read(cgpu, buf, bufsiz, read, cmd) \ |
||||
_usb_read(cgpu, DEFAULT_INTINFO, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, NULL, cmd, false, false) |
||||
|
||||
#define usb_read_cancellable(cgpu, buf, bufsiz, read, cmd) \ |
||||
_usb_read(cgpu, DEFAULT_INTINFO, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, NULL, cmd, false, true) |
||||
|
||||
#define usb_read_ii(cgpu, intinfo, buf, bufsiz, read, cmd) \ |
||||
_usb_read(cgpu, intinfo, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, NULL, cmd, false, false) |
||||
|
||||
#define usb_read_once(cgpu, buf, bufsiz, read, cmd) \ |
||||
_usb_read(cgpu, DEFAULT_INTINFO, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, NULL, cmd, true, false) |
||||
|
||||
#define usb_read_ii_once(cgpu, intinfo, buf, bufsiz, read, cmd) \ |
||||
_usb_read(cgpu, intinfo, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, NULL, cmd, true, false) |
||||
|
||||
#define usb_read_once_timeout(cgpu, buf, bufsiz, read, timeout, cmd) \ |
||||
_usb_read(cgpu, DEFAULT_INTINFO, DEFAULT_EP_IN, buf, bufsiz, read, timeout, NULL, cmd, true, false) |
||||
|
||||
#define usb_read_once_timeout_cancellable(cgpu, buf, bufsiz, read, timeout, cmd) \ |
||||
_usb_read(cgpu, DEFAULT_INTINFO, DEFAULT_EP_IN, buf, bufsiz, read, timeout, NULL, cmd, true, true) |
||||
|
||||
#define usb_read_ii_once_timeout(cgpu, intinfo, buf, bufsiz, read, timeout, cmd) \ |
||||
_usb_read(cgpu, intinfo, DEFAULT_EP_IN, buf, bufsiz, read, timeout, NULL, cmd, true, false) |
||||
|
||||
#define usb_read_nl(cgpu, buf, bufsiz, read, cmd) \ |
||||
_usb_read(cgpu, DEFAULT_INTINFO, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, "\n", cmd, false, false) |
||||
|
||||
#define usb_read_nl_timeout(cgpu, buf, bufsiz, read, timeout, cmd) \ |
||||
_usb_read(cgpu, DEFAULT_INTINFO, DEFAULT_EP_IN, buf, bufsiz, read, timeout, "\n", cmd, false, false) |
||||
|
||||
#define usb_read_ok(cgpu, buf, bufsiz, read, cmd) \ |
||||
_usb_read(cgpu, DEFAULT_INTINFO, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, "OK\n", cmd, false, false) |
||||
|
||||
#define usb_read_ok_timeout(cgpu, buf, bufsiz, read, timeout, cmd) \ |
||||
_usb_read(cgpu, DEFAULT_INTINFO, DEFAULT_EP_IN, buf, bufsiz, read, timeout, "OK\n", cmd, false, false) |
||||
|
||||
#define usb_read_ep(cgpu, ep, buf, bufsiz, read, cmd) \ |
||||
_usb_read(cgpu, DEFAULT_INTINFO, ep, buf, bufsiz, read, DEVTIMEOUT, NULL, cmd, false, false) |
||||
|
||||
#define usb_read_timeout(cgpu, buf, bufsiz, read, timeout, cmd) \ |
||||
_usb_read(cgpu, DEFAULT_INTINFO, DEFAULT_EP_IN, buf, bufsiz, read, timeout, NULL, cmd, false, false) |
||||
|
||||
#define usb_read_timeout_cancellable(cgpu, buf, bufsiz, read, timeout, cmd) \ |
||||
_usb_read(cgpu, DEFAULT_INTINFO, DEFAULT_EP_IN, buf, bufsiz, read, timeout, NULL, cmd, false, true) |
||||
|
||||
#define usb_read_ii_timeout(cgpu, intinfo, buf, bufsiz, read, timeout, cmd) \ |
||||
_usb_read(cgpu, intinfo, DEFAULT_EP_IN, buf, bufsiz, read, timeout, NULL, cmd, false, false) |
||||
|
||||
#define usb_read_ii_timeout_cancellable(cgpu, intinfo, buf, bufsiz, read, timeout, cmd) \ |
||||
_usb_read(cgpu, intinfo, DEFAULT_EP_IN, buf, bufsiz, read, timeout, NULL, cmd, false, true) |
||||
|
||||
#define usb_read_ep_timeout(cgpu, ep, buf, bufsiz, read, timeout, cmd) \ |
||||
_usb_read(cgpu, DEFAULT_INTINFO, ep, buf, bufsiz, read, timeout, NULL, cmd, false, false) |
||||
|
||||
#define usb_write(cgpu, buf, bufsiz, wrote, cmd) \ |
||||
_usb_write(cgpu, DEFAULT_INTINFO, DEFAULT_EP_OUT, buf, bufsiz, wrote, DEVTIMEOUT, cmd) |
||||
|
||||
#define usb_write_ii(cgpu, intinfo, buf, bufsiz, wrote, cmd) \ |
||||
_usb_write(cgpu, intinfo, DEFAULT_EP_OUT, buf, bufsiz, wrote, DEVTIMEOUT, cmd) |
||||
|
||||
#define usb_write_ep(cgpu, ep, buf, bufsiz, wrote, cmd) \ |
||||
_usb_write(cgpu, DEFAULT_INTINFO, ep, buf, bufsiz, wrote, DEVTIMEOUT, cmd) |
||||
|
||||
#define usb_write_timeout(cgpu, buf, bufsiz, wrote, timeout, cmd) \ |
||||
_usb_write(cgpu, DEFAULT_INTINFO, DEFAULT_EP_OUT, buf, bufsiz, wrote, timeout, cmd) |
||||
|
||||
#define usb_write_ep_timeout(cgpu, ep, buf, bufsiz, wrote, timeout, cmd) \ |
||||
_usb_write(cgpu, DEFAULT_INTINFO, ep, buf, bufsiz, wrote, timeout, cmd) |
||||
|
||||
#define usb_transfer(cgpu, typ, req, val, idx, cmd) \ |
||||
_usb_transfer(cgpu, typ, req, val, idx, NULL, 0, DEVTIMEOUT, cmd) |
||||
|
||||
#define usb_transfer_data(cgpu, typ, req, val, idx, data, len, cmd) \ |
||||
_usb_transfer(cgpu, typ, req, val, idx, data, len, DEVTIMEOUT, cmd) |
||||
|
||||
#define usb_transfer_read(cgpu, typ, req, val, idx, buf, bufsiz, read, cmd) \ |
||||
_usb_transfer_read(cgpu, typ, req, val, idx, buf, bufsiz, read, DEVTIMEOUT, cmd) |
||||
|
||||
#endif |
Loading…
Reference in new issue