driver-hashfast.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  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 <utlist.h>
  16. #include "deviceapi.h"
  17. #include "logging.h"
  18. #include "lowlevel.h"
  19. #include "lowl-vcom.h"
  20. #include "util.h"
  21. BFG_REGISTER_DRIVER(hashfast_ums_drv)
  22. #define HASHFAST_QUEUE_MEMORY 0x20
  23. #define HASHFAST_ALL_CHIPS 0xff
  24. #define HASHFAST_ALL_CORES 0xff
  25. #define HASHFAST_HEADER_SIZE 8
  26. #define HASHFAST_MAX_DATA 0x3fc
  27. #define HASHFAST_HASH_SIZE (0x20 + 0xc + 4 + 4 + 2 + 1 + 1)
  28. #define HASHFAST_MAX_VOLTAGES 4
  29. enum hashfast_opcode {
  30. HFOP_NULL = 0,
  31. HFOP_ROOT = 1,
  32. HFOP_RESET = 2,
  33. HFOP_PLL_CONFIG = 3,
  34. HFOP_ADDRESS = 4,
  35. HFOP_READDRESS = 5,
  36. HFOP_HIGHEST = 6,
  37. HFOP_BAUD = 7,
  38. HFOP_UNROOT = 8,
  39. HFOP_HASH = 9,
  40. HFOP_NONCE = 0x0a,
  41. HFOP_ABORT = 0x0b,
  42. HFOP_STATUS = 0x0c,
  43. HFOP_GPIO = 0x0d,
  44. HFOP_CONFIG = 0x0e,
  45. HFOP_STATISTICS = 0x0f,
  46. HFOP_GROUP = 0x10,
  47. HFOP_CLOCKGATE = 0x11,
  48. HFOP_USB_INIT = 0x80,
  49. HFOP_GET_TRACE = 0x81,
  50. HFOP_LOOPBACK_USB = 0x82,
  51. HFOP_LOOPBACK_UART = 0x83,
  52. HFOP_DFU = 0x84,
  53. HFOP_USB_SHUTDOWN = 0x85,
  54. HFOP_DIE_STATUS = 0x86,
  55. HFOP_GWQ_STATUS = 0x87,
  56. HFOP_WORK_RESTART = 0x88,
  57. HFOP_USB_STATS1 = 0x89,
  58. HFOP_USB_GWQSTATS = 0x8a,
  59. HFOP_USB_NOTICE = 0x8b,
  60. HFOP_USB_DEBUG = 0xff,
  61. };
  62. typedef unsigned long hashfast_isn_t;
  63. static inline
  64. float hashfast_temperature_conv(const uint8_t * const data)
  65. {
  66. // Temperature is 12-bit fraction ranging between -61.5 C and ~178.5 C
  67. uint32_t tempdata = ((uint32_t)data[1] << 8) | data[0];
  68. tempdata &= 0xfff;
  69. tempdata *= 240;
  70. tempdata -= 251904; // 61.5 * 4096
  71. float temp = tempdata;
  72. temp /= 4096.;
  73. return temp;
  74. }
  75. static inline
  76. float hashfast_voltage_conv(const uint8_t vdata)
  77. {
  78. // Voltage is 8-bit fraction ranging between 0 V and ~1.2 V
  79. return (float)vdata / 256. * 1.2;
  80. }
  81. struct hashfast_parsed_msg {
  82. uint8_t opcode;
  83. uint8_t chipaddr;
  84. uint8_t coreaddr;
  85. uint16_t hdata;
  86. uint8_t data[HASHFAST_MAX_DATA];
  87. size_t datalen;
  88. };
  89. static
  90. ssize_t hashfast_write(const int fd, void * const buf, size_t bufsz)
  91. {
  92. const ssize_t rv = write(fd, buf, bufsz);
  93. if ((opt_debug && opt_dev_protocol) || unlikely(rv != bufsz))
  94. {
  95. const int e = errno;
  96. char hex[(bufsz * 2) + 1];
  97. bin2hex(hex, buf, bufsz);
  98. if (rv < 0)
  99. applog(LOG_WARNING, "%s fd=%d: SEND (%s) => %d errno=%d(%s)",
  100. "hashfast", fd, hex, (int)rv, e, bfg_strerror(e, BST_ERRNO));
  101. else
  102. if (rv < bufsz)
  103. applog(LOG_WARNING, "%s fd=%d: SEND %.*s(%s)",
  104. "hashfast", fd, rv * 2, hex, &hex[rv * 2]);
  105. else
  106. if (rv > bufsz)
  107. applog(LOG_WARNING, "%s fd=%d: SEND %s => +%d",
  108. "hashfast", fd, hex, (int)(rv - bufsz));
  109. else
  110. applog(LOG_DEBUG, "%s fd=%d: SEND %s",
  111. "hashfast", fd, hex);
  112. }
  113. return rv;
  114. }
  115. static
  116. ssize_t hashfast_read(const int fd, void * const buf, size_t bufsz)
  117. {
  118. const ssize_t rv = serial_read(fd, buf, bufsz);
  119. if (opt_debug && opt_dev_protocol && rv)
  120. {
  121. char hex[(rv * 2) + 1];
  122. bin2hex(hex, buf, rv);
  123. applog(LOG_DEBUG, "%s fd=%d: RECV %s",
  124. "hashfast", fd, hex);
  125. }
  126. return rv;
  127. }
  128. static
  129. 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)
  130. {
  131. buf[0] = '\xaa';
  132. buf[1] = opcode;
  133. buf[2] = chipaddr;
  134. buf[3] = coreaddr;
  135. buf[4] = hdata & 0xff;
  136. buf[5] = hdata >> 8;
  137. if (datalen > 1020 || datalen % 4)
  138. return false;
  139. buf[6] = datalen / 4;
  140. buf[7] = crc8ccitt(&buf[1], 6);
  141. return true;
  142. }
  143. static
  144. 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)
  145. {
  146. if (!hashfast_prepare_msg(buf, opcode, chipaddr, coreaddr, hdata, datalen))
  147. return false;
  148. const size_t buflen = HASHFAST_HEADER_SIZE + datalen;
  149. return (buflen == hashfast_write(fd, buf, buflen));
  150. }
  151. static
  152. bool hashfast_parse_msg(const int fd, struct hashfast_parsed_msg * const out_msg)
  153. {
  154. uint8_t buf[HASHFAST_HEADER_SIZE];
  155. startover:
  156. if (HASHFAST_HEADER_SIZE != hashfast_read(fd, buf, HASHFAST_HEADER_SIZE))
  157. return false;
  158. uint8_t *p = memchr(buf, '\xaa', HASHFAST_HEADER_SIZE);
  159. if (p != buf)
  160. {
  161. ignoresome:
  162. if (!p)
  163. goto startover;
  164. int moreneeded = p - buf;
  165. int alreadyhave = HASHFAST_HEADER_SIZE - moreneeded;
  166. memmove(buf, p, alreadyhave);
  167. if (moreneeded != hashfast_read(fd, &buf[alreadyhave], moreneeded))
  168. return false;
  169. }
  170. const uint8_t correct_crc8 = crc8ccitt(&buf[1], 6);
  171. if (buf[7] != correct_crc8)
  172. {
  173. p = memchr(&buf[1], '\xaa', HASHFAST_HEADER_SIZE - 1);
  174. goto ignoresome;
  175. }
  176. out_msg->opcode = buf[1];
  177. out_msg->chipaddr = buf[2];
  178. out_msg->coreaddr = buf[3];
  179. out_msg->hdata = (uint16_t)buf[4] | ((uint16_t)buf[5] << 8);
  180. out_msg->datalen = buf[6] * 4;
  181. return (out_msg->datalen == hashfast_read(fd, &out_msg->data[0], out_msg->datalen));
  182. }
  183. static
  184. bool hashfast_lowl_match(const struct lowlevel_device_info * const info)
  185. {
  186. if (!lowlevel_match_id(info, &lowl_vcom, 0, 0))
  187. return false;
  188. return (info->manufacturer && strstr(info->manufacturer, "HashFast"));
  189. }
  190. static
  191. bool hashfast_detect_one(const char * const devpath)
  192. {
  193. uint16_t clock = 550;
  194. uint8_t buf[HASHFAST_HEADER_SIZE];
  195. const int fd = serial_open(devpath, 0, 100, true);
  196. if (fd == -1)
  197. {
  198. applog(LOG_DEBUG, "%s: Failed to open %s", __func__, devpath);
  199. return false;
  200. }
  201. struct hashfast_parsed_msg * const pmsg = malloc(sizeof(*pmsg));
  202. hashfast_send_msg(fd, buf, HFOP_USB_INIT, 0, 0, clock, 0);
  203. do {
  204. if (!hashfast_parse_msg(fd, pmsg))
  205. {
  206. applog(LOG_DEBUG, "%s: Failed to parse response on %s",
  207. __func__, devpath);
  208. serial_close(fd);
  209. goto err;
  210. }
  211. } while (pmsg->opcode != HFOP_USB_INIT);
  212. serial_close(fd);
  213. const int expectlen = 0x20 + (pmsg->chipaddr * pmsg->coreaddr) / 8;
  214. if (pmsg->datalen < expectlen)
  215. {
  216. applog(LOG_DEBUG, "%s: USB_INIT response too short on %s (%d < %d)",
  217. __func__, devpath, (int)pmsg->datalen, expectlen);
  218. goto err;
  219. }
  220. if (pmsg->data[8] != 0)
  221. {
  222. applog(LOG_DEBUG, "%s: USB_INIT failed on %s (err=%d)",
  223. __func__, devpath, pmsg->data[8]);
  224. goto err;
  225. }
  226. if (serial_claim_v(devpath, &hashfast_ums_drv))
  227. return false;
  228. struct cgpu_info * const cgpu = malloc(sizeof(*cgpu));
  229. *cgpu = (struct cgpu_info){
  230. .drv = &hashfast_ums_drv,
  231. .device_path = strdup(devpath),
  232. .deven = DEV_ENABLED,
  233. .procs = (pmsg->chipaddr * pmsg->coreaddr),
  234. .threads = 1,
  235. .device_data = pmsg,
  236. .cutofftemp = 100,
  237. };
  238. return add_cgpu(cgpu);
  239. err:
  240. free(pmsg);
  241. return false;
  242. }
  243. static
  244. bool hashfast_lowl_probe(const struct lowlevel_device_info * const info)
  245. {
  246. return vcom_lowl_probe_wrapper(info, hashfast_detect_one);
  247. }
  248. struct hashfast_dev_state {
  249. uint8_t cores_per_chip;
  250. int fd;
  251. struct hashfast_chip_state *chipstates;
  252. };
  253. struct hashfast_chip_state {
  254. struct cgpu_info **coreprocs;
  255. hashfast_isn_t last_isn;
  256. float voltages[HASHFAST_MAX_VOLTAGES];
  257. };
  258. struct hashfast_core_state {
  259. uint8_t chipaddr;
  260. uint8_t coreaddr;
  261. int next_device_id;
  262. uint8_t last_seq;
  263. hashfast_isn_t last_isn;
  264. hashfast_isn_t last2_isn;
  265. bool has_pending;
  266. unsigned queued;
  267. };
  268. static
  269. bool hashfast_init(struct thr_info * const master_thr)
  270. {
  271. struct cgpu_info * const dev = master_thr->cgpu, *proc;
  272. struct hashfast_parsed_msg * const pmsg = dev->device_data;
  273. struct hashfast_dev_state * const devstate = malloc(sizeof(*devstate));
  274. struct hashfast_chip_state * const chipstates = malloc(sizeof(*chipstates) * pmsg->chipaddr), *chipstate;
  275. struct hashfast_core_state * const corestates = malloc(sizeof(*corestates) * dev->procs), *cs;
  276. int i;
  277. *devstate = (struct hashfast_dev_state){
  278. .chipstates = chipstates,
  279. .cores_per_chip = pmsg->coreaddr,
  280. .fd = serial_open(dev->device_path, 0, 1, true),
  281. };
  282. for (i = 0; i < pmsg->chipaddr; ++i)
  283. {
  284. chipstate = &chipstates[i];
  285. *chipstate = (struct hashfast_chip_state){
  286. .coreprocs = malloc(sizeof(struct cgpu_info *) * pmsg->coreaddr),
  287. };
  288. }
  289. for ((i = 0), (proc = dev); proc; ++i, (proc = proc->next_proc))
  290. {
  291. struct thr_info * const thr = proc->thr[0];
  292. const bool core_is_working = pmsg->data[0x20 + (i / 8)] & (1 << (i % 8));
  293. if (!core_is_working)
  294. proc->deven = DEV_RECOVER_DRV;
  295. proc->device_data = devstate;
  296. thr->cgpu_data = cs = &corestates[i];
  297. *cs = (struct hashfast_core_state){
  298. .chipaddr = i / pmsg->coreaddr,
  299. .coreaddr = i % pmsg->coreaddr,
  300. };
  301. chipstates[cs->chipaddr].coreprocs[cs->coreaddr] = proc;
  302. }
  303. free(pmsg);
  304. // TODO: actual clock = [12,13]
  305. timer_set_now(&master_thr->tv_poll);
  306. return true;
  307. }
  308. static
  309. bool hashfast_queue_append(struct thr_info * const thr, struct work * const work)
  310. {
  311. struct cgpu_info * const proc = thr->cgpu;
  312. struct hashfast_dev_state * const devstate = proc->device_data;
  313. const int fd = devstate->fd;
  314. struct hashfast_core_state * const cs = thr->cgpu_data;
  315. struct hashfast_chip_state * const chipstate = &devstate->chipstates[cs->chipaddr];
  316. const size_t cmdlen = HASHFAST_HEADER_SIZE + HASHFAST_HASH_SIZE;
  317. uint8_t cmd[cmdlen];
  318. uint8_t * const hashdata = &cmd[HASHFAST_HEADER_SIZE];
  319. hashfast_isn_t isn;
  320. uint8_t seq;
  321. if (cs->has_pending)
  322. {
  323. thr->queue_full = true;
  324. return false;
  325. }
  326. isn = ++chipstate->last_isn;
  327. seq = ++cs->last_seq;
  328. work->device_id = seq;
  329. cs->last2_isn = cs->last_isn;
  330. cs->last_isn = isn;
  331. hashfast_prepare_msg(cmd, HFOP_HASH, cs->chipaddr, cs->coreaddr, (cs->coreaddr << 8) | seq, 56);
  332. memcpy(&hashdata[ 0], work->midstate, 0x20);
  333. memcpy(&hashdata[0x20], &work->data[64], 0xc);
  334. memset(&hashdata[0x2c], '\0', 0xa); // starting_nonce, nonce_loops, ntime_loops
  335. hashdata[0x36] = 32; // search target (number of zero bits)
  336. hashdata[0x37] = 0;
  337. cs->has_pending = true;
  338. if (cmdlen != hashfast_write(fd, cmd, cmdlen))
  339. return false;
  340. DL_APPEND(thr->work, work);
  341. if (cs->queued > HASHFAST_QUEUE_MEMORY)
  342. {
  343. struct work * const old_work = thr->work;
  344. DL_DELETE(thr->work, old_work);
  345. free_work(old_work);
  346. }
  347. else
  348. ++cs->queued;
  349. return true;
  350. }
  351. static
  352. void hashfast_queue_flush(struct thr_info * const thr)
  353. {
  354. struct cgpu_info * const proc = thr->cgpu;
  355. struct hashfast_dev_state * const devstate = proc->device_data;
  356. const int fd = devstate->fd;
  357. struct hashfast_core_state * const cs = thr->cgpu_data;
  358. uint8_t cmd[HASHFAST_HEADER_SIZE];
  359. uint16_t hdata = 2;
  360. if ((!thr->work) || stale_work(thr->work->prev, true))
  361. {
  362. applog(LOG_DEBUG, "%"PRIpreprv": Flushing both active and pending work",
  363. proc->proc_repr);
  364. hdata |= 1;
  365. }
  366. else
  367. applog(LOG_DEBUG, "%"PRIpreprv": Flushing pending work",
  368. proc->proc_repr);
  369. hashfast_send_msg(fd, cmd, HFOP_ABORT, cs->chipaddr, cs->coreaddr, hdata, 0);
  370. }
  371. static
  372. struct cgpu_info *hashfast_find_proc(struct thr_info * const master_thr, int chipaddr, int coreaddr)
  373. {
  374. struct cgpu_info *proc = master_thr->cgpu;
  375. struct hashfast_dev_state * const devstate = proc->device_data;
  376. if (coreaddr >= devstate->cores_per_chip)
  377. return NULL;
  378. const unsigned chip_count = proc->procs / devstate->cores_per_chip;
  379. if (chipaddr >= chip_count)
  380. return NULL;
  381. struct hashfast_chip_state * const chipstate = &devstate->chipstates[chipaddr];
  382. return chipstate->coreprocs[coreaddr];
  383. }
  384. static
  385. hashfast_isn_t hashfast_get_isn(struct hashfast_chip_state * const chipstate, uint16_t hfseq)
  386. {
  387. const uint8_t coreaddr = hfseq >> 8;
  388. const uint8_t seq = hfseq & 0xff;
  389. struct cgpu_info * const proc = chipstate->coreprocs[coreaddr];
  390. struct thr_info * const thr = proc->thr[0];
  391. struct hashfast_core_state * const cs = thr->cgpu_data;
  392. if (cs->last_seq == seq)
  393. return cs->last_isn;
  394. if (cs->last_seq == (uint8_t)(seq + 1))
  395. return cs->last2_isn;
  396. return 0;
  397. }
  398. static
  399. void hashfast_submit_nonce(struct thr_info * const thr, struct work * const work, const uint32_t nonce, const bool searched)
  400. {
  401. struct cgpu_info * const proc = thr->cgpu;
  402. struct hashfast_core_state * const cs = thr->cgpu_data;
  403. applog(LOG_DEBUG, "%"PRIpreprv": Found nonce for seq %02x (last=%02x): %08lx%s",
  404. proc->proc_repr, (unsigned)work->device_id, (unsigned)cs->last_seq,
  405. (unsigned long)nonce, searched ? " (searched)" : "");
  406. submit_nonce(thr, work, nonce);
  407. }
  408. static
  409. bool hashfast_poll_msg(struct thr_info * const master_thr)
  410. {
  411. struct cgpu_info * const dev = master_thr->cgpu;
  412. struct hashfast_dev_state * const devstate = dev->device_data;
  413. const int fd = devstate->fd;
  414. struct hashfast_parsed_msg msg;
  415. if (!hashfast_parse_msg(fd, &msg))
  416. return false;
  417. switch (msg.opcode)
  418. {
  419. case HFOP_NONCE:
  420. {
  421. const uint8_t *data = msg.data;
  422. for (int i = msg.datalen / 8; i; --i, (data = &data[8]))
  423. {
  424. const uint32_t nonce = (data[0] << 0)
  425. | (data[1] << 8)
  426. | (data[2] << 16)
  427. | (data[3] << 24);
  428. const uint8_t seq = data[4];
  429. const uint8_t coreaddr = data[5];
  430. // uint32_t ntime = data[6] | ((data[7] & 0xf) << 8);
  431. const bool search = data[7] & 0x10;
  432. struct cgpu_info * const proc = hashfast_find_proc(master_thr, msg.chipaddr, coreaddr);
  433. if (unlikely(!proc))
  434. {
  435. applog(LOG_ERR, "%s: Unknown chip/core address %u/%u",
  436. dev->dev_repr, (unsigned)msg.chipaddr, (unsigned)coreaddr);
  437. inc_hw_errors_only(master_thr);
  438. continue;
  439. }
  440. struct thr_info * const thr = proc->thr[0];
  441. struct hashfast_core_state * const cs = thr->cgpu_data;
  442. struct work *work;
  443. DL_SEARCH_SCALAR(thr->work, work, device_id, seq);
  444. if (unlikely(!work))
  445. {
  446. applog(LOG_WARNING, "%"PRIpreprv": Unknown seq %02x (last=%02x)",
  447. proc->proc_repr, (unsigned)seq, (unsigned)cs->last_seq);
  448. inc_hw_errors2(thr, NULL, &nonce);
  449. continue;
  450. }
  451. unsigned nonces_found = 1;
  452. hashfast_submit_nonce(thr, work, nonce, false);
  453. if (search)
  454. {
  455. for (int noffset = 1; noffset <= 0x80; ++noffset)
  456. {
  457. const uint32_t nonce2 = nonce + noffset;
  458. if (test_nonce(work, nonce2, false))
  459. {
  460. hashfast_submit_nonce(thr, work, nonce2, true);
  461. ++nonces_found;
  462. }
  463. }
  464. if (!nonces_found)
  465. {
  466. inc_hw_errors_only(thr);
  467. applog(LOG_WARNING, "%"PRIpreprv": search=1, but failed to turn up any additional solutions",
  468. proc->proc_repr);
  469. }
  470. }
  471. hashes_done2(thr, 0x100000000 * nonces_found, NULL);
  472. }
  473. break;
  474. }
  475. case HFOP_STATUS:
  476. {
  477. const uint8_t *data = &msg.data[8];
  478. struct cgpu_info *proc = hashfast_find_proc(master_thr, msg.chipaddr, 0);
  479. if (unlikely(!proc))
  480. {
  481. applog(LOG_ERR, "%s: Unknown chip address %u",
  482. dev->dev_repr, (unsigned)msg.chipaddr);
  483. inc_hw_errors_only(master_thr);
  484. break;
  485. }
  486. struct hashfast_chip_state * const chipstate = &devstate->chipstates[msg.chipaddr];
  487. hashfast_isn_t isn = hashfast_get_isn(chipstate, msg.hdata);
  488. const float temp = hashfast_temperature_conv(&msg.data[0]);
  489. for (int i = 0; i < HASHFAST_MAX_VOLTAGES; ++i)
  490. chipstate->voltages[i] = hashfast_voltage_conv(msg.data[2 + i]);
  491. int cores_uptodate, cores_active, cores_pending, cores_transitioned;
  492. cores_uptodate = cores_active = cores_pending = cores_transitioned = 0;
  493. for (int i = 0; i < devstate->cores_per_chip; ++i, (proc = proc->next_proc))
  494. {
  495. struct thr_info * const thr = proc->thr[0];
  496. struct hashfast_core_state * const cs = thr->cgpu_data;
  497. const uint8_t bits = data[i / 4] >> (2 * (i % 4));
  498. const bool has_active = bits & 1;
  499. const bool has_pending = bits & 2;
  500. bool try_transition = true;
  501. proc->temp = temp;
  502. if (cs->last_isn <= isn)
  503. ++cores_uptodate;
  504. else
  505. try_transition = false;
  506. if (has_active)
  507. ++cores_active;
  508. if (has_pending)
  509. ++cores_pending;
  510. else
  511. if (try_transition)
  512. {
  513. ++cores_transitioned;
  514. cs->has_pending = false;
  515. thr->queue_full = false;
  516. }
  517. }
  518. applog(LOG_DEBUG, "%s: STATUS from chipaddr=0x%02x with hdata=0x%04x (isn=0x%lx): total=%d uptodate=%d active=%d pending=%d transitioned=%d",
  519. dev->dev_repr, (unsigned)msg.chipaddr, (unsigned)msg.hdata, isn,
  520. devstate->cores_per_chip, cores_uptodate,
  521. cores_active, cores_pending, cores_transitioned);
  522. break;
  523. }
  524. }
  525. return true;
  526. }
  527. static
  528. void hashfast_poll(struct thr_info * const master_thr)
  529. {
  530. struct cgpu_info * const dev = master_thr->cgpu;
  531. struct timeval tv_timeout;
  532. timer_set_delay_from_now(&tv_timeout, 10000);
  533. while (true)
  534. {
  535. if (!hashfast_poll_msg(master_thr))
  536. {
  537. applog(LOG_DEBUG, "%s poll: No more messages", dev->dev_repr);
  538. break;
  539. }
  540. if (timer_passed(&tv_timeout, NULL))
  541. {
  542. applog(LOG_DEBUG, "%s poll: 10ms timeout met", dev->dev_repr);
  543. break;
  544. }
  545. }
  546. timer_set_delay_from_now(&master_thr->tv_poll, 100000);
  547. }
  548. static
  549. struct api_data *hashfast_api_stats(struct cgpu_info * const proc)
  550. {
  551. struct hashfast_dev_state * const devstate = proc->device_data;
  552. struct thr_info * const thr = proc->thr[0];
  553. struct hashfast_core_state * const cs = thr->cgpu_data;
  554. struct hashfast_chip_state * const chipstate = &devstate->chipstates[cs->chipaddr];
  555. struct api_data *root = NULL;
  556. char key[] = "VoltageNN";
  557. for (int i = 0; i < HASHFAST_MAX_VOLTAGES; ++i)
  558. {
  559. snprintf(&key[7], 3, "%d", i);
  560. if (chipstate->voltages[i])
  561. root = api_add_volts(root, key, &chipstate->voltages[i], false);
  562. }
  563. return root;
  564. }
  565. #ifdef HAVE_CURSES
  566. static
  567. void hashfast_wlogprint_status(struct cgpu_info * const proc)
  568. {
  569. struct hashfast_dev_state * const devstate = proc->device_data;
  570. struct thr_info * const thr = proc->thr[0];
  571. struct hashfast_core_state * const cs = thr->cgpu_data;
  572. struct hashfast_chip_state * const chipstate = &devstate->chipstates[cs->chipaddr];
  573. {
  574. // -> "NNN.xxx / NNN.xxx / NNN.xxx"
  575. size_t sz = (HASHFAST_MAX_VOLTAGES * 10) + 1;
  576. char buf[sz];
  577. char *s = buf;
  578. int rv = 0;
  579. for (int i = 0; i < HASHFAST_MAX_VOLTAGES; ++i)
  580. {
  581. const float voltage = chipstate->voltages[i];
  582. if (!voltage)
  583. continue;
  584. _SNP("%.3f / ", voltage);
  585. }
  586. if (rv >= 3 && s[-2] == '/')
  587. {
  588. s[-3] = '\0';
  589. wlogprint("Voltages: %s\n", buf);
  590. }
  591. }
  592. }
  593. #endif
  594. struct device_drv hashfast_ums_drv = {
  595. .dname = "hashfast_ums",
  596. .name = "HFA",
  597. .lowl_match = hashfast_lowl_match,
  598. .lowl_probe = hashfast_lowl_probe,
  599. .thread_init = hashfast_init,
  600. .minerloop = minerloop_queue,
  601. .queue_append = hashfast_queue_append,
  602. .queue_flush = hashfast_queue_flush,
  603. .poll = hashfast_poll,
  604. .get_api_stats = hashfast_api_stats,
  605. #ifdef HAVE_CURSES
  606. .proc_wlogprint_status = hashfast_wlogprint_status,
  607. #endif
  608. };