driver-blockerupter.c.bak 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. #include "config.h"
  2. #include <limits.h>
  3. #include <pthread.h>
  4. #include <stdio.h>
  5. #include <sys/time.h>
  6. #include <sys/types.h>
  7. #include <dirent.h>
  8. #include <unistd.h>
  9. #include <math.h>
  10. #ifndef WIN32
  11. #include <termios.h>
  12. #include <sys/stat.h>
  13. #include <fcntl.h>
  14. #ifndef O_CLOEXEC
  15. #define O_CLOEXEC 0
  16. #endif
  17. #else
  18. #ifdef WIN32
  19. #include <windows.h>
  20. #endif
  21. #include <io.h>
  22. #endif
  23. #include "elist.h"
  24. #include "miner.h"
  25. #include "driver-blockerupter.h"
  26. #include "usbutils.h"
  27. static void blockerupter_space_mode(struct cgpu_info *blockerupter)
  28. {
  29. int interface;
  30. unsigned int bits = 0;
  31. interface = usb_interface(blockerupter);
  32. bits |= CP210X_BITS_DATA_8;
  33. bits |= CP210X_BITS_PARITY_SPACE;
  34. usb_transfer_data(blockerupter, CP210X_TYPE_OUT, CP210X_SET_LINE_CTL, bits, interface, NULL, 0, C_SETPARITY);
  35. }
  36. static void blockerupter_mark_mode(struct cgpu_info *blockerupter)
  37. {
  38. int interface;
  39. unsigned int bits = 0;
  40. interface = usb_interface(blockerupter);
  41. bits |= CP210X_BITS_DATA_8;
  42. bits |= CP210X_BITS_PARITY_MARK;
  43. usb_transfer_data(blockerupter, CP210X_TYPE_OUT, CP210X_SET_LINE_CTL, bits, interface, NULL, 0, C_SETPARITY);
  44. }
  45. static void blockerupter_init_com(struct cgpu_info *blockerupter)
  46. {
  47. uint32_t baudrate;
  48. int interface;
  49. if (blockerupter->usbinfo.nodev)
  50. return;
  51. interface = usb_interface(blockerupter);
  52. // Enable the UART
  53. usb_transfer_data(blockerupter, CP210X_TYPE_OUT, CP210X_REQUEST_IFC_ENABLE,
  54. CP210X_VALUE_UART_ENABLE, interface, NULL, 0, C_ENABLE_UART);
  55. if (blockerupter->usbinfo.nodev)
  56. return;
  57. // Set data control
  58. usb_transfer_data(blockerupter, CP210X_TYPE_OUT, CP210X_REQUEST_DATA, CP210X_VALUE_DATA,
  59. interface, NULL, 0, C_SETDATA);
  60. if (blockerupter->usbinfo.nodev)
  61. return;
  62. // Set the baud
  63. baudrate = BET_BAUD;
  64. usb_transfer_data(blockerupter, CP210X_TYPE_OUT, CP210X_REQUEST_BAUD, 0,
  65. interface, &baudrate, sizeof (baudrate), C_SETBAUD);
  66. // Set space mode
  67. blockerupter_space_mode(blockerupter);
  68. }
  69. static int blockerupter_send(struct cgpu_info *blockerupter, char *data, int len)
  70. {
  71. int err;
  72. int bytes_sent;
  73. if (unlikely(blockerupter->usbinfo.nodev))
  74. return SEND_FAIL;
  75. err = usb_write(blockerupter, data, len, &bytes_sent, C_BET_WRITE);
  76. if (err || bytes_sent != len) {
  77. applog(LOG_DEBUG, "blockerupter: Send (%d/%d)", bytes_sent, len);
  78. return SEND_FAIL;
  79. }
  80. return SEND_OK;
  81. }
  82. static int blockerupter_read(struct cgpu_info *blockerupter, char *data, int len)
  83. {
  84. int err;
  85. int bytes_read;
  86. if (unlikely(blockerupter->usbinfo.nodev))
  87. return READ_FAIL;
  88. err = usb_read_timeout(blockerupter, data, len, &bytes_read, 2, C_BET_READ);
  89. if (err || bytes_read != len) {
  90. applog(LOG_DEBUG, "blockerupter: Read (%d/%d)", bytes_read, len);
  91. return READ_FAIL;
  92. }
  93. return READ_OK;
  94. }
  95. static void blockerupter_setclock(struct cgpu_info *blockerupter, uint8_t clock)
  96. {
  97. struct blockerupter_info *info;
  98. info = blockerupter->device_data;
  99. char command;
  100. int err;
  101. command = C_GCK | clock;
  102. info->clock = clock;
  103. err = blockerupter_send(blockerupter, &command, 1);
  104. if (!err)
  105. applog(LOG_DEBUG, "%s%d: Set Clock to %d MHz", blockerupter->drv->name,
  106. blockerupter->device_id, (clock + 1) * 10 / 2);
  107. }
  108. static void blockerupter_setdiff(struct cgpu_info *blockerupter, int diff)
  109. {
  110. struct blockerupter_info *info;
  111. info = blockerupter->device_data;
  112. char command,bits;
  113. int err;
  114. int local_diff;
  115. // min_diff for driver is 64
  116. if (diff >= 262144) {
  117. bits = 3;
  118. local_diff = 262144;
  119. } else if (diff >= 4096) {
  120. bits = 2;
  121. local_diff = 4096;
  122. } else {
  123. bits = 1;
  124. local_diff = 64;
  125. }
  126. if (local_diff == info->diff)
  127. return;
  128. command = C_DIF | bits;
  129. err = blockerupter_send(blockerupter, &command, 1);
  130. if (!err) {
  131. applog(LOG_DEBUG, "%s%d: Set Diff Bits to %d", blockerupter->drv->name,
  132. blockerupter->device_id, bits);
  133. info->diff = local_diff;
  134. }
  135. }
  136. static void blockerupter_setrolling(struct cgpu_info *blockerupter, uint8_t rolling)
  137. {
  138. struct blockerupter_info *info;
  139. info = blockerupter->device_data;
  140. char command;
  141. int err;
  142. command = C_LPO | rolling;
  143. err = blockerupter_send(blockerupter, &command, 1);
  144. if (!err) {
  145. applog(LOG_DEBUG, "%s%d: Set nTime Rolling to %d seconds", blockerupter->drv->name,
  146. blockerupter->device_id, (rolling + 1) * 30);
  147. info->rolling = (rolling + 1) * 30;
  148. }
  149. }
  150. static void blockerupter_init(struct cgpu_info *blockerupter)
  151. {
  152. struct blockerupter_info *info;
  153. info = blockerupter->device_data;
  154. // Set Clock
  155. if (!opt_bet_clk || opt_bet_clk< 19 || opt_bet_clk > 31) {
  156. opt_bet_clk = BET_CLOCK_DEFAULT;
  157. }
  158. blockerupter_setclock(blockerupter, opt_bet_clk);
  159. info->clock = (opt_bet_clk + 1) * 10;
  160. info->expected = info->clock * 24 * 32 * info->found / 1000.0;
  161. // Set Diff
  162. blockerupter_setdiff(blockerupter, BET_DIFF_DEFAULT);
  163. info->diff = BET_DIFF_DEFAULT;
  164. // Set nTime Rolling
  165. blockerupter_setrolling(blockerupter, BET_ROLLING_DEFAULT);
  166. info->rolling = (BET_ROLLING_DEFAULT + 1) * 30;
  167. cgtime(&info->start_time);
  168. }
  169. static struct cgpu_info *blockerupter_detect_one(struct libusb_device *dev, struct usb_find_devices *found)
  170. {
  171. struct blockerupter_info *info;
  172. struct cgpu_info *blockerupter = usb_alloc_cgpu(&blockerupter_drv, 1);
  173. int i, err;
  174. char reset = C_RES;
  175. if (!usb_init(blockerupter, dev, found)) {
  176. applog(LOG_ERR, "Blockerupter usb init failed");
  177. blockerupter = usb_free_cgpu(blockerupter);
  178. return NULL;
  179. }
  180. blockerupter->device_data = (struct blockerupter_info *) malloc(sizeof(struct blockerupter_info));
  181. info = blockerupter->device_data;
  182. memset(info, 0, sizeof(blockerupter_info));
  183. blockerupter_init_com(blockerupter);
  184. err = blockerupter_send(blockerupter, &reset, 1);
  185. if (err) {
  186. applog(LOG_ERR, "Blockerupter detect failed");
  187. blockerupter = usb_free_cgpu(blockerupter);
  188. return NULL;
  189. }
  190. cgsleep_ms(5000);
  191. for (i = 0; i < BET_MAXBOARDS; i++) {
  192. char detect, answer;
  193. answer = 0;
  194. detect = C_ASK | (uint8_t)i;
  195. blockerupter_send(blockerupter, &detect, 1);
  196. blockerupter_read(blockerupter, &answer, 1);
  197. if (answer == A_WAL) {
  198. applog(LOG_DEBUG, "BlockErupter found Board: %d", i);
  199. info->boards[i] = 1;
  200. info->found++;
  201. } else {
  202. if (!i) {
  203. applog(LOG_DEBUG, "BlockErupter no boards found, likely not BET");
  204. break;
  205. }
  206. applog(LOG_DEBUG, "BlockErupter missing board: %d, received %02x",
  207. i, answer);
  208. }
  209. }
  210. if (!info->found) {
  211. usb_uninit(blockerupter);
  212. blockerupter = usb_free_cgpu(blockerupter);
  213. free(info);
  214. return NULL;
  215. } else {
  216. blockerupter->threads = 1;
  217. add_cgpu(blockerupter);
  218. applog(LOG_DEBUG, "Add BlockErupter with %d/%d Boards", info->found,
  219. BET_MAXBOARDS);
  220. blockerupter_init(blockerupter);
  221. return blockerupter;
  222. }
  223. }
  224. static inline void blockerupter_detect(bool __maybe_unused hotplug)
  225. {
  226. usb_detect(&blockerupter_drv, blockerupter_detect_one);
  227. }
  228. static struct api_data *blockerupter_api_stats(struct cgpu_info *blockerupter)
  229. {
  230. struct blockerupter_info *info = blockerupter->device_data;
  231. struct api_data *root = NULL;
  232. struct timeval now, elapsed;
  233. char buf[32];
  234. int i;
  235. cgtime(&now);
  236. timersub(&now, &info->start_time, &elapsed);
  237. info->hashrate = elapsed.tv_sec ? info->hashes * 4.295 / elapsed.tv_sec : 0;
  238. info->eff = info->hashrate / info->expected;
  239. root = api_add_int(root, "Nonces", &info->nonces, false);
  240. root = api_add_uint8(root, "Board", &info->found, false);
  241. root = api_add_int(root, "Clock", &info->clock, false);
  242. root = api_add_int(root,"Accepted", &info->accepted, false);
  243. root = api_add_double(root, "HashRate", &info->hashrate , false);
  244. root = api_add_double(root, "Expected", &info->expected , false);
  245. root = api_add_double(root, "Efficiency", &info->eff, false);
  246. for (i = 0; i < BET_MAXBOARDS; i++) {
  247. double brd_hashrate;
  248. if (info->boards[i]) {
  249. sprintf(buf, "Board%02d accepted", i);
  250. root = api_add_int(root, buf, &info->b_info[i].accepted, false);
  251. sprintf(buf, "Board%02d nonces", i);
  252. root = api_add_int(root, buf, &info->b_info[i].nonces, false);
  253. sprintf(buf, "Board%02d hwerror", i);
  254. root = api_add_double(root, buf, &info->b_info[i].hwe, false);
  255. sprintf(buf, "Board%02d hashrate", i);
  256. brd_hashrate = elapsed.tv_sec ? info->b_info[i].hashes * 4.295 / elapsed.tv_sec : 0;
  257. root = api_add_double(root, buf, &brd_hashrate, false);
  258. }
  259. }
  260. return root;
  261. }
  262. static bool blockerupter_prepare(struct thr_info *thr)
  263. {
  264. struct cgpu_info *blockerupter = thr->cgpu;
  265. struct blockerupter_info *info = blockerupter->device_data;
  266. cglock_init(&(info->pool.data_lock));
  267. return true;
  268. }
  269. static void blockerupter_sendjob(struct cgpu_info *blockerupter, int board)
  270. {
  271. struct blockerupter_info *info = blockerupter->device_data;
  272. struct thr_info *thr = blockerupter->thr[0];
  273. struct work *work;
  274. uint8_t command, answer;
  275. int err;
  276. work = get_work(thr, thr->id);
  277. memcpy(&info->works[info->work_idx],work,sizeof(struct work));
  278. blockerupter_setdiff(blockerupter,floor(work->work_difficulty));
  279. command = C_JOB | (uint8_t)board;
  280. blockerupter_send(blockerupter, (char *)&command, 1);
  281. blockerupter_mark_mode(blockerupter);
  282. cgsleep_ms(1);
  283. blockerupter_send(blockerupter, (char *)(work->midstate), 32);
  284. blockerupter_send(blockerupter, (char *)&(work->data[64]), 12);
  285. blockerupter_send(blockerupter, (char *)&work->nonce2, 4);
  286. blockerupter_send(blockerupter, (char *)&info->work_idx, 1);
  287. cgsleep_ms(1);
  288. blockerupter_space_mode(blockerupter);
  289. answer = 0;
  290. err = blockerupter_read(blockerupter, (char *)&answer, 1);
  291. cgtime(&info->last_job);
  292. if (err || answer != A_GET) {
  293. applog(LOG_ERR, "%s%d: Sync Error", blockerupter->drv->name, blockerupter->device_id);
  294. } else {
  295. info->b_info[board].job_count++;
  296. applog(LOG_DEBUG, "%s%d: Sent work %d to board %d", blockerupter->drv->name,
  297. blockerupter->device_id, info->work_idx, board);
  298. }
  299. info->work_idx++;
  300. if (info->work_idx >= BET_WORK_FIFO)
  301. info->work_idx = 0;
  302. }
  303. static uint64_t blockerupter_checknonce(struct cgpu_info *blockerupter, struct blockerupter_response *resp, int board)
  304. {
  305. uint8_t test;
  306. struct blockerupter_info *info;
  307. struct thr_info *thr = blockerupter->thr[0];
  308. struct work work;
  309. uint32_t nonce;
  310. uint64_t hashes=0;
  311. int i;
  312. struct board_info *cur_brd;
  313. struct asic_info *cur_asic;
  314. info = blockerupter->device_data;
  315. work = info->works[resp->work_idx];
  316. nonce = *(uint32_t *)resp->nonce;
  317. applog(LOG_DEBUG, "%s%d: Nonce %08x from board %d, asic %d for work %d",
  318. blockerupter->drv->name, blockerupter->device_id, *(uint32_t *) resp->nonce,
  319. board, resp->chip, resp->work_idx);
  320. memcpy(work.data + 4 + 32 + 32, resp->ntime, 4);
  321. __bin2hex(work.ntime, resp->ntime, 4);
  322. info->nonces++;
  323. cur_brd = &info->b_info[board];
  324. cur_brd->nonces++;
  325. cur_asic = &info->b_info[board].asics[resp->chip];
  326. cur_asic->nonces++;
  327. for (i = 0; i < BET_NONCE_FIX; i++) {
  328. test = test_nonce_diff(&work, nonce + i, (double)info->diff);
  329. if (test) {
  330. applog(LOG_DEBUG, "%s%d: Nonce Fix Pass @%d", blockerupter->drv->name,
  331. blockerupter->device_id, i);
  332. info->hashes += info->diff;
  333. cur_brd->hashes += info->diff;
  334. cur_asic->hashes += info->diff;
  335. if (test_nonce_diff(&work, nonce + i, work.work_difficulty)) {
  336. if (submit_nonce(thr, &work, nonce + i)) {
  337. hashes += floor(work.work_difficulty) * (uint64_t) 0xffffffff;
  338. info->accepted++;
  339. cur_brd->accepted++;
  340. cur_asic->accepted++;
  341. }
  342. }
  343. break;
  344. }
  345. }
  346. if (i == BET_NONCE_FIX) {
  347. applog(LOG_DEBUG, "%s%d: Nonce Fix Failed", blockerupter->drv->name,
  348. blockerupter->device_id);
  349. cur_brd->bad++;
  350. cur_brd->hwe = cur_brd->nonces ? (double)cur_brd->bad / cur_brd->nonces : 0;
  351. cur_asic->bad++;
  352. cur_asic->hwe = cur_asic->nonces ? (double)cur_asic->bad / cur_asic->nonces : 0;
  353. }
  354. return hashes;
  355. }
  356. static uint64_t blockerupter_getresp(struct cgpu_info *blockerupter, int board)
  357. {
  358. struct blockerupter_response *resp;
  359. int err;
  360. uint64_t hashes = 0;
  361. resp = (struct blockerupter_response *) malloc(BET_RESP_SZ);
  362. err = blockerupter_read(blockerupter, (char *)resp, BET_RESP_SZ);
  363. if (!err)
  364. hashes = blockerupter_checknonce(blockerupter, resp, board);
  365. free(resp);
  366. return hashes;
  367. }
  368. static int64_t blockerupter_scanhash(struct thr_info *thr)
  369. {
  370. struct cgpu_info *blockerupter = thr->cgpu;
  371. struct blockerupter_info *info = blockerupter->device_data;
  372. char ask;
  373. uint8_t answer;
  374. int i;
  375. int64_t hashes=0;
  376. if (unlikely(blockerupter->usbinfo.nodev)) {
  377. applog(LOG_ERR, "%s%d: Device disappeared, shutting down thread",
  378. blockerupter->drv->name, blockerupter->device_id);
  379. return -1;
  380. }
  381. for (i = 0; i < BET_MAXBOARDS; i++) {
  382. if (!info->boards[i])
  383. continue;
  384. ask = C_ASK | (uint8_t)i;
  385. blockerupter_send(blockerupter, &ask, 1);
  386. cgsleep_ms(1);
  387. answer = 0;
  388. blockerupter_read(blockerupter, (char *)&answer, 1);
  389. switch (answer) {
  390. case A_WAL:
  391. blockerupter_sendjob(blockerupter, i);
  392. break;
  393. case A_YES:
  394. hashes += blockerupter_getresp(blockerupter, i);
  395. break;
  396. case A_NO:
  397. break;
  398. default:
  399. applog(LOG_ERR, "%s%d: Unexpected value %02x received", blockerupter->drv->name,
  400. blockerupter->device_id, answer);
  401. break;
  402. }
  403. }
  404. return hashes;
  405. }
  406. static void blockerupter_flush_work(struct cgpu_info *blockerupter)
  407. {
  408. uint8_t command = C_LPO | BET_ROLLING_DEFAULT;
  409. blockerupter_send(blockerupter, (char *)&command, 1);
  410. }
  411. struct device_drv blockerupter_drv = {
  412. .drv_id = DRIVER_blockerupter,
  413. .dname = "blockerupter",
  414. .name = "BET",
  415. .min_diff = 64,
  416. .get_api_stats = blockerupter_api_stats,
  417. .drv_detect = blockerupter_detect,
  418. .thread_prepare = blockerupter_prepare,
  419. .hash_work = hash_driver_work,
  420. .flush_work = blockerupter_flush_work,
  421. .scanwork = blockerupter_scanhash
  422. };