driver-bitfury.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. /*
  2. * Copyright 2013 bitfury
  3. * Copyright 2013 legkodymov
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy
  6. * of this software and associated documentation files (the "Software"), to deal
  7. * in the Software without restriction, including without limitation the rights
  8. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. * copies of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in
  13. * all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. * THE SOFTWARE.
  22. */
  23. #include "config.h"
  24. #include "miner.h"
  25. #include <unistd.h>
  26. #include <sha2.h>
  27. #include "deviceapi.h"
  28. #include "dynclock.h"
  29. #include "libbitfury.h"
  30. #include "util.h"
  31. #include "spidevc.h"
  32. #define GOLDEN_BACKLOG 5
  33. #define LINE_LEN 2048
  34. struct device_drv bitfury_drv;
  35. int calc_stat(time_t * stat_ts, time_t stat, struct timeval now);
  36. double shares_to_ghashes(int shares, int seconds);
  37. static
  38. int bitfury_autodetect()
  39. {
  40. RUNONCE(0);
  41. int chip_n;
  42. struct cgpu_info *bitfury_info;
  43. bitfury_info = calloc(1, sizeof(struct cgpu_info));
  44. bitfury_info->drv = &bitfury_drv;
  45. bitfury_info->threads = 1;
  46. applog(LOG_INFO, "INFO: bitfury_detect");
  47. spi_init();
  48. if (!sys_spi)
  49. return 0;
  50. chip_n = libbitfury_detectChips1(sys_spi);
  51. if (!chip_n) {
  52. applog(LOG_WARNING, "No Bitfury chips detected!");
  53. return 0;
  54. } else {
  55. applog(LOG_WARNING, "BITFURY: %d chips detected!", chip_n);
  56. }
  57. bitfury_info->procs = chip_n;
  58. add_cgpu(bitfury_info);
  59. return 1;
  60. }
  61. static void bitfury_detect(void)
  62. {
  63. noserial_detect_manual(&bitfury_drv, bitfury_autodetect);
  64. }
  65. static
  66. bool bitfury_change_osc6_bits(struct thr_info *thr, int multiplier)
  67. {
  68. struct cgpu_info * const cgpu = thr->cgpu;
  69. struct bitfury_device * const bitfury = cgpu->device_data;
  70. uint8_t old_bits = bitfury->osc6_bits;
  71. bitfury->osc6_bits = multiplier;
  72. send_reinit(bitfury->spi, bitfury->slot, bitfury->fasync, bitfury->osc6_bits);
  73. bitfury->dclk.freqM = multiplier;
  74. dclk_msg_freqchange(cgpu->proc_repr, old_bits, bitfury->osc6_bits, NULL);
  75. return true;
  76. }
  77. void *bitfury_just_io(struct bitfury_device * const bitfury)
  78. {
  79. struct spi_port * const spi = bitfury->spi;
  80. const int chip = bitfury->fasync;
  81. spi_clear_buf(spi);
  82. spi_emit_break(spi);
  83. spi_emit_fasync(spi, chip);
  84. spi_emit_data(spi, 0x3000, &bitfury->atrvec[0], 19 * 4);
  85. spi_txrx(spi);
  86. return spi_getrxbuf(spi) + 4 + chip;
  87. }
  88. static
  89. void bitfury_debug_nonce_array(const struct cgpu_info * const proc, const char *msg, const uint32_t * const inp)
  90. {
  91. const struct bitfury_device * const bitfury = proc->device_data;
  92. const int active = bitfury->active;
  93. char s[((1 + 8) * 0x10) + 1];
  94. char *sp = s;
  95. for (int i = 0; i < 0x10; ++i)
  96. sp += sprintf(sp, "%c%08lx",
  97. (active == i) ? '>' : ' ',
  98. (unsigned long)bitfury_decnonce(inp[i]));
  99. applog(LOG_DEBUG, "%"PRIpreprv": %s%s (job=%08lx)",
  100. proc->proc_repr, msg, s, (unsigned long)inp[0x10]);
  101. }
  102. void bitfury_init_dclk(struct cgpu_info * const proc, uint8_t def, uint8_t max)
  103. {
  104. struct bitfury_device * const bitfury = proc->device_data;
  105. dclk_prepare(&bitfury->dclk);
  106. bitfury->dclk.freqMDefault = def;
  107. bitfury->dclk.freqM = bitfury->dclk.freqMDefault;
  108. bitfury_change_osc6_bits(proc->thr[0], bitfury->dclk.freqM);
  109. bitfury->dclk.freqMaxM = max;
  110. }
  111. bool bitfury_init_oldbuf(struct cgpu_info * const proc)
  112. {
  113. struct bitfury_device * const bitfury = proc->device_data;
  114. uint32_t * const oldbuf = &bitfury->oldbuf[0];
  115. uint32_t * const buf = &bitfury->newbuf[0];
  116. const uint32_t *inp;
  117. int i, differ, tried = 0;
  118. inp = bitfury_just_io(bitfury);
  119. tryagain:
  120. if (tried > 3)
  121. {
  122. applog(LOG_ERR, "%"PRIpreprv": %s: Giving up after %d tries",
  123. proc->proc_repr, __func__, tried);
  124. return false;
  125. }
  126. ++tried;
  127. memcpy(buf, inp, 0x10 * 4);
  128. inp = bitfury_just_io(bitfury);
  129. differ = -1;
  130. for (i = 0; i < 0x10; ++i)
  131. {
  132. if (inp[i] != buf[i])
  133. {
  134. if (differ != -1)
  135. {
  136. applog(LOG_DEBUG, "%"PRIpreprv": %s: Second differ at %d; trying again",
  137. proc->proc_repr, __func__, i);
  138. goto tryagain;
  139. }
  140. differ = i;
  141. applog(LOG_DEBUG, "%"PRIpreprv": %s: Differ at %d",
  142. proc->proc_repr, __func__, i);
  143. }
  144. }
  145. if (-1 == differ)
  146. {
  147. applog(LOG_DEBUG, "%"PRIpreprv": %s: No differ found; trying again",
  148. proc->proc_repr, __func__);
  149. goto tryagain;
  150. }
  151. bitfury->active = differ;
  152. memcpy(&oldbuf[0], &inp[bitfury->active], 4 * (0x10 - bitfury->active));
  153. memcpy(&oldbuf[0x10 - bitfury->active], &inp[0], 4 * bitfury->active);
  154. bitfury->oldjob = inp[0x10];
  155. if (opt_debug)
  156. bitfury_debug_nonce_array(proc, "Init", inp);
  157. return true;
  158. }
  159. static
  160. bool bitfury_init(struct thr_info *thr)
  161. {
  162. struct cgpu_info *proc;
  163. struct bitfury_device *bitfury;
  164. for (proc = thr->cgpu; proc; proc = proc->next_proc)
  165. {
  166. bitfury = proc->device_data = malloc(sizeof(struct bitfury_device));
  167. *bitfury = (struct bitfury_device){
  168. .spi = sys_spi,
  169. .fasync = proc->proc_id,
  170. };
  171. bitfury_init_oldbuf(proc);
  172. }
  173. return true;
  174. }
  175. static
  176. bool bitfury_queue_full(struct cgpu_info *cgpu)
  177. {
  178. struct cgpu_info *proc;
  179. struct bitfury_device *bitfury;
  180. for (proc = cgpu; proc; proc = proc->next_proc)
  181. {
  182. bitfury = proc->device_data;
  183. if (bitfury->work)
  184. continue;
  185. bitfury->work = get_queued(cgpu);
  186. if (!bitfury->work)
  187. return false;
  188. work_to_payload(&bitfury->payload, bitfury->work);
  189. }
  190. return true;
  191. }
  192. int64_t bitfury_scanHash(struct thr_info *thr)
  193. {
  194. struct cgpu_info * const cgpu = thr->cgpu;
  195. struct bitfury_device * const sds = cgpu->device_data;
  196. struct cgpu_info *proc;
  197. struct thr_info *pthr;
  198. struct bitfury_device *bitfury;
  199. struct timeval now;
  200. char line[LINE_LEN];
  201. int short_stat = 10;
  202. int long_stat = 1800;
  203. int i;
  204. if (!bitfury_queue_full(cgpu))
  205. return 0;
  206. for (proc = cgpu; proc; proc = proc->next_proc)
  207. {
  208. const int chip = proc->proc_id;
  209. pthr = proc->thr[0];
  210. bitfury = proc->device_data;
  211. bitfury->job_switched = 0;
  212. payload_to_atrvec(bitfury->atrvec, &bitfury->payload);
  213. libbitfury_sendHashData1(chip, bitfury, pthr);
  214. }
  215. cgsleep_ms(5);
  216. cgtime(&now);
  217. for (proc = cgpu; proc; proc = proc->next_proc)
  218. {
  219. pthr = proc->thr[0];
  220. bitfury = proc->device_data;
  221. if (bitfury->job_switched) {
  222. int i,j;
  223. unsigned int * const res = bitfury->results;
  224. struct work * const work = bitfury->work;
  225. struct work * const owork = bitfury->owork;
  226. struct work * const o2work = bitfury->o2work;
  227. i = bitfury->results_n;
  228. for (j = i - 1; j >= 0; j--) {
  229. if (owork) {
  230. submit_nonce(pthr, owork, bswap_32(res[j]));
  231. bitfury->stat_ts[bitfury->stat_counter++] =
  232. now.tv_sec;
  233. if (bitfury->stat_counter == BITFURY_STAT_N) {
  234. bitfury->stat_counter = 0;
  235. }
  236. }
  237. if (o2work) {
  238. // TEST
  239. //submit_nonce(pthr, owork, bswap_32(res[j]));
  240. }
  241. }
  242. bitfury->results_n = 0;
  243. bitfury->job_switched = 0;
  244. if (bitfury->old_nonce && o2work) {
  245. submit_nonce(pthr, o2work, bswap_32(bitfury->old_nonce));
  246. i++;
  247. }
  248. if (bitfury->future_nonce) {
  249. submit_nonce(pthr, work, bswap_32(bitfury->future_nonce));
  250. i++;
  251. }
  252. if (o2work)
  253. work_completed(cgpu, o2work);
  254. bitfury->o2work = bitfury->owork;
  255. bitfury->owork = bitfury->work;
  256. bitfury->work = NULL;
  257. hashes_done2(pthr, 0xbd000000, NULL);
  258. }
  259. }
  260. if (now.tv_sec - sds->short_out_t > short_stat) {
  261. int shares_first = 0, shares_last = 0, shares_total = 0;
  262. char stat_lines[32][LINE_LEN] = {{0}};
  263. int len, k;
  264. double gh[32][8] = {{0}};
  265. double ghsum = 0, gh1h = 0, gh2h = 0;
  266. unsigned strange_counter = 0;
  267. for (proc = cgpu; proc; proc = proc->next_proc)
  268. {
  269. const int chip = proc->proc_id;
  270. bitfury = proc->device_data;
  271. int shares_found = calc_stat(bitfury->stat_ts, short_stat, now);
  272. double ghash;
  273. len = strlen(stat_lines[bitfury->slot]);
  274. ghash = shares_to_ghashes(shares_found, short_stat);
  275. gh[bitfury->slot][chip & 0x07] = ghash;
  276. snprintf(stat_lines[bitfury->slot] + len, LINE_LEN - len, "%.1f-%3.0f ", ghash, bitfury->mhz);
  277. if(sds->short_out_t && ghash < 0.5) {
  278. applog(LOG_WARNING, "Chip_id %d FREQ CHANGE", chip);
  279. send_freq(bitfury->spi, bitfury->slot, bitfury->fasync, bitfury->osc6_bits - 1);
  280. cgsleep_ms(1);
  281. send_freq(bitfury->spi, bitfury->slot, bitfury->fasync, bitfury->osc6_bits);
  282. }
  283. shares_total += shares_found;
  284. shares_first += chip < 4 ? shares_found : 0;
  285. shares_last += chip > 3 ? shares_found : 0;
  286. strange_counter += bitfury->strange_counter;
  287. bitfury->strange_counter = 0;
  288. }
  289. sprintf(line, "vvvvwww SHORT stat %ds: wwwvvvv", short_stat);
  290. applog(LOG_WARNING, "%s", line);
  291. sprintf(line, "stranges: %u", strange_counter);
  292. applog(LOG_WARNING, "%s", line);
  293. for(i = 0; i < 32; i++)
  294. if(strlen(stat_lines[i])) {
  295. len = strlen(stat_lines[i]);
  296. ghsum = 0;
  297. gh1h = 0;
  298. gh2h = 0;
  299. for(k = 0; k < 4; k++) {
  300. gh1h += gh[i][k];
  301. gh2h += gh[i][k+4];
  302. ghsum += gh[i][k] + gh[i][k+4];
  303. }
  304. snprintf(stat_lines[i] + len, LINE_LEN - len, "- %2.1f + %2.1f = %2.1f slot %i ", gh1h, gh2h, ghsum, i);
  305. applog(LOG_WARNING, "%s", stat_lines[i]);
  306. }
  307. sds->short_out_t = now.tv_sec;
  308. }
  309. if (now.tv_sec - sds->long_out_t > long_stat) {
  310. int shares_first = 0, shares_last = 0, shares_total = 0;
  311. char stat_lines[32][LINE_LEN] = {{0}};
  312. int len, k;
  313. double gh[32][8] = {{0}};
  314. double ghsum = 0, gh1h = 0, gh2h = 0;
  315. for (proc = cgpu; proc; proc = proc->next_proc)
  316. {
  317. const int chip = proc->proc_id;
  318. bitfury = proc->device_data;
  319. int shares_found = calc_stat(bitfury->stat_ts, long_stat, now);
  320. double ghash;
  321. len = strlen(stat_lines[bitfury->slot]);
  322. ghash = shares_to_ghashes(shares_found, long_stat);
  323. gh[bitfury->slot][chip & 0x07] = ghash;
  324. snprintf(stat_lines[bitfury->slot] + len, LINE_LEN - len, "%.1f-%3.0f ", ghash, bitfury->mhz);
  325. shares_total += shares_found;
  326. shares_first += chip < 4 ? shares_found : 0;
  327. shares_last += chip > 3 ? shares_found : 0;
  328. }
  329. sprintf(line, "!!!_________ LONG stat %ds: ___________!!!", long_stat);
  330. applog(LOG_WARNING, "%s", line);
  331. for(i = 0; i < 32; i++)
  332. if(strlen(stat_lines[i])) {
  333. len = strlen(stat_lines[i]);
  334. ghsum = 0;
  335. gh1h = 0;
  336. gh2h = 0;
  337. for(k = 0; k < 4; k++) {
  338. gh1h += gh[i][k];
  339. gh2h += gh[i][k+4];
  340. ghsum += gh[i][k] + gh[i][k+4];
  341. }
  342. snprintf(stat_lines[i] + len, LINE_LEN - len, "- %2.1f + %2.1f = %2.1f slot %i ", gh1h, gh2h, ghsum, i);
  343. applog(LOG_WARNING, "%s", stat_lines[i]);
  344. }
  345. sds->long_out_t = now.tv_sec;
  346. }
  347. return 0;
  348. }
  349. double shares_to_ghashes(int shares, int seconds) {
  350. return (double)shares / (double)seconds * 4.84387; //orig: 4.77628
  351. }
  352. int calc_stat(time_t * stat_ts, time_t stat, struct timeval now) {
  353. int j;
  354. int shares_found = 0;
  355. for(j = 0; j < BITFURY_STAT_N; j++) {
  356. if (now.tv_sec - stat_ts[j] < stat) {
  357. shares_found++;
  358. }
  359. }
  360. return shares_found;
  361. }
  362. bool bitfury_prepare(struct thr_info *thr)
  363. {
  364. struct cgpu_info *cgpu = thr->cgpu;
  365. get_now_datestamp(cgpu->init, sizeof(cgpu->init));
  366. applog(LOG_INFO, "INFO bitfury_prepare");
  367. return true;
  368. }
  369. void bitfury_shutdown(struct thr_info *thr) {
  370. struct cgpu_info *cgpu = thr->cgpu, *proc;
  371. struct bitfury_device *bitfury;
  372. applog(LOG_INFO, "INFO bitfury_shutdown");
  373. for (proc = cgpu; proc; proc = proc->next_proc)
  374. {
  375. bitfury = proc->device_data;
  376. send_shutdown(bitfury->spi, bitfury->slot, bitfury->fasync);
  377. }
  378. }
  379. bool bitfury_job_prepare(struct thr_info *thr, struct work *work, __maybe_unused uint64_t max_nonce)
  380. {
  381. struct cgpu_info * const proc = thr->cgpu;
  382. struct bitfury_device * const bitfury = proc->device_data;
  383. if (opt_debug)
  384. {
  385. char hex[153];
  386. bin2hex(hex, &work->data[0], 76);
  387. applog(LOG_DEBUG, "%"PRIpreprv": Preparing work %s",
  388. proc->proc_repr, hex);
  389. }
  390. work_to_payload(&bitfury->payload, work);
  391. payload_to_atrvec(bitfury->atrvec, &bitfury->payload);
  392. work->blk.nonce = 0xffffffff;
  393. return true;
  394. }
  395. static
  396. bool fudge_nonce(struct work * const work, uint32_t *nonce_p) {
  397. static const uint32_t offsets[] = {0, 0xffc00000, 0xff800000, 0x02800000, 0x02C00000, 0x00400000};
  398. uint32_t nonce;
  399. int i;
  400. if (unlikely(!work))
  401. return false;
  402. for (i = 0; i < 6; ++i)
  403. {
  404. nonce = *nonce_p + offsets[i];
  405. if (test_nonce(work, nonce, false))
  406. {
  407. *nonce_p = nonce;
  408. return true;
  409. }
  410. }
  411. return false;
  412. }
  413. void bitfury_do_io(struct thr_info *thr)
  414. {
  415. struct cgpu_info * const proc = thr->cgpu;
  416. struct bitfury_device * const bitfury = proc->device_data;
  417. const uint32_t *inp;
  418. uint32_t * const newbuf = &bitfury->newbuf[0];
  419. uint32_t * const oldbuf = &bitfury->oldbuf[0];
  420. int n, i;
  421. bool newjob;
  422. uint32_t nonce;
  423. inp = bitfury_just_io(bitfury);
  424. if (opt_debug)
  425. bitfury_debug_nonce_array(proc, "Read", inp);
  426. // To avoid dealing with wrap-around entirely, we rotate array so previous active uint32_t is at index 0
  427. memcpy(&newbuf[0], &inp[bitfury->active], 4 * (0x10 - bitfury->active));
  428. memcpy(&newbuf[0x10 - bitfury->active], &inp[0], 4 * bitfury->active);
  429. newjob = inp[0x10];
  430. if (newbuf[0xf] != oldbuf[0xf])
  431. {
  432. inc_hw_errors2(thr, NULL, NULL);
  433. applog(LOG_DEBUG, "%"PRIpreprv": Previous nonce mismatch, ignoring response",
  434. proc->proc_repr);
  435. goto out;
  436. }
  437. if (bitfury->oldjob != newjob && thr->next_work)
  438. {
  439. mt_job_transition(thr);
  440. // TODO: Delay morework until right before it's needed
  441. timer_set_now(&thr->tv_morework);
  442. job_start_complete(thr);
  443. }
  444. for (n = 0; newbuf[n] == oldbuf[n]; ++n)
  445. {
  446. if (unlikely(n >= 0xf))
  447. {
  448. inc_hw_errors2(thr, NULL, NULL);
  449. applog(LOG_DEBUG, "%"PRIpreprv": Full result match, ignoring response",
  450. proc->proc_repr);
  451. goto out;
  452. }
  453. }
  454. if (n)
  455. {
  456. for (i = 0; i < n; ++i)
  457. {
  458. nonce = bitfury_decnonce(newbuf[i]);
  459. if (fudge_nonce(thr->work, &nonce))
  460. {
  461. applog(LOG_DEBUG, "%"PRIpreprv": nonce %x = %08lx (work=%p)",
  462. proc->proc_repr, i, (unsigned long)nonce, thr->work);
  463. submit_nonce(thr, thr->work, nonce);
  464. }
  465. else
  466. if (fudge_nonce(thr->prev_work, &nonce))
  467. {
  468. applog(LOG_DEBUG, "%"PRIpreprv": nonce %x = %08lx (prev work=%p)",
  469. proc->proc_repr, i, (unsigned long)nonce, thr->prev_work);
  470. submit_nonce(thr, thr->prev_work, nonce);
  471. }
  472. else
  473. {
  474. inc_hw_errors(thr, thr->work, nonce);
  475. ++bitfury->dclk_hwe;
  476. }
  477. if (++bitfury->dclk_tot >= 0x10)
  478. {
  479. double errrate = (double)bitfury->dclk_hwe / (double)bitfury->dclk_tot;
  480. applog(LOG_DEBUG, "%"PRIpreprv": DynClock: %d of %d results were bad",
  481. proc->proc_repr, bitfury->dclk_hwe, bitfury->dclk_tot);
  482. dclk_gotNonces(&bitfury->dclk);
  483. dclk_errorCount(&bitfury->dclk, errrate);
  484. dclk_preUpdate(&bitfury->dclk);
  485. dclk_updateFreq(&bitfury->dclk, bitfury_change_osc6_bits, thr);
  486. bitfury->dclk_tot = bitfury->dclk_hwe = 0;
  487. }
  488. }
  489. bitfury->active = (bitfury->active + n) % 0x10;
  490. }
  491. memcpy(&oldbuf[0], &newbuf[n], 4 * (0x10 - n));
  492. memcpy(&oldbuf[0x10 - n], &newbuf[0], 4 * n);
  493. bitfury->oldjob = newjob;
  494. out:
  495. timer_set_delay_from_now(&thr->tv_poll, 10000);
  496. }
  497. int64_t bitfury_job_process_results(struct thr_info *thr, struct work *work, bool stopping)
  498. {
  499. if (unlikely(stopping))
  500. timer_unset(&thr->tv_poll);
  501. // Bitfury chips process only 768/1024 of the nonce range
  502. return 0xbd000000;
  503. }
  504. struct device_drv bitfury_drv = {
  505. .dname = "bitfury_gpio",
  506. .name = "BFY",
  507. .drv_detect = bitfury_detect,
  508. .thread_prepare = bitfury_prepare,
  509. .thread_init = bitfury_init,
  510. .queue_full = bitfury_queue_full,
  511. .scanwork = bitfury_scanHash,
  512. .thread_shutdown = bitfury_shutdown,
  513. .minerloop = hash_queued_work,
  514. };