Browse Source

Remove USB, FPGA and ASIC files.

Code referencing these files is still present, but not compiled through the use of defines.
nfactor-troky
Noel Maersk 11 years ago
parent
commit
9f64ee9c99
  1. 32
      01-cgminer.rules
  2. 108
      bitforce-firmware-flash.c
  3. 23
      bitstreams/COPYING_fpgaminer
  4. BIN
      bitstreams/fpgaminer_top_fixed7_197MHz.ncd
  5. 1361
      diablo130302.cl
  6. 599
      diakgcn121016.cl
  7. 1689
      driver-avalon.c
  8. 200
      driver-avalon.h
  9. 1948
      driver-bflsc.c
  10. 363
      driver-bflsc.h
  11. 756
      driver-bitforce.c
  12. 370
      driver-bitfury.c
  13. 33
      driver-bitfury.h
  14. 937
      driver-hashfast.c
  15. 97
      driver-hashfast.h
  16. 1421
      driver-icarus.c
  17. 1557
      driver-klondike.c
  18. 762
      driver-knc-spi-fpga.c
  19. 1144
      driver-modminer.c
  20. 610
      fpgautils.c
  21. 84
      fpgautils.h
  22. 305
      linux-usb-cgminer
  23. 417
      phatk121016.cl
  24. 1388
      poclbm130302.cl
  25. 3709
      usbutils.c
  26. 486
      usbutils.h

32
01-cgminer.rules

@ -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"

108
bitforce-firmware-flash.c

@ -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;
}

23
bitstreams/COPYING_fpgaminer

@ -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

BIN
bitstreams/fpgaminer_top_fixed7_197MHz.ncd

Binary file not shown.

1361
diablo130302.cl

File diff suppressed because it is too large Load Diff

599
diakgcn121016.cl

@ -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
}

1689
driver-avalon.c

File diff suppressed because it is too large Load Diff

200
driver-avalon.h

@ -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 */

1948
driver-bflsc.c

File diff suppressed because it is too large Load Diff

363
driver-bflsc.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 */

756
driver-bitforce.c

@ -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
};

370
driver-bitfury.c

@ -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
};

33
driver-bitfury.h

@ -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 */

937
driver-hashfast.c

@ -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,
};

97
driver-hashfast.h

@ -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 */

1421
driver-icarus.c

File diff suppressed because it is too large Load Diff

1557
driver-klondike.c

File diff suppressed because it is too large Load Diff

762
driver-knc-spi-fpga.c

@ -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,
};

1144
driver-modminer.c

File diff suppressed because it is too large Load Diff

610
fpgautils.c

@ -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

84
fpgautils.h

@ -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

305
linux-usb-cgminer

@ -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

417
phatk121016.cl

@ -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
}

1388
poclbm130302.cl

File diff suppressed because it is too large Load Diff

3709
usbutils.c

File diff suppressed because it is too large Load Diff

486
usbutils.h

@ -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…
Cancel
Save