driver-cointerra.c 39 KB

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