driver-alchemist.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. /*
  2. * Copyright 2015-2016 John Stefanopoulos
  3. * Copyright 2014-2015 Luke Dashjr
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License as published by the Free
  7. * Software Foundation; either version 3 of the License, or (at your option)
  8. * any later version. See COPYING for more details.
  9. */
  10. // THIS DRIVER REQUIRES THE LATEST FIRMWARE FOR AlCHEMINERS DEVELOPED BY JSTEFANOP
  11. // IT WILL NOT WORK WITH THE STOCK FACTORY FIRMWARE ON THE BOARDS
  12. // PLEASE CONTACT JSTEFANOP AT MAC DOT COM OR JSTEFANOP ON LITECOINTALK DOT ORG FOR MORE INFO
  13. #include "config.h"
  14. #include <stdbool.h>
  15. #include <stdint.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <unistd.h>
  19. #include <stdio.h>
  20. #include <fcntl.h>
  21. #include "deviceapi.h"
  22. #include "logging.h"
  23. #include "lowlevel.h"
  24. #include "lowl-vcom.h"
  25. #include "util.h"
  26. static const uint8_t alchemist_max_chips = 0x20;
  27. #define ALCHEMIST_DEFAULT_FREQUENCY 352
  28. #define ALCHEMIST_MIN_CLOCK 200
  29. #define ALCHEMIST_MAX_CLOCK 400
  30. // Number of seconds full board of 1728 cores @ 352mhz takes to scan full range
  31. #define ALCHEMIST_HASH_SPEED 134.0
  32. #define ALCHEMIST_MAX_NONCE 0xffffffff
  33. #define ALCHEMIST_READ_SIZE 9
  34. #define alchemist_max_clusters_per_chip 6
  35. #define alchemist_max_cores_per_cluster 9
  36. static const uint8_t alchemist_g_head[] = {
  37. 0xd4, 0x59, 0x2d, 0x01, 0x1d, 0x01, 0x8e, 0xa7, 0x4e, 0xbb, 0x17, 0xb8, 0x06, 0x6b, 0x2a, 0x75,
  38. 0x83, 0x99, 0xd5, 0xf1, 0x9b, 0x5c, 0x60, 0x73, 0xd0, 0x9b, 0x50, 0x0d, 0x92, 0x59, 0x82, 0xad,
  39. 0xc4, 0xb3, 0xed, 0xd3, 0x52, 0xef, 0xe1, 0x46, 0x67, 0xa8, 0xca, 0x9f, 0x27, 0x9f, 0x63, 0x30,
  40. 0xcc, 0xbb, 0xb9, 0x10, 0x3b, 0x9e, 0x3a, 0x53, 0x50, 0x76, 0x50, 0x52, 0x08, 0x1d, 0xdb, 0xae,
  41. 0x89, 0x8f, 0x1e, 0xf6, 0xb8, 0xc6, 0x4f, 0x3b, 0xce, 0xf7, 0x15, 0xf6, 0, 0, 0, 1,
  42. 0, 0, 0, 1, 0x8e, 0xa7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  43. 0, 0, 0, 0, 0, 0, 0
  44. };
  45. BFG_REGISTER_DRIVER(alchemist_drv)
  46. static const struct bfg_set_device_definition alchemist_set_device_funcs_probe[];
  47. struct alchemist_chip {
  48. uint8_t chipid;
  49. uint8_t global_reg[8];
  50. uint16_t chip_mask[alchemist_max_clusters_per_chip];
  51. uint32_t clst_offset[alchemist_max_clusters_per_chip];
  52. unsigned active_cores;
  53. unsigned freq;
  54. unsigned reset_mode;
  55. };
  56. static
  57. void alchemist_chip_init(struct alchemist_chip * const chip, const uint8_t chipid)
  58. {
  59. *chip = (struct alchemist_chip){
  60. .chipid = chipid,
  61. .global_reg = {0, 4, 0x40, 0, 0, 0, 0, 1},
  62. .chip_mask = {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
  63. .clst_offset = {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
  64. .active_cores = 1728,
  65. .freq = ALCHEMIST_DEFAULT_FREQUENCY,
  66. .reset_mode = 0,
  67. };
  68. }
  69. static
  70. void alchemist_reset_board(const char * const devpath, struct alchemist_chip * const chip, const int fd)
  71. {
  72. if (chip->reset_mode == 0) {
  73. char gpio[8];
  74. int fd;
  75. char buf[50];
  76. // TODO: allow custom reset pin through --set for non-stock controller
  77. if (strcmp(devpath, "/dev/ttyO1") == 0)
  78. strcpy(gpio, "gpio117");
  79. else if (strcmp(devpath, "/dev/ttyO2") == 0)
  80. strcpy(gpio, "gpio110");
  81. else if (strcmp(devpath, "/dev/ttyO3") == 0)
  82. strcpy(gpio, "gpio111");
  83. else if (strcmp(devpath, "/dev/ttyO4") == 0)
  84. strcpy(gpio, "gpio112");
  85. else if (strcmp(devpath, "/dev/ttyUSB0") == 0)
  86. strcpy(gpio, "gpio113");
  87. else if (strcmp(devpath, "/dev/ttyUSB1") == 0)
  88. strcpy(gpio, "gpio114");
  89. else if (strcmp(devpath, "/dev/ttyUSB2") == 0)
  90. strcpy(gpio, "gpio115");
  91. else if (strcmp(devpath, "/dev/ttyUSB3") == 0)
  92. strcpy(gpio, "gpio116");
  93. else if (strcmp(devpath, "/dev/ttyAMA0") == 0)
  94. strcpy(gpio, "gpio25");
  95. else
  96. return;
  97. sprintf(buf, "/sys/class/gpio/%s/value", gpio);
  98. fd = open(buf, O_WRONLY);
  99. if (write(fd, "0", 1) != 1)
  100. applog(LOG_DEBUG, "%s: %s %s", alchemist_drv.dname, "GPIO write error", devpath);
  101. cgsleep_ms(100);
  102. if (write(fd, "1", 1) != 1)
  103. applog(LOG_DEBUG, "%s: %s %s", alchemist_drv.dname, "GPIO write error", devpath);
  104. close(fd);
  105. } else {
  106. applog(LOG_DEBUG, "START IOCTL RTS RESET");
  107. if (set_serial_rts(fd, BGV_HIGH) == BGV_ERROR) {
  108. applog(LOG_DEBUG, "IOCTL RTS RESET FAILED");
  109. }
  110. if (set_serial_dtr(fd, BGV_HIGH) == BGV_ERROR) {
  111. applog(LOG_DEBUG, "IOCTL DTR RESET FAILED");
  112. }
  113. cgsleep_ms(100);
  114. if (set_serial_rts(fd, BGV_LOW) == BGV_ERROR) {
  115. applog(LOG_DEBUG, "IOCTL RTS RESET FAILED");
  116. }
  117. if (set_serial_dtr(fd, BGV_LOW) == BGV_ERROR) {
  118. applog(LOG_DEBUG, "IOCTL DTR RESET FAILED");
  119. }
  120. }
  121. }
  122. static
  123. void alchemist_set_diag_mode(struct alchemist_chip * const chip, bool diag_enable)
  124. {
  125. if (diag_enable)
  126. chip->global_reg[1] |= 1;
  127. else
  128. chip->global_reg[1] &= ~1;
  129. }
  130. static
  131. bool alchemist_write_global_reg(const int fd, const struct alchemist_chip * const chip)
  132. {
  133. uint8_t buf[113];
  134. memset(&buf, 0, 102);
  135. memcpy(&buf[102], &chip->global_reg[0], 8);
  136. buf[110] = 0;
  137. buf[111] = 0xff;
  138. buf[112] = chip->chipid;
  139. //char output[(sizeof(chip->global_reg) * 2) + 1];
  140. //bin2hex(output, chip->global_reg, sizeof(chip->global_reg));
  141. //applog(LOG_DEBUG, "GLOBAL REG %s", output);
  142. if (write(fd, buf, sizeof(buf)) != sizeof(buf))
  143. return false;
  144. return true;
  145. }
  146. static
  147. bool alchemist_write_cluster_reg(const int fd, const struct alchemist_chip * const chip, const uint16_t cores_active, const uint32_t offset, const uint8_t clstid)
  148. {
  149. uint8_t buf[113];
  150. memset(&buf, 0, 104);
  151. pk_u16be(buf, 104, cores_active);
  152. pk_u32be(buf, 106, offset);
  153. buf[110] = clstid;
  154. buf[111] = 0xfe;
  155. buf[112] = chip->chipid;
  156. //applog(LOG_DEBUG, " %u: %u: %u : %u", buf[106], buf[107], buf[108], buf[109]);
  157. if (write(fd, buf, sizeof(buf)) != sizeof(buf))
  158. return false;
  159. return true;
  160. }
  161. static
  162. bool alchemist_init_pll(const int fd, struct alchemist_chip * const chip)
  163. {
  164. unsigned freq = chip->freq;
  165. uint8_t divider = (freq - 16)/16;
  166. divider <<= 1;
  167. uint8_t bytes1 = 0x60 | ((divider & 0xf0) >> 4);
  168. uint8_t bytes2 = 0x20 | ((divider & 0xf0) >> 4);
  169. uint8_t bytes3 = 0x00 | ((divider & 0x0f) << 4);
  170. pk_u16be(chip->global_reg, 2, 0x4000);
  171. chip->global_reg[1] |= 0xc;
  172. if (!alchemist_write_global_reg(fd, chip))
  173. return false;
  174. chip->global_reg[2] = bytes1;
  175. chip->global_reg[3] = bytes3;
  176. cgsleep_ms(20);
  177. if (!alchemist_write_global_reg(fd, chip))
  178. return false;
  179. chip->global_reg[2] = bytes2;
  180. chip->global_reg[1] &= ~8;
  181. cgsleep_ms(20);
  182. if (!alchemist_write_global_reg(fd, chip))
  183. return false;
  184. chip->global_reg[1] &= ~4;
  185. cgsleep_ms(20);
  186. if (!alchemist_write_global_reg(fd, chip))
  187. return false;
  188. return true;
  189. }
  190. static
  191. bool alchemist_send_golden(const int fd, const struct alchemist_chip * const chip, const bool diag, const void * const data, const void * const target_p)
  192. {
  193. uint8_t buf[113];
  194. const uint8_t * const target = target_p;
  195. memcpy(buf, data, 80);
  196. if (target && !target[0x1f])
  197. memcpy(&buf[80], target, 0x20);
  198. else
  199. {
  200. memset(&buf[80], 0xff, 0x1f);
  201. buf[111] = 0;
  202. }
  203. buf[112] = chip->chipid;
  204. if (diag)
  205. buf[112] |= 0x80;
  206. if (write(fd, buf, sizeof(buf)) != sizeof(buf))
  207. return false;
  208. return true;
  209. }
  210. static
  211. bool alchemist_send_work(const struct thr_info * const thr, struct work * const work)
  212. {
  213. struct cgpu_info *device = thr->cgpu;
  214. uint8_t buf[113];
  215. uint8_t cmd[113];
  216. const uint8_t * const target = work->target;
  217. unsigned char swpdata[80];
  218. buf[0] = 0xff;
  219. memset(&buf[1], 0, 0x18);
  220. memcpy(&buf[25], &target[24], 0x8);
  221. //pk_u64be(buf, 25, 0x0000feff01000000);
  222. swap32tobe(swpdata, work->data, 80/4);
  223. memcpy(&buf[33], swpdata, 80);
  224. for (int i = 0; i<113; i++) {
  225. cmd[i] = buf[112 - i];
  226. }
  227. //char output[(sizeof(cmd) * 2) + 1];
  228. //bin2hex(output, cmd, sizeof(cmd));
  229. //applog(LOG_DEBUG, "OUTPUT %s", output);
  230. if (write(device->device_fd, cmd, sizeof(cmd)) != sizeof(cmd))
  231. return false;
  232. work->blk.nonce = ALCHEMIST_MAX_NONCE;
  233. return true;
  234. }
  235. static
  236. bool alchemist_detect_one(const char * const devpath)
  237. {
  238. struct alchemist_chip *chips = NULL;
  239. const int fd = serial_open(devpath, 115200, 1, true);
  240. if (fd < 0)
  241. return_via_applog(err, , LOG_DEBUG, "%s: %s %s", alchemist_drv.dname, "Failed to open", devpath);
  242. applog(LOG_DEBUG, "%s: %s %s", alchemist_drv.dname, "Successfully opened", devpath);
  243. // Init chips, setup PLL, and scan for good cores
  244. chips = malloc(alchemist_max_chips * sizeof(*chips));
  245. struct alchemist_chip * const dummy_chip = &chips[0];
  246. alchemist_chip_init(dummy_chip, 0);
  247. // pick up any user-defined settings passed in via --set
  248. drv_set_defaults(&alchemist_drv, alchemist_set_device_funcs_probe, dummy_chip, devpath, detectone_meta_info.serial, 1);
  249. unsigned freq = dummy_chip->freq;
  250. unsigned mode = dummy_chip->reset_mode;
  251. unsigned total_cores = 0;
  252. alchemist_reset_board(devpath, dummy_chip, fd);
  253. {
  254. uint8_t buf[9];
  255. for (unsigned i = 0; i < alchemist_max_chips; ++i)
  256. {
  257. struct alchemist_chip * const chip = &chips[i];
  258. alchemist_chip_init(chip, i);
  259. chip->freq = freq;
  260. chip->reset_mode = mode;
  261. alchemist_set_diag_mode(chip, true);
  262. if (!alchemist_init_pll(fd, chip))
  263. return_via_applog(err, , LOG_DEBUG, "%s: Failed to (%s) %s", alchemist_drv.dname, "init PLL", devpath);
  264. if (!alchemist_send_golden(fd, chip, true, alchemist_g_head, NULL))
  265. return_via_applog(err, , LOG_DEBUG, "%s: Failed to (%s) %s", alchemist_drv.dname, "send scan job", devpath);
  266. while (serial_read(fd, buf, 9) == 9)
  267. {
  268. const uint8_t chipid = buf[8];
  269. if (chipid >= alchemist_max_chips)
  270. applog(LOG_DEBUG, "%s: Bad %s id (%u) during scan of %s chip %u", alchemist_drv.dname, "chip", chipid, devpath, i);
  271. const uint8_t clsid = buf[7];
  272. if (clsid >= alchemist_max_clusters_per_chip)
  273. applog(LOG_DEBUG, "%s: Bad %s id (%u) during scan of %s chip %u", alchemist_drv.dname, "cluster", clsid, devpath, i);
  274. const uint8_t coreid = buf[6];
  275. if (coreid >= alchemist_max_cores_per_cluster)
  276. applog(LOG_DEBUG, "%s: Bad %s id (%u) during scan of %s chip %u", alchemist_drv.dname, "core", coreid, devpath, i);
  277. if (buf[0] != 0xd9 || buf[1] != 0xeb || buf[2] != 0x86 || buf[3] != 0x63) {
  278. //chips[i].chip_good[clsid][coreid] = false;
  279. applog(LOG_DEBUG, "%s: Bad %s at core (%u) during scan of %s chip %u cluster %u", alchemist_drv.dname, "nonce", coreid, devpath, i, clsid);
  280. } else {
  281. ++total_cores;
  282. chips[i].chip_mask[clsid] |= (1 << coreid);
  283. }
  284. }
  285. }
  286. }
  287. applog(LOG_DEBUG, "%s: Identified %d cores on %s", alchemist_drv.dname, total_cores, devpath);
  288. if (!total_cores)
  289. goto err;
  290. alchemist_reset_board(devpath, dummy_chip, fd);
  291. // config nonce ranges per cluster based on core responses
  292. unsigned mutiple = ALCHEMIST_MAX_NONCE / total_cores;
  293. uint32_t n_offset = 0x00000000;
  294. for (unsigned i = 0; i < alchemist_max_chips; ++i)
  295. {
  296. struct alchemist_chip * const chip = &chips[i];
  297. chips[i].active_cores = total_cores;
  298. alchemist_set_diag_mode(chip, false);
  299. if (!alchemist_init_pll(fd, chip))
  300. return_via_applog(err, , LOG_DEBUG, "%s: Failed to (%s) %s", alchemist_drv.dname, "init PLL", devpath);
  301. cgsleep_ms(10);
  302. for (unsigned x = 0; x < alchemist_max_clusters_per_chip; ++x) {
  303. unsigned gc = 0;
  304. uint16_t core_mask = chips[i].chip_mask[x];
  305. chips[i].clst_offset[x] = n_offset;
  306. //applog(LOG_DEBUG, "OFFSET %u CHIP %u CLUSTER %u", n_offset, i, x);
  307. if (!alchemist_write_cluster_reg(fd, chip, core_mask, n_offset, x))
  308. return_via_applog(err, , LOG_DEBUG, "%s: Failed to (%s) %s", alchemist_drv.dname, "send config register", devpath);
  309. for (unsigned z = 0; z < 15; ++z) {
  310. if (core_mask & 0x0001)
  311. gc += 1;
  312. core_mask >>= 1;
  313. }
  314. n_offset += mutiple * gc;
  315. }
  316. }
  317. if (serial_claim_v(devpath, &alchemist_drv))
  318. goto err;
  319. //serial_close(fd);
  320. struct cgpu_info * const cgpu = malloc(sizeof(*cgpu));
  321. *cgpu = (struct cgpu_info){
  322. .drv = &alchemist_drv,
  323. .device_path = strdup(devpath),
  324. .deven = DEV_ENABLED,
  325. .procs = 1,
  326. .threads = 1,
  327. .device_data = chips,
  328. };
  329. // NOTE: Xcode's clang has a bug where it cannot find fields inside anonymous unions (more details in fpgautils)
  330. cgpu->device_fd = fd;
  331. return add_cgpu(cgpu);
  332. err:
  333. if (fd >= 0)
  334. serial_close(fd);
  335. free(chips);
  336. return false;
  337. }
  338. /*
  339. * scanhash mining loop
  340. */
  341. static
  342. void alchemist_submit_nonce(struct thr_info * const thr, const uint8_t buf[9], struct work * const work)
  343. {
  344. struct cgpu_info *device = thr->cgpu;
  345. struct alchemist_chip *chips = device->device_data;
  346. uint32_t nonce = *(uint32_t *)buf;
  347. nonce = bswap_32(nonce);
  348. submit_nonce(thr, work, nonce);
  349. // hashrate calc
  350. const uint8_t chipid = buf[8];
  351. const uint8_t clstid = buf[7];
  352. uint32_t range = chips[chipid].clst_offset[clstid];
  353. uint32_t mutiple = ALCHEMIST_MAX_NONCE / chips[chipid].active_cores;
  354. double diff_mutiple = .5/work->work_difficulty;
  355. for (unsigned x = 0; x < alchemist_max_cores_per_cluster; ++x) {
  356. if (nonce > range && nonce < (range + mutiple)) {
  357. uint64_t hashes = (nonce - range) * chips[chipid].active_cores * diff_mutiple;
  358. if (hashes > ALCHEMIST_MAX_NONCE)
  359. hashes = 1;
  360. hashes_done2(thr, hashes, NULL);
  361. }
  362. range += mutiple;
  363. }
  364. }
  365. // send work to the device
  366. static
  367. int64_t alchemist_scanhash(struct thr_info *thr, struct work *work, int64_t __maybe_unused max_nonce)
  368. {
  369. struct cgpu_info *device = thr->cgpu;
  370. int fd = device->device_fd;
  371. struct alchemist_chip *chips = device->device_data;
  372. struct timeval start_tv, nonce_range_tv;
  373. // amount of time it takes this device to scan a nonce range:
  374. uint32_t nonce_full_range_sec = ALCHEMIST_HASH_SPEED * 352.0 / ALCHEMIST_DEFAULT_FREQUENCY * 1728.0 / chips[0].active_cores;
  375. // timer to break out of scanning should we close in on an entire nonce range
  376. // should break out before the range is scanned, so we are doing 95% of the range
  377. uint64_t nonce_near_range_usec = (nonce_full_range_sec * 1000000. * 0.95);
  378. timer_set_delay_from_now(&nonce_range_tv, nonce_near_range_usec);
  379. // start the job
  380. timer_set_now(&start_tv);
  381. if (!alchemist_send_work(thr, work)) {
  382. applog(LOG_DEBUG, "Failed to start job");
  383. dev_error(device, REASON_DEV_COMMS_ERROR);
  384. }
  385. uint8_t buf[9];
  386. int read = 0;
  387. bool range_nearly_scanned = false;
  388. while (!thr->work_restart // true when new work is available (miner.c)
  389. && ((read = serial_read(fd, buf, 9)) >= 0) // only check for failure - allow 0 bytes
  390. && !(range_nearly_scanned = timer_passed(&nonce_range_tv, NULL))) // true when we've nearly scanned a nonce range
  391. {
  392. if (read == 0)
  393. continue;
  394. if (read == 9) {
  395. alchemist_submit_nonce(thr, buf, work);
  396. }
  397. else
  398. applog(LOG_ERR, "%"PRIpreprv": Unrecognized response", device->proc_repr);
  399. }
  400. if (read == -1)
  401. {
  402. applog(LOG_ERR, "%s: Failed to read result", device->dev_repr);
  403. dev_error(device, REASON_DEV_COMMS_ERROR);
  404. }
  405. return 0;
  406. }
  407. /*
  408. * setup & shutdown
  409. */
  410. static
  411. bool alchemist_lowl_probe(const struct lowlevel_device_info * const info)
  412. {
  413. return vcom_lowl_probe_wrapper(info, alchemist_detect_one);
  414. }
  415. static
  416. void alchemist_thread_shutdown(struct thr_info *thr)
  417. {
  418. struct cgpu_info *device = thr->cgpu;
  419. struct alchemist_chip *chips = device->device_data;
  420. alchemist_reset_board(device->device_path, &chips[0], device->device_fd);
  421. serial_close(device->device_fd);
  422. }
  423. /*
  424. * specify settings / options via RPC or command line
  425. */
  426. // support for --set
  427. // must be set before probing the device
  428. // for setting clock and chips during probe / detect
  429. static
  430. const char *alchemist_set_clock(struct cgpu_info * const device, const char * const option, const char * const setting, char * const replybuf, enum bfg_set_device_replytype * const success)
  431. {
  432. struct alchemist_chip * const chip = device->device_data;
  433. int val = atoi(setting);
  434. if (val < ALCHEMIST_MIN_CLOCK || val > ALCHEMIST_MAX_CLOCK || (val%16)) {
  435. sprintf(replybuf, "invalid clock: '%s' valid range %d-%d and a mutiple of 16",
  436. setting, ALCHEMIST_MIN_CLOCK, ALCHEMIST_MAX_CLOCK);
  437. return replybuf;
  438. } else
  439. chip->freq = val;
  440. return NULL;
  441. }
  442. static
  443. const char *alchemist_set_mode(struct cgpu_info * const device, const char * const option, const char * const setting, char * const replybuf, enum bfg_set_device_replytype * const success)
  444. {
  445. struct alchemist_chip * const chip = device->device_data;
  446. int val = atoi(setting);
  447. if (val == 1) {
  448. chip->reset_mode = val;
  449. sprintf(replybuf, "Driver mode set to raspery pi controller using USB->UART Dongles");
  450. return replybuf;
  451. }
  452. return NULL;
  453. }
  454. static
  455. const struct bfg_set_device_definition alchemist_set_device_funcs_probe[] = {
  456. { "clock", alchemist_set_clock, NULL },
  457. { "mode", alchemist_set_mode, NULL },
  458. { NULL },
  459. };
  460. struct device_drv alchemist_drv = {
  461. .dname = "alchemist",
  462. .name = "ALC",
  463. .drv_min_nonce_diff = common_scrypt_min_nonce_diff,
  464. // detect device
  465. .lowl_probe = alchemist_lowl_probe,
  466. // specify mining type - scanhash
  467. .minerloop = minerloop_scanhash,
  468. // scanhash mining hooks
  469. .scanhash = alchemist_scanhash,
  470. // teardown device
  471. .thread_shutdown = alchemist_thread_shutdown,
  472. };