driver-minergate.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /*
  2. * Copyright 2014 Luke Dashjr
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License as published by the Free
  6. * Software Foundation; either version 3 of the License, or (at your option)
  7. * any later version. See COPYING for more details.
  8. *
  9. * To avoid doubt: Programs using the minergate protocol to interface with
  10. * BFGMiner are considered part of the Corresponding Source, and not an
  11. * independent work. This means that such programs distrbuted with BFGMiner
  12. * must be released under the terms of the GPLv3 license, or sufficiently
  13. * compatible terms.
  14. */
  15. #include "config.h"
  16. #include <math.h>
  17. #include <stdbool.h>
  18. #include <stdint.h>
  19. #include <sys/epoll.h>
  20. #include <sys/types.h>
  21. #include <sys/socket.h>
  22. #include <sys/un.h>
  23. #include "deviceapi.h"
  24. #include "logging.h"
  25. #include "miner.h"
  26. #define MINERGATE_MAX_NONCE_DIFF 0x20
  27. #define MINERGATE_PROTOCOL_VER 6
  28. #define MINERGATE_MAGIC 0xcaf4
  29. static const int minergate_max_responses = 300;
  30. #define MINERGATE_PKT_HEADER_SZ 8
  31. #define MINERGATE_PKT_REQ_ITEM_SZ 0x34
  32. #define MINERGATE_PKT_REQ_MAX 100
  33. #define MINERGATE_PKT_RSP_ITEM_SZ 0x14
  34. #define MINERGATE_PKT_RSP_MAX 300
  35. #define MINERGATE_POLL_US 100000
  36. #define MINERGATE_RETRY_US 5000000
  37. #define MINERGATE_PKT_REQ_SZ (MINERGATE_PKT_HEADER_SZ + (MINERGATE_PKT_REQ_ITEM_SZ * MINERGATE_PKT_REQ_MAX))
  38. #define MINERGATE_PKT_RSP_SZ (MINERGATE_PKT_HEADER_SZ + (MINERGATE_PKT_RSP_ITEM_SZ * MINERGATE_PKT_RSP_MAX))
  39. BFG_REGISTER_DRIVER(minergate_drv)
  40. enum minergate_reqpkt_flags {
  41. MRPF_FIRST = 1,
  42. MRPF_FLUSH = 2,
  43. };
  44. struct minergate_state {
  45. work_device_id_t next_jobid;
  46. unsigned ready_to_queue;
  47. uint8_t *req_buffer;
  48. };
  49. static
  50. int minergate_open(const char * const devpath)
  51. {
  52. size_t devpath_len = strlen(devpath);
  53. struct sockaddr_un sa = {
  54. .sun_family = AF_UNIX,
  55. };
  56. #ifdef UNIX_PATH_MAX
  57. if (devpath_len >= UNIX_PATH_MAX)
  58. #else
  59. if (devpath_len >= sizeof(sa.sun_path))
  60. #endif
  61. return -1;
  62. const int fd = socket(PF_UNIX, SOCK_STREAM, 0);
  63. strcpy(sa.sun_path, devpath);
  64. if (connect(fd, &sa, sizeof(sa)))
  65. {
  66. close(fd);
  67. return -1;
  68. }
  69. return fd;
  70. }
  71. static
  72. ssize_t minergate_read(const int fd, void * const buf_p, size_t bufLen)
  73. {
  74. uint8_t *buf = buf_p;
  75. ssize_t rv, ret = 0;
  76. while (bufLen > 0)
  77. {
  78. rv = read(fd, buf, bufLen);
  79. if (rv <= 0)
  80. {
  81. if (ret > 0)
  82. return ret;
  83. return rv;
  84. }
  85. buf += rv;
  86. bufLen -= rv;
  87. ret += rv;
  88. }
  89. return ret;
  90. }
  91. static
  92. bool minergate_detect_one(const char * const devpath)
  93. {
  94. bool rv = false;
  95. const int fd = minergate_open(devpath);
  96. if (unlikely(fd < 0))
  97. applogr(false, LOG_DEBUG, "%s: %s: Cannot connect", minergate_drv.dname, devpath);
  98. int epfd = -1;
  99. uint8_t buf[MINERGATE_PKT_REQ_SZ] = {0xbf, 0x90, MINERGATE_PROTOCOL_VER, MRPF_FIRST, 0,0, 0 /* req count */,};
  100. pk_u16le(buf, 4, MINERGATE_MAGIC);
  101. if (MINERGATE_PKT_REQ_SZ != write(fd, buf, MINERGATE_PKT_REQ_SZ))
  102. return_via_applog(out, , LOG_DEBUG, "%s: %s: write incomplete or failed", minergate_drv.dname, devpath);
  103. epfd = epoll_create(1);
  104. if (epfd < 0)
  105. return_via_applog(out, , LOG_DEBUG, "%s: %s: %s failed", minergate_drv.dname, devpath, "epoll_create");
  106. struct epoll_event eev;
  107. eev.events = EPOLLIN;
  108. if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &eev))
  109. return_via_applog(out, , LOG_DEBUG, "%s: %s: %s failed", minergate_drv.dname, devpath, "epoll_ctl");
  110. size_t read_bytes = 0;
  111. static const size_t read_expect = MINERGATE_PKT_HEADER_SZ;
  112. ssize_t r;
  113. while (read_bytes < read_expect)
  114. {
  115. if (epoll_wait(epfd, &eev, 1, 1000) != 1)
  116. return_via_applog(out, , LOG_DEBUG, "%s: %s: Timeout waiting for response", minergate_drv.dname, devpath);
  117. r = read(fd, &buf[read_bytes], read_expect - read_bytes);
  118. if (r <= 0)
  119. return_via_applog(out, , LOG_DEBUG, "%s: %s: %s failed", minergate_drv.dname, devpath, "read");
  120. read_bytes += r;
  121. }
  122. if (buf[1] != 0x90)
  123. return_via_applog(out, , LOG_DEBUG, "%s: %s: %s mismatch", minergate_drv.dname, devpath, "request_id");
  124. if (buf[2] != MINERGATE_PROTOCOL_VER)
  125. return_via_applog(out, , LOG_DEBUG, "%s: %s: %s mismatch", minergate_drv.dname, devpath, "Protocol version");
  126. if (upk_u16le(buf, 4) != MINERGATE_MAGIC)
  127. return_via_applog(out, , LOG_DEBUG, "%s: %s: %s mismatch", minergate_drv.dname, devpath, "magic");
  128. uint16_t responses = upk_u16le(buf, 6);
  129. if (responses > minergate_max_responses)
  130. return_via_applog(out, , LOG_DEBUG, "%s: %s: More than maximum responses", minergate_drv.dname, devpath);
  131. struct cgpu_info * const cgpu = malloc(sizeof(*cgpu));
  132. *cgpu = (struct cgpu_info){
  133. .drv = &minergate_drv,
  134. .device_path = strdup(devpath),
  135. .deven = DEV_ENABLED,
  136. .threads = 1,
  137. };
  138. rv = add_cgpu(cgpu);
  139. out:
  140. close(fd);
  141. if (epfd >= 0)
  142. close(epfd);
  143. return rv;
  144. }
  145. static
  146. int minergate_detect_auto(void)
  147. {
  148. return minergate_detect_one("/tmp/connection_pipe") ? 1 : 0;
  149. }
  150. static
  151. void minergate_detect(void)
  152. {
  153. generic_detect(&minergate_drv, minergate_detect_one, minergate_detect_auto, 0);
  154. }
  155. static
  156. bool minergate_init(struct thr_info * const thr)
  157. {
  158. struct cgpu_info * const dev = thr->cgpu;
  159. const int fd = minergate_open(dev->device_path);
  160. dev->device_fd = fd;
  161. if (fd < 0)
  162. applogr(false, LOG_ERR, "%s: Cannot connect", dev->dev_repr);
  163. struct minergate_state * const state = malloc(sizeof(*state) + MINERGATE_PKT_REQ_SZ);
  164. if (!state)
  165. applogr(false, LOG_ERR, "%s: %s failed", dev->dev_repr, "malloc");
  166. *state = (struct minergate_state){
  167. .req_buffer = (void*)&state[1]
  168. };
  169. thr->cgpu_data = state;
  170. thr->work = thr->work_list = NULL;
  171. memset(state->req_buffer, 0, MINERGATE_PKT_REQ_SZ);
  172. pk_u8(state->req_buffer, 2, MINERGATE_PROTOCOL_VER);
  173. state->req_buffer[3] = MRPF_FIRST;
  174. pk_u16le(state->req_buffer, 4, MINERGATE_MAGIC);
  175. return true;
  176. }
  177. static
  178. bool minergate_queue_full(struct thr_info * const thr)
  179. {
  180. static const unsigned max_minergate_jobs = 300, max_requests = 100;
  181. struct minergate_state * const state = thr->cgpu_data;
  182. bool qf;
  183. if (HASH_COUNT(thr->work) + state->ready_to_queue >= max_minergate_jobs)
  184. qf = true;
  185. else
  186. if (state->ready_to_queue >= max_requests)
  187. qf = true;
  188. else
  189. qf = false;
  190. thr->queue_full = qf;
  191. return qf;
  192. }
  193. static
  194. bool minergate_queue_append(struct thr_info * const thr, struct work * const work)
  195. {
  196. struct minergate_state * const state = thr->cgpu_data;
  197. if (minergate_queue_full(thr))
  198. return false;
  199. work->device_id = (uint32_t)(state->next_jobid++);
  200. uint8_t * const my_buf = &state->req_buffer[MINERGATE_PKT_HEADER_SZ + (MINERGATE_PKT_REQ_ITEM_SZ * state->ready_to_queue++)];
  201. pk_u32be(my_buf, 0, work->device_id);
  202. memcpy(&my_buf[ 4], &work->data[0x48], 4); // nbits
  203. memcpy(&my_buf[ 8], &work->data[0x44], 4); // ntime
  204. memcpy(&my_buf[0x0c], &work->data[0x40], 4); // merkle-tail
  205. memcpy(&my_buf[0x10], work->midstate, 0x20);
  206. if (work->work_difficulty >= MINERGATE_MAX_NONCE_DIFF)
  207. work->nonce_diff = MINERGATE_MAX_NONCE_DIFF;
  208. else
  209. work->nonce_diff = work->work_difficulty;
  210. const uint16_t zerobits = log2(floor(work->nonce_diff * 4294967296));
  211. work->nonce_diff = pow(2, zerobits) / 4294967296;
  212. pk_u8(my_buf, 0x30, zerobits);
  213. pk_u8(my_buf, 0x31, 0); // ntime limit
  214. pk_u8(my_buf, 0x32, 0); // ntime offset
  215. pk_u8(my_buf, 0x33, 0); // reserved
  216. HASH_ADD(hh, thr->work, device_id, sizeof(work->device_id), work);
  217. LL_PREPEND(thr->work_list, work);
  218. timer_set_delay_from_now(&thr->tv_poll, 0);
  219. minergate_queue_full(thr);
  220. return true;
  221. }
  222. static
  223. void minergate_queue_flush(struct thr_info * const thr)
  224. {
  225. struct minergate_state * const state = thr->cgpu_data;
  226. // TODO: prune state->ready_to_queue
  227. state->req_buffer[3] |= MRPF_FLUSH;
  228. timer_set_delay_from_now(&thr->tv_poll, 0);
  229. }
  230. static
  231. void minergate_poll(struct thr_info * const thr)
  232. {
  233. struct cgpu_info * const dev = thr->cgpu;
  234. struct minergate_state * const state = thr->cgpu_data;
  235. const int fd = dev->device_fd;
  236. if (opt_dev_protocol || state->ready_to_queue)
  237. applog(LOG_DEBUG, "%s: Polling with %u new jobs", dev->dev_repr, state->ready_to_queue);
  238. pk_u16le(state->req_buffer, 6, state->ready_to_queue);
  239. if (MINERGATE_PKT_REQ_SZ != write(fd, state->req_buffer, MINERGATE_PKT_REQ_SZ))
  240. return_via_applog(err, , LOG_ERR, "%s: write incomplete or failed", dev->dev_repr);
  241. state->req_buffer[3] = 0;
  242. state->ready_to_queue = 0;
  243. thr->work_list = NULL;
  244. uint8_t buf[MINERGATE_PKT_RSP_SZ];
  245. if (minergate_read(fd, buf, MINERGATE_PKT_RSP_SZ) != MINERGATE_PKT_RSP_SZ)
  246. return_via_applog(err, , LOG_ERR, "%s: %s failed", dev->dev_repr, "read");
  247. if (upk_u8(buf, 2) != MINERGATE_PROTOCOL_VER || upk_u16le(buf, 4) != MINERGATE_MAGIC)
  248. return_via_applog(err, , LOG_ERR, "%s: Protocol mismatch", dev->dev_repr);
  249. uint8_t *jobrsp = &buf[MINERGATE_PKT_HEADER_SZ];
  250. struct work *work;
  251. uint16_t rsp_count = upk_u16le(buf, 6);
  252. if (rsp_count || opt_dev_protocol)
  253. applog(LOG_DEBUG, "%s: Received %u job completions", dev->dev_repr, rsp_count);
  254. uint32_t nonce;
  255. for (unsigned i = 0; i < rsp_count; ++i, (jobrsp += MINERGATE_PKT_RSP_ITEM_SZ))
  256. {
  257. work_device_id_t jobid = upk_u32be(jobrsp, 0);
  258. nonce = upk_u32le(jobrsp, 8);
  259. HASH_FIND(hh, thr->work, &jobid, sizeof(jobid), work);
  260. if (!work)
  261. {
  262. applog(LOG_ERR, "%s: Unknown job %"PRIwdi, dev->dev_repr, jobid);
  263. if (nonce)
  264. {
  265. inc_hw_errors3(thr, NULL, &nonce, 1.);
  266. nonce = upk_u32le(jobrsp, 0xc);
  267. if (nonce)
  268. inc_hw_errors3(thr, NULL, &nonce, 1.);
  269. }
  270. else
  271. inc_hw_errors_only(thr);
  272. continue;
  273. }
  274. if (nonce)
  275. {
  276. submit_nonce(thr, work, nonce);
  277. nonce = upk_u32be(jobrsp, 0xc);
  278. if (nonce)
  279. submit_nonce(thr, work, nonce);
  280. }
  281. HASH_DEL(thr->work, work);
  282. free_work(work);
  283. }
  284. minergate_queue_full(thr);
  285. timer_set_delay_from_now(&thr->tv_poll, MINERGATE_POLL_US);
  286. return;
  287. err:
  288. // TODO: reconnect
  289. timer_set_delay_from_now(&thr->tv_poll, MINERGATE_RETRY_US);
  290. }
  291. struct device_drv minergate_drv = {
  292. .dname = "minergate",
  293. .name = "MGT",
  294. .drv_detect = minergate_detect,
  295. .thread_init = minergate_init,
  296. .minerloop = minerloop_queue,
  297. .queue_append = minergate_queue_append,
  298. .queue_flush = minergate_queue_flush,
  299. .poll = minergate_poll,
  300. };