driver-hashfast.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. /*
  2. * Copyright 2013 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. #include "config.h"
  10. #include <stdbool.h>
  11. #include <stdint.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <unistd.h>
  15. #include "deviceapi.h"
  16. #include "logging.h"
  17. #include "lowlevel.h"
  18. #include "lowl-vcom.h"
  19. #include "util.h"
  20. BFG_REGISTER_DRIVER(hashfast_ums_drv)
  21. #define HASHFAST_ALL_CHIPS 0xff
  22. #define HASHFAST_ALL_CORES 0xff
  23. #define HASHFAST_HEADER_SIZE 8
  24. #define HASHFAST_MAX_DATA 0x3fc
  25. #define HASHFAST_HASH_SIZE (0x20 + 0xc + 4 + 4 + 2 + 1 + 1)
  26. enum hashfast_opcode {
  27. HFOP_NULL = 0,
  28. HFOP_ROOT = 1,
  29. HFOP_RESET = 2,
  30. HFOP_PLL_CONFIG = 3,
  31. HFOP_ADDRESS = 4,
  32. HFOP_READDRESS = 5,
  33. HFOP_HIGHEST = 6,
  34. HFOP_BAUD = 7,
  35. HFOP_UNROOT = 8,
  36. HFOP_HASH = 9,
  37. HFOP_NONCE = 0x0a,
  38. HFOP_ABORT = 0x0b,
  39. HFOP_STATUS = 0x0c,
  40. HFOP_GPIO = 0x0d,
  41. HFOP_CONFIG = 0x0e,
  42. HFOP_STATISTICS = 0x0f,
  43. HFOP_GROUP = 0x10,
  44. HFOP_CLOCKGATE = 0x11,
  45. HFOP_USB_INIT = 0x80,
  46. HFOP_GET_TRACE = 0x81,
  47. HFOP_LOOPBACK_USB = 0x82,
  48. HFOP_LOOPBACK_UART = 0x83,
  49. HFOP_DFU = 0x84,
  50. HFOP_USB_SHUTDOWN = 0x85,
  51. HFOP_DIE_STATUS = 0x86,
  52. HFOP_GWQ_STATUS = 0x87,
  53. HFOP_WORK_RESTART = 0x88,
  54. HFOP_USB_STATS1 = 0x89,
  55. HFOP_USB_GWQSTATS = 0x8a,
  56. HFOP_USB_NOTICE = 0x8b,
  57. HFOP_USB_DEBUG = 0xff,
  58. };
  59. typedef unsigned long hashfast_isn_t;
  60. struct hashfast_parsed_msg {
  61. uint8_t opcode;
  62. uint8_t chipaddr;
  63. uint8_t coreaddr;
  64. uint16_t hdata;
  65. uint8_t data[HASHFAST_MAX_DATA];
  66. size_t datalen;
  67. };
  68. static
  69. ssize_t hashfast_write(const int fd, void * const buf, size_t bufsz)
  70. {
  71. const ssize_t rv = write(fd, buf, bufsz);
  72. if (opt_debug && opt_dev_protocol)
  73. {
  74. char hex[(bufsz * 2) + 1];
  75. bin2hex(hex, buf, bufsz);
  76. if (rv < 0)
  77. applog(LOG_DEBUG, "%s fd=%d: SEND (%s) => %d",
  78. "hashfast", fd, hex, (int)rv);
  79. else
  80. if (rv < bufsz)
  81. applog(LOG_DEBUG, "%s fd=%d: SEND %.*s(%s)",
  82. "hashfast", fd, rv * 2, hex, &hex[rv * 2]);
  83. else
  84. if (rv > bufsz)
  85. applog(LOG_DEBUG, "%s fd=%d: SEND %s => +%d",
  86. "hashfast", fd, hex, (int)(rv - bufsz));
  87. else
  88. applog(LOG_DEBUG, "%s fd=%d: SEND %s",
  89. "hashfast", fd, hex);
  90. }
  91. return rv;
  92. }
  93. static
  94. ssize_t hashfast_read(const int fd, void * const buf, size_t bufsz)
  95. {
  96. const ssize_t rv = serial_read(fd, buf, bufsz);
  97. if (opt_debug && opt_dev_protocol && rv)
  98. {
  99. char hex[(rv * 2) + 1];
  100. bin2hex(hex, buf, rv);
  101. applog(LOG_DEBUG, "%s fd=%d: RECV %s",
  102. "hashfast", fd, hex);
  103. }
  104. return rv;
  105. }
  106. static
  107. bool hashfast_prepare_msg(uint8_t * const buf, const uint8_t opcode, const uint8_t chipaddr, const uint8_t coreaddr, const uint16_t hdata, const size_t datalen)
  108. {
  109. buf[0] = '\xaa';
  110. buf[1] = opcode;
  111. buf[2] = chipaddr;
  112. buf[3] = coreaddr;
  113. buf[4] = hdata & 0xff;
  114. buf[5] = hdata >> 8;
  115. if (datalen > 1020 || datalen % 4)
  116. return false;
  117. buf[6] = datalen / 4;
  118. buf[7] = crc8ccitt(&buf[1], 6);
  119. return true;
  120. }
  121. static
  122. bool hashfast_send_msg(const int fd, uint8_t * const buf, const uint8_t opcode, const uint8_t chipaddr, const uint8_t coreaddr, const uint16_t hdata, const size_t datalen)
  123. {
  124. if (!hashfast_prepare_msg(buf, opcode, chipaddr, coreaddr, hdata, datalen))
  125. return false;
  126. const size_t buflen = HASHFAST_HEADER_SIZE + datalen;
  127. return (buflen == hashfast_write(fd, buf, buflen));
  128. }
  129. static
  130. bool hashfast_parse_msg(const int fd, struct hashfast_parsed_msg * const out_msg)
  131. {
  132. uint8_t buf[HASHFAST_HEADER_SIZE];
  133. startover:
  134. if (HASHFAST_HEADER_SIZE != hashfast_read(fd, buf, HASHFAST_HEADER_SIZE))
  135. return false;
  136. uint8_t *p = memchr(buf, '\xaa', HASHFAST_HEADER_SIZE);
  137. if (p != buf)
  138. {
  139. ignoresome:
  140. if (!p)
  141. goto startover;
  142. int moreneeded = p - buf;
  143. int alreadyhave = HASHFAST_HEADER_SIZE - moreneeded;
  144. memmove(buf, p, alreadyhave);
  145. if (moreneeded != hashfast_read(fd, &buf[alreadyhave], moreneeded))
  146. return false;
  147. }
  148. const uint8_t correct_crc8 = crc8ccitt(&buf[1], 6);
  149. if (buf[7] != correct_crc8)
  150. {
  151. p = memchr(&buf[1], '\xaa', HASHFAST_HEADER_SIZE - 1);
  152. goto ignoresome;
  153. }
  154. out_msg->opcode = buf[1];
  155. out_msg->chipaddr = buf[2];
  156. out_msg->coreaddr = buf[3];
  157. out_msg->hdata = (uint16_t)buf[4] | ((uint16_t)buf[5] << 8);
  158. out_msg->datalen = buf[6] * 4;
  159. return (out_msg->datalen == hashfast_read(fd, &out_msg->data[0], out_msg->datalen));
  160. }
  161. static
  162. bool hashfast_lowl_match(const struct lowlevel_device_info * const info)
  163. {
  164. if (!lowlevel_match_id(info, &lowl_vcom, 0, 0))
  165. return false;
  166. return (info->manufacturer && strstr(info->manufacturer, "HashFast"));
  167. }
  168. static
  169. bool hashfast_detect_one(const char * const devpath)
  170. {
  171. uint16_t clock = 550;
  172. uint8_t buf[HASHFAST_HEADER_SIZE];
  173. const int fd = serial_open(devpath, 0, 100, true);
  174. if (fd == -1)
  175. {
  176. applog(LOG_DEBUG, "%s: Failed to open %s", __func__, devpath);
  177. return false;
  178. }
  179. struct hashfast_parsed_msg * const pmsg = malloc(sizeof(*pmsg));
  180. hashfast_send_msg(fd, buf, HFOP_USB_INIT, 0, 0, clock, 0);
  181. do {
  182. if (!hashfast_parse_msg(fd, pmsg))
  183. {
  184. applog(LOG_DEBUG, "%s: Failed to parse response on %s",
  185. __func__, devpath);
  186. serial_close(fd);
  187. goto err;
  188. }
  189. } while (pmsg->opcode != HFOP_USB_INIT);
  190. serial_close(fd);
  191. const int expectlen = 0x20 + (pmsg->chipaddr * pmsg->coreaddr) / 8;
  192. if (pmsg->datalen < expectlen)
  193. {
  194. applog(LOG_DEBUG, "%s: USB_INIT response too short on %s (%d < %d)",
  195. __func__, devpath, (int)pmsg->datalen, expectlen);
  196. goto err;
  197. }
  198. if (pmsg->data[8] != 0)
  199. {
  200. applog(LOG_DEBUG, "%s: USB_INIT failed on %s (err=%d)",
  201. __func__, devpath, pmsg->data[8]);
  202. goto err;
  203. }
  204. struct cgpu_info * const cgpu = malloc(sizeof(*cgpu));
  205. *cgpu = (struct cgpu_info){
  206. .drv = &hashfast_ums_drv,
  207. .device_path = strdup(devpath),
  208. .deven = DEV_ENABLED,
  209. .procs = (pmsg->chipaddr * pmsg->coreaddr),
  210. .threads = 1,
  211. .device_data = pmsg,
  212. };
  213. return add_cgpu(cgpu);
  214. err:
  215. free(pmsg);
  216. return false;
  217. }
  218. static
  219. bool hashfast_lowl_probe(const struct lowlevel_device_info * const info)
  220. {
  221. return vcom_lowl_probe_wrapper(info, hashfast_detect_one);
  222. }
  223. struct hashfast_dev_state {
  224. uint8_t cores_per_chip;
  225. int fd;
  226. struct hashfast_chip_state *chipstates;
  227. };
  228. struct hashfast_chip_state {
  229. struct cgpu_info **coreprocs;
  230. hashfast_isn_t last_isn;
  231. };
  232. struct hashfast_core_state {
  233. uint8_t chipaddr;
  234. uint8_t coreaddr;
  235. int next_device_id;
  236. uint8_t last_seq;
  237. hashfast_isn_t last_isn;
  238. hashfast_isn_t last2_isn;
  239. bool has_pending;
  240. };
  241. static
  242. bool hashfast_init(struct thr_info * const master_thr)
  243. {
  244. struct cgpu_info * const dev = master_thr->cgpu, *proc;
  245. struct hashfast_parsed_msg * const pmsg = dev->device_data;
  246. struct hashfast_dev_state * const devstate = malloc(sizeof(*devstate));
  247. struct hashfast_chip_state * const chipstates = malloc(sizeof(*chipstates) * pmsg->chipaddr), *chipstate;
  248. struct hashfast_core_state * const corestates = malloc(sizeof(*corestates) * dev->procs), *cs;
  249. int i;
  250. *devstate = (struct hashfast_dev_state){
  251. .chipstates = chipstates,
  252. .cores_per_chip = pmsg->coreaddr,
  253. .fd = serial_open(dev->device_path, 0, 1, true),
  254. };
  255. for (i = 0; i < pmsg->chipaddr; ++i)
  256. {
  257. chipstate = &chipstates[i];
  258. *chipstate = (struct hashfast_chip_state){
  259. .coreprocs = malloc(sizeof(struct cgpu_info *) * pmsg->coreaddr),
  260. };
  261. }
  262. for ((i = 0), (proc = dev); proc; ++i, (proc = proc->next_proc))
  263. {
  264. struct thr_info * const thr = proc->thr[0];
  265. const bool core_is_working = pmsg->data[0x20 + (i / 8)] & (1 << (i % 8));
  266. if (!core_is_working)
  267. proc->deven = DEV_RECOVER_DRV;
  268. proc->device_data = devstate;
  269. thr->cgpu_data = cs = &corestates[i];
  270. *cs = (struct hashfast_core_state){
  271. .chipaddr = i / pmsg->coreaddr,
  272. .coreaddr = i % pmsg->coreaddr,
  273. };
  274. chipstates[cs->chipaddr].coreprocs[cs->coreaddr] = proc;
  275. }
  276. free(pmsg);
  277. // TODO: actual clock = [12,13]
  278. timer_set_now(&master_thr->tv_poll);
  279. return true;
  280. }
  281. static
  282. bool hashfast_job_prepare(struct thr_info * const thr, struct work * const work, __maybe_unused const uint64_t max_nonce)
  283. {
  284. struct cgpu_info * const proc = thr->cgpu;
  285. struct hashfast_dev_state * const devstate = proc->device_data;
  286. const int fd = devstate->fd;
  287. struct hashfast_core_state * const cs = thr->cgpu_data;
  288. struct hashfast_chip_state * const chipstate = &devstate->chipstates[cs->chipaddr];
  289. const size_t cmdlen = HASHFAST_HEADER_SIZE + HASHFAST_HASH_SIZE;
  290. uint8_t cmd[cmdlen];
  291. uint8_t * const hashdata = &cmd[HASHFAST_HEADER_SIZE];
  292. hashfast_isn_t isn;
  293. uint8_t seq;
  294. if (cs->has_pending)
  295. hashfast_send_msg(fd, cmd, HFOP_ABORT, cs->chipaddr, cs->coreaddr, 2, 0);
  296. isn = ++chipstate->last_isn;
  297. seq = ++cs->last_seq;
  298. cs->last2_isn = cs->last_isn;
  299. cs->last_isn = isn;
  300. hashfast_prepare_msg(cmd, HFOP_HASH, cs->chipaddr, cs->coreaddr, (cs->coreaddr << 8) | seq, 56);
  301. memcpy(&hashdata[ 0], work->midstate, 0x20);
  302. memcpy(&hashdata[0x20], &work->data[64], 0xc);
  303. memset(&hashdata[0x2c], '\0', 0xa); // starting_nonce, nonce_loops, ntime_loops
  304. hashdata[0x36] = 32; // search target (number of zero bits)
  305. hashdata[0x37] = 0;
  306. cs->has_pending = true;
  307. if (cmdlen != hashfast_write(fd, cmd, cmdlen))
  308. return false;
  309. work->blk.nonce = 0xffffffff;
  310. return true;
  311. }
  312. static
  313. void hashfast_noop_job_start(struct thr_info __maybe_unused * const thr)
  314. {
  315. }
  316. static
  317. int64_t hashfast_job_process_results(struct thr_info * const thr, struct work * const work, const bool stopping)
  318. {
  319. return 0xffffffff;
  320. }
  321. static
  322. struct cgpu_info *hashfast_find_proc(struct thr_info * const master_thr, int chipaddr, int coreaddr)
  323. {
  324. struct cgpu_info *proc = master_thr->cgpu;
  325. struct hashfast_dev_state * const devstate = proc->device_data;
  326. struct hashfast_chip_state * const chipstate = &devstate->chipstates[chipaddr];
  327. return chipstate->coreprocs[coreaddr];
  328. }
  329. static
  330. hashfast_isn_t hashfast_get_isn(struct hashfast_chip_state * const chipstate, uint16_t hfseq)
  331. {
  332. const uint8_t coreaddr = hfseq >> 8;
  333. const uint8_t seq = hfseq & 0xff;
  334. struct cgpu_info * const proc = chipstate->coreprocs[coreaddr];
  335. struct thr_info * const thr = proc->thr[0];
  336. struct hashfast_core_state * const cs = thr->cgpu_data;
  337. if (cs->last_seq == seq)
  338. return cs->last_isn;
  339. if (cs->last_seq == (uint8_t)(seq + 1))
  340. return cs->last2_isn;
  341. return 0;
  342. }
  343. static
  344. bool hashfast_poll_msg(struct thr_info * const master_thr)
  345. {
  346. struct cgpu_info * const dev = master_thr->cgpu;
  347. struct hashfast_dev_state * const devstate = dev->device_data;
  348. const int fd = devstate->fd;
  349. struct hashfast_parsed_msg msg;
  350. if (!hashfast_parse_msg(fd, &msg))
  351. return false;
  352. switch (msg.opcode)
  353. {
  354. case HFOP_NONCE:
  355. {
  356. const uint8_t *data = msg.data;
  357. for (int i = msg.datalen / 8; i; --i, (data = &data[8]))
  358. {
  359. const uint32_t nonce = (data[0] << 0)
  360. | (data[1] << 8)
  361. | (data[2] << 16)
  362. | (data[3] << 24);
  363. const uint8_t seq = data[4];
  364. const uint8_t coreaddr = data[5];
  365. uint32_t ntime = data[6] | ((data[7] & 0xf) << 8);
  366. const bool search = data[7] & 0x10;
  367. struct cgpu_info * const proc = hashfast_find_proc(master_thr, msg.chipaddr, coreaddr);
  368. struct thr_info * const thr = proc->thr[0];
  369. struct hashfast_core_state * const cs = thr->cgpu_data;
  370. struct work *work;
  371. const char *workdesc;
  372. uint8_t next_work_seq = cs->last_seq + (thr->next_work ? 0 : 1);
  373. if (seq == next_work_seq)
  374. {
  375. work = thr->next_work;
  376. workdesc = "next work";
  377. }
  378. else
  379. if ((uint8_t)(seq + 1) == next_work_seq)
  380. {
  381. work = thr->work;
  382. workdesc = "current work";
  383. }
  384. else
  385. if ((uint8_t)(seq + 2) == next_work_seq)
  386. {
  387. work = thr->prev_work;
  388. workdesc = "previous work";
  389. }
  390. else
  391. {
  392. applog(LOG_WARNING, "%"PRIpreprv": Unknown seq %02x (last=%02x)",
  393. proc->proc_repr, (unsigned)seq, (unsigned)cs->last_seq);
  394. inc_hw_errors2(thr, NULL, &nonce);
  395. continue;
  396. }
  397. if (unlikely(!work))
  398. {
  399. applog(LOG_WARNING, "%"PRIpreprv": Got nonce for undefined %s",
  400. proc->proc_repr, workdesc);
  401. continue;
  402. }
  403. // TODO: implement 'search' option
  404. applog(LOG_DEBUG, "%"PRIpreprv": Found nonce for %s %08lx",
  405. proc->proc_repr, workdesc, (unsigned long)nonce);
  406. submit_nonce(thr, work, nonce);
  407. }
  408. break;
  409. }
  410. case HFOP_STATUS:
  411. {
  412. const uint8_t *data = &msg.data[8];
  413. struct cgpu_info *proc = hashfast_find_proc(master_thr, msg.chipaddr, 0);
  414. struct hashfast_chip_state * const chipstate = &devstate->chipstates[msg.chipaddr];
  415. hashfast_isn_t isn = hashfast_get_isn(chipstate, msg.hdata);
  416. int cores_uptodate, cores_loaded, cores_active, cores_pending, cores_transitioned;
  417. cores_uptodate = cores_loaded = cores_active = cores_pending = cores_transitioned = 0;
  418. for (int i = 0; i < devstate->cores_per_chip; ++i, (proc = proc->next_proc))
  419. {
  420. struct thr_info * const thr = proc->thr[0];
  421. struct hashfast_core_state * const cs = thr->cgpu_data;
  422. const uint8_t bits = data[i / 4] >> (2 * (i % 4));
  423. const bool has_active = bits & 1;
  424. const bool has_pending = bits & 2;
  425. bool try_transition = true;
  426. if (likely(thr->next_work))
  427. ++cores_loaded;
  428. else
  429. try_transition = false;
  430. if (cs->last_isn <= isn)
  431. ++cores_uptodate;
  432. else
  433. try_transition = false;
  434. if (has_active)
  435. ++cores_active;
  436. if (has_pending)
  437. ++cores_pending;
  438. else
  439. if (try_transition)
  440. {
  441. ++cores_transitioned;
  442. mt_job_transition(thr);
  443. timer_set_now(&thr->tv_morework);
  444. job_start_complete(thr);
  445. cs->has_pending = false;
  446. }
  447. }
  448. applog(LOG_DEBUG, "%s: STATUS from chipaddr=0x%02x with hdata=0x%04x (isn=0x%lx): total=%d loaded=%d uptodate=%d active=%d pending=%d transitioned=%d",
  449. dev->dev_repr, (unsigned)msg.chipaddr, (unsigned)msg.hdata, isn,
  450. devstate->cores_per_chip, cores_loaded, cores_uptodate,
  451. cores_active, cores_pending, cores_transitioned);
  452. break;
  453. }
  454. }
  455. return true;
  456. }
  457. static
  458. void hashfast_poll(struct thr_info * const master_thr)
  459. {
  460. struct cgpu_info * const dev = master_thr->cgpu;
  461. struct timeval tv_timeout;
  462. timer_set_delay_from_now(&tv_timeout, 10000);
  463. while (true)
  464. {
  465. if (!hashfast_poll_msg(master_thr))
  466. {
  467. applog(LOG_DEBUG, "%s poll: No more messages", dev->dev_repr);
  468. break;
  469. }
  470. if (timer_passed(&tv_timeout, NULL))
  471. {
  472. applog(LOG_DEBUG, "%s poll: 10ms timeout met", dev->dev_repr);
  473. break;
  474. }
  475. }
  476. timer_set_delay_from_now(&master_thr->tv_poll, 100000);
  477. }
  478. struct device_drv hashfast_ums_drv = {
  479. .dname = "hashfast_ums",
  480. .name = "HFA",
  481. .lowl_match = hashfast_lowl_match,
  482. .lowl_probe = hashfast_lowl_probe,
  483. .thread_init = hashfast_init,
  484. .minerloop = minerloop_async,
  485. .job_prepare = hashfast_job_prepare,
  486. .job_start = hashfast_noop_job_start,
  487. .job_process_results = hashfast_job_process_results,
  488. .poll = hashfast_poll,
  489. };