driver-antminer.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. * Copyright 2013 Luke Dashjr
  3. * Copyright 2013 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 "icarus-common.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. BFG_REGISTER_DRIVER(antminer_drv)
  29. static
  30. bool antminer_detect_one(const char *devpath)
  31. {
  32. struct device_drv *drv = &antminer_drv;
  33. struct ICARUS_INFO *info = calloc(1, sizeof(struct ICARUS_INFO));
  34. if (unlikely(!info))
  35. quit(1, "Failed to malloc ICARUS_INFO");
  36. *info = (struct ICARUS_INFO){
  37. .baud = ANTMINER_IO_SPEED,
  38. .Hs = ANTMINER_HASH_TIME,
  39. .timing_mode = MODE_DEFAULT,
  40. .read_size = 5,
  41. };
  42. if (!icarus_detect_custom(devpath, drv, info))
  43. {
  44. free(info);
  45. return false;
  46. }
  47. info->read_count = 15;
  48. return true;
  49. }
  50. static
  51. bool antminer_lowl_probe(const struct lowlevel_device_info * const info)
  52. {
  53. return vcom_lowl_probe_wrapper(info, antminer_detect_one);
  54. }
  55. static
  56. char *antminer_get_clock(struct cgpu_info *cgpu, char *replybuf)
  57. {
  58. uint8_t rdreg_buf[4] = {0};
  59. unsigned char rebuf[ANTMINER_STATUS_LEN] = {0};
  60. struct timeval tv_now;
  61. rdreg_buf[0] = 4;
  62. rdreg_buf[0] |= 0x80;
  63. rdreg_buf[1] = 0; //16-23
  64. rdreg_buf[2] = 0x04; // 8-15
  65. rdreg_buf[3] = crc5usb(rdreg_buf, 27);
  66. 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]);
  67. timer_set_now(&tv_now);
  68. int err = icarus_write(cgpu->device_fd, rdreg_buf, sizeof(rdreg_buf));
  69. if (err != 0)
  70. {
  71. sprintf(replybuf, "invalid send get clock: comms error (err=%d)", err);
  72. return replybuf;
  73. }
  74. applog(LOG_DEBUG, "%"PRIpreprv": Get clock: OK", cgpu->proc_repr);
  75. memset(rebuf, 0, sizeof(rebuf));
  76. err = icarus_gets(rebuf, cgpu->device_fd, &tv_now, NULL, 10, ANTMINER_STATUS_LEN);
  77. // Timeout is ok - checking specifically for an error here
  78. if (err == ICA_GETS_ERROR)
  79. {
  80. sprintf(replybuf, "invalid recv get clock: comms error (err=%d)", err);
  81. return replybuf;
  82. }
  83. applog(LOG_DEBUG, "%"PRIpreprv": Get clock: %02x%02x%02x%02x%02x", cgpu->proc_repr, rebuf[0], rebuf[1], rebuf[2], rebuf[3], rebuf[4]);
  84. return NULL;
  85. }
  86. static
  87. char *antminer_set_clock(struct cgpu_info *cgpu, char *setting, char *replybuf)
  88. {
  89. if (!setting || !*setting)
  90. return "missing clock setting";
  91. // For now we only allow hex values that use BITMAINtech's lookup table
  92. // This means values should be prefixed with an x so that later we can
  93. // accept and distinguish decimal values
  94. if (setting[0] != 'x')
  95. {
  96. sprintf(replybuf, "invalid clock: '%s' data must be prefixed with an x", setting);
  97. return replybuf;
  98. }
  99. //remove leading character
  100. char *hex_setting = setting + 1;
  101. uint8_t reg_data[4] = {0};
  102. if (!hex2bin(reg_data, hex_setting, strlen(hex_setting) / 2))
  103. {
  104. sprintf(replybuf, "invalid clock: '%s' data must be a hexidecimal value", hex_setting);
  105. return replybuf;
  106. }
  107. uint8_t cmd_buf[4] = {0};
  108. cmd_buf[0] = 2;
  109. cmd_buf[0] |= 0x80;
  110. cmd_buf[1] = reg_data[0]; //16-23
  111. cmd_buf[2] = reg_data[1]; // 8-15
  112. cmd_buf[3] = crc5usb(cmd_buf, 27);
  113. 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]);
  114. int err = icarus_write(cgpu->device_fd, cmd_buf, sizeof(cmd_buf));
  115. if (err != 0)
  116. {
  117. sprintf(replybuf, "invalid send clock: '%s' comms error (err=%d)", setting, err);
  118. return replybuf;
  119. }
  120. applog(LOG_DEBUG, "%"PRIpreprv": Set clock: OK", cgpu->proc_repr);
  121. // This is confirmed required in order for the clock change to "take"
  122. cgsleep_ms(500);
  123. return antminer_get_clock(cgpu, replybuf);
  124. }
  125. static
  126. char *antminer_set_device(struct cgpu_info *cgpu, char *option, char *setting, char *replybuf)
  127. {
  128. if (strcasecmp(option, "clock") == 0)
  129. {
  130. return antminer_set_clock(cgpu, setting, replybuf);
  131. }
  132. sprintf(replybuf, "Unknown option: %s", option);
  133. return replybuf;
  134. }
  135. static
  136. void antminer_drv_init()
  137. {
  138. antminer_drv = icarus_drv;
  139. antminer_drv.dname = "antminer";
  140. antminer_drv.name = "AMU";
  141. antminer_drv.lowl_probe = antminer_lowl_probe;
  142. antminer_drv.set_device = antminer_set_device,
  143. ++antminer_drv.probe_priority;
  144. }
  145. struct device_drv antminer_drv = {
  146. .drv_init = antminer_drv_init,
  147. };