driver-antminer.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*
  2. * Copyright 2013-2015 Luke Dashjr
  3. * Copyright 2013-2014 Nate Woolls
  4. * Copyright 2013 Lingchao Xu
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the Free
  8. * Software Foundation; either version 3 of the License, or (at your option)
  9. * any later version. See COPYING for more details.
  10. */
  11. #include "config.h"
  12. #include <stdbool.h>
  13. #include <stdint.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <strings.h>
  18. #include "miner.h"
  19. #include "driver-icarus.h"
  20. #include "lowlevel.h"
  21. #include "lowl-vcom.h"
  22. #include "deviceapi.h"
  23. #include "logging.h"
  24. #include "util.h"
  25. #define ANTMINER_IO_SPEED 115200
  26. #define ANTMINER_HASH_TIME 0.0000000004761
  27. #define ANTMINER_STATUS_LEN 5
  28. #define ANTMINER_COMMAND_PREFIX 128
  29. #define ANTMINER_COMMAND_LED 1
  30. #define ANTMINER_COMMAND_ON 1
  31. #define ANTMINER_COMMAND_OFFSET 32
  32. BFG_REGISTER_DRIVER(antminer_drv)
  33. static
  34. const struct bfg_set_device_definition antminer_set_device_funcs[];
  35. static
  36. bool antminer_detect_one(const char *devpath)
  37. {
  38. struct device_drv *drv = &antminer_drv;
  39. struct ICARUS_INFO *info = calloc(1, sizeof(struct ICARUS_INFO));
  40. if (unlikely(!info))
  41. quit(1, "Failed to malloc ICARUS_INFO");
  42. *info = (struct ICARUS_INFO){
  43. .baud = ANTMINER_IO_SPEED,
  44. .Hs = ANTMINER_HASH_TIME,
  45. .timing_mode = MODE_DEFAULT,
  46. .read_size = 5,
  47. };
  48. struct cgpu_info * const dev = icarus_detect_custom(devpath, drv, info);
  49. if (!dev)
  50. {
  51. free(info);
  52. return false;
  53. }
  54. dev->set_device_funcs = antminer_set_device_funcs;
  55. info->read_count = 15;
  56. return true;
  57. }
  58. static
  59. bool antminer_lowl_probe(const struct lowlevel_device_info * const info)
  60. {
  61. return vcom_lowl_probe_wrapper(info, antminer_detect_one);
  62. }
  63. static
  64. char *antminer_get_clock(struct cgpu_info *cgpu, char *replybuf)
  65. {
  66. uint8_t rdreg_buf[4] = {0};
  67. unsigned char rebuf[ANTMINER_STATUS_LEN] = {0};
  68. struct timeval tv_now;
  69. rdreg_buf[0] = 4;
  70. rdreg_buf[0] |= 0x80;
  71. rdreg_buf[1] = 0; //16-23
  72. rdreg_buf[2] = 0x04; // 8-15
  73. rdreg_buf[3] = crc5usb(rdreg_buf, 27);
  74. applog(LOG_DEBUG, "%"PRIpreprv": Get clock: %02x%02x%02x%02x", cgpu->proc_repr, rdreg_buf[0], rdreg_buf[1], rdreg_buf[2], rdreg_buf[3]);
  75. timer_set_now(&tv_now);
  76. int err = icarus_write(cgpu->device_fd, rdreg_buf, sizeof(rdreg_buf));
  77. if (err != 0)
  78. {
  79. sprintf(replybuf, "invalid send get clock: comms error (err=%d)", err);
  80. return replybuf;
  81. }
  82. applog(LOG_DEBUG, "%"PRIpreprv": Get clock: OK", cgpu->proc_repr);
  83. memset(rebuf, 0, sizeof(rebuf));
  84. err = icarus_gets(rebuf, cgpu->device_fd, &tv_now, NULL, 10, ANTMINER_STATUS_LEN);
  85. // Timeout is ok - checking specifically for an error here
  86. if (err == ICA_GETS_ERROR)
  87. {
  88. sprintf(replybuf, "invalid recv get clock: comms error (err=%d)", err);
  89. return replybuf;
  90. }
  91. applog(LOG_DEBUG, "%"PRIpreprv": Get clock: %02x%02x%02x%02x%02x", cgpu->proc_repr, rebuf[0], rebuf[1], rebuf[2], rebuf[3], rebuf[4]);
  92. return NULL;
  93. }
  94. static
  95. const char *antminer_set_clock(struct cgpu_info * const cgpu, const char * const optname, const char * const setting, char * const replybuf, enum bfg_set_device_replytype * const out_success)
  96. {
  97. if (!setting || !*setting)
  98. return "missing clock setting";
  99. // For now we only allow hex values that use BITMAINtech's lookup table
  100. // This means values should be prefixed with an x so that later we can
  101. // accept and distinguish decimal values
  102. if (setting[0] != 'x')
  103. {
  104. sprintf(replybuf, "invalid clock: '%s' data must be prefixed with an x", setting);
  105. return replybuf;
  106. }
  107. //remove leading character
  108. const char * const hex_setting = &setting[1];
  109. uint8_t reg_data[4] = {0};
  110. if (!hex2bin(reg_data, hex_setting, strlen(hex_setting) / 2))
  111. {
  112. sprintf(replybuf, "invalid clock: '%s' data must be a hexadecimal value", hex_setting);
  113. return replybuf;
  114. }
  115. uint8_t cmd_buf[4] = {0};
  116. cmd_buf[0] = 2;
  117. cmd_buf[0] |= 0x80;
  118. cmd_buf[1] = reg_data[0]; //16-23
  119. cmd_buf[2] = reg_data[1]; // 8-15
  120. cmd_buf[3] = crc5usb(cmd_buf, 27);
  121. applog(LOG_DEBUG, "%"PRIpreprv": Set clock: %02x%02x%02x%02x", cgpu->proc_repr, cmd_buf[0], cmd_buf[1], cmd_buf[2], cmd_buf[3]);
  122. int err = icarus_write(cgpu->device_fd, cmd_buf, sizeof(cmd_buf));
  123. if (err != 0)
  124. {
  125. sprintf(replybuf, "invalid send clock: '%s' comms error (err=%d)", setting, err);
  126. return replybuf;
  127. }
  128. applog(LOG_DEBUG, "%"PRIpreprv": Set clock: OK", cgpu->proc_repr);
  129. // This is confirmed required in order for the clock change to "take"
  130. cgsleep_ms(500);
  131. return antminer_get_clock(cgpu, replybuf);
  132. }
  133. static
  134. void antminer_flash_led(const struct cgpu_info *antminer)
  135. {
  136. const int offset = ANTMINER_COMMAND_OFFSET;
  137. uint8_t cmd_buf[4 + offset];
  138. memset(cmd_buf, 0, sizeof(cmd_buf));
  139. cmd_buf[offset + 0] = ANTMINER_COMMAND_PREFIX;
  140. cmd_buf[offset + 1] = ANTMINER_COMMAND_LED;
  141. cmd_buf[offset + 2] = ANTMINER_COMMAND_ON;
  142. cmd_buf[offset + 3] = crc5usb(cmd_buf, sizeof(cmd_buf));
  143. const int fd = antminer->device_fd;
  144. icarus_write(fd, (char *)(&cmd_buf), sizeof(cmd_buf));
  145. }
  146. static
  147. bool antminer_identify(struct cgpu_info *antminer)
  148. {
  149. for (int i = 0; i < 10; i++)
  150. {
  151. antminer_flash_led(antminer);
  152. cgsleep_ms(250);
  153. }
  154. return true;
  155. }
  156. static
  157. const struct bfg_set_device_definition antminer_set_device_funcs[] = {
  158. {"baud" , icarus_set_baud , "serial baud rate"},
  159. {"work_division", icarus_set_work_division, "number of pieces work is split into"},
  160. {"reopen" , icarus_set_reopen , "how often to reopen device: never, timeout, cycle, (or now for a one-shot reopen)"},
  161. {"timing" , icarus_set_timing , "timing of device; see README.FPGA"},
  162. {"clock", antminer_set_clock, "clock frequency"},
  163. {NULL},
  164. };
  165. #ifdef HAVE_CURSES
  166. static
  167. void antminer_tui_wlogprint_choices(struct cgpu_info * const proc)
  168. {
  169. struct ICARUS_INFO * const info = proc->device_data;
  170. if (info->has_bm1382_freq_register)
  171. wlogprint("[C]lock speed ");
  172. }
  173. static
  174. const char *antminer_tui_handle_choice(struct cgpu_info * const proc, const int input)
  175. {
  176. switch (input)
  177. {
  178. case 'c': case 'C':
  179. return proc_set_device_tui_wrapper(proc, NULL, antminer_set_clock, "Set clock speed", NULL);
  180. }
  181. return NULL;
  182. }
  183. #endif
  184. static
  185. void antminer_drv_init()
  186. {
  187. antminer_drv = icarus_drv;
  188. antminer_drv.dname = "antminer";
  189. antminer_drv.name = "AMU";
  190. antminer_drv.lowl_probe = antminer_lowl_probe;
  191. antminer_drv.identify_device = antminer_identify;
  192. #ifdef HAVE_CURSES
  193. antminer_drv.proc_tui_wlogprint_choices = antminer_tui_wlogprint_choices;
  194. antminer_drv.proc_tui_handle_choice = antminer_tui_handle_choice;
  195. #endif
  196. ++antminer_drv.probe_priority;
  197. }
  198. struct device_drv antminer_drv = {
  199. .drv_init = antminer_drv_init,
  200. };