driver-cointerra.c 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341
  1. /*
  2. * Copyright 2013-2014 Con Kolivas
  3. * Copyright 2014 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. #include "config.h"
  11. #include <string.h>
  12. #include "miner.h"
  13. #include "deviceapi.h"
  14. #include "driver-cointerra.h"
  15. #include "lowlevel.h"
  16. #include "lowl-usb.h"
  17. #include <math.h>
  18. static const unsigned cointerra_desired_roll = 60;
  19. static const unsigned long cointerra_latest_result_usecs = (10 * 1000000);
  20. BFG_REGISTER_DRIVER(cointerra_drv)
  21. static const char *cointerra_hdr = "ZZ";
  22. int opt_ps_load;
  23. static void cta_gen_message(char *msg, char type)
  24. {
  25. memset(msg, 0, CTA_MSG_SIZE);
  26. memcpy(msg, cointerra_hdr, 2);
  27. msg[CTA_MSG_TYPE] = type;
  28. }
  29. /* Find the number of leading zero bits in diff */
  30. static uint8_t diff_to_bits(double diff)
  31. {
  32. uint64_t diff64;
  33. uint8_t i;
  34. diff *= (double)2147483648.0;
  35. if (diff > 0x8000000000000000ULL)
  36. diff = 0x8000000000000000ULL;
  37. /* Convert it to an integer */
  38. diff64 = diff;
  39. for (i = 0; diff64; i++, diff64 >>= 1);
  40. return i;
  41. }
  42. static double bits_to_diff(uint8_t bits)
  43. {
  44. double ret = 1.0;
  45. if (likely(bits > 32))
  46. ret *= 1ull << (bits - 32);
  47. else if (unlikely(bits < 32))
  48. ret /= 1ull << (32 - bits);
  49. return ret;
  50. }
  51. static bool cta_reset_init(char *buf)
  52. {
  53. return ((buf[CTA_MSG_TYPE] == CTA_RECV_RDONE) && ((buf[CTA_RESET_TYPE]&0x3) == CTA_RESET_INIT));
  54. }
  55. static char *mystrstr(char *haystack, int size, const char *needle)
  56. {
  57. int loop = 0;
  58. while (loop < (size-1)) {
  59. if ((haystack[loop] == needle[0])&&
  60. (haystack[loop+1] == needle[1]))
  61. return &haystack[loop];
  62. loop++;
  63. }
  64. return NULL;
  65. }
  66. static
  67. bool cta_open(struct lowl_usb_endpoint * const ep, const char * const repr)
  68. {
  69. int amount, offset = 0;
  70. char buf[CTA_MSG_SIZE];
  71. cgtimer_t ts_start;
  72. bool ret = false;
  73. applog(LOG_INFO, "CTA_OPEN");
  74. cta_gen_message(buf, CTA_SEND_RESET);
  75. // set the initial difficulty
  76. buf[CTA_RESET_TYPE] = CTA_RESET_INIT | CTA_RESET_DIFF;
  77. buf[CTA_RESET_DIFF] = diff_to_bits(CTA_INIT_DIFF);
  78. buf[CTA_RESET_LOAD] = opt_cta_load ? opt_cta_load : 255;
  79. buf[CTA_RESET_PSLOAD] = opt_ps_load;
  80. amount = usb_write(ep, buf, CTA_MSG_SIZE);
  81. if (amount != CTA_MSG_SIZE) {
  82. applog(LOG_INFO, "Write error %s, wrote %d of %d",
  83. bfg_strerror(errno, BST_ERRNO),
  84. amount, CTA_MSG_SIZE);
  85. return ret;
  86. }
  87. cgtimer_time(&ts_start);
  88. /* Read from the device for up to 2 seconds discarding any data that
  89. * doesn't match a reset complete acknowledgement. */
  90. while (42) {
  91. cgtimer_t ts_now, ts_diff;
  92. char *msg;
  93. cgtimer_time(&ts_now);
  94. cgtimer_sub(&ts_now, &ts_start, &ts_diff);
  95. if (cgtimer_to_ms(&ts_diff) > 2000) {
  96. applog(LOG_DEBUG, "%s: Timed out waiting for response to reset init", repr);
  97. break;
  98. }
  99. amount = usb_read(ep, buf + offset, CTA_MSG_SIZE - offset);
  100. if (amount != (CTA_MSG_SIZE - offset) && amount != 0) {
  101. applog(LOG_INFO, "%s: Read error %s, read %d",
  102. repr, bfg_strerror(errno, BST_ERRNO), amount);
  103. break;
  104. }
  105. if (!amount)
  106. continue;
  107. msg = mystrstr(buf, amount, cointerra_hdr);
  108. if (!msg) {
  109. /* Keep the last byte in case it's the first byte of
  110. * the 2 byte header. */
  111. offset = 1;
  112. memmove(buf, buf + amount - 1, offset);
  113. continue;
  114. }
  115. if (msg > buf) {
  116. /* length of message = offset for next usb_read after moving */
  117. offset = CTA_MSG_SIZE - (msg - buf);
  118. memmove(buf, msg, offset);
  119. continue;
  120. }
  121. /* We have a full sized message starting with the header now */
  122. if (cta_reset_init(buf)) {
  123. /* We can't store any other data returned with this
  124. * reset since we have not allocated any memory for
  125. * a cointerra_info structure yet. */
  126. applog(LOG_INFO, "%s: Successful reset init received", repr);
  127. ret = true;
  128. break;
  129. }
  130. }
  131. return ret;
  132. }
  133. static
  134. bool cointerra_open(const struct lowlevel_device_info * const info, const char * const repr, struct libusb_device_handle ** const usbh_p, struct lowl_usb_endpoint ** const ep_p)
  135. {
  136. if (libusb_open(info->lowl_data, usbh_p))
  137. applogr(false, LOG_DEBUG, "%s: USB open failed on %s",
  138. cointerra_drv.dname, info->devid);
  139. *ep_p = usb_open_ep_pair(*usbh_p, LIBUSB_ENDPOINT_IN | 1, 64, LIBUSB_ENDPOINT_OUT | 1, 64);
  140. if (!*ep_p)
  141. {
  142. applog(LOG_DEBUG, "%s: Endpoint open failed on %s",
  143. cointerra_drv.dname, info->devid);
  144. fail:
  145. libusb_close(*usbh_p);
  146. *usbh_p = NULL;
  147. return false;
  148. }
  149. if (!cta_open(*ep_p, repr))
  150. {
  151. usb_close_ep(*ep_p);
  152. *ep_p = NULL;
  153. goto fail;
  154. }
  155. return true;
  156. }
  157. static void cta_clear_work(struct cgpu_info *cgpu)
  158. {
  159. struct work *work, *tmp;
  160. wr_lock(&cgpu->qlock);
  161. HASH_ITER(hh, cgpu->queued_work, work, tmp) {
  162. __work_completed(cgpu, work);
  163. free_work(work);
  164. }
  165. wr_unlock(&cgpu->qlock);
  166. }
  167. static void cta_close(struct cgpu_info *cointerra)
  168. {
  169. struct cointerra_info *info = cointerra->device_data;
  170. /* Wait for read thread to die */
  171. pthread_join(info->read_thr, NULL);
  172. /* Open does the same reset init followed by response as is required to
  173. * close the device. */
  174. if (!cta_open(info->ep, cointerra->dev_repr)) {
  175. applog(LOG_INFO, "%s %d: Reset on close failed", cointerra->drv->name,
  176. cointerra->device_id);
  177. }
  178. mutex_destroy(&info->lock);
  179. mutex_destroy(&info->sendlock);
  180. /* Don't free info here to avoid trying to access dereferenced members
  181. * once a device is unplugged. */
  182. cta_clear_work(cointerra);
  183. }
  184. static void cta_parse_info(struct cgpu_info *, struct cointerra_info *, char *);
  185. static void msg_from_hu16(char *, int, uint16_t);
  186. static
  187. bool cointerra_wait_for_info(struct cointerra_info * const ctainfo, struct lowl_usb_endpoint * const ep)
  188. {
  189. char buf[CTA_MSG_SIZE];
  190. int amount;
  191. cta_gen_message(buf, CTA_SEND_REQUEST);
  192. msg_from_hu16(buf, CTA_REQ_MSGTYPE, CTA_RECV_INFO);
  193. msg_from_hu16(buf, CTA_REQ_INTERVAL, 0);
  194. amount = usb_write(ep, buf, CTA_MSG_SIZE);
  195. if (amount != CTA_MSG_SIZE)
  196. return false;
  197. do {
  198. amount = usb_read(ep, buf, CTA_MSG_SIZE);
  199. if (amount != CTA_MSG_SIZE)
  200. applogr(false, LOG_ERR, "%s: Read error %s, read %d",
  201. __func__, bfg_strerror(errno, BST_ERRNO), amount);
  202. if (memcmp(buf, cointerra_hdr, 2))
  203. applogr(false, LOG_ERR, "%s: Packet header mismatch", __func__);
  204. } while (buf[CTA_MSG_TYPE] != CTA_RECV_INFO);
  205. cta_parse_info(NULL, ctainfo, buf);
  206. return true;
  207. }
  208. static
  209. bool cointerra_lowl_probe(const struct lowlevel_device_info * const info)
  210. {
  211. struct cointerra_info ctainfo;
  212. struct libusb_device_handle *usbh;
  213. struct lowl_usb_endpoint *ep;
  214. bool b;
  215. if (!cointerra_open(info, cointerra_drv.dname, &usbh, &ep))
  216. return false;
  217. mutex_init(&ctainfo.lock);
  218. b = cointerra_wait_for_info(&ctainfo, ep);
  219. mutex_destroy(&ctainfo.lock);
  220. usb_close_ep(ep);
  221. libusb_close(usbh);
  222. if (!b)
  223. return false;
  224. applog(LOG_DEBUG, "%s: Found %lu cores on %s",
  225. __func__, (unsigned long)ctainfo.cores, info->devid);
  226. struct cgpu_info * const dev = malloc(sizeof(*dev));
  227. *dev = (struct cgpu_info){
  228. .drv = &cointerra_drv,
  229. .procs = ctainfo.cores,
  230. .device_data = lowlevel_ref(info),
  231. .threads = 1,
  232. .device_path = strdup(info->devid),
  233. .dev_manufacturer = maybe_strdup(info->manufacturer),
  234. .dev_product = maybe_strdup(info->product),
  235. .dev_serial = maybe_strdup(info->serial),
  236. .deven = DEV_ENABLED,
  237. .min_nonce_diff = CTA_INIT_DIFF,
  238. };
  239. const bool rv = add_cgpu(dev);
  240. applog(LOG_INFO, "%s: Successfully set up %s",
  241. cointerra_drv.dname, dev->dev_repr);
  242. return rv;
  243. }
  244. static
  245. bool cointerra_lowl_match(const struct lowlevel_device_info * const info)
  246. {
  247. return lowlevel_match_lowlproduct(info, &lowl_usb, "GoldStrike");
  248. }
  249. /* This function will remove a work item from the hashtable if it matches the
  250. * id in work->subid and return a pointer to the work but it will not free the
  251. * work. It may return NULL if it cannot find matching work. */
  252. static struct work *take_work_by_id(struct cgpu_info *cgpu, uint16_t id)
  253. {
  254. struct work *work, *tmp, *ret = NULL;
  255. wr_lock(&cgpu->qlock);
  256. HASH_ITER(hh, cgpu->queued_work, work, tmp) {
  257. if (work->subid == id) {
  258. ret = work;
  259. break;
  260. }
  261. }
  262. if (ret)
  263. __work_completed(cgpu, ret);
  264. wr_unlock(&cgpu->qlock);
  265. return ret;
  266. }
  267. /* This function will look up a work item in the hashtable if it matches the
  268. * id in work->subid and return a cloned work item if it matches. It may return
  269. * NULL if it cannot find matching work. */
  270. static struct work *clone_work_by_id(struct cgpu_info *cgpu, uint16_t id)
  271. {
  272. struct work *work, *tmp, *ret = NULL;
  273. rd_lock(&cgpu->qlock);
  274. HASH_ITER(hh, cgpu->queued_work, work, tmp) {
  275. if (work->subid == id) {
  276. ret = work;
  277. break;
  278. }
  279. }
  280. if (ret)
  281. ret = copy_work(ret);
  282. rd_unlock(&cgpu->qlock);
  283. return ret;
  284. }
  285. static bool cta_send_msg(struct cgpu_info *cointerra, char *buf);
  286. static uint16_t hu16_from_msg(char *buf, int msg)
  287. {
  288. return le16toh(*(uint16_t *)&buf[msg]);
  289. }
  290. static uint32_t hu32_from_msg(char *buf, int msg)
  291. {
  292. return le32toh(*(uint32_t *)&buf[msg]);
  293. }
  294. static uint64_t hu64_from_msg(char *buf, int msg)
  295. {
  296. return le64toh(*(uint64_t *)&buf[msg]);
  297. }
  298. static uint8_t u8_from_msg(char *buf, int msg)
  299. {
  300. return *(uint8_t *)&buf[msg];
  301. }
  302. static void msg_from_hu16(char *buf, int msg, uint16_t val)
  303. {
  304. *(uint16_t *)&buf[msg] = htole16(val);
  305. }
  306. static void cta_parse_reqwork(struct cgpu_info *cointerra, struct cointerra_info *info,
  307. char *buf)
  308. {
  309. uint16_t retwork;
  310. retwork = hu16_from_msg(buf, CTA_REQWORK_REQUESTS);
  311. applog(LOG_DEBUG, "%s %d: Request work message for %u items received",
  312. cointerra->drv->name, cointerra->device_id, retwork);
  313. mutex_lock(&info->lock);
  314. info->requested = retwork;
  315. /* Wake up the main scanwork loop since we need more
  316. * work. */
  317. pthread_cond_signal(&info->wake_cond);
  318. mutex_unlock(&info->lock);
  319. }
  320. static void cta_parse_recvmatch(struct thr_info *thr, struct cgpu_info *cointerra,
  321. struct cointerra_info *info, char *buf)
  322. {
  323. struct cgpu_info *corecgpu;
  324. struct thr_info *corethr;
  325. uint32_t timestamp_offset, mcu_tag;
  326. uint16_t retwork;
  327. struct work *work;
  328. uint8_t asic, core, pipe, coreno;
  329. int pipeno, bitchar, bitbit;
  330. /* No endian switch needs doing here since it's sent and returned as
  331. * the same 4 bytes */
  332. retwork = *(uint16_t *)(&buf[CTA_DRIVER_TAG]);
  333. mcu_tag = hu32_from_msg(buf, CTA_MCU_TAG);
  334. const uint8_t wdiffbits = u8_from_msg(buf, CTA_WORK_DIFFBITS);
  335. const uint32_t nonce = hu32_from_msg(buf, CTA_MATCH_NONCE);
  336. asic = u8_from_msg(buf, CTA_MCU_ASIC);
  337. core = u8_from_msg(buf, CTA_MCU_CORE);
  338. pipe = u8_from_msg(buf, CTA_MCU_PIPE);
  339. pipeno = asic * 512 + core * 128 + pipe;
  340. // For some reason, pipe numbers skip 0x?f
  341. const int bfg_pipeno = ((pipe >> 4) * 0xf) + (pipe & 0xf);
  342. const unsigned procno = (asic * 480) + (core * 120) + bfg_pipeno;
  343. corecgpu = device_proc_by_id(cointerra, procno) ?: cointerra;
  344. corethr = corecgpu->thr[0];
  345. applog(LOG_DEBUG, "%s %d: Match message for id 0x%04x MCU id 0x%08x received",
  346. cointerra->drv->name, cointerra->device_id, retwork, mcu_tag);
  347. work = clone_work_by_id(cointerra, retwork);
  348. if (likely(work)) {
  349. unsigned char rhash[32];
  350. char outhash[16];
  351. double wdiff;
  352. uint64_t hashes;
  353. bool ret;
  354. timestamp_offset = hu32_from_msg(buf, CTA_MATCH_NOFFSET);
  355. if (timestamp_offset) {
  356. struct work *base_work = work;
  357. work = copy_work_noffset(base_work, timestamp_offset);
  358. free_work(base_work);
  359. }
  360. /* Test against the difficulty we asked for along with the work */
  361. wdiff = bits_to_diff(wdiffbits);
  362. hashes = (uint64_t)wdiff * 0x100000000ull;
  363. ret = true; // TODO: test_nonce_diff(work, nonce, wdiff);
  364. if (opt_debug) {
  365. /* Debugging, remove me */
  366. swab256(rhash, work->hash);
  367. bin2hex(outhash, rhash, 8);
  368. applog(LOG_DEBUG, "submit work %s 0x%04x 0x%08x %d 0x%08x",
  369. outhash, retwork, mcu_tag, timestamp_offset, nonce);
  370. }
  371. hashes_done2(corethr, hashes, NULL);
  372. if (likely(ret)) {
  373. coreno = asic * 4 + core;
  374. if (unlikely(asic > 1 || core > 3 || pipe > 127 || pipeno > 1023)) {
  375. applog(LOG_WARNING, "%s %d: MCU invalid pipe asic %d core %d pipe %d",
  376. cointerra->drv->name, cointerra->device_id, asic, core, pipe);
  377. coreno = 0;
  378. } else {
  379. info->last_pipe_nonce[pipeno] = time(NULL);
  380. bitchar = pipeno / 8;
  381. bitbit = pipeno % 8;
  382. info->pipe_bitmap[bitchar] |= 0x80 >> bitbit;
  383. }
  384. applog(LOG_DEBUG, "%"PRIpreprv": Submitting tested work job_id %s work_id %u",
  385. corecgpu->proc_repr, work->job_id, work->subid);
  386. ret = submit_nonce(corethr, work, nonce);
  387. mutex_lock(&info->lock);
  388. info->share_hashes += hashes;
  389. info->tot_core_hashes[coreno] += hashes;
  390. info->hashes += nonce;
  391. mutex_unlock(&info->lock);
  392. } else {
  393. char sendbuf[CTA_MSG_SIZE];
  394. applog(LOG_DEBUG, "%s %d: Notify bad match work",
  395. cointerra->drv->name, cointerra->device_id);
  396. if (opt_debug) {
  397. unsigned char midstate[32], wdata[12];
  398. char hexmidstate[68], hexwdata[28];
  399. uint16_t wid;
  400. memcpy(&wid, &info->work_id, 2);
  401. flip32(midstate, work->midstate);
  402. bin2hex(hexmidstate, midstate, 32);
  403. flip12(wdata, &work->data[64]);
  404. bin2hex(hexwdata, wdata, 12);
  405. applog(LOG_DEBUG, "False match sent: work id %u midstate %s blkhdr %s",
  406. wid, hexmidstate, hexwdata);
  407. applog(LOG_DEBUG, "False match reports: work id 0x%04x MCU id 0x%08x work diff %.1f",
  408. retwork, mcu_tag, wdiff);
  409. applog(LOG_DEBUG, "False match tested: nonce 0x%08x noffset %d %s",
  410. nonce, timestamp_offset, outhash);
  411. }
  412. /* Tell the device we got a false match */
  413. cta_gen_message(sendbuf, CTA_SEND_FMATCH);
  414. memcpy(sendbuf + 3, buf, CTA_MSG_SIZE - 3);
  415. cta_send_msg(cointerra, sendbuf);
  416. }
  417. free_work(work);
  418. } else {
  419. applog(LOG_INFO, "%s %d: Matching work id 0x%X %d not found", cointerra->drv->name,
  420. cointerra->device_id, retwork, __LINE__);
  421. inc_hw_errors3(corethr, NULL, &nonce, bits_to_diff(wdiffbits));
  422. mutex_lock(&info->lock);
  423. info->no_matching_work++;
  424. mutex_unlock(&info->lock);
  425. }
  426. }
  427. static void cta_parse_wdone(struct thr_info *thr, struct cgpu_info *cointerra,
  428. struct cointerra_info *info, char *buf)
  429. {
  430. uint16_t retwork = *(uint16_t *)(&buf[CTA_DRIVER_TAG]);
  431. struct work *work = take_work_by_id(cointerra, retwork);
  432. uint64_t hashes;
  433. if (likely(work))
  434. free_work(work);
  435. else {
  436. applog(LOG_INFO, "%s %d: Done work not found id 0x%X %d",
  437. cointerra->drv->name, cointerra->device_id, retwork, __LINE__);
  438. inc_hw_errors_only(thr);
  439. }
  440. /* Removing hashes from work done message */
  441. hashes = hu64_from_msg(buf, CTA_WDONE_NONCES);
  442. if (unlikely(hashes > (61 * 0x100000000ull))) {
  443. applog(LOG_INFO, "%s Invalid hash returned %"PRIu64"x %"PRIu64"x %"PRIu64"X",
  444. __func__, info->hashes, hashes, hashes);
  445. hashes = 0;
  446. }
  447. mutex_lock(&info->lock);
  448. info->hashes += hashes;
  449. mutex_unlock(&info->lock);
  450. }
  451. static void u16array_from_msg(uint16_t *u16, int entries, int var, char *buf)
  452. {
  453. int i, j;
  454. for (i = 0, j = 0; i < entries; i++, j += sizeof(uint16_t))
  455. u16[i] = hu16_from_msg(buf, var + j);
  456. }
  457. static void cta_parse_statread(struct cgpu_info *cointerra, struct cointerra_info *info,
  458. char *buf)
  459. {
  460. float max_temp = 0;
  461. int i;
  462. mutex_lock(&info->lock);
  463. u16array_from_msg(info->coretemp, CTA_CORES, CTA_STAT_CORETEMPS, buf);
  464. info->ambtemp_low = hu16_from_msg(buf, CTA_STAT_AMBTEMP_LOW);
  465. info->ambtemp_avg = hu16_from_msg(buf, CTA_STAT_AMBTEMP_AVG);
  466. info->ambtemp_high = hu16_from_msg(buf, CTA_STAT_AMBTEMP_HIGH);
  467. u16array_from_msg(info->pump_tachs, CTA_PUMPS, CTA_STAT_PUMP_TACHS, buf);
  468. u16array_from_msg(info->fan_tachs, CTA_FANS, CTA_STAT_FAN_TACHS, buf);
  469. u16array_from_msg(info->corevolts, CTA_CORES, CTA_STAT_CORE_VOLTS, buf);
  470. info->volts33 = hu16_from_msg(buf, CTA_STAT_VOLTS33);
  471. info->volts12 = hu16_from_msg(buf, CTA_STAT_VOLTS12);
  472. info->inactive = hu16_from_msg(buf, CTA_STAT_INACTIVE);
  473. info->active = hu16_from_msg(buf, CTA_STAT_ACTIVE);
  474. mutex_unlock(&info->lock);
  475. for (i = 0; i < CTA_CORES; i++) {
  476. if (info->coretemp[i] > max_temp)
  477. max_temp = info->coretemp[i];
  478. }
  479. max_temp /= 100.0;
  480. /* Store the max temperature in the cgpu struct as an exponentially
  481. * changing value. */
  482. cointerra->temp = cointerra->temp * 0.63 + max_temp * 0.37;
  483. }
  484. static void u8array_from_msg(uint8_t *u8, int entries, int var, char *buf)
  485. {
  486. int i;
  487. for (i = 0; i < entries; i++)
  488. u8[i] = u8_from_msg(buf, var + i);
  489. }
  490. static void cta_parse_statset(struct cointerra_info *info, char *buf)
  491. {
  492. mutex_lock(&info->lock);
  493. u8array_from_msg(info->coreperf, CTA_CORES, CTA_STAT_PERFMODE, buf);
  494. u8array_from_msg(info->fanspeed, CTA_FANS, CTA_STAT_FANSPEEDS, buf);
  495. info->dies_active = u8_from_msg(buf, CTA_STAT_DIES_ACTIVE);
  496. u8array_from_msg(info->pipes_enabled, CTA_CORES, CTA_STAT_PIPES_ENABLED, buf);
  497. u16array_from_msg(info->corefreqs, CTA_CORES, CTA_STAT_CORE_FREQS, buf);
  498. info->uptime = hu32_from_msg(buf,CTA_STAT_UPTIME);
  499. mutex_unlock(&info->lock);
  500. }
  501. static void cta_parse_info(struct cgpu_info *cointerra, struct cointerra_info *info,
  502. char *buf)
  503. {
  504. mutex_lock(&info->lock);
  505. info->hwrev = hu64_from_msg(buf, CTA_INFO_HWREV);
  506. info->serial = hu32_from_msg(buf, CTA_INFO_SERNO);
  507. info->asics = u8_from_msg(buf, CTA_INFO_NUMASICS);
  508. info->dies = u8_from_msg(buf, CTA_INFO_NUMDIES);
  509. info->cores = hu16_from_msg(buf, CTA_INFO_NUMCORES);
  510. info->board_number = u8_from_msg(buf, CTA_INFO_BOARDNUMBER);
  511. info->fwrev[0] = u8_from_msg(buf, CTA_INFO_FWREV_MAJ);
  512. info->fwrev[1] = u8_from_msg(buf, CTA_INFO_FWREV_MIN);
  513. info->fwrev[2] = u8_from_msg(buf, CTA_INFO_FWREV_MIC);
  514. info->fw_year = hu16_from_msg(buf, CTA_INFO_FWDATE_YEAR);
  515. info->fw_month = u8_from_msg(buf, CTA_INFO_FWDATE_MONTH);
  516. info->fw_day = u8_from_msg(buf, CTA_INFO_FWDATE_DAY);
  517. info->init_diffbits = u8_from_msg(buf, CTA_INFO_INITDIFFBITS);
  518. info->min_diffbits = u8_from_msg(buf, CTA_INFO_MINDIFFBITS);
  519. info->max_diffbits = u8_from_msg(buf, CTA_INFO_MAXDIFFBITS);
  520. mutex_unlock(&info->lock);
  521. #if 0
  522. if (!cointerra->unique_id) {
  523. uint32_t b32 = htobe32(info->serial);
  524. cointerra->unique_id = malloc((4 * 2) + 1);
  525. bin2hex(cointerra->unique_id, &b32, 4);
  526. }
  527. #endif
  528. }
  529. static void cta_parse_rdone(struct cgpu_info *cointerra, struct cointerra_info *info,
  530. char *buf)
  531. {
  532. uint8_t reset_type, diffbits;
  533. uint64_t wdone;
  534. reset_type = buf[CTA_RESET_TYPE];
  535. diffbits = buf[CTA_RESET_DIFF];
  536. wdone = hu64_from_msg(buf, CTA_WDONE_NONCES);
  537. applog(LOG_INFO, "%s %d: Reset done type %u message %u diffbits %"PRIu64" done received",
  538. cointerra->drv->name, cointerra->device_id, reset_type, diffbits, wdone);
  539. if (wdone) {
  540. applog(LOG_INFO, "%s %d: Reset done type %u message %u diffbits %"PRIu64" done received",
  541. cointerra->drv->name, cointerra->device_id, reset_type, diffbits, wdone);
  542. mutex_lock(&info->lock);
  543. info->hashes += wdone;
  544. mutex_unlock(&info->lock);
  545. }
  546. /* Note that the cgsem that is posted here must not be waited on while
  547. * holding the info->lock to not get into a livelock since this
  548. * function also grabs the lock first and it's always best to not sleep
  549. * while holding a lock. */
  550. if (reset_type == CTA_RESET_NEW) {
  551. cta_clear_work(cointerra);
  552. /* Tell reset sender that the reset is complete
  553. * and it may resume. */
  554. notifier_wake(info->reset_notifier);
  555. }
  556. }
  557. static void cta_zero_stats(struct cgpu_info *cointerra);
  558. static void cta_parse_debug(struct cointerra_info *info, char *buf)
  559. {
  560. mutex_lock(&info->lock);
  561. info->tot_underruns = hu16_from_msg(buf, CTA_STAT_UNDERRUNS);
  562. u16array_from_msg(info->tot_hw_errors, CTA_CORES, CTA_STAT_HW_ERRORS, buf);
  563. info->tot_hashes = hu64_from_msg(buf, CTA_STAT_HASHES);
  564. info->tot_flushed_hashes = hu64_from_msg(buf, CTA_STAT_FLUSHED_HASHES);
  565. info->autovoltage = u8_from_msg(buf, CTA_STAT_AUTOVOLTAGE);
  566. info->current_ps_percent = u8_from_msg(buf, CTA_STAT_POWER_PERCENT);
  567. info->power_used = hu16_from_msg(buf,CTA_STAT_POWER_USED);
  568. info->power_voltage = hu16_from_msg(buf,CTA_STAT_VOLTAGE);
  569. info->ipower_used = hu16_from_msg(buf,CTA_STAT_IPOWER_USED);
  570. info->ipower_voltage = hu16_from_msg(buf,CTA_STAT_IVOLTAGE);
  571. info->power_temps[0] = hu16_from_msg(buf,CTA_STAT_PS_TEMP1);
  572. info->power_temps[1] = hu16_from_msg(buf,CTA_STAT_PS_TEMP2);
  573. mutex_unlock(&info->lock);
  574. #if 0
  575. /* Autovoltage is positive only once at startup and eventually drops
  576. * to zero. After that time we reset the stats since they're unreliable
  577. * till then. */
  578. if (unlikely(!info->autovoltage_complete && !info->autovoltage)) {
  579. struct cgpu_info *cointerra = info->thr->cgpu;
  580. info->autovoltage_complete = true;
  581. cgtime(&cointerra->dev_start_tv);
  582. cta_zero_stats(cointerra);
  583. cointerra->total_mhashes = 0;
  584. cointerra->accepted = 0;
  585. cointerra->rejected = 0;
  586. cointerra->hw_errors = 0;
  587. cointerra->utility = 0.0;
  588. cointerra->last_share_pool_time = 0;
  589. cointerra->diff1 = 0;
  590. cointerra->diff_accepted = 0;
  591. cointerra->diff_rejected = 0;
  592. cointerra->last_share_diff = 0;
  593. }
  594. #endif
  595. }
  596. static void cta_parse_msg(struct thr_info *thr, struct cgpu_info *cointerra,
  597. struct cointerra_info *info, char *buf)
  598. {
  599. switch (buf[CTA_MSG_TYPE]) {
  600. default:
  601. case CTA_RECV_UNUSED:
  602. applog(LOG_INFO, "%s %d: Unidentified message type %u",
  603. cointerra->drv->name, cointerra->device_id, buf[CTA_MSG_TYPE]);
  604. break;
  605. case CTA_RECV_REQWORK:
  606. cta_parse_reqwork(cointerra, info, buf);
  607. break;
  608. case CTA_RECV_MATCH:
  609. cta_parse_recvmatch(thr, cointerra, info, buf);
  610. break;
  611. case CTA_RECV_WDONE:
  612. applog(LOG_DEBUG, "%s %d: Work done message received",
  613. cointerra->drv->name, cointerra->device_id);
  614. cta_parse_wdone(thr, cointerra, info, buf);
  615. break;
  616. case CTA_RECV_STATREAD:
  617. applog(LOG_DEBUG, "%s %d: Status readings message received",
  618. cointerra->drv->name, cointerra->device_id);
  619. cta_parse_statread(cointerra, info, buf);
  620. break;
  621. case CTA_RECV_STATSET:
  622. applog(LOG_DEBUG, "%s %d: Status settings message received",
  623. cointerra->drv->name, cointerra->device_id);
  624. cta_parse_statset(info, buf);
  625. break;
  626. case CTA_RECV_INFO:
  627. applog(LOG_DEBUG, "%s %d: Info message received",
  628. cointerra->drv->name, cointerra->device_id);
  629. cta_parse_info(cointerra, info, buf);
  630. break;
  631. case CTA_RECV_MSG:
  632. applog(LOG_NOTICE, "%s %d: MSG: %s",
  633. cointerra->drv->name, cointerra->device_id, &buf[CTA_MSG_RECVD]);
  634. break;
  635. case CTA_RECV_RDONE:
  636. cta_parse_rdone(cointerra, info, buf);
  637. break;
  638. case CTA_RECV_STATDEBUG:
  639. cta_parse_debug(info, buf);
  640. break;
  641. }
  642. }
  643. static void *cta_recv_thread(void *arg)
  644. {
  645. struct thr_info *thr = (struct thr_info *)arg;
  646. struct cgpu_info *cointerra = thr->cgpu;
  647. struct cointerra_info *info = cointerra->device_data;
  648. char threadname[24];
  649. int offset = 0;
  650. snprintf(threadname, 24, "cta_recv/%d", cointerra->device_id);
  651. RenameThread(threadname);
  652. while (likely(!cointerra->shutdown)) {
  653. char buf[CTA_READBUF_SIZE];
  654. int amount;
  655. if (unlikely(0))
  656. {
  657. applog(LOG_DEBUG, "%s %d: Device disappeared, disabling recv thread",
  658. cointerra->drv->name, cointerra->device_id);
  659. break;
  660. }
  661. amount = usb_read(info->ep, buf + offset, CTA_MSG_SIZE);
  662. if (amount != CTA_MSG_SIZE && amount != 0) {
  663. applog(LOG_ERR, "%s: Read error %s, read %d",
  664. cointerra->dev_repr, bfg_strerror(errno, BST_ERRNO), amount);
  665. break;
  666. }
  667. offset += amount;
  668. while (offset >= CTA_MSG_SIZE) {
  669. char *msg = mystrstr(buf, offset, cointerra_hdr);
  670. int begin;
  671. if (unlikely(!msg)) {
  672. applog(LOG_WARNING, "%s %d: No message header found, discarding buffer",
  673. cointerra->drv->name, cointerra->device_id);
  674. inc_hw_errors_only(thr);
  675. /* Save the last byte in case it's the fist
  676. * byte of a header. */
  677. begin = CTA_MSG_SIZE - 1;
  678. offset -= begin;
  679. memmove(buf, buf + begin, offset);
  680. continue;
  681. }
  682. if (unlikely(msg != buf)) {
  683. begin = msg - buf;
  684. applog(LOG_WARNING, "%s %d: Reads out of sync, discarding %d bytes",
  685. cointerra->drv->name, cointerra->device_id, begin);
  686. inc_hw_errors_only(thr);
  687. offset -= begin;
  688. memmove(buf, msg, offset);
  689. if (offset < CTA_MSG_SIZE)
  690. break;
  691. }
  692. /* We have enough buffer for a full message, parse now */
  693. cta_parse_msg(thr, cointerra, info, msg);
  694. offset -= CTA_MSG_SIZE;
  695. if (offset > 0)
  696. memmove(buf, buf + CTA_MSG_SIZE, offset);
  697. }
  698. }
  699. return NULL;
  700. }
  701. static bool cta_send_msg(struct cgpu_info *cointerra, char *buf)
  702. {
  703. struct cointerra_info *info = cointerra->device_data;
  704. int amount;
  705. /* Serialise usb writes to prevent overlap in case multiple threads
  706. * send messages */
  707. mutex_lock(&info->sendlock);
  708. amount = usb_write(info->ep, buf, CTA_MSG_SIZE);
  709. mutex_unlock(&info->sendlock);
  710. if (unlikely(amount != CTA_MSG_SIZE)) {
  711. applog(LOG_ERR, "%s: Write error %s, wrote %d of %d",
  712. cointerra->dev_repr, bfg_strerror(errno, BST_ERRNO), amount, CTA_MSG_SIZE);
  713. return false;
  714. }
  715. return true;
  716. }
  717. static bool cta_prepare(struct thr_info *thr)
  718. {
  719. struct cgpu_info *cointerra = thr->cgpu;
  720. struct lowlevel_device_info * const llinfo = cointerra->device_data;
  721. struct cointerra_info *info = calloc(sizeof(struct cointerra_info), 1);
  722. char buf[CTA_MSG_SIZE];
  723. sleep(1);
  724. if (unlikely(!info))
  725. quit(1, "Failed to calloc info in cta_detect_one");
  726. for_each_managed_proc(proc, cointerra)
  727. proc->device_data = info;
  728. /* Nominally set a requested value when starting, preempting the need
  729. * for a req-work message. */
  730. info->requested = CTA_MAX_QUEUE;
  731. if (!cointerra_open(llinfo, cointerra->dev_repr, &info->usbh, &info->ep))
  732. return false;
  733. info->thr = thr;
  734. mutex_init(&info->lock);
  735. mutex_init(&info->sendlock);
  736. if (unlikely(pthread_cond_init(&info->wake_cond, NULL)))
  737. quit(1, "Failed to create cta pthread cond");
  738. notifier_init(info->reset_notifier);
  739. if (pthread_create(&info->read_thr, NULL, cta_recv_thread, (void *)thr))
  740. quit(1, "Failed to create cta_recv_thread");
  741. /* Request a single status setting message */
  742. cta_gen_message(buf, CTA_SEND_REQUEST);
  743. msg_from_hu16(buf, CTA_REQ_MSGTYPE, CTA_RECV_STATSET);
  744. msg_from_hu16(buf, CTA_REQ_INTERVAL, 0);
  745. if (!cta_send_msg(cointerra, buf))
  746. return false;
  747. /* Request status debug messages every 60 seconds */
  748. cta_gen_message(buf, CTA_SEND_REQUEST);
  749. msg_from_hu16(buf, CTA_REQ_MSGTYPE, CTA_RECV_STATDEBUG);
  750. msg_from_hu16(buf, CTA_REQ_INTERVAL, 6000);
  751. if (!cta_send_msg(cointerra, buf))
  752. return false;
  753. cgtime(&info->core_hash_start);
  754. return true;
  755. }
  756. static void cta_send_reset(struct cgpu_info *cointerra, struct cointerra_info *info,
  757. uint8_t reset_type, uint8_t diffbits);
  758. static void cta_flush_work(struct cgpu_info *cointerra);
  759. /* *_fill and *_scanwork are serialised wrt to each other */
  760. static bool cta_fill(struct cgpu_info *cointerra)
  761. {
  762. struct cointerra_info *info = cointerra->device_data;
  763. bool ret = true;
  764. struct timeval tv_now, tv_latest;
  765. char buf[CTA_MSG_SIZE];
  766. struct work *work = NULL;
  767. unsigned short nroll_limit;
  768. uint32_t swab[8];
  769. uint8_t diffbits;
  770. //applog(LOG_WARNING, "%s %d: cta_fill %d", cointerra->drv->name, cointerra->device_id,__LINE__);
  771. if (unlikely(info->thr->work_restart))
  772. cta_flush_work(cointerra);
  773. mutex_lock(&info->lock);
  774. if (!info->requested)
  775. goto out_unlock;
  776. work = get_queued(cointerra);
  777. if (unlikely(!work)) {
  778. ret = false;
  779. goto out_unlock;
  780. }
  781. if (--info->requested > 0)
  782. ret = false;
  783. /* It does not matter what endian this uint16_t is since it will be
  784. * the same value on sending to the MC as returning in match/done. This
  785. * will automatically wrap as a uint16_t. It cannot be zero for the MCU
  786. * though. */
  787. if (unlikely(++info->work_id == 0))
  788. info->work_id = 1;
  789. work->subid = info->work_id;
  790. diffbits = diff_to_bits(work->nonce_diff);
  791. cta_gen_message(buf, CTA_SEND_WORK);
  792. memcpy(buf + CTA_DRIVER_TAG, &info->work_id, 2);
  793. flip32(swab, work->midstate);
  794. memcpy(buf + CTA_WORK_MIDSTATE, swab, 32);
  795. flip12(swab, &work->data[64]);
  796. memcpy(buf + CTA_WORK_DATA, swab, 12);
  797. timer_set_now(&tv_now);
  798. timer_set_delay(&tv_latest, &tv_now, cointerra_latest_result_usecs);
  799. nroll_limit = max(0, work_ntime_range(work, &tv_now, &tv_latest, cointerra_desired_roll));
  800. nroll_limit = htole16(nroll_limit);
  801. memcpy(buf + CTA_WORK_NROLL, &nroll_limit, 2);
  802. memcpy(buf + CTA_WORK_DIFFBITS, &diffbits, 1);
  803. out_unlock:
  804. mutex_unlock(&info->lock);
  805. if (work) {
  806. cgtime(&work->tv_work_start);
  807. applog(LOG_DEBUG, "%s %d: Sending work job_id %s work_id %u", cointerra->drv->name,
  808. cointerra->device_id, work->job_id, work->subid);
  809. if (unlikely(!cta_send_msg(cointerra, buf))) {
  810. work_completed(cointerra, work);
  811. applog(LOG_INFO, "%s %d: Failed to send work",
  812. cointerra->drv->name, cointerra->device_id);
  813. /* The device will fail after this */
  814. }
  815. }
  816. return ret;
  817. }
  818. static void cta_send_reset(struct cgpu_info *cointerra, struct cointerra_info *info,
  819. uint8_t reset_type, uint8_t diffbits)
  820. {
  821. char buf[CTA_MSG_SIZE];
  822. int ret, retries = 0;
  823. /* Clear any accumulated messages in case we've gotten out of sync. */
  824. notifier_reset(info->reset_notifier);
  825. resend:
  826. cta_gen_message(buf, CTA_SEND_RESET);
  827. buf[CTA_RESET_TYPE] = reset_type;
  828. buf[CTA_RESET_LOAD] = opt_cta_load ? opt_cta_load : 255;
  829. buf[CTA_RESET_PSLOAD] = opt_ps_load;
  830. applog(LOG_INFO, "%s %d: Sending Reset type %u with diffbits %u", cointerra->drv->name,
  831. cointerra->device_id, reset_type, diffbits);
  832. cta_send_msg(cointerra, buf);
  833. /* Wait for read thread to parse a reset message and signal us we may
  834. * return to submitting other messages. Use a timeout in case we have
  835. * a problem and the reset done message never returns. */
  836. if (reset_type == CTA_RESET_NEW) {
  837. ret = notifier_wait_us(info->reset_notifier, CTA_RESET_TIMEOUT * 1000);
  838. if (ret) {
  839. if (++retries < 3) {
  840. applog(LOG_INFO, "%s %d: Timed out waiting for reset done msg, retrying",
  841. cointerra->drv->name, cointerra->device_id);
  842. goto resend;
  843. }
  844. applog(LOG_WARNING, "%s %d: Timed out waiting for reset done msg",
  845. cointerra->drv->name, cointerra->device_id);
  846. }
  847. /* Good place to flush any work we have */
  848. flush_queue(cointerra);
  849. }
  850. }
  851. static void cta_update_work(struct cgpu_info *);
  852. static void cta_flush_work(struct cgpu_info *cointerra)
  853. {
  854. struct cointerra_info *info = cointerra->device_data;
  855. if (1)
  856. cta_update_work(cointerra);
  857. else
  858. {
  859. applog(LOG_INFO, "%s %d: cta_flush_work %d", cointerra->drv->name, cointerra->device_id,
  860. __LINE__);
  861. cta_send_reset(cointerra, info, CTA_RESET_NEW, 0);
  862. }
  863. info->thr->work_restart = false;
  864. }
  865. static void cta_update_work(struct cgpu_info *cointerra)
  866. {
  867. struct cointerra_info *info = cointerra->device_data;
  868. applog(LOG_INFO, "%s %d: Update work", cointerra->drv->name, cointerra->device_id);
  869. cta_send_reset(cointerra, info, CTA_RESET_UPDATE, 0);
  870. }
  871. static void cta_zero_corehashes(struct cointerra_info *info)
  872. {
  873. int i;
  874. for (i = 0; i < CTA_CORES; i++)
  875. info->tot_core_hashes[i] = 0;
  876. cgtime(&info->core_hash_start);
  877. }
  878. /* Send per core hashrate calculations at regular intervals ~every 5 minutes */
  879. static void cta_send_corehashes(struct cgpu_info *cointerra, struct cointerra_info *info,
  880. double corehash_time)
  881. {
  882. uint16_t core_ghs[CTA_CORES];
  883. double k[CTA_CORES];
  884. char buf[CTA_MSG_SIZE];
  885. int i, offset;
  886. for (i = 0; i < CTA_CORES; i++) {
  887. k[i] = (double)info->tot_core_hashes[i] / ((double)32 * (double)0x100000000ull);
  888. k[i] = sqrt(k[i]) + 1;
  889. k[i] *= k[i];
  890. k[i] = k[i] * 32 * ((double)0x100000000ull / (double)1000000000) / corehash_time;
  891. core_ghs[i] = k[i];
  892. }
  893. cta_gen_message(buf, CTA_SEND_COREHASHRATE);
  894. offset = CTA_CORE_HASHRATES;
  895. for (i = 0; i < CTA_CORES; i++) {
  896. msg_from_hu16(buf, offset, core_ghs[i]);
  897. offset += 2; // uint16_t
  898. }
  899. cta_send_msg(cointerra, buf);
  900. }
  901. static int64_t cta_scanwork(struct thr_info *thr)
  902. {
  903. struct cgpu_info *cointerra = thr->cgpu;
  904. struct cointerra_info *info = cointerra->device_data;
  905. double corehash_time;
  906. struct timeval now;
  907. int64_t hashes;
  908. hashes = 0;
  909. if (unlikely(0))
  910. {
  911. hashes = -1;
  912. goto out;
  913. }
  914. cgtime(&now);
  915. if (unlikely(thr->work_restart)) {
  916. applog(LOG_INFO, "%s %d: Flush work line %d",
  917. cointerra->drv->name, cointerra->device_id,__LINE__);
  918. cta_flush_work(cointerra);
  919. } else {
  920. struct timespec abstime, tsdiff = {0, 500000000};
  921. time_t now_t;
  922. int i;
  923. timeval_to_spec(&abstime, &now);
  924. timeraddspec(&abstime, &tsdiff);
  925. /* Discard work that was started more than 5 minutes ago as
  926. * a safety precaution backup in case the hardware failed to
  927. * return a work done message for some work items. */
  928. age_queued_work(cointerra, 300.0);
  929. /* Each core should be 1.7MH so at max diff of 32 should
  930. * average a share every ~80 seconds.Use this opportunity to
  931. * unset the bits in any pipes that have not returned a valid
  932. * nonce for over 30 full nonce ranges or 2400s. */
  933. now_t = time(NULL);
  934. for (i = 0; i < 1024; i++) {
  935. if (unlikely(now_t > info->last_pipe_nonce[i] + 2400)) {
  936. int bitchar = i / 8, bitbit = i % 8;
  937. info->pipe_bitmap[bitchar] &= ~(0x80 >> bitbit);
  938. }
  939. }
  940. /* Sleep for up to 0.5 seconds, waking if we need work or
  941. * have received a restart message. */
  942. mutex_lock(&info->lock);
  943. pthread_cond_timedwait(&info->wake_cond, &info->lock, &abstime);
  944. mutex_unlock(&info->lock);
  945. if (thr->work_restart) {
  946. applog(LOG_INFO, "%s %d: Flush work line %d",
  947. cointerra->drv->name, cointerra->device_id,__LINE__);
  948. cta_flush_work(cointerra);
  949. }
  950. }
  951. corehash_time = tdiff(&now, &info->core_hash_start);
  952. if (corehash_time > 300) {
  953. cta_send_corehashes(cointerra, info, corehash_time);
  954. cta_zero_corehashes(info);
  955. }
  956. mutex_lock(&info->lock);
  957. info->tot_share_hashes += info->share_hashes;
  958. info->tot_calc_hashes += info->hashes;
  959. info->hashes = info->share_hashes = 0;
  960. mutex_unlock(&info->lock);
  961. if (unlikely(0))
  962. hashes = -1;
  963. out:
  964. return hashes;
  965. }
  966. /* This is used for a work restart. We don't actually perform the work restart
  967. * here but wake up the scanwork loop if it's waiting on the conditional so
  968. * that it can test for the restart message. */
  969. static void cta_wake(struct cgpu_info *cointerra)
  970. {
  971. struct cointerra_info *info = cointerra->device_data;
  972. mutex_lock(&info->lock);
  973. pthread_cond_signal(&info->wake_cond);
  974. mutex_unlock(&info->lock);
  975. }
  976. static void cta_shutdown(struct thr_info *thr)
  977. {
  978. struct cgpu_info *cointerra = thr->cgpu;
  979. cta_close(cointerra);
  980. }
  981. static void cta_zero_stats(struct cgpu_info *cointerra)
  982. {
  983. struct cointerra_info *info = cointerra->device_data;
  984. info->tot_calc_hashes = 0;
  985. info->tot_reset_hashes = info->tot_hashes;
  986. info->tot_share_hashes = 0;
  987. cta_zero_corehashes(info);
  988. }
  989. static int bits_set(char v)
  990. {
  991. int c;
  992. for (c = 0; v; c++)
  993. v &= v - 1;
  994. return c;
  995. }
  996. static struct api_data *cta_api_stats(struct cgpu_info *cgpu)
  997. {
  998. struct api_data *root = NULL;
  999. struct cointerra_info *info = cgpu->device_data;
  1000. double dev_runtime = cgpu_runtime(cgpu);
  1001. int i, asic, core, coreno = 0;
  1002. struct timeval now;
  1003. char bitmaphex[36];
  1004. uint64_t ghs, val;
  1005. char buf[64];
  1006. asic = cgpu->proc_id / 480;
  1007. int coreabs = cgpu->proc_id / 120;
  1008. core = coreabs % 4;
  1009. /* Info data */
  1010. root = api_add_uint16(root, "HW Revision", &info->hwrev, false);
  1011. root = api_add_uint32(root, "Serial", &info->serial, false);
  1012. root = api_add_uint8(root, "Asics", &info->asics, false);
  1013. root = api_add_uint8(root, "Dies", &info->dies, false);
  1014. root = api_add_uint16(root, "Cores", &info->cores, false);
  1015. root = api_add_uint8(root, "Board number", &info->board_number, false);
  1016. sprintf(buf, "%u.%u.%u", info->fwrev[0], info->fwrev[1], info->fwrev[2]);
  1017. root = api_add_string(root, "FW Revision", buf, true);
  1018. sprintf(buf, "%04u-%02u-%02u", info->fw_year, info->fw_month, info->fw_day);
  1019. root = api_add_string(root, "FW Date", buf, true);
  1020. root = api_add_uint8(root, "Init diffbits", &info->init_diffbits, false);
  1021. root = api_add_uint8(root, "Min diffbits", &info->min_diffbits, false);
  1022. root = api_add_uint8(root, "Max diffbits", &info->max_diffbits, false);
  1023. /* Status readings */
  1024. {
  1025. i = coreabs;
  1026. sprintf(buf, "CoreTemp%d", i);
  1027. root = api_add_int16(root, buf, &info->coretemp[i], false);
  1028. }
  1029. root = api_add_int16(root, "Ambient Low", &info->ambtemp_low, false);
  1030. root = api_add_int16(root, "Ambient Avg", &info->ambtemp_avg, false);
  1031. root = api_add_int16(root, "Ambient High", &info->ambtemp_high, false);
  1032. for (i = 0; i < CTA_PUMPS; i++) {
  1033. sprintf(buf, "PumpRPM%d", i);
  1034. root = api_add_uint16(root, buf, &info->pump_tachs[i], false);
  1035. }
  1036. for (i = 0; i < CTA_FANS; i++) {
  1037. sprintf(buf, "FanRPM%d", i);
  1038. root = api_add_uint16(root, buf, &info->fan_tachs[i], false);
  1039. }
  1040. {
  1041. i = coreabs;
  1042. sprintf(buf, "CoreFreqs%d", i);
  1043. root = api_add_uint16(root, buf, &info->corefreqs[i], false);
  1044. }
  1045. {
  1046. i = coreabs;
  1047. sprintf(buf, "CoreVolts%d", i);
  1048. root = api_add_uint16(root, buf, &info->corevolts[i], false);
  1049. }
  1050. root = api_add_uint16(root, "Volts3.3", &info->volts33, false);
  1051. root = api_add_uint16(root, "Volts12", &info->volts12, false);
  1052. root = api_add_uint16(root, "Inactive", &info->inactive, false);
  1053. root = api_add_uint16(root, "Active", &info->active, false);
  1054. /* Status settings */
  1055. {
  1056. i = coreabs;
  1057. sprintf(buf, "CorePerfMode%d", i);
  1058. root = api_add_uint8(root, buf, &info->coreperf[i], false);
  1059. }
  1060. for (i = 0; i < CTA_FANS; i++) {
  1061. sprintf(buf, "FanSpeed%d", i);
  1062. root = api_add_uint8(root, buf, &info->fanspeed[i], false);
  1063. }
  1064. root = api_add_uint8(root, "DiesActive", &info->dies_active, false);
  1065. {
  1066. i = coreabs;
  1067. sprintf(buf, "PipesEnabled%d", i);
  1068. root = api_add_uint8(root, buf, &info->pipes_enabled[i], false);
  1069. }
  1070. /* Status debug */
  1071. root = api_add_int(root, "Underruns", &info->tot_underruns, false);
  1072. {
  1073. i = coreabs;
  1074. sprintf(buf, "HWErrors%d", i);
  1075. root = api_add_uint16(root, buf, &info->tot_hw_errors[i], false);
  1076. }
  1077. ghs = info->tot_calc_hashes / dev_runtime;
  1078. root = api_add_uint64(root, "Calc hashrate", &ghs, true);
  1079. ghs = (info->tot_hashes - info->tot_reset_hashes) / dev_runtime;
  1080. root = api_add_uint64(root, "Hashrate", &ghs, true);
  1081. ghs = info->tot_share_hashes / dev_runtime;
  1082. root = api_add_uint64(root, "Share hashrate", &ghs, true);
  1083. root = api_add_uint64(root, "Total calc hashes", &info->tot_calc_hashes, false);
  1084. ghs = info->tot_hashes - info->tot_reset_hashes;
  1085. root = api_add_uint64(root, "Total hashes", &ghs, true);
  1086. root = api_add_uint64(root, "Total raw hashes", &info->tot_hashes, false);
  1087. root = api_add_uint64(root, "Total share hashes", &info->tot_share_hashes, false);
  1088. root = api_add_uint64(root, "Total flushed hashes", &info->tot_flushed_hashes, false);
  1089. val = cgpu->diff_accepted * 0x100000000ull;
  1090. root = api_add_uint64(root, "Accepted hashes", &val, true);
  1091. ghs = val / dev_runtime;
  1092. root = api_add_uint64(root, "Accepted hashrate", &ghs, true);
  1093. val = cgpu->diff_rejected * 0x100000000ull;
  1094. root = api_add_uint64(root, "Rejected hashes", &val, true);
  1095. ghs = val / dev_runtime;
  1096. root = api_add_uint64(root, "Rejected hashrate", &ghs, true);
  1097. cgtime(&now);
  1098. dev_runtime = tdiff(&now, &info->core_hash_start);
  1099. if (dev_runtime < 1)
  1100. dev_runtime = 1;
  1101. {
  1102. i = coreabs;
  1103. sprintf(buf, "Core%d hashrate", i);
  1104. ghs = info->tot_core_hashes[i] / dev_runtime;
  1105. root = api_add_uint64(root, buf, &ghs, true);
  1106. }
  1107. root = api_add_uint32(root, "Uptime",&info->uptime,false);
  1108. {
  1109. char bitmapcount[40], asiccore[12];
  1110. int count = 0;
  1111. sprintf(asiccore, "Asic%dCore%d", asic, core);
  1112. bin2hex(bitmaphex, &info->pipe_bitmap[coreno], 16);
  1113. for (i = coreno; i < coreno + 16; i++)
  1114. count += bits_set(info->pipe_bitmap[i]);
  1115. snprintf(bitmapcount, 40, "%d:%s", count, bitmaphex);
  1116. root = api_add_string(root, asiccore, bitmapcount, true);
  1117. coreno += 16;
  1118. }
  1119. root = api_add_uint8(root, "AV", &info->autovoltage, false);
  1120. root = api_add_uint8(root, "Power Supply Percent", &info->current_ps_percent, false);
  1121. root = api_add_uint16(root, "Power Used", &info->power_used, false);
  1122. root = api_add_uint16(root, "IOUT", &info->power_used, false);
  1123. root = api_add_uint16(root, "VOUT", &info->power_voltage, false);
  1124. root = api_add_uint16(root, "IIN", &info->ipower_used, false);
  1125. root = api_add_uint16(root, "VIN", &info->ipower_voltage, false);
  1126. root = api_add_uint16(root, "PSTemp1", &info->power_temps[0], false);
  1127. root = api_add_uint16(root, "PSTemp2", &info->power_temps[1], false);
  1128. return root;
  1129. }
  1130. struct device_drv cointerra_drv = {
  1131. .dname = "cointerra",
  1132. .name = "CTA",
  1133. .lowl_match = cointerra_lowl_match,
  1134. .lowl_probe = cointerra_lowl_probe,
  1135. .thread_init = cta_prepare,
  1136. .minerloop = hash_queued_work,
  1137. .queue_full = cta_fill,
  1138. // TODO .update_work = cta_update_work,
  1139. .scanwork = cta_scanwork,
  1140. .flush_work = cta_wake,
  1141. .get_api_stats = cta_api_stats,
  1142. .thread_shutdown = cta_shutdown,
  1143. .zero_stats = cta_zero_stats,
  1144. };