driver-cointerra.c 38 KB

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