driver-klondike.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164
  1. /*
  2. * Copyright 2013 Andrew Smith
  3. * Copyright 2013 Con Kolivas
  4. * Copyright 2013 Chris Savery
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the Free
  8. * Software Foundation; either version 3 of the License, or (at your option)
  9. * any later version. See COPYING for more details.
  10. */
  11. #include <float.h>
  12. #include <limits.h>
  13. #include <pthread.h>
  14. #include <stdint.h>
  15. #include <stdio.h>
  16. #include <strings.h>
  17. #include <sys/time.h>
  18. #include <unistd.h>
  19. #include <math.h>
  20. #include "config.h"
  21. #ifdef WIN32
  22. #include <windows.h>
  23. #endif
  24. #include "compat.h"
  25. #include "miner.h"
  26. #include "usbutils.h"
  27. #define K1 "K1"
  28. #define K16 "K16"
  29. #define K64 "K64"
  30. #define MIDSTATE_BYTES 32
  31. #define MERKLE_OFFSET 64
  32. #define MERKLE_BYTES 12
  33. #define REPLY_SIZE 15 // adequate for all types of replies
  34. #define MAX_KLINES 1024 // unhandled reply limit
  35. #define REPLY_WAIT_TIME 100 // poll interval for a cmd waiting it's reply
  36. #define CMD_REPLY_RETRIES 8 // how many retries for cmds
  37. #define MAX_WORK_COUNT 4 // for now, must be binary multiple and match firmware
  38. #define TACH_FACTOR 87890 // fan rpm divisor
  39. /*
  40. * Work older than 5s will already be completed
  41. * FYI it must not be possible to complete 256 work
  42. * items this quickly on a single device -
  43. * thus limited to 219.9GH/s per device
  44. */
  45. #define OLD_WORK_MS ((int)(5 * 1000))
  46. struct device_drv klondike_drv;
  47. typedef struct klondike_header {
  48. uint8_t cmd;
  49. uint8_t dev;
  50. uint8_t buf[REPLY_SIZE-2];
  51. } HEADER;
  52. #define K_2(_bytes) ((int)(_bytes[0]) + \
  53. ((int)(_bytes[1]) << 8))
  54. #define K_4(_bytes) ((uint64_t)(_bytes[0]) + \
  55. ((uint64_t)(_bytes[1]) << 8) + \
  56. ((uint64_t)(_bytes[2]) << 16) + \
  57. ((uint64_t)(_bytes[3]) << 24))
  58. #define K_SERIAL(_serial) K_4(_serial)
  59. #define K_HASHCOUNT(_hashcount) K_2(_hashcount)
  60. #define K_MAXCOUNT(_maxcount) K_2(_maxcount)
  61. #define K_NONCE(_nonce) K_4(_nonce)
  62. #define K_HASHCLOCK(_hashclock) K_2(_hashclock)
  63. #define SET_HASHCLOCK(_hashclock, _value) do { \
  64. (_hashclock)[0] = (uint8_t)((_value) & 0xff); \
  65. (_hashclock)[1] = (uint8_t)(((_value) >> 8) & 0xff); \
  66. } while(0)
  67. #define KSENDHD(_add) (sizeof(char) + sizeof(uint8_t) + _add)
  68. typedef struct klondike_id {
  69. uint8_t cmd;
  70. uint8_t dev;
  71. uint8_t version;
  72. uint8_t product[7];
  73. uint8_t serial[4];
  74. } IDENTITY;
  75. typedef struct klondike_status {
  76. uint8_t cmd;
  77. uint8_t dev;
  78. uint8_t state;
  79. uint8_t chipcount;
  80. uint8_t slavecount;
  81. uint8_t workqc;
  82. uint8_t workid;
  83. uint8_t temp;
  84. uint8_t fanspeed;
  85. uint8_t errorcount;
  86. uint8_t hashcount[2];
  87. uint8_t maxcount[2];
  88. uint8_t noise;
  89. } WORKSTATUS;
  90. typedef struct _worktask {
  91. uint8_t cmd;
  92. uint8_t dev;
  93. uint8_t workid;
  94. uint8_t midstate[32];
  95. uint8_t merkle[12];
  96. } WORKTASK;
  97. typedef struct _workresult {
  98. uint8_t cmd;
  99. uint8_t dev;
  100. uint8_t workid;
  101. uint8_t nonce[4];
  102. } WORKRESULT;
  103. typedef struct klondike_cfg {
  104. uint8_t cmd;
  105. uint8_t dev;
  106. uint8_t hashclock[2];
  107. uint8_t temptarget;
  108. uint8_t tempcritical;
  109. uint8_t fantarget;
  110. uint8_t pad2;
  111. } WORKCFG;
  112. typedef struct kline {
  113. union {
  114. HEADER hd;
  115. IDENTITY id;
  116. WORKSTATUS ws;
  117. WORKTASK wt;
  118. WORKRESULT wr;
  119. WORKCFG cfg;
  120. };
  121. } KLINE;
  122. typedef struct device_info {
  123. uint32_t noncecount;
  124. uint32_t nextworkid;
  125. uint16_t lasthashcount;
  126. uint64_t totalhashcount;
  127. uint32_t rangesize;
  128. uint32_t *chipstats;
  129. } DEVINFO;
  130. typedef struct klist {
  131. struct klist *prev;
  132. struct klist *next;
  133. KLINE kline;
  134. struct timeval tv_when;
  135. int block_seq;
  136. bool ready;
  137. bool working;
  138. } KLIST;
  139. struct klondike_info {
  140. bool shutdown;
  141. pthread_rwlock_t stat_lock;
  142. struct thr_info replies_thr;
  143. cglock_t klist_lock;
  144. KLIST *used;
  145. KLIST *free;
  146. int kline_count;
  147. int used_count;
  148. int block_seq;
  149. KLIST *status;
  150. DEVINFO *devinfo;
  151. KLIST *cfg;
  152. int noncecount;
  153. uint64_t hashcount;
  154. uint64_t errorcount;
  155. uint64_t noisecount;
  156. // us Delay from USB reply to being processed
  157. double delay_count;
  158. double delay_total;
  159. double delay_min;
  160. double delay_max;
  161. struct timeval tv_last_nonce_received;
  162. // Time from recieving one nonce to the next
  163. double nonce_count;
  164. double nonce_total;
  165. double nonce_min;
  166. double nonce_max;
  167. int wque_size;
  168. int wque_cleared;
  169. };
  170. static KLIST *new_klist_set(struct cgpu_info *klncgpu)
  171. {
  172. struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
  173. KLIST *klist = NULL;
  174. int i;
  175. klist = calloc(MAX_KLINES, sizeof(*klist));
  176. if (!klist)
  177. quit(1, "Failed to calloc klist - when old count=%d", klninfo->kline_count);
  178. klninfo->kline_count += MAX_KLINES;
  179. klist[0].prev = NULL;
  180. klist[0].next = &(klist[1]);
  181. for (i = 1; i < MAX_KLINES-1; i++) {
  182. klist[i].prev = &klist[i-1];
  183. klist[i].next = &klist[i+1];
  184. }
  185. klist[MAX_KLINES-1].prev = &(klist[MAX_KLINES-2]);
  186. klist[MAX_KLINES-1].next = NULL;
  187. return klist;
  188. }
  189. static KLIST *allocate_kitem(struct cgpu_info *klncgpu)
  190. {
  191. struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
  192. KLIST *kitem = NULL;
  193. int ran_out = 0;
  194. char errbuf[1024];
  195. cg_wlock(&klninfo->klist_lock);
  196. if (klninfo->free == NULL) {
  197. ran_out = klninfo->kline_count;
  198. klninfo->free = new_klist_set(klncgpu);
  199. snprintf(errbuf, sizeof(errbuf),
  200. "%s%i: KLINE count exceeded %d, now %d",
  201. klncgpu->drv->name, klncgpu->device_id,
  202. ran_out, klninfo->kline_count);
  203. }
  204. kitem = klninfo->free;
  205. klninfo->free = klninfo->free->next;
  206. if (klninfo->free)
  207. klninfo->free->prev = NULL;
  208. kitem->next = klninfo->used;
  209. kitem->prev = NULL;
  210. if (kitem->next)
  211. kitem->next->prev = kitem;
  212. klninfo->used = kitem;
  213. kitem->ready = false;
  214. kitem->working = false;
  215. memset((void *)&(kitem->kline), 0, sizeof(kitem->kline));
  216. klninfo->used_count++;
  217. cg_wunlock(&klninfo->klist_lock);
  218. if (ran_out > 0)
  219. applog(LOG_ERR, "%s", errbuf);
  220. return kitem;
  221. }
  222. static void release_kitem(struct cgpu_info *klncgpu, KLIST *kitem)
  223. {
  224. struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
  225. cg_wlock(&klninfo->klist_lock);
  226. if (kitem == klninfo->used)
  227. klninfo->used = kitem->next;
  228. if (kitem->next)
  229. kitem->next->prev = kitem->prev;
  230. if (kitem->prev)
  231. kitem->prev->next = kitem->next;
  232. kitem->next = klninfo->free;
  233. if (klninfo->free)
  234. klninfo->free->prev = kitem;
  235. kitem->prev = NULL;
  236. klninfo->free = kitem;
  237. klninfo->used_count--;
  238. cg_wunlock(&klninfo->klist_lock);
  239. }
  240. static double cvtKlnToC(uint8_t temp)
  241. {
  242. double Rt, stein, celsius;
  243. if (temp == 0)
  244. return 0.0;
  245. Rt = 1000.0 * 255.0 / (double)temp - 1000.0;
  246. stein = log(Rt / 2200.0) / 3987.0;
  247. stein += 1.0 / (double)(25.0 + 273.15);
  248. celsius = (1.0 / stein) - 273.15;
  249. // For display of bad data
  250. if (celsius < 0.0)
  251. celsius = 0.0;
  252. if (celsius > 200.0)
  253. celsius = 200.0;
  254. return celsius;
  255. }
  256. static int cvtCToKln(double deg)
  257. {
  258. double Rt, stein, temp;
  259. if (deg < 0.0)
  260. deg = 0.0;
  261. stein = 1.0 / (deg + 273.15);
  262. stein -= 1.0 / (double)(25.0 + 273.15);
  263. Rt = exp(stein * 3987.0) * 2200.0;
  264. if (Rt == -1000.0)
  265. Rt++;
  266. temp = 1000.0 * 256.0 / (Rt + 1000.0);
  267. if (temp > 255)
  268. temp = 255;
  269. if (temp < 0)
  270. temp = 0;
  271. return (int)temp;
  272. }
  273. // Change this to LOG_WARNING if you wish to always see the replies
  274. #define READ_DEBUG LOG_DEBUG
  275. //#define READ_DEBUG LOG_ERR
  276. static void display_kline(struct cgpu_info *klncgpu, KLINE *kline)
  277. {
  278. char *hexdata;
  279. switch (kline->hd.cmd) {
  280. case '=':
  281. applog(READ_DEBUG,
  282. "%s (%s) work [%c] dev=%d workid=%d"
  283. " nonce=0x%08x",
  284. klncgpu->drv->dname, klncgpu->device_path,
  285. kline->wr.cmd,
  286. (int)(kline->wr.dev),
  287. (int)(kline->wr.workid),
  288. (unsigned int)K_NONCE(kline->wr.nonce));
  289. break;
  290. case 'S':
  291. case 'W':
  292. case 'A':
  293. case 'E':
  294. applog(READ_DEBUG,
  295. "%s (%s) status [%c] dev=%d chips=%d"
  296. " slaves=%d workcq=%d workid=%d temp=%d fan=%d"
  297. " errors=%d hashes=%d max=%d noise=%d",
  298. klncgpu->drv->dname, klncgpu->device_path,
  299. kline->ws.cmd,
  300. (int)(kline->ws.dev),
  301. (int)(kline->ws.chipcount),
  302. (int)(kline->ws.slavecount),
  303. (int)(kline->ws.workqc),
  304. (int)(kline->ws.workid),
  305. (int)(kline->ws.temp),
  306. (int)(kline->ws.fanspeed),
  307. (int)(kline->ws.errorcount),
  308. K_HASHCOUNT(kline->ws.hashcount),
  309. K_MAXCOUNT(kline->ws.maxcount),
  310. (int)(kline->ws.noise));
  311. break;
  312. case 'C':
  313. applog(READ_DEBUG,
  314. "%s (%s) config [%c] dev=%d clock=%d"
  315. " temptarget=%d tempcrit=%d fan=%d",
  316. klncgpu->drv->dname, klncgpu->device_path,
  317. kline->cfg.cmd,
  318. (int)(kline->cfg.dev),
  319. K_HASHCLOCK(kline->cfg.hashclock),
  320. (int)(kline->cfg.temptarget),
  321. (int)(kline->cfg.tempcritical),
  322. (int)(kline->cfg.fantarget));
  323. break;
  324. case 'I':
  325. applog(READ_DEBUG,
  326. "%s (%s) info [%c] version=0x%02x prod=%.7s"
  327. " serial=0x%08x",
  328. klncgpu->drv->dname, klncgpu->device_path,
  329. kline->hd.cmd,
  330. (int)(kline->id.version),
  331. kline->id.product,
  332. (unsigned int)K_SERIAL(kline->id.serial));
  333. break;
  334. default:
  335. hexdata = bin2hex((unsigned char *)&(kline->hd.dev), REPLY_SIZE - 1);
  336. applog(LOG_ERR,
  337. "%s (%s) [%c:%s] unknown and ignored",
  338. klncgpu->drv->dname, klncgpu->device_path,
  339. kline->hd.cmd, hexdata);
  340. free(hexdata);
  341. break;
  342. }
  343. }
  344. static KLIST *SendCmdGetReply(struct cgpu_info *klncgpu, KLINE *kline, int datalen)
  345. {
  346. struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
  347. KLIST *kitem;
  348. int retries = CMD_REPLY_RETRIES;
  349. int err, amt, writ;
  350. if (klncgpu->usbinfo.nodev)
  351. return NULL;
  352. writ = KSENDHD(datalen);
  353. err = usb_write(klncgpu, (char *)kline, writ, &amt, C_REQUESTRESULTS);
  354. if (err < 0 || amt != writ) {
  355. applog(LOG_ERR, "%s (%s) Cmd:%c Dev:%d, write failed (%d:%d:%d)",
  356. klncgpu->drv->dname, klncgpu->device_path,
  357. kline->hd.cmd, (int)kline->hd.dev,
  358. writ, amt, err);
  359. }
  360. while (retries-- > 0 && klninfo->shutdown == false) {
  361. cgsleep_ms(REPLY_WAIT_TIME);
  362. cg_rlock(&klninfo->klist_lock);
  363. kitem = klninfo->used;
  364. while (kitem) {
  365. if (kitem->kline.hd.cmd == kline->hd.cmd &&
  366. kitem->kline.hd.dev == kline->hd.dev &&
  367. kitem->ready == true && kitem->working == false) {
  368. kitem->working = true;
  369. cg_runlock(&klninfo->klist_lock);
  370. return kitem;
  371. }
  372. kitem = kitem->next;
  373. }
  374. cg_runlock(&klninfo->klist_lock);
  375. }
  376. return NULL;
  377. }
  378. static bool klondike_get_stats(struct cgpu_info *klncgpu)
  379. {
  380. struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
  381. KLIST *kitem;
  382. KLINE kline;
  383. int slaves, dev;
  384. if (klncgpu->usbinfo.nodev || klninfo->status == NULL)
  385. return false;
  386. applog(LOG_DEBUG, "Klondike getting status");
  387. slaves = klninfo->status[0].kline.ws.slavecount;
  388. // loop thru devices and get status for each
  389. for (dev = 0; dev <= slaves; dev++) {
  390. kline.hd.cmd = 'S';
  391. kline.hd.dev = dev;
  392. kitem = SendCmdGetReply(klncgpu, &kline, 0);
  393. if (kitem != NULL) {
  394. wr_lock(&(klninfo->stat_lock));
  395. memcpy((void *)(&(klninfo->status[dev])),
  396. (void *)kitem,
  397. sizeof(klninfo->status[dev]));
  398. wr_unlock(&(klninfo->stat_lock));
  399. release_kitem(klncgpu, kitem);
  400. kitem = NULL;
  401. }
  402. }
  403. // todo: detect slavecount change and realloc space
  404. return true;
  405. }
  406. static bool klondike_init(struct cgpu_info *klncgpu)
  407. {
  408. struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
  409. KLIST *kitem;
  410. KLINE kline;
  411. int slaves, dev;
  412. kline.hd.cmd = 'S';
  413. kline.hd.dev = 0;
  414. kitem = SendCmdGetReply(klncgpu, &kline, 0);
  415. if (kitem == NULL)
  416. return false;
  417. slaves = kitem->kline.ws.slavecount;
  418. release_kitem(klncgpu, kitem);
  419. kitem = NULL;
  420. if (klninfo->status == NULL) {
  421. applog(LOG_DEBUG, "Klondike initializing data");
  422. // alloc space for status, devinfo and cfg for master and slaves
  423. klninfo->status = calloc(slaves+1, sizeof(KLIST));
  424. if (unlikely(!klninfo->status))
  425. quit(1, "Failed to calloc status array in klondke_get_stats");
  426. klninfo->devinfo = calloc(slaves+1, sizeof(DEVINFO));
  427. if (unlikely(!klninfo->devinfo))
  428. quit(1, "Failed to calloc devinfo array in klondke_get_stats");
  429. klninfo->cfg = calloc(slaves+1, sizeof(KLIST));
  430. if (unlikely(!klninfo->cfg))
  431. quit(1, "Failed to calloc cfg array in klondke_get_stats");
  432. }
  433. // zero init triggers read back only
  434. memset(&(kline.cfg), 0, sizeof(kline.cfg));
  435. kline.cfg.cmd = 'C';
  436. int size = 2;
  437. // boundaries are checked by device, with valid values returned
  438. if (opt_klondike_options != NULL) {
  439. int hashclock;
  440. double temp1, temp2;
  441. sscanf(opt_klondike_options, "%d:%lf:%lf:%"SCNu8,
  442. &hashclock,
  443. &temp1, &temp2,
  444. &kline.cfg.fantarget);
  445. SET_HASHCLOCK(kline.cfg.hashclock, hashclock);
  446. kline.cfg.temptarget = cvtCToKln(temp1);
  447. kline.cfg.tempcritical = cvtCToKln(temp2);
  448. kline.cfg.fantarget = (int)255*kline.cfg.fantarget/100;
  449. size = sizeof(kline.cfg) - 2;
  450. }
  451. for (dev = 0; dev <= slaves; dev++) {
  452. kline.cfg.dev = dev;
  453. kitem = SendCmdGetReply(klncgpu, &kline, size);
  454. if (kitem != NULL) {
  455. memcpy((void *)&(klninfo->cfg[dev]), kitem, sizeof(klninfo->cfg[dev]));
  456. applog(LOG_WARNING, "Klondike config (%d: Clk: %d, T:%.0lf, C:%.0lf, F:%d)",
  457. dev, K_HASHCLOCK(klninfo->cfg[dev].kline.cfg.hashclock),
  458. cvtKlnToC(klninfo->cfg[dev].kline.cfg.temptarget),
  459. cvtKlnToC(klninfo->cfg[dev].kline.cfg.tempcritical),
  460. (int)100*klninfo->cfg[dev].kline.cfg.fantarget/256);
  461. release_kitem(klncgpu, kitem);
  462. kitem = NULL;
  463. }
  464. }
  465. klondike_get_stats(klncgpu);
  466. for (dev = 0; dev <= slaves; dev++) {
  467. klninfo->devinfo[dev].rangesize = ((uint64_t)1<<32) / klninfo->status[dev].kline.ws.chipcount;
  468. klninfo->devinfo[dev].chipstats = calloc(klninfo->status[dev].kline.ws.chipcount*2 , sizeof(uint32_t));
  469. }
  470. int tries = 2;
  471. bool ok = false;
  472. kline.hd.cmd = 'E';
  473. kline.hd.dev = 0;
  474. kline.hd.buf[0] = '1';
  475. while (tries-- > 0) {
  476. kitem = SendCmdGetReply(klncgpu, &kline, 1);
  477. if (kitem) {
  478. release_kitem(klncgpu, kitem);
  479. kitem = NULL;
  480. ok = true;
  481. break;
  482. }
  483. }
  484. if (!ok)
  485. applog(LOG_ERR, "%s%i: failed to enable", klncgpu->drv->name, klncgpu->device_id);
  486. return ok;
  487. }
  488. static bool klondike_detect_one(struct libusb_device *dev, struct usb_find_devices *found)
  489. {
  490. struct cgpu_info *klncgpu = usb_alloc_cgpu(&klondike_drv, 1);
  491. struct klondike_info *klninfo = NULL;
  492. if (unlikely(!klncgpu))
  493. quit(1, "Failed to calloc klncgpu in klondike_detect_one");
  494. klninfo = calloc(1, sizeof(*klninfo));
  495. if (unlikely(!klninfo))
  496. quit(1, "Failed to calloc klninfo in klondke_detect_one");
  497. klncgpu->device_data = (void *)klninfo;
  498. klninfo->free = new_klist_set(klncgpu);
  499. if (usb_init(klncgpu, dev, found)) {
  500. int sent, recd, err;
  501. KLIST kitem;
  502. int attempts = 0;
  503. while (attempts++ < 3) {
  504. err = usb_write(klncgpu, "I", 2, &sent, C_REQUESTRESULTS);
  505. if (err < 0 || sent != 2) {
  506. applog(LOG_ERR, "%s (%s) detect write failed (%d:%d)",
  507. klncgpu->drv->dname,
  508. klncgpu->device_path,
  509. sent, err);
  510. }
  511. cgsleep_ms(REPLY_WAIT_TIME*10);
  512. err = usb_read(klncgpu, (char *)&(kitem.kline), REPLY_SIZE, &recd, C_GETRESULTS);
  513. if (err < 0) {
  514. applog(LOG_ERR, "%s (%s) detect read failed (%d:%d)",
  515. klncgpu->drv->dname,
  516. klncgpu->device_path,
  517. recd, err);
  518. } else if (recd < 1) {
  519. applog(LOG_ERR, "%s (%s) detect empty reply (%d)",
  520. klncgpu->drv->dname,
  521. klncgpu->device_path,
  522. recd);
  523. } else if (kitem.kline.hd.cmd == 'I' && kitem.kline.hd.dev == 0) {
  524. display_kline(klncgpu, &kitem.kline);
  525. applog(LOG_DEBUG, "%s (%s) detect successful (%d attempt%s)",
  526. klncgpu->drv->dname,
  527. klncgpu->device_path,
  528. attempts, attempts == 1 ? "" : "s");
  529. if (!add_cgpu(klncgpu))
  530. break;
  531. update_usb_stats(klncgpu);
  532. applog(LOG_DEBUG, "Klondike cgpu added");
  533. cglock_init(&klninfo->klist_lock);
  534. return true;
  535. }
  536. }
  537. usb_uninit(klncgpu);
  538. }
  539. free(klninfo->free);
  540. free(klninfo);
  541. free(klncgpu);
  542. return false;
  543. }
  544. static void klondike_detect(bool __maybe_unused hotplug)
  545. {
  546. usb_detect(&klondike_drv, klondike_detect_one);
  547. }
  548. static void klondike_identify(__maybe_unused struct cgpu_info *klncgpu)
  549. {
  550. /*
  551. KLINE kline;
  552. kline.hd.cmd = 'I';
  553. kline.hd.dev = 0;
  554. SendCmdGetReply(klncgpu, &kline, KSENDHD(0));
  555. */
  556. }
  557. static void klondike_check_nonce(struct cgpu_info *klncgpu, KLIST *kitem)
  558. {
  559. struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
  560. struct work *work, *tmp;
  561. KLINE *kline = &(kitem->kline);
  562. struct timeval tv_now;
  563. double us_diff;
  564. uint32_t nonce = K_NONCE(kline->wr.nonce) - 0xC0;
  565. applog(LOG_DEBUG, "Klondike FOUND NONCE (%02x:%08x)",
  566. kline->wr.workid, (unsigned int)nonce);
  567. cgtime(&tv_now);
  568. HASH_ITER(hh, klncgpu->queued_work, work, tmp) {
  569. if (work->queued && ms_tdiff(&tv_now, &(work->tv_stamp)) < OLD_WORK_MS &&
  570. (work->subid == (kline->wr.dev*256 + kline->wr.workid))) {
  571. wr_lock(&(klninfo->stat_lock));
  572. klninfo->devinfo[kline->wr.dev].noncecount++;
  573. klninfo->noncecount++;
  574. wr_unlock(&(klninfo->stat_lock));
  575. // kline->wr.nonce = le32toh(kline->wr.nonce - 0xC0);
  576. applog(LOG_DEBUG, "Klondike SUBMIT NONCE (%02x:%08x)",
  577. kline->wr.workid, (unsigned int)nonce);
  578. cgtime(&tv_now);
  579. bool ok = submit_nonce(klncgpu->thr[0], work, nonce);
  580. applog(LOG_DEBUG, "Klondike chip stats %d, %08x, %d, %d",
  581. kline->wr.dev, (unsigned int)nonce,
  582. klninfo->devinfo[kline->wr.dev].rangesize,
  583. klninfo->status[kline->wr.dev].kline.ws.chipcount);
  584. klninfo->devinfo[kline->wr.dev].chipstats[(nonce / klninfo->devinfo[kline->wr.dev].rangesize) + (ok ? 0 : klninfo->status[kline->wr.dev].kline.ws.chipcount)]++;
  585. us_diff = us_tdiff(&tv_now, &(kitem->tv_when));
  586. if (klninfo->delay_count == 0) {
  587. klninfo->delay_min = us_diff;
  588. klninfo->delay_max = us_diff;
  589. } else {
  590. if (klninfo->delay_min > us_diff)
  591. klninfo->delay_min = us_diff;
  592. if (klninfo->delay_max < us_diff)
  593. klninfo->delay_max = us_diff;
  594. }
  595. klninfo->delay_count++;
  596. klninfo->delay_total += us_diff;
  597. if (klninfo->nonce_count > 0) {
  598. us_diff = us_tdiff(&(kitem->tv_when), &(klninfo->tv_last_nonce_received));
  599. if (klninfo->nonce_count == 1) {
  600. klninfo->nonce_min = us_diff;
  601. klninfo->nonce_max = us_diff;
  602. } else {
  603. if (klninfo->nonce_min > us_diff)
  604. klninfo->nonce_min = us_diff;
  605. if (klninfo->nonce_max < us_diff)
  606. klninfo->nonce_max = us_diff;
  607. }
  608. klninfo->nonce_total += us_diff;
  609. }
  610. klninfo->nonce_count++;
  611. memcpy(&(klninfo->tv_last_nonce_received), &(kitem->tv_when),
  612. sizeof(klninfo->tv_last_nonce_received));
  613. return;
  614. }
  615. }
  616. applog(LOG_ERR, "%s%i:%d unknown work (%02x:%08x) - ignored",
  617. klncgpu->drv->name, klncgpu->device_id,
  618. kline->wr.dev, kline->wr.workid, (unsigned int)nonce);
  619. //inc_hw_errors(klncgpu->thr[0]);
  620. }
  621. // thread to keep looking for replies
  622. static void *klondike_get_replies(void *userdata)
  623. {
  624. struct cgpu_info *klncgpu = (struct cgpu_info *)userdata;
  625. struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
  626. KLIST *kitem = NULL;
  627. char *hexdata;
  628. int err, recd;
  629. applog(LOG_ERR, "Klondike listening for replies");
  630. while (klninfo->shutdown == false) {
  631. if (klncgpu->usbinfo.nodev)
  632. return NULL;
  633. if (kitem == NULL)
  634. kitem = allocate_kitem(klncgpu);
  635. else
  636. memset((void *)&(kitem->kline), 0, sizeof(kitem->kline));
  637. err = usb_read(klncgpu, (char *)&(kitem->kline), REPLY_SIZE, &recd, C_GETRESULTS);
  638. if (!err && recd == REPLY_SIZE) {
  639. cgtime(&(kitem->tv_when));
  640. kitem->block_seq = klninfo->block_seq;
  641. if (opt_log_level <= READ_DEBUG) {
  642. hexdata = bin2hex((unsigned char *)&(kitem->kline.hd.dev), recd-1);
  643. applog(READ_DEBUG, "%s (%s) reply [%c:%s]",
  644. klncgpu->drv->dname, klncgpu->device_path,
  645. kitem->kline.hd.cmd, hexdata);
  646. free(hexdata);
  647. }
  648. switch (kitem->kline.hd.cmd) {
  649. case '=':
  650. klondike_check_nonce(klncgpu, kitem);
  651. display_kline(klncgpu, &kitem->kline);
  652. break;
  653. case 'S':
  654. case 'W':
  655. case 'A':
  656. case 'E':
  657. wr_lock(&(klninfo->stat_lock));
  658. klninfo->errorcount += kitem->kline.ws.errorcount;
  659. klninfo->noisecount += kitem->kline.ws.noise;
  660. wr_unlock(&(klninfo->stat_lock));
  661. display_kline(klncgpu, &kitem->kline);
  662. kitem->ready = true;
  663. kitem = NULL;
  664. break;
  665. case 'C':
  666. display_kline(klncgpu, &kitem->kline);
  667. kitem->ready = true;
  668. kitem = NULL;
  669. break;
  670. case 'I':
  671. display_kline(klncgpu, &kitem->kline);
  672. kitem->ready = true;
  673. kitem = NULL;
  674. break;
  675. default:
  676. display_kline(klncgpu, &kitem->kline);
  677. break;
  678. }
  679. }
  680. }
  681. return NULL;
  682. }
  683. static void klondike_flush_work(struct cgpu_info *klncgpu)
  684. {
  685. struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
  686. KLIST *kitem;
  687. KLINE kline;
  688. int slaves, dev;
  689. klninfo->block_seq++;
  690. applog(LOG_DEBUG, "Klondike flushing work");
  691. slaves = klninfo->status[0].kline.ws.slavecount;
  692. kline.hd.cmd = 'A';
  693. for (dev = 0; dev <= slaves; dev++) {
  694. kline.hd.dev = dev;
  695. kitem = SendCmdGetReply(klncgpu, &kline, KSENDHD(0));
  696. if (kitem != NULL) {
  697. wr_lock(&(klninfo->stat_lock));
  698. memcpy((void *)&(klninfo->status[dev]),
  699. kitem,
  700. sizeof(klninfo->status[dev]));
  701. wr_unlock(&(klninfo->stat_lock));
  702. release_kitem(klncgpu, kitem);
  703. kitem = NULL;
  704. }
  705. }
  706. }
  707. static bool klondike_thread_prepare(struct thr_info *thr)
  708. {
  709. struct cgpu_info *klncgpu = thr->cgpu;
  710. struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
  711. if (thr_info_create(&(klninfo->replies_thr), NULL, klondike_get_replies, (void *)klncgpu)) {
  712. applog(LOG_ERR, "%s%i: thread create failed", klncgpu->drv->name, klncgpu->device_id);
  713. return false;
  714. }
  715. pthread_detach(klninfo->replies_thr.pth);
  716. // let the listening get started
  717. cgsleep_ms(100);
  718. return klondike_init(klncgpu);
  719. }
  720. static bool klondike_thread_init(struct thr_info *thr)
  721. {
  722. struct cgpu_info *klncgpu = thr->cgpu;
  723. if (klncgpu->usbinfo.nodev)
  724. return false;
  725. klondike_flush_work(klncgpu);
  726. return true;
  727. }
  728. static void klondike_shutdown(struct thr_info *thr)
  729. {
  730. struct cgpu_info *klncgpu = thr->cgpu;
  731. struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
  732. KLIST *kitem;
  733. KLINE kline;
  734. int dev;
  735. applog(LOG_DEBUG, "Klondike shutting down work");
  736. kline.hd.cmd = 'E';
  737. for (dev = 0; dev <= klninfo->status[0].kline.ws.slavecount; dev++) {
  738. kline.hd.dev = dev;
  739. kline.hd.buf[0] = '0';
  740. kitem = SendCmdGetReply(klncgpu, &kline, KSENDHD(1));
  741. if (kitem)
  742. release_kitem(klncgpu, kitem);
  743. }
  744. klncgpu->shutdown = klninfo->shutdown = true;
  745. }
  746. static void klondike_thread_enable(struct thr_info *thr)
  747. {
  748. struct cgpu_info *klncgpu = thr->cgpu;
  749. if (klncgpu->usbinfo.nodev)
  750. return;
  751. /*
  752. KLINE kline;
  753. kline.hd.cmd = 'E';
  754. kline.hd.dev = dev;
  755. kline.hd.buf[0] = '0';
  756. kitem = SendCmdGetReply(klncgpu, &kline, KSENDHD(1));
  757. */
  758. }
  759. static bool klondike_send_work(struct cgpu_info *klncgpu, int dev, struct work *work)
  760. {
  761. struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
  762. struct work *tmp;
  763. KLINE kline;
  764. struct timeval tv_old;
  765. int wque_size, wque_cleared;
  766. if (klncgpu->usbinfo.nodev)
  767. return false;
  768. kline.wt.cmd = 'W';
  769. kline.wt.dev = dev;
  770. memcpy(kline.wt.midstate, work->midstate, MIDSTATE_BYTES);
  771. memcpy(kline.wt.merkle, work->data + MERKLE_OFFSET, MERKLE_BYTES);
  772. kline.wt.workid = (uint8_t)(klninfo->devinfo[dev].nextworkid++ & 0xFF);
  773. work->subid = dev*256 + kline.wt.workid;
  774. cgtime(&work->tv_stamp);
  775. if (opt_log_level <= LOG_DEBUG) {
  776. char *hexdata = bin2hex((void *)&kline.wt, sizeof(kline.wt));
  777. applog(LOG_DEBUG, "WORKDATA: %s", hexdata);
  778. free(hexdata);
  779. }
  780. applog(LOG_DEBUG, "Klondike sending work (%d:%02x)", dev, kline.wt.workid);
  781. KLIST *kitem = SendCmdGetReply(klncgpu, &kline, sizeof(kline.wt));
  782. if (kitem != NULL) {
  783. wr_lock(&(klninfo->stat_lock));
  784. memcpy((void *)&(klninfo->status[dev]), kitem, sizeof(klninfo->status[dev]));
  785. wr_unlock(&(klninfo->stat_lock));
  786. release_kitem(klncgpu, kitem);
  787. kitem = NULL;
  788. // remove old work
  789. wque_size = 0;
  790. wque_cleared = 0;
  791. cgtime(&tv_old);
  792. HASH_ITER(hh, klncgpu->queued_work, work, tmp) {
  793. if (work->queued) {
  794. if (ms_tdiff(&tv_old, &(work->tv_stamp)) > OLD_WORK_MS) {
  795. work_completed(klncgpu, work);
  796. wque_cleared++;
  797. }
  798. else
  799. wque_size++;
  800. }
  801. }
  802. wr_lock(&(klninfo->stat_lock));
  803. klninfo->wque_size = wque_size;
  804. klninfo->wque_cleared = wque_cleared;
  805. wr_unlock(&(klninfo->stat_lock));
  806. return true;
  807. }
  808. return false;
  809. }
  810. static bool klondike_queue_full(struct cgpu_info *klncgpu)
  811. {
  812. struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
  813. struct work *work = NULL;
  814. int dev, queued, slaves;
  815. slaves = klninfo->status[0].kline.ws.slavecount;
  816. for (queued = 0; queued < MAX_WORK_COUNT-1; queued++)
  817. for (dev = 0; dev <= slaves; dev++)
  818. if (klninfo->status[dev].kline.ws.workqc <= queued) {
  819. if (!work)
  820. work = get_queued(klncgpu);
  821. if (unlikely(!work))
  822. return false;
  823. if (klondike_send_work(klncgpu, dev, work)) {
  824. work = NULL;
  825. break;
  826. }
  827. }
  828. return true;
  829. }
  830. static int64_t klondike_scanwork(struct thr_info *thr)
  831. {
  832. struct cgpu_info *klncgpu = thr->cgpu;
  833. struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
  834. int64_t newhashcount = 0;
  835. int dev, slaves;
  836. if (klncgpu->usbinfo.nodev)
  837. return -1;
  838. restart_wait(thr, 200);
  839. if (klninfo->status != NULL) {
  840. rd_lock(&(klninfo->stat_lock));
  841. slaves = klninfo->status[0].kline.ws.slavecount;
  842. for (dev = 0; dev <= slaves; dev++) {
  843. uint64_t newhashdev = 0, hashcount;
  844. int maxcount;
  845. hashcount = K_HASHCOUNT(klninfo->status[dev].kline.ws.hashcount);
  846. maxcount = K_MAXCOUNT(klninfo->status[dev].kline.ws.maxcount);
  847. if (klninfo->devinfo[dev].lasthashcount > hashcount) // todo: chg this to check workid for wrapped instead
  848. newhashdev += maxcount; // hash counter wrapped
  849. newhashdev += hashcount - klninfo->devinfo[dev].lasthashcount;
  850. klninfo->devinfo[dev].lasthashcount = hashcount;
  851. if (maxcount != 0)
  852. klninfo->hashcount += (newhashdev << 32) / maxcount;
  853. // todo: check stats for critical conditions
  854. }
  855. newhashcount += 0xffffffffull * (uint64_t)klninfo->noncecount;
  856. klninfo->noncecount = 0;
  857. rd_unlock(&(klninfo->stat_lock));
  858. }
  859. return newhashcount;
  860. }
  861. static void get_klondike_statline_before(char *buf, size_t siz, struct cgpu_info *klncgpu)
  862. {
  863. struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
  864. uint8_t temp = 0xFF;
  865. uint16_t fan = 0;
  866. uint16_t clock = 0;
  867. int dev, slaves;
  868. char tmp[16];
  869. if (klninfo->status == NULL) {
  870. blank_get_statline_before(buf, siz, klncgpu);
  871. return;
  872. }
  873. rd_lock(&(klninfo->stat_lock));
  874. slaves = klninfo->status[0].kline.ws.slavecount;
  875. for (dev = 0; dev <= slaves; dev++) {
  876. if (klninfo->status[dev].kline.ws.temp < temp)
  877. temp = klninfo->status[dev].kline.ws.temp;
  878. fan += klninfo->cfg[dev].kline.cfg.fantarget;
  879. clock += (uint16_t)K_HASHCLOCK(klninfo->cfg[dev].kline.cfg.hashclock);
  880. }
  881. fan /= slaves + 1;
  882. clock /= slaves + 1;
  883. rd_unlock(&(klninfo->stat_lock));
  884. snprintf(tmp, sizeof(tmp), "%2.0fC", cvtKlnToC(temp));
  885. if (strlen(tmp) < 4)
  886. strcat(tmp, " ");
  887. tailsprintf(buf, siz, "%3dMHz %3d%% %s| ", (int)clock, fan*100/255, tmp);
  888. }
  889. static struct api_data *klondike_api_stats(struct cgpu_info *klncgpu)
  890. {
  891. struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data);
  892. struct api_data *root = NULL;
  893. char buf[32];
  894. int dev, slaves;
  895. if (klninfo->status == NULL)
  896. return NULL;
  897. rd_lock(&(klninfo->stat_lock));
  898. slaves = klninfo->status[0].kline.ws.slavecount;
  899. for (dev = 0; dev <= slaves; dev++) {
  900. float fTemp = cvtKlnToC(klninfo->status[dev].kline.ws.temp);
  901. sprintf(buf, "Temp %d", dev);
  902. root = api_add_temp(root, buf, &fTemp, true);
  903. double dClk = (double)K_HASHCLOCK(klninfo->cfg[dev].kline.cfg.hashclock);
  904. sprintf(buf, "Clock %d", dev);
  905. root = api_add_freq(root, buf, &dClk, true);
  906. unsigned int iFan = (unsigned int)100 * klninfo->cfg[dev].kline.cfg.fantarget / 255;
  907. sprintf(buf, "Fan Percent %d", dev);
  908. root = api_add_int(root, buf, (int *)(&iFan), true);
  909. iFan = 0;
  910. if (klninfo->status[dev].kline.ws.fanspeed > 0)
  911. iFan = (unsigned int)TACH_FACTOR / klninfo->status[dev].kline.ws.fanspeed;
  912. sprintf(buf, "Fan RPM %d", dev);
  913. root = api_add_int(root, buf, (int *)(&iFan), true);
  914. if (klninfo->devinfo[dev].chipstats != NULL) {
  915. char data[2048];
  916. char one[32];
  917. int n;
  918. sprintf(buf, "Nonces / Chip %d", dev);
  919. data[0] = '\0';
  920. for (n = 0; n < klninfo->status[dev].kline.ws.chipcount; n++) {
  921. snprintf(one, sizeof(one), "%07d ", klninfo->devinfo[dev].chipstats[n]);
  922. strcat(data, one);
  923. }
  924. root = api_add_string(root, buf, data, true);
  925. sprintf(buf, "Errors / Chip %d", dev);
  926. data[0] = '\0';
  927. for (n = 0; n < klninfo->status[dev].kline.ws.chipcount; n++) {
  928. snprintf(one, sizeof(one), "%07d ", klninfo->devinfo[dev].chipstats[n + klninfo->status[dev].kline.ws.chipcount]);
  929. strcat(data, one);
  930. }
  931. root = api_add_string(root, buf, data, true);
  932. }
  933. }
  934. root = api_add_uint64(root, "Hash Count", &(klninfo->hashcount), true);
  935. root = api_add_uint64(root, "Error Count", &(klninfo->errorcount), true);
  936. root = api_add_uint64(root, "Noise Count", &(klninfo->noisecount), true);
  937. root = api_add_int(root, "KLine Limit", &(klninfo->kline_count), true);
  938. root = api_add_int(root, "KLine Used", &(klninfo->used_count), true);
  939. root = api_add_elapsed(root, "KQue Delay Count", &(klninfo->delay_count), true);
  940. root = api_add_elapsed(root, "KQue Delay Total", &(klninfo->delay_total), true);
  941. root = api_add_elapsed(root, "KQue Delay Min", &(klninfo->delay_min), true);
  942. root = api_add_elapsed(root, "KQue Delay Max", &(klninfo->delay_max), true);
  943. double avg;
  944. if (klninfo->delay_count == 0)
  945. avg = 0;
  946. else
  947. avg = klninfo->delay_total / klninfo->delay_count;
  948. root = api_add_diff(root, "KQue Delay Avg", &avg, true);
  949. root = api_add_elapsed(root, "KQue Nonce Count", &(klninfo->nonce_count), true);
  950. root = api_add_elapsed(root, "KQue Nonce Total", &(klninfo->nonce_total), true);
  951. root = api_add_elapsed(root, "KQue Nonce Min", &(klninfo->nonce_min), true);
  952. root = api_add_elapsed(root, "KQue Nonce Max", &(klninfo->nonce_max), true);
  953. if (klninfo->nonce_count == 0)
  954. avg = 0;
  955. else
  956. avg = klninfo->nonce_total / klninfo->nonce_count;
  957. root = api_add_diff(root, "KQue Nonce Avg", &avg, true);
  958. root = api_add_int(root, "WQue Size", &(klninfo->wque_size), true);
  959. root = api_add_int(root, "WQue Cleared", &(klninfo->wque_cleared), true);
  960. rd_unlock(&(klninfo->stat_lock));
  961. return root;
  962. }
  963. struct device_drv klondike_drv = {
  964. .drv_id = DRIVER_klondike,
  965. .dname = "Klondike",
  966. .name = "KLN",
  967. .drv_detect = klondike_detect,
  968. .get_api_stats = klondike_api_stats,
  969. .get_statline_before = get_klondike_statline_before,
  970. .get_stats = klondike_get_stats,
  971. .identify_device = klondike_identify,
  972. .thread_prepare = klondike_thread_prepare,
  973. .thread_init = klondike_thread_init,
  974. .hash_work = hash_queued_work,
  975. .scanwork = klondike_scanwork,
  976. .queue_full = klondike_queue_full,
  977. .flush_work = klondike_flush_work,
  978. .thread_shutdown = klondike_shutdown,
  979. .thread_enable = klondike_thread_enable
  980. };